@slidev/cli 52.20.1 → 53.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -62,7 +62,7 @@ Presentation <b>slide</b>s for <b>dev</b>elopers 🧑‍💻👩‍💻👨‍
62
62
 
63
63
  ### Init Project Locally
64
64
 
65
- Install [Node.js >= 20.12.0](https://nodejs.org/) and run the following command:
65
+ Install [Node.js >= 22.12.0](https://nodejs.org/) and run the following command:
66
66
 
67
67
  ```bash
68
68
  npm init slidev
@@ -1,4 +1,4 @@
1
- import { n as resolveViteConfigs } from "./serve-Be4VBJJX.mjs";
1
+ import { n as resolveViteConfigs } from "./serve-CjzN30uY.mjs";
2
2
  import { join, resolve } from "pathe";
3
3
  import { build as build$1 } from "vite";
4
4
  import { existsSync } from "node:fs";
@@ -6,7 +6,7 @@ import fs$1 from "node:fs/promises";
6
6
  import http from "node:http";
7
7
  import connect from "connect";
8
8
  import sirv from "sirv";
9
- //#region node/commands/build.ts
9
+ // node/commands/build.ts
10
10
  async function build(options, viteConfig = {}, args) {
11
11
  const indexHtmlId = resolve(options.userRoot, "index.html");
12
12
  let config = void 0;
@@ -52,7 +52,7 @@ async function build(options, viteConfig = {}, args) {
52
52
  dev: true
53
53
  }));
54
54
  server.listen(port);
55
- const { exportSlides } = await import("./export-LauAJGMx.mjs");
55
+ const { exportSlides } = await import("./export-qz37iJkE.mjs");
56
56
  const tempDir = resolve(outDir, "temp");
57
57
  await fs$1.mkdir(tempDir, { recursive: true });
58
58
  await exportSlides({
@@ -93,7 +93,7 @@ async function build(options, viteConfig = {}, args) {
93
93
  "true",
94
94
  "auto"
95
95
  ].includes(options.data.config.download)) {
96
- const { exportSlides, getExportOptions } = await import("./export-LauAJGMx.mjs");
96
+ const { exportSlides, getExportOptions } = await import("./export-qz37iJkE.mjs");
97
97
  const port = 12445;
98
98
  const app = connect();
99
99
  const server = http.createServer(app);
@@ -112,5 +112,4 @@ async function build(options, viteConfig = {}, args) {
112
112
  server.close();
113
113
  }
114
114
  }
115
- //#endregion
116
115
  export { build };
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { i as isInstalledGlobally, o as resolveEntry } from "./resolver-BIhhHpe7.mjs";
2
- import { c as getThemeMeta, d as loadSetups, f as updateFrontmatterPatch, l as resolveTheme, o as resolveOptions, s as parser, t as createServer, u as version } from "./serve-Be4VBJJX.mjs";
1
+ import { c as getThemeMeta, d as loadSetups, f as updateFrontmatterPatch, l as resolveTheme, o as resolveOptions, s as parser, t as createServer, u as version } from "./serve-CjzN30uY.mjs";
2
+ import { i as isInstalledGlobally, o as resolveEntry } from "./resolver-DMfPHs-L.mjs";
3
3
  import process from "node:process";
4
4
  import path from "pathe";
5
5
  import fs from "node:fs/promises";
@@ -13,7 +13,7 @@ import { verifyConfig } from "@slidev/parser";
13
13
  import { getPort } from "get-port-please";
14
14
  import openBrowser from "open";
15
15
  import yargs from "yargs";
16
- //#region node/setups/preparser.ts
16
+ // node/setups/preparser.ts
17
17
  function setupPreparser() {
18
18
  injectPreparserExtensionLoader(async (roots, headmatter, filepath, mode) => {
19
19
  return (await loadSetups(roots, "preparser.ts", [{
@@ -23,8 +23,7 @@ function setupPreparser() {
23
23
  }])).flat();
24
24
  });
25
25
  }
26
- //#endregion
27
- //#region node/cli.ts
26
+ // node/cli.ts
28
27
  const RE_NODE_MODULES_OR_GIT = /node_modules|\.git/;
29
28
  const CONFIG_RESTART_FIELDS = [
30
29
  "monaco",
@@ -311,7 +310,7 @@ cli.command("build [entry..]", "Build hostable SPA", (args) => exportOptions(com
311
310
  describe: "enable the inspect plugin for debugging"
312
311
  }).strict().help(), async (args) => {
313
312
  const { entry, theme, base, download, out, inspect, "without-notes": withoutNotes, "router-mode": routerMode } = args;
314
- const { build } = await import("./build-BUQLxoIx.mjs");
313
+ const { build } = await import("./build-D8BmN29F.mjs");
315
314
  for (const entryFile of entry) {
316
315
  const options = await resolveOptions({
317
316
  entry: entryFile,
@@ -340,7 +339,7 @@ cli.command("format [entry..]", "Format the markdown file", (args) => commonOpti
340
339
  }
341
340
  });
342
341
  cli.command("mcp [entry]", "Start an MCP (Model Context Protocol) server over stdio for AI agents to inspect and edit the slides", (args) => commonOptions(args).strict().help(), async ({ entry }) => {
343
- const { startMcpStdioServer } = await import("./stdio-SXW6hFKc.mjs");
342
+ const { startMcpStdioServer } = await import("./stdio-CgBcWuMv.mjs");
344
343
  await startMcpStdioServer(await resolveEntry(entry));
345
344
  });
346
345
  cli.command("theme [subcommand]", "Theme related operations", (command) => {
@@ -380,7 +379,7 @@ cli.command("theme [subcommand]", "Theme related operations", (command) => {
380
379
  });
381
380
  cli.command("export [entry..]", "Export slides to PDF", (args) => exportOptions(commonOptions(args)).strict().help(), async (args) => {
382
381
  const { entry, theme } = args;
383
- const { exportSlides, getExportOptions } = await import("./export-LauAJGMx.mjs");
382
+ const { exportSlides, getExportOptions } = await import("./export-qz37iJkE.mjs");
384
383
  const candidatePort = await getPort(12445);
385
384
  let warned = false;
386
385
  for (const entryFile of entry) {
@@ -432,7 +431,7 @@ cli.command("export-notes [entry..]", "Export slide notes to PDF", (args) => arg
432
431
  type: "number",
433
432
  describe: "wait for the specified ms before exporting"
434
433
  }).strict().help(), async ({ entry, output, timeout, wait }) => {
435
- const { exportNotes } = await import("./export-LauAJGMx.mjs");
434
+ const { exportNotes } = await import("./export-qz37iJkE.mjs");
436
435
  const candidatePort = await getPort(12445);
437
436
  for (const entryFile of entry) {
438
437
  const options = await resolveOptions({ entry: entryFile }, "export");
@@ -581,5 +580,4 @@ function printInfo(options, port, base, remote, tunnelUrl, publicIp) {
581
580
  return lastRemoteUrl;
582
581
  }
583
582
  }
584
- //#endregion
585
583
  export {};
@@ -1,4 +1,4 @@
1
- import { n as getRoots } from "./resolver-BIhhHpe7.mjs";
1
+ import { n as getRoots } from "./resolver-DMfPHs-L.mjs";
2
2
  import process from "node:process";
3
3
  import path, { dirname, relative } from "pathe";
4
4
  import fs from "node:fs/promises";
@@ -11,7 +11,7 @@ import { parseRangeString } from "@slidev/parser/core";
11
11
  import { Presets, SingleBar } from "cli-progress";
12
12
  import * as pdfLib from "pdf-lib";
13
13
  import { PDFDocument } from "pdf-lib";
14
- //#region node/commands/export.ts
14
+ // node/commands/export.ts
15
15
  const RE_CLICKS_PARAM = /clicks=([1-9]\d*)/;
16
16
  function addToTree(tree, info, slideIndexes, level = 1) {
17
17
  const titleLevel = info.level;
@@ -105,6 +105,7 @@ async function exportNotes({ port = 18724, base = "/", output = "notes", timeout
105
105
  }
106
106
  async function exportSlides({ port = 18724, total = 0, range, format = "pdf", output = "slides", slides, base = "/", timeout = 3e4, wait = 0, dark = false, routerMode = "history", width = 1920, height = 1080, withClicks = false, executablePath = void 0, withToc = false, perSlide = false, scale = 1, waitUntil, omitBackground = false }) {
107
107
  const pages = parseRangeString(total, range);
108
+ await fs.mkdir(dirname(path.resolve(output)), { recursive: true });
108
109
  const { chromium } = await importPlaywright();
109
110
  const browser = await chromium.launch({ executablePath });
110
111
  const page = await (await browser.newContext({
@@ -352,7 +353,7 @@ async function exportSlides({ port = 18724, total = 0, range, format = "pdf", ou
352
353
  }
353
354
  async function genPagePptxEditable() {
354
355
  if (perSlide) throw new Error("[slidev] `--per-slide` is not supported with `--format pptx-editable`");
355
- const { exportPptxEditable, reportEditableExport } = await import("./pptx-D2UE590V.mjs");
356
+ const { exportPptxEditable, reportEditableExport } = await import("./pptx-B_Yds7Vz.mjs");
356
357
  const result = await exportPptxEditable({
357
358
  page,
358
359
  slides,
@@ -440,5 +441,4 @@ async function importPlaywright() {
440
441
  } catch {}
441
442
  throw new Error("The exporting for Slidev is powered by Playwright, please install it via `npm i -D playwright-chromium`");
442
443
  }
443
- //#endregion
444
444
  export { exportNotes, exportSlides, getExportOptions };
package/dist/index.d.mts CHANGED
@@ -1,14 +1,8 @@
1
1
  import { InlineConfig, PluginOption } from "vite";
2
2
  import * as parser from "@slidev/parser/fs";
3
3
  import { ResolvedSlidevOptions, ResolvedSlidevUtils, SlidevEntryOptions, SlidevPluginOptions, SlidevServerOptions } from "@slidev/types";
4
- //#region node/commands/serve.d.ts
5
4
  export declare function createServer(options: ResolvedSlidevOptions, viteConfig?: InlineConfig, serverOptions?: SlidevServerOptions): Promise<import("vite").ViteDevServer>;
6
- //#endregion
7
- //#region node/options.d.ts
8
5
  export declare function resolveOptions(entryOptions: SlidevEntryOptions, mode: ResolvedSlidevOptions['mode']): Promise<ResolvedSlidevOptions>;
9
6
  export declare function createDataUtils(resolved: Omit<ResolvedSlidevOptions, 'utils'>): Promise<ResolvedSlidevUtils>;
10
- //#endregion
11
- //#region node/vite/index.d.ts
12
7
  export declare function ViteSlidevPlugin(options: ResolvedSlidevOptions, pluginOptions?: SlidevPluginOptions, serverOptions?: SlidevServerOptions): Promise<PluginOption[]>;
13
- //#endregion
14
8
  export { parser };
package/dist/index.mjs CHANGED
@@ -1,2 +1 @@
1
- import { a as createDataUtils, o as resolveOptions, r as ViteSlidevPlugin, s as parser, t as createServer } from "./serve-Be4VBJJX.mjs";
2
- export { ViteSlidevPlugin, createDataUtils, createServer, parser, resolveOptions };
1
+ export { r as ViteSlidevPlugin, a as createDataUtils, t as createServer, s as parser, o as resolveOptions } from "./serve-CjzN30uY.mjs";
@@ -1,12 +1,11 @@
1
1
  import fs from "node:fs/promises";
2
2
  import { dim, yellow } from "ansis";
3
3
  import { Buffer } from "node:buffer";
4
- //#region node/commands/pptx/ir.ts
4
+ // node/commands/pptx/ir.ts
5
5
  const INCHES_PER_PX = 1 / 96;
6
6
  /** Points per pixel (72 pt per inch against 96 px per inch), for font size, letter spacing and line height. */
7
7
  const PT_PER_PX = .75;
8
- //#endregion
9
- //#region node/commands/pptx/build.ts
8
+ // node/commands/pptx/build.ts
10
9
  /**
11
10
  * Extra width beyond the measured glyph bounds: PowerPoint sets the same
12
11
  * string slightly wider than Chromium, so a tight single-line box re-wraps.
@@ -256,8 +255,7 @@ async function buildPptx(Pptx, slides, options) {
256
255
  }
257
256
  return await pptx.write({ outputType: "nodebuffer" });
258
257
  }
259
- //#endregion
260
- //#region node/commands/pptx/capture.ts
258
+ // node/commands/pptx/capture.ts
261
259
  /**
262
260
  * The only Playwright glue in the exporter. Rasterization runs as a second phase,
263
261
  * after every measurement is in hand, because isolating an element for a screenshot
@@ -581,8 +579,7 @@ async function capture(page, slides, requests) {
581
579
  });
582
580
  return report;
583
581
  }
584
- //#endregion
585
- //#region node/commands/pptx/color.ts
582
+ // node/commands/pptx/color.ts
586
583
  function numbers(body) {
587
584
  return body.split(/[\s,/]+/).filter(Boolean).map((token) => {
588
585
  const n = Number.parseFloat(token);
@@ -731,8 +728,7 @@ function withOpacity(color, opacity) {
731
728
  a: color.a * Math.max(0, opacity)
732
729
  };
733
730
  }
734
- //#endregion
735
- //#region node/commands/pptx/normalize.ts
731
+ // node/commands/pptx/normalize.ts
736
732
  /**
737
733
  * `RawSnapshot` to `SlideIr`: every judgement in the exporter, in one pure module with
738
734
  * no DOM or Playwright access, so each rule is testable from a hand-written fixture.
@@ -1480,8 +1476,7 @@ function normalize(snapshot, options) {
1480
1476
  unparsedColors: [...unparsedColors].sort()
1481
1477
  };
1482
1478
  }
1483
- //#endregion
1484
- //#region node/commands/pptx/walker.ts
1479
+ // node/commands/pptx/walker.ts
1485
1480
  /**
1486
1481
  * The one function that runs inside the browser. Invariant: zero free variables.
1487
1482
  * Playwright serializes this function's source and evaluates it where none of this
@@ -1841,8 +1836,7 @@ function collectSnapshot(options) {
1841
1836
  unplaceablePseudos
1842
1837
  };
1843
1838
  }
1844
- //#endregion
1845
- //#region node/commands/pptx/index.ts
1839
+ // node/commands/pptx/index.ts
1846
1840
  /**
1847
1841
  * Export the deck as PowerPoint with native shapes and editable text. One
1848
1842
  * navigation covers everything: the print route renders every slide and click
@@ -1903,5 +1897,4 @@ function reportEditableExport(result) {
1903
1897
  console.warn(dim(" a .pptx names fonts rather than embedding them, so recipients need these installed"));
1904
1898
  }
1905
1899
  }
1906
- //#endregion
1907
1900
  export { exportPptxEditable, reportEditableExport };
@@ -11,7 +11,7 @@ import { resolve as resolve$1, resolvePath } from "mlly";
11
11
  import prompts from "prompts";
12
12
  import { resolveGlobal } from "resolve-global";
13
13
  import { findClosestPkgJsonPath, findDepPkgJsonPath } from "vitefu";
14
- //#region node/resolver.ts
14
+ // node/resolver.ts
15
15
  const RE_PATH_SEPARATOR = /[/\\]/;
16
16
  const RE_SAFE_PKG_NAME = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
17
17
  const cliRoot = fileURLToPath(new URL("..", import.meta.url));
@@ -302,5 +302,4 @@ function resolveSourceFiles(roots, subpath, extensions = [
302
302
  }
303
303
  return results;
304
304
  }
305
- //#endregion
306
305
  export { promptForOptionalInstallation as a, resolveImportUrl as c, isInstalledGlobally as i, resolveSourceFiles as l, getRoots as n, resolveEntry as o, importOptionalDependency as r, resolveImportPath as s, createResolver as t, toAtFS as u };
@@ -1,4 +1,4 @@
1
- import { a as promptForOptionalInstallation, c as resolveImportUrl, i as isInstalledGlobally, l as resolveSourceFiles, n as getRoots, o as resolveEntry, r as importOptionalDependency, s as resolveImportPath, t as createResolver, u as toAtFS } from "./resolver-BIhhHpe7.mjs";
1
+ import { a as promptForOptionalInstallation, c as resolveImportUrl, i as isInstalledGlobally, l as resolveSourceFiles, n as getRoots, o as resolveEntry, r as importOptionalDependency, s as resolveImportPath, t as createResolver, u as toAtFS } from "./resolver-DMfPHs-L.mjs";
2
2
  import { builtinModules } from "node:module";
3
3
  import process from "node:process";
4
4
  import path, { basename, dirname, isAbsolute, join, relative, resolve, win32 } from "pathe";
@@ -48,7 +48,7 @@ import UnoCSS from "unocss/vite";
48
48
  import { mergeConfigs, presetIcons } from "unocss";
49
49
  import Vue from "@vitejs/plugin-vue";
50
50
  import VueJsx from "@vitejs/plugin-vue-jsx";
51
- //#region node/syntax/link.ts
51
+ // node/syntax/link.ts
52
52
  const RE_DIGITS_ONLY = /^\d+$/;
53
53
  function MarkdownItLink(md) {
54
54
  const defaultRender = md.renderer.rules.link_open ?? ((tokens, idx, options, _env, self) => self.renderToken(tokens, idx, options));
@@ -68,8 +68,7 @@ function MarkdownItLink(md) {
68
68
  return defaultRender(tokens, idx, options, env, self);
69
69
  };
70
70
  }
71
- //#endregion
72
- //#region node/virtual/deprecated.ts
71
+ // node/virtual/deprecated.ts
73
72
  /**
74
73
  * Kept for backward compatibility, use #slidev/slides instead
75
74
  *
@@ -100,8 +99,7 @@ console.warn('/@slidev/titles.md is deprecated, import from #slidev/title-render
100
99
  `;
101
100
  }
102
101
  };
