fix(highlight): vendor pure-Lezer Nix and C# parsers
The Nix grammar package imports @codemirror/autocomplete at the top level for its keyword snippets, but only declares it as a peer dependency. electron-builder packs node_modules by walking declared production dependencies, so it omitted the package from app.asar and the desktop daemon died on startup with ERR_MODULE_NOT_FOUND. Dev and CI never saw it because the workspace hoists everything. This is the same failure that just shipped for Svelte, and the previous fix removed @codemirror/autocomplete on the assumption Svelte was its only consumer. Vendoring both remaining grammars removes the class of bug rather than the current instance: these packages are interactive editor extensions, so importing one drags a DOM editor runtime into a headless token highlighter. The vendored language modules keep upstream's indent and fold props. The web file editor consumes getLanguageForFile().extension, so dropping them would have silently degraded editing for .nix and .cs. The new dependency-closure test replicates electron-builder's traversal statically and would have failed both PRs. It is scoped to @getpaseo/highlight because that tree is small and pure; the same walk over the server tree is dominated by false positives from optional dependencies loaded behind try/catch.
This commit is contained in:
@@ -124,6 +124,16 @@ PASEO_DESKTOP_SMOKE_ARTIFACT_DIR=/tmp/paseo-desktop-smoke \
|
||||
npm run build:desktop -- --publish never --linux --x64 --dir
|
||||
```
|
||||
|
||||
### Undeclared peer dependencies break app.asar
|
||||
|
||||
electron-builder packs `node_modules` by walking declared production `dependencies`. A package that imports something it only lists as a `peerDependency` resolves fine in this hoisted workspace, passes every test, and then throws `ERR_MODULE_NOT_FOUND` inside `app.asar` — killing the desktop daemon at startup. That shipped twice from `@replit/codemirror-lang-*` grammars, which are interactive editor extensions published as if they were bare parsers.
|
||||
|
||||
The packaged smoke catches it but only runs when a PR touches the `desktop` filter in `.github/ci-paths.yml`. Both offenders landed under `packages/highlight/**`, which maps to `sdk`.
|
||||
|
||||
`packages/highlight/src/__tests__/dependency-closure.test.ts` replicates the packer's traversal statically and runs with the normal unit tests. It is scoped to `@getpaseo/highlight` on purpose: that tree is small and pure, so the check is exact. Running the same walk over `@getpaseo/server` produces dozens of false positives from optional dependencies loaded behind `try`/`catch`.
|
||||
|
||||
Prefer a `@lezer/*` grammar. When a language only ships inside an editor extension, vendor the grammar into `packages/highlight/src/<lang>/` — see `svelte/`, `nix/`, and `csharp/`.
|
||||
|
||||
### Desktop browser regression
|
||||
|
||||
The desktop browser E2E launches an isolated real daemon, Metro, and Electron app. It forces workspace LRU eviction to reparent the original tab and replace its guest `WebContents`, then makes one MCP call each for tab listing, snapshot, and click against that original browser id. A final MCP wait proves the real target page received the click.
|
||||
|
||||
Reference in New Issue
Block a user