From 5e726cb221c142de4f9600fb4c26e19c9c0b93ae Mon Sep 17 00:00:00 2001
From: KennyMcSimpson <70093673+KennyMcSimpson@users.noreply.github.com>
Date: Sat, 24 Oct 2026 20:02:59 +0800
Subject: [PATCH 1/2] test: fix Windows development smoke launch and math
coverage
---
source/scripts/smoke-desktop.mjs | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/source/scripts/smoke-desktop.mjs b/source/scripts/smoke-desktop.mjs
index 09fa6af..12a90f5 100644
--- a/source/scripts/smoke-desktop.mjs
+++ b/source/scripts/smoke-desktop.mjs
@@ -11,7 +11,7 @@ await mkdir(results, { recursive: true });
await mkdir(path.join(fixture, 'images'));
await writeFile(path.join(fixture, 'images', '本地 图片.png'), Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAF0lEQVR4nGN82ejPQAgwEVQxqmgAFAEAEL0B0TGFd2QAAAAASUVORK5CYII=', 'base64'));
const filename = path.join(fixture, '中文 file.md');
-await writeFile(filename, '# Desktop smoke test\n\n离线阅读验证。SearchNeedle is here. SearchNeedle is here again.\n\n\n\n## Features\n\n| A | B |\n|---|---|\n| one | two |\n\nInline $E=mc^2$.\n\n```js\nconst local = true;\n```\n\n```mermaid\ngraph TD\n A[Local file] --> B[Desktop reader]\n```\n\n\n');
+await writeFile(filename, '# Desktop smoke test\n\n离线阅读验证。SearchNeedle is here. SearchNeedle is here again.\n\n\n\n## Features\n\n| A | B |\n|---|---|\n| one | two |\n\nInline $E=mc^2$.\n\n$$\n\\frac{1}{2} + \\sqrt{x}\n$$\n\n```js\nconst local = true;\n```\n\n```mermaid\ngraph TD\n A[Local file] --> B[Desktop reader]\n```\n\n\n');
const executable = process.env.MODU_EXECUTABLE;
const launchArgs = executable ? [filename] : ['.', filename];
let app;
@@ -24,7 +24,7 @@ try {
page.on('request', request => { if (/^https?:/.test(request.url())) network.push(request.url()); });
await page.getByRole('heading', { name: 'Desktop smoke test', exact: true }).waitFor();
assert.equal(await page.evaluate(() => typeof window.require), 'undefined');
- assert.equal(await page.evaluate(() => window.injected), undefined);
+ assert.equal(await page.evaluate(() => window.__moduUntrustedMarkdownExecuted), undefined);
const prefs = await app.evaluate(({ BrowserWindow }) => {
const p = BrowserWindow.getAllWindows()[0].webContents.getLastWebPreferences();
return { sandbox: p.sandbox, contextIsolation: p.contextIsolation, nodeIntegration: p.nodeIntegration };
@@ -32,7 +32,12 @@ try {
assert.deepEqual(prefs, { sandbox: true, contextIsolation: true, nodeIntegration: false });
await page.waitForFunction(() => { const image = document.querySelector('article img'); return image?.complete && image.naturalWidth > 0; });
assert.equal(await page.locator('article table').count(), 1);
- assert.equal(await page.locator('article .katex').count(), 1);
+ assert.equal(await page.locator('article .katex').count(), 2);
+ assert.equal(await page.locator('article .katex-display').count(), 1);
+ assert.equal(await page.locator('article .katex-error').count(), 0);
+ assert.equal(await page.locator('article .katex-mathml').count(), 2);
+ await page.evaluate(() => document.fonts.ready);
+ assert.equal(await page.locator('article .katex-html').first().evaluate(el => getComputedStyle(el).fontFamily.includes('KaTeX')), true);
await page.locator('.mermaid-diagram, .diagram-block').first().scrollIntoViewIfNeeded().catch(() => {});
await page.locator('article .mermaid-rendered svg, article .mermaid-diagram svg, article .diagram-block svg').first().waitFor({ timeout: 30000 });
assert.match((await page.locator(".diagram-svg").textContent()) || "", /Local file/);
@@ -63,8 +68,10 @@ try {
const secondFile = path.join(fixture, 'second.md');
await writeFile(secondFile, '# Second instance\n\nOpened from the operating system.');
const childArgs = executable ? [secondFile] : ['.', secondFile];
+ // Playwright may launch Electron through cmd.exe on Windows.
+ const childExecutable = executable || await app.evaluate(() => process.execPath);
await new Promise((resolve, reject) => {
- const child = spawn(executable || app.process().spawnfile, childArgs, { env: { ...process.env, NODE_ENV: 'test', MODU_TEST_USER_DATA: path.join(fixture, 'profile') }, stdio: 'ignore' });
+ const child = spawn(childExecutable, childArgs, { env: { ...process.env, NODE_ENV: 'test', MODU_TEST_USER_DATA: path.join(fixture, 'profile') }, stdio: 'ignore' });
const timer = setTimeout(() => { child.kill(); reject(new Error('Second instance did not exit')); }, 20000);
child.on('error', reject); child.on('exit', code => { clearTimeout(timer); code === 0 ? resolve() : reject(new Error(`Second instance exit ${code}`)); });
});
From 5203c4b879c6c1e5315b1fbd125d3182d0545afb Mon Sep 17 00:00:00 2001
From: KennyMcSimpson <70093673+KennyMcSimpson@users.noreply.github.com>
Date: Sat, 24 Oct 2026 20:02:59 +0800
Subject: [PATCH 2/2] fix: use patched KaTeX across Markdown renderers
---
source/package.json | 2 +-
source/pnpm-lock.yaml | 25 +++++++++++++------------
source/pnpm-workspace.yaml | 2 ++
3 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/source/package.json b/source/package.json
index c8b068a..2c6b161 100644
--- a/source/package.json
+++ b/source/package.json
@@ -37,7 +37,7 @@
"class-variance-authority": "0.7.1",
"clsx": "2.1.1",
"dompurify": "3.4.17",
- "katex": "0.16.47",
+ "katex": "0.18.2",
"lucide-react": "1.31.0",
"mermaid": "11.17.2",
"radix-ui": "1.6.7",
diff --git a/source/pnpm-lock.yaml b/source/pnpm-lock.yaml
index 8af2166..7bed4bc 100644
--- a/source/pnpm-lock.yaml
+++ b/source/pnpm-lock.yaml
@@ -5,6 +5,7 @@ settings:
excludeLinksFromLockfile: false
overrides:
+ katex: 0.18.2
miniflare>sharp: 0.35.4
importers:
@@ -21,8 +22,8 @@ importers:
specifier: 3.4.17
version: 3.4.17
katex:
- specifier: 0.16.47
- version: 0.16.47
+ specifier: 0.18.2
+ version: 0.18.2
lucide-react:
specifier: 1.31.0
version: 1.31.0(react@19.2.6)
@@ -2154,8 +2155,8 @@ packages:
jsonfile@6.2.1:
resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==}
- katex@0.16.47:
- resolution: {integrity: sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==}
+ katex@0.18.2:
+ resolution: {integrity: sha512-3snve4y0SXTMequLim1FMiPvLGElySam0blN5xQZBqEY3lOJz1TnuaaiugnBZBqHzlSAGmFTYL7MCQkORuLKCA==}
hasBin: true
keyv@4.5.4:
@@ -5252,7 +5253,7 @@ snapshots:
es6-error: 4.1.1
matcher: 3.0.0
roarr: 2.15.4
- semver: 7.7.4
+ semver: 7.8.5
serialize-error: 7.0.1
optional: true
@@ -5493,7 +5494,7 @@ snapshots:
optionalDependencies:
graceful-fs: 4.2.11
- katex@0.16.47:
+ katex@0.18.2:
dependencies:
commander: 8.3.0
@@ -5826,7 +5827,7 @@ snapshots:
dompurify: 3.4.17
es-toolkit: 1.52.0
fastdom: 1.0.12
- katex: 0.16.47
+ katex: 0.18.2
khroma: 2.1.0
marked: 16.4.2
roughjs: 4.6.6
@@ -5915,7 +5916,7 @@ snapshots:
dependencies:
'@types/katex': 0.16.8
devlop: 1.1.0
- katex: 0.16.47
+ katex: 0.18.2
micromark-factory-space: 2.0.1
micromark-util-character: 2.1.1
micromark-util-symbol: 2.0.1
@@ -6081,11 +6082,11 @@ snapshots:
node-abi@4.35.0:
dependencies:
- semver: 7.7.4
+ semver: 7.8.5
node-api-version@0.2.1:
dependencies:
- semver: 7.7.4
+ semver: 7.8.5
node-gyp@12.4.0:
dependencies:
@@ -6094,7 +6095,7 @@ snapshots:
graceful-fs: 4.2.11
nopt: 9.0.0
proc-log: 6.1.0
- semver: 7.7.4
+ semver: 7.8.5
tar: 7.5.22
tinyglobby: 0.2.17
undici: 6.28.1
@@ -6365,7 +6366,7 @@ snapshots:
'@types/katex': 0.16.8
hast-util-from-html-isomorphic: 2.0.0
hast-util-to-text: 4.0.2
- katex: 0.16.47
+ katex: 0.18.2
unist-util-visit-parents: 6.0.2
vfile: 6.0.3
diff --git a/source/pnpm-workspace.yaml b/source/pnpm-workspace.yaml
index 1b07c85..8eef7d7 100644
--- a/source/pnpm-workspace.yaml
+++ b/source/pnpm-workspace.yaml
@@ -20,4 +20,6 @@ packageImportMethod: clone-or-copy
verifyDepsBeforeRun: false
optimisticRepeatInstall: false
overrides:
+ # All Markdown and Mermaid math renderers must use the patched KaTeX build.
+ katex: 0.18.2
miniflare>sharp: 0.35.4