@slidev/parser 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/core.d.mts +1 -1
- package/dist/core.mjs +38 -13
- package/dist/fs.d.mts +7 -3
- package/dist/fs.mjs +7 -9
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +2 -3
- package/dist/utils.d.mts +1 -1
- package/dist/utils.mjs +144 -3
- package/package.json +6 -3
- package/dist/utils-CmVawvVO.mjs +0 -148
- /package/dist/{utils-Bas9O4Gd.d.mts → utils-DpcPp-I0.d.mts} +0 -0
package/dist/core.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as TimesplitOutput, i as TimesplitInput, n as parseRangeString, o as parseTimesplits, r as parseTimeString, t as parseAspectRatio } from "./utils-
|
|
1
|
+
import { a as TimesplitOutput, i as TimesplitInput, n as parseRangeString, o as parseTimesplits, r as parseTimeString, t as parseAspectRatio } from "./utils-DpcPp-I0.mjs";
|
|
2
2
|
import { FontOptions, ResolvedFontOptions, SlidevConfig, SlidevDetectedFeatures, SlidevMarkdown, SlidevPreparserExtension, SlidevThemeMeta, SourceSlideInfo } from "@slidev/types";
|
|
3
3
|
|
|
4
4
|
//#region src/config.d.ts
|
package/dist/core.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseAspectRatio, parseRangeString, parseTimeString, parseTimesplits } from "./utils.mjs";
|
|
2
2
|
import { ensurePrefix, toArray, uniq } from "@antfu/utils";
|
|
3
3
|
import YAML from "yaml";
|
|
4
|
-
|
|
5
4
|
//#region src/config.ts
|
|
6
5
|
const RE_QUOTED_STRING = /^(['"]).*\1$/;
|
|
7
6
|
const RE_FILENAME_STEM = /([^\\/]+?)(?:\.\w+)?$/;
|
|
@@ -192,7 +191,6 @@ function resolveDrawings(options = {}, filepath) {
|
|
|
192
191
|
syncAll
|
|
193
192
|
};
|
|
194
193
|
}
|
|
195
|
-
|
|
196
194
|
//#endregion
|
|
197
195
|
//#region src/core.ts
|
|
198
196
|
const RE_FRONTMATTER = /^---.*\r?\n([\s\S]*?)---/;
|
|
@@ -206,6 +204,22 @@ const RE_MERMAID_CODEBLOCK = /^```mermaid/m;
|
|
|
206
204
|
const RE_HEADING = /^(#+) (.*)$/m;
|
|
207
205
|
const RE_LEADING_BACKTICKS = /^\s*`+/;
|
|
208
206
|
const RE_CRLF = /\r?\n/g;
|
|
207
|
+
function advanceHtmlCommentState(line, inHtmlComment) {
|
|
208
|
+
let cursor = 0;
|
|
209
|
+
while (cursor < line.length) if (inHtmlComment) {
|
|
210
|
+
const end = line.indexOf("-->", cursor);
|
|
211
|
+
if (end < 0) return true;
|
|
212
|
+
inHtmlComment = false;
|
|
213
|
+
cursor = end + 3;
|
|
214
|
+
} else {
|
|
215
|
+
const start = line.indexOf("<!--", cursor);
|
|
216
|
+
if (start < 0) return false;
|
|
217
|
+
const end = line.indexOf("-->", start + 4);
|
|
218
|
+
if (end < 0) return true;
|
|
219
|
+
cursor = end + 3;
|
|
220
|
+
}
|
|
221
|
+
return inHtmlComment;
|
|
222
|
+
}
|
|
209
223
|
function stringify(data) {
|
|
210
224
|
return `${data.slides.map(stringifySlide).join("\n").trim()}\n`;
|
|
211
225
|
}
|
|
@@ -321,6 +335,7 @@ async function parse(markdown, filepath, extensions, options = {}) {
|
|
|
321
335
|
const slides = [];
|
|
322
336
|
let start = 0;
|
|
323
337
|
let contentStart = 0;
|
|
338
|
+
let inHtmlComment = false;
|
|
324
339
|
async function slice(end) {
|
|
325
340
|
if (start === end) return;
|
|
326
341
|
const slide = {
|
|
@@ -351,7 +366,12 @@ async function parse(markdown, filepath, extensions, options = {}) {
|
|
|
351
366
|
for (const e of extensions) if (e.transformRawLines) await e.transformRawLines(lines);
|
|
352
367
|
}
|
|
353
368
|
for (let i = 0; i < lines.length; i++) {
|
|
354
|
-
const
|
|
369
|
+
const rawLine = lines[i];
|
|
370
|
+
const line = rawLine.trimEnd();
|
|
371
|
+
if (inHtmlComment) {
|
|
372
|
+
inHtmlComment = advanceHtmlCommentState(rawLine, true);
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
355
375
|
if (line.startsWith("---")) {
|
|
356
376
|
await slice(i);
|
|
357
377
|
const next = lines[i + 1];
|
|
@@ -365,7 +385,7 @@ async function parse(markdown, filepath, extensions, options = {}) {
|
|
|
365
385
|
let j = i + 1;
|
|
366
386
|
for (; j < lines.length; j++) if (lines[j].startsWith(codeBlockLevel)) break;
|
|
367
387
|
if (j !== lines.length) i = j;
|
|
368
|
-
}
|
|
388
|
+
} else inHtmlComment = advanceHtmlCommentState(rawLine, false);
|
|
369
389
|
}
|
|
370
390
|
if (start <= lines.length - 1) await slice(lines.length);
|
|
371
391
|
return {
|
|
@@ -379,6 +399,7 @@ function parseSync(markdown, filepath, options = {}) {
|
|
|
379
399
|
const slides = [];
|
|
380
400
|
let start = 0;
|
|
381
401
|
let contentStart = 0;
|
|
402
|
+
let inHtmlComment = false;
|
|
382
403
|
function slice(end) {
|
|
383
404
|
if (start === end) return;
|
|
384
405
|
const slide = {
|
|
@@ -394,7 +415,12 @@ function parseSync(markdown, filepath, options = {}) {
|
|
|
394
415
|
contentStart = end + 1;
|
|
395
416
|
}
|
|
396
417
|
for (let i = 0; i < lines.length; i++) {
|
|
397
|
-
const
|
|
418
|
+
const rawLine = lines[i];
|
|
419
|
+
const line = rawLine.trimEnd();
|
|
420
|
+
if (inHtmlComment) {
|
|
421
|
+
inHtmlComment = advanceHtmlCommentState(rawLine, true);
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
398
424
|
if (line.startsWith("---")) {
|
|
399
425
|
slice(i);
|
|
400
426
|
const next = lines[i + 1];
|
|
@@ -408,7 +434,7 @@ function parseSync(markdown, filepath, options = {}) {
|
|
|
408
434
|
let j = i + 1;
|
|
409
435
|
for (; j < lines.length; j++) if (lines[j].startsWith(codeBlockLevel)) break;
|
|
410
436
|
if (j !== lines.length) i = j;
|
|
411
|
-
}
|
|
437
|
+
} else inHtmlComment = advanceHtmlCommentState(rawLine, false);
|
|
412
438
|
}
|
|
413
439
|
if (start <= lines.length - 1) slice(lines.length);
|
|
414
440
|
return {
|
|
@@ -442,13 +468,12 @@ function scanMonacoReferencedMods(md) {
|
|
|
442
468
|
};
|
|
443
469
|
}
|
|
444
470
|
function hash(str) {
|
|
445
|
-
let hash
|
|
471
|
+
let hash = 0;
|
|
446
472
|
for (let i = 0; i < str.length; i++) {
|
|
447
|
-
hash
|
|
448
|
-
hash
|
|
473
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
474
|
+
hash |= 0;
|
|
449
475
|
}
|
|
450
|
-
return hash
|
|
476
|
+
return hash.toString(36).slice(0, 12);
|
|
451
477
|
}
|
|
452
|
-
|
|
453
478
|
//#endregion
|
|
454
|
-
export { detectFeatures, extractImagesUsage, getDefaultConfig, parse, parseAspectRatio, parseRangeString, parseSlide, parseSync, parseTimeString, parseTimesplits, prettify, prettifySlide, resolveConfig, resolveFonts, stringify, stringifySlide, verifyConfig };
|
|
479
|
+
export { detectFeatures, extractImagesUsage, getDefaultConfig, parse, parseAspectRatio, parseRangeString, parseSlide, parseSync, parseTimeString, parseTimesplits, prettify, prettifySlide, resolveConfig, resolveFonts, stringify, stringifySlide, verifyConfig };
|
package/dist/fs.d.mts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
import { a as TimesplitOutput, i as TimesplitInput, n as parseRangeString, o as parseTimesplits, r as parseTimeString, t as parseAspectRatio } from "./utils-
|
|
1
|
+
import { a as TimesplitOutput, i as TimesplitInput, n as parseRangeString, o as parseTimesplits, r as parseTimeString, t as parseAspectRatio } from "./utils-DpcPp-I0.mjs";
|
|
2
2
|
import { SlidevParserOptions, detectFeatures, extractImagesUsage, getDefaultConfig, parse, parseSlide, parseSync, prettify, prettifySlide, resolveConfig, resolveFonts, stringify, stringifySlide, verifyConfig } from "./core.mjs";
|
|
3
3
|
import { PreparserExtensionLoader, SlidevData, SlidevMarkdown } from "@slidev/types";
|
|
4
4
|
|
|
5
5
|
//#region src/fs.d.ts
|
|
6
6
|
declare function injectPreparserExtensionLoader(fn: PreparserExtensionLoader): void;
|
|
7
|
+
interface LoadRootsInfo {
|
|
8
|
+
roots: string[];
|
|
9
|
+
userRoot: string;
|
|
10
|
+
}
|
|
7
11
|
/**
|
|
8
12
|
* Slidev data without config and themeMeta,
|
|
9
13
|
* because config and themeMeta depends on the theme to be loaded.
|
|
10
14
|
*/
|
|
11
15
|
type LoadedSlidevData = Omit<SlidevData, 'config' | 'themeMeta'>;
|
|
12
|
-
declare function load(
|
|
16
|
+
declare function load(options: LoadRootsInfo, filepath: string, sources?: Record<string, string> | ((path: string) => Promise<string>), mode?: string): Promise<LoadedSlidevData>;
|
|
13
17
|
declare function save(markdown: SlidevMarkdown): Promise<string>;
|
|
14
18
|
//#endregion
|
|
15
|
-
export { LoadedSlidevData, SlidevParserOptions, TimesplitInput, TimesplitOutput, detectFeatures, extractImagesUsage, getDefaultConfig, injectPreparserExtensionLoader, load, parse, parseAspectRatio, parseRangeString, parseSlide, parseSync, parseTimeString, parseTimesplits, prettify, prettifySlide, resolveConfig, resolveFonts, save, stringify, stringifySlide, verifyConfig };
|
|
19
|
+
export { LoadRootsInfo, LoadedSlidevData, SlidevParserOptions, TimesplitInput, TimesplitOutput, detectFeatures, extractImagesUsage, getDefaultConfig, injectPreparserExtensionLoader, load, parse, parseAspectRatio, parseRangeString, parseSlide, parseSync, parseTimeString, parseTimesplits, prettify, prettifySlide, resolveConfig, resolveFonts, save, stringify, stringifySlide, verifyConfig };
|
package/dist/fs.mjs
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseAspectRatio, parseRangeString, parseTimeString, parseTimesplits } from "./utils.mjs";
|
|
2
2
|
import { detectFeatures, extractImagesUsage, getDefaultConfig, parse, parseSlide, parseSync, prettify, prettifySlide, resolveConfig, resolveFonts, stringify, stringifySlide, verifyConfig } from "./core.mjs";
|
|
3
3
|
import { slash } from "@antfu/utils";
|
|
4
4
|
import YAML from "yaml";
|
|
5
5
|
import { existsSync } from "node:fs";
|
|
6
6
|
import { readFile, writeFile } from "node:fs/promises";
|
|
7
7
|
import { dirname, resolve } from "node:path";
|
|
8
|
-
|
|
9
8
|
//#region src/fs.ts
|
|
10
9
|
const RE_FRONTMATTER_START = /^---(?:[^-].*)?$/;
|
|
11
10
|
const RE_BLANK_LINE = /^\s*$/;
|
|
@@ -15,7 +14,7 @@ let preparserExtensionLoader = null;
|
|
|
15
14
|
function injectPreparserExtensionLoader(fn) {
|
|
16
15
|
preparserExtensionLoader = fn;
|
|
17
16
|
}
|
|
18
|
-
async function load(
|
|
17
|
+
async function load(options, filepath, sources = {}, mode) {
|
|
19
18
|
const loadSource = typeof sources === "function" ? sources : async (path) => sources[path] ?? readFile(path, "utf-8");
|
|
20
19
|
const markdown = await loadSource(filepath);
|
|
21
20
|
let extensions;
|
|
@@ -28,12 +27,12 @@ async function load(userRoot, filepath, sources = {}, mode) {
|
|
|
28
27
|
hm = lines.slice(1, hEnd).join("\n");
|
|
29
28
|
}
|
|
30
29
|
const o = YAML.parse(hm) ?? {};
|
|
31
|
-
extensions = await preparserExtensionLoader(o, filepath, mode);
|
|
30
|
+
extensions = await preparserExtensionLoader(options.roots, o, filepath, mode);
|
|
32
31
|
}
|
|
33
32
|
const markdownFiles = {};
|
|
34
33
|
const watchFiles = {};
|
|
35
34
|
const slides = [];
|
|
36
|
-
async function loadMarkdown(path, range
|
|
35
|
+
async function loadMarkdown(path, range, frontmatterOverride, importers) {
|
|
37
36
|
let md = markdownFiles[path];
|
|
38
37
|
if (!md) {
|
|
39
38
|
md = await parse(await loadSource(path), path, extensions);
|
|
@@ -41,7 +40,7 @@ async function load(userRoot, filepath, sources = {}, mode) {
|
|
|
41
40
|
watchFiles[path] = /* @__PURE__ */ new Set();
|
|
42
41
|
}
|
|
43
42
|
const directImporter = importers?.at(-1);
|
|
44
|
-
for (const index of parseRangeString(md.slides.length, range
|
|
43
|
+
for (const index of parseRangeString(md.slides.length, range)) {
|
|
45
44
|
const subSlide = md.slides[index - 1];
|
|
46
45
|
try {
|
|
47
46
|
await loadSlide(md, subSlide, frontmatterOverride, importers);
|
|
@@ -61,7 +60,7 @@ async function load(userRoot, filepath, sources = {}, mode) {
|
|
|
61
60
|
if (slide.frontmatter.disabled || slide.frontmatter.hide) return;
|
|
62
61
|
if (slide.frontmatter.src) {
|
|
63
62
|
const [rawPath, rangeRaw] = slide.frontmatter.src.split("#");
|
|
64
|
-
const path = slash(rawPath.startsWith("/") ? resolve(userRoot, rawPath.substring(1)) : resolve(dirname(slide.filepath), rawPath));
|
|
63
|
+
const path = slash(rawPath.startsWith("/") ? resolve(options.userRoot, rawPath.substring(1)) : resolve(dirname(slide.filepath), rawPath));
|
|
65
64
|
frontmatterOverride = {
|
|
66
65
|
...slide.frontmatter,
|
|
67
66
|
...frontmatterOverride
|
|
@@ -107,6 +106,5 @@ async function save(markdown) {
|
|
|
107
106
|
await writeFile(markdown.filepath, fileContent, "utf-8");
|
|
108
107
|
return fileContent;
|
|
109
108
|
}
|
|
110
|
-
|
|
111
109
|
//#endregion
|
|
112
|
-
export { detectFeatures, extractImagesUsage, getDefaultConfig, injectPreparserExtensionLoader, load, parse, parseAspectRatio, parseRangeString, parseSlide, parseSync, parseTimeString, parseTimesplits, prettify, prettifySlide, resolveConfig, resolveFonts, save, stringify, stringifySlide, verifyConfig };
|
|
110
|
+
export { detectFeatures, extractImagesUsage, getDefaultConfig, injectPreparserExtensionLoader, load, parse, parseAspectRatio, parseRangeString, parseSlide, parseSync, parseTimeString, parseTimesplits, prettify, prettifySlide, resolveConfig, resolveFonts, save, stringify, stringifySlide, verifyConfig };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as TimesplitOutput, i as TimesplitInput, n as parseRangeString, o as parseTimesplits, r as parseTimeString, t as parseAspectRatio } from "./utils-
|
|
1
|
+
import { a as TimesplitOutput, i as TimesplitInput, n as parseRangeString, o as parseTimesplits, r as parseTimeString, t as parseAspectRatio } from "./utils-DpcPp-I0.mjs";
|
|
2
2
|
import { SlidevParserOptions, detectFeatures, extractImagesUsage, getDefaultConfig, parse, parseSlide, parseSync, prettify, prettifySlide, resolveConfig, resolveFonts, stringify, stringifySlide, verifyConfig } from "./core.mjs";
|
|
3
3
|
export { SlidevParserOptions, TimesplitInput, TimesplitOutput, detectFeatures, extractImagesUsage, getDefaultConfig, parse, parseAspectRatio, parseRangeString, parseSlide, parseSync, parseTimeString, parseTimesplits, prettify, prettifySlide, resolveConfig, resolveFonts, stringify, stringifySlide, verifyConfig };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseAspectRatio, parseRangeString, parseTimeString, parseTimesplits } from "./utils.mjs";
|
|
2
2
|
import { detectFeatures, extractImagesUsage, getDefaultConfig, parse, parseSlide, parseSync, prettify, prettifySlide, resolveConfig, resolveFonts, stringify, stringifySlide, verifyConfig } from "./core.mjs";
|
|
3
|
-
|
|
4
|
-
export { detectFeatures, extractImagesUsage, getDefaultConfig, parse, parseAspectRatio, parseRangeString, parseSlide, parseSync, parseTimeString, parseTimesplits, prettify, prettifySlide, resolveConfig, resolveFonts, stringify, stringifySlide, verifyConfig };
|
|
3
|
+
export { detectFeatures, extractImagesUsage, getDefaultConfig, parse, parseAspectRatio, parseRangeString, parseSlide, parseSync, parseTimeString, parseTimesplits, prettify, prettifySlide, resolveConfig, resolveFonts, stringify, stringifySlide, verifyConfig };
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as TimesplitOutput, i as TimesplitInput, n as parseRangeString, o as parseTimesplits, r as parseTimeString, t as parseAspectRatio } from "./utils-
|
|
1
|
+
import { a as TimesplitOutput, i as TimesplitInput, n as parseRangeString, o as parseTimesplits, r as parseTimeString, t as parseAspectRatio } from "./utils-DpcPp-I0.mjs";
|
|
2
2
|
export { TimesplitInput, TimesplitOutput, parseAspectRatio, parseRangeString, parseTimeString, parseTimesplits };
|
package/dist/utils.mjs
CHANGED
|
@@ -1,3 +1,144 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { isNumber, range, uniq } from "@antfu/utils";
|
|
2
|
+
//#region src/timesplit/timestring.ts
|
|
3
|
+
/**
|
|
4
|
+
* Parse timestamp into seconds
|
|
5
|
+
*
|
|
6
|
+
* Accepts:
|
|
7
|
+
* - 10:50.1
|
|
8
|
+
* - 10s
|
|
9
|
+
* - 5m
|
|
10
|
+
* - 3min
|
|
11
|
+
* - 3mins 5secs
|
|
12
|
+
* - 10.5m3s
|
|
13
|
+
* - +10s
|
|
14
|
+
* - 1h10m30s
|
|
15
|
+
* - 1h4s
|
|
16
|
+
* - 1:1:1
|
|
17
|
+
*/
|
|
18
|
+
const RE_ALPHA = /[a-z]/i;
|
|
19
|
+
function parseTimeString(timestamp) {
|
|
20
|
+
if (typeof timestamp === "number") return {
|
|
21
|
+
seconds: timestamp,
|
|
22
|
+
relative: false
|
|
23
|
+
};
|
|
24
|
+
const relative = timestamp.startsWith("+");
|
|
25
|
+
if (relative) timestamp = timestamp.slice(1);
|
|
26
|
+
let seconds = 0;
|
|
27
|
+
if (timestamp.includes(":")) {
|
|
28
|
+
const parts = timestamp.split(":").map(Number);
|
|
29
|
+
let h = 0;
|
|
30
|
+
let m = 0;
|
|
31
|
+
let s = 0;
|
|
32
|
+
if (parts.length === 3) {
|
|
33
|
+
h = parts[0];
|
|
34
|
+
m = parts[1];
|
|
35
|
+
s = parts[2];
|
|
36
|
+
} else if (parts.length === 2) {
|
|
37
|
+
m = parts[0];
|
|
38
|
+
s = parts[1];
|
|
39
|
+
} else if (parts.length === 1) s = parts[0];
|
|
40
|
+
else throw new TypeError("Invalid timestamp format");
|
|
41
|
+
if (Number.isNaN(h) || Number.isNaN(m) || Number.isNaN(s)) throw new TypeError("Invalid timestamp format");
|
|
42
|
+
seconds = (h || 0) * 3600 + (m || 0) * 60 + (s || 0);
|
|
43
|
+
} else if (!RE_ALPHA.test(timestamp)) seconds = Number(timestamp);
|
|
44
|
+
else {
|
|
45
|
+
const unitMap = {
|
|
46
|
+
s: 1,
|
|
47
|
+
sec: 1,
|
|
48
|
+
secs: 1,
|
|
49
|
+
m: 60,
|
|
50
|
+
min: 60,
|
|
51
|
+
mins: 60,
|
|
52
|
+
h: 3600,
|
|
53
|
+
hr: 3600,
|
|
54
|
+
hrs: 3600,
|
|
55
|
+
hour: 3600,
|
|
56
|
+
hours: 3600,
|
|
57
|
+
day: 86400,
|
|
58
|
+
days: 86400,
|
|
59
|
+
week: 604800,
|
|
60
|
+
weeks: 604800,
|
|
61
|
+
month: 2629746,
|
|
62
|
+
months: 2629746,
|
|
63
|
+
year: 31556952,
|
|
64
|
+
years: 31556952
|
|
65
|
+
};
|
|
66
|
+
const regex = /([\d.]+)([a-z]+)/gi;
|
|
67
|
+
const matches = timestamp.matchAll(regex);
|
|
68
|
+
if (matches) for (const match of matches) {
|
|
69
|
+
const value = Number(match[1]);
|
|
70
|
+
if (Number.isNaN(value)) throw new TypeError(`Invalid timestamp value: ${match[1]}`);
|
|
71
|
+
const unit = match[2].toLowerCase();
|
|
72
|
+
if (!(unit in unitMap)) throw new TypeError(`Invalid timestamp unit: ${unit}`);
|
|
73
|
+
seconds += value * unitMap[unit];
|
|
74
|
+
}
|
|
75
|
+
const remaining = timestamp.replace(regex, "").trim();
|
|
76
|
+
if (remaining) throw new TypeError(`Unknown timestamp remaining: ${remaining}`);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
seconds,
|
|
80
|
+
relative
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/timesplit/timesplit.ts
|
|
85
|
+
function parseTimesplits(inputs) {
|
|
86
|
+
let ts = 0;
|
|
87
|
+
const outputs = [];
|
|
88
|
+
let current = {
|
|
89
|
+
timestampStart: ts,
|
|
90
|
+
timestampEnd: ts,
|
|
91
|
+
noStart: 0,
|
|
92
|
+
noEnd: 0,
|
|
93
|
+
title: "[start]"
|
|
94
|
+
};
|
|
95
|
+
outputs.push(current);
|
|
96
|
+
for (const input of inputs) {
|
|
97
|
+
const time = parseTimeString(input.timesplit);
|
|
98
|
+
const end = time.relative ? ts + time.seconds : time.seconds;
|
|
99
|
+
if (end < ts) throw new Error(`Timesplit end ${end} is before start ${ts}`);
|
|
100
|
+
current.timestampEnd = end;
|
|
101
|
+
current.noEnd = input.no;
|
|
102
|
+
if (input.title) current.title = input.title;
|
|
103
|
+
ts = end;
|
|
104
|
+
current = {
|
|
105
|
+
timestampStart: end,
|
|
106
|
+
timestampEnd: end,
|
|
107
|
+
noStart: input.no,
|
|
108
|
+
noEnd: input.no
|
|
109
|
+
};
|
|
110
|
+
outputs.push(current);
|
|
111
|
+
}
|
|
112
|
+
return outputs;
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/utils.ts
|
|
116
|
+
const RE_ASPECT_RATIO_SEPARATOR = /[:/x|]/;
|
|
117
|
+
/**
|
|
118
|
+
* 1,3-5,8 => [1, 3, 4, 5, 8]
|
|
119
|
+
*/
|
|
120
|
+
function parseRangeString(total, rangeStr) {
|
|
121
|
+
if (!rangeStr || rangeStr === "all" || rangeStr === "*") return range(1, total + 1);
|
|
122
|
+
if (rangeStr === "none") return [];
|
|
123
|
+
const indexes = [];
|
|
124
|
+
for (const part of rangeStr.split(/[,;]/g)) if (!part.includes("-")) indexes.push(+part);
|
|
125
|
+
else {
|
|
126
|
+
const [start, end] = part.split("-", 2);
|
|
127
|
+
indexes.push(...range(+start, !end ? total + 1 : +end + 1));
|
|
128
|
+
}
|
|
129
|
+
return uniq(indexes).filter((i) => i <= total).sort((a, b) => a - b);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Accepts `16/9` `1:1` `3x4`
|
|
133
|
+
*/
|
|
134
|
+
function parseAspectRatio(str) {
|
|
135
|
+
if (isNumber(str)) return str;
|
|
136
|
+
if (!Number.isNaN(+str)) return +str;
|
|
137
|
+
const [wStr = "", hStr = ""] = str.split(RE_ASPECT_RATIO_SEPARATOR);
|
|
138
|
+
const w = Number.parseFloat(wStr.trim());
|
|
139
|
+
const h = Number.parseFloat(hStr.trim());
|
|
140
|
+
if (Number.isNaN(w) || Number.isNaN(h) || h === 0) throw new Error(`Invalid aspect ratio "${str}"`);
|
|
141
|
+
return w / h;
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
export { parseAspectRatio, parseRangeString, parseTimeString, parseTimesplits };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/parser",
|
|
3
|
-
"version": "52.
|
|
3
|
+
"version": "52.16.0",
|
|
4
4
|
"description": "Markdown parser for Slidev",
|
|
5
5
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,8 +30,11 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@antfu/utils": "^9.3.0",
|
|
33
|
-
"yaml": "^2.
|
|
34
|
-
"@slidev/types": "52.
|
|
33
|
+
"yaml": "^2.9.0",
|
|
34
|
+
"@slidev/types": "52.16.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"tsdown-stale-guard": "^0.1.2"
|
|
35
38
|
},
|
|
36
39
|
"scripts": {
|
|
37
40
|
"build": "tsdown",
|
package/dist/utils-CmVawvVO.mjs
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { isNumber, range, uniq } from "@antfu/utils";
|
|
2
|
-
|
|
3
|
-
//#region src/timesplit/timestring.ts
|
|
4
|
-
/**
|
|
5
|
-
* Parse timestamp into seconds
|
|
6
|
-
*
|
|
7
|
-
* Accepts:
|
|
8
|
-
* - 10:50.1
|
|
9
|
-
* - 10s
|
|
10
|
-
* - 5m
|
|
11
|
-
* - 3min
|
|
12
|
-
* - 3mins 5secs
|
|
13
|
-
* - 10.5m3s
|
|
14
|
-
* - +10s
|
|
15
|
-
* - 1h10m30s
|
|
16
|
-
* - 1h4s
|
|
17
|
-
* - 1:1:1
|
|
18
|
-
*/
|
|
19
|
-
const RE_ALPHA = /[a-z]/i;
|
|
20
|
-
function parseTimeString(timestamp) {
|
|
21
|
-
if (typeof timestamp === "number") return {
|
|
22
|
-
seconds: timestamp,
|
|
23
|
-
relative: false
|
|
24
|
-
};
|
|
25
|
-
const relative = timestamp.startsWith("+");
|
|
26
|
-
if (relative) timestamp = timestamp.slice(1);
|
|
27
|
-
let seconds = 0;
|
|
28
|
-
if (timestamp.includes(":")) {
|
|
29
|
-
const parts = timestamp.split(":").map(Number);
|
|
30
|
-
let h = 0;
|
|
31
|
-
let m = 0;
|
|
32
|
-
let s = 0;
|
|
33
|
-
if (parts.length === 3) {
|
|
34
|
-
h = parts[0];
|
|
35
|
-
m = parts[1];
|
|
36
|
-
s = parts[2];
|
|
37
|
-
} else if (parts.length === 2) {
|
|
38
|
-
m = parts[0];
|
|
39
|
-
s = parts[1];
|
|
40
|
-
} else if (parts.length === 1) s = parts[0];
|
|
41
|
-
else throw new TypeError("Invalid timestamp format");
|
|
42
|
-
if (Number.isNaN(h) || Number.isNaN(m) || Number.isNaN(s)) throw new TypeError("Invalid timestamp format");
|
|
43
|
-
seconds = (h || 0) * 3600 + (m || 0) * 60 + (s || 0);
|
|
44
|
-
} else if (!RE_ALPHA.test(timestamp)) seconds = Number(timestamp);
|
|
45
|
-
else {
|
|
46
|
-
const unitMap = {
|
|
47
|
-
s: 1,
|
|
48
|
-
sec: 1,
|
|
49
|
-
secs: 1,
|
|
50
|
-
m: 60,
|
|
51
|
-
min: 60,
|
|
52
|
-
mins: 60,
|
|
53
|
-
h: 3600,
|
|
54
|
-
hr: 3600,
|
|
55
|
-
hrs: 3600,
|
|
56
|
-
hour: 3600,
|
|
57
|
-
hours: 3600,
|
|
58
|
-
day: 86400,
|
|
59
|
-
days: 86400,
|
|
60
|
-
week: 604800,
|
|
61
|
-
weeks: 604800,
|
|
62
|
-
month: 2629746,
|
|
63
|
-
months: 2629746,
|
|
64
|
-
year: 31556952,
|
|
65
|
-
years: 31556952
|
|
66
|
-
};
|
|
67
|
-
const regex = /([\d.]+)([a-z]+)/gi;
|
|
68
|
-
const matches = timestamp.matchAll(regex);
|
|
69
|
-
if (matches) for (const match of matches) {
|
|
70
|
-
const value = Number(match[1]);
|
|
71
|
-
if (Number.isNaN(value)) throw new TypeError(`Invalid timestamp value: ${match[1]}`);
|
|
72
|
-
const unit = match[2].toLowerCase();
|
|
73
|
-
if (!(unit in unitMap)) throw new TypeError(`Invalid timestamp unit: ${unit}`);
|
|
74
|
-
seconds += value * unitMap[unit];
|
|
75
|
-
}
|
|
76
|
-
const remaining = timestamp.replace(regex, "").trim();
|
|
77
|
-
if (remaining) throw new TypeError(`Unknown timestamp remaining: ${remaining}`);
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
seconds,
|
|
81
|
-
relative
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
//#endregion
|
|
86
|
-
//#region src/timesplit/timesplit.ts
|
|
87
|
-
function parseTimesplits(inputs) {
|
|
88
|
-
let ts = 0;
|
|
89
|
-
const outputs = [];
|
|
90
|
-
let current = {
|
|
91
|
-
timestampStart: ts,
|
|
92
|
-
timestampEnd: ts,
|
|
93
|
-
noStart: 0,
|
|
94
|
-
noEnd: 0,
|
|
95
|
-
title: "[start]"
|
|
96
|
-
};
|
|
97
|
-
outputs.push(current);
|
|
98
|
-
for (const input of inputs) {
|
|
99
|
-
const time = parseTimeString(input.timesplit);
|
|
100
|
-
const end = time.relative ? ts + time.seconds : time.seconds;
|
|
101
|
-
if (end < ts) throw new Error(`Timesplit end ${end} is before start ${ts}`);
|
|
102
|
-
current.timestampEnd = end;
|
|
103
|
-
current.noEnd = input.no;
|
|
104
|
-
if (input.title) current.title = input.title;
|
|
105
|
-
ts = end;
|
|
106
|
-
current = {
|
|
107
|
-
timestampStart: end,
|
|
108
|
-
timestampEnd: end,
|
|
109
|
-
noStart: input.no,
|
|
110
|
-
noEnd: input.no
|
|
111
|
-
};
|
|
112
|
-
outputs.push(current);
|
|
113
|
-
}
|
|
114
|
-
return outputs;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
//#endregion
|
|
118
|
-
//#region src/utils.ts
|
|
119
|
-
const RE_ASPECT_RATIO_SEPARATOR = /[:/x|]/;
|
|
120
|
-
/**
|
|
121
|
-
* 1,3-5,8 => [1, 3, 4, 5, 8]
|
|
122
|
-
*/
|
|
123
|
-
function parseRangeString(total, rangeStr) {
|
|
124
|
-
if (!rangeStr || rangeStr === "all" || rangeStr === "*") return range(1, total + 1);
|
|
125
|
-
if (rangeStr === "none") return [];
|
|
126
|
-
const indexes = [];
|
|
127
|
-
for (const part of rangeStr.split(/[,;]/g)) if (!part.includes("-")) indexes.push(+part);
|
|
128
|
-
else {
|
|
129
|
-
const [start, end] = part.split("-", 2);
|
|
130
|
-
indexes.push(...range(+start, !end ? total + 1 : +end + 1));
|
|
131
|
-
}
|
|
132
|
-
return uniq(indexes).filter((i) => i <= total).sort((a, b) => a - b);
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Accepts `16/9` `1:1` `3x4`
|
|
136
|
-
*/
|
|
137
|
-
function parseAspectRatio(str) {
|
|
138
|
-
if (isNumber(str)) return str;
|
|
139
|
-
if (!Number.isNaN(+str)) return +str;
|
|
140
|
-
const [wStr = "", hStr = ""] = str.split(RE_ASPECT_RATIO_SEPARATOR);
|
|
141
|
-
const w = Number.parseFloat(wStr.trim());
|
|
142
|
-
const h = Number.parseFloat(hStr.trim());
|
|
143
|
-
if (Number.isNaN(w) || Number.isNaN(h) || h === 0) throw new Error(`Invalid aspect ratio "${str}"`);
|
|
144
|
-
return w / h;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
//#endregion
|
|
148
|
-
export { parseTimeString as i, parseRangeString as n, parseTimesplits as r, parseAspectRatio as t };
|
|
File without changes
|