From e3b0b2d5765dc86a11f65856d28fc97b4b78bd85 Mon Sep 17 00:00:00 2001 From: yulonger's MacBook Pro 14 Date: Sun, 30 Aug 2026 18:51:35 +0800 Subject: [PATCH] feat: manage Chromium installation in engine --- .github/workflows/ci.yml | 2 +- README.md | 3 +++ dist-cli/cli.js | 4 ++++ dist-cli/cli.js.map | 2 +- dist-cli/init.js | 1 + dist-cli/init.js.map | 2 +- dist-cli/install-browser.d.ts | 1 + dist-cli/install-browser.js | 16 +++++++++++++++ dist-cli/install-browser.js.map | 1 + dist-cli/lib/browser-install.d.ts | 5 +++++ dist-cli/lib/browser-install.js | 23 +++++++++++++++++++++ dist-cli/lib/browser-install.js.map | 1 + scripts/cli.ts | 4 ++++ scripts/init.ts | 1 + scripts/install-browser.ts | 18 ++++++++++++++++ scripts/lib/browser-install.ts | 32 +++++++++++++++++++++++++++++ tests/core.test.ts | 26 +++++++++++++++++++++++ 17 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 dist-cli/install-browser.d.ts create mode 100644 dist-cli/install-browser.js create mode 100644 dist-cli/install-browser.js.map create mode 100644 dist-cli/lib/browser-install.d.ts create mode 100644 dist-cli/lib/browser-install.js create mode 100644 dist-cli/lib/browser-install.js.map create mode 100644 scripts/install-browser.ts create mode 100644 scripts/lib/browser-install.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5d726c..34997b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,5 +20,5 @@ jobs: - run: pnpm verify - name: Verify committed Git distribution run: git diff --exit-code -- dist-cli - - run: pnpm exec playwright install --with-deps chromium + - run: node dist-cli/cli.js install-browser --with-deps - run: pnpm test:e2e diff --git a/README.md b/README.md index 4d61595..8b4f4e4 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ export default { pnpm dev -- pnpm present -- pnpm check +pnpm exec easy-slides install-browser pnpm build pnpm export -- --format pdf pnpm export -- --format png @@ -130,6 +131,8 @@ pnpm export -- --format pptx `dev` 提供 VS Code/浏览器实时预览。`present` 监听局域网,打印观众地址、带同步密码的演示者二维码和手机遥控入口。`build` 扫描全部非 draft 演示,生成博客式首页与 `//` 静态站点。 +`build` 的最终排版检查会启动引擎版本匹配的 Chromium。首次构建前运行 `pnpm exec easy-slides install-browser`;Linux CI 建议运行 `pnpm exec easy-slides install-browser --with-deps`,同时安装 Chromium 所需的系统依赖。`easy-slides init` 生成的 GitHub Pages workflow 已自动包含这一步,内容仓库不需要直接依赖或调用 `playwright-chromium`。 + ## 主题与演示能力 CLI 会自动加载其版本匹配的 `slidev-theme-easy-jyy`,内容仓库不需要复制主题源码。 diff --git a/dist-cli/cli.js b/dist-cli/cli.js index a8a9f5e..dcfacc4 100755 --- a/dist-cli/cli.js +++ b/dist-cli/cli.js @@ -30,6 +30,9 @@ switch (command) { case 'init': await import("./init.js"); break; + case 'install-browser': + await import("./install-browser.js"); + break; case undefined: case 'help': case '--help': @@ -46,6 +49,7 @@ function printHelp() { 用法: easy-slides init [directory] [--engine ] + easy-slides install-browser [--with-deps] easy-slides dev [slug|slides.md] easy-slides present easy-slides build diff --git a/dist-cli/cli.js.map b/dist-cli/cli.js.map index 9577c20..f048ac7 100644 --- a/dist-cli/cli.js.map +++ b/dist-cli/cli.js.map @@ -1 +1 @@ -{"version":3,"file":"cli.js","sourceRoot":"","sources":["../scripts/cli.ts"],"names":[],"mappings":";AACA,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACrC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,EAAE,CAAA;AAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAC3C,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;IACnB,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;IACnC,IAAI,CAAC,IAAI;QACP,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAA;IAClC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IAC5B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;AACnC,CAAC;AACD,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAA;AAE7D,QAAQ,OAAO,EAAE,CAAC;IAChB,KAAK,KAAK;QACR,MAAM,MAAM,CAAC,UAAU,CAAC,CAAA;QACxB,MAAK;IACP,KAAK,SAAS;QACZ,MAAM,MAAM,CAAC,cAAc,CAAC,CAAA;QAC5B,MAAK;IACP,KAAK,OAAO;QACV,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;QAC1B,MAAK;IACP,KAAK,OAAO;QACV,MAAM,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;QAC7C,MAAK;IACP,KAAK,QAAQ;QACX,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;QAC3B,MAAK;IACP,KAAK,MAAM;QACT,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;QACzB,MAAK;IACP,KAAK,SAAS,CAAC;IACf,KAAK,MAAM,CAAC;IACZ,KAAK,QAAQ,CAAC;IACd,KAAK,IAAI;QACP,SAAS,EAAE,CAAA;QACX,MAAK;IACP;QACE,OAAO,CAAC,KAAK,CAAC,QAAQ,OAAO,EAAE,CAAC,CAAA;QAChC,SAAS,EAAE,CAAA;QACX,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;AACxB,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;iCAWmB,CAAC,CAAA;AAClC,CAAC"} \ No newline at end of file +{"version":3,"file":"cli.js","sourceRoot":"","sources":["../scripts/cli.ts"],"names":[],"mappings":";AACA,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AACrC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,EAAE,CAAA;AAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;AAC3C,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;IACnB,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;IACnC,IAAI,CAAC,IAAI;QACP,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAA;IAClC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IAC5B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;AACnC,CAAC;AACD,OAAO,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAA;AAE7D,QAAQ,OAAO,EAAE,CAAC;IAChB,KAAK,KAAK;QACR,MAAM,MAAM,CAAC,UAAU,CAAC,CAAA;QACxB,MAAK;IACP,KAAK,SAAS;QACZ,MAAM,MAAM,CAAC,cAAc,CAAC,CAAA;QAC5B,MAAK;IACP,KAAK,OAAO;QACV,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;QAC1B,MAAK;IACP,KAAK,OAAO;QACV,MAAM,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;QAC7C,MAAK;IACP,KAAK,QAAQ;QACX,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;QAC3B,MAAK;IACP,KAAK,MAAM;QACT,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;QACzB,MAAK;IACP,KAAK,iBAAiB;QACpB,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAA;QACpC,MAAK;IACP,KAAK,SAAS,CAAC;IACf,KAAK,MAAM,CAAC;IACZ,KAAK,QAAQ,CAAC;IACd,KAAK,IAAI;QACP,SAAS,EAAE,CAAA;QACX,MAAK;IACP;QACE,OAAO,CAAC,KAAK,CAAC,QAAQ,OAAO,EAAE,CAAC,CAAA;QAChC,SAAS,EAAE,CAAA;QACX,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;AACxB,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;iCAYmB,CAAC,CAAA;AAClC,CAAC"} \ No newline at end of file diff --git a/dist-cli/init.js b/dist-cli/init.js index 62bf180..c3a5cc1 100644 --- a/dist-cli/init.js +++ b/dist-cli/init.js @@ -93,6 +93,7 @@ jobs: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile + - run: pnpm exec easy-slides install-browser --with-deps - run: pnpm check env: PRESENTER_TOKEN: \${{ secrets.PRESENTER_TOKEN }} diff --git a/dist-cli/init.js.map b/dist-cli/init.js.map index 03bafb2..c931a67 100644 --- a/dist-cli/init.js.map +++ b/dist-cli/init.js.map @@ -1 +1 @@ -{"version":3,"file":"init.js","sourceRoot":"","sources":["../scripts/init.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"init.js","sourceRoot":"","sources":["../scripts/init.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist-cli/install-browser.d.ts b/dist-cli/install-browser.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist-cli/install-browser.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist-cli/install-browser.js b/dist-cli/install-browser.js new file mode 100644 index 0000000..af4e0f8 --- /dev/null +++ b/dist-cli/install-browser.js @@ -0,0 +1,16 @@ +import { spawn } from 'node:child_process'; +import { createBrowserInstallCommand } from "./lib/browser-install.js"; +const { command, args } = createBrowserInstallCommand(process.argv.slice(2)); +const child = spawn(command, args, { stdio: 'inherit' }); +child.once('error', (error) => { + console.error(`无法启动 Chromium 安装程序:${error.message}`); + process.exitCode = 1; +}); +child.once('exit', (code, signal) => { + if (signal) { + process.kill(process.pid, signal); + return; + } + process.exitCode = code ?? 1; +}); +//# sourceMappingURL=install-browser.js.map \ No newline at end of file diff --git a/dist-cli/install-browser.js.map b/dist-cli/install-browser.js.map new file mode 100644 index 0000000..935b9aa --- /dev/null +++ b/dist-cli/install-browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"install-browser.js","sourceRoot":"","sources":["../scripts/install-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAA;AAEtE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,2BAA2B,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AAC5E,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;AAExD,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;IAC5B,OAAO,CAAC,KAAK,CAAC,sBAAsB,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;IACpD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;AACtB,CAAC,CAAC,CAAA;AAEF,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;IAClC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QACjC,OAAM;IACR,CAAC;IACD,OAAO,CAAC,QAAQ,GAAG,IAAI,IAAI,CAAC,CAAA;AAC9B,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist-cli/lib/browser-install.d.ts b/dist-cli/lib/browser-install.d.ts new file mode 100644 index 0000000..e7ba351 --- /dev/null +++ b/dist-cli/lib/browser-install.d.ts @@ -0,0 +1,5 @@ +export interface BrowserInstallCommand { + command: string; + args: string[]; +} +export declare function createBrowserInstallCommand(args: string[]): BrowserInstallCommand; diff --git a/dist-cli/lib/browser-install.js b/dist-cli/lib/browser-install.js new file mode 100644 index 0000000..6aec94a --- /dev/null +++ b/dist-cli/lib/browser-install.js @@ -0,0 +1,23 @@ +import { createRequire } from 'node:module'; +import path from 'node:path'; +const require = createRequire(import.meta.url); +export function createBrowserInstallCommand(args) { + const unsupported = args.filter(argument => argument !== '--with-deps'); + const withDepsCount = args.filter(argument => argument === '--with-deps').length; + if (unsupported.length > 0) + throw new Error(`install-browser 不支持参数:${unsupported.join(' ')}`); + if (withDepsCount > 1) + throw new Error('install-browser 的 --with-deps 只能指定一次'); + const packageJson = require.resolve('playwright-chromium/package.json'); + const playwrightCli = path.join(path.dirname(packageJson), 'cli.js'); + return { + command: process.execPath, + args: [ + playwrightCli, + 'install', + ...(withDepsCount === 1 ? ['--with-deps'] : []), + 'chromium', + ], + }; +} +//# sourceMappingURL=browser-install.js.map \ No newline at end of file diff --git a/dist-cli/lib/browser-install.js.map b/dist-cli/lib/browser-install.js.map new file mode 100644 index 0000000..35d69db --- /dev/null +++ b/dist-cli/lib/browser-install.js.map @@ -0,0 +1 @@ +{"version":3,"file":"browser-install.js","sourceRoot":"","sources":["../../scripts/lib/browser-install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAO9C,MAAM,UAAU,2BAA2B,CAAC,IAAc;IACxD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAA;IACvE,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,KAAK,aAAa,CAAC,CAAC,MAAM,CAAA;IAEhF,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,yBAAyB,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACnE,IAAI,aAAa,GAAG,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;IAEzD,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,kCAAkC,CAAC,CAAA;IACvE,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAA;IAEpE,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,QAAQ;QACzB,IAAI,EAAE;YACJ,aAAa;YACb,SAAS;YACT,GAAG,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,UAAU;SACX;KACF,CAAA;AACH,CAAC"} \ No newline at end of file diff --git a/scripts/cli.ts b/scripts/cli.ts index ec26233..a648069 100644 --- a/scripts/cli.ts +++ b/scripts/cli.ts @@ -32,6 +32,9 @@ switch (command) { case 'init': await import('./init.ts') break + case 'install-browser': + await import('./install-browser.ts') + break case undefined: case 'help': case '--help': @@ -49,6 +52,7 @@ function printHelp() { 用法: easy-slides init [directory] [--engine ] + easy-slides install-browser [--with-deps] easy-slides dev [slug|slides.md] easy-slides present easy-slides build diff --git a/scripts/init.ts b/scripts/init.ts index 708f68d..b80c463 100644 --- a/scripts/init.ts +++ b/scripts/init.ts @@ -101,6 +101,7 @@ jobs: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile + - run: pnpm exec easy-slides install-browser --with-deps - run: pnpm check env: PRESENTER_TOKEN: \${{ secrets.PRESENTER_TOKEN }} diff --git a/scripts/install-browser.ts b/scripts/install-browser.ts new file mode 100644 index 0000000..d2ddda6 --- /dev/null +++ b/scripts/install-browser.ts @@ -0,0 +1,18 @@ +import { spawn } from 'node:child_process' +import { createBrowserInstallCommand } from './lib/browser-install.ts' + +const { command, args } = createBrowserInstallCommand(process.argv.slice(2)) +const child = spawn(command, args, { stdio: 'inherit' }) + +child.once('error', (error) => { + console.error(`无法启动 Chromium 安装程序:${error.message}`) + process.exitCode = 1 +}) + +child.once('exit', (code, signal) => { + if (signal) { + process.kill(process.pid, signal) + return + } + process.exitCode = code ?? 1 +}) diff --git a/scripts/lib/browser-install.ts b/scripts/lib/browser-install.ts new file mode 100644 index 0000000..fac4e8f --- /dev/null +++ b/scripts/lib/browser-install.ts @@ -0,0 +1,32 @@ +import { createRequire } from 'node:module' +import path from 'node:path' + +const require = createRequire(import.meta.url) + +export interface BrowserInstallCommand { + command: string + args: string[] +} + +export function createBrowserInstallCommand(args: string[]): BrowserInstallCommand { + const unsupported = args.filter(argument => argument !== '--with-deps') + const withDepsCount = args.filter(argument => argument === '--with-deps').length + + if (unsupported.length > 0) + throw new Error(`install-browser 不支持参数:${unsupported.join(' ')}`) + if (withDepsCount > 1) + throw new Error('install-browser 的 --with-deps 只能指定一次') + + const packageJson = require.resolve('playwright-chromium/package.json') + const playwrightCli = path.join(path.dirname(packageJson), 'cli.js') + + return { + command: process.execPath, + args: [ + playwrightCli, + 'install', + ...(withDepsCount === 1 ? ['--with-deps'] : []), + 'chromium', + ], + } +} diff --git a/tests/core.test.ts b/tests/core.test.ts index 70f3347..6481b5f 100644 --- a/tests/core.test.ts +++ b/tests/core.test.ts @@ -10,8 +10,34 @@ import { joinBase, normalizeSiteBase } from '../scripts/lib/site-base.ts' import { StaticOverflowAuditor, auditStaticDecks } from '../scripts/lib/static-overflow.ts' import { hasPresenterToken, hashPresenterToken } from '../scripts/lib/token.ts' import { auditBuiltDecks } from '../scripts/lib/overflow-audit.ts' +import { createBrowserInstallCommand } from '../scripts/lib/browser-install.ts' import { resolveImageSource } from '../packages/slidev-theme-easy-jyy/utils/resolve-image.ts' +describe('browser installation', () => { + it('uses the Chromium-only Playwright CLI bundled with the engine', () => { + const command = createBrowserInstallCommand([]) + + expect(command.command).toBe(process.execPath) + expect(command.args.at(-3)).toMatch(/playwright-chromium[/\\]cli\.js$/) + expect(command.args.slice(-2)).toEqual(['install', 'chromium']) + }) + + it('supports Linux system dependency installation and rejects unknown options', () => { + expect(createBrowserInstallCommand(['--with-deps']).args.slice(-3)).toEqual([ + 'install', + '--with-deps', + 'chromium', + ]) + expect(() => createBrowserInstallCommand(['--firefox'])).toThrow('不支持参数') + expect(() => createBrowserInstallCommand(['--with-deps', '--with-deps'])).toThrow('只能指定一次') + }) + + it('includes browser installation in generated CI workflows', async () => { + const source = await readFile(path.join(process.cwd(), 'scripts/init.ts'), 'utf8') + expect(source).toContain('pnpm exec easy-slides install-browser --with-deps') + }) +}) + function overflowingList(title: string, count: number) { return `# ${title}\n\n${Array.from({ length: count }, (_, index) => `- 第 ${index + 1} 条内容用于触发明显的静态高度风险`).join('\n')}\n` }