@slidev/cli 0.46.3 → 0.47.1

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.
@@ -2,9 +2,9 @@ import {
2
2
  ViteSlidevPlugin,
3
3
  getIndexHtml,
4
4
  mergeViteConfigs
5
- } from "./chunk-BDBBIE6Z.mjs";
5
+ } from "./chunk-SCUI4URK.mjs";
6
6
  import "./chunk-CTBVOVLQ.mjs";
7
- import "./chunk-5L3XKTHL.mjs";
7
+ import "./chunk-O6VUSZMJ.mjs";
8
8
  import "./chunk-BXO7ZPPU.mjs";
9
9
 
10
10
  // node/build.ts
@@ -98,7 +98,7 @@ async function build(options, viteConfig = {}, args) {
98
98
  await fs.writeFile(redirectsPath, `${config.base}* ${config.base}index.html 200
99
99
  `, "utf-8");
100
100
  if ([true, "true", "auto"].includes(options.data.config.download)) {
101
- const { exportSlides, getExportOptions } = await import("./export-WYWYD5MK.mjs");
101
+ const { exportSlides, getExportOptions } = await import("./export-DBOVADXI.mjs");
102
102
  const port = 12445;
103
103
  const app = connect();
104
104
  const server = http.createServer(app);
@@ -1,21 +1,19 @@
1
1
  // node/utils.ts
2
- import { dirname, join } from "node:path";
2
+ import { join } from "node:path";
3
3
  import { createRequire } from "node:module";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { ensurePrefix, slash } from "@antfu/utils";
6
6
  import isInstalledGlobally from "is-installed-globally";
7
- import resolve from "resolve";
7
+ import { resolvePath } from "mlly";
8
8
  import globalDirs from "global-directory";
9
9
  var require2 = createRequire(import.meta.url);
10
- var __dirname = dirname(fileURLToPath(import.meta.url));
11
10
  function toAtFS(path) {
12
11
  return `/@fs${ensurePrefix("/", slash(path))}`;
13
12
  }
14
- function resolveImportPath(importName, ensure = false) {
13
+ async function resolveImportPath(importName, ensure = false) {
15
14
  try {
16
- return resolve.sync(importName, {
17
- preserveSymlinks: false,
18
- basedir: __dirname
15
+ return resolvePath(importName, {
16
+ url: fileURLToPath(import.meta.url)
19
17
  });
20
18
  } catch {
21
19
  }
@@ -33,11 +31,10 @@ function resolveImportPath(importName, ensure = false) {
33
31
  throw new Error(`Failed to resolve package "${importName}"`);
34
32
  return void 0;
35
33
  }
36
- function resolveGlobalImportPath(importName) {
34
+ async function resolveGlobalImportPath(importName) {
37
35
  try {
38
- return resolve.sync(importName, {
39
- preserveSymlinks: false,
40
- basedir: __dirname
36
+ return resolvePath(importName, {
37
+ url: fileURLToPath(import.meta.url)
41
38
  });
42
39
  } catch {
43
40
  }
@@ -59,8 +56,8 @@ function generateGoogleFontsUrl(options) {
59
56
  const fonts = options.webfonts.map((i) => `family=${i.replace(/^(['"])(.*)\1$/, "$1").replace(/\s+/g, "+")}:${options.italic ? "ital," : ""}wght@${weights}`).join("&");
60
57
  return `https://fonts.googleapis.com/css2?${fonts}&display=swap`;
61
58
  }
62
- function packageExists(name) {
63
- if (resolveImportPath(`${name}/package.json`))
59
+ async function packageExists(name) {
60
+ if (await resolveImportPath(`${name}/package.json`))
64
61
  return true;
65
62
  return false;
66
63
  }
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  ViteSlidevPlugin,
3
3
  mergeViteConfigs
4
- } from "./chunk-BDBBIE6Z.mjs";
4
+ } from "./chunk-SCUI4URK.mjs";
5
5
  import {
6
6
  packageExists,
7
7
  resolveImportPath
8
- } from "./chunk-5L3XKTHL.mjs";
8
+ } from "./chunk-O6VUSZMJ.mjs";
9
9
  import {
10
10
  __commonJS,
11
11
  __toESM
@@ -2523,7 +2523,7 @@ async function createServer(options2, viteConfig = {}, serverOptions = {}) {
2523
2523
  import * as parser from "@slidev/parser/fs";
2524
2524
 
2525
2525
  // package.json
2526
- var version = "0.46.3";
2526
+ var version = "0.47.1";
2527
2527
 
2528
2528
  // node/themes.ts
2529
2529
  import prompts2 from "prompts";
@@ -7911,7 +7911,7 @@ var import_semver = __toESM(require_semver2());
7911
7911
  import fs2 from "fs-extra";
7912
7912
  async function getPackageJson(root) {
7913
7913
  try {
7914
- const file = resolveImportPath(`${root}/package.json`, true);
7914
+ const file = await resolveImportPath(`${root}/package.json`, true);
7915
7915
  if (file && fs2.existsSync(file))
7916
7916
  return await fs2.readJSON(file);
7917
7917
  return {};
@@ -7923,7 +7923,7 @@ async function getAddons(userRoot, config2) {
7923
7923
  const { slidev = {} } = await getPackageJson(userRoot);
7924
7924
  const configAddons = Array.isArray(config2.addons) ? config2.addons : [];
7925
7925
  const addons = configAddons.concat(Array.isArray(slidev?.addons) ? slidev.addons : []);
7926
- return (await getRecursivePlugins(addons.map(resolvePluginName), 3)).filter(Boolean);
7926
+ return (await getRecursivePlugins(await Promise.all(addons.map(resolvePluginName)), 3)).filter(Boolean);
7927
7927
  }
7928
7928
  async function getRecursivePlugins(addons, depth) {
7929
7929
  const addonsArray = await Promise.all(addons.map(async (addon) => {
@@ -7941,47 +7941,52 @@ async function checkEngine(name, engines) {
7941
7941
  if (engines.slidev && !(0, import_semver.satisfies)(version, engines.slidev, { includePrerelease: true }))
7942
7942
  throw new Error(`[slidev] addon "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
7943
7943
  }
7944
- function resolvePluginName(name) {
7944
+ async function resolvePluginName(name) {
7945
7945
  if (!name)
7946
7946
  return "";
7947
7947
  if (isPath(name))
7948
7948
  return name;
7949
- if (packageExists(`slidev-addon-${name}`))
7949
+ if (await packageExists(`slidev-addon-${name}`))
7950
7950
  return `slidev-addon-${name}`;
7951
7951
  return name;
7952
7952
  }
7953
7953
 
7954
7954
  // node/options.ts
7955
7955
  var debug = _debug("slidev:options");
7956
- var __dirname = dirname2(fileURLToPath2(import.meta.url));
7957
- function getClientRoot() {
7958
- return dirname2(resolveImportPath("@slidev/client/package.json", true));
7956
+ async function getClientRoot() {
7957
+ return dirname2(await resolveImportPath("@slidev/client/package.json", true));
7959
7958
  }
7960
7959
  function getCLIRoot() {
7961
- return resolve2(__dirname, "..");
7960
+ return fileURLToPath2(new URL("..", import.meta.url));
7962
7961
  }
7963
7962
  function isPath(name) {
7964
7963
  return name.startsWith("/") || /^\.\.?[\/\\]/.test(name);
7965
7964
  }
7966
- function getThemeRoots(name, entry) {
7965
+ async function getThemeRoots(name, entry) {
7967
7966
  if (!name)
7968
7967
  return [];
7969
- return [getRoot(name, entry)];
7968
+ return [await getRoot(name, entry)];
7970
7969
  }
7971
- function getAddonRoots(addons, entry) {
7970
+ async function getAddonRoots(addons, entry) {
7972
7971
  if (addons.length === 0)
7973
7972
  return [];
7974
- return addons.map((name) => getRoot(name, entry));
7973
+ return await Promise.all(addons.map((name) => getRoot(name, entry)));
7975
7974
  }
7976
- function getRoot(name, entry) {
7975
+ async function getRoot(name, entry) {
7977
7976
  if (isPath(name))
7978
7977
  return resolve2(dirname2(entry), name);
7979
- return dirname2(resolveImportPath(`${name}/package.json`, true));
7978
+ return dirname2(await resolveImportPath(`${name}/package.json`, true));
7980
7979
  }
7981
7980
  function getUserRoot(options2) {
7982
- const { entry: rawEntry = "slides.md", userRoot = process3.cwd() } = options2;
7981
+ const {
7982
+ entry: rawEntry = "slides.md",
7983
+ userRoot = process3.cwd()
7984
+ } = options2;
7983
7985
  const fullEntry = resolve2(userRoot, rawEntry);
7984
- return { entry: fullEntry, userRoot: dirname2(fullEntry) };
7986
+ return {
7987
+ entry: fullEntry,
7988
+ userRoot: dirname2(fullEntry)
7989
+ };
7985
7990
  }
7986
7991
  async function resolveOptions(options2, mode2, promptForInstallation = true) {
7987
7992
  const { remote, inspect } = options2;
@@ -7990,21 +7995,21 @@ async function resolveOptions(options2, mode2, promptForInstallation = true) {
7990
7995
  userRoot
7991
7996
  } = getUserRoot(options2);
7992
7997
  const data = await parser.load(entry);
7993
- const theme = resolveThemeName(options2.theme || data.config.theme);
7998
+ const theme = await resolveThemeName(options2.theme || data.config.theme);
7994
7999
  if (promptForInstallation) {
7995
8000
  if (await promptForThemeInstallation(theme) === false)
7996
8001
  process3.exit(1);
7997
8002
  } else {
7998
- if (!packageExists(theme)) {
8003
+ if (!await packageExists(theme)) {
7999
8004
  console.error(`Theme "${theme}" not found, have you installed it?`);
8000
8005
  process3.exit(1);
8001
8006
  }
8002
8007
  }
8003
- const clientRoot = getClientRoot();
8008
+ const clientRoot = await getClientRoot();
8004
8009
  const cliRoot = getCLIRoot();
8005
- const themeRoots = getThemeRoots(theme, entry);
8010
+ const themeRoots = await getThemeRoots(theme, entry);
8006
8011
  const addons = await getAddons(userRoot, data.config);
8007
- const addonRoots = getAddonRoots(addons, entry);
8012
+ const addonRoots = await getAddonRoots(addons, entry);
8008
8013
  const roots = uniq([clientRoot, ...themeRoots, ...addonRoots, userRoot]);
8009
8014
  if (themeRoots.length) {
8010
8015
  const themeMeta = await getThemeMeta(theme, join3(themeRoots[0], "package.json"));
@@ -8061,18 +8066,18 @@ async function getThemeMeta(name, path2) {
8061
8066
  }
8062
8067
  return void 0;
8063
8068
  }
8064
- function resolveThemeName(name) {
8069
+ async function resolveThemeName(name) {
8065
8070
  if (!name || name === "none")
8066
8071
  return "";
8067
8072
  if (name.startsWith("@slidev/theme-") || name.startsWith("slidev-theme-"))
8068
8073
  return name;
8069
8074
  if (isPath(name))
8070
8075
  return name;
8071
- if (packageExists(`@slidev/theme-${name}`))
8076
+ if (await packageExists(`@slidev/theme-${name}`))
8072
8077
  return `@slidev/theme-${name}`;
8073
- if (packageExists(`slidev-theme-${name}`))
8078
+ if (await packageExists(`slidev-theme-${name}`))
8074
8079
  return `slidev-theme-${name}`;
8075
- if (packageExists(name))
8080
+ if (await packageExists(name))
8076
8081
  return name;
8077
8082
  if (officialThemes[name] != null)
8078
8083
  return officialThemes[name];
@@ -8081,10 +8086,10 @@ function resolveThemeName(name) {
8081
8086
  return `slidev-theme-${name}`;
8082
8087
  }
8083
8088
  async function promptForThemeInstallation(name) {
8084
- name = resolveThemeName(name);
8089
+ name = await resolveThemeName(name);
8085
8090
  if (!name)
8086
8091
  return name;
8087
- if (isPath(name) || packageExists(name))
8092
+ if (isPath(name) || await packageExists(name))
8088
8093
  return name;
8089
8094
  const { confirm: confirm2 } = await prompts2({
8090
8095
  name: "confirm",
@@ -7,7 +7,7 @@ import {
7
7
  resolveImportPath,
8
8
  stringifyMarkdownTokens,
9
9
  toAtFS
10
- } from "./chunk-5L3XKTHL.mjs";
10
+ } from "./chunk-O6VUSZMJ.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
  }));
@@ -134,38 +134,6 @@ import { mergeConfig as mergeConfig2 } from "vite";
134
134
  import isInstalledGlobally from "is-installed-globally";
135
135
  import { uniq as uniq2 } from "@antfu/utils";
136
136
 
137
- // ../client/package.json
138
- var dependencies = {
139
- "@antfu/utils": "^0.7.7",
140
- "@slidev/parser": "workspace:*",
141
- "@slidev/types": "workspace:*",
142
- "@unhead/vue": "^1.8.10",
143
- "@unocss/reset": "^0.58.3",
144
- "@vueuse/core": "^10.7.2",
145
- "@vueuse/math": "^10.7.2",
146
- "@vueuse/motion": "^2.0.0",
147
- codemirror: "^5.65.5",
148
- defu: "^6.1.4",
149
- drauu: "^0.3.7",
150
- "file-saver": "^2.0.5",
151
- "fuse.js": "^7.0.0",
152
- "js-base64": "^3.7.6",
153
- "js-yaml": "^4.1.0",
154
- katex: "^0.16.9",
155
- mermaid: "^10.7.0",
156
- "monaco-editor": "^0.37.1",
157
- nanoid: "^5.0.4",
158
- prettier: "^3.2.4",
159
- recordrtc: "^5.6.2",
160
- resolve: "^1.22.8",
161
- unocss: "^0.58.3",
162
- "vite-plugin-windicss": "^1.9.3",
163
- vue: "^3.4.15",
164
- "vue-router": "^4.2.5",
165
- "vue-starport": "^0.4.0",
166
- windicss: "^3.5.6"
167
- };
168
-
169
137
  // node/vite/searchRoot.ts
170
138
  import fs3 from "node:fs";
171
139
  import { dirname as dirname2, join as join3 } from "node:path";
@@ -180,21 +148,21 @@ var ROOT_FILES = [
180
148
  // 'nx.json'
181
149
  ];
182
150
  function hasWorkspacePackageJSON(root) {
183
- const path = join3(root, "package.json");
151
+ const path2 = join3(root, "package.json");
184
152
  try {
185
- fs3.accessSync(path, fs3.constants.R_OK);
153
+ fs3.accessSync(path2, fs3.constants.R_OK);
186
154
  } catch {
187
155
  return false;
188
156
  }
189
- const content = JSON.parse(fs3.readFileSync(path, "utf-8")) || {};
157
+ const content = JSON.parse(fs3.readFileSync(path2, "utf-8")) || {};
190
158
  return !!content.workspaces;
191
159
  }
192
160
  function hasRootFile(root) {
193
161
  return ROOT_FILES.some((file) => fs3.existsSync(join3(root, file)));
194
162
  }
195
163
  function hasPackageJSON(root) {
196
- const path = join3(root, "package.json");
197
- return fs3.existsSync(path);
164
+ const path2 = join3(root, "package.json");
165
+ return fs3.existsSync(path2);
198
166
  }
199
167
  function searchForPackageRoot(current, root = current) {
200
168
  if (hasPackageJSON(current))
@@ -227,7 +195,6 @@ var EXCLUDE = [
227
195
  "@unocss/reset",
228
196
  "unocss",
229
197
  "mermaid",
230
- "vite-plugin-windicss",
231
198
  "vue-demi",
232
199
  "vue"
233
200
  ];
@@ -244,21 +211,6 @@ function createConfigPlugin(options) {
244
211
  dedupe: ["vue"]
245
212
  },
246
213
  optimizeDeps: {
247
- include: [
248
- ...Object.keys(dependencies).filter((i) => !EXCLUDE.includes(i)),
249
- "codemirror/mode/javascript/javascript",
250
- "codemirror/mode/css/css",
251
- "codemirror/mode/markdown/markdown",
252
- "codemirror/mode/xml/xml",
253
- "codemirror/mode/htmlmixed/htmlmixed",
254
- "codemirror/addon/display/placeholder",
255
- "prettier/plugins/babel",
256
- "prettier/plugins/html",
257
- "prettier/plugins/typescript",
258
- "mermaid/dist/mermaid.esm.min.mjs",
259
- "mermaid/dist/mermaid.esm.mjs",
260
- "vite-plugin-vue-server-ref/client"
261
- ],
262
214
  exclude: EXCLUDE
263
215
  },
264
216
  css: options.data.config.css === "unocss" ? {
@@ -274,17 +226,22 @@ function createConfigPlugin(options) {
274
226
  allow: uniq2([
275
227
  searchForWorkspaceRoot(options.userRoot),
276
228
  searchForWorkspaceRoot(options.cliRoot),
277
- ...isInstalledGlobally ? [dirname3(resolveGlobalImportPath("@slidev/client/package.json")), dirname3(resolveGlobalImportPath("katex/package.json"))] : []
229
+ ...isInstalledGlobally ? [
230
+ dirname3(await resolveGlobalImportPath("@slidev/client/package.json")),
231
+ dirname3(await resolveGlobalImportPath("katex/package.json"))
232
+ ] : []
278
233
  ])
279
234
  }
280
235
  },
281
236
  publicDir: join4(options.userRoot, "public")
282
237
  };
238
+ injection.resolve ||= {};
239
+ injection.resolve.alias ||= {};
283
240
  if (isInstalledGlobally) {
284
241
  injection.cacheDir = join4(options.cliRoot, "node_modules/.vite");
285
242
  injection.root = options.cliRoot;
286
- injection.resolve.alias.vue = `${resolveImportPath("vue/dist/vue.esm-browser.js", true)}`;
287
243
  }
244
+ injection.resolve.alias.vue = await resolveImportPath("vue/dist/vue.esm-browser.js", true);
288
245
  return mergeConfig2(injection, config);
289
246
  },
290
247
  configureServer(server) {
@@ -318,7 +275,6 @@ function getDefine(options) {
318
275
 
319
276
  // node/plugins/loaders.ts
320
277
  import { basename as basename2, join as join5 } from "node:path";
321
- import process from "node:process";
322
278
  import { isString, notNullish, objectMap, range, slash, uniq as uniq3 } from "@antfu/utils";
323
279
  import fg2 from "fast-glob";
324
280
  import fs4 from "fs-extra";
@@ -330,7 +286,7 @@ import equal from "fast-deep-equal";
330
286
  var regexId = /^\/\@slidev\/slide\/(\d+)\.(md|json)(?:\?import)?$/;
331
287
  var regexIdQuery = /(\d+?)\.(md|json|frontmatter)$/;
332
288
  var vueContextImports = [
333
- 'import { inject as _vueInject, provide as _vueProvide, toRef as _vueToRef } from "vue"',
289
+ `import { inject as _vueInject, provide as _vueProvide, toRef as _vueToRef } from "vue"`,
334
290
  `import {
335
291
  injectionSlidevContext as _injectionSlidevContext,
336
292
  injectionClicks as _injectionClicks,
@@ -345,13 +301,13 @@ var vueContextImports = [
345
301
  "const $renderContext = _vueInject(_injectionRenderContext)"
346
302
  ];
347
303
  function getBodyJson(req) {
348
- return new Promise((resolve4, reject) => {
304
+ return new Promise((resolve3, reject) => {
349
305
  let body = "";
350
306
  req.on("data", (chunk) => body += chunk);
351
307
  req.on("error", reject);
352
308
  req.on("end", () => {
353
309
  try {
354
- resolve4(JSON.parse(body) || {});
310
+ resolve3(JSON.parse(body) || {});
355
311
  } catch (e) {
356
312
  reject(e);
357
313
  }
@@ -436,7 +392,14 @@ function createSlidesLoader({ data, entry, clientRoot, themeRoots, addonRoots, u
436
392
  for (let i = 0; i < length; i++) {
437
393
  const a = data.slides[i];
438
394
  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))
395
+ 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]) => {
396
+ try {
397
+ const newContent = fs4.readFileSync(file, "utf-8");
398
+ return oldContent === newContent;
399
+ } catch {
400
+ return false;
401
+ }
402
+ }))
440
403
  continue;
441
404
  ctx.server.ws.send({
442
405
  type: "custom",
@@ -511,11 +474,18 @@ ${title}
511
474
  map: { mappings: "" }
512
475
  };
513
476
  } else if (type === "frontmatter") {
477
+ const slideBase = {
478
+ ...prepareSlideInfo(slide),
479
+ frontmatter: void 0,
480
+ // remove raw content in build, optimize the bundle size
481
+ ...mode === "build" ? { raw: "", content: "", note: "" } : {}
482
+ };
483
+ const fontmatter = getFrontmatter(pageNo);
514
484
  return {
515
485
  code: [
516
486
  "// @unocss-include",
517
487
  'import { reactive, computed } from "vue"',
518
- `export const frontmatter = reactive(${JSON.stringify(slide.frontmatter)})`,
488
+ `export const frontmatter = reactive(${JSON.stringify(fontmatter)})`,
519
489
  `export const meta = reactive({
520
490
  layout: computed(() => frontmatter.layout),
521
491
  transition: computed(() => frontmatter.transition),
@@ -524,12 +494,7 @@ ${title}
524
494
  name: computed(() => frontmatter.name),
525
495
  preload: computed(() => frontmatter.preload),
526
496
  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
- })}),
497
+ ...(${JSON.stringify(slideBase)}),
533
498
  frontmatter,
534
499
  filepath: ${JSON.stringify(slide.source?.filepath || entry)},
535
500
  id: ${pageNo},
@@ -575,7 +540,7 @@ ${title}
575
540
  if (type !== "md")
576
541
  return;
577
542
  const pageNo = Number.parseInt(no) - 1;
578
- return transformMarkdown(code, pageNo, data);
543
+ return transformMarkdown(code, pageNo);
579
544
  }
580
545
  },
581
546
  {
@@ -613,12 +578,15 @@ ${title}
613
578
  return;
614
579
  server.watcher.add(data.entries?.map(slash) || []);
615
580
  }
616
- async function transformMarkdown(code, pageNo, data2) {
617
- const layouts = await getLayouts();
618
- const frontmatter = {
619
- ...data2.headmatter?.defaults || {},
620
- ...data2.slides[pageNo]?.frontmatter || {}
581
+ function getFrontmatter(pageNo) {
582
+ return {
583
+ ...data.headmatter?.defaults || {},
584
+ ...data.slides[pageNo]?.frontmatter || {}
621
585
  };
586
+ }
587
+ async function transformMarkdown(code, pageNo) {
588
+ const layouts = await getLayouts();
589
+ const frontmatter = getFrontmatter(pageNo);
622
590
  let layoutName = frontmatter?.layout || (pageNo === 0 ? "cover" : "default");
623
591
  if (!layouts[layoutName]) {
624
592
  console.error(red(`
@@ -741,13 +709,19 @@ defineProps<{ no: number | string }>()`);
741
709
  _layouts_cache = layouts;
742
710
  return layouts;
743
711
  }
712
+ async function resolveUrl(id) {
713
+ return toAtFS(await resolveImportPath(id, true));
714
+ }
715
+ function resolveUrlOfClient(name) {
716
+ return toAtFS(join5(clientRoot, name));
717
+ }
744
718
  async function generateUserStyles() {
745
719
  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"))}"`
720
+ `import "${resolveUrlOfClient("styles/vars.css")}"`,
721
+ `import "${resolveUrlOfClient("styles/index.css")}"`,
722
+ `import "${resolveUrlOfClient("styles/code.css")}"`,
723
+ `import "${resolveUrlOfClient("styles/katex.css")}"`,
724
+ `import "${resolveUrlOfClient("styles/transitions.css")}"`
751
725
  ];
752
726
  const roots2 = uniq3([
753
727
  ...themeRoots,
@@ -770,25 +744,21 @@ defineProps<{ no: number | string }>()`);
770
744
  }
771
745
  }
772
746
  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))}"`);
747
+ imports.push(`import "${await resolveUrl("katex/dist/katex.min.css")}"`);
748
+ if (data.config.highlighter === "shiki") {
749
+ imports.push(
750
+ `import "${await resolveUrl("@shikijs/vitepress-twoslash/style.css")}"`,
751
+ `import "${resolveUrlOfClient("styles/shiki-twoslash.css")}"`
752
+ );
753
+ }
776
754
  if (data.config.css === "unocss") {
777
755
  imports.unshift(
778
- 'import "@unocss/reset/tailwind.css"',
756
+ `import "${await resolveUrl("@unocss/reset/tailwind.css")}"`,
779
757
  'import "uno:preflights.css"',
780
758
  'import "uno:typography.css"',
781
759
  'import "uno:shortcuts.css"'
782
760
  );
783
761
  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
762
  }
793
763
  return imports.join("\n");
794
764
  }
@@ -895,11 +865,11 @@ export default {
895
865
  // node/plugins/monacoTransform.ts
896
866
  import { dirname as dirname4, join as join6 } from "node:path";
897
867
  import fs5 from "node:fs/promises";
898
- import process2 from "node:process";
868
+ import process from "node:process";
899
869
  import { slash as slash2 } from "@antfu/utils";
900
870
  import { findDepPkgJsonPath } from "vitefu";
901
871
  async function getPackageData(pkg) {
902
- const pkgJsonPath = await findDepPkgJsonPath(pkg, process2.cwd());
872
+ const pkgJsonPath = await findDepPkgJsonPath(pkg, process.cwd());
903
873
  if (!pkgJsonPath)
904
874
  return;
905
875
  const pkgJson = JSON.parse(await fs5.readFile(pkgJsonPath, "utf-8"));
@@ -958,10 +928,10 @@ function createClientSetupPlugin({ clientRoot, themeRoots, addonRoots, userRoot
958
928
  ...addonRoots,
959
929
  userRoot
960
930
  ]).map((i) => join7(i, "setup", name));
961
- setups.forEach((path, idx) => {
962
- if (!existsSync2(path))
931
+ setups.forEach((path2, idx) => {
932
+ if (!existsSync2(path2))
963
933
  return;
964
- imports.push(`import __n${idx} from '${toAtFS(path)}'`);
934
+ imports.push(`import __n${idx} from '${toAtFS(path2)}'`);
965
935
  let fn = `:AWAIT:__n${idx}`;
966
936
  if (/\binjection_return\b/g.test(code))
967
937
  fn = `injection_return = ${fn}`;
@@ -975,7 +945,7 @@ function createClientSetupPlugin({ clientRoot, themeRoots, addonRoots, userRoot
975
945
  fn += "(:LAST:)";
976
946
  }
977
947
  injections.push(
978
- `// ${path}`,
948
+ `// ${path2}`,
979
949
  fn
980
950
  );
981
951
  });
@@ -992,7 +962,7 @@ function createClientSetupPlugin({ clientRoot, themeRoots, addonRoots, userRoot
992
962
  }
993
963
 
994
964
  // node/plugins/markdown.ts
995
- import { resolve as resolve3 } from "node:path";
965
+ import fs7 from "node:fs/promises";
996
966
  import Markdown2 from "unplugin-vue-markdown/vite";
997
967
  import * as base64 from "js-base64";
998
968
  import { slash as slash4 } from "@antfu/utils";
@@ -1130,8 +1100,6 @@ import { Optional } from "@mrdrogdrog/optional";
1130
1100
  // node/plugins/markdown.ts
1131
1101
  import { encode as encode2 } from "plantuml-encoder";
1132
1102
  import Mdc from "markdown-it-mdc";
1133
- import { addClassToHast } from "shikiji";
1134
- import fs6 from "fs-extra";
1135
1103
 
1136
1104
  // node/plugins/markdown-it-katex.ts
1137
1105
  import katex from "katex";
@@ -1381,97 +1349,121 @@ function markdownItPrism(markdownit, useroptions) {
1381
1349
  markdownit.options.highlight = (text, lang) => highlight(markdownit, options, text, lang);
1382
1350
  }
1383
1351
 
1384
- // node/plugins/markdown-it-shiki.ts
1385
- function getThemeName(theme) {
1386
- if (typeof theme === "string")
1387
- return theme;
1388
- return theme.name;
1352
+ // node/plugins/transformSnippet.ts
1353
+ import path from "node:path";
1354
+ import fs6 from "fs-extra";
1355
+ function dedent(text) {
1356
+ const lines = text.split("\n");
1357
+ const minIndentLength = lines.reduce((acc, line) => {
1358
+ for (let i = 0; i < line.length; i++) {
1359
+ if (line[i] !== " " && line[i] !== " ")
1360
+ return Math.min(i, acc);
1361
+ }
1362
+ return acc;
1363
+ }, Number.POSITIVE_INFINITY);
1364
+ if (minIndentLength < Number.POSITIVE_INFINITY)
1365
+ return lines.map((x) => x.slice(minIndentLength)).join("\n");
1366
+ return text;
1389
1367
  }
1390
- function isShikiDarkModeThemes(theme) {
1391
- return typeof theme === "object" && ("dark" in theme || "light" in theme);
1368
+ function testLine(line, regexp, regionName, end = false) {
1369
+ const [full, tag, name] = regexp.exec(line.trim()) || [];
1370
+ return full && tag && name === regionName && tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/);
1392
1371
  }
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);
1372
+ function findRegion(lines, regionName) {
1373
+ const regionRegexps = [
1374
+ /^\/\/ ?#?((?:end)?region) ([\w*-]+)$/,
1375
+ // javascript, typescript, java
1376
+ /^\/\* ?#((?:end)?region) ([\w*-]+) ?\*\/$/,
1377
+ // css, less, scss
1378
+ /^#pragma ((?:end)?region) ([\w*-]+)$/,
1379
+ // C, C++
1380
+ /^<!-- #?((?:end)?region) ([\w*-]+) -->$/,
1381
+ // HTML, markdown
1382
+ /^#((?:End )Region) ([\w*-]+)$/,
1383
+ // Visual Basic
1384
+ /^::#((?:end)region) ([\w*-]+)$/,
1385
+ // Bat
1386
+ /^# ?((?:end)?region) ([\w*-]+)$/
1387
+ // C#, PHP, Powershell, Python, perl & misc
1388
+ ];
1389
+ let regexp = null;
1390
+ let start = -1;
1391
+ for (const [lineId, line] of lines.entries()) {
1392
+ if (regexp === null) {
1393
+ for (const reg of regionRegexps) {
1394
+ if (testLine(line, reg, regionName)) {
1395
+ start = lineId + 1;
1396
+ regexp = reg;
1397
+ break;
1398
+ }
1399
+ }
1400
+ } else if (testLine(line, regexp, regionName, true)) {
1401
+ return { start, end: lineId, regexp };
1407
1402
  }
1408
1403
  }
1409
- return {
1410
- ...options,
1411
- themes,
1412
- darkModeThemes: darkModeThemes ? {
1413
- dark: getThemeName(darkModeThemes.dark),
1414
- light: getThemeName(darkModeThemes.light)
1415
- } : void 0
1416
- };
1417
- }
1418
- function trimEndNewLine(code) {
1419
- return code.replace(/\n$/, "");
1404
+ return null;
1420
1405
  }
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
- );
1406
+ function transformSnippet(md2, options, id) {
1407
+ const slideId = id.match(/(\d+)\.md$/)?.[1];
1408
+ if (!slideId)
1409
+ return md2;
1410
+ const data = options.data;
1411
+ const slideInfo = data.slides[+slideId - 1];
1412
+ const dir = path.dirname(slideInfo.source?.filepath ?? options?.entry ?? options.userRoot);
1413
+ return md2.replace(
1414
+ /^<<< *(.+?)(#[\w-]+)? *(?: (\S+?))? *(\{.*)?$/mg,
1415
+ (full, filepath = "", regionName = "", lang = "", meta = "") => {
1416
+ const firstLine = `\`\`\`${lang || path.extname(filepath).slice(1)} ${meta}`;
1417
+ const src = /^\@[\/]/.test(filepath) ? path.resolve(options.userRoot, filepath.slice(2)) : path.resolve(dir, filepath);
1418
+ data.entries.push(src);
1419
+ const isAFile = fs6.statSync(src).isFile();
1420
+ if (!fs6.existsSync(src) || !isAFile) {
1421
+ throw new Error(isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`);
1422
+ }
1423
+ let content = fs6.readFileSync(src, "utf8");
1424
+ slideInfo.snippetsUsed ??= {};
1425
+ slideInfo.snippetsUsed[src] = content;
1426
+ if (regionName) {
1427
+ const lines = content.split(/\r?\n/);
1428
+ const region = findRegion(lines, regionName.slice(1));
1429
+ if (region) {
1430
+ content = dedent(
1431
+ lines.slice(region.start, region.end).filter((line) => !region.regexp.test(line.trim())).join("\n")
1432
+ );
1433
+ }
1434
+ }
1435
+ return `${firstLine}
1436
+ ${content}
1437
+ \`\`\``;
1434
1438
  }
1435
- };
1436
- };
1437
- var markdown_it_shiki_default = MarkdownItShiki;
1439
+ );
1440
+ }
1438
1441
 
1439
1442
  // 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 }) {
1443
+ async function createMarkdownPlugin(options, { markdown: mdOptions }) {
1444
+ const { data: { config }, roots, mode, entry } = options;
1447
1445
  const setups = [];
1448
1446
  const entryPath = slash4(entry);
1449
1447
  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,
1448
+ const MarkdownItShiki = await import("@shikijs/markdown-it").then((r) => r.default);
1449
+ const { transformerTwoslash } = await import("@shikijs/vitepress-twoslash");
1450
+ const options2 = await loadShikiSetups(roots);
1451
+ const plugin = await MarkdownItShiki({
1452
+ ...options2,
1461
1453
  transformers: [
1462
- ...options.transformers || [],
1463
- transformerTwoSlash({
1454
+ ...options2.transformers || [],
1455
+ transformerTwoslash({
1464
1456
  explicitTrigger: true,
1465
- renderer: rendererRich(),
1466
1457
  twoslashOptions: {
1467
- defaultOptions: {
1458
+ handbookOptions: {
1468
1459
  noErrorValidation: true
1469
1460
  }
1470
1461
  }
1471
1462
  }),
1472
1463
  {
1473
1464
  pre(pre) {
1474
- addClassToHast(pre, "slidev-code shikiji");
1465
+ this.addClassToHast(pre, "slidev-code");
1466
+ delete pre.properties.tabindex;
1475
1467
  },
1476
1468
  postprocess(code) {
1477
1469
  return escapeVueInCode(code);
@@ -1491,6 +1483,7 @@ async function createMarkdownPlugin({ data: { config }, roots, mode, entry }, {
1491
1483
  wrapperClasses: "",
1492
1484
  headEnabled: false,
1493
1485
  frontmatter: false,
1486
+ escapeCodeTagInterpolation: false,
1494
1487
  markdownItOptions: {
1495
1488
  quotes: `""''`,
1496
1489
  html: true,
@@ -1518,6 +1511,7 @@ async function createMarkdownPlugin({ data: { config }, roots, mode, entry }, {
1518
1511
  return "";
1519
1512
  const monaco = config.monaco === true || config.monaco === mode ? transformMarkdownMonaco : truncateMancoMark;
1520
1513
  code = transformSlotSugar(code);
1514
+ code = transformSnippet(code, options, id);
1521
1515
  code = transformMermaid(code);
1522
1516
  code = transformPlantUml(code, config.plantUmlServer);
1523
1517
  code = monaco(code);
@@ -1649,12 +1643,23 @@ function transformPlantUml(md2, server) {
1649
1643
  function escapeVueInCode(md2) {
1650
1644
  return md2.replace(/{{(.*?)}}/g, "&lbrace;&lbrace;$1&rbrace;&rbrace;");
1651
1645
  }
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);
1646
+ async function loadShikiSetups(roots) {
1647
+ const result = await loadSetups(
1648
+ roots,
1649
+ "shiki.ts",
1650
+ {
1651
+ /** @deprecated */
1652
+ async loadTheme(path2) {
1653
+ 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.");
1654
+ return JSON.parse(await fs7.readFile(path2, "utf-8"));
1655
+ }
1656
+ },
1657
+ {},
1658
+ false
1659
+ );
1655
1660
  if ("theme" in result && "themes" in result)
1656
1661
  delete result.theme;
1657
- if (result.theme && typeof result.theme !== "string") {
1662
+ if (result.theme && typeof result.theme !== "string" && !result.theme.name && !result.theme.tokenColors) {
1658
1663
  result.themes = result.theme;
1659
1664
  delete result.theme;
1660
1665
  }
@@ -1769,7 +1774,7 @@ async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
1769
1774
  ...addonRoots.map((i) => join8(i, "components")),
1770
1775
  "src/components",
1771
1776
  "components",
1772
- join8(process3.cwd(), "components")
1777
+ join8(process2.cwd(), "components")
1773
1778
  ],
1774
1779
  include: [/\.vue$/, /\.vue\?vue/, /\.vue\?v=/, /\.md$/],
1775
1780
  exclude: [],
@@ -1800,7 +1805,7 @@ async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
1800
1805
  ...remoteAssetsOptions
1801
1806
  })) : null,
1802
1807
  ServerRef({
1803
- debug: process3.env.NODE_ENV === "development",
1808
+ debug: process2.env.NODE_ENV === "development",
1804
1809
  state: {
1805
1810
  sync: false,
1806
1811
  nav: {
@@ -1833,7 +1838,7 @@ async function ViteSlidevPlugin(options, pluginOptions, serverOptions = {}) {
1833
1838
  dev: true,
1834
1839
  build: true
1835
1840
  })) : 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))
1841
+ config.css === "none" ? null : import("./unocss-6IVIFJMZ.mjs").then((r) => r.createUnocssPlugin(options, pluginOptions))
1837
1842
  ];
1838
1843
  return (await Promise.all(plugins)).flat().filter(notNullish2);
1839
1844
  }
package/dist/cli.mjs CHANGED
@@ -9,12 +9,12 @@ import {
9
9
  resolveOptions,
10
10
  resolveThemeName,
11
11
  version
12
- } from "./chunk-P5XEHWCU.mjs";
13
- import "./chunk-BDBBIE6Z.mjs";
12
+ } from "./chunk-R2UPIVJX.mjs";
13
+ import "./chunk-SCUI4URK.mjs";
14
14
  import {
15
15
  loadSetups
16
16
  } from "./chunk-CTBVOVLQ.mjs";
17
- import "./chunk-5L3XKTHL.mjs";
17
+ import "./chunk-O6VUSZMJ.mjs";
18
18
  import "./chunk-BXO7ZPPU.mjs";
19
19
 
20
20
  // node/cli.ts
@@ -48,8 +48,8 @@ injectPreparserExtensionLoader(async (headmatter, filepath) => {
48
48
  /* uniq */
49
49
  [
50
50
  getUserRoot({}).userRoot,
51
- ...getAddonRoots(addons, ""),
52
- getClientRoot()
51
+ ...await getAddonRoots(addons, ""),
52
+ await getClientRoot()
53
53
  ]
54
54
  );
55
55
  const mergeArrays = (a, b) => a.concat(b);
@@ -101,7 +101,7 @@ cli.command(
101
101
  message: `Entry file ${yellow(`"${entry}"`)} does not exist, do you want to create it?`
102
102
  });
103
103
  if (create)
104
- await fs.copyFile(path.resolve(__dirname, "../template.md"), entry);
104
+ await fs.copyFile(new URL("../template.md", import.meta.url), entry);
105
105
  else
106
106
  process.exit(0);
107
107
  }
@@ -131,8 +131,8 @@ cli.command(
131
131
  logLevel: log
132
132
  },
133
133
  {
134
- onDataReload(newData, data) {
135
- if (!theme && resolveThemeName(newData.config.theme) !== resolveThemeName(data.config.theme)) {
134
+ async onDataReload(newData, data) {
135
+ if (!theme && await resolveThemeName(newData.config.theme) !== await resolveThemeName(data.config.theme)) {
136
136
  console.log(yellow("\n restarting on theme change\n"));
137
137
  initServer();
138
138
  } else if (CONFIG_RESTART_FIELDS.some((i) => !equal(newData.config[i], data.config[i]))) {
@@ -269,7 +269,7 @@ cli.command(
269
269
  }).strict().help(),
270
270
  async (args) => {
271
271
  const { entry, theme, watch, base, download, out, inspect } = args;
272
- const { build } = await import("./build-XIN6SGB6.mjs");
272
+ const { build } = await import("./build-MGE5JI2Q.mjs");
273
273
  for (const entryFile of entry) {
274
274
  const options = await resolveOptions({ entry: entryFile, theme, inspect }, "build");
275
275
  if (download && !options.data.config.download)
@@ -310,7 +310,7 @@ cli.command(
310
310
  }),
311
311
  async ({ entry, dir, theme: themeInput }) => {
312
312
  const data = await parser.load(entry);
313
- const theme = resolveThemeName(themeInput || data.config.theme);
313
+ const theme = await resolveThemeName(themeInput || data.config.theme);
314
314
  if (theme === "none") {
315
315
  console.error('Cannot eject theme "none"');
316
316
  process.exit(1);
@@ -319,7 +319,7 @@ cli.command(
319
319
  console.error("Theme is already ejected");
320
320
  process.exit(1);
321
321
  }
322
- const roots = getThemeRoots(theme, entry);
322
+ const roots = await getThemeRoots(theme, entry);
323
323
  if (!roots.length) {
324
324
  console.error(`Could not find theme "${theme}"`);
325
325
  process.exit(1);
@@ -348,7 +348,7 @@ cli.command(
348
348
  async (args) => {
349
349
  const { entry, theme } = args;
350
350
  process.env.NODE_ENV = "production";
351
- const { exportSlides, getExportOptions } = await import("./export-WYWYD5MK.mjs");
351
+ const { exportSlides, getExportOptions } = await import("./export-DBOVADXI.mjs");
352
352
  const port = await findFreePort(12445);
353
353
  for (const entryFile of entry) {
354
354
  const options = await resolveOptions({ entry: entryFile, theme }, "export");
@@ -394,7 +394,7 @@ cli.command(
394
394
  timeout
395
395
  }) => {
396
396
  process.env.NODE_ENV = "production";
397
- const { exportNotes } = await import("./export-WYWYD5MK.mjs");
397
+ const { exportNotes } = await import("./export-DBOVADXI.mjs");
398
398
  const port = await findFreePort(12445);
399
399
  for (const entryFile of entry) {
400
400
  const options = await resolveOptions({ entry: entryFile }, "export");
@@ -1,6 +1,7 @@
1
1
  import {
2
- packageExists
3
- } from "./chunk-5L3XKTHL.mjs";
2
+ packageExists,
3
+ resolveGlobalImportPath
4
+ } from "./chunk-O6VUSZMJ.mjs";
4
5
  import "./chunk-BXO7ZPPU.mjs";
5
6
 
6
7
  // node/export.ts
@@ -13,6 +14,7 @@ import { parseRangeString } from "@slidev/parser/core";
13
14
  import { outlinePdfFactory } from "@lillallol/outline-pdf";
14
15
  import * as pdfLib from "pdf-lib";
15
16
  import { PDFDocument } from "pdf-lib";
17
+ import isInstalledGlobally from "is-installed-globally";
16
18
  function addToTree(tree, info, slideIndexes, level = 1) {
17
19
  const titleLevel = info.level;
18
20
  if (titleLevel && titleLevel > level && tree.length > 0) {
@@ -74,9 +76,7 @@ async function exportNotes({
74
76
  output = "notes",
75
77
  timeout = 3e4
76
78
  }) {
77
- if (!packageExists("playwright-chromium"))
78
- throw new Error("The exporting for Slidev is powered by Playwright, please install it via `npm i -D playwright-chromium`");
79
- const { chromium } = await import("playwright-chromium");
79
+ const { chromium } = await importPlaywright();
80
80
  const browser = await chromium.launch();
81
81
  const context = await browser.newContext();
82
82
  const page = await context.newPage();
@@ -120,10 +120,8 @@ async function exportSlides({
120
120
  withToc = false,
121
121
  perSlide = false
122
122
  }) {
123
- if (!packageExists("playwright-chromium"))
124
- throw new Error("The exporting for Slidev is powered by Playwright, please install it via `npm i -D playwright-chromium`");
125
123
  const pages = parseRangeString(total, range);
126
- const { chromium } = await import("playwright-chromium");
124
+ const { chromium } = await importPlaywright();
127
125
  const browser = await chromium.launch({
128
126
  executablePath
129
127
  });
@@ -382,6 +380,21 @@ function getExportOptions(args, options, outDir, outFilename) {
382
380
  perSlide: perSlide || false
383
381
  };
384
382
  }
383
+ async function importPlaywright() {
384
+ if (await packageExists("playwright-chromium"))
385
+ return await import("playwright-chromium");
386
+ let globalPath = isInstalledGlobally ? await resolveGlobalImportPath("playwright-chromium") : void 0;
387
+ if (globalPath)
388
+ return await import(globalPath);
389
+ const { resolveGlobal } = await import("resolve-global");
390
+ try {
391
+ globalPath = resolveGlobal("playwright-chromium");
392
+ } catch {
393
+ }
394
+ if (globalPath)
395
+ return await import(globalPath);
396
+ throw new Error("The exporting for Slidev is powered by Playwright, please install it via `npm i -D playwright-chromium`");
397
+ }
385
398
  export {
386
399
  exportNotes,
387
400
  exportSlides,
package/dist/index.d.mts CHANGED
@@ -3,7 +3,6 @@ import VueJsx from '@vitejs/plugin-vue-jsx';
3
3
  import Icons from 'unplugin-icons/vite';
4
4
  import Components from 'unplugin-vue-components/vite';
5
5
  import Markdown from 'unplugin-vue-markdown/vite';
6
- import WindiCSS from 'vite-plugin-windicss';
7
6
  import { VitePluginConfig } from 'unocss/vite';
8
7
  import RemoteAssets from 'vite-plugin-remote-assets';
9
8
  import ServerRef from 'vite-plugin-vue-server-ref';
@@ -59,7 +58,6 @@ interface SlidevPluginOptions extends SlidevEntryOptions {
59
58
  vuejsx?: ArgumentsType<typeof VueJsx>[0];
60
59
  markdown?: ArgumentsType<typeof Markdown>[0];
61
60
  components?: ArgumentsType<typeof Components>[0];
62
- windicss?: ArgumentsType<typeof WindiCSS>[0];
63
61
  icons?: ArgumentsType<typeof Icons>[0];
64
62
  remoteAssets?: ArgumentsType<typeof RemoteAssets>[0];
65
63
  serverRef?: ArgumentsType<typeof ServerRef>[0];
@@ -68,12 +66,12 @@ interface SlidevPluginOptions extends SlidevEntryOptions {
68
66
  interface SlidevServerOptions {
69
67
  onDataReload?: (newData: SlidevMarkdown, data: SlidevMarkdown) => void;
70
68
  }
71
- declare function getClientRoot(): string;
69
+ declare function getClientRoot(): Promise<string>;
72
70
  declare function getCLIRoot(): string;
73
71
  declare function isPath(name: string): boolean;
74
- declare function getThemeRoots(name: string, entry: string): string[];
75
- declare function getAddonRoots(addons: string[], entry: string): string[];
76
- declare function getRoot(name: string, entry: string): string;
72
+ declare function getThemeRoots(name: string, entry: string): Promise<string[]>;
73
+ declare function getAddonRoots(addons: string[], entry: string): Promise<string[]>;
74
+ declare function getRoot(name: string, entry: string): Promise<string>;
77
75
  declare function getUserRoot(options: SlidevEntryOptions): {
78
76
  entry: string;
79
77
  userRoot: string;
@@ -95,6 +93,4 @@ declare function createServer(options: ResolvedSlidevOptions, viteConfig?: Inlin
95
93
 
96
94
  declare function ViteSlidevPlugin(options: ResolvedSlidevOptions, pluginOptions: SlidevPluginOptions, serverOptions?: SlidevServerOptions): Promise<Plugin[]>;
97
95
 
98
- declare function createWindiCSSPlugin({ themeRoots, addonRoots, clientRoot, userRoot, roots, data }: ResolvedSlidevOptions, { windicss: windiOptions }: SlidevPluginOptions): Promise<vite.Plugin<any>[]>;
99
-
100
- export { type ResolvedSlidevOptions, type SlidevEntryOptions, type SlidevPluginOptions, type SlidevServerOptions, ViteSlidevPlugin, createServer, createWindiCSSPlugin, getAddonRoots, getCLIRoot, getClientRoot, getRoot, getThemeRoots, getUserRoot, isPath, resolveOptions };
96
+ export { type ResolvedSlidevOptions, type SlidevEntryOptions, type SlidevPluginOptions, type SlidevServerOptions, ViteSlidevPlugin, createServer, getAddonRoots, getCLIRoot, getClientRoot, getRoot, getThemeRoots, getUserRoot, isPath, resolveOptions };
package/dist/index.mjs CHANGED
@@ -9,20 +9,16 @@ import {
9
9
  isPath,
10
10
  parser,
11
11
  resolveOptions
12
- } from "./chunk-P5XEHWCU.mjs";
13
- import {
14
- createWindiCSSPlugin
15
- } from "./chunk-GLZC72RJ.mjs";
12
+ } from "./chunk-R2UPIVJX.mjs";
16
13
  import {
17
14
  ViteSlidevPlugin
18
- } from "./chunk-BDBBIE6Z.mjs";
15
+ } from "./chunk-SCUI4URK.mjs";
19
16
  import "./chunk-CTBVOVLQ.mjs";
20
- import "./chunk-5L3XKTHL.mjs";
17
+ import "./chunk-O6VUSZMJ.mjs";
21
18
  import "./chunk-BXO7ZPPU.mjs";
22
19
  export {
23
20
  ViteSlidevPlugin,
24
21
  createServer,
25
- createWindiCSSPlugin,
26
22
  getAddonRoots,
27
23
  getCLIRoot,
28
24
  getClientRoot,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slidev/cli",
3
- "version": "0.46.3",
3
+ "version": "0.47.1",
4
4
  "description": "Presentation slides for developers",
5
5
  "author": "antfu <anthonyfu117@hotmail.com>",
6
6
  "license": "MIT",
@@ -44,14 +44,16 @@
44
44
  "dependencies": {
45
45
  "@antfu/utils": "^0.7.7",
46
46
  "@iconify-json/carbon": "^1.1.28",
47
- "@iconify-json/ph": "^1.1.10",
47
+ "@iconify-json/ph": "^1.1.11",
48
48
  "@lillallol/outline-pdf": "^4.0.0",
49
49
  "@mrdrogdrog/optional": "^1.2.1",
50
- "@unocss/extractor-mdc": "^0.58.3",
51
- "@unocss/reset": "^0.58.3",
50
+ "@shikijs/markdown-it": "^1.0.0-beta.3",
51
+ "@shikijs/twoslash": "^1.0.0-beta.3",
52
+ "@shikijs/vitepress-twoslash": "1.0.0-beta.3",
53
+ "@unocss/extractor-mdc": "^0.58.4",
54
+ "@unocss/reset": "^0.58.4",
52
55
  "@vitejs/plugin-vue": "^5.0.3",
53
56
  "@vitejs/plugin-vue-jsx": "^3.1.0",
54
- "@windicss/config": "^1.9.3",
55
57
  "cli-progress": "^3.12.0",
56
58
  "codemirror": "^5.65.5",
57
59
  "connect": "^3.7.0",
@@ -62,7 +64,6 @@
62
64
  "get-port-please": "^3.1.2",
63
65
  "global-directory": "^4.0.1",
64
66
  "htmlparser2": "^9.1.0",
65
- "import-from": "^4.0.0",
66
67
  "is-installed-globally": "^1.0.0",
67
68
  "jiti": "^1.21.0",
68
69
  "js-base64": "^3.7.6",
@@ -74,9 +75,9 @@
74
75
  "markdown-it-footnote": "^4.0.0",
75
76
  "markdown-it-link-attributes": "^4.0.1",
76
77
  "markdown-it-mdc": "^0.2.1",
77
- "markdown-it-shikiji": "^0.9.19",
78
+ "mlly": "^1.5.0",
78
79
  "monaco-editor": "^0.37.1",
79
- "nanoid": "^5.0.4",
80
+ "nanoid": "^5.0.5",
80
81
  "open": "^10.0.3",
81
82
  "pdf-lib": "^1.17.1",
82
83
  "plantuml-encoder": "^1.4.0",
@@ -87,28 +88,24 @@
87
88
  "resolve": "^1.22.8",
88
89
  "resolve-from": "^5.0.0",
89
90
  "resolve-global": "^2.0.0",
90
- "shikiji": "^0.9.19",
91
- "shiki": "npm:shikiji-compat@^0.9.19",
92
- "shikiji-twoslash": "^0.9.19",
91
+ "shiki": "^1.0.0-beta.3",
93
92
  "sirv": "^2.0.4",
94
- "unocss": "^0.58.3",
95
- "unplugin-icons": "^0.18.2",
93
+ "unocss": "^0.58.4",
94
+ "unplugin-icons": "^0.18.3",
96
95
  "unplugin-vue-components": "^0.26.0",
97
96
  "unplugin-vue-markdown": "^0.25.2",
98
97
  "uqr": "^0.1.2",
99
98
  "vite": "^5.0.12",
100
- "vite-plugin-inspect": "^0.8.1",
99
+ "vite-plugin-inspect": "^0.8.3",
101
100
  "vite-plugin-remote-assets": "^0.4.1",
102
- "vite-plugin-static-copy": "^1.0.0",
103
- "vite-plugin-vue-server-ref": "^0.4.0",
104
- "vite-plugin-windicss": "^1.9.3",
101
+ "vite-plugin-static-copy": "^1.0.1",
102
+ "vite-plugin-vue-server-ref": "^0.4.1",
105
103
  "vitefu": "^0.2.5",
106
104
  "vue": "^3.4.15",
107
- "windicss": "^3.5.6",
108
105
  "yargs": "^17.7.2",
109
- "@slidev/client": "0.46.3",
110
- "@slidev/parser": "0.46.3",
111
- "@slidev/types": "0.46.3"
106
+ "@slidev/types": "0.47.1",
107
+ "@slidev/parser": "0.47.1",
108
+ "@slidev/client": "0.47.1"
112
109
  },
113
110
  "devDependencies": {
114
111
  "@hedgedoc/markdown-it-plugins": "^2.1.4",
package/template.md CHANGED
@@ -4,7 +4,7 @@ theme: seriph
4
4
  # random image from a curated Unsplash collection by Anthony
5
5
  # like them? see https://unsplash.com/collections/94734566/slidev
6
6
  background: https://source.unsplash.com/collection/94734566/1920x1080
7
- # apply any windi css classes to the current slide
7
+ # apply any unocss classes to the current slide
8
8
  class: 'text-center'
9
9
  # https://sli.dev/custom/highlighters.html
10
10
  highlighter: shiki
@@ -1,66 +0,0 @@
1
- import {
2
- loadSetups
3
- } from "./chunk-CTBVOVLQ.mjs";
4
- import {
5
- resolveImportPath
6
- } from "./chunk-5L3XKTHL.mjs";
7
-
8
- // node/plugins/windicss.ts
9
- import { dirname, resolve } from "node:path";
10
- import { existsSync } from "node:fs";
11
- import { fileURLToPath } from "node:url";
12
- import { slash, uniq } from "@antfu/utils";
13
- import jiti from "jiti";
14
- async function createWindiCSSPlugin({ themeRoots, addonRoots, clientRoot, userRoot, roots, data }, { windicss: windiOptions }) {
15
- const { default: WindiCSS } = await import("vite-plugin-windicss");
16
- const { defaultConfigureFiles } = await import("@windicss/config");
17
- const configFiles = uniq([
18
- ...defaultConfigureFiles.map((i) => resolve(userRoot, i)),
19
- ...themeRoots.map((i) => `${i}/windi.config.ts`),
20
- ...addonRoots.map((i) => `${i}/windi.config.ts`),
21
- resolve(clientRoot, "windi.config.ts")
22
- ]);
23
- const configFile = configFiles.find((i) => existsSync(i));
24
- let config = jiti(fileURLToPath(import.meta.url))(configFile);
25
- if (config.default)
26
- config = config.default;
27
- config = await loadSetups(roots, "windicss.ts", {}, config, true);
28
- return WindiCSS(
29
- {
30
- configFiles: [configFile],
31
- config,
32
- onConfigResolved(config2) {
33
- if (!config2.theme)
34
- config2.theme = {};
35
- if (!config2.theme.extend)
36
- config2.theme.extend = {};
37
- if (!config2.theme.extend.fontFamily)
38
- config2.theme.extend.fontFamily = {};
39
- const fontFamily = config2.theme.extend.fontFamily;
40
- fontFamily.sans ||= data.config.fonts.sans.join(",");
41
- fontFamily.mono ||= data.config.fonts.mono.join(",");
42
- fontFamily.serif ||= data.config.fonts.serif.join(",");
43
- return config2;
44
- },
45
- onOptionsResolved(config2) {
46
- themeRoots.forEach((i) => {
47
- config2.scanOptions.include.push(`${i}/components/**/*.{vue,ts}`);
48
- config2.scanOptions.include.push(`${i}/layouts/**/*.{vue,ts}`);
49
- });
50
- addonRoots.forEach((i) => {
51
- config2.scanOptions.include.push(`${i}/components/**/*.{vue,ts}`);
52
- config2.scanOptions.include.push(`${i}/layouts/**/*.{vue,ts}`);
53
- });
54
- config2.scanOptions.include.push(`!${slash(resolve(userRoot, "node_modules"))}`);
55
- config2.scanOptions.exclude.push(dirname(resolveImportPath("monaco-editor/package.json", true)));
56
- config2.scanOptions.exclude.push(dirname(resolveImportPath("katex/package.json", true)));
57
- config2.scanOptions.exclude.push(dirname(resolveImportPath("prettier/package.json", true)));
58
- },
59
- ...windiOptions
60
- }
61
- );
62
- }
63
-
64
- export {
65
- createWindiCSSPlugin
66
- };
@@ -1,9 +0,0 @@
1
- import {
2
- createWindiCSSPlugin
3
- } from "./chunk-GLZC72RJ.mjs";
4
- import "./chunk-CTBVOVLQ.mjs";
5
- import "./chunk-5L3XKTHL.mjs";
6
- import "./chunk-BXO7ZPPU.mjs";
7
- export {
8
- createWindiCSSPlugin
9
- };