@slidev/parser 52.19.2 → 52.20.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/core.mjs +22 -4
- package/dist/fs.mjs +8 -0
- package/dist/utils.mjs +4 -2
- package/package.json +2 -2
package/dist/core.mjs
CHANGED
|
@@ -56,6 +56,7 @@ function getDefaultConfig() {
|
|
|
56
56
|
duration: "30min",
|
|
57
57
|
timer: "stopwatch",
|
|
58
58
|
magicMoveDuration: 800,
|
|
59
|
+
shiki: {},
|
|
59
60
|
preloadImages: true,
|
|
60
61
|
clickAnimation: ""
|
|
61
62
|
};
|
|
@@ -81,7 +82,11 @@ function resolveConfig(headmatter, themeMeta = {}, filepath, verify = false) {
|
|
|
81
82
|
...headmatter.config?.fonts,
|
|
82
83
|
...headmatter?.fonts
|
|
83
84
|
}),
|
|
84
|
-
drawings: resolveDrawings(
|
|
85
|
+
drawings: resolveDrawings({
|
|
86
|
+
...themeMeta.defaults?.drawings,
|
|
87
|
+
...headmatter.config?.drawings,
|
|
88
|
+
...headmatter?.drawings
|
|
89
|
+
}, filepath),
|
|
85
90
|
htmlAttrs: {
|
|
86
91
|
...defaultConfig.htmlAttrs,
|
|
87
92
|
...themeMeta.defaults?.htmlAttrs,
|
|
@@ -204,6 +209,7 @@ const RE_TWEET_TAG = /<Tweet\b/;
|
|
|
204
209
|
const RE_BLUESKY_TAG = /<BlueSky\b/;
|
|
205
210
|
const RE_MERMAID_CODEBLOCK = /^```mermaid/m;
|
|
206
211
|
const RE_HEADING = /^(#+) (.*)$/m;
|
|
212
|
+
const RE_CODE_BLOCK = /^```[\s\S]+?^```/gm;
|
|
207
213
|
const RE_LEADING_BACKTICKS = /^\s*`+/;
|
|
208
214
|
const RE_CRLF = /\r?\n/g;
|
|
209
215
|
function advanceHtmlCommentState(line, inHtmlComment) {
|
|
@@ -261,6 +267,15 @@ function matter(code, options) {
|
|
|
261
267
|
};
|
|
262
268
|
}
|
|
263
269
|
const IMAGE_EXTENSIONS = /\.(?:png|jpe?g|gif|svg|webp|avif|ico|bmp|tiff?)$/i;
|
|
270
|
+
const RE_MD_IMAGE_TITLE = /\s+(?:"[^"]*"|'[^']*')\s*$/;
|
|
271
|
+
/**
|
|
272
|
+
* Strip the optional CommonMark title and the angle-bracket form from a
|
|
273
|
+
* markdown image destination, so `` yields `/x.png`.
|
|
274
|
+
*/
|
|
275
|
+
function normalizeMarkdownImageTarget(target) {
|
|
276
|
+
const url = target.trim().replace(RE_MD_IMAGE_TITLE, "").trim();
|
|
277
|
+
return url.startsWith("<") && url.endsWith(">") ? url.slice(1, -1).trim() : url;
|
|
278
|
+
}
|
|
264
279
|
/**
|
|
265
280
|
* Extract image URLs from slide content and frontmatter.
|
|
266
281
|
* Strips code blocks first to avoid false positives.
|
|
@@ -279,8 +294,11 @@ function extractImagesUsage(content, frontmatter) {
|
|
|
279
294
|
} else images.add(val);
|
|
280
295
|
}
|
|
281
296
|
}
|
|
282
|
-
const stripped = content.replace(
|
|
283
|
-
for (const [,
|
|
297
|
+
const stripped = content.replace(RE_CODE_BLOCK, "");
|
|
298
|
+
for (const [, target] of stripped.matchAll(/!\[[^\]]*\]\(([^)]+)\)/g)) {
|
|
299
|
+
const url = normalizeMarkdownImageTarget(target);
|
|
300
|
+
if (url && !url.startsWith("data:")) images.add(url);
|
|
301
|
+
}
|
|
284
302
|
for (const [, url] of stripped.matchAll(/\b(?:src|image)=["']([^"']+)["']/g)) if (url && !url.startsWith("data:") && !url.includes("{{") && IMAGE_EXTENSIONS.test(url)) images.add(url.trim());
|
|
285
303
|
for (const [, url] of stripped.matchAll(/:(?:src|image)=["']'([^']+)'["']/g)) if (url && !url.startsWith("data:") && IMAGE_EXTENSIONS.test(url)) images.add(url.trim());
|
|
286
304
|
for (const [, url] of stripped.matchAll(/url\(["']?([^"')]+)["']?\)/g)) if (url && !url.startsWith("data:") && IMAGE_EXTENSIONS.test(url)) images.add(url.trim());
|
|
@@ -313,7 +331,7 @@ function parseSlide(raw, options = {}) {
|
|
|
313
331
|
let level;
|
|
314
332
|
if (frontmatter.title || frontmatter.name) title = frontmatter.title || frontmatter.name;
|
|
315
333
|
else {
|
|
316
|
-
const match = content.match(RE_HEADING);
|
|
334
|
+
const match = content.replace(RE_CODE_BLOCK, "").match(RE_HEADING);
|
|
317
335
|
title = match?.[2]?.trim();
|
|
318
336
|
level = match?.[1]?.length;
|
|
319
337
|
}
|
package/dist/fs.mjs
CHANGED
|
@@ -54,6 +54,14 @@ async function load(options, filepath, sources = {}, mode) {
|
|
|
54
54
|
const directImporter = importers?.at(-1);
|
|
55
55
|
for (const index of parseRangeString(md.slides.length, range)) {
|
|
56
56
|
const subSlide = md.slides[index - 1];
|
|
57
|
+
if (!subSlide) {
|
|
58
|
+
md.errors ??= [];
|
|
59
|
+
md.errors.push({
|
|
60
|
+
row: 0,
|
|
61
|
+
message: `Slide ${index} does not exist in "${path}", which has ${md.slides.length} slides`
|
|
62
|
+
});
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
57
65
|
try {
|
|
58
66
|
await loadSlide(md, subSlide, frontmatterOverride, importers);
|
|
59
67
|
} catch (e) {
|
package/dist/utils.mjs
CHANGED
|
@@ -40,8 +40,10 @@ function parseTimeString(timestamp) {
|
|
|
40
40
|
else throw new TypeError("Invalid timestamp format");
|
|
41
41
|
if (Number.isNaN(h) || Number.isNaN(m) || Number.isNaN(s)) throw new TypeError("Invalid timestamp format");
|
|
42
42
|
seconds = (h || 0) * 3600 + (m || 0) * 60 + (s || 0);
|
|
43
|
-
} else if (!RE_ALPHA.test(timestamp))
|
|
44
|
-
|
|
43
|
+
} else if (!RE_ALPHA.test(timestamp)) {
|
|
44
|
+
seconds = Number(timestamp);
|
|
45
|
+
if (Number.isNaN(seconds)) throw new TypeError("Invalid timestamp format");
|
|
46
|
+
} else {
|
|
45
47
|
const unitMap = {
|
|
46
48
|
s: 1,
|
|
47
49
|
sec: 1,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/parser",
|
|
3
|
-
"version": "52.
|
|
3
|
+
"version": "52.20.1",
|
|
4
4
|
"description": "Markdown parser for Slidev",
|
|
5
5
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@antfu/utils": "^9.3.0",
|
|
33
|
-
"@slidev/types": "52.
|
|
33
|
+
"@slidev/types": "52.20.1",
|
|
34
34
|
"pathe": "^2.0.3",
|
|
35
35
|
"yaml": "^2.9.1"
|
|
36
36
|
},
|