103
- //#endregion
104
- //#region node/virtual/titles.ts
102
+ // node/virtual/titles.ts
105
103
  const templateTitleRendererMd = {
106
104
  id: "/@slidev/title-renderer.md",
107
105
  getContent({ data }) {
@@ -116,16 +114,14 @@ const templateTitleRenderer = {
116
114
  return "export { default } from \"/@slidev/title-renderer.md\"";
117
115
  }
118
116
  };
119
- //#endregion
120
- //#region node/vite/common.ts
117
+ // node/vite/common.ts
121
118
  const regexSlideReqPath = /^\/__slidev\/slides\/(\d+)\.json$/;
122
119
  const regexSlideFacadeId = /^\/@slidev\/slides\/(\d+)\/(md|frontmatter)($|\?)/;
123
120
  const regexSlideSourceId = /__slidev_(\d+)\.(md|frontmatter)$/;
124
121
  const templateInjectionMarker = "/* @slidev-injection */";
125
122
  const templateImportContextUtils = `import { useSlideContext as _useSlideContext, frontmatterToProps as _frontmatterToProps } from "@slidev/client/context.ts"`;
126
123
  const templateInitContext = `const { $slidev, $nav, $clicksContext, $clicks, $page, $renderContext, $frontmatter } = _useSlideContext()`;
127
- //#endregion
128
- //#region node/vite/importGuard.ts
124
+ // node/vite/importGuard.ts
129
125
  const virtualSlideMarkdownIds = /* @__PURE__ */ new Set([templateTitleRendererMd.id, templateLegacyTitles.id]);
130
126
  function createSlideImportGuardPlugin() {
131
127
  let config;
@@ -240,8 +236,7 @@ function parseStringLiteral(raw) {
240
236
  return trimmed.slice(1, -1);
241
237
  }
242
238
  }
243
- //#endregion
244
- //#region node/utils.ts
239
+ // node/utils.ts
245
240
  /**
246
241
  * Whether `filePath` resolves inside any of `roots` (no `..` escape). Shared
247
242
  * containment predicate reused by the snippet (`<<<`) and `src:` deck-file
@@ -274,7 +269,7 @@ function applyNotesAutoRuby(md, notesAutoRuby) {
274
269
  }
275
270
  function generateFontParams(options) {
276
271
  const weights = options.weights.flatMap((i) => options.italic ? [`0,${i}`, `1,${i}`] : [`${i}`]).sort().join(";");
277
- return options.webfonts.map((i) => `family=${i.replace(RE_QUOTED_STRING, "$1").replace(RE_WHITESPACE, "+")}:${options.italic ? "ital," : ""}wght@${weights}`).join("&");
272
+ return options.webfonts.map((i) => `family=${i.replace(RE_QUOTED_STRING, "$2").replace(RE_WHITESPACE, "+")}:${options.italic ? "ital," : ""}wght@${weights}`).join("&");
278
273
  }
279
274
  function generateGoogleFontsUrl(options) {
280
275
  return `https://fonts.googleapis.com/css2?${generateFontParams(options)}&display=swap`;
@@ -359,8 +354,7 @@ function makeAbsoluteImportGlobExpression(self, globs, options = {}) {
359
354
  };
360
355
  return `import.meta.glob(${JSON.stringify(relativeGlobs)}, ${JSON.stringify(opts)})`;
361
356
  }
362
- //#endregion
363
- //#region node/setups/load.ts
357
+ // node/setups/load.ts
364
358
  async function loadSetups(roots, filename, args, extraLoader) {
365
359
  return await Promise.all(roots.flatMap((root) => {
366
360
  const tasks = [];
@@ -370,13 +364,11 @@ async function loadSetups(roots, filename, args, extraLoader) {
370
364
  return tasks;
371
365
  }));
372
366
  }
373
- //#endregion
374
- //#region node/setups/vite-plugins.ts
367
+ // node/setups/vite-plugins.ts
375
368
  async function setupVitePlugins(options) {
376
369
  return await loadSetups(options.roots, "vite-plugins.ts", [options]);
377
370
  }
378
- //#endregion
379
- //#region node/vite/compilerFlagsVue.ts
371
+ // node/vite/compilerFlagsVue.ts
380
372
  const RE_VUE_FILE = /\.vue(?:$|\?)/;
381
373
  /**
382
374
  * Replace compiler flags like `__DEV__` in Vue SFC
@@ -396,8 +388,7 @@ function createVueCompilerFlagsPlugin(options) {
396
388
  } }
397
389
  };
398
390
  }
399
- //#endregion
400
- //#region node/vite/components.ts
391
+ // node/vite/components.ts
401
392
  const RE_VUE_EXT$1 = /\.vue$/;
402
393
  const RE_VUE_QUERY_VUE$1 = /\.vue\?vue/;
403
394
  const RE_VUE_QUERY_V$1 = /\.vue\?v=/;
@@ -431,8 +422,7 @@ function createComponentsPlugin({ clientRoot, roots }, pluginOptions) {
431
422
  ...pluginOptions.components
432
423
  });
433
424
  }
434
- //#endregion
435
- //#region node/vite/contextInjection.ts
425
+ // node/vite/contextInjection.ts
436
426
  const RE_EXPORT_DEFAULT_OBJECT = /export\s+default\s+\{/;
437
427
  const RE_INJECT_OPTION = /.*inject\s*:\s*([[{])/;
438
428
  /**
@@ -485,8 +475,7 @@ ${code.slice(scriptIndex)}`;
485
475
  } }
486
476
  };
487
477
  }
488
- //#endregion
489
- //#region node/vite/extendConfig.ts
478
+ // node/vite/extendConfig.ts
490
479
  const RE_SLIDEV_CLIENT = /^@slidev\/client$/;
491
480
  const RE_SLIDEV_CLIENT_SUBPATH = /^@slidev\/client\/(.*)/;
492
481
  const RE_SLIDEV_VIRTUAL = /^#slidev\/(.*)/;
@@ -638,8 +627,7 @@ function createConfigPlugin(options) {
638
627
  }
639
628
  };
640
629
  }
641
- //#endregion
642
- //#region node/vite/hmrPatch.ts
630
+ // node/vite/hmrPatch.ts
643
631
  /**
644
632
  * force reload slide component to ensure v-click resolves correctly
645
633
  */
@@ -655,8 +643,7 @@ function createHmrPatchPlugin() {
655
643
  }
656
644
  };
