prosemirror-changeset 2.3.0 → 2.4.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/CHANGELOG.md +12 -0
- package/README.md +30 -1
- package/dist/index.cjs +24 -3
- package/dist/index.d.cts +32 -2
- package/dist/index.d.ts +32 -2
- package/dist/index.js +29 -6
- package/package.json +1 -1
- package/src/README.md +3 -1
- package/src/change.ts +18 -0
- package/src/changeset.ts +10 -4
- package/src/diff.ts +13 -5
- package/test/test-diff.ts +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 2.4.0 (2026-02-14)
|
|
2
|
+
|
|
3
|
+
### New features
|
|
4
|
+
|
|
5
|
+
`Change` objects can now be serialized to and deserialized from JSON, and `ChangeSet.create` allows you to pass in a set of changes.
|
|
6
|
+
|
|
7
|
+
## 2.3.1 (2025-05-28)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Improve diffing to not treat closing tokens of different node types as the same token.
|
|
12
|
+
|
|
1
13
|
## 2.3.0 (2025-05-05)
|
|
2
14
|
|
|
3
15
|
### New features
|
package/README.md
CHANGED
|
@@ -43,11 +43,17 @@ A replaced range with metadata associated with it.
|
|
|
43
43
|
Data associated with the inserted content. Length adds up to
|
|
44
44
|
`this.toB - this.fromB`.
|
|
45
45
|
|
|
46
|
+
* **`toJSON`**`() → ChangeJSON`\
|
|
47
|
+
Returns a JSON-serializeable object to represent this change.
|
|
48
|
+
|
|
46
49
|
* `static `**`merge`**`<Data>(x: readonly Change[], y: readonly Change[], combine: fn(dataA: Data, dataB: Data) → Data) → readonly Change[]`\
|
|
47
50
|
This merges two changesets (the end document of x should be the
|
|
48
51
|
start document of y) into a single one spanning the start of x to
|
|
49
52
|
the end of y.
|
|
50
53
|
|
|
54
|
+
* `static `**`fromJSON`**`<Data>(json: ChangeJSON) → Change`\
|
|
55
|
+
Deserialize a change from JSON format.
|
|
56
|
+
|
|
51
57
|
|
|
52
58
|
### class Span`<Data = any>`
|
|
53
59
|
|
|
@@ -96,7 +102,7 @@ partially undo themselves by comparing their content.
|
|
|
96
102
|
make sure the method is called on the old set and passed the new
|
|
97
103
|
set. The returned positions will be in new document coordinates.
|
|
98
104
|
|
|
99
|
-
* `static `**`create`**`<Data = any>(doc: Node, combine?: fn(dataA: Data, dataB: Data) → Data = (a, b) => a === b ? a : null as any, tokenEncoder?: TokenEncoder = DefaultEncoder) → ChangeSet`\
|
|
105
|
+
* `static `**`create`**`<Data = any>(doc: Node, combine?: fn(dataA: Data, dataB: Data) → Data = (a, b) => a === b ? a : null as any, tokenEncoder?: TokenEncoder = DefaultEncoder, changes?: readonly Change[] = []) → ChangeSet`\
|
|
100
106
|
Create a changeset with the given base object and configuration.
|
|
101
107
|
|
|
102
108
|
The `combine` function is used to compare and combine metadata—it
|
|
@@ -108,6 +114,11 @@ partially undo themselves by comparing their content.
|
|
|
108
114
|
changes. The default is to just compare nodes by name and text
|
|
109
115
|
by character, ignoring marks and attributes.
|
|
110
116
|
|
|
117
|
+
To serialize a change set, you can store its document and
|
|
118
|
+
change array as JSON, and then pass the deserialized (via
|
|
119
|
+
[`Change.fromJSON`](#changes.Change^fromJSON)) set of changes
|
|
120
|
+
as fourth argument to `create` to recreate the set.
|
|
121
|
+
|
|
111
122
|
|
|
112
123
|
* **`simplifyChanges`**`(changes: readonly Change[], doc: Node) → Change[]`\
|
|
113
124
|
Simplifies a set of changes for presentation. This makes the
|
|
@@ -144,3 +155,21 @@ performance.
|
|
|
144
155
|
Compare the given tokens. Should return true when they count as
|
|
145
156
|
equal.
|
|
146
157
|
|
|
158
|
+
|
|
159
|
+
### type ChangeJSON`<Data>`
|
|
160
|
+
|
|
161
|
+
JSON-serialized form of a change.
|
|
162
|
+
|
|
163
|
+
* **`fromA`**`: number`
|
|
164
|
+
|
|
165
|
+
* **`toA`**`: number`
|
|
166
|
+
|
|
167
|
+
* **`fromB`**`: number`
|
|
168
|
+
|
|
169
|
+
* **`toB`**`: number`
|
|
170
|
+
|
|
171
|
+
* **`deleted`**`: readonly {length: number, data: Data}[]`
|
|
172
|
+
|
|
173
|
+
* **`inserted`**`: readonly {length: number, data: Data}[]`
|
|
174
|
+
|
|
175
|
+
|
package/dist/index.cjs
CHANGED
|
@@ -12,6 +12,12 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
|
|
|
12
12
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
13
13
|
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
|
|
14
14
|
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
15
|
+
function typeID(type) {
|
|
16
|
+
var cache = type.schema.cached.changeSetIDs || (type.schema.cached.changeSetIDs = Object.create(null));
|
|
17
|
+
var id = cache[type.name];
|
|
18
|
+
if (id == null) cache[type.name] = id = Object.keys(type.schema.nodes).indexOf(type.name) + 1;
|
|
19
|
+
return id;
|
|
20
|
+
}
|
|
15
21
|
var DefaultEncoder = {
|
|
16
22
|
encodeCharacter: function encodeCharacter(_char) {
|
|
17
23
|
return _char;
|
|
@@ -19,8 +25,8 @@ var DefaultEncoder = {
|
|
|
19
25
|
encodeNodeStart: function encodeNodeStart(node) {
|
|
20
26
|
return node.type.name;
|
|
21
27
|
},
|
|
22
|
-
encodeNodeEnd: function encodeNodeEnd() {
|
|
23
|
-
return -
|
|
28
|
+
encodeNodeEnd: function encodeNodeEnd(node) {
|
|
29
|
+
return -typeID(node.type);
|
|
24
30
|
},
|
|
25
31
|
compareTokens: function compareTokens(a, b) {
|
|
26
32
|
return a === b;
|
|
@@ -204,6 +210,11 @@ var Change = function () {
|
|
|
204
210
|
if (startA == 0 && startB == 0 && endA == this.toA - this.fromA && endB == this.toB - this.fromB) return this;
|
|
205
211
|
return new Change(this.fromA + startA, this.fromA + endA, this.fromB + startB, this.fromB + endB, Span.slice(this.deleted, startA, endA), Span.slice(this.inserted, startB, endB));
|
|
206
212
|
}
|
|
213
|
+
}, {
|
|
214
|
+
key: "toJSON",
|
|
215
|
+
value: function toJSON() {
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
207
218
|
}], [{
|
|
208
219
|
key: "merge",
|
|
209
220
|
value: function merge(x, y, combine) {
|
|
@@ -270,6 +281,15 @@ var Change = function () {
|
|
|
270
281
|
}
|
|
271
282
|
}
|
|
272
283
|
}
|
|
284
|
+
}, {
|
|
285
|
+
key: "fromJSON",
|
|
286
|
+
value: function fromJSON(json) {
|
|
287
|
+
return new Change(json.fromA, json.toA, json.fromB, json.toB, json.deleted.map(function (d) {
|
|
288
|
+
return new Span(d.length, d.data);
|
|
289
|
+
}), json.inserted.map(function (d) {
|
|
290
|
+
return new Span(d.length, d.data);
|
|
291
|
+
}));
|
|
292
|
+
}
|
|
273
293
|
}]);
|
|
274
294
|
return Change;
|
|
275
295
|
}();
|
|
@@ -501,11 +521,12 @@ var ChangeSet = function () {
|
|
|
501
521
|
return a === b ? a : null;
|
|
502
522
|
};
|
|
503
523
|
var tokenEncoder = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DefaultEncoder;
|
|
524
|
+
var changes = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
|
|
504
525
|
return new ChangeSet({
|
|
505
526
|
combine: combine,
|
|
506
527
|
doc: doc,
|
|
507
528
|
encoder: tokenEncoder
|
|
508
|
-
},
|
|
529
|
+
}, changes);
|
|
509
530
|
}
|
|
510
531
|
}]);
|
|
511
532
|
return ChangeSet;
|
package/dist/index.d.cts
CHANGED
|
@@ -50,7 +50,32 @@ declare class Change<Data = any> {
|
|
|
50
50
|
the end of y.
|
|
51
51
|
*/
|
|
52
52
|
static merge<Data>(x: readonly Change<Data>[], y: readonly Change<Data>[], combine: (dataA: Data, dataB: Data) => Data): readonly Change<Data>[];
|
|
53
|
+
/**
|
|
54
|
+
Deserialize a change from JSON format.
|
|
55
|
+
*/
|
|
56
|
+
static fromJSON<Data>(json: ChangeJSON<Data>): Change<Data>;
|
|
57
|
+
/**
|
|
58
|
+
Returns a JSON-serializeable object to represent this change.
|
|
59
|
+
*/
|
|
60
|
+
toJSON(): ChangeJSON<Data>;
|
|
53
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
JSON-serialized form of a change.
|
|
64
|
+
*/
|
|
65
|
+
type ChangeJSON<Data> = {
|
|
66
|
+
fromA: number;
|
|
67
|
+
toA: number;
|
|
68
|
+
fromB: number;
|
|
69
|
+
toB: number;
|
|
70
|
+
deleted: readonly {
|
|
71
|
+
length: number;
|
|
72
|
+
data: Data;
|
|
73
|
+
}[];
|
|
74
|
+
inserted: readonly {
|
|
75
|
+
length: number;
|
|
76
|
+
data: Data;
|
|
77
|
+
}[];
|
|
78
|
+
};
|
|
54
79
|
|
|
55
80
|
/**
|
|
56
81
|
A token encoder can be passed when creating a `ChangeSet` in order
|
|
@@ -149,8 +174,13 @@ declare class ChangeSet<Data = any> {
|
|
|
149
174
|
serialized and compared when diffing the content produced by
|
|
150
175
|
changes. The default is to just compare nodes by name and text
|
|
151
176
|
by character, ignoring marks and attributes.
|
|
177
|
+
|
|
178
|
+
To serialize a change set, you can store its document and
|
|
179
|
+
change array as JSON, and then pass the deserialized (via
|
|
180
|
+
[`Change.fromJSON`](https://prosemirror.net/docs/ref/#changes.Change^fromJSON)) set of changes
|
|
181
|
+
as fourth argument to `create` to recreate the set.
|
|
152
182
|
*/
|
|
153
|
-
static create<Data = any>(doc: Node, combine?: (dataA: Data, dataB: Data) => Data, tokenEncoder?: TokenEncoder<any>): ChangeSet<Data>;
|
|
183
|
+
static create<Data = any>(doc: Node, combine?: (dataA: Data, dataB: Data) => Data, tokenEncoder?: TokenEncoder<any>, changes?: readonly Change<Data>[]): ChangeSet<Data>;
|
|
154
184
|
}
|
|
155
185
|
|
|
156
|
-
export { Change, ChangeSet, Span, type TokenEncoder, simplifyChanges };
|
|
186
|
+
export { Change, type ChangeJSON, ChangeSet, Span, type TokenEncoder, simplifyChanges };
|
package/dist/index.d.ts
CHANGED
|
@@ -50,7 +50,32 @@ declare class Change<Data = any> {
|
|
|
50
50
|
the end of y.
|
|
51
51
|
*/
|
|
52
52
|
static merge<Data>(x: readonly Change<Data>[], y: readonly Change<Data>[], combine: (dataA: Data, dataB: Data) => Data): readonly Change<Data>[];
|
|
53
|
+
/**
|
|
54
|
+
Deserialize a change from JSON format.
|
|
55
|
+
*/
|
|
56
|
+
static fromJSON<Data>(json: ChangeJSON<Data>): Change<Data>;
|
|
57
|
+
/**
|
|
58
|
+
Returns a JSON-serializeable object to represent this change.
|
|
59
|
+
*/
|
|
60
|
+
toJSON(): ChangeJSON<Data>;
|
|
53
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
JSON-serialized form of a change.
|
|
64
|
+
*/
|
|
65
|
+
type ChangeJSON<Data> = {
|
|
66
|
+
fromA: number;
|
|
67
|
+
toA: number;
|
|
68
|
+
fromB: number;
|
|
69
|
+
toB: number;
|
|
70
|
+
deleted: readonly {
|
|
71
|
+
length: number;
|
|
72
|
+
data: Data;
|
|
73
|
+
}[];
|
|
74
|
+
inserted: readonly {
|
|
75
|
+
length: number;
|
|
76
|
+
data: Data;
|
|
77
|
+
}[];
|
|
78
|
+
};
|
|
54
79
|
|
|
55
80
|
/**
|
|
56
81
|
A token encoder can be passed when creating a `ChangeSet` in order
|
|
@@ -149,8 +174,13 @@ declare class ChangeSet<Data = any> {
|
|
|
149
174
|
serialized and compared when diffing the content produced by
|
|
150
175
|
changes. The default is to just compare nodes by name and text
|
|
151
176
|
by character, ignoring marks and attributes.
|
|
177
|
+
|
|
178
|
+
To serialize a change set, you can store its document and
|
|
179
|
+
change array as JSON, and then pass the deserialized (via
|
|
180
|
+
[`Change.fromJSON`](https://prosemirror.net/docs/ref/#changes.Change^fromJSON)) set of changes
|
|
181
|
+
as fourth argument to `create` to recreate the set.
|
|
152
182
|
*/
|
|
153
|
-
static create<Data = any>(doc: Node, combine?: (dataA: Data, dataB: Data) => Data, tokenEncoder?: TokenEncoder<any>): ChangeSet<Data>;
|
|
183
|
+
static create<Data = any>(doc: Node, combine?: (dataA: Data, dataB: Data) => Data, tokenEncoder?: TokenEncoder<any>, changes?: readonly Change<Data>[]): ChangeSet<Data>;
|
|
154
184
|
}
|
|
155
185
|
|
|
156
|
-
export { Change, ChangeSet, Span, type TokenEncoder, simplifyChanges };
|
|
186
|
+
export { Change, type ChangeJSON, ChangeSet, Span, type TokenEncoder, simplifyChanges };
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
function typeID(type) {
|
|
2
|
+
let cache = type.schema.cached.changeSetIDs || (type.schema.cached.changeSetIDs = Object.create(null));
|
|
3
|
+
let id = cache[type.name];
|
|
4
|
+
if (id == null)
|
|
5
|
+
cache[type.name] = id = Object.keys(type.schema.nodes).indexOf(type.name) + 1;
|
|
6
|
+
return id;
|
|
7
|
+
}
|
|
8
|
+
// The default token encoder, which encodes node open tokens are
|
|
9
|
+
// encoded as strings holding the node name, characters as their
|
|
10
|
+
// character code, and node close tokens as negative numbers.
|
|
1
11
|
const DefaultEncoder = {
|
|
2
12
|
encodeCharacter: char => char,
|
|
3
13
|
encodeNodeStart: node => node.type.name,
|
|
4
|
-
encodeNodeEnd:
|
|
14
|
+
encodeNodeEnd: node => -typeID(node.type),
|
|
5
15
|
compareTokens: (a, b) => a === b
|
|
6
16
|
};
|
|
7
|
-
// Convert the given range of a fragment to tokens
|
|
8
|
-
// tokens are encoded as strings holding the node name, characters as
|
|
9
|
-
// their character code, and node close tokens as -1.
|
|
17
|
+
// Convert the given range of a fragment to tokens.
|
|
10
18
|
function tokens(frag, encoder, start, end, target) {
|
|
11
19
|
for (let i = 0, off = 0; i < frag.childCount; i++) {
|
|
12
20
|
let child = frag.child(i), endOff = off + child.nodeSize;
|
|
@@ -342,6 +350,16 @@ class Change {
|
|
|
342
350
|
}
|
|
343
351
|
}
|
|
344
352
|
}
|
|
353
|
+
/**
|
|
354
|
+
Deserialize a change from JSON format.
|
|
355
|
+
*/
|
|
356
|
+
static fromJSON(json) {
|
|
357
|
+
return new Change(json.fromA, json.toA, json.fromB, json.toB, json.deleted.map(d => new Span(d.length, d.data)), json.inserted.map(d => new Span(d.length, d.data)));
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
Returns a JSON-serializeable object to represent this change.
|
|
361
|
+
*/
|
|
362
|
+
toJSON() { return this; }
|
|
345
363
|
}
|
|
346
364
|
|
|
347
365
|
let letter;
|
|
@@ -638,9 +656,14 @@ class ChangeSet {
|
|
|
638
656
|
serialized and compared when diffing the content produced by
|
|
639
657
|
changes. The default is to just compare nodes by name and text
|
|
640
658
|
by character, ignoring marks and attributes.
|
|
659
|
+
|
|
660
|
+
To serialize a change set, you can store its document and
|
|
661
|
+
change array as JSON, and then pass the deserialized (via
|
|
662
|
+
[`Change.fromJSON`](https://prosemirror.net/docs/ref/#changes.Change^fromJSON)) set of changes
|
|
663
|
+
as fourth argument to `create` to recreate the set.
|
|
641
664
|
*/
|
|
642
|
-
static create(doc, combine = (a, b) => a === b ? a : null, tokenEncoder = DefaultEncoder) {
|
|
643
|
-
return new ChangeSet({ combine, doc, encoder: tokenEncoder },
|
|
665
|
+
static create(doc, combine = (a, b) => a === b ? a : null, tokenEncoder = DefaultEncoder, changes = []) {
|
|
666
|
+
return new ChangeSet({ combine, doc, encoder: tokenEncoder }, changes);
|
|
644
667
|
}
|
|
645
668
|
}
|
|
646
669
|
/**
|
package/package.json
CHANGED
package/src/README.md
CHANGED
package/src/change.ts
CHANGED
|
@@ -168,4 +168,22 @@ export class Change<Data = any> {
|
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
+
|
|
172
|
+
/// Deserialize a change from JSON format.
|
|
173
|
+
static fromJSON<Data>(json: ChangeJSON<Data>) {
|
|
174
|
+
return new Change(json.fromA, json.toA, json.fromB, json.toB,
|
|
175
|
+
json.deleted.map(d => new Span(d.length, d.data)),
|
|
176
|
+
json.inserted.map(d => new Span(d.length, d.data)))
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/// Returns a JSON-serializeable object to represent this change.
|
|
180
|
+
toJSON(): ChangeJSON<Data> { return this }
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// JSON-serialized form of a change.
|
|
184
|
+
export type ChangeJSON<Data> = {
|
|
185
|
+
fromA: number, toA: number,
|
|
186
|
+
fromB: number, toB: number,
|
|
187
|
+
deleted: readonly {length: number, data: Data}[],
|
|
188
|
+
inserted: readonly {length: number, data: Data}[]
|
|
171
189
|
}
|
package/src/changeset.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {Node} from "prosemirror-model"
|
|
2
2
|
import {StepMap} from "prosemirror-transform"
|
|
3
3
|
import {computeDiff, TokenEncoder, DefaultEncoder} from "./diff"
|
|
4
|
-
import {Change, Span} from "./change"
|
|
5
|
-
export {Change, Span}
|
|
4
|
+
import {Change, Span, ChangeJSON} from "./change"
|
|
5
|
+
export {Change, Span, ChangeJSON}
|
|
6
6
|
export {simplifyChanges} from "./simplify"
|
|
7
7
|
export {TokenEncoder}
|
|
8
8
|
|
|
@@ -146,12 +146,18 @@ export class ChangeSet<Data = any> {
|
|
|
146
146
|
/// serialized and compared when diffing the content produced by
|
|
147
147
|
/// changes. The default is to just compare nodes by name and text
|
|
148
148
|
/// by character, ignoring marks and attributes.
|
|
149
|
+
///
|
|
150
|
+
/// To serialize a change set, you can store its document and
|
|
151
|
+
/// change array as JSON, and then pass the deserialized (via
|
|
152
|
+
/// [`Change.fromJSON`](#changes.Change^fromJSON)) set of changes
|
|
153
|
+
/// as fourth argument to `create` to recreate the set.
|
|
149
154
|
static create<Data = any>(
|
|
150
155
|
doc: Node,
|
|
151
156
|
combine: (dataA: Data, dataB: Data) => Data = (a, b) => a === b ? a : null as any,
|
|
152
|
-
tokenEncoder: TokenEncoder<any> = DefaultEncoder
|
|
157
|
+
tokenEncoder: TokenEncoder<any> = DefaultEncoder,
|
|
158
|
+
changes: readonly Change<Data>[] = []
|
|
153
159
|
) {
|
|
154
|
-
return new ChangeSet({combine, doc, encoder: tokenEncoder},
|
|
160
|
+
return new ChangeSet({combine, doc, encoder: tokenEncoder}, changes)
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
/// Exported for testing @internal
|
package/src/diff.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Fragment, Node, Mark} from "prosemirror-model"
|
|
1
|
+
import {Fragment, Node, NodeType, Mark} from "prosemirror-model"
|
|
2
2
|
import {Change} from "./change"
|
|
3
3
|
|
|
4
4
|
/// A token encoder can be passed when creating a `ChangeSet` in order
|
|
@@ -23,16 +23,24 @@ export interface TokenEncoder<T> {
|
|
|
23
23
|
compareTokens(a: T, b: T): boolean
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
function typeID(type: NodeType) {
|
|
27
|
+
let cache: Record<string, number> = type.schema.cached.changeSetIDs || (type.schema.cached.changeSetIDs = Object.create(null))
|
|
28
|
+
let id = cache[type.name]
|
|
29
|
+
if (id == null) cache[type.name] = id = Object.keys(type.schema.nodes).indexOf(type.name) + 1
|
|
30
|
+
return id
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// The default token encoder, which encodes node open tokens are
|
|
34
|
+
// encoded as strings holding the node name, characters as their
|
|
35
|
+
// character code, and node close tokens as negative numbers.
|
|
26
36
|
export const DefaultEncoder: TokenEncoder<number | string> = {
|
|
27
37
|
encodeCharacter: char => char,
|
|
28
38
|
encodeNodeStart: node => node.type.name,
|
|
29
|
-
encodeNodeEnd:
|
|
39
|
+
encodeNodeEnd: node => -typeID(node.type),
|
|
30
40
|
compareTokens: (a, b) => a === b
|
|
31
41
|
}
|
|
32
42
|
|
|
33
|
-
// Convert the given range of a fragment to tokens
|
|
34
|
-
// tokens are encoded as strings holding the node name, characters as
|
|
35
|
-
// their character code, and node close tokens as -1.
|
|
43
|
+
// Convert the given range of a fragment to tokens.
|
|
36
44
|
function tokens<T>(frag: Fragment, encoder: TokenEncoder<T>, start: number, end: number, target: T[]) {
|
|
37
45
|
for (let i = 0, off = 0; i < frag.childCount; i++) {
|
|
38
46
|
let child = frag.child(i), endOff = off + child.nodeSize
|
package/test/test-diff.ts
CHANGED