@slidev/cli 52.8.0 → 52.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{build-Co9SDEv9.mjs → build-C0y4MWcQ.mjs} +4 -4
- package/dist/cli.mjs +6 -6
- package/dist/{export-dSJYnjas.mjs → export-snweM1-1.mjs} +1 -1
- package/dist/index.mjs +3 -3
- package/dist/{resolver-Dl3RCceV.mjs → resolver-Du-CxvL9.mjs} +48 -32
- package/dist/{serve-DiGMRooB.mjs → serve-BrA39NVM.mjs} +1 -1
- package/dist/{shared-OlAiAU1s.mjs → shared-D3BW4vqA.mjs} +295 -202
- package/package.json +5 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as resolveViteConfigs } from "./shared-
|
|
2
|
-
import "./resolver-
|
|
1
|
+
import { t as resolveViteConfigs } from "./shared-D3BW4vqA.mjs";
|
|
2
|
+
import "./resolver-Du-CxvL9.mjs";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import { join, resolve } from "node:path";
|
|
5
5
|
import { build as build$1 } from "vite";
|
|
@@ -45,7 +45,7 @@ async function build(options, viteConfig = {}, args) {
|
|
|
45
45
|
dev: true
|
|
46
46
|
}));
|
|
47
47
|
server.listen(port);
|
|
48
|
-
const { exportSlides } = await import("./export-
|
|
48
|
+
const { exportSlides } = await import("./export-snweM1-1.mjs");
|
|
49
49
|
const tempDir = resolve(outDir, "temp");
|
|
50
50
|
await fs.mkdir(tempDir, { recursive: true });
|
|
51
51
|
await exportSlides({
|
|
@@ -86,7 +86,7 @@ async function build(options, viteConfig = {}, args) {
|
|
|
86
86
|
"true",
|
|
87
87
|
"auto"
|
|
88
88
|
].includes(options.data.config.download)) {
|
|
89
|
-
const { exportSlides, getExportOptions } = await import("./export-
|
|
89
|
+
const { exportSlides, getExportOptions } = await import("./export-snweM1-1.mjs");
|
|
90
90
|
const port = 12445;
|
|
91
91
|
const app = connect();
|
|
92
92
|
const server = http.createServer(app);
|
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as loadSetups, c as resolveTheme, d as version, i as resolveOptions, l as resolveAddons, o as parser, s as getThemeMeta, u as updateFrontmatterPatch } from "./shared-
|
|
2
|
-
import { i as resolveEntry, n as getRoots, r as isInstalledGlobally } from "./resolver-
|
|
3
|
-
import { t as createServer } from "./serve-
|
|
1
|
+
import { a as loadSetups, c as resolveTheme, d as version, i as resolveOptions, l as resolveAddons, o as parser, s as getThemeMeta, u as updateFrontmatterPatch } from "./shared-D3BW4vqA.mjs";
|
|
2
|
+
import { i as resolveEntry, n as getRoots, r as isInstalledGlobally } from "./resolver-Du-CxvL9.mjs";
|
|
3
|
+
import { t as createServer } from "./serve-BrA39NVM.mjs";
|
|
4
4
|
import { exec } from "node:child_process";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
6
6
|
import os from "node:os";
|
|
@@ -292,7 +292,7 @@ cli.command("build [entry..]", "Build hostable SPA", (args) => exportOptions(com
|
|
|
292
292
|
describe: "enable the inspect plugin for debugging"
|
|
293
293
|
}).strict().help(), async (args) => {
|
|
294
294
|
const { entry, theme, base, download, out, inspect } = args;
|
|
295
|
-
const { build } = await import("./build-
|
|
295
|
+
const { build } = await import("./build-C0y4MWcQ.mjs");
|
|
296
296
|
for (const entryFile of entry) {
|
|
297
297
|
const options = await resolveOptions({
|
|
298
298
|
entry: entryFile,
|
|
@@ -355,7 +355,7 @@ cli.command("theme [subcommand]", "Theme related operations", (command) => {
|
|
|
355
355
|
});
|
|
356
356
|
cli.command("export [entry..]", "Export slides to PDF", (args) => exportOptions(commonOptions(args)).strict().help(), async (args) => {
|
|
357
357
|
const { entry, theme } = args;
|
|
358
|
-
const { exportSlides, getExportOptions } = await import("./export-
|
|
358
|
+
const { exportSlides, getExportOptions } = await import("./export-snweM1-1.mjs");
|
|
359
359
|
const port = await getPort(12445);
|
|
360
360
|
let warned = false;
|
|
361
361
|
for (const entryFile of entry) {
|
|
@@ -402,7 +402,7 @@ cli.command("export-notes [entry..]", "Export slide notes to PDF", (args) => arg
|
|
|
402
402
|
type: "number",
|
|
403
403
|
describe: "wait for the specified ms before exporting"
|
|
404
404
|
}).strict().help(), async ({ entry, output, timeout, wait }) => {
|
|
405
|
-
const { exportNotes } = await import("./export-
|
|
405
|
+
const { exportNotes } = await import("./export-snweM1-1.mjs");
|
|
406
406
|
const port = await getPort(12445);
|
|
407
407
|
for (const entryFile of entry) {
|
|
408
408
|
const options = await resolveOptions({ entry: entryFile }, "export");
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as resolveOptions, n as ViteSlidevPlugin, o as parser, r as createDataUtils } from "./shared-
|
|
2
|
-
import "./resolver-
|
|
3
|
-
import { t as createServer } from "./serve-
|
|
1
|
+
import { i as resolveOptions, n as ViteSlidevPlugin, o as parser, r as createDataUtils } from "./shared-D3BW4vqA.mjs";
|
|
2
|
+
import "./resolver-Du-CxvL9.mjs";
|
|
3
|
+
import { t as createServer } from "./serve-BrA39NVM.mjs";
|
|
4
4
|
|
|
5
5
|
export { ViteSlidevPlugin, createDataUtils, createServer, parser, resolveOptions };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import { copyFile, readFile } from "node:fs/promises";
|
|
1
2
|
import { dirname, join, relative, resolve } from "node:path";
|
|
2
3
|
import process from "node:process";
|
|
3
4
|
import { underline, yellow } from "ansis";
|
|
4
|
-
import
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { ensurePrefix, slash } from "@antfu/utils";
|
|
7
|
-
import { resolvePath } from "mlly";
|
|
8
7
|
import { parseNi, run } from "@antfu/ni";
|
|
8
|
+
import { ensurePrefix, slash } from "@antfu/utils";
|
|
9
9
|
import globalDirs from "global-directory";
|
|
10
|
+
import { resolvePath } from "mlly";
|
|
10
11
|
import prompts from "prompts";
|
|
11
12
|
import { resolveGlobal } from "resolve-global";
|
|
12
13
|
import { findClosestPkgJsonPath, findDepPkgJsonPath } from "vitefu";
|
|
@@ -39,23 +40,29 @@ async function findPkgRoot(dep, parent, ensure = false) {
|
|
|
39
40
|
return path$1;
|
|
40
41
|
}
|
|
41
42
|
async function findGlobalPkgRoot(name, ensure = false) {
|
|
43
|
+
const localPath = await findDepPkgJsonPath(name, cliRoot);
|
|
44
|
+
if (localPath) return dirname(localPath);
|
|
42
45
|
const yarnPath = join(globalDirs.yarn.packages, name);
|
|
43
|
-
if (
|
|
46
|
+
if (existsSync(`${yarnPath}/package.json`)) return yarnPath;
|
|
44
47
|
const npmPath = join(globalDirs.npm.packages, name);
|
|
45
|
-
if (
|
|
48
|
+
if (existsSync(`${npmPath}/package.json`)) return npmPath;
|
|
46
49
|
if (ensure) throw new Error(`Failed to resolve global package "${name}"`);
|
|
47
50
|
}
|
|
48
51
|
async function resolveEntry(entryRaw) {
|
|
49
|
-
if (!
|
|
52
|
+
if (!existsSync(entryRaw) && !entryRaw.endsWith(".md") && !/[/\\]/.test(entryRaw)) entryRaw += ".md";
|
|
50
53
|
const entry = resolve(entryRaw);
|
|
51
|
-
if (!
|
|
54
|
+
if (!existsSync(entry)) {
|
|
55
|
+
if (!process.stdin.isTTY) {
|
|
56
|
+
console.error(`Entry file "${entry}" does not exist and cannot prompt for confirmation`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
52
59
|
const { create } = await prompts({
|
|
53
60
|
name: "create",
|
|
54
61
|
type: "confirm",
|
|
55
62
|
initial: "Y",
|
|
56
63
|
message: `Entry file ${yellow(`"${entry}"`)} does not exist, do you want to create it?`
|
|
57
64
|
});
|
|
58
|
-
if (create)
|
|
65
|
+
if (create) await copyFile(resolve(cliRoot, "template.md"), entry);
|
|
59
66
|
else process.exit(0);
|
|
60
67
|
}
|
|
61
68
|
return slash(entry);
|
|
@@ -65,6 +72,10 @@ async function resolveEntry(entryRaw) {
|
|
|
65
72
|
*/
|
|
66
73
|
function createResolver(type, officials) {
|
|
67
74
|
async function promptForInstallation(pkgName) {
|
|
75
|
+
if (!process.stdin.isTTY) {
|
|
76
|
+
console.error(`The ${type} "${pkgName}" was not found and cannot prompt for installation`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
68
79
|
const { confirm } = await prompts({
|
|
69
80
|
name: "confirm",
|
|
70
81
|
initial: "Y",
|
|
@@ -81,16 +92,9 @@ function createResolver(type, officials) {
|
|
|
81
92
|
if (name[0] === "/") return [name, name];
|
|
82
93
|
if (name.startsWith("@/")) return [name, resolve(userRoot, name.slice(2))];
|
|
83
94
|
if (name[0] === "." || name[0] !== "@" && name.includes("/")) return [name, resolve(dirname(importer), name)];
|
|
84
|
-
if (name.startsWith(`@slidev/${type}-`) || name.startsWith(`slidev-${type}-`)) {
|
|
85
|
-
if (!await findPkgRoot(name, importer)) await promptForInstallation(name);
|
|
86
|
-
return [name, await findPkgRoot(name, importer, true)];
|
|
87
|
-
}
|
|
88
95
|
{
|
|
89
|
-
const possiblePkgNames = [
|
|
90
|
-
|
|
91
|
-
`slidev-${type}-${name}`,
|
|
92
|
-
name
|
|
93
|
-
];
|
|
96
|
+
const possiblePkgNames = [name];
|
|
97
|
+
if (!name.includes("/") && !name.startsWith("@")) possiblePkgNames.push(`@slidev/${type}-${name}`, `slidev-${type}-${name}`);
|
|
94
98
|
for (const pkgName$1 of possiblePkgNames) {
|
|
95
99
|
const pkgRoot = await findPkgRoot(pkgName$1, importer);
|
|
96
100
|
if (pkgRoot) return [pkgName$1, pkgRoot];
|
|
@@ -101,29 +105,25 @@ function createResolver(type, officials) {
|
|
|
101
105
|
return [pkgName, await findPkgRoot(pkgName, importer, true)];
|
|
102
106
|
};
|
|
103
107
|
}
|
|
104
|
-
function getUserPkgJson(userRoot) {
|
|
108
|
+
async function getUserPkgJson(userRoot) {
|
|
105
109
|
const path$1 = resolve(userRoot, "package.json");
|
|
106
|
-
if (
|
|
110
|
+
if (existsSync(path$1)) return JSON.parse(await readFile(path$1, "utf-8"));
|
|
107
111
|
return {};
|
|
108
112
|
}
|
|
109
|
-
function hasWorkspacePackageJSON(root) {
|
|
113
|
+
async function hasWorkspacePackageJSON(root) {
|
|
110
114
|
const path$1 = join(root, "package.json");
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
} catch {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
return !!(JSON.parse(fs$1.readFileSync(path$1, "utf-8")) || {}).workspaces;
|
|
115
|
+
if (!existsSync(path$1)) return false;
|
|
116
|
+
return !!(JSON.parse(await readFile(path$1, "utf-8")) || {}).workspaces;
|
|
117
117
|
}
|
|
118
118
|
function hasRootFile(root) {
|
|
119
|
-
return ["pnpm-workspace.yaml"].some((file) =>
|
|
119
|
+
return ["pnpm-workspace.yaml"].some((file) => existsSync(join(root, file)));
|
|
120
120
|
}
|
|
121
121
|
/**
|
|
122
122
|
* Search up for the nearest workspace root
|
|
123
123
|
*/
|
|
124
|
-
function searchForWorkspaceRoot(current, root = current) {
|
|
124
|
+
async function searchForWorkspaceRoot(current, root = current) {
|
|
125
125
|
if (hasRootFile(current)) return current;
|
|
126
|
-
if (hasWorkspacePackageJSON(current)) return current;
|
|
126
|
+
if (await hasWorkspacePackageJSON(current)) return current;
|
|
127
127
|
const dir = dirname(current);
|
|
128
128
|
if (!dir || dir === current) return root;
|
|
129
129
|
return searchForWorkspaceRoot(dir, root);
|
|
@@ -140,11 +140,27 @@ async function getRoots(entry) {
|
|
|
140
140
|
cliRoot,
|
|
141
141
|
clientRoot,
|
|
142
142
|
userRoot,
|
|
143
|
-
userPkgJson: getUserPkgJson(closestPkgRoot),
|
|
144
|
-
userWorkspaceRoot: searchForWorkspaceRoot(closestPkgRoot)
|
|
143
|
+
userPkgJson: await getUserPkgJson(closestPkgRoot),
|
|
144
|
+
userWorkspaceRoot: await searchForWorkspaceRoot(closestPkgRoot)
|
|
145
145
|
};
|
|
146
146
|
return rootsInfo;
|
|
147
147
|
}
|
|
148
|
+
function resolveSourceFiles(roots, subpath, extensions = [
|
|
149
|
+
".mjs",
|
|
150
|
+
".js",
|
|
151
|
+
".mts",
|
|
152
|
+
".ts"
|
|
153
|
+
]) {
|
|
154
|
+
const results = [];
|
|
155
|
+
for (const root of roots) for (const ext of extensions) {
|
|
156
|
+
const fullPath = join(root, subpath + ext);
|
|
157
|
+
if (existsSync(fullPath)) {
|
|
158
|
+
results.push(fullPath);
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return results;
|
|
163
|
+
}
|
|
148
164
|
|
|
149
165
|
//#endregion
|
|
150
|
-
export { resolveImportPath as a, resolveEntry as i, getRoots as n, resolveImportUrl as o, isInstalledGlobally as r,
|
|
166
|
+
export { resolveImportPath as a, toAtFS as c, resolveEntry as i, getRoots as n, resolveImportUrl as o, isInstalledGlobally as r, resolveSourceFiles as s, createResolver as t };
|
|
@@ -1,39 +1,41 @@
|
|
|
1
|
-
import { a as resolveImportPath, i as resolveEntry, n as getRoots, o as resolveImportUrl, r as isInstalledGlobally, s as
|
|
1
|
+
import { a as resolveImportPath, c as toAtFS, i as resolveEntry, n as getRoots, o as resolveImportUrl, r as isInstalledGlobally, s as resolveSourceFiles, t as createResolver } from "./resolver-Du-CxvL9.mjs";
|
|
2
2
|
import { builtinModules } from "node:module";
|
|
3
3
|
import fs, { readFile } from "node:fs/promises";
|
|
4
4
|
import path, { basename, dirname, join, resolve } from "node:path";
|
|
5
5
|
import { bold, gray, red, white, yellow } from "ansis";
|
|
6
6
|
import equal from "fast-deep-equal";
|
|
7
7
|
import { loadConfigFromFile, mergeConfig } from "vite";
|
|
8
|
-
import fs$1, { existsSync, readFileSync } from "node:fs";
|
|
9
8
|
import MarkdownIt from "markdown-it";
|
|
9
|
+
import fs$1, { existsSync } from "node:fs";
|
|
10
10
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
11
|
+
import { isString, isTruthy, notNullish, objectEntries, objectMap, range, slash, uniq } from "@antfu/utils";
|
|
12
|
+
import { createResolve } from "mlly";
|
|
13
|
+
import { findDepPkgJsonPath } from "vitefu";
|
|
11
14
|
import { createJiti } from "jiti";
|
|
12
15
|
import YAML from "yaml";
|
|
13
|
-
import { isString, isTruthy, notNullish, objectEntries, objectMap, range, slash, uniq } from "@antfu/utils";
|
|
14
16
|
import IconsResolver from "unplugin-icons/resolver";
|
|
15
17
|
import Components from "unplugin-vue-components/vite";
|
|
16
|
-
import { createResolve } from "mlly";
|
|
17
|
-
import { findDepPkgJsonPath } from "vitefu";
|
|
18
18
|
import Icons from "unplugin-icons/vite";
|
|
19
19
|
import * as parser from "@slidev/parser/fs";
|
|
20
|
-
import Debug from "debug";
|
|
21
20
|
import fg from "fast-glob";
|
|
21
|
+
import { createDebug } from "obug";
|
|
22
22
|
import pm from "picomatch";
|
|
23
23
|
import { satisfies } from "semver";
|
|
24
24
|
import { escapeHtml } from "markdown-it/lib/common/utils.mjs";
|
|
25
25
|
import { createHead, extractUnheadInputFromHtml, transformHtmlTemplate } from "unhead/server";
|
|
26
|
-
import {
|
|
26
|
+
import { createSingletonShorthands, createdBundledHighlighter } from "shiki/core";
|
|
27
|
+
import { createJavaScriptRegexEngine } from "shiki/engine/javascript";
|
|
28
|
+
import { bundledLanguages, bundledThemes } from "shiki";
|
|
27
29
|
import katex from "katex";
|
|
28
30
|
import MagicString from "magic-string-stack";
|
|
29
31
|
import Markdown from "unplugin-vue-markdown/vite";
|
|
30
32
|
import Token from "markdown-it/lib/token.mjs";
|
|
31
33
|
import MarkdownItFootnote from "markdown-it-footnote";
|
|
32
34
|
import MarkdownItMdc from "markdown-it-mdc";
|
|
33
|
-
import {
|
|
35
|
+
import { fromAsyncCodeToHtml } from "@shikijs/markdown-it/async";
|
|
34
36
|
import { SourceMapConsumer } from "source-map-js";
|
|
35
37
|
import lz from "lz-string";
|
|
36
|
-
import {
|
|
38
|
+
import { toKeyedTokens } from "shiki-magic-move/core";
|
|
37
39
|
import { encode } from "plantuml-encoder";
|
|
38
40
|
import ServerRef from "vite-plugin-vue-server-ref";
|
|
39
41
|
import UnoCSS from "unocss/vite";
|
|
@@ -42,7 +44,7 @@ import Vue from "@vitejs/plugin-vue";
|
|
|
42
44
|
import VueJsx from "@vitejs/plugin-vue-jsx";
|
|
43
45
|
|
|
44
46
|
//#region package.json
|
|
45
|
-
var version = "52.
|
|
47
|
+
var version = "52.9.1";
|
|
46
48
|
|
|
47
49
|
//#endregion
|
|
48
50
|
//#region node/syntax/markdown-it/markdown-it-link.ts
|
|
@@ -252,7 +254,8 @@ const INCLUDE_GLOBAL = [
|
|
|
252
254
|
"prettier",
|
|
253
255
|
"recordrtc",
|
|
254
256
|
"typescript",
|
|
255
|
-
"yaml"
|
|
257
|
+
"yaml",
|
|
258
|
+
"pptxgenjs"
|
|
256
259
|
];
|
|
257
260
|
const INCLUDE_LOCAL = INCLUDE_GLOBAL.map((i) => `@slidev/cli > @slidev/client > ${i}`);
|
|
258
261
|
const EXCLUDE_GLOBAL = [
|
|
@@ -444,7 +447,7 @@ function createLayoutWrapperPlugin({ data, utils }) {
|
|
|
444
447
|
const [, no, type] = match;
|
|
445
448
|
if (type !== "md") return;
|
|
446
449
|
const index = +no - 1;
|
|
447
|
-
const layouts = utils.getLayouts();
|
|
450
|
+
const layouts = await utils.getLayouts();
|
|
448
451
|
let layoutName = (data.slides[index]?.frontmatter?.layout ?? data.slides[0]?.frontmatter?.defaults?.layout) || (index === 0 ? "cover" : "default");
|
|
449
452
|
if (!layouts[layoutName]) {
|
|
450
453
|
console.error(red(`\nUnknown layout "${bold(layoutName)}".${yellow(" Available layouts are:")}`) + Object.keys(layouts).map((i, idx) => (idx % 3 === 0 ? "\n " : "") + gray(i.padEnd(15, " "))).join(" "));
|
|
@@ -520,13 +523,13 @@ function toAttrValue(unsafe) {
|
|
|
520
523
|
return JSON.stringify(escapeHtml(String(unsafe)));
|
|
521
524
|
}
|
|
522
525
|
async function setupIndexHtml({ mode, entry, clientRoot, userRoot, roots, data, base }) {
|
|
523
|
-
let main =
|
|
526
|
+
let main = await readFile(join(clientRoot, "index.html"), "utf-8");
|
|
524
527
|
let body = "";
|
|
525
528
|
const inputs = [];
|
|
526
529
|
for (const root of roots) {
|
|
527
530
|
const path$1 = join(root, "index.html");
|
|
528
531
|
if (!existsSync(path$1)) continue;
|
|
529
|
-
const html =
|
|
532
|
+
const html = await readFile(path$1, "utf-8");
|
|
530
533
|
if (root === userRoot && html.includes("<!DOCTYPE")) {
|
|
531
534
|
console.error(yellow(`[Slidev] Ignored provided index.html with doctype declaration. (${white(path$1)})`));
|
|
532
535
|
console.error(yellow("This file may be generated by Slidev, please remove it from your project."));
|
|
@@ -629,8 +632,13 @@ async function setupIndexHtml({ mode, entry, clientRoot, userRoot, roots, data,
|
|
|
629
632
|
}
|
|
630
633
|
].filter((x) => x.content)
|
|
631
634
|
}, ...inputs] });
|
|
632
|
-
const
|
|
633
|
-
|
|
635
|
+
const mainUrl = toAtFS(join(clientRoot, "main.ts"));
|
|
636
|
+
if (mode === "build") main = main.replace("__ENTRY__", mainUrl);
|
|
637
|
+
else {
|
|
638
|
+
const basePrefix = base ? base.slice(0, -1) : "";
|
|
639
|
+
main = main.replace("__ENTRY__", encodeURI(basePrefix + mainUrl));
|
|
640
|
+
}
|
|
641
|
+
main = main.replace("<!-- body -->", body);
|
|
634
642
|
return await transformHtmlTemplate(unhead, main);
|
|
635
643
|
}
|
|
636
644
|
|
|
@@ -658,16 +666,8 @@ async function setupKatex(roots) {
|
|
|
658
666
|
}
|
|
659
667
|
|
|
660
668
|
//#endregion
|
|
661
|
-
//#region
|
|
662
|
-
|
|
663
|
-
let cachedShiki;
|
|
664
|
-
async function setupShiki(roots) {
|
|
665
|
-
if (cachedRoots === roots) return cachedShiki;
|
|
666
|
-
cachedShiki?.shiki.dispose();
|
|
667
|
-
const options = await loadSetups(roots, "shiki.ts", [{ async loadTheme(path$1) {
|
|
668
|
-
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.");
|
|
669
|
-
return JSON.parse(await fs.readFile(path$1, "utf-8"));
|
|
670
|
-
} }]);
|
|
669
|
+
//#region ../client/setup/shiki-options.ts
|
|
670
|
+
function resolveShikiOptions(options) {
|
|
671
671
|
const mergedOptions = Object.assign({}, ...options);
|
|
672
672
|
if ("theme" in mergedOptions && "themes" in mergedOptions) delete mergedOptions.theme;
|
|
673
673
|
if (mergedOptions.theme && typeof mergedOptions.theme !== "string" && !mergedOptions.theme.name && !mergedOptions.theme.tokenColors) {
|
|
@@ -679,21 +679,89 @@ async function setupShiki(roots) {
|
|
|
679
679
|
light: "vitesse-light"
|
|
680
680
|
};
|
|
681
681
|
if (mergedOptions.themes) mergedOptions.defaultColor = false;
|
|
682
|
-
const
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
682
|
+
const themeOption = extractThemeName(mergedOptions.theme) || extractThemeNames(mergedOptions.themes || {});
|
|
683
|
+
const themeNames = typeof themeOption === "string" ? [themeOption] : Object.values(themeOption);
|
|
684
|
+
const themeInput = Object.assign({}, bundledThemes);
|
|
685
|
+
if (typeof mergedOptions.theme === "object" && mergedOptions.theme?.name) themeInput[mergedOptions.theme.name] = mergedOptions.theme;
|
|
686
|
+
if (mergedOptions.themes) {
|
|
687
|
+
for (const theme of Object.values(mergedOptions.themes)) if (typeof theme === "object" && theme?.name) themeInput[theme.name] = theme;
|
|
688
|
+
}
|
|
689
|
+
const languageNames = new Set([
|
|
690
|
+
"markdown",
|
|
691
|
+
"vue",
|
|
692
|
+
"javascript",
|
|
693
|
+
"typescript",
|
|
694
|
+
"html",
|
|
695
|
+
"css"
|
|
696
|
+
]);
|
|
697
|
+
const languageInput = Object.assign({}, bundledLanguages);
|
|
698
|
+
for (const option of options) {
|
|
699
|
+
const langs = option?.langs;
|
|
700
|
+
if (langs == null) continue;
|
|
701
|
+
if (Array.isArray(langs)) for (const lang of langs.flat()) if (typeof lang === "function") console.error(red("[slidev] `langs` option returned by setup/shiki.ts cannot be an array containing functions. Please use the record format (`{ [name]: () => {...} }`) instead."));
|
|
702
|
+
else if (typeof lang === "string") languageNames.add(lang);
|
|
703
|
+
else if (lang.name) {
|
|
704
|
+
languageNames.add(lang.name);
|
|
705
|
+
languageInput[lang.name] = lang;
|
|
706
|
+
for (const alias of lang.aliases || []) {
|
|
707
|
+
languageNames.add(alias);
|
|
708
|
+
languageInput[alias] = lang;
|
|
709
|
+
}
|
|
710
|
+
} else console.error(red("[slidev] Invalid lang option in shiki setup:"), lang);
|
|
711
|
+
else if (typeof langs === "object") {
|
|
712
|
+
for (const name of Object.keys(langs)) languageNames.add(name);
|
|
713
|
+
Object.assign(languageInput, langs);
|
|
714
|
+
} else console.error(red("[slidev] Invalid langs option in shiki setup:"), langs);
|
|
715
|
+
}
|
|
716
|
+
return {
|
|
717
|
+
options: mergedOptions,
|
|
718
|
+
themeOption,
|
|
719
|
+
themeNames,
|
|
720
|
+
themeInput,
|
|
721
|
+
languageNames,
|
|
722
|
+
languageInput
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
function extractThemeName(theme) {
|
|
726
|
+
if (!theme) return void 0;
|
|
727
|
+
if (typeof theme === "string") return theme;
|
|
728
|
+
if (!theme.name) console.warn(yellow("[slidev] Theme"), theme, yellow("does not have a name, which may cause issues."));
|
|
729
|
+
return theme.name;
|
|
730
|
+
}
|
|
731
|
+
function extractThemeNames(themes) {
|
|
732
|
+
if (!themes) return {};
|
|
733
|
+
return objectMap(themes, (key, theme) => {
|
|
734
|
+
const name = extractThemeName(theme);
|
|
735
|
+
if (!name) return void 0;
|
|
736
|
+
return [key, name];
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
//#endregion
|
|
741
|
+
//#region node/setups/shiki.ts
|
|
742
|
+
let cachedRoots;
|
|
743
|
+
let cachedShiki;
|
|
744
|
+
async function setupShiki(roots) {
|
|
745
|
+
if (cachedRoots === roots) return cachedShiki;
|
|
746
|
+
const { options, languageInput, themeInput } = resolveShikiOptions(await loadSetups(roots, "shiki.ts", [{ async loadTheme(path$1) {
|
|
747
|
+
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.");
|
|
748
|
+
return JSON.parse(await fs.readFile(path$1, "utf-8"));
|
|
749
|
+
} }]));
|
|
750
|
+
const createHighlighter = createdBundledHighlighter({
|
|
751
|
+
engine: createJavaScriptRegexEngine,
|
|
752
|
+
langs: languageInput,
|
|
753
|
+
themes: themeInput
|
|
686
754
|
});
|
|
687
755
|
cachedRoots = roots;
|
|
688
756
|
return cachedShiki = {
|
|
689
|
-
shiki,
|
|
690
|
-
shikiOptions:
|
|
757
|
+
shiki: createSingletonShorthands(createHighlighter),
|
|
758
|
+
shikiOptions: options
|
|
691
759
|
};
|
|
692
760
|
}
|
|
693
761
|
|
|
694
762
|
//#endregion
|
|
695
763
|
//#region node/options.ts
|
|
696
|
-
const debug =
|
|
764
|
+
const debug = createDebug("slidev:options");
|
|
697
765
|
async function resolveOptions(entryOptions, mode) {
|
|
698
766
|
const entry = await resolveEntry(entryOptions.entry);
|
|
699
767
|
const rootsInfo = await getRoots(entry);
|
|
@@ -748,7 +816,7 @@ async function resolveOptions(entryOptions, mode) {
|
|
|
748
816
|
async function createDataUtils(resolved) {
|
|
749
817
|
const monacoTypesIgnorePackagesMatches = (resolved.data.config.monacoTypesIgnorePackages || []).map((i) => pm.makeRe(i));
|
|
750
818
|
let _layouts_cache_time = 0;
|
|
751
|
-
let _layouts_cache =
|
|
819
|
+
let _layouts_cache = null;
|
|
752
820
|
return {
|
|
753
821
|
...await setupShiki(resolved.roots),
|
|
754
822
|
katexOptions: await setupKatex(resolved.roots),
|
|
@@ -758,22 +826,22 @@ async function createDataUtils(resolved) {
|
|
|
758
826
|
isMonacoTypesIgnored: (pkg) => monacoTypesIgnorePackagesMatches.some((i) => i.test(pkg)),
|
|
759
827
|
getLayouts: () => {
|
|
760
828
|
const now = Date.now();
|
|
761
|
-
if (now - _layouts_cache_time < 2e3) return _layouts_cache;
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
829
|
+
if (_layouts_cache && now - _layouts_cache_time < 2e3) return _layouts_cache;
|
|
830
|
+
_layouts_cache_time = now;
|
|
831
|
+
return _layouts_cache = worker();
|
|
832
|
+
async function worker() {
|
|
833
|
+
const layouts = {};
|
|
834
|
+
const layoutPaths = await Promise.all([resolved.clientRoot, ...resolved.roots].map((root) => fg("layouts/**/*.{vue,js,mjs,ts,mts}", {
|
|
765
835
|
cwd: root,
|
|
766
836
|
absolute: true,
|
|
767
837
|
suppressErrors: true
|
|
768
|
-
});
|
|
769
|
-
for (const layoutPath of layoutPaths) {
|
|
838
|
+
})));
|
|
839
|
+
for (const layoutPath of layoutPaths.flat(1)) {
|
|
770
840
|
const layoutName = path.basename(layoutPath).replace(/\.\w+$/, "");
|
|
771
841
|
layouts[layoutName] = layoutPath;
|
|
772
842
|
}
|
|
843
|
+
return layouts;
|
|
773
844
|
}
|
|
774
|
-
_layouts_cache_time = now;
|
|
775
|
-
_layouts_cache = layouts;
|
|
776
|
-
return layouts;
|
|
777
845
|
}
|
|
778
846
|
};
|
|
779
847
|
}
|
|
@@ -799,6 +867,60 @@ function getDefine(options) {
|
|
|
799
867
|
}, (v, k) => [v, JSON.stringify(k)]);
|
|
800
868
|
}
|
|
801
869
|
|
|
870
|
+
//#endregion
|
|
871
|
+
//#region node/syntax/transform/utils.ts
|
|
872
|
+
function normalizeRangeStr(rangeStr = "") {
|
|
873
|
+
return !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
|
|
874
|
+
}
|
|
875
|
+
function getCodeBlocks(md) {
|
|
876
|
+
const codeblocks = Array.from(md.matchAll(/^```[\s\S]*?^```/gm)).map((m) => {
|
|
877
|
+
const start = m.index;
|
|
878
|
+
const end = m.index + m[0].length;
|
|
879
|
+
return [
|
|
880
|
+
start,
|
|
881
|
+
end,
|
|
882
|
+
md.slice(0, start).match(/\n/g)?.length || 0,
|
|
883
|
+
md.slice(0, end).match(/\n/g)?.length || 0
|
|
884
|
+
];
|
|
885
|
+
});
|
|
886
|
+
return {
|
|
887
|
+
codeblocks,
|
|
888
|
+
isInsideCodeblocks(idx) {
|
|
889
|
+
return codeblocks.some(([s, e]) => s <= idx && idx <= e);
|
|
890
|
+
},
|
|
891
|
+
isLineInsideCodeblocks(line) {
|
|
892
|
+
return codeblocks.some(([, , s, e]) => s <= line && line <= e);
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
function getCommentBlocks(md) {
|
|
897
|
+
const commentBlocks = Array.from(md.matchAll(/<!--[\s\S]*?-->/g)).map((m) => {
|
|
898
|
+
const start = m.index;
|
|
899
|
+
const end = m.index + m[0].length;
|
|
900
|
+
return [
|
|
901
|
+
start,
|
|
902
|
+
end,
|
|
903
|
+
md.slice(0, start).match(/\n/g)?.length || 0,
|
|
904
|
+
md.slice(0, end).match(/\n/g)?.length || 0
|
|
905
|
+
];
|
|
906
|
+
});
|
|
907
|
+
return {
|
|
908
|
+
commentBlocks,
|
|
909
|
+
isInsideCommentBlocks(idx) {
|
|
910
|
+
return commentBlocks.some(([s, e]) => s <= idx && idx <= e);
|
|
911
|
+
},
|
|
912
|
+
isLineInsideCommentBlocks(line) {
|
|
913
|
+
return commentBlocks.some(([, , s, e]) => s <= line && line <= e);
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Escape `{{` in code block to prevent Vue interpret it, #99, #1316
|
|
919
|
+
*/
|
|
920
|
+
function escapeVueInCode(md) {
|
|
921
|
+
return md.replace(/\{\{/g, "{{");
|
|
922
|
+
}
|
|
923
|
+
|
|
802
924
|
//#endregion
|
|
803
925
|
//#region node/syntax/markdown-it/markdown-it-katex.ts
|
|
804
926
|
function isValidDelim(state, pos) {
|
|
@@ -896,7 +1018,7 @@ function MarkdownItKatex(md, options) {
|
|
|
896
1018
|
const katexInline = function(latex) {
|
|
897
1019
|
options.displayMode = false;
|
|
898
1020
|
try {
|
|
899
|
-
return katex.renderToString(latex, options);
|
|
1021
|
+
return escapeVueInCode(katex.renderToString(latex, options));
|
|
900
1022
|
} catch (error) {
|
|
901
1023
|
if (options.throwOnError) console.warn(error);
|
|
902
1024
|
return latex;
|
|
@@ -908,7 +1030,7 @@ function MarkdownItKatex(md, options) {
|
|
|
908
1030
|
const katexBlock = function(latex) {
|
|
909
1031
|
options.displayMode = true;
|
|
910
1032
|
try {
|
|
911
|
-
return `<p>${katex.renderToString(latex, options)}</p>`;
|
|
1033
|
+
return `<p>${escapeVueInCode(katex.renderToString(latex, options))}</p>`;
|
|
912
1034
|
} catch (error) {
|
|
913
1035
|
if (options.throwOnError) console.warn(error);
|
|
914
1036
|
return latex;
|
|
@@ -1013,9 +1135,9 @@ const templateGlobalLayers = {
|
|
|
1013
1135
|
//#region node/virtual/layouts.ts
|
|
1014
1136
|
const templateLayouts = {
|
|
1015
1137
|
id: "/@slidev/layouts",
|
|
1016
|
-
getContent({ utils }) {
|
|
1138
|
+
async getContent({ utils }) {
|
|
1017
1139
|
const imports = [];
|
|
1018
|
-
const layouts = objectMap(utils.getLayouts(), (k, v) => {
|
|
1140
|
+
const layouts = objectMap(await utils.getLayouts(), (k, v) => {
|
|
1019
1141
|
imports.push(`import __layout_${k} from "${toAtFS(v)}"`);
|
|
1020
1142
|
return [k, `__layout_${k}`];
|
|
1021
1143
|
});
|
|
@@ -1104,15 +1226,7 @@ function createSetupTemplate(name) {
|
|
|
1104
1226
|
return {
|
|
1105
1227
|
id: `/@slidev/setups/${name}`,
|
|
1106
1228
|
getContent({ roots }) {
|
|
1107
|
-
const setups = roots
|
|
1108
|
-
const path$1 = join(i, "setup", name);
|
|
1109
|
-
return [
|
|
1110
|
-
".ts",
|
|
1111
|
-
".mts",
|
|
1112
|
-
".js",
|
|
1113
|
-
".mjs"
|
|
1114
|
-
].map((ext) => path$1 + ext);
|
|
1115
|
-
}).filter((i) => existsSync(i));
|
|
1229
|
+
const setups = resolveSourceFiles(roots, `setup/${name}`);
|
|
1116
1230
|
const imports = [];
|
|
1117
1231
|
setups.forEach((path$1, idx) => {
|
|
1118
1232
|
imports.push(`import __n${idx} from '${toAtFS(path$1)}'`);
|
|
@@ -1135,51 +1249,15 @@ const setupModules = [
|
|
|
1135
1249
|
];
|
|
1136
1250
|
const templateSetups = setupModules.map(createSetupTemplate);
|
|
1137
1251
|
|
|
1138
|
-
//#endregion
|
|
1139
|
-
//#region node/virtual/shiki.ts
|
|
1140
|
-
const templateShiki = {
|
|
1141
|
-
id: "/@slidev/shiki",
|
|
1142
|
-
getContent: async ({ utils }) => {
|
|
1143
|
-
const options = utils.shikiOptions;
|
|
1144
|
-
const langs = await resolveLangs(options.langs || [
|
|
1145
|
-
"markdown",
|
|
1146
|
-
"vue",
|
|
1147
|
-
"javascript",
|
|
1148
|
-
"typescript",
|
|
1149
|
-
"html",
|
|
1150
|
-
"css"
|
|
1151
|
-
]);
|
|
1152
|
-
const resolvedThemeOptions = "themes" in options ? { themes: Object.fromEntries(await Promise.all(Object.entries(options.themes).map(async ([name, value]) => [name, await resolveTheme$1(value)]))) } : { theme: await resolveTheme$1(options.theme || "vitesse-dark") };
|
|
1153
|
-
const themes = resolvedThemeOptions.themes ? Object.values(resolvedThemeOptions.themes) : [resolvedThemeOptions.theme];
|
|
1154
|
-
const themeOptionsNames = resolvedThemeOptions.themes ? { themes: Object.fromEntries(Object.entries(resolvedThemeOptions.themes).map(([name, value]) => [name, typeof value === "string" ? value : value.name])) } : { theme: typeof resolvedThemeOptions.theme === "string" ? resolvedThemeOptions.theme : resolvedThemeOptions.theme.name };
|
|
1155
|
-
async function normalizeGetter(p) {
|
|
1156
|
-
const r = typeof p === "function" ? p() : p;
|
|
1157
|
-
return r.default || r;
|
|
1158
|
-
}
|
|
1159
|
-
async function resolveLangs(langs$1) {
|
|
1160
|
-
return uniq((await Promise.all(langs$1.map((lang) => normalizeGetter(lang)))).flat());
|
|
1161
|
-
}
|
|
1162
|
-
async function resolveTheme$1(theme) {
|
|
1163
|
-
return typeof theme === "string" ? theme : await normalizeGetter(theme);
|
|
1164
|
-
}
|
|
1165
|
-
const langsInit = await Promise.all(langs.map(async (lang) => typeof lang === "string" ? `import('${await resolveImportUrl(`shiki/langs/${lang}.mjs`)}')` : JSON.stringify(lang)));
|
|
1166
|
-
const themesInit = await Promise.all(themes.map(async (theme) => typeof theme === "string" ? `import('${await resolveImportUrl(`shiki/themes/${theme}.mjs`)}')` : JSON.stringify(theme)));
|
|
1167
|
-
const langNames = langs.flatMap((lang) => typeof lang === "string" ? lang : lang.name);
|
|
1168
|
-
const lines = [];
|
|
1169
|
-
lines.push(`import { createHighlighterCore } from "${await resolveImportUrl("shiki/core")}"`, `import { createJavaScriptRegexEngine } from "${await resolveImportUrl("@shikijs/engine-javascript")}"`, `export { shikiToMonaco } from "${await resolveImportUrl("@shikijs/monaco")}"`, `export const languages = ${JSON.stringify(langNames)}`, `export const themes = ${JSON.stringify(themeOptionsNames.themes || themeOptionsNames.theme)}`, "export const shiki = createHighlighterCore({", ` themes: [${themesInit.join(",")}],`, ` langs: [${langsInit.join(",")}],`, ` engine: createJavaScriptRegexEngine(),`, "})", "let highlight", "export async function getHighlighter() {", " if (highlight) return highlight", " const highlighter = await shiki", " highlight = (code, lang, options) => highlighter.codeToHtml(code, {", " lang,", ` theme: ${JSON.stringify(themeOptionsNames.theme)},`, ` themes: ${JSON.stringify(themeOptionsNames.themes)},`, " defaultColor: false,", " ...options,", " })", " return highlight", "}");
|
|
1170
|
-
return lines.join("\n");
|
|
1171
|
-
}
|
|
1172
|
-
};
|
|
1173
|
-
|
|
1174
1252
|
//#endregion
|
|
1175
1253
|
//#region node/virtual/slides.ts
|
|
1176
1254
|
const VIRTUAL_SLIDE_PREFIX = "/@slidev/slides/";
|
|
1177
1255
|
const templateSlides = {
|
|
1178
1256
|
id: "/@slidev/slides",
|
|
1179
|
-
getContent({ data, utils }) {
|
|
1257
|
+
async getContent({ data, utils }) {
|
|
1180
1258
|
const statements = [
|
|
1181
1259
|
`import { defineAsyncComponent, shallowRef } from 'vue'`,
|
|
1182
|
-
`import SlideError from '${utils.getLayouts().error}'`,
|
|
1260
|
+
`import SlideError from '${(await utils.getLayouts()).error}'`,
|
|
1183
1261
|
`import SlideLoading from '@slidev/client/internals/SlideLoading.vue'`,
|
|
1184
1262
|
`const componentsCache = new Array(${data.slides.length})`,
|
|
1185
1263
|
`const getAsyncComponent = (idx, loader) => defineAsyncComponent({`,
|
|
@@ -1265,7 +1343,6 @@ const templateTitleRenderer = {
|
|
|
1265
1343
|
//#endregion
|
|
1266
1344
|
//#region node/virtual/index.ts
|
|
1267
1345
|
const templates = [
|
|
1268
|
-
templateShiki,
|
|
1269
1346
|
templateMonacoTypes,
|
|
1270
1347
|
templateMonacoRunDeps,
|
|
1271
1348
|
templateConfigs,
|
|
@@ -1472,10 +1549,8 @@ function createSlidesLoader(options, serverOptions) {
|
|
|
1472
1549
|
"import { computed, reactive, shallowReactive } from \"vue\"",
|
|
1473
1550
|
`export const frontmatterData = ${JSON.stringify(fontmatter)}`,
|
|
1474
1551
|
"if (import.meta.hot) {",
|
|
1475
|
-
" const firstLoad = !import.meta.hot.data.frontmatter",
|
|
1476
1552
|
" import.meta.hot.data.frontmatter ??= reactive(frontmatterData)",
|
|
1477
1553
|
" import.meta.hot.accept(({ frontmatterData: update }) => {",
|
|
1478
|
-
" if (firstLoad) return",
|
|
1479
1554
|
" const frontmatter = import.meta.hot.data.frontmatter",
|
|
1480
1555
|
" Object.keys(frontmatter).forEach(key => {",
|
|
1481
1556
|
" if (!(key in update)) delete frontmatter[key]",
|
|
@@ -1649,69 +1724,29 @@ function MarkdownItEscapeInlineCode(md) {
|
|
|
1649
1724
|
};
|
|
1650
1725
|
}
|
|
1651
1726
|
|
|
1652
|
-
//#endregion
|
|
1653
|
-
//#region node/syntax/transform/utils.ts
|
|
1654
|
-
function normalizeRangeStr(rangeStr = "") {
|
|
1655
|
-
return !rangeStr.trim() ? [] : rangeStr.trim().split(/\|/g).map((i) => i.trim());
|
|
1656
|
-
}
|
|
1657
|
-
function getCodeBlocks(md) {
|
|
1658
|
-
const codeblocks = Array.from(md.matchAll(/^```[\s\S]*?^```/gm)).map((m) => {
|
|
1659
|
-
const start = m.index;
|
|
1660
|
-
const end = m.index + m[0].length;
|
|
1661
|
-
return [
|
|
1662
|
-
start,
|
|
1663
|
-
end,
|
|
1664
|
-
md.slice(0, start).match(/\n/g)?.length || 0,
|
|
1665
|
-
md.slice(0, end).match(/\n/g)?.length || 0
|
|
1666
|
-
];
|
|
1667
|
-
});
|
|
1668
|
-
return {
|
|
1669
|
-
codeblocks,
|
|
1670
|
-
isInsideCodeblocks(idx) {
|
|
1671
|
-
return codeblocks.some(([s, e]) => s <= idx && idx <= e);
|
|
1672
|
-
},
|
|
1673
|
-
isLineInsideCodeblocks(line) {
|
|
1674
|
-
return codeblocks.some(([, , s, e]) => s <= line && line <= e);
|
|
1675
|
-
}
|
|
1676
|
-
};
|
|
1677
|
-
}
|
|
1678
|
-
function getCommentBlocks(md) {
|
|
1679
|
-
const commentBlocks = Array.from(md.matchAll(/<!--[\s\S]*?-->/g)).map((m) => {
|
|
1680
|
-
const start = m.index;
|
|
1681
|
-
const end = m.index + m[0].length;
|
|
1682
|
-
return [
|
|
1683
|
-
start,
|
|
1684
|
-
end,
|
|
1685
|
-
md.slice(0, start).match(/\n/g)?.length || 0,
|
|
1686
|
-
md.slice(0, end).match(/\n/g)?.length || 0
|
|
1687
|
-
];
|
|
1688
|
-
});
|
|
1689
|
-
return {
|
|
1690
|
-
commentBlocks,
|
|
1691
|
-
isInsideCommentBlocks(idx) {
|
|
1692
|
-
return commentBlocks.some(([s, e]) => s <= idx && idx <= e);
|
|
1693
|
-
},
|
|
1694
|
-
isLineInsideCommentBlocks(line) {
|
|
1695
|
-
return commentBlocks.some(([, , s, e]) => s <= line && line <= e);
|
|
1696
|
-
}
|
|
1697
|
-
};
|
|
1698
|
-
}
|
|
1699
|
-
/**
|
|
1700
|
-
* Escape `{{` in code block to prevent Vue interpret it, #99, #1316
|
|
1701
|
-
*/
|
|
1702
|
-
function escapeVueInCode(md) {
|
|
1703
|
-
return md.replace(/\{\{/g, "{{");
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1706
1727
|
//#endregion
|
|
1707
1728
|
//#region node/syntax/markdown-it/markdown-it-shiki.ts
|
|
1708
|
-
async function MarkdownItShiki({ data: { config }, mode, utils }) {
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1729
|
+
async function MarkdownItShiki({ data: { config }, mode, utils: { shiki, shikiOptions } }) {
|
|
1730
|
+
async function getTwoslashTransformer() {
|
|
1731
|
+
const [, , { transformerTwoslash }] = await Promise.all([
|
|
1732
|
+
shiki.codeToHast("", {
|
|
1733
|
+
lang: "js",
|
|
1734
|
+
...shikiOptions
|
|
1735
|
+
}),
|
|
1736
|
+
shiki.codeToHast("", {
|
|
1737
|
+
lang: "ts",
|
|
1738
|
+
...shikiOptions
|
|
1739
|
+
}),
|
|
1740
|
+
import("@shikijs/vitepress-twoslash")
|
|
1741
|
+
]);
|
|
1742
|
+
return transformerTwoslash({
|
|
1712
1743
|
explicitTrigger: true,
|
|
1713
1744
|
twoslashOptions: { handbookOptions: { noErrorValidation: true } }
|
|
1714
|
-
})
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
const transformers = [
|
|
1748
|
+
...shikiOptions.transformers || [],
|
|
1749
|
+
(config.twoslash === true || config.twoslash === mode) && await getTwoslashTransformer(),
|
|
1715
1750
|
{
|
|
1716
1751
|
pre(pre) {
|
|
1717
1752
|
this.addClassToHast(pre, "slidev-code");
|
|
@@ -1722,8 +1757,8 @@ async function MarkdownItShiki({ data: { config }, mode, utils }) {
|
|
|
1722
1757
|
}
|
|
1723
1758
|
}
|
|
1724
1759
|
].filter(isTruthy);
|
|
1725
|
-
return
|
|
1726
|
-
...
|
|
1760
|
+
return fromAsyncCodeToHtml(shiki.codeToHtml, {
|
|
1761
|
+
...shikiOptions,
|
|
1727
1762
|
transformers
|
|
1728
1763
|
});
|
|
1729
1764
|
}
|
|
@@ -1873,28 +1908,51 @@ function transformKaTexWrapper(ctx) {
|
|
|
1873
1908
|
|
|
1874
1909
|
//#endregion
|
|
1875
1910
|
//#region node/syntax/transform/magic-move.ts
|
|
1876
|
-
const reMagicMoveBlock = /^````(?:md|markdown) magic-move(?: *\[([^\]]*)\])?(?: *(\{[^}]*\}))? *([
|
|
1911
|
+
const reMagicMoveBlock = /^````(?:md|markdown) magic-move(?: *\[([^\]]*)\])?(?: *(\{[^}]*\}))? *([^\n]*)\n([\s\S]+?)^````\s*?$/gm;
|
|
1877
1912
|
function parseLineNumbersOption(options) {
|
|
1878
1913
|
return /lines: *true/.test(options) ? true : /lines: *false/.test(options) ? false : void 0;
|
|
1879
1914
|
}
|
|
1880
1915
|
/**
|
|
1881
1916
|
* Transform magic-move code blocks
|
|
1882
1917
|
*/
|
|
1883
|
-
function transformMagicMove(ctx) {
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
const
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1918
|
+
async function transformMagicMove(ctx) {
|
|
1919
|
+
const { codeToTokens } = ctx.options.utils.shiki;
|
|
1920
|
+
const replacements = [];
|
|
1921
|
+
ctx.s.replace(reMagicMoveBlock, (full, title = "", options = "{}", _attrs = "", body, start) => {
|
|
1922
|
+
const end = start + full.length;
|
|
1923
|
+
replacements.push([
|
|
1924
|
+
start,
|
|
1925
|
+
end,
|
|
1926
|
+
worker()
|
|
1927
|
+
]);
|
|
1928
|
+
return "";
|
|
1929
|
+
async function worker() {
|
|
1930
|
+
const matches = Array.from(body.matchAll(reCodeBlock));
|
|
1931
|
+
if (!matches.length) throw new Error("Magic Move block must contain at least one code block");
|
|
1932
|
+
const defaultLineNumbers = parseLineNumbersOption(options) ?? ctx.options.data.config.lineNumbers;
|
|
1933
|
+
const ranges = matches.map((i) => normalizeRangeStr(i[3]));
|
|
1934
|
+
const steps = await Promise.all(matches.map(async (i) => {
|
|
1935
|
+
const lang = i[1];
|
|
1936
|
+
const lineNumbers = parseLineNumbersOption(i[4]) ?? defaultLineNumbers;
|
|
1937
|
+
const code = i[6].trimEnd();
|
|
1938
|
+
const options$1 = {
|
|
1939
|
+
...ctx.options.utils.shikiOptions,
|
|
1940
|
+
lang
|
|
1941
|
+
};
|
|
1942
|
+
const { tokens, bg, fg: fg$1, rootStyle, themeName } = await codeToTokens(code, options$1);
|
|
1943
|
+
return {
|
|
1944
|
+
...toKeyedTokens(code, tokens, JSON.stringify([lang, "themes" in options$1 ? options$1.themes : options$1.theme]), lineNumbers),
|
|
1945
|
+
bg,
|
|
1946
|
+
fg: fg$1,
|
|
1947
|
+
rootStyle,
|
|
1948
|
+
themeName,
|
|
1949
|
+
lang
|
|
1950
|
+
};
|
|
1951
|
+
}));
|
|
1952
|
+
return `<ShikiMagicMove v-bind="${options}" steps-lz="${lz.compressToBase64(JSON.stringify(steps))}" :title='${JSON.stringify(title)}' :step-ranges='${JSON.stringify(ranges)}' />`;
|
|
1953
|
+
}
|
|
1897
1954
|
});
|
|
1955
|
+
for (const [start, end, content] of replacements) ctx.s.overwrite(start, end, await content);
|
|
1898
1956
|
}
|
|
1899
1957
|
|
|
1900
1958
|
//#endregion
|
|
@@ -2015,31 +2073,67 @@ function dedent(text) {
|
|
|
2015
2073
|
if (minIndentLength < Number.POSITIVE_INFINITY) return lines.map((x) => x.slice(minIndentLength)).join("\n");
|
|
2016
2074
|
return text;
|
|
2017
2075
|
}
|
|
2076
|
+
const markers = [
|
|
2077
|
+
{
|
|
2078
|
+
start: /^\s*\/\/\s*#?region\b\s*(.*?)\s*$/,
|
|
2079
|
+
end: /^\s*\/\/\s*#?endregion\b\s*(.*?)\s*$/
|
|
2080
|
+
},
|
|
2081
|
+
{
|
|
2082
|
+
start: /^\s*<!--\s*#?region\b\s*(.*?)\s*-->/,
|
|
2083
|
+
end: /^\s*<!--\s*#?endregion\b\s*(.*?)\s*-->/
|
|
2084
|
+
},
|
|
2085
|
+
{
|
|
2086
|
+
start: /^\s*\/\*\s*#region\b\s*(.*?)\s*\*\//,
|
|
2087
|
+
end: /^\s*\/\*\s*#endregion\b\s*(.*?)\s*\*\//
|
|
2088
|
+
},
|
|
2089
|
+
{
|
|
2090
|
+
start: /^\s*#[rR]egion\b\s*(.*?)\s*$/,
|
|
2091
|
+
end: /^\s*#[eE]nd ?[rR]egion\b\s*(.*?)\s*$/
|
|
2092
|
+
},
|
|
2093
|
+
{
|
|
2094
|
+
start: /^\s*#\s*#?region\b\s*(.*?)\s*$/,
|
|
2095
|
+
end: /^\s*#\s*#?endregion\b\s*(.*?)\s*$/
|
|
2096
|
+
},
|
|
2097
|
+
{
|
|
2098
|
+
start: /^\s*(?:--|::|@?REM)\s*#region\b\s*(.*?)\s*$/,
|
|
2099
|
+
end: /^\s*(?:--|::|@?REM)\s*#endregion\b\s*(.*?)\s*$/
|
|
2100
|
+
},
|
|
2101
|
+
{
|
|
2102
|
+
start: /^\s*#pragma\s+region\b\s*(.*?)\s*$/,
|
|
2103
|
+
end: /^\s*#pragma\s+endregion\b\s*(.*?)\s*$/
|
|
2104
|
+
},
|
|
2105
|
+
{
|
|
2106
|
+
start: /^\s*\(\*\s*#region\b\s*(.*?)\s*\*\)/,
|
|
2107
|
+
end: /^\s*\(\*\s*#endregion\b\s*(.*?)\s*\*\)/
|
|
2108
|
+
}
|
|
2109
|
+
];
|
|
2018
2110
|
function findRegion(lines, regionName) {
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
[/^# ?region ([\w*-]+)$/, /^# ?endregion/]
|
|
2027
|
-
];
|
|
2028
|
-
let endReg = null;
|
|
2029
|
-
let start = -1;
|
|
2030
|
-
for (const [lineId, line] of lines.entries()) if (endReg === null) for (const [startReg, end] of regionRegexps) {
|
|
2031
|
-
const match = line.trim().match(startReg);
|
|
2032
|
-
if (match && match[1] === regionName) {
|
|
2033
|
-
start = lineId + 1;
|
|
2034
|
-
endReg = end;
|
|
2111
|
+
let chosen = null;
|
|
2112
|
+
for (let i = 0; i < lines.length; i++) {
|
|
2113
|
+
for (const re of markers) if (re.start.exec(lines[i])?.[1] === regionName) {
|
|
2114
|
+
chosen = {
|
|
2115
|
+
re,
|
|
2116
|
+
start: i + 1
|
|
2117
|
+
};
|
|
2035
2118
|
break;
|
|
2036
2119
|
}
|
|
2120
|
+
if (chosen) break;
|
|
2121
|
+
}
|
|
2122
|
+
if (!chosen) return null;
|
|
2123
|
+
let counter = 1;
|
|
2124
|
+
for (let i = chosen.start; i < lines.length; i++) {
|
|
2125
|
+
if (chosen.re.start.exec(lines[i])?.[1] === regionName) {
|
|
2126
|
+
counter++;
|
|
2127
|
+
continue;
|
|
2128
|
+
}
|
|
2129
|
+
const endRegion = chosen.re.end.exec(lines[i])?.[1];
|
|
2130
|
+
if (endRegion === regionName || endRegion === "") {
|
|
2131
|
+
if (--counter === 0) return {
|
|
2132
|
+
...chosen,
|
|
2133
|
+
end: i
|
|
2134
|
+
};
|
|
2135
|
+
}
|
|
2037
2136
|
}
|
|
2038
|
-
else if (endReg.test(line.trim())) return {
|
|
2039
|
-
start,
|
|
2040
|
-
end: lineId,
|
|
2041
|
-
regexp: endReg
|
|
2042
|
-
};
|
|
2043
2137
|
return null;
|
|
2044
2138
|
}
|
|
2045
2139
|
const reMonacoWrite = /^\{monaco-write\}/;
|
|
@@ -2068,7 +2162,7 @@ function transformSnippet({ s, slide, options }) {
|
|
|
2068
2162
|
if (regionName) {
|
|
2069
2163
|
const lines = content.split(/\r?\n/);
|
|
2070
2164
|
const region = findRegion(lines, regionName.slice(1));
|
|
2071
|
-
if (region) content = dedent(lines.slice(region.start, region.end).filter((
|
|
2165
|
+
if (region) content = dedent(lines.slice(region.start, region.end).filter((l) => !(region.re.start.test(l) || region.re.end.test(l))).join("\n"));
|
|
2072
2166
|
}
|
|
2073
2167
|
if (meta.match(reMonacoWrite)) {
|
|
2074
2168
|
monacoWriterWhitelist.add(filepath);
|
|
@@ -2358,7 +2452,7 @@ async function setupUnocss({ clientRoot, roots, data, utils }) {
|
|
|
2358
2452
|
{
|
|
2359
2453
|
presets: [presetIcons({
|
|
2360
2454
|
collectionsNodeResolvePath: utils.iconsResolvePath,
|
|
2361
|
-
collections: { slidev: { logo: () =>
|
|
2455
|
+
collections: { slidev: { logo: () => readFile(resolve(clientRoot, "assets/logo.svg"), "utf-8") } }
|
|
2362
2456
|
})],
|
|
2363
2457
|
safelist: tokens
|
|
2364
2458
|
},
|
|
@@ -2490,12 +2584,11 @@ async function resolveViteConfigs(options, baseConfig, overrideConfigs, command,
|
|
|
2490
2584
|
mode: command === "build" ? "production" : "development",
|
|
2491
2585
|
command
|
|
2492
2586
|
};
|
|
2493
|
-
const files = options.roots
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
baseConfig = mergeConfig(baseConfig, viteConfig.config);
|
|
2587
|
+
const files = resolveSourceFiles(options.roots, "vite.config");
|
|
2588
|
+
const configs = await Promise.all(files.map((file) => loadConfigFromFile(configEnv, file)));
|
|
2589
|
+
for (const config of configs) {
|
|
2590
|
+
if (!config?.config) continue;
|
|
2591
|
+
baseConfig = mergeConfig(baseConfig, config.config);
|
|
2499
2592
|
}
|
|
2500
2593
|
baseConfig = mergeConfig(baseConfig, overrideConfigs);
|
|
2501
2594
|
baseConfig = mergeConfig(baseConfig, {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "52.
|
|
4
|
+
"version": "52.9.1",
|
|
5
5
|
"description": "Presentation slides for developers",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -59,7 +59,6 @@
|
|
|
59
59
|
"chokidar": "^4.0.3",
|
|
60
60
|
"cli-progress": "^3.12.0",
|
|
61
61
|
"connect": "^3.7.0",
|
|
62
|
-
"debug": "^4.4.3",
|
|
63
62
|
"fast-deep-equal": "^3.1.3",
|
|
64
63
|
"fast-glob": "^3.3.3",
|
|
65
64
|
"get-port-please": "^3.2.0",
|
|
@@ -77,6 +76,7 @@
|
|
|
77
76
|
"markdown-it-mdc": "^0.2.6",
|
|
78
77
|
"mlly": "^1.8.0",
|
|
79
78
|
"monaco-editor": "^0.54.0",
|
|
79
|
+
"obug": "^2.0.0",
|
|
80
80
|
"open": "^10.2.0",
|
|
81
81
|
"pdf-lib": "^1.17.1",
|
|
82
82
|
"picomatch": "^4.0.3",
|
|
@@ -109,9 +109,9 @@
|
|
|
109
109
|
"vue": "^3.5.24",
|
|
110
110
|
"yaml": "^2.8.1",
|
|
111
111
|
"yargs": "^18.0.0",
|
|
112
|
-
"@slidev/
|
|
113
|
-
"@slidev/
|
|
114
|
-
"@slidev/
|
|
112
|
+
"@slidev/client": "52.9.1",
|
|
113
|
+
"@slidev/parser": "52.9.1",
|
|
114
|
+
"@slidev/types": "52.9.1"
|
|
115
115
|
},
|
|
116
116
|
"devDependencies": {
|
|
117
117
|
"@hedgedoc/markdown-it-plugins": "^2.1.4",
|