Skip to content

fix(app): move markdown parsing to worker - #40356

Merged
Hona merged 4 commits into
anomalyco:devfrom
Hona:markdown-worker
Aug 4, 2026
Merged

fix(app): move markdown parsing to worker#40356
Hona merged 4 commits into
anomalyco:devfrom
Hona:markdown-worker

Conversation

@Hona

@Hona Hona commented Aug 4, 2026

Copy link
Copy Markdown
Member

Summary

  • upgrade Marked to 18.0.7 and remove the released code-span workaround and unused marked-katex-extension dependency
  • run Markdown projection, parsing, KaTeX rendering, and Shiki highlighting in the existing session worker
  • lazy-load Shiki/WASM only when Markdown contains code and preserve Pierre's OpenCode theme registration for file/diff workers
  • keep sanitization and the rendered HTML cache on the renderer while preserving home-session preloading
  • preserve completed Markdown blocks when streaming finishes to avoid the idle full reparse and flicker
  • keep stale projections visible without entering route Suspense while worker updates complete
  • isolate Marked, KaTeX, and marked-shiki to the worker bundle, reducing the browser entry by about 41.6 KB and the Electron renderer by about 56.1 KB

Refs #40347

Testing

  • full pre-push turbo typecheck: 30 packages passed
  • UI tests: 12 passed
  • session-ui tests: 78 passed
  • app browser tests: 41 passed
  • app, Electron, and web production builds passed
  • real Chromium streaming trace: provider-paced Suspense transitions 107 -> 0; burst transitions 379 -> 0; no remounts or runtime errors
  • real Chromium finalization trace: parsed live tail transitioned directly to identical parsed full HTML
  • real Chromium dependency trace: plain prose loaded no Shiki WASM; Pierre OpenCode worker pool initialized successfully
  • app unit tests: 693 passed; the existing Arabic translation parity test failed on five unrelated missing keys

@Hona
Hona requested a review from Brendonovich as a code owner August 4, 2026 02:32
Copilot AI review requested due to automatic review settings August 4, 2026 02:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR moves Markdown projection/parsing (including KaTeX rendering and Shiki highlighting) off the renderer thread into the existing session Markdown worker, while upgrading marked to v18 and removing now-unneeded workarounds/dependencies to reduce bundle size and avoid UI freezes.

Changes:

  • Upgrade marked to 18.0.7, remove the code-span workaround and marked-katex-extension usage, and centralize markdown parsing in a shared createMarkdownParser.
  • Extend the session Markdown worker to support projection + full markdown parsing in addition to streaming code highlighting, and update renderer integration to call the worker.
  • Extract the OpenCode Shiki theme into a dedicated module and remove the app-level MarkedProvider dependency.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/ui/src/context/marked.tsx Refactors Marked context to use shared parser + extracted theme and removes the previous inline parsing/highlighting logic.
packages/ui/src/context/marked-theme.tsx New extracted OpenCode Shiki theme definition.
packages/ui/src/context/marked-regression.test.ts Updates regression test to rely on marked v18 behavior (removes workaround extension).
packages/ui/src/context/marked-parser.tsx New shared markdown parser factory (Marked + KaTeX + marked-shiki).
packages/ui/src/context/marked-parser.test.ts New unit tests covering link rendering, math rendering, and configured highlighter behavior.
packages/ui/src/context/marked-code-span.ts Removes the legacy code-span boundary workaround module.
packages/ui/package.json Drops marked-katex-extension dependency from UI package.
packages/session-ui/src/components/markdown.worker.ts Adds “parse” + “project” capabilities to the worker and wires in the shared markdown parser + theme.
packages/session-ui/src/components/markdown.tsx Switches rendering to worker-backed projection + parsing, updates code highlighting integration, and adds projection disposal.
packages/session-ui/src/components/markdown-worker.ts Updates worker bootstrap and adds parse/project request handling + lifecycle management.
packages/session-ui/src/components/markdown-worker-protocol.ts Extends protocol for parse/project responses and includes language in highlight responses/state.
packages/session-ui/src/components/markdown-worker-protocol.test.ts Updates protocol tests for new language field and response shapes.
packages/session-ui/src/components/markdown-stream.ts Moves canReusePendingBlock out to a new module.
packages/session-ui/src/components/markdown-stream.test.ts Updates imports for the extracted canReusePendingBlock.
packages/session-ui/src/components/markdown-projection.ts New module containing canReusePendingBlock logic.
packages/session-ui/src/components/markdown-preload.test.ts Removes prior markdown preload cache test.
packages/session-ui/src/components/markdown-cache.tsx Changes preload to worker-based parsing and simplifies caching to a single full-block entry.
packages/session-ui/package.json Removes KaTeX/Marked parsing deps from session-ui (now pulled via UI worker bundle).
packages/app/src/pages/home/home-sessions-controller.tsx Updates home preloading to the new preloadMarkdown signature (no provider parser needed).
packages/app/src/app.tsx Removes MarkedProvider from app provider tree.
package.json Bumps root catalog marked version to 18.0.7.
bun.lock Lockfile updates reflecting dependency removals and marked version bump.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +360 to +362
function pendingProjection(text: string): Projection {
return { text, blocks: text ? [{ raw: text, src: text, mode: "live" }] : [] }
}
Comment on lines +55 to +68
export async function preloadMarkdown(text: string, cacheKey: string) {
const key = `${cacheKey}:0:full`
const cached = getCachedMarkdown(key)
if (cached?.raw === text) {
touchCachedMarkdown(key, cached)
return
}
const hash = checksum(text)
if (!hash) return
touchCachedMarkdown(key, {
raw: text,
hash,
html: sanitizeMarkdown(await parseMarkdown(text)),
})
@Hona
Hona enabled auto-merge (squash) August 4, 2026 04:01
@Hona
Hona merged commit 638788f into anomalyco:dev Aug 4, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants