@slidev/cli 0.49.17 → 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.17";
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,71 +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 Icons from "unplugin-icons/vite";
7261
- import IconsResolver from "unplugin-icons/resolver";
7262
- import Components from "unplugin-vue-components/vite";
7263
- import ServerRef from "vite-plugin-vue-server-ref";
7264
- import { notNullish as notNullish2 } from "@antfu/utils";
7265
-
7266
- // node/integrations/drawings.ts
7267
- import { basename, dirname, join, resolve } from "node:path";
7268
- import fs from "fs-extra";
7269
- import fg from "fast-glob";
7270
- function resolveDrawingsDir(options) {
7271
- return options.data.config.drawings.persist ? resolve(
7272
- dirname(options.entry),
7273
- options.data.config.drawings.persist
7274
- ) : void 0;
7275
- }
7276
- async function loadDrawings(options) {
7277
- const dir = resolveDrawingsDir(options);
7278
- if (!dir || !fs.existsSync(dir))
7279
- return {};
7280
- const files = await fg("*.svg", {
7281
- onlyFiles: true,
7282
- cwd: dir,
7283
- absolute: true,
7284
- 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
+ });
7285
7281
  });
7286
- const obj = {};
7287
- await Promise.all(files.map(async (path4) => {
7288
- const num = +basename(path4, ".svg");
7289
- if (Number.isNaN(num))
7290
- return;
7291
- const content = await fs.readFile(path4, "utf8");
7292
- const lines = content.split(/\n/g);
7293
- obj[num.toString()] = lines.slice(1, -1).join("\n");
7294
- }));
7295
- return obj;
7296
- }
7297
- async function writeDrawings(options, drawing) {
7298
- const dir = resolveDrawingsDir(options);
7299
- if (!dir)
7300
- return;
7301
- const width = options.data.config.canvasWidth;
7302
- const height = Math.round(width / options.data.config.aspectRatio);
7303
- const SVG_HEAD = `<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">`;
7304
- await fs.ensureDir(dir);
7305
- return Promise.all(
7306
- Object.entries(drawing).map(async ([key, value]) => {
7307
- if (!value)
7308
- return;
7309
- const svg = `${SVG_HEAD}
7310
- ${value}
7311
- </svg>`;
7312
- await fs.writeFile(join(dir, `${key}.svg`), svg, "utf-8");
7313
- })
7314
- );
7315
7282
  }
7316
7283
 
7284
+ // node/vite/compilerFlagsVue.ts
7285
+ import { objectEntries } from "@antfu/utils";
7286
+
7317
7287
  // node/vite/extendConfig.ts
7318
- import { join as join2 } from "node:path";
7319
- import { fileURLToPath, pathToFileURL } from "node:url";
7288
+ import { join } from "node:path";
7289
+ import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
7320
7290
  import { mergeConfig } from "vite";
7321
7291
  import { slash, uniq } from "@antfu/utils";
7322
7292
  import { createResolve } from "mlly";
@@ -7397,7 +7367,7 @@ function createConfigPlugin(options) {
7397
7367
  },
7398
7368
  ...isInstalledGlobally.value ? await Promise.all(INCLUDE_GLOBAL.map(async (dep) => ({
7399
7369
  find: dep,
7400
- replacement: fileURLToPath(await resolveClientDep(dep))
7370
+ replacement: fileURLToPath2(await resolveClientDep(dep))
7401
7371
  }))) : []
7402
7372
  ],
7403
7373
  dedupe: ["vue"]
@@ -7429,7 +7399,7 @@ function createConfigPlugin(options) {
7429
7399
  ])
7430
7400
  }
7431
7401
  },
