@slidev/cli 0.48.0-beta.24 → 0.48.0-beta.26

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,21 +1,18 @@
1
1
  import {
2
2
  loadSetups
3
- } from "./chunk-O6TYYGU6.mjs";
3
+ } from "./chunk-LOUKLO2C.mjs";
4
4
  import {
5
5
  resolveImportPath,
6
+ resolveImportUrl,
6
7
  toAtFS
7
- } from "./chunk-CV7OWJOF.mjs";
8
+ } from "./chunk-HKSSAKUU.mjs";
8
9
 
9
- // package.json
10
- var version = "0.48.0-beta.24";
11
-
12
- // node/common.ts
10
+ // node/commands/shared.ts
13
11
  import { existsSync, promises as fs } from "node:fs";
14
12
  import { join } from "node:path";
15
13
  import { loadConfigFromFile, mergeConfig, resolveConfig } from "vite";
16
14
 
17
15
  // node/utils.ts
18
- import { satisfies } from "semver";
19
16
  function stringifyMarkdownTokens(tokens) {
20
17
  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(" ");
21
18
  }
@@ -24,12 +21,8 @@ function generateGoogleFontsUrl(options) {
24
21
  const fonts = options.webfonts.map((i) => `family=${i.replace(/^(['"])(.*)\1$/, "$1").replace(/\s+/g, "+")}:${options.italic ? "ital," : ""}wght@${weights}`).join("&");
25
22
  return `https://fonts.googleapis.com/css2?${fonts}&display=swap`;
26
23
  }
27
- function checkEngine(name, engines = {}) {
28
- if (engines.slidev && !satisfies(version, engines.slidev, { includePrerelease: true }))
29
- throw new Error(`[slidev] addon "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
30
- }
31
24
 
32
- // node/common.ts
25
+ // node/commands/shared.ts
33
26
  async function getIndexHtml({ clientRoot, roots, data }) {
34
27
  let main = await fs.readFile(join(clientRoot, "index.html"), "utf-8");
35
28
  let head = "";
@@ -73,20 +66,18 @@ async function mergeViteConfigs({ roots, entry }, viteConfig, config, command) {
73
66
  return config;
74
67
  }
75
68
 
76
- // node/plugins/preset.ts
77
- import { join as join6 } from "node:path";
78
- import { existsSync as existsSync3 } from "node:fs";
69
+ // node/vite/index.ts
70
+ import { join as join8 } from "node:path";
71
+ import { existsSync as existsSync5 } from "node:fs";
79
72
  import process from "node:process";
80
73
  import { fileURLToPath } from "node:url";
81
- import Vue from "@vitejs/plugin-vue";
82
- import VueJsx from "@vitejs/plugin-vue-jsx";
83
74
  import Icons from "unplugin-icons/vite";
84
75
  import IconsResolver from "unplugin-icons/resolver";
85
76
  import Components from "unplugin-vue-components/vite";
86
77
  import ServerRef from "vite-plugin-vue-server-ref";
87
78
  import { notNullish as notNullish2 } from "@antfu/utils";
88
79
 
89
- // node/drawings.ts
80
+ // node/integrations/drawings.ts
90
81
  import { basename, dirname, join as join2, resolve } from "node:path";
91
82
  import fs2 from "fs-extra";
92
83
  import fg from "fast-glob";
@@ -137,7 +128,7 @@ ${value}
137
128
  );
138
129
  }
139
130
 
140
- // node/plugins/extendConfig.ts
131
+ // node/vite/extendConfig.ts
141
132
  import { join as join3 } from "node:path";
142
133
  import { mergeConfig as mergeConfig2 } from "vite";
143
134
  import isInstalledGlobally from "is-installed-globally";
@@ -181,7 +172,7 @@ var dependencies = {
181
172
  "vue-router": "^4.3.0"
182
173
  };
183
174
 
184
- // node/plugins/extendConfig.ts
175
+ // node/vite/extendConfig.ts
185
176
  var INCLUDE = [
186
177
  ...Object.keys(dependencies),
187
178
  // CodeMirror
@@ -226,11 +217,24 @@ function createConfigPlugin(options) {
226
217
  const injection = {
227
218
  define: getDefine(options),
228
219
  resolve: {
229
- alias: {
230
- "@slidev/client/": `${toAtFS(options.clientRoot)}/`,
231
- "#slidev/": "/@slidev/",
232
- "vue": await resolveImportPath("vue/dist/vue.esm-browser.js", true)
233
- },
220
+ alias: [
221
+ {
222
+ find: /^@slidev\/client$/,
223
+ replacement: `${toAtFS(options.clientRoot)}/index.ts`
224
+ },
225
+ {
226
+ find: /^@slidev\/client\/(.*)/,
227
+ replacement: `${toAtFS(options.clientRoot)}/$1`
228
+ },
229
+ {
230
+ find: /^#slidev\/(.*)/,
231
+ replacement: "/@slidev/$1"
232
+ },
233
+ {
234
+ find: "vue",
235
+ replacement: await resolveImportPath("vue/dist/vue.esm-browser.js", true)
236
+ }
237
+ ],
234
238
  dedupe: ["vue"]
235
239
  },
236
240
  optimizeDeps: {
@@ -322,851 +326,522 @@ function getDefine(options) {
322
326
  };
323
327
  }
324
328
 
325
- // node/plugins/loaders.ts
326
- import { basename as basename2, join as join4, resolve as resolve2 } from "node:path";
327
- import { builtinModules } from "node:module";
328
- import { isString, isTruthy as isTruthy2, notNullish, objectMap, range, uniq as uniq2 } from "@antfu/utils";
329
- import fg2 from "fast-glob";
330
- import fs5 from "fs-extra";
331
- import Markdown2 from "markdown-it";
329
+ // node/vite/loaders.ts
330
+ import { basename as basename2 } from "node:path";
331
+ import { isString as isString2, isTruthy as isTruthy2, notNullish, range } from "@antfu/utils";
332
+ import fg3 from "fast-glob";
333
+ import fs4 from "fs-extra";
334
+ import Markdown from "markdown-it";
332
335
  import { bold, gray, red, yellow } from "kolorist";
333
- import mila2 from "markdown-it-link-attributes";
336
+ import mila from "markdown-it-link-attributes";
334
337
  import * as parser from "@slidev/parser/fs";
335
338
  import equal from "fast-deep-equal";
336
339
 
337
- // node/plugins/markdown.ts
338
- import fs4 from "node:fs/promises";
339
- import Markdown from "unplugin-vue-markdown/vite";
340
- import { isTruthy, slash } from "@antfu/utils";
341
-
342
- // ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.0.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/image-size/specialCharacters.js
343
- var SpecialCharacters;
344
- (function(SpecialCharacters2) {
345
- SpecialCharacters2[SpecialCharacters2["EXCLAMATION_MARK"] = 33] = "EXCLAMATION_MARK";
346
- SpecialCharacters2[SpecialCharacters2["OPENING_BRACKET"] = 91] = "OPENING_BRACKET";
347
- SpecialCharacters2[SpecialCharacters2["OPENING_PARENTHESIS"] = 40] = "OPENING_PARENTHESIS";
348
- SpecialCharacters2[SpecialCharacters2["WHITESPACE"] = 32] = "WHITESPACE";
349
- SpecialCharacters2[SpecialCharacters2["NEW_LINE"] = 10] = "NEW_LINE";
350
- SpecialCharacters2[SpecialCharacters2["EQUALS"] = 61] = "EQUALS";
351
- SpecialCharacters2[SpecialCharacters2["LOWER_CASE_X"] = 120] = "LOWER_CASE_X";
352
- SpecialCharacters2[SpecialCharacters2["NUMBER_ZERO"] = 48] = "NUMBER_ZERO";
353
- SpecialCharacters2[SpecialCharacters2["NUMBER_NINE"] = 57] = "NUMBER_NINE";
354
- SpecialCharacters2[SpecialCharacters2["PERCENTAGE"] = 37] = "PERCENTAGE";
355
- SpecialCharacters2[SpecialCharacters2["CLOSING_PARENTHESIS"] = 41] = "CLOSING_PARENTHESIS";
356
- })(SpecialCharacters || (SpecialCharacters = {}));
357
-
358
- // ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.0.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/task-lists/index.js
359
- import Token from "markdown-it/lib/token.mjs";
360
- var checkboxRegex = /^ *\[([\sx])] /i;
361
- function taskLists(md2, options = { enabled: false, label: false, lineNumber: false }) {
362
- md2.core.ruler.after("inline", "task-lists", (state) => processToken(state, options));
363
- md2.renderer.rules.taskListItemCheckbox = (tokens) => {
364
- const token = tokens[0];
365
- const checkedAttribute = token.attrGet("checked") ? 'checked="" ' : "";
366
- const disabledAttribute = token.attrGet("disabled") ? 'disabled="" ' : "";
367
- const line = token.attrGet("line");
368
- const idAttribute = `id="${token.attrGet("id")}" `;
369
- const dataLineAttribute = line && options.lineNumber ? `data-line="${line}" ` : "";
370
- return `<input class="task-list-item-checkbox" type="checkbox" ${checkedAttribute}${disabledAttribute}${dataLineAttribute}${idAttribute}/>`;
371
- };
372
- md2.renderer.rules.taskListItemLabel_close = () => {
373
- return "</label>";
374
- };
375
- md2.renderer.rules.taskListItemLabel_open = (tokens) => {
376
- const token = tokens[0];
377
- const id = token.attrGet("id");
378
- return `<label for="${id}">`;
379
- };
380
- }
381
- function processToken(state, options) {
382
- const allTokens = state.tokens;
383
- for (let i = 2; i < allTokens.length; i++) {
384
- if (!isTodoItem(allTokens, i)) {
385
- continue;
386
- }
387
- todoify(allTokens[i], options);
388
- allTokens[i - 2].attrJoin("class", `task-list-item ${options.enabled ? " enabled" : ""}`);
389
- const parentToken = findParentToken(allTokens, i - 2);
390
- if (parentToken) {
391
- const classes = parentToken.attrGet("class") ?? "";
392
- if (!classes.match(/(^| )contains-task-list/)) {
393
- parentToken.attrJoin("class", "contains-task-list");
340
+ // node/virtual/configs.ts
341
+ import { isString } from "@antfu/utils";
342
+ var templateConfigs = {
343
+ id: "/@slidev/configs",
344
+ getContent: async ({ data, remote }, { md: md2 }) => {
345
+ function getTitle() {
346
+ if (isString(data.config.title)) {
347
+ const tokens = md2.parseInline(data.config.title, {});
348
+ return stringifyMarkdownTokens(tokens);
394
349
  }
350
+ return data.config.title;
395
351
  }
352
+ const config = {
353
+ ...data.config,
354
+ remote,
355
+ title: getTitle()
356
+ };
357
+ if (isString(config.info))
358
+ config.info = md2.render(config.info);
359
+ return `export default ${JSON.stringify(config)}`;
396
360
  }
397
- return false;
398
- }
399
- function findParentToken(tokens, index) {
400
- const targetLevel = tokens[index].level - 1;
401
- for (let currentTokenIndex = index - 1; currentTokenIndex >= 0; currentTokenIndex--) {
402
- if (tokens[currentTokenIndex].level === targetLevel) {
403
- return tokens[currentTokenIndex];
404
- }
405
- }
406
- return void 0;
407
- }
408
- function isTodoItem(tokens, index) {
409
- return isInline(tokens[index]) && isParagraph(tokens[index - 1]) && isListItem(tokens[index - 2]) && startsWithTodoMarkdown(tokens[index]);
410
- }
411
- function todoify(token, options) {
412
- if (token.children == null) {
413
- return;
414
- }
415
- const id = generateIdForToken(token);
416
- token.children.splice(0, 0, createCheckboxToken(token, options.enabled, id));
417
- token.children[1].content = token.children[1].content.replace(checkboxRegex, "");
418
- if (options.label) {
419
- token.children.splice(1, 0, createLabelBeginToken(id));
420
- token.children.push(createLabelEndToken());
361
+ };
362
+
363
+ // node/virtual/deprecated.ts
364
+ var templateLegacyRoutes = {
365
+ id: "/@slidev/routes",
366
+ getContent() {
367
+ return [
368
+ `export { slides } from '#slidev/slides'`,
369
+ `console.warn('[slidev] #slidev/routes is deprecated, use #slidev/slides instead')`
370
+ ].join("\n");
421
371
  }
422
- }
423
- function generateIdForToken(token) {
424
- if (token.map) {
425
- return `task-item-${token.map[0]}`;
426
- } else {
427
- return `task-item-${Math.ceil(Math.random() * (1e4 * 1e3) - 1e3)}`;
372
+ };
373
+ var templateLegacyTitles = {
374
+ id: "/@slidev/titles.md",
375
+ async getContent() {
376
+ return `
377
+ <script setup lang="ts">
378
+ import TitleRenderer from '#slidev/title-renderer'
379
+ defineProps<{ no: number | string }>()
380
+ console.warn('/@slidev/titles.md is deprecated, import from #slidev/title-renderer instead')
381
+ </script>
382
+
383
+ <TitleRenderer :no="no" />
384
+ `;
428
385
  }
386
+ };
387
+
388
+ // node/virtual/global-components.ts
389
+ import { existsSync as existsSync2 } from "node:fs";
390
+ import { join as join4 } from "node:path";
391
+ function createGlobalComponentTemplate(layer) {
392
+ return {
393
+ id: `/@slidev/global-components/${layer}`,
394
+ getContent({ roots }) {
395
+ const components = roots.flatMap((root) => {
396
+ if (layer === "top") {
397
+ return [
398
+ join4(root, "global.vue"),
399
+ join4(root, "global-top.vue"),
400
+ join4(root, "GlobalTop.vue")
401
+ ];
402
+ } else {
403
+ return [
404
+ join4(root, "global-bottom.vue"),
405
+ join4(root, "GlobalBottom.vue")
406
+ ];
407
+ }
408
+ }).filter((i) => existsSync2(i));
409
+ const imports = components.map((i, idx) => `import __n${idx} from '${toAtFS(i)}'`).join("\n");
410
+ const render = components.map((i, idx) => `h(__n${idx})`).join(",");
411
+ return `
412
+ ${imports}
413
+ import { h } from 'vue'
414
+ export default {
415
+ render() {
416
+ return [${render}]
429
417
  }
430
- function createCheckboxToken(token, enabled, id) {
431
- const checkbox = new Token("taskListItemCheckbox", "", 0);
432
- if (!enabled) {
433
- checkbox.attrSet("disabled", "true");
434
- }
435
- if (token.map) {
436
- checkbox.attrSet("line", token.map[0].toString());
437
- }
438
- checkbox.attrSet("id", id);
439
- const checkboxRegexResult = checkboxRegex.exec(token.content);
440
- const isChecked = checkboxRegexResult?.[1].toLowerCase() === "x";
441
- if (isChecked) {
442
- checkbox.attrSet("checked", "true");
443
- }
444
- return checkbox;
445
418
  }
446
- function createLabelBeginToken(id) {
447
- const labelBeginToken = new Token("taskListItemLabel_open", "", 1);
448
- labelBeginToken.attrSet("id", id);
449
- return labelBeginToken;
419
+ `;
420
+ }
421
+ };
450
422
  }
451
- function createLabelEndToken() {
452
- return new Token("taskListItemLabel_close", "", -1);
423
+ var templateNavControls = {
424
+ id: "/@slidev/custom-nav-controls",
425
+ getContent({ roots }) {
426
+ const components = roots.flatMap((root) => {
427
+ return [
428
+ join4(root, "custom-nav-controls.vue"),
429
+ join4(root, "CustomNavControls.vue")
430
+ ];
431
+ }).filter((i) => existsSync2(i));
432
+ const imports = components.map((i, idx) => `import __n${idx} from '${toAtFS(i)}'`).join("\n");
433
+ const render = components.map((i, idx) => `h(__n${idx})`).join(",");
434
+ return `
435
+ ${imports}
436
+ import { h } from 'vue'
437
+ export default {
438
+ render() {
439
+ return [${render}]
453
440
  }
454
- function isInline(token) {
455
- return token.type === "inline";
456
441
  }
457
- function isParagraph(token) {
458
- return token.type === "paragraph_open";
442
+ `;
443
+ }
444
+ };
445
+ var templateGlobalTop = createGlobalComponentTemplate("top");
446
+ var templateGlobalBottom = createGlobalComponentTemplate("bottom");
447
+
448
+ // node/virtual/layouts.ts
449
+ import { objectMap } from "@antfu/utils";
450
+ var templateLayouts = {
451
+ id: "/@slidev/layouts",
452
+ async getContent(_, { getLayouts }) {
453
+ const imports = [];
454
+ const layouts = objectMap(
455
+ await getLayouts(),
456
+ (k, v) => {
457
+ imports.push(`import __layout_${k} from "${toAtFS(v)}"`);
458
+ return [k, `__layout_${k}`];
459
+ }
460
+ );
461
+ return [
462
+ imports.join("\n"),
463
+ `export default {
464
+ ${Object.entries(layouts).map(([k, v]) => `"${k}": ${v}`).join(",\n")}
465
+ }`
466
+ ].join("\n\n");
467
+ }
468
+ };
469
+
470
+ // node/virtual/monaco-types.ts
471
+ import { builtinModules } from "node:module";
472
+ import { join as join5, resolve as resolve2 } from "node:path";
473
+ import fg2 from "fast-glob";
474
+ import { uniq as uniq2 } from "@antfu/utils";
475
+
476
+ // node/syntax/transform/monaco.ts
477
+ import { isTruthy } from "@antfu/utils";
478
+ import lz from "lz-string";
479
+ function transformMonaco(md2, enabled = true) {
480
+ if (!enabled)
481
+ return truncateMancoMark(md2);
482
+ md2 = md2.replace(
483
+ /^```(\w+?)\s*{monaco-diff}\s*?({.*?})?\s*?\n([\s\S]+?)^~~~\s*?\n([\s\S]+?)^```/mg,
484
+ (full, lang = "ts", options = "{}", code, diff) => {
485
+ lang = lang.trim();
486
+ options = options.trim() || "{}";
487
+ const encoded = lz.compressToBase64(code);
488
+ const encodedDiff = lz.compressToBase64(diff);
489
+ return `<Monaco code-lz="${encoded}" diff-lz="${encodedDiff}" lang="${lang}" v-bind="${options}" />`;
490
+ }
491
+ );
492
+ md2 = md2.replace(
493
+ /^```(\w+?)\s*{monaco}\s*?({.*?})?\s*?\n([\s\S]+?)^```/mg,
494
+ (full, lang = "ts", options = "{}", code) => {
495
+ lang = lang.trim();
496
+ options = options.trim() || "{}";
497
+ const encoded = lz.compressToBase64(code);
498
+ return `<Monaco code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
499
+ }
500
+ );
501
+ md2 = md2.replace(
502
+ /^```(\w+?)\s*{monaco-run}\s*?({.*?})?\s*?\n([\s\S]+?)^```/mg,
503
+ (full, lang = "ts", options = "{}", code) => {
504
+ lang = lang.trim();
505
+ options = options.trim() || "{}";
506
+ const encoded = lz.compressToBase64(code);
507
+ return `<Monaco runnable code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
508
+ }
509
+ );
510
+ return md2;
459
511
  }
460
- function isListItem(token) {
461
- return token.type === "list_item_open";
512
+ function scanMonacoModules(md2) {
513
+ const typeModules = /* @__PURE__ */ new Set();
514
+ md2.replace(
515
+ /^```(\w+?)\s*{monaco([\w:,-]*)}[\s\n]*([\s\S]+?)^```/mg,
516
+ (full, lang = "ts", options, code) => {
517
+ options = options || "";
518
+ lang = lang.trim();
519
+ if (lang === "ts" || lang === "typescript") {
520
+ Array.from(code.matchAll(/\s+from\s+(["'])([\/\w@-]+)\1/g)).map((i) => i[2]).filter(isTruthy).map((i) => typeModules.add(i));
521
+ }
522
+ return "";
523
+ }
524
+ );
525
+ return Array.from(typeModules);
462
526
  }
463
- function startsWithTodoMarkdown(token) {
464
- return checkboxRegex.test(token.content);
527
+ function truncateMancoMark(md2) {
528
+ return md2.replace(/{monaco([\w:,-]*)}/g, "");
465
529
  }
466
530
 
467
- // node/plugins/markdown.ts
468
- import { encode as encodePlantUml } from "plantuml-encoder";
469
- import Mdc from "markdown-it-mdc";
470
- import { codeToKeyedTokens } from "shiki-magic-move/core";
471
- import mila from "markdown-it-link-attributes";
472
- import mif from "markdown-it-footnote";
473
- import lz from "lz-string";
474
-
475
- // node/plugins/markdown-it-katex.ts
476
- import katex from "katex";
477
- function isValidDelim(state, pos) {
478
- const max = state.posMax;
479
- let can_open = true;
480
- let can_close = true;
481
- const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
482
- const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
483
- if (prevChar === 32 || prevChar === 9 || /* \t */
484
- nextChar >= 48 && nextChar <= 57)
485
- can_close = false;
486
- if (nextChar === 32 || nextChar === 9)
487
- can_open = false;
488
- return {
489
- can_open,
490
- can_close
491
- };
492
- }
493
- function math_inline(state, silent) {
494
- let match, token, res, pos;
495
- if (state.src[state.pos] !== "$")
496
- return false;
497
- res = isValidDelim(state, state.pos);
498
- if (!res.can_open) {
499
- if (!silent)
500
- state.pending += "$";
501
- state.pos += 1;
502
- return true;
503
- }
504
- const start = state.pos + 1;
505
- match = start;
506
- while ((match = state.src.indexOf("$", match)) !== -1) {
507
- pos = match - 1;
508
- while (state.src[pos] === "\\")
509
- pos -= 1;
510
- if ((match - pos) % 2 === 1)
511
- break;
512
- match += 1;
513
- }
514
- if (match === -1) {
515
- if (!silent)
516
- state.pending += "$";
517
- state.pos = start;
518
- return true;
519
- }
520
- if (match - start === 0) {
521
- if (!silent)
522
- state.pending += "$$";
523
- state.pos = start + 1;
524
- return true;
525
- }
526
- res = isValidDelim(state, match);
527
- if (!res.can_close) {
528
- if (!silent)
529
- state.pending += "$";
530
- state.pos = start;
531
- return true;
532
- }
533
- if (!silent) {
534
- token = state.push("math_inline", "math", 0);
535
- token.markup = "$";
536
- token.content = state.src.slice(start, match);
537
- }
538
- state.pos = match + 1;
539
- return true;
540
- }
541
- function math_block(state, start, end, silent) {
542
- let firstLine;
543
- let lastLine;
544
- let next;
545
- let lastPos;
546
- let found = false;
547
- let pos = state.bMarks[start] + state.tShift[start];
548
- let max = state.eMarks[start];
549
- if (pos + 2 > max)
550
- return false;
551
- if (state.src.slice(pos, pos + 2) !== "$$")
552
- return false;
553
- pos += 2;
554
- firstLine = state.src.slice(pos, max);
555
- if (silent)
556
- return true;
557
- if (firstLine.trim().slice(-2) === "$$") {
558
- firstLine = firstLine.trim().slice(0, -2);
559
- found = true;
560
- }
561
- for (next = start; !found; ) {
562
- next++;
563
- if (next >= end)
564
- break;
565
- pos = state.bMarks[next] + state.tShift[next];
566
- max = state.eMarks[next];
567
- if (pos < max && state.tShift[next] < state.blkIndent) {
568
- break;
531
+ // node/virtual/monaco-types.ts
532
+ var templateMonacoTypes = {
533
+ id: "/@slidev/monaco-types",
534
+ getContent: async ({ userRoot, data }) => {
535
+ const typesRoot = join5(userRoot, "snippets");
536
+ const files = await fg2(["**/*.ts", "**/*.mts", "**/*.cts"], { cwd: typesRoot });
537
+ let result = 'import { addFile } from "@slidev/client/setup/monaco.ts"\n';
538
+ for (const file of files) {
539
+ const url = `${toAtFS(resolve2(typesRoot, file))}?monaco-types&raw`;
540
+ result += `addFile(import(${JSON.stringify(url)}), ${JSON.stringify(file)})
541
+ `;
569
542
  }
570
- if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
571
- lastPos = state.src.slice(0, max).lastIndexOf("$$");
572
- lastLine = state.src.slice(pos, lastPos);
573
- found = true;
543
+ const deps = [...data.config.monacoTypesAdditionalPackages];
544
+ if (data.config.monacoTypesSource === "local")
545
+ deps.push(...scanMonacoModules(data.slides.map((s) => s.source.raw).join()));
546
+ function mapModuleNameToModule(moduleSpecifier) {
547
+ if (moduleSpecifier.startsWith("node:"))
548
+ return "node";
549
+ if (builtinModules.includes(moduleSpecifier))
550
+ return "node";
551
+ const mainPackageName = moduleSpecifier.split("/")[0];
552
+ if (builtinModules.includes(mainPackageName) && !mainPackageName.startsWith("@"))
553
+ return "node";
554
+ const [a = "", b = ""] = moduleSpecifier.split("/");
555
+ const moduleName = a.startsWith("@") ? `${a}/${b}` : a;
556
+ return moduleName;
574
557
  }
575
- }
576
- state.line = next + 1;
577
- const token = state.push("math_block", "math", 0);
578
- token.block = true;
579
- token.content = (firstLine && firstLine.trim() ? `${firstLine}
580
- ` : "") + state.getLines(start + 1, next, state.tShift[start], true) + (lastLine && lastLine.trim() ? lastLine : "");
581
- token.map = [start, state.line];
582
- token.markup = "$$";
583
- return true;
584
- }
585
- function math_plugin(md2, options) {
586
- options = options || {};
587
- const katexInline = function(latex) {
588
- options.displayMode = false;
589
- try {
590
- return katex.renderToString(latex, options);
591
- } catch (error) {
592
- if (options.throwOnError)
593
- console.warn(error);
594
- return latex;
558
+ for (const specifier of uniq2(deps)) {
559
+ if (specifier[0] === ".")
560
+ continue;
561
+ const moduleName = mapModuleNameToModule(specifier);
562
+ result += `import(${JSON.stringify(`/@slidev-monaco-types/resolve?pkg=${moduleName}`)})
563
+ `;
595
564
  }
596
- };
597
- const inlineRenderer = function(tokens, idx) {
598
- return katexInline(tokens[idx].content);
599
- };
600
- const katexBlock = function(latex) {
601
- options.displayMode = true;
602
- try {
603
- return `<p>${katex.renderToString(latex, options)}</p>`;
604
- } catch (error) {
605
- if (options.throwOnError)
606
- console.warn(error);
607
- return latex;
565
+ return result;
566
+ }
567
+ };
568
+
569
+ // node/virtual/setups.ts
570
+ import { existsSync as existsSync3 } from "node:fs";
571
+ import { join as join6 } from "node:path";
572
+ function createSetupTemplate(name) {
573
+ return {
574
+ id: `/@slidev/setups/${name}`,
575
+ getContent({ roots }) {
576
+ const setups = roots.flatMap((i) => {
577
+ const path2 = join6(i, "setup", name);
578
+ return [".ts", ".mts", ".js", ".mjs"].map((ext) => path2 + ext);
579
+ }).filter((i) => existsSync3(i));
580
+ const imports = [];
581
+ setups.forEach((path2, idx) => {
582
+ imports.push(`import __n${idx} from '${toAtFS(path2)}'`);
583
+ });
584
+ imports.push(`export default [${setups.map((_, idx) => `__n${idx}`).join(",")}]`);
585
+ return imports.join("\n");
608
586
  }
609
587
  };
610
- const blockRenderer = function(tokens, idx) {
611
- return `${katexBlock(tokens[idx].content)}
612
- `;
613
- };
614
- md2.inline.ruler.after("escape", "math_inline", math_inline);
615
- md2.block.ruler.after("blockquote", "math_block", math_block, {
616
- alt: ["paragraph", "reference", "blockquote", "list"]
617
- });
618
- md2.renderer.rules.math_inline = inlineRenderer;
619
- md2.renderer.rules.math_block = blockRenderer;
620
588
  }
589
+ var setupModules = ["shiki", "code-runners", "monaco", "mermaid", "main", "root", "shortcuts"];
590
+ var templateSetups = setupModules.map(createSetupTemplate);
621
591
 
622
- // node/plugins/markdown-it-prism.ts
623
- import { createRequire } from "node:module";
624
- import Prism from "prismjs";
625
- import loadLanguages from "prismjs/components/index.js";
626
- import * as htmlparser2 from "htmlparser2";
627
- var require2 = createRequire(import.meta.url);
628
- var Tag = class {
629
- tagname;
630
- attributes;
631
- constructor(tagname, attributes) {
632
- this.tagname = tagname;
633
- this.attributes = attributes;
592
+ // node/setups/shiki.ts
593
+ import fs3 from "node:fs/promises";
594
+ async function loadShikiSetups(clientRoot, roots) {
595
+ const result = await loadSetups(
596
+ clientRoot,
597
+ roots,
598
+ "shiki.ts",
599
+ {
600
+ /** @deprecated */
601
+ async loadTheme(path2) {
602
+ 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.");
603
+ return JSON.parse(await fs3.readFile(path2, "utf-8"));
604
+ }
605
+ },
606
+ {},
607
+ false
608
+ );
609
+ if ("theme" in result && "themes" in result)
610
+ delete result.theme;
611
+ if (result.theme && typeof result.theme !== "string" && !result.theme.name && !result.theme.tokenColors) {
612
+ result.themes = result.theme;
613
+ delete result.theme;
634
614
  }
635
- asOpen() {
636
- return `<${this.tagname} ${Object.entries(this.attributes).map(([key, value]) => `${key}="${value}"`).join(" ")}>`;
615
+ if (!result.theme && !result.themes) {
616
+ result.themes = {
617
+ dark: "vitesse-dark",
618
+ light: "vitesse-light"
619
+ };
637
620
  }
638
- asClosed() {
639
- return `</${this.tagname}>`;
621
+ if (result.themes)
622
+ result.defaultColor = false;
623
+ return result;
624
+ }
625
+
626
+ // node/virtual/shiki.ts
627
+ var templateShiki = {
628
+ id: "/@slidev/shiki",
629
+ getContent: async ({ clientRoot, roots }) => {
630
+ const options = await loadShikiSetups(clientRoot, roots);
631
+ const langs = await resolveLangs(options.langs || ["javascript", "typescript", "html", "css"]);
632
+ const resolvedThemeOptions = "themes" in options ? {
633
+ themes: Object.fromEntries(await Promise.all(
634
+ Object.entries(options.themes).map(async ([name, value]) => [name, await resolveTheme(value)])
635
+ ))
636
+ } : {
637
+ theme: await resolveTheme(options.theme || "vitesse-dark")
638
+ };
639
+ const themes = resolvedThemeOptions.themes ? Object.values(resolvedThemeOptions.themes) : [resolvedThemeOptions.theme];
640
+ 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 };
641
+ async function normalizeGetter(p) {
642
+ return Promise.resolve(typeof p === "function" ? p() : p).then((r) => r.default || r);
643
+ }
644
+ async function resolveLangs(langs2) {
645
+ return Array.from(new Set((await Promise.all(
646
+ langs2.map(async (lang) => await normalizeGetter(lang).then((r) => Array.isArray(r) ? r : [r]))
647
+ )).flat()));
648
+ }
649
+ async function resolveTheme(theme) {
650
+ return typeof theme === "string" ? theme : await normalizeGetter(theme);
651
+ }
652
+ const langsInit = await Promise.all(
653
+ langs.map(async (lang) => typeof lang === "string" ? `import('${await resolveImportUrl(`shiki/langs/${lang}.mjs`)}')` : JSON.stringify(lang))
654
+ );
655
+ const themesInit = await Promise.all(themes.map(async (theme) => typeof theme === "string" ? `import('${await resolveImportUrl(`shiki/themes/${theme}.mjs`)}')` : JSON.stringify(theme)));
656
+ const langNames = langs.flatMap((lang) => typeof lang === "string" ? lang : lang.name);
657
+ const lines = [];
658
+ lines.push(
659
+ `import { getHighlighterCore } from "${await resolveImportUrl("shiki/core")}"`,
660
+ `export { shikiToMonaco } from "${await resolveImportUrl("@shikijs/monaco")}"`,
661
+ `export const languages = ${JSON.stringify(langNames)}`,
662
+ `export const themes = ${JSON.stringify(themeOptionsNames.themes || themeOptionsNames.theme)}`,
663
+ "export const shiki = getHighlighterCore({",
664
+ ` themes: [${themesInit.join(",")}],`,
665
+ ` langs: [${langsInit.join(",")}],`,
666
+ ` loadWasm: import('${await resolveImportUrl("shiki/wasm")}'),`,
667
+ "})"
668
+ );
669
+ return lines.join("\n");
640
670
  }
641
671
  };
642
- var DEFAULTS = {
643
- plugins: [],
644
- init: () => {
645
- },
646
- defaultLanguageForUnknown: void 0,
647
- defaultLanguageForUnspecified: void 0,
648
- defaultLanguage: void 0
649
- };
650
- function loadPrismLang(lang) {
651
- if (!lang)
652
- return void 0;
653
- let langObject = Prism.languages[lang];
654
- if (langObject === void 0) {
655
- loadLanguages([lang]);
656
- langObject = Prism.languages[lang];
657
- }
658
- return langObject;
659
- }
660
- function loadPrismPlugin(name) {
661
- try {
662
- require2(`prismjs/plugins/${name}/prism-${name}`);
663
- } catch (e) {
664
- throw new Error(`Cannot load Prism plugin "${name}". Please check the spelling.`);
665
- }
666
- }
667
- function selectLanguage(options, lang) {
668
- let langToUse = lang;
669
- if (langToUse === "" && options.defaultLanguageForUnspecified !== void 0)
670
- langToUse = options.defaultLanguageForUnspecified;
671
- let prismLang = loadPrismLang(langToUse);
672
- if (prismLang === void 0 && options.defaultLanguageForUnknown !== void 0) {
673
- langToUse = options.defaultLanguageForUnknown;
674
- prismLang = loadPrismLang(langToUse);
672
+
673
+ // node/virtual/slides.ts
674
+ var VIRTUAL_SLIDE_PREFIX = "/@slidev/slides/";
675
+ var templateSlides = {
676
+ id: "/@slidev/slides",
677
+ async getContent({ data }, { getLayouts }) {
678
+ const layouts = await getLayouts();
679
+ const imports = [
680
+ `import { shallowRef } from 'vue'`,
681
+ `import * as __layout__error from '${layouts.error}'`
682
+ ];
683
+ const slides = data.slides.map((_, idx) => {
684
+ const no = idx + 1;
685
+ imports.push(`import { meta as f${no} } from '${VIRTUAL_SLIDE_PREFIX}${no}.frontmatter'`);
686
+ return `{
687
+ no: ${no},
688
+ meta: f${no},
689
+ component: async () => {
690
+ try {
691
+ return await import('${VIRTUAL_SLIDE_PREFIX}${no}.md')
692
+ }
693
+ catch {
694
+ return __layout__error
695
+ }
696
+ },
697
+ }`;
698
+ });
699
+ return [
700
+ ...imports,
701
+ `const data = [
702
+ ${slides.join(",\n")}
703
+ ]`,
704
+ `if (import.meta.hot) {`,
705
+ ` import.meta.hot.data.slides ??= shallowRef()`,
706
+ ` import.meta.hot.data.slides.value = data`,
707
+ ` import.meta.hot.accept()`,
708
+ `}`,
709
+ `export const slides = import.meta.hot ? import.meta.hot.data.slides : shallowRef(data)`
710
+ ].join("\n");
675
711
  }
676
- return [langToUse, prismLang];
677
- }
678
- function highlight(markdownit, options, text, lang) {
679
- const [langToUse, prismLang] = selectLanguage(options, lang);
680
- let code = text.trimEnd();
681
- code = prismLang ? highlightPrism(code, prismLang, langToUse) : markdownit.utils.escapeHtml(code);
682
- code = code.split(/\r?\n/g).map((line) => `<span class="line">${line}</span>`).join("\n");
683
- const classAttribute = langToUse ? ` class="slidev-code ${markdownit.options.langPrefix}${markdownit.utils.escapeHtml(langToUse)}"` : "";
684
- return escapeVueInCode(`<pre${classAttribute}><code>${code}</code></pre>`);
685
- }
686
- function highlightPrism(code, prismLang, langToUse) {
687
- const openTags = [];
688
- const parser2 = new htmlparser2.Parser({
689
- onopentag(tagname, attributes) {
690
- openTags.push(new Tag(tagname, attributes));
691
- },
692
- onclosetag() {
693
- openTags.pop();
694
- }
695
- });
696
- code = Prism.highlight(code, prismLang, langToUse);
697
- code = code.split(/\r?\n/g).map((line) => {
698
- const prefix = openTags.map((tag) => tag.asOpen()).join("");
699
- parser2.write(line);
700
- const postfix = openTags.reverse().map((tag) => tag.asClosed()).join("");
701
- return prefix + line + postfix;
702
- }).join("\n");
703
- parser2.end();
704
- return code;
705
- }
706
- function checkLanguageOption(options, optionName) {
707
- const language = options[optionName];
708
- if (language !== void 0 && loadPrismLang(language) === void 0)
709
- throw new Error(`Bad option ${optionName}: There is no Prism language '${language}'.`);
710
- }
711
- function markdownItPrism(markdownit, useroptions) {
712
- const options = Object.assign({}, DEFAULTS, useroptions);
713
- checkLanguageOption(options, "defaultLanguage");
714
- checkLanguageOption(options, "defaultLanguageForUnknown");
715
- checkLanguageOption(options, "defaultLanguageForUnspecified");
716
- options.defaultLanguageForUnknown = options.defaultLanguageForUnknown || options.defaultLanguage;
717
- options.defaultLanguageForUnspecified = options.defaultLanguageForUnspecified || options.defaultLanguage;
718
- options.plugins.forEach(loadPrismPlugin);
719
- options.init(Prism);
720
- markdownit.options.highlight = (text, lang) => highlight(markdownit, options, text, lang);
721
- }
712
+ };
722
713
 
723
- // node/plugins/transformSnippet.ts
724
- import path from "node:path";
725
- import fs3 from "fs-extra";
726
- function dedent(text) {
727
- const lines = text.split("\n");
728
- const minIndentLength = lines.reduce((acc, line) => {
729
- for (let i = 0; i < line.length; i++) {
730
- if (line[i] !== " " && line[i] !== " ")
731
- return Math.min(i, acc);
714
+ // node/virtual/styles.ts
715
+ import { join as join7 } from "node:path";
716
+ import { existsSync as existsSync4 } from "node:fs";
717
+ var templateStyle = {
718
+ id: "/@slidev/styles",
719
+ getContent: async ({ data, clientRoot, roots }) => {
720
+ function resolveUrlOfClient(name) {
721
+ return toAtFS(join7(clientRoot, name));
732
722
  }
733
- return acc;
734
- }, Number.POSITIVE_INFINITY);
735
- if (minIndentLength < Number.POSITIVE_INFINITY)
736
- return lines.map((x) => x.slice(minIndentLength)).join("\n");
737
- return text;
738
- }
739
- function testLine(line, regexp, regionName, end = false) {
740
- const [full, tag, name] = regexp.exec(line.trim()) || [];
741
- return full && tag && name === regionName && tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/);
742
- }
743
- function findRegion(lines, regionName) {
744
- const regionRegexps = [
745
- /^\/\/ ?#?((?:end)?region) ([\w*-]+)$/,
746
- // javascript, typescript, java
747
- /^\/\* ?#((?:end)?region) ([\w*-]+) ?\*\/$/,
748
- // css, less, scss
749
- /^#pragma ((?:end)?region) ([\w*-]+)$/,
750
- // C, C++
751
- /^<!-- #?((?:end)?region) ([\w*-]+) -->$/,
752
- // HTML, markdown
753
- /^#((?:End )Region) ([\w*-]+)$/,
754
- // Visual Basic
755
- /^::#((?:end)region) ([\w*-]+)$/,
756
- // Bat
757
- /^# ?((?:end)?region) ([\w*-]+)$/
758
- // C#, PHP, Powershell, Python, perl & misc
759
- ];
760
- let regexp = null;
761
- let start = -1;
762
- for (const [lineId, line] of lines.entries()) {
763
- if (regexp === null) {
764
- for (const reg of regionRegexps) {
765
- if (testLine(line, reg, regionName)) {
766
- start = lineId + 1;
767
- regexp = reg;
768
- break;
723
+ const imports = [
724
+ `import "${resolveUrlOfClient("styles/vars.css")}"`,
725
+ `import "${resolveUrlOfClient("styles/index.css")}"`,
726
+ `import "${resolveUrlOfClient("styles/code.css")}"`,
727
+ `import "${resolveUrlOfClient("styles/katex.css")}"`,
728
+ `import "${resolveUrlOfClient("styles/transitions.css")}"`
729
+ ];
730
+ for (const root of roots) {
731
+ const styles = [
732
+ join7(root, "styles", "index.ts"),
733
+ join7(root, "styles", "index.js"),
734
+ join7(root, "styles", "index.css"),
735
+ join7(root, "styles.css"),
736
+ join7(root, "style.css")
737
+ ];
738
+ for (const style of styles) {
739
+ if (existsSync4(style)) {
740
+ imports.push(`import "${toAtFS(style)}"`);
741
+ continue;
769
742
  }
770
743
  }
771
- } else if (testLine(line, regexp, regionName, true)) {
772
- return { start, end: lineId, regexp };
773
744
  }
745
+ if (data.features.katex)
746
+ imports.push(`import "${await resolveImportUrl("katex/dist/katex.min.css")}"`);
747
+ if (data.config.highlighter === "shiki") {
748
+ imports.push(
749
+ `import "${await resolveImportUrl("@shikijs/vitepress-twoslash/style.css")}"`,
750
+ `import "${resolveUrlOfClient("styles/shiki-twoslash.css")}"`
751
+ );
752
+ }
753
+ if (data.config.css === "unocss") {
754
+ imports.unshift(
755
+ `import "${await resolveImportUrl("@unocss/reset/tailwind.css")}"`,
756
+ 'import "uno:preflights.css"',
757
+ 'import "uno:typography.css"',
758
+ 'import "uno:shortcuts.css"'
759
+ );
760
+ imports.push('import "uno.css"');
761
+ }
762
+ return imports.join("\n");
774
763
  }
775
- return null;
776
- }
777
- function transformSnippet(md2, options, id) {
778
- const slideId = id.match(/(\d+)\.md$/)?.[1];
779
- if (!slideId)
780
- return md2;
781
- const data = options.data;
782
- const slideInfo = data.slides[+slideId - 1];
783
- const dir = path.dirname(slideInfo.source?.filepath ?? options.entry ?? options.userRoot);
784
- return md2.replace(
785
- /^<<< *(.+?)(#[\w-]+)? *(?: (\S+?))? *(\{.*)?$/mg,
786
- (full, filepath = "", regionName = "", lang = "", meta = "") => {
787
- const firstLine = `\`\`\`${lang || path.extname(filepath).slice(1)} ${meta}`;
788
- const src = /^\@[\/]/.test(filepath) ? path.resolve(options.userRoot, filepath.slice(2)) : path.resolve(dir, filepath);
789
- data.watchFiles.push(src);
790
- const isAFile = fs3.statSync(src).isFile();
791
- if (!fs3.existsSync(src) || !isAFile) {
792
- throw new Error(isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`);
793
- }
794
- let content = fs3.readFileSync(src, "utf8");
795
- slideInfo.snippetsUsed ??= {};
796
- slideInfo.snippetsUsed[src] = content;
797
- if (regionName) {
798
- const lines = content.split(/\r?\n/);
799
- const region = findRegion(lines, regionName.slice(1));
800
- if (region) {
801
- content = dedent(
802
- lines.slice(region.start, region.end).filter((line) => !region.regexp.test(line.trim())).join("\n")
803
- );
804
- }
764
+ };
765
+
766
+ // node/virtual/titles.ts
767
+ var templateTitleRendererMd = {
768
+ id: "/@slidev/title-renderer.md",
769
+ async getContent({ data }) {
770
+ const lines = data.slides.map(({ title }, i) => `<template ${i === 0 ? "v-if" : "v-else-if"}="+no === ${i + 1}">
771
+
772
+ ${title}
773
+
774
+ </template>`);
775
+ lines.push(`<script setup lang="ts">defineProps<{ no: number | string }>()</script>`);
776
+ return lines.join("\n");
777
+ }
778
+ };
779
+ var templateTitleRenderer = {
780
+ id: "/@slidev/title-renderer",
781
+ async getContent() {
782
+ return 'export { default } from "/@slidev/title-renderer.md"';
783
+ }
784
+ };
785
+
786
+ // node/virtual/index.ts
787
+ var templates = [
788
+ templateShiki,
789
+ templateMonacoTypes,
790
+ templateConfigs,
791
+ templateStyle,
792
+ templateGlobalBottom,
793
+ templateGlobalTop,
794
+ templateNavControls,
795
+ templateSlides,
796
+ templateLayouts,
797
+ templateTitleRenderer,
798
+ templateTitleRendererMd,
799
+ ...templateSetups,
800
+ // Deprecated
801
+ templateLegacyRoutes,
802
+ templateLegacyTitles
803
+ ];
804
+
805
+ // node/vite/loaders.ts
806
+ var regexId = /^\/\@slidev\/slide\/(\d+)\.(md|json)(?:\?import)?$/;
807
+ var regexIdQuery = /(\d+?)\.(md|json|frontmatter)$/;
808
+ var templateInjectionMarker = "/* @slidev-injection */";
809
+ var templateImportContextUtils = `import {
810
+ useSlideContext,
811
+ provideFrontmatter as _provideFrontmatter,
812
+ frontmatterToProps as _frontmatterToProps,
813
+ } from "@slidev/client/context.ts"`.replace(/\n\s*/g, " ");
814
+ var templateInitContext = `const { $slidev, $nav, $clicksContext, $clicks, $page, $renderContext, $frontmatter } = useSlideContext()`;
815
+ function getBodyJson(req) {
816
+ return new Promise((resolve4, reject) => {
817
+ let body = "";
818
+ req.on("data", (chunk) => body += chunk);
819
+ req.on("error", reject);
820
+ req.on("end", () => {
821
+ try {
822
+ resolve4(JSON.parse(body) || {});
823
+ } catch (e) {
824
+ reject(e);
805
825
  }
806
- return `${firstLine}
807
- ${content}
808
- \`\`\``;
809
- }
826
+ });
827
+ });
828
+ }
829
+ var md = Markdown({ html: true });
830
+ md.use(mila, {
831
+ attrs: {
832
+ target: "_blank",
833
+ rel: "noopener"
834
+ }
835
+ });
836
+ function renderNote(text = "") {
837
+ let clickCount = 0;
838
+ const html = md.render(
839
+ text.replace(/\[click(?::(\d+))?\]/gi, (_, count = 1) => {
840
+ clickCount += Number(count);
841
+ return `<span class="slidev-note-click-mark" data-clicks="${clickCount}"></span>`;
842
+ })
810
843
  );
811
- }
812
-
813
- // node/plugins/markdown.ts
814
- var shiki;
815
- var shikiOptions;
816
- async function createMarkdownPlugin(options, { markdown: mdOptions }) {
817
- const { data: { config }, roots, mode, entry, clientRoot } = options;
818
- const setups = [];
819
- const entryPath = slash(entry);
820
- if (config.highlighter === "shiki") {
821
- const [
822
- options2,
823
- { getHighlighter, bundledLanguages },
824
- markdownItShiki,
825
- transformerTwoslash
826
- ] = await Promise.all([
827
- loadShikiSetups(clientRoot, roots),
828
- import("shiki").then(({ getHighlighter: getHighlighter2, bundledLanguages: bundledLanguages2 }) => ({ bundledLanguages: bundledLanguages2, getHighlighter: getHighlighter2 })),
829
- import("@shikijs/markdown-it/core").then(({ fromHighlighter }) => fromHighlighter),
830
- import("@shikijs/vitepress-twoslash").then(({ transformerTwoslash: transformerTwoslash2 }) => transformerTwoslash2)
831
- ]);
832
- shikiOptions = options2;
833
- shiki = await getHighlighter({
834
- ...options2,
835
- langs: options2.langs ?? Object.keys(bundledLanguages),
836
- themes: "themes" in options2 ? Object.values(options2.themes) : [options2.theme]
837
- });
838
- const transformers = [
839
- ...options2.transformers || [],
840
- transformerTwoslash({
841
- explicitTrigger: true,
842
- twoslashOptions: {
843
- handbookOptions: {
844
- noErrorValidation: true
845
- }
846
- }
847
- }),
848
- {
849
- pre(pre) {
850
- this.addClassToHast(pre, "slidev-code");
851
- delete pre.properties.tabindex;
852
- },
853
- postprocess(code) {
854
- return escapeVueInCode(code);
855
- }
856
- }
857
- ];
858
- const plugin = markdownItShiki(shiki, {
859
- ...options2,
860
- transformers
861
- });
862
- setups.push((md2) => md2.use(plugin));
863
- } else {
864
- setups.push((md2) => md2.use(markdownItPrism));
865
- }
866
- if (config.mdc)
867
- setups.push((md2) => md2.use(Mdc));
868
- const KatexOptions = await loadSetups(options.clientRoot, roots, "katex.ts", {}, { strict: false }, false);
869
- return Markdown({
870
- include: [/\.md$/],
871
- wrapperClasses: "",
872
- headEnabled: false,
873
- frontmatter: false,
874
- escapeCodeTagInterpolation: false,
875
- markdownItOptions: {
876
- quotes: `""''`,
877
- html: true,
878
- xhtmlOut: true,
879
- linkify: true,
880
- ...mdOptions?.markdownItOptions
881
- },
882
- ...mdOptions,
883
- markdownItSetup(md2) {
884
- md2.use(mila, {
885
- attrs: {
886
- target: "_blank",
887
- rel: "noopener"
888
- }
889
- });
890
- md2.use(mif);
891
- md2.use(taskLists, { enabled: true, lineNumber: true, label: true });
892
- md2.use(math_plugin, KatexOptions);
893
- setups.forEach((i) => i(md2));
894
- mdOptions?.markdownItSetup?.(md2);
895
- },
896
- transforms: {
897
- before(code, id) {
898
- if (id === entryPath)
899
- return "";
900
- const monaco = config.monaco === true || config.monaco === mode ? transformMarkdownMonaco : truncateMancoMark;
901
- if (config.highlighter === "shiki")
902
- code = transformMagicMove(code, shiki, shikiOptions);
903
- code = transformSlotSugar(code);
904
- code = transformSnippet(code, options, id);
905
- code = transformMermaid(code);
906
- code = transformPlantUml(code, config.plantUmlServer);
907
- code = monaco(code);
908
- code = transformHighlighter(code);
909
- code = transformPageCSS(code, id);
910
- code = transformKaTex(code);
911
- return code;
912
- }
913
- }
914
- });
915
- }
916
- function transformKaTex(md2) {
917
- return md2.replace(
918
- /^\$\$(?:\s*{([\d\w*,\|-]+)}\s*?({.*?})?\s*?)?\n([\s\S]+?)^\$\$/mg,
919
- (full, rangeStr = "", options = "", code) => {
920
- const ranges = !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
921
- code = code.trimEnd();
922
- options = options.trim() || "{}";
923
- return `<KaTexBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
924
-
925
- $$
926
- ${code}
927
- $$
928
- </KaTexBlockWrapper>
929
- `;
930
- }
931
- );
932
- }
933
- function transformMarkdownMonaco(md2) {
934
- md2 = md2.replace(
935
- /^```(\w+?)\s*{monaco-diff}\s*?({.*?})?\s*?\n([\s\S]+?)^~~~\s*?\n([\s\S]+?)^```/mg,
936
- (full, lang = "ts", options = "{}", code, diff) => {
937
- lang = lang.trim();
938
- options = options.trim() || "{}";
939
- const encoded = lz.compressToBase64(code);
940
- const encodedDiff = lz.compressToBase64(diff);
941
- return `<Monaco code-lz="${encoded}" diff-lz="${encodedDiff}" lang="${lang}" v-bind="${options}" />`;
942
- }
943
- );
944
- md2 = md2.replace(
945
- /^```(\w+?)\s*{monaco}\s*?({.*?})?\s*?\n([\s\S]+?)^```/mg,
946
- (full, lang = "ts", options = "{}", code) => {
947
- lang = lang.trim();
948
- options = options.trim() || "{}";
949
- const encoded = lz.compressToBase64(code);
950
- return `<Monaco code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
951
- }
952
- );
953
- md2 = md2.replace(
954
- /^```(\w+?)\s*{monaco-run}\s*?({.*?})?\s*?\n([\s\S]+?)^```/mg,
955
- (full, lang = "ts", options = "{}", code) => {
956
- lang = lang.trim();
957
- options = options.trim() || "{}";
958
- const encoded = lz.compressToBase64(code);
959
- return `<Monaco runnable code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
960
- }
961
- );
962
- return md2;
963
- }
964
- function scanMonacoModules(md2) {
965
- const typeModules = /* @__PURE__ */ new Set();
966
- md2.replace(
967
- /^```(\w+?)\s*{monaco([\w:,-]*)}[\s\n]*([\s\S]+?)^```/mg,
968
- (full, lang = "ts", options, code) => {
969
- options = options || "";
970
- lang = lang.trim();
971
- if (lang === "ts" || lang === "typescript") {
972
- Array.from(code.matchAll(/\s+from\s+(["'])([\/\w@-]+)\1/g)).map((i) => i[2]).filter(isTruthy).map((i) => typeModules.add(i));
973
- }
974
- return "";
975
- }
976
- );
977
- return Array.from(typeModules);
978
- }
979
- function truncateMancoMark(md2) {
980
- return md2.replace(/{monaco.*?}/g, "");
981
- }
982
- function transformSlotSugar(md2) {
983
- const lines = md2.split(/\r?\n/g);
984
- let prevSlot = false;
985
- const { isLineInsideCodeblocks } = getCodeBlocks(md2);
986
- lines.forEach((line, idx) => {
987
- if (isLineInsideCodeblocks(idx))
988
- return;
989
- const match = line.trimEnd().match(/^::\s*([\w\.\-\:]+)\s*::$/);
990
- if (match) {
991
- lines[idx] = `${prevSlot ? "\n\n</template>\n" : "\n"}<template v-slot:${match[1]}="slotProps">
992
- `;
993
- prevSlot = true;
994
- }
995
- });
996
- if (prevSlot)
997
- lines[lines.length - 1] += "\n\n</template>";
998
- return lines.join("\n");
999
- }
1000
- var reMagicMoveBlock = /^````(?:md|markdown) magic-move(?:[ ]*(\{.*?\})?([^\n]*?))?\n([\s\S]+?)^````$/mg;
1001
- var reCodeBlock = /^```(\w+?)(?:\s*{([\d\w*,\|-]+)}\s*?({.*?})?(.*?))?\n([\s\S]+?)^```$/mg;
1002
- function transformMagicMove(md2, shiki2, shikiOptions2) {
1003
- return md2.replace(
1004
- reMagicMoveBlock,
1005
- (full, options = "{}", _attrs = "", body) => {
1006
- if (!shiki2 || !shikiOptions2)
1007
- throw new Error("Shiki is required for Magic Move. You may need to set `highlighter: shiki` in your Slidev config.");
1008
- const matches = Array.from(body.matchAll(reCodeBlock));
1009
- if (!matches.length)
1010
- throw new Error("Magic Move block must contain at least one code block");
1011
- const ranges = matches.map((i) => normalizeRangeStr(i[2]));
1012
- const steps = matches.map(
1013
- (i) => codeToKeyedTokens(shiki2, i[5].trimEnd(), {
1014
- ...shikiOptions2,
1015
- lang: i[1]
1016
- })
1017
- );
1018
- const compressed = lz.compressToBase64(JSON.stringify(steps));
1019
- return `<ShikiMagicMove v-bind="${options}" steps-lz="${compressed}" :step-ranges='${JSON.stringify(ranges)}' />`;
1020
- }
1021
- );
1022
- }
1023
- function transformHighlighter(md2) {
1024
- return md2.replace(
1025
- reCodeBlock,
1026
- (full, lang = "", rangeStr = "", options = "", attrs = "", code) => {
1027
- const ranges = normalizeRangeStr(rangeStr);
1028
- code = code.trimEnd();
1029
- options = options.trim() || "{}";
1030
- return `
1031
- <CodeBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
1032
-
1033
- \`\`\`${lang}${attrs}
1034
- ${code}
1035
- \`\`\`
1036
-
1037
- </CodeBlockWrapper>`;
1038
- }
1039
- );
1040
- }
1041
- function normalizeRangeStr(rangeStr = "") {
1042
- return !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
1043
- }
1044
- function getCodeBlocks(md2) {
1045
- const codeblocks = Array.from(md2.matchAll(/^```[\s\S]*?^```/mg)).map((m) => {
1046
- const start = m.index;
1047
- const end = m.index + m[0].length;
1048
- const startLine = md2.slice(0, start).match(/\n/g)?.length || 0;
1049
- const endLine = md2.slice(0, end).match(/\n/g)?.length || 0;
1050
- return [start, end, startLine, endLine];
1051
- });
1052
- return {
1053
- codeblocks,
1054
- isInsideCodeblocks(idx) {
1055
- return codeblocks.some(([s, e]) => s <= idx && idx <= e);
1056
- },
1057
- isLineInsideCodeblocks(line) {
1058
- return codeblocks.some(([, , s, e]) => s <= line && line <= e);
1059
- }
1060
- };
1061
- }
1062
- function transformPageCSS(md2, id) {
1063
- const page = id.match(/(\d+)\.md$/)?.[1];
1064
- if (!page)
1065
- return md2;
1066
- const { isInsideCodeblocks } = getCodeBlocks(md2);
1067
- const result = md2.replace(
1068
- /(\n<style[^>]*?>)([\s\S]+?)(<\/style>)/g,
1069
- (full, start, css, end, index) => {
1070
- if (index < 0 || isInsideCodeblocks(index))
1071
- return full;
1072
- if (!start.includes("scoped"))
1073
- start = start.replace("<style", "<style scoped");
1074
- return `${start}
1075
- ${css}${end}`;
1076
- }
1077
- );
1078
- return result;
1079
- }
1080
- function transformMermaid(md2) {
1081
- return md2.replace(/^```mermaid\s*?({.*?})?\n([\s\S]+?)\n```/mg, (full, options = "", code = "") => {
1082
- code = code.trim();
1083
- options = options.trim() || "{}";
1084
- const encoded = lz.compressToBase64(code);
1085
- return `<Mermaid code-lz="${encoded}" v-bind="${options}" />`;
1086
- });
1087
- }
1088
- function transformPlantUml(md2, server) {
1089
- return md2.replace(/^```plantuml\s*?({.*?})?\n([\s\S]+?)\n```/mg, (full, options = "", content = "") => {
1090
- const code = encodePlantUml(content.trim());
1091
- options = options.trim() || "{}";
1092
- return `<PlantUml :code="'${code}'" :server="'${server}'" v-bind="${options}" />`;
1093
- });
1094
- }
1095
- function escapeVueInCode(md2) {
1096
- return md2.replace(/{{/g, "&lbrace;&lbrace;");
1097
- }
1098
- async function loadShikiSetups(clientRoot, roots) {
1099
- const result = await loadSetups(
1100
- clientRoot,
1101
- roots,
1102
- "shiki.ts",
1103
- {
1104
- /** @deprecated */
1105
- async loadTheme(path2) {
1106
- 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.");
1107
- return JSON.parse(await fs4.readFile(path2, "utf-8"));
1108
- }
1109
- },
1110
- {},
1111
- false
1112
- );
1113
- if ("theme" in result && "themes" in result)
1114
- delete result.theme;
1115
- if (result.theme && typeof result.theme !== "string" && !result.theme.name && !result.theme.tokenColors) {
1116
- result.themes = result.theme;
1117
- delete result.theme;
1118
- }
1119
- if (!result.theme && !result.themes) {
1120
- result.themes = {
1121
- dark: "vitesse-dark",
1122
- light: "vitesse-light"
1123
- };
1124
- }
1125
- if (result.themes)
1126
- result.defaultColor = false;
1127
- return result;
1128
- }
1129
-
1130
- // node/plugins/loaders.ts
1131
- var regexId = /^\/\@slidev\/slide\/(\d+)\.(md|json)(?:\?import)?$/;
1132
- var regexIdQuery = /(\d+?)\.(md|json|frontmatter)$/;
1133
- var templateInjectionMarker = "/* @slidev-injection */";
1134
- var templateImportContextUtils = `import {
1135
- useSlideContext,
1136
- provideFrontmatter as _provideFrontmatter,
1137
- frontmatterToProps as _frontmatterToProps,
1138
- } from "@slidev/client/context.ts"`.replace(/\n\s*/g, " ");
1139
- var templateInitContext = `const { $slidev, $nav, $clicksContext, $clicks, $page, $renderContext, $frontmatter } = useSlideContext()`;
1140
- function getBodyJson(req) {
1141
- return new Promise((resolve5, reject) => {
1142
- let body = "";
1143
- req.on("data", (chunk) => body += chunk);
1144
- req.on("error", reject);
1145
- req.on("end", () => {
1146
- try {
1147
- resolve5(JSON.parse(body) || {});
1148
- } catch (e) {
1149
- reject(e);
1150
- }
1151
- });
1152
- });
1153
- }
1154
- var md = Markdown2({ html: true });
1155
- md.use(mila2, {
1156
- attrs: {
1157
- target: "_blank",
1158
- rel: "noopener"
1159
- }
1160
- });
1161
- function renderNote(text = "") {
1162
- let clickCount = 0;
1163
- const html = md.render(
1164
- text.replace(/\[click(?::(\d+))?\]/gi, (_, count = 1) => {
1165
- clickCount += Number(count);
1166
- return `<span class="slidev-note-click-mark" data-clicks="${clickCount}"></span>`;
1167
- })
1168
- );
1169
- return html;
844
+ return html;
1170
845
  }
1171
846
  function withRenderedNote(data) {
1172
847
  return {
@@ -1174,12 +849,37 @@ function withRenderedNote(data) {
1174
849
  noteHTML: renderNote(data?.note)
1175
850
  };
1176
851
  }
1177
- function createSlidesLoader({ data, clientRoot, roots, remote, mode, userRoot }, pluginOptions, serverOptions) {
1178
- const slidePrefix = "/@slidev/slides/";
852
+ function createSlidesLoader(options, pluginOptions, serverOptions) {
1179
853
  const hmrPages = /* @__PURE__ */ new Set();
1180
854
  let server;
1181
855
  let _layouts_cache_time = 0;
1182
856
  let _layouts_cache = {};
857
+ const { data, clientRoot, roots, mode } = options;
858
+ const templateCtx = {
859
+ md,
860
+ async getLayouts() {
861
+ const now = Date.now();
862
+ if (now - _layouts_cache_time < 2e3)
863
+ return _layouts_cache;
864
+ const layouts = {};
865
+ for (const root of [...roots, clientRoot]) {
866
+ const layoutPaths = await fg3("layouts/**/*.{vue,ts}", {
867
+ cwd: root,
868
+ absolute: true,
869
+ suppressErrors: true
870
+ });
871
+ for (const layoutPath of layoutPaths) {
872
+ const layout = basename2(layoutPath).replace(/\.\w+$/, "");
873
+ if (layouts[layout])
874
+ continue;
875
+ layouts[layout] = layoutPath;
876
+ }
877
+ }
878
+ _layouts_cache_time = now;
879
+ _layouts_cache = layouts;
880
+ return layouts;
881
+ }
882
+ };
1183
883
  return [
1184
884
  {
1185
885
  name: "slidev:loader",
@@ -1220,15 +920,15 @@ function createSlidesLoader({ data, clientRoot, roots, remote, mode, userRoot },
1220
920
  return [];
1221
921
  const moduleIds = /* @__PURE__ */ new Set();
1222
922
  if (data.slides.length !== newData.slides.length) {
1223
- moduleIds.add("/@slidev/slides");
923
+ moduleIds.add(templateSlides.id);
1224
924
  range(newData.slides.length).map((i) => hmrPages.add(i));
1225
925
  }
1226
926
  if (!equal(data.headmatter.defaults, newData.headmatter.defaults)) {
1227
- moduleIds.add("/@slidev/slides");
927
+ moduleIds.add(templateSlides.id);
1228
928
  range(data.slides.length).map((i) => hmrPages.add(i));
1229
929
  }
1230
930
  if (!equal(data.config, newData.config))
1231
- moduleIds.add("/@slidev/configs");
931
+ moduleIds.add(templateConfigs.id);
1232
932
  if (!equal(data.features, newData.features)) {
1233
933
  setTimeout(() => {
1234
934
  ctx.server.hot.send({ type: "full-reload" });
@@ -1240,7 +940,7 @@ function createSlidesLoader({ data, clientRoot, roots, remote, mode, userRoot },
1240
940
  const b = newData.slides[i];
1241
941
  if (!hmrPages.has(i) && a.content.trim() === b.content.trim() && a.title?.trim() === b.title?.trim() && equal(a.frontmatter, b.frontmatter) && Object.entries(a.snippetsUsed ?? {}).every(([file, oldContent]) => {
1242
942
  try {
1243
- const newContent = fs5.readFileSync(file, "utf-8");
943
+ const newContent = fs4.readFileSync(file, "utf-8");
1244
944
  return oldContent === newContent;
1245
945
  } catch {
1246
946
  return false;
@@ -1269,10 +969,10 @@ function createSlidesLoader({ data, clientRoot, roots, remote, mode, userRoot },
1269
969
  }
1270
970
  Object.assign(data, newData);
1271
971
  if (hmrPages.size > 0)
1272
- moduleIds.add("/@slidev/titles.md");
972
+ moduleIds.add(templateTitleRendererMd.id);
1273
973
  const vueModules = Array.from(hmrPages).flatMap((i) => [
1274
- ctx.server.moduleGraph.getModuleById(`${slidePrefix}${i + 1}.frontmatter`),
1275
- ctx.server.moduleGraph.getModuleById(`${slidePrefix}${i + 1}.md`)
974
+ ctx.server.moduleGraph.getModuleById(`${VIRTUAL_SLIDE_PREFIX}${i + 1}.frontmatter`),
975
+ ctx.server.moduleGraph.getModuleById(`${VIRTUAL_SLIDE_PREFIX}${i + 1}.md`)
1276
976
  ]);
1277
977
  hmrPages.clear();
1278
978
  const moduleEntries = [
@@ -1283,43 +983,20 @@ function createSlidesLoader({ data, clientRoot, roots, remote, mode, userRoot },
1283
983
  return moduleEntries;
1284
984
  },
1285
985
  resolveId(id) {
1286
- if (id.startsWith(slidePrefix) || id.startsWith("/@slidev/"))
986
+ if (id.startsWith(VIRTUAL_SLIDE_PREFIX) || id.startsWith("/@slidev/"))
1287
987
  return id;
1288
988
  return null;
1289
989
  },
1290
- load(id) {
1291
- if (id === "/@slidev/slides")
1292
- return generateSlideRoutes();
1293
- if (id === "/@slidev/routes")
1294
- return generateDummyRoutes();
1295
- if (id === "/@slidev/layouts")
1296
- return generateLayouts();
1297
- if (id === "/@slidev/styles")
1298
- return generateUserStyles();
1299
- if (id === "/@slidev/monaco-types")
1300
- return generateMonacoTypes();
1301
- if (id === "/@slidev/configs")
1302
- return generateConfigs();
1303
- if (id === "/@slidev/global-components/top")
1304
- return generateGlobalComponents("top");
1305
- if (id === "/@slidev/global-components/bottom")
1306
- return generateGlobalComponents("bottom");
1307
- if (id === "/@slidev/custom-nav-controls")
1308
- return generateCustomNavControls();
1309
- if (id === "/@slidev/shiki")
1310
- return generteShikiBundle();
1311
- if (id === "/@slidev/titles.md") {
990
+ async load(id) {
991
+ const template = templates.find((i) => i.id === id);
992
+ if (template) {
1312
993
  return {
1313
- code: data.slides.map(({ title }, i) => `<template ${i === 0 ? "v-if" : "v-else-if"}="+no === ${i + 1}">
1314
-
1315
- ${title}
1316
-
1317
- </template>`).join(""),
994
+ code: await template.getContent(options, templateCtx),
1318
995
  map: { mappings: "" }
1319
996
  };
1320
997
  }
1321
- if (id.startsWith(slidePrefix)) {
1322
- const remaning = id.slice(slidePrefix.length);
998
+ if (id.startsWith(VIRTUAL_SLIDE_PREFIX)) {
999
+ const remaning = id.slice(VIRTUAL_SLIDE_PREFIX.length);
1323
1000
  const match = remaning.match(regexIdQuery);
1324
1001
  if (match) {
1325
1002
  const [, no, type] = match;
@@ -1391,9 +1068,9 @@ ${title}
1391
1068
  name: "slidev:layout-transform:pre",
1392
1069
  enforce: "pre",
1393
1070
  async transform(code, id) {
1394
- if (!id.startsWith(slidePrefix))
1071
+ if (!id.startsWith(VIRTUAL_SLIDE_PREFIX))
1395
1072
  return;
1396
- const remaning = id.slice(slidePrefix.length);
1073
+ const remaning = id.slice(VIRTUAL_SLIDE_PREFIX.length);
1397
1074
  const match = remaning.match(regexIdQuery);
1398
1075
  if (!match)
1399
1076
  return;
@@ -1413,15 +1090,6 @@ ${title}
1413
1090
  return transformVue(code);
1414
1091
  }
1415
1092
  },
1416
- {
1417
- name: "slidev:title-transform:pre",
1418
- enforce: "pre",
1419
- transform(code, id) {
1420
- if (id !== "/@slidev/titles.md")
1421
- return;
1422
- return transformTitles(code);
1423
- }
1424
- },
1425
1093
  {
1426
1094
  name: "slidev:slide-transform:post",
1427
1095
  enforce: "post",
@@ -1479,7 +1147,7 @@ ${title}
1479
1147
  };
1480
1148
  }
1481
1149
  async function transformMarkdown(code, pageNo) {
1482
- const layouts = await getLayouts();
1150
+ const layouts = await templateCtx.getLayouts();
1483
1151
  const frontmatter = getFrontmatter(pageNo);
1484
1152
  let layoutName = frontmatter?.layout || (pageNo === 0 ? "cover" : "default");
1485
1153
  if (!layouts[layoutName]) {
@@ -1491,7 +1159,7 @@ Unknown layout "${bold(layoutName)}".${yellow(" Available layouts are:")}`) + Ob
1491
1159
  delete frontmatter.title;
1492
1160
  const imports = [
1493
1161
  `import InjectedLayout from "${toAtFS(layouts[layoutName])}"`,
1494
- `import frontmatter from "${toAtFS(`${slidePrefix + (pageNo + 1)}.frontmatter`)}"`,
1162
+ `import frontmatter from "${toAtFS(`${VIRTUAL_SLIDE_PREFIX + (pageNo + 1)}.frontmatter`)}"`,
1495
1163
  templateImportContextUtils,
1496
1164
  "_provideFrontmatter(frontmatter)",
1497
1165
  templateInitContext,
@@ -1512,387 +1180,800 @@ ${body}
1512
1180
  ${code.slice(injectB)}`;
1513
1181
  return code;
1514
1182
  }
1515
- function transformVue(code) {
1516
- if (code.includes(templateInjectionMarker) || code.includes("useSlideContext()"))
1517
- return code;
1518
- const imports = [
1519
- templateImportContextUtils,
1520
- templateInitContext,
1521
- templateInjectionMarker
1522
- ];
1523
- const matchScript = code.match(/<script((?!setup).)*(setup)?.*>/);
1524
- if (matchScript && matchScript[2]) {
1525
- return code.replace(/(<script.*>)/g, `$1
1526
- ${imports.join("\n")}
1527
- `);
1528
- } else if (matchScript && !matchScript[2]) {
1529
- const matchExport = code.match(/export\s+default\s+{/);
1530
- if (matchExport) {
1531
- const exportIndex = (matchExport.index || 0) + matchExport[0].length;
1532
- let component = code.slice(exportIndex);
1533
- component = component.slice(0, component.indexOf("</script>"));
1534
- const scriptIndex = (matchScript.index || 0) + matchScript[0].length;
1535
- const provideImport = '\nimport { injectionSlidevContext } from "@slidev/client/constants.ts"\n';
1536
- code = `${code.slice(0, scriptIndex)}${provideImport}${code.slice(scriptIndex)}`;
1537
- let injectIndex = exportIndex + provideImport.length;
1538
- let injectObject = "$slidev: { from: injectionSlidevContext },";
1539
- const matchInject = component.match(/.*inject\s*:\s*([\[{])/);
1540
- if (matchInject) {
1541
- injectIndex += (matchInject.index || 0) + matchInject[0].length;
1542
- if (matchInject[1] === "[") {
1543
- let injects = component.slice((matchInject.index || 0) + matchInject[0].length);
1544
- const injectEndIndex = injects.indexOf("]");
1545
- injects = injects.slice(0, injectEndIndex);
1546
- injectObject += injects.split(",").map((inject) => `${inject}: {from: ${inject}}`).join(",");
1547
- return `${code.slice(0, injectIndex - 1)}{
1548
- ${injectObject}
1549
- }${code.slice(injectIndex + injectEndIndex + 1)}`;
1550
- } else {
1551
- return `${code.slice(0, injectIndex)}
1552
- ${injectObject}
1553
- ${code.slice(injectIndex)}`;
1554
- }
1555
- }
1556
- return `${code.slice(0, injectIndex)}
1557
- inject: { ${injectObject} },
1558
- ${code.slice(injectIndex)}`;
1559
- }
1560
- }
1561
- return `<script setup>
1562
- ${imports.join("\n")}
1563
- </script>
1564
- ${code}`;
1183
+ function transformVue(code) {
1184
+ if (code.includes(templateInjectionMarker) || code.includes("useSlideContext()"))
1185
+ return code;
1186
+ const imports = [
1187
+ templateImportContextUtils,
1188
+ templateInitContext,
1189
+ templateInjectionMarker
1190
+ ];
1191
+ const matchScript = code.match(/<script((?!setup).)*(setup)?.*>/);
1192
+ if (matchScript && matchScript[2]) {
1193
+ return code.replace(/(<script.*>)/g, `$1
1194
+ ${imports.join("\n")}
1195
+ `);
1196
+ } else if (matchScript && !matchScript[2]) {
1197
+ const matchExport = code.match(/export\s+default\s+{/);
1198
+ if (matchExport) {
1199
+ const exportIndex = (matchExport.index || 0) + matchExport[0].length;
1200
+ let component = code.slice(exportIndex);
1201
+ component = component.slice(0, component.indexOf("</script>"));
1202
+ const scriptIndex = (matchScript.index || 0) + matchScript[0].length;
1203
+ const provideImport = '\nimport { injectionSlidevContext } from "@slidev/client/constants.ts"\n';
1204
+ code = `${code.slice(0, scriptIndex)}${provideImport}${code.slice(scriptIndex)}`;
1205
+ let injectIndex = exportIndex + provideImport.length;
1206
+ let injectObject = "$slidev: { from: injectionSlidevContext },";
1207
+ const matchInject = component.match(/.*inject\s*:\s*([\[{])/);
1208
+ if (matchInject) {
1209
+ injectIndex += (matchInject.index || 0) + matchInject[0].length;
1210
+ if (matchInject[1] === "[") {
1211
+ let injects = component.slice((matchInject.index || 0) + matchInject[0].length);
1212
+ const injectEndIndex = injects.indexOf("]");
1213
+ injects = injects.slice(0, injectEndIndex);
1214
+ injectObject += injects.split(",").map((inject) => `${inject}: {from: ${inject}}`).join(",");
1215
+ return `${code.slice(0, injectIndex - 1)}{
1216
+ ${injectObject}
1217
+ }${code.slice(injectIndex + injectEndIndex + 1)}`;
1218
+ } else {
1219
+ return `${code.slice(0, injectIndex)}
1220
+ ${injectObject}
1221
+ ${code.slice(injectIndex)}`;
1222
+ }
1223
+ }
1224
+ return `${code.slice(0, injectIndex)}
1225
+ inject: { ${injectObject} },
1226
+ ${code.slice(injectIndex)}`;
1227
+ }
1228
+ }
1229
+ return `<script setup>
1230
+ ${imports.join("\n")}
1231
+ </script>
1232
+ ${code}`;
1233
+ }
1234
+ function getTitle() {
1235
+ if (isString2(data.config.title)) {
1236
+ const tokens = md.parseInline(data.config.title, {});
1237
+ return stringifyMarkdownTokens(tokens);
1238
+ }
1239
+ return data.config.title;
1240
+ }
1241
+ }
1242
+
1243
+ // node/vite/markdown.ts
1244
+ import Markdown2 from "unplugin-vue-markdown/vite";
1245
+ import { slash } from "@antfu/utils";
1246
+
1247
+ // ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.0.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/image-size/specialCharacters.js
1248
+ var SpecialCharacters;
1249
+ (function(SpecialCharacters2) {
1250
+ SpecialCharacters2[SpecialCharacters2["EXCLAMATION_MARK"] = 33] = "EXCLAMATION_MARK";
1251
+ SpecialCharacters2[SpecialCharacters2["OPENING_BRACKET"] = 91] = "OPENING_BRACKET";
1252
+ SpecialCharacters2[SpecialCharacters2["OPENING_PARENTHESIS"] = 40] = "OPENING_PARENTHESIS";
1253
+ SpecialCharacters2[SpecialCharacters2["WHITESPACE"] = 32] = "WHITESPACE";
1254
+ SpecialCharacters2[SpecialCharacters2["NEW_LINE"] = 10] = "NEW_LINE";
1255
+ SpecialCharacters2[SpecialCharacters2["EQUALS"] = 61] = "EQUALS";
1256
+ SpecialCharacters2[SpecialCharacters2["LOWER_CASE_X"] = 120] = "LOWER_CASE_X";
1257
+ SpecialCharacters2[SpecialCharacters2["NUMBER_ZERO"] = 48] = "NUMBER_ZERO";
1258
+ SpecialCharacters2[SpecialCharacters2["NUMBER_NINE"] = 57] = "NUMBER_NINE";
1259
+ SpecialCharacters2[SpecialCharacters2["PERCENTAGE"] = 37] = "PERCENTAGE";
1260
+ SpecialCharacters2[SpecialCharacters2["CLOSING_PARENTHESIS"] = 41] = "CLOSING_PARENTHESIS";
1261
+ })(SpecialCharacters || (SpecialCharacters = {}));
1262
+
1263
+ // ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.0.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/task-lists/index.js
1264
+ import Token from "markdown-it/lib/token.mjs";
1265
+ var checkboxRegex = /^ *\[([\sx])] /i;
1266
+ function taskLists(md2, options = { enabled: false, label: false, lineNumber: false }) {
1267
+ md2.core.ruler.after("inline", "task-lists", (state) => processToken(state, options));
1268
+ md2.renderer.rules.taskListItemCheckbox = (tokens) => {
1269
+ const token = tokens[0];
1270
+ const checkedAttribute = token.attrGet("checked") ? 'checked="" ' : "";
1271
+ const disabledAttribute = token.attrGet("disabled") ? 'disabled="" ' : "";
1272
+ const line = token.attrGet("line");
1273
+ const idAttribute = `id="${token.attrGet("id")}" `;
1274
+ const dataLineAttribute = line && options.lineNumber ? `data-line="${line}" ` : "";
1275
+ return `<input class="task-list-item-checkbox" type="checkbox" ${checkedAttribute}${disabledAttribute}${dataLineAttribute}${idAttribute}/>`;
1276
+ };
1277
+ md2.renderer.rules.taskListItemLabel_close = () => {
1278
+ return "</label>";
1279
+ };
1280
+ md2.renderer.rules.taskListItemLabel_open = (tokens) => {
1281
+ const token = tokens[0];
1282
+ const id = token.attrGet("id");
1283
+ return `<label for="${id}">`;
1284
+ };
1285
+ }
1286
+ function processToken(state, options) {
1287
+ const allTokens = state.tokens;
1288
+ for (let i = 2; i < allTokens.length; i++) {
1289
+ if (!isTodoItem(allTokens, i)) {
1290
+ continue;
1291
+ }
1292
+ todoify(allTokens[i], options);
1293
+ allTokens[i - 2].attrJoin("class", `task-list-item ${options.enabled ? " enabled" : ""}`);
1294
+ const parentToken = findParentToken(allTokens, i - 2);
1295
+ if (parentToken) {
1296
+ const classes = parentToken.attrGet("class") ?? "";
1297
+ if (!classes.match(/(^| )contains-task-list/)) {
1298
+ parentToken.attrJoin("class", "contains-task-list");
1299
+ }
1300
+ }
1301
+ }
1302
+ return false;
1303
+ }
1304
+ function findParentToken(tokens, index) {
1305
+ const targetLevel = tokens[index].level - 1;
1306
+ for (let currentTokenIndex = index - 1; currentTokenIndex >= 0; currentTokenIndex--) {
1307
+ if (tokens[currentTokenIndex].level === targetLevel) {
1308
+ return tokens[currentTokenIndex];
1309
+ }
1310
+ }
1311
+ return void 0;
1312
+ }
1313
+ function isTodoItem(tokens, index) {
1314
+ return isInline(tokens[index]) && isParagraph(tokens[index - 1]) && isListItem(tokens[index - 2]) && startsWithTodoMarkdown(tokens[index]);
1315
+ }
1316
+ function todoify(token, options) {
1317
+ if (token.children == null) {
1318
+ return;
1319
+ }
1320
+ const id = generateIdForToken(token);
1321
+ token.children.splice(0, 0, createCheckboxToken(token, options.enabled, id));
1322
+ token.children[1].content = token.children[1].content.replace(checkboxRegex, "");
1323
+ if (options.label) {
1324
+ token.children.splice(1, 0, createLabelBeginToken(id));
1325
+ token.children.push(createLabelEndToken());
1326
+ }
1327
+ }
1328
+ function generateIdForToken(token) {
1329
+ if (token.map) {
1330
+ return `task-item-${token.map[0]}`;
1331
+ } else {
1332
+ return `task-item-${Math.ceil(Math.random() * (1e4 * 1e3) - 1e3)}`;
1333
+ }
1334
+ }
1335
+ function createCheckboxToken(token, enabled, id) {
1336
+ const checkbox = new Token("taskListItemCheckbox", "", 0);
1337
+ if (!enabled) {
1338
+ checkbox.attrSet("disabled", "true");
1339
+ }
1340
+ if (token.map) {
1341
+ checkbox.attrSet("line", token.map[0].toString());
1342
+ }
1343
+ checkbox.attrSet("id", id);
1344
+ const checkboxRegexResult = checkboxRegex.exec(token.content);
1345
+ const isChecked = checkboxRegexResult?.[1].toLowerCase() === "x";
1346
+ if (isChecked) {
1347
+ checkbox.attrSet("checked", "true");
1348
+ }
1349
+ return checkbox;
1350
+ }
1351
+ function createLabelBeginToken(id) {
1352
+ const labelBeginToken = new Token("taskListItemLabel_open", "", 1);
1353
+ labelBeginToken.attrSet("id", id);
1354
+ return labelBeginToken;
1355
+ }
1356
+ function createLabelEndToken() {
1357
+ return new Token("taskListItemLabel_close", "", -1);
1358
+ }
1359
+ function isInline(token) {
1360
+ return token.type === "inline";
1361
+ }
1362
+ function isParagraph(token) {
1363
+ return token.type === "paragraph_open";
1364
+ }
1365
+ function isListItem(token) {
1366
+ return token.type === "list_item_open";
1367
+ }
1368
+ function startsWithTodoMarkdown(token) {
1369
+ return checkboxRegex.test(token.content);
1370
+ }
1371
+
1372
+ // node/vite/markdown.ts
1373
+ import MarkdownItMdc from "markdown-it-mdc";
1374
+ import MarkdownItAttrs from "markdown-it-link-attributes";
1375
+ import MarkdownItFootnote from "markdown-it-footnote";
1376
+
1377
+ // node/syntax/markdown-it/markdown-it-katex.ts
1378
+ import katex from "katex";
1379
+ function isValidDelim(state, pos) {
1380
+ const max = state.posMax;
1381
+ let can_open = true;
1382
+ let can_close = true;
1383
+ const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
1384
+ const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
1385
+ if (prevChar === 32 || prevChar === 9 || /* \t */
1386
+ nextChar >= 48 && nextChar <= 57)
1387
+ can_close = false;
1388
+ if (nextChar === 32 || nextChar === 9)
1389
+ can_open = false;
1390
+ return {
1391
+ can_open,
1392
+ can_close
1393
+ };
1394
+ }
1395
+ function math_inline(state, silent) {
1396
+ let match, token, res, pos;
1397
+ if (state.src[state.pos] !== "$")
1398
+ return false;
1399
+ res = isValidDelim(state, state.pos);
1400
+ if (!res.can_open) {
1401
+ if (!silent)
1402
+ state.pending += "$";
1403
+ state.pos += 1;
1404
+ return true;
1405
+ }
1406
+ const start = state.pos + 1;
1407
+ match = start;
1408
+ while ((match = state.src.indexOf("$", match)) !== -1) {
1409
+ pos = match - 1;
1410
+ while (state.src[pos] === "\\")
1411
+ pos -= 1;
1412
+ if ((match - pos) % 2 === 1)
1413
+ break;
1414
+ match += 1;
1415
+ }
1416
+ if (match === -1) {
1417
+ if (!silent)
1418
+ state.pending += "$";
1419
+ state.pos = start;
1420
+ return true;
1565
1421
  }
1566
- function transformTitles(code) {
1567
- return code.replace(/<template>\s*<div>\s*<p>/, "<template>").replace(/<\/p>\s*<\/div>\s*<\/template>/, "</template>").replace(/<script\ssetup>/, `<script setup lang="ts">
1568
- defineProps<{ no: number | string }>()`);
1422
+ if (match - start === 0) {
1423
+ if (!silent)
1424
+ state.pending += "$$";
1425
+ state.pos = start + 1;
1426
+ return true;
1569
1427
  }
1570
- async function getLayouts() {
1571
- const now = Date.now();
1572
- if (now - _layouts_cache_time < 2e3)
1573
- return _layouts_cache;
1574
- const layouts = {};
1575
- for (const root of [...roots, clientRoot]) {
1576
- const layoutPaths = await fg2("layouts/**/*.{vue,ts}", {
1577
- cwd: root,
1578
- absolute: true,
1579
- suppressErrors: true
1580
- });
1581
- for (const layoutPath of layoutPaths) {
1582
- const layout = basename2(layoutPath).replace(/\.\w+$/, "");
1583
- if (layouts[layout])
1584
- continue;
1585
- layouts[layout] = layoutPath;
1586
- }
1587
- }
1588
- _layouts_cache_time = now;
1589
- _layouts_cache = layouts;
1590
- return layouts;
1428
+ res = isValidDelim(state, match);
1429
+ if (!res.can_close) {
1430
+ if (!silent)
1431
+ state.pending += "$";
1432
+ state.pos = start;
1433
+ return true;
1591
1434
  }
1592
- async function resolveUrl(id) {
1593
- return toAtFS(await resolveImportPath(id, true));
1435
+ if (!silent) {
1436
+ token = state.push("math_inline", "math", 0);
1437
+ token.markup = "$";
1438
+ token.content = state.src.slice(start, match);
1594
1439
  }
1595
- function resolveUrlOfClient(name) {
1596
- return toAtFS(join4(clientRoot, name));
1440
+ state.pos = match + 1;
1441
+ return true;
1442
+ }
1443
+ function math_block(state, start, end, silent) {
1444
+ let firstLine;
1445
+ let lastLine;
1446
+ let next;
1447
+ let lastPos;
1448
+ let found = false;
1449
+ let pos = state.bMarks[start] + state.tShift[start];
1450
+ let max = state.eMarks[start];
1451
+ if (pos + 2 > max)
1452
+ return false;
1453
+ if (state.src.slice(pos, pos + 2) !== "$$")
1454
+ return false;
1455
+ pos += 2;
1456
+ firstLine = state.src.slice(pos, max);
1457
+ if (silent)
1458
+ return true;
1459
+ if (firstLine.trim().slice(-2) === "$$") {
1460
+ firstLine = firstLine.trim().slice(0, -2);
1461
+ found = true;
1597
1462
  }
1598
- async function generateUserStyles() {
1599
- const imports = [
1600
- `import "${resolveUrlOfClient("styles/vars.css")}"`,
1601
- `import "${resolveUrlOfClient("styles/index.css")}"`,
1602
- `import "${resolveUrlOfClient("styles/code.css")}"`,
1603
- `import "${resolveUrlOfClient("styles/katex.css")}"`,
1604
- `import "${resolveUrlOfClient("styles/transitions.css")}"`
1605
- ];
1606
- for (const root of roots) {
1607
- const styles = [
1608
- join4(root, "styles", "index.ts"),
1609
- join4(root, "styles", "index.js"),
1610
- join4(root, "styles", "index.css"),
1611
- join4(root, "styles.css"),
1612
- join4(root, "style.css")
1613
- ];
1614
- for (const style of styles) {
1615
- if (fs5.existsSync(style)) {
1616
- imports.push(`import "${toAtFS(style)}"`);
1617
- continue;
1618
- }
1619
- }
1620
- }
1621
- if (data.features.katex)
1622
- imports.push(`import "${await resolveUrl("katex/dist/katex.min.css")}"`);
1623
- if (data.config.highlighter === "shiki") {
1624
- imports.push(
1625
- `import "${await resolveUrl("@shikijs/vitepress-twoslash/style.css")}"`,
1626
- `import "${resolveUrlOfClient("styles/shiki-twoslash.css")}"`
1627
- );
1463
+ for (next = start; !found; ) {
1464
+ next++;
1465
+ if (next >= end)
1466
+ break;
1467
+ pos = state.bMarks[next] + state.tShift[next];
1468
+ max = state.eMarks[next];
1469
+ if (pos < max && state.tShift[next] < state.blkIndent) {
1470
+ break;
1628
1471
  }
1629
- if (data.config.css === "unocss") {
1630
- imports.unshift(
1631
- `import "${await resolveUrl("@unocss/reset/tailwind.css")}"`,
1632
- 'import "uno:preflights.css"',
1633
- 'import "uno:typography.css"',
1634
- 'import "uno:shortcuts.css"'
1635
- );
1636
- imports.push('import "uno.css"');
1472
+ if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
1473
+ lastPos = state.src.slice(0, max).lastIndexOf("$$");
1474
+ lastLine = state.src.slice(pos, lastPos);
1475
+ found = true;
1637
1476
  }
1638
- return imports.join("\n");
1639
1477
  }
1640
- async function generateMonacoTypes() {
1641
- const typesRoot = join4(userRoot, "snippets");
1642
- const files = await fg2(["**/*.ts", "**/*.mts", "**/*.cts"], { cwd: typesRoot });
1643
- let result = 'import { addFile } from "@slidev/client/setup/monaco.ts"\n';
1644
- for (const file of files) {
1645
- const url = `${toAtFS(resolve2(typesRoot, file))}?monaco-types&raw`;
1646
- result += `addFile(import(${JSON.stringify(url)}), ${JSON.stringify(file)})
1647
- `;
1478
+ state.line = next + 1;
1479
+ const token = state.push("math_block", "math", 0);
1480
+ token.block = true;
1481
+ token.content = (firstLine && firstLine.trim() ? `${firstLine}
1482
+ ` : "") + state.getLines(start + 1, next, state.tShift[start], true) + (lastLine && lastLine.trim() ? lastLine : "");
1483
+ token.map = [start, state.line];
1484
+ token.markup = "$$";
1485
+ return true;
1486
+ }
1487
+ function math_plugin(md2, options) {
1488
+ options = options || {};
1489
+ const katexInline = function(latex) {
1490
+ options.displayMode = false;
1491
+ try {
1492
+ return katex.renderToString(latex, options);
1493
+ } catch (error) {
1494
+ if (options.throwOnError)
1495
+ console.warn(error);
1496
+ return latex;
1648
1497
  }
1649
- const deps = [...data.config.monacoTypesAdditionalPackages];
1650
- if (data.config.monacoTypesSource === "local")
1651
- deps.push(...scanMonacoModules(data.slides.map((s) => s.source.raw).join()));
1652
- function mapModuleNameToModule(moduleSpecifier) {
1653
- if (moduleSpecifier.startsWith("node:"))
1654
- return "node";
1655
- if (builtinModules.includes(moduleSpecifier))
1656
- return "node";
1657
- const mainPackageName = moduleSpecifier.split("/")[0];
1658
- if (builtinModules.includes(mainPackageName) && !mainPackageName.startsWith("@"))
1659
- return "node";
1660
- const [a = "", b = ""] = moduleSpecifier.split("/");
1661
- const moduleName = a.startsWith("@") ? `${a}/${b}` : a;
1662
- return moduleName;
1498
+ };
1499
+ const inlineRenderer = function(tokens, idx) {
1500
+ return katexInline(tokens[idx].content);
1501
+ };
1502
+ const katexBlock = function(latex) {
1503
+ options.displayMode = true;
1504
+ try {
1505
+ return `<p>${katex.renderToString(latex, options)}</p>`;
1506
+ } catch (error) {
1507
+ if (options.throwOnError)
1508
+ console.warn(error);
1509
+ return latex;
1663
1510
  }
1664
- for (const specifier of uniq2(deps)) {
1665
- if (specifier[0] === ".")
1666
- continue;
1667
- const moduleName = mapModuleNameToModule(specifier);
1668
- result += `import(${JSON.stringify(`/@slidev-monaco-types/resolve?pkg=${moduleName}`)})
1511
+ };
1512
+ const blockRenderer = function(tokens, idx) {
1513
+ return `${katexBlock(tokens[idx].content)}
1669
1514
  `;
1670
- }
1671
- return result;
1672
- }
1673
- async function generateLayouts() {
1674
- const imports = [];
1675
- const layouts = objectMap(
1676
- await getLayouts(),
1677
- (k, v) => {
1678
- imports.push(`import __layout_${k} from "${toAtFS(v)}"`);
1679
- return [k, `__layout_${k}`];
1680
- }
1681
- );
1682
- return [
1683
- imports.join("\n"),
1684
- `export default {
1685
- ${Object.entries(layouts).map(([k, v]) => `"${k}": ${v}`).join(",\n")}
1686
- }`
1687
- ].join("\n\n");
1688
- }
1689
- async function generateSlideRoutes() {
1690
- const layouts = await getLayouts();
1691
- const imports = [
1692
- `import { shallowRef } from 'vue'`,
1693
- `import * as __layout__error from '${layouts.error}'`
1694
- ];
1695
- const slides = data.slides.map((_, idx) => {
1696
- const no = idx + 1;
1697
- imports.push(`import { meta as f${no} } from '${slidePrefix}${no}.frontmatter'`);
1698
- return `{
1699
- no: ${no},
1700
- meta: f${no},
1701
- component: async () => {
1702
- try {
1703
- return await import('${slidePrefix}${no}.md')
1704
- }
1705
- catch {
1706
- return __layout__error
1707
- }
1708
- },
1709
- }`;
1710
- });
1711
- return [
1712
- ...imports,
1713
- `const data = [
1714
- ${slides.join(",\n")}
1715
- ]`,
1716
- `if (import.meta.hot) {`,
1717
- ` import.meta.hot.data.slides ??= shallowRef()`,
1718
- ` import.meta.hot.data.slides.value = data`,
1719
- ` import.meta.hot.accept()`,
1720
- `}`,
1721
- `export const slides = import.meta.hot ? import.meta.hot.data.slides : shallowRef(data)`
1722
- ].join("\n");
1515
+ };
1516
+ md2.inline.ruler.after("escape", "math_inline", math_inline);
1517
+ md2.block.ruler.after("blockquote", "math_block", math_block, {
1518
+ alt: ["paragraph", "reference", "blockquote", "list"]
1519
+ });
1520
+ md2.renderer.rules.math_inline = inlineRenderer;
1521
+ md2.renderer.rules.math_block = blockRenderer;
1522
+ }
1523
+
1524
+ // node/syntax/markdown-it/markdown-it-prism.ts
1525
+ import { createRequire } from "node:module";
1526
+ import Prism from "prismjs";
1527
+ import loadLanguages from "prismjs/components/index.js";
1528
+ import * as htmlparser2 from "htmlparser2";
1529
+
1530
+ // node/syntax/transform/utils.ts
1531
+ function normalizeRangeStr(rangeStr = "") {
1532
+ return !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
1533
+ }
1534
+ function getCodeBlocks(md2) {
1535
+ const codeblocks = Array.from(md2.matchAll(/^```[\s\S]*?^```/mg)).map((m) => {
1536
+ const start = m.index;
1537
+ const end = m.index + m[0].length;
1538
+ const startLine = md2.slice(0, start).match(/\n/g)?.length || 0;
1539
+ const endLine = md2.slice(0, end).match(/\n/g)?.length || 0;
1540
+ return [start, end, startLine, endLine];
1541
+ });
1542
+ return {
1543
+ codeblocks,
1544
+ isInsideCodeblocks(idx) {
1545
+ return codeblocks.some(([s, e]) => s <= idx && idx <= e);
1546
+ },
1547
+ isLineInsideCodeblocks(line) {
1548
+ return codeblocks.some(([, , s, e]) => s <= line && line <= e);
1549
+ }
1550
+ };
1551
+ }
1552
+ function escapeVueInCode(md2) {
1553
+ return md2.replace(/{{/g, "&lbrace;&lbrace;");
1554
+ }
1555
+
1556
+ // node/syntax/markdown-it/markdown-it-prism.ts
1557
+ var require2 = createRequire(import.meta.url);
1558
+ var Tag = class {
1559
+ tagname;
1560
+ attributes;
1561
+ constructor(tagname, attributes) {
1562
+ this.tagname = tagname;
1563
+ this.attributes = attributes;
1723
1564
  }
1724
- function generateDummyRoutes() {
1725
- return [
1726
- `export { slides } from '#slidev/slides'`,
1727
- `console.warn('[slidev] #slidev/routes is deprecated, use #slidev/slides instead')`
1728
- ].join("\n");
1565
+ asOpen() {
1566
+ return `<${this.tagname} ${Object.entries(this.attributes).map(([key, value]) => `${key}="${value}"`).join(" ")}>`;
1729
1567
  }
1730
- function getTitle() {
1731
- if (isString(data.config.title)) {
1732
- const tokens = md.parseInline(data.config.title, {});
1733
- return stringifyMarkdownTokens(tokens);
1734
- }
1735
- return data.config.title;
1568
+ asClosed() {
1569
+ return `</${this.tagname}>`;
1736
1570
  }
1737
- function generateConfigs() {
1738
- const config = {
1739
- ...data.config,
1740
- remote,
1741
- title: getTitle()
1742
- };
1743
- if (isString(config.info))
1744
- config.info = md.render(config.info);
1745
- return `export default ${JSON.stringify(config)}`;
1571
+ };
1572
+ var DEFAULTS = {
1573
+ plugins: [],
1574
+ init: () => {
1575
+ },
1576
+ defaultLanguageForUnknown: void 0,
1577
+ defaultLanguageForUnspecified: void 0,
1578
+ defaultLanguage: void 0
1579
+ };
1580
+ function loadPrismLang(lang) {
1581
+ if (!lang)
1582
+ return void 0;
1583
+ let langObject = Prism.languages[lang];
1584
+ if (langObject === void 0) {
1585
+ loadLanguages([lang]);
1586
+ langObject = Prism.languages[lang];
1746
1587
  }
1747
- async function generateGlobalComponents(layer) {
1748
- const components = roots.flatMap((root) => {
1749
- if (layer === "top") {
1750
- return [
1751
- join4(root, "global.vue"),
1752
- join4(root, "global-top.vue"),
1753
- join4(root, "GlobalTop.vue")
1754
- ];
1755
- } else {
1756
- return [
1757
- join4(root, "global-bottom.vue"),
1758
- join4(root, "GlobalBottom.vue")
1759
- ];
1760
- }
1761
- }).filter((i) => fs5.existsSync(i));
1762
- const imports = components.map((i, idx) => `import __n${idx} from '${toAtFS(i)}'`).join("\n");
1763
- const render = components.map((i, idx) => `h(__n${idx})`).join(",");
1764
- return `
1765
- ${imports}
1766
- import { h } from 'vue'
1767
- export default {
1768
- render() {
1769
- return [${render}]
1588
+ return langObject;
1589
+ }
1590
+ function loadPrismPlugin(name) {
1591
+ try {
1592
+ require2(`prismjs/plugins/${name}/prism-${name}`);
1593
+ } catch (e) {
1594
+ throw new Error(`Cannot load Prism plugin "${name}". Please check the spelling.`);
1770
1595
  }
1771
1596
  }
1772
- `;
1597
+ function selectLanguage(options, lang) {
1598
+ let langToUse = lang;
1599
+ if (langToUse === "" && options.defaultLanguageForUnspecified !== void 0)
1600
+ langToUse = options.defaultLanguageForUnspecified;
1601
+ let prismLang = loadPrismLang(langToUse);
1602
+ if (prismLang === void 0 && options.defaultLanguageForUnknown !== void 0) {
1603
+ langToUse = options.defaultLanguageForUnknown;
1604
+ prismLang = loadPrismLang(langToUse);
1773
1605
  }
1774
- async function generateCustomNavControls() {
1775
- const components = roots.flatMap((root) => {
1776
- return [
1777
- join4(root, "custom-nav-controls.vue"),
1778
- join4(root, "CustomNavControls.vue")
1779
- ];
1780
- }).filter((i) => fs5.existsSync(i));
1781
- const imports = components.map((i, idx) => `import __n${idx} from '${toAtFS(i)}'`).join("\n");
1782
- const render = components.map((i, idx) => `h(__n${idx})`).join(",");
1783
- return `
1784
- ${imports}
1785
- import { h } from 'vue'
1786
- export default {
1787
- render() {
1788
- return [${render}]
1606
+ return [langToUse, prismLang];
1607
+ }
1608
+ function highlight(markdownit, options, text, lang) {
1609
+ const [langToUse, prismLang] = selectLanguage(options, lang);
1610
+ let code = text.trimEnd();
1611
+ code = prismLang ? highlightPrism(code, prismLang, langToUse) : markdownit.utils.escapeHtml(code);
1612
+ code = code.split(/\r?\n/g).map((line) => `<span class="line">${line}</span>`).join("\n");
1613
+ const classAttribute = langToUse ? ` class="slidev-code ${markdownit.options.langPrefix}${markdownit.utils.escapeHtml(langToUse)}"` : "";
1614
+ return escapeVueInCode(`<pre${classAttribute}><code>${code}</code></pre>`);
1615
+ }
1616
+ function highlightPrism(code, prismLang, langToUse) {
1617
+ const openTags = [];
1618
+ const parser2 = new htmlparser2.Parser({
1619
+ onopentag(tagname, attributes) {
1620
+ openTags.push(new Tag(tagname, attributes));
1621
+ },
1622
+ onclosetag() {
1623
+ openTags.pop();
1624
+ }
1625
+ });
1626
+ code = Prism.highlight(code, prismLang, langToUse);
1627
+ code = code.split(/\r?\n/g).map((line) => {
1628
+ const prefix = openTags.map((tag) => tag.asOpen()).join("");
1629
+ parser2.write(line);
1630
+ const postfix = openTags.reverse().map((tag) => tag.asClosed()).join("");
1631
+ return prefix + line + postfix;
1632
+ }).join("\n");
1633
+ parser2.end();
1634
+ return code;
1635
+ }
1636
+ function checkLanguageOption(options, optionName) {
1637
+ const language = options[optionName];
1638
+ if (language !== void 0 && loadPrismLang(language) === void 0)
1639
+ throw new Error(`Bad option ${optionName}: There is no Prism language '${language}'.`);
1640
+ }
1641
+ function markdownItPrism(markdownit, useroptions) {
1642
+ const options = Object.assign({}, DEFAULTS, useroptions);
1643
+ checkLanguageOption(options, "defaultLanguage");
1644
+ checkLanguageOption(options, "defaultLanguageForUnknown");
1645
+ checkLanguageOption(options, "defaultLanguageForUnspecified");
1646
+ options.defaultLanguageForUnknown = options.defaultLanguageForUnknown || options.defaultLanguage;
1647
+ options.defaultLanguageForUnspecified = options.defaultLanguageForUnspecified || options.defaultLanguage;
1648
+ options.plugins.forEach(loadPrismPlugin);
1649
+ options.init(Prism);
1650
+ markdownit.options.highlight = (text, lang) => highlight(markdownit, options, text, lang);
1651
+ }
1652
+
1653
+ // node/syntax/transform/code-wrapper.ts
1654
+ var reCodeBlock = /^```([\w'-]+?)(?:\s*{([\d\w*,\|-]+)}\s*?({.*?})?(.*?))?\n([\s\S]+?)^```$/mg;
1655
+ function transformCodeWrapper(md2) {
1656
+ return md2.replace(
1657
+ reCodeBlock,
1658
+ (full, lang = "", rangeStr = "", options = "", attrs = "", code) => {
1659
+ const ranges = normalizeRangeStr(rangeStr);
1660
+ code = code.trimEnd();
1661
+ options = options.trim() || "{}";
1662
+ return `
1663
+ <CodeBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
1664
+
1665
+ \`\`\`${lang}${attrs}
1666
+ ${code}
1667
+ \`\`\`
1668
+
1669
+ </CodeBlockWrapper>`;
1670
+ }
1671
+ );
1672
+ }
1673
+
1674
+ // node/syntax/transform/magic-move.ts
1675
+ import { codeToKeyedTokens } from "shiki-magic-move/core";
1676
+ import lz2 from "lz-string";
1677
+ var reMagicMoveBlock = /^````(?:md|markdown) magic-move(?:[ ]*(\{.*?\})?([^\n]*?))?\n([\s\S]+?)^````$/mg;
1678
+ function transformMagicMove(md2, shiki2, shikiOptions2) {
1679
+ return md2.replace(
1680
+ reMagicMoveBlock,
1681
+ (full, options = "{}", _attrs = "", body) => {
1682
+ if (!shiki2 || !shikiOptions2)
1683
+ throw new Error("Shiki is required for Magic Move. You may need to set `highlighter: shiki` in your Slidev config.");
1684
+ const matches = Array.from(body.matchAll(reCodeBlock));
1685
+ if (!matches.length)
1686
+ throw new Error("Magic Move block must contain at least one code block");
1687
+ const ranges = matches.map((i) => normalizeRangeStr(i[2]));
1688
+ const steps = matches.map(
1689
+ (i) => codeToKeyedTokens(shiki2, i[5].trimEnd(), {
1690
+ ...shikiOptions2,
1691
+ lang: i[1]
1692
+ })
1693
+ );
1694
+ const compressed = lz2.compressToBase64(JSON.stringify(steps));
1695
+ return `<ShikiMagicMove v-bind="${options}" steps-lz="${compressed}" :step-ranges='${JSON.stringify(ranges)}' />`;
1696
+ }
1697
+ );
1698
+ }
1699
+
1700
+ // node/syntax/transform/mermaid.ts
1701
+ import lz3 from "lz-string";
1702
+ function transformMermaid(md2) {
1703
+ return md2.replace(/^```mermaid\s*?({.*?})?\n([\s\S]+?)\n```/mg, (full, options = "", code = "") => {
1704
+ code = code.trim();
1705
+ options = options.trim() || "{}";
1706
+ const encoded = lz3.compressToBase64(code);
1707
+ return `<Mermaid code-lz="${encoded}" v-bind="${options}" />`;
1708
+ });
1709
+ }
1710
+
1711
+ // node/syntax/transform/plant-uml.ts
1712
+ import { encode as encodePlantUml } from "plantuml-encoder";
1713
+ function transformPlantUml(md2, server) {
1714
+ return md2.replace(/^```plantuml\s*?({.*?})?\n([\s\S]+?)\n```/mg, (full, options = "", content = "") => {
1715
+ const code = encodePlantUml(content.trim());
1716
+ options = options.trim() || "{}";
1717
+ return `<PlantUml :code="'${code}'" :server="'${server}'" v-bind="${options}" />`;
1718
+ });
1719
+ }
1720
+
1721
+ // node/syntax/transform/snippet.ts
1722
+ import path from "node:path";
1723
+ import fs5 from "fs-extra";
1724
+ function dedent(text) {
1725
+ const lines = text.split("\n");
1726
+ const minIndentLength = lines.reduce((acc, line) => {
1727
+ for (let i = 0; i < line.length; i++) {
1728
+ if (line[i] !== " " && line[i] !== " ")
1729
+ return Math.min(i, acc);
1730
+ }
1731
+ return acc;
1732
+ }, Number.POSITIVE_INFINITY);
1733
+ if (minIndentLength < Number.POSITIVE_INFINITY)
1734
+ return lines.map((x) => x.slice(minIndentLength)).join("\n");
1735
+ return text;
1736
+ }
1737
+ function testLine(line, regexp, regionName, end = false) {
1738
+ const [full, tag, name] = regexp.exec(line.trim()) || [];
1739
+ return full && tag && name === regionName && tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/);
1740
+ }
1741
+ function findRegion(lines, regionName) {
1742
+ const regionRegexps = [
1743
+ /^\/\/ ?#?((?:end)?region) ([\w*-]+)$/,
1744
+ // javascript, typescript, java
1745
+ /^\/\* ?#((?:end)?region) ([\w*-]+) ?\*\/$/,
1746
+ // css, less, scss
1747
+ /^#pragma ((?:end)?region) ([\w*-]+)$/,
1748
+ // C, C++
1749
+ /^<!-- #?((?:end)?region) ([\w*-]+) -->$/,
1750
+ // HTML, markdown
1751
+ /^#((?:End )Region) ([\w*-]+)$/,
1752
+ // Visual Basic
1753
+ /^::#((?:end)region) ([\w*-]+)$/,
1754
+ // Bat
1755
+ /^# ?((?:end)?region) ([\w*-]+)$/
1756
+ // C#, PHP, Powershell, Python, perl & misc
1757
+ ];
1758
+ let regexp = null;
1759
+ let start = -1;
1760
+ for (const [lineId, line] of lines.entries()) {
1761
+ if (regexp === null) {
1762
+ for (const reg of regionRegexps) {
1763
+ if (testLine(line, reg, regionName)) {
1764
+ start = lineId + 1;
1765
+ regexp = reg;
1766
+ break;
1767
+ }
1768
+ }
1769
+ } else if (testLine(line, regexp, regionName, true)) {
1770
+ return { start, end: lineId, regexp };
1771
+ }
1789
1772
  }
1773
+ return null;
1774
+ }
1775
+ function transformSnippet(md2, options, id) {
1776
+ const slideId = id.match(/(\d+)\.md$/)?.[1];
1777
+ if (!slideId)
1778
+ return md2;
1779
+ const data = options.data;
1780
+ const slideInfo = data.slides[+slideId - 1];
1781
+ const dir = path.dirname(slideInfo.source?.filepath ?? options.entry ?? options.userRoot);
1782
+ return md2.replace(
1783
+ /^<<< *(.+?)(#[\w-]+)? *(?: (\S+?))? *(\{.*)?$/mg,
1784
+ (full, filepath = "", regionName = "", lang = "", meta = "") => {
1785
+ const firstLine = `\`\`\`${lang || path.extname(filepath).slice(1)} ${meta}`;
1786
+ const src = /^\@[\/]/.test(filepath) ? path.resolve(options.userRoot, filepath.slice(2)) : path.resolve(dir, filepath);
1787
+ data.watchFiles.push(src);
1788
+ const isAFile = fs5.statSync(src).isFile();
1789
+ if (!fs5.existsSync(src) || !isAFile) {
1790
+ throw new Error(isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`);
1791
+ }
1792
+ let content = fs5.readFileSync(src, "utf8");
1793
+ slideInfo.snippetsUsed ??= {};
1794
+ slideInfo.snippetsUsed[src] = content;
1795
+ if (regionName) {
1796
+ const lines = content.split(/\r?\n/);
1797
+ const region = findRegion(lines, regionName.slice(1));
1798
+ if (region) {
1799
+ content = dedent(
1800
+ lines.slice(region.start, region.end).filter((line) => !region.regexp.test(line.trim())).join("\n")
1801
+ );
1802
+ }
1803
+ }
1804
+ return `${firstLine}
1805
+ ${content}
1806
+ \`\`\``;
1807
+ }
1808
+ );
1790
1809
  }
1810
+
1811
+ // node/syntax/transform/slot-sugar.ts
1812
+ function transformSlotSugar(md2) {
1813
+ const lines = md2.split(/\r?\n/g);
1814
+ let prevSlot = false;
1815
+ const { isLineInsideCodeblocks } = getCodeBlocks(md2);
1816
+ lines.forEach((line, idx) => {
1817
+ if (isLineInsideCodeblocks(idx))
1818
+ return;
1819
+ const match = line.trimEnd().match(/^::\s*([\w\.\-\:]+)\s*::$/);
1820
+ if (match) {
1821
+ lines[idx] = `${prevSlot ? "\n\n</template>\n" : "\n"}<template v-slot:${match[1]}="slotProps">
1791
1822
  `;
1792
- }
1793
- async function generteShikiBundle() {
1794
- const options = await loadShikiSetups(clientRoot, roots);
1795
- const langs = await resolveLangs(options.langs || ["javascript", "typescript", "html", "css"]);
1796
- const resolvedThemeOptions = "themes" in options ? {
1797
- themes: Object.fromEntries(await Promise.all(
1798
- Object.entries(options.themes).map(async ([name, value]) => [name, await resolveTheme(value)])
1799
- ))
1800
- } : {
1801
- theme: await resolveTheme(options.theme || "vitesse-dark")
1802
- };
1803
- const themes = resolvedThemeOptions.themes ? Object.values(resolvedThemeOptions.themes) : [resolvedThemeOptions.theme];
1804
- 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 };
1805
- async function normalizeGetter(p) {
1806
- return Promise.resolve(typeof p === "function" ? p() : p).then((r) => r.default || r);
1823
+ prevSlot = true;
1807
1824
  }
1808
- async function resolveLangs(langs2) {
1809
- return Array.from(new Set((await Promise.all(
1810
- langs2.map(async (lang) => await normalizeGetter(lang).then((r) => Array.isArray(r) ? r : [r]))
1811
- )).flat()));
1825
+ });
1826
+ if (prevSlot)
1827
+ lines[lines.length - 1] += "\n\n</template>";
1828
+ return lines.join("\n");
1829
+ }
1830
+
1831
+ // node/syntax/transform/in-page-css.ts
1832
+ function transformPageCSS(md2, id) {
1833
+ const page = id.match(/(\d+)\.md$/)?.[1];
1834
+ if (!page)
1835
+ return md2;
1836
+ const { isInsideCodeblocks } = getCodeBlocks(md2);
1837
+ const result = md2.replace(
1838
+ /(\n<style[^>]*?>)([\s\S]+?)(<\/style>)/g,
1839
+ (full, start, css, end, index) => {
1840
+ if (index < 0 || isInsideCodeblocks(index))
1841
+ return full;
1842
+ if (!start.includes("scoped"))
1843
+ start = start.replace("<style", "<style scoped");
1844
+ return `${start}
1845
+ ${css}${end}`;
1812
1846
  }
1813
- async function resolveTheme(theme) {
1814
- return typeof theme === "string" ? theme : await normalizeGetter(theme);
1847
+ );
1848
+ return result;
1849
+ }
1850
+
1851
+ // node/syntax/transform/katex-wrapper.ts
1852
+ function transformKaTexWrapper(md2) {
1853
+ return md2.replace(
1854
+ /^\$\$(?:\s*{([\d\w*,\|-]+)}\s*?({.*?})?\s*?)?\n([\s\S]+?)^\$\$/mg,
1855
+ (full, rangeStr = "", options = "", code) => {
1856
+ const ranges = !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
1857
+ code = code.trimEnd();
1858
+ options = options.trim() || "{}";
1859
+ return `<KaTexBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
1860
+
1861
+ $$
1862
+ ${code}
1863
+ $$
1864
+ </KaTexBlockWrapper>
1865
+ `;
1815
1866
  }
1816
- const langsInit = await Promise.all(
1817
- langs.map(async (lang) => typeof lang === "string" ? `import('${await resolveUrl(`shiki/langs/${lang}.mjs`)}')` : JSON.stringify(lang))
1818
- );
1819
- const themesInit = await Promise.all(themes.map(async (theme) => typeof theme === "string" ? `import('${await resolveUrl(`shiki/themes/${theme}.mjs`)}')` : JSON.stringify(theme)));
1820
- const langNames = langs.flatMap((lang) => typeof lang === "string" ? lang : lang.name);
1821
- const lines = [];
1822
- lines.push(
1823
- `import { getHighlighterCore } from "${await resolveUrl("shiki/core")}"`,
1824
- `export { shikiToMonaco } from "${await resolveUrl("@shikijs/monaco")}"`,
1825
- `export const languages = ${JSON.stringify(langNames)}`,
1826
- `export const themes = ${JSON.stringify(themeOptionsNames.themes || themeOptionsNames.theme)}`,
1827
- "export const shiki = getHighlighterCore({",
1828
- ` themes: [${themesInit.join(",")}],`,
1829
- ` langs: [${langsInit.join(",")}],`,
1830
- ` loadWasm: import('${await resolveUrl("shiki/wasm")}'),`,
1831
- "})"
1832
- );
1833
- return lines.join("\n");
1834
- }
1867
+ );
1835
1868
  }
1836
1869
 
1837
- // node/plugins/setupClient.ts
1838
- import { existsSync as existsSync2 } from "node:fs";
1839
- import { join as join5, resolve as resolve3 } from "node:path";
1840
- import { slash as slash2, uniq as uniq3 } from "@antfu/utils";
1841
- function createClientSetupPlugin({ themeRoots, addonRoots, userRoot, clientRoot }) {
1842
- const setupEntry = slash2(resolve3(clientRoot, "setup"));
1843
- return {
1844
- name: "slidev:setup",
1845
- enforce: "pre",
1846
- async transform(code, id) {
1847
- if (id.startsWith(setupEntry)) {
1848
- let getInjections2 = function(isAwait = false, isChained = false) {
1849
- return injections.join("\n").replace(/:AWAIT:/g, isAwait ? "await " : "").replace(/(,\s*)?:LAST:/g, isChained ? "$1injection_return" : "");
1850
- };
1851
- var getInjections = getInjections2;
1852
- const name = id.slice(setupEntry.length + 1).replace(/\?.*$/, "");
1853
- const imports = [];
1854
- const injections = [];
1855
- const setups = uniq3([
1856
- ...themeRoots,
1857
- ...addonRoots,
1858
- userRoot
1859
- ]).map((i) => join5(i, "setup", name));
1860
- setups.forEach((path2, idx) => {
1861
- if (!existsSync2(path2))
1862
- return;
1863
- imports.push(`import __n${idx} from '${toAtFS(path2)}'`);
1864
- let fn = `:AWAIT:__n${idx}`;
1865
- if (/\binjection_return\b/g.test(code))
1866
- fn = `injection_return = ${fn}`;
1867
- if (/\binjection_arg\b/g.test(code)) {
1868
- fn += "(";
1869
- const matches = Array.from(code.matchAll(/\binjection_arg(_\d+)?\b/g));
1870
- const dedupedMatches = Array.from(new Set(matches.map((m) => m[0])));
1871
- fn += dedupedMatches.join(", ");
1872
- fn += ", :LAST:)";
1873
- } else {
1874
- fn += "(:LAST:)";
1870
+ // node/vite/markdown.ts
1871
+ var shiki;
1872
+ var shikiOptions;
1873
+ async function createMarkdownPlugin(options, { markdown: mdOptions }) {
1874
+ const { data: { config }, roots, mode, entry, clientRoot } = options;
1875
+ const setups = [];
1876
+ const entryPath = slash(entry);
1877
+ if (config.highlighter === "shiki") {
1878
+ const [
1879
+ options2,
1880
+ { getHighlighter, bundledLanguages },
1881
+ markdownItShiki,
1882
+ transformerTwoslash
1883
+ ] = await Promise.all([
1884
+ loadShikiSetups(clientRoot, roots),
1885
+ import("shiki").then(({ getHighlighter: getHighlighter2, bundledLanguages: bundledLanguages2 }) => ({ bundledLanguages: bundledLanguages2, getHighlighter: getHighlighter2 })),
1886
+ import("@shikijs/markdown-it/core").then(({ fromHighlighter }) => fromHighlighter),
1887
+ import("@shikijs/vitepress-twoslash").then(({ transformerTwoslash: transformerTwoslash2 }) => transformerTwoslash2)
1888
+ ]);
1889
+ shikiOptions = options2;
1890
+ shiki = await getHighlighter({
1891
+ ...options2,
1892
+ langs: options2.langs ?? Object.keys(bundledLanguages),
1893
+ themes: "themes" in options2 ? Object.values(options2.themes) : [options2.theme]
1894
+ });
1895
+ const transformers = [
1896
+ ...options2.transformers || [],
1897
+ transformerTwoslash({
1898
+ explicitTrigger: true,
1899
+ twoslashOptions: {
1900
+ handbookOptions: {
1901
+ noErrorValidation: true
1875
1902
  }
1876
- injections.push(
1877
- `// ${path2}`,
1878
- fn
1879
- );
1880
- });
1881
- code = code.replace("/* __imports__ */", imports.join("\n"));
1882
- code = code.replace("/* __injections__ */", getInjections2());
1883
- code = code.replace("/* __async_injections__ */", getInjections2(true));
1884
- code = code.replace("/* __chained_injections__ */", getInjections2(false, true));
1885
- code = code.replace("/* __chained_async_injections__ */", getInjections2(true, true));
1903
+ }
1904
+ }),
1905
+ {
1906
+ pre(pre) {
1907
+ this.addClassToHast(pre, "slidev-code");
1908
+ delete pre.properties.tabindex;
1909
+ },
1910
+ postprocess(code) {
1911
+ return escapeVueInCode(code);
1912
+ }
1913
+ }
1914
+ ];
1915
+ const plugin = markdownItShiki(shiki, {
1916
+ ...options2,
1917
+ transformers
1918
+ });
1919
+ setups.push((md2) => md2.use(plugin));
1920
+ } else {
1921
+ setups.push((md2) => md2.use(markdownItPrism));
1922
+ }
1923
+ if (config.mdc)
1924
+ setups.push((md2) => md2.use(MarkdownItMdc));
1925
+ const KatexOptions = await loadSetups(options.clientRoot, roots, "katex.ts", {}, { strict: false }, false);
1926
+ return Markdown2({
1927
+ include: [/\.md$/],
1928
+ wrapperClasses: "",
1929
+ headEnabled: false,
1930
+ frontmatter: false,
1931
+ escapeCodeTagInterpolation: false,
1932
+ markdownItOptions: {
1933
+ quotes: `""''`,
1934
+ html: true,
1935
+ xhtmlOut: true,
1936
+ linkify: true,
1937
+ ...mdOptions?.markdownItOptions
1938
+ },
1939
+ ...mdOptions,
1940
+ markdownItSetup(md2) {
1941
+ md2.use(MarkdownItAttrs, {
1942
+ attrs: {
1943
+ target: "_blank",
1944
+ rel: "noopener"
1945
+ }
1946
+ });
1947
+ md2.use(MarkdownItFootnote);
1948
+ md2.use(taskLists, { enabled: true, lineNumber: true, label: true });
1949
+ md2.use(math_plugin, KatexOptions);
1950
+ setups.forEach((i) => i(md2));
1951
+ mdOptions?.markdownItSetup?.(md2);
1952
+ },
1953
+ transforms: {
1954
+ before(code, id) {
1955
+ if (id === entryPath)
1956
+ return "";
1957
+ const monacoEnabled = config.monaco === true || config.monaco === mode;
1958
+ if (config.highlighter === "shiki")
1959
+ code = transformMagicMove(code, shiki, shikiOptions);
1960
+ code = transformSlotSugar(code);
1961
+ code = transformSnippet(code, options, id);
1962
+ code = transformMermaid(code);
1963
+ code = transformPlantUml(code, config.plantUmlServer);
1964
+ code = transformMonaco(code, monacoEnabled);
1965
+ code = transformCodeWrapper(code);
1966
+ code = transformPageCSS(code, id);
1967
+ code = transformKaTexWrapper(code);
1886
1968
  return code;
1887
1969
  }
1888
- return null;
1889
1970
  }
1890
- };
1971
+ });
1891
1972
  }
1892
1973
 
1893
- // node/plugins/patchTransform.ts
1974
+ // node/vite/compilerFlagsVue.ts
1894
1975
  import { objectEntries } from "@antfu/utils";
1895
- function createFixPlugins(options) {
1976
+ function createVueCompilerFlagsPlugin(options) {
1896
1977
  const define = objectEntries(getDefine(options));
1897
1978
  return [
1898
1979
  {
@@ -1912,11 +1993,11 @@ function createFixPlugins(options) {
1912
1993
  ];
1913
1994
  }
1914
1995
 
1915
- // node/plugins/monacoTypes.ts
1996
+ // node/vite/monacoTypes.ts
1916
1997
  import fs6 from "node:fs/promises";
1917
- import { dirname as dirname2, resolve as resolve4 } from "node:path";
1918
- import { slash as slash3 } from "@antfu/utils";
1919
- import fg3 from "fast-glob";
1998
+ import { dirname as dirname2, resolve as resolve3 } from "node:path";
1999
+ import { slash as slash2 } from "@antfu/utils";
2000
+ import fg4 from "fast-glob";
1920
2001
  import { findDepPkgJsonPath } from "vitefu";
1921
2002
  function createMonacoTypesLoader({ userRoot }) {
1922
2003
  const resolvedDepsMap = {};
@@ -1942,14 +2023,14 @@ function createMonacoTypesLoader({ userRoot }) {
1942
2023
  const pkgJson = JSON.parse(await fs6.readFile(pkgJsonPath, "utf-8"));
1943
2024
  const deps = pkgJson.dependencies ?? {};
1944
2025
  return [
1945
- `import "/@slidev-monaco-types/load?root=${slash3(root)}&name=${pkgJson.name}"`,
1946
- ...Object.keys(deps).map((dep) => `import "/@slidev-monaco-types/resolve?pkg=${dep}&importer=${slash3(root)}"`)
2026
+ `import "/@slidev-monaco-types/load?root=${slash2(root)}&name=${pkgJson.name}"`,
2027
+ ...Object.keys(deps).map((dep) => `import "/@slidev-monaco-types/resolve?pkg=${dep}&importer=${slash2(root)}"`)
1947
2028
  ].join("\n");
1948
2029
  }
1949
2030
  const matchLoad = id.match(/^\/\@slidev-monaco-types\/load\?root=(.*?)&name=(.*)$/);
1950
2031
  if (matchLoad) {
1951
2032
  const [_, root, name] = matchLoad;
1952
- const files = await fg3(
2033
+ const files = await fg4(
1953
2034
  [
1954
2035
  "**/*.ts",
1955
2036
  "**/*.mts",
@@ -1966,14 +2047,16 @@ function createMonacoTypesLoader({ userRoot }) {
1966
2047
  return "";
1967
2048
  return [
1968
2049
  'import { addFile } from "@slidev/client/setup/monaco.ts"',
1969
- ...files.map((file) => `addFile(import(${JSON.stringify(`${toAtFS(resolve4(root, file))}?monaco-types&raw`)}), ${JSON.stringify(`node_modules/${name}/${file}`)})`)
2050
+ ...files.map((file) => `addFile(import(${JSON.stringify(`${toAtFS(resolve3(root, file))}?monaco-types&raw`)}), ${JSON.stringify(`node_modules/${name}/${file}`)})`)
1970
2051
  ].join("\n");
1971
2052
  }
1972
2053
  }
1973
2054
  };
1974
2055
  }
1975
2056
 
1976
- // node/plugins/preset.ts
2057
+ // node/vite/vue.ts
2058
+ import Vue from "@vitejs/plugin-vue";
2059
+ import VueJsx from "@vitejs/plugin-vue-jsx";
1977
2060
  var customElements = /* @__PURE__ */ new Set([
1978
2061
  // katex
1979
2062
  "annotation",
@@ -2004,22 +2087,11 @@ var customElements = /* @__PURE__ */ new Set([
2004
2087
  "munderover",
2005
2088
  "semantics"
2006
2089
  ]);
2007
- async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
2090
+ async function createVuePlugin(options, pluginOptions) {
2008
2091
  const {
2009
2092
  vue: vueOptions = {},
2010
- vuejsx: vuejsxOptions = {},
2011
- components: componentsOptions = {},
2012
- icons: iconsOptions = {},
2013
- remoteAssets: remoteAssetsOptions = {},
2014
- serverRef: serverRefOptions = {}
2093
+ vuejsx: vuejsxOptions = {}
2015
2094
  } = pluginOptions;
2016
- const {
2017
- mode,
2018
- themeRoots,
2019
- addonRoots,
2020
- roots,
2021
- data: { config }
2022
- } = options;
2023
2095
  const VuePlugin = Vue({
2024
2096
  include: [/\.vue$/, /\.md$/],
2025
2097
  exclude: [],
@@ -2034,22 +2106,41 @@ async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
2034
2106
  ...vueOptions
2035
2107
  });
2036
2108
  const VueJsxPlugin = VueJsx(vuejsxOptions);
2037
- const MarkdownPlugin = await createMarkdownPlugin(options, pluginOptions);
2109
+ return [
2110
+ VueJsxPlugin,
2111
+ VuePlugin
2112
+ ];
2113
+ }
2114
+
2115
+ // node/vite/index.ts
2116
+ async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
2117
+ const {
2118
+ components: componentsOptions = {},
2119
+ icons: iconsOptions = {},
2120
+ remoteAssets: remoteAssetsOptions = {},
2121
+ serverRef: serverRefOptions = {}
2122
+ } = pluginOptions;
2123
+ const {
2124
+ mode,
2125
+ themeRoots,
2126
+ addonRoots,
2127
+ roots,
2128
+ data: { config }
2129
+ } = options;
2038
2130
  const drawingData = await loadDrawings(options);
2039
- const publicRoots = [...themeRoots, ...addonRoots].map((i) => join6(i, "public")).filter(existsSync3);
2131
+ const publicRoots = [...themeRoots, ...addonRoots].map((i) => join8(i, "public")).filter(existsSync5);
2040
2132
  const plugins = [
2041
- MarkdownPlugin,
2042
- VueJsxPlugin,
2043
- VuePlugin,
2133
+ createMarkdownPlugin(options, pluginOptions),
2134
+ createVuePlugin(options, pluginOptions),
2044
2135
  createSlidesLoader(options, pluginOptions, serverOptions),
2045
2136
  Components({
2046
2137
  extensions: ["vue", "md", "js", "ts", "jsx", "tsx"],
2047
2138
  dirs: [
2048
- join6(options.clientRoot, "builtin"),
2049
- ...roots.map((i) => join6(i, "components")),
2139
+ join8(options.clientRoot, "builtin"),
2140
+ ...roots.map((i) => join8(i, "components")),
2050
2141
  "src/components",
2051
2142
  "components",
2052
- join6(process.cwd(), "components")
2143
+ join8(process.cwd(), "components")
2053
2144
  ],
2054
2145
  include: [/\.vue$/, /\.vue\?vue/, /\.vue\?v=/, /\.md$/, /\.md\?vue/],
2055
2146
  exclude: [],
@@ -2100,9 +2191,8 @@ async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
2100
2191
  }
2101
2192
  }),
2102
2193
  createConfigPlugin(options),
2103
- createClientSetupPlugin(options),
2104
2194
  createMonacoTypesLoader(options),
2105
- createFixPlugins(options),
2195
+ createVueCompilerFlagsPlugin(options),
2106
2196
  publicRoots.length ? import("vite-plugin-static-copy").then((r) => r.viteStaticCopy({
2107
2197
  silent: true,
2108
2198
  targets: publicRoots.map((r2) => ({
@@ -2114,14 +2204,12 @@ async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
2114
2204
  dev: true,
2115
2205
  build: true
2116
2206
  })) : null,
2117
- config.css === "none" ? null : import("./unocss-M5KPNI4Z.mjs").then((r) => r.createUnocssPlugin(options, pluginOptions))
2207
+ config.css === "none" ? null : import("./unocss-AGKZGMYO.mjs").then((r) => r.createUnocssPlugin(options, pluginOptions))
2118
2208
  ];
2119
2209
  return (await Promise.all(plugins)).flat().filter(notNullish2);
2120
2210
  }
2121
2211
 
2122
2212
  export {
2123
- version,
2124
- checkEngine,
2125
2213
  getIndexHtml,
2126
2214
  mergeViteConfigs,
2127
2215
  ViteSlidevPlugin