@cudoment/cudoc 0.4.0 → 0.5.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/README.md +1 -1
- package/dist/document.d.ts +11 -1
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +33 -2
- package/dist/document.js.map +1 -1
- package/dist/internal/core/mdx/imports.d.ts +21 -0
- package/dist/internal/core/mdx/imports.d.ts.map +1 -0
- package/dist/internal/core/mdx/imports.js +80 -0
- package/dist/internal/core/mdx/imports.js.map +1 -0
- package/dist/internal/core/mdx/index.d.ts +1 -0
- package/dist/internal/core/mdx/index.d.ts.map +1 -1
- package/dist/internal/core/mdx/index.js +1 -0
- package/dist/internal/core/mdx/index.js.map +1 -1
- package/dist/internal/transforms/table-column-layout/create-table.d.ts.map +1 -1
- package/dist/internal/transforms/table-column-layout/create-table.js +40 -17
- package/dist/internal/transforms/table-column-layout/create-table.js.map +1 -1
- package/dist/internal/transforms/table-column-layout/index.d.ts +32 -0
- package/dist/internal/transforms/table-column-layout/index.d.ts.map +1 -1
- package/dist/internal/transforms/table-column-layout/index.js +66 -0
- package/dist/internal/transforms/table-column-layout/index.js.map +1 -1
- package/dist/markdown.d.ts +8 -0
- package/dist/markdown.d.ts.map +1 -1
- package/dist/markdown.js +9 -1
- package/dist/markdown.js.map +1 -1
- package/dist/node/check.d.ts +6 -3
- package/dist/node/check.d.ts.map +1 -1
- package/dist/node/check.js +101 -23
- package/dist/node/check.js.map +1 -1
- package/dist/node/cli.js +26 -1
- package/dist/node/cli.js.map +1 -1
- package/dist/node/dataset.d.ts +14 -1
- package/dist/node/dataset.d.ts.map +1 -1
- package/dist/node/dataset.js +40 -4
- package/dist/node/dataset.js.map +1 -1
- package/dist/node/glob.d.ts +21 -0
- package/dist/node/glob.d.ts.map +1 -0
- package/dist/node/glob.js +61 -0
- package/dist/node/glob.js.map +1 -0
- package/dist/node/library.d.ts +70 -4
- package/dist/node/library.d.ts.map +1 -1
- package/dist/node/library.js +196 -32
- package/dist/node/library.js.map +1 -1
- package/dist/node/local-target.d.ts +28 -8
- package/dist/node/local-target.d.ts.map +1 -1
- package/dist/node/local-target.js +41 -12
- package/dist/node/local-target.js.map +1 -1
- package/dist/node/prepare-embeds.d.ts +16 -2
- package/dist/node/prepare-embeds.d.ts.map +1 -1
- package/dist/node/prepare-embeds.js +41 -5
- package/dist/node/prepare-embeds.js.map +1 -1
- package/dist/node/resolve-embed.d.ts +79 -1
- package/dist/node/resolve-embed.d.ts.map +1 -1
- package/dist/node/resolve-embed.js +251 -43
- package/dist/node/resolve-embed.js.map +1 -1
- package/dist/node/roots.d.ts +67 -0
- package/dist/node/roots.d.ts.map +1 -0
- package/dist/node/roots.js +134 -0
- package/dist/node/roots.js.map +1 -0
- package/dist/node/storage.d.ts +21 -3
- package/dist/node/storage.d.ts.map +1 -1
- package/dist/node/storage.js +41 -12
- package/dist/node/storage.js.map +1 -1
- package/dist/node/watch.d.ts +81 -0
- package/dist/node/watch.d.ts.map +1 -0
- package/dist/node/watch.js +140 -0
- package/dist/node/watch.js.map +1 -0
- package/dist/paged.d.ts +34 -0
- package/dist/paged.d.ts.map +1 -0
- package/dist/paged.js +44 -0
- package/dist/paged.js.map +1 -0
- package/package.json +15 -2
- package/styles.css +5 -2
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where documents come from, and how a library path maps back to a file.
|
|
3
|
+
*
|
|
4
|
+
* A library has one coordinate system: the library path, which is a root's
|
|
5
|
+
* `base` followed by the file's path under that root. Document ids, links,
|
|
6
|
+
* embed sources and the checker all speak that system, so a project can
|
|
7
|
+
* collect `content/` under `docs` and `glossary/` under `terms` and have
|
|
8
|
+
* `/docs/guide` and `/terms/token` mean what they mean on the site. These
|
|
9
|
+
* helpers are the one place that knows which directory a library path lives
|
|
10
|
+
* in, so nothing else has to.
|
|
11
|
+
*/
|
|
12
|
+
import fs from "node:fs";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import { posix, safePath } from "./storage.js";
|
|
15
|
+
/** `/docs/` and `docs` are the same base; `..`, `?` and `#` never are one. */
|
|
16
|
+
export function normalizeBase(base) {
|
|
17
|
+
if (base === undefined)
|
|
18
|
+
return "";
|
|
19
|
+
if (typeof base !== "string")
|
|
20
|
+
throw new Error("cudoc: a root base must be a string");
|
|
21
|
+
const value = base.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
22
|
+
if (!value)
|
|
23
|
+
return "";
|
|
24
|
+
if (value.split("/").some((part) => !part || part === "." || part === "..") ||
|
|
25
|
+
/[?#]/.test(value))
|
|
26
|
+
throw new Error(`cudoc: invalid root base: ${base}`);
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The roots a collection or a consumer was given. `sourceRoot` is the
|
|
31
|
+
* single-root shorthand for `roots: [{ dir: sourceRoot }]`; giving both is an
|
|
32
|
+
* error rather than a merge, because the two spell the same thing.
|
|
33
|
+
*/
|
|
34
|
+
export function resolveRoots(options) {
|
|
35
|
+
if (options.sourceRoot !== undefined && options.roots !== undefined)
|
|
36
|
+
throw new Error("cudoc: give either sourceRoot or roots, not both");
|
|
37
|
+
const given = options.roots ??
|
|
38
|
+
(options.sourceRoot === undefined ? [] : [{ dir: options.sourceRoot }]);
|
|
39
|
+
if (!Array.isArray(given) || !given.length)
|
|
40
|
+
throw new Error("cudoc: sourceRoot or a non-empty roots list is required");
|
|
41
|
+
const roots = given.map((root) => {
|
|
42
|
+
if (!root || typeof root !== "object" || typeof root.dir !== "string")
|
|
43
|
+
throw new Error("cudoc: each root needs a dir");
|
|
44
|
+
if (!root.dir)
|
|
45
|
+
throw new Error("cudoc: a root dir must not be empty");
|
|
46
|
+
return { dir: path.resolve(root.dir), base: normalizeBase(root.base) };
|
|
47
|
+
});
|
|
48
|
+
const dirs = new Set();
|
|
49
|
+
for (const root of roots) {
|
|
50
|
+
if (dirs.has(root.dir))
|
|
51
|
+
throw new Error(`cudoc: root directory listed twice: ${root.dir}`);
|
|
52
|
+
dirs.add(root.dir);
|
|
53
|
+
}
|
|
54
|
+
return roots;
|
|
55
|
+
}
|
|
56
|
+
/** A root's path for a file inside it, or undefined when the file is elsewhere. */
|
|
57
|
+
const under = (dir, file) => {
|
|
58
|
+
const relative = path.relative(dir, file);
|
|
59
|
+
if (!relative ||
|
|
60
|
+
relative === ".." ||
|
|
61
|
+
relative.startsWith(`..${path.sep}`) ||
|
|
62
|
+
path.isAbsolute(relative))
|
|
63
|
+
return undefined;
|
|
64
|
+
return posix(relative);
|
|
65
|
+
};
|
|
66
|
+
/** `base/relative`, or just `relative` for a root at the top. */
|
|
67
|
+
export const libraryPath = (root, relative) => root.base ? `${root.base}/${relative}` : relative;
|
|
68
|
+
/**
|
|
69
|
+
* The library path of a file, from the innermost root that contains it.
|
|
70
|
+
*
|
|
71
|
+
* Nested root directories are allowed — a project may collect `docs/` and
|
|
72
|
+
* give `docs/api/` its own base — and the deeper one owns the file.
|
|
73
|
+
*/
|
|
74
|
+
export function libraryPathOf(roots, file) {
|
|
75
|
+
const absolute = path.resolve(file);
|
|
76
|
+
let best;
|
|
77
|
+
for (const root of roots) {
|
|
78
|
+
const relative = under(root.dir, absolute);
|
|
79
|
+
if (relative === undefined)
|
|
80
|
+
continue;
|
|
81
|
+
const depth = root.dir.split(path.sep).length;
|
|
82
|
+
if (!best || depth > best.depth)
|
|
83
|
+
best = { depth, value: libraryPath(root, relative) };
|
|
84
|
+
}
|
|
85
|
+
return best?.value;
|
|
86
|
+
}
|
|
87
|
+
/** The document id a file collects as: its library path without the extension. */
|
|
88
|
+
export const documentIdOf = (roots, file) => libraryPathOf(roots, file)?.replace(/\.mdx?$/i, "");
|
|
89
|
+
/** Whether `libraryPath` sits under the root's base. */
|
|
90
|
+
const inBase = (root, target) => {
|
|
91
|
+
if (!root.base)
|
|
92
|
+
return target;
|
|
93
|
+
if (target === root.base)
|
|
94
|
+
return "";
|
|
95
|
+
return target.startsWith(`${root.base}/`)
|
|
96
|
+
? target.slice(root.base.length + 1)
|
|
97
|
+
: undefined;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Every file a library path could name, most specific base first.
|
|
101
|
+
*
|
|
102
|
+
* Two roots may share a base, and one base may extend another, so the answer
|
|
103
|
+
* is a list: the caller that wants the file that exists checks each, and the
|
|
104
|
+
* caller that wants to know whether the path could exist at all takes the
|
|
105
|
+
* first. A path that would escape a root's directory is left out.
|
|
106
|
+
*/
|
|
107
|
+
export function candidateFiles(roots, target) {
|
|
108
|
+
return [...roots]
|
|
109
|
+
.map((root, order) => ({ root, order }))
|
|
110
|
+
.sort((a, b) => b.root.base.length - a.root.base.length || a.order - b.order)
|
|
111
|
+
.flatMap(({ root }) => {
|
|
112
|
+
const relative = inBase(root, target);
|
|
113
|
+
if (relative === undefined)
|
|
114
|
+
return [];
|
|
115
|
+
try {
|
|
116
|
+
return [safePath(root.dir, relative)];
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The file a library path names, preferring one that exists.
|
|
125
|
+
*
|
|
126
|
+
* When none exists — the caller is about to compile a slice of a document
|
|
127
|
+
* that has since been deleted, say — the first candidate is returned so an
|
|
128
|
+
* error names a real location.
|
|
129
|
+
*/
|
|
130
|
+
export function sourceFileOf(roots, target) {
|
|
131
|
+
const candidates = candidateFiles(roots, target);
|
|
132
|
+
return candidates.find((file) => fs.existsSync(file)) ?? candidates[0];
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=roots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roots.js","sourceRoot":"","sources":["../../src/node/roots.ts"],"names":[],"mappings":"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"}
|
package/dist/node/storage.d.ts
CHANGED
|
@@ -3,8 +3,26 @@ export declare const posix: (value: string) => string;
|
|
|
3
3
|
export declare function contained(root: string, target: string): boolean;
|
|
4
4
|
export declare function realPath(target: string): string;
|
|
5
5
|
export declare function safePath(root: string, relative: string): string;
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Every file under `root` with one of the extensions, sorted, as absolute
|
|
8
|
+
* paths. Dot entries and `node_modules` are always skipped; `exclude` is asked
|
|
9
|
+
* about each remaining entry's POSIX path relative to `root`, and a directory
|
|
10
|
+
* it excludes is not entered, so a symlink inside one is never seen.
|
|
11
|
+
*/
|
|
12
|
+
export declare function sourceFiles(root: string, extensions?: string[], options?: {
|
|
13
|
+
exclude?: (relative: string) => boolean;
|
|
14
|
+
}): string[];
|
|
7
15
|
export declare function writeJson(file: string, value: unknown): void;
|
|
8
|
-
/**
|
|
9
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Only replace directories bearing our ownership marker. Never delete arbitrary output.
|
|
18
|
+
*
|
|
19
|
+
* `inputRoots` are the directories the build reads; the output may not sit
|
|
20
|
+
* inside or around any of them. A build callback may be synchronous or
|
|
21
|
+
* asynchronous. The return value of `build` is what decides: a thenable defers
|
|
22
|
+
* the commit until it settles and makes this function return a promise,
|
|
23
|
+
* anything else commits immediately and returns nothing. The overloads are a
|
|
24
|
+
* convenience; the runtime check is the authority.
|
|
25
|
+
*/
|
|
26
|
+
export declare function publishDirectory(inputRoots: string | string[], outputRoot: string, build: (staging: string) => void): void;
|
|
27
|
+
export declare function publishDirectory(inputRoots: string | string[], outputRoot: string, build: (staging: string) => Promise<void>): Promise<void>;
|
|
10
28
|
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/node/storage.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,IAAI,GAAI,OAAO,MAAM,WACuB,CAAA;AACzD,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,WAAoC,CAAA;AACvE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAQ/D;AACD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAI/C;AACD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ/D;AACD,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,UAAU,WAAkB,
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/node/storage.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,IAAI,GAAI,OAAO,MAAM,WACuB,CAAA;AACzD,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,WAAoC,CAAA;AACvE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAQ/D;AACD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAI/C;AACD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ/D;AACD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,UAAU,WAAkB,EAC5B,OAAO,GAAE;IAAE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;CAAO,GACxD,MAAM,EAAE,CAmBV;AACD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,QAGrD;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,EAC7B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAC/B,IAAI,CAAA;AACP,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,EAC7B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACxC,OAAO,CAAC,IAAI,CAAC,CAAA"}
|
package/dist/node/storage.js
CHANGED
|
@@ -23,7 +23,14 @@ export function safePath(root, relative) {
|
|
|
23
23
|
throw new Error(`cudoc: path escapes document root: ${relative}`);
|
|
24
24
|
return target;
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Every file under `root` with one of the extensions, sorted, as absolute
|
|
28
|
+
* paths. Dot entries and `node_modules` are always skipped; `exclude` is asked
|
|
29
|
+
* about each remaining entry's POSIX path relative to `root`, and a directory
|
|
30
|
+
* it excludes is not entered, so a symlink inside one is never seen.
|
|
31
|
+
*/
|
|
32
|
+
export function sourceFiles(root, extensions = [".md", ".mdx"], options = {}) {
|
|
33
|
+
const base = path.resolve(root);
|
|
27
34
|
const walk = (dir) => fs
|
|
28
35
|
.readdirSync(dir, { withFileTypes: true })
|
|
29
36
|
.sort((a, b) => a.name.localeCompare(b.name, "en"))
|
|
@@ -31,6 +38,8 @@ export function sourceFiles(root, extensions = [".md", ".mdx"]) {
|
|
|
31
38
|
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
32
39
|
return [];
|
|
33
40
|
const file = path.join(dir, entry.name);
|
|
41
|
+
if (options.exclude?.(posix(path.relative(base, file))))
|
|
42
|
+
return [];
|
|
34
43
|
if (entry.isSymbolicLink())
|
|
35
44
|
throw new Error(`cudoc: symlink in source tree: ${file}`);
|
|
36
45
|
if (entry.isDirectory())
|
|
@@ -39,19 +48,21 @@ export function sourceFiles(root, extensions = [".md", ".mdx"]) {
|
|
|
39
48
|
? [file]
|
|
40
49
|
: [];
|
|
41
50
|
});
|
|
42
|
-
return walk(
|
|
51
|
+
return walk(base);
|
|
43
52
|
}
|
|
44
53
|
export function writeJson(file, value) {
|
|
45
54
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
46
55
|
fs.writeFileSync(file, JSON.stringify(value));
|
|
47
56
|
}
|
|
48
|
-
|
|
49
|
-
export function publishDirectory(inputRoot, outputRoot, build) {
|
|
57
|
+
export function publishDirectory(inputRoots, outputRoot, build) {
|
|
50
58
|
if (fs.existsSync(outputRoot) && fs.lstatSync(outputRoot).isSymbolicLink())
|
|
51
59
|
throw new Error("cudoc: output directory must not be a symlink");
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
const output = realPath(outputRoot);
|
|
61
|
+
for (const inputRoot of [inputRoots].flat()) {
|
|
62
|
+
const input = realPath(inputRoot);
|
|
63
|
+
if (contained(input, output) || contained(output, input))
|
|
64
|
+
throw new Error("cudoc: input and output directories overlap");
|
|
65
|
+
}
|
|
55
66
|
fs.mkdirSync(path.dirname(output), { recursive: true });
|
|
56
67
|
const owner = path.join(output, ".cudoc-output");
|
|
57
68
|
if (fs.existsSync(output) &&
|
|
@@ -61,9 +72,7 @@ export function publishDirectory(inputRoot, outputRoot, build) {
|
|
|
61
72
|
const fd = fs.openSync(lock, "wx");
|
|
62
73
|
const staging = fs.mkdtempSync(`${output}.tmp-`);
|
|
63
74
|
const backup = `${output}.previous-${crypto.randomUUID()}`;
|
|
64
|
-
|
|
65
|
-
fs.writeFileSync(path.join(staging, ".cudoc-output"), "cudoc\n");
|
|
66
|
-
build(staging);
|
|
75
|
+
const commit = () => {
|
|
67
76
|
if (fs.existsSync(output))
|
|
68
77
|
fs.renameSync(output, backup);
|
|
69
78
|
try {
|
|
@@ -75,11 +84,31 @@ export function publishDirectory(inputRoot, outputRoot, build) {
|
|
|
75
84
|
throw error;
|
|
76
85
|
}
|
|
77
86
|
fs.rmSync(backup, { recursive: true, force: true });
|
|
78
|
-
}
|
|
79
|
-
|
|
87
|
+
};
|
|
88
|
+
const cleanup = () => {
|
|
80
89
|
fs.rmSync(staging, { recursive: true, force: true });
|
|
81
90
|
fs.closeSync(fd);
|
|
82
91
|
fs.unlinkSync(lock);
|
|
92
|
+
};
|
|
93
|
+
let result;
|
|
94
|
+
try {
|
|
95
|
+
fs.writeFileSync(path.join(staging, ".cudoc-output"), "cudoc\n");
|
|
96
|
+
result = build(staging);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
cleanup();
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
const pending = result;
|
|
103
|
+
if (typeof pending?.then !== "function") {
|
|
104
|
+
try {
|
|
105
|
+
commit();
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
cleanup();
|
|
109
|
+
}
|
|
110
|
+
return;
|
|
83
111
|
}
|
|
112
|
+
return pending.then(commit).finally(cleanup);
|
|
84
113
|
}
|
|
85
114
|
//# sourceMappingURL=storage.js.map
|
package/dist/node/storage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/node/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,MAAM,MAAM,aAAa,CAAA;AAEhC,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE,CACpC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACzD,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACvE,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,MAAc;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC5C,OAAO,CACL,QAAQ,KAAK,EAAE;QACf,CAAC,QAAQ,KAAK,IAAI;YAChB,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;YACrC,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAC9B,CAAA;AACH,CAAC;AACD,MAAM,UAAU,QAAQ,CAAC,MAAc;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACrC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;IAC7D,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;AAC7E,CAAC;AACD,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,QAAgB;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IAC3C,IACE,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QAE7B,MAAM,IAAI,KAAK,CAAC,sCAAsC,QAAQ,EAAE,CAAC,CAAA;IACnE,OAAO,MAAM,CAAA;AACf,CAAC;AACD,MAAM,UAAU,WAAW,CACzB,IAAY,EACZ,UAAU,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/node/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection that repeats as sources change.
|
|
3
|
+
*
|
|
4
|
+
* A pass is what the CLI's `collect` does once: build the library, then
|
|
5
|
+
* prepare the embeds. Here every pass after the first hands the previous
|
|
6
|
+
* library and the previous preparation back in, so only the documents whose
|
|
7
|
+
* text changed compile again and only the blocks that read a changed document
|
|
8
|
+
* resolve again. The watcher runs a pass when a file under any root changes,
|
|
9
|
+
* after a short quiet period, and keeps the last good result when a pass
|
|
10
|
+
* fails, so a half-typed document is an error message rather than a broken
|
|
11
|
+
* library.
|
|
12
|
+
*/
|
|
13
|
+
import type { CompiledDocument } from "../markdown.js";
|
|
14
|
+
import { type BuildDocumentsOptions, type Library } from "./library.js";
|
|
15
|
+
import { type PreparedEmbeds } from "./prepare-embeds.js";
|
|
16
|
+
/**
|
|
17
|
+
* A collection configuration as a config file exports it: the build options,
|
|
18
|
+
* where the compiler may return its result synchronously or as a promise.
|
|
19
|
+
*/
|
|
20
|
+
export type CollectConfig = Omit<BuildDocumentsOptions, "compiler"> & {
|
|
21
|
+
compiler?: (...parameters: Parameters<NonNullable<BuildDocumentsOptions["compiler"]>>) => CompiledDocument | Promise<CompiledDocument>;
|
|
22
|
+
};
|
|
23
|
+
/** What one pass produced and how much of it was new. */
|
|
24
|
+
export type CollectionPass = {
|
|
25
|
+
library: Library;
|
|
26
|
+
prepared: PreparedEmbeds;
|
|
27
|
+
documentCount: number;
|
|
28
|
+
/** Ids of the documents this pass compiled. Every document on a full pass. */
|
|
29
|
+
compiled: string[];
|
|
30
|
+
/** Documents taken from the previous library unchanged. */
|
|
31
|
+
reused: number;
|
|
32
|
+
/** Embed blocks in the library, and how many were taken from the previous preparation. */
|
|
33
|
+
blocks: number;
|
|
34
|
+
reusedBlocks: number;
|
|
35
|
+
outDir: string;
|
|
36
|
+
/** Wall-clock milliseconds the pass took. */
|
|
37
|
+
elapsed: number;
|
|
38
|
+
};
|
|
39
|
+
export type CollectionState = {
|
|
40
|
+
library?: Library;
|
|
41
|
+
prepared?: PreparedEmbeds;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* The library and preparation already in `outDir`, when they load and are
|
|
45
|
+
* worth reusing, so a watcher's first pass compiles only what changed since
|
|
46
|
+
* the last run. Anything unreadable or incompatible means starting fresh.
|
|
47
|
+
*/
|
|
48
|
+
export declare function previousCollection(outDir?: string): CollectionState;
|
|
49
|
+
/**
|
|
50
|
+
* One pass: collect, then prepare. With `previous`, an unchanged document is
|
|
51
|
+
* not compiled and an unaffected block is not resolved; the published files
|
|
52
|
+
* are complete either way.
|
|
53
|
+
*/
|
|
54
|
+
export declare function collectDocuments(config: CollectConfig, previous?: CollectionState): Promise<CollectionPass>;
|
|
55
|
+
export type WatchOptions = {
|
|
56
|
+
/** Quiet time after the last change before a pass starts, in milliseconds. Default 150. */
|
|
57
|
+
debounce?: number;
|
|
58
|
+
/** The result of every pass, the first included. */
|
|
59
|
+
onPass?: (pass: CollectionPass) => void;
|
|
60
|
+
/** A failed pass. The watcher keeps the last good result and keeps running. */
|
|
61
|
+
onError?: (error: unknown) => void;
|
|
62
|
+
/**
|
|
63
|
+
* Whether the first pass may start from what `outDir` already holds.
|
|
64
|
+
* Default true.
|
|
65
|
+
*/
|
|
66
|
+
reuseOutput?: boolean;
|
|
67
|
+
};
|
|
68
|
+
export type CollectionWatcher = {
|
|
69
|
+
/** Resolves when the first pass has finished, whether it succeeded or failed. */
|
|
70
|
+
ready: Promise<void>;
|
|
71
|
+
/** Stops watching. A pass in progress finishes. */
|
|
72
|
+
close(): void;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Collects once, then again whenever a `.md` or `.mdx` file under any root is
|
|
76
|
+
* created, changed, renamed or deleted. Changes that arrive while a pass runs
|
|
77
|
+
* start another pass when it finishes, so the output always reflects the
|
|
78
|
+
* latest files.
|
|
79
|
+
*/
|
|
80
|
+
export declare function watchDocuments(config: CollectConfig, options?: WatchOptions): CollectionWatcher;
|
|
81
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/node/watch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,EAKL,KAAK,qBAAqB,EAC1B,KAAK,OAAO,EACb,MAAM,cAAc,CAAA;AACrB,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAExE;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB,EAAE,UAAU,CAAC,GAAG;IACpE,QAAQ,CAAC,EAAE,CACT,GAAG,UAAU,EAAE,UAAU,CAAC,WAAW,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC,KACtE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;CAClD,CAAA;AAED,yDAAyD;AACzD,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,cAAc,CAAA;IACxB,aAAa,EAAE,MAAM,CAAA;IACrB,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAA;IACd,0FAA0F;IAC1F,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,cAAc,CAAA;CAC1B,CAAA;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,SAAqB,GAC1B,eAAe,CAkBjB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,aAAa,EACrB,QAAQ,GAAE,eAAoB,GAC7B,OAAO,CAAC,cAAc,CAAC,CA8BzB;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,2FAA2F;IAC3F,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IACvC,+EAA+E;IAC/E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAClC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,iFAAiF;IACjF,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IACpB,mDAAmD;IACnD,KAAK,IAAI,IAAI,CAAA;CACd,CAAA;AAOD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,OAAO,GAAE,YAAiB,GACzB,iBAAiB,CAoDnB"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection that repeats as sources change.
|
|
3
|
+
*
|
|
4
|
+
* A pass is what the CLI's `collect` does once: build the library, then
|
|
5
|
+
* prepare the embeds. Here every pass after the first hands the previous
|
|
6
|
+
* library and the previous preparation back in, so only the documents whose
|
|
7
|
+
* text changed compile again and only the blocks that read a changed document
|
|
8
|
+
* resolve again. The watcher runs a pass when a file under any root changes,
|
|
9
|
+
* after a short quiet period, and keeps the last good result when a pass
|
|
10
|
+
* fails, so a half-typed document is an error message rather than a broken
|
|
11
|
+
* library.
|
|
12
|
+
*/
|
|
13
|
+
import fs from "node:fs";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import { buildDocuments, buildDocumentsAsync, loadLibrary, resolveRoots, } from "./library.js";
|
|
16
|
+
import { prepareEmbeds } from "./prepare-embeds.js";
|
|
17
|
+
/**
|
|
18
|
+
* The library and preparation already in `outDir`, when they load and are
|
|
19
|
+
* worth reusing, so a watcher's first pass compiles only what changed since
|
|
20
|
+
* the last run. Anything unreadable or incompatible means starting fresh.
|
|
21
|
+
*/
|
|
22
|
+
export function previousCollection(outDir = ".cudoc/documents") {
|
|
23
|
+
const state = {};
|
|
24
|
+
try {
|
|
25
|
+
if (fs.existsSync(path.join(outDir, "manifest.json")))
|
|
26
|
+
state.library = loadLibrary(outDir);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const file = path.join(outDir, "embeds.json");
|
|
33
|
+
if (state.library && fs.existsSync(file)) {
|
|
34
|
+
const prepared = JSON.parse(fs.readFileSync(file, "utf8"));
|
|
35
|
+
if (prepared?.schemaVersion === 2)
|
|
36
|
+
state.prepared = prepared;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
delete state.prepared;
|
|
41
|
+
}
|
|
42
|
+
return state;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* One pass: collect, then prepare. With `previous`, an unchanged document is
|
|
46
|
+
* not compiled and an unaffected block is not resolved; the published files
|
|
47
|
+
* are complete either way.
|
|
48
|
+
*/
|
|
49
|
+
export async function collectDocuments(config, previous = {}) {
|
|
50
|
+
const started = Date.now();
|
|
51
|
+
const outDir = config.outDir ?? ".cudoc/documents";
|
|
52
|
+
const { compiler, ...rest } = config;
|
|
53
|
+
const options = { ...rest, previous: previous.library };
|
|
54
|
+
const library = compiler
|
|
55
|
+
? await buildDocumentsAsync({
|
|
56
|
+
...options,
|
|
57
|
+
compiler: async (...parameters) => compiler(...parameters),
|
|
58
|
+
})
|
|
59
|
+
: buildDocuments(options);
|
|
60
|
+
const prepared = await prepareEmbeds(library, outDir, {
|
|
61
|
+
previous: previous.prepared,
|
|
62
|
+
});
|
|
63
|
+
const keys = Object.keys(prepared.blocks);
|
|
64
|
+
return {
|
|
65
|
+
library,
|
|
66
|
+
prepared,
|
|
67
|
+
documentCount: library.documents.length,
|
|
68
|
+
compiled: library.incremental?.compiled ??
|
|
69
|
+
library.documents.map((document) => document.id),
|
|
70
|
+
reused: library.incremental?.reused.length ?? 0,
|
|
71
|
+
blocks: keys.length,
|
|
72
|
+
reusedBlocks: keys.filter((key) => previous.prepared?.blocks[key] === prepared.blocks[key]).length,
|
|
73
|
+
outDir,
|
|
74
|
+
elapsed: Date.now() - started,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Whether a changed path is one collection reads. */
|
|
78
|
+
const isSource = (filename) => filename === null ||
|
|
79
|
+
/\.mdx?$/i.test(typeof filename === "string" ? filename : String(filename));
|
|
80
|
+
/**
|
|
81
|
+
* Collects once, then again whenever a `.md` or `.mdx` file under any root is
|
|
82
|
+
* created, changed, renamed or deleted. Changes that arrive while a pass runs
|
|
83
|
+
* start another pass when it finishes, so the output always reflects the
|
|
84
|
+
* latest files.
|
|
85
|
+
*/
|
|
86
|
+
export function watchDocuments(config, options = {}) {
|
|
87
|
+
const debounce = options.debounce ?? 150;
|
|
88
|
+
const roots = resolveRoots(config);
|
|
89
|
+
let state = options.reuseOutput === false ? {} : previousCollection(config.outDir);
|
|
90
|
+
let running;
|
|
91
|
+
let pending = false;
|
|
92
|
+
let timer;
|
|
93
|
+
let closed = false;
|
|
94
|
+
const pass = async () => {
|
|
95
|
+
try {
|
|
96
|
+
const result = await collectDocuments(config, state);
|
|
97
|
+
state = { library: result.library, prepared: result.prepared };
|
|
98
|
+
options.onPass?.(result);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
options.onError?.(error);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const run = () => {
|
|
105
|
+
if (running) {
|
|
106
|
+
pending = true;
|
|
107
|
+
return running;
|
|
108
|
+
}
|
|
109
|
+
running = pass().then(async () => {
|
|
110
|
+
running = undefined;
|
|
111
|
+
if (pending && !closed) {
|
|
112
|
+
pending = false;
|
|
113
|
+
await run();
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return running;
|
|
117
|
+
};
|
|
118
|
+
const schedule = (_event, filename) => {
|
|
119
|
+
if (closed || !isSource(filename))
|
|
120
|
+
return;
|
|
121
|
+
if (timer)
|
|
122
|
+
clearTimeout(timer);
|
|
123
|
+
timer = setTimeout(() => {
|
|
124
|
+
timer = undefined;
|
|
125
|
+
void run();
|
|
126
|
+
}, debounce);
|
|
127
|
+
};
|
|
128
|
+
const watchers = roots.map((root) => fs.watch(root.dir, { recursive: true }, schedule));
|
|
129
|
+
return {
|
|
130
|
+
ready: run(),
|
|
131
|
+
close() {
|
|
132
|
+
closed = true;
|
|
133
|
+
if (timer)
|
|
134
|
+
clearTimeout(timer);
|
|
135
|
+
for (const watcher of watchers)
|
|
136
|
+
watcher.close();
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/node/watch.ts"],"names":[],"mappings":"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"}
|
package/dist/paged.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the paginated output formats have to agree on.
|
|
3
|
+
*
|
|
4
|
+
* A PDF is printed by a browser and a `.docx` is assembled by a writer that
|
|
5
|
+
* never sees CSS, so the only thing keeping the two in step is a shared
|
|
6
|
+
* definition rather than two implementations that happen to match. This module
|
|
7
|
+
* is browser-safe and holds no I/O.
|
|
8
|
+
*/
|
|
9
|
+
import type { Position } from "unist";
|
|
10
|
+
import type { DocumentNode } from "./document.js";
|
|
11
|
+
/** The info string an author writes on a fence to force a page break. */
|
|
12
|
+
export declare const PAGE_BREAK_FENCE = "cudoc-pagebreak";
|
|
13
|
+
/** `data.cudoc.kind` on the node the fence normalizes to. */
|
|
14
|
+
export declare const PAGE_BREAK_KIND = "pageBreak";
|
|
15
|
+
/** The class the printed stylesheets key their `break-after` rule off. */
|
|
16
|
+
export declare const PAGE_BREAK_CLASS = "cudoc-page-break";
|
|
17
|
+
/**
|
|
18
|
+
* Whether a node is an authored page break.
|
|
19
|
+
*
|
|
20
|
+
* A writer must test this **before** any generic `thematicBreak` handling: the
|
|
21
|
+
* break is carried on a `thematicBreak` because that is a childless flow node
|
|
22
|
+
* which can never swallow content, so a handler that dispatches on `type` alone
|
|
23
|
+
* turns an authored page break into a horizontal rule.
|
|
24
|
+
*/
|
|
25
|
+
export declare const isPageBreak: (node: DocumentNode) => boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The node an authored break becomes.
|
|
28
|
+
*
|
|
29
|
+
* `hidden` gives it the user agent's `display: none`, so a host stylesheet
|
|
30
|
+
* cudoc does not own cannot give the empty element a margin on the primary
|
|
31
|
+
* site. The printed stylesheet turns it back on and breaks after it.
|
|
32
|
+
*/
|
|
33
|
+
export declare const pageBreakNode: (position?: Position) => DocumentNode;
|
|
34
|
+
//# sourceMappingURL=paged.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paged.d.ts","sourceRoot":"","sources":["../src/paged.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAEjD,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,oBAAoB,CAAA;AAEjD,6DAA6D;AAC7D,eAAO,MAAM,eAAe,cAAc,CAAA;AAE1C,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,qBAAqB,CAAA;AAElD;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,YAAY,KAAG,OACL,CAAA;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,GAAI,WAAW,QAAQ,KAAG,YAYlD,CAAA"}
|
package/dist/paged.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the paginated output formats have to agree on.
|
|
3
|
+
*
|
|
4
|
+
* A PDF is printed by a browser and a `.docx` is assembled by a writer that
|
|
5
|
+
* never sees CSS, so the only thing keeping the two in step is a shared
|
|
6
|
+
* definition rather than two implementations that happen to match. This module
|
|
7
|
+
* is browser-safe and holds no I/O.
|
|
8
|
+
*/
|
|
9
|
+
/** The info string an author writes on a fence to force a page break. */
|
|
10
|
+
export const PAGE_BREAK_FENCE = "cudoc-pagebreak";
|
|
11
|
+
/** `data.cudoc.kind` on the node the fence normalizes to. */
|
|
12
|
+
export const PAGE_BREAK_KIND = "pageBreak";
|
|
13
|
+
/** The class the printed stylesheets key their `break-after` rule off. */
|
|
14
|
+
export const PAGE_BREAK_CLASS = "cudoc-page-break";
|
|
15
|
+
/**
|
|
16
|
+
* Whether a node is an authored page break.
|
|
17
|
+
*
|
|
18
|
+
* A writer must test this **before** any generic `thematicBreak` handling: the
|
|
19
|
+
* break is carried on a `thematicBreak` because that is a childless flow node
|
|
20
|
+
* which can never swallow content, so a handler that dispatches on `type` alone
|
|
21
|
+
* turns an authored page break into a horizontal rule.
|
|
22
|
+
*/
|
|
23
|
+
export const isPageBreak = (node) => node.data?.cudoc?.kind === PAGE_BREAK_KIND;
|
|
24
|
+
/**
|
|
25
|
+
* The node an authored break becomes.
|
|
26
|
+
*
|
|
27
|
+
* `hidden` gives it the user agent's `display: none`, so a host stylesheet
|
|
28
|
+
* cudoc does not own cannot give the empty element a margin on the primary
|
|
29
|
+
* site. The printed stylesheet turns it back on and breaks after it.
|
|
30
|
+
*/
|
|
31
|
+
export const pageBreakNode = (position) => ({
|
|
32
|
+
type: "thematicBreak",
|
|
33
|
+
...(position ? { position } : {}),
|
|
34
|
+
data: {
|
|
35
|
+
hName: "div",
|
|
36
|
+
hProperties: {
|
|
37
|
+
className: [PAGE_BREAK_CLASS],
|
|
38
|
+
"data-cudoc-break": "page",
|
|
39
|
+
hidden: true,
|
|
40
|
+
},
|
|
41
|
+
cudoc: { kind: PAGE_BREAK_KIND },
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=paged.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paged.js","sourceRoot":"","sources":["../src/paged.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,yEAAyE;AACzE,MAAM,CAAC,MAAM,gBAAgB,GAAG,iBAAiB,CAAA;AAEjD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAA;AAE1C,0EAA0E;AAC1E,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAA;AAElD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAkB,EAAW,EAAE,CACzD,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,eAAe,CAAA;AAE5C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAmB,EAAgB,EAAE,CAAC,CAAC;IACnE,IAAI,EAAE,eAAe;IACrB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACjC,IAAI,EAAE;QACJ,KAAK,EAAE,KAAK;QACZ,WAAW,EAAE;YACX,SAAS,EAAE,CAAC,gBAAgB,CAAC;YAC7B,kBAAkB,EAAE,MAAM;YAC1B,MAAM,EAAE,IAAI;SACb;QACD,KAAK,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE;KACjC;CACF,CAAC,CAAA"}
|