Skip to content

0.9.34

Choose a tag to compare

@github-actions github-actions released this 05 Sep 17:07
· 6 commits to develop since this release

Improvements

  • Cheaper preview updates while editing — Every preview refresh (each debounced keystroke with live update) copied the full rendered HTML into a React state variable, re-rendering the entire webview component tree with a multi-MB string on large documents. The state was write-only — no component ever read it — so it is removed; the post-update light/dark background re-detection now keys off the existing markdown state instead.
  • In-preview editor: stop accumulating line decorations and trim default editor chrome — The jump-to-line effect re-ran after every preview update while the editor was open and called createDecorationsCollection each time, accumulating a new decoration collection per update; it now reuses a single collection and replaces its content. The minimap (pure render cost in a small inline editor) is disabled and the editor no longer scrolls past the last line.
  • Cache Prism highlighting and KaTeX rendering across preview updates — Every preview refresh re-highlighted every code block with Prism and re-rendered every formula with KaTeX from scratch, so editing a code- or math-heavy note re-processed all of its unchanged blocks on each keystroke. Both renderers now keep a bounded, content-keyed LRU cache (Prism: 200 entries, blocks ≤ 64 KB; KaTeX: 1000 entries, formulas ≤ 16 KB, keyed on the KaTeX config fingerprint so config changes miss the cache). Rendered output is byte-identical. On a 195 KB document with 240 code blocks and 360 formulas this cuts a typical edit-keystroke render from ~540 ms to ~460 ms, with the full re-parse pipeline (dominated by the cheerio enhancement passes) remaining as the next bottleneck.
  • Reuse the sidebar TOC markdown-it instanceparseMD built a fresh markdown-it instance with the full plugin chain (18 plugins) on every render just to generate the sidebar TOC HTML. The instance is now created lazily once per notebook and reused (this.md.options never change after construction).

Bug fixes

  • In-preview editor no longer fetches monaco from a CDN — "Open In-preview Editor" works offline — Right-clicking the preview and choosing Edit Markdown → Open In-preview Editor mounted the editor shell but loaded the actual monaco editor at runtime from cdn.jsdelivr.net (@monaco-editor/loader's default). When that CDN was unreachable — offline, firewalled, or jsdelivr blocked — the editor stayed on "Loading editor..." forever, so the menu item looked like it did nothing (vscode-mpe#2164 reported by @CVStratACGrant). The webview now calls loader.config({ monaco }) with the locally bundled monaco-editor, so the editor opens instantly with zero network requests. monaco-editor is upgraded from 0.43.0 to 0.55.0 (the newest version whose exports map still allows the esm/vs/editor/editor.api.js import this repo's CommonJS TypeScript resolution requires; 0.56 rewrote its subpaths and would need a repo-wide moduleResolution switch).
  • "Open In-preview Editor" no longer silently does nothing when the preview has no visible end-of-document anchor — The menu item attached the editor to the first .final-line element in the page and gave up when none existed. Two visible failures: while a render was in flight the hidden preview element also holds a .final-line copy, so a click there portaled the editor into an invisible element (and the next render pass deleted it), and in zen mode (or when a file has no source map at all) no usable anchor existed. The item now scopes its lookup to the real preview container, skips invisible elements, and — when none is found — appends a fresh anchor at the end of the preview so the editor always opens. The item is now hidden in zen mode, where the in-preview editor cannot be shown at all (like presentation mode).
  • deleteNote(path, true) no longer deletes a file that exists at the path — the alreadyDeleted flag was wired backwards: passing true (which Markdown Preview Enhanced's file watcher does for every deletion event) guaranteed the unlink() branch ran instead of skipping it. When Git removed and then recreated a Markdown file during a branch checkout, the watcher's delayed deletion notification deleted the freshly recreated replacement — data loss that surfaced as unstaged deletions in git status. In the common case where the file really was gone, unlink() also rejected with ENOENT before the note's relations and search entry were cleaned up. deleteNote now only unlinks when asked to perform the deletion itself (alreadyDeleted: false and the file still exists); the internal bookkeeping always runs (#481 reported by @Josh-Cena).