@slidev/cli 0.49.29 → 0.50.0-beta.10
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.
- package/README.md +1 -1
- package/dist/{build-2WDSCT4J.js → build-E2JY62WB.js} +6 -7
- package/dist/{chunk-YP37OZJY.js → chunk-Q74EQR62.js} +1147 -1086
- package/dist/{chunk-IVWMFGB5.js → chunk-T7CH4MWU.js} +1 -1
- package/dist/cli.js +21 -27
- package/dist/{export-FTRUCBWA.js → export-I2C456L6.js} +10 -12
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -4
- package/package.json +39 -40
- package/template.md +5 -7
- package/dist/chunk-6DS3IPOB.js +0 -31
- package/dist/markdown-it-prism-P475G4NP.js +0 -107
- package/dist/{chunk-HOVIRHCR.js → chunk-UNQ5DBLZ.js} +6 -6
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
escapeVueInCode,
|
|
3
|
-
getCodeBlocks,
|
|
4
|
-
normalizeRangeStr
|
|
5
|
-
} from "./chunk-6DS3IPOB.js";
|
|
6
1
|
import {
|
|
7
2
|
createResolver,
|
|
8
3
|
getRoots,
|
|
@@ -11,10 +6,79 @@ import {
|
|
|
11
6
|
resolveImportPath,
|
|
12
7
|
resolveImportUrl,
|
|
13
8
|
toAtFS
|
|
14
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-UNQ5DBLZ.js";
|
|
10
|
+
|
|
11
|
+
// package.json
|
|
12
|
+
var version = "0.50.0-beta.10";
|
|
13
|
+
|
|
14
|
+
// node/integrations/themes.ts
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import fs from "fs-extra";
|
|
17
|
+
import { satisfies } from "semver";
|
|
18
|
+
var officialThemes = {
|
|
19
|
+
"none": "",
|
|
20
|
+
"default": "@slidev/theme-default",
|
|
21
|
+
"seriph": "@slidev/theme-seriph",
|
|
22
|
+
"apple-basic": "@slidev/theme-apple-basic",
|
|
23
|
+
"shibainu": "@slidev/theme-shibainu",
|
|
24
|
+
"bricks": "@slidev/theme-bricks"
|
|
25
|
+
};
|
|
26
|
+
var resolveTheme = createResolver("theme", officialThemes);
|
|
27
|
+
async function getThemeMeta(name, root) {
|
|
28
|
+
const path4 = join(root, "package.json");
|
|
29
|
+
if (!fs.existsSync(path4))
|
|
30
|
+
return {};
|
|
31
|
+
const { slidev = {}, engines = {} } = await fs.readJSON(path4);
|
|
32
|
+
if (engines.slidev && !satisfies(version, engines.slidev, { includePrerelease: true }))
|
|
33
|
+
throw new Error(`[slidev] theme "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
|
|
34
|
+
return slidev;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// node/parser.ts
|
|
38
|
+
import * as parser from "@slidev/parser/fs";
|
|
39
|
+
|
|
40
|
+
// node/options.ts
|
|
41
|
+
import path3 from "node:path";
|
|
42
|
+
import { uniq as uniq5 } from "@antfu/utils";
|
|
43
|
+
import Debug from "debug";
|
|
44
|
+
import fg4 from "fast-glob";
|
|
45
|
+
import mm from "micromatch";
|
|
46
|
+
|
|
47
|
+
// node/integrations/addons.ts
|
|
48
|
+
import { resolve } from "node:path";
|
|
49
|
+
import fs2 from "fs-extra";
|
|
50
|
+
import { satisfies as satisfies2 } from "semver";
|
|
51
|
+
async function resolveAddons(addonsInConfig) {
|
|
52
|
+
const { userRoot, userPkgJson } = await getRoots();
|
|
53
|
+
const resolved = [];
|
|
54
|
+
const resolveAddonNameAndRoot = createResolver("addon", {});
|
|
55
|
+
async function resolveAddon(name, parent) {
|
|
56
|
+
const [, pkgRoot] = await resolveAddonNameAndRoot(name, parent);
|
|
57
|
+
if (!pkgRoot)
|
|
58
|
+
return;
|
|
59
|
+
resolved.push(pkgRoot);
|
|
60
|
+
const { slidev = {}, engines = {} } = await fs2.readJSON(resolve(pkgRoot, "package.json"));
|
|
61
|
+
if (engines.slidev && !satisfies2(version, engines.slidev, { includePrerelease: true }))
|
|
62
|
+
throw new Error(`[slidev] addon "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
|
|
63
|
+
if (Array.isArray(slidev.addons))
|
|
64
|
+
await Promise.all(slidev.addons.map((addon) => resolveAddon(addon, pkgRoot)));
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(addonsInConfig))
|
|
67
|
+
await Promise.all(addonsInConfig.map((addon) => resolveAddon(addon, userRoot)));
|
|
68
|
+
if (Array.isArray(userPkgJson.slidev?.addons))
|
|
69
|
+
await Promise.all(userPkgJson.slidev.addons.map((addon) => resolveAddon(addon, userRoot)));
|
|
70
|
+
return resolved;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// node/setups/indexHtml.ts
|
|
74
|
+
import { existsSync as existsSync8, readFileSync as readFileSync2 } from "node:fs";
|
|
75
|
+
import { join as join13 } from "node:path";
|
|
76
|
+
import { slash as slash4 } from "@antfu/utils";
|
|
77
|
+
import { white, yellow as yellow2 } from "kolorist";
|
|
78
|
+
import { escapeHtml } from "markdown-it/lib/common/utils.mjs";
|
|
15
79
|
|
|
16
80
|
// node/commands/shared.ts
|
|
17
|
-
import { existsSync as
|
|
81
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
18
82
|
import { join as join12 } from "node:path";
|
|
19
83
|
import MarkdownIt from "markdown-it";
|
|
20
84
|
import { loadConfigFromFile, mergeConfig as mergeConfig2 } from "vite";
|
|
@@ -45,12 +109,12 @@ function MarkdownItLink(md) {
|
|
|
45
109
|
|
|
46
110
|
// node/utils.ts
|
|
47
111
|
import { fileURLToPath } from "node:url";
|
|
112
|
+
import { createJiti } from "jiti";
|
|
48
113
|
import YAML from "yaml";
|
|
49
|
-
import createJiti from "jiti";
|
|
50
114
|
var jiti;
|
|
51
115
|
function loadModule(absolutePath) {
|
|
52
116
|
jiti ??= createJiti(fileURLToPath(import.meta.url));
|
|
53
|
-
return jiti(absolutePath);
|
|
117
|
+
return jiti.import(absolutePath);
|
|
54
118
|
}
|
|
55
119
|
function stringifyMarkdownTokens(tokens) {
|
|
56
120
|
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(" ");
|
|
@@ -94,13 +158,13 @@ function updateFrontmatterPatch(slide, frontmatter) {
|
|
|
94
158
|
}
|
|
95
159
|
}
|
|
96
160
|
function getBodyJson(req) {
|
|
97
|
-
return new Promise((
|
|
161
|
+
return new Promise((resolve9, reject) => {
|
|
98
162
|
let body = "";
|
|
99
163
|
req.on("data", (chunk) => body += chunk);
|
|
100
164
|
req.on("error", reject);
|
|
101
165
|
req.on("end", () => {
|
|
102
166
|
try {
|
|
103
|
-
|
|
167
|
+
resolve9(JSON.parse(body) || {});
|
|
104
168
|
} catch (e) {
|
|
105
169
|
reject(e);
|
|
106
170
|
}
|
|
@@ -110,13 +174,122 @@ function getBodyJson(req) {
|
|
|
110
174
|
|
|
111
175
|
// node/vite/compilerFlagsVue.ts
|
|
112
176
|
import { objectEntries } from "@antfu/utils";
|
|
177
|
+
function createVueCompilerFlagsPlugin(options) {
|
|
178
|
+
const define = objectEntries(options.utils.define);
|
|
179
|
+
return {
|
|
180
|
+
name: "slidev:flags",
|
|
181
|
+
enforce: "pre",
|
|
182
|
+
transform(code, id) {
|
|
183
|
+
if (!id.match(/\.vue($|\?)/) && !id.includes("?vue&"))
|
|
184
|
+
return;
|
|
185
|
+
const original = code;
|
|
186
|
+
define.forEach(([from, to]) => {
|
|
187
|
+
code = code.replaceAll(from, to);
|
|
188
|
+
});
|
|
189
|
+
if (original !== code)
|
|
190
|
+
return code;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// node/vite/components.ts
|
|
196
|
+
import { join as join2 } from "node:path";
|
|
197
|
+
import IconsResolver from "unplugin-icons/resolver";
|
|
198
|
+
import Components from "unplugin-vue-components/vite";
|
|
199
|
+
function createComponentsPlugin({ clientRoot, roots }, pluginOptions) {
|
|
200
|
+
return Components({
|
|
201
|
+
extensions: ["vue", "md", "js", "ts", "jsx", "tsx"],
|
|
202
|
+
dirs: [
|
|
203
|
+
join2(clientRoot, "builtin"),
|
|
204
|
+
...roots.map((i) => join2(i, "components"))
|
|
205
|
+
],
|
|
206
|
+
include: [/\.vue$/, /\.vue\?vue/, /\.vue\?v=/, /\.md$/, /\.md\?vue/],
|
|
207
|
+
exclude: [],
|
|
208
|
+
resolvers: [
|
|
209
|
+
IconsResolver({
|
|
210
|
+
prefix: "",
|
|
211
|
+
customCollections: Object.keys(pluginOptions.icons?.customCollections || [])
|
|
212
|
+
})
|
|
213
|
+
],
|
|
214
|
+
dts: false,
|
|
215
|
+
...pluginOptions.components
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// node/vite/common.ts
|
|
220
|
+
var regexSlideReqPath = /^\/__slidev\/slides\/(\d+)\.json$/;
|
|
221
|
+
var regexSlideFacadeId = /^\/@slidev\/slides\/(\d+)\/(md|frontmatter)($|\?)/;
|
|
222
|
+
var regexSlideSourceId = /__slidev_(\d+)\.(md|frontmatter)$/;
|
|
223
|
+
var templateInjectionMarker = "/* @slidev-injection */";
|
|
224
|
+
var templateImportContextUtils = `import { useSlideContext as _useSlideContext, frontmatterToProps as _frontmatterToProps } from "@slidev/client/context.ts"`;
|
|
225
|
+
var templateInitContext = `const { $slidev, $nav, $clicksContext, $clicks, $page, $renderContext, $frontmatter } = _useSlideContext()`;
|
|
226
|
+
|
|
227
|
+
// node/vite/contextInjection.ts
|
|
228
|
+
function createContextInjectionPlugin() {
|
|
229
|
+
return {
|
|
230
|
+
name: "slidev:context-injection",
|
|
231
|
+
async transform(code, id) {
|
|
232
|
+
if (!id.endsWith(".vue") || id.includes("/@slidev/client/") || id.includes("/packages/client/"))
|
|
233
|
+
return;
|
|
234
|
+
if (code.includes(templateInjectionMarker) || code.includes("useSlideContext()"))
|
|
235
|
+
return code;
|
|
236
|
+
const imports = [
|
|
237
|
+
templateImportContextUtils,
|
|
238
|
+
templateInitContext,
|
|
239
|
+
templateInjectionMarker
|
|
240
|
+
];
|
|
241
|
+
const matchScript = code.match(/<script((?!setup).)*(setup)?.*>/);
|
|
242
|
+
if (matchScript && matchScript[2]) {
|
|
243
|
+
return code.replace(/(<script.*>)/g, `$1
|
|
244
|
+
${imports.join("\n")}
|
|
245
|
+
`);
|
|
246
|
+
} else if (matchScript && !matchScript[2]) {
|
|
247
|
+
const matchExport = code.match(/export\s+default\s+\{/);
|
|
248
|
+
if (matchExport) {
|
|
249
|
+
const exportIndex = (matchExport.index || 0) + matchExport[0].length;
|
|
250
|
+
let component = code.slice(exportIndex);
|
|
251
|
+
component = component.slice(0, component.indexOf("</script>"));
|
|
252
|
+
const scriptIndex = (matchScript.index || 0) + matchScript[0].length;
|
|
253
|
+
const provideImport = '\nimport { injectionSlidevContext } from "@slidev/client/constants.ts"\n';
|
|
254
|
+
code = `${code.slice(0, scriptIndex)}${provideImport}${code.slice(scriptIndex)}`;
|
|
255
|
+
let injectIndex = exportIndex + provideImport.length;
|
|
256
|
+
let injectObject = "$slidev: { from: injectionSlidevContext },";
|
|
257
|
+
const matchInject = component.match(/.*inject\s*:\s*([[{])/);
|
|
258
|
+
if (matchInject) {
|
|
259
|
+
injectIndex += (matchInject.index || 0) + matchInject[0].length;
|
|
260
|
+
if (matchInject[1] === "[") {
|
|
261
|
+
let injects = component.slice((matchInject.index || 0) + matchInject[0].length);
|
|
262
|
+
const injectEndIndex = injects.indexOf("]");
|
|
263
|
+
injects = injects.slice(0, injectEndIndex);
|
|
264
|
+
injectObject += injects.split(",").map((inject) => `${inject}: {from: ${inject}}`).join(",");
|
|
265
|
+
return `${code.slice(0, injectIndex - 1)}{
|
|
266
|
+
${injectObject}
|
|
267
|
+
}${code.slice(injectIndex + injectEndIndex + 1)}`;
|
|
268
|
+
} else {
|
|
269
|
+
return `${code.slice(0, injectIndex)}
|
|
270
|
+
${injectObject}
|
|
271
|
+
${code.slice(injectIndex)}`;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return `${code.slice(0, injectIndex)}
|
|
275
|
+
inject: { ${injectObject} },
|
|
276
|
+
${code.slice(injectIndex)}`;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return `<script setup>
|
|
280
|
+
${imports.join("\n")}
|
|
281
|
+
</script>
|
|
282
|
+
${code}`;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
}
|
|
113
286
|
|
|
114
287
|
// node/vite/extendConfig.ts
|
|
115
|
-
import { join } from "node:path";
|
|
288
|
+
import { join as join3 } from "node:path";
|
|
116
289
|
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
|
|
117
|
-
import { mergeConfig } from "vite";
|
|
118
290
|
import { slash, uniq } from "@antfu/utils";
|
|
119
291
|
import { createResolve } from "mlly";
|
|
292
|
+
import { mergeConfig } from "vite";
|
|
120
293
|
var INCLUDE_GLOBAL = [
|
|
121
294
|
"@typescript/ata",
|
|
122
295
|
"file-saver",
|
|
@@ -124,7 +297,8 @@ var INCLUDE_GLOBAL = [
|
|
|
124
297
|
"prettier",
|
|
125
298
|
"recordrtc",
|
|
126
299
|
"typescript",
|
|
127
|
-
"yaml"
|
|
300
|
+
"yaml",
|
|
301
|
+
"html-to-image"
|
|
128
302
|
];
|
|
129
303
|
var INCLUDE_LOCAL = INCLUDE_GLOBAL.map((i) => `@slidev/cli > @slidev/client > ${i}`);
|
|
130
304
|
var EXCLUDE_GLOBAL = [
|
|
@@ -173,7 +347,7 @@ function createConfigPlugin(options) {
|
|
|
173
347
|
name: "slidev:config",
|
|
174
348
|
async config(config) {
|
|
175
349
|
const injection = {
|
|
176
|
-
define:
|
|
350
|
+
define: options.utils.define,
|
|
177
351
|
resolve: {
|
|
178
352
|
alias: [
|
|
179
353
|
{
|
|
@@ -226,7 +400,7 @@ function createConfigPlugin(options) {
|
|
|
226
400
|
])
|
|
227
401
|
}
|
|
228
402
|
},
|
|
229
|
-
publicDir:
|
|
403
|
+
publicDir: join3(options.userRoot, "public"),
|
|
230
404
|
build: {
|
|
231
405
|
rollupOptions: {
|
|
232
406
|
output: {
|
|
@@ -253,21 +427,18 @@ function createConfigPlugin(options) {
|
|
|
253
427
|
}
|
|
254
428
|
}
|
|
255
429
|
}
|
|
256
|
-
}
|
|
430
|
+
},
|
|
431
|
+
cacheDir: isInstalledGlobally.value ? join3(options.cliRoot, "node_modules/.vite") : void 0
|
|
257
432
|
};
|
|
258
433
|
function isSlidevClient(id) {
|
|
259
434
|
return id.includes("/@slidev/") || id.includes("/slidev/packages/client/") || id.includes("/@vueuse/");
|
|
260
435
|
}
|
|
261
|
-
if (isInstalledGlobally.value) {
|
|
262
|
-
injection.cacheDir = join(options.cliRoot, "node_modules/.vite");
|
|
263
|
-
injection.root = options.cliRoot;
|
|
264
|
-
}
|
|
265
436
|
return mergeConfig(injection, config);
|
|
266
437
|
},
|
|
267
438
|
configureServer(server) {
|
|
268
439
|
return () => {
|
|
269
440
|
server.middlewares.use(async (req, res, next) => {
|
|
270
|
-
if (req.url
|
|
441
|
+
if (req.url === "/index.html") {
|
|
271
442
|
res.setHeader("Content-Type", "text/html");
|
|
272
443
|
res.statusCode = 200;
|
|
273
444
|
res.end(options.utils.indexHtml);
|
|
@@ -279,174 +450,46 @@ function createConfigPlugin(options) {
|
|
|
279
450
|
}
|
|
280
451
|
};
|
|
281
452
|
}
|
|
282
|
-
|
|
453
|
+
|
|
454
|
+
// node/vite/hmrPatch.ts
|
|
455
|
+
function createHmrPatchPlugin() {
|
|
283
456
|
return {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
__SLIDEV_FEATURE_RECORD__: JSON.stringify(options.data.config.record === true || options.data.config.record === options.mode),
|
|
291
|
-
__SLIDEV_FEATURE_PRESENTER__: JSON.stringify(options.data.config.presenter === true || options.data.config.presenter === options.mode),
|
|
292
|
-
__SLIDEV_FEATURE_PRINT__: JSON.stringify(options.mode === "export" || options.mode === "build" && [true, "true", "auto"].includes(options.data.config.download)),
|
|
293
|
-
__SLIDEV_FEATURE_WAKE_LOCK__: JSON.stringify(options.data.config.wakeLock === true || options.data.config.wakeLock === options.mode),
|
|
294
|
-
__SLIDEV_HAS_SERVER__: options.mode !== "build" ? "true" : "false"
|
|
457
|
+
name: "slidev:hmr-patch",
|
|
458
|
+
transform(code, id) {
|
|
459
|
+
if (!id.match(regexSlideSourceId))
|
|
460
|
+
return;
|
|
461
|
+
return code.replace("if (_rerender_only)", "if (false)");
|
|
462
|
+
}
|
|
295
463
|
};
|
|
296
464
|
}
|
|
297
465
|
|
|
298
|
-
// node/vite/
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
return
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if (id.match(/\.vue($|\?)/)) {
|
|
307
|
-
const original = code;
|
|
308
|
-
define.forEach(([from, to]) => {
|
|
309
|
-
code = code.replace(new RegExp(from, "g"), to);
|
|
310
|
-
});
|
|
311
|
-
if (original !== code)
|
|
312
|
-
return code;
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
];
|
|
466
|
+
// node/vite/icons.ts
|
|
467
|
+
import Icons from "unplugin-icons/vite";
|
|
468
|
+
function createIconsPlugin(options, pluginOptions) {
|
|
469
|
+
return Icons({
|
|
470
|
+
defaultClass: "slidev-icon",
|
|
471
|
+
collectionsNodeResolvePath: options.utils.iconsResolvePath,
|
|
472
|
+
...pluginOptions.icons
|
|
473
|
+
});
|
|
317
474
|
}
|
|
318
475
|
|
|
319
|
-
// node/vite/
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
return
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
...roots.map((i) => join2(i, "components"))
|
|
329
|
-
],
|
|
330
|
-
include: [/\.vue$/, /\.vue\?vue/, /\.vue\?v=/, /\.md$/, /\.md\?vue/],
|
|
331
|
-
exclude: [],
|
|
332
|
-
resolvers: [
|
|
333
|
-
IconsResolver({
|
|
334
|
-
prefix: "",
|
|
335
|
-
customCollections: Object.keys(pluginOptions.icons?.customCollections || [])
|
|
336
|
-
})
|
|
337
|
-
],
|
|
338
|
-
dts: false,
|
|
339
|
-
...pluginOptions.components
|
|
476
|
+
// node/vite/inspect.ts
|
|
477
|
+
async function createInspectPlugin(options, pluginOptions) {
|
|
478
|
+
if (!options.inspect)
|
|
479
|
+
return;
|
|
480
|
+
const { default: PluginInspect } = await import("vite-plugin-inspect");
|
|
481
|
+
return PluginInspect({
|
|
482
|
+
dev: true,
|
|
483
|
+
build: true,
|
|
484
|
+
...pluginOptions.inspect
|
|
340
485
|
});
|
|
341
486
|
}
|
|
342
487
|
|
|
343
|
-
// node/vite/
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
var regexSlideSourceId = /__slidev_(\d+)\.(md|frontmatter)$/;
|
|
347
|
-
var templateInjectionMarker = "/* @slidev-injection */";
|
|
348
|
-
var templateImportContextUtils = `import { useSlideContext as _useSlideContext, frontmatterToProps as _frontmatterToProps } from "@slidev/client/context.ts"`;
|
|
349
|
-
var templateInitContext = `const { $slidev, $nav, $clicksContext, $clicks, $page, $renderContext, $frontmatter } = _useSlideContext()`;
|
|
350
|
-
|
|
351
|
-
// node/vite/contextInjection.ts
|
|
352
|
-
function createContextInjectionPlugin() {
|
|
488
|
+
// node/vite/layoutWrapper.ts
|
|
489
|
+
import { bold, gray, red, yellow } from "kolorist";
|
|
490
|
+
function createLayoutWrapperPlugin({ data, utils }) {
|
|
353
491
|
return {
|
|
354
|
-
name: "slidev:
|
|
355
|
-
async transform(code, id) {
|
|
356
|
-
if (!id.endsWith(".vue") || id.includes("/@slidev/client/") || id.includes("/packages/client/"))
|
|
357
|
-
return;
|
|
358
|
-
if (code.includes(templateInjectionMarker) || code.includes("useSlideContext()"))
|
|
359
|
-
return code;
|
|
360
|
-
const imports = [
|
|
361
|
-
templateImportContextUtils,
|
|
362
|
-
templateInitContext,
|
|
363
|
-
templateInjectionMarker
|
|
364
|
-
];
|
|
365
|
-
const matchScript = code.match(/<script((?!setup).)*(setup)?.*>/);
|
|
366
|
-
if (matchScript && matchScript[2]) {
|
|
367
|
-
return code.replace(/(<script.*>)/g, `$1
|
|
368
|
-
${imports.join("\n")}
|
|
369
|
-
`);
|
|
370
|
-
} else if (matchScript && !matchScript[2]) {
|
|
371
|
-
const matchExport = code.match(/export\s+default\s+\{/);
|
|
372
|
-
if (matchExport) {
|
|
373
|
-
const exportIndex = (matchExport.index || 0) + matchExport[0].length;
|
|
374
|
-
let component = code.slice(exportIndex);
|
|
375
|
-
component = component.slice(0, component.indexOf("</script>"));
|
|
376
|
-
const scriptIndex = (matchScript.index || 0) + matchScript[0].length;
|
|
377
|
-
const provideImport = '\nimport { injectionSlidevContext } from "@slidev/client/constants.ts"\n';
|
|
378
|
-
code = `${code.slice(0, scriptIndex)}${provideImport}${code.slice(scriptIndex)}`;
|
|
379
|
-
let injectIndex = exportIndex + provideImport.length;
|
|
380
|
-
let injectObject = "$slidev: { from: injectionSlidevContext },";
|
|
381
|
-
const matchInject = component.match(/.*inject\s*:\s*([[{])/);
|
|
382
|
-
if (matchInject) {
|
|
383
|
-
injectIndex += (matchInject.index || 0) + matchInject[0].length;
|
|
384
|
-
if (matchInject[1] === "[") {
|
|
385
|
-
let injects = component.slice((matchInject.index || 0) + matchInject[0].length);
|
|
386
|
-
const injectEndIndex = injects.indexOf("]");
|
|
387
|
-
injects = injects.slice(0, injectEndIndex);
|
|
388
|
-
injectObject += injects.split(",").map((inject) => `${inject}: {from: ${inject}}`).join(",");
|
|
389
|
-
return `${code.slice(0, injectIndex - 1)}{
|
|
390
|
-
${injectObject}
|
|
391
|
-
}${code.slice(injectIndex + injectEndIndex + 1)}`;
|
|
392
|
-
} else {
|
|
393
|
-
return `${code.slice(0, injectIndex)}
|
|
394
|
-
${injectObject}
|
|
395
|
-
${code.slice(injectIndex)}`;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
return `${code.slice(0, injectIndex)}
|
|
399
|
-
inject: { ${injectObject} },
|
|
400
|
-
${code.slice(injectIndex)}`;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
return `<script setup>
|
|
404
|
-
${imports.join("\n")}
|
|
405
|
-
</script>
|
|
406
|
-
${code}`;
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
// node/vite/hmrPatch.ts
|
|
412
|
-
function createHmrPatchPlugin() {
|
|
413
|
-
return {
|
|
414
|
-
name: "slidev:slide-transform:post",
|
|
415
|
-
transform(code, id) {
|
|
416
|
-
if (!id.match(regexSlideSourceId))
|
|
417
|
-
return;
|
|
418
|
-
return code.replace("if (_rerender_only)", "if (false)");
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// node/vite/icons.ts
|
|
424
|
-
import Icons from "unplugin-icons/vite";
|
|
425
|
-
function createIconsPlugin(options, pluginOptions) {
|
|
426
|
-
return Icons({
|
|
427
|
-
defaultClass: "slidev-icon",
|
|
428
|
-
collectionsNodeResolvePath: options.utils.iconsResolvePath,
|
|
429
|
-
...pluginOptions.icons
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// node/vite/inspect.ts
|
|
434
|
-
async function createInspectPlugin(options, pluginOptions) {
|
|
435
|
-
if (!options.inspect)
|
|
436
|
-
return;
|
|
437
|
-
const { default: PluginInspect } = await import("vite-plugin-inspect");
|
|
438
|
-
return PluginInspect({
|
|
439
|
-
dev: true,
|
|
440
|
-
build: true,
|
|
441
|
-
...pluginOptions.inspect
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// node/vite/layoutWrapper.ts
|
|
446
|
-
import { bold, gray, red, yellow } from "kolorist";
|
|
447
|
-
function createLayoutWrapperPlugin({ data, utils }) {
|
|
448
|
-
return {
|
|
449
|
-
name: "slidev:layout-wrapper",
|
|
492
|
+
name: "slidev:layout-wrapper",
|
|
450
493
|
async transform(code, id) {
|
|
451
494
|
const match = id.match(regexSlideSourceId);
|
|
452
495
|
if (!match)
|
|
@@ -455,7 +498,7 @@ function createLayoutWrapperPlugin({ data, utils }) {
|
|
|
455
498
|
if (type !== "md")
|
|
456
499
|
return;
|
|
457
500
|
const index = +no - 1;
|
|
458
|
-
const layouts =
|
|
501
|
+
const layouts = utils.getLayouts();
|
|
459
502
|
const rawLayoutName = data.slides[index]?.frontmatter?.layout ?? data.slides[0]?.frontmatter?.defaults?.layout;
|
|
460
503
|
let layoutName = rawLayoutName || (index === 0 ? "cover" : "default");
|
|
461
504
|
if (!layouts[layoutName]) {
|
|
@@ -541,14 +584,14 @@ console.warn('/@slidev/titles.md is deprecated, import from #slidev/title-render
|
|
|
541
584
|
|
|
542
585
|
// node/virtual/global-layers.ts
|
|
543
586
|
import { existsSync } from "node:fs";
|
|
544
|
-
import { join as
|
|
587
|
+
import { join as join4 } from "node:path";
|
|
545
588
|
var templateGlobalLayers = {
|
|
546
589
|
id: `/@slidev/global-layers`,
|
|
547
590
|
getContent({ roots }) {
|
|
548
591
|
const imports = [];
|
|
549
592
|
let n = 0;
|
|
550
593
|
function getComponent(names) {
|
|
551
|
-
const components = roots.flatMap((root) => names.map((name) =>
|
|
594
|
+
const components = roots.flatMap((root) => names.map((name) => join4(root, name))).filter((i) => existsSync(i));
|
|
552
595
|
imports.push(components.map((path4, i) => `import __n${n}_${i} from '${toAtFS(path4)}'`).join("\n"));
|
|
553
596
|
const render = components.map((_, i) => `h(__n${n}_${i})`).join(",");
|
|
554
597
|
n++;
|
|
@@ -569,28 +612,6 @@ var templateGlobalLayers = {
|
|
|
569
612
|
}
|
|
570
613
|
};
|
|
571
614
|
|
|
572
|
-
// node/virtual/nav-controls.ts
|
|
573
|
-
import { existsSync as existsSync2 } from "node:fs";
|
|
574
|
-
import { join as join4 } from "node:path";
|
|
575
|
-
var templateNavControls = {
|
|
576
|
-
id: "/@slidev/custom-nav-controls",
|
|
577
|
-
getContent({ roots }) {
|
|
578
|
-
const components = roots.flatMap((root) => {
|
|
579
|
-
return [
|
|
580
|
-
join4(root, "custom-nav-controls.vue"),
|
|
581
|
-
join4(root, "CustomNavControls.vue")
|
|
582
|
-
];
|
|
583
|
-
}).filter((i) => existsSync2(i));
|
|
584
|
-
const imports = components.map((i, idx) => `import __n${idx} from '${toAtFS(i)}'`).join("\n");
|
|
585
|
-
const render = components.map((i, idx) => `h(__n${idx})`).join(",");
|
|
586
|
-
return `${imports}
|
|
587
|
-
import { h } from 'vue'
|
|
588
|
-
export default {
|
|
589
|
-
render: () => [${render}],
|
|
590
|
-
}`;
|
|
591
|
-
}
|
|
592
|
-
};
|
|
593
|
-
|
|
594
615
|
// node/virtual/layouts.ts
|
|
595
616
|
import { objectMap } from "@antfu/utils";
|
|
596
617
|
var templateLayouts = {
|
|
@@ -614,7 +635,7 @@ ${Object.entries(layouts).map(([k, v]) => `"${k}": ${v}`).join(",\n")}
|
|
|
614
635
|
};
|
|
615
636
|
|
|
616
637
|
// node/virtual/monaco-deps.ts
|
|
617
|
-
import { resolve } from "node:path";
|
|
638
|
+
import { resolve as resolve2 } from "node:path";
|
|
618
639
|
import { uniq as uniq2 } from "@antfu/utils";
|
|
619
640
|
var templateMonacoRunDeps = {
|
|
620
641
|
id: "/@slidev/monaco-run-deps",
|
|
@@ -622,7 +643,7 @@ var templateMonacoRunDeps = {
|
|
|
622
643
|
if (!data.features.monaco)
|
|
623
644
|
return "";
|
|
624
645
|
const deps = uniq2(data.features.monaco.deps.concat(data.config.monacoTypesAdditionalPackages));
|
|
625
|
-
const importerPath =
|
|
646
|
+
const importerPath = resolve2(userRoot, "./snippets/__importer__.ts");
|
|
626
647
|
let result = "";
|
|
627
648
|
for (let i = 0; i < deps.length; i++) {
|
|
628
649
|
const specifier = deps[i];
|
|
@@ -643,9 +664,9 @@ var templateMonacoRunDeps = {
|
|
|
643
664
|
|
|
644
665
|
// node/virtual/monaco-types.ts
|
|
645
666
|
import { builtinModules } from "node:module";
|
|
646
|
-
import { join as join5, resolve as
|
|
647
|
-
import fg from "fast-glob";
|
|
667
|
+
import { join as join5, resolve as resolve3 } from "node:path";
|
|
648
668
|
import { uniq as uniq3 } from "@antfu/utils";
|
|
669
|
+
import fg from "fast-glob";
|
|
649
670
|
var templateMonacoTypes = {
|
|
650
671
|
id: "/@slidev/monaco-types",
|
|
651
672
|
getContent: async ({ userRoot, data, utils }) => {
|
|
@@ -655,7 +676,7 @@ var templateMonacoTypes = {
|
|
|
655
676
|
const files = await fg(["**/*.ts", "**/*.mts", "**/*.cts"], { cwd: typesRoot });
|
|
656
677
|
let result = 'import { addFile } from "@slidev/client/setup/monaco.ts"\n';
|
|
657
678
|
for (const file of files) {
|
|
658
|
-
const url = `${toAtFS(
|
|
679
|
+
const url = `${toAtFS(resolve3(typesRoot, file))}?monaco-types&raw`;
|
|
659
680
|
result += `addFile(() => import(${JSON.stringify(url)}), ${JSON.stringify(file)})
|
|
660
681
|
`;
|
|
661
682
|
}
|
|
@@ -688,15 +709,37 @@ var templateMonacoTypes = {
|
|
|
688
709
|
}
|
|
689
710
|
};
|
|
690
711
|
|
|
712
|
+
// node/virtual/nav-controls.ts
|
|
713
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
714
|
+
import { join as join6 } from "node:path";
|
|
715
|
+
var templateNavControls = {
|
|
716
|
+
id: "/@slidev/custom-nav-controls",
|
|
717
|
+
getContent({ roots }) {
|
|
718
|
+
const components = roots.flatMap((root) => {
|
|
719
|
+
return [
|
|
720
|
+
join6(root, "custom-nav-controls.vue"),
|
|
721
|
+
join6(root, "CustomNavControls.vue")
|
|
722
|
+
];
|
|
723
|
+
}).filter((i) => existsSync2(i));
|
|
724
|
+
const imports = components.map((i, idx) => `import __n${idx} from '${toAtFS(i)}'`).join("\n");
|
|
725
|
+
const render = components.map((i, idx) => `h(__n${idx})`).join(",");
|
|
726
|
+
return `${imports}
|
|
727
|
+
import { h } from 'vue'
|
|
728
|
+
export default {
|
|
729
|
+
render: () => [${render}],
|
|
730
|
+
}`;
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
|
|
691
734
|
// node/virtual/setups.ts
|
|
692
735
|
import { existsSync as existsSync3 } from "node:fs";
|
|
693
|
-
import { join as
|
|
736
|
+
import { join as join7 } from "node:path";
|
|
694
737
|
function createSetupTemplate(name) {
|
|
695
738
|
return {
|
|
696
739
|
id: `/@slidev/setups/${name}`,
|
|
697
740
|
getContent({ roots }) {
|
|
698
741
|
const setups = roots.flatMap((i) => {
|
|
699
|
-
const path4 =
|
|
742
|
+
const path4 = join7(i, "setup", name);
|
|
700
743
|
return [".ts", ".mts", ".js", ".mjs"].map((ext) => path4 + ext);
|
|
701
744
|
}).filter((i) => existsSync3(i));
|
|
702
745
|
const imports = [];
|
|
@@ -820,13 +863,13 @@ ${slides.join(",\n")}
|
|
|
820
863
|
};
|
|
821
864
|
|
|
822
865
|
// node/virtual/styles.ts
|
|
823
|
-
import { join as join7 } from "node:path";
|
|
824
866
|
import { existsSync as existsSync4 } from "node:fs";
|
|
867
|
+
import { join as join8 } from "node:path";
|
|
825
868
|
var templateStyle = {
|
|
826
869
|
id: "/@slidev/styles",
|
|
827
870
|
async getContent({ data, clientRoot, roots }) {
|
|
828
871
|
function resolveUrlOfClient(name) {
|
|
829
|
-
return toAtFS(
|
|
872
|
+
return toAtFS(join8(clientRoot, name));
|
|
830
873
|
}
|
|
831
874
|
const imports = [
|
|
832
875
|
`import "${resolveUrlOfClient("styles/vars.css")}"`,
|
|
@@ -837,11 +880,11 @@ var templateStyle = {
|
|
|
837
880
|
];
|
|
838
881
|
for (const root of roots) {
|
|
839
882
|
const styles = [
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
883
|
+
join8(root, "styles", "index.ts"),
|
|
884
|
+
join8(root, "styles", "index.js"),
|
|
885
|
+
join8(root, "styles", "index.css"),
|
|
886
|
+
join8(root, "styles.css"),
|
|
887
|
+
join8(root, "style.css")
|
|
845
888
|
];
|
|
846
889
|
for (const style of styles) {
|
|
847
890
|
if (existsSync4(style)) {
|
|
@@ -917,290 +960,40 @@ var templates = [
|
|
|
917
960
|
templateLegacyTitles
|
|
918
961
|
];
|
|
919
962
|
|
|
920
|
-
// node/
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
// node/integrations/themes.ts
|
|
931
|
-
import { join as join8 } from "node:path";
|
|
932
|
-
import fs from "fs-extra";
|
|
933
|
-
import { satisfies } from "semver";
|
|
934
|
-
|
|
935
|
-
// package.json
|
|
936
|
-
var version = "0.49.29";
|
|
937
|
-
|
|
938
|
-
// node/integrations/themes.ts
|
|
939
|
-
var officialThemes = {
|
|
940
|
-
"none": "",
|
|
941
|
-
"default": "@slidev/theme-default",
|
|
942
|
-
"seriph": "@slidev/theme-seriph",
|
|
943
|
-
"apple-basic": "@slidev/theme-apple-basic",
|
|
944
|
-
"shibainu": "@slidev/theme-shibainu",
|
|
945
|
-
"bricks": "@slidev/theme-bricks"
|
|
946
|
-
};
|
|
947
|
-
var resolveTheme = createResolver("theme", officialThemes);
|
|
948
|
-
async function getThemeMeta(name, root) {
|
|
949
|
-
const path4 = join8(root, "package.json");
|
|
950
|
-
if (!fs.existsSync(path4))
|
|
951
|
-
return {};
|
|
952
|
-
const { slidev = {}, engines = {} } = await fs.readJSON(path4);
|
|
953
|
-
if (engines.slidev && !satisfies(version, engines.slidev, { includePrerelease: true }))
|
|
954
|
-
throw new Error(`[slidev] theme "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
|
|
955
|
-
return slidev;
|
|
963
|
+
// node/vite/loaders.ts
|
|
964
|
+
function renderNote(text = "") {
|
|
965
|
+
let clickCount = 0;
|
|
966
|
+
const html = sharedMd.render(
|
|
967
|
+
text.replace(/\[click(?::(\d+))?\]/gi, (_, count = 1) => {
|
|
968
|
+
clickCount += Number(count);
|
|
969
|
+
return `<span class="slidev-note-click-mark" data-clicks="${clickCount}"></span>`;
|
|
970
|
+
})
|
|
971
|
+
);
|
|
972
|
+
return html;
|
|
956
973
|
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
async function resolveAddons(addonsInConfig) {
|
|
963
|
-
const { userRoot, userPkgJson } = await getRoots();
|
|
964
|
-
const resolved = [];
|
|
965
|
-
const resolveAddonNameAndRoot = createResolver("addon", {});
|
|
966
|
-
async function resolveAddon(name, parent) {
|
|
967
|
-
const [, pkgRoot] = await resolveAddonNameAndRoot(name, parent);
|
|
968
|
-
if (!pkgRoot)
|
|
969
|
-
return;
|
|
970
|
-
resolved.push(pkgRoot);
|
|
971
|
-
const { slidev = {}, engines = {} } = await fs2.readJSON(resolve3(pkgRoot, "package.json"));
|
|
972
|
-
if (engines.slidev && !satisfies2(version, engines.slidev, { includePrerelease: true }))
|
|
973
|
-
throw new Error(`[slidev] addon "${name}" requires Slidev version range "${engines.slidev}" but found "${version}"`);
|
|
974
|
-
if (Array.isArray(slidev.addons))
|
|
975
|
-
await Promise.all(slidev.addons.map((addon) => resolveAddon(addon, pkgRoot)));
|
|
976
|
-
}
|
|
977
|
-
if (Array.isArray(addonsInConfig))
|
|
978
|
-
await Promise.all(addonsInConfig.map((addon) => resolveAddon(addon, userRoot)));
|
|
979
|
-
if (Array.isArray(userPkgJson.slidev?.addons))
|
|
980
|
-
await Promise.all(userPkgJson.slidev.addons.map((addon) => resolveAddon(addon, userRoot)));
|
|
981
|
-
return resolved;
|
|
974
|
+
function withRenderedNote(data) {
|
|
975
|
+
return {
|
|
976
|
+
...data,
|
|
977
|
+
noteHTML: renderNote(data?.note)
|
|
978
|
+
};
|
|
982
979
|
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
const ret = await setup(...args);
|
|
999
|
-
if (ret)
|
|
1000
|
-
returns.push(ret);
|
|
980
|
+
function createSlidesLoader(options, serverOptions) {
|
|
981
|
+
const { data, mode, utils } = options;
|
|
982
|
+
const hmrSlidesIndexes = /* @__PURE__ */ new Set();
|
|
983
|
+
let server;
|
|
984
|
+
let skipHmr = null;
|
|
985
|
+
let sourceIds = resolveSourceIds(data);
|
|
986
|
+
function resolveSourceIds(data2) {
|
|
987
|
+
const ids = {
|
|
988
|
+
md: [],
|
|
989
|
+
frontmatter: []
|
|
990
|
+
};
|
|
991
|
+
for (const type of ["md", "frontmatter"]) {
|
|
992
|
+
for (let i = 0; i < data2.slides.length; i++) {
|
|
993
|
+
ids[type].push(`${data2.slides[i].source.filepath}__slidev_${i + 1}.${type}`);
|
|
994
|
+
}
|
|
1001
995
|
}
|
|
1002
|
-
|
|
1003
|
-
returns.push(...extraLoader(root));
|
|
1004
|
-
}
|
|
1005
|
-
return returns;
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
// node/setups/shiki.ts
|
|
1009
|
-
var cachedRoots;
|
|
1010
|
-
var cachedShiki;
|
|
1011
|
-
async function setupShiki(roots) {
|
|
1012
|
-
if (cachedRoots === roots)
|
|
1013
|
-
return cachedShiki;
|
|
1014
|
-
cachedShiki?.shiki.dispose();
|
|
1015
|
-
const options = await loadSetups(
|
|
1016
|
-
roots,
|
|
1017
|
-
"shiki.ts",
|
|
1018
|
-
[{
|
|
1019
|
-
/** @deprecated */
|
|
1020
|
-
async loadTheme(path4) {
|
|
1021
|
-
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.");
|
|
1022
|
-
return JSON.parse(await fs4.readFile(path4, "utf-8"));
|
|
1023
|
-
}
|
|
1024
|
-
}]
|
|
1025
|
-
);
|
|
1026
|
-
const mergedOptions = Object.assign({}, ...options);
|
|
1027
|
-
if ("theme" in mergedOptions && "themes" in mergedOptions)
|
|
1028
|
-
delete mergedOptions.theme;
|
|
1029
|
-
if (mergedOptions.theme && typeof mergedOptions.theme !== "string" && !mergedOptions.theme.name && !mergedOptions.theme.tokenColors) {
|
|
1030
|
-
mergedOptions.themes = mergedOptions.theme;
|
|
1031
|
-
delete mergedOptions.theme;
|
|
1032
|
-
}
|
|
1033
|
-
if (!mergedOptions.theme && !mergedOptions.themes) {
|
|
1034
|
-
mergedOptions.themes = {
|
|
1035
|
-
dark: "vitesse-dark",
|
|
1036
|
-
light: "vitesse-light"
|
|
1037
|
-
};
|
|
1038
|
-
}
|
|
1039
|
-
if (mergedOptions.themes)
|
|
1040
|
-
mergedOptions.defaultColor = false;
|
|
1041
|
-
const shiki = await createHighlighter({
|
|
1042
|
-
...mergedOptions,
|
|
1043
|
-
langs: mergedOptions.langs ?? Object.keys(bundledLanguages),
|
|
1044
|
-
themes: "themes" in mergedOptions ? Object.values(mergedOptions.themes) : [mergedOptions.theme]
|
|
1045
|
-
});
|
|
1046
|
-
cachedRoots = roots;
|
|
1047
|
-
return cachedShiki = {
|
|
1048
|
-
shiki,
|
|
1049
|
-
shikiOptions: mergedOptions
|
|
1050
|
-
};
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
// node/setups/indexHtml.ts
|
|
1054
|
-
import { existsSync as existsSync5, readFileSync } from "node:fs";
|
|
1055
|
-
import { join as join9 } from "node:path";
|
|
1056
|
-
import { slash as slash2 } from "@antfu/utils";
|
|
1057
|
-
import { white, yellow as yellow2 } from "kolorist";
|
|
1058
|
-
import { escapeHtml } from "markdown-it/lib/common/utils.mjs";
|
|
1059
|
-
function toAttrValue(unsafe) {
|
|
1060
|
-
return JSON.stringify(escapeHtml(String(unsafe)));
|
|
1061
|
-
}
|
|
1062
|
-
function setupIndexHtml({ mode, entry, clientRoot, userRoot, roots, data }) {
|
|
1063
|
-
let main = readFileSync(join9(clientRoot, "index.html"), "utf-8");
|
|
1064
|
-
let head = "";
|
|
1065
|
-
let body = "";
|
|
1066
|
-
const { info, author, keywords } = data.headmatter;
|
|
1067
|
-
head += [
|
|
1068
|
-
`<meta name="slidev:version" content="${version}">`,
|
|
1069
|
-
mode === "dev" && `<meta charset="slidev:entry" content="${slash2(entry)}">`,
|
|
1070
|
-
`<link rel="icon" href="${data.config.favicon}">`,
|
|
1071
|
-
`<title>${getSlideTitle(data)}</title>`,
|
|
1072
|
-
info && `<meta name="description" content=${toAttrValue(info)}>`,
|
|
1073
|
-
author && `<meta name="author" content=${toAttrValue(author)}>`,
|
|
1074
|
-
keywords && `<meta name="keywords" content=${toAttrValue(Array.isArray(keywords) ? keywords.join(", ") : keywords)}>`
|
|
1075
|
-
].filter(Boolean).join("\n");
|
|
1076
|
-
for (const root of roots) {
|
|
1077
|
-
const path4 = join9(root, "index.html");
|
|
1078
|
-
if (!existsSync5(path4))
|
|
1079
|
-
continue;
|
|
1080
|
-
const index = readFileSync(path4, "utf-8");
|
|
1081
|
-
if (root === userRoot && index.includes("<!DOCTYPE")) {
|
|
1082
|
-
console.error(yellow2(`[Slidev] Ignored provided index.html with doctype declaration. (${white(path4)})`));
|
|
1083
|
-
console.error(yellow2("This file may be generated by Slidev, please remove it from your project."));
|
|
1084
|
-
continue;
|
|
1085
|
-
}
|
|
1086
|
-
head += `
|
|
1087
|
-
${(index.match(/<head>([\s\S]*?)<\/head>/i)?.[1] || "").trim()}`;
|
|
1088
|
-
body += `
|
|
1089
|
-
${(index.match(/<body>([\s\S]*?)<\/body>/i)?.[1] || "").trim()}`;
|
|
1090
|
-
}
|
|
1091
|
-
if (data.features.tweet)
|
|
1092
|
-
body += '\n<script async src="https://platform.twitter.com/widgets.js"></script>';
|
|
1093
|
-
if (data.config.fonts.webfonts.length && data.config.fonts.provider !== "none")
|
|
1094
|
-
head += `
|
|
1095
|
-
<link rel="stylesheet" href="${generateGoogleFontsUrl(data.config.fonts)}" type="text/css">`;
|
|
1096
|
-
main = main.replace("__ENTRY__", toAtFS(join9(clientRoot, "main.ts"))).replace("<!-- head -->", head).replace("<!-- body -->", body);
|
|
1097
|
-
return main;
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
// node/options.ts
|
|
1101
|
-
var debug = Debug("slidev:options");
|
|
1102
|
-
async function resolveOptions(entryOptions, mode) {
|
|
1103
|
-
const entry = await resolveEntry(entryOptions.entry);
|
|
1104
|
-
const rootsInfo = await getRoots(entry);
|
|
1105
|
-
const loaded = await parser.load(rootsInfo.userRoot, entry, void 0, mode);
|
|
1106
|
-
let themeRaw = entryOptions.theme || loaded.headmatter.theme;
|
|
1107
|
-
themeRaw = themeRaw === null ? "none" : themeRaw || "default";
|
|
1108
|
-
const [theme, themeRoot] = await resolveTheme(themeRaw, entry);
|
|
1109
|
-
const themeRoots = themeRoot ? [themeRoot] : [];
|
|
1110
|
-
const themeMeta = themeRoot ? await getThemeMeta(theme, themeRoot) : void 0;
|
|
1111
|
-
const config = parser.resolveConfig(loaded.headmatter, themeMeta, entryOptions.entry);
|
|
1112
|
-
const addonRoots = await resolveAddons(config.addons);
|
|
1113
|
-
const roots = uniq5([...themeRoots, ...addonRoots, rootsInfo.userRoot]);
|
|
1114
|
-
debug({
|
|
1115
|
-
...rootsInfo,
|
|
1116
|
-
...entryOptions,
|
|
1117
|
-
config,
|
|
1118
|
-
mode,
|
|
1119
|
-
entry,
|
|
1120
|
-
themeRaw,
|
|
1121
|
-
theme,
|
|
1122
|
-
themeRoots,
|
|
1123
|
-
addonRoots,
|
|
1124
|
-
roots
|
|
1125
|
-
});
|
|
1126
|
-
const data = {
|
|
1127
|
-
...loaded,
|
|
1128
|
-
config,
|
|
1129
|
-
themeMeta
|
|
1130
|
-
};
|
|
1131
|
-
const resolved = {
|
|
1132
|
-
...rootsInfo,
|
|
1133
|
-
...entryOptions,
|
|
1134
|
-
data,
|
|
1135
|
-
mode,
|
|
1136
|
-
entry,
|
|
1137
|
-
themeRaw,
|
|
1138
|
-
theme,
|
|
1139
|
-
themeRoots,
|
|
1140
|
-
addonRoots,
|
|
1141
|
-
roots
|
|
1142
|
-
};
|
|
1143
|
-
return {
|
|
1144
|
-
...resolved,
|
|
1145
|
-
utils: await createDataUtils(resolved)
|
|
1146
|
-
};
|
|
1147
|
-
}
|
|
1148
|
-
async function createDataUtils(resolved) {
|
|
1149
|
-
const monacoTypesIgnorePackagesMatches = (resolved.data.config.monacoTypesIgnorePackages || []).map((i) => mm.matcher(i));
|
|
1150
|
-
let _layouts_cache_time = 0;
|
|
1151
|
-
let _layouts_cache = {};
|
|
1152
|
-
return {
|
|
1153
|
-
...await setupShiki(resolved.roots),
|
|
1154
|
-
indexHtml: setupIndexHtml(resolved),
|
|
1155
|
-
iconsResolvePath: [resolved.clientRoot, ...resolved.roots].reverse(),
|
|
1156
|
-
isMonacoTypesIgnored: (pkg) => monacoTypesIgnorePackagesMatches.some((i) => i(pkg)),
|
|
1157
|
-
getLayouts: () => {
|
|
1158
|
-
const now = Date.now();
|
|
1159
|
-
if (now - _layouts_cache_time < 2e3)
|
|
1160
|
-
return _layouts_cache;
|
|
1161
|
-
const layouts = {};
|
|
1162
|
-
for (const root of [resolved.clientRoot, ...resolved.roots]) {
|
|
1163
|
-
const layoutPaths = fg2.sync("layouts/**/*.{vue,ts}", {
|
|
1164
|
-
cwd: root,
|
|
1165
|
-
absolute: true,
|
|
1166
|
-
suppressErrors: true
|
|
1167
|
-
});
|
|
1168
|
-
for (const layoutPath of layoutPaths) {
|
|
1169
|
-
const layoutName = path.basename(layoutPath).replace(/\.\w+$/, "");
|
|
1170
|
-
layouts[layoutName] = layoutPath;
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
_layouts_cache_time = now;
|
|
1174
|
-
_layouts_cache = layouts;
|
|
1175
|
-
return layouts;
|
|
1176
|
-
}
|
|
1177
|
-
};
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
// node/vite/loaders.ts
|
|
1181
|
-
function renderNote(text = "") {
|
|
1182
|
-
let clickCount = 0;
|
|
1183
|
-
const html = sharedMd.render(
|
|
1184
|
-
text.replace(/\[click(?::(\d+))?\]/gi, (_, count = 1) => {
|
|
1185
|
-
clickCount += Number(count);
|
|
1186
|
-
return `<span class="slidev-note-click-mark" data-clicks="${clickCount}"></span>`;
|
|
1187
|
-
})
|
|
1188
|
-
);
|
|
1189
|
-
return html;
|
|
1190
|
-
}
|
|
1191
|
-
function withRenderedNote(data) {
|
|
1192
|
-
return {
|
|
1193
|
-
...data,
|
|
1194
|
-
noteHTML: renderNote(data?.note)
|
|
1195
|
-
};
|
|
1196
|
-
}
|
|
1197
|
-
function createSlidesLoader(options, serverOptions) {
|
|
1198
|
-
const hmrSlidesIndexes = /* @__PURE__ */ new Set();
|
|
1199
|
-
let server;
|
|
1200
|
-
let skipHmr = null;
|
|
1201
|
-
const { data, mode, utils } = options;
|
|
1202
|
-
function getSourceId(index, type) {
|
|
1203
|
-
return `${data.slides[index].source.filepath}__slidev_${index + 1}.${type}`;
|
|
996
|
+
return ids;
|
|
1204
997
|
}
|
|
1205
998
|
function updateServerWatcher() {
|
|
1206
999
|
if (!server)
|
|
@@ -1258,11 +1051,11 @@ function createSlidesLoader(options, serverOptions) {
|
|
|
1258
1051
|
fileContent
|
|
1259
1052
|
};
|
|
1260
1053
|
server?.moduleGraph.invalidateModule(
|
|
1261
|
-
server.moduleGraph.getModuleById(
|
|
1054
|
+
server.moduleGraph.getModuleById(sourceIds.md[idx])
|
|
1262
1055
|
);
|
|
1263
1056
|
if (body.frontmatter) {
|
|
1264
1057
|
server?.moduleGraph.invalidateModule(
|
|
1265
|
-
server.moduleGraph.getModuleById(
|
|
1058
|
+
server.moduleGraph.getModuleById(sourceIds.frontmatter[idx])
|
|
1266
1059
|
);
|
|
1267
1060
|
}
|
|
1268
1061
|
}
|
|
@@ -1290,9 +1083,19 @@ function createSlidesLoader(options, serverOptions) {
|
|
|
1290
1083
|
return [];
|
|
1291
1084
|
}
|
|
1292
1085
|
const moduleIds = /* @__PURE__ */ new Set();
|
|
1086
|
+
const newSourceIds = resolveSourceIds(newData);
|
|
1087
|
+
for (const type of ["md", "frontmatter"]) {
|
|
1088
|
+
const old = sourceIds[type];
|
|
1089
|
+
const newIds = newSourceIds[type];
|
|
1090
|
+
for (let i = 0; i < newIds.length; i++) {
|
|
1091
|
+
if (old[i] !== newIds[i]) {
|
|
1092
|
+
moduleIds.add(`${VIRTUAL_SLIDE_PREFIX}${i + 1}/${type}`);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
sourceIds = newSourceIds;
|
|
1293
1097
|
if (data.slides.length !== newData.slides.length) {
|
|
1294
1098
|
moduleIds.add(templateSlides.id);
|
|
1295
|
-
range(newData.slides.length).map((i) => hmrSlidesIndexes.add(i));
|
|
1296
1099
|
}
|
|
1297
1100
|
if (!equal(data.headmatter.defaults, newData.headmatter.defaults)) {
|
|
1298
1101
|
moduleIds.add(templateSlides.id);
|
|
@@ -1336,8 +1139,8 @@ function createSlidesLoader(options, serverOptions) {
|
|
|
1336
1139
|
if (hmrSlidesIndexes.size > 0)
|
|
1337
1140
|
moduleIds.add(templateTitleRendererMd.id);
|
|
1338
1141
|
const vueModules = Array.from(hmrSlidesIndexes).flatMap((idx) => {
|
|
1339
|
-
const frontmatter = ctx.server.moduleGraph.getModuleById(
|
|
1340
|
-
const main = ctx.server.moduleGraph.getModuleById(
|
|
1142
|
+
const frontmatter = ctx.server.moduleGraph.getModuleById(sourceIds.frontmatter[idx]);
|
|
1143
|
+
const main = ctx.server.moduleGraph.getModuleById(sourceIds.md[idx]);
|
|
1341
1144
|
const styles = main ? [...main.clientImportedModules].find((m) => m.id?.includes(`&type=style`)) : void 0;
|
|
1342
1145
|
return [
|
|
1343
1146
|
frontmatter,
|
|
@@ -1374,7 +1177,7 @@ function createSlidesLoader(options, serverOptions) {
|
|
|
1374
1177
|
if (matchFacade) {
|
|
1375
1178
|
const [, no, type] = matchFacade;
|
|
1376
1179
|
const idx = +no - 1;
|
|
1377
|
-
const sourceId = JSON.stringify(
|
|
1180
|
+
const sourceId = JSON.stringify(sourceIds[type][idx]);
|
|
1378
1181
|
return [
|
|
1379
1182
|
`export * from ${sourceId}`,
|
|
1380
1183
|
`export { default } from ${sourceId}`
|
|
@@ -1453,503 +1256,175 @@ function createSlidesLoader(options, serverOptions) {
|
|
|
1453
1256
|
}
|
|
1454
1257
|
|
|
1455
1258
|
// node/vite/markdown.ts
|
|
1456
|
-
import Markdown from "unplugin-vue-markdown/vite";
|
|
1457
1259
|
import MagicString from "magic-string-stack";
|
|
1260
|
+
import Markdown from "unplugin-vue-markdown/vite";
|
|
1458
1261
|
|
|
1459
|
-
//
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1262
|
+
// ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.1.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/image-size/specialCharacters.js
|
|
1263
|
+
var SpecialCharacters;
|
|
1264
|
+
(function(SpecialCharacters2) {
|
|
1265
|
+
SpecialCharacters2[SpecialCharacters2["EXCLAMATION_MARK"] = 33] = "EXCLAMATION_MARK";
|
|
1266
|
+
SpecialCharacters2[SpecialCharacters2["OPENING_BRACKET"] = 91] = "OPENING_BRACKET";
|
|
1267
|
+
SpecialCharacters2[SpecialCharacters2["OPENING_PARENTHESIS"] = 40] = "OPENING_PARENTHESIS";
|
|
1268
|
+
SpecialCharacters2[SpecialCharacters2["WHITESPACE"] = 32] = "WHITESPACE";
|
|
1269
|
+
SpecialCharacters2[SpecialCharacters2["NEW_LINE"] = 10] = "NEW_LINE";
|
|
1270
|
+
SpecialCharacters2[SpecialCharacters2["EQUALS"] = 61] = "EQUALS";
|
|
1271
|
+
SpecialCharacters2[SpecialCharacters2["LOWER_CASE_X"] = 120] = "LOWER_CASE_X";
|
|
1272
|
+
SpecialCharacters2[SpecialCharacters2["NUMBER_ZERO"] = 48] = "NUMBER_ZERO";
|
|
1273
|
+
SpecialCharacters2[SpecialCharacters2["NUMBER_NINE"] = 57] = "NUMBER_NINE";
|
|
1274
|
+
SpecialCharacters2[SpecialCharacters2["PERCENTAGE"] = 37] = "PERCENTAGE";
|
|
1275
|
+
SpecialCharacters2[SpecialCharacters2["CLOSING_PARENTHESIS"] = 41] = "CLOSING_PARENTHESIS";
|
|
1276
|
+
})(SpecialCharacters || (SpecialCharacters = {}));
|
|
1277
|
+
|
|
1278
|
+
// ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.1.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/task-lists/index.js
|
|
1279
|
+
import Token from "markdown-it/lib/token.mjs";
|
|
1280
|
+
var checkboxRegex = /^ *\[([\sx])] /i;
|
|
1281
|
+
function taskLists(md, options = { enabled: false, label: false, lineNumber: false }) {
|
|
1282
|
+
md.core.ruler.after("inline", "task-lists", (state) => processToken(state, options));
|
|
1283
|
+
md.renderer.rules.taskListItemCheckbox = (tokens) => {
|
|
1284
|
+
const token = tokens[0];
|
|
1285
|
+
const checkedAttribute = token.attrGet("checked") ? 'checked="" ' : "";
|
|
1286
|
+
const disabledAttribute = token.attrGet("disabled") ? 'disabled="" ' : "";
|
|
1287
|
+
const line = token.attrGet("line");
|
|
1288
|
+
const idAttribute = `id="${token.attrGet("id")}" `;
|
|
1289
|
+
const dataLineAttribute = line && options.lineNumber ? `data-line="${line}" ` : "";
|
|
1290
|
+
return `<input class="task-list-item-checkbox" type="checkbox" ${checkedAttribute}${disabledAttribute}${dataLineAttribute}${idAttribute}/>`;
|
|
1291
|
+
};
|
|
1292
|
+
md.renderer.rules.taskListItemLabel_close = () => {
|
|
1293
|
+
return "</label>";
|
|
1294
|
+
};
|
|
1295
|
+
md.renderer.rules.taskListItemLabel_open = (tokens) => {
|
|
1296
|
+
const token = tokens[0];
|
|
1297
|
+
const id = token.attrGet("id");
|
|
1298
|
+
return `<label for="${id}">`;
|
|
1467
1299
|
};
|
|
1468
|
-
for (const r of [...returns].reverse()) {
|
|
1469
|
-
if (r.pre)
|
|
1470
|
-
result.pre.push(...r.pre);
|
|
1471
|
-
if (r.preCodeblock)
|
|
1472
|
-
result.preCodeblock.push(...r.preCodeblock);
|
|
1473
|
-
}
|
|
1474
|
-
for (const r of returns) {
|
|
1475
|
-
if (r.postCodeblock)
|
|
1476
|
-
result.postCodeblock.push(...r.postCodeblock);
|
|
1477
|
-
if (r.post)
|
|
1478
|
-
result.post.push(...r.post);
|
|
1479
|
-
}
|
|
1480
|
-
return result;
|
|
1481
1300
|
}
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
reCodeBlock,
|
|
1488
|
-
(full, lang = "", rangeStr = "", options = "", attrs = "", code) => {
|
|
1489
|
-
const ranges = normalizeRangeStr(rangeStr);
|
|
1490
|
-
code = code.trimEnd();
|
|
1491
|
-
options = options.trim() || "{}";
|
|
1492
|
-
return `
|
|
1493
|
-
<CodeBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
|
|
1494
|
-
|
|
1495
|
-
\`\`\`${lang}${attrs}
|
|
1496
|
-
${code}
|
|
1497
|
-
\`\`\`
|
|
1498
|
-
|
|
1499
|
-
</CodeBlockWrapper>`;
|
|
1301
|
+
function processToken(state, options) {
|
|
1302
|
+
const allTokens = state.tokens;
|
|
1303
|
+
for (let i = 2; i < allTokens.length; i++) {
|
|
1304
|
+
if (!isTodoItem(allTokens, i)) {
|
|
1305
|
+
continue;
|
|
1500
1306
|
}
|
|
1501
|
-
|
|
1502
|
-
}
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
(full, start, css, end, index) => {
|
|
1510
|
-
if (codeBlocks.isInsideCodeblocks(index))
|
|
1511
|
-
return full;
|
|
1512
|
-
if (!start.includes("scoped"))
|
|
1513
|
-
start = start.replace("<style", "<style scoped");
|
|
1514
|
-
return `${start}
|
|
1515
|
-
${css}${end}`;
|
|
1307
|
+
todoify(allTokens[i], options);
|
|
1308
|
+
allTokens[i - 2].attrJoin("class", `task-list-item ${options.enabled ? " enabled" : ""}`);
|
|
1309
|
+
const parentToken = findParentToken(allTokens, i - 2);
|
|
1310
|
+
if (parentToken) {
|
|
1311
|
+
const classes = parentToken.attrGet("class") ?? "";
|
|
1312
|
+
if (!classes.match(/(^| )contains-task-list/)) {
|
|
1313
|
+
parentToken.attrJoin("class", "contains-task-list");
|
|
1314
|
+
}
|
|
1516
1315
|
}
|
|
1517
|
-
|
|
1316
|
+
}
|
|
1317
|
+
return false;
|
|
1518
1318
|
}
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
(full, rangeStr = "", options = "", code) => {
|
|
1525
|
-
const ranges = !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
|
|
1526
|
-
code = code.trimEnd();
|
|
1527
|
-
options = options.trim() || "{}";
|
|
1528
|
-
return `<KaTexBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
|
|
1529
|
-
|
|
1530
|
-
$$
|
|
1531
|
-
${code}
|
|
1532
|
-
$$
|
|
1533
|
-
</KaTexBlockWrapper>
|
|
1534
|
-
`;
|
|
1319
|
+
function findParentToken(tokens, index) {
|
|
1320
|
+
const targetLevel = tokens[index].level - 1;
|
|
1321
|
+
for (let currentTokenIndex = index - 1; currentTokenIndex >= 0; currentTokenIndex--) {
|
|
1322
|
+
if (tokens[currentTokenIndex].level === targetLevel) {
|
|
1323
|
+
return tokens[currentTokenIndex];
|
|
1535
1324
|
}
|
|
1536
|
-
|
|
1325
|
+
}
|
|
1326
|
+
return void 0;
|
|
1537
1327
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
import { codeToKeyedTokens } from "shiki-magic-move/core";
|
|
1541
|
-
import lz from "lz-string";
|
|
1542
|
-
var reMagicMoveBlock = /^````(?:md|markdown) magic-move *(\{[^}]*\})?([^ \n]*)\n([\s\S]+?)^````$/gm;
|
|
1543
|
-
function parseLineNumbersOption(options) {
|
|
1544
|
-
return /lines: *true/.test(options) ? true : /lines: *false/.test(options) ? false : void 0;
|
|
1328
|
+
function isTodoItem(tokens, index) {
|
|
1329
|
+
return isInline(tokens[index]) && isParagraph(tokens[index - 1]) && isListItem(tokens[index - 2]) && startsWithTodoMarkdown(tokens[index]);
|
|
1545
1330
|
}
|
|
1546
|
-
function
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
return codeToKeyedTokens(ctx.options.utils.shiki, i[5].trimEnd(), {
|
|
1558
|
-
...ctx.options.utils.shikiOptions,
|
|
1559
|
-
lang: i[1]
|
|
1560
|
-
}, lineNumbers);
|
|
1561
|
-
});
|
|
1562
|
-
const compressed = lz.compressToBase64(JSON.stringify(steps));
|
|
1563
|
-
return `<ShikiMagicMove v-bind="${options}" steps-lz="${compressed}" :step-ranges='${JSON.stringify(ranges)}' />`;
|
|
1564
|
-
}
|
|
1565
|
-
);
|
|
1331
|
+
function todoify(token, options) {
|
|
1332
|
+
if (token.children == null) {
|
|
1333
|
+
return;
|
|
1334
|
+
}
|
|
1335
|
+
const id = generateIdForToken(token);
|
|
1336
|
+
token.children.splice(0, 0, createCheckboxToken(token, options.enabled, id));
|
|
1337
|
+
token.children[1].content = token.children[1].content.replace(checkboxRegex, "");
|
|
1338
|
+
if (options.label) {
|
|
1339
|
+
token.children.splice(1, 0, createLabelBeginToken(id));
|
|
1340
|
+
token.children.push(createLabelEndToken());
|
|
1341
|
+
}
|
|
1566
1342
|
}
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
(full, options = "", code = "") => {
|
|
1574
|
-
code = code.trim();
|
|
1575
|
-
options = options.trim() || "{}";
|
|
1576
|
-
const encoded = lz2.compressToBase64(code);
|
|
1577
|
-
return `<Mermaid code-lz="${encoded}" v-bind="${options}" />`;
|
|
1578
|
-
}
|
|
1579
|
-
);
|
|
1343
|
+
function generateIdForToken(token) {
|
|
1344
|
+
if (token.map) {
|
|
1345
|
+
return `task-item-${token.map[0]}`;
|
|
1346
|
+
} else {
|
|
1347
|
+
return `task-item-${Math.ceil(Math.random() * (1e4 * 1e3) - 1e3)}`;
|
|
1348
|
+
}
|
|
1580
1349
|
}
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
import lz3 from "lz-string";
|
|
1584
|
-
function transformMonaco(ctx) {
|
|
1585
|
-
const enabled = ctx.options.data.config.monaco === true || ctx.options.data.config.monaco === ctx.options.mode;
|
|
1350
|
+
function createCheckboxToken(token, enabled, id) {
|
|
1351
|
+
const checkbox = new Token("taskListItemCheckbox", "", 0);
|
|
1586
1352
|
if (!enabled) {
|
|
1587
|
-
|
|
1588
|
-
return;
|
|
1353
|
+
checkbox.attrSet("disabled", "true");
|
|
1589
1354
|
}
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1355
|
+
if (token.map) {
|
|
1356
|
+
checkbox.attrSet("line", token.map[0].toString());
|
|
1357
|
+
}
|
|
1358
|
+
checkbox.attrSet("id", id);
|
|
1359
|
+
const checkboxRegexResult = checkboxRegex.exec(token.content);
|
|
1360
|
+
const isChecked = checkboxRegexResult?.[1].toLowerCase() === "x";
|
|
1361
|
+
if (isChecked) {
|
|
1362
|
+
checkbox.attrSet("checked", "true");
|
|
1363
|
+
}
|
|
1364
|
+
return checkbox;
|
|
1365
|
+
}
|
|
1366
|
+
function createLabelBeginToken(id) {
|
|
1367
|
+
const labelBeginToken = new Token("taskListItemLabel_open", "", 1);
|
|
1368
|
+
labelBeginToken.attrSet("id", id);
|
|
1369
|
+
return labelBeginToken;
|
|
1370
|
+
}
|
|
1371
|
+
function createLabelEndToken() {
|
|
1372
|
+
return new Token("taskListItemLabel_close", "", -1);
|
|
1373
|
+
}
|
|
1374
|
+
function isInline(token) {
|
|
1375
|
+
return token.type === "inline";
|
|
1376
|
+
}
|
|
1377
|
+
function isParagraph(token) {
|
|
1378
|
+
return token.type === "paragraph_open";
|
|
1379
|
+
}
|
|
1380
|
+
function isListItem(token) {
|
|
1381
|
+
return token.type === "list_item_open";
|
|
1382
|
+
}
|
|
1383
|
+
function startsWithTodoMarkdown(token) {
|
|
1384
|
+
return checkboxRegex.test(token.content);
|
|
1618
1385
|
}
|
|
1619
1386
|
|
|
1620
|
-
// node/syntax/
|
|
1621
|
-
import
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1387
|
+
// node/syntax/markdown-it/index.ts
|
|
1388
|
+
import MarkdownItFootnote from "markdown-it-footnote";
|
|
1389
|
+
import MarkdownItMdc from "markdown-it-mdc";
|
|
1390
|
+
|
|
1391
|
+
// node/setups/load.ts
|
|
1392
|
+
import { resolve as resolve4 } from "node:path";
|
|
1393
|
+
import { deepMergeWithArray } from "@antfu/utils";
|
|
1394
|
+
import fs3 from "fs-extra";
|
|
1395
|
+
async function loadSetups(roots, filename, args, extraLoader) {
|
|
1396
|
+
const returns = [];
|
|
1397
|
+
for (const root of roots) {
|
|
1398
|
+
const path4 = resolve4(root, "setup", filename);
|
|
1399
|
+
if (fs3.existsSync(path4)) {
|
|
1400
|
+
const { default: setup } = await loadModule(path4);
|
|
1401
|
+
const ret = await setup(...args);
|
|
1402
|
+
if (ret)
|
|
1403
|
+
returns.push(ret);
|
|
1630
1404
|
}
|
|
1631
|
-
|
|
1405
|
+
if (extraLoader)
|
|
1406
|
+
returns.push(...await extraLoader(root));
|
|
1407
|
+
}
|
|
1408
|
+
return returns;
|
|
1632
1409
|
}
|
|
1633
1410
|
|
|
1634
|
-
// node/
|
|
1635
|
-
function
|
|
1636
|
-
const
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
const newline = linesWithNewline[i + 1] || "";
|
|
1642
|
-
lines.push(line + newline);
|
|
1643
|
-
}
|
|
1644
|
-
let prevSlot = false;
|
|
1645
|
-
let offset = 0;
|
|
1646
|
-
lines.forEach((line) => {
|
|
1647
|
-
const start = offset;
|
|
1648
|
-
offset += line.length;
|
|
1649
|
-
if (codeBlocks.isInsideCodeblocks(offset))
|
|
1650
|
-
return;
|
|
1651
|
-
const match = line.match(/^::\s*([\w.\-:]+)\s*::(\s*)$/);
|
|
1652
|
-
if (match) {
|
|
1653
|
-
ctx.s.overwrite(start, offset - match[2].length, `${prevSlot ? "\n\n</template>\n" : "\n"}<template v-slot:${match[1]}="slotProps">
|
|
1654
|
-
`);
|
|
1655
|
-
prevSlot = true;
|
|
1656
|
-
}
|
|
1657
|
-
});
|
|
1658
|
-
if (prevSlot)
|
|
1659
|
-
ctx.s.append("\n\n</template>");
|
|
1411
|
+
// node/setups/katex.ts
|
|
1412
|
+
async function setupKatex(roots) {
|
|
1413
|
+
const options = await loadSetups(roots, "katex.ts", []);
|
|
1414
|
+
return Object.assign(
|
|
1415
|
+
{ strict: false },
|
|
1416
|
+
...options
|
|
1417
|
+
);
|
|
1660
1418
|
}
|
|
1661
1419
|
|
|
1662
|
-
// node/syntax/
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
import path2 from "node:path";
|
|
1671
|
-
var monacoWriterWhitelist = /* @__PURE__ */ new Set();
|
|
1672
|
-
function createMonacoWriterPlugin({ userRoot }) {
|
|
1673
|
-
return {
|
|
1674
|
-
name: "slidev:monaco-write",
|
|
1675
|
-
apply: "serve",
|
|
1676
|
-
configureServer(server) {
|
|
1677
|
-
server.ws.on("connection", (socket) => {
|
|
1678
|
-
socket.on("message", async (data) => {
|
|
1679
|
-
let json;
|
|
1680
|
-
try {
|
|
1681
|
-
json = JSON.parse(data.toString());
|
|
1682
|
-
} catch {
|
|
1683
|
-
return;
|
|
1684
|
-
}
|
|
1685
|
-
if (json.type === "custom" && json.event === "slidev:monaco-write") {
|
|
1686
|
-
const { file, content } = json.data;
|
|
1687
|
-
if (!monacoWriterWhitelist.has(file)) {
|
|
1688
|
-
console.error(`[Slidev] Unauthorized file write: ${file}`);
|
|
1689
|
-
return;
|
|
1690
|
-
}
|
|
1691
|
-
const filepath = path2.join(userRoot, file);
|
|
1692
|
-
console.log("[Slidev] Writing file:", filepath);
|
|
1693
|
-
await fs5.writeFile(filepath, content, "utf-8");
|
|
1694
|
-
}
|
|
1695
|
-
});
|
|
1696
|
-
});
|
|
1697
|
-
}
|
|
1698
|
-
};
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1701
|
-
// node/syntax/transform/snippet.ts
|
|
1702
|
-
function dedent(text) {
|
|
1703
|
-
const lines = text.split("\n");
|
|
1704
|
-
const minIndentLength = lines.reduce((acc, line) => {
|
|
1705
|
-
for (let i = 0; i < line.length; i++) {
|
|
1706
|
-
if (line[i] !== " " && line[i] !== " ")
|
|
1707
|
-
return Math.min(i, acc);
|
|
1708
|
-
}
|
|
1709
|
-
return acc;
|
|
1710
|
-
}, Number.POSITIVE_INFINITY);
|
|
1711
|
-
if (minIndentLength < Number.POSITIVE_INFINITY)
|
|
1712
|
-
return lines.map((x) => x.slice(minIndentLength)).join("\n");
|
|
1713
|
-
return text;
|
|
1714
|
-
}
|
|
1715
|
-
function testLine(line, regexp, regionName, end = false) {
|
|
1716
|
-
const [full, tag, name] = regexp.exec(line.trim()) || [];
|
|
1717
|
-
return full && tag && name === regionName && tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/);
|
|
1718
|
-
}
|
|
1719
|
-
function findRegion(lines, regionName) {
|
|
1720
|
-
const regionRegexps = [
|
|
1721
|
-
/^\/\/ ?#?((?:end)?region) ([\w*-]+)$/,
|
|
1722
|
-
// javascript, typescript, java
|
|
1723
|
-
/^\/\* ?#((?:end)?region) ([\w*-]+) ?\*\/$/,
|
|
1724
|
-
// css, less, scss
|
|
1725
|
-
/^#pragma ((?:end)?region) ([\w*-]+)$/,
|
|
1726
|
-
// C, C++
|
|
1727
|
-
/^<!-- #?((?:end)?region) ([\w*-]+) -->$/,
|
|
1728
|
-
// HTML, markdown
|
|
1729
|
-
/^#(End Region) ([\w*-]+)$/,
|
|
1730
|
-
// Visual Basic
|
|
1731
|
-
/^::#(endregion) ([\w*-]+)$/,
|
|
1732
|
-
// Bat
|
|
1733
|
-
/^# ?((?:end)?region) ([\w*-]+)$/
|
|
1734
|
-
// C#, PHP, Powershell, Python, perl & misc
|
|
1735
|
-
];
|
|
1736
|
-
let regexp = null;
|
|
1737
|
-
let start = -1;
|
|
1738
|
-
for (const [lineId, line] of lines.entries()) {
|
|
1739
|
-
if (regexp === null) {
|
|
1740
|
-
for (const reg of regionRegexps) {
|
|
1741
|
-
if (testLine(line, reg, regionName)) {
|
|
1742
|
-
start = lineId + 1;
|
|
1743
|
-
regexp = reg;
|
|
1744
|
-
break;
|
|
1745
|
-
}
|
|
1746
|
-
}
|
|
1747
|
-
} else if (testLine(line, regexp, regionName, true)) {
|
|
1748
|
-
return { start, end: lineId, regexp };
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
return null;
|
|
1752
|
-
}
|
|
1753
|
-
function transformSnippet({ s, slide, options }) {
|
|
1754
|
-
const watchFiles = options.data.watchFiles;
|
|
1755
|
-
const dir = path3.dirname(slide.source?.filepath ?? options.entry ?? options.userRoot);
|
|
1756
|
-
s.replace(
|
|
1757
|
-
// eslint-disable-next-line regexp/no-super-linear-backtracking
|
|
1758
|
-
/^<<<\s*(\S.*?)(#[\w-]+)?\s*(?:\s(\S+?))?\s*(\{.*)?$/gm,
|
|
1759
|
-
(full, filepath = "", regionName = "", lang = "", meta = "") => {
|
|
1760
|
-
const src = slash3(
|
|
1761
|
-
/^@\//.test(filepath) ? path3.resolve(options.userRoot, filepath.slice(2)) : path3.resolve(dir, filepath)
|
|
1762
|
-
);
|
|
1763
|
-
watchFiles[src] ??= /* @__PURE__ */ new Set();
|
|
1764
|
-
watchFiles[src].add(slide.index);
|
|
1765
|
-
const isAFile = fs6.statSync(src).isFile();
|
|
1766
|
-
if (!fs6.existsSync(src) || !isAFile) {
|
|
1767
|
-
throw new Error(isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`);
|
|
1768
|
-
}
|
|
1769
|
-
let content = fs6.readFileSync(src, "utf8");
|
|
1770
|
-
if (regionName) {
|
|
1771
|
-
const lines = content.split(/\r?\n/);
|
|
1772
|
-
const region = findRegion(lines, regionName.slice(1));
|
|
1773
|
-
if (region) {
|
|
1774
|
-
content = dedent(
|
|
1775
|
-
lines.slice(region.start, region.end).filter((line) => !region.regexp.test(line.trim())).join("\n")
|
|
1776
|
-
);
|
|
1777
|
-
}
|
|
1778
|
-
}
|
|
1779
|
-
meta = meta.trim();
|
|
1780
|
-
lang = lang.trim();
|
|
1781
|
-
lang = lang || path3.extname(filepath).slice(1);
|
|
1782
|
-
if (meta.match(/^\{monaco-write\}/)) {
|
|
1783
|
-
monacoWriterWhitelist.add(filepath);
|
|
1784
|
-
lang = lang.trim();
|
|
1785
|
-
meta = meta.replace(/^\{monaco-write\}/, "").trim() || "{}";
|
|
1786
|
-
const encoded = lz4.compressToBase64(content);
|
|
1787
|
-
return `<Monaco writable=${JSON.stringify(filepath)} code-lz="${encoded}" lang="${lang}" v-bind="${meta}" />`;
|
|
1788
|
-
}
|
|
1789
|
-
return `\`\`\`${lang} ${meta}
|
|
1790
|
-
${content}
|
|
1791
|
-
\`\`\``;
|
|
1792
|
-
}
|
|
1793
|
-
);
|
|
1794
|
-
}
|
|
1795
|
-
|
|
1796
|
-
// node/syntax/transform/index.ts
|
|
1797
|
-
async function getMarkdownTransformers(options) {
|
|
1798
|
-
const extras = await setupTransformers(options.roots);
|
|
1799
|
-
return [
|
|
1800
|
-
...extras.pre,
|
|
1801
|
-
transformSnippet,
|
|
1802
|
-
options.data.config.highlighter === "shiki" && transformMagicMove,
|
|
1803
|
-
...extras.preCodeblock,
|
|
1804
|
-
transformMermaid,
|
|
1805
|
-
transformPlantUml,
|
|
1806
|
-
options.data.features.monaco && transformMonaco,
|
|
1807
|
-
...extras.postCodeblock,
|
|
1808
|
-
transformCodeWrapper,
|
|
1809
|
-
options.data.features.katex && transformKaTexWrapper,
|
|
1810
|
-
transformPageCSS,
|
|
1811
|
-
transformSlotSugar,
|
|
1812
|
-
...extras.post
|
|
1813
|
-
];
|
|
1814
|
-
}
|
|
1815
|
-
|
|
1816
|
-
// ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.1.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/image-size/specialCharacters.js
|
|
1817
|
-
var SpecialCharacters;
|
|
1818
|
-
(function(SpecialCharacters2) {
|
|
1819
|
-
SpecialCharacters2[SpecialCharacters2["EXCLAMATION_MARK"] = 33] = "EXCLAMATION_MARK";
|
|
1820
|
-
SpecialCharacters2[SpecialCharacters2["OPENING_BRACKET"] = 91] = "OPENING_BRACKET";
|
|
1821
|
-
SpecialCharacters2[SpecialCharacters2["OPENING_PARENTHESIS"] = 40] = "OPENING_PARENTHESIS";
|
|
1822
|
-
SpecialCharacters2[SpecialCharacters2["WHITESPACE"] = 32] = "WHITESPACE";
|
|
1823
|
-
SpecialCharacters2[SpecialCharacters2["NEW_LINE"] = 10] = "NEW_LINE";
|
|
1824
|
-
SpecialCharacters2[SpecialCharacters2["EQUALS"] = 61] = "EQUALS";
|
|
1825
|
-
SpecialCharacters2[SpecialCharacters2["LOWER_CASE_X"] = 120] = "LOWER_CASE_X";
|
|
1826
|
-
SpecialCharacters2[SpecialCharacters2["NUMBER_ZERO"] = 48] = "NUMBER_ZERO";
|
|
1827
|
-
SpecialCharacters2[SpecialCharacters2["NUMBER_NINE"] = 57] = "NUMBER_NINE";
|
|
1828
|
-
SpecialCharacters2[SpecialCharacters2["PERCENTAGE"] = 37] = "PERCENTAGE";
|
|
1829
|
-
SpecialCharacters2[SpecialCharacters2["CLOSING_PARENTHESIS"] = 41] = "CLOSING_PARENTHESIS";
|
|
1830
|
-
})(SpecialCharacters || (SpecialCharacters = {}));
|
|
1831
|
-
|
|
1832
|
-
// ../../node_modules/.pnpm/@hedgedoc+markdown-it-plugins@2.1.4_patch_hash=tuyuxytl56b2vxulpkzt2wf4o4_markdown-it@14.1.0/node_modules/@hedgedoc/markdown-it-plugins/dist/esm/task-lists/index.js
|
|
1833
|
-
import Token from "markdown-it/lib/token.mjs";
|
|
1834
|
-
var checkboxRegex = /^ *\[([\sx])] /i;
|
|
1835
|
-
function taskLists(md, options = { enabled: false, label: false, lineNumber: false }) {
|
|
1836
|
-
md.core.ruler.after("inline", "task-lists", (state) => processToken(state, options));
|
|
1837
|
-
md.renderer.rules.taskListItemCheckbox = (tokens) => {
|
|
1838
|
-
const token = tokens[0];
|
|
1839
|
-
const checkedAttribute = token.attrGet("checked") ? 'checked="" ' : "";
|
|
1840
|
-
const disabledAttribute = token.attrGet("disabled") ? 'disabled="" ' : "";
|
|
1841
|
-
const line = token.attrGet("line");
|
|
1842
|
-
const idAttribute = `id="${token.attrGet("id")}" `;
|
|
1843
|
-
const dataLineAttribute = line && options.lineNumber ? `data-line="${line}" ` : "";
|
|
1844
|
-
return `<input class="task-list-item-checkbox" type="checkbox" ${checkedAttribute}${disabledAttribute}${dataLineAttribute}${idAttribute}/>`;
|
|
1845
|
-
};
|
|
1846
|
-
md.renderer.rules.taskListItemLabel_close = () => {
|
|
1847
|
-
return "</label>";
|
|
1848
|
-
};
|
|
1849
|
-
md.renderer.rules.taskListItemLabel_open = (tokens) => {
|
|
1850
|
-
const token = tokens[0];
|
|
1851
|
-
const id = token.attrGet("id");
|
|
1852
|
-
return `<label for="${id}">`;
|
|
1853
|
-
};
|
|
1854
|
-
}
|
|
1855
|
-
function processToken(state, options) {
|
|
1856
|
-
const allTokens = state.tokens;
|
|
1857
|
-
for (let i = 2; i < allTokens.length; i++) {
|
|
1858
|
-
if (!isTodoItem(allTokens, i)) {
|
|
1859
|
-
continue;
|
|
1860
|
-
}
|
|
1861
|
-
todoify(allTokens[i], options);
|
|
1862
|
-
allTokens[i - 2].attrJoin("class", `task-list-item ${options.enabled ? " enabled" : ""}`);
|
|
1863
|
-
const parentToken = findParentToken(allTokens, i - 2);
|
|
1864
|
-
if (parentToken) {
|
|
1865
|
-
const classes = parentToken.attrGet("class") ?? "";
|
|
1866
|
-
if (!classes.match(/(^| )contains-task-list/)) {
|
|
1867
|
-
parentToken.attrJoin("class", "contains-task-list");
|
|
1868
|
-
}
|
|
1869
|
-
}
|
|
1870
|
-
}
|
|
1871
|
-
return false;
|
|
1872
|
-
}
|
|
1873
|
-
function findParentToken(tokens, index) {
|
|
1874
|
-
const targetLevel = tokens[index].level - 1;
|
|
1875
|
-
for (let currentTokenIndex = index - 1; currentTokenIndex >= 0; currentTokenIndex--) {
|
|
1876
|
-
if (tokens[currentTokenIndex].level === targetLevel) {
|
|
1877
|
-
return tokens[currentTokenIndex];
|
|
1878
|
-
}
|
|
1879
|
-
}
|
|
1880
|
-
return void 0;
|
|
1881
|
-
}
|
|
1882
|
-
function isTodoItem(tokens, index) {
|
|
1883
|
-
return isInline(tokens[index]) && isParagraph(tokens[index - 1]) && isListItem(tokens[index - 2]) && startsWithTodoMarkdown(tokens[index]);
|
|
1884
|
-
}
|
|
1885
|
-
function todoify(token, options) {
|
|
1886
|
-
if (token.children == null) {
|
|
1887
|
-
return;
|
|
1888
|
-
}
|
|
1889
|
-
const id = generateIdForToken(token);
|
|
1890
|
-
token.children.splice(0, 0, createCheckboxToken(token, options.enabled, id));
|
|
1891
|
-
token.children[1].content = token.children[1].content.replace(checkboxRegex, "");
|
|
1892
|
-
if (options.label) {
|
|
1893
|
-
token.children.splice(1, 0, createLabelBeginToken(id));
|
|
1894
|
-
token.children.push(createLabelEndToken());
|
|
1895
|
-
}
|
|
1896
|
-
}
|
|
1897
|
-
function generateIdForToken(token) {
|
|
1898
|
-
if (token.map) {
|
|
1899
|
-
return `task-item-${token.map[0]}`;
|
|
1900
|
-
} else {
|
|
1901
|
-
return `task-item-${Math.ceil(Math.random() * (1e4 * 1e3) - 1e3)}`;
|
|
1902
|
-
}
|
|
1903
|
-
}
|
|
1904
|
-
function createCheckboxToken(token, enabled, id) {
|
|
1905
|
-
const checkbox = new Token("taskListItemCheckbox", "", 0);
|
|
1906
|
-
if (!enabled) {
|
|
1907
|
-
checkbox.attrSet("disabled", "true");
|
|
1908
|
-
}
|
|
1909
|
-
if (token.map) {
|
|
1910
|
-
checkbox.attrSet("line", token.map[0].toString());
|
|
1911
|
-
}
|
|
1912
|
-
checkbox.attrSet("id", id);
|
|
1913
|
-
const checkboxRegexResult = checkboxRegex.exec(token.content);
|
|
1914
|
-
const isChecked = checkboxRegexResult?.[1].toLowerCase() === "x";
|
|
1915
|
-
if (isChecked) {
|
|
1916
|
-
checkbox.attrSet("checked", "true");
|
|
1917
|
-
}
|
|
1918
|
-
return checkbox;
|
|
1919
|
-
}
|
|
1920
|
-
function createLabelBeginToken(id) {
|
|
1921
|
-
const labelBeginToken = new Token("taskListItemLabel_open", "", 1);
|
|
1922
|
-
labelBeginToken.attrSet("id", id);
|
|
1923
|
-
return labelBeginToken;
|
|
1924
|
-
}
|
|
1925
|
-
function createLabelEndToken() {
|
|
1926
|
-
return new Token("taskListItemLabel_close", "", -1);
|
|
1927
|
-
}
|
|
1928
|
-
function isInline(token) {
|
|
1929
|
-
return token.type === "inline";
|
|
1930
|
-
}
|
|
1931
|
-
function isParagraph(token) {
|
|
1932
|
-
return token.type === "paragraph_open";
|
|
1933
|
-
}
|
|
1934
|
-
function isListItem(token) {
|
|
1935
|
-
return token.type === "list_item_open";
|
|
1936
|
-
}
|
|
1937
|
-
function startsWithTodoMarkdown(token) {
|
|
1938
|
-
return checkboxRegex.test(token.content);
|
|
1939
|
-
}
|
|
1940
|
-
|
|
1941
|
-
// node/syntax/markdown-it/index.ts
|
|
1942
|
-
import MarkdownItMdc from "markdown-it-mdc";
|
|
1943
|
-
import MarkdownItFootnote from "markdown-it-footnote";
|
|
1944
|
-
|
|
1945
|
-
// node/setups/katex.ts
|
|
1946
|
-
async function setupKatex(roots) {
|
|
1947
|
-
const options = await loadSetups(roots, "katex.ts", []);
|
|
1948
|
-
return Object.assign(
|
|
1949
|
-
{ strict: false },
|
|
1950
|
-
...options
|
|
1951
|
-
);
|
|
1952
|
-
}
|
|
1420
|
+
// node/syntax/markdown-it/markdown-it-escape-code.ts
|
|
1421
|
+
function MarkdownItEscapeInlineCode(md) {
|
|
1422
|
+
const codeInline = md.renderer.rules.code_inline;
|
|
1423
|
+
md.renderer.rules.code_inline = (tokens, idx, options, env, self) => {
|
|
1424
|
+
const result = codeInline(tokens, idx, options, env, self);
|
|
1425
|
+
return result.replace(/^<code/, "<code v-pre");
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1953
1428
|
|
|
1954
1429
|
// node/syntax/markdown-it/markdown-it-katex.ts
|
|
1955
1430
|
import katex from "katex";
|
|
@@ -2096,11 +1571,69 @@ function MarkdownItKatex(md, options) {
|
|
|
2096
1571
|
md.renderer.rules.math_block = blockRenderer;
|
|
2097
1572
|
}
|
|
2098
1573
|
|
|
2099
|
-
// node/syntax/markdown-it/markdown-it-
|
|
2100
|
-
import {
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
1574
|
+
// node/syntax/markdown-it/markdown-it-shiki.ts
|
|
1575
|
+
import { isTruthy } from "@antfu/utils";
|
|
1576
|
+
import { fromHighlighter } from "@shikijs/markdown-it/core";
|
|
1577
|
+
|
|
1578
|
+
// node/syntax/transform/utils.ts
|
|
1579
|
+
function normalizeRangeStr(rangeStr = "") {
|
|
1580
|
+
return !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
|
|
1581
|
+
}
|
|
1582
|
+
function getCodeBlocks(md) {
|
|
1583
|
+
const codeblocks = Array.from(md.matchAll(/^```[\s\S]*?^```/gm)).map((m) => {
|
|
1584
|
+
const start = m.index;
|
|
1585
|
+
const end = m.index + m[0].length;
|
|
1586
|
+
const startLine = md.slice(0, start).match(/\n/g)?.length || 0;
|
|
1587
|
+
const endLine = md.slice(0, end).match(/\n/g)?.length || 0;
|
|
1588
|
+
return [start, end, startLine, endLine];
|
|
1589
|
+
});
|
|
1590
|
+
return {
|
|
1591
|
+
codeblocks,
|
|
1592
|
+
isInsideCodeblocks(idx) {
|
|
1593
|
+
return codeblocks.some(([s, e]) => s <= idx && idx <= e);
|
|
1594
|
+
},
|
|
1595
|
+
isLineInsideCodeblocks(line) {
|
|
1596
|
+
return codeblocks.some(([, , s, e]) => s <= line && line <= e);
|
|
1597
|
+
}
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
function escapeVueInCode(md) {
|
|
1601
|
+
return md.replace(/\{\{/g, "{{");
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
// node/syntax/markdown-it/markdown-it-shiki.ts
|
|
1605
|
+
async function MarkdownItShiki({ data: { config }, mode, utils }) {
|
|
1606
|
+
const transformers = [
|
|
1607
|
+
...utils.shikiOptions.transformers || [],
|
|
1608
|
+
(config.twoslash === true || config.twoslash === mode) && (await import("@shikijs/vitepress-twoslash")).transformerTwoslash({
|
|
1609
|
+
explicitTrigger: true,
|
|
1610
|
+
twoslashOptions: {
|
|
1611
|
+
handbookOptions: {
|
|
1612
|
+
noErrorValidation: true
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}),
|
|
1616
|
+
{
|
|
1617
|
+
pre(pre) {
|
|
1618
|
+
this.addClassToHast(pre, "slidev-code");
|
|
1619
|
+
delete pre.properties.tabindex;
|
|
1620
|
+
},
|
|
1621
|
+
postprocess(code) {
|
|
1622
|
+
return escapeVueInCode(code);
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
].filter(isTruthy);
|
|
1626
|
+
return fromHighlighter(utils.shiki, {
|
|
1627
|
+
...utils.shikiOptions,
|
|
1628
|
+
transformers
|
|
1629
|
+
});
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
// node/syntax/markdown-it/markdown-it-v-drag.ts
|
|
1633
|
+
import { SourceMapConsumer } from "source-map-js";
|
|
1634
|
+
var dragComponentRegex = /<(v-?drag-?\w*)([\s>])/i;
|
|
1635
|
+
var dragDirectiveRegex = /(?<![</\w])v-drag(=".*?")?/i;
|
|
1636
|
+
function MarkdownItVDrag(md, markdownTransformMap) {
|
|
2104
1637
|
const visited = /* @__PURE__ */ new WeakSet();
|
|
2105
1638
|
const sourceMapConsumers = /* @__PURE__ */ new WeakMap();
|
|
2106
1639
|
function getSourceMapConsumer(id) {
|
|
@@ -2153,54 +1686,11 @@ function MarkdownItVDrag(md, markdownTransformMap) {
|
|
|
2153
1686
|
};
|
|
2154
1687
|
}
|
|
2155
1688
|
|
|
2156
|
-
// node/syntax/markdown-it/markdown-it-shiki.ts
|
|
2157
|
-
import { isTruthy } from "@antfu/utils";
|
|
2158
|
-
import { fromHighlighter } from "@shikijs/markdown-it/core";
|
|
2159
|
-
async function MarkdownItShiki({ data: { config }, mode, utils }) {
|
|
2160
|
-
const transformers = [
|
|
2161
|
-
...utils.shikiOptions.transformers || [],
|
|
2162
|
-
(config.twoslash === true || config.twoslash === mode) && (await import("@shikijs/vitepress-twoslash")).transformerTwoslash({
|
|
2163
|
-
explicitTrigger: true,
|
|
2164
|
-
twoslashOptions: {
|
|
2165
|
-
handbookOptions: {
|
|
2166
|
-
noErrorValidation: true
|
|
2167
|
-
}
|
|
2168
|
-
}
|
|
2169
|
-
}),
|
|
2170
|
-
{
|
|
2171
|
-
pre(pre) {
|
|
2172
|
-
this.addClassToHast(pre, "slidev-code");
|
|
2173
|
-
delete pre.properties.tabindex;
|
|
2174
|
-
},
|
|
2175
|
-
postprocess(code) {
|
|
2176
|
-
return escapeVueInCode(code);
|
|
2177
|
-
}
|
|
2178
|
-
}
|
|
2179
|
-
].filter(isTruthy);
|
|
2180
|
-
return fromHighlighter(utils.shiki, {
|
|
2181
|
-
...utils.shikiOptions,
|
|
2182
|
-
transformers
|
|
2183
|
-
});
|
|
2184
|
-
}
|
|
2185
|
-
|
|
2186
|
-
// node/syntax/markdown-it/markdown-it-escape-code.ts
|
|
2187
|
-
function MarkdownItEscapeInlineCode(md) {
|
|
2188
|
-
const codeInline = md.renderer.rules.code_inline;
|
|
2189
|
-
md.renderer.rules.code_inline = (tokens, idx, options, env, self) => {
|
|
2190
|
-
const result = codeInline(tokens, idx, options, env, self);
|
|
2191
|
-
return result.replace(/^<code/, "<code v-pre");
|
|
2192
|
-
};
|
|
2193
|
-
}
|
|
2194
|
-
|
|
2195
1689
|
// node/syntax/markdown-it/index.ts
|
|
2196
1690
|
async function useMarkdownItPlugins(md, options, markdownTransformMap) {
|
|
2197
1691
|
const { roots, data: { features, config } } = options;
|
|
2198
1692
|
if (config.highlighter === "shiki") {
|
|
2199
1693
|
md.use(await MarkdownItShiki(options));
|
|
2200
|
-
} else {
|
|
2201
|
-
console.warn("[Slidev] Highlighter: Prism highlighter is deprecated, and will be removed in v0.50. Refer to https://github.com/slidevjs/slidev/issues/1390");
|
|
2202
|
-
const { default: MarkdownItPrism } = await import("./markdown-it-prism-P475G4NP.js");
|
|
2203
|
-
md.use(MarkdownItPrism);
|
|
2204
1694
|
}
|
|
2205
1695
|
md.use(MarkdownItLink);
|
|
2206
1696
|
md.use(MarkdownItEscapeInlineCode);
|
|
@@ -2213,6 +1703,366 @@ async function useMarkdownItPlugins(md, options, markdownTransformMap) {
|
|
|
2213
1703
|
md.use(MarkdownItMdc);
|
|
2214
1704
|
}
|
|
2215
1705
|
|
|
1706
|
+
// node/setups/transformers.ts
|
|
1707
|
+
async function setupTransformers(roots) {
|
|
1708
|
+
const returns = await loadSetups(roots, "transformers.ts", []);
|
|
1709
|
+
const result = {
|
|
1710
|
+
pre: [],
|
|
1711
|
+
preCodeblock: [],
|
|
1712
|
+
postCodeblock: [],
|
|
1713
|
+
post: []
|
|
1714
|
+
};
|
|
1715
|
+
for (const r of [...returns].reverse()) {
|
|
1716
|
+
if (r.pre)
|
|
1717
|
+
result.pre.push(...r.pre);
|
|
1718
|
+
if (r.preCodeblock)
|
|
1719
|
+
result.preCodeblock.push(...r.preCodeblock);
|
|
1720
|
+
}
|
|
1721
|
+
for (const r of returns) {
|
|
1722
|
+
if (r.postCodeblock)
|
|
1723
|
+
result.postCodeblock.push(...r.postCodeblock);
|
|
1724
|
+
if (r.post)
|
|
1725
|
+
result.post.push(...r.post);
|
|
1726
|
+
}
|
|
1727
|
+
return result;
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
// node/syntax/transform/code-wrapper.ts
|
|
1731
|
+
var reCodeBlock = /^```([\w'-]+)?\s*(?:\{([\w*,|-]+)\}\s*?(\{[^}]*\})?([^\r\n]*))?\r?\n([ \t]*\S[\s\S]*?)^```$/gm;
|
|
1732
|
+
function transformCodeWrapper(ctx) {
|
|
1733
|
+
ctx.s.replace(
|
|
1734
|
+
reCodeBlock,
|
|
1735
|
+
(full, lang = "", rangeStr = "", options = "", attrs = "", code) => {
|
|
1736
|
+
const ranges = normalizeRangeStr(rangeStr);
|
|
1737
|
+
code = code.trimEnd();
|
|
1738
|
+
options = options.trim() || "{}";
|
|
1739
|
+
return `
|
|
1740
|
+
<CodeBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
|
|
1741
|
+
|
|
1742
|
+
\`\`\`${lang}${attrs}
|
|
1743
|
+
${code}
|
|
1744
|
+
\`\`\`
|
|
1745
|
+
|
|
1746
|
+
</CodeBlockWrapper>`;
|
|
1747
|
+
}
|
|
1748
|
+
);
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
// node/syntax/transform/in-page-css.ts
|
|
1752
|
+
function transformPageCSS(ctx) {
|
|
1753
|
+
const codeBlocks = getCodeBlocks(ctx.s.original);
|
|
1754
|
+
ctx.s.replace(
|
|
1755
|
+
/(\n<style[^>]*>)([\s\S]+?)(<\/style>)/g,
|
|
1756
|
+
(full, start, css, end, index) => {
|
|
1757
|
+
if (codeBlocks.isInsideCodeblocks(index))
|
|
1758
|
+
return full;
|
|
1759
|
+
if (!start.includes("scoped"))
|
|
1760
|
+
start = start.replace("<style", "<style scoped");
|
|
1761
|
+
return `${start}
|
|
1762
|
+
${css}${end}`;
|
|
1763
|
+
}
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
// node/syntax/transform/katex-wrapper.ts
|
|
1768
|
+
function transformKaTexWrapper(ctx) {
|
|
1769
|
+
ctx.s.replace(
|
|
1770
|
+
/^\$\$(?:\s*\{([\w*,|-]+)\}\s*?(?:(\{[^}]*\})\s*?)?)?\n(\S[\s\S]*?)^\$\$/gm,
|
|
1771
|
+
(full, rangeStr = "", options = "", code) => {
|
|
1772
|
+
const ranges = !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
|
|
1773
|
+
code = code.trimEnd();
|
|
1774
|
+
options = options.trim() || "{}";
|
|
1775
|
+
return `<KaTexBlockWrapper v-bind="${options}" :ranges='${JSON.stringify(ranges)}'>
|
|
1776
|
+
|
|
1777
|
+
$$
|
|
1778
|
+
${code}
|
|
1779
|
+
$$
|
|
1780
|
+
</KaTexBlockWrapper>
|
|
1781
|
+
`;
|
|
1782
|
+
}
|
|
1783
|
+
);
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
// node/syntax/transform/magic-move.ts
|
|
1787
|
+
import lz from "lz-string";
|
|
1788
|
+
import { codeToKeyedTokens } from "shiki-magic-move/core";
|
|
1789
|
+
var reMagicMoveBlock = /^````(?:md|markdown) magic-move *(\{[^}]*\})?([^ \n]*)\n([\s\S]+?)^````$/gm;
|
|
1790
|
+
function parseLineNumbersOption(options) {
|
|
1791
|
+
return /lines: *true/.test(options) ? true : /lines: *false/.test(options) ? false : void 0;
|
|
1792
|
+
}
|
|
1793
|
+
function transformMagicMove(ctx) {
|
|
1794
|
+
ctx.s.replace(
|
|
1795
|
+
reMagicMoveBlock,
|
|
1796
|
+
(full, options = "{}", _attrs = "", body) => {
|
|
1797
|
+
const matches = Array.from(body.matchAll(reCodeBlock));
|
|
1798
|
+
if (!matches.length)
|
|
1799
|
+
throw new Error("Magic Move block must contain at least one code block");
|
|
1800
|
+
const defaultLineNumbers = parseLineNumbersOption(options) ?? ctx.options.data.config.lineNumbers;
|
|
1801
|
+
const ranges = matches.map((i) => normalizeRangeStr(i[2]));
|
|
1802
|
+
const steps = matches.map((i) => {
|
|
1803
|
+
const lineNumbers = parseLineNumbersOption(i[3]) ?? defaultLineNumbers;
|
|
1804
|
+
return codeToKeyedTokens(ctx.options.utils.shiki, i[5].trimEnd(), {
|
|
1805
|
+
...ctx.options.utils.shikiOptions,
|
|
1806
|
+
lang: i[1]
|
|
1807
|
+
}, lineNumbers);
|
|
1808
|
+
});
|
|
1809
|
+
const compressed = lz.compressToBase64(JSON.stringify(steps));
|
|
1810
|
+
return `<ShikiMagicMove v-bind="${options}" steps-lz="${compressed}" :step-ranges='${JSON.stringify(ranges)}' />`;
|
|
1811
|
+
}
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
// node/syntax/transform/mermaid.ts
|
|
1816
|
+
import lz2 from "lz-string";
|
|
1817
|
+
function transformMermaid(ctx) {
|
|
1818
|
+
ctx.s.replace(
|
|
1819
|
+
/^```mermaid *(\{[^\n]*\})?\n([\s\S]+?)\n```/gm,
|
|
1820
|
+
(full, options = "", code = "") => {
|
|
1821
|
+
code = code.trim();
|
|
1822
|
+
options = options.trim() || "{}";
|
|
1823
|
+
const encoded = lz2.compressToBase64(code);
|
|
1824
|
+
return `<Mermaid code-lz="${encoded}" v-bind="${options}" />`;
|
|
1825
|
+
}
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
// node/syntax/transform/monaco.ts
|
|
1830
|
+
import lz3 from "lz-string";
|
|
1831
|
+
function transformMonaco(ctx) {
|
|
1832
|
+
const enabled = ctx.options.data.config.monaco === true || ctx.options.data.config.monaco === ctx.options.mode;
|
|
1833
|
+
if (!enabled) {
|
|
1834
|
+
ctx.s.replace(/\{monaco([\w:,-]*)\}/g, "");
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1837
|
+
ctx.s.replace(
|
|
1838
|
+
/^```(\w+) *\{monaco-diff\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^~~~ *\n([\s\S]+?)^```/gm,
|
|
1839
|
+
(full, lang = "ts", options = "{}", code, diff) => {
|
|
1840
|
+
lang = lang.trim();
|
|
1841
|
+
options = options.trim() || "{}";
|
|
1842
|
+
const encoded = lz3.compressToBase64(code);
|
|
1843
|
+
const encodedDiff = lz3.compressToBase64(diff);
|
|
1844
|
+
return `<Monaco code-lz="${encoded}" diff-lz="${encodedDiff}" lang="${lang}" v-bind="${options}" />`;
|
|
1845
|
+
}
|
|
1846
|
+
);
|
|
1847
|
+
ctx.s.replace(
|
|
1848
|
+
/^```(\w+) *\{monaco\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm,
|
|
1849
|
+
(full, lang = "ts", options = "{}", code) => {
|
|
1850
|
+
lang = lang.trim();
|
|
1851
|
+
options = options.trim() || "{}";
|
|
1852
|
+
const encoded = lz3.compressToBase64(code);
|
|
1853
|
+
return `<Monaco code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
|
|
1854
|
+
}
|
|
1855
|
+
);
|
|
1856
|
+
ctx.s.replace(
|
|
1857
|
+
/^```(\w+) *\{monaco-run\} *(?:(\{[^\n]*\}) *)?\n([\s\S]+?)^```/gm,
|
|
1858
|
+
(full, lang = "ts", options = "{}", code) => {
|
|
1859
|
+
lang = lang.trim();
|
|
1860
|
+
options = options.trim() || "{}";
|
|
1861
|
+
const encoded = lz3.compressToBase64(code);
|
|
1862
|
+
return `<Monaco runnable code-lz="${encoded}" lang="${lang}" v-bind="${options}" />`;
|
|
1863
|
+
}
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
// node/syntax/transform/plant-uml.ts
|
|
1868
|
+
import { encode as encodePlantUml } from "plantuml-encoder";
|
|
1869
|
+
function transformPlantUml(ctx) {
|
|
1870
|
+
const server = ctx.options.data.config.plantUmlServer;
|
|
1871
|
+
ctx.s.replace(
|
|
1872
|
+
/^```plantuml[^\n{}]*(\{[^}\n]*\})?\n([\s\S]+?)\n```/gm,
|
|
1873
|
+
(full, options = "", content = "") => {
|
|
1874
|
+
const code = encodePlantUml(content.trim());
|
|
1875
|
+
options = options.trim() || "{}";
|
|
1876
|
+
return `<PlantUml :code="'${code}'" :server="'${server}'" v-bind="${options}" />`;
|
|
1877
|
+
}
|
|
1878
|
+
);
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
// node/syntax/transform/slot-sugar.ts
|
|
1882
|
+
function transformSlotSugar(ctx) {
|
|
1883
|
+
const linesWithNewline = ctx.s.original.split(/(\r?\n)/g);
|
|
1884
|
+
const codeBlocks = getCodeBlocks(ctx.s.original);
|
|
1885
|
+
const lines = [];
|
|
1886
|
+
for (let i = 0; i < linesWithNewline.length; i += 2) {
|
|
1887
|
+
const line = linesWithNewline[i];
|
|
1888
|
+
const newline = linesWithNewline[i + 1] || "";
|
|
1889
|
+
lines.push(line + newline);
|
|
1890
|
+
}
|
|
1891
|
+
let prevSlot = false;
|
|
1892
|
+
let offset = 0;
|
|
1893
|
+
lines.forEach((line) => {
|
|
1894
|
+
const start = offset;
|
|
1895
|
+
offset += line.length;
|
|
1896
|
+
if (codeBlocks.isInsideCodeblocks(offset))
|
|
1897
|
+
return;
|
|
1898
|
+
const match = line.match(/^::\s*([\w.\-:]+)\s*::(\s*)$/);
|
|
1899
|
+
if (match) {
|
|
1900
|
+
ctx.s.overwrite(start, offset - match[2].length, `${prevSlot ? "\n\n</template>\n" : "\n"}<template v-slot:${match[1]}="slotProps">
|
|
1901
|
+
`);
|
|
1902
|
+
prevSlot = true;
|
|
1903
|
+
}
|
|
1904
|
+
});
|
|
1905
|
+
if (prevSlot)
|
|
1906
|
+
ctx.s.append("\n\n</template>");
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
// node/syntax/transform/snippet.ts
|
|
1910
|
+
import path2 from "node:path";
|
|
1911
|
+
import { slash as slash2 } from "@antfu/utils";
|
|
1912
|
+
import fs5 from "fs-extra";
|
|
1913
|
+
import lz4 from "lz-string";
|
|
1914
|
+
|
|
1915
|
+
// node/vite/monacoWrite.ts
|
|
1916
|
+
import fs4 from "node:fs/promises";
|
|
1917
|
+
import path from "node:path";
|
|
1918
|
+
var monacoWriterWhitelist = /* @__PURE__ */ new Set();
|
|
1919
|
+
function createMonacoWriterPlugin({ userRoot }) {
|
|
1920
|
+
return {
|
|
1921
|
+
name: "slidev:monaco-write",
|
|
1922
|
+
apply: "serve",
|
|
1923
|
+
configureServer(server) {
|
|
1924
|
+
server.ws.on("connection", (socket) => {
|
|
1925
|
+
socket.on("message", async (data) => {
|
|
1926
|
+
let json;
|
|
1927
|
+
try {
|
|
1928
|
+
json = JSON.parse(data.toString());
|
|
1929
|
+
} catch {
|
|
1930
|
+
return;
|
|
1931
|
+
}
|
|
1932
|
+
if (json.type === "custom" && json.event === "slidev:monaco-write") {
|
|
1933
|
+
const { file, content } = json.data;
|
|
1934
|
+
if (!monacoWriterWhitelist.has(file)) {
|
|
1935
|
+
console.error(`[Slidev] Unauthorized file write: ${file}`);
|
|
1936
|
+
return;
|
|
1937
|
+
}
|
|
1938
|
+
const filepath = path.join(userRoot, file);
|
|
1939
|
+
console.log("[Slidev] Writing file:", filepath);
|
|
1940
|
+
await fs4.writeFile(filepath, content, "utf-8");
|
|
1941
|
+
}
|
|
1942
|
+
});
|
|
1943
|
+
});
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// node/syntax/transform/snippet.ts
|
|
1949
|
+
function dedent(text) {
|
|
1950
|
+
const lines = text.split("\n");
|
|
1951
|
+
const minIndentLength = lines.reduce((acc, line) => {
|
|
1952
|
+
for (let i = 0; i < line.length; i++) {
|
|
1953
|
+
if (line[i] !== " " && line[i] !== " ")
|
|
1954
|
+
return Math.min(i, acc);
|
|
1955
|
+
}
|
|
1956
|
+
return acc;
|
|
1957
|
+
}, Number.POSITIVE_INFINITY);
|
|
1958
|
+
if (minIndentLength < Number.POSITIVE_INFINITY)
|
|
1959
|
+
return lines.map((x) => x.slice(minIndentLength)).join("\n");
|
|
1960
|
+
return text;
|
|
1961
|
+
}
|
|
1962
|
+
function findRegion(lines, regionName) {
|
|
1963
|
+
const regionRegexps = [
|
|
1964
|
+
// javascript, typescript, java
|
|
1965
|
+
[/^\/\/ ?#?region ([\w*-]+)$/, /^\/\/ ?#?endregion/],
|
|
1966
|
+
// css, less, scss
|
|
1967
|
+
[/^\/\* ?#region ([\w*-]+) ?\*\/$/, /^\/\* ?#endregion[\s\w*-]*\*\/$/],
|
|
1968
|
+
// C, C++
|
|
1969
|
+
[/^#pragma region ([\w*-]+)$/, /^#pragma endregion/],
|
|
1970
|
+
// HTML, markdown
|
|
1971
|
+
[/^<!-- #?region ([\w*-]+) -->$/, /^<!-- #?region[\s\w*-]*-->$/],
|
|
1972
|
+
// Visual Basic
|
|
1973
|
+
[/^#Region ([\w*-]+)$/, /^#End Region/],
|
|
1974
|
+
// Bat
|
|
1975
|
+
[/^::#region ([\w*-]+)$/, /^::#endregion/],
|
|
1976
|
+
// C#, PHP, Powershell, Python, perl & misc
|
|
1977
|
+
[/^# ?region ([\w*-]+)$/, /^# ?endregion/]
|
|
1978
|
+
];
|
|
1979
|
+
let endReg = null;
|
|
1980
|
+
let start = -1;
|
|
1981
|
+
for (const [lineId, line] of lines.entries()) {
|
|
1982
|
+
if (endReg === null) {
|
|
1983
|
+
for (const [startReg, end] of regionRegexps) {
|
|
1984
|
+
const match = line.trim().match(startReg);
|
|
1985
|
+
if (match && match[1] === regionName) {
|
|
1986
|
+
start = lineId + 1;
|
|
1987
|
+
endReg = end;
|
|
1988
|
+
break;
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
} else if (endReg.test(line.trim())) {
|
|
1992
|
+
return {
|
|
1993
|
+
start,
|
|
1994
|
+
end: lineId,
|
|
1995
|
+
regexp: endReg
|
|
1996
|
+
};
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
return null;
|
|
2000
|
+
}
|
|
2001
|
+
var reMonacoWrite = /^\{monaco-write\}/;
|
|
2002
|
+
function transformSnippet({ s, slide, options }) {
|
|
2003
|
+
const watchFiles = options.data.watchFiles;
|
|
2004
|
+
const dir = path2.dirname(slide.source?.filepath ?? options.entry ?? options.userRoot);
|
|
2005
|
+
s.replace(
|
|
2006
|
+
// eslint-disable-next-line regexp/no-super-linear-backtracking
|
|
2007
|
+
/^<<<\s*(\S.*?)(#[\w-]+)?\s*(?:\s(\S+?))?\s*(\{.*)?$/gm,
|
|
2008
|
+
(full, filepath = "", regionName = "", lang = "", meta = "") => {
|
|
2009
|
+
const src = slash2(
|
|
2010
|
+
/^@\//.test(filepath) ? path2.resolve(options.userRoot, filepath.slice(2)) : path2.resolve(dir, filepath)
|
|
2011
|
+
);
|
|
2012
|
+
meta = meta.trim();
|
|
2013
|
+
lang = lang.trim();
|
|
2014
|
+
lang = lang || path2.extname(filepath).slice(1);
|
|
2015
|
+
const isAFile = fs5.statSync(src).isFile();
|
|
2016
|
+
if (!fs5.existsSync(src) || !isAFile) {
|
|
2017
|
+
throw new Error(isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`);
|
|
2018
|
+
}
|
|
2019
|
+
let content = fs5.readFileSync(src, "utf8");
|
|
2020
|
+
if (regionName) {
|
|
2021
|
+
const lines = content.split(/\r?\n/);
|
|
2022
|
+
const region = findRegion(lines, regionName.slice(1));
|
|
2023
|
+
if (region) {
|
|
2024
|
+
content = dedent(
|
|
2025
|
+
lines.slice(region.start, region.end).filter((line) => !region.regexp.test(line.trim())).join("\n")
|
|
2026
|
+
);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
if (meta.match(reMonacoWrite)) {
|
|
2030
|
+
monacoWriterWhitelist.add(filepath);
|
|
2031
|
+
lang = lang.trim();
|
|
2032
|
+
meta = meta.replace(reMonacoWrite, "").trim() || "{}";
|
|
2033
|
+
const encoded = lz4.compressToBase64(content);
|
|
2034
|
+
return `<Monaco writable=${JSON.stringify(filepath)} code-lz="${encoded}" lang="${lang}" v-bind="${meta}" />`;
|
|
2035
|
+
} else {
|
|
2036
|
+
watchFiles[src] ??= /* @__PURE__ */ new Set();
|
|
2037
|
+
watchFiles[src].add(slide.index);
|
|
2038
|
+
}
|
|
2039
|
+
return `\`\`\`${lang} ${meta}
|
|
2040
|
+
${content}
|
|
2041
|
+
\`\`\``;
|
|
2042
|
+
}
|
|
2043
|
+
);
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
// node/syntax/transform/index.ts
|
|
2047
|
+
async function getMarkdownTransformers(options) {
|
|
2048
|
+
const extras = await setupTransformers(options.roots);
|
|
2049
|
+
return [
|
|
2050
|
+
...extras.pre,
|
|
2051
|
+
transformSnippet,
|
|
2052
|
+
options.data.config.highlighter === "shiki" && transformMagicMove,
|
|
2053
|
+
...extras.preCodeblock,
|
|
2054
|
+
transformMermaid,
|
|
2055
|
+
transformPlantUml,
|
|
2056
|
+
options.data.features.monaco && transformMonaco,
|
|
2057
|
+
...extras.postCodeblock,
|
|
2058
|
+
transformCodeWrapper,
|
|
2059
|
+
options.data.features.katex && transformKaTexWrapper,
|
|
2060
|
+
transformPageCSS,
|
|
2061
|
+
transformSlotSugar,
|
|
2062
|
+
...extras.post
|
|
2063
|
+
];
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2216
2066
|
// node/vite/markdown.ts
|
|
2217
2067
|
async function createMarkdownPlugin(options, { markdown: mdOptions }) {
|
|
2218
2068
|
const markdownTransformMap = /* @__PURE__ */ new Map();
|
|
@@ -2265,10 +2115,10 @@ async function createMarkdownPlugin(options, { markdown: mdOptions }) {
|
|
|
2265
2115
|
}
|
|
2266
2116
|
|
|
2267
2117
|
// node/vite/monacoTypes.ts
|
|
2268
|
-
import
|
|
2118
|
+
import fs6 from "node:fs/promises";
|
|
2269
2119
|
import { dirname, resolve as resolve5 } from "node:path";
|
|
2270
|
-
import { slash as
|
|
2271
|
-
import
|
|
2120
|
+
import { slash as slash3 } from "@antfu/utils";
|
|
2121
|
+
import fg2 from "fast-glob";
|
|
2272
2122
|
import { findDepPkgJsonPath } from "vitefu";
|
|
2273
2123
|
function createMonacoTypesLoader({ userRoot, utils }) {
|
|
2274
2124
|
return {
|
|
@@ -2289,8 +2139,8 @@ function createMonacoTypesLoader({ userRoot, utils }) {
|
|
|
2289
2139
|
const pkgJsonPath = await findDepPkgJsonPath(pkg, importer);
|
|
2290
2140
|
if (!pkgJsonPath)
|
|
2291
2141
|
throw new Error(`Package "${pkg}" not found in "${importer}"`);
|
|
2292
|
-
const root =
|
|
2293
|
-
const pkgJson = JSON.parse(await
|
|
2142
|
+
const root = slash3(dirname(pkgJsonPath));
|
|
2143
|
+
const pkgJson = JSON.parse(await fs6.readFile(pkgJsonPath, "utf-8"));
|
|
2294
2144
|
let deps = Object.keys(pkgJson.dependencies ?? {});
|
|
2295
2145
|
deps = deps.filter((pkg2) => !utils.isMonacoTypesIgnored(pkg2));
|
|
2296
2146
|
return [
|
|
@@ -2302,7 +2152,7 @@ function createMonacoTypesLoader({ userRoot, utils }) {
|
|
|
2302
2152
|
const query = new URLSearchParams(url.search);
|
|
2303
2153
|
const root = query.get("root");
|
|
2304
2154
|
const name = query.get("name");
|
|
2305
|
-
const files = await
|
|
2155
|
+
const files = await fg2(
|
|
2306
2156
|
[
|
|
2307
2157
|
"**/*.ts",
|
|
2308
2158
|
"**/*.mts",
|
|
@@ -2350,9 +2200,9 @@ async function createRemoteAssetsPlugin({ data: { config }, mode }, pluginOption
|
|
|
2350
2200
|
import ServerRef from "vite-plugin-vue-server-ref";
|
|
2351
2201
|
|
|
2352
2202
|
// node/integrations/drawings.ts
|
|
2353
|
-
import { basename, dirname as dirname2, join as
|
|
2354
|
-
import
|
|
2355
|
-
import
|
|
2203
|
+
import { basename, dirname as dirname2, join as join9, resolve as resolve6 } from "node:path";
|
|
2204
|
+
import fg3 from "fast-glob";
|
|
2205
|
+
import fs7 from "fs-extra";
|
|
2356
2206
|
function resolveDrawingsDir(options) {
|
|
2357
2207
|
return options.data.config.drawings.persist ? resolve6(
|
|
2358
2208
|
dirname2(options.entry),
|
|
@@ -2361,9 +2211,9 @@ function resolveDrawingsDir(options) {
|
|
|
2361
2211
|
}
|
|
2362
2212
|
async function loadDrawings(options) {
|
|
2363
2213
|
const dir = resolveDrawingsDir(options);
|
|
2364
|
-
if (!dir || !
|
|
2214
|
+
if (!dir || !fs7.existsSync(dir))
|
|
2365
2215
|
return {};
|
|
2366
|
-
const files = await
|
|
2216
|
+
const files = await fg3("*.svg", {
|
|
2367
2217
|
onlyFiles: true,
|
|
2368
2218
|
cwd: dir,
|
|
2369
2219
|
absolute: true,
|
|
@@ -2374,7 +2224,7 @@ async function loadDrawings(options) {
|
|
|
2374
2224
|
const num = +basename(path4, ".svg");
|
|
2375
2225
|
if (Number.isNaN(num))
|
|
2376
2226
|
return;
|
|
2377
|
-
const content = await
|
|
2227
|
+
const content = await fs7.readFile(path4, "utf8");
|
|
2378
2228
|
const lines = content.split(/\n/g);
|
|
2379
2229
|
obj[num.toString()] = lines.slice(1, -1).join("\n");
|
|
2380
2230
|
}));
|
|
@@ -2387,7 +2237,7 @@ async function writeDrawings(options, drawing) {
|
|
|
2387
2237
|
const width = options.data.config.canvasWidth;
|
|
2388
2238
|
const height = Math.round(width / options.data.config.aspectRatio);
|
|
2389
2239
|
const SVG_HEAD = `<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">`;
|
|
2390
|
-
await
|
|
2240
|
+
await fs7.ensureDir(dir);
|
|
2391
2241
|
return Promise.all(
|
|
2392
2242
|
Object.entries(drawing).map(async ([key, value]) => {
|
|
2393
2243
|
if (!value)
|
|
@@ -2395,14 +2245,34 @@ async function writeDrawings(options, drawing) {
|
|
|
2395
2245
|
const svg = `${SVG_HEAD}
|
|
2396
2246
|
${value}
|
|
2397
2247
|
</svg>`;
|
|
2398
|
-
await
|
|
2248
|
+
await fs7.writeFile(join9(dir, `${key}.svg`), svg, "utf-8");
|
|
2399
2249
|
})
|
|
2400
2250
|
);
|
|
2401
2251
|
}
|
|
2402
2252
|
|
|
2253
|
+
// node/integrations/snapshots.ts
|
|
2254
|
+
import { dirname as dirname3, join as join10, resolve as resolve7 } from "node:path";
|
|
2255
|
+
import fs8 from "fs-extra";
|
|
2256
|
+
function resolveSnapshotsDir(options) {
|
|
2257
|
+
return resolve7(dirname3(options.entry), ".slidev/snapshots");
|
|
2258
|
+
}
|
|
2259
|
+
async function loadSnapshots(options) {
|
|
2260
|
+
const dir = resolveSnapshotsDir(options);
|
|
2261
|
+
const file = join10(dir, "snapshots.json");
|
|
2262
|
+
if (!dir || !fs8.existsSync(file))
|
|
2263
|
+
return {};
|
|
2264
|
+
return JSON.parse(await fs8.readFile(file, "utf8"));
|
|
2265
|
+
}
|
|
2266
|
+
async function writeSnapshots(options, data) {
|
|
2267
|
+
const dir = resolveSnapshotsDir(options);
|
|
2268
|
+
if (!dir)
|
|
2269
|
+
return;
|
|
2270
|
+
await fs8.ensureDir(dir);
|
|
2271
|
+
await fs8.writeFile(join10(dir, "snapshots.json"), JSON.stringify(data, null, 2), "utf-8");
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2403
2274
|
// node/vite/serverRef.ts
|
|
2404
2275
|
async function createServerRefPlugin(options, pluginOptions) {
|
|
2405
|
-
const drawingData = await loadDrawings(options);
|
|
2406
2276
|
return ServerRef({
|
|
2407
2277
|
debug: false,
|
|
2408
2278
|
// process.env.NODE_ENV === 'development',
|
|
@@ -2412,37 +2282,56 @@ async function createServerRefPlugin(options, pluginOptions) {
|
|
|
2412
2282
|
page: 0,
|
|
2413
2283
|
clicks: 0
|
|
2414
2284
|
},
|
|
2415
|
-
drawings:
|
|
2285
|
+
drawings: await loadDrawings(options),
|
|
2286
|
+
snapshots: await loadSnapshots(options),
|
|
2416
2287
|
...pluginOptions.serverRef?.state
|
|
2417
2288
|
},
|
|
2418
2289
|
onChanged(key, data, patch, timestamp) {
|
|
2419
2290
|
pluginOptions.serverRef?.onChanged?.(key, data, patch, timestamp);
|
|
2420
|
-
if (
|
|
2421
|
-
return;
|
|
2422
|
-
if (key === "drawings")
|
|
2291
|
+
if (options.data.config.drawings.persist && key === "drawings")
|
|
2423
2292
|
writeDrawings(options, patch ?? data);
|
|
2293
|
+
if (key === "snapshots")
|
|
2294
|
+
writeSnapshots(options, data);
|
|
2424
2295
|
}
|
|
2425
2296
|
});
|
|
2426
2297
|
}
|
|
2427
2298
|
|
|
2299
|
+
// node/vite/staticCopy.ts
|
|
2300
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
2301
|
+
import { join as join11 } from "node:path";
|
|
2302
|
+
async function createStaticCopyPlugin({ themeRoots, addonRoots }, pluginOptions) {
|
|
2303
|
+
const publicDirs = [...themeRoots, ...addonRoots].map((i) => join11(i, "public")).filter(existsSync5);
|
|
2304
|
+
if (!publicDirs.length)
|
|
2305
|
+
return;
|
|
2306
|
+
const { viteStaticCopy } = await import("vite-plugin-static-copy");
|
|
2307
|
+
return viteStaticCopy({
|
|
2308
|
+
silent: true,
|
|
2309
|
+
targets: publicDirs.map((dir) => ({
|
|
2310
|
+
src: `${dir}/*`,
|
|
2311
|
+
dest: "theme"
|
|
2312
|
+
})),
|
|
2313
|
+
...pluginOptions.staticCopy
|
|
2314
|
+
});
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2428
2317
|
// node/vite/unocss.ts
|
|
2429
2318
|
import UnoCSS from "unocss/vite";
|
|
2430
2319
|
|
|
2431
2320
|
// node/setups/unocss.ts
|
|
2432
|
-
import {
|
|
2433
|
-
import {
|
|
2321
|
+
import { existsSync as existsSync6, readFileSync } from "node:fs";
|
|
2322
|
+
import { resolve as resolve8 } from "node:path";
|
|
2434
2323
|
import { mergeConfigs, presetIcons } from "unocss";
|
|
2435
2324
|
async function setupUnocss({ clientRoot, roots, data, utils }) {
|
|
2436
|
-
function loadFileConfigs(root) {
|
|
2437
|
-
return [
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
].map((i) => {
|
|
2325
|
+
async function loadFileConfigs(root) {
|
|
2326
|
+
return (await Promise.all([
|
|
2327
|
+
resolve8(root, "uno.config.ts"),
|
|
2328
|
+
resolve8(root, "unocss.config.ts")
|
|
2329
|
+
].map(async (i) => {
|
|
2441
2330
|
if (!existsSync6(i))
|
|
2442
2331
|
return void 0;
|
|
2443
|
-
const loaded = loadModule(i);
|
|
2332
|
+
const loaded = await loadModule(i);
|
|
2444
2333
|
return "default" in loaded ? loaded.default : loaded;
|
|
2445
|
-
});
|
|
2334
|
+
}))).filter((x) => !!x);
|
|
2446
2335
|
}
|
|
2447
2336
|
const configs = [
|
|
2448
2337
|
{
|
|
@@ -2451,13 +2340,13 @@ async function setupUnocss({ clientRoot, roots, data, utils }) {
|
|
|
2451
2340
|
collectionsNodeResolvePath: utils.iconsResolvePath,
|
|
2452
2341
|
collections: {
|
|
2453
2342
|
slidev: {
|
|
2454
|
-
logo: () =>
|
|
2343
|
+
logo: () => readFileSync(resolve8(clientRoot, "assets/logo.svg"), "utf-8")
|
|
2455
2344
|
}
|
|
2456
2345
|
}
|
|
2457
2346
|
})
|
|
2458
2347
|
]
|
|
2459
2348
|
},
|
|
2460
|
-
...loadFileConfigs(clientRoot),
|
|
2349
|
+
...await loadFileConfigs(clientRoot),
|
|
2461
2350
|
...await loadSetups(roots, "unocss.ts", [], loadFileConfigs)
|
|
2462
2351
|
].filter(Boolean);
|
|
2463
2352
|
const config = mergeConfigs(configs);
|
|
@@ -2521,12 +2410,13 @@ async function createVuePlugin(_options, pluginOptions) {
|
|
|
2521
2410
|
exclude: [],
|
|
2522
2411
|
...vueOptions,
|
|
2523
2412
|
template: {
|
|
2413
|
+
...vueOptions?.template,
|
|
2524
2414
|
compilerOptions: {
|
|
2415
|
+
...vueOptions?.template?.compilerOptions,
|
|
2525
2416
|
isCustomElement(tag) {
|
|
2526
2417
|
return customElements.has(tag) || vueOptions?.template?.compilerOptions?.isCustomElement?.(tag);
|
|
2527
2418
|
}
|
|
2528
|
-
}
|
|
2529
|
-
...vueOptions?.template
|
|
2419
|
+
}
|
|
2530
2420
|
}
|
|
2531
2421
|
});
|
|
2532
2422
|
const VueJsxPlugin = VueJsx(vuejsxOptions);
|
|
@@ -2536,26 +2426,8 @@ async function createVuePlugin(_options, pluginOptions) {
|
|
|
2536
2426
|
];
|
|
2537
2427
|
}
|
|
2538
2428
|
|
|
2539
|
-
// node/vite/staticCopy.ts
|
|
2540
|
-
import { existsSync as existsSync7 } from "node:fs";
|
|
2541
|
-
import { join as join11 } from "node:path";
|
|
2542
|
-
async function createStaticCopyPlugin({ themeRoots, addonRoots }, pluginOptions) {
|
|
2543
|
-
const publicDirs = [...themeRoots, ...addonRoots].map((i) => join11(i, "public")).filter(existsSync7);
|
|
2544
|
-
if (!publicDirs.length)
|
|
2545
|
-
return;
|
|
2546
|
-
const { viteStaticCopy } = await import("vite-plugin-static-copy");
|
|
2547
|
-
return viteStaticCopy({
|
|
2548
|
-
silent: true,
|
|
2549
|
-
targets: publicDirs.map((dir) => ({
|
|
2550
|
-
src: `${dir}/*`,
|
|
2551
|
-
dest: "theme"
|
|
2552
|
-
})),
|
|
2553
|
-
...pluginOptions.staticCopy
|
|
2554
|
-
});
|
|
2555
|
-
}
|
|
2556
|
-
|
|
2557
2429
|
// node/vite/index.ts
|
|
2558
|
-
|
|
2430
|
+
function ViteSlidevPlugin(options, pluginOptions = {}, serverOptions = {}) {
|
|
2559
2431
|
return Promise.all([
|
|
2560
2432
|
createSlidesLoader(options, serverOptions),
|
|
2561
2433
|
createMarkdownPlugin(options, pluginOptions),
|
|
@@ -2593,7 +2465,7 @@ async function resolveViteConfigs(options, baseConfig, overrideConfigs, command,
|
|
|
2593
2465
|
};
|
|
2594
2466
|
const files = options.roots.map((i) => join12(i, "vite.config.ts"));
|
|
2595
2467
|
for (const file of files) {
|
|
2596
|
-
if (!
|
|
2468
|
+
if (!existsSync7(file))
|
|
2597
2469
|
continue;
|
|
2598
2470
|
const viteConfig = await loadConfigFromFile(configEnv, file);
|
|
2599
2471
|
if (!viteConfig?.config)
|
|
@@ -2613,15 +2485,204 @@ async function resolveViteConfigs(options, baseConfig, overrideConfigs, command,
|
|
|
2613
2485
|
return baseConfig;
|
|
2614
2486
|
}
|
|
2615
2487
|
|
|
2488
|
+
// node/setups/indexHtml.ts
|
|
2489
|
+
function toAttrValue(unsafe) {
|
|
2490
|
+
return JSON.stringify(escapeHtml(String(unsafe)));
|
|
2491
|
+
}
|
|
2492
|
+
function setupIndexHtml({ mode, entry, clientRoot, userRoot, roots, data }) {
|
|
2493
|
+
let main = readFileSync2(join13(clientRoot, "index.html"), "utf-8");
|
|
2494
|
+
let head = "";
|
|
2495
|
+
let body = "";
|
|
2496
|
+
const { info, author, keywords } = data.headmatter;
|
|
2497
|
+
head += [
|
|
2498
|
+
`<meta name="slidev:version" content="${version}">`,
|
|
2499
|
+
mode === "dev" && `<meta charset="slidev:entry" content="${slash4(entry)}">`,
|
|
2500
|
+
`<link rel="icon" href="${data.config.favicon}">`,
|
|
2501
|
+
`<title>${getSlideTitle(data)}</title>`,
|
|
2502
|
+
info && `<meta name="description" content=${toAttrValue(info)}>`,
|
|
2503
|
+
author && `<meta name="author" content=${toAttrValue(author)}>`,
|
|
2504
|
+
keywords && `<meta name="keywords" content=${toAttrValue(Array.isArray(keywords) ? keywords.join(", ") : keywords)}>`
|
|
2505
|
+
].filter(Boolean).join("\n");
|
|
2506
|
+
for (const root of roots) {
|
|
2507
|
+
const path4 = join13(root, "index.html");
|
|
2508
|
+
if (!existsSync8(path4))
|
|
2509
|
+
continue;
|
|
2510
|
+
const index = readFileSync2(path4, "utf-8");
|
|
2511
|
+
if (root === userRoot && index.includes("<!DOCTYPE")) {
|
|
2512
|
+
console.error(yellow2(`[Slidev] Ignored provided index.html with doctype declaration. (${white(path4)})`));
|
|
2513
|
+
console.error(yellow2("This file may be generated by Slidev, please remove it from your project."));
|
|
2514
|
+
continue;
|
|
2515
|
+
}
|
|
2516
|
+
head += `
|
|
2517
|
+
${(index.match(/<head>([\s\S]*?)<\/head>/i)?.[1] || "").trim()}`;
|
|
2518
|
+
body += `
|
|
2519
|
+
${(index.match(/<body>([\s\S]*?)<\/body>/i)?.[1] || "").trim()}`;
|
|
2520
|
+
}
|
|
2521
|
+
if (data.features.tweet)
|
|
2522
|
+
body += '\n<script async src="https://platform.twitter.com/widgets.js"></script>';
|
|
2523
|
+
if (data.config.fonts.webfonts.length && data.config.fonts.provider !== "none")
|
|
2524
|
+
head += `
|
|
2525
|
+
<link rel="stylesheet" href="${generateGoogleFontsUrl(data.config.fonts)}" type="text/css">`;
|
|
2526
|
+
if (data.headmatter.lang)
|
|
2527
|
+
main = main.replace('<html lang="en">', `<html lang="${data.headmatter.lang}">`);
|
|
2528
|
+
main = main.replace("__ENTRY__", toAtFS(join13(clientRoot, "main.ts"))).replace("<!-- head -->", head).replace("<!-- body -->", body);
|
|
2529
|
+
return main;
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
// node/setups/shiki.ts
|
|
2533
|
+
import fs9 from "node:fs/promises";
|
|
2534
|
+
import { bundledLanguages, createHighlighter } from "shiki";
|
|
2535
|
+
var cachedRoots;
|
|
2536
|
+
var cachedShiki;
|
|
2537
|
+
async function setupShiki(roots) {
|
|
2538
|
+
if (cachedRoots === roots)
|
|
2539
|
+
return cachedShiki;
|
|
2540
|
+
cachedShiki?.shiki.dispose();
|
|
2541
|
+
const options = await loadSetups(
|
|
2542
|
+
roots,
|
|
2543
|
+
"shiki.ts",
|
|
2544
|
+
[{
|
|
2545
|
+
/** @deprecated */
|
|
2546
|
+
async loadTheme(path4) {
|
|
2547
|
+
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.");
|
|
2548
|
+
return JSON.parse(await fs9.readFile(path4, "utf-8"));
|
|
2549
|
+
}
|
|
2550
|
+
}]
|
|
2551
|
+
);
|
|
2552
|
+
const mergedOptions = Object.assign({}, ...options);
|
|
2553
|
+
if ("theme" in mergedOptions && "themes" in mergedOptions)
|
|
2554
|
+
delete mergedOptions.theme;
|
|
2555
|
+
if (mergedOptions.theme && typeof mergedOptions.theme !== "string" && !mergedOptions.theme.name && !mergedOptions.theme.tokenColors) {
|
|
2556
|
+
mergedOptions.themes = mergedOptions.theme;
|
|
2557
|
+
delete mergedOptions.theme;
|
|
2558
|
+
}
|
|
2559
|
+
if (!mergedOptions.theme && !mergedOptions.themes) {
|
|
2560
|
+
mergedOptions.themes = {
|
|
2561
|
+
dark: "vitesse-dark",
|
|
2562
|
+
light: "vitesse-light"
|
|
2563
|
+
};
|
|
2564
|
+
}
|
|
2565
|
+
if (mergedOptions.themes)
|
|
2566
|
+
mergedOptions.defaultColor = false;
|
|
2567
|
+
const shiki = await createHighlighter({
|
|
2568
|
+
...mergedOptions,
|
|
2569
|
+
langs: mergedOptions.langs ?? Object.keys(bundledLanguages),
|
|
2570
|
+
themes: "themes" in mergedOptions ? Object.values(mergedOptions.themes) : [mergedOptions.theme]
|
|
2571
|
+
});
|
|
2572
|
+
cachedRoots = roots;
|
|
2573
|
+
return cachedShiki = {
|
|
2574
|
+
shiki,
|
|
2575
|
+
shikiOptions: mergedOptions
|
|
2576
|
+
};
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2579
|
+
// node/options.ts
|
|
2580
|
+
var debug = Debug("slidev:options");
|
|
2581
|
+
async function resolveOptions(entryOptions, mode) {
|
|
2582
|
+
const entry = await resolveEntry(entryOptions.entry);
|
|
2583
|
+
const rootsInfo = await getRoots(entry);
|
|
2584
|
+
const loaded = await parser.load(rootsInfo.userRoot, entry, void 0, mode);
|
|
2585
|
+
let themeRaw = entryOptions.theme || loaded.headmatter.theme;
|
|
2586
|
+
themeRaw = themeRaw === null ? "none" : themeRaw || "default";
|
|
2587
|
+
const [theme, themeRoot] = await resolveTheme(themeRaw, entry);
|
|
2588
|
+
const themeRoots = themeRoot ? [themeRoot] : [];
|
|
2589
|
+
const themeMeta = themeRoot ? await getThemeMeta(theme, themeRoot) : void 0;
|
|
2590
|
+
const config = parser.resolveConfig(loaded.headmatter, themeMeta, entryOptions.entry);
|
|
2591
|
+
const addonRoots = await resolveAddons(config.addons);
|
|
2592
|
+
const roots = uniq5([...themeRoots, ...addonRoots, rootsInfo.userRoot]);
|
|
2593
|
+
if (entryOptions.download)
|
|
2594
|
+
config.download ||= entryOptions.download;
|
|
2595
|
+
debug({
|
|
2596
|
+
...rootsInfo,
|
|
2597
|
+
...entryOptions,
|
|
2598
|
+
config,
|
|
2599
|
+
mode,
|
|
2600
|
+
entry,
|
|
2601
|
+
themeRaw,
|
|
2602
|
+
theme,
|
|
2603
|
+
themeRoots,
|
|
2604
|
+
addonRoots,
|
|
2605
|
+
roots
|
|
2606
|
+
});
|
|
2607
|
+
const data = {
|
|
2608
|
+
...loaded,
|
|
2609
|
+
config,
|
|
2610
|
+
themeMeta
|
|
2611
|
+
};
|
|
2612
|
+
const resolved = {
|
|
2613
|
+
...rootsInfo,
|
|
2614
|
+
...entryOptions,
|
|
2615
|
+
data,
|
|
2616
|
+
mode,
|
|
2617
|
+
entry,
|
|
2618
|
+
themeRaw,
|
|
2619
|
+
theme,
|
|
2620
|
+
themeRoots,
|
|
2621
|
+
addonRoots,
|
|
2622
|
+
roots
|
|
2623
|
+
};
|
|
2624
|
+
return {
|
|
2625
|
+
...resolved,
|
|
2626
|
+
utils: await createDataUtils(resolved)
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
async function createDataUtils(resolved) {
|
|
2630
|
+
const monacoTypesIgnorePackagesMatches = (resolved.data.config.monacoTypesIgnorePackages || []).map((i) => mm.matcher(i));
|
|
2631
|
+
let _layouts_cache_time = 0;
|
|
2632
|
+
let _layouts_cache = {};
|
|
2633
|
+
return {
|
|
2634
|
+
...await setupShiki(resolved.roots),
|
|
2635
|
+
indexHtml: setupIndexHtml(resolved),
|
|
2636
|
+
define: getDefine(resolved),
|
|
2637
|
+
iconsResolvePath: [resolved.clientRoot, ...resolved.roots].reverse(),
|
|
2638
|
+
isMonacoTypesIgnored: (pkg) => monacoTypesIgnorePackagesMatches.some((i) => i(pkg)),
|
|
2639
|
+
getLayouts: () => {
|
|
2640
|
+
const now = Date.now();
|
|
2641
|
+
if (now - _layouts_cache_time < 2e3)
|
|
2642
|
+
return _layouts_cache;
|
|
2643
|
+
const layouts = {};
|
|
2644
|
+
for (const root of [resolved.clientRoot, ...resolved.roots]) {
|
|
2645
|
+
const layoutPaths = fg4.sync("layouts/**/*.{vue,ts}", {
|
|
2646
|
+
cwd: root,
|
|
2647
|
+
absolute: true,
|
|
2648
|
+
suppressErrors: true
|
|
2649
|
+
});
|
|
2650
|
+
for (const layoutPath of layoutPaths) {
|
|
2651
|
+
const layoutName = path3.basename(layoutPath).replace(/\.\w+$/, "");
|
|
2652
|
+
layouts[layoutName] = layoutPath;
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
_layouts_cache_time = now;
|
|
2656
|
+
_layouts_cache = layouts;
|
|
2657
|
+
return layouts;
|
|
2658
|
+
}
|
|
2659
|
+
};
|
|
2660
|
+
}
|
|
2661
|
+
function getDefine(options) {
|
|
2662
|
+
return {
|
|
2663
|
+
__DEV__: options.mode === "dev" ? "true" : "false",
|
|
2664
|
+
__SLIDEV_CLIENT_ROOT__: JSON.stringify(toAtFS(options.clientRoot)),
|
|
2665
|
+
__SLIDEV_HASH_ROUTE__: JSON.stringify(options.data.config.routerMode === "hash"),
|
|
2666
|
+
__SLIDEV_FEATURE_DRAWINGS__: JSON.stringify(options.data.config.drawings.enabled === true || options.data.config.drawings.enabled === options.mode),
|
|
2667
|
+
__SLIDEV_FEATURE_EDITOR__: JSON.stringify(options.mode === "dev" && options.data.config.editor !== false),
|
|
2668
|
+
__SLIDEV_FEATURE_DRAWINGS_PERSIST__: JSON.stringify(!!options.data.config.drawings.persist === true),
|
|
2669
|
+
__SLIDEV_FEATURE_RECORD__: JSON.stringify(options.data.config.record === true || options.data.config.record === options.mode),
|
|
2670
|
+
__SLIDEV_FEATURE_PRESENTER__: JSON.stringify(options.data.config.presenter === true || options.data.config.presenter === options.mode),
|
|
2671
|
+
__SLIDEV_FEATURE_PRINT__: JSON.stringify(options.mode === "export" || options.mode === "build" && [true, "true", "auto"].includes(options.data.config.download)),
|
|
2672
|
+
__SLIDEV_FEATURE_WAKE_LOCK__: JSON.stringify(options.data.config.wakeLock === true || options.data.config.wakeLock === options.mode),
|
|
2673
|
+
__SLIDEV_HAS_SERVER__: options.mode !== "build" ? "true" : "false"
|
|
2674
|
+
};
|
|
2675
|
+
}
|
|
2676
|
+
|
|
2616
2677
|
export {
|
|
2617
|
-
resolveViteConfigs,
|
|
2618
|
-
parser,
|
|
2619
2678
|
version,
|
|
2679
|
+
resolveAddons,
|
|
2620
2680
|
resolveTheme,
|
|
2621
2681
|
getThemeMeta,
|
|
2622
|
-
|
|
2682
|
+
parser,
|
|
2623
2683
|
loadSetups,
|
|
2624
2684
|
resolveOptions,
|
|
2625
2685
|
createDataUtils,
|
|
2626
|
-
ViteSlidevPlugin
|
|
2686
|
+
ViteSlidevPlugin,
|
|
2687
|
+
resolveViteConfigs
|
|
2627
2688
|
};
|