edytor 6.0.0 → 7.0.0
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/README.md +3 -3
- package/dist/cloudflare/DocumentRoom.d.ts +77 -2
- package/dist/cloudflare/DocumentRoom.js +37 -1
- package/dist/cloudflare/index.d.ts +1 -1
- package/dist/cloudflare/index.js +1 -1
- package/dist/cloudflare/room/access.d.ts +6 -1
- package/dist/cloudflare/room/access.js +30 -4
- package/dist/cloudflare/room/admission.d.ts +11 -0
- package/dist/cloudflare/room/admission.js +43 -10
- package/dist/cloudflare/room/context.d.ts +11 -2
- package/dist/cloudflare/room/context.js +17 -6
- package/dist/cloudflare/room/forged.d.ts +1 -1
- package/dist/cloudflare/room/forged.js +11 -9
- package/dist/cloudflare/room/frames.d.ts +2 -0
- package/dist/cloudflare/room/frames.js +2 -0
- package/dist/cloudflare/room/presence.js +1 -4
- package/dist/cloudflare/room/reseed.d.ts +93 -0
- package/dist/cloudflare/room/reseed.js +500 -0
- package/dist/cloudflare/room/scheduler.d.ts +1 -1
- package/dist/cloudflare/room/scheduler.js +9 -1
- package/dist/cloudflare/room/shared.d.ts +10 -0
- package/dist/cloudflare/room/shared.js +10 -0
- package/dist/cloudflare/room/storage.d.ts +7 -0
- package/dist/cloudflare/room/storage.js +33 -1
- package/dist/components/Edytor.svelte +18 -3
- package/dist/components/Edytor.svelte.d.ts +10 -1
- package/dist/components/EdytorRoot.svelte +17 -0
- package/dist/components/EdytorRoot.svelte.d.ts +4 -0
- package/dist/components/Suggestion.svelte +1 -1
- package/dist/crdt/attribution/block.d.ts +3 -0
- package/dist/crdt/attribution/block.js +3 -2
- package/dist/crdt/doc/suggest.d.ts +6 -2
- package/dist/crdt/doc/suggest.js +6 -5
- package/dist/crdt/edytor-doc.d.ts +1 -1
- package/dist/crdt/edytor-doc.js +1 -1
- package/dist/crdt/engine-room.d.ts +4 -0
- package/dist/crdt/engine-room.js +6 -0
- package/dist/crdt/index.d.ts +2 -1
- package/dist/crdt/protocol.d.ts +2 -2
- package/dist/crdt/protocol.js +2 -2
- package/dist/crdt/protocols/auth.d.ts +8 -1
- package/dist/crdt/protocols/auth.js +14 -1
- package/dist/crdt/providers/index.d.ts +1 -0
- package/dist/crdt/providers/index.js +22 -3
- package/dist/crdt/providers/room.d.ts +15 -0
- package/dist/crdt/providers/room.js +15 -0
- package/dist/crdt/providers/websocket.d.ts +4 -2
- package/dist/crdt/providers/websocket.js +36 -9
- package/dist/crdt/reseed.d.ts +127 -0
- package/dist/crdt/reseed.js +533 -0
- package/dist/crdt/restore.d.ts +13 -1
- package/dist/crdt/restore.js +8 -3
- package/dist/crdt/schema.d.ts +6 -0
- package/dist/crdt/schema.js +6 -0
- package/dist/crdt/structs.d.ts +8 -11
- package/dist/crdt/structs.js +25 -44
- package/dist/crdt/text/index/build.d.ts +3 -9
- package/dist/crdt/text/index/build.js +87 -181
- package/dist/crdt/vendor/yjs/UPSTREAM.md +101 -5
- package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
- package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +10 -10
- package/dist/crdt/vendor/yjs/dts/utils/encoding.d.ts +1 -0
- package/dist/crdt/vendor/yjs/src/index.js +1 -1
- package/dist/crdt/vendor/yjs/src/structs/Item.js +24 -13
- package/dist/crdt/vendor/yjs/src/utils/Transaction.js +12 -10
- package/dist/crdt/vendor/yjs/src/utils/encoding.js +42 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/selection/selection.svelte.d.ts +1 -1
- package/dist/selection/selection.svelte.js +87 -106
- package/dist/session/commands.js +49 -51
- package/dist/surface/attributes.d.ts +3 -3
- package/dist/surface/attributes.js +2 -2
- package/dist/surface/observer.svelte.d.ts +7 -7
- package/dist/surface/observer.svelte.js +213 -309
- package/package.json +1 -1
|
@@ -33,7 +33,7 @@ is no longer a dependency of any kind: `tests/packed-consumer/smoke.js` and
|
|
|
33
33
|
## Layout
|
|
34
34
|
|
|
35
35
|
```text
|
|
36
|
-
src/ upstream src/, plus patches YP1 (import specifiers), YP4, YP5, YP7, YP8 (pruning), YP9–YP15, YP16 (no delta layer), YP17 (one update encoding), YP18 (no undo manager), YP19 (only what edytor calls), YP20 (hold records), YP21 (claim items), YP22 (move records), YP23 (a block set's trim), YP24 (a string table per update), YP25 (paired marks written in parts), YP26 (a client table per update), YP27 (the parent kind in the info byte), YP28 (large integers in content values), YP29 (a collected mark or claim keeps its class)
|
|
36
|
+
src/ upstream src/, plus patches YP1 (import specifiers), YP4, YP5, YP7, YP8 (pruning), YP9–YP15, YP16 (no delta layer), YP17 (one update encoding), YP18 (no undo manager), YP19 (only what edytor calls), YP20 (hold records), YP21 (claim items), YP22 (move records), YP23 (a block set's trim), YP24 (a string table per update), YP25 (paired marks written in parts), YP26 (a client table per update), YP27 (the parent kind in the info byte), YP28 (large integers in content values), YP29 (a collected mark or claim keeps its class), YP30 (a transaction's `beforeCommit`), YP31 (a hold inside a nested node holds nothing), YP32 (a delete that proposes), YP33 (one transaction log) and YP34 (an update read at an earlier state)
|
|
37
37
|
global.d.ts upstream global.d.ts, plus patches YP1, YP8 and YP19
|
|
38
38
|
dts/ generated TypeScript declarations (not upstream source — see below)
|
|
39
39
|
LICENSE upstream MIT license, verbatim
|
|
@@ -1022,7 +1022,8 @@ Patch (new code delimited by `// YP20 begin` / `// YP20 end`, edits marked `// Y
|
|
|
1022
1022
|
text a room lost is stored and acknowledged at once. A GC struct takes
|
|
1023
1023
|
nothing. An item that starts or stops being held (and is not removed)
|
|
1024
1024
|
moves its parent's length, drops its search markers, joins
|
|
1025
|
-
`transaction.changed` and is logged in `transaction.holds`
|
|
1025
|
+
`transaction.changed` and is logged in `transaction.holds` (since YP33:
|
|
1026
|
+
`transaction.log`, kind 1)
|
|
1026
1027
|
(`client, clock, ±len`, in order: the index's edits).
|
|
1027
1028
|
- **`YNode#delete(index, length, into, fresh)`**: with `into` (the records
|
|
1028
1029
|
list) the live units are held by one record appended there instead of
|
|
@@ -1038,7 +1039,8 @@ Edytor side: a text delete passes the records list (`crdt/text/model.ts`
|
|
|
1038
1039
|
copies the record (never the text), an undo of typing holds the typed text,
|
|
1039
1040
|
a dropped step removes what this writer's records of it hold
|
|
1040
1041
|
(`hist.delete-marks.release`); the purge removes what a record older than
|
|
1041
|
-
the horizon holds; the index folds `transaction.holds
|
|
1042
|
+
the horizon holds; the index folds `transaction.holds` (since YP33, the one
|
|
1043
|
+
`transaction.log`). Removed:
|
|
1042
1044
|
`bindCrdt(Y).doc.keepCopies`, `PurgeReport.records`, the restoration
|
|
1043
1045
|
records root, the engine object's `ContentAny`.
|
|
1044
1046
|
|
|
@@ -1172,7 +1174,8 @@ Patch (new code delimited by `// YP22 begin` / `// YP22 end`, edits marked `// Y
|
|
|
1172
1174
|
pending holds only. A
|
|
1173
1175
|
unit that starts or stops being moved (and is not gone) moves
|
|
1174
1176
|
its home sequence's length and drops its search markers; one whose mover
|
|
1175
|
-
changed is logged in `transaction.moves` (
|
|
1177
|
+
changed is logged in `transaction.moves` (since YP33: `transaction.log`,
|
|
1178
|
+
kind 2; `client, clock, len`, in
|
|
1176
1179
|
order), and its home and its new mover's sequences are marked changed.
|
|
1177
1180
|
- **`doc._clock`** (was YP13's `_markClock`): the greatest Lamport
|
|
1178
1181
|
timestamp of a mark or a move this document integrated; a local mark or
|
|
@@ -1537,7 +1540,7 @@ Patch (new code delimited by `// YP31 begin` / `// YP31 end`, edits marked `// Y
|
|
|
1537
1540
|
records list, `textdel`). `ContentHold#integrate` and `ContentHold#delete`
|
|
1538
1541
|
hold and release only then; inside a nested node's sequence the record is
|
|
1539
1542
|
a list of ids: it moves no length, waits in no `pendingHolds`, logs
|
|
1540
|
-
nothing in `transaction.holds
|
|
1543
|
+
nothing in `transaction.holds` (YP33: `transaction.log`), and its delete (an undo, a reviewer's
|
|
1541
1544
|
withdrawal, its node's delete) releases nothing. `YNode#hold(ids)` on a
|
|
1542
1545
|
nested node appends one such list entry.
|
|
1543
1546
|
|
|
@@ -1598,6 +1601,99 @@ schedules with the index's self-checks on), `suggesting-input.test.tsx`
|
|
|
1598
1601
|
(typing over a selection, a paste, Backspace and Delete over struck text),
|
|
1599
1602
|
the YP20 rows, the upstream suite unchanged.
|
|
1600
1603
|
|
|
1604
|
+
### YP33 — one log of what a transaction did to items (`src/utils/Transaction.js`, `src/structs/Item.js`)
|
|
1605
|
+
|
|
1606
|
+
Reason: edytor's index folds each transaction into its derived facts (rows,
|
|
1607
|
+
streams, slots, placements) once at commit and, for read-your-writes, over
|
|
1608
|
+
the part of an open transaction a read has not folded. The engine logged
|
|
1609
|
+
the holds (YP20, `transaction.holds`) and the mover changes (YP22,
|
|
1610
|
+
`transaction.moves`) in order, but the inserts and removals only as id sets,
|
|
1611
|
+
so the fold reconstructed them: it kept, per open transaction, copies of the
|
|
1612
|
+
insert and delete sets and diffed them at every read, walked both sets'
|
|
1613
|
+
structs again for the texts and again for the sequences, and decided by set
|
|
1614
|
+
membership which edits cancelled within a fold (about 1.6 KB minified in
|
|
1615
|
+
every app, `makeEditIndex` and `syncPending` in `crdt/text/index/build.ts`).
|
|
1616
|
+
The engine now logs the edits in the same log as the holds and the moves,
|
|
1617
|
+
and the fold reads one log from a cursor. In memory only: nothing encoded,
|
|
1618
|
+
no schema change.
|
|
1619
|
+
|
|
1620
|
+
Patch (new code delimited by `// YP33 begin` / `// YP33 end`, edits marked `// YP33`):
|
|
1621
|
+
|
|
1622
|
+
- **`transaction.log`** (replaces YP20's `holds` and YP22's `moves`): per
|
|
1623
|
+
run of one writer's items `kind, client, clock, len`, in the order the
|
|
1624
|
+
transaction did them; an item that continues the last entry (its kind,
|
|
1625
|
+
its client, the next clock, its sign) extends it, so a bulk insert or
|
|
1626
|
+
delete is a few entries, as the id sets' ranges were. Kind 0, an edit:
|
|
1627
|
+
`Item#integrate` logs `+length` before its content integrates (a node's
|
|
1628
|
+
children follow it; nothing for an item integrated removed, a
|
|
1629
|
+
`ContentDeleted`), `Item#delete` `-length`; kind 1,
|
|
1630
|
+
a hold record's change of visibility (YP20's entries, unchanged: a held
|
|
1631
|
+
item removed logs its give-back, so an item's kinds 0 and 1 sum to its
|
|
1632
|
+
visibility change); kind 2, a mover change (YP22's entries, unchanged).
|
|
1633
|
+
- **`logItem(tr, kind, item, len, mark)`** (`Item.js`): the one writer (it
|
|
1634
|
+
extends a run's entry), which also marks the parent changed (it replaces
|
|
1635
|
+
`logHold` and `Item#delete`'s `addChangedTypeToTransaction`; `logMove`
|
|
1636
|
+
calls it). `Item#integrate` logs with `mark` false and keeps its own
|
|
1637
|
+
mark, after its content, so `transaction.changed` keeps its order.
|
|
1638
|
+
|
|
1639
|
+
The insert and delete sets, `transaction.changed` and every upstream path
|
|
1640
|
+
are untouched: the log is a list the engine appends to and never reads.
|
|
1641
|
+
|
|
1642
|
+
Edytor side: the fold keeps one number per open transaction (the length of
|
|
1643
|
+
its log a read folded and that entry's last length then, so the units the
|
|
1644
|
+
engine added to it since are folded too), reads each entry's structs once
|
|
1645
|
+
(`walkRange`, the walk `walkIdSet` now runs per range) and replays the units each item showed
|
|
1646
|
+
or hid in order, so an edit made and undone within one fold moves the row
|
|
1647
|
+
by nothing; the sequences read kind 0 as their slots and records written and
|
|
1648
|
+
removed, kind 2 as their units whose mover changed. Removed: the copied and
|
|
1649
|
+
diffed id sets, the watermark, the second and third walks, the membership
|
|
1650
|
+
tests, the incomplete-walk fallback.
|
|
1651
|
+
|
|
1652
|
+
Measured (`scripts/bundle-size.mjs`, own minified): minimal 425,374 →
|
|
1653
|
+
424,034 (−1,340 B; gzip −290), every plugin 675,230 → 673,890 (−1,340),
|
|
1654
|
+
`edytor/export` unchanged; the engine's share +106 B (one log writer, which
|
|
1655
|
+
extends a run's entry). A first version logged one entry per item: the
|
|
1656
|
+
fold walked them one by one where the id sets gave it ranges, and a 5,000
|
|
1657
|
+
block construction and a 40-block range delete got slower (`bench/scale.js`);
|
|
1658
|
+
the runs bring both back.
|
|
1659
|
+
|
|
1660
|
+
Oracle: `src/tests/crdt/yp33-log.test.ts` (edits, holds and a removed held
|
|
1661
|
+
item's give-back, a move, a remote update with an item integrated removed),
|
|
1662
|
+
the YP20, YP22 and YP31 rows reading their entries of the log, the index's
|
|
1663
|
+
self-checks after every fold (they rebuild from the replicated state and
|
|
1664
|
+
never read the log), the fold's counters (`foldedStructs`, the scale rows),
|
|
1665
|
+
the random corpus, the upstream suite unchanged.
|
|
1666
|
+
|
|
1667
|
+
### YP34 — an update read at an earlier state (`src/utils/encoding.js`, `src/index.js`)
|
|
1668
|
+
|
|
1669
|
+
Reason: a re-seed's rebase (`room.reseed.rebase`, `crdt/reseed.ts`) gets an
|
|
1670
|
+
offline client's whole old document and must split it into the part the
|
|
1671
|
+
room held at the cut (the client's base) and the rest (its unsaved edits).
|
|
1672
|
+
`diffUpdate(update, sv)` gives the rest; nothing gave the base, and edytor
|
|
1673
|
+
has no access to the lazy struct reader and writer it would need (they are
|
|
1674
|
+
not exported). The engine now gives the counterpart. Encoding unchanged, no
|
|
1675
|
+
schema change.
|
|
1676
|
+
|
|
1677
|
+
Patch (new code delimited by `// YP34 begin` / `// YP34 end`, edits marked `// YP34`):
|
|
1678
|
+
|
|
1679
|
+
- **`clipUpdate(update, sv, ds)`**: the structs of `update` under the state
|
|
1680
|
+
vector `sv` (a struct that crosses it is cut there, through the content's
|
|
1681
|
+
`offsetEnd`; a skip is written only where a later struct of its client
|
|
1682
|
+
follows it), and the deletes of `update` that the id set `ds` also holds
|
|
1683
|
+
(`intersectSets`). Exported from `src/index.js`, not from edytor's engine
|
|
1684
|
+
object (`crdt/engine.js`): only the room calls it, so apps keep none of it.
|
|
1685
|
+
|
|
1686
|
+
Deleted content a document collected cannot come back (a collecting
|
|
1687
|
+
document writes it as deleted); edytor's text deletes are hold records
|
|
1688
|
+
(YP20), which keep it.
|
|
1689
|
+
|
|
1690
|
+
Measured: vendored execution lines +30; the app bundle unchanged (the
|
|
1691
|
+
engine object does not hold it).
|
|
1692
|
+
|
|
1693
|
+
Oracle: `src/tests/crdt/yp34-clip.test.ts` (an update read at an earlier
|
|
1694
|
+
state, its later deletes left out; a run cut at the state vector), the
|
|
1695
|
+
re-seed rows (`src/tests/crdt/reseed/`), the upstream suite unchanged.
|
|
1696
|
+
|
|
1601
1697
|
## Generated declarations (`dts/`)
|
|
1602
1698
|
|
|
1603
1699
|
`svelte-package` copies JS verbatim but emits no `.d.ts` for JS inputs, so
|
|
@@ -11,7 +11,7 @@ export { GC } from "./structs/GC.js";
|
|
|
11
11
|
export { Skip } from "./structs/Skip.js";
|
|
12
12
|
export type ContentIds = import("./utils/ids.js").ContentIds;
|
|
13
13
|
export { IdSet, createDeleteSetFromStructStore, diffIdSet, createIdSet, mergeIdSets, insertIntoIdSet, iterateStructsByIdSet, readIdSet, writeIdSet, intersectSets } from "./utils/ids.js";
|
|
14
|
-
export { applyUpdate, encodeStateAsUpdate, encodeStateVector, decodeStateVector, diffUpdate, mergeUpdates } from "./utils/encoding.js";
|
|
14
|
+
export { applyUpdate, encodeStateAsUpdate, encodeStateVector, decodeStateVector, diffUpdate, clipUpdate, mergeUpdates } from "./utils/encoding.js";
|
|
15
15
|
export { ID, createID, compareIDs, findRootTypeKey } from "./utils/ID.js";
|
|
16
16
|
export { idAtIndex, indexOfId } from "./utils/positions.js";
|
|
17
17
|
export { findIndexSS, getItemCleanStart, getItemCleanEnd, isKeptReplaced } from "./utils/transaction-helpers.js";
|
|
@@ -31,18 +31,18 @@ export class Transaction {
|
|
|
31
31
|
*/
|
|
32
32
|
insertSet: import("./ids.js").IdSet;
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
* `client, clock, len` (
|
|
36
|
-
*
|
|
34
|
+
* What the transaction did to items, in order: per run of one writer's
|
|
35
|
+
* items `kind, client, clock, len` (an item that continues the last entry
|
|
36
|
+
* extends it). Kind 0, an edit: integrated (`len > 0`, before its content
|
|
37
|
+
* integrates; an item integrated removed logs none) or removed (`len < 0`);
|
|
38
|
+
* kind 1, a hold record's
|
|
39
|
+
* (YP20): shown (`len > 0`) or hidden (`< 0`; an item removed while held
|
|
40
|
+
* is logged shown, so an item's kinds 0 and 1 sum to its visibility
|
|
41
|
+
* change); kind 2, its mover changed (YP22: a move record integrated or
|
|
42
|
+
* deleted, a moved unit removed).
|
|
37
43
|
* @type {Array<number>}
|
|
38
44
|
*/
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* YP22: the units whose mover changed (a move record integrated or
|
|
42
|
-
* deleted, a moved unit removed), in order: per item `client, clock, len`.
|
|
43
|
-
* @type {Array<number>}
|
|
44
|
-
*/
|
|
45
|
-
moves: Array<number>;
|
|
45
|
+
log: Array<number>;
|
|
46
46
|
/**
|
|
47
47
|
* All types that were directly modified (property added or child
|
|
48
48
|
* inserted/deleted). New types are not included in this Set.
|
|
@@ -5,6 +5,7 @@ export function writeStateAsUpdate(encoder: UpdateEncoder, doc: Doc, targetState
|
|
|
5
5
|
export function encodeStateAsUpdate(doc: Doc, encodedTargetStateVector?: Uint8Array): Uint8Array<ArrayBuffer>;
|
|
6
6
|
export function mergeUpdates(updates: Array<Uint8Array<ArrayBuffer>>): Uint8Array<ArrayBuffer>;
|
|
7
7
|
export function diffUpdate(update: Uint8Array, sv: Uint8Array): Uint8Array<ArrayBuffer>;
|
|
8
|
+
export function clipUpdate(update: Uint8Array, sv: Uint8Array, ds: import("./ids.js").IdSet): Uint8Array<ArrayBuffer>;
|
|
8
9
|
export function decodeStateVector(decodedState: Uint8Array): Map<number, number>;
|
|
9
10
|
export function encodeStateVector(doc: Doc | Map<number, number>): Uint8Array<ArrayBuffer>;
|
|
10
11
|
import { UpdateEncoder } from './UpdateEncoder.js';
|
|
@@ -7,7 +7,7 @@ export { IdSet, createDeleteSetFromStructStore, diffIdSet, createIdSet, mergeIdS
|
|
|
7
7
|
export { Doc } from './utils/Doc.js'
|
|
8
8
|
export { UpdateDecoder } from './utils/UpdateDecoder.js'
|
|
9
9
|
export { UpdateEncoder } from './utils/UpdateEncoder.js'
|
|
10
|
-
export { applyUpdate, encodeStateAsUpdate, encodeStateVector, decodeStateVector, diffUpdate, mergeUpdates } from './utils/encoding.js'
|
|
10
|
+
export { applyUpdate, encodeStateAsUpdate, encodeStateVector, decodeStateVector, diffUpdate, clipUpdate, mergeUpdates } from './utils/encoding.js' // YP34: clipUpdate
|
|
11
11
|
export { ID, createID, compareIDs, findRootTypeKey } from './utils/ID.js'
|
|
12
12
|
export { isParentOf } from './utils/isParentOf.js'
|
|
13
13
|
export { idAtIndex, indexOfId } from './utils/positions.js' // YP19
|
|
@@ -308,6 +308,8 @@ export class Item extends AbstractStruct {
|
|
|
308
308
|
}
|
|
309
309
|
addStructToIdSet(transaction.insertSet, this)
|
|
310
310
|
transaction.doc.store.add(this)
|
|
311
|
+
// YP33: log the units it shows before its content integrates (a node's children follow it)
|
|
312
|
+
logItem(transaction, 0, this, this.content.constructor === ContentDeleted ? 0 : this.length, false)
|
|
311
313
|
this.content.integrate(transaction, this)
|
|
312
314
|
// add parent to transaction.changed
|
|
313
315
|
addChangedTypeToTransaction(transaction, /** @type {YNode} */ (this.parent), this.parentSub)
|
|
@@ -393,7 +395,7 @@ export class Item extends AbstractStruct {
|
|
|
393
395
|
// adjust the length of parent
|
|
394
396
|
if (this.holds > 0) {
|
|
395
397
|
// YP20: already hidden — the delete set counts it again, the log gives it back
|
|
396
|
-
|
|
398
|
+
logItem(transaction, 1, this, this.length) // YP33
|
|
397
399
|
} else if (this.movers !== null) {
|
|
398
400
|
// YP22: hidden at home already; its mover shows it no more (`gone`)
|
|
399
401
|
logMove(transaction, this, this.mover)
|
|
@@ -411,7 +413,7 @@ export class Item extends AbstractStruct {
|
|
|
411
413
|
}
|
|
412
414
|
this.markDeleted()
|
|
413
415
|
transaction.deleteSet.add(this.id.client, this.id.clock, this.length)
|
|
414
|
-
|
|
416
|
+
logItem(transaction, 0, this, -this.length) // YP33
|
|
415
417
|
// YP14: a node a concurrent value replaced keeps its subtree (the document asked)
|
|
416
418
|
if (!isKeptReplaced(this)) this.content.delete(transaction, this) // YP22: a move record drops itself from its units' movers
|
|
417
419
|
}
|
|
@@ -929,26 +931,36 @@ export class ContentDeleted {
|
|
|
929
931
|
}
|
|
930
932
|
|
|
931
933
|
// YP20 begin (edytor fork: hold records — see UPSTREAM.md YP20)
|
|
934
|
+
// YP33 begin (edytor fork: one log of what a transaction did to items — see UPSTREAM.md YP33)
|
|
932
935
|
/**
|
|
933
|
-
* Log
|
|
934
|
-
*
|
|
936
|
+
* Log `len` units of `item` as `kind` (0 an edit, 1 a hold, 2 a move) in
|
|
937
|
+
* `tr.log`, in order, and (unless `mark` is false) its parent as changed.
|
|
938
|
+
* An entry the last one continues (its kind, its client, the next clock, its
|
|
939
|
+
* sign) extends it, so a run of one writer's items is one entry; `len` 0
|
|
940
|
+
* logs none.
|
|
935
941
|
*
|
|
936
942
|
* @param {Transaction} tr
|
|
943
|
+
* @param {number} kind
|
|
937
944
|
* @param {Item} item
|
|
938
945
|
* @param {number} len
|
|
946
|
+
* @param {boolean} [mark]
|
|
939
947
|
*/
|
|
940
|
-
const
|
|
941
|
-
tr.
|
|
942
|
-
|
|
948
|
+
const logItem = (tr, kind, item, len, mark = true) => {
|
|
949
|
+
const log = tr.log
|
|
950
|
+
const n = log.length
|
|
951
|
+
const { client, clock } = item.id
|
|
952
|
+
if (log[n - 4] === kind && log[n - 3] === client && log[n - 2] + math.abs(log[n - 1]) === clock && log[n - 1] * len > 0) log[n - 1] += len
|
|
953
|
+
else if (len !== 0) log.push(kind, client, clock, len)
|
|
954
|
+
if (mark) addChangedTypeToTransaction(tr, /** @type {YNode} */ (item.parent), item.parentSub)
|
|
943
955
|
}
|
|
956
|
+
// YP33 end
|
|
944
957
|
|
|
945
958
|
/**
|
|
946
959
|
* Add `delta` (1, or -1: release) of a hold record (`record` null: `holds`)
|
|
947
960
|
* or of the move record `record` (its `movers`, YP22; a record never moves a
|
|
948
961
|
* record) to `item`. An item that is not removed and starts or stops being
|
|
949
962
|
* hidden moves its parent's length and drops its search markers; a hold that
|
|
950
|
-
* does is logged (`tr.
|
|
951
|
-
* (`tr.moves`).
|
|
963
|
+
* does is logged (`tr.log`, YP33), and so is a unit whose mover changed.
|
|
952
964
|
*
|
|
953
965
|
* @param {Transaction} tr
|
|
954
966
|
* @param {Item} item
|
|
@@ -976,7 +988,7 @@ const holdItem = (tr, item, delta, record) => {
|
|
|
976
988
|
if (item.countable && item.parentSub === null) parent._length += len
|
|
977
989
|
// the indices the search markers counted moved (a held delete moves them itself)
|
|
978
990
|
if (parent._searchMarker) parent._searchMarker.length = 0
|
|
979
|
-
if (record === null)
|
|
991
|
+
if (record === null) logItem(tr, 1, item, len) // YP33
|
|
980
992
|
}
|
|
981
993
|
const after = item.mover
|
|
982
994
|
if (before !== after) {
|
|
@@ -1223,15 +1235,14 @@ const stronger = (a, b) =>
|
|
|
1223
1235
|
|
|
1224
1236
|
/**
|
|
1225
1237
|
* Log that `item`'s mover changed (or it left its mover: removed) in
|
|
1226
|
-
* `tr.
|
|
1238
|
+
* `tr.log` (YP33), and its home and its new mover's sequences as changed.
|
|
1227
1239
|
*
|
|
1228
1240
|
* @param {Transaction} tr
|
|
1229
1241
|
* @param {Item} item
|
|
1230
1242
|
* @param {Item|null} mover
|
|
1231
1243
|
*/
|
|
1232
1244
|
const logMove = (tr, item, mover) => {
|
|
1233
|
-
tr
|
|
1234
|
-
addChangedTypeToTransaction(tr, /** @type {YNode} */ (item.parent), item.parentSub)
|
|
1245
|
+
logItem(tr, 2, item, item.length) // YP33
|
|
1235
1246
|
if (mover !== null) addChangedTypeToTransaction(tr, /** @type {YNode} */ (mover.parent), null)
|
|
1236
1247
|
}
|
|
1237
1248
|
|
|
@@ -40,19 +40,21 @@ export class Transaction {
|
|
|
40
40
|
* Describes the set of inserted items by ids
|
|
41
41
|
*/
|
|
42
42
|
this.insertSet = createIdSet()
|
|
43
|
+
// YP33 begin (edytor fork: one log of what the transaction did to items — see UPSTREAM.md YP33)
|
|
43
44
|
/**
|
|
44
|
-
*
|
|
45
|
-
* `client, clock, len` (
|
|
46
|
-
*
|
|
45
|
+
* What the transaction did to items, in order: per run of one writer's
|
|
46
|
+
* items `kind, client, clock, len` (an item that continues the last entry
|
|
47
|
+
* extends it). Kind 0, an edit: integrated (`len > 0`, before its content
|
|
48
|
+
* integrates; an item integrated removed logs none) or removed (`len < 0`);
|
|
49
|
+
* kind 1, a hold record's
|
|
50
|
+
* (YP20): shown (`len > 0`) or hidden (`< 0`; an item removed while held
|
|
51
|
+
* is logged shown, so an item's kinds 0 and 1 sum to its visibility
|
|
52
|
+
* change); kind 2, its mover changed (YP22: a move record integrated or
|
|
53
|
+
* deleted, a moved unit removed).
|
|
47
54
|
* @type {Array<number>}
|
|
48
55
|
*/
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
* YP22: the units whose mover changed (a move record integrated or
|
|
52
|
-
* deleted, a moved unit removed), in order: per item `client, clock, len`.
|
|
53
|
-
* @type {Array<number>}
|
|
54
|
-
*/
|
|
55
|
-
this.moves = []
|
|
56
|
+
this.log = []
|
|
57
|
+
// YP33 end
|
|
56
58
|
/**
|
|
57
59
|
* All types that were directly modified (property added or child
|
|
58
60
|
* inserted/deleted). New types are not included in this Set.
|
|
@@ -22,7 +22,7 @@ import * as array from 'lib0-v14/array'
|
|
|
22
22
|
|
|
23
23
|
import { getStateVector, StructStore } from './StructStore.js'
|
|
24
24
|
import { getItemCleanStart, getItemCleanEnd } from './transaction-helpers.js'
|
|
25
|
-
import { createIdSet, IdRange, readAndApplyDeleteSet, readIdSet, mergeIdSets, writeIdSet } from './ids.js'
|
|
25
|
+
import { createIdSet, IdRange, readAndApplyDeleteSet, readIdSet, mergeIdSets, writeIdSet, intersectSets } from './ids.js' // YP34: intersectSets
|
|
26
26
|
import { createID, ID } from './ID.js'
|
|
27
27
|
import { UpdateDecoder } from './UpdateDecoder.js'
|
|
28
28
|
import { UpdateEncoder } from './UpdateEncoder.js'
|
|
@@ -469,6 +469,47 @@ export const diffUpdate = (update, sv) => {
|
|
|
469
469
|
return encoder.toUint8Array()
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
+
// YP34 begin
|
|
473
|
+
/**
|
|
474
|
+
* The part of `update` that the state vector `sv` covers, with only the
|
|
475
|
+
* deletes `ds` also holds: `update` as it read at an earlier state (the
|
|
476
|
+
* counterpart of `diffUpdate`). A struct that crosses the state vector is
|
|
477
|
+
* cut at it; a skip is written only where a later struct of its client
|
|
478
|
+
* follows it.
|
|
479
|
+
*
|
|
480
|
+
* @param {Uint8Array} update
|
|
481
|
+
* @param {Uint8Array} sv
|
|
482
|
+
* @param {import('./ids.js').IdSet} ds
|
|
483
|
+
*/
|
|
484
|
+
export const clipUpdate = (update, sv, ds) => {
|
|
485
|
+
const state = decodeStateVector(sv)
|
|
486
|
+
const encoder = new UpdateEncoder()
|
|
487
|
+
const lazyStructWriter = new LazyStructWriter(encoder)
|
|
488
|
+
const decoder = new UpdateDecoder(decoding.createDecoder(update))
|
|
489
|
+
const reader = new LazyStructReader(decoder, false)
|
|
490
|
+
/** @type {Array<Skip>} */
|
|
491
|
+
let skips = []
|
|
492
|
+
let client = -1
|
|
493
|
+
for (let curr = reader.curr; curr !== null; curr = reader.next()) {
|
|
494
|
+
if (curr.id.client !== client) [client, skips] = [curr.id.client, []]
|
|
495
|
+
const svClock = state.get(client) || 0
|
|
496
|
+
if (curr.id.clock >= svClock) continue
|
|
497
|
+
if (curr.constructor === Skip) {
|
|
498
|
+
skips.push(/** @type {Skip} */ (curr))
|
|
499
|
+
continue
|
|
500
|
+
}
|
|
501
|
+
if (lazyStructWriter.written > 0 && lazyStructWriter.currClient === client) {
|
|
502
|
+
for (const skip of skips) writeStructToLazyStructWriter(lazyStructWriter, skip, 0, 0)
|
|
503
|
+
}
|
|
504
|
+
skips = []
|
|
505
|
+
writeStructToLazyStructWriter(lazyStructWriter, curr, 0, math.max(curr.id.clock + curr.length - svClock, 0))
|
|
506
|
+
}
|
|
507
|
+
finishLazyStructWriting(lazyStructWriter)
|
|
508
|
+
writeIdSet(encoder, intersectSets(readIdSet(decoder), ds))
|
|
509
|
+
return encoder.toUint8Array()
|
|
510
|
+
}
|
|
511
|
+
// YP34 end
|
|
512
|
+
|
|
472
513
|
/**
|
|
473
514
|
* Read decodedState and return State as Map.
|
|
474
515
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* This module re-exports the `.svelte` component, so it requires a
|
|
26
26
|
* bundler that understands Svelte (vite-plugin-svelte).
|
|
27
27
|
*/
|
|
28
|
-
export { default as Edytor } from './components/
|
|
28
|
+
export { default as Edytor } from './components/EdytorRoot.svelte';
|
|
29
29
|
export { useEdytor } from './edytor.svelte.js';
|
|
30
30
|
/** The editor instance plugins, hotkeys and `bind:edytor` receive (`Edytor` names the component). */
|
|
31
31
|
export type { Edytor as EdytorInstance, EdytorDocData } from './edytor.svelte.js';
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* bundler that understands Svelte (vite-plugin-svelte).
|
|
27
27
|
*/
|
|
28
28
|
// ── The editor ─────────────────────────────────────────────────────────
|
|
29
|
-
export { default as Edytor } from './components/
|
|
29
|
+
export { default as Edytor } from './components/EdytorRoot.svelte';
|
|
30
30
|
export { useEdytor } from './edytor.svelte.js';
|
|
31
31
|
export { Block } from './block/block.svelte.js';
|
|
32
32
|
export { InlineBlock } from './block/inlineBlock.svelte.js';
|
|
@@ -34,7 +34,7 @@ export type Caret = {
|
|
|
34
34
|
* order), comparing boundary points — a focus on an ancestor element of the
|
|
35
35
|
* anchor (`(textElement, childCount)`) is after it.
|
|
36
36
|
*/
|
|
37
|
-
export declare const isBackward: (
|
|
37
|
+
export declare const isBackward: ({ anchorNode, anchorOffset, focusNode, focusOffset }: {
|
|
38
38
|
anchorNode: Node | null;
|
|
39
39
|
anchorOffset: number;
|
|
40
40
|
focusNode: Node | null;
|