mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
d39bc871b7
* feat(ui): render markdown math * feat(ui): support more markdown math delimiters * feat(ui): renders spaced dollar-delimited TeX support * chore(deps): update katex * Update bun.lock chore(deps): update chore(deps): update chore(deps): update chore(deps): update chore(deps): update * feat(highlight): highlight math * feat(ui): support formule & text highlight together * fix(ui): make rendered math drag-selectable for annotation Drag-selecting an inline formula did nothing: the browser normalizes the selection focus to offset 0 of the following text node, so the strict anchor/focus check in selectionHasNonMathContent treated every inline drag as "mixed prose+math" and bailed without claiming the event. Control fell to web-highlighter, which excludes .katex/.math-annotatable, so no annotation was created and the selection just collapsed. Drop the anchor/focus check and rely on the existing clone-and-strip logic (leftover text => genuinely mixed), plus a guard for selections wholly inside one formula. Add a regression test that reproduces the real spilled-endpoint drag, which the prior empty-selection tests missed. Also paint a preview highlight the moment a formula's toolbar/popover opens (stripped on cancel, committed on submit) and show cursor: pointer on hover so formulas read as annotation targets. * chore(ui): reconcile lockfile and math styles after rebase onto main Rebase reconciliation, not new behavior: - Re-add katex to bun.lock. The lockfile conflicted on every replayed commit and was resolved to main's copy throughout; regenerate it here so package.json (katex) and the lockfile agree again. - Move the math annotation styles (.math-inline-annotation / .math-block-annotation) into packages/ui/theme.css. main relocated all annotation-highlight rules there to share them with the code-review description annotations; the PR had added the math variants to the old editor/index.css location. * test(ui): lazy-load highlighter hook so DOM-less bun test skips cleanly The math-annotation test statically imported useAnnotationHighlighter, which pulls in @plannotator/web-highlighter — a UMD bundle that reads `window` at module-eval time. Under the default `bun test` (no DOM), that threw a ReferenceError on import, failing CI before the skipIf(!hasDom) guards ever ran. Import the hook lazily, gated on hasDom, so the file loads and its tests skip cleanly in CI while DOM_TESTS=1 still exercises them. * fix(ui): stop display math from swallowing the document The `$$`/`\[` block parser only recognized the closing delimiter when it was the last non-space text on its line. A line like `$$E=mc^2$$.` (trailing period) or `$$E=mc^2$$ where E is energy.` therefore looked like an unterminated opener and consumed every following line until the next fence or EOF — silently hiding the rest of the plan. Detect the closing delimiter anywhere on the line and re-process any trailing text as its own line, so the equation renders and the following content is preserved instead of dropped. Same fix for the multi-line closing path and the `\[ ... \]` branch. Adds parser regression tests (these run in CI; no DOM). --------- Co-authored-by: ishowman <ishowman@users.noreply.github.com> Co-authored-by: Michael Ramos <mdramos8@gmail.com>
37 lines
938 B
TypeScript
37 lines
938 B
TypeScript
import React, { useMemo } from 'react';
|
|
import katex from 'katex';
|
|
import type { Block } from '../../types';
|
|
|
|
type MathBlockProps = {
|
|
block: Block;
|
|
};
|
|
|
|
export const normalizeMathTex = (tex: string): string => tex.trim();
|
|
|
|
export const renderMathToHtml = (tex: string, displayMode: boolean): string => (
|
|
katex.renderToString(tex, {
|
|
displayMode,
|
|
throwOnError: false,
|
|
strict: 'warn',
|
|
trust: false,
|
|
output: 'html',
|
|
})
|
|
);
|
|
|
|
export const MathBlock: React.FC<MathBlockProps> = ({ block }) => {
|
|
const tex = normalizeMathTex(block.content);
|
|
const html = useMemo(() => renderMathToHtml(tex, true), [tex]);
|
|
|
|
return (
|
|
<div
|
|
className="math-block math-annotatable my-5 overflow-x-auto py-2 text-foreground"
|
|
data-block-id={block.id}
|
|
data-block-type="math"
|
|
data-math-tex={tex}
|
|
data-math-display="true"
|
|
aria-label={tex}
|
|
dangerouslySetInnerHTML={{ __html: html }}
|
|
/>
|
|
);
|
|
};
|