Skip to content

fix(mermaid): share pending render for concurrent re-renders - #1997

Merged
yanglbme merged 1 commit into
doocs:mainfrom
yanglfree:fix/mermaid-concurrent-render
Oct 21, 2026
Merged

yanglbme merged 1 commit into
doocs:mainfrom
yanglfree:fix/mermaid-concurrent-render

Conversation

@yanglfree

Copy link
Copy Markdown
Contributor

Summary

renderMermaidSvg only consults the finished-SVG cache. If the preview re-renders while the first render of a diagram is still pending, a second mermaid.render('mermaid-svg-<cacheKey>', code) starts with the same element id. This happens in practice when MathJax finishes loading and fires md:mathjax-ready, which re-renders a document that contains a Mermaid block.

The two concurrent runs measure each other's temporary elements, and the SVG that ends up in svgCache has no viewBox, class or max-width, so the diagram renders blank, and stays blank because the broken SVG is now cached.

This PR keeps a pendingRenders: Map<string, Promise<string>> keyed by the same cache key. A render that arrives while one is in flight awaits the existing promise instead of calling mermaid.render again; the entry is removed in finally, so a failed render can be retried on the next pass. Each caller still updates its own placeholder element through renderMermaid's handleResult.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor
  • Documentation / workflow update
  • Test

Test Procedure

  • Added packages/core/src/extensions/mermaid.test.ts: mocks mermaid with a gated render, renders the same Mermaid markdown twice while the first render is pending, then asserts mermaid.render was called once, the placeholder receives the SVG, and the next render inlines the cached SVG.
  • The new test fails on main (render called twice) and passes with this change.
  • pnpm --filter @md/core test passes (158 tests); tsc --noEmit in packages/core passes.

Pre-flight Checklist

  • Self-review of the diff
  • pnpm run lint passes (ESLint clean on the changed files)
  • Tests added or updated when behavior changes
  • User-facing copy updated in zh-CN, zh-TW, en-US, and ja-JP when UI text changes (n/a)
  • Docs updated when public API or contributor workflow changes (n/a)

🤖 Generated with Claude Code

A preview re-render while a diagram is still rendering (e.g. when MathJax
fires md:mathjax-ready) started a second mermaid.render with the same
element id. The two runs measured each other's temporary elements and the
cached SVG lost its viewBox, class and max-width, so the diagram rendered
blank. Share the in-flight render per cache key instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🚀 Surge Preview has been successfully deployed!

Preview URL: https://doocs-md-preview-pr-1997.surge.sh

Built with commit ca359df

@yanglbme
yanglbme merged commit 67bba7d into doocs:main Oct 21, 2026
5 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