Skip to content

0.8.32

Choose a tag to compare

@github-actions github-actions released this 31 Aug 06:46
· 22 commits to develop since this release

Updated crossnote to 0.9.32.

Features

  • New setting markdown-preview-enhanced.enablePreviewContextMenu (default true) — Disable it to turn off the custom right-click menu in the preview and fall back to the browser's native context menu with its usual Copy/Paste entries. The custom menu also gains a Copy item at the top when text is selected (the selection is captured as it changes, so clicking the item copies what was selected when the menu opened) and closes on Escape like native menus. Fixes #2356 and #2363. Reported by @andy-clapham and @miblooming.
  • AI translation preview — Translate the current Markdown preview into another language and switch back to the original content (#2353 by @loorr). Translations are cached per Markdown block, so contiguous changed blocks can be retranslated after edits without retranslating the entire document. New commands set the AI translation API key (stored in VS Code SecretStorage), translate the current preview, and show the original content; the preview context menu also gains a Translate / Show Original toggle that switches between the two states. New settings: aiTranslationProvider (provider id such as openai, anthropic, minimax-cn, deepseek), aiTranslationModel, and aiTranslationAutoUpdate (re-translate changed blocks 3 s after typing stops; off by default to avoid unattended API usage).
  • Localize the preview webview UI — The preview's UI widgets (context menu, footer, topbar, backlinks, in-preview markdown editor, image helper, floating actions) now follow the VS Code display language (vscode.env.language), covering the same ten locales as this extension's settings: English, 简体中文, 繁體中文, 日本語, 한국어, Español, Français, Nederlands, Português (Brasil) and Türkçe. The translations live in crossnote; unknown locales and unknown keys fall back to English (then to the key), so a missing translation can never break the UI, and universal terms (HTML, ePub, Pandoc, theme file names, VS Code) stay untranslated.
  • Explicit opt-in for custom preview scripts (markdown-preview-enhanced.enablePreviewScripts) — Restores an escape hatch for the script injection that 0.8.30 removed (crossnote#446). When enabled (default false), <script src> tags in .crossnote/head.html and @import "*.js" file imports load again — but only workspace-local files: resolved paths (symlinks included) cannot escape the workspace, and inline scripts and URL-scheme sources (https://, file://, data:, …) stay blocked. The setting is application-scope (user settings only — a repository's .vscode/settings.json cannot enable it), matching crossnote's rule that untrusted .crossnote/config.js content can never turn the channel on, and it is ignored in untrusted workspaces. HTML/eBook exports continue to strip all scripts unconditionally.
  • Browser/HTML exports follow the reader's system color scheme — Exports used to hardcode the light github page/code theme for every export path whenever printBackground was off. That forced-light behavior is now scoped to paper output (Chrome PDF / Prince), while screen output (Open in Browser, HTML export) embeds the configured theme together with its dark counterpart under @media (prefers-color-scheme: dark) — plus <meta name="color-scheme" content="light dark"> so the page background and GitHub-style <picture> images resolve correctly on dark-OS readers. Ported from @TaurusWood's extension-side PR #2327 (#2271).

Security

  • Add a Content-Security-Policy to the preview webview — The preview webview shipped without any CSP, so nothing constrained what injected content could load or connect to. The new policy restricts scripts and styles to webview resources and https CDNs, blocks object-src/form-action entirely, and leaves images/media/frames permissive since those come from arbitrary user markdown (iframes are already forced into sandbox="" by the sanitizer). Inline script/style remain allowed because crossnote emits its configuration as inline blocks; the executable-script surface is gated by crossnote's script stripping plus the new opt-in flag.
  • Harden @import "*.js" script emission in the preview webview — crossnote's generateJSAndCssFilesForPreview() used to emit <script src> tags for any collected path, including remote https?:// URLs written in note content (reachable when script execution was enabled). Script emission now additionally requires the host opt-in, rejects URL-scheme and protocol-relative sources, and confines resolved paths to the workspace (via realpath, so symlinks cannot escape). Stylesheet imports are unaffected.

Updates

  • Update mermaid to 11.17.2, including the vendored offline preview bundle (now downloaded from the official jsDelivr dist via scripts/update-mermaid-bundle.mjs) and the CDN fallback.

Bug fixes

  • Preserve Preview Only scroll position when switching tabs — Custom-editor previews now retain their webview context while hidden, preventing a reload and scroll-position jump when returning to a rendered Markdown tab. Fixes #2147.
  • Fix "Open in Browser" doing nothing on WSL distros without xdg-utils — crossnote's openFile() unconditionally ran xdg-open on Linux, but WSL has no Linux browser by default and plain Ubuntu images don't even ship xdg-utils, so the spawn failed with ENOENT and nothing opened. On WSL it now tries wslview (wslu) first, then xdg-open (WSLg setups with a real Linux browser), and finally falls back to wslpath -w + explorer.exe — opening the Windows default browser. This also fixes clicked links in the preview opening nothing on the same setups. All spawns remain shell-free, preserving the injection hardening.
  • Fix blockquote/list markers leaking into $$…$$ display math — The block-level math rule scanned the raw document source for the closing $$, so a display-math block inside a blockquote absorbed the > quote markers of its continuation lines and rendered them as greater-than signs inside the formula. The rule now reconstructs the block's logical text line by line via markdown-it's marker-stripped block boundaries, which also stops list-item indentation from leaking into math. Fixes #2361. Reported by @calculus1437.
  • Fix # in project path breaking image loading in preview — crossnote built file:// URLs by string concatenation without percent-encoding, so a # in a directory name (e.g. 2026-06-10#1-AI-platform-arch/) was parsed as a fragment separator by the browser and every image (and @imported script/stylesheet) under it 404'd. URLs are now built via pathToFileURL() (also normalizing Windows backslashes). Fixes crossnote#453. Reported by @Hubbitus.
  • Fix toc: ordered: true front matter option having no effect — crossnote's generateSidebarToCHTML() accepted the ordered option but never read it, so both the [TOC] block and the sidebar TOC always rendered as the default collapsible <details> tree. When toc.ordered: true is set in the front matter, the TOC now renders as a nested ordered list (<ol>/<li>) with browser-provided numbering, in both the document body [TOC] and the sidebar TOC. Fixes crossnote#451. Reported by @KarlYao-SystemDesign.
  • Fix embedded d2 diagrams failing to render when they reference relative images```d2 fences using local assets (e.g. icon: ./icons/x.svg) rendered blank because renderD2 wrote its temp input to os.tmpdir(), and d2 resolves relative image paths against the input file's own directory. The temp input is now written beside the source document (falling back to the temp dir when it is missing or not writable), and fileDirectoryPath is included in the render checksum to avoid cross-folder cache collisions.
  • Fix d2 image/render errors and a missing d2 binary both rendering blank — d2's own "failed to bundle local images … no such file or directory" error was misclassified as a missing binary, so a missing icon silently hid the whole diagram; the heuristic is now limited to a genuine ENOENT/"not recognized as an internal or external command". Separately, when the d2 binary is not installed the ```d2 fence now falls back to a plain-text code block instead of being removed entirely.
  • Fix slow rendering of documents with long lines — crossnote's ^block-id transform's cost grew quadratically with line length, so large documents written one sentence per line could take seconds per preview refresh. It now runs in linear time, including on lines ending in long whitespace runs. (crossnote#455 by @zeyutang)