rapier-html 1.2.33 → 1.2.42

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.
@@ -10,7 +10,7 @@ const historyBoundary = (source, at) => Number.isSafeInteger(at) && at >= 0 && !
10
10
  !(at > 0 && at < source.length && (source.charCodeAt(at - 1) & 0xFC00) === 0xD800 &&
11
11
  (source.charCodeAt(at) & 0xFC00) === 0xDC00);
12
12
 
13
- function minimalHistorySplice(before, after, pos = 0) {
13
+ export function minimalHistorySplice(before, after, pos = 0) {
14
14
  let first = 0, a = before.length, b = after.length;
15
15
  while (first < a && first < b && before[first] === after[first]) first++;
16
16
  if (!historyBoundary(before, first) || !historyBoundary(after, first)) first--;
@@ -32,6 +32,8 @@ function historyHunks(row) {
32
32
  }
33
33
 
34
34
 
35
+ const differentActors = (a, b) => !!a && !!b && (a.kind !== b.kind || a.id !== b.id);
36
+
35
37
  export function projectInverseSource(prepared, selected, projectedEffects, options = {}) {
36
38
  const records = prepared.records || prepared.rows.map(({record, splices}) => record.splices === splices ? record : {...record, splices});
37
39
  if (!options.origins && !records.some(record => !prepared.effects.references.get(record.transaction.id)?.length &&
@@ -40,6 +42,7 @@ export function projectInverseSource(prepared, selected, projectedEffects, optio
40
42
  try {
41
43
  let pieces = prepared.initialSource ? [{text: prepared.initialSource, owner: null, lineage: []}] : [];
42
44
  const all = [], byId = new Map(), byAct = new Map(), processed = [], keptInverseAncestors = new Set();
45
+ const actorOf = new Map(records.map(record => [record.transaction.id, record.transaction.actor]));
43
46
  const recordsForCover = prepared.records || prepared.rows.map(({record, splices}) => record.splices === splices ? record : {...record, splices});
44
47
  const coverGroups = new Map();
45
48
  let coverOrigins = null;
@@ -262,7 +265,11 @@ export function projectInverseSource(prepared, selected, projectedEffects, optio
262
265
  const start = boundary(row.pos), end = boundary(row.pos + row.removed.length);
263
266
  let at = start.last, count = Math.max(0, end.first - at);
264
267
  if (!row.removed.length) {
265
- const marker = pieces.slice(start.first, start.last).findIndex(item => item.mark?.inserted.length);
268
+ const run = pieces.slice(start.first, start.last), next = pieces[start.last];
269
+ let before = start.first - 1; while (before >= 0 && !pieces[before].text) before--;
270
+ const leftAct = before >= 0 ? byId.get(pieces[before].owner)?.actId : undefined;
271
+ const sameAct = leftAct !== undefined && run.some(item => item.mark?.actId === leftAct);
272
+ const marker = run.findIndex(item => item.mark?.inserted.length && (next && owns(next, item.mark) || !sameAct));
266
273
  at = marker < 0 ? start.last : start.first + marker; count = 0;
267
274
  }
268
275
  const removed = pieces.slice(at, at + count);
@@ -276,6 +283,12 @@ export function projectInverseSource(prepared, selected, projectedEffects, optio
276
283
  const id = tx.id + '#' + rowIndex + ':' + index;
277
284
  const lineage = new Set([id]);
278
285
  for (const piece of removed) for (const parent of piece.lineage || piece.mark?.lineage || []) lineage.add(parent);
286
+ if (!row.removed.length && !count && at > 0 && /[\p{L}\p{N}\p{M}]/u.test(row.inserted)) {
287
+ const left = pieces[at - 1], right = pieces[at];
288
+ const inner = left?.text && right?.text && left.owner === right.owner ? byId.get(left.owner) : null;
289
+ if (inner && inner.actId !== tx.id && inner.removed && differentActors(actorOf.get(inner.actId), tx.actor) && /[\p{L}\p{N}\p{M}]$/u.test(left.text) && /^[\p{L}\p{N}\p{M}]/u.test(right.text))
290
+ for (const parent of [inner.id, ...(left.lineage || [])]) lineage.add(parent);
291
+ }
279
292
  const hunk = {id, actId: tx.id, removed: row.removed, inserted: row.inserted, before: removed, derived,
280
293
  chosen, kept: selected.has(tx.id) && !chosen, lineage: [...lineage], supersededBy: new Set(), active: true,
281
294
  ...(coverIdsFor(tx.id) ? {coverIds: coverIdsFor(tx.id)} : {})};
@@ -1,6 +1,7 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  import {fields, scalar, plainPrototype} from './data.mjs';
3
3
  import {transformText} from './source.mjs';
4
+ import {dataImage} from './md-assets.mjs';
4
5
 
5
6
  const _RAPIER_TRANSACTION_ACTOR_LIMIT = 160;
6
7
  const _RAPIER_TRANSACTION_OPERATION_LIMIT = 96;
@@ -75,7 +76,7 @@ function _rapierValidAuthored(origin) {
75
76
  !/[\uD800-\uDFFF]/u.test(row.removed) && !/[\uD800-\uDFFF]/u.test(row.inserted));
76
77
  }
77
78
 
78
- function _rapierRecordIndex(records) {
79
+ function _rapierRecordIndex(records, shared = false) {
79
80
  const byId = new Map(), splices = new Map(), metadata = new Map();
80
81
  for (const record of records) {
81
82
  const id = record?.transaction?.id;
@@ -99,9 +100,12 @@ function _rapierRecordIndex(records) {
99
100
  }
100
101
  cache.set(current, value);
101
102
  for (let i = path.length - 1; i >= 0; i--) {
102
- if (path[i].transaction.reverts && value != null) value = effects
103
- ? Object.fromEntries(Object.entries(value).map(([key, pair]) => [key, {before: pair.after, after: pair.before}]))
104
- : value.slice().reverse().map(row => ({pos: row.pos, removed: row.inserted, inserted: row.removed}));
103
+ if (path[i].transaction.reverts && value != null) {
104
+ value = effects
105
+ ? Object.fromEntries(Object.entries(value).map(([key, pair]) => [key, {before: pair.after, after: pair.before}]))
106
+ : value.slice().reverse().map(row => ({pos: row.pos, removed: row.inserted, inserted: row.removed}));
107
+ if (shared) { for (const row of Object.values(value)) Object.freeze(row); Object.freeze(value); }
108
+ }
105
109
  cache.set(path[i], value);
106
110
  }
107
111
  return value;
@@ -109,10 +113,27 @@ function _rapierRecordIndex(records) {
109
113
  return {byId, splices: record => resolve(record, false), metadata: record => resolve(record, true)};
110
114
  }
111
115
 
116
+ const _rapierLedgerIndexes = new WeakMap();
117
+ function _rapierLedgerIndex(ledger) {
118
+ const records = ledger || [];
119
+ if (!Array.isArray(records)) return _rapierRecordIndex(records);
120
+ const held = _rapierLedgerIndexes.get(records);
121
+ if (held && held.records.length === records.length && held.records.at(-1) === records.at(-1) &&
122
+ (held.checked || held.records.every((record, at) => record === records[at]))) {
123
+ if (!held.checked) { held.checked = true; queueMicrotask(() => { held.checked = false; }); }
124
+ return held.index;
125
+ }
126
+ if (!records.every(record => record && typeof record === 'object' && Object.isFrozen(record) && Object.isFrozen(record.transaction ?? {})))
127
+ return _rapierRecordIndex(records);
128
+ const index = _rapierRecordIndex(records, true);
129
+ _rapierLedgerIndexes.set(records, {records: records.slice(), index});
130
+ return index;
131
+ }
132
+
112
133
  function _rapierRecordSplices(entry, ledger) {
113
134
  try {
114
135
  if (entry && Array.isArray(entry.splices)) return entry.splices;
115
- return _rapierRecordIndex(ledger || []).splices(entry);
136
+ return _rapierLedgerIndex(ledger).splices(entry);
116
137
  } catch (_) { return null; }
117
138
  }
118
139
 
@@ -162,7 +183,7 @@ function _rapierRecordMetadata(entry, ledger) {
162
183
  try {
163
184
  if (Object.hasOwn(entry, 'metadata')) return _rapierValidMetadataEffect(entry.metadata) ? entry.metadata : undefined;
164
185
  if (Array.isArray(entry.splices)) return null;
165
- return _rapierRecordIndex(ledger || []).metadata(entry);
186
+ return _rapierLedgerIndex(ledger).metadata(entry);
166
187
  } catch (_) { return undefined; }
167
188
  }
168
189
 
@@ -175,10 +196,10 @@ function _rapierPictureFinish(record, original, earlier, lookup) {
175
196
  if (!reference || !/^\]\[[a-z0-9-]+\]$/i.test(reference.inserted) || reference.removed === reference.inserted) return false;
176
197
  const definition = rows.find(row => row !== reference), oldLabel = reference.removed.slice(2, -1), newLabel = reference.inserted.slice(2, -1);
177
198
  const body = (text, label) => {
178
- const prefix = '[' + label + ']: data:image/svg+xml;base64,';
199
+ const prefix = '[' + label + ']: ';
179
200
  if (typeof text !== 'string' || !text.startsWith(prefix)) return null;
180
201
  const value = text.slice(prefix.length), end = value.indexOf(' '), bytes = end < 0 ? value : value.slice(0, end), title = end < 0 ? '' : value.slice(end);
181
- return /^[A-Za-z0-9+/]+={0,2}$/.test(bytes) && !/[\r\n]/.test(title) ? title : null;
202
+ return dataImage(bytes)?.codec === 'image/svg+xml' && !/[\r\n]/.test(title) ? title : null;
182
203
  };
183
204
  const title = body(definition.removed, oldLabel);
184
205
  if (title === null || body(definition.inserted, newLabel) !== title) return false;
@@ -292,6 +313,7 @@ function _rapierWalkHistoryEffects(records, lookup, visit = null, observe = null
292
313
  }
293
314
  }
294
315
  if (refs.some(id => typeof id !== 'string' || !nodes.has(id) || pictures.has(id))) return {ok: false};
316
+ if (tx.actor?.kind === 'agent' && refs.some(id => byId.get(id).transaction.actor?.kind !== 'agent')) return {ok: false};
295
317
  nodes.set(tx.id, {active: true, blockers: 0, references: refs, dependents: []}); references.set(tx.id, refs.slice());
296
318
  byId.set(tx.id, record); earlier.push(record);
297
319
  for (const ref of refs) {
@@ -505,9 +527,10 @@ const _rapierPrepareHistoryRecords = (() => {
505
527
 
506
528
  const _rapierJournalRecord = (() => {
507
529
  const copies = new WeakMap();
530
+ const fixed = value => { if (value && typeof value === 'object') { for (const key of Object.keys(value)) fixed(value[key]); Object.freeze(value); } return value; };
508
531
  return record => {
509
532
  let copy = copies.get(record);
510
- if (!copy) { copy = JSON.parse(JSON.stringify(record)); copies.set(record, copy); }
533
+ if (!copy) { copy = fixed(JSON.parse(JSON.stringify(record))); copies.set(record, copy); }
511
534
  return copy;
512
535
  };
513
536
  })();