@slidev/parser 52.19.2 → 52.20.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/core.mjs CHANGED
@@ -81,7 +81,11 @@ function resolveConfig(headmatter, themeMeta = {}, filepath, verify = false) {
81
81
  ...headmatter.config?.fonts,
82
82
  ...headmatter?.fonts
83
83
  }),
84
- drawings: resolveDrawings(headmatter.drawings, filepath),
84
+ drawings: resolveDrawings({
85
+ ...themeMeta.defaults?.drawings,
86
+ ...headmatter.config?.drawings,
87
+ ...headmatter?.drawings
88
+ }, filepath),
85
89
  htmlAttrs: {
86
90
  ...defaultConfig.htmlAttrs,
87
91
  ...themeMeta.defaults?.htmlAttrs,
@@ -204,6 +208,7 @@ const RE_TWEET_TAG = /<Tweet\b/;
204
208
  const RE_BLUESKY_TAG = /<BlueSky\b/;
205
209
  const RE_MERMAID_CODEBLOCK = /^```mermaid/m;
206
210
  const RE_HEADING = /^(#+) (.*)$/m;
211
+ const RE_CODE_BLOCK = /^```[\s\S]+?^```/gm;
207
212
  const RE_LEADING_BACKTICKS = /^\s*`+/;
208
213
  const RE_CRLF = /\r?\n/g;
209
214
  function advanceHtmlCommentState(line, inHtmlComment) {
@@ -261,6 +266,15 @@ function matter(code, options) {
261
266
  };
262
267
  }
263
268
  const IMAGE_EXTENSIONS = /\.(?:png|jpe?g|gif|svg|webp|avif|ico|bmp|tiff?)$/i;
269
+ const RE_MD_IMAGE_TITLE = /\s+(?:"[^"]*"|'[^']*')\s*$/;
270
+ /**
271
+ * Strip the optional CommonMark title and the angle-bracket form from a
272
+ * markdown image destination, so `![a](/x.png "Title")` yields `/x.png`.
273
+ */
274
+ function normalizeMarkdownImageTarget(target) {
275
+ const url = target.trim().replace(RE_MD_IMAGE_TITLE, "").trim();
276
+ return url.startsWith("<") && url.endsWith(">") ? url.slice(1, -1).trim() : url;
277
+ }
264
278
  /**
265
279
  * Extract image URLs from slide content and frontmatter.
266
280
  * Strips code blocks first to avoid false positives.
@@ -279,8 +293,11 @@ function extractImagesUsage(content, frontmatter) {
279
293
  } else images.add(val);
280
294
  }
281
295
  }
282
- const stripped = content.replace(/^```[\s\S]+?^```/gm, "");
283
- for (const [, url] of stripped.matchAll(/!\[[^\]]*\]\(([^)]+)\)/g)) if (url && !url.startsWith("data:")) images.add(url.trim());
296
+ const stripped = content.replace(RE_CODE_BLOCK, "");
297
+ for (const [, target] of stripped.matchAll(/!\[[^\]]*\]\(([^)]+)\)/g)) {
298
+ const url = normalizeMarkdownImageTarget(target);
299
+ if (url && !url.startsWith("data:")) images.add(url);
300
+ }
284
301
  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
302
  for (const [, url] of stripped.matchAll(/:(?:src|image)=["']'([^']+)'["']/g)) if (url && !url.startsWith("data:") && IMAGE_EXTENSIONS.test(url)) images.add(url.trim());
286
303
  for (const [, url] of stripped.matchAll(/url\(["']?([^"')]+)["']?\)/g)) if (url && !url.startsWith("data:") && IMAGE_EXTENSIONS.test(url)) images.add(url.trim());
@@ -313,7 +330,7 @@ function parseSlide(raw, options = {}) {
313
330
  let level;
314
331
  if (frontmatter.title || frontmatter.name) title = frontmatter.title || frontmatter.name;
315
332
  else {
316
- const match = content.match(RE_HEADING);
333
+ const match = content.replace(RE_CODE_BLOCK, "").match(RE_HEADING);
317
334
  title = match?.[2]?.trim();
318
335
  level = match?.[1]?.length;
319
336
  }
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)) seconds = Number(timestamp);
44
- else {
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.19.2",
3
+ "version": "52.20.0",
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.19.2",
33
+ "@slidev/types": "52.20.0",
34
34
  "pathe": "^2.0.3",
35
35
  "yaml": "^2.9.1"
36
36
  },