@slidev/cli 0.46.3 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ import {
7
7
  resolveImportPath,
8
8
  stringifyMarkdownTokens,
9
9
  toAtFS
10
- } from "./chunk-5L3XKTHL.mjs";
10
+ } from "./chunk-LU235VRZ.mjs";
11
11
 
12
12
  // node/common.ts
13
13
  import { existsSync, promises as fs } from "node:fs";
@@ -25,10 +25,10 @@ async function getIndexHtml({ clientRoot, themeRoots, addonRoots, data, userRoot
25
25
  userRoot
26
26
  ]);
27
27
  for (const root of roots) {
28
- const path = join(root, "index.html");
29
- if (!existsSync(path))
28
+ const path2 = join(root, "index.html");
29
+ if (!existsSync(path2))
30
30
  continue;
31
- const index = await fs.readFile(path, "utf-8");
31
+ const index = await fs.readFile(path2, "utf-8");
32
32
  head += `
33
33
  ${(index.match(/<head>([\s\S]*?)<\/head>/im)?.[1] || "").trim()}`;
34
34
  body += `
@@ -68,7 +68,7 @@ async function mergeViteConfigs({ addonRoots, themeRoots, entry }, viteConfig, c
68
68
  // node/plugins/preset.ts
69
69
  import { join as join8 } from "node:path";
70
70
  import { existsSync as existsSync3 } from "node:fs";
71
- import process3 from "node:process";
71
+ import process2 from "node:process";
72
72
  import Vue from "@vitejs/plugin-vue";
73
73
  import VueJsx from "@vitejs/plugin-vue-jsx";
74
74
  import Icons from "unplugin-icons/vite";
@@ -98,11 +98,11 @@ async function loadDrawings(options) {
98
98
  suppressErrors: true
99
99
  });
100
100
  const obj = {};
101
- await Promise.all(files.map(async (path) => {
102
- const num = +basename(path, ".svg");
101
+ await Promise.all(files.map(async (path2) => {
102
+ const num = +basename(path2, ".svg");
103
103
  if (Number.isNaN(num))
104
104
  return;
105
- const content = await fs2.readFile(path, "utf8");
105
+ const content = await fs2.readFile(path2, "utf8");
106
106
  const lines = content.split(/\n/g);
107
107
  obj[num.toString()] = lines.slice(1, -1).join("\n");
108
108
  }));
@@ -137,10 +137,11 @@ import { uniq as uniq2 } from "@antfu/utils";
137
137
  // ../client/package.json
138
138
  var dependencies = {
139
139
  "@antfu/utils": "^0.7.7",
140
+ "@shikijs/vitepress-twoslash": "^1.0.0-beta.3",
140
141
  "@slidev/parser": "workspace:*",
141
142
  "@slidev/types": "workspace:*",
142
143
  "@unhead/vue": "^1.8.10",
143
- "@unocss/reset": "^0.58.3",
144
+ "@unocss/reset": "^0.58.4",
144
145
  "@vueuse/core": "^10.7.2",
145
146
  "@vueuse/math": "^10.7.2",
146
147
  "@vueuse/motion": "^2.0.0",
@@ -148,22 +149,20 @@ var dependencies = {
148
149
  defu: "^6.1.4",
149
150
  drauu: "^0.3.7",
150
151
  "file-saver": "^2.0.5",
152
+ "floating-vue": "^5.2.2",
151
153
  "fuse.js": "^7.0.0",
152
154
  "js-base64": "^3.7.6",
153
155
  "js-yaml": "^4.1.0",
154
156
  katex: "^0.16.9",
155
- mermaid: "^10.7.0",
157
+ mermaid: "^10.8.0",
156
158
  "monaco-editor": "^0.37.1",
157
- nanoid: "^5.0.4",
159
+ nanoid: "^5.0.5",
158
160
  prettier: "^3.2.4",
159
161
  recordrtc: "^5.6.2",
160
162
  resolve: "^1.22.8",
161
- unocss: "^0.58.3",
162
- "vite-plugin-windicss": "^1.9.3",
163
+ unocss: "^0.58.4",
163
164
  vue: "^3.4.15",
164
- "vue-router": "^4.2.5",
165
- "vue-starport": "^0.4.0",
166
- windicss: "^3.5.6"
165
+ "vue-router": "^4.2.5"
167
166
  };
168
167
 
169
168
  // node/vite/searchRoot.ts
@@ -180,21 +179,21 @@ var ROOT_FILES = [
180
179
  // 'nx.json'
181
180
  ];
182
181
  function hasWorkspacePackageJSON(root) {
183
- const path = join3(root, "package.json");
182
+ const path2 = join3(root, "package.json");
184
183
  try {
185
- fs3.accessSync(path, fs3.constants.R_OK);
184
+ fs3.accessSync(path2, fs3.constants.R_OK);
186
185
  } catch {
187
186
  return false;
188
187
  }
189
- const content = JSON.parse(fs3.readFileSync(path, "utf-8")) || {};
188
+ const content = JSON.parse(fs3.readFileSync(path2, "utf-8")) || {};
190
189
  return !!content.workspaces;
191
190
  }
192
191
  function hasRootFile(root) {
193
192
  return ROOT_FILES.some((file) => fs3.existsSync(join3(root, file)));
194
193
  }
195
194
  function hasPackageJSON(root) {
196
- const path = join3(root, "package.json");
197
- return fs3.existsSync(path);
195
+ const path2 = join3(root, "package.json");
196
+ return fs3.existsSync(path2);
198
197
  }
199
198
  function searchForPackageRoot(current, root = current) {
200
199
  if (hasPackageJSON(current))
@@ -227,7 +226,6 @@ var EXCLUDE = [
227
226
  "@unocss/reset",
228
227
  "unocss",
229
228
  "mermaid",
230
- "vite-plugin-windicss",
231
229
  "vue-demi",
232
230
  "vue"
233
231
  ];
@@ -274,17 +272,22 @@ function createConfigPlugin(options) {
274
272
  allow: uniq2([
275
273
  searchForWorkspaceRoot(options.userRoot),
276
274
  searchForWorkspaceRoot(options.cliRoot),
277
- ...isInstalledGlobally ? [dirname3(resolveGlobalImportPath("@slidev/client/package.json")), dirname3(resolveGlobalImportPath("katex/package.json"))] : []
275
+ ...isInstalledGlobally ? [
276
+ dirname3(await resolveGlobalImportPath("@slidev/client/package.json")),
277
+ dirname3(await resolveGlobalImportPath("katex/package.json"))
278
+ ] : []
278
279
  ])
279
280
  }
280
281
  },
281
282
  publicDir: join4(options.userRoot, "public")
282
283
  };
284
+ injection.resolve ||= {};
285
+ injection.resolve.alias ||= {};
283
286
  if (isInstalledGlobally) {
284
287
  injection.cacheDir = join4(options.cliRoot, "node_modules/.vite");
285
288
  injection.root = options.cliRoot;
286
- injection.resolve.alias.vue = `${resolveImportPath("vue/dist/vue.esm-browser.js", true)}`;
287
289
  }
290
+ injection.resolve.alias.vue = await resolveImportPath("vue/dist/vue.esm-browser.js", true);
288
291
  return mergeConfig2(injection, config);
289
292
  },
290
293
  configureServer(server) {
@@ -318,7 +321,6 @@ function getDefine(options) {
318
321
 
319
322
  // node/plugins/loaders.ts
320
323
  import { basename as basename2, join as join5 } from "node:path";
321
- import process from "node:process";
322
324
  import { isString, notNullish, objectMap, range, slash, uniq as uniq3 } from "@antfu/utils";
323
325
  import fg2 from "fast-glob";
324
326
  import fs4 from "fs-extra";
@@ -330,7 +332,7 @@ import equal from "fast-deep-equal";
330
332
  var regexId = /^\/\@slidev\/slide\/(\d+)\.(md|json)(?:\?import)?$/;
331
333
  var regexIdQuery = /(\d+?)\.(md|json|frontmatter)$/;
332
334
  var vueContextImports = [
333
- 'import { inject as _vueInject, provide as _vueProvide, toRef as _vueToRef } from "vue"',
335
+ `import { inject as _vueInject, provide as _vueProvide, toRef as _vueToRef } from "vue"`,
334
336
  `import {
335
337
  injectionSlidevContext as _injectionSlidevContext,
336
338
  injectionClicks as _injectionClicks,
@@ -345,13 +347,13 @@ var vueContextImports = [
345
347
  "const $renderContext = _vueInject(_injectionRenderContext)"
346
348
  ];
347
349
  function getBodyJson(req) {
348
- return new Promise((resolve4, reject) => {
350
+ return new Promise((resolve3, reject) => {
349
351
  let body = "";
350
352
  req.on("data", (chunk) => body += chunk);
351
353
  req.on("error", reject);
352
354
  req.on("end", () => {
353
355
  try {
354
- resolve4(JSON.parse(body) || {});
356
+ resolve3(JSON.parse(body) || {});
355
357
  } catch (e) {
356
358
  reject(e);
357
359
  }
@@ -436,7 +438,14 @@ function createSlidesLoader({ data, entry, clientRoot, themeRoots, addonRoots, u
436
438
  for (let i = 0; i < length; i++) {
437
439
  const a = data.slides[i];
438
440
  const b = newData.slides[i];
439
- if (a?.content.trim() === b?.content.trim() && a?.title?.trim() === b?.title?.trim() && a?.note === b?.note && equal(a.frontmatter, b.frontmatter))
441
+ if (a?.content.trim() === b?.content.trim() && a?.title?.trim() === b?.title?.trim() && a?.note === b?.note && equal(a.frontmatter, b.frontmatter) && Object.entries(a.snippetsUsed ?? {}).every(([file, oldContent]) => {
442
+ try {
443
+ const newContent = fs4.readFileSync(file, "utf-8");
444
+ return oldContent === newContent;
445
+ } catch {
446
+ return false;
447
+ }
448
+ }))
440
449
  continue;
441
450
  ctx.server.ws.send({
442
451
  type: "custom",
@@ -511,11 +520,18 @@ ${title}
511
520
  map: { mappings: "" }
512
521
  };
513
522
  } else if (type === "frontmatter") {
523
+ const slideBase = {
524
+ ...prepareSlideInfo(slide),
525
+ frontmatter: void 0,
526
+ // remove raw content in build, optimize the bundle size
527
+ ...mode === "build" ? { raw: "", content: "", note: "" } : {}
528
+ };
529
+ const fontmatter = getFrontmatter(pageNo);
514
530
  return {
515
531
  code: [
516
532
  "// @unocss-include",
517
533
  'import { reactive, computed } from "vue"',
518
- `export const frontmatter = reactive(${JSON.stringify(slide.frontmatter)})`,
534
+ `export const frontmatter = reactive(${JSON.stringify(fontmatter)})`,
519
535
  `export const meta = reactive({
520
536
  layout: computed(() => frontmatter.layout),
521
537
  transition: computed(() => frontmatter.transition),
@@ -524,12 +540,7 @@ ${title}
524
540
  name: computed(() => frontmatter.name),
525
541
  preload: computed(() => frontmatter.preload),
526
542
  slide: {
527
- ...(${JSON.stringify({
528
- ...prepareSlideInfo(slide),
529
- frontmatter: void 0,
530
- // remove raw content in build, optimize the bundle size
531
- ...mode === "build" ? { raw: "", content: "", note: "" } : {}
532
- })}),
543
+ ...(${JSON.stringify(slideBase)}),
533
544
  frontmatter,
534
545
  filepath: ${JSON.stringify(slide.source?.filepath || entry)},
535
546
  id: ${pageNo},
@@ -575,7 +586,7 @@ ${title}
575
586
  if (type !== "md")
576
587
  return;
577
588
  const pageNo = Number.parseInt(no) - 1;
578
- return transformMarkdown(code, pageNo, data);
589
+ return transformMarkdown(code, pageNo);
579
590
  }
580
591
  },
581
592
  {
@@ -613,12 +624,15 @@ ${title}
613
624
  return;
614
625
  server.watcher.add(data.entries?.map(slash) || []);
615
626
  }
616
- async function transformMarkdown(code, pageNo, data2) {
617
- const layouts = await getLayouts();
618
- const frontmatter = {
619
- ...data2.headmatter?.defaults || {},
620
- ...data2.slides[pageNo]?.frontmatter || {}
627
+ function getFrontmatter(pageNo) {
628
+ return {
629
+ ...data.headmatter?.defaults || {},
630
+ ...data.slides[pageNo]?.frontmatter || {}
621
631
  };
632
+ }
633
+ async function transformMarkdown(code, pageNo) {
634
+ const layouts = await getLayouts();
635
+ const frontmatter = getFrontmatter(pageNo);
622
636
  let layoutName = frontmatter?.layout || (pageNo === 0 ? "cover" : "default");
623
637
  if (!layouts[layoutName]) {
624
638
  console.error(red(`
@@ -741,13 +755,19 @@ defineProps<{ no: number | string }>()`);
741
755
  _layouts_cache = layouts;
742
756
  return layouts;
743
757
  }
758
+ async function resolveUrl(id) {
759
+ return toAtFS(await resolveImportPath(id, true));
760
+ }
761
+ function resolveUrlOfClient(name) {
762
+ return toAtFS(join5(clientRoot, name));
763
+ }
744
764
  async function generateUserStyles() {
745
765
  const imports = [
746
- `import "${toAtFS(join5(clientRoot, "styles/vars.css"))}"`,
747
- `import "${toAtFS(join5(clientRoot, "styles/index.css"))}"`,
748
- `import "${toAtFS(join5(clientRoot, "styles/code.css"))}"`,
749
- `import "${toAtFS(join5(clientRoot, "styles/katex.css"))}"`,
750
- `import "${toAtFS(join5(clientRoot, "styles/transitions.css"))}"`
766
+ `import "${resolveUrlOfClient("styles/vars.css")}"`,
767
+ `import "${resolveUrlOfClient("styles/index.css")}"`,
768
+ `import "${resolveUrlOfClient("styles/code.css")}"`,
769
+ `import "${resolveUrlOfClient("styles/katex.css")}"`,
770
+ `import "${resolveUrlOfClient("styles/transitions.css")}"`
751
771
  ];
752
772
  const roots2 = uniq3([
753
773
  ...themeRoots,
@@ -770,25 +790,21 @@ defineProps<{ no: number | string }>()`);
770
790
  }
771
791
  }
772
792
  if (data.features.katex)
773
- imports.push(`import "${toAtFS(resolveImportPath("katex/dist/katex.min.css", true))}"`);
774
- if (data.config.highlighter === "shikiji")
775
- imports.push(`import "${toAtFS(resolveImportPath("shikiji-twoslash/style-rich.css", true))}"`);
793
+ imports.push(`import "${await resolveUrl("katex/dist/katex.min.css")}"`);
794
+ if (data.config.highlighter === "shiki") {
795
+ imports.push(
796
+ `import "${await resolveUrl("@shikijs/vitepress-twoslash/style.css")}"`,
797
+ `import "${resolveUrlOfClient("styles/shiki-twoslash.css")}"`
798
+ );
799
+ }
776
800
  if (data.config.css === "unocss") {
777
801
  imports.unshift(
778
- 'import "@unocss/reset/tailwind.css"',
802
+ `import "${await resolveUrl("@unocss/reset/tailwind.css")}"`,
779
803
  'import "uno:preflights.css"',
780
804
  'import "uno:typography.css"',
781
805
  'import "uno:shortcuts.css"'
782
806
  );
783
807
  imports.push('import "uno.css"');
784
- } else {
785
- imports.unshift(
786
- 'import "virtual:windi-components.css"',
787
- 'import "virtual:windi-base.css"'
788
- );
789
- imports.push('import "virtual:windi-utilities.css"');
790
- if (process.env.NODE_ENV !== "production")
791
- imports.push('import "virtual:windi-devtools"');
792
808
  }
793
809
  return imports.join("\n");
794
810
  }
@@ -895,11 +911,11 @@ export default {
895
911
  // node/plugins/monacoTransform.ts
896
912
  import { dirname as dirname4, join as join6 } from "node:path";
897
913
  import fs5 from "node:fs/promises";
898
- import process2 from "node:process";
914
+ import process from "node:process";
899
915
  import { slash as slash2 } from "@antfu/utils";
900
916
  import { findDepPkgJsonPath } from "vitefu";
901
917
  async function getPackageData(pkg) {
902
- const pkgJsonPath = await findDepPkgJsonPath(pkg, process2.cwd());
918
+ const pkgJsonPath = await findDepPkgJsonPath(pkg, process.cwd());
903
919
  if (!pkgJsonPath)
904
920
  return;
905
921
  const pkgJson = JSON.parse(await fs5.readFile(pkgJsonPath, "utf-8"));
@@ -958,10 +974,10 @@ function createClientSetupPlugin({ clientRoot, themeRoots, addonRoots, userRoot
958
974
  ...addonRoots,
959
975
  userRoot
960
976
  ]).map((i) => join7(i, "setup", name));
961
- setups.forEach((path, idx) => {
962
- if (!existsSync2(path))
977
+ setups.forEach((path2, idx) => {
978
+ if (!existsSync2(path2))
963
979
  return;
964
- imports.push(`import __n${idx} from '${toAtFS(path)}'`);
980
+ imports.push(`import __n${idx} from '${toAtFS(path2)}'`);
965
981
  let fn = `:AWAIT:__n${idx}`;
966
982
  if (/\binjection_return\b/g.test(code))
967
983
  fn = `injection_return = ${fn}`;
@@ -975,7 +991,7 @@ function createClientSetupPlugin({ clientRoot, themeRoots, addonRoots, userRoot
975
991
  fn += "(:LAST:)";
976
992
  }
977
993
  injections.push(
978
- `// ${path}`,
994
+ `// ${path2}`,
979
995
  fn
980
996
  );
981
997
  });
@@ -992,7 +1008,7 @@ function createClientSetupPlugin({ clientRoot, themeRoots, addonRoots, userRoot
992
1008
  }
993
1009
 
994
1010
  // node/plugins/markdown.ts
995
- import { resolve as resolve3 } from "node:path";
1011
+ import fs7 from "node:fs/promises";
996
1012
  import Markdown2 from "unplugin-vue-markdown/vite";
997
1013
  import * as base64 from "js-base64";
998
1014
  import { slash as slash4 } from "@antfu/utils";
@@ -1130,8 +1146,6 @@ import { Optional } from "@mrdrogdrog/optional";
1130
1146
  // node/plugins/markdown.ts
1131
1147
  import { encode as encode2 } from "plantuml-encoder";
1132
1148
  import Mdc from "markdown-it-mdc";
1133
- import { addClassToHast } from "shikiji";
1134
- import fs6 from "fs-extra";
1135
1149
 
1136
1150
  // node/plugins/markdown-it-katex.ts
1137
1151
  import katex from "katex";
@@ -1381,97 +1395,121 @@ function markdownItPrism(markdownit, useroptions) {
1381
1395
  markdownit.options.highlight = (text, lang) => highlight(markdownit, options, text, lang);
1382
1396
  }
1383
1397
 
1384
- // node/plugins/markdown-it-shiki.ts
1385
- function getThemeName(theme) {
1386
- if (typeof theme === "string")
1387
- return theme;
1388
- return theme.name;
1398
+ // node/plugins/transformSnippet.ts
1399
+ import path from "node:path";
1400
+ import fs6 from "fs-extra";
1401
+ function dedent(text) {
1402
+ const lines = text.split("\n");
1403
+ const minIndentLength = lines.reduce((acc, line) => {
1404
+ for (let i = 0; i < line.length; i++) {
1405
+ if (line[i] !== " " && line[i] !== " ")
1406
+ return Math.min(i, acc);
1407
+ }
1408
+ return acc;
1409
+ }, Number.POSITIVE_INFINITY);
1410
+ if (minIndentLength < Number.POSITIVE_INFINITY)
1411
+ return lines.map((x) => x.slice(minIndentLength)).join("\n");
1412
+ return text;
1389
1413
  }
1390
- function isShikiDarkModeThemes(theme) {
1391
- return typeof theme === "object" && ("dark" in theme || "light" in theme);
1414
+ function testLine(line, regexp, regionName, end = false) {
1415
+ const [full, tag, name] = regexp.exec(line.trim()) || [];
1416
+ return full && tag && name === regionName && tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/);
1392
1417
  }
1393
- function resolveShikiOptions(options) {
1394
- const themes = [];
1395
- let darkModeThemes;
1396
- if (!options.theme) {
1397
- themes.push("nord");
1398
- } else if (typeof options.theme === "string") {
1399
- themes.push(options.theme);
1400
- } else {
1401
- if (isShikiDarkModeThemes(options.theme)) {
1402
- darkModeThemes = options.theme;
1403
- themes.push(options.theme.dark);
1404
- themes.push(options.theme.light);
1405
- } else {
1406
- themes.push(options.theme);
1418
+ function findRegion(lines, regionName) {
1419
+ const regionRegexps = [
1420
+ /^\/\/ ?#?((?:end)?region) ([\w*-]+)$/,
1421
+ // javascript, typescript, java
1422
+ /^\/\* ?#((?:end)?region) ([\w*-]+) ?\*\/$/,
1423
+ // css, less, scss
1424
+ /^#pragma ((?:end)?region) ([\w*-]+)$/,
1425
+ // C, C++
1426
+ /^<!-- #?((?:end)?region) ([\w*-]+) -->$/,
1427
+ // HTML, markdown
1428
+ /^#((?:End )Region) ([\w*-]+)$/,
1429
+ // Visual Basic
1430
+ /^::#((?:end)region) ([\w*-]+)$/,
1431
+ // Bat
1432
+ /^# ?((?:end)?region) ([\w*-]+)$/
1433
+ // C#, PHP, Powershell, Python, perl & misc
1434
+ ];
1435
+ let regexp = null;
1436
+ let start = -1;
1437
+ for (const [lineId, line] of lines.entries()) {
1438
+ if (regexp === null) {
1439
+ for (const reg of regionRegexps) {
1440
+ if (testLine(line, reg, regionName)) {
1441
+ start = lineId + 1;
1442
+ regexp = reg;
1443
+ break;
1444
+ }
1445
+ }
1446
+ } else if (testLine(line, regexp, regionName, true)) {
1447
+ return { start, end: lineId, regexp };
1407
1448
  }
1408
1449
  }
1409
- return {
1410
- ...options,
1411
- themes,
1412
- darkModeThemes: darkModeThemes ? {
1413
- dark: getThemeName(darkModeThemes.dark),
1414
- light: getThemeName(darkModeThemes.light)
1415
- } : void 0
1416
- };
1450
+ return null;
1417
1451
  }
1418
- function trimEndNewLine(code) {
1419
- return code.replace(/\n$/, "");
1420
- }
1421
- var MarkdownItShiki = (markdownit, options = {}) => {
1422
- const _highlighter = options.highlighter;
1423
- const { darkModeThemes } = resolveShikiOptions(options);
1424
- markdownit.options.highlight = (code, lang) => {
1425
- if (darkModeThemes) {
1426
- const trimmed = trimEndNewLine(code);
1427
- const dark = _highlighter.codeToHtml(trimmed, { lang: lang || "text", theme: darkModeThemes.dark }).replace('<pre class="shiki', '<pre class="slidev-code shiki shiki-dark');
1428
- const light = _highlighter.codeToHtml(trimmed, { lang: lang || "text", theme: darkModeThemes.light }).replace('<pre class="shiki', '<pre class="slidev-code shiki shiki-light');
1429
- return escapeVueInCode(`<pre class="shiki-container">${dark}${light}</pre>`);
1430
- } else {
1431
- return escapeVueInCode(
1432
- _highlighter.codeToHtml(code, { lang: lang || "text" }).replace('<pre class="shiki"', '<pre class="slidev-code shiki"')
1433
- );
1452
+ function transformSnippet(md2, options, id) {
1453
+ const slideId = id.match(/(\d+)\.md$/)?.[1];
1454
+ if (!slideId)
1455
+ return md2;
1456
+ const data = options.data;
1457
+ const slideInfo = data.slides[+slideId - 1];
1458
+ const dir = path.dirname(slideInfo.source?.filepath ?? options?.entry ?? options.userRoot);
1459
+ return md2.replace(
1460
+ /^<<< *(.+?)(#[\w-]+)? *(?: (\S+?))? *(\{.*)?$/mg,
1461
+ (full, filepath = "", regionName = "", lang = "", meta = "") => {
1462
+ const firstLine = `\`\`\`${lang || path.extname(filepath).slice(1)} ${meta}`;
1463
+ const src = /^\@[\/]/.test(filepath) ? path.resolve(options.userRoot, filepath.slice(2)) : path.resolve(dir, filepath);
1464
+ data.entries.push(src);
1465
+ const isAFile = fs6.statSync(src).isFile();
1466
+ if (!fs6.existsSync(src) || !isAFile) {
1467
+ throw new Error(isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`);
1468
+ }
1469
+ let content = fs6.readFileSync(src, "utf8");
1470
+ slideInfo.snippetsUsed ??= {};
1471
+ slideInfo.snippetsUsed[src] = content;
1472
+ if (regionName) {
1473
+ const lines = content.split(/\r?\n/);
1474
+ const region = findRegion(lines, regionName.slice(1));
1475
+ if (region) {
1476
+ content = dedent(
1477
+ lines.slice(region.start, region.end).filter((line) => !region.regexp.test(line.trim())).join("\n")
1478
+ );
1479
+ }
1480
+ }
1481
+ return `${firstLine}
1482
+ ${content}
1483
+ \`\`\``;
1434
1484
  }
1435
- };
1436
- };
1437
- var markdown_it_shiki_default = MarkdownItShiki;
1485
+ );
1486
+ }
1438
1487
 
1439
1488
  // node/plugins/markdown.ts
1440
- var DEFAULT_SHIKI_OPTIONS = {
1441
- theme: {
1442
- dark: "min-dark",
1443
- light: "min-light"
1444
- }
1445
- };
1446
- async function createMarkdownPlugin({ data: { config }, roots, mode, entry }, { markdown: mdOptions }) {
1489
+ async function createMarkdownPlugin(options, { markdown: mdOptions }) {
1490
+ const { data: { config }, roots, mode, entry } = options;
1447
1491
  const setups = [];
1448
1492
  const entryPath = slash4(entry);
1449
1493
  if (config.highlighter === "shiki") {
1450
- const Shiki = await import("shiki");
1451
- const shikiOptions = await loadSetups(roots, "shiki.ts", Shiki, DEFAULT_SHIKI_OPTIONS, false);
1452
- const { langs, themes } = resolveShikiOptions(shikiOptions);
1453
- shikiOptions.highlighter = await Shiki.getHighlighter({ themes, langs });
1454
- setups.push((md2) => md2.use(markdown_it_shiki_default, shikiOptions));
1455
- } else if (config.highlighter === "shikiji") {
1456
- const MarkdownItShikiji = await import("markdown-it-shikiji").then((r) => r.default);
1457
- const { transformerTwoSlash, rendererRich } = await import("shikiji-twoslash");
1458
- const options = await loadShikijiSetups(roots);
1459
- const plugin = await MarkdownItShikiji({
1460
- ...options,
1494
+ const MarkdownItShiki = await import("@shikijs/markdown-it").then((r) => r.default);
1495
+ const { transformerTwoslash } = await import("@shikijs/vitepress-twoslash");
1496
+ const options2 = await loadShikiSetups(roots);
1497
+ const plugin = await MarkdownItShiki({
1498
+ ...options2,
1461
1499
  transformers: [
1462
- ...options.transformers || [],
1463
- transformerTwoSlash({
1500
+ ...options2.transformers || [],
1501
+ transformerTwoslash({
1464
1502
  explicitTrigger: true,
1465
- renderer: rendererRich(),
1466
1503
  twoslashOptions: {
1467
- defaultOptions: {
1504
+ handbookOptions: {
1468
1505
  noErrorValidation: true
1469
1506
  }
1470
1507
  }
1471
1508
  }),
1472
1509
  {
1473
1510
  pre(pre) {
1474
- addClassToHast(pre, "slidev-code shikiji");
1511
+ this.addClassToHast(pre, "slidev-code");
1512
+ delete pre.properties.tabindex;
1475
1513
  },
1476
1514
  postprocess(code) {
1477
1515
  return escapeVueInCode(code);
@@ -1491,6 +1529,7 @@ async function createMarkdownPlugin({ data: { config }, roots, mode, entry }, {
1491
1529
  wrapperClasses: "",
1492
1530
  headEnabled: false,
1493
1531
  frontmatter: false,
1532
+ escapeCodeTagInterpolation: false,
1494
1533
  markdownItOptions: {
1495
1534
  quotes: `""''`,
1496
1535
  html: true,
@@ -1518,6 +1557,7 @@ async function createMarkdownPlugin({ data: { config }, roots, mode, entry }, {
1518
1557
  return "";
1519
1558
  const monaco = config.monaco === true || config.monaco === mode ? transformMarkdownMonaco : truncateMancoMark;
1520
1559
  code = transformSlotSugar(code);
1560
+ code = transformSnippet(code, options, id);
1521
1561
  code = transformMermaid(code);
1522
1562
  code = transformPlantUml(code, config.plantUmlServer);
1523
1563
  code = monaco(code);
@@ -1649,12 +1689,23 @@ function transformPlantUml(md2, server) {
1649
1689
  function escapeVueInCode(md2) {
1650
1690
  return md2.replace(/{{(.*?)}}/g, "&lbrace;&lbrace;$1&rbrace;&rbrace;");
1651
1691
  }
1652
- async function loadShikijiSetups(roots) {
1653
- const anyShikiji = roots.some((root) => fs6.existsSync(resolve3(root, "setup", "shikiji.ts")));
1654
- const result = anyShikiji ? await loadSetups(roots, "shikiji.ts", void 0, {}, false) : await loadSetups(roots, "shiki.ts", await import("shiki"), {}, false);
1692
+ async function loadShikiSetups(roots) {
1693
+ const result = await loadSetups(
1694
+ roots,
1695
+ "shiki.ts",
1696
+ {
1697
+ /** @deprecated */
1698
+ async loadTheme(path2) {
1699
+ 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.");
1700
+ return JSON.parse(await fs7.readFile(path2, "utf-8"));
1701
+ }
1702
+ },
1703
+ {},
1704
+ false
1705
+ );
1655
1706
  if ("theme" in result && "themes" in result)
1656
1707
  delete result.theme;
1657
- if (result.theme && typeof result.theme !== "string") {
1708
+ if (result.theme && typeof result.theme !== "string" && !result.theme.name && !result.theme.tokenColors) {
1658
1709
  result.themes = result.theme;
1659
1710
  delete result.theme;
1660
1711
  }
@@ -1769,7 +1820,7 @@ async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
1769
1820
  ...addonRoots.map((i) => join8(i, "components")),
1770
1821
  "src/components",
1771
1822
  "components",
1772
- join8(process3.cwd(), "components")
1823
+ join8(process2.cwd(), "components")
1773
1824
  ],
1774
1825
  include: [/\.vue$/, /\.vue\?vue/, /\.vue\?v=/, /\.md$/],
1775
1826
  exclude: [],
@@ -1800,7 +1851,7 @@ async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
1800
1851
  ...remoteAssetsOptions
1801
1852
  })) : null,
1802
1853
  ServerRef({
1803
- debug: process3.env.NODE_ENV === "development",
1854
+ debug: process2.env.NODE_ENV === "development",
1804
1855
  state: {
1805
1856
  sync: false,
1806
1857
  nav: {
@@ -1833,7 +1884,7 @@ async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
1833
1884
  dev: true,
1834
1885
  build: true
1835
1886
  })) : null,
1836
- config.css === "none" ? null : config.css === "windicss" ? import("./windicss-V4JJMSQI.mjs").then((r) => r.createWindiCSSPlugin(options, pluginOptions)) : import("./unocss-6IVIFJMZ.mjs").then((r) => r.createUnocssPlugin(options, pluginOptions))
1887
+ config.css === "none" ? null : import("./unocss-6IVIFJMZ.mjs").then((r) => r.createUnocssPlugin(options, pluginOptions))
1837
1888
  ];
1838
1889
  return (await Promise.all(plugins)).flat().filter(notNullish2);
1839
1890
  }