Skip to content

fix: renderAsync honors monkey-patched renderer.render - #34

Merged
serkodev merged 1 commit into
serkodev:mainfrom
ShenQingchuan:fix/render-async-honor-render-patch
Aug 22, 2026
Merged

serkodev merged 1 commit into
serkodev:mainfrom
ShenQingchuan:fix/render-async-honor-render-patch

Conversation

@ShenQingchuan

Copy link
Copy Markdown
Contributor

Fixes #33

Problem

renderAsync() calls renderer.renderAsync() directly, while render() goes through renderer.render(). Plugins that monkey-patch md.renderer.render — a widespread markdown-it ecosystem pattern, e.g. @mdit-vue/plugin-headers (used by VitePress to extract page headers into env) — are silently bypassed under renderAsync(), and their env writes never happen.

Fix

Renderer.renderAsync now detects whether render has been overridden or monkey-patched on the instance (this.render !== Renderer.prototype.render) and delegates to it, so patched logic applies on the async path too.

Trade-off, made explicit: on the delegated sync path, async rules still throw the descriptive async rule detected error — same behavior as render(). Plugins that patch render are synchronous collectors by nature, so this combination is rare; when it does happen, the error message points the way.

Tests

Three new tests in tests/renderer.test.ts:

  • renderAsync honors a monkey-patched render (env write lands, output correct)
  • the parallel path still runs when render is untouched
  • a patched render combined with an async rule still surfaces the async-rule error

Full suite: 963 passed (960 baseline + 3 new), lint clean.

Plugins in the markdown-it ecosystem commonly wrap `md.renderer.render`
to collect data into `env` (e.g. @mdit-vue/plugin-headers, used by
VitePress). Since `renderAsync()` calls `renderer.renderAsync()`
directly, those wrappers were silently bypassed and `env` came back
empty.

`Renderer.renderAsync` now detects an overridden/patched `render` on the
instance and delegates to it, so patched logic applies to async
rendering as well. Async rules still throw the descriptive
"async rule detected" error on that path, same as `render()`.
@ShenQingchuan
ShenQingchuan force-pushed the fix/render-async-honor-render-patch branch from 1c63cc5 to 2c907c7 Compare August 21, 2026 16:22
@serkodev
serkodev merged commit 8fa2801 into serkodev:main Aug 22, 2026
4 checks passed
@codspeed

codspeed Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing ShenQingchuan:fix/render-async-honor-render-patch (2c907c7) with main (1c1c7cb)

Open in CodSpeed

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.

renderAsync() bypasses renderer.render, silently breaking plugins that wrap it (e.g. @mdit-vue)

2 participants