657
645
  }
658
- //#endregion
659
- //#region node/vite/icons.ts
646
+ // node/vite/icons.ts
660
647
  function createIconsPlugin(options, pluginOptions) {
661
648
  return Icons({
662
649
  defaultClass: "slidev-icon",
@@ -664,8 +651,7 @@ function createIconsPlugin(options, pluginOptions) {
664
651
  ...pluginOptions.icons
665
652
  });
666
653
  }
667
- //#endregion
668
- //#region node/vite/inspect.ts
654
+ // node/vite/inspect.ts
669
655
  async function createInspectPlugin(options, pluginOptions) {
670
656
  if (!options.inspect) return;
671
657
  const { default: PluginInspect } = await import("vite-plugin-inspect");
@@ -675,8 +661,7 @@ async function createInspectPlugin(options, pluginOptions) {
675
661
  ...pluginOptions.inspect
676
662
  });
677
663
  }
678
- //#endregion
679
- //#region node/vite/layoutWrapper.ts
664
+ // node/vite/layoutWrapper.ts
680
665
  const RE_SCRIPT_SETUP_TAG = /^<script setup.*>/m;
681
666
  function createLayoutWrapperPlugin({ data, utils }) {
682
667
  return {
@@ -720,11 +705,9 @@ function createLayoutWrapperPlugin({ data, utils }) {
720
705
  }
721
706
  };
722
707
  }
