@slidev/cli 51.6.0 → 51.7.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.
@@ -0,0 +1,2475 @@
1
+ import { createResolver, getRoots, isInstalledGlobally, resolveEntry, resolveImportPath, resolveImportUrl, toAtFS } from "./resolver-BShaA6qw.js";
2
+ import { builtinModules } from "node:module";
3
+ import fs from "node:fs/promises";
4
+ import path, { basename, dirname, join, resolve } from "node:path";
5
+ import { bold, gray, red, white, yellow } from "ansis";
6
+ import equal from "fast-deep-equal";
7
+ import { loadConfigFromFile, mergeConfig } from "vite";
8
+ import fs$1, { existsSync, readFileSync } from "node:fs";
9
+ import MarkdownIt from "markdown-it";
10
+ import { fileURLToPath, pathToFileURL } from "node:url";
11
+ import { createJiti } from "jiti";
12
+ import YAML from "yaml";
13
+ import { isString, isTruthy, notNullish, objectEntries, objectMap, range, slash, uniq } from "@antfu/utils";
14
+ import IconsResolver from "unplugin-icons/resolver";
15
+ import Components from "unplugin-vue-components/vite";
16
+ import { createResolve } from "mlly";
17
+ import { findDepPkgJsonPath } from "vitefu";
18
+ import Icons from "unplugin-icons/vite";
19
+ import * as parser$1 from "@slidev/parser/fs";
20
+ import * as parser from "@slidev/parser/fs";
21
+ import Debug from "debug";
22
+ import fg from "fast-glob";
23
+ import pm from "picomatch";
24
+ import { satisfies } from "semver";
25
+ import { escapeHtml } from "markdown-it/lib/common/utils.mjs";
26
+ import { createHead, extractUnheadInputFromHtml, transformHtmlTemplate } from "unhead/server";
27
+ import { bundledLanguages, createHighlighter } from "shiki";
28
+ import katex from "katex";
29
+ import MagicString from "magic-string-stack";
30
+ import Markdown from "unplugin-vue-markdown/vite";
31
+ import Token from "markdown-it/lib/token.mjs";
32
+ import MarkdownItFootnote from "markdown-it-footnote";
33
+ import MarkdownItMdc from "markdown-it-mdc";
34
+ import { fromHighlighter } from "@shikijs/markdown-it/core";
35
+ import { SourceMapConsumer } from "source-map-js";
36
+ import lz from "lz-string";
37
+ import { codeToKeyedTokens } from "shiki-magic-move/core";
38
+ import { encode } from "plantuml-encoder";
39
+ import ServerRef from "vite-plugin-vue-server-ref";
40
+ import UnoCSS from "unocss/vite";
41
+ import { mergeConfigs, presetIcons } from "unocss";
42
+ import Vue from "@vitejs/plugin-vue";
43
+ import VueJsx from "@vitejs/plugin-vue-jsx";
44
+
45
+ //#region package.json
46
+ var version = "51.7.0";
47
+
48
+ //#endregion
49
+ //#region node/syntax/markdown-it/markdown-it-link.ts
50
+ function MarkdownItLink(md) {
51
+ const defaultRender = md.renderer.rules.link_open ?? ((tokens, idx, options, _env, self) => self.renderToken(tokens, idx, options));
52
+ md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
53
+ const token = tokens[idx];
54
+ const hrefIndex = token.attrIndex("href");
55
+ const attr = token.attrs?.[hrefIndex];
56
+ const href = attr?.[1] ?? "";
57
+ if ("./#".includes(href[0]) || /^\d+$/.test(href)) {
58
+ token.tag = "Link";
59
+ attr[0] = "to";
60
+ for (let i = idx + 1; i < tokens.length; i++) if (tokens[i].type === "link_close") {
61
+ tokens[i].tag = "Link";
62
+ break;
63
+ }
64
+ } else if (token.attrGet("target") == null) token.attrPush(["target", "_blank"]);
65
+ return defaultRender(tokens, idx, options, env, self);
66
+ };
67
+ }
68
+
69
+ //#endregion
70
+ //#region node/utils.ts
71
+ let jiti;
72
+ function loadModule(absolutePath) {
73
+ jiti ??= createJiti(fileURLToPath(import.meta.url), { moduleCache: false });
74
+ return jiti.import(absolutePath);
75
+ }
76
+ function stringifyMarkdownTokens(tokens) {
77
+ 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(" ");
78
+ }
79
+ function generateFontParams(options) {
80
+ const weights = options.weights.flatMap((i) => options.italic ? [`0,${i}`, `1,${i}`] : [`${i}`]).sort().join(";");
81
+ const fontParams = options.webfonts.map((i) => `family=${i.replace(/^(['"])(.*)\1$/, "$1").replace(/\s+/g, "+")}:${options.italic ? "ital," : ""}wght@${weights}`).join("&");
82
+ return fontParams;
83
+ }
84
+ function generateGoogleFontsUrl(options) {
85
+ return `https://fonts.googleapis.com/css2?${generateFontParams(options)}&display=swap`;
86
+ }
87
+ function generateCoollabsFontsUrl(options) {
88
+ return `https://api.fonts.coollabs.io/fonts?${generateFontParams(options)}&display=swap`;
89
+ }
90
+ /**
91
+ * Update frontmatter patch and preserve the comments
92
+ */
93
+ function updateFrontmatterPatch(source, frontmatter) {
94
+ let doc = source.frontmatterDoc;
95
+ if (!doc) {
96
+ source.frontmatterStyle = "frontmatter";
97
+ source.frontmatterDoc = doc = new YAML.Document({});
98
+ }
99
+ for (const [key, value] of Object.entries(frontmatter)) {
100
+ source.frontmatter[key] = value;
101
+ if (value == null) doc.delete(key);
102
+ else {
103
+ const valueNode = doc.createNode(value);
104
+ let found = false;
105
+ YAML.visit(doc.contents, { Pair(_key, node, path$1) {
106
+ if (path$1.length === 1 && YAML.isScalar(node.key) && node.key.value === key) {
107
+ node.value = valueNode;
108
+ found = true;
109
+ return YAML.visit.BREAK;
110
+ }
111
+ } });
112
+ if (!found) {
113
+ if (!YAML.isMap(doc.contents)) doc.contents = doc.createNode({});
114
+ doc.contents.add(doc.createPair(key, valueNode));
115
+ }
116
+ }
117
+ }
118
+ }
119
+ function getBodyJson(req) {
120
+ return new Promise((resolve$2, reject) => {
121
+ let body = "";
122
+ req.on("data", (chunk) => body += chunk);
123
+ req.on("error", reject);
124
+ req.on("end", () => {
125
+ try {
126
+ resolve$2(JSON.parse(body) || {});
127
+ } catch (e) {
128
+ reject(e);
129
+ }
130
+ });
131
+ });
132
+ }
133
+
134
+ //#endregion
135
+ //#region node/vite/compilerFlagsVue.ts
136
+ /**
137
+ * Replace compiler flags like `__DEV__` in Vue SFC
138
+ */
139
+ function createVueCompilerFlagsPlugin(options) {
140
+ const define = objectEntries(options.utils.define);
141
+ return {
142
+ name: "slidev:flags",
143
+ enforce: "pre",
144
+ transform(code, id) {
145
+ if (!id.match(/\.vue($|\?)/) && !id.includes("?vue&")) return;
146
+ const original = code;
147
+ define.forEach(([from, to]) => {
148
+ code = code.replaceAll(from, to);
149
+ });
150
+ if (original !== code) return code;
151
+ }
152
+ };
153
+ }
154
+
155
+ //#endregion
156
+ //#region node/vite/components.ts
157
+ function createComponentsPlugin({ clientRoot, roots }, pluginOptions) {
158
+ return Components({
159
+ extensions: [
160
+ "vue",
161
+ "md",
162
+ "js",
163
+ "ts",
164
+ "jsx",
165
+ "tsx"
166
+ ],
167
+ dirs: [join(clientRoot, "builtin"), ...roots.map((i) => join(i, "components"))],
168
+ globsExclude: [],
169
+ include: [
170
+ /\.vue$/,
171
+ /\.vue\?vue/,
172
+ /\.vue\?v=/,
173
+ /\.md$/,
174
+ /\.md\?vue/
175
+ ],
176
+ exclude: [],
177
+ resolvers: [IconsResolver({
178
+ prefix: "",
179
+ customCollections: Object.keys(pluginOptions.icons?.customCollections || [])
180
+ })],
181
+ dts: false,
182
+ ...pluginOptions.components
183
+ });
184
+ }
185
+
186
+ //#endregion
187
+ //#region node/vite/common.ts
188
+ const regexSlideReqPath = /^\/__slidev\/slides\/(\d+)\.json$/;
189
+ const regexSlideFacadeId = /^\/@slidev\/slides\/(\d+)\/(md|frontmatter)($|\?)/;
190
+ const regexSlideSourceId = /__slidev_(\d+)\.(md|frontmatter)$/;
191
+ const templateInjectionMarker = "/* @slidev-injection */";
192
+ const templateImportContextUtils = `import { useSlideContext as _useSlideContext, frontmatterToProps as _frontmatterToProps } from "@slidev/client/context.ts"`;
193
+ const templateInitContext = `const { $slidev, $nav, $clicksContext, $clicks, $page, $renderContext, $frontmatter } = _useSlideContext()`;
194
+
195
+ //#endregion
196
+ //#region node/vite/contextInjection.ts
197
+ /**
198
+ * Inject `$slidev` into the script block of a Vue component
199
+ */
200
+ function createContextInjectionPlugin() {
201
+ return {
202
+ name: "slidev:context-injection",
203
+ async transform(code, id) {
204
+ if (!id.endsWith(".vue") || id.includes("/@slidev/client/") || id.includes("/packages/client/")) return;
205
+ if (code.includes(templateInjectionMarker) || code.includes("useSlideContext()")) return code;
206
+ const imports = [
207
+ templateImportContextUtils,
208
+ templateInitContext,
209
+ templateInjectionMarker
210
+ ];
211
+ const matchScript = code.match(/<script((?!setup).)*(setup)?.*>/);
212
+ if (matchScript && matchScript[2]) return code.replace(/(<script.*>)/g, `$1\n${imports.join("\n")}\n`);
213
+ else if (matchScript && !matchScript[2]) {
214
+ const matchExport = code.match(/export\s+default\s+\{/);
215
+ if (matchExport) {
216
+ const exportIndex = (matchExport.index || 0) + matchExport[0].length;
217
+ let component = code.slice(exportIndex);
218
+ component = component.slice(0, component.indexOf("</script>"));
219
+ const scriptIndex = (matchScript.index || 0) + matchScript[0].length;
220
+ const provideImport = "\nimport { injectionSlidevContext } from \"@slidev/client/constants.ts\"\n";
221
+ code = `${code.slice(0, scriptIndex)}${provideImport}${code.slice(scriptIndex)}`;
222
+ let injectIndex = exportIndex + provideImport.length;
223
+ let injectObject = "$slidev: { from: injectionSlidevContext },";
224
+ const matchInject = component.match(/.*inject\s*:\s*([[{])/);
225
+ if (matchInject) {
226
+ injectIndex += (matchInject.index || 0) + matchInject[0].length;
227
+ if (matchInject[1] === "[") {
228
+ let injects = component.slice((matchInject.index || 0) + matchInject[0].length);
229
+ const injectEndIndex = injects.indexOf("]");
230
+ injects = injects.slice(0, injectEndIndex);
231
+ injectObject += injects.split(",").map((inject) => `${inject}: {from: ${inject}}`).join(",");
232
+ return `${code.slice(0, injectIndex - 1)}{\n${injectObject}\n}${code.slice(injectIndex + injectEndIndex + 1)}`;
233
+ } else return `${code.slice(0, injectIndex)}\n${injectObject}\n${code.slice(injectIndex)}`;
234
+ }
235
+ return `${code.slice(0, injectIndex)}\ninject: { ${injectObject} },\n${code.slice(injectIndex)}`;
236
+ }
237
+ }
238
+ return `<script setup>\n${imports.join("\n")}\n</script>\n${code}`;
239
+ }
240
+ };
241
+ }
242
+
243
+ //#endregion
244
+ //#region node/vite/extendConfig.ts
245
+ const INCLUDE_GLOBAL = [
246
+ "@typescript/ata",
247
+ "file-saver",
248
+ "lz-string",
249
+ "prettier",
250
+ "recordrtc",
251
+ "typescript",
252
+ "yaml"
253
+ ];
254
+ const INCLUDE_LOCAL = INCLUDE_GLOBAL.map((i) => `@slidev/cli > @slidev/client > ${i}`);
255
+ const EXCLUDE_GLOBAL = [
256
+ "@antfu/utils",
257
+ "@shikijs/monaco",
258
+ "@shikijs/vitepress-twoslash/client",
259
+ "@slidev/client",
260
+ "@slidev/client/constants",
261
+ "@slidev/client/context",
262
+ "@slidev/client/logic/dark",
263
+ "@slidev/parser",
264
+ "@slidev/parser/core",
265
+ "@slidev/rough-notation",
266
+ "@slidev/types",
267
+ "@unhead/vue",
268
+ "@unocss/reset",
269
+ "@vueuse/core",
270
+ "@vueuse/math",
271
+ "@vueuse/motion",
272
+ "@vueuse/shared",
273
+ "drauu",
274
+ "floating-vue",
275
+ "fuse.js",
276
+ "mermaid",
277
+ "monaco-editor",
278
+ "shiki-magic-move/vue",
279
+ "shiki",
280
+ "shiki/core",
281
+ "vue-demi",
282
+ "vue-router",
283
+ "vue"
284
+ ];
285
+ const EXCLUDE_LOCAL = EXCLUDE_GLOBAL;
286
+ const ASYNC_MODULES = [
287
+ "file-saver",
288
+ "vue",
289
+ "@vue"
290
+ ];
291
+ function createConfigPlugin(options) {
292
+ const resolveClientDep = createResolve({
293
+ conditions: [
294
+ "import",
295
+ "module",
296
+ "browser",
297
+ "default",
298
+ options.mode === "build" ? "production" : "development"
299
+ ],
300
+ url: pathToFileURL(options.clientRoot)
301
+ });
302
+ return {
303
+ name: "slidev:config",
304
+ async config(config) {
305
+ const injection = {
306
+ define: options.utils.define,
307
+ resolve: {
308
+ alias: [
309
+ {
310
+ find: /^@slidev\/client$/,
311
+ replacement: `${toAtFS(options.clientRoot)}/index.ts`
312
+ },
313
+ {
314
+ find: /^@slidev\/client\/(.*)/,
315
+ replacement: `${toAtFS(options.clientRoot)}/$1`
316
+ },
317
+ {
318
+ find: /^#slidev\/(.*)/,
319
+ replacement: "/@slidev/$1"
320
+ },
321
+ {
322
+ find: "vue",
323
+ replacement: await resolveImportPath("vue/dist/vue.esm-bundler.js", true)
324
+ },
325
+ ...isInstalledGlobally.value ? await Promise.all(INCLUDE_GLOBAL.map(async (dep) => ({
326
+ find: dep,
327
+ replacement: fileURLToPath(await resolveClientDep(dep))
328
+ }))) : []
329
+ ],
330
+ dedupe: ["vue"]
331
+ },
332
+ optimizeDeps: isInstalledGlobally.value ? {
333
+ exclude: EXCLUDE_GLOBAL,
334
+ include: INCLUDE_GLOBAL
335
+ } : {
336
+ exclude: EXCLUDE_LOCAL,
337
+ include: INCLUDE_LOCAL
338
+ },
339
+ css: { postcss: { plugins: [await import("postcss-nested").then((r) => (r.default || r)())] } },
340
+ server: { fs: {
341
+ strict: true,
342
+ allow: uniq([
343
+ options.userWorkspaceRoot,
344
+ options.clientRoot,
345
+ isInstalledGlobally.value ? slash(options.cliRoot).replace(/\/\.pnpm\/.*$/gi, "") : options.cliRoot,
346
+ ...options.roots
347
+ ])
348
+ } },
349
+ publicDir: join(options.userRoot, "public"),
350
+ build: { rollupOptions: { output: {
351
+ chunkFileNames(chunkInfo) {
352
+ const DEFAULT = "assets/[name]-[hash].js";
353
+ if (chunkInfo.name.includes("/")) return DEFAULT;
354
+ if (chunkInfo.moduleIds.filter((i) => isSlidevClient(i)).length > chunkInfo.moduleIds.length * .6) return "assets/slidev/[name]-[hash].js";
355
+ if (chunkInfo.moduleIds.filter((i) => i.match(/\/monaco-editor(-core)?\//)).length > chunkInfo.moduleIds.length * .6) return "assets/monaco/[name]-[hash].js";
356
+ return DEFAULT;
357
+ },
358
+ manualChunks(id) {
359
+ if (id.startsWith("/@slidev-monaco-types/") || id.includes("/@slidev/monaco-types") || id.endsWith("?monaco-types&raw")) return "monaco/bundled-types";
360
+ if (id.includes("/shiki/") || id.includes("/@shikijs/")) return `modules/shiki`;
361
+ if (id.startsWith("~icons/")) return "modules/unplugin-icons";
362
+ const matchedAsyncModule = ASYNC_MODULES.find((i) => id.includes(`/node_modules/${i}`));
363
+ if (matchedAsyncModule) return `modules/${matchedAsyncModule.replace("@", "").replace("/", "-")}`;
364
+ }
365
+ } } },
366
+ cacheDir: isInstalledGlobally.value ? join(options.cliRoot, "node_modules/.vite") : void 0
367
+ };
368
+ function isSlidevClient(id) {
369
+ return id.includes("/@slidev/") || id.includes("/slidev/packages/client/") || id.includes("/@vueuse/");
370
+ }
371
+ return mergeConfig(injection, config);
372
+ },
373
+ configureServer(server) {
374
+ return () => {
375
+ server.middlewares.use(async (req, res, next) => {
376
+ if (req.url === "/index.html") {
377
+ res.setHeader("Content-Type", "text/html");
378
+ res.statusCode = 200;
379
+ res.end(options.utils.indexHtml);
380
+ return;
381
+ }
382
+ next();
383
+ });
384
+ };
385
+ }
386
+ };
387
+ }
388
+
389
+ //#endregion
390
+ //#region node/vite/hmrPatch.ts
391
+ /**
392
+ * force reload slide component to ensure v-click resolves correctly
393
+ */
394
+ function createHmrPatchPlugin() {
395
+ return {
396
+ name: "slidev:hmr-patch",
397
+ transform(code, id) {
398
+ if (!id.match(regexSlideSourceId)) return;
399
+ return code.replace("if (_rerender_only)", "if (false)");
400
+ }
401
+ };
402
+ }
403
+
404
+ //#endregion
405
+ //#region node/vite/icons.ts
406
+ function createIconsPlugin(options, pluginOptions) {
407
+ return Icons({
408
+ defaultClass: "slidev-icon",
409
+ collectionsNodeResolvePath: options.utils.iconsResolvePath,
410
+ ...pluginOptions.icons
411
+ });
412
+ }
413
+
414
+ //#endregion
415
+ //#region node/vite/inspect.ts
416
+ async function createInspectPlugin(options, pluginOptions) {
417
+ if (!options.inspect) return;
418
+ const { default: PluginInspect } = await import("vite-plugin-inspect");
419
+ return PluginInspect({
420
+ dev: true,
421
+ build: true,
422
+ ...pluginOptions.inspect
423
+ });
424
+ }
425
+
426
+ //#endregion
427
+ //#region node/vite/layoutWrapper.ts
428
+ function createLayoutWrapperPlugin({ data, utils }) {
429
+ return {
430
+ name: "slidev:layout-wrapper",
431
+ async transform(code, id) {
432
+ const match = id.match(regexSlideSourceId);
433
+ if (!match) return;
434
+ const [, no, type] = match;
435
+ if (type !== "md") return;
436
+ const index = +no - 1;
437
+ const layouts = utils.getLayouts();
438
+ const rawLayoutName = data.slides[index]?.frontmatter?.layout ?? data.slides[0]?.frontmatter?.defaults?.layout;
439
+ let layoutName = rawLayoutName || (index === 0 ? "cover" : "default");
440
+ if (!layouts[layoutName]) {
441
+ console.error(red(`\nUnknown layout "${bold(layoutName)}".${yellow(" Available layouts are:")}`) + Object.keys(layouts).map((i, idx) => (idx % 3 === 0 ? "\n " : "") + gray(i.padEnd(15, " "))).join(" "));
442
+ console.error();
443
+ layoutName = "default";
444
+ }
445
+ const setupTag = code.match(/^<script setup.*>/m);
446
+ if (!setupTag) throw new Error(`[Slidev] Internal error: <script setup> block not found in slide ${index + 1}.`);
447
+ const templatePart = code.slice(0, setupTag.index);
448
+ const scriptPart = code.slice(setupTag.index);
449
+ const bodyStart = templatePart.indexOf("<template>") + 10;
450
+ const bodyEnd = templatePart.lastIndexOf("</template>");
451
+ let body = code.slice(bodyStart, bodyEnd).trim();
452
+ if (body.startsWith("<div>") && body.endsWith("</div>")) body = body.slice(5, -6);
453
+ return [
454
+ templatePart.slice(0, bodyStart),
455
+ `<InjectedLayout v-bind="_frontmatterToProps($frontmatter,${index})">\n${body}\n</InjectedLayout>`,
456
+ templatePart.slice(bodyEnd),
457
+ scriptPart.slice(0, setupTag[0].length),
458
+ `import InjectedLayout from "${toAtFS(layouts[layoutName])}"`,
459
+ templateImportContextUtils,
460
+ templateInitContext,
461
+ "$clicksContext.setup()",
462
+ templateInjectionMarker,
463
+ scriptPart.slice(setupTag[0].length)
464
+ ].join("\n");
465
+ }
466
+ };
467
+ }
468
+
469
+ //#endregion
470
+ //#region node/integrations/addons.ts
471
+ async function resolveAddons(addonsInConfig) {
472
+ const { userRoot, userPkgJson } = await getRoots();
473
+ const resolved = [];
474
+ const resolveAddonNameAndRoot = createResolver("addon", {});
475
+ async function resolveAddon(name, parent) {
476
+ const [, pkgRoot] = await resolveAddonNameAndRoot(name, parent);
477
+ if (!pkgRoot) return;
478
+ resolved.push(pkgRoot);
479
+ const { slidev = {}, engines = {} } = JSON.parse(await fs.readFile(resolve(pkgRoot, "package.json"), "utf-8"));
480
+ if (engines.slidev && !satisfies(version, engines.slidev, { includePrerelease: true })) throw new Error(`[slidev] addon "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
481
+ if (Array.isArray(slidev.addons)) await Promise.all(slidev.addons.map((addon) => resolveAddon(addon, pkgRoot)));
482
+ }
483
+ if (Array.isArray(addonsInConfig)) await Promise.all(addonsInConfig.map((addon) => resolveAddon(addon, userRoot)));
484
+ if (Array.isArray(userPkgJson.slidev?.addons)) await Promise.all(userPkgJson.slidev.addons.map((addon) => resolveAddon(addon, userRoot)));
485
+ return resolved;
486
+ }
487
+
488
+ //#endregion
489
+ //#region node/integrations/themes.ts
490
+ const officialThemes = {
491
+ "none": "",
492
+ "default": "@slidev/theme-default",
493
+ "seriph": "@slidev/theme-seriph",
494
+ "apple-basic": "@slidev/theme-apple-basic",
495
+ "shibainu": "@slidev/theme-shibainu",
496
+ "bricks": "@slidev/theme-bricks"
497
+ };
498
+ const resolveTheme = createResolver("theme", officialThemes);
499
+ async function getThemeMeta(name, root) {
500
+ const path$1 = join(root, "package.json");
501
+ if (!existsSync(path$1)) return {};
502
+ const { slidev = {}, engines = {} } = JSON.parse(await fs.readFile(path$1, "utf-8"));
503
+ if (engines.slidev && !satisfies(version, engines.slidev, { includePrerelease: true })) throw new Error(`[slidev] theme "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
504
+ return slidev;
505
+ }
506
+
507
+ //#endregion
508
+ //#region node/setups/indexHtml.ts
509
+ function toAttrValue(unsafe) {
510
+ return JSON.stringify(escapeHtml(String(unsafe)));
511
+ }
512
+ async function setupIndexHtml({ mode, entry, clientRoot, userRoot, roots, data, base }) {
513
+ let main = readFileSync(join(clientRoot, "index.html"), "utf-8");
514
+ let body = "";
515
+ const inputs = [];
516
+ for (const root of roots) {
517
+ const path$1 = join(root, "index.html");
518
+ if (!existsSync(path$1)) continue;
519
+ const html$1 = readFileSync(path$1, "utf-8");
520
+ if (root === userRoot && html$1.includes("<!DOCTYPE")) {
521
+ console.error(yellow(`[Slidev] Ignored provided index.html with doctype declaration. (${white(path$1)})`));
522
+ console.error(yellow("This file may be generated by Slidev, please remove it from your project."));
523
+ continue;
524
+ }
525
+ inputs.push(extractUnheadInputFromHtml(html$1).input);
526
+ body += `\n${(html$1.match(/<body>([\s\S]*?)<\/body>/i)?.[1] || "").trim()}`;
527
+ }
528
+ if (data.features.tweet) body += "\n<script async src=\"https://platform.twitter.com/widgets.js\"></script>";
529
+ const webFontsLink = [];
530
+ if (data.config.fonts.webfonts.length) {
531
+ const { provider } = data.config.fonts;
532
+ if (provider === "google") webFontsLink.push({
533
+ rel: "stylesheet",
534
+ href: generateGoogleFontsUrl(data.config.fonts),
535
+ type: "text/css"
536
+ });
537
+ else if (provider === "coollabs") webFontsLink.push({
538
+ rel: "stylesheet",
539
+ href: generateCoollabsFontsUrl(data.config.fonts),
540
+ type: "text/css"
541
+ });
542
+ }
543
+ const { info, author, keywords } = data.headmatter;
544
+ const seoMeta = data.headmatter.seoMeta ?? {};
545
+ const title = getSlideTitle(data);
546
+ const description = info ? toAttrValue(info) : null;
547
+ const unhead = createHead({ init: [{
548
+ htmlAttrs: data.headmatter.lang ? { lang: data.headmatter.lang } : void 0,
549
+ title,
550
+ link: [data.config.favicon ? {
551
+ rel: "icon",
552
+ href: data.config.favicon
553
+ } : null, ...webFontsLink].filter((x) => x),
554
+ meta: [
555
+ {
556
+ property: "slidev:version",
557
+ content: version
558
+ },
559
+ {
560
+ charset: "slidev:entry",
561
+ content: mode === "dev" && slash(entry)
562
+ },
563
+ {
564
+ name: "description",
565
+ content: description
566
+ },
567
+ {
568
+ name: "author",
569
+ content: author ? toAttrValue(author) : null
570
+ },
571
+ {
572
+ name: "keywords",
573
+ content: keywords ? toAttrValue(Array.isArray(keywords) ? keywords.join(", ") : keywords) : null
574
+ },
575
+ {
576
+ property: "og:title",
577
+ content: seoMeta.ogTitle || title
578
+ },
579
+ {
580
+ property: "og:description",
581
+ content: seoMeta.ogDescription || description
582
+ },
583
+ {
584
+ property: "og:image",
585
+ content: seoMeta.ogImage
586
+ },
587
+ {
588
+ property: "og:url",
589
+ content: seoMeta.ogUrl
590
+ },
591
+ {
592
+ property: "twitter:card",
593
+ content: seoMeta.twitterCard
594
+ },
595
+ {
596
+ property: "twitter:site",
597
+ content: seoMeta.twitterSite
598
+ },
599
+ {
600
+ property: "twitter:title",
601
+ content: seoMeta.twitterTitle
602
+ },
603
+ {
604
+ property: "twitter:description",
605
+ content: seoMeta.twitterDescription
606
+ },
607
+ {
608
+ property: "twitter:image",
609
+ content: seoMeta.twitterImage
610
+ },
611
+ {
612
+ property: "twitter:url",
613
+ content: seoMeta.twitterUrl
614
+ }
615
+ ].filter((x) => x.content)
616
+ }, ...inputs] });
617
+ const baseInDev = mode === "dev" && base ? base.slice(0, -1) : "";
618
+ main = main.replace("__ENTRY__", baseInDev + toAtFS(join(clientRoot, "main.ts"))).replace("<!-- body -->", body);
619
+ const html = await transformHtmlTemplate(unhead, main);
620
+ return html;
621
+ }
622
+
623
+ //#endregion
624
+ //#region node/setups/load.ts
625
+ async function loadSetups(roots, filename, args, extraLoader) {
626
+ const returns = [];
627
+ for (const root of roots) {
628
+ const path$1 = resolve(root, "setup", filename);
629
+ if (existsSync(path$1)) {
630
+ const { default: setup } = await loadModule(path$1);
631
+ const ret = await setup(...args);
632
+ if (ret) returns.push(ret);
633
+ }
634
+ if (extraLoader) returns.push(...await extraLoader(root));
635
+ }
636
+ return returns;
637
+ }
638
+
639
+ //#endregion
640
+ //#region node/setups/katex.ts
641
+ async function setupKatex(roots) {
642
+ const options = await loadSetups(roots, "katex.ts", []);
643
+ return Object.assign({ strict: false }, ...options);
644
+ }
645
+
646
+ //#endregion
647
+ //#region node/setups/shiki.ts
648
+ let cachedRoots;
649
+ let cachedShiki;
650
+ async function setupShiki(roots) {
651
+ if (cachedRoots === roots) return cachedShiki;
652
+ cachedShiki?.shiki.dispose();
653
+ const options = await loadSetups(roots, "shiki.ts", [{ async loadTheme(path$1) {
654
+ 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.");
655
+ return JSON.parse(await fs.readFile(path$1, "utf-8"));
656
+ } }]);
657
+ const mergedOptions = Object.assign({}, ...options);
658
+ if ("theme" in mergedOptions && "themes" in mergedOptions) delete mergedOptions.theme;
659
+ if (mergedOptions.theme && typeof mergedOptions.theme !== "string" && !mergedOptions.theme.name && !mergedOptions.theme.tokenColors) {
660
+ mergedOptions.themes = mergedOptions.theme;
661
+ delete mergedOptions.theme;
662
+ }
663
+ if (!mergedOptions.theme && !mergedOptions.themes) mergedOptions.themes = {
664
+ dark: "vitesse-dark",
665
+ light: "vitesse-light"
666
+ };
667
+ if (mergedOptions.themes) mergedOptions.defaultColor = false;
668
+ const shiki = await createHighlighter({
669
+ ...mergedOptions,
670
+ langs: mergedOptions.langs ?? Object.keys(bundledLanguages),
671
+ themes: "themes" in mergedOptions ? Object.values(mergedOptions.themes) : [mergedOptions.theme]
672
+ });
673
+ cachedRoots = roots;
674
+ return cachedShiki = {
675
+ shiki,
676
+ shikiOptions: mergedOptions
677
+ };
678
+ }
679
+
680
+ //#endregion
681
+ //#region node/options.ts
682
+ const debug = Debug("slidev:options");
683
+ async function resolveOptions(entryOptions, mode) {
684
+ const entry = await resolveEntry(entryOptions.entry);
685
+ const rootsInfo = await getRoots(entry);
686
+ const loaded = await parser$1.load(rootsInfo.userRoot, entry, void 0, mode);
687
+ let themeRaw = entryOptions.theme || loaded.headmatter.theme;
688
+ themeRaw = themeRaw === null ? "none" : themeRaw || "default";
689
+ const [theme, themeRoot] = await resolveTheme(themeRaw, entry);
690
+ const themeRoots = themeRoot ? [themeRoot] : [];
691
+ const themeMeta = themeRoot ? await getThemeMeta(theme, themeRoot) : void 0;
692
+ const config = parser$1.resolveConfig(loaded.headmatter, themeMeta, entryOptions.entry);
693
+ const addonRoots = await resolveAddons(config.addons);
694
+ const roots = uniq([
695
+ ...themeRoots,
696
+ ...addonRoots,
697
+ rootsInfo.userRoot
698
+ ]);
699
+ if (entryOptions.download) config.download ||= entryOptions.download;
700
+ debug({
701
+ ...rootsInfo,
702
+ ...entryOptions,
703
+ config,
704
+ mode,
705
+ entry,
706
+ themeRaw,
707
+ theme,
708
+ themeRoots,
709
+ addonRoots,
710
+ roots
711
+ });
712
+ const data = {
713
+ ...loaded,
714
+ config,
715
+ themeMeta
716
+ };
717
+ const resolved = {
718
+ ...rootsInfo,
719
+ ...entryOptions,
720
+ data,
721
+ mode,
722
+ entry,
723
+ themeRaw,
724
+ theme,
725
+ themeRoots,
726
+ addonRoots,
727
+ roots
728
+ };
729
+ return {
730
+ ...resolved,
731
+ utils: await createDataUtils(resolved)
732
+ };
733
+ }
734
+ async function createDataUtils(resolved) {
735
+ const monacoTypesIgnorePackagesMatches = (resolved.data.config.monacoTypesIgnorePackages || []).map((i) => pm.makeRe(i));
736
+ let _layouts_cache_time = 0;
737
+ let _layouts_cache = {};
738
+ return {
739
+ ...await setupShiki(resolved.roots),
740
+ katexOptions: await setupKatex(resolved.roots),
741
+ indexHtml: await setupIndexHtml(resolved),
742
+ define: getDefine(resolved),
743
+ iconsResolvePath: [resolved.clientRoot, ...resolved.roots].reverse(),
744
+ isMonacoTypesIgnored: (pkg) => monacoTypesIgnorePackagesMatches.some((i) => i.test(pkg)),
745
+ getLayouts: () => {
746
+ const now = Date.now();
747
+ if (now - _layouts_cache_time < 2e3) return _layouts_cache;
748
+ const layouts = {};
749
+ for (const root of [resolved.clientRoot, ...resolved.roots]) {
750
+ const layoutPaths = fg.sync("layouts/**/*.{vue,ts}", {
751
+ cwd: root,
752
+ absolute: true,
753
+ suppressErrors: true
754
+ });
755
+ for (const layoutPath of layoutPaths) {
756
+ const layoutName = path.basename(layoutPath).replace(/\.\w+$/, "");
757
+ layouts[layoutName] = layoutPath;
758
+ }
759
+ }
760
+ _layouts_cache_time = now;
761
+ _layouts_cache = layouts;
762
+ return layouts;
763
+ }
764
+ };
765
+ }
766
+ function getDefine(options) {
767
+ const matchMode = (mode) => mode === true || mode === options.mode;
768
+ return objectMap({
769
+ __DEV__: options.mode === "dev",
770
+ __SLIDEV_CLIENT_ROOT__: toAtFS(options.clientRoot),
771
+ __SLIDEV_HASH_ROUTE__: options.data.config.routerMode === "hash",
772
+ __SLIDEV_FEATURE_DRAWINGS__: matchMode(options.data.config.drawings.enabled),
773
+ __SLIDEV_FEATURE_EDITOR__: options.mode === "dev" && options.data.config.editor !== false,
774
+ __SLIDEV_FEATURE_DRAWINGS_PERSIST__: !!options.data.config.drawings.persist,
775
+ __SLIDEV_FEATURE_RECORD__: matchMode(options.data.config.record),
776
+ __SLIDEV_FEATURE_PRESENTER__: matchMode(options.data.config.presenter),
777
+ __SLIDEV_FEATURE_PRINT__: options.mode === "export" || options.mode === "build" && [
778
+ true,
779
+ "true",
780
+ "auto"
781
+ ].includes(options.data.config.download),
782
+ __SLIDEV_FEATURE_BROWSER_EXPORTER__: matchMode(options.data.config.browserExporter),
783
+ __SLIDEV_FEATURE_WAKE_LOCK__: matchMode(options.data.config.wakeLock),
784
+ __SLIDEV_HAS_SERVER__: options.mode !== "build"
785
+ }, (v, k) => [v, JSON.stringify(k)]);
786
+ }
787
+
788
+ //#endregion
789
+ //#region node/syntax/markdown-it/markdown-it-katex.ts
790
+ function isValidDelim(state, pos) {
791
+ const max = state.posMax;
792
+ let can_open = true;
793
+ let can_close = true;
794
+ const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
795
+ const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
796
+ if (prevChar === 32 || prevChar === 9 || nextChar >= 48 && nextChar <= 57) can_close = false;
797
+ if (nextChar === 32 || nextChar === 9) can_open = false;
798
+ return {
799
+ can_open,
800
+ can_close
801
+ };
802
+ }
803
+ function math_inline(state, silent) {
804
+ let match, token, res, pos;
805
+ if (state.src[state.pos] !== "$") return false;
806
+ res = isValidDelim(state, state.pos);
807
+ if (!res.can_open) {
808
+ if (!silent) state.pending += "$";
809
+ state.pos += 1;
810
+ return true;
811
+ }
812
+ const start = state.pos + 1;
813
+ match = start;
814
+ while ((match = state.src.indexOf("$", match)) !== -1) {
815
+ pos = match - 1;
816
+ while (state.src[pos] === "\\") pos -= 1;
817
+ if ((match - pos) % 2 === 1) break;
818
+ match += 1;
819
+ }
820
+ if (match === -1) {
821
+ if (!silent) state.pending += "$";
822
+ state.pos = start;
823
+ return true;
824
+ }
825
+ if (match - start === 0) {
826
+ if (!silent) state.pending += "$$";
827
+ state.pos = start + 1;
828
+ return true;
829
+ }
830
+ res = isValidDelim(state, match);
831
+ if (!res.can_close) {
832
+ if (!silent) state.pending += "$";
833
+ state.pos = start;
834
+ return true;
835
+ }
836
+ if (!silent) {
837
+ token = state.push("math_inline", "math", 0);
838
+ token.markup = "$";
839
+ token.content = state.src.slice(start, match);
840
+ }
841
+ state.pos = match + 1;
842
+ return true;
843
+ }
844
+ function math_block(state, start, end, silent) {
845
+ let firstLine;
846
+ let lastLine;
847
+ let next;
848
+ let lastPos;
849
+ let found = false;
850
+ let pos = state.bMarks[start] + state.tShift[start];
851
+ let max = state.eMarks[start];
852
+ if (pos + 2 > max) return false;
853
+ if (state.src.slice(pos, pos + 2) !== "$$") return false;
854
+ pos += 2;
855
+ firstLine = state.src.slice(pos, max);
856
+ if (silent) return true;
857
+ if (firstLine.trim().slice(-2) === "$$") {
858
+ firstLine = firstLine.trim().slice(0, -2);
859
+ found = true;
860
+ }
861
+ for (next = start; !found;) {
862
+ next++;
863
+ if (next >= end) break;
864
+ pos = state.bMarks[next] + state.tShift[next];
865
+ max = state.eMarks[next];
866
+ if (pos < max && state.tShift[next] < state.blkIndent) break;
867
+ if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
868
+ lastPos = state.src.slice(0, max).lastIndexOf("$$");
869
+ lastLine = state.src.slice(pos, lastPos);
870
+ found = true;
871
+ }
872
+ }
873
+ state.line = next + 1;
874
+ const token = state.push("math_block", "math", 0);
875
+ token.block = true;
876
+ token.content = (firstLine && firstLine.trim() ? `${firstLine}\n` : "") + state.getLines(start + 1, next, state.tShift[start], true) + (lastLine && lastLine.trim() ? lastLine : "");
877
+ token.map = [start, state.line];
878
+ token.markup = "$$";
879
+ return true;
880
+ }
881
+ function MarkdownItKatex(md, options) {
882
+ const katexInline = function(latex) {
883
+ options.displayMode = false;
884
+ try {
885
+ return katex.renderToString(latex, options);
886
+ } catch (error) {
887
+ if (options.throwOnError) console.warn(error);
888
+ return latex;
889
+ }
890
+ };
891
+ const inlineRenderer = function(tokens, idx) {
892
+ return katexInline(tokens[idx].content);
893
+ };
894
+ const katexBlock = function(latex) {
895
+ options.displayMode = true;
896
+ try {
897
+ return `<p>${katex.renderToString(latex, options)}</p>`;
898
+ } catch (error) {
899
+ if (options.throwOnError) console.warn(error);
900
+ return latex;
901
+ }
902
+ };
903
+ const blockRenderer = function(tokens, idx) {
904
+ return `${katexBlock(tokens[idx].content)}\n`;
905
+ };
906
+ md.inline.ruler.after("escape", "math_inline", math_inline);
907
+ md.block.ruler.after("blockquote", "math_block", math_block, { alt: [
908
+ "paragraph",
909
+ "reference",
910
+ "blockquote",
911
+ "list"
912
+ ] });
913
+ md.renderer.rules.math_inline = inlineRenderer;
914
+ md.renderer.rules.math_block = blockRenderer;
915
+ }
916
+
917
+ //#endregion
918
+ //#region node/virtual/configs.ts
919
+ const templateConfigs = {
920
+ id: "/@slidev/configs",
921
+ getContent({ data, remote }) {
922
+ const config = {
923
+ ...data.config,
924
+ remote,
925
+ slidesTitle: getSlideTitle(data)
926
+ };
927
+ if (isString(config.info)) config.info = sharedMd.render(config.info);
928
+ return `export default ${JSON.stringify(config)}`;
929
+ }
930
+ };
931
+
932
+ //#endregion
933
+ //#region node/virtual/deprecated.ts
934
+ /**
935
+ * Kept for backward compatibility, use #slidev/slides instead
936
+ *
937
+ * @deprecated
938
+ */
939
+ const templateLegacyRoutes = {
940
+ id: "/@slidev/routes",
941
+ getContent() {
942
+ return [`export { slides } from '#slidev/slides'`, `console.warn('[slidev] #slidev/routes is deprecated, use #slidev/slides instead')`].join("\n");
943
+ }
944
+ };
945
+ /**
946
+ * Kept for backward compatibility, use #slidev/title-renderer instead
947
+ *
948
+ * @deprecated
949
+ */
950
+ const templateLegacyTitles = {
951
+ id: "/@slidev/titles.md",
952
+ getContent() {
953
+ return `
954
+ <script setup lang="ts">
955
+ import TitleRenderer from '#slidev/title-renderer'
956
+ defineProps<{ no: number | string }>()
957
+ console.warn('/@slidev/titles.md is deprecated, import from #slidev/title-renderer instead')
958
+ </script>
959
+
960
+ <TitleRenderer :no="no" />
961
+ `;
962
+ }
963
+ };
964
+
965
+ //#endregion
966
+ //#region node/virtual/global-layers.ts
967
+ const templateGlobalLayers = {
968
+ id: `/@slidev/global-layers`,
969
+ getContent({ roots }) {
970
+ const imports = [];
971
+ let n = 0;
972
+ function getComponent(names) {
973
+ const components = roots.flatMap((root) => names.map((name) => join(root, name))).filter((i) => existsSync(i));
974
+ imports.push(components.map((path$1, i) => `import __n${n}_${i} from '${toAtFS(path$1)}'`).join("\n"));
975
+ const render = components.map((_, i) => `h(__n${n}_${i})`).join(",");
976
+ n++;
977
+ return `{ render: () => [${render}] }`;
978
+ }
979
+ const globalTop = getComponent([
980
+ "global.vue",
981
+ "global-top.vue",
982
+ "GlobalTop.vue"
983
+ ]);
984
+ const globalBottom = getComponent(["global-bottom.vue", "GlobalBottom.vue"]);
985
+ const slideTop = getComponent(["slide-top.vue", "SlideTop.vue"]);
986
+ const slideBottom = getComponent(["slide-bottom.vue", "SlideBottom.vue"]);
987
+ return [
988
+ imports.join("\n"),
989
+ `import { h } from 'vue'`,
990
+ `export const GlobalTop = ${globalTop}`,
991
+ `export const GlobalBottom = ${globalBottom}`,
992
+ `export const SlideTop = ${slideTop}`,
993
+ `export const SlideBottom = ${slideBottom}`
994
+ ].join("\n");
995
+ }
996
+ };
997
+
998
+ //#endregion
999
+ //#region node/virtual/layouts.ts
1000
+ const templateLayouts = {
1001
+ id: "/@slidev/layouts",
1002
+ getContent({ utils }) {
1003
+ const imports = [];
1004
+ const layouts = objectMap(utils.getLayouts(), (k, v) => {
1005
+ imports.push(`import __layout_${k} from "${toAtFS(v)}"`);
1006
+ return [k, `__layout_${k}`];
1007
+ });
1008
+ return [imports.join("\n"), `export default {\n${Object.entries(layouts).map(([k, v]) => `"${k}": ${v}`).join(",\n")}\n}`].join("\n\n");
1009
+ }
1010
+ };
1011
+
1012
+ //#endregion
1013
+ //#region node/virtual/monaco-deps.ts
1014
+ const templateMonacoRunDeps = {
1015
+ id: "/@slidev/monaco-run-deps",
1016
+ async getContent({ userRoot, data }) {
1017
+ if (!data.features.monaco) return "";
1018
+ const deps = uniq(data.features.monaco.deps.concat(data.config.monacoTypesAdditionalPackages));
1019
+ const importerPath = resolve(userRoot, "./snippets/__importer__.ts");
1020
+ let result = "";
1021
+ for (let i = 0; i < deps.length; i++) {
1022
+ const specifier = deps[i];
1023
+ const resolved = await this.resolve(specifier, importerPath);
1024
+ if (!resolved) continue;
1025
+ result += `import * as vendored${i} from ${JSON.stringify(resolved.id)}\n`;
1026
+ }
1027
+ result += "export default {\n";
1028
+ for (let i = 0; i < deps.length; i++) result += `${JSON.stringify(deps[i])}: vendored${i},\n`;
1029
+ result += "}\n";
1030
+ return result;
1031
+ }
1032
+ };
1033
+
1034
+ //#endregion
1035
+ //#region node/virtual/monaco-types.ts
1036
+ const templateMonacoTypes = {
1037
+ id: "/@slidev/monaco-types",
1038
+ getContent: async ({ userRoot, data, utils }) => {
1039
+ if (!data.features.monaco) return "";
1040
+ const typesRoot = join(userRoot, "snippets");
1041
+ const files = await fg([
1042
+ "**/*.ts",
1043
+ "**/*.mts",
1044
+ "**/*.cts"
1045
+ ], { cwd: typesRoot });
1046
+ let result = "import { addFile } from \"@slidev/client/setup/monaco.ts\"\n";
1047
+ for (const file of files) {
1048
+ const url = `${toAtFS(resolve(typesRoot, file))}?monaco-types&raw`;
1049
+ result += `addFile(() => import(${JSON.stringify(url)}), ${JSON.stringify(file)})\n`;
1050
+ }
1051
+ function mapModuleNameToModule(moduleSpecifier) {
1052
+ if (moduleSpecifier.startsWith("node:")) return "node";
1053
+ if (builtinModules.includes(moduleSpecifier)) return "node";
1054
+ const mainPackageName = moduleSpecifier.split("/")[0];
1055
+ if (builtinModules.includes(mainPackageName) && !mainPackageName.startsWith("@")) return "node";
1056
+ const [a = "", b = ""] = moduleSpecifier.split("/");
1057
+ const moduleName = a.startsWith("@") ? `${a}/${b}` : a;
1058
+ return moduleName;
1059
+ }
1060
+ let deps = [...data.config.monacoTypesAdditionalPackages];
1061
+ if (data.config.monacoTypesSource === "local") deps.push(...data.features.monaco.types);
1062
+ deps = uniq(deps.map((specifier) => {
1063
+ if (specifier[0] === ".") return "";
1064
+ return mapModuleNameToModule(specifier);
1065
+ }).filter(Boolean));
1066
+ deps = deps.filter((pkg) => !utils.isMonacoTypesIgnored(pkg));
1067
+ for (const pkg of deps) result += `import(${JSON.stringify(`/@slidev-monaco-types/resolve?${new URLSearchParams({ pkg })}`)})\n`;
1068
+ return result;
1069
+ }
1070
+ };
1071
+
1072
+ //#endregion
1073
+ //#region node/virtual/nav-controls.ts
1074
+ const templateNavControls = {
1075
+ id: "/@slidev/custom-nav-controls",
1076
+ getContent({ roots }) {
1077
+ const components = roots.flatMap((root) => {
1078
+ return [join(root, "custom-nav-controls.vue"), join(root, "CustomNavControls.vue")];
1079
+ }).filter((i) => existsSync(i));
1080
+ const imports = components.map((i, idx) => `import __n${idx} from '${toAtFS(i)}'`).join("\n");
1081
+ const render = components.map((i, idx) => `h(__n${idx})`).join(",");
1082
+ return `${imports}
1083
+ import { h } from 'vue'
1084
+ export default {
1085
+ render: () => [${render}],
1086
+ }`;
1087
+ }
1088
+ };
1089
+
1090
+ //#endregion
1091
+ //#region node/virtual/setups.ts
1092
+ function createSetupTemplate(name) {
1093
+ return {
1094
+ id: `/@slidev/setups/${name}`,
1095
+ getContent({ roots }) {
1096
+ const setups = roots.flatMap((i) => {
1097
+ const path$1 = join(i, "setup", name);
1098
+ return [
1099
+ ".ts",
1100
+ ".mts",
1101
+ ".js",
1102
+ ".mjs"
1103
+ ].map((ext) => path$1 + ext);
1104
+ }).filter((i) => existsSync(i));
1105
+ const imports = [];
1106
+ setups.forEach((path$1, idx) => {
1107
+ imports.push(`import __n${idx} from '${toAtFS(path$1)}'`);
1108
+ });
1109
+ imports.push(`export default [${setups.map((_, idx) => `__n${idx}`).join(",")}]`);
1110
+ return imports.join("\n");
1111
+ }
1112
+ };
1113
+ }
1114
+ const setupModules = [
1115
+ "shiki",
1116
+ "code-runners",
1117
+ "monaco",
1118
+ "mermaid",
1119
+ "main",
1120
+ "root",
1121
+ "routes",
1122
+ "shortcuts",
1123
+ "context-menu"
1124
+ ];
1125
+ const templateSetups = setupModules.map(createSetupTemplate);
1126
+
1127
+ //#endregion
1128
+ //#region node/virtual/shiki.ts
1129
+ const templateShiki = {
1130
+ id: "/@slidev/shiki",
1131
+ getContent: async ({ utils }) => {
1132
+ const options = utils.shikiOptions;
1133
+ const langs = await resolveLangs(options.langs || [
1134
+ "markdown",
1135
+ "vue",
1136
+ "javascript",
1137
+ "typescript",
1138
+ "html",
1139
+ "css"
1140
+ ]);
1141
+ const resolvedThemeOptions = "themes" in options ? { themes: Object.fromEntries(await Promise.all(Object.entries(options.themes).map(async ([name, value]) => [name, await resolveTheme$1(value)]))) } : { theme: await resolveTheme$1(options.theme || "vitesse-dark") };
1142
+ const themes = resolvedThemeOptions.themes ? Object.values(resolvedThemeOptions.themes) : [resolvedThemeOptions.theme];
1143
+ 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 };
1144
+ async function normalizeGetter(p) {
1145
+ const r = typeof p === "function" ? p() : p;
1146
+ return r.default || r;
1147
+ }
1148
+ async function resolveLangs(langs$1) {
1149
+ const awaited = await Promise.all(langs$1.map((lang) => normalizeGetter(lang)));
1150
+ return uniq(awaited.flat());
1151
+ }
1152
+ async function resolveTheme$1(theme) {
1153
+ return typeof theme === "string" ? theme : await normalizeGetter(theme);
1154
+ }
1155
+ const langsInit = await Promise.all(langs.map(async (lang) => typeof lang === "string" ? `import('${await resolveImportUrl(`shiki/langs/${lang}.mjs`)}')` : JSON.stringify(lang)));
1156
+ const themesInit = await Promise.all(themes.map(async (theme) => typeof theme === "string" ? `import('${await resolveImportUrl(`shiki/themes/${theme}.mjs`)}')` : JSON.stringify(theme)));
1157
+ const langNames = langs.flatMap((lang) => typeof lang === "string" ? lang : lang.name);
1158
+ const lines = [];
1159
+ lines.push(`import { createHighlighterCore } from "${await resolveImportUrl("shiki/core")}"`, `import { createJavaScriptRegexEngine } from "${await resolveImportUrl("@shikijs/engine-javascript")}"`, `export { shikiToMonaco } from "${await resolveImportUrl("@shikijs/monaco")}"`, `export const languages = ${JSON.stringify(langNames)}`, `export const themes = ${JSON.stringify(themeOptionsNames.themes || themeOptionsNames.theme)}`, "export const shiki = createHighlighterCore({", ` themes: [${themesInit.join(",")}],`, ` langs: [${langsInit.join(",")}],`, ` engine: createJavaScriptRegexEngine(),`, "})", "let highlight", "export async function getHighlighter() {", " if (highlight) return highlight", " const highlighter = await shiki", " highlight = (code, lang, options) => highlighter.codeToHtml(code, {", " lang,", ` theme: ${JSON.stringify(themeOptionsNames.theme)},`, ` themes: ${JSON.stringify(themeOptionsNames.themes)},`, " defaultColor: false,", " ...options,", " })", " return highlight", "}");
1160
+ return lines.join("\n");
1161
+ }
1162
+ };
1163
+
1164
+ //#endregion
1165
+ //#region node/virtual/slides.ts
1166
+ const VIRTUAL_SLIDE_PREFIX = "/@slidev/slides/";
1167
+ const templateSlides = {
1168
+ id: "/@slidev/slides",
1169
+ getContent({ data, utils }) {
1170
+ const layouts = utils.getLayouts();
1171
+ const statements = [
1172
+ `import { defineAsyncComponent, shallowRef } from 'vue'`,
1173
+ `import SlideError from '${layouts.error}'`,
1174
+ `import SlideLoading from '@slidev/client/internals/SlideLoading.vue'`,
1175
+ `const componentsCache = new Array(${data.slides.length})`,
1176
+ `const getAsyncComponent = (idx, loader) => defineAsyncComponent({`,
1177
+ ` loader,`,
1178
+ ` delay: 300,`,
1179
+ ` loadingComponent: SlideLoading,`,
1180
+ ` errorComponent: SlideError,`,
1181
+ ` onError: e => console.error('Failed to load slide ' + (idx + 1), e) `,
1182
+ `})`
1183
+ ];
1184
+ const slides = data.slides.map((_, idx) => {
1185
+ const no = idx + 1;
1186
+ statements.push(
1187
+ `import { meta as f${no} } from '${VIRTUAL_SLIDE_PREFIX}${no}/frontmatter'`,
1188
+ // For some unknown reason, import error won't be caught by the error component. Catch it here.
1189
+ `const load${no} = async () => {`,
1190
+ ` try { return componentsCache[${idx}] ??= await import('${VIRTUAL_SLIDE_PREFIX}${no}/md') }`,
1191
+ ` catch (e) { console.error('slide failed to load', e); return SlideError }`,
1192
+ `}`
1193
+ );
1194
+ return `{ no: ${no}, meta: f${no}, load: load${no}, component: getAsyncComponent(${idx}, load${no}) }`;
1195
+ });
1196
+ return [
1197
+ ...statements,
1198
+ `const data = [\n${slides.join(",\n")}\n]`,
1199
+ `if (import.meta.hot) {`,
1200
+ ` import.meta.hot.data.slides ??= shallowRef()`,
1201
+ ` import.meta.hot.data.slides.value = data`,
1202
+ ` import.meta.hot.dispose(() => componentsCache.length = 0)`,
1203
+ ` import.meta.hot.accept()`,
1204
+ `}`,
1205
+ `export const slides = import.meta.hot ? import.meta.hot.data.slides : shallowRef(data)`
1206
+ ].join("\n");
1207
+ }
1208
+ };
1209
+
1210
+ //#endregion
1211
+ //#region node/virtual/styles.ts
1212
+ const templateStyle = {
1213
+ id: "/@slidev/styles",
1214
+ async getContent({ data, clientRoot, roots }) {
1215
+ function resolveUrlOfClient(name) {
1216
+ return toAtFS(join(clientRoot, name));
1217
+ }
1218
+ const imports = [
1219
+ `import "${resolveUrlOfClient("styles/vars.css")}"`,
1220
+ `import "${resolveUrlOfClient("styles/index.css")}"`,
1221
+ `import "${resolveUrlOfClient("styles/code.css")}"`,
1222
+ `import "${resolveUrlOfClient("styles/katex.css")}"`,
1223
+ `import "${resolveUrlOfClient("styles/transitions.css")}"`
1224
+ ];
1225
+ for (const root of roots) {
1226
+ const styles = [
1227
+ join(root, "styles", "index.ts"),
1228
+ join(root, "styles", "index.js"),
1229
+ join(root, "styles", "index.css"),
1230
+ join(root, "styles.css"),
1231
+ join(root, "style.css")
1232
+ ];
1233
+ for (const style of styles) if (existsSync(style)) {
1234
+ imports.push(`import "${toAtFS(style)}"`);
1235
+ continue;
1236
+ }
1237
+ }
1238
+ if (data.features.katex) imports.push(`import "${await resolveImportUrl("katex/dist/katex.min.css")}"`);
1239
+ if (data.config.highlighter === "shiki") imports.push(`import "${await resolveImportUrl("@shikijs/vitepress-twoslash/style.css")}"`, `import "${resolveUrlOfClient("styles/shiki-twoslash.css")}"`, `import "${await resolveImportUrl("shiki-magic-move/style.css")}"`);
1240
+ imports.unshift(`import "${await resolveImportUrl("@unocss/reset/tailwind.css")}"`, "import \"uno:preflights.css\"", "import \"uno:typography.css\"", "import \"uno:shortcuts.css\"");
1241
+ imports.push("import \"uno.css\"");
1242
+ return imports.join("\n");
1243
+ }
1244
+ };
1245
+
1246
+ //#endregion
1247
+ //#region node/virtual/titles.ts
1248
+ const templateTitleRendererMd = {
1249
+ id: "/@slidev/title-renderer.md",
1250
+ getContent({ data }) {
1251
+ const lines = data.slides.map(({ title }, i) => `<template ${i === 0 ? "v-if" : "v-else-if"}="no === ${i + 1}">\n\n${title}\n\n</template>`);
1252
+ lines.push(`<script setup lang="ts">`, `import { useSlideContext } from '@slidev/client/context.ts'`, `import { computed } from 'vue'`, `const props = defineProps<{ no?: number | string }>()`, `const { $page } = useSlideContext()`, `const no = computed(() => +(props.no ?? $page.value))`, `</script>`);
1253
+ return lines.join("\n");
1254
+ }
1255
+ };
1256
+ const templateTitleRenderer = {
1257
+ id: "/@slidev/title-renderer",
1258
+ async getContent() {
1259
+ return "export { default } from \"/@slidev/title-renderer.md\"";
1260
+ }
1261
+ };
1262
+
1263
+ //#endregion
1264
+ //#region node/virtual/index.ts
1265
+ const templates = [
1266
+ templateShiki,
1267
+ templateMonacoTypes,
1268
+ templateMonacoRunDeps,
1269
+ templateConfigs,
1270
+ templateStyle,
1271
+ templateGlobalLayers,
1272
+ templateNavControls,
1273
+ templateSlides,
1274
+ templateLayouts,
1275
+ templateTitleRenderer,
1276
+ templateTitleRendererMd,
1277
+ ...templateSetups,
1278
+ templateLegacyRoutes,
1279
+ templateLegacyTitles
1280
+ ];
1281
+
1282
+ //#endregion
1283
+ //#region node/vite/loaders.ts
1284
+ function createSlidesLoader(options, serverOptions) {
1285
+ const { data, mode, utils } = options;
1286
+ const notesMd = MarkdownIt({ html: true });
1287
+ notesMd.use(MarkdownItLink);
1288
+ if (data.features.katex) notesMd.use(MarkdownItKatex, utils.katexOptions);
1289
+ const hmrSlidesIndexes = new Set();
1290
+ let server;
1291
+ let skipHmr = null;
1292
+ let sourceIds = resolveSourceIds(data);
1293
+ function resolveSourceIds(data$1) {
1294
+ const ids = {
1295
+ md: [],
1296
+ frontmatter: []
1297
+ };
1298
+ for (const type of ["md", "frontmatter"]) for (let i = 0; i < data$1.slides.length; i++) ids[type].push(`${data$1.slides[i].source.filepath}__slidev_${i + 1}.${type}`);
1299
+ return ids;
1300
+ }
1301
+ function updateServerWatcher() {
1302
+ if (!server) return;
1303
+ server.watcher.add(Object.keys(data.watchFiles));
1304
+ }
1305
+ function getFrontmatter(pageNo) {
1306
+ return {
1307
+ ...data.headmatter?.defaults || {},
1308
+ ...data.slides[pageNo]?.frontmatter || {}
1309
+ };
1310
+ }
1311
+ return {
1312
+ name: "slidev:loader",
1313
+ enforce: "pre",
1314
+ configureServer(_server) {
1315
+ server = _server;
1316
+ updateServerWatcher();
1317
+ server.middlewares.use(async (req, res, next) => {
1318
+ const match = req.url?.match(regexSlideReqPath);
1319
+ if (!match) return next();
1320
+ const [, no] = match;
1321
+ const idx = Number.parseInt(no) - 1;
1322
+ if (req.method === "GET") {
1323
+ res.write(JSON.stringify(withRenderedNote(data.slides[idx])));
1324
+ return res.end();
1325
+ } else if (req.method === "POST") {
1326
+ const body = await getBodyJson(req);
1327
+ const slide = data.slides[idx];
1328
+ if (body.content && body.content !== slide.source.content) hmrSlidesIndexes.add(idx);
1329
+ if (body.content) slide.content = slide.source.content = body.content;
1330
+ if (body.frontmatterRaw != null) if (body.frontmatterRaw.trim() === "") slide.source.frontmatterDoc = slide.source.frontmatterStyle = void 0;
1331
+ else {
1332
+ const parsed = YAML.parseDocument(body.frontmatterRaw);
1333
+ if (parsed.errors.length) console.error("ERROR when saving frontmatter", parsed.errors);
1334
+ else slide.source.frontmatterDoc = parsed;
1335
+ }
1336
+ if (body.note) slide.note = slide.source.note = body.note;
1337
+ if (body.frontmatter) {
1338
+ updateFrontmatterPatch(slide.source, body.frontmatter);
1339
+ Object.assign(slide.frontmatter, body.frontmatter);
1340
+ }
1341
+ parser.prettifySlide(slide.source);
1342
+ const fileContent = await parser.save(data.markdownFiles[slide.source.filepath]);
1343
+ if (body.skipHmr) {
1344
+ skipHmr = {
1345
+ filePath: slide.source.filepath,
1346
+ fileContent
1347
+ };
1348
+ server?.moduleGraph.invalidateModule(server.moduleGraph.getModuleById(sourceIds.md[idx]));
1349
+ if (body.frontmatter) server?.moduleGraph.invalidateModule(server.moduleGraph.getModuleById(sourceIds.frontmatter[idx]));
1350
+ }
1351
+ res.statusCode = 200;
1352
+ res.write(JSON.stringify(withRenderedNote(slide)));
1353
+ return res.end();
1354
+ }
1355
+ next();
1356
+ });
1357
+ },
1358
+ async handleHotUpdate(ctx) {
1359
+ const forceChangedSlides = data.watchFiles[ctx.file];
1360
+ if (!forceChangedSlides) return;
1361
+ for (const index of forceChangedSlides) hmrSlidesIndexes.add(index);
1362
+ const newData = await serverOptions.loadData?.({ [ctx.file]: await ctx.read() });
1363
+ if (!newData) return [];
1364
+ if (skipHmr && newData.markdownFiles[skipHmr.filePath]?.raw === skipHmr.fileContent) {
1365
+ skipHmr = null;
1366
+ return [];
1367
+ }
1368
+ const moduleIds = new Set();
1369
+ const newSourceIds = resolveSourceIds(newData);
1370
+ for (const type of ["md", "frontmatter"]) {
1371
+ const old = sourceIds[type];
1372
+ const newIds = newSourceIds[type];
1373
+ for (let i = 0; i < newIds.length; i++) if (old[i] !== newIds[i]) moduleIds.add(`${VIRTUAL_SLIDE_PREFIX}${i + 1}/${type}`);
1374
+ }
1375
+ sourceIds = newSourceIds;
1376
+ if (data.slides.length !== newData.slides.length) moduleIds.add(templateSlides.id);
1377
+ if (!equal(data.headmatter.defaults, newData.headmatter.defaults)) {
1378
+ moduleIds.add(templateSlides.id);
1379
+ range(data.slides.length).map((i) => hmrSlidesIndexes.add(i));
1380
+ }
1381
+ if (!equal(data.config, newData.config)) moduleIds.add(templateConfigs.id);
1382
+ if (!equal(data.features, newData.features)) setTimeout(() => {
1383
+ ctx.server.hot.send({ type: "full-reload" });
1384
+ }, 1);
1385
+ const length = Math.min(data.slides.length, newData.slides.length);
1386
+ for (let i = 0; i < length; i++) {
1387
+ const a = data.slides[i];
1388
+ const b = newData.slides[i];
1389
+ if (!hmrSlidesIndexes.has(i) && a.content.trim() === b.content.trim() && a.title?.trim() === b.title?.trim() && equal(a.frontmatter, b.frontmatter)) {
1390
+ if (a.note !== b.note) ctx.server.hot.send("slidev:update-note", {
1391
+ no: i + 1,
1392
+ note: b.note || "",
1393
+ noteHTML: renderNote(b.note || "")
1394
+ });
1395
+ continue;
1396
+ }
1397
+ ctx.server.hot.send("slidev:update-slide", {
1398
+ no: i + 1,
1399
+ data: withRenderedNote(newData.slides[i])
1400
+ });
1401
+ hmrSlidesIndexes.add(i);
1402
+ }
1403
+ Object.assign(data, newData);
1404
+ Object.assign(utils, createDataUtils(options));
1405
+ if (hmrSlidesIndexes.size > 0) moduleIds.add(templateTitleRendererMd.id);
1406
+ const vueModules = Array.from(hmrSlidesIndexes).flatMap((idx) => {
1407
+ const frontmatter = ctx.server.moduleGraph.getModuleById(sourceIds.frontmatter[idx]);
1408
+ const main = ctx.server.moduleGraph.getModuleById(sourceIds.md[idx]);
1409
+ const styles = main ? [...main.clientImportedModules].find((m) => m.id?.includes(`&type=style`)) : void 0;
1410
+ return [
1411
+ frontmatter,
1412
+ main,
1413
+ styles
1414
+ ];
1415
+ });
1416
+ hmrSlidesIndexes.clear();
1417
+ const moduleEntries = [
1418
+ ...ctx.modules.filter((i) => i.id === templateMonacoRunDeps.id || i.id === templateMonacoTypes.id),
1419
+ ...vueModules,
1420
+ ...Array.from(moduleIds).map((id) => ctx.server.moduleGraph.getModuleById(id))
1421
+ ].filter(notNullish).filter((i) => !i.id?.startsWith("/@id/@vite-icons"));
1422
+ updateServerWatcher();
1423
+ return moduleEntries;
1424
+ },
1425
+ resolveId: {
1426
+ order: "pre",
1427
+ handler(id) {
1428
+ if (id.startsWith("/@slidev/") || id.includes("__slidev_")) return id;
1429
+ return null;
1430
+ }
1431
+ },
1432
+ async load(id) {
1433
+ const template = templates.find((i) => i.id === id);
1434
+ if (template) return {
1435
+ code: await template.getContent.call(this, options),
1436
+ map: { mappings: "" }
1437
+ };
1438
+ const matchFacade = id.match(regexSlideFacadeId);
1439
+ if (matchFacade) {
1440
+ const [, no, type] = matchFacade;
1441
+ const idx = +no - 1;
1442
+ const sourceId = JSON.stringify(sourceIds[type][idx]);
1443
+ return [`export * from ${sourceId}`, `export { default } from ${sourceId}`].join("\n");
1444
+ }
1445
+ const matchSource = id.match(regexSlideSourceId);
1446
+ if (matchSource) {
1447
+ const [, no, type] = matchSource;
1448
+ const idx = +no - 1;
1449
+ const slide = data.slides[idx];
1450
+ if (!slide) return;
1451
+ if (type === "md") return {
1452
+ code: slide.content,
1453
+ map: { mappings: "" }
1454
+ };
1455
+ else if (type === "frontmatter") {
1456
+ const slideBase = {
1457
+ ...withRenderedNote(slide),
1458
+ frontmatter: void 0,
1459
+ source: void 0,
1460
+ importChain: void 0,
1461
+ ...mode === "build" ? {
1462
+ raw: "",
1463
+ content: "",
1464
+ note: ""
1465
+ } : {}
1466
+ };
1467
+ const fontmatter = getFrontmatter(idx);
1468
+ return {
1469
+ code: [
1470
+ "// @unocss-include",
1471
+ "import { computed, reactive, shallowReactive } from \"vue\"",
1472
+ `export const frontmatterData = ${JSON.stringify(fontmatter)}`,
1473
+ "if (import.meta.hot) {",
1474
+ " const firstLoad = !import.meta.hot.data.frontmatter",
1475
+ " import.meta.hot.data.frontmatter ??= reactive(frontmatterData)",
1476
+ " import.meta.hot.accept(({ frontmatterData: update }) => {",
1477
+ " if (firstLoad) return",
1478
+ " const frontmatter = import.meta.hot.data.frontmatter",
1479
+ " Object.keys(frontmatter).forEach(key => {",
1480
+ " if (!(key in update)) delete frontmatter[key]",
1481
+ " })",
1482
+ " Object.assign(frontmatter, update)",
1483
+ " })",
1484
+ "}",
1485
+ "export const frontmatter = import.meta.hot ? import.meta.hot.data.frontmatter : reactive(frontmatterData)",
1486
+ "export default frontmatter",
1487
+ "export const meta = shallowReactive({",
1488
+ " get layout(){ return frontmatter.layout },",
1489
+ " get transition(){ return frontmatter.transition },",
1490
+ " get class(){ return frontmatter.class },",
1491
+ " get clicks(){ return frontmatter.clicks },",
1492
+ " get name(){ return frontmatter.name },",
1493
+ " get preload(){ return frontmatter.preload },",
1494
+ " slide: {",
1495
+ ` ...(${JSON.stringify(slideBase)}),`,
1496
+ ` frontmatter,`,
1497
+ ` filepath: ${JSON.stringify(mode === "dev" ? slide.source.filepath : "")},`,
1498
+ ` start: ${JSON.stringify(slide.source.start)},`,
1499
+ ` id: ${idx},`,
1500
+ ` no: ${no},`,
1501
+ " },",
1502
+ " __clicksContext: null,",
1503
+ " __preloaded: false,",
1504
+ "})"
1505
+ ].join("\n"),
1506
+ map: { mappings: "" }
1507
+ };
1508
+ }
1509
+ }
1510
+ if (data.markdownFiles[id]) return "";
1511
+ }
1512
+ };
1513
+ function renderNote(text = "") {
1514
+ let clickCount = 0;
1515
+ const html = notesMd.render(text.replace(/\[click(?::(\d+))?\]/gi, (_, count = 1) => {
1516
+ clickCount += Number(count);
1517
+ return `<span class="slidev-note-click-mark" data-clicks="${clickCount}"></span>`;
1518
+ }));
1519
+ return html;
1520
+ }
1521
+ function withRenderedNote(data$1) {
1522
+ return {
1523
+ ...data$1,
1524
+ noteHTML: renderNote(data$1?.note)
1525
+ };
1526
+ }
1527
+ }
1528
+
1529
+ //#endregion
1530
+ //#region ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=49e14003b6caa0b7d164cbe71da573809d375bab_d6f3113a192503d8f8553bee4b7feffb/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/image-size/specialCharacters.js
1531
+ var SpecialCharacters;
1532
+ (function(SpecialCharacters$1) {
1533
+ SpecialCharacters$1[SpecialCharacters$1["EXCLAMATION_MARK"] = 33] = "EXCLAMATION_MARK";
1534
+ SpecialCharacters$1[SpecialCharacters$1["OPENING_BRACKET"] = 91] = "OPENING_BRACKET";
1535
+ SpecialCharacters$1[SpecialCharacters$1["OPENING_PARENTHESIS"] = 40] = "OPENING_PARENTHESIS";
1536
+ SpecialCharacters$1[SpecialCharacters$1["WHITESPACE"] = 32] = "WHITESPACE";
1537
+ SpecialCharacters$1[SpecialCharacters$1["NEW_LINE"] = 10] = "NEW_LINE";
1538
+ SpecialCharacters$1[SpecialCharacters$1["EQUALS"] = 61] = "EQUALS";
1539
+ SpecialCharacters$1[SpecialCharacters$1["LOWER_CASE_X"] = 120] = "LOWER_CASE_X";
1540
+ SpecialCharacters$1[SpecialCharacters$1["NUMBER_ZERO"] = 48] = "NUMBER_ZERO";
1541
+ SpecialCharacters$1[SpecialCharacters$1["NUMBER_NINE"] = 57] = "NUMBER_NINE";
1542
+ SpecialCharacters$1[SpecialCharacters$1["PERCENTAGE"] = 37] = "PERCENTAGE";
1543
+ SpecialCharacters$1[SpecialCharacters$1["CLOSING_PARENTHESIS"] = 41] = "CLOSING_PARENTHESIS";
1544
+ })(SpecialCharacters || (SpecialCharacters = {}));
1545
+
1546
+ //#endregion
1547
+ //#region ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=49e14003b6caa0b7d164cbe71da573809d375bab_d6f3113a192503d8f8553bee4b7feffb/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/task-lists/index.js
1548
+ const checkboxRegex = /^ *\[([\sx])] /i;
1549
+ function taskLists(md, options = {
1550
+ enabled: false,
1551
+ label: false,
1552
+ lineNumber: false
1553
+ }) {
1554
+ md.core.ruler.after("inline", "task-lists", (state) => processToken(state, options));
1555
+ md.renderer.rules.taskListItemCheckbox = (tokens) => {
1556
+ const token = tokens[0];
1557
+ const checkedAttribute = token.attrGet("checked") ? "checked=\"\" " : "";
1558
+ const disabledAttribute = token.attrGet("disabled") ? "disabled=\"\" " : "";
1559
+ const line = token.attrGet("line");
1560
+ const idAttribute = `id="${token.attrGet("id")}" `;
1561
+ const dataLineAttribute = line && options.lineNumber ? `data-line="${line}" ` : "";
1562
+ return `<input class="task-list-item-checkbox" type="checkbox" ${checkedAttribute}${disabledAttribute}${dataLineAttribute}${idAttribute}/>`;
1563
+ };
1564
+ md.renderer.rules.taskListItemLabel_close = () => {
1565
+ return "</label>";
1566
+ };
1567
+ md.renderer.rules.taskListItemLabel_open = (tokens) => {
1568
+ const token = tokens[0];
1569
+ const id = token.attrGet("id");
1570
+ return `<label for="${id}">`;
1571
+ };
1572
+ }
1573
+ function processToken(state, options) {
1574
+ const allTokens = state.tokens;
1575
+ for (let i = 2; i < allTokens.length; i++) {
1576
+ if (!isTodoItem(allTokens, i)) continue;
1577
+ todoify(allTokens[i], options);
1578
+ allTokens[i - 2].attrJoin("class", `task-list-item ${options.enabled ? " enabled" : ""}`);
1579
+ const parentToken = findParentToken(allTokens, i - 2);
1580
+ if (parentToken) {
1581
+ const classes = parentToken.attrGet("class") ?? "";
1582
+ if (!classes.match(/(^| )contains-task-list/)) parentToken.attrJoin("class", "contains-task-list");
1583
+ }
1584
+ }
1585
+ return false;
1586
+ }
1587
+ function findParentToken(tokens, index) {
1588
+ const targetLevel = tokens[index].level - 1;
1589
+ for (let currentTokenIndex = index - 1; currentTokenIndex >= 0; currentTokenIndex--) if (tokens[currentTokenIndex].level === targetLevel) return tokens[currentTokenIndex];
1590
+ return void 0;
1591
+ }
1592
+ function isTodoItem(tokens, index) {
1593
+ return isInline(tokens[index]) && isParagraph(tokens[index - 1]) && isListItem(tokens[index - 2]) && startsWithTodoMarkdown(tokens[index]);
1594
+ }
1595
+ function todoify(token, options) {
1596
+ if (token.children == null) return;
1597
+ const id = generateIdForToken(token);
1598
+ token.children.splice(0, 0, createCheckboxToken(token, options.enabled, id));
1599
+ token.children[1].content = token.children[1].content.replace(checkboxRegex, "");
1600
+ if (options.label) {
1601
+ token.children.splice(1, 0, createLabelBeginToken(id));
1602
+ token.children.push(createLabelEndToken());
1603
+ }
1604
+ }
1605
+ function generateIdForToken(token) {
1606
+ if (token.map) return `task-item-${token.map[0]}`;
1607
+ else return `task-item-${Math.ceil(Math.random() * (1e4 * 1e3) - 1e3)}`;
1608
+ }
1609
+ function createCheckboxToken(token, enabled, id) {
1610
+ const checkbox = new Token("taskListItemCheckbox", "", 0);
1611
+ if (!enabled) checkbox.attrSet("disabled", "true");
1612
+ if (token.map) checkbox.attrSet("line", token.map[0].toString());
1613
+ checkbox.attrSet("id", id);
1614
+ const checkboxRegexResult = checkboxRegex.exec(token.content);
1615
+ const isChecked = checkboxRegexResult?.[1].toLowerCase() === "x";
1616
+ if (isChecked) checkbox.attrSet("checked", "true");
1617
+ return checkbox;
1618
+ }
1619
+ function createLabelBeginToken(id) {
1620
+ const labelBeginToken = new Token("taskListItemLabel_open", "", 1);
1621
+ labelBeginToken.attrSet("id", id);
1622
+ return labelBeginToken;
1623
+ }
1624
+ function createLabelEndToken() {
1625
+ return new Token("taskListItemLabel_close", "", -1);
1626
+ }
1627
+ function isInline(token) {
1628
+ return token.type === "inline";
1629
+ }
1630
+ function isParagraph(token) {
1631
+ return token.type === "paragraph_open";
1632
+ }
1633
+ function isListItem(token) {
1634
+ return token.type === "list_item_open";
1635
+ }
1636
+ function startsWithTodoMarkdown(token) {
1637
+ return checkboxRegex.test(token.content);
1638
+ }
1639
+
1640
+ //#endregion
1641
+ //#region node/syntax/markdown-it/markdown-it-escape-code.ts
1642
+ function MarkdownItEscapeInlineCode(md) {
1643
+ const codeInline = md.renderer.rules.code_inline;
1644
+ md.renderer.rules.code_inline = (tokens, idx, options, env, self) => {
1645
+ const result = codeInline(tokens, idx, options, env, self);
1646
+ return result.replace(/^<code/, "<code v-pre");
1647
+ };
1648
+ }
1649
+
1650
+ //#endregion
1651
+ //#region node/syntax/transform/utils.ts
1652
+ function normalizeRangeStr(rangeStr = "") {
1653
+ return !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
1654
+ }
1655
+ function getCodeBlocks(md) {
1656
+ const codeblocks = Array.from(md.matchAll(/^```[\s\S]*?^```/gm)).map((m) => {
1657
+ const start = m.index;
1658
+ const end = m.index + m[0].length;
1659
+ const startLine = md.slice(0, start).match(/\n/g)?.length || 0;
1660
+ const endLine = md.slice(0, end).match(/\n/g)?.length || 0;
1661
+ return [
1662
+ start,
1663
+ end,
1664
+ startLine,
1665
+ endLine
1666
+ ];
1667
+ });
1668
+ return {
1669
+ codeblocks,
1670
+ isInsideCodeblocks(idx) {
1671
+ return codeblocks.some(([s, e]) => s <= idx && idx <= e);
1672
+ },
1673
+ isLineInsideCodeblocks(line) {
1674
+ return codeblocks.some(([, , s, e]) => s <= line && line <= e);
1675
+ }
1676
+ };
1677
+ }
1678
+ /**
1679
+ * Escape `{{` in code block to prevent Vue interpret it, #99, #1316
1680
+ */
1681
+ function escapeVueInCode(md) {
1682
+ return md.replace(/\{\{/g, "&lbrace;&lbrace;");
1683
+ }
1684
+
1685
+ //#endregion
1686
+ //#region node/syntax/markdown-it/markdown-it-shiki.ts
1687
+ async function MarkdownItShiki({ data: { config }, mode, utils }) {
1688
+ const transformers = [
1689
+ ...utils.shikiOptions.transformers || [],
1690
+ (config.twoslash === true || config.twoslash === mode) && (await import("@shikijs/vitepress-twoslash")).transformerTwoslash({
1691
+ explicitTrigger: true,
1692
+ twoslashOptions: { handbookOptions: { noErrorValidation: true } }
1693
+ }),
1694
+ {
1695
+ pre(pre) {
1696
+ this.addClassToHast(pre, "slidev-code");
1697
+ delete pre.properties.tabindex;
1698
+ },
1699
+ postprocess(code) {
1700
+ return escapeVueInCode(code);
1701
+ }
1702
+ }
1703
+ ].filter(isTruthy);
1704
+ return fromHighlighter(utils.shiki, {
1705
+ ...utils.shikiOptions,
1706
+ transformers
1707
+ });
1708
+ }
1709
+
1710
+ //#endregion
1711
+ //#region node/syntax/markdown-it/markdown-it-v-drag.ts
1712
+ const dragComponentRegex = /<(v-?drag-?\w*)([\s>])/i;
1713
+ const dragDirectiveRegex = /(?<![</\w])v-drag(=".*?")?/i;
1714
+ function MarkdownItVDrag(md, markdownTransformMap) {
1715
+ const visited = new WeakSet();
1716
+ const sourceMapConsumers = new WeakMap();
1717
+ function getSourceMapConsumer(id) {
1718
+ const s = markdownTransformMap.get(id);
1719
+ if (!s) return void 0;
1720
+ let smc = sourceMapConsumers.get(s);
1721
+ if (smc) return smc;
1722
+ const sourceMap = s.generateMap();
1723
+ smc = new SourceMapConsumer({
1724
+ ...sourceMap,
1725
+ version: sourceMap.version.toString()
1726
+ });
1727
+ sourceMapConsumers.set(s, smc);
1728
+ return smc;
1729
+ }
1730
+ const _parse = md.parse;
1731
+ md.parse = function(src, env) {
1732
+ const smc = getSourceMapConsumer(env.id);
1733
+ const toOriginalPos = smc ? (line) => smc.originalPositionFor({
1734
+ line: line + 1,
1735
+ column: 0
1736
+ }).line - 1 : (line) => line;
1737
+ function toMarkdownSource(map, idx) {
1738
+ const start = toOriginalPos(map[0]);
1739
+ const end = toOriginalPos(map[1]);
1740
+ return `[${start},${Math.max(start + 1, end)},${idx}]`;
1741
+ }
1742
+ function replaceChildren(token, regex, replacement) {
1743
+ for (const child of token.children ?? []) {
1744
+ if (child.type === "html_block" || child.type === "html_inline") child.content = child.content.replace(regex, replacement);
1745
+ replaceChildren(child, regex, replacement);
1746
+ }
1747
+ }
1748
+ return _parse.call(this, src, env).map((token) => {
1749
+ if (![
1750
+ "html_block",
1751
+ "html_inline",
1752
+ "inline"
1753
+ ].includes(token.type) || !token.content.includes("drag") || visited.has(token)) return token;
1754
+ token.content = token.content.replace(dragComponentRegex, (_, tag, space, idx) => {
1755
+ const replacement = `<${tag} :markdownSource="${toMarkdownSource(token.map, idx)}"${space}`;
1756
+ replaceChildren(token, dragComponentRegex, replacement);
1757
+ return replacement;
1758
+ }).replace(dragDirectiveRegex, (_, value, idx) => {
1759
+ const replacement = `v-drag${value ?? ""} :markdownSource="${toMarkdownSource(token.map, idx)}"`;
1760
+ replaceChildren(token, dragDirectiveRegex, replacement);
1761
+ return replacement;
1762
+ });
1763
+ visited.add(token);
1764
+ return token;
1765
+ });
1766
+ };
1767
+ }
1768
+
1769
+ //#endregion
1770
+ //#region node/syntax/markdown-it/index.ts
1771
+ async function useMarkdownItPlugins(md, options, markdownTransformMap) {
1772
+ const { data: { features, config }, utils: { katexOptions } } = options;
1773
+ if (config.highlighter === "shiki") md.use(await MarkdownItShiki(options));
1774
+ md.use(MarkdownItLink);
1775
+ md.use(MarkdownItEscapeInlineCode);
1776
+ md.use(MarkdownItFootnote);
1777
+ md.use(taskLists, {
1778
+ enabled: true,
1779
+ lineNumber: true,
1780
+ label: true
1781
+ });
1782
+ if (features.katex) md.use(MarkdownItKatex, katexOptions);
1783
+ md.use(MarkdownItVDrag, markdownTransformMap);
1784
+ if (config.mdc) md.use(MarkdownItMdc);
1785
+ }
1786
+
1787
+ //#endregion
1788
+ //#region node/setups/transformers.ts
1789
+ async function setupTransformers(roots) {
1790
+ const returns = await loadSetups(roots, "transformers.ts", []);
1791
+ const result = {
1792
+ pre: [],
1793
+ preCodeblock: [],
1794
+ postCodeblock: [],
1795
+ post: []
1796
+ };
1797
+ for (const r of [...returns].reverse()) {
1798
+ if (r.pre) result.pre.push(...r.pre);
1799
+ if (r.preCodeblock) result.preCodeblock.push(...r.preCodeblock);
1800
+ }
1801
+ for (const r of returns) {
1802
+ if (r.postCodeblock) result.postCodeblock.push(...r.postCodeblock);
1803
+ if (r.post) result.post.push(...r.post);
1804
+ }
1805
+ return result;
1806
+ }
1807
+
1808
+ //#endregion
1809
+ //#region node/syntax/transform/code-wrapper.ts
1810
+ const reCodeBlock = /^```([\w'-]+)?\s*(?:\{([\w*,|-]+)\}\s*?(\{[^}]*\})?([^\r\n]*))?\r?\n([ \t]*\S[\s\S]*?)^```$/gm;
1811
+ /**
1812
+ * Transform code block with wrapper
1813
+ */
1814
+ function transformCodeWrapper(ctx) {
1815
+ ctx.s.replace(reCodeBlock, (full, lang = "", rangeStr = "", options = "", attrs = "", code) => {
1816
+ const ranges = normalizeRangeStr(rangeStr);
1817
+ code = code.trimEnd();
1818
+ options = options.trim() || "{}";
1819
+ return `\n<CodeBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>\n\n\`\`\`${lang}${attrs}\n${code}\n\`\`\`\n\n</CodeBlockWrapper>`;
1820
+ });
1821
+ }
1822
+
1823
+ //#endregion
1824
+ //#region node/syntax/transform/in-page-css.ts
1825
+ /**
1826
+ * Transform <style> in markdown to scoped style with page selector
1827
+ */
1828
+ function transformPageCSS(ctx) {
1829
+ const codeBlocks = getCodeBlocks(ctx.s.original);
1830
+ ctx.s.replace(/(\n<style[^>]*>)([\s\S]+?)(<\/style>)/g, (full, start, css, end, index) => {
1831
+ if (codeBlocks.isInsideCodeblocks(index)) return full;
1832
+ if (!start.includes("scoped")) start = start.replace("<style", "<style scoped");
1833
+ return `${start}\n${css}${end}`;
1834
+ });
1835
+ }
1836
+
1837
+ //#endregion
1838
+ //#region node/syntax/transform/katex-wrapper.ts
1839
+ /**
1840
+ * Wrapper KaTex syntax `$$...$$` for highlighting
1841
+ */
1842
+ function transformKaTexWrapper(ctx) {
1843
+ ctx.s.replace(/^\$\$(?:\s*\{([\w*,|-]+)\}\s*?(?:(\{[^}]*\})\s*?)?)?\n(\S[\s\S]*?)^\$\$/gm, (full, rangeStr = "", options = "", code) => {
1844
+ const ranges = !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
1845
+ code = code.trimEnd();
1846
+ options = options.trim() || "{}";
1847
+ return `<KaTexBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>\n\n\$\$\n${code}\n\$\$\n</KaTexBlockWrapper>\n`;
1848
+ });
1849
+ }
1850
+
1851
+ //#endregion
1852
+ //#region node/syntax/transform/magic-move.ts
1853
+ const reMagicMoveBlock = /^````(?:md|markdown) magic-move *(\{[^}]*\})?([^ \n]*)\n([\s\S]+?)^````$/gm;
1854
+ function parseLineNumbersOption(options) {
1855
+ return /lines: *true/.test(options) ? true : /lines: *false/.test(options) ? false : void 0;
1856
+ }
1857
+ /**
1858
+ * Transform magic-move code blocks
1859
+ */
1860
+ function transformMagicMove(ctx) {
1861
+ ctx.s.replace(reMagicMoveBlock, (full, options = "{}", _attrs = "", body) => {
1862
+ const matches = Array.from(body.matchAll(reCodeBlock));
1863
+ if (!matches.length) throw new Error("Magic Move block must contain at least one code block");
1864
+ const defaultLineNumbers = parseLineNumbersOption(options) ?? ctx.options.data.config.lineNumbers;
1865
+ const ranges = matches.map((i) => normalizeRangeStr(i[2]));
1866
+ const steps = matches.map((i) => {
1867
+ const lineNumbers = parseLineNumbersOption(i[3]) ?? defaultLineNumbers;
1868
+ return codeToKeyedTokens(ctx.options.utils.shiki, i[5].trimEnd(), {
1869
+ ...ctx.options.utils.shikiOptions,
1870
+ lang: i[1]
1871
+ }, lineNumbers);
1872
+ });
1873
+ const compressed = lz.compressToBase64(JSON.stringify(steps));
1874
+ return `<ShikiMagicMove v-bind="${options}" steps-lz="${compressed}" :step-ranges='${JSON.stringify(ranges)}' />`;
1875
+ });
1876
+ }
1877
+
1878
+ //#endregion
1879
+ //#region node/syntax/transform/mermaid.ts
1880
+ /**
1881
+ * Transform Mermaid code blocks (render done on client side)
1882
+ */
1883
+ function transformMermaid(ctx) {
1884
+ ctx.s.replace(/^```mermaid *(\{[^\n]*\})?\n([\s\S]+?)\n```/gm, (full, options = "", code = "") => {
1885
+ code = code.trim();
1886
+ options = options.trim() || "{}";
1887
+ const encoded = lz.compressToBase64(code);
1888
+ return `<Mermaid code-lz="${encoded}" v-bind="${options}" />`;
1889
+ });
1890
+ }
1891
+
1892
+ //#endregion
1893
+ //#region node/syntax/transform/monaco.ts
1894
+ function transformMonaco(ctx) {
1895
+ const enabled = ctx.options.data.config.monaco === true || ctx.options.data.config.monaco === ctx.options.mode;
1896
+ if (!enabled) {
1897
+ ctx.s.replace(/\{monaco([\w:,-]*)\}/g, "");
1898
+ return;
1899
+ }
1900
+ ctx.s.replace(/^```(\w+) *\{monaco-diff\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^~~~ *\n([\s\S]+?)^```/gm, (full, lang = "ts", options = "{}", code, diff) => {
1901
+ lang = lang.trim();
1902
+ options = options.trim() || "{}";
1903
+ const encoded = lz.compressToBase64(code);
1904
+ const encodedDiff = lz.compressToBase64(diff);
1905
+ return `<Monaco code-lz="${encoded}" diff-lz="${encodedDiff}" lang="${lang}" v-bind="${options}" />`;
1906
+ });
1907
+ ctx.s.replace(/^```(\w+) *\{monaco\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm, (full, lang = "ts", options = "{}", code) => {
1908
+ lang = lang.trim();
1909
+ options = options.trim() || "{}";
1910
+ const encoded = lz.compressToBase64(code);
1911
+ return `<Monaco code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
1912
+ });
1913
+ ctx.s.replace(/^```(\w+) *\{monaco-run\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm, (full, lang = "ts", options = "{}", code) => {
1914
+ lang = lang.trim();
1915
+ options = options.trim() || "{}";
1916
+ const encoded = lz.compressToBase64(code);
1917
+ return `<Monaco runnable code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
1918
+ });
1919
+ }
1920
+
1921
+ //#endregion
1922
+ //#region node/syntax/transform/plant-uml.ts
1923
+ function transformPlantUml(ctx) {
1924
+ const server = ctx.options.data.config.plantUmlServer;
1925
+ ctx.s.replace(/^```plantuml[^\n{}]*(\{[^}\n]*\})?\n([\s\S]+?)\n```/gm, (full, options = "", content = "") => {
1926
+ const code = encode(content.trim());
1927
+ options = options.trim() || "{}";
1928
+ return `<PlantUml :code="'${code}'" :server="'${server}'" v-bind="${options}" />`;
1929
+ });
1930
+ }
1931
+
1932
+ //#endregion
1933
+ //#region node/syntax/transform/slot-sugar.ts
1934
+ function transformSlotSugar(ctx) {
1935
+ const linesWithNewline = ctx.s.original.split(/(\r?\n)/g);
1936
+ const codeBlocks = getCodeBlocks(ctx.s.original);
1937
+ const lines = [];
1938
+ for (let i = 0; i < linesWithNewline.length; i += 2) {
1939
+ const line = linesWithNewline[i];
1940
+ const newline = linesWithNewline[i + 1] || "";
1941
+ lines.push(line + newline);
1942
+ }
1943
+ let prevSlot = false;
1944
+ let offset = 0;
1945
+ lines.forEach((line) => {
1946
+ const start = offset;
1947
+ offset += line.length;
1948
+ if (codeBlocks.isInsideCodeblocks(offset)) return;
1949
+ const match = line.match(/^::\s*([\w.\-:]+)\s*::(\s*)$/);
1950
+ if (match) {
1951
+ ctx.s.overwrite(start, offset - match[2].length, `${prevSlot ? "\n\n</template>\n" : "\n"}<template v-slot:${match[1]}="slotProps">\n`);
1952
+ prevSlot = true;
1953
+ }
1954
+ });
1955
+ if (prevSlot) ctx.s.append("\n\n</template>");
1956
+ }
1957
+
1958
+ //#endregion
1959
+ //#region node/vite/monacoWrite.ts
1960
+ const monacoWriterWhitelist = new Set();
1961
+ function createMonacoWriterPlugin({ userRoot }) {
1962
+ return {
1963
+ name: "slidev:monaco-write",
1964
+ apply: "serve",
1965
+ configureServer(server) {
1966
+ server.ws.on("connection", (socket) => {
1967
+ socket.on("message", async (data) => {
1968
+ let json;
1969
+ try {
1970
+ json = JSON.parse(data.toString());
1971
+ } catch {
1972
+ return;
1973
+ }
1974
+ if (json.type === "custom" && json.event === "slidev:monaco-write") {
1975
+ const { file, content } = json.data;
1976
+ if (!monacoWriterWhitelist.has(file)) {
1977
+ console.error(`[Slidev] Unauthorized file write: ${file}`);
1978
+ return;
1979
+ }
1980
+ const filepath = path.join(userRoot, file);
1981
+ console.log("[Slidev] Writing file:", filepath);
1982
+ await fs.writeFile(filepath, content, "utf-8");
1983
+ }
1984
+ });
1985
+ });
1986
+ }
1987
+ };
1988
+ }
1989
+
1990
+ //#endregion
1991
+ //#region node/syntax/transform/snippet.ts
1992
+ function dedent(text) {
1993
+ const lines = text.split("\n");
1994
+ const minIndentLength = lines.reduce((acc, line) => {
1995
+ for (let i = 0; i < line.length; i++) if (line[i] !== " " && line[i] !== " ") return Math.min(i, acc);
1996
+ return acc;
1997
+ }, Number.POSITIVE_INFINITY);
1998
+ if (minIndentLength < Number.POSITIVE_INFINITY) return lines.map((x) => x.slice(minIndentLength)).join("\n");
1999
+ return text;
2000
+ }
2001
+ function findRegion(lines, regionName) {
2002
+ const regionRegexps = [
2003
+ [/^\/\/ ?#?region ([\w*-]+)$/, /^\/\/ ?#?endregion/],
2004
+ [/^\/\* ?#region ([\w*-]+) ?\*\/$/, /^\/\* ?#endregion[\s\w*-]*\*\/$/],
2005
+ [/^#pragma region ([\w*-]+)$/, /^#pragma endregion/],
2006
+ [/^<!-- #?region ([\w*-]+) -->$/, /^<!-- #?region[\s\w*-]*-->$/],
2007
+ [/^#Region ([\w*-]+)$/, /^#End Region/],
2008
+ [/^::#region ([\w*-]+)$/, /^::#endregion/],
2009
+ [/^# ?region ([\w*-]+)$/, /^# ?endregion/]
2010
+ ];
2011
+ let endReg = null;
2012
+ let start = -1;
2013
+ for (const [lineId, line] of lines.entries()) if (endReg === null) for (const [startReg, end] of regionRegexps) {
2014
+ const match = line.trim().match(startReg);
2015
+ if (match && match[1] === regionName) {
2016
+ start = lineId + 1;
2017
+ endReg = end;
2018
+ break;
2019
+ }
2020
+ }
2021
+ else if (endReg.test(line.trim())) return {
2022
+ start,
2023
+ end: lineId,
2024
+ regexp: endReg
2025
+ };
2026
+ return null;
2027
+ }
2028
+ const reMonacoWrite = /^\{monaco-write\}/;
2029
+ /**
2030
+ * format: ">>> /path/to/file.extension#region language meta..."
2031
+ * where #region, language and meta are optional
2032
+ * meta should starts with {
2033
+ * lang can contain special characters like C++, C#, F#, etc.
2034
+ * path can be relative to the current file or absolute
2035
+ * file extension is optional
2036
+ * path can contain spaces and dots
2037
+ *
2038
+ * captures: ['/path/to/file.extension', '#region', 'language', '{meta}']
2039
+ */
2040
+ function transformSnippet({ s, slide, options }) {
2041
+ const watchFiles = options.data.watchFiles;
2042
+ const dir = path.dirname(slide.source?.filepath ?? options.entry ?? options.userRoot);
2043
+ s.replace(
2044
+ // eslint-disable-next-line regexp/no-super-linear-backtracking
2045
+ /^<<<\s*(\S.*?)(#[\w-]+)?\s*(?:\s(\S+?))?\s*(\{.*)?$/gm,
2046
+ (full, filepath = "", regionName = "", lang = "", meta = "") => {
2047
+ const src = slash(/^@\//.test(filepath) ? path.resolve(options.userRoot, filepath.slice(2)) : path.resolve(dir, filepath));
2048
+ meta = meta.trim();
2049
+ lang = lang.trim();
2050
+ lang = lang || path.extname(filepath).slice(1);
2051
+ const isAFile = fs$1.statSync(src).isFile();
2052
+ if (!fs$1.existsSync(src) || !isAFile) throw new Error(isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`);
2053
+ let content = fs$1.readFileSync(src, "utf8");
2054
+ if (regionName) {
2055
+ const lines = content.split(/\r?\n/);
2056
+ const region = findRegion(lines, regionName.slice(1));
2057
+ if (region) content = dedent(lines.slice(region.start, region.end).filter((line) => !region.regexp.test(line.trim())).join("\n"));
2058
+ }
2059
+ if (meta.match(reMonacoWrite)) {
2060
+ monacoWriterWhitelist.add(filepath);
2061
+ lang = lang.trim();
2062
+ meta = meta.replace(reMonacoWrite, "").trim() || "{}";
2063
+ const encoded = lz.compressToBase64(content);
2064
+ return `<Monaco writable=${JSON.stringify(filepath)} code-lz="${encoded}" lang="${lang}" v-bind="${meta}" />`;
2065
+ } else {
2066
+ watchFiles[src] ??= new Set();
2067
+ watchFiles[src].add(slide.index);
2068
+ }
2069
+ return `\`\`\`${lang} ${meta}\n${content}\n\`\`\``;
2070
+ }
2071
+ );
2072
+ }
2073
+
2074
+ //#endregion
2075
+ //#region node/syntax/transform/index.ts
2076
+ async function getMarkdownTransformers(options) {
2077
+ const extras = await setupTransformers(options.roots);
2078
+ return [
2079
+ ...extras.pre,
2080
+ transformSnippet,
2081
+ options.data.config.highlighter === "shiki" && transformMagicMove,
2082
+ ...extras.preCodeblock,
2083
+ transformMermaid,
2084
+ transformPlantUml,
2085
+ options.data.features.monaco && transformMonaco,
2086
+ ...extras.postCodeblock,
2087
+ transformCodeWrapper,
2088
+ options.data.features.katex && transformKaTexWrapper,
2089
+ transformPageCSS,
2090
+ transformSlotSugar,
2091
+ ...extras.post
2092
+ ];
2093
+ }
2094
+
2095
+ //#endregion
2096
+ //#region node/vite/markdown.ts
2097
+ async function createMarkdownPlugin(options, { markdown: mdOptions }) {
2098
+ const markdownTransformMap = new Map();
2099
+ const transformers = await getMarkdownTransformers(options);
2100
+ return Markdown({
2101
+ include: [/\.md$/],
2102
+ wrapperClasses: "",
2103
+ headEnabled: false,
2104
+ frontmatter: false,
2105
+ escapeCodeTagInterpolation: false,
2106
+ markdownItOptions: {
2107
+ quotes: "\"\"''",
2108
+ html: true,
2109
+ xhtmlOut: true,
2110
+ linkify: true,
2111
+ ...mdOptions?.markdownItOptions
2112
+ },
2113
+ ...mdOptions,
2114
+ async markdownItSetup(md) {
2115
+ await useMarkdownItPlugins(md, options, markdownTransformMap);
2116
+ await mdOptions?.markdownItSetup?.(md);
2117
+ },
2118
+ transforms: {
2119
+ ...mdOptions?.transforms,
2120
+ async before(code, id) {
2121
+ if (options.data.markdownFiles[id]) return "";
2122
+ code = await mdOptions?.transforms?.before?.(code, id) ?? code;
2123
+ const match = id.match(regexSlideSourceId);
2124
+ if (!match) return code;
2125
+ const s = new MagicString(code);
2126
+ markdownTransformMap.set(id, s);
2127
+ const ctx = {
2128
+ s,
2129
+ slide: options.data.slides[+match[1] - 1],
2130
+ options
2131
+ };
2132
+ for (const transformer of transformers) {
2133
+ if (!transformer) continue;
2134
+ await transformer(ctx);
2135
+ if (!ctx.s.isEmpty()) ctx.s.commit();
2136
+ }
2137
+ return s.toString();
2138
+ }
2139
+ }
2140
+ });
2141
+ }
2142
+
2143
+ //#endregion
2144
+ //#region node/vite/monacoTypes.ts
2145
+ function createMonacoTypesLoader({ userRoot, utils }) {
2146
+ return {
2147
+ name: "slidev:monaco-types-loader",
2148
+ resolveId(id) {
2149
+ if (id.startsWith("/@slidev-monaco-types/")) return id;
2150
+ return null;
2151
+ },
2152
+ async load(id) {
2153
+ if (!id.startsWith("/@slidev-monaco-types/")) return null;
2154
+ const url = new URL(id, "http://localhost");
2155
+ if (url.pathname === "/@slidev-monaco-types/resolve") {
2156
+ const query = new URLSearchParams(url.search);
2157
+ const pkg = query.get("pkg");
2158
+ const importer = query.get("importer") ?? userRoot;
2159
+ const pkgJsonPath = await findDepPkgJsonPath(pkg, importer);
2160
+ if (!pkgJsonPath) throw new Error(`Package "${pkg}" not found in "${importer}"`);
2161
+ const root = slash(dirname(pkgJsonPath));
2162
+ const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, "utf-8"));
2163
+ let deps = Object.keys(pkgJson.dependencies ?? {});
2164
+ deps = deps.filter((pkg$1) => !utils.isMonacoTypesIgnored(pkg$1));
2165
+ return [`import "/@slidev-monaco-types/load?${new URLSearchParams({
2166
+ root,
2167
+ name: pkgJson.name
2168
+ })}"`, ...deps.map((dep) => `import "/@slidev-monaco-types/resolve?${new URLSearchParams({
2169
+ pkg: dep,
2170
+ importer: root
2171
+ })}"`)].join("\n");
2172
+ }
2173
+ if (url.pathname === "/@slidev-monaco-types/load") {
2174
+ const query = new URLSearchParams(url.search);
2175
+ const root = query.get("root");
2176
+ const name = query.get("name");
2177
+ const files = await fg([
2178
+ "**/*.ts",
2179
+ "**/*.mts",
2180
+ "**/*.cts",
2181
+ "package.json"
2182
+ ], {
2183
+ cwd: root,
2184
+ followSymbolicLinks: true,
2185
+ ignore: ["**/node_modules/**"]
2186
+ });
2187
+ if (!files.length) return "/** No files found **/";
2188
+ return ["import { addFile } from \"@slidev/client/setup/monaco.ts\"", ...files.map((file) => `addFile(() => import(${JSON.stringify(`${toAtFS(resolve(root, file))}?monaco-types&raw`)}), ${JSON.stringify(`node_modules/${name}/${file}`)})`)].join("\n");
2189
+ }
2190
+ }
2191
+ };
2192
+ }
2193
+
2194
+ //#endregion
2195
+ //#region node/vite/remoteAssets.ts
2196
+ async function createRemoteAssetsPlugin({ data: { config }, mode }, pluginOptions) {
2197
+ if (!(config.remoteAssets === true || config.remoteAssets === mode)) return;
2198
+ const { VitePluginRemoteAssets, DefaultRules } = await import("vite-plugin-remote-assets");
2199
+ return VitePluginRemoteAssets({
2200
+ resolveMode: (id) => id.endsWith("index.html") ? "relative" : "@fs",
2201
+ awaitDownload: mode === "build",
2202
+ ...pluginOptions.remoteAssets,
2203
+ rules: [
2204
+ ...DefaultRules,
2205
+ {
2206
+ match: /\b(https?:\/\/image.unsplash\.com.*?)(?=[`'")\]])/gi,
2207
+ ext: ".png"
2208
+ },
2209
+ ...pluginOptions.remoteAssets?.rules ?? []
2210
+ ]
2211
+ });
2212
+ }
2213
+
2214
+ //#endregion
2215
+ //#region node/integrations/drawings.ts
2216
+ function resolveDrawingsDir(options) {
2217
+ return options.data.config.drawings.persist ? resolve(dirname(options.entry), options.data.config.drawings.persist) : void 0;
2218
+ }
2219
+ async function loadDrawings(options) {
2220
+ const dir = resolveDrawingsDir(options);
2221
+ if (!dir || !existsSync(dir)) return {};
2222
+ const files = await fg("*.svg", {
2223
+ onlyFiles: true,
2224
+ cwd: dir,
2225
+ absolute: true,
2226
+ suppressErrors: true
2227
+ });
2228
+ const obj = {};
2229
+ await Promise.all(files.map(async (path$1) => {
2230
+ const num = +basename(path$1, ".svg");
2231
+ if (Number.isNaN(num)) return;
2232
+ const content = await fs.readFile(path$1, "utf8");
2233
+ const lines = content.split(/\n/g);
2234
+ obj[num.toString()] = lines.slice(1, -1).join("\n");
2235
+ }));
2236
+ return obj;
2237
+ }
2238
+ async function writeDrawings(options, drawing) {
2239
+ const dir = resolveDrawingsDir(options);
2240
+ if (!dir) return;
2241
+ const width = options.data.config.canvasWidth;
2242
+ const height = Math.round(width / options.data.config.aspectRatio);
2243
+ const SVG_HEAD = `<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">`;
2244
+ await fs.mkdir(dir, { recursive: true });
2245
+ return Promise.all(Object.entries(drawing).map(async ([key, value]) => {
2246
+ if (!value) return;
2247
+ const svg = `${SVG_HEAD}\n${value}\n</svg>`;
2248
+ await fs.writeFile(join(dir, `${key}.svg`), svg, "utf-8");
2249
+ }));
2250
+ }
2251
+
2252
+ //#endregion
2253
+ //#region node/integrations/snapshots.ts
2254
+ function resolveSnapshotsDir(options) {
2255
+ return resolve(dirname(options.entry), ".slidev/snapshots");
2256
+ }
2257
+ async function loadSnapshots(options) {
2258
+ const dir = resolveSnapshotsDir(options);
2259
+ const file = join(dir, "snapshots.json");
2260
+ if (!dir || !existsSync(file)) return {};
2261
+ return JSON.parse(await fs.readFile(file, "utf8"));
2262
+ }
2263
+ async function writeSnapshots(options, data) {
2264
+ const dir = resolveSnapshotsDir(options);
2265
+ if (!dir) return;
2266
+ await fs.mkdir(dir, { recursive: true });
2267
+ await fs.writeFile(join(dir, "snapshots.json"), JSON.stringify(data, null, 2), "utf-8");
2268
+ }
2269
+
2270
+ //#endregion
2271
+ //#region node/vite/serverRef.ts
2272
+ async function createServerRefPlugin(options, pluginOptions) {
2273
+ return ServerRef({
2274
+ debug: false,
2275
+ state: {
2276
+ sync: false,
2277
+ nav: {
2278
+ page: 0,
2279
+ clicks: 0
2280
+ },
2281
+ drawings: await loadDrawings(options),
2282
+ snapshots: await loadSnapshots(options),
2283
+ ...pluginOptions.serverRef?.state
2284
+ },
2285
+ onChanged(key, data, patch, timestamp) {
2286
+ pluginOptions.serverRef?.onChanged?.(key, data, patch, timestamp);
2287
+ if (options.data.config.drawings.persist && key === "drawings") writeDrawings(options, patch ?? data);
2288
+ if (key === "snapshots") writeSnapshots(options, data);
2289
+ }
2290
+ });
2291
+ }
2292
+
2293
+ //#endregion
2294
+ //#region node/vite/staticCopy.ts
2295
+ async function createStaticCopyPlugin({ themeRoots, addonRoots }, pluginOptions) {
2296
+ const publicDirs = [...themeRoots, ...addonRoots].map((i) => join(i, "public")).filter(existsSync);
2297
+ if (!publicDirs.length) return;
2298
+ const { viteStaticCopy } = await import("vite-plugin-static-copy");
2299
+ return viteStaticCopy({
2300
+ silent: true,
2301
+ targets: publicDirs.map((dir) => ({
2302
+ src: `${dir}/*`,
2303
+ dest: "theme"
2304
+ })),
2305
+ ...pluginOptions.staticCopy
2306
+ });
2307
+ }
2308
+
2309
+ //#endregion
2310
+ //#region node/setups/unocss.ts
2311
+ async function setupUnocss({ clientRoot, roots, data, utils }) {
2312
+ async function loadFileConfigs(root) {
2313
+ return (await Promise.all([resolve(root, "uno.config.ts"), resolve(root, "unocss.config.ts")].map(async (i) => {
2314
+ if (!existsSync(i)) return void 0;
2315
+ const loaded = await loadModule(i);
2316
+ return "default" in loaded ? loaded.default : loaded;
2317
+ }))).filter((x) => !!x);
2318
+ }
2319
+ const configs = [
2320
+ { presets: [presetIcons({
2321
+ collectionsNodeResolvePath: utils.iconsResolvePath,
2322
+ collections: { slidev: { logo: () => readFileSync(resolve(clientRoot, "assets/logo.svg"), "utf-8") } }
2323
+ })] },
2324
+ ...await loadFileConfigs(clientRoot),
2325
+ ...await loadSetups(roots, "unocss.ts", [], loadFileConfigs)
2326
+ ].filter(Boolean);
2327
+ const config = mergeConfigs(configs);
2328
+ config.theme ||= {};
2329
+ config.theme.fontFamily ||= {};
2330
+ config.theme.fontFamily.sans ||= data.config.fonts.sans.join(",");
2331
+ config.theme.fontFamily.mono ||= data.config.fonts.mono.join(",");
2332
+ config.theme.fontFamily.serif ||= data.config.fonts.serif.join(",");
2333
+ return config;
2334
+ }
2335
+
2336
+ //#endregion
2337
+ //#region node/vite/unocss.ts
2338
+ async function createUnocssPlugin(options, pluginOptions) {
2339
+ return UnoCSS({
2340
+ configFile: false,
2341
+ ...await setupUnocss(options),
2342
+ ...pluginOptions.unocss
2343
+ });
2344
+ }
2345
+
2346
+ //#endregion
2347
+ //#region node/vite/userPlugins.ts
2348
+ async function createUserVitePlugins(options) {
2349
+ const createPluginTasks = options.roots.map(async (root) => {
2350
+ const modulePath = path.join(root, "setup", "vite-plugins.ts");
2351
+ if (existsSync(modulePath)) {
2352
+ const module = await loadModule(modulePath);
2353
+ return module.default(options);
2354
+ }
2355
+ return [];
2356
+ });
2357
+ return (await Promise.all(createPluginTasks)).flatMap((p) => p);
2358
+ }
2359
+
2360
+ //#endregion
2361
+ //#region node/vite/vue.ts
2362
+ const customElements = new Set([
2363
+ "annotation",
2364
+ "math",
2365
+ "menclose",
2366
+ "mfrac",
2367
+ "mglyph",
2368
+ "mi",
2369
+ "mlabeledtr",
2370
+ "mn",
2371
+ "mo",
2372
+ "mover",
2373
+ "mpadded",
2374
+ "mphantom",
2375
+ "mroot",
2376
+ "mrow",
2377
+ "mspace",
2378
+ "msqrt",
2379
+ "mstyle",
2380
+ "msub",
2381
+ "msubsup",
2382
+ "msup",
2383
+ "mtable",
2384
+ "mtd",
2385
+ "mtext",
2386
+ "mtr",
2387
+ "munder",
2388
+ "munderover",
2389
+ "semantics"
2390
+ ]);
2391
+ async function createVuePlugin(_options, pluginOptions) {
2392
+ const { vue: vueOptions = {}, vuejsx: vuejsxOptions = {} } = pluginOptions;
2393
+ const VuePlugin = Vue({
2394
+ include: [
2395
+ /\.vue$/,
2396
+ /\.vue\?vue/,
2397
+ /\.vue\?v=/,
2398
+ /\.md$/,
2399
+ /\.md\?vue/
2400
+ ],
2401
+ exclude: [],
2402
+ ...vueOptions,
2403
+ template: {
2404
+ ...vueOptions?.template,
2405
+ compilerOptions: {
2406
+ ...vueOptions?.template?.compilerOptions,
2407
+ isCustomElement(tag) {
2408
+ return customElements.has(tag) || vueOptions?.template?.compilerOptions?.isCustomElement?.(tag);
2409
+ }
2410
+ }
2411
+ }
2412
+ });
2413
+ const VueJsxPlugin = VueJsx(vuejsxOptions);
2414
+ return [VueJsxPlugin, VuePlugin];
2415
+ }
2416
+
2417
+ //#endregion
2418
+ //#region node/vite/index.ts
2419
+ function ViteSlidevPlugin(options, pluginOptions = {}, serverOptions = {}) {
2420
+ return Promise.all([
2421
+ createSlidesLoader(options, serverOptions),
2422
+ createMarkdownPlugin(options, pluginOptions),
2423
+ createLayoutWrapperPlugin(options),
2424
+ createContextInjectionPlugin(),
2425
+ createVuePlugin(options, pluginOptions),
2426
+ createHmrPatchPlugin(),
2427
+ createComponentsPlugin(options, pluginOptions),
2428
+ createIconsPlugin(options, pluginOptions),
2429
+ createRemoteAssetsPlugin(options, pluginOptions),
2430
+ createServerRefPlugin(options, pluginOptions),
2431
+ createConfigPlugin(options),
2432
+ createMonacoTypesLoader(options),
2433
+ createMonacoWriterPlugin(options),
2434
+ createVueCompilerFlagsPlugin(options),
2435
+ createUnocssPlugin(options, pluginOptions),
2436
+ createStaticCopyPlugin(options, pluginOptions),
2437
+ createInspectPlugin(options, pluginOptions),
2438
+ createUserVitePlugins(options)
2439
+ ]);
2440
+ }
2441
+
2442
+ //#endregion
2443
+ //#region node/commands/shared.ts
2444
+ const sharedMd = MarkdownIt({ html: true });
2445
+ sharedMd.use(MarkdownItLink);
2446
+ function getSlideTitle(data) {
2447
+ const tokens = sharedMd.parseInline(data.config.title, {});
2448
+ const title = stringifyMarkdownTokens(tokens);
2449
+ const slideTitle = data.config.titleTemplate.replace("%s", title);
2450
+ return slideTitle === "Slidev - Slidev" ? "Slidev" : slideTitle;
2451
+ }
2452
+ async function resolveViteConfigs(options, baseConfig, overrideConfigs, command, serverOptions) {
2453
+ const configEnv = {
2454
+ mode: command === "build" ? "production" : "development",
2455
+ command
2456
+ };
2457
+ const files = options.roots.map((i) => join(i, "vite.config.ts"));
2458
+ for (const file of files) {
2459
+ if (!existsSync(file)) continue;
2460
+ const viteConfig = await loadConfigFromFile(configEnv, file);
2461
+ if (!viteConfig?.config) continue;
2462
+ baseConfig = mergeConfig(baseConfig, viteConfig.config);
2463
+ }
2464
+ baseConfig = mergeConfig(baseConfig, overrideConfigs);
2465
+ baseConfig = mergeConfig(baseConfig, {
2466
+ configFile: false,
2467
+ root: options.userRoot,
2468
+ plugins: await ViteSlidevPlugin(options, baseConfig.slidev, serverOptions),
2469
+ define: { __VUE_PROD_DEVTOOLS__: false }
2470
+ });
2471
+ return baseConfig;
2472
+ }
2473
+
2474
+ //#endregion
2475
+ export { ViteSlidevPlugin, createDataUtils, getThemeMeta, loadSetups, parser$1 as parser, resolveAddons, resolveOptions, resolveTheme, resolveViteConfigs, updateFrontmatterPatch, version };