@slidev/cli 52.15.1 → 52.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{build-yk6Ejluk.mjs → build-BtXN8hyb.mjs} +4 -7
- package/dist/cli.mjs +26 -25
- package/dist/{export-DA_9kPXd.mjs → export-BHxAO7pf.mjs} +23 -25
- package/dist/index.d.mts +1 -2
- package/dist/index.mjs +2 -5
- package/dist/{resolver-XedCEhxI.mjs → resolver-CZx9LFrt.mjs} +114 -23
- package/dist/{shared-ClfjhvJo.mjs → serve-bnzg299W.mjs} +532 -428
- package/package.json +27 -27
- package/dist/serve-CYSWeFFN.mjs +0 -13
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
import { t as resolveViteConfigs } from "./shared-ClfjhvJo.mjs";
|
|
1
|
+
import { n as resolveViteConfigs } from "./serve-bnzg299W.mjs";
|
|
3
2
|
import { join, resolve } from "node:path";
|
|
4
3
|
import { build as build$1 } from "vite";
|
|
5
4
|
import { existsSync } from "node:fs";
|
|
@@ -7,7 +6,6 @@ import fs$1 from "node:fs/promises";
|
|
|
7
6
|
import http from "node:http";
|
|
8
7
|
import connect from "connect";
|
|
9
8
|
import sirv from "sirv";
|
|
10
|
-
|
|
11
9
|
//#region node/commands/build.ts
|
|
12
10
|
async function build(options, viteConfig = {}, args) {
|
|
13
11
|
const indexHtmlId = resolve(options.userRoot, "index.html");
|
|
@@ -53,7 +51,7 @@ async function build(options, viteConfig = {}, args) {
|
|
|
53
51
|
dev: true
|
|
54
52
|
}));
|
|
55
53
|
server.listen(port);
|
|
56
|
-
const { exportSlides } = await import("./export-
|
|
54
|
+
const { exportSlides } = await import("./export-BHxAO7pf.mjs");
|
|
57
55
|
const tempDir = resolve(outDir, "temp");
|
|
58
56
|
await fs$1.mkdir(tempDir, { recursive: true });
|
|
59
57
|
await exportSlides({
|
|
@@ -94,7 +92,7 @@ async function build(options, viteConfig = {}, args) {
|
|
|
94
92
|
"true",
|
|
95
93
|
"auto"
|
|
96
94
|
].includes(options.data.config.download)) {
|
|
97
|
-
const { exportSlides, getExportOptions } = await import("./export-
|
|
95
|
+
const { exportSlides, getExportOptions } = await import("./export-BHxAO7pf.mjs");
|
|
98
96
|
const port = 12445;
|
|
99
97
|
const app = connect();
|
|
100
98
|
const server = http.createServer(app);
|
|
@@ -113,6 +111,5 @@ async function build(options, viteConfig = {}, args) {
|
|
|
113
111
|
server.close();
|
|
114
112
|
}
|
|
115
113
|
}
|
|
116
|
-
|
|
117
114
|
//#endregion
|
|
118
|
-
export { build };
|
|
115
|
+
export { build };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { i as resolveEntry,
|
|
2
|
-
import { a as
|
|
3
|
-
import { t as createServer } from "./serve-CYSWeFFN.mjs";
|
|
1
|
+
import { i as resolveEntry, r as isInstalledGlobally } from "./resolver-CZx9LFrt.mjs";
|
|
2
|
+
import { a as resolveOptions, c as resolveTheme, d as updateFrontmatterPatch, l as version, o as parser, s as getThemeMeta, t as createServer, u as loadSetups } from "./serve-bnzg299W.mjs";
|
|
4
3
|
import path from "node:path";
|
|
5
4
|
import process from "node:process";
|
|
6
5
|
import fs from "node:fs/promises";
|
|
7
|
-
import { uniq } from "@antfu/utils";
|
|
8
6
|
import { blue, bold, cyan, cyanBright, dim, gray, green, underline, yellow } from "ansis";
|
|
9
7
|
import { injectPreparserExtensionLoader } from "@slidev/parser/fs";
|
|
10
8
|
import equal from "fast-deep-equal";
|
|
@@ -15,20 +13,16 @@ import { verifyConfig } from "@slidev/parser";
|
|
|
15
13
|
import { getPort } from "get-port-please";
|
|
16
14
|
import openBrowser from "open";
|
|
17
15
|
import yargs from "yargs";
|
|
18
|
-
|
|
19
16
|
//#region node/setups/preparser.ts
|
|
20
17
|
function setupPreparser() {
|
|
21
|
-
injectPreparserExtensionLoader(async (headmatter, filepath, mode) => {
|
|
22
|
-
|
|
23
|
-
const { userRoot } = await getRoots();
|
|
24
|
-
return (await loadSetups(uniq([...await resolveAddons(addons), userRoot]), "preparser.ts", [{
|
|
18
|
+
injectPreparserExtensionLoader(async (roots, headmatter, filepath, mode) => {
|
|
19
|
+
return (await loadSetups(roots, "preparser.ts", [{
|
|
25
20
|
filepath,
|
|
26
21
|
headmatter,
|
|
27
22
|
mode
|
|
28
23
|
}])).flat();
|
|
29
24
|
});
|
|
30
25
|
}
|
|
31
|
-
|
|
32
26
|
//#endregion
|
|
33
27
|
//#region node/cli.ts
|
|
34
28
|
const RE_NODE_MODULES_OR_GIT = /node_modules|\.git/;
|
|
@@ -131,7 +125,6 @@ cli.command("* [entry]", "Start a local server for Slidev", (args) => commonOpti
|
|
|
131
125
|
server: {
|
|
132
126
|
port,
|
|
133
127
|
strictPort: true,
|
|
134
|
-
open,
|
|
135
128
|
host,
|
|
136
129
|
force
|
|
137
130
|
},
|
|
@@ -139,8 +132,8 @@ cli.command("* [entry]", "Start a local server for Slidev", (args) => commonOpti
|
|
|
139
132
|
logLevel: log,
|
|
140
133
|
base
|
|
141
134
|
}, { async loadData(loadedSource) {
|
|
142
|
-
const { data: oldData, entry
|
|
143
|
-
const loaded = await parser.load(options
|
|
135
|
+
const { data: oldData, entry } = options;
|
|
136
|
+
const loaded = await parser.load(options, entry, loadedSource, "dev");
|
|
144
137
|
const themeRaw = theme || loaded.headmatter.theme || "default";
|
|
145
138
|
if (options.themeRaw !== themeRaw) {
|
|
146
139
|
console.log(yellow("\n restarting on theme change\n"));
|
|
@@ -151,7 +144,7 @@ cli.command("* [entry]", "Start a local server for Slidev", (args) => commonOpti
|
|
|
151
144
|
const newData = {
|
|
152
145
|
...loaded,
|
|
153
146
|
themeMeta,
|
|
154
|
-
config: parser.resolveConfig(loaded.headmatter, themeMeta, entry
|
|
147
|
+
config: parser.resolveConfig(loaded.headmatter, themeMeta, entry)
|
|
155
148
|
};
|
|
156
149
|
if (CONFIG_RESTART_FIELDS.some((i) => !equal(newData.config[i], oldData.config[i]))) {
|
|
157
150
|
console.log(yellow("\n restarting on config change\n"));
|
|
@@ -172,12 +165,21 @@ cli.command("* [entry]", "Start a local server for Slidev", (args) => commonOpti
|
|
|
172
165
|
let publicIp;
|
|
173
166
|
if (remote) publicIp = await import("public-ip").then((r) => r.publicIpv4());
|
|
174
167
|
lastRemoteUrl = printInfo(options, port, base, remote, tunnelUrl, publicIp);
|
|
168
|
+
if (open) await openSlidevInBrowser();
|
|
175
169
|
return options;
|
|
176
170
|
}
|
|
177
|
-
async function
|
|
171
|
+
async function openSlidevInBrowser() {
|
|
172
|
+
const url = `http://localhost:${port}${base}`;
|
|
173
|
+
try {
|
|
174
|
+
await openBrowser(url);
|
|
175
|
+
} catch {
|
|
176
|
+
console.log(yellow(`\n Could not open the browser automatically. Please open ${url} in your browser.\n`));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
async function openTunnel(port) {
|
|
178
180
|
const { startTunnel } = await import("untun");
|
|
179
181
|
return await (await startTunnel({
|
|
180
|
-
port
|
|
182
|
+
port,
|
|
181
183
|
acceptCloudflareNotice: true
|
|
182
184
|
}))?.getURL() ?? "";
|
|
183
185
|
}
|
|
@@ -193,7 +195,7 @@ cli.command("* [entry]", "Start a local server for Slidev", (args) => commonOpti
|
|
|
193
195
|
name: "o",
|
|
194
196
|
fullname: "open",
|
|
195
197
|
action() {
|
|
196
|
-
|
|
198
|
+
openSlidevInBrowser();
|
|
197
199
|
}
|
|
198
200
|
},
|
|
199
201
|
{
|
|
@@ -223,7 +225,7 @@ cli.command("* [entry]", "Start a local server for Slidev", (args) => commonOpti
|
|
|
223
225
|
const code = r.renderUnicodeCompact(lastRemoteUrl);
|
|
224
226
|
console.log(`\n${dim(" QR Code for remote control: ")}\n ${blue(lastRemoteUrl)}\n`);
|
|
225
227
|
console.log(code.split("\n").map((i) => ` ${i}`).join("\n"));
|
|
226
|
-
const publicIp = await import("public-ip").then((r
|
|
228
|
+
const publicIp = await import("public-ip").then((r) => r.publicIpv4());
|
|
227
229
|
if (publicIp) console.log(`\n${dim(" Public IP: ")} ${blue(publicIp)}\n`);
|
|
228
230
|
});
|
|
229
231
|
}
|
|
@@ -294,7 +296,7 @@ cli.command("build [entry..]", "Build hostable SPA", (args) => exportOptions(com
|
|
|
294
296
|
describe: "enable the inspect plugin for debugging"
|
|
295
297
|
}).strict().help(), async (args) => {
|
|
296
298
|
const { entry, theme, base, download, out, inspect, "without-notes": withoutNotes, "router-mode": routerMode } = args;
|
|
297
|
-
const { build } = await import("./build-
|
|
299
|
+
const { build } = await import("./build-BtXN8hyb.mjs");
|
|
298
300
|
for (const entryFile of entry) {
|
|
299
301
|
const options = await resolveOptions({
|
|
300
302
|
entry: entryFile,
|
|
@@ -328,8 +330,8 @@ cli.command("theme [subcommand]", "Theme related operations", (command) => {
|
|
|
328
330
|
default: "theme"
|
|
329
331
|
}), async ({ entry: entryRaw, dir, theme: themeInput }) => {
|
|
330
332
|
const entry = await resolveEntry(entryRaw);
|
|
331
|
-
const
|
|
332
|
-
const data = await parser.load(
|
|
333
|
+
const options = await resolveOptions({ entry }, "dev");
|
|
334
|
+
const data = await parser.load(options, entry);
|
|
333
335
|
let themeRaw = themeInput || data.headmatter.theme;
|
|
334
336
|
themeRaw = themeRaw === null ? "none" : themeRaw || "default";
|
|
335
337
|
if (themeRaw === "none") {
|
|
@@ -359,7 +361,7 @@ cli.command("theme [subcommand]", "Theme related operations", (command) => {
|
|
|
359
361
|
});
|
|
360
362
|
cli.command("export [entry..]", "Export slides to PDF", (args) => exportOptions(commonOptions(args)).strict().help(), async (args) => {
|
|
361
363
|
const { entry, theme } = args;
|
|
362
|
-
const { exportSlides, getExportOptions } = await import("./export-
|
|
364
|
+
const { exportSlides, getExportOptions } = await import("./export-BHxAO7pf.mjs");
|
|
363
365
|
const candidatePort = await getPort(12445);
|
|
364
366
|
let warned = false;
|
|
365
367
|
for (const entryFile of entry) {
|
|
@@ -411,7 +413,7 @@ cli.command("export-notes [entry..]", "Export slide notes to PDF", (args) => arg
|
|
|
411
413
|
type: "number",
|
|
412
414
|
describe: "wait for the specified ms before exporting"
|
|
413
415
|
}).strict().help(), async ({ entry, output, timeout, wait }) => {
|
|
414
|
-
const { exportNotes } = await import("./export-
|
|
416
|
+
const { exportNotes } = await import("./export-BHxAO7pf.mjs");
|
|
415
417
|
const candidatePort = await getPort(12445);
|
|
416
418
|
for (const entryFile of entry) {
|
|
417
419
|
const options = await resolveOptions({ entry: entryFile }, "export");
|
|
@@ -558,6 +560,5 @@ function printInfo(options, port, base, remote, tunnelUrl, publicIp) {
|
|
|
558
560
|
return lastRemoteUrl;
|
|
559
561
|
}
|
|
560
562
|
}
|
|
561
|
-
|
|
562
563
|
//#endregion
|
|
563
|
-
export {
|
|
564
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as getRoots } from "./resolver-
|
|
1
|
+
import { n as getRoots } from "./resolver-CZx9LFrt.mjs";
|
|
2
2
|
import path, { dirname, relative } from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
@@ -11,7 +11,6 @@ import { parseRangeString } from "@slidev/parser/core";
|
|
|
11
11
|
import { Presets, SingleBar } from "cli-progress";
|
|
12
12
|
import * as pdfLib from "pdf-lib";
|
|
13
13
|
import { PDFDocument } from "pdf-lib";
|
|
14
|
-
|
|
15
14
|
//#region node/commands/export.ts
|
|
16
15
|
const RE_CLICKS_PARAM = /clicks=([1-9]\d*)/;
|
|
17
16
|
function addToTree(tree, info, slideIndexes, level = 1) {
|
|
@@ -28,8 +27,8 @@ function addToTree(tree, info, slideIndexes, level = 1) {
|
|
|
28
27
|
});
|
|
29
28
|
}
|
|
30
29
|
function makeOutline(tree) {
|
|
31
|
-
return tree.map(({ title, path
|
|
32
|
-
const rootOutline = title ? `${path
|
|
30
|
+
return tree.map(({ title, path, level, children }) => {
|
|
31
|
+
const rootOutline = title ? `${path}|${"-".repeat(level - 1)}|${title}` : null;
|
|
33
32
|
const childrenOutline = makeOutline(children);
|
|
34
33
|
return childrenOutline.length > 0 ? `${rootOutline}\n${childrenOutline}` : rootOutline;
|
|
35
34
|
}).filter((outline) => !!outline).join("\n");
|
|
@@ -101,8 +100,8 @@ async function exportNotes({ port = 18724, base = "/", output = "notes", timeout
|
|
|
101
100
|
browser.close();
|
|
102
101
|
return output;
|
|
103
102
|
}
|
|
104
|
-
async function exportSlides({ port = 18724, total = 0, range
|
|
105
|
-
const pages = parseRangeString(total, range
|
|
103
|
+
async function exportSlides({ port = 18724, total = 0, range, format = "pdf", output = "slides", slides, base = "/", timeout = 3e4, wait = 0, dark = false, routerMode = "history", width = 1920, height = 1080, withClicks = false, executablePath = void 0, withToc = false, perSlide = false, scale = 1, waitUntil, omitBackground = false }) {
|
|
104
|
+
const pages = parseRangeString(total, range);
|
|
106
105
|
const { chromium } = await importPlaywright();
|
|
107
106
|
const browser = await chromium.launch({ executablePath });
|
|
108
107
|
const page = await (await browser.newContext({
|
|
@@ -127,7 +126,7 @@ async function exportSlides({ port = 18724, total = 0, range: range$1, format =
|
|
|
127
126
|
const query = new URLSearchParams();
|
|
128
127
|
if (withClicks) query.set("print", "clicks");
|
|
129
128
|
else query.set("print", "true");
|
|
130
|
-
if (range
|
|
129
|
+
if (range) query.set("range", range);
|
|
131
130
|
if (clicks) query.set("clicks", clicks);
|
|
132
131
|
const url = routerMode === "hash" ? `http://localhost:${port}${base}?${query}#${no}` : `http://localhost:${port}${base}${no}?${query}`;
|
|
133
132
|
await page.goto(url, {
|
|
@@ -182,15 +181,15 @@ async function exportSlides({ port = 18724, total = 0, range: range$1, format =
|
|
|
182
181
|
}
|
|
183
182
|
async function getSlidesIndex() {
|
|
184
183
|
const clicksBySlide = {};
|
|
185
|
-
const slides
|
|
186
|
-
const count = await slides
|
|
184
|
+
const slides = page.locator(".print-slide-container");
|
|
185
|
+
const count = await slides.count();
|
|
187
186
|
for (let i = 0; i < count; i++) {
|
|
188
|
-
const id = await slides
|
|
189
|
-
const path
|
|
190
|
-
clicksBySlide[path
|
|
187
|
+
const id = await slides.nth(i).getAttribute("id") || "";
|
|
188
|
+
const path = Number(id.split("-")[0]);
|
|
189
|
+
clicksBySlide[path] = (clicksBySlide[path] || 0) + 1;
|
|
191
190
|
}
|
|
192
|
-
return Object.fromEntries(Object.entries(clicksBySlide).reduce((acc, [path
|
|
193
|
-
acc.push([path
|
|
191
|
+
return Object.fromEntries(Object.entries(clicksBySlide).reduce((acc, [path, clicks], i) => {
|
|
192
|
+
acc.push([path, clicks + (acc[i - 1]?.[1] ?? 0)]);
|
|
194
193
|
return acc;
|
|
195
194
|
}, []));
|
|
196
195
|
}
|
|
@@ -232,8 +231,8 @@ async function exportSlides({ port = 18724, total = 0, range: range$1, format =
|
|
|
232
231
|
let mergedPdf = await PDFDocument.create({});
|
|
233
232
|
for (const pdfBytes of buffers) {
|
|
234
233
|
const pdf = await PDFDocument.load(pdfBytes);
|
|
235
|
-
(await mergedPdf.copyPages(pdf, pdf.getPageIndices())).forEach((page
|
|
236
|
-
mergedPdf.addPage(page
|
|
234
|
+
(await mergedPdf.copyPages(pdf, pdf.getPageIndices())).forEach((page) => {
|
|
235
|
+
mergedPdf.addPage(page);
|
|
237
236
|
});
|
|
238
237
|
}
|
|
239
238
|
addPdfMetadata(mergedPdf);
|
|
@@ -304,9 +303,9 @@ async function exportSlides({ port = 18724, total = 0, range: range$1, format =
|
|
|
304
303
|
if (!output.endsWith(".pdf")) output = `${output}.pdf`;
|
|
305
304
|
return perSlide ? genPagePdfPerSlide() : genPagePdfOnePiece();
|
|
306
305
|
}
|
|
307
|
-
async function genPagePng(writeToDisk) {
|
|
306
|
+
async function genPagePng(writeToDisk, cleanOutput = true) {
|
|
308
307
|
if (writeToDisk) {
|
|
309
|
-
await fs.rm(writeToDisk, {
|
|
308
|
+
if (cleanOutput) await fs.rm(writeToDisk, {
|
|
310
309
|
force: true,
|
|
311
310
|
recursive: true
|
|
312
311
|
});
|
|
@@ -315,7 +314,7 @@ async function exportSlides({ port = 18724, total = 0, range: range$1, format =
|
|
|
315
314
|
return perSlide ? genPagePngPerSlide(writeToDisk) : genPagePngOnePiece(writeToDisk);
|
|
316
315
|
}
|
|
317
316
|
async function genPageMd() {
|
|
318
|
-
const pngs = await genPagePng(dirname(output));
|
|
317
|
+
const pngs = await genPagePng(dirname(output), false);
|
|
319
318
|
const content = slides.filter(({ index }) => pages.includes(index + 1)).map(({ title, index, note }) => pngs.filter(({ slideIndex }) => slideIndex === index).map(({ filename }) => `\n\n`).join("") + (note ? `${note.trim()}\n\n` : "")).join("---\n\n");
|
|
320
319
|
await fs.writeFile(ensureSuffix(".md", output), content);
|
|
321
320
|
}
|
|
@@ -334,9 +333,9 @@ async function exportSlides({ port = 18724, total = 0, range: range$1, format =
|
|
|
334
333
|
pptx.company = "Created using Slidev";
|
|
335
334
|
if (titleSlide?.title) pptx.title = titleSlide?.title;
|
|
336
335
|
if (titleSlide?.frontmatter?.info) pptx.subject = titleSlide?.frontmatter?.info;
|
|
337
|
-
pngs.forEach(({ slideIndex, buffer
|
|
336
|
+
pngs.forEach(({ slideIndex, buffer }) => {
|
|
338
337
|
const slide = pptx.addSlide();
|
|
339
|
-
slide.background = { data: `data:image/png;base64,${buffer
|
|
338
|
+
slide.background = { data: `data:image/png;base64,${buffer.toString("base64")}` };
|
|
340
339
|
const note = slides[slideIndex].note;
|
|
341
340
|
if (note) slide.addNotes(note);
|
|
342
341
|
});
|
|
@@ -365,7 +364,7 @@ async function exportSlides({ port = 18724, total = 0, range: range$1, format =
|
|
|
365
364
|
}
|
|
366
365
|
}
|
|
367
366
|
function getExportOptions(args, options, outFilename) {
|
|
368
|
-
const { entry, output, format, timeout, wait, waitUntil, range
|
|
367
|
+
const { entry, output, format, timeout, wait, waitUntil, range, dark, withClicks, executablePath, withToc, perSlide, scale, omitBackground } = {
|
|
369
368
|
...options.data.config.export,
|
|
370
369
|
...args,
|
|
371
370
|
...clearUndefined({
|
|
@@ -382,7 +381,7 @@ function getExportOptions(args, options, outFilename) {
|
|
|
382
381
|
output: outFilename,
|
|
383
382
|
slides: options.data.slides,
|
|
384
383
|
total: options.data.slides.length,
|
|
385
|
-
range
|
|
384
|
+
range,
|
|
386
385
|
format: format || "pdf",
|
|
387
386
|
timeout: timeout ?? 3e4,
|
|
388
387
|
wait: wait ?? 0,
|
|
@@ -417,6 +416,5 @@ async function importPlaywright() {
|
|
|
417
416
|
} catch {}
|
|
418
417
|
throw new Error("The exporting for Slidev is powered by Playwright, please install it via `npm i -D playwright-chromium`");
|
|
419
418
|
}
|
|
420
|
-
|
|
421
419
|
//#endregion
|
|
422
|
-
export { exportNotes, exportSlides, getExportOptions };
|
|
420
|
+
export { exportNotes, exportSlides, getExportOptions };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import * as vite0 from "vite";
|
|
2
1
|
import { InlineConfig, PluginOption } from "vite";
|
|
3
2
|
import * as parser from "@slidev/parser/fs";
|
|
4
3
|
import { ResolvedSlidevOptions, ResolvedSlidevUtils, SlidevEntryOptions, SlidevPluginOptions, SlidevServerOptions } from "@slidev/types";
|
|
5
4
|
|
|
6
5
|
//#region node/commands/serve.d.ts
|
|
7
|
-
declare function createServer(options: ResolvedSlidevOptions, viteConfig?: InlineConfig, serverOptions?: SlidevServerOptions): Promise<
|
|
6
|
+
declare function createServer(options: ResolvedSlidevOptions, viteConfig?: InlineConfig, serverOptions?: SlidevServerOptions): Promise<import("vite").ViteDevServer>;
|
|
8
7
|
//#endregion
|
|
9
8
|
//#region node/options.d.ts
|
|
10
9
|
declare function resolveOptions(entryOptions: SlidevEntryOptions, mode: ResolvedSlidevOptions['mode']): Promise<ResolvedSlidevOptions>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
|
|
3
|
-
import { t as createServer } from "./serve-CYSWeFFN.mjs";
|
|
4
|
-
|
|
5
|
-
export { ViteSlidevPlugin, createDataUtils, createServer, parser, resolveOptions };
|
|
1
|
+
import { a as resolveOptions, i as createDataUtils, o as parser, r as ViteSlidevPlugin, t as createServer } from "./serve-bnzg299W.mjs";
|
|
2
|
+
export { ViteSlidevPlugin, createDataUtils, createServer, parser, resolveOptions };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { dirname, join, relative, resolve } from "node:path";
|
|
1
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
2
2
|
import process from "node:process";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
3
|
+
import { existsSync, lstatSync, readdirSync, readlinkSync } from "node:fs";
|
|
4
4
|
import { copyFile, readFile } from "node:fs/promises";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
6
|
import { parseNi, run } from "@antfu/ni";
|
|
7
7
|
import { ensurePrefix, slash } from "@antfu/utils";
|
|
8
8
|
import { underline, yellow } from "ansis";
|
|
@@ -11,10 +11,90 @@ import { resolvePath } from "mlly";
|
|
|
11
11
|
import prompts from "prompts";
|
|
12
12
|
import { resolveGlobal } from "resolve-global";
|
|
13
13
|
import { findClosestPkgJsonPath, findDepPkgJsonPath } from "vitefu";
|
|
14
|
-
|
|
15
14
|
//#region node/resolver.ts
|
|
16
15
|
const RE_PATH_SEPARATOR = /[/\\]/;
|
|
16
|
+
const RE_SAFE_PKG_NAME = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
17
17
|
const cliRoot = fileURLToPath(new URL("..", import.meta.url));
|
|
18
|
+
/**
|
|
19
|
+
* Detect the `node_modules/` directory the running slidev binary was
|
|
20
|
+
* dispatched from. The simple `findDepPkgJsonPath(name, cliRoot)` walk fails
|
|
21
|
+
* in pnpm v11+ global installs because `cliRoot` is the realpath inside the
|
|
22
|
+
* content-addressable store, with no path back to the install directory. The
|
|
23
|
+
* invocation path (`process.argv[1]`), however, is one of:
|
|
24
|
+
*
|
|
25
|
+
* - `{PNPM_HOME}/v11/{hash}/node_modules/@slidev/cli/bin/slidev.mjs` — pnpm
|
|
26
|
+
* v11 globals dispatch through a shell shim in `{PNPM_HOME}/bin/` that exec's
|
|
27
|
+
* `node` with this argv[1].
|
|
28
|
+
* - `{globals}/node_modules/@slidev/cli/bin/slidev.mjs` — npm/yarn globals,
|
|
29
|
+
* where the bin is a fs symlink and the resolved script path keeps the
|
|
30
|
+
* `node_modules` segment.
|
|
31
|
+
* - `./node_modules/.bin/slidev` — local project, where Node resolves the
|
|
32
|
+
* `.bin` symlink before populating argv[1].
|
|
33
|
+
*
|
|
34
|
+
* Returns the trailing `node_modules` directory of that path, or `undefined`
|
|
35
|
+
* if `argv1` doesn't pass through one.
|
|
36
|
+
*
|
|
37
|
+
* Exported for tests.
|
|
38
|
+
*/
|
|
39
|
+
function findInvocationNodeModulesPath(argv1) {
|
|
40
|
+
if (!argv1) return void 0;
|
|
41
|
+
const direct = resolve(argv1);
|
|
42
|
+
const segment = `${sep}node_modules${sep}`;
|
|
43
|
+
const directIdx = direct.lastIndexOf(segment);
|
|
44
|
+
if (directIdx >= 0) return direct.slice(0, directIdx + 1 + 12);
|
|
45
|
+
let current = direct;
|
|
46
|
+
for (let i = 0; i < 16; i++) {
|
|
47
|
+
let stat;
|
|
48
|
+
try {
|
|
49
|
+
stat = lstatSync(current);
|
|
50
|
+
} catch {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (!stat.isSymbolicLink()) return void 0;
|
|
54
|
+
const target = readlinkSync(current);
|
|
55
|
+
current = resolve(dirname(current), target);
|
|
56
|
+
const idx = current.lastIndexOf(segment);
|
|
57
|
+
if (idx >= 0) return current.slice(0, idx + 1 + 12);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Candidate `node_modules` directories to search when slidev is installed
|
|
62
|
+
* globally. Always includes the invocation's own `node_modules` (the install
|
|
63
|
+
* group `@slidev/cli` lives in), plus every sibling install group's
|
|
64
|
+
* `node_modules` so cross-group lookups can succeed.
|
|
65
|
+
*
|
|
66
|
+
* pnpm v11 lays globals out as `{root}/v11/{hash}/node_modules/...`; each
|
|
67
|
+
* `pnpm add -g <pkg>` invocation creates its own `{hash}` directory even
|
|
68
|
+
* when multiple packages are listed in one call. Walking the parent of the
|
|
69
|
+
* cli's install group lets us discover packages that landed in sibling
|
|
70
|
+
* groups (e.g. a theme installed alongside `@slidev/cli`).
|
|
71
|
+
*
|
|
72
|
+
* Exported for tests.
|
|
73
|
+
*/
|
|
74
|
+
function computeInvocationSearchPaths(ownNodeModules) {
|
|
75
|
+
if (!ownNodeModules) return [];
|
|
76
|
+
const paths = [ownNodeModules];
|
|
77
|
+
const installDir = dirname(ownNodeModules);
|
|
78
|
+
const globalRoot = dirname(installDir);
|
|
79
|
+
if (!globalRoot || globalRoot === installDir) return paths;
|
|
80
|
+
let siblings;
|
|
81
|
+
try {
|
|
82
|
+
siblings = readdirSync(globalRoot);
|
|
83
|
+
} catch {
|
|
84
|
+
return paths;
|
|
85
|
+
}
|
|
86
|
+
for (const sib of siblings) {
|
|
87
|
+
const sibInstall = join(globalRoot, sib);
|
|
88
|
+
if (sibInstall === installDir) continue;
|
|
89
|
+
const sibNm = join(sibInstall, "node_modules");
|
|
90
|
+
try {
|
|
91
|
+
if (lstatSync(sibNm).isDirectory()) paths.push(sibNm);
|
|
92
|
+
} catch {}
|
|
93
|
+
}
|
|
94
|
+
return paths;
|
|
95
|
+
}
|
|
96
|
+
const invocationNodeModules = findInvocationNodeModulesPath(process.argv[1]);
|
|
97
|
+
const invocationSearchPaths = computeInvocationSearchPaths(invocationNodeModules);
|
|
18
98
|
const isInstalledGlobally = {};
|
|
19
99
|
/**
|
|
20
100
|
* Resolve path for import url on Vite client side
|
|
@@ -22,27 +102,38 @@ const isInstalledGlobally = {};
|
|
|
22
102
|
async function resolveImportUrl(id) {
|
|
23
103
|
return toAtFS(await resolveImportPath(id, true));
|
|
24
104
|
}
|
|
25
|
-
function toAtFS(path
|
|
26
|
-
return `/@fs${ensurePrefix("/", slash(path
|
|
105
|
+
function toAtFS(path) {
|
|
106
|
+
return `/@fs${ensurePrefix("/", slash(path))}`;
|
|
27
107
|
}
|
|
28
108
|
async function resolveImportPath(importName, ensure = false) {
|
|
29
109
|
try {
|
|
30
110
|
return await resolvePath(importName, { url: import.meta.url });
|
|
31
111
|
} catch {}
|
|
32
|
-
if (isInstalledGlobally.value)
|
|
33
|
-
|
|
34
|
-
|
|
112
|
+
if (isInstalledGlobally.value) {
|
|
113
|
+
for (const nm of invocationSearchPaths) try {
|
|
114
|
+
return await resolvePath(importName, { url: pathToFileURL(`${nm}${sep}`) });
|
|
115
|
+
} catch {}
|
|
116
|
+
try {
|
|
117
|
+
return resolveGlobal(importName);
|
|
118
|
+
} catch {}
|
|
119
|
+
}
|
|
35
120
|
if (ensure) throw new Error(`Failed to resolve package "${importName}"`);
|
|
36
121
|
}
|
|
37
122
|
async function findPkgRoot(dep, parent, ensure = false) {
|
|
38
123
|
const pkgJsonPath = await findDepPkgJsonPath(dep, parent);
|
|
39
|
-
const path
|
|
40
|
-
if (ensure && !path
|
|
41
|
-
return path
|
|
124
|
+
const path = pkgJsonPath ? dirname(pkgJsonPath) : isInstalledGlobally.value ? await findGlobalPkgRoot(dep, false) : void 0;
|
|
125
|
+
if (ensure && !path) throw new Error(`Failed to resolve package "${dep}"`);
|
|
126
|
+
return path;
|
|
42
127
|
}
|
|
43
128
|
async function findGlobalPkgRoot(name, ensure = false) {
|
|
44
129
|
const localPath = await findDepPkgJsonPath(name, cliRoot);
|
|
45
130
|
if (localPath) return dirname(localPath);
|
|
131
|
+
for (const nm of invocationSearchPaths) {
|
|
132
|
+
const direct = join(nm, ...name.split("/"), "package.json");
|
|
133
|
+
if (existsSync(direct)) return dirname(direct);
|
|
134
|
+
const walked = await findDepPkgJsonPath(name, nm);
|
|
135
|
+
if (walked) return dirname(walked);
|
|
136
|
+
}
|
|
46
137
|
const yarnPath = join(globalDirs.yarn.packages, name);
|
|
47
138
|
if (existsSync(`${yarnPath}/package.json`)) return yarnPath;
|
|
48
139
|
const npmPath = join(globalDirs.npm.packages, name);
|
|
@@ -93,12 +184,13 @@ function createResolver(type, officials) {
|
|
|
93
184
|
if (name[0] === "/") return [name, name];
|
|
94
185
|
if (name.startsWith("@/")) return [name, resolve(userRoot, name.slice(2))];
|
|
95
186
|
if (name[0] === "." || name[0] !== "@" && name.includes("/")) return [name, resolve(dirname(importer), name)];
|
|
187
|
+
if (!RE_SAFE_PKG_NAME.test(name)) throw new Error(`Invalid ${type} name "${name}". Only valid npm package names are allowed.`);
|
|
96
188
|
{
|
|
97
189
|
const possiblePkgNames = [name];
|
|
98
190
|
if (!name.includes("/") && !name.startsWith("@")) possiblePkgNames.unshift(`@slidev/${type}-${name}`, `slidev-${type}-${name}`);
|
|
99
|
-
for (const pkgName
|
|
100
|
-
const pkgRoot = await findPkgRoot(pkgName
|
|
101
|
-
if (pkgRoot) return [pkgName
|
|
191
|
+
for (const pkgName of possiblePkgNames) {
|
|
192
|
+
const pkgRoot = await findPkgRoot(pkgName, importer);
|
|
193
|
+
if (pkgRoot) return [pkgName, pkgRoot];
|
|
102
194
|
}
|
|
103
195
|
}
|
|
104
196
|
const pkgName = officials[name] ?? (name[0] === "@" ? name : `slidev-${type}-${name}`);
|
|
@@ -107,14 +199,14 @@ function createResolver(type, officials) {
|
|
|
107
199
|
};
|
|
108
200
|
}
|
|
109
201
|
async function getUserPkgJson(userRoot) {
|
|
110
|
-
const path
|
|
111
|
-
if (existsSync(path
|
|
202
|
+
const path = resolve(userRoot, "package.json");
|
|
203
|
+
if (existsSync(path)) return JSON.parse(await readFile(path, "utf-8"));
|
|
112
204
|
return {};
|
|
113
205
|
}
|
|
114
206
|
async function hasWorkspacePackageJSON(root) {
|
|
115
|
-
const path
|
|
116
|
-
if (!existsSync(path
|
|
117
|
-
return !!(JSON.parse(await readFile(path
|
|
207
|
+
const path = join(root, "package.json");
|
|
208
|
+
if (!existsSync(path)) return false;
|
|
209
|
+
return !!(JSON.parse(await readFile(path, "utf-8")) || {}).workspaces;
|
|
118
210
|
}
|
|
119
211
|
function hasRootFile(root) {
|
|
120
212
|
return ["pnpm-workspace.yaml"].some((file) => existsSync(join(root, file)));
|
|
@@ -134,7 +226,7 @@ async function getRoots(entry) {
|
|
|
134
226
|
if (rootsInfo) return rootsInfo;
|
|
135
227
|
if (!entry) throw new Error("[slidev] Cannot find roots without entry");
|
|
136
228
|
const userRoot = dirname(entry);
|
|
137
|
-
isInstalledGlobally.value = slash(relative(userRoot, process.argv[1])).includes("/.pnpm/") || (await import("is-installed-globally")).default;
|
|
229
|
+
isInstalledGlobally.value = slash(relative(userRoot, process.argv[1])).includes("/.pnpm/") || invocationNodeModules != null && slash(relative(userRoot, invocationNodeModules)).startsWith("..") || (await import("is-installed-globally")).default;
|
|
138
230
|
const clientRoot = await findPkgRoot("@slidev/client", cliRoot, true);
|
|
139
231
|
const closestPkgRoot = dirname(await findClosestPkgJsonPath(userRoot) || userRoot);
|
|
140
232
|
rootsInfo = {
|
|
@@ -162,6 +254,5 @@ function resolveSourceFiles(roots, subpath, extensions = [
|
|
|
162
254
|
}
|
|
163
255
|
return results;
|
|
164
256
|
}
|
|
165
|
-
|
|
166
257
|
//#endregion
|
|
167
|
-
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 };
|
|
258
|
+
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 };
|