rapier-markdown-kit 1.1.102 → 1.1.104

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.
Files changed (60) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +213 -53
  3. package/dist/agent/vendor/hyphen-en-us/LICENSE +14 -0
  4. package/dist/agent/vendor/hyphen-en-us/SOURCE.json +33 -0
  5. package/dist/agent/vendor/hyphen-en-us/hyph-en-us.hyp.txt +14 -0
  6. package/dist/agent/vendor/hyphen-en-us/hyph-en-us.pat.txt +4938 -0
  7. package/dist/agent/vendor/hyphen-en-us/patterns.js +25 -0
  8. package/dist/agent/vendor/pretext/LICENSE +208 -0
  9. package/dist/agent/vendor/pretext/NOTICE +26 -13
  10. package/dist/agent/vendor/pretext/SOURCE.json +213 -45
  11. package/dist/agent/vendor/pretext/analysis.js +675 -1224
  12. package/dist/agent/vendor/pretext/entry-geometry.js +183 -0
  13. package/dist/agent/vendor/pretext/gecko-line-breaks.js +688 -0
  14. package/dist/agent/vendor/pretext/generated/engine-break-data.js +57 -0
  15. package/dist/agent/vendor/pretext/generated/webkit-generic-families.js +80 -0
  16. package/dist/agent/vendor/pretext/graphemes.js +98 -0
  17. package/dist/agent/vendor/pretext/han-kerning.js +253 -0
  18. package/dist/agent/vendor/pretext/layout.js +352 -290
  19. package/dist/agent/vendor/pretext/line-break.js +1154 -588
  20. package/dist/agent/vendor/pretext/line-breaks.js +892 -0
  21. package/dist/agent/vendor/pretext/line-text.js +81 -39
  22. package/dist/agent/vendor/pretext/measurement.js +1105 -176
  23. package/dist/agent/vendor/pretext/prepare.js +807 -0
  24. package/dist/agent/vendor/pretext/rich-inline.js +1242 -273
  25. package/dist/agent/will.mjs +2 -0
  26. package/dist/kit/assets.mjs +5 -1
  27. package/dist/kit/conformance/run.mjs +4 -4
  28. package/dist/kit/export-fonts.mjs +26 -11
  29. package/dist/kit/index.mjs +1 -0
  30. package/dist/kit/ledger/carried.mjs +9 -7
  31. package/dist/kit/ledger/data.mjs +73 -13
  32. package/dist/kit/ledger/format.mjs +166 -53
  33. package/dist/kit/ledger/hash.mjs +75 -18
  34. package/dist/kit/ledger/history.mjs +143 -115
  35. package/dist/kit/ledger/inverse-source.mjs +158 -19
  36. package/dist/kit/ledger/journal-records.mjs +292 -67
  37. package/dist/kit/model.mjs +1 -1
  38. package/dist/kit/pdf-glyphs.mjs +4 -4
  39. package/dist/kit/render-markdown.mjs +259 -122
  40. package/dist/kit/render-sanitize.mjs +24 -4
  41. package/dist/kit/render-work.mjs +99 -20
  42. package/dist/kit/render.mjs +101 -65
  43. package/dist/kit/typography.mjs +2 -0
  44. package/dist/layout/hyphenation.mjs +127 -0
  45. package/dist/layout/line-plan.mjs +88 -96
  46. package/dist/layout/model.mjs +61 -80
  47. package/dist/layout/paragraph-fit.mjs +191 -0
  48. package/dist/layout/preparation.mjs +373 -0
  49. package/dist/layout/prepared-paragraph.mjs +223 -0
  50. package/dist/layout/typography.mjs +345 -111
  51. package/dist/packages/rapier-diff/index.mjs +288 -196
  52. package/dist/spec/document-fonts.mjs +13 -4
  53. package/dist/spec/md-assets.mjs +149 -30
  54. package/dist/spec/md-layout.mjs +5 -2
  55. package/dist/spec/md-marks.mjs +218 -3
  56. package/dist/spec/md-source.mjs +122 -0
  57. package/package.json +2 -1
  58. package/style.css +9 -0
  59. package/dist/agent/vendor/pretext/bidi.js +0 -151
  60. package/dist/agent/vendor/pretext/generated/bidi-data.js +0 -3831
