diff --git a/.changeset/integrator-sub-extension-context.md b/.changeset/integrator-sub-extension-context.md new file mode 100644 index 00000000..d2ce6a8e --- /dev/null +++ b/.changeset/integrator-sub-extension-context.md @@ -0,0 +1,5 @@ +--- +'@prosemark/vscode-extension-integrator': patch +--- + +Pass sub-extension callback context as a single object including `webview`, so companion extensions can resolve webview resource URLs. diff --git a/.changeset/latex-vite-plugin-mathjax.md b/.changeset/latex-vite-plugin-mathjax.md new file mode 100644 index 00000000..17fc9bcb --- /dev/null +++ b/.changeset/latex-vite-plugin-mathjax.md @@ -0,0 +1,5 @@ +--- +'@prosemark/latex': patch +--- + +Add `@prosemark/latex/vite-plugin-mathjax` to copy configurable paths from the `mathjax` npm package into a Vite build output. diff --git a/.changeset/vscode-latex-mathjax-url-import.md b/.changeset/vscode-latex-mathjax-url-import.md new file mode 100644 index 00000000..be0278e5 --- /dev/null +++ b/.changeset/vscode-latex-mathjax-url-import.md @@ -0,0 +1,5 @@ +--- +vscode-prosemark-latex-integration: patch +--- + +Fix LaTeX math rendering issue in the VS Code extension webview by self-hosting MathJax inside the extension instead of using a CDN. diff --git a/apps/docs/src/content/docs/guides/latex-math.md b/apps/docs/src/content/docs/guides/latex-math.md index c7307f63..85317e06 100644 --- a/apps/docs/src/content/docs/guides/latex-math.md +++ b/apps/docs/src/content/docs/guides/latex-math.md @@ -76,7 +76,7 @@ If you assemble markdown extensions yourself (without `prosemarkMarkdownSyntaxEx ## How MathJax is loaded -In **`url-import`** mode (the default), this package sets `window.MathJax` with `skipStartupTypeset: true` and loader paths, then dynamically imports the startup bundle. Do not set conflicting `tex` / `svg` / `chtml` options on `window.MathJax` yourself before that runs. +In **`url-import`** mode (the default), this package sets `window.MathJax` with `startup.typeset: false` and loader paths, then dynamically imports the startup bundle. Do not set conflicting `tex` / `svg` / `chtml` options on `window.MathJax` yourself before that runs. ### Runtime URL — `mathJaxLoadMode: 'url-import'` (default) @@ -113,6 +113,27 @@ import 'mathjax/tex-svg.js'; }), ``` +**Accessibility / speech worker:** the combined startup bundle includes MathJax a11y support and loads **`sre/speech-worker.js` as a web worker** at runtime. Your bundler typically only ships the main JS file, so the worker is missing unless you also copy `sre/` and configure MathJax’s loader paths, or use **`url-import`** with a self-hosted `mathjax/` folder (see [`@prosemark/latex/vite-plugin-mathjax`](https://www.npmjs.com/package/@prosemark/latex) on npm). + +If you do not need speech or enrichment and want to avoid shipping the `sre/` worker, configure `window.MathJax` **before** importing MathJax: + +```javascript +window.MathJax = { + startup: { + typeset: false, + }, + options: { + enableSpeech: false, + enableBraille: false, + enableEnrichment: false, + menuOptions: { + settings: { enrich: false, speech: false, braille: false }, + }, + }, +}; +import 'mathjax/tex-svg.js'; +``` + Use one load mode per page (`url-import` or `static-import`, not both). ## Block vs inline diff --git a/apps/vscode-extensions/core/src/sub-extensions/core.ts b/apps/vscode-extensions/core/src/sub-extensions/core.ts index 8abf0f0f..4bcc5bc2 100644 --- a/apps/vscode-extensions/core/src/sub-extensions/core.ts +++ b/apps/vscode-extensions/core/src/sub-extensions/core.ts @@ -249,7 +249,7 @@ export class Core implements SubExtension< export function createCore( extensionUri: vscode.Uri, ): SubExtensionCallback { - return (document, callProcAndForget, _callProcWithReturnValue) => { + return ({ document, callProcAndForget }) => { return new Core(extensionUri, document, callProcAndForget); }; } diff --git a/apps/vscode-extensions/core/src/sub-extensions/word-count-status-bar-item.ts b/apps/vscode-extensions/core/src/sub-extensions/word-count-status-bar-item.ts index 5de75895..e8272973 100644 --- a/apps/vscode-extensions/core/src/sub-extensions/word-count-status-bar-item.ts +++ b/apps/vscode-extensions/core/src/sub-extensions/word-count-status-bar-item.ts @@ -67,7 +67,7 @@ export const createWordCountStatusBarItem: SubExtensionCallback< typeof extId, Record, WordCountVSCodeProcs -> = (document) => { +> = ({ document }) => { return new WordCountStatusBarItem(document); }; diff --git a/apps/vscode-extensions/cspell-integration/src/sub-extension.ts b/apps/vscode-extensions/cspell-integration/src/sub-extension.ts index 4e328cb9..81d8cba0 100644 --- a/apps/vscode-extensions/cspell-integration/src/sub-extension.ts +++ b/apps/vscode-extensions/cspell-integration/src/sub-extension.ts @@ -151,7 +151,7 @@ export function createCSpellIntegration( extensionUri: vscode.Uri, cSpellApi: CSpell.ExtensionApi, ): SubExtensionCallback { - return (document, callProcAndForget, callProcWithReturnValue) => { + return ({ document, callProcAndForget, callProcWithReturnValue }) => { return new CSpellIntegration( extensionUri, cSpellApi, diff --git a/apps/vscode-extensions/latex-integration/README.md b/apps/vscode-extensions/latex-integration/README.md index 158a443b..1540e464 100644 --- a/apps/vscode-extensions/latex-integration/README.md +++ b/apps/vscode-extensions/latex-integration/README.md @@ -24,4 +24,35 @@ Please report bugs on the [GitHub issues page](https://github.com/jsimonrichard/ ## Developing this extension -After `bun install`, run `bun run build`. **Vite** produces `dist/webview/webview.js` with MathJax SVG output inlined into that bundle (see `src/webview/main.ts`). Bump the **`mathjax`** dependency when you want a different MathJax version. +After `bun install`, run `bun run build`. **Vite** produces `dist/webview/webview.js` and copies `tex-svg.js` plus `sre/` from the **`mathjax`** npm package into `dist/webview/mathjax/` via `@prosemark/latex/vite-plugin-mathjax`. The webview loads MathJax with `url-import` from that folder. Bump the **`mathjax`** dependency when you want a different MathJax version. + +### MathJax load modes + +This extension uses **`url-import`**: the extension host passes a webview URL for `dist/webview/mathjax/`, and the webview dynamically imports `tex-svg.js` from there. That keeps `webview.js` small and lets MathJax load `sre/speech-worker.js` as a separate file (copied by the Vite plugin). + +If you switch to **`static-import`** (`import 'mathjax/tex-svg.js'` bundled into `webview.js`), note that the combined `tex-svg` startup includes MathJax **a11y** support. It tries to load **`sre/speech-worker.js` as a web worker** at runtime. A bundler usually only emits your main bundle, so the worker is missing unless you handle it explicitly. + +Pick one approach: + +1. **Disable a11y** (simplest with `static-import` when you are not copying `sre/`) — set options on `window.MathJax` **before** the static import: + + ```ts + window.MathJax = { + startup: { + typeset: false, + }, + options: { + enableSpeech: false, + enableBraille: false, + enableEnrichment: false, + menuOptions: { + settings: { enrich: false, speech: false, braille: false }, + }, + }, + }; + import 'mathjax/tex-svg.js'; + ``` + +2. **Keep a11y** — copy `sre/` from the `mathjax` npm package next to where `tex-svg.js` is served, and point MathJax at that root (for example with `preconfigureMathJaxLoader` and `loader.paths.mathjax`, or `@prosemark/latex/vite-plugin-mathjax` with `url-import`). The worker cannot be inlined into an IIFE the way the main startup script can. + +The shipped extension uses **url-import + copied `sre/`** so math renders without bundling ~1.8 MB of MathJax into `webview.js`. diff --git a/apps/vscode-extensions/latex-integration/src/common.ts b/apps/vscode-extensions/latex-integration/src/common.ts index 9316c285..7ca9d578 100644 --- a/apps/vscode-extensions/latex-integration/src/common.ts +++ b/apps/vscode-extensions/latex-integration/src/common.ts @@ -1,6 +1,10 @@ /** VS Code extension host: no procedures exposed to the webview for LaTeX. */ export type VSCodeExtensionProcMap = Record; +export interface LatexSetupConfig { + mathJaxPackageUrl: string; +} + export interface WebviewProcMap { - setup: () => Promise; + setup: (config: LatexSetupConfig) => Promise; } diff --git a/apps/vscode-extensions/latex-integration/src/global.d.ts b/apps/vscode-extensions/latex-integration/src/global.d.ts index c0a40625..35306c6f 100644 --- a/apps/vscode-extensions/latex-integration/src/global.d.ts +++ b/apps/vscode-extensions/latex-integration/src/global.d.ts @@ -1,3 +1 @@ declare module '*.css'; - -declare module 'mathjax/tex-svg.js'; diff --git a/apps/vscode-extensions/latex-integration/src/sub-extension.ts b/apps/vscode-extensions/latex-integration/src/sub-extension.ts index b19142c2..9da276a8 100644 --- a/apps/vscode-extensions/latex-integration/src/sub-extension.ts +++ b/apps/vscode-extensions/latex-integration/src/sub-extension.ts @@ -14,15 +14,18 @@ export class LatexIntegration implements SubExtension< VSCodeExtensionProcMap > { #extensionUri: vscode.Uri; + #webview: vscode.Webview; #callProcWithReturnValue: CallProcWithReturnValue; constructor( extensionUri: vscode.Uri, + webview: vscode.Webview, _document: vscode.TextDocument, _callProcAndForget: CallProc, callProcWithReturnValue: CallProcWithReturnValue, ) { this.#extensionUri = extensionUri; + this.#webview = webview; this.#callProcWithReturnValue = callProcWithReturnValue; } @@ -52,8 +55,20 @@ export class LatexIntegration implements SubExtension< return [this.#extensionUri]; } + #getMathJaxPackageUrl(): string { + const mathJaxUri = vscode.Uri.joinPath( + this.#extensionUri, + 'dist', + 'webview', + 'mathjax', + ); + return this.#webview.asWebviewUri(mathJaxUri).toString().replace(/\/$/, ''); + } + onReady(): void { - void this.#callProcWithReturnValue('setup').catch((e: unknown) => { + void this.#callProcWithReturnValue('setup', { + mathJaxPackageUrl: this.#getMathJaxPackageUrl(), + }).catch((e: unknown) => { console.error(e); }); } @@ -64,9 +79,15 @@ export class LatexIntegration implements SubExtension< export function createLatexIntegration( extensionUri: vscode.Uri, ): SubExtensionCallback { - return (document, callProcAndForget, callProcWithReturnValue) => { + return ({ + document, + callProcAndForget, + callProcWithReturnValue, + webview, + }) => { return new LatexIntegration( extensionUri, + webview, document, callProcAndForget, callProcWithReturnValue, diff --git a/apps/vscode-extensions/latex-integration/src/webview/main.ts b/apps/vscode-extensions/latex-integration/src/webview/main.ts index 2417e67d..23a4df43 100644 --- a/apps/vscode-extensions/latex-integration/src/webview/main.ts +++ b/apps/vscode-extensions/latex-integration/src/webview/main.ts @@ -7,13 +7,34 @@ import type { CallbackFromProcMap, WebviewVSCodeApiWithPostMessage, } from '@prosemark/vscode-extension-integrator/types'; +import { + latexMarkdownEditorExtensions, + latexMarkdownSyntaxTheme, +} from '@prosemark/latex'; import './style.css'; +type LatexWebviewVscodeApi = WebviewVSCodeApiWithPostMessage< + CallbackFromProcMap<'latex-integration', WebviewProcMap> +>; + +const isLatexWebviewVscodeApi = ( + value: unknown, +): value is LatexWebviewVscodeApi => { + if (typeof value !== 'object' || value === null) { + return false; + } + if (!('postMessage' in value)) { + return false; + } + return typeof value.postMessage === 'function'; +}; + let latexSetupDone = false; const procs: WebviewProcMap = { - setup: async () => { + // eslint-disable-next-line @typescript-eslint/require-await -- async setup matches other integrations + setup: async ({ mathJaxPackageUrl }) => { const view = window.proseMark?.view; if (!view) { console.warn('[ProseMark] latex-integration setup: no view'); @@ -22,19 +43,17 @@ const procs: WebviewProcMap = { if (latexSetupDone) { return; } + latexSetupDone = true; try { - // Bundle MathJax tex-svg into webview.js (Vite resolves `mathjax/...` from npm). - await import('mathjax/tex-svg.js'); - const latex = await import('@prosemark/latex'); appendToExtraCodeMirrorExtensions(view, [ - ...latex.latexMarkdownSyntaxTheme, - ...latex.latexMarkdownEditorExtensions({ - mathJaxLoadMode: 'static-import', + ...latexMarkdownSyntaxTheme, + ...latexMarkdownEditorExtensions({ + mathJaxLoadMode: 'url-import', + mathJaxPackageUrl, output: 'svg', }), ]); - latexSetupDone = true; } catch (err: unknown) { console.error('[ProseMark] latex-integration setup failed', err); throw err; @@ -42,10 +61,9 @@ const procs: WebviewProcMap = { }, }; -registerWebviewMessageHandler( - 'latex-integration', - procs, - window.proseMark?.vscode as WebviewVSCodeApiWithPostMessage< - CallbackFromProcMap<'latex-integration', WebviewProcMap> - >, -); +const vscodeApi = window.proseMark?.vscode; +if (isLatexWebviewVscodeApi(vscodeApi)) { + registerWebviewMessageHandler('latex-integration', procs, vscodeApi); +} else { + console.error('[ProseMark] latex-integration: vscode API is not available'); +} diff --git a/apps/vscode-extensions/latex-integration/vite.config.ts b/apps/vscode-extensions/latex-integration/vite.config.mts similarity index 59% rename from apps/vscode-extensions/latex-integration/vite.config.ts rename to apps/vscode-extensions/latex-integration/vite.config.mts index 2f7b1d65..5b7f79b1 100644 --- a/apps/vscode-extensions/latex-integration/vite.config.ts +++ b/apps/vscode-extensions/latex-integration/vite.config.mts @@ -1,9 +1,21 @@ import { defineConfig } from 'vite'; import { resolve } from 'node:path'; import proseMarkVSCodeExtensionIntegratorPlugin from '@prosemark/vscode-extension-integrator/rolldown-plugin'; +import { + copyMathJaxAssets, + MATHJAX_TEX_SVG_COPY_ENTRIES, +} from '@prosemark/latex/vite-plugin-mathjax'; + +const webviewOutDir = resolve(__dirname, 'dist/webview'); export default defineConfig({ - plugins: [proseMarkVSCodeExtensionIntegratorPlugin()], + plugins: [ + proseMarkVSCodeExtensionIntegratorPlugin(), + copyMathJaxAssets({ + outDir: webviewOutDir, + copy: MATHJAX_TEX_SVG_COPY_ENTRIES, + }), + ], build: { outDir: 'dist/webview', target: 'es2022', diff --git a/bun.lock b/bun.lock index 60ff80c7..3912aa6b 100644 --- a/bun.lock +++ b/bun.lock @@ -261,12 +261,15 @@ "tsdown": "^0.15.6", "typescript": "^5.9.3", "typescript-eslint": "^8.50.0", + "vite": "^8.0.5", }, "peerDependencies": { "mathjax": "^4.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", }, "optionalPeers": [ "mathjax", + "vite", ], }, "packages/paste-rich-text": { @@ -2423,7 +2426,7 @@ "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], - "vite": ["vite@5.4.21", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="], + "vite": ["vite@8.0.14", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.15", "rolldown": "1.0.2", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.18", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw=="], "vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="], @@ -2619,6 +2622,10 @@ "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], + "debug-vsc-extn-in-web/vite": ["vite@5.4.21", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="], + + "demo/vite": ["vite@5.4.21", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="], + "dir-glob/path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], "encoding-sniffer/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], @@ -2709,16 +2716,12 @@ "unstorage/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], - "vscode-prosemark/tsdown": ["tsdown@0.14.2", "", { "dependencies": { "ansis": "^4.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.1", "diff": "^8.0.2", "empathic": "^2.0.0", "hookable": "^5.5.3", "rolldown": "latest", "rolldown-plugin-dts": "^0.15.8", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.14", "tree-kill": "^1.2.2", "unconfig": "^7.3.3" }, "peerDependencies": { "@arethetypeswrong/core": "^0.18.1", "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["@arethetypeswrong/core", "publint", "typescript", "unplugin-lightningcss", "unplugin-unused"], "bin": { "tsdown": "dist/run.mjs" } }, "sha512-6ThtxVZoTlR5YJov5rYvH8N1+/S/rD/pGfehdCLGznGgbxz+73EASV1tsIIZkLw2n+SXcERqHhcB/OkyxdKv3A=="], + "vite/rolldown": ["rolldown@1.0.2", "", { "dependencies": { "@oxc-project/types": "=0.132.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.2", "@rolldown/binding-darwin-arm64": "1.0.2", "@rolldown/binding-darwin-x64": "1.0.2", "@rolldown/binding-freebsd-x64": "1.0.2", "@rolldown/binding-linux-arm-gnueabihf": "1.0.2", "@rolldown/binding-linux-arm64-gnu": "1.0.2", "@rolldown/binding-linux-arm64-musl": "1.0.2", "@rolldown/binding-linux-ppc64-gnu": "1.0.2", "@rolldown/binding-linux-s390x-gnu": "1.0.2", "@rolldown/binding-linux-x64-gnu": "1.0.2", "@rolldown/binding-linux-x64-musl": "1.0.2", "@rolldown/binding-openharmony-arm64": "1.0.2", "@rolldown/binding-wasm32-wasi": "1.0.2", "@rolldown/binding-win32-arm64-msvc": "1.0.2", "@rolldown/binding-win32-x64-msvc": "1.0.2" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g=="], - "vscode-prosemark/vite": ["vite@8.0.14", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.15", "rolldown": "1.0.2", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.18", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw=="], + "vscode-prosemark/tsdown": ["tsdown@0.14.2", "", { "dependencies": { "ansis": "^4.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.1", "diff": "^8.0.2", "empathic": "^2.0.0", "hookable": "^5.5.3", "rolldown": "latest", "rolldown-plugin-dts": "^0.15.8", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.14", "tree-kill": "^1.2.2", "unconfig": "^7.3.3" }, "peerDependencies": { "@arethetypeswrong/core": "^0.18.1", "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["@arethetypeswrong/core", "publint", "typescript", "unplugin-lightningcss", "unplugin-unused"], "bin": { "tsdown": "dist/run.mjs" } }, "sha512-6ThtxVZoTlR5YJov5rYvH8N1+/S/rD/pGfehdCLGznGgbxz+73EASV1tsIIZkLw2n+SXcERqHhcB/OkyxdKv3A=="], "vscode-prosemark-cspell-integration/tsdown": ["tsdown@0.14.2", "", { "dependencies": { "ansis": "^4.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.1", "diff": "^8.0.2", "empathic": "^2.0.0", "hookable": "^5.5.3", "rolldown": "latest", "rolldown-plugin-dts": "^0.15.8", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.14", "tree-kill": "^1.2.2", "unconfig": "^7.3.3" }, "peerDependencies": { "@arethetypeswrong/core": "^0.18.1", "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["@arethetypeswrong/core", "publint", "typescript", "unplugin-lightningcss", "unplugin-unused"], "bin": { "tsdown": "dist/run.mjs" } }, "sha512-6ThtxVZoTlR5YJov5rYvH8N1+/S/rD/pGfehdCLGznGgbxz+73EASV1tsIIZkLw2n+SXcERqHhcB/OkyxdKv3A=="], - "vscode-prosemark-cspell-integration/vite": ["vite@8.0.14", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.15", "rolldown": "1.0.2", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.18", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw=="], - - "vscode-prosemark-latex-integration/vite": ["vite@8.0.14", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.15", "rolldown": "1.0.2", "tinyglobby": "^0.2.16" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.18", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw=="], - "whatwg-encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], "widest-line/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], @@ -2889,15 +2892,41 @@ "unstorage/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], - "vscode-prosemark-cspell-integration/tsdown/rolldown-plugin-dts": ["rolldown-plugin-dts@0.15.10", "", { "dependencies": { "@babel/generator": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "ast-kit": "^2.1.2", "birpc": "^2.5.0", "debug": "^4.4.1", "dts-resolver": "^2.1.2", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~3.0.3" }, "optionalPeers": ["@typescript/native-preview", "typescript", "vue-tsc"] }, "sha512-8cPVAVQUo9tYAoEpc3jFV9RxSil13hrRRg8cHC9gLXxRMNtWPc1LNMSDXzjyD+5Vny49sDZH77JlXp/vlc4I3g=="], + "vite/rolldown/@oxc-project/types": ["@oxc-project/types@0.132.0", "", {}, "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ=="], - "vscode-prosemark-cspell-integration/vite/rolldown": ["rolldown@1.0.2", "", { "dependencies": { "@oxc-project/types": "=0.132.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.2", "@rolldown/binding-darwin-arm64": "1.0.2", "@rolldown/binding-darwin-x64": "1.0.2", "@rolldown/binding-freebsd-x64": "1.0.2", "@rolldown/binding-linux-arm-gnueabihf": "1.0.2", "@rolldown/binding-linux-arm64-gnu": "1.0.2", "@rolldown/binding-linux-arm64-musl": "1.0.2", "@rolldown/binding-linux-ppc64-gnu": "1.0.2", "@rolldown/binding-linux-s390x-gnu": "1.0.2", "@rolldown/binding-linux-x64-gnu": "1.0.2", "@rolldown/binding-linux-x64-musl": "1.0.2", "@rolldown/binding-openharmony-arm64": "1.0.2", "@rolldown/binding-wasm32-wasi": "1.0.2", "@rolldown/binding-win32-arm64-msvc": "1.0.2", "@rolldown/binding-win32-x64-msvc": "1.0.2" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g=="], + "vite/rolldown/@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.2", "", { "os": "android", "cpu": "arm64" }, "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ=="], - "vscode-prosemark-latex-integration/vite/rolldown": ["rolldown@1.0.2", "", { "dependencies": { "@oxc-project/types": "=0.132.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.2", "@rolldown/binding-darwin-arm64": "1.0.2", "@rolldown/binding-darwin-x64": "1.0.2", "@rolldown/binding-freebsd-x64": "1.0.2", "@rolldown/binding-linux-arm-gnueabihf": "1.0.2", "@rolldown/binding-linux-arm64-gnu": "1.0.2", "@rolldown/binding-linux-arm64-musl": "1.0.2", "@rolldown/binding-linux-ppc64-gnu": "1.0.2", "@rolldown/binding-linux-s390x-gnu": "1.0.2", "@rolldown/binding-linux-x64-gnu": "1.0.2", "@rolldown/binding-linux-x64-musl": "1.0.2", "@rolldown/binding-openharmony-arm64": "1.0.2", "@rolldown/binding-wasm32-wasi": "1.0.2", "@rolldown/binding-win32-arm64-msvc": "1.0.2", "@rolldown/binding-win32-x64-msvc": "1.0.2" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g=="], + "vite/rolldown/@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w=="], - "vscode-prosemark/tsdown/rolldown-plugin-dts": ["rolldown-plugin-dts@0.15.10", "", { "dependencies": { "@babel/generator": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "ast-kit": "^2.1.2", "birpc": "^2.5.0", "debug": "^4.4.1", "dts-resolver": "^2.1.2", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~3.0.3" }, "optionalPeers": ["@typescript/native-preview", "typescript", "vue-tsc"] }, "sha512-8cPVAVQUo9tYAoEpc3jFV9RxSil13hrRRg8cHC9gLXxRMNtWPc1LNMSDXzjyD+5Vny49sDZH77JlXp/vlc4I3g=="], + "vite/rolldown/@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA=="], + + "vite/rolldown/@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA=="], + + "vite/rolldown/@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w=="], + + "vite/rolldown/@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig=="], + + "vite/rolldown/@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw=="], + + "vite/rolldown/@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA=="], + + "vite/rolldown/@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ=="], + + "vite/rolldown/@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ=="], + + "vite/rolldown/@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw=="], + + "vite/rolldown/@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w=="], - "vscode-prosemark/vite/rolldown": ["rolldown@1.0.2", "", { "dependencies": { "@oxc-project/types": "=0.132.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.2", "@rolldown/binding-darwin-arm64": "1.0.2", "@rolldown/binding-darwin-x64": "1.0.2", "@rolldown/binding-freebsd-x64": "1.0.2", "@rolldown/binding-linux-arm-gnueabihf": "1.0.2", "@rolldown/binding-linux-arm64-gnu": "1.0.2", "@rolldown/binding-linux-arm64-musl": "1.0.2", "@rolldown/binding-linux-ppc64-gnu": "1.0.2", "@rolldown/binding-linux-s390x-gnu": "1.0.2", "@rolldown/binding-linux-x64-gnu": "1.0.2", "@rolldown/binding-linux-x64-musl": "1.0.2", "@rolldown/binding-openharmony-arm64": "1.0.2", "@rolldown/binding-wasm32-wasi": "1.0.2", "@rolldown/binding-win32-arm64-msvc": "1.0.2", "@rolldown/binding-win32-x64-msvc": "1.0.2" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g=="], + "vite/rolldown/@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.2", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ=="], + + "vite/rolldown/@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A=="], + + "vite/rolldown/@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ=="], + + "vscode-prosemark-cspell-integration/tsdown/rolldown-plugin-dts": ["rolldown-plugin-dts@0.15.10", "", { "dependencies": { "@babel/generator": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "ast-kit": "^2.1.2", "birpc": "^2.5.0", "debug": "^4.4.1", "dts-resolver": "^2.1.2", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~3.0.3" }, "optionalPeers": ["@typescript/native-preview", "typescript", "vue-tsc"] }, "sha512-8cPVAVQUo9tYAoEpc3jFV9RxSil13hrRRg8cHC9gLXxRMNtWPc1LNMSDXzjyD+5Vny49sDZH77JlXp/vlc4I3g=="], + + "vscode-prosemark/tsdown/rolldown-plugin-dts": ["rolldown-plugin-dts@0.15.10", "", { "dependencies": { "@babel/generator": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "ast-kit": "^2.1.2", "birpc": "^2.5.0", "debug": "^4.4.1", "dts-resolver": "^2.1.2", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~3.0.3" }, "optionalPeers": ["@typescript/native-preview", "typescript", "vue-tsc"] }, "sha512-8cPVAVQUo9tYAoEpc3jFV9RxSil13hrRRg8cHC9gLXxRMNtWPc1LNMSDXzjyD+5Vny49sDZH77JlXp/vlc4I3g=="], "widest-line/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], @@ -2973,102 +3002,6 @@ "typedoc/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - "vscode-prosemark-cspell-integration/vite/rolldown/@oxc-project/types": ["@oxc-project/types@0.132.0", "", {}, "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.2", "", { "os": "android", "cpu": "arm64" }, "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.2", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A=="], - - "vscode-prosemark-cspell-integration/vite/rolldown/@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@oxc-project/types": ["@oxc-project/types@0.132.0", "", {}, "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.2", "", { "os": "android", "cpu": "arm64" }, "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.2", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A=="], - - "vscode-prosemark-latex-integration/vite/rolldown/@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ=="], - - "vscode-prosemark/vite/rolldown/@oxc-project/types": ["@oxc-project/types@0.132.0", "", {}, "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.2", "", { "os": "android", "cpu": "arm64" }, "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.2", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A=="], - - "vscode-prosemark/vite/rolldown/@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ=="], - "widest-line/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "@manypkg/find-root/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], diff --git a/packages/latex/README.md b/packages/latex/README.md index 857d83b2..471a77f3 100644 --- a/packages/latex/README.md +++ b/packages/latex/README.md @@ -25,7 +25,7 @@ Optionally add **`mathjax`** if you want to self-host it from npm (see below). I MathJax is **not** bundled into `@prosemark/latex`. See **How to load MathJax** below for **`url-import`** (default) vs **`static-import`**. -Before the dynamic import runs in **`url-import`** mode, this package sets `window.MathJax = { options: { skipStartupTypeset: true }, loader: { paths: { … } } }`. MathJax’s startup must own the full `tex` / `svg` / `chtml` configuration. +Before the dynamic import runs in **`url-import`** mode, this package sets `window.MathJax = { startup: { typeset: false }, loader: { paths: { … } } }`. MathJax’s startup must own the full `tex` / `svg` / `chtml` configuration. ### How to load MathJax @@ -60,6 +60,27 @@ latexMarkdownEditorExtensions({ }); ``` +**Accessibility / speech worker:** the combined `tex-svg.js` / `tex-chtml.js` startup includes MathJax a11y extensions. At runtime it loads **`sre/speech-worker.js` as a separate web worker**. Bundlers usually only emit your main bundle, so the worker is missing unless you copy `sre/` from the `mathjax` package and configure `loader.paths.mathjax`, or use **`url-import`** with `@prosemark/latex/vite-plugin-mathjax` instead. + +If you do not need speech or enrichment and want to avoid shipping the `sre/` worker, disable a11y by setting `window.MathJax.options` **before** the static import: + +```ts +window.MathJax = { + startup: { + typeset: false, + }, + options: { + enableSpeech: false, + enableBraille: false, + enableEnrichment: false, + menuOptions: { + settings: { enrich: false, speech: false, braille: false }, + }, + }, +}; +import 'mathjax/tex-svg.js'; +``` + **Note:** `@prosemark/latex` does not read `node_modules` at runtime for `url-import`. Serving a copied tree under `public/` (or similar) is enough for self-hosting. You still need the **parser** section above so `Math` nodes exist. ## Usage diff --git a/packages/latex/eslint.config.ts b/packages/latex/eslint.config.ts index a76972d8..480ad335 100644 --- a/packages/latex/eslint.config.ts +++ b/packages/latex/eslint.config.ts @@ -5,7 +5,7 @@ import { defineConfig } from 'eslint/config'; export default defineConfig([ ...baseConfig, { - files: ['**/*.ts'], + files: ['**/*.ts', '**/*.mts'], languageOptions: { parserOptions: { tsconfigRootDir: import.meta.dirname, diff --git a/packages/latex/lib/main.ts b/packages/latex/lib/main.ts index 0487746c..0c320b37 100644 --- a/packages/latex/lib/main.ts +++ b/packages/latex/lib/main.ts @@ -97,11 +97,11 @@ interface MathJaxReady { } interface MathJaxConfig { - options?: { skipStartupTypeset?: boolean }; + startup?: { typeset?: boolean }; loader?: { paths?: Record }; + options?: Record; tex?: Record; svg?: Record; - startup?: Record; } declare global { @@ -130,8 +130,8 @@ export function preconfigureMathJaxLoader(packageUrl: string): void { ); } window.MathJax = { - options: { - skipStartupTypeset: true, + startup: { + typeset: false, }, loader: { paths: { @@ -213,8 +213,8 @@ const ensureMathJax = ( // modules from the app origin (`/input/...`, etc.) and `tex2svgPromise` // never resolves. Point `mathjax` at the published package tree instead. window.MathJax = { - options: { - skipStartupTypeset: true, + startup: { + typeset: false, }, loader: { paths: { diff --git a/packages/latex/lib/vite-plugin-mathjax.ts b/packages/latex/lib/vite-plugin-mathjax.ts new file mode 100644 index 00000000..8f0944b6 --- /dev/null +++ b/packages/latex/lib/vite-plugin-mathjax.ts @@ -0,0 +1,60 @@ +import { cpSync, existsSync, mkdirSync, statSync } from 'node:fs'; +import { createRequire } from 'node:module'; +import { dirname, resolve } from 'node:path'; +import type { Plugin } from 'vite'; + +const require = createRequire(import.meta.url); + +/** Default copy set for self-hosted `tex-svg` + speech worker (VS Code webviews, static apps). */ +export const MATHJAX_TEX_SVG_COPY_ENTRIES = ['tex-svg.js', 'sre'] as const; + +export interface CopyMathJaxAssetsOptions { + /** Directory Vite writes bundles to (e.g. `dist/webview`). */ + outDir: string; + /** + * Folder under `outDir` where MathJax files are placed. + * @default 'mathjax' + */ + destDir?: string; + /** + * Paths relative to the `mathjax` npm package root (files or directories). + * Each entry is copied to `{outDir}/{destDir}/{entry}`. + */ + copy: readonly string[]; +} + +/** Absolute path to the installed `mathjax` package root. */ +export const resolveMathJaxPackageRoot = (): string => + resolve(require.resolve('mathjax/package.json'), '..'); + +const copyPath = (src: string, dest: string): void => { + if (!existsSync(src)) { + throw new Error(`MathJax copy source not found: ${src}`); + } + mkdirSync(dirname(dest), { recursive: true }); + if (statSync(src).isDirectory()) { + cpSync(src, dest, { recursive: true }); + } else { + cpSync(src, dest); + } +}; + +/** + * Vite plugin: copy selected files/directories from the `mathjax` npm package + * into your build output (for self-hosted {@link mathJaxLoadMode} `url-import`). + */ +export function copyMathJaxAssets(options: CopyMathJaxAssetsOptions): Plugin { + const { outDir, destDir = 'mathjax', copy } = options; + + return { + name: '@prosemark/latex/copy-mathjax-assets', + closeBundle() { + const mathjaxRoot = resolveMathJaxPackageRoot(); + const destRoot = resolve(outDir, destDir); + + for (const entry of copy) { + copyPath(resolve(mathjaxRoot, entry), resolve(destRoot, entry)); + } + }, + }; +} diff --git a/packages/latex/package.json b/packages/latex/package.json index 6ef41c38..7080dfba 100644 --- a/packages/latex/package.json +++ b/packages/latex/package.json @@ -24,6 +24,10 @@ ".": { "types": "./dist/main.d.ts", "import": "./dist/main.js" + }, + "./vite-plugin-mathjax": { + "types": "./dist/vite-plugin-mathjax.d.ts", + "import": "./dist/vite-plugin-mathjax.js" } }, "main": "./dist/main.js", @@ -48,11 +52,15 @@ "@prosemark/core": "workspace:*" }, "peerDependencies": { - "mathjax": "^4.0.0" + "mathjax": "^4.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "mathjax": { "optional": true + }, + "vite": { + "optional": true } }, "devDependencies": { @@ -62,6 +70,7 @@ "eslint": "^9.39.2", "tsdown": "^0.15.6", "typescript": "^5.9.3", - "typescript-eslint": "^8.50.0" + "typescript-eslint": "^8.50.0", + "vite": "^8.0.5" } } diff --git a/packages/latex/tests/mathjax-load-modes.test.ts b/packages/latex/tests/mathjax-load-modes.test.ts index 45a8c98c..b5892bb5 100644 --- a/packages/latex/tests/mathjax-load-modes.test.ts +++ b/packages/latex/tests/mathjax-load-modes.test.ts @@ -5,6 +5,18 @@ import { resetLatexMathJaxStateForTests, } from '../lib/main.ts'; +function getConfiguredMathJaxPackageUrl(): string { + const mathJaxPackageUrl = ( + globalThis as typeof globalThis & { + MathJax?: { loader?: { paths?: { mathjax?: string } } }; + } + ).MathJax?.loader?.paths?.mathjax; + if (typeof mathJaxPackageUrl !== 'string') { + throw new Error('expected MathJax loader.paths.mathjax on globalThis'); + } + return mathJaxPackageUrl; +} + function installBrowserGlobals(): void { const g = globalThis as unknown as { window: typeof globalThis; @@ -29,12 +41,13 @@ afterEach(() => { describe('MathJax load helpers', () => { test('preconfigureMathJaxLoader sets loader paths', () => { preconfigureMathJaxLoader('https://example.test/mj'); + expect(getConfiguredMathJaxPackageUrl()).toBe('https://example.test/mj'); expect( ( - globalThis as unknown as { - MathJax: { loader: { paths: { mathjax: string } } }; + globalThis as typeof globalThis & { + MathJax?: { startup?: { typeset?: boolean } }; } - ).MathJax.loader.paths.mathjax, - ).toBe('https://example.test/mj'); + ).MathJax?.startup?.typeset, + ).toBe(false); }); }); diff --git a/packages/latex/tsdown.config.ts b/packages/latex/tsdown.config.ts index b73fe75e..953b0cc3 100644 --- a/packages/latex/tsdown.config.ts +++ b/packages/latex/tsdown.config.ts @@ -1,7 +1,14 @@ import { defineConfig } from 'tsdown'; -export default defineConfig({ - entry: 'lib/main.ts', - dts: true, - sourcemap: true, -}); +export default defineConfig([ + { + entry: 'lib/main.ts', + dts: true, + sourcemap: true, + }, + { + entry: 'lib/vite-plugin-mathjax.ts', + dts: true, + sourcemap: true, + }, +]); diff --git a/packages/vscode-extension-integrator/README.md b/packages/vscode-extension-integrator/README.md index d3a34290..c9ed26cd 100644 --- a/packages/vscode-extension-integrator/README.md +++ b/packages/vscode-extension-integrator/README.md @@ -6,12 +6,12 @@ Published on npm: [`@prosemark/vscode-extension-integrator`](https://www.npmjs.c ## Subpath exports -| Import | Purpose | -| -------------------------------------------------------- | ----------------------------------------------------------------------- | -| `@prosemark/vscode-extension-integrator` | `SubExtensionManager`, `SubExtensionCallbackManager` (extension host) | -| `@prosemark/vscode-extension-integrator/webview` | Webview message handlers, `appendToExtraCodeMirrorExtensions` | -| `@prosemark/vscode-extension-integrator/types` | `ProseMarkExtensionApi`, `SubExtensionCallback`, proc maps, `Change`, … | -| `@prosemark/vscode-extension-integrator/rolldown-plugin` | Rolldown/Vite plugin for webview bundles | +| Import | Purpose | +| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | +| `@prosemark/vscode-extension-integrator` | `SubExtensionManager`, `SubExtensionCallbackManager` (extension host) | +| `@prosemark/vscode-extension-integrator/webview` | Webview message handlers, `appendToExtraCodeMirrorExtensions` | +| `@prosemark/vscode-extension-integrator/types` | `ProseMarkExtensionApi`, `SubExtensionCallback`, `SubExtensionCallbackContext`, proc maps, `Change`, … | +| `@prosemark/vscode-extension-integrator/rolldown-plugin` | Rolldown/Vite plugin for webview bundles | ## Architecture diff --git a/packages/vscode-extension-integrator/lib/main.ts b/packages/vscode-extension-integrator/lib/main.ts index 744bad6d..069d349f 100644 --- a/packages/vscode-extension-integrator/lib/main.ts +++ b/packages/vscode-extension-integrator/lib/main.ts @@ -110,11 +110,12 @@ export class SubExtensionManager { const extensions: Record = {}; for (const [key, callback] of Object.entries(subExtensionCallbacks)) { - extensions[key] = callback( + extensions[key] = callback({ document, - this.#callProcAndForget(key), - this.#callProcWithReturnValue(key), - ); + callProcAndForget: this.#callProcAndForget(key), + callProcWithReturnValue: this.#callProcWithReturnValue(key), + webview: this.#webview, + }); } this.#subExtensions = extensions; diff --git a/packages/vscode-extension-integrator/lib/types.ts b/packages/vscode-extension-integrator/lib/types.ts index d8f6c62b..6192df08 100644 --- a/packages/vscode-extension-integrator/lib/types.ts +++ b/packages/vscode-extension-integrator/lib/types.ts @@ -195,10 +195,15 @@ export interface SubExtension { export type UnknownSubExtension = SubExtension; +export interface SubExtensionCallbackContext { + document: vscode.TextDocument; + callProcAndForget: CallProc; + callProcWithReturnValue: CallProcWithReturnValue; + webview: vscode.Webview; +} + export type SubExtensionCallback = ( - document: vscode.TextDocument, - callProcAndForget: CallProc, - callProcWithReturnValue: CallProcWithReturnValue, + ctx: SubExtensionCallbackContext, ) => SubExtension; export interface ProseMarkExtensionApi {