723
- //#endregion
724
- //#region package.json
725
- var version = "52.20.1";
726
- //#endregion
727
- //#region node/integrations/addons.ts
708
+ // package.json
709
+ var version = "53.1.0";
710
+ // node/integrations/addons.ts
728
711
  async function resolveAddons(addonsInConfig) {
729
712
  const { userRoot, userPkgJson } = await getRoots();
730
713
  const resolved = [];
@@ -756,8 +739,7 @@ async function getThemeMeta(name, root) {
756
739
  if (engines.slidev && !satisfies(version, engines.slidev, { includePrerelease: true })) throw new Error(`[slidev] theme "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
757
740
  return slidev;
758
741
  }
759
- //#endregion
760
- //#region node/setups/indexHtml.ts
742
+ // node/setups/indexHtml.ts
761
743
  const RE_TRAILING_SLASH = /\/$/;
762
744
  const RE_BODY_CONTENT = /<body>([\s\S]*?)<\/body>/i;
763
745
  function escapeHtml(str) {
@@ -911,14 +893,12 @@ async function setupIndexHtml({ mode, entry, clientRoot, userRoot, roots, data,
911
893
  main = main.replace("<!-- body -->", body);
912
894
  return transformHtmlTemplate(unhead, main);
913
895
  }
914
- //#endregion
915
- //#region node/setups/katex.ts
896
+ // node/setups/katex.ts
916
897
  async function setupKatex(roots) {
917
898
  const options = await loadSetups(roots, "katex.ts", []);
918
899
  return Object.assign({ strict: false }, ...options);
919
900
  }
920
- //#endregion
921
- //#region ../client/setup/shiki-options.ts
901
+ // ../client/setup/shiki-options.ts
922
902
  function resolveShikiOptions(options) {
923
903
  const mergedOptions = Object.assign({}, ...options);
924
904
  if ("theme" in mergedOptions && "themes" in mergedOptions) delete mergedOptions.theme;
@@ -988,8 +968,7 @@ function extractThemeNames(themes) {
988
968
  return [key, name];
989
969
  });
990
970
  }
991
- //#endregion
992
- //#region node/setups/shiki.ts
971
+ // node/setups/shiki.ts
993
972
  let cachedRoots;
994
973
  let cachedShiki;
995
974
  async function setupShiki(roots) {
@@ -1011,8 +990,7 @@ async loadTheme(path) {
1011
990
  shikiOptions: options
1012
991
  };
1013
992
  }
1014
- //#endregion
1015
- //#region node/options.ts
993
+ // node/options.ts
1016
994
  const RE_FILE_EXTENSION = /\.\w+$/;
1017
995
  const debug = createDebug("slidev:options");
1018
996
  async function resolveOptions(entryOptions, mode) {
@@ -1134,8 +1112,7 @@ function getDefine(options) {
1134
1112
  __SLIDEV_HAS_SERVER__: options.mode !== "build"
1135
1113
  }, (v, k) => [v, JSON.stringify(k)]);
1136
1114
  }
1137
- //#endregion
1138
- //#region node/syntax/utils.ts
1115
+ // node/syntax/utils.ts
1139
1116
  function normalizeRangeStr(rangeStr = "") {
1140
1117
  return !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
1141
1118
  }
@@ -1145,8 +1122,7 @@ function normalizeRangeStr(rangeStr = "") {
1145
1122
  function escapeVueInCode(md) {
1146
1123
  return md.replace(/\{\{/g, "&lbrace;&lbrace;");
1147
1124
  }
1148
- //#endregion
1149
- //#region node/syntax/katex.ts
1125
+ // node/syntax/katex.ts
1150
1126
  const RE_KATEX_BLOCK_INFO = /^\{([\w*,|-]+)\}\s*(\{[^}]*\})?/;
1151
1127
  function isValidDelim(state, pos) {
1152
1128
  const max = state.posMax;
@@ -1299,8 +1275,7 @@ const templateConditionalStyles = {
1299
1275
  return imports.join("\n");
1300
1276
  }
1301
1277
  };
1302
- //#endregion
1303
- //#region node/virtual/configs.ts
1278
+ // node/virtual/configs.ts
1304
1279
  const templateConfigs = {
1305
1280
  id: "/@slidev/configs",
1306
1281
  getContent({ data, remote }) {
@@ -1343,8 +1318,7 @@ const templateGlobalLayers = {
1343
1318
  return `${imports.join("\n")}\n\n${body}`;
1344
1319
  }
1345
1320
  };
1346
- //#endregion
1347
- //#region node/virtual/layouts.ts
1321
+ // node/virtual/layouts.ts
1348
1322
  const templateLayouts = {
1349
1323
  id: "/@slidev/layouts",
1350
1324
  async getContent({ utils }) {
@@ -1356,8 +1330,7 @@ const templateLayouts = {
1356
1330
  return [imports.join("\n"), `export default {\n${Object.entries(layouts).map(([k, v]) => `"${k}": ${v}`).join(",\n")}\n}`].join("\n\n");
1357
1331
  }
1358
1332
  };
1359
- //#endregion
1360
- //#region node/virtual/monaco-deps.ts
1333
+ // node/virtual/monaco-deps.ts
1361
1334
  const templateMonacoRunDeps = {
1362
1335
  id: "/@slidev/monaco-run-deps",
1363
1336
  async getContent({ userRoot, data }) {
@@ -1381,8 +1354,7 @@ const templateMonacoRunDeps = {
1381
1354
  return result;
1382
1355
  }
1383
1356
  };
1384
- //#endregion
1385
- //#region node/virtual/monaco-types.ts
1357
+ // node/virtual/monaco-types.ts
1386
1358
  const templateMonacoTypes = {
1387
1359
  id: "/@slidev/monaco-types",
1388
1360
  getContent: async ({ userRoot, data, utils }) => {
@@ -1417,8 +1389,7 @@ const templateMonacoTypes = {
1417
1389
  return result;
1418
1390
  }
1419
1391
  };
1420
- //#endregion
1421
- //#region node/virtual/nav-controls.ts
1392
+ // node/virtual/nav-controls.ts
1422
1393
  const templateNavControls = {
1423
1394
  id: "/@slidev/custom-nav-controls",
1424
1395
  getContent({ roots }) {
@@ -1432,8 +1403,7 @@ export default {
1432
1403
  }`;
1433
1404
  }
1434
1405
  };
1435
- //#endregion
1436
- //#region node/virtual/setups.ts
1406
+ // node/virtual/setups.ts
1437
1407
  function createSetupTemplate(name) {
1438
1408
  return {
1439
1409
  id: `/@slidev/setups/${name}`,
@@ -1461,8 +1431,7 @@ const templateSetups = [
1461
1431
  "shortcuts",
1462
1432
  "context-menu"
1463
1433
  ].map(createSetupTemplate);
1464
- //#endregion
1465
- //#region node/virtual/slides.ts
1434
+ // node/virtual/slides.ts
1466
1435
  const VIRTUAL_SLIDE_PREFIX = "/@slidev/slides/";
1467
1436
  const templateSlides = {
1468
1437
  id: "/@slidev/slides",
@@ -1498,8 +1467,7 @@ const templateSlides = {
1498
1467
  ].join("\n");
1499
1468
  }
1500
1469
  };
1501
- //#endregion
1502
- //#region node/virtual/index.ts
1470
+ // node/virtual/index.ts
1503
1471
  const templates = [
1504
1472
  templateMonacoTypes,
1505
1473
  templateMonacoRunDeps,
@@ -1515,8 +1483,7 @@ const templates = [
1515
1483
  templateLegacyRoutes,
1516
1484
  templateLegacyTitles
1517
1485
  ];
1518
- //#endregion
1519
- //#region node/vite/loaders.ts
1486
+ // node/vite/loaders.ts
1520
1487
  function createSlidesLoader(options, serverOptions) {
1521
1488
  const { data, mode, utils, withoutNotes } = options;
1522
1489
  const notesMd = MarkdownExit({ html: true });
@@ -1627,6 +1594,7 @@ function createSlidesLoader(options, serverOptions) {
1627
1594
  ctx.server.hot.send({ type: "full-reload" });
1628
1595
  }, 1);
1629
1596
  const length = Math.min(data.slides.length, newData.slides.length);
1597
+ const titlesChanged = data.slides.length !== newData.slides.length || range(length).some((i) => data.slides[i].title?.trim() !== newData.slides[i].title?.trim());
1630
1598
  for (let i = 0; i < length; i++) {
1631
1599
  const a = data.slides[i];
1632
1600
  const b = newData.slides[i];
@@ -1646,7 +1614,7 @@ function createSlidesLoader(options, serverOptions) {
1646
1614
  }
1647
1615
  Object.assign(data, newData);
1648
1616
  Object.assign(utils, createDataUtils(options));
1649
- if (hmrSlidesIndexes.size > 0) moduleIds.add(templateTitleRendererMd.id);
1617
+ if (titlesChanged) moduleIds.add(templateTitleRendererMd.id);
1650
1618
  for (const idx of hmrSlidesIndexes) moduleIds.add(sourceIds.frontmatter[idx]);
1651
1619
  const reloadBeforeOthers = [];
1652
1620
  const vueModules = [];
@@ -1782,8 +1750,7 @@ function createSlidesLoader(options, serverOptions) {
1782
1750
  };
1783
1751
  }
1784
1752
  }
1785
- //#endregion
1786
- //#region node/setups/transformers.ts
1753
+ // node/setups/transformers.ts
1787
1754
  async function setupTransformers(roots) {
1788
1755
  const returns = await loadSetups(roots, "transformers.ts", []);
1789
1756
  const result = {
@@ -1804,8 +1771,7 @@ async function setupTransformers(roots) {
1804
1771
  }
1805
1772
  return result;
1806
1773
  }
1807
- //#endregion
1808
- //#region ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=49e14003b6caa0b7d164cbe71da573809d375bab_18adf40ca8d248c8719aefb5f4dca995/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/image-size/specialCharacters.js
1774
+ // ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=49e14003b6caa0b7d164cbe71da573809d375bab_18adf40ca8d248c8719aefb5f4dca995/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/image-size/specialCharacters.js
1809
1775
  var SpecialCharacters;
1810
1776
  (function(SpecialCharacters) {
1811
1777
  SpecialCharacters[SpecialCharacters["EXCLAMATION_MARK"] = 33] = "EXCLAMATION_MARK";
@@ -1820,8 +1786,7 @@ var SpecialCharacters;
1820
1786
  SpecialCharacters[SpecialCharacters["PERCENTAGE"] = 37] = "PERCENTAGE";
1821
1787
  SpecialCharacters[SpecialCharacters["CLOSING_PARENTHESIS"] = 41] = "CLOSING_PARENTHESIS";
1822
1788
  })(SpecialCharacters || (SpecialCharacters = {}));
1823
- //#endregion
1824
- //#region ../../node_modules/.pnpm/markdown-it@14.3.2/node_modules/markdown-it/lib/token.mjs
1789
+ // ../../node_modules/.pnpm/markdown-it@14.3.2/node_modules/markdown-it/lib/token.mjs
1825
1790
  /**
1826
1791
  * class Token
1827
1792
  **/
@@ -1974,8 +1939,7 @@ Token.prototype.attrJoin = function attrJoin(name, value) {
1974
1939
  if (idx < 0) this.attrPush([name, value]);
1975
1940
  else this.attrs[idx][1] = this.attrs[idx][1] + " " + value;
1976
1941
  };
1977
- //#endregion
1978
- //#region ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=49e14003b6caa0b7d164cbe71da573809d375bab_18adf40ca8d248c8719aefb5f4dca995/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/task-lists/index.js
1942
+ // ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=49e14003b6caa0b7d164cbe71da573809d375bab_18adf40ca8d248c8719aefb5f4dca995/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/task-lists/index.js
1979
1943
  const checkboxRegex = /^ *\[([\sx])] /i;
1980
1944
  function taskLists(md, options = {
1981
1945
  enabled: false,
@@ -2060,8 +2024,7 @@ function isListItem(token) {
2060
2024
  function startsWithTodoMarkdown(token) {
2061
2025
  return checkboxRegex.test(token.content);
2062
2026
  }
2063
- //#endregion
2064
- //#region node/vite/monacoWrite.ts
2027
+ // node/vite/monacoWrite.ts
2065
2028
  const monacoWriterWhitelist = /* @__PURE__ */ new Set();
2066
2029
  function createMonacoWriterPlugin({ userRoot }) {
2067
2030
  return {
@@ -2096,8 +2059,7 @@ function createMonacoWriterPlugin({ userRoot }) {
2096
2059
  }
2097
2060
  };
2098
2061
  }
2099
- //#endregion
2100
- //#region node/syntax/snippet.ts
2062
+ // node/syntax/snippet.ts
2101
2063
  const RE_NEWLINE = /\r?\n/;
2102
2064
  function dedent(text) {
2103
2065
  const lines = text.split("\n");
@@ -2245,10 +2207,9 @@ function MarkdownItSnippet(md, { userRoot, userWorkspaceRoot, roots, data: { wat
2245
2207
  "list"
2246
2208
  ] });
2247
2209
  }
2248
- //#endregion
2249
- //#region node/syntax/codeblock/magic-move.ts
2210
+ // node/syntax/codeblock/magic-move.ts
2250
2211
  const RE_MAGIC_MOVE_INFO = /^(?:md|markdown) magic-move\s*(?:\[([^\]]*)\])?\s*(\{[^}]*\})?/;
2251
- const RE_CODE_BLOCK = /^```([\w'-]+)?(?:[ \t]*|[ \t][ \w\t'-]*)(?:\[([^\]]*)\])?[ \t]*(?:\{([\w*,|-]+)\}[ \t]*(\{[^}]*\})?([^\r\n]*))?\r?\n((?:(?!^```)[\s\S])*?)^```$/gm;
2212
+ const RE_CODE_BLOCK = /^```([\w'#+-]+)?(?:[ \t]*|[ \t][ \w\t'-]*)(?:\[([^\]]*)\])?[ \t]*(?:\{([\w*,|-]+)\}[ \t]*(\{[^}]*\})?([^\r\n]*))?\r?\n((?:(?!^```)[\s\S])*?)^```$/gm;
2252
2213
  const RE_INNER_CODE_FENCE = /^```/;
2253
2214
  const RE_LINES_TRUE = /\blines: *true\b/;
2254
2215
  const RE_LINES_FALSE = /\blines: *false\b/;
@@ -2300,8 +2261,7 @@ var magic_move_default = defineCodeblockTransformer(async ({ info, fence, code,
2300
2261
  }));
2301
2262
  return `<ShikiMagicMove v-bind="${options}" steps-lz="${lz.compressToBase64(JSON.stringify(steps))}" :title='${JSON.stringify(title)}' :step-ranges='${JSON.stringify(ranges)}' />`;
2302
2263
  });
2303
- //#endregion
2304
- //#region node/syntax/codeblock/mermaid.ts
2264
+ // node/syntax/codeblock/mermaid.ts
2305
2265
  const RE_MERMAID = /^mermaid\s*(\{[^\n]*\})?/;
2306
2266
  var mermaid_default = defineCodeblockTransformer(async ({ info, code }) => {
2307
2267
  const match = info.match(RE_MERMAID);
@@ -2309,8 +2269,7 @@ var mermaid_default = defineCodeblockTransformer(async ({ info, code }) => {
2309
2269
  const [, options] = match;
2310
2270
  return `<Mermaid ${options ? `v-bind="${options}"` : ""} code-lz="${lz.compressToBase64(code.trim())}" />`;
2311
2271
  });
2312
- //#endregion
2313
- //#region node/syntax/codeblock/monaco.ts
2272
+ // node/syntax/codeblock/monaco.ts
2314
2273
  const RE_MONACO = /^([\w'-]+)?\s*\{(monaco[\w-]*)\}\s*(\{[^}]*\})?(.*)$/;
2315
2274
  const RE_DIFF_SEPARATOR = /^\s*~~~\s*\n/m;
2316
2275
  var monaco_default = defineCodeblockTransformer(async ({ info, code, options: { data: { config }, mode } }) => {
@@ -2327,8 +2286,7 @@ var monaco_default = defineCodeblockTransformer(async ({ info, code, options: {
2327
2286
  } else encoded = lz.compressToBase64(code);
2328
2287
  return `<Monaco ${options ? `v-bind="${options}"` : ""} ${monaco === "monaco-run" ? "runnable" : ""} lang="${lang}" code-lz="${encoded}" ${diff} />`;
2329
2288
  });
2330
- //#endregion
2331
- //#region node/syntax/codeblock/plant-uml.ts
2289
+ // node/syntax/codeblock/plant-uml.ts
2332
2290
  const RE_PLANT_UML = /^plantuml\s*(\{[^\n]*\})?/;
2333
2291
  var plant_uml_default = defineCodeblockTransformer(async ({ info, code, options: { data: { config: { plantUmlServer } } } }) => {
2334
2292
  const match = info.match(RE_PLANT_UML);
@@ -2336,9 +2294,8 @@ var plant_uml_default = defineCodeblockTransformer(async ({ info, code, options:
2336
2294
  const [, options] = match;
2337
2295
  return `<PlantUml ${options ? `v-bind="${options}"` : ""} code="${encode(code.trim())}"${plantUmlServer === void 0 ? "" : ` server=${JSON.stringify(plantUmlServer)}`} />`;
2338
2296
  });
2339
- //#endregion
2340
- //#region node/syntax/codeblock/wrapper.ts
2341
- const RE_BLOCK_INFO = /^([\w'-]+)?(?:[ \t]*|[ \t][ \w\t'-]*)(?:\[([^\]]*)\])?[ \t]*(?:\{([\w,|\-*]+)\})?[ \t]*(\{[^}]*\})?(.*)$/;
2297
+ // node/syntax/codeblock/wrapper.ts
2298
+ const RE_BLOCK_INFO = /^([\w'#+-]+)?(?:[ \t]*|[ \t][ \w\t'-]*)(?:\[([^\]]*)\])?[ \t]*(?:\{([\w,|\-*]+)\})?[ \t]*(\{[^}]*\})?(.*)$/;
2342
2299
  var wrapper_default = defineCodeblockTransformer(async ({ info, renderHighlighted }) => {
2343
2300
  const [, lang = "", title = "", rangeStr = "", options, rest = ""] = info.match(RE_BLOCK_INFO) ?? [];
2344
2301
  const ranges = normalizeRangeStr(rangeStr);
@@ -2346,8 +2303,7 @@ var wrapper_default = defineCodeblockTransformer(async ({ info, renderHighlighte
2346
2303
  const code = await renderHighlighted({ info: `${lang} ${rest}` });
2347
2304
  return `<CodeBlockWrapper ${optionsProp} title=${JSON.stringify(title)} :ranges='${JSON.stringify(ranges)}'>${escapeVueInCode(code)}</CodeBlockWrapper>`;
2348
2305
  });
2349
- //#endregion
2350
- //#region node/syntax/codeblock/index.ts
2306
+ // node/syntax/codeblock/index.ts
2351
2307
  function MarkdownItCodeblocks(md, options, extraTransformers) {
2352
2308
  const oldFence = md.renderer.rules.fence;
2353
2309
  md.renderer.rules.fence = async function(tokens, idx, renderOptions, env, slf) {
@@ -2381,8 +2337,7 @@ function MarkdownItCodeblocks(md, options, extraTransformers) {
2381
2337
  throw new Error("Should not reach here");
2382
2338
  };
2383
2339
  }
2384
- //#endregion
2385
- //#region node/syntax/drag.ts
2340
+ // node/syntax/drag.ts
2386
2341
  const dragComponentRegex = /<(v-?drag-?\w*)([\s>])/i;
2387
2342
  const dragDirectiveRegex = /(?<![</\w])v-drag(=".*?")?/i;
2388
2343
  function MarkdownItVDrag(md, markdownTransformMap) {
@@ -2405,13 +2360,27 @@ function MarkdownItVDrag(md, markdownTransformMap) {
2405
2360
  const _parse = md.parse;
2406
2361
  md.parse = function(src, env) {
2407
2362
  const smc = getSourceMapConsumer(env?.id);
2408
- const toOriginalPos = smc ? (line) => smc.originalPositionFor({
2409
- line: line + 1,
2410
- column: 0
2411
- }).line - 1 : (line) => line;
2363
+ const toOriginalPos = (line) => {
2364
+ if (!smc) return line;
2365
+ const mapped = smc.originalPositionFor({
2366
+ line: line + 1,
2367
+ column: 0
2368
+ }).line;
2369
+ return mapped == null || mapped <= 0 ? null : mapped - 1;
2370
+ };
2412
2371
  function toMarkdownSource(map, idx) {
2413
- const start = toOriginalPos(map[0]);
2414
- const end = toOriginalPos(map[1]);
2372
+ const start = toOriginalPos(map[0]) ?? map[0];
2373
+ let end = toOriginalPos(map[1]);
2374
+ if (end == null) {
2375
+ end = start + 1;
2376
+ for (let line = map[1] - 1; line > map[0]; line--) {
2377
+ const mapped = toOriginalPos(line);
2378
+ if (mapped != null) {
2379
+ end = mapped + 1;
2380
+ break;
2381
+ }
2382
+ }
2383
+ }
2415
2384
  return `[${start},${Math.max(start + 1, end)},${idx}]`;
2416
2385
  }
2417
2386
  function replaceChildren(token, regex, replacement) {
@@ -2440,8 +2409,7 @@ function MarkdownItVDrag(md, markdownTransformMap) {
2440
2409
  });
2441
2410
  };
2442
2411
  }
2443
- //#endregion
2444
- //#region node/syntax/escape-code.ts
2412
+ // node/syntax/escape-code.ts
2445
2413
  const RE_CODE_TAG_OPEN = /^<code/;
2446
2414
  function MarkdownItEscapeInlineCode(md) {
2447
2415
  const codeInline = md.renderer.rules.code_inline;
@@ -2449,8 +2417,7 @@ function MarkdownItEscapeInlineCode(md) {
2449
2417
  return (await codeInline(tokens, idx, options, env, self)).replace(RE_CODE_TAG_OPEN, "<code v-pre");
2450
2418
  };
2451
2419
  }
2452
- //#endregion
2453
- //#region node/syntax/scoped.ts
2420
+ // node/syntax/scoped.ts
2454
2421
  const RE_STYLE_TAG_OPEN = /<style\b([^>]*)>/gi;
2455
2422
  const RE_SCOPED_ATTR = /\bscoped\b/i;
2456
2423
  function MarkdownItStyleScoped(md) {
@@ -2465,8 +2432,7 @@ function MarkdownItStyleScoped(md) {
2465
2432
  const htmlInline = md.renderer.rules.html_inline;
2466
2433
  md.renderer.rules.html_inline = async (...args) => addScoped(await htmlInline(...args));
2467
2434
  }
2468
- //#endregion
2469
- //#region node/syntax/shiki.ts
2435
+ // node/syntax/shiki.ts
2470
2436
  async function MarkdownItShiki({ data: { config }, mode, utils: { shiki, shikiOptions } }) {
2471
2437
  async function getTwoslashTransformer() {
2472
2438
  const [, , { transformerTwoslash }] = await Promise.all([
@@ -2512,8 +2478,7 @@ function transformerTwoslashConditional() {
2512
2478
  }
2513
2479
  };
2514
2480
  }
2515
- //#endregion
2516
- //#region node/syntax/slot-sugar.ts
2481
+ // node/syntax/slot-sugar.ts
2517
2482
  const RE_SLOT_MARKER = /^::\s*([\w.\-:]+)\s*::\s*$/;
2518
2483
  function MarkdownItSlotSugar(md) {
2519
2484
  md.block.ruler.before("fence", "slot_marker", (state, startLine, _endLine, silent) => {
@@ -2562,8 +2527,7 @@ function MarkdownItSlotSugar(md) {
2562
2527
  state.tokens = newTokens;
2563
2528
  });
2564
2529
  }
2565
- //#endregion
2566
- //#region node/syntax/index.ts
2530
+ // node/syntax/index.ts
2567
2531
  async function useMarkdownItPlugins(md, options, markdownTransformMap, codeblockTransformers) {
2568
2532
  const { data: { features, config }, utils: { katexOptions } } = options;
2569
2533
  md.use(MarkdownItSnippet, options);
@@ -2584,8 +2548,7 @@ async function useMarkdownItPlugins(md, options, markdownTransformMap, codeblock
2584
2548
  md.use(MarkdownItStyleScoped);
2585
2549
  md.use(MarkdownItGitHubAlerts);
2586
2550
  }
2587
- //#endregion
2588
- //#region node/vite/markdown.ts
2551
+ // node/vite/markdown.ts
2589
2552
  const RE_MD_EXT$1 = /\.md$/;
2590
2553
  async function createMarkdownPlugin(options, { markdown: mdOptions }) {
2591
2554
  const markdownTransformMap = /* @__PURE__ */ new Map();
@@ -2611,6 +2574,7 @@ async function createMarkdownPlugin(options, { markdown: mdOptions }) {
2611
2574
  },
2612
2575
  ...mdOptions,
2613
2576
  async markdownSetup(md) {
2577
+ md.linkify.set({ fuzzyLink: true });
2614
2578
  await useMarkdownItPlugins(md, options, markdownTransformMap, extras.codeblocks);
2615
2579
  await mdOptions?.markdownSetup?.(md);
2616
2580
  },
@@ -2638,8 +2602,7 @@ async function createMarkdownPlugin(options, { markdown: mdOptions }) {
2638
2602
  }
2639
2603
  });
2640
2604
  }
2641
- //#endregion
2642
- //#region node/mcp/operations.ts
2605
+ // node/mcp/operations.ts
2643
2606
  /**
2644
2607
  * Resolve a rendered slide (1-based, as displayed in the presentation) or
2645
2608
  * throw a descriptive error.
@@ -2763,8 +2726,7 @@ async function moveSlide(data, options) {
2763
2726
  fileContent
2764
2727
  };
2765
2728
  }
2766
- //#endregion
2767
- //#region node/mcp/server.ts
2729
+ // node/mcp/server.ts
2768
2730
  function result(data) {
2769
2731
  return { content: [{
2770
2732
  type: "text",
@@ -2922,8 +2884,7 @@ function createSlidevMcpServer(ctx) {
2922
2884
  }
2923
2885
  return server;
2924
2886
  }
2925
- //#endregion
2926
- //#region node/integrations/drawings.ts
2887
+ // node/integrations/drawings.ts
2927
2888
  /**
2928
2889
  * Whether `key` is a safe bare slide id that can be joined onto `dir` without
2929
2890
  * escaping it. `loadDrawings` only ever produces numeric keys, so writes
@@ -2972,8 +2933,7 @@ async function writeDrawings(options, drawing) {
2972
2933
  await fs$1.writeFile(join(dir, `${key}.svg`), svg, "utf-8");
2973
2934
  }));
2974
2935
  }
2975
- //#endregion
2976
- //#region node/integrations/snapshots.ts
2936
+ // node/integrations/snapshots.ts
2977
2937
  function resolveSnapshotsDir(options) {
2978
2938
  return resolve(dirname(options.entry), ".slidev/snapshots");
2979
2939
  }
@@ -2989,8 +2949,7 @@ async function writeSnapshots(options, data) {
2989
2949
  await fs$1.mkdir(dir, { recursive: true });
2990
2950
  await fs$1.writeFile(join(dir, "snapshots.json"), JSON.stringify(data, null, 2), "utf-8");
2991
2951
  }
2992
- //#endregion
2993
- //#region node/vite/serverRef.ts
2952
+ // node/vite/serverRef.ts
2994
2953
  const serverRefStates = /* @__PURE__ */ new WeakMap();
2995
2954
  /**
2996
2955
  * Access the server-side state shared with the clients via
@@ -3140,8 +3099,7 @@ function navigateClients(server, options, page, clicks) {
3140
3099
  }
3141
3100
  });
3142
3101
  }
3143
- //#endregion
3144
- //#region node/vite/monacoTypes.ts
3102
+ // node/vite/monacoTypes.ts
3145
3103
  function createMonacoTypesLoader({ userRoot, utils }) {
3146
3104
  return {
3147
3105
  name: "slidev:monaco-types-loader",
@@ -3190,8 +3148,7 @@ function createMonacoTypesLoader({ userRoot, utils }) {
3190
3148
  }
3191
3149
  };
3192
3150
  }
3193
- //#endregion
3194
- //#region node/vite/patchMonacoSourceMap.ts
3151
+ // node/vite/patchMonacoSourceMap.ts
3195
3152
  const postfixRE = /[?#].*$/;
3196
3153
  function cleanUrl(url) {
3197
3154
  return url.replace(postfixRE, "");
@@ -3209,8 +3166,7 @@ function createPatchMonacoSourceMapPlugin() {
3209
3166
  }
3210
3167
  };
3211
3168
  }
3212
- //#endregion
3213
- //#region node/vite/pwa.ts
3169
+ // node/vite/pwa.ts
3214
3170
  const PWA_PACKAGE = "vite-plugin-pwa";
3215
3171
  async function createPWAPlugin(options) {
3216
3172
  const matchMode = (mode) => mode === true || mode === options.mode;
@@ -3271,8 +3227,7 @@ function createPWARegisterStubPlugin() {
3271
3227
  }
3272
3228
  };
3273
3229
  }
3274
- //#endregion
3275
- //#region node/vite/remoteAssets.ts
3230
+ // node/vite/remoteAssets.ts
3276
3231
  async function createRemoteAssetsPlugin({ data: { config }, mode }, pluginOptions) {
3277
3232
  if (!(config.remoteAssets === true || config.remoteAssets === mode)) return;
3278
3233
  const { VitePluginRemoteAssets, DefaultRules } = await import("vite-plugin-remote-assets");
@@ -3290,8 +3245,7 @@ async function createRemoteAssetsPlugin({ data: { config }, mode }, pluginOption
3290
3245
  ]
3291
3246
  });
3292
3247
  }
3293
- //#endregion
3294
- //#region node/vite/staticCopy.ts
3248
+ // node/vite/staticCopy.ts
3295
3249
  async function createStaticCopyPlugin({ themeRoots, addonRoots }, pluginOptions) {
3296
3250
  const publicDirs = [...themeRoots, ...addonRoots].map((i) => join(i, "public")).filter(existsSync);
3297
3251
  if (!publicDirs.length) return;
@@ -3305,8 +3259,7 @@ async function createStaticCopyPlugin({ themeRoots, addonRoots }, pluginOptions)
3305
3259
  ...pluginOptions.staticCopy
3306
3260
  });
3307
3261
  }
3308
- //#endregion
3309
- //#region node/setups/unocss.ts
3262
+ // node/setups/unocss.ts
3310
3263
  async function setupUnocss({ clientRoot, roots, data, utils }) {
3311
3264
  function loadFileConfigs(root) {
3312
3265
  return [resolve(root, "uno.config.ts"), resolve(root, "unocss.config.ts")].map(async (i) => {
@@ -3334,8 +3287,7 @@ async function setupUnocss({ clientRoot, roots, data, utils }) {
3334
3287
  config.theme.fontFamily.serif ||= data.config.fonts.serif.join(",");
3335
3288
  return config;
3336
3289
  }
3337
- //#endregion
3338
- //#region node/vite/unocss.ts
3290
+ // node/vite/unocss.ts
3339
3291
  async function createUnocssPlugin(options, pluginOptions) {
3340
3292
  return UnoCSS({
3341
3293
  configFile: false,
@@ -3343,8 +3295,7 @@ async function createUnocssPlugin(options, pluginOptions) {
3343
3295
  ...pluginOptions.unocss
3344
3296
  });
3345
3297
  }
3346
- //#endregion
3347
- //#region node/vite/vue.ts
3298
+ // node/vite/vue.ts
3348
3299
  const RE_VUE_EXT = /\.vue$/;
3349
3300
  const RE_VUE_QUERY_VUE = /\.vue\?vue/;
3350
3301
  const RE_VUE_QUERY_V = /\.vue\?v=/;
@@ -3403,8 +3354,7 @@ async function createVuePlugin(_options, pluginOptions) {
3403
3354
  });
3404
3355
  return [VueJsx(vuejsxOptions), VuePlugin];
3405
3356
  }
3406
- //#endregion
3407
- //#region node/vite/index.ts
3357
+ // node/vite/index.ts
3408
3358
  function ViteSlidevPlugin(options, pluginOptions = {}, serverOptions = {}) {
3409
3359
  return Promise.all([
3410
3360
  createSlidesLoader(options, serverOptions),
@@ -3431,8 +3381,7 @@ function ViteSlidevPlugin(options, pluginOptions = {}, serverOptions = {}) {
3431
3381
  setupVitePlugins(options)
3432
3382
  ]);
3433
3383
  }
3434
- //#endregion
3435
- //#region node/commands/shared.ts
3384
+ // node/commands/shared.ts
3436
3385
  const sharedMd = MarkdownExit({ html: true });
3437
3386
  sharedMd.use(MarkdownItLink);
3438
3387
  function getSlideTitle(data) {
@@ -3460,12 +3409,10 @@ async function resolveViteConfigs(options, baseConfig, overrideConfigs, command,
3460
3409
  });
3461
3410
  return baseConfig;
3462
3411
  }
3463
- //#endregion
3464
- //#region node/commands/serve.ts
3412
+ // node/commands/serve.ts
3465
3413
  async function createServer$1(options, viteConfig = {}, serverOptions) {
3466
3414
  process.env.EDITOR = process.env.EDITOR || "code";
3467
3415
  const inlineConfig = await resolveViteConfigs(options, { optimizeDeps: { entries: [join(options.clientRoot, "main.ts")] } }, viteConfig, "serve", serverOptions);
3468
3416
  return await createServer(inlineConfig);
3469
3417
  }
3470
- //#endregion
3471
3418
  export { createDataUtils as a, getThemeMeta as c, loadSetups as d, updateFrontmatterPatch as f, createSlidevMcpServer as i, resolveTheme as l, resolveViteConfigs as n, resolveOptions as o, ViteSlidevPlugin as r, parser as s, createServer$1 as t, version as u };
@@ -1,7 +1,7 @@
1
- import { n as getRoots } from "./resolver-BIhhHpe7.mjs";
2
- import { i as createSlidevMcpServer, s as parser, u as version } from "./serve-Be4VBJJX.mjs";
1
+ import { i as createSlidevMcpServer, s as parser, u as version } from "./serve-CjzN30uY.mjs";
2
+ import { n as getRoots } from "./resolver-DMfPHs-L.mjs";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
4
- //#region node/mcp/stdio.ts
4
+ // node/mcp/stdio.ts
5
5
  /**
6
6
  * Start a Slidev MCP server over stdio, operating on the markdown files
7
7
  * directly (no dev server required, so no live-navigation tool).
@@ -20,5 +20,4 @@ async function startMcpStdioServer(entry) {
20
20
  }, entry)
21
21
  }).connect(new StdioServerTransport());
22
22
  }
23
- //#endregion
24
23
  export { startMcpStdioServer };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@slidev/cli",
3
3
  "type": "module",
4
- "version": "52.20.1",
4
+ "version": "53.1.0",
5
5
  "description": "Presentation slides for developers",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -32,7 +32,7 @@
32
32
  "template.md"
33
33
  ],
34
34
  "engines": {
35
- "node": ">=20.12.0"
35
+ "node": ">=22.22.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "playwright-chromium": "^1.10.0",
@@ -47,87 +47,84 @@
47
47
  }
48
48
  },
49
49
  "dependencies": {
50
- "@antfu/ni": "^30.5.0",
50
+ "@antfu/ni": "^30.6.0",
51
51
  "@antfu/utils": "^9.3.0",
52
- "@comark/markdown-it": "^0.3.4",
53
- "@iconify-json/carbon": "^1.2.27",
52
+ "@comark/markdown-it": "^0.4.0",
53
+ "@iconify-json/carbon": "^1.2.29",
54
54
  "@iconify-json/ph": "^1.2.2",
55
55
  "@iconify-json/svg-spinners": "^1.2.4",
56
56
  "@lillallol/outline-pdf": "^4.0.0",
57
- "@modelcontextprotocol/node": "^2.0.0",
58
- "@modelcontextprotocol/server": "^2.0.0",
59
- "@shikijs/magic-move": "^4.4.3",
60
- "@shikijs/markdown-it": "^4.4.3",
61
- "@shikijs/twoslash": "^4.4.3",
62
- "@shikijs/vitepress-twoslash": "^4.4.3",
63
- "@slidev/client": "52.20.1",
64
- "@slidev/parser": "52.20.1",
65
- "@slidev/types": "52.20.1",
66
- "@unocss/extractor-mdc": "^66.10.4",
67
- "@unocss/reset": "^66.10.4",
68
- "@vitejs/plugin-vue": "^6.0.9",
57
+ "@modelcontextprotocol/node": "^2.1.2",
58
+ "@modelcontextprotocol/server": "^2.4.0",
59
+ "@shikijs/magic-move": "^4.6.0",
60
+ "@shikijs/markdown-it": "^4.6.0",
61
+ "@shikijs/twoslash": "^4.6.0",
62
+ "@shikijs/vitepress-twoslash": "^4.6.0",
63
+ "@slidev/client": "53.1.0",
64
+ "@slidev/parser": "53.1.0",
65
+ "@slidev/types": "53.1.0",
66
+ "@unocss/extractor-mdc": "^66.12.0",
67
+ "@unocss/reset": "^66.12.0",
68
+ "@vitejs/plugin-vue": "^6.0.10",
69
69
  "@vitejs/plugin-vue-jsx": "^5.1.6",
70
- "ansis": "^4.4.0",
71
- "chokidar": "^5.0.0",
70
+ "ansis": "^4.5.0",
71
+ "chokidar": "^6.0.0",
72
72
  "cli-progress": "^3.12.0",
73
73
  "connect": "^3.7.0",
74
74
  "fast-deep-equal": "^3.1.3",
75
75
  "fast-glob": "^3.3.3",
76
76
  "get-port-please": "^3.2.0",
77
77
  "global-directory": "^5.0.0",
78
- "htmlparser2": "^12.0.0",
79
- "is-installed-globally": "^1.0.0",
78
+ "is-installed-globally": "^1.0.1",
80
79
  "jiti": "^2.7.0",
81
- "katex": "^0.18.7",
82
- "local-pkg": "^1.2.1",
80
+ "katex": "^0.19.1",
83
81
  "lz-string": "^1.5.0",
84
- "magic-string": "^1.4.1",
82
+ "magic-string": "^1.4.5",
85
83
  "magic-string-stack": "^2.0.0",
86
- "markdown-exit": "^1.3.0",
84
+ "markdown-exit": "^2.1.3",
87
85
  "markdown-it-footnote": "^4.0.0",
88
86
  "markdown-it-github-alerts": "^1.0.1",
89
87
  "mlly": "^1.8.2",
90
- "monaco-editor": "^0.56.0",
88
+ "monaco-editor": "^0.57.0",
91
89
  "obug": "^3.0.0",
92
90
  "open": "^11.0.4",
93
91
  "pathe": "^2.0.3",
94
92
  "pdf-lib": "^1.17.1",
95
93
  "picomatch": "^4.0.7",
96
94
  "plantuml-encoder": "^1.4.0",
97
- "postcss-nested": "^8.0.1",
95
+ "postcss-nested": "^9.0.1",
98
96
  "pptxgenjs": "^4.0.1",
99
97
  "prompts": "^2.4.2",
100
98
  "public-ip": "^8.0.0",
101
- "resolve-from": "^5.0.0",
102
99
  "resolve-global": "^2.0.0",
103
- "shiki": "^4.4.3",
100
+ "shiki": "^4.6.0",
104
101
  "sirv": "^3.0.2",
105
- "source-map-js": "^1.2.1",
102
+ "source-map-js": "^1.2.2",
106
103
  "typescript": "^6.0.3",
107
- "unhead": "^3.4.1",
108
- "unocss": "^66.10.4",
104
+ "unhead": "^3.4.3",
105
+ "unocss": "^66.12.0",
109
106
  "unplugin-icons": "^24.0.0",
110
107
  "unplugin-vue-components": "^32.1.0",
111
108
  "unplugin-vue-markdown": "^32.1.1",
112
109
  "untun": "^0.2.2",
113
110
  "uqr": "^0.1.3",
114
- "verkit": "^0.4.0",
115
- "vite": "^8.3.0",
116
- "vite-plugin-inspect": "^12.0.2",
111
+ "verkit": "^0.5.0",
112
+ "vite": "^8.3.6",
113
+ "vite-plugin-inspect": "^12.1.0",
117
114
  "vite-plugin-remote-assets": "^2.1.0",
118
115
  "vite-plugin-static-copy": "^4.1.1",
119
116
  "vite-plugin-vue-server-ref": "^1.0.0",
120
117
  "vitefu": "^1.1.3",
121
- "vue": "^3.5.42",
118
+ "vue": "^3.5.44",
122
119
  "yaml": "^2.9.1",
123
- "yargs": "^18.1.0",
124
- "zod": "^4.6.5"
120
+ "yargs": "^18.2.0",
121
+ "zod": "^4.6.7"
125
122
  },
126
123
  "devDependencies": {
127
124
  "@hedgedoc/markdown-it-plugins": "^2.1.4",
128
125
  "@types/picomatch": "^4.0.3",
129
126
  "@types/plantuml-encoder": "^1.4.2",
130
- "jszip": "^3.10.1"
127
+ "jszip": "^3.10.2"
131
128
  },
132
129
  "scripts": {
133
130
  "build": "tsdown node/index.ts node/cli.ts",
@@ -10,6 +10,10 @@ npx skills add slidevjs/slidev
10
10
 
11
11
  This will add the Slidev skill to your Claude Code configuration.
12
12
 
13
+ ## Requirements
14
+
15
+ Slidev itself needs [Node.js](https://nodejs.org) >= 22.12.0 and a package manager (pnpm recommended). The skill tells the agent to check for both before creating a project.
16
+
13
17
  ## What's Included
14
18
 
15
19
  The Slidev skill provides Claude Code with knowledge about:
@@ -17,6 +17,15 @@ Web-based slides maker built on Vite, Vue, and Markdown.
17
17
  - Export to PDF, PPTX, or host as SPA
18
18
  - Code walkthroughs for developer talks or workshops
19
19
 
20
+ ## Prerequisites
21
+
22
+ Slidev is a Node.js project. Before creating or running a deck, check that the machine has:
23
+
24
+ - **Node.js >= 22.12.0**: `node -v`. If it is missing or older, install the LTS release from https://nodejs.org or use a version manager such as `nvm` or `fnm`.
25
+ - **pnpm** (recommended package manager): `pnpm -v`. If it is missing, run `npm i -g pnpm` or `corepack enable`. npm, yarn, and bun also work; replace `pnpm` in the commands below.
26
+
27
+ Do not assume a development setup exists. If either check fails, walk the user through the installation before running any Slidev command.
28
+
20
29
  ## Quick Start
21
30
 
22
31
  ```bash
@@ -69,7 +69,7 @@ Options:
69
69
  | `--timeout` | 30000 | Timeout per slide (ms) |
70
70
  | `--range` | - | Slide range (e.g., 1,4-7) |
71
71
  | `--dark` | false | Export dark mode |
72
- | `--with-clicks` | false | Include click steps |
72
+ | `--with-clicks` | false (true for PPTX) | Include click steps |
73
73
  | `--with-toc` | false | PDF table of contents |
74
74
  | `--wait` | 0 | Wait ms before export |
75
75
  | `--wait-until` | networkidle | Wait condition |
@@ -12,6 +12,7 @@ Export presentations to PDF, PPTX, PNG, or Markdown.
12
12
  Access at `http://localhost:3030/export`:
13
13
  - Select format and options
14
14
  - Preview and download
15
+ - PPTX here is image-based; use the CLI for `pptx-editable`
15
16
 
16
17
  ## CLI Export
17
18
 
@@ -53,7 +54,7 @@ slidev export --format md
53
54
 
54
55
  ### With Click Steps
55
56
 
56
- Export each click as separate page:
57
+ Export each click as separate page (default for PPTX formats):
57
58
  ```bash
58
59
  slidev export --with-clicks
59
60
  ```
@@ -137,7 +138,7 @@ slidev export --wait 3000 --timeout 60000
137
138
 
138
139
  ### Wrong Global Layer State
139
140
 
140
- Use `--per-slide` or use `slide-top.vue` instead of `global-top.vue`.
141
+ Use `--per-slide` (not supported with `pptx-editable`) or use `slide-top.vue` instead of `global-top.vue`.
141
142
 
142
143
  ### Broken Emojis
143
144
 
@@ -47,4 +47,4 @@ Create in project root:
47
47
 
48
48
  ## Export Note
49
49
 
50
- Use `--per-slide` export option when global layers depend on navigation state.
50
+ Use `--per-slide` export option when global layers depend on navigation state (not supported with `pptx-editable`; use `slide-top.vue`/`slide-bottom.vue` instead).