@@ -9,6 +9,137 @@ const historyBoundary = (source, at) => Number.isSafeInteger(at) && at >= 0 && !
9
9
  !(at > 0 && at < source.length && (source.charCodeAt(at - 1) & 0xFC00) === 0xD800 &&
10
10
  (source.charCodeAt(at) & 0xFC00) === 0xDC00);
11
11
 
12
+ // Persistent AVL pieces retain original strings and coordinates. A revision costs
13
+ // only the edited paths; reading a range visits its leaves, never earlier bodies.
14
+ const sourceLeaf = (text, from = 0, to = text.length) => to > from
15
+ ? {text, from, length: to - from, height: 1} : null;
16
+ const sourceHeight = node => node?.height || 0;
17
+ const sourceNode = (left, right) => !left ? right : !right ? left
18
+ : {left, right, length: left.length + right.length, height: 1 + Math.max(left.height, right.height)};
19
+ function sourceBalance(left, right) {
20
+ if (sourceHeight(left) > sourceHeight(right) + 1) {
21
+ if (sourceHeight(left.left) >= sourceHeight(left.right)) return sourceNode(left.left, sourceNode(left.right, right));
22
+ return sourceNode(sourceNode(left.left, left.right.left), sourceNode(left.right.right, right));
23
+ }
24
+ if (sourceHeight(right) > sourceHeight(left) + 1) {
25
+ if (sourceHeight(right.right) >= sourceHeight(right.left)) return sourceNode(sourceNode(left, right.left), right.right);
26
+ return sourceNode(sourceNode(left, right.left.left), sourceNode(right.left.right, right.right));
27
+ }
28
+ return sourceNode(left, right);
29
+ }
30
+ function sourceJoin(left, right) {
31
+ if (!left || !right) return left || right;
32
+ if (left.height > right.height + 1) return sourceBalance(left.left, sourceJoin(left.right, right));
33
+ if (right.height > left.height + 1) return sourceBalance(sourceJoin(left, right.left), right.right);
34
+ return sourceNode(left, right);
35
+ }
36
+ function sourceSplit(node, at) {
37
+ if (!node || at === 0) return [null, node];
38
+ if (at === node.length) return [node, null];
39
+ if (node.text !== undefined) return [sourceLeaf(node.text, node.from, node.from + at), sourceLeaf(node.text, node.from + at, node.from + node.length)];
40
+ if (at < node.left.length) {
41
+ const [left, right] = sourceSplit(node.left, at);
42
+ return [left, sourceJoin(right, node.right)];
43
+ }
44
+ const [left, right] = sourceSplit(node.right, at - node.left.length);
45
+ return [sourceJoin(node.left, left), right];
46
+ }
47
+ function* sourceParts(node, from, to) {
48
+ if (!node || from >= to) return;
49
+ if (node.text !== undefined) {
50
+ yield node.from + from === 0 && node.from + to === node.text.length ? node.text : node.text.slice(node.from + from, node.from + to); return;
51
+ }
52
+ if (from < node.left.length) yield* sourceParts(node.left, from, Math.min(to, node.left.length));
53
+ if (to > node.left.length) yield* sourceParts(node.right, Math.max(0, from - node.left.length), to - node.left.length);
54
+ }
55
+ function* sourceLeaves(node) {
56
+ if (!node) return;
57
+ if (node.text !== undefined) { yield node; return; }
58
+ yield* sourceLeaves(node.left); yield* sourceLeaves(node.right);
59
+ }
60
+ export class HistorySource {
61
+ #root;
62
+ constructor(text, root = sourceLeaf(text)) { this.#root = root; }
63
+ static fromParts(parts) {
64
+ const leaves = Array.from(parts, text => sourceLeaf(text)).filter(Boolean);
65
+ const build = (from, to) => from === to ? null : to - from === 1 ? leaves[from]
66
+ : sourceNode(build(from, Math.floor((from + to) / 2)), build(Math.floor((from + to) / 2), to));
67
+ return new HistorySource('', build(0, leaves.length));
68
+ }
69
+ get length() { return this.#root?.length || 0; }
70
+ charCodeAt(at) {
71
+ if (at < 0 || at >= this.length) return NaN;
72
+ let node = this.#root;
73
+ while (node.text === undefined) {
74
+ if (at < node.left.length) node = node.left;
75
+ else { at -= node.left.length; node = node.right; }
76
+ }
77
+ return node.text.charCodeAt(node.from + at);
78
+ }
79
+ parts(from = 0, to = this.length) { return sourceParts(this.#root, from, to); }
80
+ slice(from = 0, to = this.length) {
81
+ const root = this.#root;
82
+ if (!root || from >= to) return '';
83
+ if (root.text !== undefined) return root.from + from === 0 && root.from + to === root.text.length
84
+ ? root.text : root.text.slice(root.from + from, root.from + to);
85
+ return Array.from(this.parts(from, to)).join('');
86
+ }
87
+ matches(from, text) {
88
+ if (from < 0 || from + text.length > this.length) return false;
89
+ let at = 0;
90
+ for (const part of this.parts(from, from + text.length)) {
91
+ if (!text.startsWith(part, at)) return false;
92
+ at += part.length;
93
+ }
94
+ return at === text.length;
95
+ }
96
+ sameParts(parts) {
97
+ const leaves = sourceLeaves(this.#root);
98
+ let leaf = leaves.next().value, offset = 0;
99
+ for (const text of parts) for (let at = 0; at < text.length;) {
100
+ if (!leaf) return false;
101
+ const length = Math.min(leaf.length - offset, text.length - at), from = leaf.from + offset;
102
+ // Untouched runs share their string and coordinates. Only changed fragments
103
+ // require a text comparison; no full-body join is needed to prove the plan.
104
+ if ((leaf.text !== text || from !== at) && leaf.text.slice(from, from + length) !== text.slice(at, at + length)) return false;
105
+ offset += length; at += length;
106
+ if (offset === leaf.length) { leaf = leaves.next().value; offset = 0; }
107
+ }
108
+ return !leaf;
109
+ }
110
+ replace(pos, length, text) {
111
+ const [left, rest] = sourceSplit(this.#root, pos), [, right] = sourceSplit(rest, length);
112
+ return new HistorySource('', sourceJoin(sourceJoin(left, sourceLeaf(text)), right));
113
+ }
114
+ // Undoing an admitted repair is observation: its after-state can join a scalar
115
+ // across the deleted run. Prove the forward boundaries on the reconstructed view.
116
+ before(splices) {
117
+ let source = this;
118
+ for (let index = splices.length - 1; index >= 0; index--) {
119
+ const row = splices[index];
120
+ if (!row || !Number.isSafeInteger(row.pos) || row.pos < 0 || Object.is(row.pos, -0) ||
121
+ typeof row.removed !== 'string' || typeof row.inserted !== 'string' ||
122
+ /[\uD800-\uDFFF]/u.test(row.removed) || /[\uD800-\uDFFF]/u.test(row.inserted) || !source.matches(row.pos, row.inserted)) return null;
123
+ source = source.replace(row.pos, row.inserted.length, row.removed);
124
+ if (!historyBoundary(source, row.pos) || !historyBoundary(source, row.pos + row.removed.length)) return null;
125
+ }
126
+ return source;
127
+ }
128
+ apply(splices, inverse = false) {
129
+ if (!Array.isArray(splices)) return null;
130
+ let source = this;
131
+ for (let index = 0; index < splices.length; index++) {
132
+ const row = splices[inverse ? splices.length - 1 - index : index];
133
+ const removed = inverse ? row?.inserted : row?.removed, inserted = inverse ? row?.removed : row?.inserted;
134
+ if (typeof removed !== 'string' || typeof inserted !== 'string' ||
135
+ /[\uD800-\uDFFF]/u.test(removed) || /[\uD800-\uDFFF]/u.test(inserted) ||
136
+ !historyBoundary(source, row.pos) || !historyBoundary(source, row.pos + removed.length) || !source.matches(row.pos, removed)) return null;
137
+ source = source.replace(row.pos, removed.length, inserted);
138
+ }
139
+ return source;
140
+ }
141
+ }
142
+
12
143
  function minimalHistorySplice(before, after, pos = 0) {
13
144
  let first = 0, a = before.length, b = after.length;
14
145
  while (first < a && first < b && before[first] === after[first]) first++;
@@ -36,14 +167,18 @@ function historyHunks(row) {
36
167
  // Rows are already proved source placements, optionally carrying sourceIndices from
37
168
  // causal projection. Multiple inverse blockers can change history with no source edit.
38
169
  export function projectInverseSource(prepared, selected, projectedEffects, options = {}) {
39
- const records = prepared.rows.map(({record, splices}) => ({...record, splices}));
170
+ const records = prepared.records || prepared.rows.map(({record, splices}) => record.splices === splices ? record : {...record, splices});
40
171
  if (!records.some(record => !prepared.effects.references.get(record.transaction.id)?.length &&
41
172
  prepared.effects.active.has(record.transaction.id) !== projectedEffects.active.has(record.transaction.id)))
42
173
  return {ok: true, splices: [], after: prepared.source, superseded: [], overlaps: []};
43
174
  try {
44
175
  let pieces = prepared.initialSource ? [{text: prepared.initialSource, owner: null, lineage: []}] : [];
45
176
  const all = [], byId = new Map(), byAct = new Map(), processed = [], keptInverseAncestors = new Set();
46
- const textOf = rows => rows.map(row => row.text || '').join('');
177
+ const texts = rows => rows.map(row => row.text || '');
178
+ const textOf = rows => texts(rows).join('');
179
+ const lengthOf = (rows, to = rows.length) => { let size = 0; for (let i = 0; i < to; i++) size += rows[i].text?.length || 0; return size; };
180
+ const sourceOf = rows => HistorySource.fromParts(texts(rows));
181
+ const replays = (before, after, splices) => sourceOf(before).apply(splices)?.sameParts(texts(after)) === true;
47
182
  const boundary = pos => {
48
183
  let offset = 0;
49
184
  for (let index = 0; index < pieces.length; index++) {
@@ -68,20 +203,24 @@ export function projectInverseSource(prepared, selected, projectedEffects, optio
68
203
  };
69
204
  const owns = (piece, hunk) => piece === hunk.marker || piece.owner === hunk.id ||
70
205
  piece.restoredBy?.includes(hunk.id) || hunk.restoredMarkers?.has(piece);
71
- const effectiveBefore = (hunk, effects, visiting = new Set()) => {
72
- if (visiting.has(hunk.id)) return null;
73
- visiting.add(hunk.id); let text = '';
74
- for (const piece of hunk.before) {
206
+ const effectiveBefore = (hunk, effects) => {
207
+ const active = new Set([hunk.id]), pending = [{hunk, at: 0, parts: []}];
208
+ while (pending.length) {
209
+ const frame = pending[pending.length - 1];
210
+ if (frame.at === frame.hunk.before.length) {
211
+ const text = frame.parts.join(''); pending.pop(); active.delete(frame.hunk.id);
212
+ if (!pending.length) return text;
213
+ pending[pending.length - 1].parts.push(text); continue;
214
+ }
215
+ const piece = frame.hunk.before[frame.at++];
75
216
  if (!piece.text) continue;
76
217
  const owner = byId.get(piece.owner);
77
218
  if (owner && !effects.active.has(owner.actId) && !owner.kept) {
78
- if (piece.text !== owner.inserted) return null;
79
- const prior = effectiveBefore(owner, effects, new Set(visiting));
80
- if (prior === null) return null;
81
- text += prior;
82
- } else text += piece.text;
219
+ if (piece.text !== owner.inserted || active.has(owner.id)) return null;
220
+ active.add(owner.id); pending.push({hunk: owner, at: 0, parts: []});
221
+ } else frame.parts.push(piece.text);
83
222
  }
84
- return text;
223
+ return null;
85
224
  };
86
225
  const restoreHunk = hunk => {
87
226
  if (!pieces.includes(hunk.marker)) throw Error('reactivation');
@@ -111,9 +250,9 @@ export function projectInverseSource(prepared, selected, projectedEffects, optio
111
250
  hunk.active = true; delete hunk.undoneBy;
112
251
  continue;
113
252
  }
114
- const pos = textOf(pieces.slice(0, marker)).length, current = textOf(pieces);
253
+ const pos = lengthOf(pieces, marker);
115
254
  const removed = effectiveBefore(hunk, effects);
116
- if (removed === null || current.slice(pos, pos + removed.length) !== removed) throw Error('reactivation');
255
+ if (removed === null || !sourceOf(pieces).matches(pos, removed)) throw Error('reactivation');
117
256
  boundary(pos + removed.length);
118
257
  const start = boundary(pos), end = boundary(pos + removed.length);
119
258
  const at = start.last, count = Math.max(0, end.first - at);
@@ -160,7 +299,7 @@ export function projectInverseSource(prepared, selected, projectedEffects, optio
160
299
  if (first < 0) { restored = null; break; }
161
300
  let last = first;
162
301
  for (let at = first; at < restored.length; at++) if (owns(restored[at], target)) last = at;
163
- const pos = textOf(restored.slice(0, first)).length;
302
+ const pos = lengthOf(restored, first);
164
303
  const before = restored.slice(first, last + 1), replacement = [];
165
304
  for (const piece of before) {
166
305
  if (piece === target.marker) replacement.push(...target.before);
@@ -189,7 +328,7 @@ export function projectInverseSource(prepared, selected, projectedEffects, optio
189
328
  restored.splice(first, last + 1 - first, hunk.marker, ...insertion);
190
329
  inverses.push(hunk); priorSplices?.push({pos, removed: hunk.removed, inserted: hunk.inserted});
191
330
  }
192
- if (restored && textOf(restored) === _rapierTransformSplices(textOf(pieces), splices)) {
331
+ if (restored && replays(pieces, restored, splices)) {
193
332
  pieces = restored;
194
333
  for (const target of targets) { target.active = false; target.undoneBy = tx.id; }
195
334
  for (const piece of pieces) if (piece.mark) {
@@ -209,7 +348,7 @@ export function projectInverseSource(prepared, selected, projectedEffects, optio
209
348
  const before = pieces, priorStates = all.map(hunk => [hunk, hunk.active, hunk.undoneBy]); pieces = pieces.slice();
210
349
  try {
211
350
  reactivate(activated, current);
212
- if (textOf(pieces) === _rapierTransformSplices(textOf(before), splices)) continue;
351
+ if (replays(before, pieces, splices)) continue;
213
352
  } catch (_) {}
214
353
  pieces = before;
215
354
  for (const [hunk, active, undoneBy] of priorStates) { hunk.active = active; hunk.undoneBy = undoneBy; }
@@ -270,7 +409,7 @@ export function projectInverseSource(prepared, selected, projectedEffects, optio
270
409
  }
271
410
  }
272
411
  }
273
- if (textOf(pieces) !== prepared.source) throw Error('head');
412
+ if (!new HistorySource(prepared.source).sameParts(texts(pieces))) throw Error('head');
274
413
  const origins = new Map();
275
414
  let offset = 0;
276
415
  for (const piece of pieces) if (piece.text) { origins.set(piece, offset); offset += piece.text.length; }
@@ -310,7 +449,7 @@ export function projectInverseSource(prepared, selected, projectedEffects, optio
310
449
  const removed = prepared.source.slice(cursor);
311
450
  if (removed !== inserted) changes.push(minimalHistorySplice(removed, inserted, cursor));
312
451
  const splices = changes.length <= 64 ? changes.reverse() : [minimalHistorySplice(prepared.source, after)];
313
- if (_rapierTransformSplices(prepared.source, splices) !== after) throw Error('plan');
452
+ if (!new HistorySource(prepared.source).apply(splices)?.sameParts([after])) throw Error('plan');
314
453
  return {ok: true, splices, after, superseded, overlaps: superseded.filter(row => row.reason === 'later_edit')};
315
454
  } catch (_) { return historyFailure('history_invalid'); }
316
455
  }