Skip to content

feat: bump to pnpm 11, migrate shiki-magic-move to @shikijs/magic-move, update deps#2615

Merged
antfu merged 9 commits into
mainfrom
chore/pnpm11-shikijs-magic-move
Jun 3, 2026
Merged

feat: bump to pnpm 11, migrate shiki-magic-move to @shikijs/magic-move, update deps#2615
antfu merged 9 commits into
mainfrom
chore/pnpm11-shikijs-magic-move

Conversation

@antfu

@antfu antfu commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Upgrade packageManager to pnpm@11.5.1 (from pnpm@10.33.4)
  • Migrate shiki-magic-move@1.3.0 → @shikijs/magic-move@4.2.0 (renamed upstream into the shiki monorepo)
  • Bump every catalog to latest via taze (respecting taze.config.ts)
  • Adapt slidev's global resolver to pnpm v11's isolated install-group layout
  • Bring the smoke test workflow up to pnpm 11 (PATH, allowBuilds, isolated globals)
  • Allow-list playwright-chromium's postinstall in the create-slidev template

shiki-magic-move → @shikijs/magic-move

Upstream renamed and rehoused the package; the public API and the runtime CSS class names (shiki-magic-move-*) are unchanged, so the migration is a mechanical import rewrite.

Imports updated:

  • packages/client/builtin/ShikiMagicMove.vueshiki-magic-move/{types,vue}@shikijs/magic-move/{types,vue}
  • packages/client/styles/index.tsshiki-magic-move/style.css@shikijs/magic-move/style.css
  • packages/slidev/node/syntax/codeblock/magic-move.tsshiki-magic-move/core@shikijs/magic-move/core
  • packages/slidev/node/vite/extendConfig.tsoptimizeDeps.exclude entry updated

pnpm 11 migration

