@raybase/record-mount 0.0.2 → 0.3.3
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 +21 -0
- package/README.md +432 -2
- package/dist/body.d.ts +165 -0
- package/dist/body.d.ts.map +1 -0
- package/dist/body.js +538 -0
- package/dist/body.js.map +1 -0
- package/dist/client.d.ts +132 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +376 -0
- package/dist/client.js.map +1 -0
- package/dist/contract.d.ts +261 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +83 -0
- package/dist/contract.js.map +1 -0
- package/dist/errors.d.ts +41 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +81 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/mount.d.ts +219 -0
- package/dist/mount.d.ts.map +1 -0
- package/dist/mount.js +372 -0
- package/dist/mount.js.map +1 -0
- package/dist/testing.d.ts +149 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +764 -0
- package/dist/testing.js.map +1 -0
- package/package.json +34 -8
package/dist/body.js
ADDED
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-family body builder: filing from a form means composing a
|
|
3
|
+
* canonical record body, and this is the machinery that composes it.
|
|
4
|
+
*
|
|
5
|
+
* **It is generic over consumer-supplied family descriptors.** No family,
|
|
6
|
+
* no field name and no id prefix is hardcoded anywhere in this package —
|
|
7
|
+
* the consumer's schema domain stays the consumer's. What this module owns
|
|
8
|
+
* is the *dialect*: which frontmatter forms it will emit, deterministically,
|
|
9
|
+
* and which inputs it refuses rather than rendering ambiguously.
|
|
10
|
+
*
|
|
11
|
+
* ## The dialect, and why it is small
|
|
12
|
+
*
|
|
13
|
+
* A record body is frontmatter plus prose, and the parser on the other end
|
|
14
|
+
* is a minimal one — the record substrate parses the envelope out of the
|
|
15
|
+
* body itself, with a hand-written reader rather than a YAML library.
|
|
16
|
+
* Emitting the full YAML surface would produce bytes that round-trip
|
|
17
|
+
* through a real YAML parser and are silently misread by a minimal one, so
|
|
18
|
+
* this composer emits four forms only:
|
|
19
|
+
*
|
|
20
|
+
* - `scalar` — `key: value`
|
|
21
|
+
* - `list` — `key: [a, b]`
|
|
22
|
+
* - `folded` — `key: >-` with two-space continuation lines, rejoined with
|
|
23
|
+
* single spaces on read
|
|
24
|
+
* - `map` — a bare `key:` with two-space `sub: value` lines
|
|
25
|
+
*
|
|
26
|
+
* and it **refuses** any value it cannot render unambiguously in that
|
|
27
|
+
* subset. A refusal is loud and typed; there is no escaping fallback,
|
|
28
|
+
* because a value that needs escaping to survive is a value the reader on
|
|
29
|
+
* the other end will get wrong.
|
|
30
|
+
*
|
|
31
|
+
* That list is the WRITE dialect, and the reader in this module is wider
|
|
32
|
+
* than it: a mount reads records other writers filed, so the reader tracks
|
|
33
|
+
* the record substrate's own reader (folded map sub-values, tab-led
|
|
34
|
+
* continuations) rather than this writer. See `parseRecordFrontmatter` —
|
|
35
|
+
* the asymmetry is deliberate and documented there.
|
|
36
|
+
*
|
|
37
|
+
* Keys are restricted to letters, `_` and `-` for the same reason: the
|
|
38
|
+
* minimal readers this dialect targets match keys with that charset and
|
|
39
|
+
* SKIP a line they do not match, which turns a key containing a digit into
|
|
40
|
+
* a silently dropped field. A refusal at compose time is the better
|
|
41
|
+
* failure.
|
|
42
|
+
*
|
|
43
|
+
* ## Refusals arrive in the door's own taxonomy
|
|
44
|
+
*
|
|
45
|
+
* A composition refusal throws `RecordDoorError` with code
|
|
46
|
+
* `invalid_record` — exactly what the door answers for a body it cannot
|
|
47
|
+
* accept. A form handler therefore has ONE error surface for "this filing
|
|
48
|
+
* is malformed", whether the composer caught it or the store did, and
|
|
49
|
+
* neither becomes a 500.
|
|
50
|
+
*/
|
|
51
|
+
import { recordDoorError } from "./errors.js";
|
|
52
|
+
const KEY_RE = /^[A-Za-z_-]+$/;
|
|
53
|
+
/**
|
|
54
|
+
* The folded block's wrap column. Cosmetic to read, load-bearing to write:
|
|
55
|
+
* a folded value rejoins with single spaces, so any width parses back to the
|
|
56
|
+
* same value — but two builds at different widths produce different BYTES,
|
|
57
|
+
* and therefore a different `body_sha256` for the same logical record. Since
|
|
58
|
+
* a record's digest is its identity, **this constant must never change.**
|
|
59
|
+
* It is private for that reason: nothing outside may make it a variable.
|
|
60
|
+
*/
|
|
61
|
+
const FOLD_WIDTH = 72;
|
|
62
|
+
/**
|
|
63
|
+
* The contract's id scheme: `<prefix>-<yyyy-mm-dd>-<slug>`, with an
|
|
64
|
+
* optional trailing ordinal that the slug charset already admits. The
|
|
65
|
+
* scheme belongs to the door, which refuses `invalid_id` on anything else;
|
|
66
|
+
* the *prefix vocabulary* belongs to the consumer, which is why a
|
|
67
|
+
* descriptor supplies the prefix and this pattern supplies the shape.
|
|
68
|
+
*/
|
|
69
|
+
export const RECORD_ID_PATTERN = /^[a-z0-9]+-\d{4}-\d{2}-\d{2}-[a-z0-9][a-z0-9-]*$/;
|
|
70
|
+
/** Mint an id under that scheme. Refuses rather than emitting one the door
|
|
71
|
+
* would reject. */
|
|
72
|
+
export function mintRecordId(input) {
|
|
73
|
+
const errors = [];
|
|
74
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(input.date)) {
|
|
75
|
+
errors.push(`date must be yyyy-mm-dd, got ${JSON.stringify(input.date)}`);
|
|
76
|
+
}
|
|
77
|
+
if (!/^[a-z0-9][a-z0-9-]*$/.test(input.slug)) {
|
|
78
|
+
errors.push(`slug must be lowercase alphanumeric and hyphens, got ${JSON.stringify(input.slug)}`);
|
|
79
|
+
}
|
|
80
|
+
if (input.ordinal !== undefined &&
|
|
81
|
+
(!Number.isInteger(input.ordinal) || input.ordinal < 0 || input.ordinal > 999)) {
|
|
82
|
+
errors.push(`ordinal must be an integer in 0..999, got ${String(input.ordinal)}`);
|
|
83
|
+
}
|
|
84
|
+
const suffix = input.ordinal === undefined ? "" : `-${String(input.ordinal).padStart(3, "0")}`;
|
|
85
|
+
const id = `${input.prefix}-${input.date}-${input.slug}${suffix}`;
|
|
86
|
+
if (errors.length === 0 && !RECORD_ID_PATTERN.test(id)) {
|
|
87
|
+
errors.push(`${JSON.stringify(id)} is not a well-formed record id`);
|
|
88
|
+
}
|
|
89
|
+
if (errors.length > 0) {
|
|
90
|
+
throw recordDoorError("invalid_record", { errors }, `invalid_record: ${errors.join("; ")}`);
|
|
91
|
+
}
|
|
92
|
+
return id;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Build a composer over the consumer's family descriptors.
|
|
96
|
+
*
|
|
97
|
+
* Descriptors are validated once, here, rather than at every filing: a
|
|
98
|
+
* malformed descriptor is a programming error and belongs at module load,
|
|
99
|
+
* not in a user's form submission.
|
|
100
|
+
*/
|
|
101
|
+
export function createRecordBodyComposer(descriptors) {
|
|
102
|
+
if (!Array.isArray(descriptors) || descriptors.length === 0) {
|
|
103
|
+
throw new Error("createRecordBodyComposer requires at least one family descriptor");
|
|
104
|
+
}
|
|
105
|
+
const byFamily = new Map();
|
|
106
|
+
for (const descriptor of descriptors) {
|
|
107
|
+
if (typeof descriptor.family !== "string" || descriptor.family.length === 0) {
|
|
108
|
+
throw new Error("record family descriptor requires a non-empty family name");
|
|
109
|
+
}
|
|
110
|
+
if (byFamily.has(descriptor.family)) {
|
|
111
|
+
throw new Error(`record family '${descriptor.family}' is declared twice`);
|
|
112
|
+
}
|
|
113
|
+
if (!Array.isArray(descriptor.fields) || descriptor.fields.length === 0) {
|
|
114
|
+
throw new Error(`record family '${descriptor.family}' declares no fields`);
|
|
115
|
+
}
|
|
116
|
+
if (descriptor.idPrefix !== undefined && !/^[a-z0-9]+$/.test(descriptor.idPrefix)) {
|
|
117
|
+
throw new Error(`record family '${descriptor.family}': id prefix '${descriptor.idPrefix}' must be lowercase ` +
|
|
118
|
+
"alphanumeric — it is the first segment of every id this family files");
|
|
119
|
+
}
|
|
120
|
+
const seen = new Set();
|
|
121
|
+
for (const field of descriptor.fields) {
|
|
122
|
+
if (!KEY_RE.test(field.key)) {
|
|
123
|
+
throw new Error(`record family '${descriptor.family}': frontmatter key '${field.key}' is outside the ` +
|
|
124
|
+
"dialect's charset (letters, '_' and '-'). Minimal frontmatter readers skip a key they " +
|
|
125
|
+
"do not match, which drops the field silently.");
|
|
126
|
+
}
|
|
127
|
+
if (seen.has(field.key)) {
|
|
128
|
+
throw new Error(`record family '${descriptor.family}': key '${field.key}' is declared twice`);
|
|
129
|
+
}
|
|
130
|
+
seen.add(field.key);
|
|
131
|
+
if (field.constant !== undefined && field.render !== undefined && field.render !== "scalar") {
|
|
132
|
+
throw new Error(`record family '${descriptor.family}': key '${field.key}' declares a constant, which is ` +
|
|
133
|
+
"scalar by construction");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
byFamily.set(descriptor.family, descriptor);
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
families: descriptors.map((d) => d.family),
|
|
140
|
+
compose(family, input) {
|
|
141
|
+
const descriptor = byFamily.get(family);
|
|
142
|
+
if (descriptor === undefined) {
|
|
143
|
+
throw recordDoorError("invalid_record", { errors: [`no descriptor for family '${family}'`] }, `invalid_record: this composer knows the families ${[...byFamily.keys()].join(", ")} — ` +
|
|
144
|
+
`'${family}' is not one of them`);
|
|
145
|
+
}
|
|
146
|
+
return composeOne(descriptor, input ?? {});
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function composeOne(descriptor, input) {
|
|
151
|
+
const errors = [];
|
|
152
|
+
const lines = [];
|
|
153
|
+
const consumed = new Set();
|
|
154
|
+
/** What each field canonically wrote, for the round-trip assertion. */
|
|
155
|
+
const written = {};
|
|
156
|
+
for (const field of descriptor.fields) {
|
|
157
|
+
const from = field.from ?? field.key;
|
|
158
|
+
const supplied = Object.prototype.hasOwnProperty.call(input, from);
|
|
159
|
+
consumed.add(from);
|
|
160
|
+
if (field.constant !== undefined) {
|
|
161
|
+
if (supplied) {
|
|
162
|
+
errors.push(`field '${from}' is a constant on family '${descriptor.family}' and may not be supplied`);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
pushScalar(lines, field.key, field.constant, errors, written);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const value = supplied ? input[from] : undefined;
|
|
169
|
+
if (isAbsent(value)) {
|
|
170
|
+
if (field.required === true)
|
|
171
|
+
errors.push(`missing required field '${from}'`);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
switch (field.render ?? "scalar") {
|
|
175
|
+
case "scalar":
|
|
176
|
+
pushScalar(lines, field.key, value, errors, written);
|
|
177
|
+
break;
|
|
178
|
+
case "list":
|
|
179
|
+
pushList(lines, field.key, value, errors, written);
|
|
180
|
+
break;
|
|
181
|
+
case "folded":
|
|
182
|
+
pushFolded(lines, field.key, value, errors, written);
|
|
183
|
+
break;
|
|
184
|
+
case "map":
|
|
185
|
+
pushMap(lines, field.key, value, errors, written);
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
let prose = "";
|
|
190
|
+
if (descriptor.prose !== undefined) {
|
|
191
|
+
consumed.add(descriptor.prose);
|
|
192
|
+
const raw = input[descriptor.prose];
|
|
193
|
+
if (isAbsent(raw)) {
|
|
194
|
+
if (descriptor.proseRequired === true) {
|
|
195
|
+
errors.push(`missing required prose field '${descriptor.prose}'`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else if (typeof raw !== "string") {
|
|
199
|
+
errors.push(`prose field '${descriptor.prose}' must be a string`);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
// Normalize line endings and trim the edges: the block's separation
|
|
203
|
+
// from the frontmatter is the composer's, so a caller's leading
|
|
204
|
+
// blank lines cannot change the bytes.
|
|
205
|
+
prose = raw.replace(/\r\n?/g, "\n").trim();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
for (const key of Object.keys(input)) {
|
|
209
|
+
if (!consumed.has(key)) {
|
|
210
|
+
errors.push(`unknown input field '${key}' for family '${descriptor.family}' — declare it in the ` +
|
|
211
|
+
"descriptor or drop it; a silently ignored field is a filing that lies");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (errors.length > 0)
|
|
215
|
+
throw composeRefusal(descriptor.family, errors);
|
|
216
|
+
const block = `---\n${lines.join("\n")}\n---\n`;
|
|
217
|
+
const body = prose.length === 0 ? block : `${block}\n${prose}\n`;
|
|
218
|
+
// The canonical-bytes discipline, asserted rather than promised.
|
|
219
|
+
//
|
|
220
|
+
// Every emitter above believes it wrote a value a minimal reader gets
|
|
221
|
+
// back. Here that belief is checked: the composed bytes are read with the
|
|
222
|
+
// dialect's own reader and compared field by field. A field that does not
|
|
223
|
+
// survive its own round trip would reach the door as bytes meaning
|
|
224
|
+
// something other than what the form said — a filing that lies, quietly,
|
|
225
|
+
// in the one place the system treats as immutable truth. Cheap, and it
|
|
226
|
+
// covers every emitter at once including ones added later.
|
|
227
|
+
const readBack = parseRecordFrontmatter(body);
|
|
228
|
+
for (const [key, expected] of Object.entries(written)) {
|
|
229
|
+
if (!sameValue(readBack[key], expected)) {
|
|
230
|
+
errors.push(`field '${key}' did not survive its own round trip — wrote ${JSON.stringify(expected)}, ` +
|
|
231
|
+
`read back ${JSON.stringify(readBack[key])}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// The id, if this family declares a prefix. Checked off the read-back
|
|
235
|
+
// rather than the input so it judges the bytes that will actually be
|
|
236
|
+
// filed.
|
|
237
|
+
if (descriptor.idPrefix !== undefined) {
|
|
238
|
+
const idKey = descriptor.idKey ?? "id";
|
|
239
|
+
const id = readBack[idKey];
|
|
240
|
+
if (typeof id !== "string") {
|
|
241
|
+
errors.push(`family '${descriptor.family}' declares an id prefix but wrote no '${idKey}' field`);
|
|
242
|
+
}
|
|
243
|
+
else if (!RECORD_ID_PATTERN.test(id)) {
|
|
244
|
+
errors.push(`id ${JSON.stringify(id)} is not a well-formed record id`);
|
|
245
|
+
}
|
|
246
|
+
else if (!id.startsWith(`${descriptor.idPrefix}-`)) {
|
|
247
|
+
errors.push(`id ${JSON.stringify(id)} does not carry family '${descriptor.family}'s prefix ` +
|
|
248
|
+
`'${descriptor.idPrefix}-'`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (errors.length > 0)
|
|
252
|
+
throw composeRefusal(descriptor.family, errors);
|
|
253
|
+
return body;
|
|
254
|
+
}
|
|
255
|
+
function composeRefusal(family, errors) {
|
|
256
|
+
return recordDoorError("invalid_record", { errors }, `invalid_record: cannot compose a '${family}' body — ${errors.join("; ")}`);
|
|
257
|
+
}
|
|
258
|
+
/** Structural equality over the three shapes the dialect carries. */
|
|
259
|
+
function sameValue(read, expected) {
|
|
260
|
+
if (Array.isArray(expected)) {
|
|
261
|
+
return (Array.isArray(read) && read.length === expected.length && read.every((v, i) => v === expected[i]));
|
|
262
|
+
}
|
|
263
|
+
if (typeof expected === "object" && expected !== null) {
|
|
264
|
+
if (typeof read !== "object" || read === null || Array.isArray(read))
|
|
265
|
+
return false;
|
|
266
|
+
const left = read;
|
|
267
|
+
const right = expected;
|
|
268
|
+
const keys = Object.keys(right);
|
|
269
|
+
return keys.length === Object.keys(left).length && keys.every((k) => left[k] === right[k]);
|
|
270
|
+
}
|
|
271
|
+
return read === expected;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* This package's frontmatter reader: `key: value`, `key: [a, b]`, `key: >-`
|
|
275
|
+
* folded blocks rejoined with single spaces, and one-level maps of two-space
|
|
276
|
+
* `sub: value` lines whose sub-values may THEMSELVES fold. Keys are letters,
|
|
277
|
+
* `_` and `-`; a line matching nothing is skipped, which is what minimal
|
|
278
|
+
* readers do and why the composer refuses to emit one.
|
|
279
|
+
*
|
|
280
|
+
* ## The reader accepts a superset of what the writer emits
|
|
281
|
+
*
|
|
282
|
+
* The reader is deliberately NOT the writer's mirror, and saying so plainly
|
|
283
|
+
* is the point of this paragraph. The composer's write dialect is the small,
|
|
284
|
+
* refusing one documented at the top of this module — it never emits a folded
|
|
285
|
+
* map sub-value, and it refuses any input it cannot render in its four forms.
|
|
286
|
+
* The reader, though, reads a corpus written by OTHER writers, and the record
|
|
287
|
+
* substrate's own reader accepts more than we emit. Reading less than the
|
|
288
|
+
* substrate does would make a mount unable to read real records the substrate
|
|
289
|
+
* happily serves, so the reader matches the substrate's reader instead:
|
|
290
|
+
*
|
|
291
|
+
* - inside an open map, ` sub: >-` **or** ` sub:` (an empty sub-value)
|
|
292
|
+
* opens a folded sub-value; the following indented lines that are not
|
|
293
|
+
* themselves two-space `sub: value` lines append, rejoined with single
|
|
294
|
+
* spaces. A new two-space `sub: value` line closes the open fold; a
|
|
295
|
+
* non-indented line closes the map;
|
|
296
|
+
* - a TAB-led line counts as indented, exactly as the substrate's reader
|
|
297
|
+
* counts it — treating it as top-level would silently drop a continuation.
|
|
298
|
+
*
|
|
299
|
+
* Note the asymmetry is one-directional and safe in the direction that
|
|
300
|
+
* matters: every byte the composer emits still reads back to what it wrote
|
|
301
|
+
* (the round-trip assertion in `composeOne` is what enforces that), while
|
|
302
|
+
* bytes the composer would refuse to write may still be read.
|
|
303
|
+
*
|
|
304
|
+
* At top level `key:` (empty) opens a MAP, not a fold — the substrate does
|
|
305
|
+
* the same, and the `sub:`-opens-a-fold rule applies only INSIDE a map.
|
|
306
|
+
*
|
|
307
|
+
* It lives beside the writer on purpose. A dialect with its reader and its
|
|
308
|
+
* writer in two modules is a dialect with two definitions, and the drift
|
|
309
|
+
* shows up as bytes nobody can explain.
|
|
310
|
+
*/
|
|
311
|
+
export function parseRecordFrontmatter(text) {
|
|
312
|
+
if (!text.startsWith("---\n")) {
|
|
313
|
+
throw new Error("body unparseable — no leading frontmatter block");
|
|
314
|
+
}
|
|
315
|
+
const end = text.indexOf("\n---", 4);
|
|
316
|
+
if (end === -1)
|
|
317
|
+
throw new Error("frontmatter block unterminated");
|
|
318
|
+
const out = {};
|
|
319
|
+
/** The open top-level folded key, if any. */
|
|
320
|
+
let folding = null;
|
|
321
|
+
/** The open one-level map, if any. */
|
|
322
|
+
let map = null;
|
|
323
|
+
/** The open folded sub-value WITHIN that map, if any. */
|
|
324
|
+
let subFolding = null;
|
|
325
|
+
for (const line of text.slice(4, end).split("\n")) {
|
|
326
|
+
// A tab-led line counts as indented too: the substrate's reader counts
|
|
327
|
+
// it, and reading it as top-level would drop a continuation silently.
|
|
328
|
+
if (line.startsWith(" ") || line.startsWith("\t")) {
|
|
329
|
+
if (map !== null) {
|
|
330
|
+
const sub = /^ {2}([A-Za-z_-]+):\s*(.*)$/.exec(line);
|
|
331
|
+
if (sub !== null && !line.startsWith(" ")) {
|
|
332
|
+
const subValue = sub[2].trim();
|
|
333
|
+
if (subValue === ">-" || subValue === "") {
|
|
334
|
+
// ` sub: >-` and a bare ` sub:` both open a folded sub-value.
|
|
335
|
+
// (A bare `sub:` opens a fold, not a nested map — maps are one
|
|
336
|
+
// level only, and this is the substrate's rule.)
|
|
337
|
+
map[sub[1]] = "";
|
|
338
|
+
subFolding = sub[1];
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
// A sub-value closes any fold the previous sub-key opened.
|
|
342
|
+
map[sub[1]] = subValue;
|
|
343
|
+
subFolding = null;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
else if (subFolding !== null) {
|
|
347
|
+
// Deeper indent, a tab, or anything else failing the sub-key
|
|
348
|
+
// form: a continuation of the open folded sub-value.
|
|
349
|
+
map[subFolding] = `${map[subFolding]} ${line.trim()}`.trim();
|
|
350
|
+
}
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
if (folding !== null)
|
|
354
|
+
out[folding] = `${out[folding]} ${line.trim()}`.trim();
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
map = null;
|
|
358
|
+
subFolding = null;
|
|
359
|
+
const matched = /^([A-Za-z_-]+):\s*(.*)$/.exec(line);
|
|
360
|
+
// A non-indented line that is not a `key:` line (a blank, a stray
|
|
361
|
+
// heading) does NOT close an open top-level fold — the substrate's
|
|
362
|
+
// reader keeps folding across it, so this one must too. Only a real
|
|
363
|
+
// key line closes the fold.
|
|
364
|
+
if (matched === null)
|
|
365
|
+
continue;
|
|
366
|
+
folding = null;
|
|
367
|
+
const key = matched[1];
|
|
368
|
+
const value = matched[2].trim();
|
|
369
|
+
if (value === ">-") {
|
|
370
|
+
out[key] = "";
|
|
371
|
+
folding = key;
|
|
372
|
+
}
|
|
373
|
+
else if (value === "") {
|
|
374
|
+
map = {};
|
|
375
|
+
out[key] = map;
|
|
376
|
+
}
|
|
377
|
+
else if (value.startsWith("[") && value.endsWith("]")) {
|
|
378
|
+
out[key] = value
|
|
379
|
+
.slice(1, -1)
|
|
380
|
+
.split(",")
|
|
381
|
+
.map((one) => one.trim())
|
|
382
|
+
.filter((one) => one.length > 0);
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
out[key] = value;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return out;
|
|
389
|
+
}
|
|
390
|
+
/** The prose beneath a composed body's frontmatter block. */
|
|
391
|
+
export function recordProseOf(text) {
|
|
392
|
+
if (!text.startsWith("---\n"))
|
|
393
|
+
return text;
|
|
394
|
+
const end = text.indexOf("\n---", 4);
|
|
395
|
+
return end === -1 ? "" : text.slice(end + 4).replace(/^\n+/, "");
|
|
396
|
+
}
|
|
397
|
+
function isAbsent(value) {
|
|
398
|
+
return value === undefined || value === null || value === "";
|
|
399
|
+
}
|
|
400
|
+
/** The scalar forms a minimal reader gets right, and nothing else. */
|
|
401
|
+
function scalarText(key, value, errors) {
|
|
402
|
+
if (typeof value === "number") {
|
|
403
|
+
if (!Number.isFinite(value)) {
|
|
404
|
+
errors.push(`field '${key}': ${String(value)} is not a finite number`);
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
return String(value);
|
|
408
|
+
}
|
|
409
|
+
if (typeof value === "boolean")
|
|
410
|
+
return value ? "true" : "false";
|
|
411
|
+
if (typeof value !== "string") {
|
|
412
|
+
errors.push(`field '${key}': a scalar takes a string, number or boolean, got ${typeof value}`);
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
const text = value.trim();
|
|
416
|
+
if (text.length === 0) {
|
|
417
|
+
errors.push(`field '${key}': an empty scalar reads as the start of a map, not as a value`);
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
if (/[\r\n]/.test(text)) {
|
|
421
|
+
errors.push(`field '${key}': a scalar cannot carry a line break — declare the field as 'folded'`);
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
424
|
+
if (text === ">-") {
|
|
425
|
+
errors.push(`field '${key}': the literal '>-' reads as a folded-block marker, not as a value`);
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
if (text.startsWith("[") && text.endsWith("]")) {
|
|
429
|
+
errors.push(`field '${key}': a bracketed scalar reads as a list — declare the field as 'list'`);
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
return text;
|
|
433
|
+
}
|
|
434
|
+
function pushScalar(lines, key, value, errors, written) {
|
|
435
|
+
const text = scalarText(key, value, errors);
|
|
436
|
+
if (text !== null) {
|
|
437
|
+
lines.push(`${key}: ${text}`);
|
|
438
|
+
written[key] = text;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function pushList(lines, key, value, errors, written) {
|
|
442
|
+
if (!Array.isArray(value)) {
|
|
443
|
+
errors.push(`field '${key}': a list field takes an array, got ${typeof value}`);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const items = [];
|
|
447
|
+
const before = errors.length;
|
|
448
|
+
for (const raw of value) {
|
|
449
|
+
if (typeof raw !== "string") {
|
|
450
|
+
errors.push(`field '${key}': list items must be strings, got ${typeof raw}`);
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
const item = raw.trim();
|
|
454
|
+
if (item.length === 0) {
|
|
455
|
+
errors.push(`field '${key}': an empty list item is dropped on read, not carried`);
|
|
456
|
+
continue;
|
|
457
|
+
}
|
|
458
|
+
if (/[,[\]\r\n]/.test(item)) {
|
|
459
|
+
errors.push(`field '${key}': list item ${JSON.stringify(raw)} carries a comma, a bracket or a line ` +
|
|
460
|
+
"break, which the inline-list form cannot survive");
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
items.push(item);
|
|
464
|
+
}
|
|
465
|
+
if (errors.length === before) {
|
|
466
|
+
lines.push(`${key}: [${items.join(", ")}]`);
|
|
467
|
+
written[key] = items;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
function pushFolded(lines, key, value, errors, written) {
|
|
471
|
+
if (typeof value !== "string") {
|
|
472
|
+
errors.push(`field '${key}': a folded field takes a string, got ${typeof value}`);
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
// A folded block is rejoined with single spaces on read, so the value a
|
|
476
|
+
// reader sees is the whitespace-collapsed one. Collapsing here rather
|
|
477
|
+
// than pretending otherwise is what makes compose→parse round-trip.
|
|
478
|
+
const collapsed = value.replace(/\s+/g, " ").trim();
|
|
479
|
+
if (collapsed.length === 0) {
|
|
480
|
+
errors.push(`field '${key}': a folded block with no content reads as an empty value`);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
lines.push(`${key}: >-`);
|
|
484
|
+
for (const line of wrap(collapsed, FOLD_WIDTH))
|
|
485
|
+
lines.push(` ${line}`);
|
|
486
|
+
written[key] = collapsed;
|
|
487
|
+
}
|
|
488
|
+
function pushMap(lines, key, value, errors, written) {
|
|
489
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
490
|
+
errors.push(`field '${key}': a map field takes an object, got ${Array.isArray(value) ? "array" : typeof value}`);
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
const entries = Object.entries(value);
|
|
494
|
+
if (entries.length === 0) {
|
|
495
|
+
errors.push(`field '${key}': an empty map is indistinguishable from an empty value on read`);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const rendered = [];
|
|
499
|
+
const canonical = {};
|
|
500
|
+
// Sorted, so the same logical map composes to the same bytes whatever
|
|
501
|
+
// order the form built it in.
|
|
502
|
+
for (const [subKey, subValue] of entries.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))) {
|
|
503
|
+
if (!KEY_RE.test(subKey)) {
|
|
504
|
+
errors.push(`field '${key}': sub-key '${subKey}' is outside the dialect's charset (letters, '_' and '-')`);
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
const text = scalarText(`${key}.${subKey}`, subValue, errors);
|
|
508
|
+
if (text !== null) {
|
|
509
|
+
rendered.push(` ${subKey}: ${text}`);
|
|
510
|
+
canonical[subKey] = text;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
if (rendered.length > 0) {
|
|
514
|
+
lines.push(`${key}:`);
|
|
515
|
+
lines.push(...rendered);
|
|
516
|
+
written[key] = canonical;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
/** Greedy word wrap. Purely cosmetic — a folded block reads the same at
|
|
520
|
+
* any width — so an over-long word rides alone rather than being cut. */
|
|
521
|
+
function wrap(text, width) {
|
|
522
|
+
const out = [];
|
|
523
|
+
let line = "";
|
|
524
|
+
for (const word of text.split(" ")) {
|
|
525
|
+
if (line.length === 0)
|
|
526
|
+
line = word;
|
|
527
|
+
else if (line.length + 1 + word.length <= width)
|
|
528
|
+
line = `${line} ${word}`;
|
|
529
|
+
else {
|
|
530
|
+
out.push(line);
|
|
531
|
+
line = word;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
if (line.length > 0)
|
|
535
|
+
out.push(line);
|
|
536
|
+
return out;
|
|
537
|
+
}
|
|
538
|
+
//# sourceMappingURL=body.js.map
|
package/dist/body.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body.js","sourceRoot":"","sources":["../src/body.ts"],"names":[],"mappings":"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"}
|