Skip to content

T-RCWI-md-obsidian-md-sync-helpers

State: closed/done · Impact: high · Complexity: small

The editor’s rendered widgets are framework-free DOM built from obsidian-md’s own markup, but the renderer only exposes an async renderToHtml, and KaTeX and mermaid rendering are inlined in two Vue components. This task adds renderToHtmlSync, renderMath and renderMermaid to the core entry, moves LoadedNote to core, and makes MathBlock and MermaidBlock consume the helpers.

LocationRole today
packages/ts/obsidian-md/src/processor.ts#renderToHtmlAsync processor.process; no sync variant
packages/ts/obsidian-md/src/vue/components/MathBlock.tsLazy import('katex') and renderToString inline
packages/ts/obsidian-md/src/vue/components/MermaidBlock.tsLazy import('mermaid'), initMermaid once-per-theme guard, id sequence inline
packages/ts/obsidian-md/src/vue/context.ts#LoadedNoteType lives in the Vue subpath; the engine’s Vue-free entry cannot import it
packages/ts/obsidian-md/src/vue/index.tsRe-exports LoadedNote
packages/ts/obsidian-md/src/index.tsCore exports; no LoadedNote, no render helpers
packages/ts/obsidian-editor/package.jsonNo direct katex or mermaid dependency
solutions/determined/experiences/notes/app/plugins/note-source.client.tsImports LoadedNote type from @sksizer/obsidian-md/vue
packages/ts/obsidian-md/test/vue-components.test.tsExisting math and mermaid component tests, the oracle for the refactor
packages/ts/obsidian-md/test/fixtures/every-feature.mdFixture for the sync-equals-async test
  • renderToHtmlSync(markdown, options = {}): string in the processor module, built on createObsidianProcessor(options).use(rehypeStringify, { allowDangerousHtml: false }) and processSync; throws Error('renderToHtmlSync: highlight requires the async renderToHtml') when options.highlight is set, because rehypeShiki is async.
  • packages/ts/obsidian-md/src/math.ts: loadKatex(): Promise<KatexModule> (memoized lazy import) and renderMath(latex: string, displayMode: boolean): Promise<string> returning the htmlAndMathml markup with throwOnError: false.
  • packages/ts/obsidian-md/src/mermaid.ts: renderMermaid(source: string, theme = 'default'): Promise<string> with the once-per-theme initialize guard and the id sequence moved from MermaidBlock.
  • LoadedNote moves to packages/ts/obsidian-md/src/types.ts; the Vue context module imports and re-exports it so @sksizer/obsidian-md/vue keeps exporting the type.
  • The core entry exports renderToHtmlSync, renderMath, loadKatex, renderMermaid, and the LoadedNote type.
  • MathBlock and MermaidBlock call the helpers; the inline copies are deleted.
  • packages/ts/obsidian-editor/package.json adds katex and mermaid as direct dependencies at the versions obsidian-md pins.
  1. Write packages/ts/obsidian-md/test/render-sync.test.ts: renderToHtmlSync(fixture) equals await renderToHtml(fixture) for the every-feature fixture with math: true; throws with highlight.
  2. Write packages/ts/obsidian-md/test/render-math.test.ts (block and inline markup contain katex-mathml; invalid TeX returns markup, not a throw) and packages/ts/obsidian-md/test/render-mermaid.test.ts (mock mermaid module: initialize called once for two renders with the same theme, twice across two themes; render failure rejects).
  3. Add renderToHtmlSync to the processor module; add the math and mermaid modules.
  4. Move LoadedNote to the core types module; re-export from the Vue context module and the core entry.
  5. Rewrite MathBlock and MermaidBlock over the helpers; run the Vue components test unchanged.
  6. Add the two dependencies to the editor manifest; bun install.
  7. bun test and tsc --noEmit in both packages; moon run product-workbench:check for the notes consumer of LoadedNote.
LocationKindChange
packages/ts/obsidian-md/src/processor.tsmodifyrenderToHtmlSync
packages/ts/obsidian-md/src/math.tsnewloadKatex, renderMath
packages/ts/obsidian-md/src/mermaid.tsnewrenderMermaid with once-per-theme init
packages/ts/obsidian-md/src/types.tsmodifyLoadedNote
packages/ts/obsidian-md/src/vue/context.tsmodifyImport and re-export LoadedNote from core
packages/ts/obsidian-md/src/vue/components/MathBlock.tsmodifyConsume renderMath
packages/ts/obsidian-md/src/vue/components/MermaidBlock.tsmodifyConsume renderMermaid
packages/ts/obsidian-md/src/index.tsmodifyExport the helpers and LoadedNote
packages/ts/obsidian-md/README.mdmodifyDocument renderToHtmlSync, renderMath, renderMermaid under “Core usage”
packages/ts/obsidian-md/test/render-sync.test.tsnewSync equals async; throws with highlight
packages/ts/obsidian-md/test/render-math.test.tsnewHelper tests
packages/ts/obsidian-md/test/render-mermaid.test.tsnewInit guard and failure tests
packages/ts/obsidian-editor/package.jsonmodifykatex, mermaid dependencies
  • AC-1: bun test packages/ts/obsidian-md passes with the three new suites and the unchanged packages/ts/obsidian-md/test/vue-components.test.ts.
  • AC-2: renderToHtmlSync over packages/ts/obsidian-md/test/fixtures/every-feature.md with { math: true } is byte-equal to await renderToHtml(...) with the same options.
  • AC-3: renderToHtmlSync(x, { highlight: rehypeShiki() }) throws.
  • AC-4: grep -rn "import('katex')\|import('mermaid')" packages/ts/obsidian-md/src matches only the new math and mermaid modules.
  • AC-5: import type { LoadedNote } from '@sksizer/obsidian-md' and from '@sksizer/obsidian-md/vue' both typecheck; moon run product-workbench:check passes with solutions/determined/experiences/notes/app/plugins/note-source.client.ts unchanged.
  • AC-6: packages/ts/obsidian-editor/package.json lists katex and mermaid under dependencies and bun install --frozen-lockfile at the repo root succeeds.
  • No task dependency. D-7VMX: the helpers wrap the existing remark pipeline and never add a parser.
  • Generalizing deletes the original per docs/PRINCIPLES.md: the inline copies in the two Vue components go.

Member of milestone M-931L; the obsidian-md prerequisites of decision D-K3EM-markdown-editor-chrome-and-plugin-environment.


← Back to Tasks