@slidev/cli 0.49.16 → 0.49.18

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.
@@ -1,6 +1,9 @@
1
1
  import {
2
- __commonJS,
3
- __toESM,
2
+ escapeVueInCode,
3
+ getCodeBlocks,
4
+ normalizeRangeStr
5
+ } from "./chunk-6DS3IPOB.js";
6
+ import {
4
7
  createResolver,
5
8
  getRoots,
6
9
  isInstalledGlobally,
@@ -8,7 +11,11 @@ import {
8
11
  resolveImportPath,
9
12
  resolveImportUrl,
10
13
  toAtFS
11
- } from "./chunk-27Q2X57X.mjs";
14
+ } from "./chunk-2BABGNMX.js";
15
+ import {
16
+ __commonJS,
17
+ __toESM
18
+ } from "./chunk-JSBRDJBE.js";
12
19
 
13
20
  // ../../node_modules/.pnpm/yaml@2.4.5/node_modules/yaml/dist/nodes/identity.js
14
21
  var require_identity = __commonJS({
@@ -6266,7 +6273,7 @@ var require_parser = __commonJS({
6266
6273
  }
6267
6274
  }
6268
6275
  }
6269
- var Parser2 = class {
6276
+ var Parser = class {
6270
6277
  /**
6271
6278
  * @param onNewLine - If defined, called separately with the start position of
6272
6279
  * each new line (in `parse()`, including the start of input).
@@ -7025,7 +7032,7 @@ var require_parser = __commonJS({
7025
7032
  }
7026
7033
  }
7027
7034
  };
7028
- exports.Parser = Parser2;
7035
+ exports.Parser = Parser;
7029
7036
  }
7030
7037
  });
7031
7038
 
@@ -7176,17 +7183,17 @@ var require_dist = __commonJS({
7176
7183
  });
7177
7184
 
7178
7185
  // package.json
7179
- var version = "0.49.16";
7186
+ var version = "0.49.18";
7180
7187
 
7181
7188
  // node/commands/shared.ts
7182
7189
  import { existsSync as existsSync7, promises as fs9 } from "node:fs";
7183
- import { join as join10 } from "node:path";
7190
+ import { join as join11 } from "node:path";
7184
7191
  import { loadConfigFromFile, mergeConfig as mergeConfig2 } from "vite";
7185
7192
  import MarkdownIt from "markdown-it";
7186
- import { slash as slash5 } from "@antfu/utils";
7193
+ import { slash as slash4 } from "@antfu/utils";
7187
7194
 
7188
7195
  // node/syntax/markdown-it/markdown-it-link.ts
7189
- function markdownItLink(md) {
7196
+ function MarkdownItLink(md) {
7190
7197
  const defaultRender = md.renderer.rules.link_open ?? ((tokens, idx, options, _env, self) => self.renderToken(tokens, idx, options));
7191
7198
  md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
7192
7199
  const token = tokens[idx];
@@ -7210,7 +7217,14 @@ function markdownItLink(md) {
7210
7217
  }
7211
7218
 
7212
7219
  // node/utils.ts
7213
- var import_yaml = __toESM(require_dist());
7220
+ var import_yaml = __toESM(require_dist(), 1);
7221
+ import { fileURLToPath } from "node:url";
7222
+ import createJiti from "jiti";
7223
+ var jiti;
7224
+ function loadModule(absolutePath) {
7225
+ jiti ??= createJiti(fileURLToPath(import.meta.url));
7226
+ return jiti(absolutePath);
7227
+ }
7214
7228
  function stringifyMarkdownTokens(tokens) {
7215
7229
  return tokens.map((token) => token.children?.filter((t) => ["text", "code_inline"].includes(t.type) && !t.content.match(/^\s*$/)).map((t) => t.content.trim()).join(" ")).filter(Boolean).join(" ");
7216
7230
  }
@@ -7252,72 +7266,27 @@ function updateFrontmatterPatch(slide, frontmatter) {
7252
7266
  }
7253
7267
  }
7254
7268
  }
7255
-
7256
- // node/vite/index.ts
7257
- import { join as join9 } from "node:path";
7258
- import { existsSync as existsSync6 } from "node:fs";
7259
- import process2 from "node:process";
7260
- import { fileURLToPath as fileURLToPath4 } from "node:url";
7261
- import Icons from "unplugin-icons/vite";
7262
- import IconsResolver from "unplugin-icons/resolver";
7263
- import Components from "unplugin-vue-components/vite";
7264
- import ServerRef from "vite-plugin-vue-server-ref";
7265
- import { notNullish as notNullish2 } from "@antfu/utils";
7266
-
7267
- // node/integrations/drawings.ts
7268
- import { basename, dirname, join, resolve } from "node:path";
7269
- import fs from "fs-extra";
7270
- import fg from "fast-glob";
7271
- function resolveDrawingsDir(options) {
7272
- return options.data.config.drawings.persist ? resolve(
7273
- dirname(options.entry),
7274
- options.data.config.drawings.persist
7275
- ) : void 0;
7276
- }
7277
- async function loadDrawings(options) {
7278
- const dir = resolveDrawingsDir(options);
7279
- if (!dir || !fs.existsSync(dir))
7280
- return {};
7281
- const files = await fg("*.svg", {
7282
- onlyFiles: true,
7283
- cwd: dir,
7284
- absolute: true,
7285
- suppressErrors: true
7269
+ function getBodyJson(req) {
7270
+ return new Promise((resolve8, reject) => {
7271
+ let body = "";
7272
+ req.on("data", (chunk) => body += chunk);
7273
+ req.on("error", reject);
7274
+ req.on("end", () => {
7275
+ try {
7276
+ resolve8(JSON.parse(body) || {});
7277
+ } catch (e) {
7278
+ reject(e);
7279
+ }
7280
+ });
7286
7281
  });
7287
- const obj = {};
7288
- await Promise.all(files.map(async (path4) => {
7289
- const num = +basename(path4, ".svg");
7290
- if (Number.isNaN(num))
7291
- return;
7292
- const content = await fs.readFile(path4, "utf8");
7293
- const lines = content.split(/\n/g);
7294
- obj[num.toString()] = lines.slice(1, -1).join("\n");
7295
- }));
7296
- return obj;
7297
- }
7298
- async function writeDrawings(options, drawing) {
7299
- const dir = resolveDrawingsDir(options);
7300
- if (!dir)
7301
- return;
7302
- const width = options.data.config.canvasWidth;
7303
- const height = Math.round(width / options.data.config.aspectRatio);
7304
- const SVG_HEAD = `<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">`;
7305
- await fs.ensureDir(dir);
7306
- return Promise.all(
7307
- Object.entries(drawing).map(async ([key, value]) => {
7308
- if (!value)
7309
- return;
7310
- const svg = `${SVG_HEAD}
7311
- ${value}
7312
- </svg>`;
7313
- await fs.writeFile(join(dir, `${key}.svg`), svg, "utf-8");
7314
- })
7315
- );
7316
7282
  }
7317
7283
 
7284
+ // node/vite/compilerFlagsVue.ts
7285
+ import { objectEntries } from "@antfu/utils";
7286
+
7318
7287
  // node/vite/extendConfig.ts
7319
- import { join as join2 } from "node:path";
7320
- import { fileURLToPath, pathToFileURL } from "node:url";
7288
+ import { join } from "node:path";
7289
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
7321
7290
  import { mergeConfig } from "vite";
7322
7291
  import { slash, uniq } from "@antfu/utils";
7323
7292
  import { createResolve } from "mlly";
@@ -7398,7 +7367,7 @@ function createConfigPlugin(options) {
7398
7367
  },
7399
7368
  ...isInstalledGlobally.value ? await Promise.all(INCLUDE_GLOBAL.map(async (dep) => ({
7400
7369
  find: dep,
7401
- replacement: fileURLToPath(await resolveClientDep(dep))
7370
+ replacement: fileURLToPath2(await resolveClientDep(dep))
7402
7371
  }))) : []
7403
7372
  ],
7404
7373
  dedupe: ["vue"]
@@ -7430,7 +7399,7 @@ function createConfigPlugin(options) {
7430
7399
  ])
7431
7400
  }
7432
7401
  },
7433
- publicDir: join2(options.userRoot, "public"),
7402
+ publicDir: join(options.userRoot, "public"),
7434
7403
  build: {
7435
7404
  rollupOptions: {
7436
7405
  output: {
@@ -7463,7 +7432,7 @@ function createConfigPlugin(options) {
7463
7432
  return id.includes("/@slidev/") || id.includes("/slidev/packages/client/") || id.includes("/@vueuse/");
7464
7433
  }
7465
7434
  if (isInstalledGlobally.value) {
7466
- injection.cacheDir = join2(options.cliRoot, "node_modules/.vite");
7435
+ injection.cacheDir = join(options.cliRoot, "node_modules/.vite");
7467
7436
  injection.root = options.cliRoot;
7468
7437
  }
7469
7438
  return mergeConfig(injection, config);
@@ -7499,11 +7468,206 @@ function getDefine(options) {
7499
7468
  };
7500
7469
  }
7501
7470
 
7471
+ // node/vite/compilerFlagsVue.ts
7472
+ function createVueCompilerFlagsPlugin(options) {
7473
+ const define = objectEntries(getDefine(options));
7474
+ return [
7475
+ {
7476
+ name: "slidev:flags",
7477
+ enforce: "pre",
7478
+ transform(code, id) {
7479
+ if (id.match(/\.vue($|\?)/)) {
7480
+ const original = code;
7481
+ define.forEach(([from, to]) => {
7482
+ code = code.replace(new RegExp(from, "g"), to);
7483
+ });
7484
+ if (original !== code)
7485
+ return code;
7486
+ }
7487
+ }
7488
+ }
7489
+ ];
7490
+ }
7491
+
7492
+ // node/vite/components.ts
7493
+ import { join as join2 } from "node:path";
7494
+ import IconsResolver from "unplugin-icons/resolver";
7495
+ import Components from "unplugin-vue-components/vite";
7496
+ function createComponentsPlugin({ clientRoot, roots }, pluginOptions) {
7497
+ return Components({
7498
+ extensions: ["vue", "md", "js", "ts", "jsx", "tsx"],
7499
+ dirs: [
7500
+ join2(clientRoot, "builtin"),
7501
+ ...roots.map((i) => join2(i, "components"))
7502
+ ],
7503
+ include: [/\.vue$/, /\.vue\?vue/, /\.vue\?v=/, /\.md$/, /\.md\?vue/],
7504
+ exclude: [],
7505
+ resolvers: [
7506
+ IconsResolver({
7507
+ prefix: "",
7508
+ customCollections: Object.keys(pluginOptions.icons?.customCollections || [])
7509
+ })
7510
+ ],
7511
+ dts: false,
7512
+ ...pluginOptions.components
7513
+ });
7514
+ }
7515
+
7516
+ // node/vite/common.ts
7517
+ var regexSlideReqPath = /^\/__slidev\/slides\/(\d+)\.json$/;
7518
+ var regexSlideFacadeId = /^\/@slidev\/slides\/(\d+)\/(md|frontmatter)($|\?)/;
7519
+ var regexSlideSourceId = /__slidev_(\d+)\.(md|frontmatter)$/;
7520
+ var templateInjectionMarker = "/* @slidev-injection */";
7521
+ var templateImportContextUtils = `import { useSlideContext as _useSlideContext, frontmatterToProps as _frontmatterToProps } from "@slidev/client/context.ts"`;
7522
+ var templateInitContext = `const { $slidev, $nav, $clicksContext, $clicks, $page, $renderContext, $frontmatter } = _useSlideContext()`;
7523
+
7524
+ // node/vite/contextInjection.ts
7525
+ function createContextInjectionPlugin() {
7526
+ return {
7527
+ name: "slidev:context-injection",
7528
+ async transform(code, id) {
7529
+ if (!id.endsWith(".vue") || id.includes("/@slidev/client/") || id.includes("/packages/client/"))
7530
+ return;
7531
+ if (code.includes(templateInjectionMarker) || code.includes("useSlideContext()"))
7532
+ return code;
7533
+ const imports = [
7534
+ templateImportContextUtils,
7535
+ templateInitContext,
7536
+ templateInjectionMarker
7537
+ ];
7538
+ const matchScript = code.match(/<script((?!setup).)*(setup)?.*>/);
7539
+ if (matchScript && matchScript[2]) {
7540
+ return code.replace(/(<script.*>)/g, `$1
7541
+ ${imports.join("\n")}
7542
+ `);
7543
+ } else if (matchScript && !matchScript[2]) {
7544
+ const matchExport = code.match(/export\s+default\s+\{/);
7545
+ if (matchExport) {
7546
+ const exportIndex = (matchExport.index || 0) + matchExport[0].length;
7547
+ let component = code.slice(exportIndex);
7548
+ component = component.slice(0, component.indexOf("</script>"));
7549
+ const scriptIndex = (matchScript.index || 0) + matchScript[0].length;
7550
+ const provideImport = '\nimport { injectionSlidevContext } from "@slidev/client/constants.ts"\n';
7551
+ code = `${code.slice(0, scriptIndex)}${provideImport}${code.slice(scriptIndex)}`;
7552
+ let injectIndex = exportIndex + provideImport.length;
7553
+ let injectObject = "$slidev: { from: injectionSlidevContext },";
7554
+ const matchInject = component.match(/.*inject\s*:\s*([[{])/);
7555
+ if (matchInject) {
7556
+ injectIndex += (matchInject.index || 0) + matchInject[0].length;
7557
+ if (matchInject[1] === "[") {
7558
+ let injects = component.slice((matchInject.index || 0) + matchInject[0].length);
7559
+ const injectEndIndex = injects.indexOf("]");
7560
+ injects = injects.slice(0, injectEndIndex);
7561
+ injectObject += injects.split(",").map((inject) => `${inject}: {from: ${inject}}`).join(",");
7562
+ return `${code.slice(0, injectIndex - 1)}{
7563
+ ${injectObject}
7564
+ }${code.slice(injectIndex + injectEndIndex + 1)}`;
7565
+ } else {
7566
+ return `${code.slice(0, injectIndex)}
7567
+ ${injectObject}
7568
+ ${code.slice(injectIndex)}`;
7569
+ }
7570
+ }
7571
+ return `${code.slice(0, injectIndex)}
7572
+ inject: { ${injectObject} },
7573
+ ${code.slice(injectIndex)}`;
7574
+ }
7575
+ }
7576
+ return `<script setup>
7577
+ ${imports.join("\n")}
7578
+ </script>
7579
+ ${code}`;
7580
+ }
7581
+ };
7582
+ }
7583
+
7584
+ // node/vite/hmrPatch.ts
7585
+ function createHmrPatchPlugin() {
7586
+ return {
7587
+ name: "slidev:slide-transform:post",
7588
+ transform(code, id) {
7589
+ if (!id.match(regexSlideSourceId))
7590
+ return;
7591
+ return code.replace("if (_rerender_only)", "if (false)");
7592
+ }
7593
+ };
7594
+ }
7595
+
7596
+ // node/vite/icons.ts
7597
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
7598
+ import Icons from "unplugin-icons/vite";
7599
+ function createIconsPlugin(_options, pluginOptions) {
7600
+ return Icons({
7601
+ defaultClass: "slidev-icon",
7602
+ collectionsNodeResolvePath: fileURLToPath3(import.meta.url),
7603
+ ...pluginOptions.icons
7604
+ });
7605
+ }
7606
+
7607
+ // node/vite/inspect.ts
7608
+ async function createInspectPlugin(options, pluginOptions) {
7609
+ if (!options.inspect)
7610
+ return;
7611
+ const { default: PluginInspect } = await import("vite-plugin-inspect");
7612
+ return PluginInspect({
7613
+ dev: true,
7614
+ build: true,
7615
+ ...pluginOptions.inspect
7616
+ });
7617
+ }
7618
+
7619
+ // node/vite/layoutWrapper.ts
7620
+ import { bold, gray, red, yellow } from "kolorist";
7621
+ function createLayoutWrapperPlugin({ data, utils }) {
7622
+ return {
7623
+ name: "slidev:layout-wrapper",
7624
+ async transform(code, id) {
7625
+ const match = id.match(regexSlideSourceId);
7626
+ if (!match)
7627
+ return;
7628
+ const [, no, type] = match;
7629
+ if (type !== "md")
7630
+ return;
7631
+ const index = +no - 1;
7632
+ const layouts = await utils.getLayouts();
7633
+ const rawLayoutName = data.slides[index]?.frontmatter?.layout ?? data.slides[0]?.frontmatter?.default?.layout;
7634
+ let layoutName = rawLayoutName || (index === 0 ? "cover" : "default");
7635
+ if (!layouts[layoutName]) {
7636
+ console.error(red(`
7637
+ Unknown layout "${bold(layoutName)}".${yellow(" Available layouts are:")}`) + Object.keys(layouts).map((i, idx) => (idx % 3 === 0 ? "\n " : "") + gray(i.padEnd(15, " "))).join(" "));
7638
+ console.error();
7639
+ layoutName = "default";
7640
+ }
7641
+ const setupTag = code.match(/^<script setup.*>/m);
7642
+ if (!setupTag)
7643
+ throw new Error(`[Slidev] Internal error: <script setup> block not found in slide ${index + 1}.`);
7644
+ const templatePart = code.slice(0, setupTag.index);
7645
+ const scriptPart = code.slice(setupTag.index);
7646
+ const bodyStart = templatePart.indexOf("<template>") + 10;
7647
+ const bodyEnd = templatePart.lastIndexOf("</template>");
7648
+ let body = code.slice(bodyStart, bodyEnd).trim();
7649
+ if (body.startsWith("<div>") && body.endsWith("</div>"))
7650
+ body = body.slice(5, -6);
7651
+ return [
7652
+ templatePart.slice(0, bodyStart),
7653
+ `<InjectedLayout v-bind="_frontmatterToProps($frontmatter,${index})">
7654
+ ${body}
7655
+ </InjectedLayout>`,
7656
+ templatePart.slice(bodyEnd),
7657
+ scriptPart.slice(0, setupTag[0].length),
7658
+ `import InjectedLayout from "${toAtFS(layouts[layoutName])}"`,
7659
+ templateImportContextUtils,
7660
+ templateInitContext,
7661
+ "$clicksContext.setup()",
7662
+ templateInjectionMarker,
7663
+ scriptPart.slice(setupTag[0].length)
7664
+ ].join("\n");
7665
+ }
7666
+ };
7667
+ }
7668
+
7502
7669
  // node/vite/loaders.ts
7503
- import path from "node:path";
7504
7670
  import { notNullish, range } from "@antfu/utils";
7505
- import fg3 from "fast-glob";
7506
- import { bold, gray, red, yellow } from "kolorist";
7507
7671
  import * as parser2 from "@slidev/parser/fs";
7508
7672
  import equal from "fast-deep-equal";
7509
7673
 
@@ -7511,14 +7675,14 @@ import equal from "fast-deep-equal";
7511
7675
  import { isString } from "@antfu/utils";
7512
7676
  var templateConfigs = {
7513
7677
  id: "/@slidev/configs",
7514
- getContent: async ({ data, remote }, { md }) => {
7678
+ getContent({ data, remote }) {
7515
7679
  const config = {
7516
7680
  ...data.config,
7517
7681
  remote,
7518
7682
  slidesTitle: getSlideTitle(data)
7519
7683
  };
7520
7684
  if (isString(config.info))
7521
- config.info = md.render(config.info);
7685
+ config.info = sharedMd.render(config.info);
7522
7686
  return `export default ${JSON.stringify(config)}`;
7523
7687
  }
7524
7688
  };
@@ -7535,7 +7699,7 @@ var templateLegacyRoutes = {
7535
7699
  };
7536
7700
  var templateLegacyTitles = {
7537
7701
  id: "/@slidev/titles.md",
7538
- async getContent() {
7702
+ getContent() {
7539
7703
  return `
7540
7704
  <script setup lang="ts">
7541
7705
  import TitleRenderer from '#slidev/title-renderer'
@@ -7604,10 +7768,10 @@ export default {
7604
7768
  import { objectMap } from "@antfu/utils";
7605
7769
  var templateLayouts = {
7606
7770
  id: "/@slidev/layouts",
7607
- async getContent(_, { getLayouts }) {
7771
+ getContent({ utils }) {
7608
7772
  const imports = [];
7609
7773
  const layouts = objectMap(
7610
- await getLayouts(),
7774
+ utils.getLayouts(),
7611
7775
  (k, v) => {
7612
7776
  imports.push(`import __layout_${k} from "${toAtFS(v)}"`);
7613
7777
  return [k, `__layout_${k}`];
@@ -7623,19 +7787,19 @@ ${Object.entries(layouts).map(([k, v]) => `"${k}": ${v}`).join(",\n")}
7623
7787
  };
7624
7788
 
7625
7789
  // node/virtual/monaco-deps.ts
7626
- import { resolve as resolve2 } from "node:path";
7790
+ import { resolve } from "node:path";
7627
7791
  import { uniq as uniq2 } from "@antfu/utils";
7628
7792
  var templateMonacoRunDeps = {
7629
7793
  id: "/@slidev/monaco-run-deps",
7630
- getContent: async ({ userRoot, data }, _ctx, pluginCtx) => {
7794
+ async getContent({ userRoot, data }) {
7631
7795
  if (!data.features.monaco)
7632
7796
  return "";
7633
7797
  const deps = uniq2(data.features.monaco.deps.concat(data.config.monacoTypesAdditionalPackages));
7634
- const importerPath = resolve2(userRoot, "./snippets/__importer__.ts");
7798
+ const importerPath = resolve(userRoot, "./snippets/__importer__.ts");
7635
7799
  let result = "";
7636
7800
  for (let i = 0; i < deps.length; i++) {
7637
7801
  const specifier = deps[i];
7638
- const resolved = await pluginCtx.resolve(specifier, importerPath);
7802
+ const resolved = await this.resolve(specifier, importerPath);
7639
7803
  if (!resolved)
7640
7804
  continue;
7641
7805
  result += `import * as vendored${i} from ${JSON.stringify(resolved.id)}
@@ -7652,8 +7816,8 @@ var templateMonacoRunDeps = {
7652
7816
 
7653
7817
  // node/virtual/monaco-types.ts
7654
7818
  import { builtinModules } from "node:module";
7655
- import { join as join5, resolve as resolve3 } from "node:path";
7656
- import fg2 from "fast-glob";
7819
+ import { join as join5, resolve as resolve2 } from "node:path";
7820
+ import fg from "fast-glob";
7657
7821
  import { uniq as uniq3 } from "@antfu/utils";
7658
7822
  var templateMonacoTypes = {
7659
7823
  id: "/@slidev/monaco-types",
@@ -7661,10 +7825,10 @@ var templateMonacoTypes = {
7661
7825
  if (!data.features.monaco)
7662
7826
  return "";
7663
7827
  const typesRoot = join5(userRoot, "snippets");
7664
- const files = await fg2(["**/*.ts", "**/*.mts", "**/*.cts"], { cwd: typesRoot });
7828
+ const files = await fg(["**/*.ts", "**/*.mts", "**/*.cts"], { cwd: typesRoot });
7665
7829
  let result = 'import { addFile } from "@slidev/client/setup/monaco.ts"\n';
7666
7830
  for (const file of files) {
7667
- const url = `${toAtFS(resolve3(typesRoot, file))}?monaco-types&raw`;
7831
+ const url = `${toAtFS(resolve2(typesRoot, file))}?monaco-types&raw`;
7668
7832
  result += `addFile(() => import(${JSON.stringify(url)}), ${JSON.stringify(file)})
7669
7833
  `;
7670
7834
  }
@@ -7720,68 +7884,12 @@ function createSetupTemplate(name) {
7720
7884
  var setupModules = ["shiki", "code-runners", "monaco", "mermaid", "main", "root", "routes", "shortcuts", "context-menu"];
7721
7885
  var templateSetups = setupModules.map(createSetupTemplate);
7722
7886
 
7723
- // node/setups/shiki.ts
7724
- import fs3 from "node:fs/promises";
7725
-
7726
- // node/setups/load.ts
7727
- import { resolve as resolve4 } from "node:path";
7728
- import { fileURLToPath as fileURLToPath2 } from "node:url";
7729
- import fs2 from "fs-extra";
7730
- import { deepMergeWithArray } from "@antfu/utils";
7731
- import jiti from "jiti";
7732
- async function loadSetups(clientRoot, roots, name, arg, initial, merge = true) {
7733
- let returns = initial;
7734
- for (const root of [clientRoot, ...roots].reverse()) {
7735
- const path4 = resolve4(root, "setup", name);
7736
- if (fs2.existsSync(path4)) {
7737
- const { default: setup } = jiti(fileURLToPath2(import.meta.url))(path4);
7738
- const result = await setup(arg);
7739
- if (result !== null) {
7740
- returns = typeof merge === "function" ? merge(returns, result) : merge ? deepMergeWithArray(returns, result) : result;
7741
- }
7742
- }
7743
- }
7744
- return returns;
7745
- }
7746
-
7747
- // node/setups/shiki.ts
7748
- async function loadShikiSetups(clientRoot, roots) {
7749
- const result = await loadSetups(
7750
- clientRoot,
7751
- roots,
7752
- "shiki.ts",
7753
- {
7754
- /** @deprecated */
7755
- async loadTheme(path4) {
7756
- console.warn("[slidev] `loadTheme` in `setup/shiki.ts` is deprecated. Pass directly the theme name it's supported by Shiki. For custom themes, load it manually via `JSON.parse(fs.readFileSync(path, 'utf-8'))` and pass the raw JSON object instead.");
7757
- return JSON.parse(await fs3.readFile(path4, "utf-8"));
7758
- }
7759
- },
7760
- {},
7761
- false
7762
- );
7763
- if ("theme" in result && "themes" in result)
7764
- delete result.theme;
7765
- if (result.theme && typeof result.theme !== "string" && !result.theme.name && !result.theme.tokenColors) {
7766
- result.themes = result.theme;
7767
- delete result.theme;
7768
- }
7769
- if (!result.theme && !result.themes) {
7770
- result.themes = {
7771
- dark: "vitesse-dark",
7772
- light: "vitesse-light"
7773
- };
7774
- }
7775
- if (result.themes)
7776
- result.defaultColor = false;
7777
- return result;
7778
- }
7779
-
7780
7887
  // node/virtual/shiki.ts
7888
+ import { uniq as uniq4 } from "@antfu/utils";
7781
7889
  var templateShiki = {
7782
7890
  id: "/@slidev/shiki",
7783
- getContent: async ({ clientRoot, roots }) => {
7784
- const options = await loadShikiSetups(clientRoot, roots);
7891
+ getContent: async ({ utils }) => {
7892
+ const options = utils.shikiOptions;
7785
7893
  const langs = await resolveLangs(options.langs || ["markdown", "vue", "javascript", "typescript", "html", "css"]);
7786
7894
  const resolvedThemeOptions = "themes" in options ? {
7787
7895
  themes: Object.fromEntries(await Promise.all(
@@ -7793,12 +7901,12 @@ var templateShiki = {
7793
7901
  const themes = resolvedThemeOptions.themes ? Object.values(resolvedThemeOptions.themes) : [resolvedThemeOptions.theme];
7794
7902
  const themeOptionsNames = resolvedThemeOptions.themes ? { themes: Object.fromEntries(Object.entries(resolvedThemeOptions.themes).map(([name, value]) => [name, typeof value === "string" ? value : value.name])) } : { theme: typeof resolvedThemeOptions.theme === "string" ? resolvedThemeOptions.theme : resolvedThemeOptions.theme.name };
7795
7903
  async function normalizeGetter(p) {
7796
- return Promise.resolve(typeof p === "function" ? p() : p).then((r) => r.default || r);
7904
+ const r = typeof p === "function" ? p() : p;
7905
+ return r.default || r;
7797
7906
  }
7798
7907
  async function resolveLangs(langs2) {
7799
- return Array.from(new Set((await Promise.all(
7800
- langs2.map(async (lang) => await normalizeGetter(lang).then((r) => Array.isArray(r) ? r : [r]))
7801
- )).flat()));
7908
+ const awaited = await Promise.all(langs2.map((lang) => normalizeGetter(lang)));
7909
+ return uniq4(awaited.flat());
7802
7910
  }
7803
7911
  async function resolveTheme2(theme) {
7804
7912
  return typeof theme === "string" ? theme : await normalizeGetter(theme);
@@ -7841,37 +7949,42 @@ var templateShiki = {
7841
7949
  var VIRTUAL_SLIDE_PREFIX = "/@slidev/slides/";
7842
7950
  var templateSlides = {
7843
7951
  id: "/@slidev/slides",
7844
- async getContent({ data }, { getLayouts }) {
7845
- const layouts = await getLayouts();
7846
- const imports = [
7847
- `import { shallowRef } from 'vue'`,
7848
- `import * as __layout__error from '${layouts.error}'`
7952
+ getContent({ data, utils }) {
7953
+ const layouts = utils.getLayouts();
7954
+ const statements = [
7955
+ `import { defineAsyncComponent, shallowRef } from 'vue'`,
7956
+ `import SlideError from '${layouts.error}'`,
7957
+ `import SlideLoading from '@slidev/client/internals/SlideLoading.vue'`,
7958
+ `const componentsCache = new Array(${data.slides.length})`,
7959
+ `const getAsyncComponent = (idx, loader) => defineAsyncComponent({`,
7960
+ ` loader,`,
7961
+ ` delay: 300,`,
7962
+ ` loadingComponent: SlideLoading,`,
7963
+ ` errorComponent: SlideError,`,
7964
+ ` onError: e => console.error('Failed to load slide ' + (idx + 1), e) `,
7965
+ `})`
7849
7966
  ];
7850
7967
  const slides = data.slides.map((_, idx) => {
7851
7968
  const no = idx + 1;
7852
- imports.push(`import { meta as f${no} } from '${VIRTUAL_SLIDE_PREFIX}${no}.frontmatter'`);
7853
- return `{
7854
- no: ${no},
7855
- meta: f${no},
7856
- component: async () => {
7857
- try {
7858
- return await import('${VIRTUAL_SLIDE_PREFIX}${no}.md')
7859
- }
7860
- catch(e) {
7861
- console.error('Failed to load slide ${no}:', e)
7862
- return __layout__error
7863
- }
7864
- },
7865
- }`;
7969
+ statements.push(
7970
+ `import { meta as f${no} } from '${VIRTUAL_SLIDE_PREFIX}${no}/frontmatter'`,
7971
+ // For some unknown reason, import error won't be caught by the error component. Catch it here.
7972
+ `const load${no} = async () => {`,
7973
+ ` try { return componentsCache[${idx}] ??= await import('${VIRTUAL_SLIDE_PREFIX}${no}/md') }`,
7974
+ ` catch (e) { return SlideError }`,
7975
+ `}`
7976
+ );
7977
+ return `{ no: ${no}, meta: f${no}, load: load${no}, component: getAsyncComponent(${idx}, load${no}) }`;
7866
7978
  });
7867
7979
  return [
7868
- ...imports,
7980
+ ...statements,
7869
7981
  `const data = [
7870
7982
  ${slides.join(",\n")}
7871
7983
  ]`,
7872
7984
  `if (import.meta.hot) {`,
7873
7985
  ` import.meta.hot.data.slides ??= shallowRef()`,
7874
7986
  ` import.meta.hot.data.slides.value = data`,
7987
+ ` import.meta.hot.dispose(() => componentsCache.length = 0)`,
7875
7988
  ` import.meta.hot.accept()`,
7876
7989
  `}`,
7877
7990
  `export const slides = import.meta.hot ? import.meta.hot.data.slides : shallowRef(data)`
@@ -7884,7 +7997,7 @@ import { join as join7 } from "node:path";
7884
7997
  import { existsSync as existsSync4 } from "node:fs";
7885
7998
  var templateStyle = {
7886
7999
  id: "/@slidev/styles",
7887
- getContent: async ({ data, clientRoot, roots }) => {
8000
+ async getContent({ data, clientRoot, roots }) {
7888
8001
  function resolveUrlOfClient(name) {
7889
8002
  return toAtFS(join7(clientRoot, name));
7890
8003
  }
@@ -7933,7 +8046,7 @@ var templateStyle = {
7933
8046
  // node/virtual/titles.ts
7934
8047
  var templateTitleRendererMd = {
7935
8048
  id: "/@slidev/title-renderer.md",
7936
- async getContent({ data }) {
8049
+ getContent({ data }) {
7937
8050
  const lines = data.slides.map(({ title }, i) => `<template ${i === 0 ? "v-if" : "v-else-if"}="no === ${i + 1}">
7938
8051
 
7939
8052
  ${title}
@@ -7941,7 +8054,7 @@ ${title}
7941
8054
  </template>`);
7942
8055
  lines.push(
7943
8056
  `<script setup lang="ts">`,
7944
- `import { useSlideContext } from '@slidev/client'`,
8057
+ `import { useSlideContext } from '@slidev/client/context.ts'`,
7945
8058
  `import { computed } from 'vue'`,
7946
8059
  `const props = defineProps<{ no?: number | string }>()`,
7947
8060
  `const { $page } = useSlideContext()`,
@@ -7978,16 +8091,18 @@ var templates = [
7978
8091
  ];
7979
8092
 
7980
8093
  // node/options.ts
7981
- import { uniq as uniq4 } from "@antfu/utils";
8094
+ import path from "node:path";
8095
+ import { uniq as uniq5 } from "@antfu/utils";
7982
8096
  import Debug from "debug";
7983
8097
  import mm from "micromatch";
8098
+ import fg2 from "fast-glob";
7984
8099
 
7985
8100
  // node/parser.ts
7986
8101
  import * as parser from "@slidev/parser/fs";
7987
8102
 
7988
8103
  // node/integrations/themes.ts
7989
8104
  import { join as join8 } from "node:path";
7990
- import fs4 from "fs-extra";
8105
+ import fs from "fs-extra";
7991
8106
  import { satisfies } from "semver";
7992
8107
  var officialThemes = {
7993
8108
  "none": "",
@@ -8000,17 +8115,17 @@ var officialThemes = {
8000
8115
  var resolveTheme = createResolver("theme", officialThemes);
8001
8116
  async function getThemeMeta(name, root) {
8002
8117
  const path4 = join8(root, "package.json");
8003
- if (!fs4.existsSync(path4))
8118
+ if (!fs.existsSync(path4))
8004
8119
  return {};
8005
- const { slidev = {}, engines = {} } = await fs4.readJSON(path4);
8120
+ const { slidev = {}, engines = {} } = await fs.readJSON(path4);
8006
8121
  if (engines.slidev && !satisfies(version, engines.slidev, { includePrerelease: true }))
8007
8122
  throw new Error(`[slidev] theme "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
8008
8123
  return slidev;
8009
8124
  }
8010
8125
 
8011
8126
  // node/integrations/addons.ts
8012
- import { resolve as resolve5 } from "node:path";
8013
- import fs5 from "fs-extra";
8127
+ import { resolve as resolve3 } from "node:path";
8128
+ import fs2 from "fs-extra";
8014
8129
  import { satisfies as satisfies2 } from "semver";
8015
8130
  async function resolveAddons(addonsInConfig) {
8016
8131
  const { userRoot, userPkgJson } = await getRoots();
@@ -8021,7 +8136,7 @@ async function resolveAddons(addonsInConfig) {
8021
8136
  if (!pkgRoot)
8022
8137
  return;
8023
8138
  resolved.push(pkgRoot);
8024
- const { slidev = {}, engines = {} } = await fs5.readJSON(resolve5(pkgRoot, "package.json"));
8139
+ const { slidev = {}, engines = {} } = await fs2.readJSON(resolve3(pkgRoot, "package.json"));
8025
8140
  if (engines.slidev && !satisfies2(version, engines.slidev, { includePrerelease: true }))
8026
8141
  throw new Error(`[slidev] addon "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
8027
8142
  if (Array.isArray(slidev.addons))
@@ -8034,23 +8149,86 @@ async function resolveAddons(addonsInConfig) {
8034
8149
  return resolved;
8035
8150
  }
8036
8151
 
8152
+ // node/setups/shiki.ts
8153
+ import fs4 from "node:fs/promises";
8154
+ import { bundledLanguages, createHighlighter } from "shiki";
8155
+
8156
+ // node/setups/load.ts
8157
+ import { resolve as resolve4 } from "node:path";
8158
+ import fs3 from "fs-extra";
8159
+ import { deepMergeWithArray } from "@antfu/utils";
8160
+ async function loadSetups(roots, filename, args, extraLoader) {
8161
+ const returns = [];
8162
+ for (const root of roots) {
8163
+ const path4 = resolve4(root, "setup", filename);
8164
+ if (fs3.existsSync(path4)) {
8165
+ const { default: setup } = loadModule(path4);
8166
+ const ret = await setup(...args);
8167
+ if (ret)
8168
+ returns.push(ret);
8169
+ }
8170
+ if (extraLoader)
8171
+ returns.push(...extraLoader(root));
8172
+ }
8173
+ return returns;
8174
+ }
8175
+
8176
+ // node/setups/shiki.ts
8177
+ async function setupShiki(roots) {
8178
+ const options = await loadSetups(
8179
+ roots,
8180
+ "shiki.ts",
8181
+ [{
8182
+ /** @deprecated */
8183
+ async loadTheme(path4) {
8184
+ console.warn("[slidev] `loadTheme` in `setup/shiki.ts` is deprecated. Pass directly the theme name it's supported by Shiki. For custom themes, load it manually via `JSON.parse(fs.readFileSync(path, 'utf-8'))` and pass the raw JSON object instead.");
8185
+ return JSON.parse(await fs4.readFile(path4, "utf-8"));
8186
+ }
8187
+ }]
8188
+ );
8189
+ const mergedOptions = Object.assign({}, ...options);
8190
+ if ("theme" in mergedOptions && "themes" in mergedOptions)
8191
+ delete mergedOptions.theme;
8192
+ if (mergedOptions.theme && typeof mergedOptions.theme !== "string" && !mergedOptions.theme.name && !mergedOptions.theme.tokenColors) {
8193
+ mergedOptions.themes = mergedOptions.theme;
8194
+ delete mergedOptions.theme;
8195
+ }
8196
+ if (!mergedOptions.theme && !mergedOptions.themes) {
8197
+ mergedOptions.themes = {
8198
+ dark: "vitesse-dark",
8199
+ light: "vitesse-light"
8200
+ };
8201
+ }
8202
+ if (mergedOptions.themes)
8203
+ mergedOptions.defaultColor = false;
8204
+ const shiki = await createHighlighter({
8205
+ ...mergedOptions,
8206
+ langs: mergedOptions.langs ?? Object.keys(bundledLanguages),
8207
+ themes: "themes" in mergedOptions ? Object.values(mergedOptions.themes) : [mergedOptions.theme]
8208
+ });
8209
+ return {
8210
+ shiki,
8211
+ shikiOptions: mergedOptions
8212
+ };
8213
+ }
8214
+
8037
8215
  // node/options.ts
8038
8216
  var debug = Debug("slidev:options");
8039
- async function resolveOptions(options, mode) {
8040
- const entry = await resolveEntry(options.entry);
8217
+ async function resolveOptions(entryOptions, mode) {
8218
+ const entry = await resolveEntry(entryOptions.entry);
8041
8219
  const rootsInfo = await getRoots(entry);
8042
8220
  const loaded = await parser.load(rootsInfo.userRoot, entry, void 0, mode);
8043
- let themeRaw = options.theme || loaded.headmatter.theme;
8221
+ let themeRaw = entryOptions.theme || loaded.headmatter.theme;
8044
8222
  themeRaw = themeRaw === null ? "none" : themeRaw || "default";
8045
8223
  const [theme, themeRoot] = await resolveTheme(themeRaw, entry);
8046
8224
  const themeRoots = themeRoot ? [themeRoot] : [];
8047
8225
  const themeMeta = themeRoot ? await getThemeMeta(theme, themeRoot) : void 0;
8048
- const config = parser.resolveConfig(loaded.headmatter, themeMeta, options.entry);
8226
+ const config = parser.resolveConfig(loaded.headmatter, themeMeta, entryOptions.entry);
8049
8227
  const addonRoots = await resolveAddons(config.addons);
8050
- const roots = uniq4([...themeRoots, ...addonRoots, rootsInfo.userRoot]);
8228
+ const roots = uniq5([...themeRoots, ...addonRoots, rootsInfo.userRoot]);
8051
8229
  debug({
8052
8230
  ...rootsInfo,
8053
- ...options,
8231
+ ...entryOptions,
8054
8232
  config,
8055
8233
  mode,
8056
8234
  entry,
@@ -8067,7 +8245,7 @@ async function resolveOptions(options, mode) {
8067
8245
  };
8068
8246
  const resolved = {
8069
8247
  ...rootsInfo,
8070
- ...options,
8248
+ ...entryOptions,
8071
8249
  data,
8072
8250
  mode,
8073
8251
  entry,
@@ -8076,37 +8254,41 @@ async function resolveOptions(options, mode) {
8076
8254
  themeRoots,
8077
8255
  addonRoots,
8078
8256
  roots,
8079
- utils: createDataUtils(data)
8257
+ utils: await createDataUtils(data, rootsInfo.clientRoot, roots)
8080
8258
  };
8081
8259
  return resolved;
8082
8260
  }
8083
- function createDataUtils(data) {
8261
+ async function createDataUtils(data, clientRoot, roots) {
8084
8262
  const monacoTypesIgnorePackagesMatches = (data.config.monacoTypesIgnorePackages || []).map((i) => mm.matcher(i));
8263
+ let _layouts_cache_time = 0;
8264
+ let _layouts_cache = {};
8085
8265
  return {
8086
- isMonacoTypesIgnored: (pkg) => monacoTypesIgnorePackagesMatches.some((i) => i(pkg))
8266
+ ...await setupShiki(roots),
8267
+ isMonacoTypesIgnored: (pkg) => monacoTypesIgnorePackagesMatches.some((i) => i(pkg)),
8268
+ getLayouts: () => {
8269
+ const now = Date.now();
8270
+ if (now - _layouts_cache_time < 2e3)
8271
+ return _layouts_cache;
8272
+ const layouts = {};
8273
+ for (const root of [clientRoot, ...roots]) {
8274
+ const layoutPaths = fg2.sync("layouts/**/*.{vue,ts}", {
8275
+ cwd: root,
8276
+ absolute: true,
8277
+ suppressErrors: true
8278
+ });
8279
+ for (const layoutPath of layoutPaths) {
8280
+ const layoutName = path.basename(layoutPath).replace(/\.\w+$/, "");
8281
+ layouts[layoutName] = layoutPath;
8282
+ }
8283
+ }
8284
+ _layouts_cache_time = now;
8285
+ _layouts_cache = layouts;
8286
+ return layouts;
8287
+ }
8087
8288
  };
8088
8289
  }
8089
8290
 
8090
8291
  // node/vite/loaders.ts
8091
- var regexId = /^\/@slidev\/slide\/(\d+)\.(md|json)(?:\?import)?$/;
8092
- var regexIdQuery = /(\d+)\.(md|json|frontmatter)$/;
8093
- var templateInjectionMarker = "/* @slidev-injection */";
8094
- var templateImportContextUtils = `import { useSlideContext as _useSlideContext, frontmatterToProps as _frontmatterToProps } from "@slidev/client/context.ts"`;
8095
- var templateInitContext = `const { $slidev, $nav, $clicksContext, $clicks, $page, $renderContext, $frontmatter } = _useSlideContext()`;
8096
- function getBodyJson(req) {
8097
- return new Promise((resolve8, reject) => {
8098
- let body = "";
8099
- req.on("data", (chunk) => body += chunk);
8100
- req.on("error", reject);
8101
- req.on("end", () => {
8102
- try {
8103
- resolve8(JSON.parse(body) || {});
8104
- } catch (e) {
8105
- reject(e);
8106
- }
8107
- });
8108
- });
8109
- }
8110
8292
  function renderNote(text = "") {
8111
8293
  let clickCount = 0;
8112
8294
  const html = sharedMd.render(
@@ -8123,1283 +8305,941 @@ function withRenderedNote(data) {
8123
8305
  noteHTML: renderNote(data?.note)
8124
8306
  };
8125
8307
  }
8126
- function createSlidesLoader(options, pluginOptions, serverOptions) {
8308
+ function createSlidesLoader(options, serverOptions) {
8127
8309
  const hmrPages = /* @__PURE__ */ new Set();
8128
8310
  let server;
8129
- let _layouts_cache_time = 0;
8130
- let _layouts_cache = {};
8131
8311
  let skipHmr = null;
8132
8312
  const { data, clientRoot, roots, mode, utils } = options;
8133
- const templateCtx = {
8134
- md: sharedMd,
8135
- async getLayouts() {
8136
- const now = Date.now();
8137
- if (now - _layouts_cache_time < 2e3)
8138
- return _layouts_cache;
8139
- const layouts = {};
8140
- for (const root of [clientRoot, ...roots]) {
8141
- const layoutPaths = await fg3("layouts/**/*.{vue,ts}", {
8142
- cwd: root,
8143
- absolute: true,
8144
- suppressErrors: true
8145
- });
8146
- for (const layoutPath of layoutPaths) {
8147
- const layoutName = path.basename(layoutPath).replace(/\.\w+$/, "");
8148
- layouts[layoutName] = layoutPath;
8149
- }
8150
- }
8151
- _layouts_cache_time = now;
8152
- _layouts_cache = layouts;
8153
- return layouts;
8154
- }
8155
- };
8156
- return [
8157
- {
8158
- name: "slidev:loader",
8159
- configureServer(_server) {
8160
- server = _server;
8161
- updateServerWatcher();
8162
- server.middlewares.use(async (req, res, next) => {
8163
- const match = req.url?.match(regexId);
8164
- if (!match)
8165
- return next();
8166
- const [, no, type] = match;
8167
- const idx = Number.parseInt(no) - 1;
8168
- if (type === "json" && req.method === "GET") {
8169
- res.write(JSON.stringify(withRenderedNote(data.slides[idx])));
8170
- return res.end();
8171
- }
8172
- if (type === "json" && req.method === "POST") {
8173
- const body = await getBodyJson(req);
8174
- const slide = data.slides[idx];
8175
- if (body.content && body.content !== slide.source.content)
8176
- hmrPages.add(idx);
8177
- if (body.content)
8178
- slide.content = slide.source.content = body.content;
8179
- if (body.note)
8180
- slide.note = slide.source.note = body.note;
8181
- if (body.frontmatter)
8182
- updateFrontmatterPatch(slide, body.frontmatter);
8183
- parser2.prettifySlide(slide.source);
8184
- const fileContent = await parser2.save(data.markdownFiles[slide.source.filepath]);
8185
- if (body.skipHmr) {
8186
- skipHmr = {
8187
- filePath: slide.source.filepath,
8188
- fileContent
8189
- };
8313
+ function getSourceId(index, type) {
8314
+ return `${data.slides[index].source.filepath}__slidev_${index + 1}.${type}`;
8315
+ }
8316
+ function updateServerWatcher() {
8317
+ if (!server)
8318
+ return;
8319
+ server.watcher.add(data.watchFiles);
8320
+ }
8321
+ function getFrontmatter(pageNo) {
8322
+ return {
8323
+ ...data.headmatter?.defaults || {},
8324
+ ...data.slides[pageNo]?.frontmatter || {}
8325
+ };
8326
+ }
8327
+ return {
8328
+ name: "slidev:loader",
8329
+ configureServer(_server) {
8330
+ server = _server;
8331
+ updateServerWatcher();
8332
+ server.middlewares.use(async (req, res, next) => {
8333
+ const match = req.url?.match(regexSlideReqPath);
8334
+ if (!match)
8335
+ return next();
8336
+ const [, no] = match;
8337
+ const idx = Number.parseInt(no) - 1;
8338
+ if (req.method === "GET") {
8339
+ res.write(JSON.stringify(withRenderedNote(data.slides[idx])));
8340
+ return res.end();
8341
+ } else if (req.method === "POST") {
8342
+ const body = await getBodyJson(req);
8343
+ const slide = data.slides[idx];
8344
+ if (body.content && body.content !== slide.source.content)
8345
+ hmrPages.add(idx);
8346
+ if (body.content)
8347
+ slide.content = slide.source.content = body.content;
8348
+ if (body.note)
8349
+ slide.note = slide.source.note = body.note;
8350
+ if (body.frontmatter)
8351
+ updateFrontmatterPatch(slide, body.frontmatter);
8352
+ parser2.prettifySlide(slide.source);
8353
+ const fileContent = await parser2.save(data.markdownFiles[slide.source.filepath]);
8354
+ if (body.skipHmr) {
8355
+ skipHmr = {
8356
+ filePath: slide.source.filepath,
8357
+ fileContent
8358
+ };
8359
+ server?.moduleGraph.invalidateModule(
8360
+ server.moduleGraph.getModuleById(getSourceId(idx, "md"))
8361
+ );
8362
+ if (body.frontmatter) {
8190
8363
  server?.moduleGraph.invalidateModule(
8191
- server.moduleGraph.getModuleById(`${VIRTUAL_SLIDE_PREFIX}${no}.md`)
8364
+ server.moduleGraph.getModuleById(getSourceId(idx, "frontmatter"))
8192
8365
  );
8193
- if (body.frontmatter) {
8194
- server?.moduleGraph.invalidateModule(
8195
- server.moduleGraph.getModuleById(`${VIRTUAL_SLIDE_PREFIX}${no}.frontmatter`)
8196
- );
8197
- }
8198
8366
  }
8199
- res.statusCode = 200;
8200
- res.write(JSON.stringify(withRenderedNote(slide)));
8201
- return res.end();
8202
8367
  }
8203
- next();
8204
- });
8205
- },
8206
- async handleHotUpdate(ctx) {
8207
- if (!data.watchFiles.includes(ctx.file))
8208
- return;
8209
- await ctx.read();
8210
- const newData = await serverOptions.loadData?.();
8211
- if (!newData)
8212
- return [];
8213
- if (skipHmr && newData.markdownFiles[skipHmr.filePath]?.raw === skipHmr.fileContent) {
8214
- skipHmr = null;
8215
- return [];
8368
+ res.statusCode = 200;
8369
+ res.write(JSON.stringify(withRenderedNote(slide)));
8370
+ return res.end();
8216
8371
  }
8217
- const moduleIds = /* @__PURE__ */ new Set();
8218
- if (data.slides.length !== newData.slides.length) {
8219
- moduleIds.add(templateSlides.id);
8220
- range(newData.slides.length).map((i) => hmrPages.add(i));
8221
- }
8222
- if (!equal(data.headmatter.defaults, newData.headmatter.defaults)) {
8223
- moduleIds.add(templateSlides.id);
8224
- range(data.slides.length).map((i) => hmrPages.add(i));
8225
- }
8226
- if (!equal(data.config, newData.config))
8227
- moduleIds.add(templateConfigs.id);
8228
- if (!equal(data.features, newData.features)) {
8229
- setTimeout(() => {
8230
- ctx.server.hot.send({ type: "full-reload" });
8231
- }, 1);
8232
- }
8233
- const length = Math.min(data.slides.length, newData.slides.length);
8234
- for (let i = 0; i < length; i++) {
8235
- const a = data.slides[i];
8236
- const b = newData.slides[i];
8237
- if (!hmrPages.has(i) && a.content.trim() === b.content.trim() && a.title?.trim() === b.title?.trim() && equal(a.frontmatter, b.frontmatter)) {
8238
- if (a.note !== b.note) {
8239
- ctx.server.hot.send(
8240
- "slidev:update-note",
8241
- {
8242
- no: i + 1,
8243
- note: b.note || "",
8244
- noteHTML: renderNote(b.note || "")
8245
- }
8246
- );
8247
- }
8248
- continue;
8372
+ next();
8373
+ });
8374
+ },
8375
+ async handleHotUpdate(ctx) {
8376
+ if (!data.watchFiles.includes(ctx.file))
8377
+ return;
8378
+ await ctx.read();
8379
+ const newData = await serverOptions.loadData?.();
8380
+ if (!newData)
8381
+ return [];
8382
+ if (skipHmr && newData.markdownFiles[skipHmr.filePath]?.raw === skipHmr.fileContent) {
8383
+ skipHmr = null;
8384
+ return [];
8385
+ }
8386
+ const moduleIds = /* @__PURE__ */ new Set();
8387
+ if (data.slides.length !== newData.slides.length) {
8388
+ moduleIds.add(templateSlides.id);
8389
+ range(newData.slides.length).map((i) => hmrPages.add(i));
8390
+ }
8391
+ if (!equal(data.headmatter.defaults, newData.headmatter.defaults)) {
8392
+ moduleIds.add(templateSlides.id);
8393
+ range(data.slides.length).map((i) => hmrPages.add(i));
8394
+ }
8395
+ if (!equal(data.config, newData.config))
8396
+ moduleIds.add(templateConfigs.id);
8397
+ if (!equal(data.features, newData.features)) {
8398
+ setTimeout(() => {
8399
+ ctx.server.hot.send({ type: "full-reload" });
8400
+ }, 1);
8401
+ }
8402
+ const length = Math.min(data.slides.length, newData.slides.length);
8403
+ for (let i = 0; i < length; i++) {
8404
+ const a = data.slides[i];
8405
+ const b = newData.slides[i];
8406
+ if (!hmrPages.has(i) && a.content.trim() === b.content.trim() && a.title?.trim() === b.title?.trim() && equal(a.frontmatter, b.frontmatter)) {
8407
+ if (a.note !== b.note) {
8408
+ ctx.server.hot.send(
8409
+ "slidev:update-note",
8410
+ {
8411
+ no: i + 1,
8412
+ note: b.note || "",
8413
+ noteHTML: renderNote(b.note || "")
8414
+ }
8415
+ );
8249
8416
  }
8250
- ctx.server.hot.send(
8251
- "slidev:update-slide",
8252
- {
8253
- no: i + 1,
8254
- data: withRenderedNote(newData.slides[i])
8255
- }
8256
- );
8257
- hmrPages.add(i);
8258
- }
8259
- Object.assign(data, newData);
8260
- Object.assign(utils, createDataUtils(newData));
8261
- if (hmrPages.size > 0)
8262
- moduleIds.add(templateTitleRendererMd.id);
8263
- const vueModules = Array.from(hmrPages).flatMap((i) => {
8264
- const id = `${VIRTUAL_SLIDE_PREFIX}${i + 1}`;
8265
- const frontmatter = ctx.server.moduleGraph.getModuleById(`${id}.frontmatter`);
8266
- const main = ctx.server.moduleGraph.getModuleById(`${id}.md`);
8267
- const styles = main ? [...main.clientImportedModules].find((m) => m.id?.startsWith(`${id}.md?vue&type=style`)) : void 0;
8268
- return [
8269
- frontmatter,
8270
- main,
8271
- styles
8272
- ];
8273
- });
8274
- hmrPages.clear();
8275
- const moduleEntries = [
8276
- ...ctx.modules.filter((i) => i.id === templateMonacoRunDeps.id || i.id === templateMonacoTypes.id),
8277
- ...vueModules,
8278
- ...Array.from(moduleIds).map((id) => ctx.server.moduleGraph.getModuleById(id))
8279
- ].filter(notNullish).filter((i) => !i.id?.startsWith("/@id/@vite-icons"));
8280
- updateServerWatcher();
8281
- return moduleEntries;
8282
- },
8283
- resolveId(id) {
8284
- if (id.startsWith("/@slidev/"))
8417
+ continue;
8418
+ }
8419
+ ctx.server.hot.send(
8420
+ "slidev:update-slide",
8421
+ {
8422
+ no: i + 1,
8423
+ data: withRenderedNote(newData.slides[i])
8424
+ }
8425
+ );
8426
+ hmrPages.add(i);
8427
+ }
8428
+ Object.assign(data, newData);
8429
+ Object.assign(utils, createDataUtils(newData, clientRoot, roots));
8430
+ if (hmrPages.size > 0)
8431
+ moduleIds.add(templateTitleRendererMd.id);
8432
+ const vueModules = Array.from(hmrPages).flatMap((idx) => {
8433
+ const frontmatter = ctx.server.moduleGraph.getModuleById(getSourceId(idx, "frontmatter"));
8434
+ const main = ctx.server.moduleGraph.getModuleById(getSourceId(idx, "md"));
8435
+ const styles = main ? [...main.clientImportedModules].find((m) => m.id?.includes(`&type=style`)) : void 0;
8436
+ return [
8437
+ frontmatter,
8438
+ main,
8439
+ styles
8440
+ ];
8441
+ });
8442
+ hmrPages.clear();
8443
+ const moduleEntries = [
8444
+ ...ctx.modules.filter((i) => i.id === templateMonacoRunDeps.id || i.id === templateMonacoTypes.id),
8445
+ ...vueModules,
8446
+ ...Array.from(moduleIds).map((id) => ctx.server.moduleGraph.getModuleById(id))
8447
+ ].filter(notNullish).filter((i) => !i.id?.startsWith("/@id/@vite-icons"));
8448
+ updateServerWatcher();
8449
+ return moduleEntries;
8450
+ },
8451
+ resolveId: {
8452
+ order: "pre",
8453
+ handler(id) {
8454
+ if (id.startsWith("/@slidev/") || id.includes("__slidev_"))
8285
8455
  return id;
8286
8456
  return null;
8287
- },
8288
- async load(id) {
8289
- const template = templates.find((i) => i.id === id);
8290
- if (template) {
8457
+ }
8458
+ },
8459
+ async load(id) {
8460
+ const template = templates.find((i) => i.id === id);
8461
+ if (template) {
8462
+ return {
8463
+ code: await template.getContent.call(this, options),
8464
+ map: { mappings: "" }
8465
+ };
8466
+ }
8467
+ const matchFacade = id.match(regexSlideFacadeId);
8468
+ if (matchFacade) {
8469
+ const [, no, type] = matchFacade;
8470
+ const idx = +no - 1;
8471
+ const sourceId = JSON.stringify(getSourceId(idx, type));
8472
+ return [
8473
+ `export * from ${sourceId}`,
8474
+ `export { default } from ${sourceId}`
8475
+ ].join("\n");
8476
+ }
8477
+ const matchSource = id.match(regexSlideSourceId);
8478
+ if (matchSource) {
8479
+ const [, no, type] = matchSource;
8480
+ const idx = +no - 1;
8481
+ const slide = data.slides[idx];
8482
+ if (!slide)
8483
+ return;
8484
+ if (type === "md") {
8291
8485
  return {
8292
- code: await template.getContent(options, templateCtx, this),
8486
+ code: slide.content,
8293
8487
  map: { mappings: "" }
8294
8488
  };
8295
- }
8296
- if (id.startsWith(VIRTUAL_SLIDE_PREFIX)) {
8297
- const remaning = id.slice(VIRTUAL_SLIDE_PREFIX.length);
8298
- const match = remaning.match(regexIdQuery);
8299
- if (match) {
8300
- const [, no, type] = match;
8301
- const pageNo = Number.parseInt(no) - 1;
8302
- const slide = data.slides[pageNo];
8303
- if (!slide)
8304
- return;
8305
- if (type === "md") {
8306
- return {
8307
- code: slide?.content,
8308
- map: { mappings: "" }
8309
- };
8310
- } else if (type === "frontmatter") {
8311
- const slideBase = {
8312
- ...withRenderedNote(slide),
8313
- frontmatter: void 0,
8314
- source: void 0,
8315
- importChain: void 0,
8316
- // remove raw content in build, optimize the bundle size
8317
- ...mode === "build" ? { raw: "", content: "", note: "" } : {}
8318
- };
8319
- const fontmatter = getFrontmatter(pageNo);
8320
- return {
8321
- code: [
8322
- "// @unocss-include",
8323
- 'import { computed, reactive, shallowReactive } from "vue"',
8324
- `export const frontmatterData = ${JSON.stringify(fontmatter)}`,
8325
- // handle HMR, update frontmatter with update
8326
- "if (import.meta.hot) {",
8327
- " const firstLoad = !import.meta.hot.data.frontmatter",
8328
- " import.meta.hot.data.frontmatter ??= reactive(frontmatterData)",
8329
- " import.meta.hot.accept(({ frontmatterData: update }) => {",
8330
- " if (firstLoad) return",
8331
- " const frontmatter = import.meta.hot.data.frontmatter",
8332
- " Object.keys(frontmatter).forEach(key => {",
8333
- " if (!(key in update)) delete frontmatter[key]",
8334
- " })",
8335
- " Object.assign(frontmatter, update)",
8336
- " })",
8337
- "}",
8338
- "export const frontmatter = import.meta.hot ? import.meta.hot.data.frontmatter : reactive(frontmatterData)",
8339
- "export default frontmatter",
8340
- "export const meta = shallowReactive({",
8341
- " get layout(){ return frontmatter.layout },",
8342
- " get transition(){ return frontmatter.transition },",
8343
- " get class(){ return frontmatter.class },",
8344
- " get clicks(){ return frontmatter.clicks },",
8345
- " get name(){ return frontmatter.name },",
8346
- " get preload(){ return frontmatter.preload },",
8347
- // No need to be reactive, as it's only used once after reload
8348
- " slide: {",
8349
- ` ...(${JSON.stringify(slideBase)}),`,
8350
- ` frontmatter,`,
8351
- ` filepath: ${JSON.stringify(mode === "dev" ? slide.source.filepath : "")},`,
8352
- ` start: ${JSON.stringify(slide.source.start)},`,
8353
- ` id: ${pageNo},`,
8354
- ` no: ${no},`,
8355
- " },",
8356
- " __clicksContext: null,",
8357
- " __preloaded: false,",
8358
- "})"
8359
- ].join("\n"),
8360
- map: { mappings: "" }
8361
- };
8362
- }
8363
- }
8489
+ } else if (type === "frontmatter") {
8490
+ const slideBase = {
8491
+ ...withRenderedNote(slide),
8492
+ frontmatter: void 0,
8493
+ source: void 0,
8494
+ importChain: void 0,
8495
+ // remove raw content in build, optimize the bundle size
8496
+ ...mode === "build" ? { raw: "", content: "", note: "" } : {}
8497
+ };
8498
+ const fontmatter = getFrontmatter(idx);
8364
8499
  return {
8365
- code: "",
8500
+ code: [
8501
+ "// @unocss-include",
8502
+ 'import { computed, reactive, shallowReactive } from "vue"',
8503
+ `export const frontmatterData = ${JSON.stringify(fontmatter)}`,
8504
+ // handle HMR, update frontmatter with update
8505
+ "if (import.meta.hot) {",
8506
+ " const firstLoad = !import.meta.hot.data.frontmatter",
8507
+ " import.meta.hot.data.frontmatter ??= reactive(frontmatterData)",
8508
+ " import.meta.hot.accept(({ frontmatterData: update }) => {",
8509
+ " if (firstLoad) return",
8510
+ " const frontmatter = import.meta.hot.data.frontmatter",
8511
+ " Object.keys(frontmatter).forEach(key => {",
8512
+ " if (!(key in update)) delete frontmatter[key]",
8513
+ " })",
8514
+ " Object.assign(frontmatter, update)",
8515
+ " })",
8516
+ "}",
8517
+ "export const frontmatter = import.meta.hot ? import.meta.hot.data.frontmatter : reactive(frontmatterData)",
8518
+ "export default frontmatter",
8519
+ "export const meta = shallowReactive({",
8520
+ " get layout(){ return frontmatter.layout },",
8521
+ " get transition(){ return frontmatter.transition },",
8522
+ " get class(){ return frontmatter.class },",
8523
+ " get clicks(){ return frontmatter.clicks },",
8524
+ " get name(){ return frontmatter.name },",
8525
+ " get preload(){ return frontmatter.preload },",
8526
+ // No need to be reactive, as it's only used once after reload
8527
+ " slide: {",
8528
+ ` ...(${JSON.stringify(slideBase)}),`,
8529
+ ` frontmatter,`,
8530
+ ` filepath: ${JSON.stringify(mode === "dev" ? slide.source.filepath : "")},`,
8531
+ ` start: ${JSON.stringify(slide.source.start)},`,
8532
+ ` id: ${idx},`,
8533
+ ` no: ${no},`,
8534
+ " },",
8535
+ " __clicksContext: null,",
8536
+ " __preloaded: false,",
8537
+ "})"
8538
+ ].join("\n"),
8366
8539
  map: { mappings: "" }
8367
8540
  };
8368
8541
  }
8369
8542
  }
8370
- },
8371
- {
8372
- name: "slidev:layout-transform:pre",
8373
- enforce: "pre",
8374
- async transform(code, id) {
8375
- if (!id.startsWith(VIRTUAL_SLIDE_PREFIX))
8376
- return;
8377
- const remaning = id.slice(VIRTUAL_SLIDE_PREFIX.length);
8378
- const match = remaning.match(regexIdQuery);
8379
- if (!match)
8380
- return;
8381
- const [, no, type] = match;
8382
- if (type !== "md")
8383
- return;
8384
- return transformMarkdown(code, +no - 1);
8385
- }
8386
- },
8387
- {
8388
- name: "slidev:context-transform:pre",
8389
- enforce: "pre",
8390
- async transform(code, id) {
8391
- if (!id.endsWith(".vue") || id.includes("/@slidev/client/") || id.includes("/packages/client/"))
8392
- return;
8393
- return transformVue(code);
8394
- }
8395
- },
8396
- {
8397
- name: "slidev:slide-transform:post",
8398
- enforce: "post",
8399
- transform(code, id) {
8400
- if (!id.match(/\/@slidev\/slides\/\d+\.md($|\?)/))
8401
- return;
8402
- const replaced = code.replace("if (_rerender_only)", "if (false)");
8403
- if (replaced !== code)
8404
- return replaced;
8405
- }
8406
- }
8407
- ];
8408
- function updateServerWatcher() {
8409
- if (!server)
8410
- return;
8411
- server.watcher.add(data.watchFiles);
8412
- }
8413
- function getFrontmatter(pageNo) {
8414
- return {
8415
- ...data.headmatter?.defaults || {},
8416
- ...data.slides[pageNo]?.frontmatter || {}
8417
- };
8418
- }
8419
- async function transformMarkdown(code, index) {
8420
- const layouts = await templateCtx.getLayouts();
8421
- const frontmatter = getFrontmatter(index);
8422
- let layoutName = frontmatter?.layout || (index === 0 ? "cover" : "default");
8423
- if (!layouts[layoutName]) {
8424
- console.error(red(`
8425
- Unknown layout "${bold(layoutName)}".${yellow(" Available layouts are:")}`) + Object.keys(layouts).map((i, idx) => (idx % 3 === 0 ? "\n " : "") + gray(i.padEnd(15, " "))).join(" "));
8426
- console.error();
8427
- layoutName = "default";
8428
- }
8429
- delete frontmatter.title;
8430
- const imports = [
8431
- `import InjectedLayout from "${toAtFS(layouts[layoutName])}"`,
8432
- templateImportContextUtils,
8433
- templateInitContext,
8434
- templateInjectionMarker
8435
- ];
8436
- code = code.replace(/(<script setup.*>)/g, `$1
8437
- ${imports.join("\n")}
8438
- `);
8439
- const injectA = code.indexOf("<template>") + "<template>".length;
8440
- const injectB = code.lastIndexOf("</template>");
8441
- let body = code.slice(injectA, injectB).trim();
8442
- if (body.startsWith("<div>") && body.endsWith("</div>"))
8443
- body = body.slice(5, -6);
8444
- code = `${code.slice(0, injectA)}
8445
- <InjectedLayout v-bind="_frontmatterToProps($frontmatter,${index})">
8446
- ${body}
8447
- </InjectedLayout>
8448
- ${code.slice(injectB)}`;
8449
- return code;
8450
- }
8451
- function transformVue(code) {
8452
- if (code.includes(templateInjectionMarker) || code.includes("useSlideContext()"))
8453
- return code;
8454
- const imports = [
8455
- templateImportContextUtils,
8456
- templateInitContext,
8457
- templateInjectionMarker
8458
- ];
8459
- const matchScript = code.match(/<script((?!setup).)*(setup)?.*>/);
8460
- if (matchScript && matchScript[2]) {
8461
- return code.replace(/(<script.*>)/g, `$1
8462
- ${imports.join("\n")}
8463
- `);
8464
- } else if (matchScript && !matchScript[2]) {
8465
- const matchExport = code.match(/export\s+default\s+\{/);
8466
- if (matchExport) {
8467
- const exportIndex = (matchExport.index || 0) + matchExport[0].length;
8468
- let component = code.slice(exportIndex);
8469
- component = component.slice(0, component.indexOf("</script>"));
8470
- const scriptIndex = (matchScript.index || 0) + matchScript[0].length;
8471
- const provideImport = '\nimport { injectionSlidevContext } from "@slidev/client/constants.ts"\n';
8472
- code = `${code.slice(0, scriptIndex)}${provideImport}${code.slice(scriptIndex)}`;
8473
- let injectIndex = exportIndex + provideImport.length;
8474
- let injectObject = "$slidev: { from: injectionSlidevContext },";
8475
- const matchInject = component.match(/.*inject\s*:\s*([[{])/);
8476
- if (matchInject) {
8477
- injectIndex += (matchInject.index || 0) + matchInject[0].length;
8478
- if (matchInject[1] === "[") {
8479
- let injects = component.slice((matchInject.index || 0) + matchInject[0].length);
8480
- const injectEndIndex = injects.indexOf("]");
8481
- injects = injects.slice(0, injectEndIndex);
8482
- injectObject += injects.split(",").map((inject) => `${inject}: {from: ${inject}}`).join(",");
8483
- return `${code.slice(0, injectIndex - 1)}{
8484
- ${injectObject}
8485
- }${code.slice(injectIndex + injectEndIndex + 1)}`;
8486
- } else {
8487
- return `${code.slice(0, injectIndex)}
8488
- ${injectObject}
8489
- ${code.slice(injectIndex)}`;
8490
- }
8491
- }
8492
- return `${code.slice(0, injectIndex)}
8493
- inject: { ${injectObject} },
8494
- ${code.slice(injectIndex)}`;
8495
- }
8496
8543
  }
8497
- return `<script setup>
8498
- ${imports.join("\n")}
8499
- </script>
8500
- ${code}`;
8501
- }
8502
- }
8503
-
8504
- // node/vite/unocss.ts
8505
- import { resolve as resolve6 } from "node:path";
8506
- import { existsSync as existsSync5 } from "node:fs";
8507
- import { fileURLToPath as fileURLToPath3 } from "node:url";
8508
- import { uniq as uniq5 } from "@antfu/utils";
8509
- import { mergeConfigs } from "unocss";
8510
- import jiti2 from "jiti";
8511
- import UnoCSS from "unocss/vite";
8512
- async function createUnocssPlugin({ themeRoots, addonRoots, clientRoot, roots, data, userRoot }, { unocss: unoOptions = {} }) {
8513
- const configFiles = uniq5([
8514
- resolve6(userRoot, "uno.config.ts"),
8515
- resolve6(userRoot, "unocss.config.ts"),
8516
- ...themeRoots.map((i) => `${i}/uno.config.ts`),
8517
- ...themeRoots.map((i) => `${i}/unocss.config.ts`),
8518
- ...addonRoots.map((i) => `${i}/uno.config.ts`),
8519
- ...addonRoots.map((i) => `${i}/unocss.config.ts`),
8520
- resolve6(clientRoot, "uno.config.ts"),
8521
- resolve6(clientRoot, "unocss.config.ts")
8522
- ]).filter((i) => existsSync5(i));
8523
- const configs = configFiles.map((i) => {
8524
- const loaded = jiti2(fileURLToPath3(import.meta.url))(i);
8525
- const config2 = "default" in loaded ? loaded.default : loaded;
8526
- return config2;
8527
- }).filter(Boolean);
8528
- configs.reverse();
8529
- let config = mergeConfigs([...configs, unoOptions]);
8530
- config = await loadSetups(clientRoot, roots, "unocss.ts", {}, config, (a, b) => mergeConfigs([a, b]));
8531
- config.theme ||= {};
8532
- config.theme.fontFamily ||= {};
8533
- config.theme.fontFamily.sans ||= data.config.fonts.sans.join(",");
8534
- config.theme.fontFamily.mono ||= data.config.fonts.mono.join(",");
8535
- config.theme.fontFamily.serif ||= data.config.fonts.serif.join(",");
8536
- return UnoCSS({
8537
- configFile: false,
8538
- configDeps: configFiles,
8539
- ...config
8540
- });
8544
+ };
8541
8545
  }
8542
8546
 
8543
8547
  // node/vite/markdown.ts
8544
8548
  import Markdown from "unplugin-vue-markdown/vite";
8545
- import { isTruthy, slash as slash3 } from "@antfu/utils";
8546
-
8547
- // ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.1.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/image-size/specialCharacters.js
8548
- var SpecialCharacters;
8549
- (function(SpecialCharacters2) {
8550
- SpecialCharacters2[SpecialCharacters2["EXCLAMATION_MARK"] = 33] = "EXCLAMATION_MARK";
8551
- SpecialCharacters2[SpecialCharacters2["OPENING_BRACKET"] = 91] = "OPENING_BRACKET";
8552
- SpecialCharacters2[SpecialCharacters2["OPENING_PARENTHESIS"] = 40] = "OPENING_PARENTHESIS";
8553
- SpecialCharacters2[SpecialCharacters2["WHITESPACE"] = 32] = "WHITESPACE";
8554
- SpecialCharacters2[SpecialCharacters2["NEW_LINE"] = 10] = "NEW_LINE";
8555
- SpecialCharacters2[SpecialCharacters2["EQUALS"] = 61] = "EQUALS";
8556
- SpecialCharacters2[SpecialCharacters2["LOWER_CASE_X"] = 120] = "LOWER_CASE_X";
8557
- SpecialCharacters2[SpecialCharacters2["NUMBER_ZERO"] = 48] = "NUMBER_ZERO";
8558
- SpecialCharacters2[SpecialCharacters2["NUMBER_NINE"] = 57] = "NUMBER_NINE";
8559
- SpecialCharacters2[SpecialCharacters2["PERCENTAGE"] = 37] = "PERCENTAGE";
8560
- SpecialCharacters2[SpecialCharacters2["CLOSING_PARENTHESIS"] = 41] = "CLOSING_PARENTHESIS";
8561
- })(SpecialCharacters || (SpecialCharacters = {}));
8549
+ import MagicString from "magic-string-stack";
8562
8550
 
8563
- // ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.1.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/task-lists/index.js
8564
- import Token from "markdown-it/lib/token.mjs";
8565
- var checkboxRegex = /^ *\[([\sx])] /i;
8566
- function taskLists(md, options = { enabled: false, label: false, lineNumber: false }) {
8567
- md.core.ruler.after("inline", "task-lists", (state) => processToken(state, options));
8568
- md.renderer.rules.taskListItemCheckbox = (tokens) => {
8569
- const token = tokens[0];
8570
- const checkedAttribute = token.attrGet("checked") ? 'checked="" ' : "";
8571
- const disabledAttribute = token.attrGet("disabled") ? 'disabled="" ' : "";
8572
- const line = token.attrGet("line");
8573
- const idAttribute = `id="${token.attrGet("id")}" `;
8574
- const dataLineAttribute = line && options.lineNumber ? `data-line="${line}" ` : "";
8575
- return `<input class="task-list-item-checkbox" type="checkbox" ${checkedAttribute}${disabledAttribute}${dataLineAttribute}${idAttribute}/>`;
8576
- };
8577
- md.renderer.rules.taskListItemLabel_close = () => {
8578
- return "</label>";
8579
- };
8580
- md.renderer.rules.taskListItemLabel_open = (tokens) => {
8581
- const token = tokens[0];
8582
- const id = token.attrGet("id");
8583
- return `<label for="${id}">`;
8551
+ // node/setups/transformers.ts
8552
+ async function setupTransformers(roots) {
8553
+ const returns = await loadSetups(roots, "transformers.ts", []);
8554
+ const result = {
8555
+ pre: [],
8556
+ preCodeblock: [],
8557
+ postCodeblock: [],
8558
+ post: []
8584
8559
  };
8585
- }
8586
- function processToken(state, options) {
8587
- const allTokens = state.tokens;
8588
- for (let i = 2; i < allTokens.length; i++) {
8589
- if (!isTodoItem(allTokens, i)) {
8590
- continue;
8591
- }
8592
- todoify(allTokens[i], options);
8593
- allTokens[i - 2].attrJoin("class", `task-list-item ${options.enabled ? " enabled" : ""}`);
8594
- const parentToken = findParentToken(allTokens, i - 2);
8595
- if (parentToken) {
8596
- const classes = parentToken.attrGet("class") ?? "";
8597
- if (!classes.match(/(^| )contains-task-list/)) {
8598
- parentToken.attrJoin("class", "contains-task-list");
8599
- }
8600
- }
8560
+ for (const r of returns.toReversed()) {
8561
+ if (r.pre)
8562
+ result.pre.push(...r.pre);
8563
+ if (r.preCodeblock)
8564
+ result.preCodeblock.push(...r.preCodeblock);
8601
8565
  }
8602
- return false;
8603
- }
8604
- function findParentToken(tokens, index) {
8605
- const targetLevel = tokens[index].level - 1;
8606
- for (let currentTokenIndex = index - 1; currentTokenIndex >= 0; currentTokenIndex--) {
8607
- if (tokens[currentTokenIndex].level === targetLevel) {
8608
- return tokens[currentTokenIndex];
8609
- }
8566
+ for (const r of returns) {
8567
+ if (r.postCodeblock)
8568
+ result.postCodeblock.push(...r.postCodeblock);
8569
+ if (r.post)
8570
+ result.post.push(...r.post);
8610
8571
  }
8611
- return void 0;
8612
- }
8613
- function isTodoItem(tokens, index) {
8614
- return isInline(tokens[index]) && isParagraph(tokens[index - 1]) && isListItem(tokens[index - 2]) && startsWithTodoMarkdown(tokens[index]);
8572
+ return result;
8615
8573
  }
8616
- function todoify(token, options) {
8617
- if (token.children == null) {
8618
- return;
8619
- }
8620
- const id = generateIdForToken(token);
8621
- token.children.splice(0, 0, createCheckboxToken(token, options.enabled, id));
8622
- token.children[1].content = token.children[1].content.replace(checkboxRegex, "");
8623
- if (options.label) {
8624
- token.children.splice(1, 0, createLabelBeginToken(id));
8625
- token.children.push(createLabelEndToken());
8626
- }
8574
+
8575
+ // node/syntax/transform/code-wrapper.ts
8576
+ var reCodeBlock = /^```([\w'-]+)?\s*(?:\{([\w*,|-]+)\}\s*?(\{[^}]*\})?([^\r\n]*))?\r?\n(\S[\s\S]*?)^```$/gm;
8577
+ function transformCodeWrapper(ctx) {
8578
+ ctx.s.replace(
8579
+ reCodeBlock,
8580
+ (full, lang = "", rangeStr = "", options = "", attrs = "", code) => {
8581
+ const ranges = normalizeRangeStr(rangeStr);
8582
+ code = code.trimEnd();
8583
+ options = options.trim() || "{}";
8584
+ return `
8585
+ <CodeBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
8586
+
8587
+ \`\`\`${lang}${attrs}
8588
+ ${code}
8589
+ \`\`\`
8590
+
8591
+ </CodeBlockWrapper>`;
8592
+ }
8593
+ );
8627
8594
  }
8628
- function generateIdForToken(token) {
8629
- if (token.map) {
8630
- return `task-item-${token.map[0]}`;
8631
- } else {
8632
- return `task-item-${Math.ceil(Math.random() * (1e4 * 1e3) - 1e3)}`;
8633
- }
8595
+
8596
+ // node/syntax/transform/in-page-css.ts
8597
+ function transformPageCSS(ctx) {
8598
+ const codeBlocks = getCodeBlocks(ctx.s.original);
8599
+ ctx.s.replace(
8600
+ /(\n<style[^>]*>)([\s\S]+?)(<\/style>)/g,
8601
+ (full, start, css, end, index) => {
8602
+ if (codeBlocks.isInsideCodeblocks(index))
8603
+ return full;
8604
+ if (!start.includes("scoped"))
8605
+ start = start.replace("<style", "<style scoped");
8606
+ return `${start}
8607
+ ${css}${end}`;
8608
+ }
8609
+ );
8634
8610
  }
8635
- function createCheckboxToken(token, enabled, id) {
8636
- const checkbox = new Token("taskListItemCheckbox", "", 0);
8637
- if (!enabled) {
8638
- checkbox.attrSet("disabled", "true");
8639
- }
8640
- if (token.map) {
8641
- checkbox.attrSet("line", token.map[0].toString());
8642
- }
8643
- checkbox.attrSet("id", id);
8644
- const checkboxRegexResult = checkboxRegex.exec(token.content);
8645
- const isChecked = checkboxRegexResult?.[1].toLowerCase() === "x";
8646
- if (isChecked) {
8647
- checkbox.attrSet("checked", "true");
8648
- }
8649
- return checkbox;
8611
+
8612
+ // node/syntax/transform/katex-wrapper.ts
8613
+ function transformKaTexWrapper(ctx) {
8614
+ ctx.s.replace(
8615
+ /^\$\$(?:\s*\{([\w*,|-]+)\}\s*?(?:(\{[^}]*\})\s*?)?)?\n(\S[\s\S]*?)^\$\$/gm,
8616
+ (full, rangeStr = "", options = "", code) => {
8617
+ const ranges = !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
8618
+ code = code.trimEnd();
8619
+ options = options.trim() || "{}";
8620
+ return `<KaTexBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
8621
+
8622
+ $$
8623
+ ${code}
8624
+ $$
8625
+ </KaTexBlockWrapper>
8626
+ `;
8627
+ }
8628
+ );
8650
8629
  }
8651
- function createLabelBeginToken(id) {
8652
- const labelBeginToken = new Token("taskListItemLabel_open", "", 1);
8653
- labelBeginToken.attrSet("id", id);
8654
- return labelBeginToken;
8630
+
8631
+ // node/syntax/transform/magic-move.ts
8632
+ import { codeToKeyedTokens } from "shiki-magic-move/core";
8633
+ import lz from "lz-string";
8634
+ var reMagicMoveBlock = /^````(?:md|markdown) magic-move *(\{[^}]*\})?([^ \n]*)\n([\s\S]+?)^````$/gm;
8635
+ function parseLineNumbersOption(options) {
8636
+ return /lines: *true/.test(options) ? true : /lines: *false/.test(options) ? false : void 0;
8655
8637
  }
8656
- function createLabelEndToken() {
8657
- return new Token("taskListItemLabel_close", "", -1);
8638
+ function transformMagicMove(ctx) {
8639
+ ctx.s.replace(
8640
+ reMagicMoveBlock,
8641
+ (full, options = "{}", _attrs = "", body) => {
8642
+ const matches = Array.from(body.matchAll(reCodeBlock));
8643
+ if (!matches.length)
8644
+ throw new Error("Magic Move block must contain at least one code block");
8645
+ const defaultLineNumbers = parseLineNumbersOption(options) ?? ctx.options.data.config.lineNumbers;
8646
+ const ranges = matches.map((i) => normalizeRangeStr(i[2]));
8647
+ const steps = matches.map((i) => {
8648
+ const lineNumbers = parseLineNumbersOption(i[3]) ?? defaultLineNumbers;
8649
+ return codeToKeyedTokens(ctx.options.utils.shiki, i[5].trimEnd(), {
8650
+ ...ctx.options.utils.shikiOptions,
8651
+ lang: i[1]
8652
+ }, lineNumbers);
8653
+ });
8654
+ const compressed = lz.compressToBase64(JSON.stringify(steps));
8655
+ return `<ShikiMagicMove v-bind="${options}" steps-lz="${compressed}" :step-ranges='${JSON.stringify(ranges)}' />`;
8656
+ }
8657
+ );
8658
8658
  }
8659
- function isInline(token) {
8660
- return token.type === "inline";
8659
+
8660
+ // node/syntax/transform/mermaid.ts
8661
+ import lz2 from "lz-string";
8662
+ function transformMermaid(ctx) {
8663
+ ctx.s.replace(
8664
+ /^```mermaid *(\{[^\n]*\})?\n([\s\S]+?)\n```/gm,
8665
+ (full, options = "", code = "") => {
8666
+ code = code.trim();
8667
+ options = options.trim() || "{}";
8668
+ const encoded = lz2.compressToBase64(code);
8669
+ return `<Mermaid code-lz="${encoded}" v-bind="${options}" />`;
8670
+ }
8671
+ );
8661
8672
  }
8662
- function isParagraph(token) {
8663
- return token.type === "paragraph_open";
8673
+
8674
+ // node/syntax/transform/monaco.ts
8675
+ import lz3 from "lz-string";
8676
+ function transformMonaco(ctx) {
8677
+ const enabled = ctx.options.data.config.monaco === true || ctx.options.data.config.monaco === ctx.options.mode;
8678
+ if (!enabled) {
8679
+ ctx.s.replace(/\{monaco([\w:,-]*)\}/g, "");
8680
+ return;
8681
+ }
8682
+ ctx.s.replace(
8683
+ /^```(\w+) *\{monaco-diff\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^~~~ *\n([\s\S]+?)^```/gm,
8684
+ (full, lang = "ts", options = "{}", code, diff) => {
8685
+ lang = lang.trim();
8686
+ options = options.trim() || "{}";
8687
+ const encoded = lz3.compressToBase64(code);
8688
+ const encodedDiff = lz3.compressToBase64(diff);
8689
+ return `<Monaco code-lz="${encoded}" diff-lz="${encodedDiff}" lang="${lang}" v-bind="${options}" />`;
8690
+ }
8691
+ );
8692
+ ctx.s.replace(
8693
+ /^```(\w+) *\{monaco\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm,
8694
+ (full, lang = "ts", options = "{}", code) => {
8695
+ lang = lang.trim();
8696
+ options = options.trim() || "{}";
8697
+ const encoded = lz3.compressToBase64(code);
8698
+ return `<Monaco code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
8699
+ }
8700
+ );
8701
+ ctx.s.replace(
8702
+ /^```(\w+) *\{monaco-run\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm,
8703
+ (full, lang = "ts", options = "{}", code) => {
8704
+ lang = lang.trim();
8705
+ options = options.trim() || "{}";
8706
+ const encoded = lz3.compressToBase64(code);
8707
+ return `<Monaco runnable code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
8708
+ }
8709
+ );
8664
8710
  }
8665
- function isListItem(token) {
8666
- return token.type === "list_item_open";
8711
+
8712
+ // node/syntax/transform/plant-uml.ts
8713
+ import { encode as encodePlantUml } from "plantuml-encoder";
8714
+ function transformPlantUml(ctx) {
8715
+ const server = ctx.options.data.config.plantUmlServer;
8716
+ ctx.s.replace(
8717
+ /^```plantuml[^\n{}]*(\{[^}\n]*\})?\n([\s\S]+?)\n```/gm,
8718
+ (full, options = "", content = "") => {
8719
+ const code = encodePlantUml(content.trim());
8720
+ options = options.trim() || "{}";
8721
+ return `<PlantUml :code="'${code}'" :server="'${server}'" v-bind="${options}" />`;
8722
+ }
8723
+ );
8667
8724
  }
8668
- function startsWithTodoMarkdown(token) {
8669
- return checkboxRegex.test(token.content);
8725
+
8726
+ // node/syntax/transform/slot-sugar.ts
8727
+ function transformSlotSugar(ctx) {
8728
+ const linesWithNewline = ctx.s.original.split(/(\r?\n)/g);
8729
+ const codeBlocks = getCodeBlocks(ctx.s.original);
8730
+ const lines = [];
8731
+ for (let i = 0; i < linesWithNewline.length; i += 2) {
8732
+ const line = linesWithNewline[i];
8733
+ const newline = linesWithNewline[i + 1] || "";
8734
+ lines.push(line + newline);
8735
+ }
8736
+ let prevSlot = false;
8737
+ let offset = 0;
8738
+ lines.forEach((line) => {
8739
+ const start = offset;
8740
+ offset += line.length;
8741
+ if (codeBlocks.isInsideCodeblocks(offset))
8742
+ return;
8743
+ const match = line.match(/^::\s*([\w.\-:]+)\s*::(\s*)$/);
8744
+ if (match) {
8745
+ ctx.s.overwrite(start, offset - match[2].length, `${prevSlot ? "\n\n</template>\n" : "\n"}<template v-slot:${match[1]}="slotProps">
8746
+ `);
8747
+ prevSlot = true;
8748
+ }
8749
+ });
8750
+ if (prevSlot)
8751
+ ctx.s.append("\n\n</template>");
8670
8752
  }
8671
8753
 
8672
- // node/vite/markdown.ts
8673
- import MarkdownItMdc from "markdown-it-mdc";
8674
- import MagicString from "magic-string-stack";
8675
- import MarkdownItFootnote from "markdown-it-footnote";
8754
+ // node/syntax/transform/snippet.ts
8755
+ import path3 from "node:path";
8756
+ import lz4 from "lz-string";
8757
+ import fs6 from "fs-extra";
8758
+ import { slash as slash2 } from "@antfu/utils";
8676
8759
 
8677
- // node/syntax/markdown-it/markdown-it-katex.ts
8678
- import katex from "katex";
8679
- function isValidDelim(state, pos) {
8680
- const max = state.posMax;
8681
- let can_open = true;
8682
- let can_close = true;
8683
- const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
8684
- const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
8685
- if (prevChar === 32 || prevChar === 9 || /* \t */
8686
- nextChar >= 48 && nextChar <= 57)
8687
- can_close = false;
8688
- if (nextChar === 32 || nextChar === 9)
8689
- can_open = false;
8760
+ // node/vite/monacoWrite.ts
8761
+ import fs5 from "node:fs/promises";
8762
+ import path2 from "node:path";
8763
+ var monacoWriterWhitelist = /* @__PURE__ */ new Set();
8764
+ function createMonacoWriterPlugin({ userRoot }) {
8690
8765
  return {
8691
- can_open,
8692
- can_close
8766
+ name: "slidev:monaco-write",
8767
+ apply: "serve",
8768
+ configureServer(server) {
8769
+ server.ws.on("connection", (socket) => {
8770
+ socket.on("message", async (data) => {
8771
+ let json;
8772
+ try {
8773
+ json = JSON.parse(data.toString());
8774
+ } catch {
8775
+ return;
8776
+ }
8777
+ if (json.type === "custom" && json.event === "slidev:monaco-write") {
8778
+ const { file, content } = json.data;
8779
+ if (!monacoWriterWhitelist.has(file)) {
8780
+ console.error(`[Slidev] Unauthorized file write: ${file}`);
8781
+ return;
8782
+ }
8783
+ const filepath = path2.join(userRoot, file);
8784
+ console.log("[Slidev] Writing file:", filepath);
8785
+ await fs5.writeFile(filepath, content, "utf-8");
8786
+ }
8787
+ });
8788
+ });
8789
+ }
8693
8790
  };
8694
8791
  }
8695
- function math_inline(state, silent) {
8696
- let match, token, res, pos;
8697
- if (state.src[state.pos] !== "$")
8698
- return false;
8699
- res = isValidDelim(state, state.pos);
8700
- if (!res.can_open) {
8701
- if (!silent)
8702
- state.pending += "$";
8703
- state.pos += 1;
8704
- return true;
8705
- }
8706
- const start = state.pos + 1;
8707
- match = start;
8708
- while ((match = state.src.indexOf("$", match)) !== -1) {
8709
- pos = match - 1;
8710
- while (state.src[pos] === "\\") pos -= 1;
8711
- if ((match - pos) % 2 === 1)
8712
- break;
8713
- match += 1;
8714
- }
8715
- if (match === -1) {
8716
- if (!silent)
8717
- state.pending += "$";
8718
- state.pos = start;
8719
- return true;
8720
- }
8721
- if (match - start === 0) {
8722
- if (!silent)
8723
- state.pending += "$$";
8724
- state.pos = start + 1;
8725
- return true;
8726
- }
8727
- res = isValidDelim(state, match);
8728
- if (!res.can_close) {
8729
- if (!silent)
8730
- state.pending += "$";
8731
- state.pos = start;
8732
- return true;
8733
- }
8734
- if (!silent) {
8735
- token = state.push("math_inline", "math", 0);
8736
- token.markup = "$";
8737
- token.content = state.src.slice(start, match);
8738
- }
8739
- state.pos = match + 1;
8740
- return true;
8741
- }
8742
- function math_block(state, start, end, silent) {
8743
- let firstLine;
8744
- let lastLine;
8745
- let next;
8746
- let lastPos;
8747
- let found = false;
8748
- let pos = state.bMarks[start] + state.tShift[start];
8749
- let max = state.eMarks[start];
8750
- if (pos + 2 > max)
8751
- return false;
8752
- if (state.src.slice(pos, pos + 2) !== "$$")
8753
- return false;
8754
- pos += 2;
8755
- firstLine = state.src.slice(pos, max);
8756
- if (silent)
8757
- return true;
8758
- if (firstLine.trim().slice(-2) === "$$") {
8759
- firstLine = firstLine.trim().slice(0, -2);
8760
- found = true;
8761
- }
8762
- for (next = start; !found; ) {
8763
- next++;
8764
- if (next >= end)
8765
- break;
8766
- pos = state.bMarks[next] + state.tShift[next];
8767
- max = state.eMarks[next];
8768
- if (pos < max && state.tShift[next] < state.blkIndent) {
8769
- break;
8792
+
8793
+ // node/syntax/transform/snippet.ts
8794
+ function dedent(text) {
8795
+ const lines = text.split("\n");
8796
+ const minIndentLength = lines.reduce((acc, line) => {
8797
+ for (let i = 0; i < line.length; i++) {
8798
+ if (line[i] !== " " && line[i] !== " ")
8799
+ return Math.min(i, acc);
8770
8800
  }
8771
- if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
8772
- lastPos = state.src.slice(0, max).lastIndexOf("$$");
8773
- lastLine = state.src.slice(pos, lastPos);
8774
- found = true;
8801
+ return acc;
8802
+ }, Number.POSITIVE_INFINITY);
8803
+ if (minIndentLength < Number.POSITIVE_INFINITY)
8804
+ return lines.map((x) => x.slice(minIndentLength)).join("\n");
8805
+ return text;
8806
+ }
8807
+ function testLine(line, regexp, regionName, end = false) {
8808
+ const [full, tag, name] = regexp.exec(line.trim()) || [];
8809
+ return full && tag && name === regionName && tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/);
8810
+ }
8811
+ function findRegion(lines, regionName) {
8812
+ const regionRegexps = [
8813
+ /^\/\/ ?#?((?:end)?region) ([\w*-]+)$/,
8814
+ // javascript, typescript, java
8815
+ /^\/\* ?#((?:end)?region) ([\w*-]+) ?\*\/$/,
8816
+ // css, less, scss
8817
+ /^#pragma ((?:end)?region) ([\w*-]+)$/,
8818
+ // C, C++
8819
+ /^<!-- #?((?:end)?region) ([\w*-]+) -->$/,
8820
+ // HTML, markdown
8821
+ /^#(End Region) ([\w*-]+)$/,
8822
+ // Visual Basic
8823
+ /^::#(endregion) ([\w*-]+)$/,
8824
+ // Bat
8825
+ /^# ?((?:end)?region) ([\w*-]+)$/
8826
+ // C#, PHP, Powershell, Python, perl & misc
8827
+ ];
8828
+ let regexp = null;
8829
+ let start = -1;
8830
+ for (const [lineId, line] of lines.entries()) {
8831
+ if (regexp === null) {
8832
+ for (const reg of regionRegexps) {
8833
+ if (testLine(line, reg, regionName)) {
8834
+ start = lineId + 1;
8835
+ regexp = reg;
8836
+ break;
8837
+ }
8838
+ }
8839
+ } else if (testLine(line, regexp, regionName, true)) {
8840
+ return { start, end: lineId, regexp };
8775
8841
  }
8776
8842
  }
8777
- state.line = next + 1;
8778
- const token = state.push("math_block", "math", 0);
8779
- token.block = true;
8780
- token.content = (firstLine && firstLine.trim() ? `${firstLine}
8781
- ` : "") + state.getLines(start + 1, next, state.tShift[start], true) + (lastLine && lastLine.trim() ? lastLine : "");
8782
- token.map = [start, state.line];
8783
- token.markup = "$$";
8784
- return true;
8843
+ return null;
8785
8844
  }
8786
- function math_plugin(md, options) {
8787
- options = options || {};
8788
- const katexInline = function(latex) {
8789
- options.displayMode = false;
8790
- try {
8791
- return katex.renderToString(latex, options);
8792
- } catch (error) {
8793
- if (options.throwOnError)
8794
- console.warn(error);
8795
- return latex;
8845
+ function transformSnippet({ s, slide, options }) {
8846
+ const data = options.data;
8847
+ const dir = path3.dirname(slide.source?.filepath ?? options.entry ?? options.userRoot);
8848
+ s.replace(
8849
+ // eslint-disable-next-line regexp/no-super-linear-backtracking
8850
+ /^<<<\s*(\S.*?)(#[\w-]+)?\s*(?:\s(\S+?))?\s*(\{.*)?$/gm,
8851
+ (full, filepath = "", regionName = "", lang = "", meta = "") => {
8852
+ const src = slash2(
8853
+ /^@\//.test(filepath) ? path3.resolve(options.userRoot, filepath.slice(2)) : path3.resolve(dir, filepath)
8854
+ );
8855
+ data.watchFiles.push(src);
8856
+ const isAFile = fs6.statSync(src).isFile();
8857
+ if (!fs6.existsSync(src) || !isAFile) {
8858
+ throw new Error(isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`);
8859
+ }
8860
+ let content = fs6.readFileSync(src, "utf8");
8861
+ slide.snippetsUsed ??= {};
8862
+ slide.snippetsUsed[src] = content;
8863
+ if (regionName) {
8864
+ const lines = content.split(/\r?\n/);
8865
+ const region = findRegion(lines, regionName.slice(1));
8866
+ if (region) {
8867
+ content = dedent(
8868
+ lines.slice(region.start, region.end).filter((line) => !region.regexp.test(line.trim())).join("\n")
8869
+ );
8870
+ }
8871
+ }
8872
+ meta = meta.trim();
8873
+ lang = lang.trim();
8874
+ lang = lang || path3.extname(filepath).slice(1);
8875
+ if (meta.match(/^\{monaco-write\}/)) {
8876
+ monacoWriterWhitelist.add(filepath);
8877
+ lang = lang.trim();
8878
+ meta = meta.replace(/^\{monaco-write\}/, "").trim() || "{}";
8879
+ const encoded = lz4.compressToBase64(content);
8880
+ return `<Monaco writable=${JSON.stringify(filepath)} code-lz="${encoded}" lang="${lang}" v-bind="${meta}" />`;
8881
+ }
8882
+ return `\`\`\`${lang} ${meta}
8883
+ ${content}
8884
+ \`\`\``;
8796
8885
  }
8886
+ );
8887
+ }
8888
+
8889
+ // node/syntax/transform/index.ts
8890
+ async function getMarkdownTransformers(options) {
8891
+ const extras = await setupTransformers(options.roots);
8892
+ return [
8893
+ ...extras.pre,
8894
+ transformSnippet,
8895
+ options.data.config.highlighter === "shiki" && transformMagicMove,
8896
+ ...extras.preCodeblock,
8897
+ transformMermaid,
8898
+ transformPlantUml,
8899
+ options.data.features.monaco && transformMonaco,
8900
+ ...extras.postCodeblock,
8901
+ transformCodeWrapper,
8902
+ options.data.features.katex && transformKaTexWrapper,
8903
+ transformPageCSS,
8904
+ transformSlotSugar,
8905
+ ...extras.post
8906
+ ];
8907
+ }
8908
+
8909
+ // ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.1.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/image-size/specialCharacters.js
8910
+ var SpecialCharacters;
8911
+ (function(SpecialCharacters2) {
8912
+ SpecialCharacters2[SpecialCharacters2["EXCLAMATION_MARK"] = 33] = "EXCLAMATION_MARK";
8913
+ SpecialCharacters2[SpecialCharacters2["OPENING_BRACKET"] = 91] = "OPENING_BRACKET";
8914
+ SpecialCharacters2[SpecialCharacters2["OPENING_PARENTHESIS"] = 40] = "OPENING_PARENTHESIS";
8915
+ SpecialCharacters2[SpecialCharacters2["WHITESPACE"] = 32] = "WHITESPACE";
8916
+ SpecialCharacters2[SpecialCharacters2["NEW_LINE"] = 10] = "NEW_LINE";
8917
+ SpecialCharacters2[SpecialCharacters2["EQUALS"] = 61] = "EQUALS";
8918
+ SpecialCharacters2[SpecialCharacters2["LOWER_CASE_X"] = 120] = "LOWER_CASE_X";
8919
+ SpecialCharacters2[SpecialCharacters2["NUMBER_ZERO"] = 48] = "NUMBER_ZERO";
8920
+ SpecialCharacters2[SpecialCharacters2["NUMBER_NINE"] = 57] = "NUMBER_NINE";
8921
+ SpecialCharacters2[SpecialCharacters2["PERCENTAGE"] = 37] = "PERCENTAGE";
8922
+ SpecialCharacters2[SpecialCharacters2["CLOSING_PARENTHESIS"] = 41] = "CLOSING_PARENTHESIS";
8923
+ })(SpecialCharacters || (SpecialCharacters = {}));
8924
+
8925
+ // ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.1.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/task-lists/index.js
8926
+ import Token from "markdown-it/lib/token.mjs";
8927
+ var checkboxRegex = /^ *\[([\sx])] /i;
8928
+ function taskLists(md, options = { enabled: false, label: false, lineNumber: false }) {
8929
+ md.core.ruler.after("inline", "task-lists", (state) => processToken(state, options));
8930
+ md.renderer.rules.taskListItemCheckbox = (tokens) => {
8931
+ const token = tokens[0];
8932
+ const checkedAttribute = token.attrGet("checked") ? 'checked="" ' : "";
8933
+ const disabledAttribute = token.attrGet("disabled") ? 'disabled="" ' : "";
8934
+ const line = token.attrGet("line");
8935
+ const idAttribute = `id="${token.attrGet("id")}" `;
8936
+ const dataLineAttribute = line && options.lineNumber ? `data-line="${line}" ` : "";
8937
+ return `<input class="task-list-item-checkbox" type="checkbox" ${checkedAttribute}${disabledAttribute}${dataLineAttribute}${idAttribute}/>`;
8797
8938
  };
8798
- const inlineRenderer = function(tokens, idx) {
8799
- return katexInline(tokens[idx].content);
8800
- };
8801
- const katexBlock = function(latex) {
8802
- options.displayMode = true;
8803
- try {
8804
- return `<p>${katex.renderToString(latex, options)}</p>`;
8805
- } catch (error) {
8806
- if (options.throwOnError)
8807
- console.warn(error);
8808
- return latex;
8809
- }
8939
+ md.renderer.rules.taskListItemLabel_close = () => {
8940
+ return "</label>";
8810
8941
  };
8811
- const blockRenderer = function(tokens, idx) {
8812
- return `${katexBlock(tokens[idx].content)}
8813
- `;
8942
+ md.renderer.rules.taskListItemLabel_open = (tokens) => {
8943
+ const token = tokens[0];
8944
+ const id = token.attrGet("id");
8945
+ return `<label for="${id}">`;
8814
8946
  };
8815
- md.inline.ruler.after("escape", "math_inline", math_inline);
8816
- md.block.ruler.after("blockquote", "math_block", math_block, {
8817
- alt: ["paragraph", "reference", "blockquote", "list"]
8818
- });
8819
- md.renderer.rules.math_inline = inlineRenderer;
8820
- md.renderer.rules.math_block = blockRenderer;
8821
8947
  }
8822
-
8823
- // node/syntax/markdown-it/markdown-it-prism.ts
8824
- import { createRequire } from "node:module";
8825
- import Prism from "prismjs";
8826
- import loadLanguages from "prismjs/components/index.js";
8827
- import * as htmlparser2 from "htmlparser2";
8828
-
8829
- // node/syntax/transform/utils.ts
8830
- function normalizeRangeStr(rangeStr = "") {
8831
- return !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
8948
+ function processToken(state, options) {
8949
+ const allTokens = state.tokens;
8950
+ for (let i = 2; i < allTokens.length; i++) {
8951
+ if (!isTodoItem(allTokens, i)) {
8952
+ continue;
8953
+ }
8954
+ todoify(allTokens[i], options);
8955
+ allTokens[i - 2].attrJoin("class", `task-list-item ${options.enabled ? " enabled" : ""}`);
8956
+ const parentToken = findParentToken(allTokens, i - 2);
8957
+ if (parentToken) {
8958
+ const classes = parentToken.attrGet("class") ?? "";
8959
+ if (!classes.match(/(^| )contains-task-list/)) {
8960
+ parentToken.attrJoin("class", "contains-task-list");
8961
+ }
8962
+ }
8963
+ }
8964
+ return false;
8832
8965
  }
8833
- function getCodeBlocks(md) {
8834
- const codeblocks = Array.from(md.matchAll(/^```[\s\S]*?^```/gm)).map((m) => {
8835
- const start = m.index;
8836
- const end = m.index + m[0].length;
8837
- const startLine = md.slice(0, start).match(/\n/g)?.length || 0;
8838
- const endLine = md.slice(0, end).match(/\n/g)?.length || 0;
8839
- return [start, end, startLine, endLine];
8840
- });
8841
- return {
8842
- codeblocks,
8843
- isInsideCodeblocks(idx) {
8844
- return codeblocks.some(([s, e]) => s <= idx && idx <= e);
8845
- },
8846
- isLineInsideCodeblocks(line) {
8847
- return codeblocks.some(([, , s, e]) => s <= line && line <= e);
8966
+ function findParentToken(tokens, index) {
8967
+ const targetLevel = tokens[index].level - 1;
8968
+ for (let currentTokenIndex = index - 1; currentTokenIndex >= 0; currentTokenIndex--) {
8969
+ if (tokens[currentTokenIndex].level === targetLevel) {
8970
+ return tokens[currentTokenIndex];
8848
8971
  }
8849
- };
8972
+ }
8973
+ return void 0;
8850
8974
  }
8851
- function escapeVueInCode(md) {
8852
- return md.replace(/\{\{/g, "&lbrace;&lbrace;");
8975
+ function isTodoItem(tokens, index) {
8976
+ return isInline(tokens[index]) && isParagraph(tokens[index - 1]) && isListItem(tokens[index - 2]) && startsWithTodoMarkdown(tokens[index]);
8853
8977
  }
8854
-
8855
- // node/syntax/markdown-it/markdown-it-prism.ts
8856
- var require2 = createRequire(import.meta.url);
8857
- var Tag = class {
8858
- tagname;
8859
- attributes;
8860
- constructor(tagname, attributes) {
8861
- this.tagname = tagname;
8862
- this.attributes = attributes;
8863
- }
8864
- asOpen() {
8865
- return `<${this.tagname} ${Object.entries(this.attributes).map(([key, value]) => `${key}="${value}"`).join(" ")}>`;
8866
- }
8867
- asClosed() {
8868
- return `</${this.tagname}>`;
8978
+ function todoify(token, options) {
8979
+ if (token.children == null) {
8980
+ return;
8869
8981
  }
8870
- };
8871
- var DEFAULTS = {
8872
- plugins: [],
8873
- init: () => {
8874
- },
8875
- defaultLanguageForUnknown: void 0,
8876
- defaultLanguageForUnspecified: void 0,
8877
- defaultLanguage: void 0
8878
- };
8879
- function loadPrismLang(lang) {
8880
- if (!lang)
8881
- return void 0;
8882
- let langObject = Prism.languages[lang];
8883
- if (langObject === void 0) {
8884
- loadLanguages([lang]);
8885
- langObject = Prism.languages[lang];
8982
+ const id = generateIdForToken(token);
8983
+ token.children.splice(0, 0, createCheckboxToken(token, options.enabled, id));
8984
+ token.children[1].content = token.children[1].content.replace(checkboxRegex, "");
8985
+ if (options.label) {
8986
+ token.children.splice(1, 0, createLabelBeginToken(id));
8987
+ token.children.push(createLabelEndToken());
8886
8988
  }
8887
- return langObject;
8888
8989
  }
8889
- function loadPrismPlugin(name) {
8890
- try {
8891
- require2(`prismjs/plugins/${name}/prism-${name}`);
8892
- } catch (e) {
8893
- throw new Error(`Cannot load Prism plugin "${name}". Please check the spelling.`);
8990
+ function generateIdForToken(token) {
8991
+ if (token.map) {
8992
+ return `task-item-${token.map[0]}`;
8993
+ } else {
8994
+ return `task-item-${Math.ceil(Math.random() * (1e4 * 1e3) - 1e3)}`;
8894
8995
  }
8895
8996
  }
8896
- function selectLanguage(options, lang) {
8897
- let langToUse = lang;
8898
- if (langToUse === "" && options.defaultLanguageForUnspecified !== void 0)
8899
- langToUse = options.defaultLanguageForUnspecified;
8900
- let prismLang = loadPrismLang(langToUse);
8901
- if (prismLang === void 0 && options.defaultLanguageForUnknown !== void 0) {
8902
- langToUse = options.defaultLanguageForUnknown;
8903
- prismLang = loadPrismLang(langToUse);
8997
+ function createCheckboxToken(token, enabled, id) {
8998
+ const checkbox = new Token("taskListItemCheckbox", "", 0);
8999
+ if (!enabled) {
9000
+ checkbox.attrSet("disabled", "true");
8904
9001
  }
8905
- return [langToUse, prismLang];
8906
- }
8907
- function highlight(markdownit, options, text, lang) {
8908
- const [langToUse, prismLang] = selectLanguage(options, lang);
8909
- let code = text.trimEnd();
8910
- code = prismLang ? highlightPrism(code, prismLang, langToUse) : markdownit.utils.escapeHtml(code);
8911
- code = code.split(/\r?\n/g).map((line) => `<span class="line">${line}</span>`).join("\n");
8912
- const classAttribute = langToUse ? ` class="slidev-code ${markdownit.options.langPrefix}${markdownit.utils.escapeHtml(langToUse)}"` : "";
8913
- return escapeVueInCode(`<pre${classAttribute}><code>${code}</code></pre>`);
8914
- }
8915
- function highlightPrism(code, prismLang, langToUse) {
8916
- const openTags = [];
8917
- const parser3 = new htmlparser2.Parser({
8918
- onopentag(tagname, attributes) {
8919
- openTags.push(new Tag(tagname, attributes));
8920
- },
8921
- onclosetag() {
8922
- openTags.pop();
8923
- }
8924
- });
8925
- code = Prism.highlight(code, prismLang, langToUse);
8926
- code = code.split(/\r?\n/g).map((line) => {
8927
- const prefix = openTags.map((tag) => tag.asOpen()).join("");
8928
- parser3.write(line);
8929
- const postfix = openTags.reverse().map((tag) => tag.asClosed()).join("");
8930
- return prefix + line + postfix;
8931
- }).join("\n");
8932
- parser3.end();
8933
- return code;
9002
+ if (token.map) {
9003
+ checkbox.attrSet("line", token.map[0].toString());
9004
+ }
9005
+ checkbox.attrSet("id", id);
9006
+ const checkboxRegexResult = checkboxRegex.exec(token.content);
9007
+ const isChecked = checkboxRegexResult?.[1].toLowerCase() === "x";
9008
+ if (isChecked) {
9009
+ checkbox.attrSet("checked", "true");
9010
+ }
9011
+ return checkbox;
8934
9012
  }
8935
- function checkLanguageOption(options, optionName) {
8936
- const language = options[optionName];
8937
- if (language !== void 0 && loadPrismLang(language) === void 0)
8938
- throw new Error(`Bad option ${optionName}: There is no Prism language '${language}'.`);
9013
+ function createLabelBeginToken(id) {
9014
+ const labelBeginToken = new Token("taskListItemLabel_open", "", 1);
9015
+ labelBeginToken.attrSet("id", id);
9016
+ return labelBeginToken;
8939
9017
  }
8940
- function markdownItPrism(markdownit, useroptions) {
8941
- const options = Object.assign({}, DEFAULTS, useroptions);
8942
- checkLanguageOption(options, "defaultLanguage");
8943
- checkLanguageOption(options, "defaultLanguageForUnknown");
8944
- checkLanguageOption(options, "defaultLanguageForUnspecified");
8945
- options.defaultLanguageForUnknown = options.defaultLanguageForUnknown || options.defaultLanguage;
8946
- options.defaultLanguageForUnspecified = options.defaultLanguageForUnspecified || options.defaultLanguage;
8947
- options.plugins.forEach(loadPrismPlugin);
8948
- options.init(Prism);
8949
- markdownit.options.highlight = (text, lang) => highlight(markdownit, options, text, lang);
9018
+ function createLabelEndToken() {
9019
+ return new Token("taskListItemLabel_close", "", -1);
8950
9020
  }
8951
-
8952
- // node/syntax/markdown-it/markdown-it-v-drag.ts
8953
- import { SourceMapConsumer } from "source-map-js";
8954
- function markdownItVDrag(md, markdownTransformMap) {
8955
- const visited = /* @__PURE__ */ new WeakSet();
8956
- const sourceMapConsumers = /* @__PURE__ */ new WeakMap();
8957
- function getSourceMapConsumer(id) {
8958
- const s = markdownTransformMap.get(id);
8959
- if (!s)
8960
- return void 0;
8961
- let smc = sourceMapConsumers.get(s);
8962
- if (smc)
8963
- return smc;
8964
- const sourceMap = s.generateMap();
8965
- smc = new SourceMapConsumer({
8966
- ...sourceMap,
8967
- version: sourceMap.version.toString()
8968
- });
8969
- sourceMapConsumers.set(s, smc);
8970
- return smc;
8971
- }
8972
- const _parse = md.parse;
8973
- md.parse = function(src, env) {
8974
- const smc = getSourceMapConsumer(env.id);
8975
- const toOriginalPos = smc ? (line) => smc.originalPositionFor({ line, column: 0 }).line : (line) => line;
8976
- function toMarkdownSource(map, idx) {
8977
- const [start, end] = map;
8978
- return `[${toOriginalPos(start)},${toOriginalPos(end)},${idx}]`;
8979
- }
8980
- return _parse.call(this, src, env).map((token) => {
8981
- if (!["html_block", "html_inline"].includes(token.type) || !token.content.includes("v-drag") || visited.has(token))
8982
- return token;
8983
- token.content = token.content.replace(
8984
- /<(v-?drag-?\w*)([\s>])/gi,
8985
- (_, tag, space, idx) => `<${tag} :markdownSource="${toMarkdownSource(token.map, idx)}"${space}`
8986
- ).replace(
8987
- /(?<![</\w])v-drag(=".*?")?/g,
8988
- (_, value, idx) => `v-drag${value ?? ""} :markdownSource="[${token.map[0]},${token.map[1]},${idx}]"`
8989
- );
8990
- visited.add(token);
8991
- return token;
8992
- });
8993
- };
9021
+ function isInline(token) {
9022
+ return token.type === "inline";
8994
9023
  }
8995
-
8996
- // node/syntax/transform/code-wrapper.ts
8997
- var reCodeBlock = /^```([\w'-]+)(?:\s*\{([\w*,|-]+)\}\s*?(\{[^}]*\})?([^\r\n]*))?\r?\n(\S[\s\S]*?)^```$/gm;
8998
- function transformCodeWrapper(ctx) {
8999
- ctx.s.replace(
9000
- reCodeBlock,
9001
- (full, lang = "", rangeStr = "", options = "", attrs = "", code) => {
9002
- const ranges = normalizeRangeStr(rangeStr);
9003
- code = code.trimEnd();
9004
- options = options.trim() || "{}";
9005
- return `
9006
- <CodeBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
9007
-
9008
- \`\`\`${lang}${attrs}
9009
- ${code}
9010
- \`\`\`
9011
-
9012
- </CodeBlockWrapper>`;
9013
- }
9014
- );
9024
+ function isParagraph(token) {
9025
+ return token.type === "paragraph_open";
9015
9026
  }
9016
-
9017
- // node/syntax/transform/magic-move.ts
9018
- import { codeToKeyedTokens } from "shiki-magic-move/core";
9019
- import lz from "lz-string";
9020
- var reMagicMoveBlock = /^````(?:md|markdown) magic-move(?: *(\{[^}]*\})?([^\n]*))?\n([\s\S]+?)^````$/gm;
9021
- function parseLineNumbersOption(options) {
9022
- return /lines: *true/.test(options) ? true : /lines: *false/.test(options) ? false : void 0;
9027
+ function isListItem(token) {
9028
+ return token.type === "list_item_open";
9023
9029
  }
9024
- function transformMagicMove(shiki, shikiOptions, configLineNumbers) {
9025
- return (ctx) => {
9026
- ctx.s.replace(
9027
- reMagicMoveBlock,
9028
- (full, options = "{}", _attrs = "", body) => {
9029
- if (!shiki || !shikiOptions)
9030
- throw new Error("Shiki is required for Magic Move. You may need to set `highlighter: shiki` in your Slidev config.");
9031
- const matches = Array.from(body.matchAll(reCodeBlock));
9032
- if (!matches.length)
9033
- throw new Error("Magic Move block must contain at least one code block");
9034
- const defaultLineNumbers = parseLineNumbersOption(options) ?? configLineNumbers;
9035
- const ranges = matches.map((i) => normalizeRangeStr(i[2]));
9036
- const steps = matches.map((i) => {
9037
- const lineNumbers = parseLineNumbersOption(i[3]) ?? defaultLineNumbers;
9038
- return codeToKeyedTokens(shiki, i[5].trimEnd(), {
9039
- ...shikiOptions,
9040
- lang: i[1]
9041
- }, lineNumbers);
9042
- });
9043
- const compressed = lz.compressToBase64(JSON.stringify(steps));
9044
- return `<ShikiMagicMove v-bind="${options}" steps-lz="${compressed}" :step-ranges='${JSON.stringify(ranges)}' />`;
9045
- }
9046
- );
9047
- };
9030
+ function startsWithTodoMarkdown(token) {
9031
+ return checkboxRegex.test(token.content);
9048
9032
  }
9049
9033
 
9050
- // node/syntax/transform/mermaid.ts
9051
- import lz2 from "lz-string";
9052
- function transformMermaid(ctx) {
9053
- ctx.s.replace(
9054
- /^```mermaid *(\{[^\n]*\})?\n([\s\S]+?)\n```/gm,
9055
- (full, options = "", code = "") => {
9056
- code = code.trim();
9057
- options = options.trim() || "{}";
9058
- const encoded = lz2.compressToBase64(code);
9059
- return `<Mermaid code-lz="${encoded}" v-bind="${options}" />`;
9060
- }
9061
- );
9062
- }
9034
+ // node/syntax/markdown-it/index.ts
9035
+ import MarkdownItMdc from "markdown-it-mdc";
9036
+ import MarkdownItFootnote from "markdown-it-footnote";
9063
9037
 
9064
- // node/syntax/transform/plant-uml.ts
9065
- import { encode as encodePlantUml } from "plantuml-encoder";
9066
- function transformPlantUml(ctx) {
9067
- const server = ctx.options.data.config.plantUmlServer;
9068
- ctx.s.replace(
9069
- /^```plantuml[^\n{}]*(\{[^}\n]*\})?\n([\s\S]+?)\n```/gm,
9070
- (full, options = "", content = "") => {
9071
- const code = encodePlantUml(content.trim());
9072
- options = options.trim() || "{}";
9073
- return `<PlantUml :code="'${code}'" :server="'${server}'" v-bind="${options}" />`;
9074
- }
9038
+ // node/setups/katex.ts
9039
+ async function setupKatex(roots) {
9040
+ const options = await loadSetups(roots, "katex.ts", []);
9041
+ return Object.assign(
9042
+ { strict: false },
9043
+ ...options
9075
9044
  );
9076
9045
  }
9077
9046
 
9078
- // node/syntax/transform/snippet.ts
9079
- import path3 from "node:path";
9080
- import lz3 from "lz-string";
9081
- import fs7 from "fs-extra";
9082
- import { slash as slash2 } from "@antfu/utils";
9083
-
9084
- // node/vite/monacoWrite.ts
9085
- import fs6 from "node:fs/promises";
9086
- import path2 from "node:path";
9087
- var monacoWriterWhitelist = /* @__PURE__ */ new Set();
9088
- function createMonacoWriter({ userRoot }) {
9047
+ // node/syntax/markdown-it/markdown-it-katex.ts
9048
+ import katex from "katex";
9049
+ function isValidDelim(state, pos) {
9050
+ const max = state.posMax;
9051
+ let can_open = true;
9052
+ let can_close = true;
9053
+ const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
9054
+ const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
9055
+ if (prevChar === 32 || prevChar === 9 || /* \t */
9056
+ nextChar >= 48 && nextChar <= 57)
9057
+ can_close = false;
9058
+ if (nextChar === 32 || nextChar === 9)
9059
+ can_open = false;
9089
9060
  return {
9090
- name: "slidev:monaco-write",
9091
- apply: "serve",
9092
- configureServer(server) {
9093
- server.ws.on("connection", (socket) => {
9094
- socket.on("message", async (data) => {
9095
- let json;
9096
- try {
9097
- json = JSON.parse(data.toString());
9098
- } catch (e) {
9099
- return;
9100
- }
9101
- if (json.type === "custom" && json.event === "slidev:monaco-write") {
9102
- const { file, content } = json.data;
9103
- if (!monacoWriterWhitelist.has(file)) {
9104
- console.error(`[Slidev] Unauthorized file write: ${file}`);
9105
- return;
9106
- }
9107
- const filepath = path2.join(userRoot, file);
9108
- console.log("[Slidev] Writing file:", filepath);
9109
- await fs6.writeFile(filepath, content, "utf-8");
9110
- }
9111
- });
9112
- });
9113
- }
9061
+ can_open,
9062
+ can_close
9114
9063
  };
9115
9064
  }
9116
-
9117
- // node/syntax/transform/snippet.ts
9118
- function dedent(text) {
9119
- const lines = text.split("\n");
9120
- const minIndentLength = lines.reduce((acc, line) => {
9121
- for (let i = 0; i < line.length; i++) {
9122
- if (line[i] !== " " && line[i] !== " ")
9123
- return Math.min(i, acc);
9124
- }
9125
- return acc;
9126
- }, Number.POSITIVE_INFINITY);
9127
- if (minIndentLength < Number.POSITIVE_INFINITY)
9128
- return lines.map((x) => x.slice(minIndentLength)).join("\n");
9129
- return text;
9130
- }
9131
- function testLine(line, regexp, regionName, end = false) {
9132
- const [full, tag, name] = regexp.exec(line.trim()) || [];
9133
- return full && tag && name === regionName && tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/);
9134
- }
9135
- function findRegion(lines, regionName) {
9136
- const regionRegexps = [
9137
- /^\/\/ ?#?((?:end)?region) ([\w*-]+)$/,
9138
- // javascript, typescript, java
9139
- /^\/\* ?#((?:end)?region) ([\w*-]+) ?\*\/$/,
9140
- // css, less, scss
9141
- /^#pragma ((?:end)?region) ([\w*-]+)$/,
9142
- // C, C++
9143
- /^<!-- #?((?:end)?region) ([\w*-]+) -->$/,
9144
- // HTML, markdown
9145
- /^#(End Region) ([\w*-]+)$/,
9146
- // Visual Basic
9147
- /^::#(endregion) ([\w*-]+)$/,
9148
- // Bat
9149
- /^# ?((?:end)?region) ([\w*-]+)$/
9150
- // C#, PHP, Powershell, Python, perl & misc
9151
- ];
9152
- let regexp = null;
9153
- let start = -1;
9154
- for (const [lineId, line] of lines.entries()) {
9155
- if (regexp === null) {
9156
- for (const reg of regionRegexps) {
9157
- if (testLine(line, reg, regionName)) {
9158
- start = lineId + 1;
9159
- regexp = reg;
9160
- break;
9161
- }
9162
- }
9163
- } else if (testLine(line, regexp, regionName, true)) {
9164
- return { start, end: lineId, regexp };
9165
- }
9065
+ function math_inline(state, silent) {
9066
+ let match, token, res, pos;
9067
+ if (state.src[state.pos] !== "$")
9068
+ return false;
9069
+ res = isValidDelim(state, state.pos);
9070
+ if (!res.can_open) {
9071
+ if (!silent)
9072
+ state.pending += "$";
9073
+ state.pos += 1;
9074
+ return true;
9166
9075
  }
9167
- return null;
9168
- }
9169
- function transformSnippet(ctx) {
9170
- const options = ctx.options;
9171
- const slideId = ctx.id.match(/(\d+)\.md$/)?.[1];
9172
- if (!slideId)
9173
- return;
9174
- const data = options.data;
9175
- const slideInfo = data.slides[+slideId - 1];
9176
- const dir = path3.dirname(slideInfo.source?.filepath ?? options.entry ?? options.userRoot);
9177
- ctx.s.replace(
9178
- // eslint-disable-next-line regexp/no-super-linear-backtracking
9179
- /^<<<\s*(\S.*?)(#[\w-]+)?\s*(?:\s(\S+?))?\s*(\{.*)?$/gm,
9180
- (full, filepath = "", regionName = "", lang = "", meta = "") => {
9181
- const src = slash2(
9182
- /^@\//.test(filepath) ? path3.resolve(options.userRoot, filepath.slice(2)) : path3.resolve(dir, filepath)
9183
- );
9184
- data.watchFiles.push(src);
9185
- const isAFile = fs7.statSync(src).isFile();
9186
- if (!fs7.existsSync(src) || !isAFile) {
9187
- throw new Error(isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`);
9188
- }
9189
- let content = fs7.readFileSync(src, "utf8");
9190
- slideInfo.snippetsUsed ??= {};
9191
- slideInfo.snippetsUsed[src] = content;
9192
- if (regionName) {
9193
- const lines = content.split(/\r?\n/);
9194
- const region = findRegion(lines, regionName.slice(1));
9195
- if (region) {
9196
- content = dedent(
9197
- lines.slice(region.start, region.end).filter((line) => !region.regexp.test(line.trim())).join("\n")
9198
- );
9199
- }
9200
- }
9201
- meta = meta.trim();
9202
- lang = lang.trim();
9203
- lang = lang || path3.extname(filepath).slice(1);
9204
- if (meta.match(/^\{monaco-write\}/)) {
9205
- monacoWriterWhitelist.add(filepath);
9206
- lang = lang.trim();
9207
- meta = meta.replace(/^\{monaco-write\}/, "").trim() || "{}";
9208
- const encoded = lz3.compressToBase64(content);
9209
- return `<Monaco writable=${JSON.stringify(filepath)} code-lz="${encoded}" lang="${lang}" v-bind="${meta}" />`;
9210
- }
9211
- return `\`\`\`${lang} ${meta}
9212
- ${content}
9213
- \`\`\``;
9214
- }
9215
- );
9216
- }
9217
-
9218
- // node/syntax/transform/slot-sugar.ts
9219
- function transformSlotSugar(ctx) {
9220
- const linesWithNewline = ctx.s.original.split(/(\r?\n)/g);
9221
- const codeBlocks = getCodeBlocks(ctx.s.original);
9222
- const lines = [];
9223
- for (let i = 0; i < linesWithNewline.length; i += 2) {
9224
- const line = linesWithNewline[i];
9225
- const newline = linesWithNewline[i + 1] || "";
9226
- lines.push(line + newline);
9076
+ const start = state.pos + 1;
9077
+ match = start;
9078
+ while ((match = state.src.indexOf("$", match)) !== -1) {
9079
+ pos = match - 1;
9080
+ while (state.src[pos] === "\\") pos -= 1;
9081
+ if ((match - pos) % 2 === 1)
9082
+ break;
9083
+ match += 1;
9227
9084
  }
9228
- let prevSlot = false;
9229
- let offset = 0;
9230
- lines.forEach((line) => {
9231
- const start = offset;
9232
- offset += line.length;
9233
- if (codeBlocks.isInsideCodeblocks(offset))
9234
- return;
9235
- const match = line.match(/^::\s*([\w.\-:]+)\s*::(\s*)$/);
9236
- if (match) {
9237
- ctx.s.overwrite(start, offset - match[2].length, `${prevSlot ? "\n\n</template>\n" : "\n"}<template v-slot:${match[1]}="slotProps">
9238
- `);
9239
- prevSlot = true;
9240
- }
9241
- });
9242
- if (prevSlot)
9243
- ctx.s.append("\n\n</template>");
9244
- }
9245
-
9246
- // node/syntax/transform/in-page-css.ts
9247
- function transformPageCSS(ctx) {
9248
- const page = ctx.id.match(/(\d+)\.md$/)?.[1];
9249
- if (!page)
9250
- return;
9251
- const codeBlocks = getCodeBlocks(ctx.s.original);
9252
- ctx.s.replace(
9253
- /(\n<style[^>]*>)([\s\S]+?)(<\/style>)/g,
9254
- (full, start, css, end, index) => {
9255
- if (codeBlocks.isInsideCodeblocks(index))
9256
- return full;
9257
- if (!start.includes("scoped"))
9258
- start = start.replace("<style", "<style scoped");
9259
- return `${start}
9260
- ${css}${end}`;
9261
- }
9262
- );
9085
+ if (match === -1) {
9086
+ if (!silent)
9087
+ state.pending += "$";
9088
+ state.pos = start;
9089
+ return true;
9090
+ }
9091
+ if (match - start === 0) {
9092
+ if (!silent)
9093
+ state.pending += "$$";
9094
+ state.pos = start + 1;
9095
+ return true;
9096
+ }
9097
+ res = isValidDelim(state, match);
9098
+ if (!res.can_close) {
9099
+ if (!silent)
9100
+ state.pending += "$";
9101
+ state.pos = start;
9102
+ return true;
9103
+ }
9104
+ if (!silent) {
9105
+ token = state.push("math_inline", "math", 0);
9106
+ token.markup = "$";
9107
+ token.content = state.src.slice(start, match);
9108
+ }
9109
+ state.pos = match + 1;
9110
+ return true;
9263
9111
  }
9264
-
9265
- // node/syntax/transform/monaco.ts
9266
- import lz4 from "lz-string";
9267
- function transformMonaco(ctx) {
9268
- const enabled = ctx.options.data.config.monaco === true || ctx.options.data.config.monaco === ctx.options.mode;
9269
- if (!enabled) {
9270
- ctx.s.replace(/\{monaco([\w:,-]*)\}/g, "");
9271
- return;
9112
+ function math_block(state, start, end, silent) {
9113
+ let firstLine;
9114
+ let lastLine;
9115
+ let next;
9116
+ let lastPos;
9117
+ let found = false;
9118
+ let pos = state.bMarks[start] + state.tShift[start];
9119
+ let max = state.eMarks[start];
9120
+ if (pos + 2 > max)
9121
+ return false;
9122
+ if (state.src.slice(pos, pos + 2) !== "$$")
9123
+ return false;
9124
+ pos += 2;
9125
+ firstLine = state.src.slice(pos, max);
9126
+ if (silent)
9127
+ return true;
9128
+ if (firstLine.trim().slice(-2) === "$$") {
9129
+ firstLine = firstLine.trim().slice(0, -2);
9130
+ found = true;
9272
9131
  }
9273
- ctx.s.replace(
9274
- /^```(\w+) *\{monaco-diff\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^~~~ *\n([\s\S]+?)^```/gm,
9275
- (full, lang = "ts", options = "{}", code, diff) => {
9276
- lang = lang.trim();
9277
- options = options.trim() || "{}";
9278
- const encoded = lz4.compressToBase64(code);
9279
- const encodedDiff = lz4.compressToBase64(diff);
9280
- return `<Monaco code-lz="${encoded}" diff-lz="${encodedDiff}" lang="${lang}" v-bind="${options}" />`;
9281
- }
9282
- );
9283
- ctx.s.replace(
9284
- /^```(\w+) *\{monaco\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm,
9285
- (full, lang = "ts", options = "{}", code) => {
9286
- lang = lang.trim();
9287
- options = options.trim() || "{}";
9288
- const encoded = lz4.compressToBase64(code);
9289
- return `<Monaco code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
9132
+ for (next = start; !found; ) {
9133
+ next++;
9134
+ if (next >= end)
9135
+ break;
9136
+ pos = state.bMarks[next] + state.tShift[next];
9137
+ max = state.eMarks[next];
9138
+ if (pos < max && state.tShift[next] < state.blkIndent) {
9139
+ break;
9290
9140
  }
9291
- );
9292
- ctx.s.replace(
9293
- /^```(\w+) *\{monaco-run\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm,
9294
- (full, lang = "ts", options = "{}", code) => {
9295
- lang = lang.trim();
9296
- options = options.trim() || "{}";
9297
- const encoded = lz4.compressToBase64(code);
9298
- return `<Monaco runnable code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
9141
+ if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
9142
+ lastPos = state.src.slice(0, max).lastIndexOf("$$");
9143
+ lastLine = state.src.slice(pos, lastPos);
9144
+ found = true;
9299
9145
  }
9300
- );
9146
+ }
9147
+ state.line = next + 1;
9148
+ const token = state.push("math_block", "math", 0);
9149
+ token.block = true;
9150
+ token.content = (firstLine && firstLine.trim() ? `${firstLine}
9151
+ ` : "") + state.getLines(start + 1, next, state.tShift[start], true) + (lastLine && lastLine.trim() ? lastLine : "");
9152
+ token.map = [start, state.line];
9153
+ token.markup = "$$";
9154
+ return true;
9301
9155
  }
9302
-
9303
- // node/syntax/transform/katex-wrapper.ts
9304
- function transformKaTexWrapper(ctx) {
9305
- ctx.s.replace(
9306
- /^\$\$(?:\s*\{([\w*,|-]+)\}\s*?(?:(\{[^}]*\})\s*?)?)?\n(\S[\s\S]*?)^\$\$/gm,
9307
- (full, rangeStr = "", options = "", code) => {
9308
- const ranges = !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
9309
- code = code.trimEnd();
9310
- options = options.trim() || "{}";
9311
- return `<KaTexBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
9312
-
9313
- $$
9314
- ${code}
9315
- $$
9316
- </KaTexBlockWrapper>
9317
- `;
9156
+ function MarkdownItKatex(md, options) {
9157
+ const katexInline = function(latex) {
9158
+ options.displayMode = false;
9159
+ try {
9160
+ return katex.renderToString(latex, options);
9161
+ } catch (error) {
9162
+ if (options.throwOnError)
9163
+ console.warn(error);
9164
+ return latex;
9165
+ }
9166
+ };
9167
+ const inlineRenderer = function(tokens, idx) {
9168
+ return katexInline(tokens[idx].content);
9169
+ };
9170
+ const katexBlock = function(latex) {
9171
+ options.displayMode = true;
9172
+ try {
9173
+ return `<p>${katex.renderToString(latex, options)}</p>`;
9174
+ } catch (error) {
9175
+ if (options.throwOnError)
9176
+ console.warn(error);
9177
+ return latex;
9318
9178
  }
9319
- );
9179
+ };
9180
+ const blockRenderer = function(tokens, idx) {
9181
+ return `${katexBlock(tokens[idx].content)}
9182
+ `;
9183
+ };
9184
+ md.inline.ruler.after("escape", "math_inline", math_inline);
9185
+ md.block.ruler.after("blockquote", "math_block", math_block, {
9186
+ alt: ["paragraph", "reference", "blockquote", "list"]
9187
+ });
9188
+ md.renderer.rules.math_inline = inlineRenderer;
9189
+ md.renderer.rules.math_block = blockRenderer;
9320
9190
  }
9321
9191
 
9322
- // node/vite/markdown.ts
9323
- async function createMarkdownPlugin(options, { markdown: mdOptions }) {
9324
- const { data: { config }, roots, mode, entry, clientRoot } = options;
9325
- const setups = [];
9326
- const entryPath = slash3(entry);
9327
- let shiki;
9328
- let shikiOptions;
9329
- if (config.highlighter === "shiki") {
9330
- const result = await createMarkdownItShiki(clientRoot, roots, config, mode);
9331
- shiki = result.shiki;
9332
- shikiOptions = result.shikiOptions;
9333
- setups.push((md) => md.use(result.plugin));
9334
- } else {
9335
- console.warn("[Slidev] Highlighter: Prism highlighter is deprecated, and will be removed in v0.50. Refer to https://github.com/slidevjs/slidev/issues/1390");
9336
- setups.push((md) => md.use(markdownItPrism));
9192
+ // node/syntax/markdown-it/markdown-it-v-drag.ts
9193
+ import { SourceMapConsumer } from "source-map-js";
9194
+ function MarkdownItVDrag(md, markdownTransformMap) {
9195
+ const visited = /* @__PURE__ */ new WeakSet();
9196
+ const sourceMapConsumers = /* @__PURE__ */ new WeakMap();
9197
+ function getSourceMapConsumer(id) {
9198
+ const s = markdownTransformMap.get(id);
9199
+ if (!s)
9200
+ return void 0;
9201
+ let smc = sourceMapConsumers.get(s);
9202
+ if (smc)
9203
+ return smc;
9204
+ const sourceMap = s.generateMap();
9205
+ smc = new SourceMapConsumer({
9206
+ ...sourceMap,
9207
+ version: sourceMap.version.toString()
9208
+ });
9209
+ sourceMapConsumers.set(s, smc);
9210
+ return smc;
9337
9211
  }
9338
- if (config.mdc)
9339
- setups.push((md) => md.use(MarkdownItMdc));
9340
- const KatexOptions = await loadSetups(options.clientRoot, roots, "katex.ts", {}, { strict: false }, false);
9341
- const markdownTransformMap = /* @__PURE__ */ new Map();
9342
- return Markdown({
9343
- include: [/\.md$/],
9344
- wrapperClasses: "",
9345
- headEnabled: false,
9346
- frontmatter: false,
9347
- escapeCodeTagInterpolation: false,
9348
- markdownItOptions: {
9349
- quotes: `""''`,
9350
- html: true,
9351
- xhtmlOut: true,
9352
- linkify: true,
9353
- ...mdOptions?.markdownItOptions
9354
- },
9355
- ...mdOptions,
9356
- markdownItSetup(md) {
9357
- md.use(markdownItLink);
9358
- md.use(MarkdownItEscapeInlineCode);
9359
- md.use(MarkdownItFootnote);
9360
- md.use(taskLists, { enabled: true, lineNumber: true, label: true });
9361
- md.use(math_plugin, KatexOptions);
9362
- md.use(markdownItVDrag, markdownTransformMap);
9363
- setups.forEach((i) => i(md));
9364
- mdOptions?.markdownItSetup?.(md);
9365
- },
9366
- transforms: {
9367
- before(code, id) {
9368
- if (id === entryPath)
9369
- return "";
9370
- const ctx = {
9371
- s: new MagicString(code),
9372
- id,
9373
- options
9374
- };
9375
- applyMarkdownTransform(ctx, shiki, shikiOptions);
9376
- markdownTransformMap.set(id, ctx.s);
9377
- return ctx.s.toString();
9378
- }
9212
+ const _parse = md.parse;
9213
+ md.parse = function(src, env) {
9214
+ const smc = getSourceMapConsumer(env.id);
9215
+ const toOriginalPos = smc ? (line) => smc.originalPositionFor({ line, column: 0 }).line : (line) => line;
9216
+ function toMarkdownSource(map, idx) {
9217
+ const [start, end] = map;
9218
+ return `[${toOriginalPos(start)},${toOriginalPos(end)},${idx}]`;
9379
9219
  }
9380
- });
9220
+ return _parse.call(this, src, env).map((token) => {
9221
+ if (!["html_block", "html_inline"].includes(token.type) || !token.content.includes("v-drag") || visited.has(token))
9222
+ return token;
9223
+ token.content = token.content.replace(
9224
+ /<(v-?drag-?\w*)([\s>])/gi,
9225
+ (_, tag, space, idx) => `<${tag} :markdownSource="${toMarkdownSource(token.map, idx)}"${space}`
9226
+ ).replace(
9227
+ /(?<![</\w])v-drag(=".*?")?/g,
9228
+ (_, value, idx) => `v-drag${value ?? ""} :markdownSource="[${token.map[0]},${token.map[1]},${idx}]"`
9229
+ );
9230
+ visited.add(token);
9231
+ return token;
9232
+ });
9233
+ };
9381
9234
  }
9382
- async function createMarkdownItShiki(clientRoot, roots, config, mode) {
9383
- const [
9384
- shikiOptions,
9385
- { createHighlighter, bundledLanguages },
9386
- markdownItShiki,
9387
- transformerTwoslash
9388
- ] = await Promise.all([
9389
- loadShikiSetups(clientRoot, roots),
9390
- import("shiki").then(({ createHighlighter: createHighlighter2, bundledLanguages: bundledLanguages2 }) => ({ bundledLanguages: bundledLanguages2, createHighlighter: createHighlighter2 })),
9391
- import("@shikijs/markdown-it/core").then(({ fromHighlighter }) => fromHighlighter),
9392
- import("@shikijs/vitepress-twoslash").then(({ transformerTwoslash: transformerTwoslash2 }) => transformerTwoslash2)
9393
- ]);
9394
- const shiki = await createHighlighter({
9395
- ...shikiOptions,
9396
- langs: shikiOptions.langs ?? Object.keys(bundledLanguages),
9397
- themes: "themes" in shikiOptions ? Object.values(shikiOptions.themes) : [shikiOptions.theme]
9398
- });
9399
- const twoslashEnabled = config.twoslash === true || config.twoslash === mode;
9235
+
9236
+ // node/syntax/markdown-it/markdown-it-shiki.ts
9237
+ import { isTruthy } from "@antfu/utils";
9238
+ import { fromHighlighter } from "@shikijs/markdown-it/core";
9239
+ async function MarkdownItShiki({ data: { config }, mode, utils }) {
9400
9240
  const transformers = [
9401
- ...shikiOptions.transformers || [],
9402
- twoslashEnabled && transformerTwoslash({
9241
+ ...utils.shikiOptions.transformers || [],
9242
+ (config.twoslash === true || config.twoslash === mode) && (await import("@shikijs/vitepress-twoslash")).transformerTwoslash({
9403
9243
  explicitTrigger: true,
9404
9244
  twoslashOptions: {
9405
9245
  handbookOptions: {
@@ -9417,16 +9257,13 @@ async function createMarkdownItShiki(clientRoot, roots, config, mode) {
9417
9257
  }
9418
9258
  }
9419
9259
  ].filter(isTruthy);
9420
- const plugin = markdownItShiki(shiki, {
9421
- ...shikiOptions,
9260
+ return fromHighlighter(utils.shiki, {
9261
+ ...utils.shikiOptions,
9422
9262
  transformers
9423
9263
  });
9424
- return {
9425
- shiki,
9426
- shikiOptions,
9427
- plugin
9428
- };
9429
9264
  }
9265
+
9266
+ // node/syntax/markdown-it/markdown-it-escape-code.ts
9430
9267
  function MarkdownItEscapeInlineCode(md) {
9431
9268
  const codeInline = md.renderer.rules.code_inline;
9432
9269
  md.renderer.rules.code_inline = (tokens, idx, options, env, self) => {
@@ -9434,55 +9271,82 @@ function MarkdownItEscapeInlineCode(md) {
9434
9271
  return result.replace(/^<code/, "<code v-pre");
9435
9272
  };
9436
9273
  }
9437
- function applyMarkdownTransform(ctx, shiki, shikiOptions) {
9438
- const transformers = [
9439
- transformSnippet,
9440
- ctx.options.data.config.highlighter ? transformMagicMove(shiki, shikiOptions, ctx.options.data.config.lineNumbers) : void 0,
9441
- transformMermaid,
9442
- transformPlantUml,
9443
- transformMonaco,
9444
- transformCodeWrapper,
9445
- transformKaTexWrapper,
9446
- transformPageCSS,
9447
- transformSlotSugar
9448
- ];
9449
- for (const transformer of transformers) {
9450
- if (!transformer)
9451
- continue;
9452
- transformer(ctx);
9453
- if (!ctx.s.isEmpty())
9454
- ctx.s.commit();
9274
+
9275
+ // node/syntax/markdown-it/index.ts
9276
+ async function useMarkdownItPlugins(md, options, markdownTransformMap) {
9277
+ const { roots, data: { features, config } } = options;
9278
+ if (config.highlighter === "shiki") {
9279
+ md.use(await MarkdownItShiki(options));
9280
+ } else {
9281
+ console.warn("[Slidev] Highlighter: Prism highlighter is deprecated, and will be removed in v0.50. Refer to https://github.com/slidevjs/slidev/issues/1390");
9282
+ const { default: MarkdownItPrism } = await import("./markdown-it-prism-GWSWY6QQ.js");
9283
+ md.use(MarkdownItPrism);
9455
9284
  }
9456
- return ctx;
9285
+ md.use(MarkdownItLink);
9286
+ md.use(MarkdownItEscapeInlineCode);
9287
+ md.use(MarkdownItFootnote);
9288
+ md.use(taskLists, { enabled: true, lineNumber: true, label: true });
9289
+ if (features.katex)
9290
+ md.use(MarkdownItKatex, await setupKatex(roots));
9291
+ md.use(MarkdownItVDrag, markdownTransformMap);
9292
+ if (config.mdc)
9293
+ md.use(MarkdownItMdc);
9457
9294
  }
9458
9295
 
9459
- // node/vite/compilerFlagsVue.ts
9460
- import { objectEntries } from "@antfu/utils";
9461
- function createVueCompilerFlagsPlugin(options) {
9462
- const define = objectEntries(getDefine(options));
9463
- return [
9464
- {
9465
- name: "slidev:flags",
9466
- enforce: "pre",
9467
- transform(code, id) {
9468
- if (id.match(/\.vue($|\?)/)) {
9469
- const original = code;
9470
- define.forEach(([from, to]) => {
9471
- code = code.replace(new RegExp(from, "g"), to);
9472
- });
9473
- if (original !== code)
9474
- return code;
9296
+ // node/vite/markdown.ts
9297
+ async function createMarkdownPlugin(options, { markdown: mdOptions }) {
9298
+ const markdownTransformMap = /* @__PURE__ */ new Map();
9299
+ const transformers = await getMarkdownTransformers(options);
9300
+ return Markdown({
9301
+ include: [/\.md$/],
9302
+ wrapperClasses: "",
9303
+ headEnabled: false,
9304
+ frontmatter: false,
9305
+ escapeCodeTagInterpolation: false,
9306
+ markdownItOptions: {
9307
+ quotes: `""''`,
9308
+ html: true,
9309
+ xhtmlOut: true,
9310
+ linkify: true,
9311
+ ...mdOptions?.markdownItOptions
9312
+ },
9313
+ ...mdOptions,
9314
+ async markdownItSetup(md) {
9315
+ await useMarkdownItPlugins(md, options, markdownTransformMap);
9316
+ await mdOptions?.markdownItSetup?.(md);
9317
+ },
9318
+ transforms: {
9319
+ ...mdOptions?.transforms,
9320
+ before(code, id) {
9321
+ code = mdOptions?.transforms?.before?.(code, id) ?? code;
9322
+ const match = id.match(regexSlideSourceId);
9323
+ if (!match)
9324
+ return code;
9325
+ const s = new MagicString(code);
9326
+ markdownTransformMap.set(id, s);
9327
+ const ctx = {
9328
+ s,
9329
+ slide: options.data.slides[+match[1] - 1],
9330
+ options
9331
+ };
9332
+ for (const transformer of transformers) {
9333
+ if (!transformer)
9334
+ continue;
9335
+ transformer(ctx);
9336
+ if (!ctx.s.isEmpty())
9337
+ ctx.s.commit();
9475
9338
  }
9339
+ return s.toString();
9476
9340
  }
9477
9341
  }
9478
- ];
9342
+ });
9479
9343
  }
9480
9344
 
9481
9345
  // node/vite/monacoTypes.ts
9482
- import fs8 from "node:fs/promises";
9483
- import { dirname as dirname2, resolve as resolve7 } from "node:path";
9484
- import { slash as slash4 } from "@antfu/utils";
9485
- import fg4 from "fast-glob";
9346
+ import fs7 from "node:fs/promises";
9347
+ import { dirname, resolve as resolve5 } from "node:path";
9348
+ import { slash as slash3 } from "@antfu/utils";
9349
+ import fg3 from "fast-glob";
9486
9350
  import { findDepPkgJsonPath } from "vitefu";
9487
9351
  function createMonacoTypesLoader({ userRoot, utils }) {
9488
9352
  return {
@@ -9503,8 +9367,8 @@ function createMonacoTypesLoader({ userRoot, utils }) {
9503
9367
  const pkgJsonPath = await findDepPkgJsonPath(pkg, importer);
9504
9368
  if (!pkgJsonPath)
9505
9369
  throw new Error(`Package "${pkg}" not found in "${importer}"`);
9506
- const root = slash4(dirname2(pkgJsonPath));
9507
- const pkgJson = JSON.parse(await fs8.readFile(pkgJsonPath, "utf-8"));
9370
+ const root = slash3(dirname(pkgJsonPath));
9371
+ const pkgJson = JSON.parse(await fs7.readFile(pkgJsonPath, "utf-8"));
9508
9372
  let deps = Object.keys(pkgJson.dependencies ?? {});
9509
9373
  deps = deps.filter((pkg2) => !utils.isMonacoTypesIgnored(pkg2));
9510
9374
  return [
@@ -9516,7 +9380,7 @@ function createMonacoTypesLoader({ userRoot, utils }) {
9516
9380
  const query = new URLSearchParams(url.search);
9517
9381
  const root = query.get("root");
9518
9382
  const name = query.get("name");
9519
- const files = await fg4(
9383
+ const files = await fg3(
9520
9384
  [
9521
9385
  "**/*.ts",
9522
9386
  "**/*.mts",
@@ -9533,13 +9397,153 @@ function createMonacoTypesLoader({ userRoot, utils }) {
9533
9397
  return "/** No files found **/";
9534
9398
  return [
9535
9399
  'import { addFile } from "@slidev/client/setup/monaco.ts"',
9536
- ...files.map((file) => `addFile(() => import(${JSON.stringify(`${toAtFS(resolve7(root, file))}?monaco-types&raw`)}), ${JSON.stringify(`node_modules/${name}/${file}`)})`)
9400
+ ...files.map((file) => `addFile(() => import(${JSON.stringify(`${toAtFS(resolve5(root, file))}?monaco-types&raw`)}), ${JSON.stringify(`node_modules/${name}/${file}`)})`)
9537
9401
  ].join("\n");
9538
9402
  }
9539
9403
  }
9540
9404
  };
9541
9405
  }
9542
9406
 
9407
+ // node/vite/remoteAssets.ts
9408
+ async function createRemoteAssetsPlugin({ data: { config }, mode }, pluginOptions) {
9409
+ if (!(config.remoteAssets === true || config.remoteAssets === mode))
9410
+ return;
9411
+ const { VitePluginRemoteAssets, DefaultRules } = await import("vite-plugin-remote-assets");
9412
+ return VitePluginRemoteAssets({
9413
+ resolveMode: (id) => id.endsWith("index.html") ? "relative" : "@fs",
9414
+ awaitDownload: mode === "build",
9415
+ ...pluginOptions.remoteAssets,
9416
+ rules: [
9417
+ ...DefaultRules,
9418
+ {
9419
+ match: /\b(https?:\/\/image.unsplash\.com.*?)(?=[`'")\]])/gi,
9420
+ ext: ".png"
9421
+ },
9422
+ ...pluginOptions.remoteAssets?.rules ?? []
9423
+ ]
9424
+ });
9425
+ }
9426
+
9427
+ // node/vite/serverRef.ts
9428
+ import ServerRef from "vite-plugin-vue-server-ref";
9429
+
9430
+ // node/integrations/drawings.ts
9431
+ import { basename, dirname as dirname2, join as join9, resolve as resolve6 } from "node:path";
9432
+ import fs8 from "fs-extra";
9433
+ import fg4 from "fast-glob";
9434
+ function resolveDrawingsDir(options) {
9435
+ return options.data.config.drawings.persist ? resolve6(
9436
+ dirname2(options.entry),
9437
+ options.data.config.drawings.persist
9438
+ ) : void 0;
9439
+ }
9440
+ async function loadDrawings(options) {
9441
+ const dir = resolveDrawingsDir(options);
9442
+ if (!dir || !fs8.existsSync(dir))
9443
+ return {};
9444
+ const files = await fg4("*.svg", {
9445
+ onlyFiles: true,
9446
+ cwd: dir,
9447
+ absolute: true,
9448
+ suppressErrors: true
9449
+ });
9450
+ const obj = {};
9451
+ await Promise.all(files.map(async (path4) => {
9452
+ const num = +basename(path4, ".svg");
9453
+ if (Number.isNaN(num))
9454
+ return;
9455
+ const content = await fs8.readFile(path4, "utf8");
9456
+ const lines = content.split(/\n/g);
9457
+ obj[num.toString()] = lines.slice(1, -1).join("\n");
9458
+ }));
9459
+ return obj;
9460
+ }
9461
+ async function writeDrawings(options, drawing) {
9462
+ const dir = resolveDrawingsDir(options);
9463
+ if (!dir)
9464
+ return;
9465
+ const width = options.data.config.canvasWidth;
9466
+ const height = Math.round(width / options.data.config.aspectRatio);
9467
+ const SVG_HEAD = `<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">`;
9468
+ await fs8.ensureDir(dir);
9469
+ return Promise.all(
9470
+ Object.entries(drawing).map(async ([key, value]) => {
9471
+ if (!value)
9472
+ return;
9473
+ const svg = `${SVG_HEAD}
9474
+ ${value}
9475
+ </svg>`;
9476
+ await fs8.writeFile(join9(dir, `${key}.svg`), svg, "utf-8");
9477
+ })
9478
+ );
9479
+ }
9480
+
9481
+ // node/vite/serverRef.ts
9482
+ async function createServerRefPlugin(options, pluginOptions) {
9483
+ const drawingData = await loadDrawings(options);
9484
+ return ServerRef({
9485
+ debug: false,
9486
+ // process.env.NODE_ENV === 'development',
9487
+ state: {
9488
+ sync: false,
9489
+ nav: {
9490
+ page: 0,
9491
+ clicks: 0
9492
+ },
9493
+ drawings: drawingData,
9494
+ ...pluginOptions.serverRef?.state
9495
+ },
9496
+ onChanged(key, data, patch, timestamp) {
9497
+ pluginOptions.serverRef?.onChanged?.(key, data, patch, timestamp);
9498
+ if (!options.data.config.drawings.persist)
9499
+ return;
9500
+ if (key === "drawings")
9501
+ writeDrawings(options, patch ?? data);
9502
+ }
9503
+ });
9504
+ }
9505
+
9506
+ // node/vite/unocss.ts
9507
+ import UnoCSS from "unocss/vite";
9508
+
9509
+ // node/setups/unocss.ts
9510
+ import { resolve as resolve7 } from "node:path";
9511
+ import { existsSync as existsSync5 } from "node:fs";
9512
+ import { mergeConfigs } from "unocss";
9513
+ async function setupUnocss({ clientRoot, roots, data }) {
9514
+ function loadFileConfigs(root) {
9515
+ return [
9516
+ resolve7(root, "uno.config.ts"),
9517
+ resolve7(root, "unocss.config.ts")
9518
+ ].map((i) => {
9519
+ if (!existsSync5(i))
9520
+ return void 0;
9521
+ const loaded = loadModule(i);
9522
+ return "default" in loaded ? loaded.default : loaded;
9523
+ });
9524
+ }
9525
+ const configs = [
9526
+ ...loadFileConfigs(clientRoot),
9527
+ ...await loadSetups(roots, "unocss.ts", [], loadFileConfigs)
9528
+ ].filter(Boolean);
9529
+ const config = mergeConfigs(configs);
9530
+ config.theme ||= {};
9531
+ config.theme.fontFamily ||= {};
9532
+ config.theme.fontFamily.sans ||= data.config.fonts.sans.join(",");
9533
+ config.theme.fontFamily.mono ||= data.config.fonts.mono.join(",");
9534
+ config.theme.fontFamily.serif ||= data.config.fonts.serif.join(",");
9535
+ return config;
9536
+ }
9537
+
9538
+ // node/vite/unocss.ts
9539
+ async function createUnocssPlugin(options, pluginOptions) {
9540
+ return UnoCSS({
9541
+ configFile: false,
9542
+ ...await setupUnocss(options),
9543
+ ...pluginOptions.unocss
9544
+ });
9545
+ }
9546
+
9543
9547
  // node/vite/vue.ts
9544
9548
  import Vue from "@vitejs/plugin-vue";
9545
9549
  import VueJsx from "@vitejs/plugin-vue-jsx";
@@ -9573,7 +9577,7 @@ var customElements = /* @__PURE__ */ new Set([
9573
9577
  "munderover",
9574
9578
  "semantics"
9575
9579
  ]);
9576
- async function createVuePlugin(options, pluginOptions) {
9580
+ async function createVuePlugin(_options, pluginOptions) {
9577
9581
  const {
9578
9582
  vue: vueOptions = {},
9579
9583
  vuejsx: vuejsxOptions = {}
@@ -9581,15 +9585,15 @@ async function createVuePlugin(options, pluginOptions) {
9581
9585
  const VuePlugin = Vue({
9582
9586
  include: [/\.vue$/, /\.vue\?vue/, /\.vue\?v=/, /\.md$/, /\.md\?vue/],
9583
9587
  exclude: [],
9588
+ ...vueOptions,
9584
9589
  template: {
9585
9590
  compilerOptions: {
9586
9591
  isCustomElement(tag) {
9587
- return customElements.has(tag);
9592
+ return customElements.has(tag) || vueOptions?.template?.compilerOptions?.isCustomElement?.(tag);
9588
9593
  }
9589
9594
  },
9590
9595
  ...vueOptions?.template
9591
- },
9592
- ...vueOptions
9596
+ }
9593
9597
  });
9594
9598
  const VueJsxPlugin = VueJsx(vuejsxOptions);
9595
9599
  return [
@@ -9598,107 +9602,50 @@ async function createVuePlugin(options, pluginOptions) {
9598
9602
  ];
9599
9603
  }
9600
9604
 
9605
+ // node/vite/staticCopy.ts
9606
+ import { existsSync as existsSync6 } from "node:fs";
9607
+ import { join as join10 } from "node:path";
9608
+ async function createStaticCopyPlugin({ themeRoots, addonRoots }, pluginOptions) {
9609
+ const publicDirs = [...themeRoots, ...addonRoots].map((i) => join10(i, "public")).filter(existsSync6);
9610
+ if (!publicDirs.length)
9611
+ return;
9612
+ const { viteStaticCopy } = await import("vite-plugin-static-copy");
9613
+ return viteStaticCopy({
9614
+ silent: true,
9615
+ targets: publicDirs.map((dir) => ({
9616
+ src: `${dir}/*`,
9617
+ dest: "theme"
9618
+ })),
9619
+ ...pluginOptions.staticCopy
9620
+ });
9621
+ }
9622
+
9601
9623
  // node/vite/index.ts
9602
- async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
9603
- const {
9604
- components: componentsOptions = {},
9605
- icons: iconsOptions = {},
9606
- remoteAssets: remoteAssetsOptions = {},
9607
- serverRef: serverRefOptions = {}
9608
- } = pluginOptions;
9609
- const {
9610
- mode,
9611
- themeRoots,
9612
- addonRoots,
9613
- roots,
9614
- data: { config }
9615
- } = options;
9616
- const drawingData = await loadDrawings(options);
9617
- const publicRoots = [...themeRoots, ...addonRoots].map((i) => join9(i, "public")).filter(existsSync6);
9618
- const plugins = [
9624
+ async function ViteSlidevPlugin(options, pluginOptions = {}, serverOptions = {}) {
9625
+ return Promise.all([
9626
+ createSlidesLoader(options, serverOptions),
9619
9627
  createMarkdownPlugin(options, pluginOptions),
9628
+ createLayoutWrapperPlugin(options),
9629
+ createContextInjectionPlugin(),
9620
9630
  createVuePlugin(options, pluginOptions),
9621
- createSlidesLoader(options, pluginOptions, serverOptions),
9622
- createMonacoWriter(options),
9623
- Components({
9624
- extensions: ["vue", "md", "js", "ts", "jsx", "tsx"],
9625
- dirs: [
9626
- join9(options.clientRoot, "builtin"),
9627
- ...roots.map((i) => join9(i, "components")),
9628
- "src/components",
9629
- "components",
9630
- join9(process2.cwd(), "components")
9631
- ],
9632
- include: [/\.vue$/, /\.vue\?vue/, /\.vue\?v=/, /\.md$/, /\.md\?vue/],
9633
- exclude: [],
9634
- resolvers: [
9635
- IconsResolver({
9636
- prefix: "",
9637
- customCollections: Object.keys(iconsOptions.customCollections || [])
9638
- })
9639
- ],
9640
- dts: false,
9641
- ...componentsOptions
9642
- }),
9643
- Icons({
9644
- defaultClass: "slidev-icon",
9645
- collectionsNodeResolvePath: fileURLToPath4(import.meta.url),
9646
- ...iconsOptions
9647
- }),
9648
- config.remoteAssets === true || config.remoteAssets === mode ? import("vite-plugin-remote-assets").then((r) => r.VitePluginRemoteAssets({
9649
- rules: [
9650
- ...r.DefaultRules,
9651
- {
9652
- match: /\b(https?:\/\/image.unsplash\.com.*?)(?=[`'")\]])/gi,
9653
- ext: ".png"
9654
- }
9655
- ],
9656
- resolveMode: (id) => id.endsWith("index.html") ? "relative" : "@fs",
9657
- awaitDownload: mode === "build",
9658
- ...remoteAssetsOptions
9659
- })) : null,
9660
- ServerRef({
9661
- debug: false,
9662
- // process.env.NODE_ENV === 'development',
9663
- state: {
9664
- sync: false,
9665
- nav: {
9666
- page: 0,
9667
- clicks: 0
9668
- },
9669
- drawings: drawingData,
9670
- ...serverRefOptions.state
9671
- },
9672
- onChanged(key, data, patch, timestamp) {
9673
- serverRefOptions.onChanged && serverRefOptions.onChanged(key, data, patch, timestamp);
9674
- if (!options.data.config.drawings.persist)
9675
- return;
9676
- if (key === "drawings")
9677
- writeDrawings(options, patch ?? data);
9678
- }
9679
- }),
9631
+ createHmrPatchPlugin(),
9632
+ createComponentsPlugin(options, pluginOptions),
9633
+ createIconsPlugin(options, pluginOptions),
9634
+ createRemoteAssetsPlugin(options, pluginOptions),
9635
+ createServerRefPlugin(options, pluginOptions),
9680
9636
  createConfigPlugin(options),
9681
9637
  createMonacoTypesLoader(options),
9638
+ createMonacoWriterPlugin(options),
9682
9639
  createVueCompilerFlagsPlugin(options),
9683
9640
  createUnocssPlugin(options, pluginOptions),
9684
- publicRoots.length ? import("vite-plugin-static-copy").then((r) => r.viteStaticCopy({
9685
- silent: true,
9686
- targets: publicRoots.map((r2) => ({
9687
- src: `${r2}/*`,
9688
- dest: "theme"
9689
- }))
9690
- })) : null,
9691
- options.inspect ? import("vite-plugin-inspect").then((r) => (r.default || r)({
9692
- dev: true,
9693
- build: true
9694
- })) : null
9695
- ];
9696
- return (await Promise.all(plugins)).flat().filter(notNullish2);
9641
+ createStaticCopyPlugin(options, pluginOptions),
9642
+ createInspectPlugin(options, pluginOptions)
9643
+ ]);
9697
9644
  }
9698
9645
 
9699
9646
  // node/commands/shared.ts
9700
9647
  var sharedMd = MarkdownIt({ html: true });
9701
- sharedMd.use(markdownItLink);
9648
+ sharedMd.use(MarkdownItLink);
9702
9649
  function getSlideTitle(data) {
9703
9650
  const tokens = sharedMd.parseInline(data.config.title, {});
9704
9651
  const title = stringifyMarkdownTokens(tokens);
@@ -9711,13 +9658,13 @@ function escapeHtml(unsafe) {
9711
9658
  );
9712
9659
  }
9713
9660
  async function getIndexHtml({ mode, entry, clientRoot, roots, data }) {
9714
- let main = await fs9.readFile(join10(clientRoot, "index.html"), "utf-8");
9661
+ let main = await fs9.readFile(join11(clientRoot, "index.html"), "utf-8");
9715
9662
  let head = "";
9716
9663
  let body = "";
9717
9664
  const { info, author, keywords } = data.headmatter;
9718
9665
  head += [
9719
9666
  `<meta name="slidev:version" content="${version}">`,
9720
- mode === "dev" && `<meta charset="slidev:entry" content="${slash5(entry)}">`,
9667
+ mode === "dev" && `<meta charset="slidev:entry" content="${slash4(entry)}">`,
9721
9668
  `<link rel="icon" href="${data.config.favicon}">`,
9722
9669
  `<title>${getSlideTitle(data)}</title>`,
9723
9670
  info && `<meta name="description" content=${escapeHtml(info)}>`,
@@ -9725,7 +9672,7 @@ async function getIndexHtml({ mode, entry, clientRoot, roots, data }) {
9725
9672
  keywords && `<meta name="keywords" content=${escapeHtml(Array.isArray(keywords) ? keywords.join(", ") : keywords)}>`
9726
9673
  ].filter(Boolean).join("\n");
9727
9674
  for (const root of roots) {
9728
- const path4 = join10(root, "index.html");
9675
+ const path4 = join11(root, "index.html");
9729
9676
  if (!existsSync7(path4))
9730
9677
  continue;
9731
9678
  const index = await fs9.readFile(path4, "utf-8");
@@ -9739,7 +9686,7 @@ ${(index.match(/<body>([\s\S]*?)<\/body>/i)?.[1] || "").trim()}`;
9739
9686
  if (data.config.fonts.webfonts.length && data.config.fonts.provider !== "none")
9740
9687
  head += `
9741
9688
  <link rel="stylesheet" href="${generateGoogleFontsUrl(data.config.fonts)}" type="text/css">`;
9742
- main = main.replace("__ENTRY__", toAtFS(join10(clientRoot, "main.ts"))).replace("<!-- head -->", head).replace("<!-- body -->", body);
9689
+ main = main.replace("__ENTRY__", toAtFS(join11(clientRoot, "main.ts"))).replace("<!-- head -->", head).replace("<!-- body -->", body);
9743
9690
  return main;
9744
9691
  }
9745
9692
  async function resolveViteConfigs(options, baseConfig, overrideConfigs, command, serverOptions) {
@@ -9747,7 +9694,7 @@ async function resolveViteConfigs(options, baseConfig, overrideConfigs, command,
9747
9694
  mode: command === "build" ? "production" : "development",
9748
9695
  command
9749
9696
  };
9750
- const files = options.roots.map((i) => join10(i, "vite.config.ts"));
9697
+ const files = options.roots.map((i) => join11(i, "vite.config.ts"));
9751
9698
  for (const file of files) {
9752
9699
  if (!existsSync7(file))
9753
9700
  continue;
@@ -9760,9 +9707,7 @@ async function resolveViteConfigs(options, baseConfig, overrideConfigs, command,
9760
9707
  baseConfig = mergeConfig2(baseConfig, {
9761
9708
  configFile: false,
9762
9709
  root: options.userRoot,
9763
- plugins: [
9764
- await ViteSlidevPlugin(options, baseConfig.slidev || {}, serverOptions)
9765
- ],
9710
+ plugins: await ViteSlidevPlugin(options, baseConfig.slidev, serverOptions),
9766
9711
  define: {
9767
9712
  // Fixes Vue production mode breaking PDF Export #1245
9768
9713
  __VUE_PROD_DEVTOOLS__: false
@@ -9775,11 +9720,11 @@ export {
9775
9720
  version,
9776
9721
  getIndexHtml,
9777
9722
  resolveViteConfigs,
9778
- loadSetups,
9779
9723
  parser,
9780
9724
  resolveTheme,
9781
9725
  getThemeMeta,
9782
9726
  resolveAddons,
9727
+ loadSetups,
9783
9728
  resolveOptions,
9784
9729
  createDataUtils,
9785
9730
  ViteSlidevPlugin