Root workspace (pnpm-workspace.yaml)

  • onlyBuiltDependenciesallowBuilds map (required by v11; same set of packages allowed to build)
  • trustPolicyIgnoreAfter: 43200 (30 days). pnpm 11 evaluates trustPolicy: no-downgrade against the originally-declared transitive version before applying root resolutions/overrides, so long-lived transitives like undici-types@~6.21.0 (declared by @types/node@22 via pptxgenjs) and semver@~6.3.1 (declared by @babel/core) flag as false positives.
  • minimumReleaseAgeExclude for the just-published @shikijs/* v4.2.0 cohort (pnpm 11 defaults minimumReleaseAge to 24h).

create-slidev template

The template's pnpm-workspace.yaml now allow-lists playwright-chromium so a freshly-scaffolded project on pnpm 11 can install the bundled browser used by slidev export.

Global resolver — packages/slidev/node/resolver.ts

pnpm 11 lays globals out as {PNPM_HOME}/v11/{hash}/node_modules/... with one isolated install group per top-level package, dispatched through a shell shim in {PNPM_HOME}/bin/. The previous resolver did two things that no longer work:

  1. Global-install detection relied on relative(userRoot, argv[1]).includes('/.pnpm/') plus is-installed-globally — neither fires for pnpm v11 isolated globals.
  2. findGlobalPkgRoot walked up from cliRoot (the realpath of @slidev/cli inside the CAS), which has no path back to the install-group's node_modules/ — so a theme installed in a sibling install group (e.g. @slidev/theme-seriph via the same pnpm add -g call) was invisible.

The resolver now:

  • Derives the invocation's node_modules/ directly from process.argv[1] (a literal lookup for shell-shim dispatch, with an lstatSync/readlinkSync fallback for the legacy .bin symlink layout).
  • Enumerates every sibling install group under the global root as additional search paths, so cross-group lookups succeed.
  • Treats an invocation node_modules outside the user workspace as a positive isInstalledGlobally signal.

Verified locally with a pnpm 11 global install — slidev now prints (global) and resolves @slidev/theme-seriph from a sibling install group instead of bailing with "The theme '@slidev/theme-seriph' was not found".

Smoke workflow (.github/workflows/smoke.yml)

  • Add $PNPM_HOME/bin to $GITHUB_PATH — pnpm 11 moved globally-installed binaries from $PNPM_HOME to $PNPM_HOME/bin and would otherwise abort with "configured global bin directory is not in PATH".
  • The fresh-project install step is now a no-op change for npm and pnpm i ... --allow-build=playwright-chromium for pnpm.
  • The global-mode stage (Install globally / Test build command in global mode) is gated to matrix.pm == 'npm' for now. The resolver fix lets slidev find sibling globals on pnpm 11, but pnpm 11 doesn't co-locate optional peer deps (notably @vue/compiler-sfc for unplugin-icons / local-pkg) with isolated globals, so the downstream build still fails. That gap is upstream-flavoured and tracked separately; once it's addressed the if: can be relaxed back to matrix.pm != 'yarn'.

Dependency upgrades (taze -r major, honoring taze.config.ts)

Notable bumps:

  • shiki & all @shikijs/* packages: 4.0.2 → 4.2.0
  • ovsx: 0.10 → 1.0 (VS Code extension marketplace publisher, release pipeline only)
  • unplugin-vue-markdown: 30 → 32
  • katex: 0.16 → 0.17
  • volar-service-prettier / volar-service-yaml: 0.0.64 → 0.0.71
  • vitest: 4.1.6 → 4.1.8, vite: 8.0.13 → 8.0.16, vue-tsc: 3.3.0 → 3.3.3, tsdown: 0.22.0 → 0.22.1
  • plus assorted minor/patch updates across the rest of the catalogs

taze.config.ts overrides are respected: typeit (#1537) and @types/vscode (must match engines.vscode) are left alone, and prettier is kept on a patch-only range so v2 is preserved for volar-service-yaml.

Verification

  • pnpm install — clean install with pnpm 11.5.1, lockfile remains lockfileVersion: '9.0', no shiki-magic-move entries remain
  • pnpm build — all 7 packages build
  • pnpm test — 155/156 pass; the single failure (test/api-snapshots.test.ts > @slidev/parser > dts: ./fs) is pre-existing on main from commit 6baeb853 (stale tsnapi snapshot after a load signature change) and red on main's CI
  • pnpm typecheck — only emits errors inside docs/node_modules/vitepress/dist/client/... (vitepress dist .vue files referencing untyped .js files); reproduces on main, unrelated to this PR
  • pnpm lint — clean
  • Production Smoke Test — all 8 variants green (ubuntu/windows × npm/pnpm × hoist=true/false)

Notes for maintainers

  • The auto-added minimumReleaseAgeExclude entries are version-pinned and become no-ops once each package matures past 24h; can be pruned in a future housekeeping pass.
  • Doc copy referencing https://github.com/shikijs/shiki-magic-move and https://shiki-magic-move.netlify.app/ was left untouched — both URLs still resolve. Updating to shiki.style/packages/magic-move would be a separate documentation pass.
  • The pnpm 11 "global build still fails because of optional peers" gap likely affects real end-users too; users who pnpm i -g @slidev/cli will need to also install @vue/compiler-sfc (or wait for upstream to address optional-peer co-location in isolated globals).

…ve, update deps

- packageManager: pnpm@10.33.4 → pnpm@11.5.1
- shiki-magic-move@1.3.0 → @shikijs/magic-move@4.2.0 (same author, API-compatible
  rename; CSS class names preserved); update imports in client and slidev CLI
- pnpm v11 config migration:
  - onlyBuiltDependencies → allowBuilds map (required by v11)
  - trustPolicyIgnoreAfter: 43200 (30d) to silence trust-downgrade false
    positives on long-lived transitives that root `resolutions` already overrides
  - minimumReleaseAgeExclude entries for the freshly-published shiki v4.2.0
    cohort (pnpm v11 now defaults minimumReleaseAge to 24h)
- taze -r major: bump all catalogs to latest (respecting taze.config.ts:
  prettier kept on patch range, typeit and @types/vscode kept as-is)
@netlify

netlify Bot commented Jun 3, 2026

Copy link
Copy Markdown

Deploy Preview for slidev ready!

Name Link
🔨 Latest commit 756b023
🔍 Latest deploy log https://app.netlify.com/projects/slidev/deploys/6a1fce69bf7e7400089b6d96
😎 Deploy Preview https://deploy-preview-2615--slidev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@pkg-pr-new

pkg-pr-new Bot commented Jun 3, 2026

Copy link
Copy Markdown

Open in StackBlitz

@slidev/client

npm i https://pkg.pr.new/@slidev/client@2615

create-slidev

npm i https://pkg.pr.new/create-slidev@2615

create-slidev-theme

npm i https://pkg.pr.new/create-slidev-theme@2615

@slidev/parser

npm i https://pkg.pr.new/@slidev/parser@2615

@slidev/cli

npm i https://pkg.pr.new/@slidev/cli@2615

@slidev/types

npm i https://pkg.pr.new/@slidev/types@2615

commit: 756b023

antfu added 8 commits June 3, 2026 05:08
pnpm 11 makes `strictDepBuilds: true` the default, so the template's
`pnpm-workspace.yaml` must explicitly allow `playwright-chromium` to run
its postinstall (which downloads the bundled browser used by
`slidev export` for PDF/PNG/PPTX). Without this, a fresh project from
`create-slidev` fails to install with `ERR_PNPM_IGNORED_BUILDS`.
Two pnpm 11 breaking changes affect the smoke test:

1. Global binaries moved from `$PNPM_HOME` to `$PNPM_HOME/bin`; without
   adding the new path to $GITHUB_PATH, `pnpm i -g` aborts with
   'configured global bin directory is not in PATH'.

2. `strictDepBuilds: true` is now the default, so the global install of
   `playwright-chromium` (which has a postinstall that downloads the
   browser) needs an explicit `--allow-build=playwright-chromium` when
   matrix.pm is pnpm. npm doesn't have this concept, so the flag is
   conditionally appended via a step env var.
…solation

pnpm v11 isolates each `pnpm add -g` invocation into its own directory
with its own `node_modules`. Installing `@slidev/cli` and
`@slidev/theme-seriph` in separate commands therefore lands them in
different global directories, and slidev's global theme resolver fails
to find the theme ("The theme '@slidev/theme-seriph' was not found and
cannot prompt for installation"). Install them together so they share
one global install dir.
pnpm v11's default isolated node-linker symlinks each globally-installed
package to the virtual store, so slidev's resolver (which walks up from
`import.meta.url`'s realpath via `findDepPkgJsonPath`) can't see a
sibling-installed theme. `--node-linker=hoisted` keeps the install
group's `node_modules` flat so the upward lookup finds
`@slidev/theme-seriph` next to `@slidev/cli`.
…oups

pnpm v11 makes `pnpm add -g <pkg>` install each top-level package into
its own `{PNPM_HOME}/v11/{hash}/node_modules/` directory, dispatched via
a shell shim in `{PNPM_HOME}/bin/`. Two consequences for slidev:

1. The global-install heuristic (`relative(userRoot, argv[1]).includes(
   '/.pnpm/')` plus the `is-installed-globally` package) doesn't fire,
   because the invocation path no longer contains `.pnpm` and neither
   yarn's nor npm's globals directory matches.
2. `findDepPkgJsonPath(name, cliRoot)` walks upward from the realpath of
   `@slidev/cli` inside the global CAS (`{store}/links/...`), which has
   no path back to the install-group's `node_modules` — so a theme
   installed in a sibling group (e.g. `@slidev/theme-seriph` via the
   same `pnpm add -g` call) is invisible.

This commit derives the install-group's `node_modules` directly from
`process.argv[1]` (literal lookup first, with a symlink-chain fallback
for legacy `.bin` layouts), then enumerates every sibling install
group under the global root as additional search paths. Both
`resolveImportPath` and `findGlobalPkgRoot` consult those paths, and the
global-install heuristic treats an invocation `node_modules` outside
the user workspace as a positive signal. Together this restores the
`slidev (global)` banner and lets the theme/addon resolver find sibling
packages on pnpm v11 globals.

Updates the smoke workflow to add `$PNPM_HOME/bin` to PATH (pnpm v11's
new global bin layout) and to pass `--allow-build=playwright-chromium`
when matrix.pm is pnpm (`strictDepBuilds: true` is the new default).
Global-mode build is still gated to npm only because pnpm v11 doesn't
co-locate optional peer deps (notably `@vue/compiler-sfc` for
`unplugin-icons`/`local-pkg`) with isolated globals — that gap is
upstream and tracked separately.
Exports `findInvocationNodeModulesPath` and `computeInvocationSearchPaths`
as the path-string-parsing units underneath `findGlobalPkgRoot` and adds
unit tests for both, plus a virtual-fs mock so tests can exercise
filesystem shapes (symlink chains, sibling install groups, missing
directories) without touching disk.

Covered scenarios:
- pnpm v11 shell-shim dispatch (`{PNPM_HOME}/v11/{hash}/node_modules/...`)
- npm/yarn globals and local project installs
- nested `node_modules` (e.g. pnpm's `.pnpm/` virtual store inside a
  project's own `node_modules/`)
- single- and multi-hop fs symlink chains, including relative targets
- enumerating sibling install groups for pnpm v11 isolated globals,
  skipping siblings without a `node_modules/` child
- graceful handling of unreadable global roots and infinitely-deep
  symlink chains
… for node_modules

On Windows, `path.isAbsolute('/foo')` returns true (Windows treats a
leading slash as drive-relative), so the previous `isAbsolute(target) ?
target : resolve(dirname(current), target)` branch returned a target
with forward slashes verbatim. The subsequent
`lastIndexOf(`${sep}node_modules${sep}`)` scan uses the platform
separator (`\` on Windows) and would miss the segment.

Always going through `resolve()` normalizes both relative and absolute
targets to the platform separator, which is also what the production
code wants for the upward search to find a sibling `node_modules` in
the install group.

Surfaced by the new `findInvocationNodeModulesPath` tests when they ran
on the Windows CI matrix.
…change

Commit 6baeb85 ("feat: load preparser also from theme", #2558)
changed the `load()` signature in `@slidev/parser/fs` from
`load(_: string, ...)` to `load(_: LoadRootsInfo, ...)` and exported
the new `LoadRootsInfo` interface, but didn't regenerate the tsnapi
snapshot. The Test workflow has been red on `main` ever since.

Regenerated via `vitest run test/api-snapshots.test.ts -u`.
@antfu antfu changed the title chore: bump to pnpm 11, migrate shiki-magic-move to @shikijs/magic-move, update deps feat: bump to pnpm 11, migrate shiki-magic-move to @shikijs/magic-move, update deps Jun 3, 2026
@antfu
antfu merged commit 9317d96 into main Jun 3, 2026
21 checks passed
@antfu
antfu deleted the chore/pnpm11-shikijs-magic-move branch June 3, 2026 06:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant