@slidev/cli 0.48.0-beta.23 → 0.48.0-beta.25

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