7432
- publicDir: join2(options.userRoot, "public"),
7402
+ publicDir: join(options.userRoot, "public"),
7433
7403
  build: {
7434
7404
  rollupOptions: {
7435
7405
  output: {
@@ -7462,7 +7432,7 @@ function createConfigPlugin(options) {
7462
7432
  return id.includes("/@slidev/") || id.includes("/slidev/packages/client/") || id.includes("/@vueuse/");
7463
7433
  }
7464
7434
  if (isInstalledGlobally.value) {
7465
- injection.cacheDir = join2(options.cliRoot, "node_modules/.vite");
7435
+ injection.cacheDir = join(options.cliRoot, "node_modules/.vite");
7466
7436
  injection.root = options.cliRoot;
7467
7437
  }
7468
7438
  return mergeConfig(injection, config);
@@ -7498,6 +7468,204 @@ function getDefine(options) {
7498
7468
  };
7499
7469
  }
7500
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
+
7501
7669
  // node/vite/loaders.ts
7502
7670
  import { notNullish, range } from "@antfu/utils";
7503
7671
  import * as parser2 from "@slidev/parser/fs";
@@ -7507,14 +7675,14 @@ import equal from "fast-deep-equal";
7507
7675
  import { isString } from "@antfu/utils";
7508
7676
  var templateConfigs = {
7509
7677
  id: "/@slidev/configs",
7510
- getContent: async ({ data, remote }, { md }) => {
7678
+ getContent({ data, remote }) {
7511
7679
  const config = {
7512
7680
  ...data.config,
7513
7681
  remote,
7514
7682
  slidesTitle: getSlideTitle(data)
7515
7683
  };
7516
7684
  if (isString(config.info))
7517
- config.info = md.render(config.info);
7685
+ config.info = sharedMd.render(config.info);
7518
7686
  return `export default ${JSON.stringify(config)}`;
7519
7687
  }
7520
7688
  };
@@ -7531,7 +7699,7 @@ var templateLegacyRoutes = {
7531
7699
  };
7532
7700
  var templateLegacyTitles = {
7533
7701
  id: "/@slidev/titles.md",
7534
- async getContent() {
7702
+ getContent() {
7535
7703
  return `
7536
7704
  <script setup lang="ts">
7537
7705
  import TitleRenderer from '#slidev/title-renderer'
@@ -7600,10 +7768,10 @@ export default {
7600
7768
  import { objectMap } from "@antfu/utils";
7601
7769
  var templateLayouts = {
7602
7770
  id: "/@slidev/layouts",
7603
- async getContent(_, { getLayouts }) {
7771
+ getContent({ utils }) {
7604
7772
  const imports = [];
7605
7773
  const layouts = objectMap(
7606
- await getLayouts(),
7774
+ utils.getLayouts(),
7607
7775
  (k, v) => {
7608
7776
  imports.push(`import __layout_${k} from "${toAtFS(v)}"`);
7609
7777
  return [k, `__layout_${k}`];
@@ -7619,19 +7787,19 @@ ${Object.entries(layouts).map(([k, v]) => `"${k}": ${v}`).join(",\n")}
7619
7787
  };
7620
7788
 
7621
7789
  // node/virtual/monaco-deps.ts
7622
- import { resolve as resolve2 } from "node:path";
7790
+ import { resolve } from "node:path";
7623
7791
  import { uniq as uniq2 } from "@antfu/utils";
7624
7792
  var templateMonacoRunDeps = {
7625
7793
  id: "/@slidev/monaco-run-deps",
7626
- getContent: async ({ userRoot, data }, _ctx, pluginCtx) => {
7794
+ async getContent({ userRoot, data }) {
7627
7795
  if (!data.features.monaco)
7628
7796
  return "";
7629
7797
  const deps = uniq2(data.features.monaco.deps.concat(data.config.monacoTypesAdditionalPackages));
7630
- const importerPath = resolve2(userRoot, "./snippets/__importer__.ts");
7798
+ const importerPath = resolve(userRoot, "./snippets/__importer__.ts");
7631
7799
  let result = "";
7632
7800
  for (let i = 0; i < deps.length; i++) {
7633
7801
  const specifier = deps[i];
7634
- const resolved = await pluginCtx.resolve(specifier, importerPath);
7802
+ const resolved = await this.resolve(specifier, importerPath);
7635
7803
  if (!resolved)
7636
7804
  continue;
7637
7805
  result += `import * as vendored${i} from ${JSON.stringify(resolved.id)}
@@ -7648,8 +7816,8 @@ var templateMonacoRunDeps = {
7648
7816
 
7649
7817
  // node/virtual/monaco-types.ts
7650
7818
  import { builtinModules } from "node:module";
7651
- import { join as join5, resolve as resolve3 } from "node:path";
7652
- import fg2 from "fast-glob";
7819
+ import { join as join5, resolve as resolve2 } from "node:path";
7820
+ import fg from "fast-glob";
7653
7821
  import { uniq as uniq3 } from "@antfu/utils";
7654
7822
  var templateMonacoTypes = {
7655
7823
  id: "/@slidev/monaco-types",
@@ -7657,10 +7825,10 @@ var templateMonacoTypes = {
7657
7825
  if (!data.features.monaco)
7658
7826
  return "";
7659
7827
  const typesRoot = join5(userRoot, "snippets");
7660
- const files = await fg2(["**/*.ts", "**/*.mts", "**/*.cts"], { cwd: typesRoot });
7828
+ const files = await fg(["**/*.ts", "**/*.mts", "**/*.cts"], { cwd: typesRoot });
7661
7829
  let result = 'import { addFile } from "@slidev/client/setup/monaco.ts"\n';
7662
7830
  for (const file of files) {
7663
- const url = `${toAtFS(resolve3(typesRoot, file))}?monaco-types&raw`;
7831
+ const url = `${toAtFS(resolve2(typesRoot, file))}?monaco-types&raw`;
7664
7832
  result += `addFile(() => import(${JSON.stringify(url)}), ${JSON.stringify(file)})
7665
7833
  `;
7666
7834
  }
@@ -7716,68 +7884,12 @@ function createSetupTemplate(name) {
7716
7884
  var setupModules = ["shiki", "code-runners", "monaco", "mermaid", "main", "root", "routes", "shortcuts", "context-menu"];
7717
7885
  var templateSetups = setupModules.map(createSetupTemplate);
7718
7886
 
7719
- // node/setups/shiki.ts
7720
- import fs3 from "node:fs/promises";
7721
-
7722
- // node/setups/load.ts
7723
- import { resolve as resolve4 } from "node:path";
7724
- import { fileURLToPath as fileURLToPath2 } from "node:url";
7725
- import fs2 from "fs-extra";
7726
- import { deepMergeWithArray } from "@antfu/utils";
7727
- import jiti from "jiti";
7728
- async function loadSetups(clientRoot, roots, name, arg, initial, merge = true) {
7729
- let returns = initial;
7730
- for (const root of [clientRoot, ...roots].reverse()) {
7731
- const path4 = resolve4(root, "setup", name);
7732
- if (fs2.existsSync(path4)) {
7733
- const { default: setup } = jiti(fileURLToPath2(import.meta.url))(path4);
7734
- const result = await setup(arg);
7735
- if (result !== null) {
7736
- returns = typeof merge === "function" ? merge(returns, result) : merge ? deepMergeWithArray(returns, result) : result;
7737
- }
7738
- }
7739
- }
7740
- return returns;
7741
- }
7742
-
7743
- // node/setups/shiki.ts
7744
- async function loadShikiSetups(clientRoot, roots) {
7745
- const result = await loadSetups(
7746
- clientRoot,
7747
- roots,
7748
- "shiki.ts",
7749
- {
7750
- /** @deprecated */
7751
- async loadTheme(path4) {
7752
- 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.");
7753
- return JSON.parse(await fs3.readFile(path4, "utf-8"));
7754
- }
7755
- },
7756
- {},
7757
- false
7758
- );
7759
- if ("theme" in result && "themes" in result)
7760
- delete result.theme;
7761
- if (result.theme && typeof result.theme !== "string" && !result.theme.name && !result.theme.tokenColors) {
7762
- result.themes = result.theme;
7763
- delete result.theme;
7764
- }
7765
- if (!result.theme && !result.themes) {
7766
- result.themes = {
7767
- dark: "vitesse-dark",
7768
- light: "vitesse-light"
7769
- };
7770
- }
7771
- if (result.themes)
7772
- result.defaultColor = false;
7773
- return result;
7774
- }
7775
-
7776
7887
  // node/virtual/shiki.ts
7888
+ import { uniq as uniq4 } from "@antfu/utils";
7777
7889
  var templateShiki = {
7778
7890
  id: "/@slidev/shiki",
7779
- getContent: async ({ clientRoot, roots }) => {
7780
- const options = await loadShikiSetups(clientRoot, roots);
7891
+ getContent: async ({ utils }) => {
7892
+ const options = utils.shikiOptions;
7781
7893
  const langs = await resolveLangs(options.langs || ["markdown", "vue", "javascript", "typescript", "html", "css"]);
7782
7894
  const resolvedThemeOptions = "themes" in options ? {
7783
7895
  themes: Object.fromEntries(await Promise.all(
@@ -7789,12 +7901,12 @@ var templateShiki = {
7789
7901
  const themes = resolvedThemeOptions.themes ? Object.values(resolvedThemeOptions.themes) : [resolvedThemeOptions.theme];
7790
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 };
7791
7903
  async function normalizeGetter(p) {
7792
- 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;
7793
7906
  }
7794
7907
  async function resolveLangs(langs2) {
7795
- return Array.from(new Set((await Promise.all(
7796
- langs2.map(async (lang) => await normalizeGetter(lang).then((r) => Array.isArray(r) ? r : [r]))
7797
- )).flat()));
7908
+ const awaited = await Promise.all(langs2.map((lang) => normalizeGetter(lang)));
7909
+ return uniq4(awaited.flat());
7798
7910
  }
7799
7911
  async function resolveTheme2(theme) {
7800
7912
  return typeof theme === "string" ? theme : await normalizeGetter(theme);
@@ -7837,8 +7949,8 @@ var templateShiki = {
7837
7949
  var VIRTUAL_SLIDE_PREFIX = "/@slidev/slides/";
7838
7950
  var templateSlides = {
7839
7951
  id: "/@slidev/slides",
7840
- async getContent({ data }, { getLayouts }) {
7841
- const layouts = await getLayouts();
7952
+ getContent({ data, utils }) {
7953
+ const layouts = utils.getLayouts();
7842
7954
  const statements = [
7843
7955
  `import { defineAsyncComponent, shallowRef } from 'vue'`,
7844
7956
  `import SlideError from '${layouts.error}'`,
@@ -7885,7 +7997,7 @@ import { join as join7 } from "node:path";
7885
7997
  import { existsSync as existsSync4 } from "node:fs";
7886
7998
  var templateStyle = {
7887
7999
  id: "/@slidev/styles",
7888
- getContent: async ({ data, clientRoot, roots }) => {
8000
+ async getContent({ data, clientRoot, roots }) {
7889
8001
  function resolveUrlOfClient(name) {
7890
8002
  return toAtFS(join7(clientRoot, name));
7891
8003
  }
@@ -7934,7 +8046,7 @@ var templateStyle = {
7934
8046
  // node/virtual/titles.ts
7935
8047
  var templateTitleRendererMd = {
7936
8048
  id: "/@slidev/title-renderer.md",
7937
- async getContent({ data }) {
8049
+ getContent({ data }) {
7938
8050
  const lines = data.slides.map(({ title }, i) => `<template ${i === 0 ? "v-if" : "v-else-if"}="no === ${i + 1}">
7939
8051
 
7940
8052
  ${title}
@@ -7980,17 +8092,17 @@ var templates = [
7980
8092
 
7981
8093
  // node/options.ts
7982
8094
  import path from "node:path";
7983
- import { uniq as uniq4 } from "@antfu/utils";
8095
+ import { uniq as uniq5 } from "@antfu/utils";
7984
8096
  import Debug from "debug";
7985
8097
  import mm from "micromatch";
7986
- import fg3 from "fast-glob";
8098
+ import fg2 from "fast-glob";
7987
8099
 
7988
8100
  // node/parser.ts
7989
8101
  import * as parser from "@slidev/parser/fs";
7990
8102
 
7991
8103
  // node/integrations/themes.ts
7992
8104
  import { join as join8 } from "node:path";
7993
- import fs4 from "fs-extra";
8105
+ import fs from "fs-extra";
7994
8106
  import { satisfies } from "semver";
7995
8107
  var officialThemes = {
7996
8108
  "none": "",
@@ -8003,17 +8115,17 @@ var officialThemes = {
8003
8115
  var resolveTheme = createResolver("theme", officialThemes);
8004
8116
  async function getThemeMeta(name, root) {
8005
8117
  const path4 = join8(root, "package.json");
8006
- if (!fs4.existsSync(path4))
8118
+ if (!fs.existsSync(path4))
8007
8119
  return {};
8008
- const { slidev = {}, engines = {} } = await fs4.readJSON(path4);
8120
+ const { slidev = {}, engines = {} } = await fs.readJSON(path4);
8009
8121
  if (engines.slidev && !satisfies(version, engines.slidev, { includePrerelease: true }))
8010
8122
  throw new Error(`[slidev] theme "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
8011
8123
  return slidev;
8012
8124
  }
8013
8125
 
8014
8126
  // node/integrations/addons.ts
8015
- import { resolve as resolve5 } from "node:path";
8016
- import fs5 from "fs-extra";
8127
+ import { resolve as resolve3 } from "node:path";
8128
+ import fs2 from "fs-extra";
8017
8129
  import { satisfies as satisfies2 } from "semver";
8018
8130
  async function resolveAddons(addonsInConfig) {
8019
8131
  const { userRoot, userPkgJson } = await getRoots();
@@ -8024,7 +8136,7 @@ async function resolveAddons(addonsInConfig) {
8024
8136
  if (!pkgRoot)
8025
8137
  return;
8026
8138
  resolved.push(pkgRoot);
8027
- const { slidev = {}, engines = {} } = await fs5.readJSON(resolve5(pkgRoot, "package.json"));
8139
+ const { slidev = {}, engines = {} } = await fs2.readJSON(resolve3(pkgRoot, "package.json"));
8028
8140
  if (engines.slidev && !satisfies2(version, engines.slidev, { includePrerelease: true }))
8029
8141
  throw new Error(`[slidev] addon "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
8030
8142
  if (Array.isArray(slidev.addons))
@@ -8037,23 +8149,86 @@ async function resolveAddons(addonsInConfig) {
8037
8149
  return resolved;
8038
8150
  }
8039
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
+
8040
8215
  // node/options.ts
8041
8216
  var debug = Debug("slidev:options");
8042
- async function resolveOptions(options, mode) {
8043
- const entry = await resolveEntry(options.entry);
8217
+ async function resolveOptions(entryOptions, mode) {
8218
+ const entry = await resolveEntry(entryOptions.entry);
8044
8219
  const rootsInfo = await getRoots(entry);
8045
8220
  const loaded = await parser.load(rootsInfo.userRoot, entry, void 0, mode);
8046
- let themeRaw = options.theme || loaded.headmatter.theme;
8221
+ let themeRaw = entryOptions.theme || loaded.headmatter.theme;
8047
8222
  themeRaw = themeRaw === null ? "none" : themeRaw || "default";
8048
8223
  const [theme, themeRoot] = await resolveTheme(themeRaw, entry);
8049
8224
  const themeRoots = themeRoot ? [themeRoot] : [];
8050
8225
  const themeMeta = themeRoot ? await getThemeMeta(theme, themeRoot) : void 0;
8051
- const config = parser.resolveConfig(loaded.headmatter, themeMeta, options.entry);
8226
+ const config = parser.resolveConfig(loaded.headmatter, themeMeta, entryOptions.entry);
8052
8227
  const addonRoots = await resolveAddons(config.addons);
8053
- const roots = uniq4([...themeRoots, ...addonRoots, rootsInfo.userRoot]);
8228
+ const roots = uniq5([...themeRoots, ...addonRoots, rootsInfo.userRoot]);
8054
8229
  debug({
8055
8230
  ...rootsInfo,
8056
- ...options,
8231
+ ...entryOptions,
8057
8232
  config,
8058
8233
  mode,
8059
8234
  entry,
@@ -8070,7 +8245,7 @@ async function resolveOptions(options, mode) {
8070
8245
  };
8071
8246
  const resolved = {
8072
8247
  ...rootsInfo,
8073
- ...options,
8248
+ ...entryOptions,
8074
8249
  data,
8075
8250
  mode,
8076
8251
  entry,
@@ -8079,23 +8254,24 @@ async function resolveOptions(options, mode) {
8079
8254
  themeRoots,
8080
8255
  addonRoots,
8081
8256
  roots,
8082
- utils: createDataUtils(data, rootsInfo.clientRoot, roots)
8257
+ utils: await createDataUtils(data, rootsInfo.clientRoot, roots)
8083
8258
  };
8084
8259
  return resolved;
8085
8260
  }
8086
- function createDataUtils(data, clientRoot, roots) {
8261
+ async function createDataUtils(data, clientRoot, roots) {
8087
8262
  const monacoTypesIgnorePackagesMatches = (data.config.monacoTypesIgnorePackages || []).map((i) => mm.matcher(i));
8088
8263
  let _layouts_cache_time = 0;
8089
8264
  let _layouts_cache = {};
8090
8265
  return {
8266
+ ...await setupShiki(roots),
8091
8267
  isMonacoTypesIgnored: (pkg) => monacoTypesIgnorePackagesMatches.some((i) => i(pkg)),
8092
- getLayouts: async () => {
8268
+ getLayouts: () => {
8093
8269
  const now = Date.now();
8094
8270
  if (now - _layouts_cache_time < 2e3)
8095
8271
  return _layouts_cache;
8096
8272
  const layouts = {};
8097
8273
  for (const root of [clientRoot, ...roots]) {
8098
- const layoutPaths = await fg3("layouts/**/*.{vue,ts}", {
8274
+ const layoutPaths = fg2.sync("layouts/**/*.{vue,ts}", {
8099
8275
  cwd: root,
8100
8276
  absolute: true,
8101
8277
  suppressErrors: true
@@ -8112,29 +8288,7 @@ function createDataUtils(data, clientRoot, roots) {
8112
8288
  };
8113
8289
  }
8114
8290
 
8115
- // node/vite/common.ts
8116
- var regexSlideReqPath = /^\/__slidev\/slides\/(\d+)\.json$/;
8117
- var regexSlideFacadeId = /^\/@slidev\/slides\/(\d+)\/(md|frontmatter)($|\?)/;
8118
- var regexSlideSourceId = /__slidev_(\d+)\.(md|frontmatter)$/;
8119
- var templateInjectionMarker = "/* @slidev-injection */";
8120
- var templateImportContextUtils = `import { useSlideContext as _useSlideContext, frontmatterToProps as _frontmatterToProps } from "@slidev/client/context.ts"`;
8121
- var templateInitContext = `const { $slidev, $nav, $clicksContext, $clicks, $page, $renderContext, $frontmatter } = _useSlideContext()`;
8122
-
8123
8291
  // node/vite/loaders.ts
8124
- function getBodyJson(req) {
8125
- return new Promise((resolve8, reject) => {
8126
- let body = "";
8127
- req.on("data", (chunk) => body += chunk);
8128
- req.on("error", reject);
8129
- req.on("end", () => {
8130
- try {
8131
- resolve8(JSON.parse(body) || {});
8132
- } catch (e) {
8133
- reject(e);
8134
- }
8135
- });
8136
- });
8137
- }
8138
8292
  function renderNote(text = "") {
8139
8293
  let clickCount = 0;
8140
8294
  const html = sharedMd.render(
@@ -8156,10 +8310,6 @@ function createSlidesLoader(options, serverOptions) {
8156
8310
  let server;
8157
8311
  let skipHmr = null;
8158
8312
  const { data, clientRoot, roots, mode, utils } = options;
8159
- const templateCtx = {
8160
- md: sharedMd,
8161
- getLayouts: utils.getLayouts
8162
- };
8163
8313
  function getSourceId(index, type) {
8164
8314
  return `${data.slides[index].source.filepath}__slidev_${index + 1}.${type}`;
8165
8315
  }
@@ -8310,7 +8460,7 @@ function createSlidesLoader(options, serverOptions) {
8310
8460
  const template = templates.find((i) => i.id === id);
8311
8461
  if (template) {
8312
8462
  return {
8313
- code: await template.getContent(options, templateCtx, this),
8463
+ code: await template.getContent.call(this, options),
8314
8464
  map: { mappings: "" }
8315
8465
  };
8316
8466
  }
@@ -8394,562 +8544,167 @@ function createSlidesLoader(options, serverOptions) {
8394
8544
  };
8395
8545
  }
8396
8546
 
8397
- // node/vite/unocss.ts
8398
- import { resolve as resolve6 } from "node:path";
8399
- import { existsSync as existsSync5 } from "node:fs";
8400
- import { fileURLToPath as fileURLToPath3 } from "node:url";
8401
- import { uniq as uniq5 } from "@antfu/utils";
8402
- import { mergeConfigs } from "unocss";
8403
- import jiti2 from "jiti";
8404
- import UnoCSS from "unocss/vite";
8405
- async function createUnocssPlugin({ themeRoots, addonRoots, clientRoot, roots, data, userRoot }, { unocss: unoOptions = {} }) {
8406
- const configFiles = uniq5([
8407
- resolve6(userRoot, "uno.config.ts"),
8408
- resolve6(userRoot, "unocss.config.ts"),
8409
- ...themeRoots.map((i) => `${i}/uno.config.ts`),
8410
- ...themeRoots.map((i) => `${i}/unocss.config.ts`),
8411
- ...addonRoots.map((i) => `${i}/uno.config.ts`),
8412
- ...addonRoots.map((i) => `${i}/unocss.config.ts`),
8413
- resolve6(clientRoot, "uno.config.ts"),
8414
- resolve6(clientRoot, "unocss.config.ts")
8415
- ]).filter((i) => existsSync5(i));
8416
- const configs = configFiles.map((i) => {
8417
- const loaded = jiti2(fileURLToPath3(import.meta.url))(i);
8418
- const config2 = "default" in loaded ? loaded.default : loaded;
8419
- return config2;
8420
- }).filter(Boolean);
8421
- configs.reverse();
8422
- let config = mergeConfigs([...configs, unoOptions]);
8423
- config = await loadSetups(clientRoot, roots, "unocss.ts", {}, config, (a, b) => mergeConfigs([a, b]));
8424
- config.theme ||= {};
8425
- config.theme.fontFamily ||= {};
8426
- config.theme.fontFamily.sans ||= data.config.fonts.sans.join(",");
8427
- config.theme.fontFamily.mono ||= data.config.fonts.mono.join(",");
8428
- config.theme.fontFamily.serif ||= data.config.fonts.serif.join(",");
8429
- return UnoCSS({
8430
- configFile: false,
8431
- configDeps: configFiles,
8432
- ...config
8433
- });
8434
- }
8435
-
8436
8547
  // node/vite/markdown.ts
8437
8548
  import Markdown from "unplugin-vue-markdown/vite";
8438
- import { isTruthy, slash as slash3 } from "@antfu/utils";
8439
-
8440
- // ../../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
8441
- var SpecialCharacters;
8442
- (function(SpecialCharacters2) {
8443
- SpecialCharacters2[SpecialCharacters2["EXCLAMATION_MARK"] = 33] = "EXCLAMATION_MARK";
8444
- SpecialCharacters2[SpecialCharacters2["OPENING_BRACKET"] = 91] = "OPENING_BRACKET";
8445
- SpecialCharacters2[SpecialCharacters2["OPENING_PARENTHESIS"] = 40] = "OPENING_PARENTHESIS";
8446
- SpecialCharacters2[SpecialCharacters2["WHITESPACE"] = 32] = "WHITESPACE";
8447
- SpecialCharacters2[SpecialCharacters2["NEW_LINE"] = 10] = "NEW_LINE";
8448
- SpecialCharacters2[SpecialCharacters2["EQUALS"] = 61] = "EQUALS";
8449
- SpecialCharacters2[SpecialCharacters2["LOWER_CASE_X"] = 120] = "LOWER_CASE_X";
8450
- SpecialCharacters2[SpecialCharacters2["NUMBER_ZERO"] = 48] = "NUMBER_ZERO";
8451
- SpecialCharacters2[SpecialCharacters2["NUMBER_NINE"] = 57] = "NUMBER_NINE";
8452
- SpecialCharacters2[SpecialCharacters2["PERCENTAGE"] = 37] = "PERCENTAGE";
8453
- SpecialCharacters2[SpecialCharacters2["CLOSING_PARENTHESIS"] = 41] = "CLOSING_PARENTHESIS";
8454
- })(SpecialCharacters || (SpecialCharacters = {}));
8549
+ import MagicString from "magic-string-stack";
8455
8550
 
8456
- // ../../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
8457
- import Token from "markdown-it/lib/token.mjs";
8458
- var checkboxRegex = /^ *\[([\sx])] /i;
8459
- function taskLists(md, options = { enabled: false, label: false, lineNumber: false }) {
8460
- md.core.ruler.after("inline", "task-lists", (state) => processToken(state, options));
8461
- md.renderer.rules.taskListItemCheckbox = (tokens) => {
8462
- const token = tokens[0];
8463
- const checkedAttribute = token.attrGet("checked") ? 'checked="" ' : "";
8464
- const disabledAttribute = token.attrGet("disabled") ? 'disabled="" ' : "";
8465
- const line = token.attrGet("line");
8466
- const idAttribute = `id="${token.attrGet("id")}" `;
8467
- const dataLineAttribute = line && options.lineNumber ? `data-line="${line}" ` : "";
8468
- return `<input class="task-list-item-checkbox" type="checkbox" ${checkedAttribute}${disabledAttribute}${dataLineAttribute}${idAttribute}/>`;
8469
- };
8470
- md.renderer.rules.taskListItemLabel_close = () => {
8471
- return "</label>";
8472
- };
8473
- md.renderer.rules.taskListItemLabel_open = (tokens) => {
8474
- const token = tokens[0];
8475
- const id = token.attrGet("id");
8476
- 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: []
8477
8559
  };
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);
8565
+ }
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);
8571
+ }
8572
+ return result;
8478
8573
  }
8479
- function processToken(state, options) {
8480
- const allTokens = state.tokens;
8481
- for (let i = 2; i < allTokens.length; i++) {
8482
- if (!isTodoItem(allTokens, i)) {
8483
- continue;
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>`;
8484
8592
  }
8485
- todoify(allTokens[i], options);
8486
- allTokens[i - 2].attrJoin("class", `task-list-item ${options.enabled ? " enabled" : ""}`);
8487
- const parentToken = findParentToken(allTokens, i - 2);
8488
- if (parentToken) {
8489
- const classes = parentToken.attrGet("class") ?? "";
8490
- if (!classes.match(/(^| )contains-task-list/)) {
8491
- parentToken.attrJoin("class", "contains-task-list");
8492
- }
8593
+ );
8594
+ }
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}`;
8493
8608
  }
8494
- }
8495
- return false;
8609
+ );
8496
8610
  }
8497
- function findParentToken(tokens, index) {
8498
- const targetLevel = tokens[index].level - 1;
8499
- for (let currentTokenIndex = index - 1; currentTokenIndex >= 0; currentTokenIndex--) {
8500
- if (tokens[currentTokenIndex].level === targetLevel) {
8501
- return tokens[currentTokenIndex];
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
+ `;
8502
8627
  }
8503
- }
8504
- return void 0;
8628
+ );
8505
8629
  }
8506
- function isTodoItem(tokens, index) {
8507
- return isInline(tokens[index]) && isParagraph(tokens[index - 1]) && isListItem(tokens[index - 2]) && startsWithTodoMarkdown(tokens[index]);
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;
8508
8637
  }
8509
- function todoify(token, options) {
8510
- if (token.children == null) {
8511
- return;
8512
- }
8513
- const id = generateIdForToken(token);
8514
- token.children.splice(0, 0, createCheckboxToken(token, options.enabled, id));
8515
- token.children[1].content = token.children[1].content.replace(checkboxRegex, "");
8516
- if (options.label) {
8517
- token.children.splice(1, 0, createLabelBeginToken(id));
8518
- token.children.push(createLabelEndToken());
8519
- }
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
+ );
8520
8658
  }
8521
- function generateIdForToken(token) {
8522
- if (token.map) {
8523
- return `task-item-${token.map[0]}`;
8524
- } else {
8525
- return `task-item-${Math.ceil(Math.random() * (1e4 * 1e3) - 1e3)}`;
8526
- }
8527
- }
8528
- function createCheckboxToken(token, enabled, id) {
8529
- const checkbox = new Token("taskListItemCheckbox", "", 0);
8530
- if (!enabled) {
8531
- checkbox.attrSet("disabled", "true");
8532
- }
8533
- if (token.map) {
8534
- checkbox.attrSet("line", token.map[0].toString());
8535
- }
8536
- checkbox.attrSet("id", id);
8537
- const checkboxRegexResult = checkboxRegex.exec(token.content);
8538
- const isChecked = checkboxRegexResult?.[1].toLowerCase() === "x";
8539
- if (isChecked) {
8540
- checkbox.attrSet("checked", "true");
8541
- }
8542
- return checkbox;
8543
- }
8544
- function createLabelBeginToken(id) {
8545
- const labelBeginToken = new Token("taskListItemLabel_open", "", 1);
8546
- labelBeginToken.attrSet("id", id);
8547
- return labelBeginToken;
8548
- }
8549
- function createLabelEndToken() {
8550
- return new Token("taskListItemLabel_close", "", -1);
8551
- }
8552
- function isInline(token) {
8553
- return token.type === "inline";
8554
- }
8555
- function isParagraph(token) {
8556
- return token.type === "paragraph_open";
8557
- }
8558
- function isListItem(token) {
8559
- return token.type === "list_item_open";
8560
- }
8561
- function startsWithTodoMarkdown(token) {
8562
- return checkboxRegex.test(token.content);
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
+ );
8563
8672
  }
8564
8673
 
8565
- // node/vite/markdown.ts
8566
- import MarkdownItMdc from "markdown-it-mdc";
8567
- import MagicString from "magic-string-stack";
8568
- import MarkdownItFootnote from "markdown-it-footnote";
8569
-
8570
- // node/syntax/markdown-it/markdown-it-katex.ts
8571
- import katex from "katex";
8572
- function isValidDelim(state, pos) {
8573
- const max = state.posMax;
8574
- let can_open = true;
8575
- let can_close = true;
8576
- const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
8577
- const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
8578
- if (prevChar === 32 || prevChar === 9 || /* \t */
8579
- nextChar >= 48 && nextChar <= 57)
8580
- can_close = false;
8581
- if (nextChar === 32 || nextChar === 9)
8582
- can_open = false;
8583
- return {
8584
- can_open,
8585
- can_close
8586
- };
8587
- }
8588
- function math_inline(state, silent) {
8589
- let match, token, res, pos;
8590
- if (state.src[state.pos] !== "$")
8591
- return false;
8592
- res = isValidDelim(state, state.pos);
8593
- if (!res.can_open) {
8594
- if (!silent)
8595
- state.pending += "$";
8596
- state.pos += 1;
8597
- return true;
8598
- }
8599
- const start = state.pos + 1;
8600
- match = start;
8601
- while ((match = state.src.indexOf("$", match)) !== -1) {
8602
- pos = match - 1;
8603
- while (state.src[pos] === "\\") pos -= 1;
8604
- if ((match - pos) % 2 === 1)
8605
- break;
8606
- match += 1;
8607
- }
8608
- if (match === -1) {
8609
- if (!silent)
8610
- state.pending += "$";
8611
- state.pos = start;
8612
- return true;
8613
- }
8614
- if (match - start === 0) {
8615
- if (!silent)
8616
- state.pending += "$$";
8617
- state.pos = start + 1;
8618
- return true;
8619
- }
8620
- res = isValidDelim(state, match);
8621
- if (!res.can_close) {
8622
- if (!silent)
8623
- state.pending += "$";
8624
- state.pos = start;
8625
- return true;
8626
- }
8627
- if (!silent) {
8628
- token = state.push("math_inline", "math", 0);
8629
- token.markup = "$";
8630
- token.content = state.src.slice(start, match);
8631
- }
8632
- state.pos = match + 1;
8633
- return true;
8634
- }
8635
- function math_block(state, start, end, silent) {
8636
- let firstLine;
8637
- let lastLine;
8638
- let next;
8639
- let lastPos;
8640
- let found = false;
8641
- let pos = state.bMarks[start] + state.tShift[start];
8642
- let max = state.eMarks[start];
8643
- if (pos + 2 > max)
8644
- return false;
8645
- if (state.src.slice(pos, pos + 2) !== "$$")
8646
- return false;
8647
- pos += 2;
8648
- firstLine = state.src.slice(pos, max);
8649
- if (silent)
8650
- return true;
8651
- if (firstLine.trim().slice(-2) === "$$") {
8652
- firstLine = firstLine.trim().slice(0, -2);
8653
- found = true;
8654
- }
8655
- for (next = start; !found; ) {
8656
- next++;
8657
- if (next >= end)
8658
- break;
8659
- pos = state.bMarks[next] + state.tShift[next];
8660
- max = state.eMarks[next];
8661
- if (pos < max && state.tShift[next] < state.blkIndent) {
8662
- break;
8663
- }
8664
- if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
8665
- lastPos = state.src.slice(0, max).lastIndexOf("$$");
8666
- lastLine = state.src.slice(pos, lastPos);
8667
- found = true;
8668
- }
8669
- }
8670
- state.line = next + 1;
8671
- const token = state.push("math_block", "math", 0);
8672
- token.block = true;
8673
- token.content = (firstLine && firstLine.trim() ? `${firstLine}
8674
- ` : "") + state.getLines(start + 1, next, state.tShift[start], true) + (lastLine && lastLine.trim() ? lastLine : "");
8675
- token.map = [start, state.line];
8676
- token.markup = "$$";
8677
- return true;
8678
- }
8679
- function math_plugin(md, options) {
8680
- options = options || {};
8681
- const katexInline = function(latex) {
8682
- options.displayMode = false;
8683
- try {
8684
- return katex.renderToString(latex, options);
8685
- } catch (error) {
8686
- if (options.throwOnError)
8687
- console.warn(error);
8688
- return latex;
8689
- }
8690
- };
8691
- const inlineRenderer = function(tokens, idx) {
8692
- return katexInline(tokens[idx].content);
8693
- };
8694
- const katexBlock = function(latex) {
8695
- options.displayMode = true;
8696
- try {
8697
- return `<p>${katex.renderToString(latex, options)}</p>`;
8698
- } catch (error) {
8699
- if (options.throwOnError)
8700
- console.warn(error);
8701
- return latex;
8702
- }
8703
- };
8704
- const blockRenderer = function(tokens, idx) {
8705
- return `${katexBlock(tokens[idx].content)}
8706
- `;
8707
- };
8708
- md.inline.ruler.after("escape", "math_inline", math_inline);
8709
- md.block.ruler.after("blockquote", "math_block", math_block, {
8710
- alt: ["paragraph", "reference", "blockquote", "list"]
8711
- });
8712
- md.renderer.rules.math_inline = inlineRenderer;
8713
- md.renderer.rules.math_block = blockRenderer;
8714
- }
8715
-
8716
- // node/syntax/markdown-it/markdown-it-prism.ts
8717
- import { createRequire } from "node:module";
8718
- import Prism from "prismjs";
8719
- import loadLanguages from "prismjs/components/index.js";
8720
- import * as htmlparser2 from "htmlparser2";
8721
-
8722
- // node/syntax/transform/utils.ts
8723
- function normalizeRangeStr(rangeStr = "") {
8724
- return !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
8725
- }
8726
- function getCodeBlocks(md) {
8727
- const codeblocks = Array.from(md.matchAll(/^```[\s\S]*?^```/gm)).map((m) => {
8728
- const start = m.index;
8729
- const end = m.index + m[0].length;
8730
- const startLine = md.slice(0, start).match(/\n/g)?.length || 0;
8731
- const endLine = md.slice(0, end).match(/\n/g)?.length || 0;
8732
- return [start, end, startLine, endLine];
8733
- });
8734
- return {
8735
- codeblocks,
8736
- isInsideCodeblocks(idx) {
8737
- return codeblocks.some(([s, e]) => s <= idx && idx <= e);
8738
- },
8739
- isLineInsideCodeblocks(line) {
8740
- return codeblocks.some(([, , s, e]) => s <= line && line <= e);
8741
- }
8742
- };
8743
- }
8744
- function escapeVueInCode(md) {
8745
- return md.replace(/\{\{/g, "&lbrace;&lbrace;");
8746
- }
8747
-
8748
- // node/syntax/markdown-it/markdown-it-prism.ts
8749
- var require2 = createRequire(import.meta.url);
8750
- var Tag = class {
8751
- tagname;
8752
- attributes;
8753
- constructor(tagname, attributes) {
8754
- this.tagname = tagname;
8755
- this.attributes = attributes;
8756
- }
8757
- asOpen() {
8758
- return `<${this.tagname} ${Object.entries(this.attributes).map(([key, value]) => `${key}="${value}"`).join(" ")}>`;
8759
- }
8760
- asClosed() {
8761
- return `</${this.tagname}>`;
8762
- }
8763
- };
8764
- var DEFAULTS = {
8765
- plugins: [],
8766
- init: () => {
8767
- },
8768
- defaultLanguageForUnknown: void 0,
8769
- defaultLanguageForUnspecified: void 0,
8770
- defaultLanguage: void 0
8771
- };
8772
- function loadPrismLang(lang) {
8773
- if (!lang)
8774
- return void 0;
8775
- let langObject = Prism.languages[lang];
8776
- if (langObject === void 0) {
8777
- loadLanguages([lang]);
8778
- langObject = Prism.languages[lang];
8779
- }
8780
- return langObject;
8781
- }
8782
- function loadPrismPlugin(name) {
8783
- try {
8784
- require2(`prismjs/plugins/${name}/prism-${name}`);
8785
- } catch (e) {
8786
- throw new Error(`Cannot load Prism plugin "${name}". Please check the spelling.`, { cause: e });
8787
- }
8788
- }
8789
- function selectLanguage(options, lang) {
8790
- let langToUse = lang;
8791
- if (langToUse === "" && options.defaultLanguageForUnspecified !== void 0)
8792
- langToUse = options.defaultLanguageForUnspecified;
8793
- let prismLang = loadPrismLang(langToUse);
8794
- if (prismLang === void 0 && options.defaultLanguageForUnknown !== void 0) {
8795
- langToUse = options.defaultLanguageForUnknown;
8796
- prismLang = loadPrismLang(langToUse);
8797
- }
8798
- return [langToUse, prismLang];
8799
- }
8800
- function highlight(markdownit, options, text, lang) {
8801
- const [langToUse, prismLang] = selectLanguage(options, lang);
8802
- let code = text.trimEnd();
8803
- code = prismLang ? highlightPrism(code, prismLang, langToUse) : markdownit.utils.escapeHtml(code);
8804
- code = code.split(/\r?\n/g).map((line) => `<span class="line">${line}</span>`).join("\n");
8805
- const classAttribute = langToUse ? ` class="slidev-code ${markdownit.options.langPrefix}${markdownit.utils.escapeHtml(langToUse)}"` : "";
8806
- return escapeVueInCode(`<pre${classAttribute}><code>${code}</code></pre>`);
8807
- }
8808
- function highlightPrism(code, prismLang, langToUse) {
8809
- const openTags = [];
8810
- const parser3 = new htmlparser2.Parser({
8811
- onopentag(tagname, attributes) {
8812
- openTags.push(new Tag(tagname, attributes));
8813
- },
8814
- onclosetag() {
8815
- openTags.pop();
8816
- }
8817
- });
8818
- code = Prism.highlight(code, prismLang, langToUse);
8819
- code = code.split(/\r?\n/g).map((line) => {
8820
- const prefix = openTags.map((tag) => tag.asOpen()).join("");
8821
- parser3.write(line);
8822
- const postfix = openTags.reverse().map((tag) => tag.asClosed()).join("");
8823
- return prefix + line + postfix;
8824
- }).join("\n");
8825
- parser3.end();
8826
- return code;
8827
- }
8828
- function checkLanguageOption(options, optionName) {
8829
- const language = options[optionName];
8830
- if (language !== void 0 && loadPrismLang(language) === void 0)
8831
- throw new Error(`Bad option ${optionName}: There is no Prism language '${language}'.`);
8832
- }
8833
- function markdownItPrism(markdownit, useroptions) {
8834
- const options = Object.assign({}, DEFAULTS, useroptions);
8835
- checkLanguageOption(options, "defaultLanguage");
8836
- checkLanguageOption(options, "defaultLanguageForUnknown");
8837
- checkLanguageOption(options, "defaultLanguageForUnspecified");
8838
- options.defaultLanguageForUnknown = options.defaultLanguageForUnknown || options.defaultLanguage;
8839
- options.defaultLanguageForUnspecified = options.defaultLanguageForUnspecified || options.defaultLanguage;
8840
- options.plugins.forEach(loadPrismPlugin);
8841
- options.init(Prism);
8842
- markdownit.options.highlight = (text, lang) => highlight(markdownit, options, text, lang);
8843
- }
8844
-
8845
- // node/syntax/markdown-it/markdown-it-v-drag.ts
8846
- import { SourceMapConsumer } from "source-map-js";
8847
- function markdownItVDrag(md, markdownTransformMap) {
8848
- const visited = /* @__PURE__ */ new WeakSet();
8849
- const sourceMapConsumers = /* @__PURE__ */ new WeakMap();
8850
- function getSourceMapConsumer(id) {
8851
- const s = markdownTransformMap.get(id);
8852
- if (!s)
8853
- return void 0;
8854
- let smc = sourceMapConsumers.get(s);
8855
- if (smc)
8856
- return smc;
8857
- const sourceMap = s.generateMap();
8858
- smc = new SourceMapConsumer({
8859
- ...sourceMap,
8860
- version: sourceMap.version.toString()
8861
- });
8862
- sourceMapConsumers.set(s, smc);
8863
- return smc;
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;
8864
8681
  }
8865
- const _parse = md.parse;
8866
- md.parse = function(src, env) {
8867
- const smc = getSourceMapConsumer(env.id);
8868
- const toOriginalPos = smc ? (line) => smc.originalPositionFor({ line, column: 0 }).line : (line) => line;
8869
- function toMarkdownSource(map, idx) {
8870
- const [start, end] = map;
8871
- return `[${toOriginalPos(start)},${toOriginalPos(end)},${idx}]`;
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}" />`;
8872
8690
  }
8873
- return _parse.call(this, src, env).map((token) => {
8874
- if (!["html_block", "html_inline"].includes(token.type) || !token.content.includes("v-drag") || visited.has(token))
8875
- return token;
8876
- token.content = token.content.replace(
8877
- /<(v-?drag-?\w*)([\s>])/gi,
8878
- (_, tag, space, idx) => `<${tag} :markdownSource="${toMarkdownSource(token.map, idx)}"${space}`
8879
- ).replace(
8880
- /(?<![</\w])v-drag(=".*?")?/g,
8881
- (_, value, idx) => `v-drag${value ?? ""} :markdownSource="[${token.map[0]},${token.map[1]},${idx}]"`
8882
- );
8883
- visited.add(token);
8884
- return token;
8885
- });
8886
- };
8887
- }
8888
-
8889
- // node/syntax/transform/code-wrapper.ts
8890
- var reCodeBlock = /^```([\w'-]+)?\s*(?:\{([\w*,|-]+)\}\s*?(\{[^}]*\})?([^\r\n]*))?\r?\n(\S[\s\S]*?)^```$/gm;
8891
- function transformCodeWrapper(ctx) {
8691
+ );
8892
8692
  ctx.s.replace(
8893
- reCodeBlock,
8894
- (full, lang = "", rangeStr = "", options = "", attrs = "", code) => {
8895
- const ranges = normalizeRangeStr(rangeStr);
8896
- code = code.trimEnd();
8693
+ /^```(\w+) *\{monaco\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm,
8694
+ (full, lang = "ts", options = "{}", code) => {
8695
+ lang = lang.trim();
8897
8696
  options = options.trim() || "{}";
8898
- return `
8899
- <CodeBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
8900
-
8901
- \`\`\`${lang}${attrs}
8902
- ${code}
8903
- \`\`\`
8904
-
8905
- </CodeBlockWrapper>`;
8697
+ const encoded = lz3.compressToBase64(code);
8698
+ return `<Monaco code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
8906
8699
  }
8907
8700
  );
8908
- }
8909
-
8910
- // node/syntax/transform/magic-move.ts
8911
- import { codeToKeyedTokens } from "shiki-magic-move/core";
8912
- import lz from "lz-string";
8913
- var reMagicMoveBlock = /^````(?:md|markdown) magic-move(?: *(\{[^}]*\})?([^\n]*))?\n([\s\S]+?)^````$/gm;
8914
- function parseLineNumbersOption(options) {
8915
- return /lines: *true/.test(options) ? true : /lines: *false/.test(options) ? false : void 0;
8916
- }
8917
- function transformMagicMove(shiki, shikiOptions, configLineNumbers) {
8918
- return (ctx) => {
8919
- ctx.s.replace(
8920
- reMagicMoveBlock,
8921
- (full, options = "{}", _attrs = "", body) => {
8922
- if (!shiki || !shikiOptions)
8923
- throw new Error("Shiki is required for Magic Move. You may need to set `highlighter: shiki` in your Slidev config.");
8924
- const matches = Array.from(body.matchAll(reCodeBlock));
8925
- if (!matches.length)
8926
- throw new Error("Magic Move block must contain at least one code block");
8927
- const defaultLineNumbers = parseLineNumbersOption(options) ?? configLineNumbers;
8928
- const ranges = matches.map((i) => normalizeRangeStr(i[2]));
8929
- const steps = matches.map((i) => {
8930
- const lineNumbers = parseLineNumbersOption(i[3]) ?? defaultLineNumbers;
8931
- return codeToKeyedTokens(shiki, i[5].trimEnd(), {
8932
- ...shikiOptions,
8933
- lang: i[1]
8934
- }, lineNumbers);
8935
- });
8936
- const compressed = lz.compressToBase64(JSON.stringify(steps));
8937
- return `<ShikiMagicMove v-bind="${options}" steps-lz="${compressed}" :step-ranges='${JSON.stringify(ranges)}' />`;
8938
- }
8939
- );
8940
- };
8941
- }
8942
-
8943
- // node/syntax/transform/mermaid.ts
8944
- import lz2 from "lz-string";
8945
- function transformMermaid(ctx) {
8946
8701
  ctx.s.replace(
8947
- /^```mermaid *(\{[^\n]*\})?\n([\s\S]+?)\n```/gm,
8948
- (full, options = "", code = "") => {
8949
- code = code.trim();
8702
+ /^```(\w+) *\{monaco-run\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm,
8703
+ (full, lang = "ts", options = "{}", code) => {
8704
+ lang = lang.trim();
8950
8705
  options = options.trim() || "{}";
8951
- const encoded = lz2.compressToBase64(code);
8952
- return `<Mermaid code-lz="${encoded}" v-bind="${options}" />`;
8706
+ const encoded = lz3.compressToBase64(code);
8707
+ return `<Monaco runnable code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
8953
8708
  }
8954
8709
  );
8955
8710
  }
@@ -8968,17 +8723,45 @@ function transformPlantUml(ctx) {
8968
8723
  );
8969
8724
  }
8970
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>");
8752
+ }
8753
+
8971
8754
  // node/syntax/transform/snippet.ts
8972
8755
  import path3 from "node:path";
8973
- import lz3 from "lz-string";
8974
- import fs7 from "fs-extra";
8756
+ import lz4 from "lz-string";
8757
+ import fs6 from "fs-extra";
8975
8758
  import { slash as slash2 } from "@antfu/utils";
8976
8759
 
8977
8760
  // node/vite/monacoWrite.ts
8978
- import fs6 from "node:fs/promises";
8761
+ import fs5 from "node:fs/promises";
8979
8762
  import path2 from "node:path";
8980
8763
  var monacoWriterWhitelist = /* @__PURE__ */ new Set();
8981
- function createMonacoWriter({ userRoot }) {
8764
+ function createMonacoWriterPlugin({ userRoot }) {
8982
8765
  return {
8983
8766
  name: "slidev:monaco-write",
8984
8767
  apply: "serve",
@@ -8999,7 +8782,7 @@ function createMonacoWriter({ userRoot }) {
8999
8782
  }
9000
8783
  const filepath = path2.join(userRoot, file);
9001
8784
  console.log("[Slidev] Writing file:", filepath);
9002
- await fs6.writeFile(filepath, content, "utf-8");
8785
+ await fs5.writeFile(filepath, content, "utf-8");
9003
8786
  }
9004
8787
  });
9005
8788
  });
@@ -9059,15 +8842,10 @@ function findRegion(lines, regionName) {
9059
8842
  }
9060
8843
  return null;
9061
8844
  }
9062
- function transformSnippet(ctx) {
9063
- const options = ctx.options;
9064
- const slideId = ctx.id.match(/(\d+)\.md$/)?.[1];
9065
- if (!slideId)
9066
- return;
8845
+ function transformSnippet({ s, slide, options }) {
9067
8846
  const data = options.data;
9068
- const slideInfo = data.slides[+slideId - 1];
9069
- const dir = path3.dirname(slideInfo.source?.filepath ?? options.entry ?? options.userRoot);
9070
- ctx.s.replace(
8847
+ const dir = path3.dirname(slide.source?.filepath ?? options.entry ?? options.userRoot);
8848
+ s.replace(
9071
8849
  // eslint-disable-next-line regexp/no-super-linear-backtracking
9072
8850
  /^<<<\s*(\S.*?)(#[\w-]+)?\s*(?:\s(\S+?))?\s*(\{.*)?$/gm,
9073
8851
  (full, filepath = "", regionName = "", lang = "", meta = "") => {
@@ -9075,13 +8853,13 @@ function transformSnippet(ctx) {
9075
8853
  /^@\//.test(filepath) ? path3.resolve(options.userRoot, filepath.slice(2)) : path3.resolve(dir, filepath)
9076
8854
  );
9077
8855
  data.watchFiles.push(src);
9078
- const isAFile = fs7.statSync(src).isFile();
9079
- if (!fs7.existsSync(src) || !isAFile) {
8856
+ const isAFile = fs6.statSync(src).isFile();
8857
+ if (!fs6.existsSync(src) || !isAFile) {
9080
8858
  throw new Error(isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`);
9081
8859
  }
9082
- let content = fs7.readFileSync(src, "utf8");
9083
- slideInfo.snippetsUsed ??= {};
9084
- slideInfo.snippetsUsed[src] = content;
8860
+ let content = fs6.readFileSync(src, "utf8");
8861
+ slide.snippetsUsed ??= {};
8862
+ slide.snippetsUsed[src] = content;
9085
8863
  if (regionName) {
9086
8864
  const lines = content.split(/\r?\n/);
9087
8865
  const region = findRegion(lines, regionName.slice(1));
@@ -9098,7 +8876,7 @@ function transformSnippet(ctx) {
9098
8876
  monacoWriterWhitelist.add(filepath);
9099
8877
  lang = lang.trim();
9100
8878
  meta = meta.replace(/^\{monaco-write\}/, "").trim() || "{}";
9101
- const encoded = lz3.compressToBase64(content);
8879
+ const encoded = lz4.compressToBase64(content);
9102
8880
  return `<Monaco writable=${JSON.stringify(filepath)} code-lz="${encoded}" lang="${lang}" v-bind="${meta}" />`;
9103
8881
  }
9104
8882
  return `\`\`\`${lang} ${meta}
@@ -9108,191 +8886,360 @@ ${content}
9108
8886
  );
9109
8887
  }
9110
8888
 
9111
- // node/syntax/transform/slot-sugar.ts
9112
- function transformSlotSugar(ctx) {
9113
- const linesWithNewline = ctx.s.original.split(/(\r?\n)/g);
9114
- const codeBlocks = getCodeBlocks(ctx.s.original);
9115
- const lines = [];
9116
- for (let i = 0; i < linesWithNewline.length; i += 2) {
9117
- const line = linesWithNewline[i];
9118
- const newline = linesWithNewline[i + 1] || "";
9119
- lines.push(line + newline);
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}/>`;
8938
+ };
8939
+ md.renderer.rules.taskListItemLabel_close = () => {
8940
+ return "</label>";
8941
+ };
8942
+ md.renderer.rules.taskListItemLabel_open = (tokens) => {
8943
+ const token = tokens[0];
8944
+ const id = token.attrGet("id");
8945
+ return `<label for="${id}">`;
8946
+ };
8947
+ }
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;
8965
+ }
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];
8971
+ }
8972
+ }
8973
+ return void 0;
8974
+ }
8975
+ function isTodoItem(tokens, index) {
8976
+ return isInline(tokens[index]) && isParagraph(tokens[index - 1]) && isListItem(tokens[index - 2]) && startsWithTodoMarkdown(tokens[index]);
8977
+ }
8978
+ function todoify(token, options) {
8979
+ if (token.children == null) {
8980
+ return;
8981
+ }
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());
8988
+ }
8989
+ }
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)}`;
8995
+ }
8996
+ }
8997
+ function createCheckboxToken(token, enabled, id) {
8998
+ const checkbox = new Token("taskListItemCheckbox", "", 0);
8999
+ if (!enabled) {
9000
+ checkbox.attrSet("disabled", "true");
9001
+ }
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;
9012
+ }
9013
+ function createLabelBeginToken(id) {
9014
+ const labelBeginToken = new Token("taskListItemLabel_open", "", 1);
9015
+ labelBeginToken.attrSet("id", id);
9016
+ return labelBeginToken;
9017
+ }
9018
+ function createLabelEndToken() {
9019
+ return new Token("taskListItemLabel_close", "", -1);
9020
+ }
9021
+ function isInline(token) {
9022
+ return token.type === "inline";
9023
+ }
9024
+ function isParagraph(token) {
9025
+ return token.type === "paragraph_open";
9026
+ }
9027
+ function isListItem(token) {
9028
+ return token.type === "list_item_open";
9029
+ }
9030
+ function startsWithTodoMarkdown(token) {
9031
+ return checkboxRegex.test(token.content);
9032
+ }
9033
+
9034
+ // node/syntax/markdown-it/index.ts
9035
+ import MarkdownItMdc from "markdown-it-mdc";
9036
+ import MarkdownItFootnote from "markdown-it-footnote";
9037
+
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
9044
+ );
9045
+ }
9046
+
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;
9060
+ return {
9061
+ can_open,
9062
+ can_close
9063
+ };
9064
+ }
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;
9075
+ }
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;
9084
+ }
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;
9111
+ }
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;
9120
9131
  }
9121
- let prevSlot = false;
9122
- let offset = 0;
9123
- lines.forEach((line) => {
9124
- const start = offset;
9125
- offset += line.length;
9126
- if (codeBlocks.isInsideCodeblocks(offset))
9127
- return;
9128
- const match = line.match(/^::\s*([\w.\-:]+)\s*::(\s*)$/);
9129
- if (match) {
9130
- ctx.s.overwrite(start, offset - match[2].length, `${prevSlot ? "\n\n</template>\n" : "\n"}<template v-slot:${match[1]}="slotProps">
9131
- `);
9132
- prevSlot = true;
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;
9133
9140
  }
9134
- });
9135
- if (prevSlot)
9136
- ctx.s.append("\n\n</template>");
9137
- }
9138
-
9139
- // node/syntax/transform/in-page-css.ts
9140
- function transformPageCSS(ctx) {
9141
- const page = ctx.id.match(/(\d+)\.md$/)?.[1];
9142
- if (!page)
9143
- return;
9144
- const codeBlocks = getCodeBlocks(ctx.s.original);
9145
- ctx.s.replace(
9146
- /(\n<style[^>]*>)([\s\S]+?)(<\/style>)/g,
9147
- (full, start, css, end, index) => {
9148
- if (codeBlocks.isInsideCodeblocks(index))
9149
- return full;
9150
- if (!start.includes("scoped"))
9151
- start = start.replace("<style", "<style scoped");
9152
- return `${start}
9153
- ${css}${end}`;
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;
9154
9145
  }
9155
- );
9156
- }
9157
-
9158
- // node/syntax/transform/monaco.ts
9159
- import lz4 from "lz-string";
9160
- function transformMonaco(ctx) {
9161
- const enabled = ctx.options.data.config.monaco === true || ctx.options.data.config.monaco === ctx.options.mode;
9162
- if (!enabled) {
9163
- ctx.s.replace(/\{monaco([\w:,-]*)\}/g, "");
9164
- return;
9165
9146
  }
9166
- ctx.s.replace(
9167
- /^```(\w+) *\{monaco-diff\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^~~~ *\n([\s\S]+?)^```/gm,
9168
- (full, lang = "ts", options = "{}", code, diff) => {
9169
- lang = lang.trim();
9170
- options = options.trim() || "{}";
9171
- const encoded = lz4.compressToBase64(code);
9172
- const encodedDiff = lz4.compressToBase64(diff);
9173
- return `<Monaco code-lz="${encoded}" diff-lz="${encodedDiff}" lang="${lang}" v-bind="${options}" />`;
9174
- }
9175
- );
9176
- ctx.s.replace(
9177
- /^```(\w+) *\{monaco\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm,
9178
- (full, lang = "ts", options = "{}", code) => {
9179
- lang = lang.trim();
9180
- options = options.trim() || "{}";
9181
- const encoded = lz4.compressToBase64(code);
9182
- return `<Monaco code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
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;
9155
+ }
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;
9183
9165
  }
9184
- );
9185
- ctx.s.replace(
9186
- /^```(\w+) *\{monaco-run\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm,
9187
- (full, lang = "ts", options = "{}", code) => {
9188
- lang = lang.trim();
9189
- options = options.trim() || "{}";
9190
- const encoded = lz4.compressToBase64(code);
9191
- return `<Monaco runnable code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
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;
9192
9178
  }
9193
- );
9194
- }
9195
-
9196
- // node/syntax/transform/katex-wrapper.ts
9197
- function transformKaTexWrapper(ctx) {
9198
- ctx.s.replace(
9199
- /^\$\$(?:\s*\{([\w*,|-]+)\}\s*?(?:(\{[^}]*\})\s*?)?)?\n(\S[\s\S]*?)^\$\$/gm,
9200
- (full, rangeStr = "", options = "", code) => {
9201
- const ranges = !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
9202
- code = code.trimEnd();
9203
- options = options.trim() || "{}";
9204
- return `<KaTexBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
9205
-
9206
- $$
9207
- ${code}
9208
- $$
9209
- </KaTexBlockWrapper>
9179
+ };
9180
+ const blockRenderer = function(tokens, idx) {
9181
+ return `${katexBlock(tokens[idx].content)}
9210
9182
  `;
9211
- }
9212
- );
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;
9213
9190
  }
9214
9191
 
9215
- // node/vite/markdown.ts
9216
- async function createMarkdownPlugin(options, { markdown: mdOptions }) {
9217
- const { data: { config }, roots, mode, entry, clientRoot } = options;
9218
- const setups = [];
9219
- const entryPath = slash3(entry);
9220
- let shiki;
9221
- let shikiOptions;
9222
- if (config.highlighter === "shiki") {
9223
- const result = await createMarkdownItShiki(clientRoot, roots, config, mode);
9224
- shiki = result.shiki;
9225
- shikiOptions = result.shikiOptions;
9226
- setups.push((md) => md.use(result.plugin));
9227
- } else {
9228
- console.warn("[Slidev] Highlighter: Prism highlighter is deprecated, and will be removed in v0.50. Refer to https://github.com/slidevjs/slidev/issues/1390");
9229
- 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;
9230
9211
  }
9231
- if (config.mdc)
9232
- setups.push((md) => md.use(MarkdownItMdc));
9233
- const KatexOptions = await loadSetups(options.clientRoot, roots, "katex.ts", {}, { strict: false }, false);
9234
- const markdownTransformMap = /* @__PURE__ */ new Map();
9235
- return Markdown({
9236
- include: [/\.md$/],
9237
- wrapperClasses: "",
9238
- headEnabled: false,
9239
- frontmatter: false,
9240
- escapeCodeTagInterpolation: false,
9241
- markdownItOptions: {
9242
- quotes: `""''`,
9243
- html: true,
9244
- xhtmlOut: true,
9245
- linkify: true,
9246
- ...mdOptions?.markdownItOptions
9247
- },
9248
- ...mdOptions,
9249
- markdownItSetup(md) {
9250
- md.use(markdownItLink);
9251
- md.use(MarkdownItEscapeInlineCode);
9252
- md.use(MarkdownItFootnote);
9253
- md.use(taskLists, { enabled: true, lineNumber: true, label: true });
9254
- md.use(math_plugin, KatexOptions);
9255
- md.use(markdownItVDrag, markdownTransformMap);
9256
- setups.forEach((i) => i(md));
9257
- mdOptions?.markdownItSetup?.(md);
9258
- },
9259
- transforms: {
9260
- before(code, id) {
9261
- if (id === entryPath)
9262
- return "";
9263
- const ctx = {
9264
- s: new MagicString(code),
9265
- id,
9266
- options
9267
- };
9268
- applyMarkdownTransform(ctx, shiki, shikiOptions);
9269
- markdownTransformMap.set(id, ctx.s);
9270
- return ctx.s.toString();
9271
- }
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}]`;
9272
9219
  }
9273
- });
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
+ };
9274
9234
  }
9275
- async function createMarkdownItShiki(clientRoot, roots, config, mode) {
9276
- const [
9277
- shikiOptions,
9278
- { createHighlighter, bundledLanguages },
9279
- markdownItShiki,
9280
- transformerTwoslash
9281
- ] = await Promise.all([
9282
- loadShikiSetups(clientRoot, roots),
9283
- import("shiki").then(({ createHighlighter: createHighlighter2, bundledLanguages: bundledLanguages2 }) => ({ bundledLanguages: bundledLanguages2, createHighlighter: createHighlighter2 })),
9284
- import("@shikijs/markdown-it/core").then(({ fromHighlighter }) => fromHighlighter),
9285
- import("@shikijs/vitepress-twoslash").then(({ transformerTwoslash: transformerTwoslash2 }) => transformerTwoslash2)
9286
- ]);
9287
- const shiki = await createHighlighter({
9288
- ...shikiOptions,
9289
- langs: shikiOptions.langs ?? Object.keys(bundledLanguages),
9290
- themes: "themes" in shikiOptions ? Object.values(shikiOptions.themes) : [shikiOptions.theme]
9291
- });
9292
- 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 }) {
9293
9240
  const transformers = [
9294
- ...shikiOptions.transformers || [],
9295
- twoslashEnabled && transformerTwoslash({
9241
+ ...utils.shikiOptions.transformers || [],
9242
+ (config.twoslash === true || config.twoslash === mode) && (await import("@shikijs/vitepress-twoslash")).transformerTwoslash({
9296
9243
  explicitTrigger: true,
9297
9244
  twoslashOptions: {
9298
9245
  handbookOptions: {
@@ -9310,16 +9257,13 @@ async function createMarkdownItShiki(clientRoot, roots, config, mode) {
9310
9257
  }
9311
9258
  }
9312
9259
  ].filter(isTruthy);
9313
- const plugin = markdownItShiki(shiki, {
9314
- ...shikiOptions,
9260
+ return fromHighlighter(utils.shiki, {
9261
+ ...utils.shikiOptions,
9315
9262
  transformers
9316
9263
  });
9317
- return {
9318
- shiki,
9319
- shikiOptions,
9320
- plugin
9321
- };
9322
9264
  }
9265
+
9266
+ // node/syntax/markdown-it/markdown-it-escape-code.ts
9323
9267
  function MarkdownItEscapeInlineCode(md) {
9324
9268
  const codeInline = md.renderer.rules.code_inline;
9325
9269
  md.renderer.rules.code_inline = (tokens, idx, options, env, self) => {
@@ -9327,55 +9271,82 @@ function MarkdownItEscapeInlineCode(md) {
9327
9271
  return result.replace(/^<code/, "<code v-pre");
9328
9272
  };
9329
9273
  }
9330
- function applyMarkdownTransform(ctx, shiki, shikiOptions) {
9331
- const transformers = [
9332
- transformSnippet,
9333
- ctx.options.data.config.highlighter ? transformMagicMove(shiki, shikiOptions, ctx.options.data.config.lineNumbers) : void 0,
9334
- transformMermaid,
9335
- transformPlantUml,
9336
- transformMonaco,
9337
- transformCodeWrapper,
9338
- transformKaTexWrapper,
9339
- transformPageCSS,
9340
- transformSlotSugar
9341
- ];
9342
- for (const transformer of transformers) {
9343
- if (!transformer)
9344
- continue;
9345
- transformer(ctx);
9346
- if (!ctx.s.isEmpty())
9347
- ctx.s.commit();
9348
- }
9349
- return ctx;
9350
- }
9351
9274
 
9352
- // node/vite/compilerFlagsVue.ts
9353
- import { objectEntries } from "@antfu/utils";
9354
- function createVueCompilerFlagsPlugin(options) {
9355
- const define = objectEntries(getDefine(options));
9356
- return [
9357
- {
9358
- name: "slidev:flags",
9359
- enforce: "pre",
9360
- transform(code, id) {
9361
- if (id.match(/\.vue($|\?)/)) {
9362
- const original = code;
9363
- define.forEach(([from, to]) => {
9364
- code = code.replace(new RegExp(from, "g"), to);
9365
- });
9366
- if (original !== code)
9367
- return code;
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);
9284
+ }
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);
9294
+ }
9295
+
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();
9368
9338
  }
9339
+ return s.toString();
9369
9340
  }
9370
9341
  }
9371
- ];
9342
+ });
9372
9343
  }
9373
9344
 
9374
9345
  // node/vite/monacoTypes.ts
9375
- import fs8 from "node:fs/promises";
9376
- import { dirname as dirname2, resolve as resolve7 } from "node:path";
9377
- import { slash as slash4 } from "@antfu/utils";
9378
- 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";
9379
9350
  import { findDepPkgJsonPath } from "vitefu";
9380
9351
  function createMonacoTypesLoader({ userRoot, utils }) {
9381
9352
  return {
@@ -9396,8 +9367,8 @@ function createMonacoTypesLoader({ userRoot, utils }) {
9396
9367
  const pkgJsonPath = await findDepPkgJsonPath(pkg, importer);
9397
9368
  if (!pkgJsonPath)
9398
9369
  throw new Error(`Package "${pkg}" not found in "${importer}"`);
9399
- const root = slash4(dirname2(pkgJsonPath));
9400
- 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"));
9401
9372
  let deps = Object.keys(pkgJson.dependencies ?? {});
9402
9373
  deps = deps.filter((pkg2) => !utils.isMonacoTypesIgnored(pkg2));
9403
9374
  return [
@@ -9409,7 +9380,7 @@ function createMonacoTypesLoader({ userRoot, utils }) {
9409
9380
  const query = new URLSearchParams(url.search);
9410
9381
  const root = query.get("root");
9411
9382
  const name = query.get("name");
9412
- const files = await fg4(
9383
+ const files = await fg3(
9413
9384
  [
9414
9385
  "**/*.ts",
9415
9386
  "**/*.mts",
@@ -9426,13 +9397,153 @@ function createMonacoTypesLoader({ userRoot, utils }) {
9426
9397
  return "/** No files found **/";
9427
9398
  return [
9428
9399
  'import { addFile } from "@slidev/client/setup/monaco.ts"',
9429
- ...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}`)})`)
9430
9401
  ].join("\n");
9431
9402
  }
9432
9403
  }
9433
9404
  };
9434
9405
  }
9435
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
+
9436
9547
  // node/vite/vue.ts
9437
9548
  import Vue from "@vitejs/plugin-vue";
9438
9549
  import VueJsx from "@vitejs/plugin-vue-jsx";
@@ -9466,7 +9577,7 @@ var customElements = /* @__PURE__ */ new Set([
9466
9577
  "munderover",
9467
9578
  "semantics"
9468
9579
  ]);
9469
- async function createVuePlugin(options, pluginOptions) {
9580
+ async function createVuePlugin(_options, pluginOptions) {
9470
9581
  const {
9471
9582
  vue: vueOptions = {},
9472
9583
  vuejsx: vuejsxOptions = {}
@@ -9474,15 +9585,15 @@ async function createVuePlugin(options, pluginOptions) {
9474
9585
  const VuePlugin = Vue({
9475
9586
  include: [/\.vue$/, /\.vue\?vue/, /\.vue\?v=/, /\.md$/, /\.md\?vue/],
9476
9587
  exclude: [],
9588
+ ...vueOptions,
9477
9589
  template: {
9478
9590
  compilerOptions: {
9479
9591
  isCustomElement(tag) {
9480
- return customElements.has(tag);
9592
+ return customElements.has(tag) || vueOptions?.template?.compilerOptions?.isCustomElement?.(tag);
9481
9593
  }
9482
9594
  },
9483
9595
  ...vueOptions?.template
9484
- },
9485
- ...vueOptions
9596
+ }
9486
9597
  });
9487
9598
  const VueJsxPlugin = VueJsx(vuejsxOptions);
9488
9599
  return [
@@ -9491,235 +9602,50 @@ async function createVuePlugin(options, pluginOptions) {
9491
9602
  ];
9492
9603
  }
9493
9604
 
9494
- // node/vite/layoutWrapper.ts
9495
- import { bold, gray, red, yellow } from "kolorist";
9496
- function createLayoutWrapperPlugin({ data, utils }) {
9497
- return {
9498
- name: "slidev:layout-wrapper",
9499
- async transform(code, id) {
9500
- const match = id.match(regexSlideSourceId);
9501
- if (!match)
9502
- return;
9503
- const [, no, type] = match;
9504
- if (type !== "md")
9505
- return;
9506
- const index = +no - 1;
9507
- const layouts = await utils.getLayouts();
9508
- const rawLayoutName = data.slides[index]?.frontmatter?.layout ?? data.slides[0]?.frontmatter?.default?.layout;
9509
- let layoutName = rawLayoutName || (index === 0 ? "cover" : "default");
9510
- if (!layouts[layoutName]) {
9511
- console.error(red(`
9512
- Unknown layout "${bold(layoutName)}".${yellow(" Available layouts are:")}`) + Object.keys(layouts).map((i, idx) => (idx % 3 === 0 ? "\n " : "") + gray(i.padEnd(15, " "))).join(" "));
9513
- console.error();
9514
- layoutName = "default";
9515
- }
9516
- const setupTag = code.match(/^<script setup.*>/m);
9517
- if (!setupTag)
9518
- throw new Error(`[Slidev] Internal error: <script setup> block not found in slide ${index + 1}.`);
9519
- const templatePart = code.slice(0, setupTag.index);
9520
- const scriptPart = code.slice(setupTag.index);
9521
- const bodyStart = templatePart.indexOf("<template>") + 10;
9522
- const bodyEnd = templatePart.lastIndexOf("</template>");
9523
- let body = code.slice(bodyStart, bodyEnd).trim();
9524
- if (body.startsWith("<div>") && body.endsWith("</div>"))
9525
- body = body.slice(5, -6);
9526
- return [
9527
- templatePart.slice(0, bodyStart),
9528
- `<InjectedLayout v-bind="_frontmatterToProps($frontmatter,${index})">
9529
- ${body}
9530
- </InjectedLayout>`,
9531
- templatePart.slice(bodyEnd),
9532
- scriptPart.slice(0, setupTag[0].length),
9533
- `import InjectedLayout from "${toAtFS(layouts[layoutName])}"`,
9534
- templateImportContextUtils,
9535
- templateInitContext,
9536
- "$clicksContext.setup()",
9537
- templateInjectionMarker,
9538
- scriptPart.slice(setupTag[0].length)
9539
- ].join("\n");
9540
- }
9541
- };
9542
- }
9543
-
9544
- // node/vite/contextInjection.ts
9545
- function createContextInjectionPlugin() {
9546
- return {
9547
- name: "slidev:context-injection",
9548
- async transform(code, id) {
9549
- if (!id.endsWith(".vue") || id.includes("/@slidev/client/") || id.includes("/packages/client/"))
9550
- return;
9551
- if (code.includes(templateInjectionMarker) || code.includes("useSlideContext()"))
9552
- return code;
9553
- const imports = [
9554
- templateImportContextUtils,
9555
- templateInitContext,
9556
- templateInjectionMarker
9557
- ];
9558
- const matchScript = code.match(/<script((?!setup).)*(setup)?.*>/);
9559
- if (matchScript && matchScript[2]) {
9560
- return code.replace(/(<script.*>)/g, `$1
9561
- ${imports.join("\n")}
9562
- `);
9563
- } else if (matchScript && !matchScript[2]) {
9564
- const matchExport = code.match(/export\s+default\s+\{/);
9565
- if (matchExport) {
9566
- const exportIndex = (matchExport.index || 0) + matchExport[0].length;
9567
- let component = code.slice(exportIndex);
9568
- component = component.slice(0, component.indexOf("</script>"));
9569
- const scriptIndex = (matchScript.index || 0) + matchScript[0].length;
9570
- const provideImport = '\nimport { injectionSlidevContext } from "@slidev/client/constants.ts"\n';
9571
- code = `${code.slice(0, scriptIndex)}${provideImport}${code.slice(scriptIndex)}`;
9572
- let injectIndex = exportIndex + provideImport.length;
9573
- let injectObject = "$slidev: { from: injectionSlidevContext },";
9574
- const matchInject = component.match(/.*inject\s*:\s*([[{])/);
9575
- if (matchInject) {
9576
- injectIndex += (matchInject.index || 0) + matchInject[0].length;
9577
- if (matchInject[1] === "[") {
9578
- let injects = component.slice((matchInject.index || 0) + matchInject[0].length);
9579
- const injectEndIndex = injects.indexOf("]");
9580
- injects = injects.slice(0, injectEndIndex);
9581
- injectObject += injects.split(",").map((inject) => `${inject}: {from: ${inject}}`).join(",");
9582
- return `${code.slice(0, injectIndex - 1)}{
9583
- ${injectObject}
9584
- }${code.slice(injectIndex + injectEndIndex + 1)}`;
9585
- } else {
9586
- return `${code.slice(0, injectIndex)}
9587
- ${injectObject}
9588
- ${code.slice(injectIndex)}`;
9589
- }
9590
- }
9591
- return `${code.slice(0, injectIndex)}
9592
- inject: { ${injectObject} },
9593
- ${code.slice(injectIndex)}`;
9594
- }
9595
- }
9596
- return `<script setup>
9597
- ${imports.join("\n")}
9598
- </script>
9599
- ${code}`;
9600
- }
9601
- };
9602
- }
9603
-
9604
- // node/vite/hmrPatch.ts
9605
- function createHmrPatchPlugin() {
9606
- return {
9607
- name: "slidev:slide-transform:post",
9608
- transform(code, id) {
9609
- if (!id.match(regexSlideSourceId))
9610
- return;
9611
- const replaced = code.replace("if (_rerender_only)", "if (false)");
9612
- if (replaced !== code)
9613
- return replaced;
9614
- }
9615
- };
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
+ });
9616
9621
  }
9617
9622
 
9618
9623
  // node/vite/index.ts
9619
- async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
9620
- const {
9621
- components: componentsOptions = {},
9622
- icons: iconsOptions = {},
9623
- remoteAssets: remoteAssetsOptions = {},
9624
- serverRef: serverRefOptions = {}
9625
- } = pluginOptions;
9626
- const {
9627
- mode,
9628
- themeRoots,
9629
- addonRoots,
9630
- roots,
9631
- data: { config }
9632
- } = options;
9633
- const drawingData = await loadDrawings(options);
9634
- const publicRoots = [...themeRoots, ...addonRoots].map((i) => join9(i, "public")).filter(existsSync6);
9635
- const plugins = [
9624
+ async function ViteSlidevPlugin(options, pluginOptions = {}, serverOptions = {}) {
9625
+ return Promise.all([
9636
9626
  createSlidesLoader(options, serverOptions),
9637
9627
  createMarkdownPlugin(options, pluginOptions),
9638
9628
  createLayoutWrapperPlugin(options),
9639
9629
  createContextInjectionPlugin(),
9640
9630
  createVuePlugin(options, pluginOptions),
9641
9631
  createHmrPatchPlugin(),
9642
- Components({
9643
- extensions: ["vue", "md", "js", "ts", "jsx", "tsx"],
9644
- dirs: [
9645
- join9(options.clientRoot, "builtin"),
9646
- ...roots.map((i) => join9(i, "components")),
9647
- "src/components",
9648
- "components",
9649
- join9(process2.cwd(), "components")
9650
- ],
9651
- include: [/\.vue$/, /\.vue\?vue/, /\.vue\?v=/, /\.md$/, /\.md\?vue/],
9652
- exclude: [],
9653
- resolvers: [
9654
- IconsResolver({
9655
- prefix: "",
9656
- customCollections: Object.keys(iconsOptions.customCollections || [])
9657
- })
9658
- ],
9659
- dts: false,
9660
- ...componentsOptions
9661
- }),
9662
- Icons({
9663
- defaultClass: "slidev-icon",
9664
- collectionsNodeResolvePath: options.cliRoot,
9665
- ...iconsOptions
9666
- }),
9667
- config.remoteAssets === true || config.remoteAssets === mode ? import("vite-plugin-remote-assets").then((r) => r.VitePluginRemoteAssets({
9668
- rules: [
9669
- ...r.DefaultRules,
9670
- {
9671
- match: /\b(https?:\/\/image.unsplash\.com.*?)(?=[`'")\]])/gi,
9672
- ext: ".png"
9673
- }
9674
- ],
9675
- resolveMode: (id) => id.endsWith("index.html") ? "relative" : "@fs",
9676
- awaitDownload: mode === "build",
9677
- ...remoteAssetsOptions
9678
- })) : null,
9679
- ServerRef({
9680
- debug: false,
9681
- // process.env.NODE_ENV === 'development',
9682
- state: {
9683
- sync: false,
9684
- nav: {
9685
- page: 0,
9686
- clicks: 0
9687
- },
9688
- drawings: drawingData,
9689
- ...serverRefOptions.state
9690
- },
9691
- onChanged(key, data, patch, timestamp) {
9692
- if (serverRefOptions.onChanged)
9693
- serverRefOptions.onChanged(key, data, patch, timestamp);
9694
- if (!options.data.config.drawings.persist)
9695
- return;
9696
- if (key === "drawings")
9697
- writeDrawings(options, patch ?? data);
9698
- }
9699
- }),
9632
+ createComponentsPlugin(options, pluginOptions),
9633
+ createIconsPlugin(options, pluginOptions),
9634
+ createRemoteAssetsPlugin(options, pluginOptions),
9635
+ createServerRefPlugin(options, pluginOptions),
9700
9636
  createConfigPlugin(options),
9701
9637
  createMonacoTypesLoader(options),
9702
- createMonacoWriter(options),
9638
+ createMonacoWriterPlugin(options),
9703
9639
  createVueCompilerFlagsPlugin(options),
9704
9640
  createUnocssPlugin(options, pluginOptions),
9705
- publicRoots.length ? import("vite-plugin-static-copy").then((r) => r.viteStaticCopy({
9706
- silent: true,
9707
- targets: publicRoots.map((r2) => ({
9708
- src: `${r2}/*`,
9709
- dest: "theme"
9710
- }))
9711
- })) : null,
9712
- options.inspect ? import("vite-plugin-inspect").then((r) => (r.default || r)({
9713
- dev: true,
9714
- build: true
9715
- })) : null
9716
- ];
9717
- return (await Promise.all(plugins)).flat().filter(notNullish2);
9641
+ createStaticCopyPlugin(options, pluginOptions),
9642
+ createInspectPlugin(options, pluginOptions)
9643
+ ]);
9718
9644
  }
9719
9645
 
9720
9646
  // node/commands/shared.ts
9721
9647
  var sharedMd = MarkdownIt({ html: true });
9722
- sharedMd.use(markdownItLink);
9648
+ sharedMd.use(MarkdownItLink);
9723
9649
  function getSlideTitle(data) {
9724
9650
  const tokens = sharedMd.parseInline(data.config.title, {});
9725
9651
  const title = stringifyMarkdownTokens(tokens);
@@ -9732,13 +9658,13 @@ function escapeHtml(unsafe) {
9732
9658
  );
9733
9659
  }
9734
9660
  async function getIndexHtml({ mode, entry, clientRoot, roots, data }) {
9735
- let main = await fs9.readFile(join10(clientRoot, "index.html"), "utf-8");
9661
+ let main = await fs9.readFile(join11(clientRoot, "index.html"), "utf-8");
9736
9662
  let head = "";
9737
9663
  let body = "";
9738
9664
  const { info, author, keywords } = data.headmatter;
9739
9665
  head += [
9740
9666
  `<meta name="slidev:version" content="${version}">`,
9741
- mode === "dev" && `<meta charset="slidev:entry" content="${slash5(entry)}">`,
9667
+ mode === "dev" && `<meta charset="slidev:entry" content="${slash4(entry)}">`,
9742
9668
  `<link rel="icon" href="${data.config.favicon}">`,
9743
9669
  `<title>${getSlideTitle(data)}</title>`,
9744
9670
  info && `<meta name="description" content=${escapeHtml(info)}>`,
@@ -9746,7 +9672,7 @@ async function getIndexHtml({ mode, entry, clientRoot, roots, data }) {
9746
9672
  keywords && `<meta name="keywords" content=${escapeHtml(Array.isArray(keywords) ? keywords.join(", ") : keywords)}>`
9747
9673
  ].filter(Boolean).join("\n");
9748
9674
  for (const root of roots) {
9749
- const path4 = join10(root, "index.html");
9675
+ const path4 = join11(root, "index.html");
9750
9676
  if (!existsSync7(path4))
9751
9677
  continue;
9752
9678
  const index = await fs9.readFile(path4, "utf-8");
@@ -9760,7 +9686,7 @@ ${(index.match(/<body>([\s\S]*?)<\/body>/i)?.[1] || "").trim()}`;
9760
9686
  if (data.config.fonts.webfonts.length && data.config.fonts.provider !== "none")
9761
9687
  head += `
9762
9688
  <link rel="stylesheet" href="${generateGoogleFontsUrl(data.config.fonts)}" type="text/css">`;
9763
- 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);
9764
9690
  return main;
9765
9691
  }
9766
9692
  async function resolveViteConfigs(options, baseConfig, overrideConfigs, command, serverOptions) {
@@ -9768,7 +9694,7 @@ async function resolveViteConfigs(options, baseConfig, overrideConfigs, command,
9768
9694
  mode: command === "build" ? "production" : "development",
9769
9695
  command
9770
9696
  };
9771
- const files = options.roots.map((i) => join10(i, "vite.config.ts"));
9697
+ const files = options.roots.map((i) => join11(i, "vite.config.ts"));
9772
9698
  for (const file of files) {
9773
9699
  if (!existsSync7(file))
9774
9700
  continue;
@@ -9781,9 +9707,7 @@ async function resolveViteConfigs(options, baseConfig, overrideConfigs, command,
9781
9707
  baseConfig = mergeConfig2(baseConfig, {
9782
9708
  configFile: false,
9783
9709
  root: options.userRoot,
9784
- plugins: [
9785
- await ViteSlidevPlugin(options, baseConfig.slidev || {}, serverOptions)
9786
- ],
9710
+ plugins: await ViteSlidevPlugin(options, baseConfig.slidev, serverOptions),
9787
9711
  define: {
9788
9712
  // Fixes Vue production mode breaking PDF Export #1245
9789
9713
  __VUE_PROD_DEVTOOLS__: false
@@ -9796,11 +9720,11 @@ export {
9796
9720
  version,
9797
9721
  getIndexHtml,
9798
9722
  resolveViteConfigs,
9799
- loadSetups,
9800
9723
  parser,
9801
9724
  resolveTheme,
9802
9725
  getThemeMeta,
9803
9726
  resolveAddons,
9727
+ loadSetups,
9804
9728
  resolveOptions,
9805
9729
  createDataUtils,
9806
9730
  ViteSlidevPlugin