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.
- package/LICENSE +2 -2
- package/README.md +213 -53
- package/dist/agent/vendor/hyphen-en-us/LICENSE +14 -0
- package/dist/agent/vendor/hyphen-en-us/SOURCE.json +33 -0
- package/dist/agent/vendor/hyphen-en-us/hyph-en-us.hyp.txt +14 -0
- package/dist/agent/vendor/hyphen-en-us/hyph-en-us.pat.txt +4938 -0
- package/dist/agent/vendor/hyphen-en-us/patterns.js +25 -0
- package/dist/agent/vendor/pretext/LICENSE +208 -0
- package/dist/agent/vendor/pretext/NOTICE +26 -13
- package/dist/agent/vendor/pretext/SOURCE.json +213 -45
- package/dist/agent/vendor/pretext/analysis.js +675 -1224
- package/dist/agent/vendor/pretext/entry-geometry.js +183 -0
- package/dist/agent/vendor/pretext/gecko-line-breaks.js +688 -0
- package/dist/agent/vendor/pretext/generated/engine-break-data.js +57 -0
- package/dist/agent/vendor/pretext/generated/webkit-generic-families.js +80 -0
- package/dist/agent/vendor/pretext/graphemes.js +98 -0
- package/dist/agent/vendor/pretext/han-kerning.js +253 -0
- package/dist/agent/vendor/pretext/layout.js +352 -290
- package/dist/agent/vendor/pretext/line-break.js +1154 -588
- package/dist/agent/vendor/pretext/line-breaks.js +892 -0
- package/dist/agent/vendor/pretext/line-text.js +81 -39
- package/dist/agent/vendor/pretext/measurement.js +1105 -176
- package/dist/agent/vendor/pretext/prepare.js +807 -0
- package/dist/agent/vendor/pretext/rich-inline.js +1242 -273
- package/dist/agent/will.mjs +2 -0
- package/dist/kit/assets.mjs +5 -1
- package/dist/kit/conformance/run.mjs +4 -4
- package/dist/kit/export-fonts.mjs +26 -11
- package/dist/kit/index.mjs +1 -0
- package/dist/kit/ledger/carried.mjs +9 -7
- package/dist/kit/ledger/data.mjs +73 -13
- package/dist/kit/ledger/format.mjs +166 -53
- package/dist/kit/ledger/hash.mjs +75 -18
- package/dist/kit/ledger/history.mjs +143 -115
- package/dist/kit/ledger/inverse-source.mjs +158 -19
- package/dist/kit/ledger/journal-records.mjs +292 -67
- package/dist/kit/model.mjs +1 -1
- package/dist/kit/pdf-glyphs.mjs +4 -4
- package/dist/kit/render-markdown.mjs +259 -122
- package/dist/kit/render-sanitize.mjs +24 -4
- package/dist/kit/render-work.mjs +99 -20
- package/dist/kit/render.mjs +101 -65
- package/dist/kit/typography.mjs +2 -0
- package/dist/layout/hyphenation.mjs +127 -0
- package/dist/layout/line-plan.mjs +88 -96
- package/dist/layout/model.mjs +61 -80
- package/dist/layout/paragraph-fit.mjs +191 -0
- package/dist/layout/preparation.mjs +373 -0
- package/dist/layout/prepared-paragraph.mjs +223 -0
- package/dist/layout/typography.mjs +345 -111
- package/dist/packages/rapier-diff/index.mjs +288 -196
- package/dist/spec/document-fonts.mjs +13 -4
- package/dist/spec/md-assets.mjs +149 -30
- package/dist/spec/md-layout.mjs +5 -2
- package/dist/spec/md-marks.mjs +218 -3
- package/dist/spec/md-source.mjs +122 -0
- package/package.json +2 -1
- package/style.css +9 -0
- package/dist/agent/vendor/pretext/bidi.js +0 -151
- 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}) =>
|
|
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
|
|
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
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
80
|
-
|
|
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
|
|
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 =
|
|
253
|
+
const pos = lengthOf(pieces, marker);
|
|
115
254
|
const removed = effectiveBefore(hunk, effects);
|
|
116
|
-
if (removed === null ||
|
|
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 =
|
|
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 &&
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
}
|