@quillmark/quiver 0.15.0 → 0.17.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/LICENSE +201 -21
- package/NOTICE +2 -0
- package/README.md +87 -201
- package/dist/bin/quiver.d.ts +4 -4
- package/dist/bin/quiver.js +28 -60
- package/dist/build.d.ts +12 -12
- package/dist/build.js +75 -32
- package/dist/built-loader.d.ts +17 -11
- package/dist/built-loader.js +116 -99
- package/dist/bundle.js +1 -1
- package/dist/digest.d.ts +19 -0
- package/dist/digest.js +25 -0
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -5
- package/dist/node.d.ts +47 -76
- package/dist/node.js +59 -64
- package/dist/quiver-yaml.js +19 -19
- package/dist/quiver.d.ts +25 -27
- package/dist/quiver.js +46 -95
- package/dist/ref.d.ts +3 -3
- package/dist/ref.js +15 -13
- package/dist/semver.d.ts +5 -1
- package/dist/semver.js +9 -10
- package/dist/source-loader.d.ts +3 -3
- package/dist/source-loader.js +26 -26
- package/dist/transports/fs-built-transport.d.ts +2 -2
- package/dist/transports/fs-built-transport.js +10 -8
- package/dist/transports/http-transport.d.ts +2 -2
- package/dist/transports/http-transport.js +11 -9
- package/package.json +66 -72
- package/dist/preview.d.ts +0 -81
- package/dist/preview.js +0 -208
- package/dist/testing.d.ts +0 -28
- package/dist/testing.js +0 -66
package/dist/semver.js
CHANGED
|
@@ -2,17 +2,16 @@
|
|
|
2
2
|
export function isCanonicalSemver(version) {
|
|
3
3
|
return /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(version);
|
|
4
4
|
}
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* Returns true if `version` (canonical) matches `selector` (partial: `x`,
|
|
7
|
+
* `x.y`, or `x.y.z`). `parseQuillRef` owns selector validation; this is a
|
|
8
|
+
* prefix comparison over an already-valid selector.
|
|
9
|
+
*/
|
|
6
10
|
export function matchesSemverSelector(version, selector) {
|
|
7
11
|
if (selector === version)
|
|
8
12
|
return true;
|
|
9
|
-
const selectorParts = selector.split(
|
|
10
|
-
const versionParts = version.split(
|
|
11
|
-
if (selectorParts.length === 0 ||
|
|
12
|
-
selectorParts.length > 3 ||
|
|
13
|
-
selectorParts.some((p) => p.length === 0 || Number.isNaN(Number(p)))) {
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
13
|
+
const selectorParts = selector.split('.');
|
|
14
|
+
const versionParts = version.split('.');
|
|
16
15
|
if (selectorParts.length > versionParts.length)
|
|
17
16
|
return false;
|
|
18
17
|
for (let i = 0; i < selectorParts.length; i++) {
|
|
@@ -23,8 +22,8 @@ export function matchesSemverSelector(version, selector) {
|
|
|
23
22
|
}
|
|
24
23
|
/** Compares two canonical semver strings. Returns <0, 0, or >0. */
|
|
25
24
|
export function compareSemver(a, b) {
|
|
26
|
-
const partsA = a.split(
|
|
27
|
-
const partsB = b.split(
|
|
25
|
+
const partsA = a.split('.').map(Number);
|
|
26
|
+
const partsB = b.split('.').map(Number);
|
|
28
27
|
const len = Math.max(partsA.length, partsB.length);
|
|
29
28
|
for (let i = 0; i < len; i++) {
|
|
30
29
|
const numA = partsA[i] ?? 0;
|
package/dist/source-loader.d.ts
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Internal filesystem scanner for Source Quiver layout.
|
|
3
3
|
*
|
|
4
4
|
* Uses Node.js `fs/promises` — this module must only be imported from
|
|
5
|
-
* Node-only contexts (fromDir
|
|
5
|
+
* Node-only contexts (`fromDir`, `build`).
|
|
6
6
|
*/
|
|
7
|
-
import type { QuiverMeta } from
|
|
8
|
-
import type { QuiverLoader } from
|
|
7
|
+
import type { QuiverMeta } from './quiver-yaml.js';
|
|
8
|
+
import type { QuiverLoader } from './quiver.js';
|
|
9
9
|
/**
|
|
10
10
|
* Scans a Source Quiver root directory.
|
|
11
11
|
*
|
package/dist/source-loader.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* Internal filesystem scanner for Source Quiver layout.
|
|
3
3
|
*
|
|
4
4
|
* Uses Node.js `fs/promises` — this module must only be imported from
|
|
5
|
-
* Node-only contexts (fromDir
|
|
5
|
+
* Node-only contexts (`fromDir`, `build`).
|
|
6
6
|
*/
|
|
7
|
-
import { readdir, readFile, stat } from
|
|
8
|
-
import { join, relative, sep } from
|
|
9
|
-
import { QuiverError } from
|
|
10
|
-
import { parseQuiverYaml } from
|
|
11
|
-
import { isCanonicalSemver, compareSemver } from
|
|
7
|
+
import { readdir, readFile, stat } from 'node:fs/promises';
|
|
8
|
+
import { join, relative, sep } from 'node:path';
|
|
9
|
+
import { QuiverError } from './errors.js';
|
|
10
|
+
import { parseQuiverYaml } from './quiver-yaml.js';
|
|
11
|
+
import { isCanonicalSemver, compareSemver } from './semver.js';
|
|
12
12
|
/**
|
|
13
13
|
* Scans a Source Quiver root directory.
|
|
14
14
|
*
|
|
@@ -24,7 +24,7 @@ import { isCanonicalSemver, compareSemver } from "./semver.js";
|
|
|
24
24
|
*/
|
|
25
25
|
export async function scanSourceQuiver(rootDir) {
|
|
26
26
|
// --- Read Quiver.yaml ---
|
|
27
|
-
const quiverYamlPath = join(rootDir,
|
|
27
|
+
const quiverYamlPath = join(rootDir, 'Quiver.yaml');
|
|
28
28
|
let raw;
|
|
29
29
|
try {
|
|
30
30
|
raw = await readFile(quiverYamlPath);
|
|
@@ -36,25 +36,25 @@ export async function scanSourceQuiver(rootDir) {
|
|
|
36
36
|
// (Contrast: missing Quill.yaml inside a version dir is quiver_invalid —
|
|
37
37
|
// the version dir exists but lacks its required sentinel file.)
|
|
38
38
|
const code = err.code;
|
|
39
|
-
if (code ===
|
|
40
|
-
throw new QuiverError(
|
|
39
|
+
if (code === 'ENOENT') {
|
|
40
|
+
throw new QuiverError('transport_error', `Source Quiver at "${rootDir}" is missing required "Quiver.yaml"`, { cause: err });
|
|
41
41
|
}
|
|
42
|
-
throw new QuiverError(
|
|
42
|
+
throw new QuiverError('transport_error', `Failed to read "Quiver.yaml" at "${quiverYamlPath}": ${err.message}`, { cause: err });
|
|
43
43
|
}
|
|
44
44
|
const meta = parseQuiverYaml(raw);
|
|
45
45
|
// --- Walk quills/ directory ---
|
|
46
|
-
const quillsDir = join(rootDir,
|
|
46
|
+
const quillsDir = join(rootDir, 'quills');
|
|
47
47
|
let quillNames;
|
|
48
48
|
try {
|
|
49
49
|
quillNames = await readdir(quillsDir);
|
|
50
50
|
}
|
|
51
51
|
catch (err) {
|
|
52
52
|
const code = err.code;
|
|
53
|
-
if (code ===
|
|
53
|
+
if (code === 'ENOENT') {
|
|
54
54
|
// Missing quills/ is fine — empty catalog
|
|
55
55
|
return { meta, catalog: new Map() };
|
|
56
56
|
}
|
|
57
|
-
throw new QuiverError(
|
|
57
|
+
throw new QuiverError('transport_error', `Failed to read "quills/" directory at "${quillsDir}": ${err.message}`, { cause: err });
|
|
58
58
|
}
|
|
59
59
|
const catalog = new Map();
|
|
60
60
|
for (const quillName of quillNames) {
|
|
@@ -65,7 +65,7 @@ export async function scanSourceQuiver(rootDir) {
|
|
|
65
65
|
st = await stat(quillNameDir);
|
|
66
66
|
}
|
|
67
67
|
catch (err) {
|
|
68
|
-
throw new QuiverError(
|
|
68
|
+
throw new QuiverError('transport_error', `Failed to stat "${quillNameDir}": ${err.message}`, { cause: err });
|
|
69
69
|
}
|
|
70
70
|
if (!st.isDirectory())
|
|
71
71
|
continue;
|
|
@@ -75,7 +75,7 @@ export async function scanSourceQuiver(rootDir) {
|
|
|
75
75
|
versionDirs = await readdir(quillNameDir);
|
|
76
76
|
}
|
|
77
77
|
catch (err) {
|
|
78
|
-
throw new QuiverError(
|
|
78
|
+
throw new QuiverError('transport_error', `Failed to read versions for quill "${quillName}": ${err.message}`, { cause: err });
|
|
79
79
|
}
|
|
80
80
|
const versions = [];
|
|
81
81
|
for (const versionDir of versionDirs) {
|
|
@@ -86,25 +86,25 @@ export async function scanSourceQuiver(rootDir) {
|
|
|
86
86
|
vst = await stat(versionPath);
|
|
87
87
|
}
|
|
88
88
|
catch (err) {
|
|
89
|
-
throw new QuiverError(
|
|
89
|
+
throw new QuiverError('transport_error', `Failed to stat "${versionPath}": ${err.message}`, { cause: err });
|
|
90
90
|
}
|
|
91
91
|
if (!vst.isDirectory())
|
|
92
92
|
continue;
|
|
93
93
|
// Non-canonical version → quiver_invalid
|
|
94
94
|
if (!isCanonicalSemver(versionDir)) {
|
|
95
|
-
throw new QuiverError(
|
|
95
|
+
throw new QuiverError('quiver_invalid', `Quill "${quillName}" has non-canonical version directory "${versionDir}" — only x.y.z format is allowed`, { quiverName: meta.name, version: versionDir });
|
|
96
96
|
}
|
|
97
97
|
// Require Quill.yaml sentinel inside the version dir
|
|
98
|
-
const quillYamlPath = join(versionPath,
|
|
98
|
+
const quillYamlPath = join(versionPath, 'Quill.yaml');
|
|
99
99
|
try {
|
|
100
100
|
await stat(quillYamlPath);
|
|
101
101
|
}
|
|
102
102
|
catch (err) {
|
|
103
103
|
const code = err.code;
|
|
104
|
-
if (code ===
|
|
105
|
-
throw new QuiverError(
|
|
104
|
+
if (code === 'ENOENT') {
|
|
105
|
+
throw new QuiverError('quiver_invalid', `Quill "${quillName}@${versionDir}" is missing required "Quill.yaml"`, { quiverName: meta.name, version: versionDir });
|
|
106
106
|
}
|
|
107
|
-
throw new QuiverError(
|
|
107
|
+
throw new QuiverError('transport_error', `Failed to stat "Quill.yaml" at "${quillYamlPath}": ${err.message}`, { cause: err });
|
|
108
108
|
}
|
|
109
109
|
versions.push(versionDir);
|
|
110
110
|
}
|
|
@@ -133,7 +133,7 @@ async function walkDir(baseDir, currentDir, tree) {
|
|
|
133
133
|
entries = await readdir(currentDir);
|
|
134
134
|
}
|
|
135
135
|
catch (err) {
|
|
136
|
-
throw new QuiverError(
|
|
136
|
+
throw new QuiverError('transport_error', `Failed to read directory "${currentDir}": ${err.message}`, { cause: err });
|
|
137
137
|
}
|
|
138
138
|
for (const entry of entries) {
|
|
139
139
|
const fullPath = join(currentDir, entry);
|
|
@@ -142,7 +142,7 @@ async function walkDir(baseDir, currentDir, tree) {
|
|
|
142
142
|
st = await stat(fullPath);
|
|
143
143
|
}
|
|
144
144
|
catch (err) {
|
|
145
|
-
throw new QuiverError(
|
|
145
|
+
throw new QuiverError('transport_error', `Failed to stat "${fullPath}": ${err.message}`, { cause: err });
|
|
146
146
|
}
|
|
147
147
|
if (st.isDirectory()) {
|
|
148
148
|
await walkDir(baseDir, fullPath, tree);
|
|
@@ -150,13 +150,13 @@ async function walkDir(baseDir, currentDir, tree) {
|
|
|
150
150
|
else {
|
|
151
151
|
// Compute relative POSIX path
|
|
152
152
|
const rel = relative(baseDir, fullPath);
|
|
153
|
-
const posixRel = sep ===
|
|
153
|
+
const posixRel = sep === '/' ? rel : rel.split(sep).join('/');
|
|
154
154
|
let bytes;
|
|
155
155
|
try {
|
|
156
156
|
bytes = await readFile(fullPath);
|
|
157
157
|
}
|
|
158
158
|
catch (err) {
|
|
159
|
-
throw new QuiverError(
|
|
159
|
+
throw new QuiverError('transport_error', `Failed to read file "${fullPath}": ${err.message}`, { cause: err });
|
|
160
160
|
}
|
|
161
161
|
tree.set(posixRel, bytes);
|
|
162
162
|
}
|
|
@@ -173,7 +173,7 @@ export class SourceLoader {
|
|
|
173
173
|
this.rootDir = rootDir;
|
|
174
174
|
}
|
|
175
175
|
async loadTree(name, version) {
|
|
176
|
-
const quillDir = join(this.rootDir,
|
|
176
|
+
const quillDir = join(this.rootDir, 'quills', name, version);
|
|
177
177
|
return readQuillTree(quillDir);
|
|
178
178
|
}
|
|
179
179
|
}
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Internal; not exported from index.ts.
|
|
5
5
|
*
|
|
6
6
|
* Static `node:*` imports — this module must never be reached from browser
|
|
7
|
-
* bundles. It is loaded lazily by `
|
|
7
|
+
* bundles. It is loaded lazily by `fromBuiltDir` in `./node.js`.
|
|
8
8
|
*/
|
|
9
|
-
import type { BuiltTransport } from
|
|
9
|
+
import type { BuiltTransport } from '../built-loader.js';
|
|
10
10
|
export declare class FsBuiltTransport implements BuiltTransport {
|
|
11
11
|
private readonly rootDir;
|
|
12
12
|
constructor(rootDir: string);
|
|
@@ -4,23 +4,25 @@
|
|
|
4
4
|
* Internal; not exported from index.ts.
|
|
5
5
|
*
|
|
6
6
|
* Static `node:*` imports — this module must never be reached from browser
|
|
7
|
-
* bundles. It is loaded lazily by `
|
|
7
|
+
* bundles. It is loaded lazily by `fromBuiltDir` in `./node.js`.
|
|
8
8
|
*/
|
|
9
|
-
import { readFile } from
|
|
10
|
-
import { join, isAbsolute, normalize, sep } from
|
|
11
|
-
import { QuiverError } from
|
|
9
|
+
import { readFile } from 'node:fs/promises';
|
|
10
|
+
import { join, isAbsolute, normalize, sep } from 'node:path';
|
|
11
|
+
import { QuiverError } from '../errors.js';
|
|
12
12
|
export class FsBuiltTransport {
|
|
13
13
|
rootDir;
|
|
14
14
|
constructor(rootDir) {
|
|
15
15
|
this.rootDir = rootDir;
|
|
16
16
|
}
|
|
17
|
+
// No cache sits between this and the bytes, so `FetchOptions` has nothing to
|
|
18
|
+
// act on here.
|
|
17
19
|
async fetchBytes(relativePath) {
|
|
18
20
|
if (isAbsolute(relativePath)) {
|
|
19
|
-
throw new QuiverError(
|
|
21
|
+
throw new QuiverError('transport_error', `FsBuiltTransport: absolute paths are not allowed: "${relativePath}"`);
|
|
20
22
|
}
|
|
21
23
|
const normalized = normalize(relativePath);
|
|
22
|
-
if (normalized.startsWith(
|
|
23
|
-
throw new QuiverError(
|
|
24
|
+
if (normalized.startsWith('..') || normalized.split(sep).includes('..')) {
|
|
25
|
+
throw new QuiverError('transport_error', `FsBuiltTransport: path escapes root: "${relativePath}"`);
|
|
24
26
|
}
|
|
25
27
|
const filePath = join(this.rootDir, normalized);
|
|
26
28
|
try {
|
|
@@ -28,7 +30,7 @@ export class FsBuiltTransport {
|
|
|
28
30
|
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
29
31
|
}
|
|
30
32
|
catch (err) {
|
|
31
|
-
throw new QuiverError(
|
|
33
|
+
throw new QuiverError('transport_error', `Failed to read "${filePath}": ${err.message}`, { cause: err });
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
36
|
}
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Uses globalThis.fetch — no node: imports at any level.
|
|
6
6
|
*/
|
|
7
|
-
import type { BuiltTransport } from
|
|
7
|
+
import type { BuiltTransport, FetchOptions } from '../built-loader.js';
|
|
8
8
|
export declare class HttpTransport implements BuiltTransport {
|
|
9
9
|
private readonly baseUrl;
|
|
10
10
|
constructor(baseUrl: string);
|
|
11
|
-
fetchBytes(relativePath: string): Promise<Uint8Array>;
|
|
11
|
+
fetchBytes(relativePath: string, opts?: FetchOptions): Promise<Uint8Array>;
|
|
12
12
|
}
|
|
@@ -4,28 +4,30 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Uses globalThis.fetch — no node: imports at any level.
|
|
6
6
|
*/
|
|
7
|
-
import { QuiverError } from
|
|
7
|
+
import { QuiverError } from '../errors.js';
|
|
8
8
|
export class HttpTransport {
|
|
9
9
|
baseUrl;
|
|
10
10
|
constructor(baseUrl) {
|
|
11
11
|
// Normalize: ensure exactly one trailing slash.
|
|
12
|
-
this.baseUrl = baseUrl.endsWith(
|
|
12
|
+
this.baseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
|
|
13
13
|
}
|
|
14
|
-
async fetchBytes(relativePath) {
|
|
14
|
+
async fetchBytes(relativePath, opts) {
|
|
15
15
|
// Strip any leading slash from relativePath to avoid double slashes.
|
|
16
|
-
const cleanPath = relativePath.startsWith(
|
|
17
|
-
? relativePath.slice(1)
|
|
18
|
-
: relativePath;
|
|
16
|
+
const cleanPath = relativePath.startsWith('/') ? relativePath.slice(1) : relativePath;
|
|
19
17
|
const url = `${this.baseUrl}${cleanPath}`;
|
|
20
18
|
let response;
|
|
21
19
|
try {
|
|
22
|
-
|
|
20
|
+
// `no-cache` revalidates with the origin rather than skipping the cache:
|
|
21
|
+
// a 304 still serves from disk. Only the pointer asks for it, and only
|
|
22
|
+
// the browser-cache layer of the stale-pointer failure is a client's to
|
|
23
|
+
// fix; a stale edge is answered by that host's cache headers.
|
|
24
|
+
response = await globalThis.fetch(url, opts?.revalidate ? { cache: 'no-cache' } : undefined);
|
|
23
25
|
}
|
|
24
26
|
catch (err) {
|
|
25
|
-
throw new QuiverError(
|
|
27
|
+
throw new QuiverError('transport_error', `Network error fetching "${url}": ${err.message}`, { cause: err });
|
|
26
28
|
}
|
|
27
29
|
if (!response.ok) {
|
|
28
|
-
throw new QuiverError(
|
|
30
|
+
throw new QuiverError('transport_error', `HTTP ${response.status} fetching "${url}"`);
|
|
29
31
|
}
|
|
30
32
|
const buffer = await response.arrayBuffer();
|
|
31
33
|
return new Uint8Array(buffer);
|
package/package.json
CHANGED
|
@@ -1,74 +1,68 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"scripts": {
|
|
69
|
-
"build": "tsc",
|
|
70
|
-
"prepack": "rm -rf dist && tsc",
|
|
71
|
-
"test": "vitest run",
|
|
72
|
-
"lint": "tsc --noEmit"
|
|
73
|
-
}
|
|
2
|
+
"name": "@quillmark/quiver",
|
|
3
|
+
"version": "0.17.0",
|
|
4
|
+
"description": "Quiver registry and build tooling for Quillmark",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/borb-sh/quillmark-js.git",
|
|
10
|
+
"directory": "packages/quiver"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/borb-sh/quillmark-js/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/borb-sh/quillmark-js/tree/main/packages/quiver#readme",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"quillmark",
|
|
18
|
+
"quiver",
|
|
19
|
+
"typst",
|
|
20
|
+
"markdown"
|
|
21
|
+
],
|
|
22
|
+
"author": "Quillmark Contributors",
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=22"
|
|
25
|
+
},
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"import": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./node": {
|
|
32
|
+
"types": "./dist/node.d.ts",
|
|
33
|
+
"import": "./dist/node.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"sideEffects": false,
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"NOTICE"
|
|
40
|
+
],
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@quillmark/wasm": ">=0.101.0-0"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"fflate": "^0.8.2",
|
|
46
|
+
"yaml": "^2.8.3"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^25.3.3",
|
|
50
|
+
"publint": "^0.3.0",
|
|
51
|
+
"typescript": "^5.9.3",
|
|
52
|
+
"vitest": "^4.0.18"
|
|
53
|
+
},
|
|
54
|
+
"bin": {
|
|
55
|
+
"quiver": "./dist/bin/quiver.js"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsc",
|
|
59
|
+
"prepare": "npm run build",
|
|
60
|
+
"prepack": "rm -rf dist && npm run build",
|
|
61
|
+
"test": "vitest run",
|
|
62
|
+
"check": "tsc --noEmit -p tsconfig.check.json",
|
|
63
|
+
"check:pack": "publint"
|
|
64
|
+
},
|
|
65
|
+
"publishConfig": {
|
|
66
|
+
"access": "public"
|
|
67
|
+
}
|
|
74
68
|
}
|
package/dist/preview.d.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Manual-validation helper for Quiver authors.
|
|
3
|
-
*
|
|
4
|
-
* `runQuiverTests` (`@quillmark/quiver/testing`) proves every quill *compiles*
|
|
5
|
-
* — it never produces a rendered artifact a human can look at. This module
|
|
6
|
-
* closes that gap: it renders each quill's example document, writes the
|
|
7
|
-
* artifacts to a directory, and emits an `index.html` gallery so an author can
|
|
8
|
-
* eyeball real output before publishing.
|
|
9
|
-
*
|
|
10
|
-
* Node-only: writes files and loads a source quiver from disk.
|
|
11
|
-
*
|
|
12
|
-
* Usage (place a script next to your Quiver.yaml):
|
|
13
|
-
*
|
|
14
|
-
* import { Engine } from "@quillmark/wasm";
|
|
15
|
-
* import { renderQuiverSamples } from "@quillmark/quiver/preview";
|
|
16
|
-
*
|
|
17
|
-
* await renderQuiverSamples(import.meta.url, { engine: new Engine() });
|
|
18
|
-
* // → open ./preview/index.html
|
|
19
|
-
*
|
|
20
|
-
* The sample document is the illustrative example seeded by
|
|
21
|
-
* `quill.seedDocument()` for each quill version — a fully filled-out,
|
|
22
|
-
* always-renderable document (the blueprint itself carries `<must-fill>`
|
|
23
|
-
* sentinels and is not renderable). Every quill always seeds an example, so no
|
|
24
|
-
* quills are skipped for lack of a sample document.
|
|
25
|
-
*
|
|
26
|
-
* A `.gitignore` is written into `outDir` so the generated artifacts are not
|
|
27
|
-
* accidentally committed.
|
|
28
|
-
*/
|
|
29
|
-
import type { Engine } from "@quillmark/wasm";
|
|
30
|
-
export interface RenderQuiverSamplesOptions {
|
|
31
|
-
/**
|
|
32
|
-
* Canonical render engine (`new Engine()` from `@quillmark/wasm`). It takes the
|
|
33
|
-
* core `Quill`/`Document` that quiver produces and clones them into the
|
|
34
|
-
* backend on demand — no build-matching or handle-crossing for the caller.
|
|
35
|
-
*/
|
|
36
|
-
engine: Engine;
|
|
37
|
-
/** Directory to write rendered artifacts into. Default: `preview`. */
|
|
38
|
-
outDir?: string;
|
|
39
|
-
/** Force an output format (`pdf`/`svg`/`png`/`txt`). Default: engine's choice. */
|
|
40
|
-
format?: string;
|
|
41
|
-
/** Suppress the console summary. Default: false. */
|
|
42
|
-
quiet?: boolean;
|
|
43
|
-
/**
|
|
44
|
-
* Render only these quills. Each entry matches a quill name (`"memo"`) or a
|
|
45
|
-
* canonical ref (`"memo@1.0.0"`). Omit to render all quills.
|
|
46
|
-
*/
|
|
47
|
-
include?: string[];
|
|
48
|
-
/**
|
|
49
|
-
* Skip these quills. Each entry matches a quill name (`"memo"`) or a
|
|
50
|
-
* canonical ref (`"memo@1.0.0"`). Applied after `include`.
|
|
51
|
-
*/
|
|
52
|
-
exclude?: string[];
|
|
53
|
-
}
|
|
54
|
-
/** Per-quill outcome returned by `renderQuiverSamples`. */
|
|
55
|
-
export interface RenderedSample {
|
|
56
|
-
/** Canonical ref, e.g. `"memo@1.0.0"`. */
|
|
57
|
-
ref: string;
|
|
58
|
-
/** `rendered` — artifacts written; `failed` — error. */
|
|
59
|
-
status: "rendered" | "failed";
|
|
60
|
-
/** Artifact filenames written under `outDir` (relative). */
|
|
61
|
-
files: string[];
|
|
62
|
-
/** Render warnings, formatted `"severity: message"`. */
|
|
63
|
-
warnings: string[];
|
|
64
|
-
/**
|
|
65
|
-
* Why the quill was skipped or failed. Empty when rendered. A failed render
|
|
66
|
-
* carries every diagnostic from the engine, not just the first.
|
|
67
|
-
*/
|
|
68
|
-
reasons: string[];
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Renders every quill's example document and writes the artifacts plus an
|
|
72
|
-
* `index.html` gallery to `outDir`.
|
|
73
|
-
*
|
|
74
|
-
* Does NOT fail fast: a quill that throws is recorded as `failed` and the
|
|
75
|
-
* run continues, so one broken quill never hides the others. Inspect the
|
|
76
|
-
* returned array (or `index.html`) for the full picture.
|
|
77
|
-
*
|
|
78
|
-
* @param metaUrlOrDir `import.meta.url` when called from the quiver root, or
|
|
79
|
-
* an absolute path to the source quiver directory.
|
|
80
|
-
*/
|
|
81
|
-
export declare function renderQuiverSamples(metaUrlOrDir: string, opts: RenderQuiverSamplesOptions): Promise<RenderedSample[]>;
|