@raybase/record-mount 0.0.2 → 0.3.4

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/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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body.js","sourceRoot":"","sources":["../src/body.ts"],"names":[],"mappings":"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"}