@nerd-bible/wordgard 0.5.3-beta5 → 0.5.3-beta6

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/dist/editor.d.ts CHANGED
@@ -4,7 +4,7 @@ import { GardState, TextblockMap, Transaction, GardSelection } from 'wordgard/st
4
4
  import { PhraseSet } from 'wordgard/phrases';
5
5
  import { StyleModule, StyleSpec } from 'style-mod';
6
6
  import { Command, Menu } from 'wordgard/command';
7
- import { PointSet, RangeSet } from 'wordgard/set';
7
+ import { PointSet, Set, RangeSet } from 'wordgard/set';
8
8
 
9
9
  type MakeSelectionStyle = (wg: Wordgard, event: MouseEvent) => Wordgard.MouseSelectionStyle | null;
10
10
 
@@ -124,7 +124,7 @@ declare namespace Decoration {
124
124
  /**
125
125
  This function allows you to define a {@link Decoration.Tag.shape
126
126
  custom node shape} that depends on the editor state. It will
127
- automatically track what slots (see {@link
127
+ automatically track which state slots (see {@link
128
128
  GardState.Facet.compute}) you use, and make sure the nodes
129
129
  are redrawn when those change.
130
130
 
@@ -255,7 +255,7 @@ declare namespace Decoration {
255
255
  Create a {@link PointSet} from an array or source function of
256
256
  point decorations.
257
257
  */
258
- static set(source: PointSet.Source<Point>): Point.Set;
258
+ static set(source: Set.Source<Point>): Point.Set;
259
259
  /**
260
260
  The empty set of point decorations.
261
261
  */
@@ -301,7 +301,7 @@ declare namespace Decoration {
301
301
  Create a {@link RangeSet} from an array or source function of
302
302
  range decorations.
303
303
  */
304
- static set(source: RangeSet.Source<Range>): Range.Set;
304
+ static set(source: Set.Source<Range>): Range.Set;
305
305
  /**
306
306
  The empty set of range decorations.
307
307
  */
@@ -1326,6 +1326,35 @@ declare namespace KeyBinding {
1326
1326
  const defaultKeymap: readonly KeyBinding[];
1327
1327
  }
1328
1328
 
1329
+ type Config = {
1330
+ /**
1331
+ The type of plot to decorate.
1332
+ */
1333
+ type: Node$1.Query;
1334
+ /**
1335
+ A function that produces range decorations for a plot. `from`
1336
+ and `to` should be relative to the start of the plot's content,
1337
+ and be fall entirely within the plot.
1338
+ */
1339
+ ranges?: (node: Plot, range: (deco: Decoration.Range, from: number, to: number) => void) => void;
1340
+ /**
1341
+ A function that produces point decorations for a plot. `pos`
1342
+ should be relative to the start of the plot's content.
1343
+ */
1344
+ points?: (node: Plot, point: (deco: Decoration.Point, pos: number) => void) => void;
1345
+ /**
1346
+ An optional function that causes the decorations to be recreated
1347
+ on matching transaction, either for the entire document (`true`)
1348
+ or for any plot where the returned predicate returns `true`.
1349
+ */
1350
+ refresh?: (tr: Transaction) => boolean | ((plot: Plot) => boolean);
1351
+ };
1352
+ /**
1353
+ Create an extension that adds decorations to plots matching the
1354
+ given type.
1355
+ */
1356
+ declare function decoratePlots(config: Config): GardState.Extension;
1357
+
1329
1358
  type PanelConfig = {
1330
1359
  /**
1331
1360
  By default, panels will be placed inside the editor's DOM
@@ -1832,4 +1861,4 @@ being dragged over the editor.
1832
1861
  */
1833
1862
  declare function dropCursor(): GardState.Extension;
1834
1863
 
1835
- export { Decoration, Dialog, InputRule, KeyBinding, Panel, Tooltip, Widget, Wordgard, dropCursor, menuBar, placeholder };
1864
+ export { Decoration, Dialog, InputRule, KeyBinding, Panel, Tooltip, Widget, Wordgard, decoratePlots, dropCursor, menuBar, placeholder };
package/dist/editor.js CHANGED
@@ -475,7 +475,7 @@ class WrapperDecoration extends Decoration.Point {
475
475
  const nodeSelectionDeco = /*@__PURE__*/Decoration.Point.attributes({ class: "wg-selected-node" });
476
476
  function nodeSelection(state) {
477
477
  if (state.selection instanceof GardSelection.Node)
478
- return PointSet.create([[state.selection.from, nodeSelectionDeco]]);
478
+ return PointSet.create([[nodeSelectionDeco, state.selection.from]]);
479
479
  return PointSet.empty;
480
480
  }
481
481
  const none = [];
@@ -621,7 +621,7 @@ class SpanIterator {
621
621
  nextActive = i;
622
622
  }
623
623
  }
624
- let { pos: pointPos, side: pointSide } = points.value ? points : { pos: 1e9, side: 1 };
624
+ let [pointPos, pointSide] = points.value ? [points.from, points.value.side] : [1e9, 1];
625
625
  let nextPos = Math.min(startPos, endPos, pointPos);
626
626
  if (this.to == this.end && nextPos > this.to) {
627
627
  this.done = true;
@@ -635,7 +635,7 @@ class SpanIterator {
635
635
  else if (pointPos == nextPos && (startPos > pointPos || pointSide < 0) && (endPos > pointPos || pointSide < 0)) {
636
636
  this.point = this.points.value;
637
637
  this.pointSource = this.points.set;
638
- this.from = this.to = this.points.pos;
638
+ this.from = this.to = this.points.from;
639
639
  this.points.next();
640
640
  break;
641
641
  }
@@ -5365,6 +5365,86 @@ class PluginInstance {
5365
5365
  }
5366
5366
  }
5367
5367
 
5368
+ function offset(add, offset) {
5369
+ return (v, from, to) => add(v, from + offset, to == null ? undefined : to + offset);
5370
+ }
5371
+ function init(type, create, source, doc) {
5372
+ return create(add => {
5373
+ doc.iterate((node, pos) => {
5374
+ if (node.isPlot && doc.schema.matchNode(node.type, type))
5375
+ source(node, pos + 1, add);
5376
+ });
5377
+ });
5378
+ }
5379
+ function refreshByPred(type, source, doc, deco, pred) {
5380
+ let recreate = [];
5381
+ doc.iterate((node, pos) => {
5382
+ if (doc.schema.matchNode(node.type, type) && pred(node))
5383
+ recreate.push({
5384
+ from: pos, to: pos + node.length,
5385
+ add: add => source(node, pos + 1, add)
5386
+ });
5387
+ });
5388
+ return recreate.length ? deco.modify({ replace: recreate }) : deco;
5389
+ }
5390
+ function update(config, create, source, deco, tr) {
5391
+ let doc = tr.newDoc;
5392
+ let refresh = config.refresh && config.refresh(tr);
5393
+ if (refresh === true)
5394
+ return init(config.type, create, source, doc);
5395
+ if (refresh)
5396
+ deco = refreshByPred(config.type, source, tr.startState.doc, deco, refresh);
5397
+ if (!tr.docChanged && !refresh)
5398
+ return deco;
5399
+ let recreate = [];
5400
+ let clear = [];
5401
+ tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
5402
+ let covered = false;
5403
+ doc.iterate(fromB, toB, (node, pos) => {
5404
+ if (doc.schema.matchNode(node.type, config.type)) {
5405
+ recreate.push({
5406
+ from: pos, to: pos + node.length,
5407
+ add: add => source(node, pos + 1, add)
5408
+ });
5409
+ if (pos < toB && pos + node.length > toB)
5410
+ covered = true;
5411
+ return false;
5412
+ }
5413
+ });
5414
+ if (!covered) {
5415
+ let end = tr.startState.doc.resolve(toA);
5416
+ let open = end.matchingParent(p => doc.schema.matchNode(p.type, config.type));
5417
+ if (open && open.before >= fromA)
5418
+ clear.push({ from: open.before, to: open.after });
5419
+ }
5420
+ });
5421
+ if (clear.length)
5422
+ deco = deco.modify({ replace: clear });
5423
+ deco = deco.map(tr.changes, recreate);
5424
+ return deco;
5425
+ }
5426
+ function decoratePlots(config) {
5427
+ let result = [];
5428
+ let { type, points, ranges } = config;
5429
+ if (points) {
5430
+ let source = (plot, start, add) => points(plot, offset(add, start));
5431
+ let field = GardState.Field.define({
5432
+ create(state) { return init(type, PointSet.create, source, state.doc); },
5433
+ update(value, tr) { return update(config, PointSet.create, source, value, tr); }
5434
+ });
5435
+ result.push(field, Decoration.Point.source.of(s => s.field(field)));
5436
+ }
5437
+ if (ranges) {
5438
+ let source = (plot, start, add) => ranges(plot, offset(add, start));
5439
+ let field = GardState.Field.define({
5440
+ create(state) { return init(type, RangeSet.create, source, state.doc); },
5441
+ update(value, tr) { return update(config, RangeSet.create, source, value, tr); }
5442
+ });
5443
+ result.push(field, Decoration.Range.source.of(s => s.field(field)));
5444
+ }
5445
+ return result;
5446
+ }
5447
+
5368
5448
  const panelConfig = /*@__PURE__*/GardState.Facet.define({
5369
5449
  combine(configs) {
5370
5450
  let topContainer, bottomContainer;
@@ -7020,7 +7100,7 @@ function showPlaceholder(state) {
7020
7100
  let shape = state.facet(placeholderShape);
7021
7101
  if (!shape.length)
7022
7102
  return Decoration.Point.none;
7023
- return Decoration.Point.set([[pos, Decoration.Point.widget(placeholderWidget.of(shape[0]), { side: 1 })]]);
7103
+ return Decoration.Point.set([[Decoration.Point.widget(placeholderWidget.of(shape[0]), { side: 1 }), pos]]);
7024
7104
  }
7025
7105
  const placeholderField = /*@__PURE__*/GardState.Field.define({
7026
7106
  create(state) {
@@ -7124,4 +7204,4 @@ function dropCursor() {
7124
7204
  return [dropCursorPos, drawDropCursor];
7125
7205
  }
7126
7206
 
7127
- export { Decoration, Dialog, InputRule, KeyBinding, Panel, Tooltip, Widget, Wordgard, dropCursor, menuBar, placeholder };
7207
+ export { Decoration, Dialog, InputRule, KeyBinding, Panel, Tooltip, Widget, Wordgard, decoratePlots, dropCursor, menuBar, placeholder };
package/dist/schema.js CHANGED
@@ -834,9 +834,9 @@ const resizeState = /*@__PURE__*/GardState.Field.define({
834
834
  let { target, resizing } = e.value;
835
835
  if (target < 0)
836
836
  return { target: -1, resizing: -1, deco: Decoration.Point.none };
837
- let deco = [[target, resizeWrapper]];
837
+ let deco = [[resizeWrapper, target]];
838
838
  if (resizing > -1)
839
- deco.push([target, Decoration.Point.attributes({ style: `width: ${resizing}px` }, { target: "img" })]);
839
+ deco.push([Decoration.Point.attributes({ style: `width: ${resizing}px` }, { target: "img" }), target]);
840
840
  return { target, resizing, deco: Decoration.Point.set(deco) };
841
841
  }
842
842
  }
package/dist/set.d.ts CHANGED
@@ -1,62 +1,139 @@
1
1
  import { ChangeSet } from 'wordgard/doc';
2
2
 
3
3
  /**
4
- Data structure that stores sets of ranges, for use with {@link
5
- Decoration.Range range decorations} or other data types
6
- implementing {@link RangeSet.Value}.
4
+ The interface shared between {@link RangeSet} and {@link
5
+ PointSet}.
7
6
  */
8
- declare class RangeSet<T extends RangeSet.Value> {
9
- private constructor();
7
+ declare abstract class Set<T> {
10
8
  /**
11
- Create a range set from an iterable of `[from, to, value]`
12
- tuples, or a function that calls its argument for every range to
13
- add.
9
+ The number of values in this set.
14
10
  */
15
- static create<T extends RangeSet.Value>(source: RangeSet.Source<T>): RangeSet<T>;
11
+ abstract length: number;
16
12
  /**
17
- The number of ranges stored in this set.
13
+ Returns `true` when this set is empty.
18
14
  */
19
- get length(): number;
15
+ abstract empty: boolean;
20
16
  /**
21
- Returns true when this set is empty.
17
+ Create a cursor over this point set, starting at the given
18
+ position and side.
22
19
  */
23
- get empty(): boolean;
20
+ abstract cursor(from?: number): Set.Cursor<T>;
24
21
  /**
25
- Create a cursor over this set, starting at the given position.
22
+ Adjust this set's positions for a set of document changes.
23
+ Returns a new set with the adjusted positions. Will delete
24
+ values when the content around them was deleted. Optionally
25
+ accepts an ordered sequence of replacements, whose positions
26
+ should refer to the post-change document.
26
27
  */
27
- cursor(from?: number): RangeSet.Cursor<T>;
28
+ abstract map(map: ChangeSet, replace?: readonly Set.Replacement<T>[]): this;
28
29
  /**
29
- Create a cursor over a collection of range sets.
30
+ Create an updated copy of this set.
30
31
  */
31
- static cursor<T extends RangeSet.Value>(sets: readonly RangeSet<T>[], from?: number): RangeSet.Cursor<T>;
32
+ abstract modify(spec: {
33
+ /**
34
+ If given, replace all values in these ranges.
35
+ */
36
+ replace?: readonly Set.Replacement<T>[];
37
+ /**
38
+ Add values from this source.
39
+ */
40
+ add?: Set.Source<T>;
41
+ /**
42
+ Optionally filter out any value where this predicate returns
43
+ false.
44
+ */
45
+ filter?: (value: T, from: number, to: number) => boolean;
46
+ }): this;
47
+ }
48
+ declare namespace Set {
32
49
  /**
33
- Adjust the positions of the ranges for the given change set.
34
- Returns a set with the updated ranges. Optionally takes an array
35
- of replacement ranges. Any ranges overlapping such a replacement
36
- will be dropped, and new ranges provided by their `add`
37
- properties will be added to the new set.
50
+ A cursor over a point or range set.
38
51
  */
39
- map(map: ChangeSet, replace?: readonly RangeSet.Replacement<T>[]): RangeSet<T>;
40
- private mapInner;
52
+ interface Cursor<T> {
53
+ /**
54
+ The value of the current range or point, or `null` when there
55
+ are no more values.
56
+ */
57
+ value: T | null;
58
+ /**
59
+ The start position of the current range or point.
60
+ */
61
+ from: number;
62
+ /**
63
+ The end position of the current range. Will be equal to `from`
64
+ for points.
65
+ */
66
+ to: number;
67
+ /**
68
+ Move the cursor to a given position.
69
+ */
70
+ goto(pos: number, side?: number): void;
71
+ /**
72
+ Continue to the next value, if any.
73
+ */
74
+ next(): void;
75
+ /**
76
+ The set object that the current value points at, if any.
77
+ */
78
+ set: any;
79
+ }
41
80
  /**
42
- Modify this set.
81
+ A source, used to create or extend a set, is either
82
+ an array of `[value, pos, pos?]` tuples, or a function that calls its
83
+ argument to add a value.
84
+
85
+ For ranges, `to` must be given, and ranges must be provided
86
+ ordered by start position. For points, `to` must be omitted or
87
+ be the same as `from`, and the points must be ordered by
88
+ position and {@link PointSet.Value.side side}.
43
89
  */
44
- modify(spec: {
90
+ type Source<T> = Iterable<[T, number, number?]> | ((add: (value: T, pos: number, to?: number) => void) => void);
91
+ /**
92
+ Represents a replaced section in a set.
93
+ */
94
+ type Replacement<T> = {
45
95
  /**
46
- Drop any ranges inside the given replacement ranges,
47
- optionally add new ranges provided by their `add` property.
96
+ The start of the replacement.
48
97
  */
49
- replace?: readonly RangeSet.Replacement<T>[];
98
+ from: number;
50
99
  /**
51
- Add new ranges to the set.
100
+ The end of the replaced range.
52
101
  */
53
- add?: RangeSet.Source<T>;
102
+ to: number;
54
103
  /**
55
- Drop any range for which this predicate function returns
56
- `false`.
104
+ An optional source of points to to this section.
57
105
  */
58
- filter?: (from: number, to: number, value: T) => boolean;
59
- }): RangeSet<T>;
106
+ add?: Source<T>;
107
+ };
108
+ }
109
+
110
+ /**
111
+ Data structure that stores sets of ranges, for use with {@link
112
+ Decoration.Range range decorations} or other data types
113
+ implementing {@link RangeSet.Value}.
114
+ */
115
+ declare class RangeSet<T extends RangeSet.Value> extends Set<T> {
116
+ private constructor();
117
+ /**
118
+ Create a range set from an iterable of `[from, to, value]`
119
+ tuples, or a function that calls its argument for every range to
120
+ add.
121
+ */
122
+ static create<T extends RangeSet.Value>(source: Set.Source<T>): RangeSet<T>;
123
+ get length(): number;
124
+ get empty(): boolean;
125
+ cursor(from?: number): Set.Cursor<T>;
126
+ /**
127
+ Create a cursor over a collection of range sets.
128
+ */
129
+ static cursor<T extends RangeSet.Value>(sets: readonly RangeSet<T>[], from?: number): Set.Cursor<T>;
130
+ map(map: ChangeSet, replace?: readonly Set.Replacement<T>[]): this;
131
+ private mapInner;
132
+ modify(spec: {
133
+ replace?: readonly Set.Replacement<T>[];
134
+ add?: Set.Source<T>;
135
+ filter?: (value: T, from: number, to: number) => boolean;
136
+ }): this;
60
137
  private modifyInner;
61
138
  /**
62
139
  Compare a section of this set with a section of the same length
@@ -88,57 +165,6 @@ declare namespace RangeSet {
88
165
  */
89
166
  eq(other: Value): boolean;
90
167
  }
91
- /**
92
- A range source, used to construct or extend a range set, must
93
- either be an array of `[from, to, value]` tuples, or a function
94
- that calls its argument for each range to add. Ranges must be
95
- provided ordered by their `from` position.
96
- */
97
- type Source<T extends Value> = Iterable<[number, number, T]> | ((add: (from: number, to: number, value: T) => void) => void);
98
- /**
99
- Represents a replaced section in a range set.
100
- */
101
- type Replacement<T extends Value> = {
102
- /**
103
- The start of the section.
104
- */
105
- from: number;
106
- /**
107
- The end of the section.
108
- */
109
- to: number;
110
- /**
111
- An optional collection of ranges to replace the section with.
112
- Must fall within `from` and `to`.
113
- */
114
- add?: Source<T>;
115
- };
116
- /**
117
- A cursor over a range set.
118
- */
119
- interface Cursor<T extends Value> {
120
- /**
121
- The current range's value, or `null` if the end of the set has
122
- been reached.
123
- */
124
- value: T | null;
125
- /**
126
- The start position of the current range.
127
- */
128
- from: number;
129
- /**
130
- The end position of the current range.
131
- */
132
- to: number;
133
- /**
134
- Move the cursor to a new position.
135
- */
136
- goto(pos: number): void;
137
- /**
138
- Move to the next range, if any.
139
- */
140
- next(): void;
141
- }
142
168
  }
143
169
 
144
170
  /**
@@ -147,31 +173,25 @@ across document changes. Mostly used for {@link Decoration.Point
147
173
  point decorations}, but can also track your own types, if you make
148
174
  sure they implement the {@link PointSet.Value} interface.
149
175
  */
150
- declare class PointSet<T extends PointSet.Value> {
176
+ declare class PointSet<T extends PointSet.Value> implements Set<T> {
151
177
  private constructor();
152
178
  /**
153
179
  Create a point set from an iterable of `[position, value]`
154
180
  tuples, or a function that calls its argument for every point to
155
181
  add.
156
182
  */
157
- static create<T extends PointSet.Value>(source: PointSet.Source<T>): PointSet<T>;
158
- /**
159
- The number of points in this set.
160
- */
183
+ static create<T extends PointSet.Value>(source: Set.Source<T>): PointSet<T>;
161
184
  get length(): number;
162
- /**
163
- Returns `true` when this set is empty.
164
- */
165
185
  get empty(): boolean;
166
186
  /**
167
187
  Create a cursor over this point set, starting at the given
168
188
  position and side.
169
189
  */
170
- cursor(from?: number, side?: number): PointSet.Cursor<T>;
190
+ cursor(from?: number, side?: number): Set.Cursor<T>;
171
191
  /**
172
192
  Create a cursor over a collection of point sets.
173
193
  */
174
- static cursor<T extends PointSet.Value>(sets: readonly PointSet<T>[], from?: number, side?: number): PointSet.Cursor<T>;
194
+ static cursor<T extends PointSet.Value>(sets: readonly PointSet<T>[], from?: number, side?: number): Set.Cursor<T>;
175
195
  /**
176
196
  Get the value at the given position, if any. If there's multiple
177
197
  values at that position, the one with the lowest side is
@@ -184,26 +204,13 @@ declare class PointSet<T extends PointSet.Value> {
184
204
  around them was deleted. Optionally accepts an ordered sequence
185
205
  of replacements.
186
206
  */
187
- map(map: ChangeSet, replace?: readonly PointSet.Replacement<T>[]): PointSet<T>;
207
+ map(map: ChangeSet, replace?: readonly Set.Replacement<T>[]): this;
188
208
  private mapInner;
189
- /**
190
- Create an updated copy of this set.
191
- */
192
209
  modify(spec: {
193
- /**
194
- If given, replace all points in these ranges.
195
- */
196
- replace?: readonly PointSet.Replacement<T>[];
197
- /**
198
- Add the points from this source.
199
- */
200
- add?: PointSet.Source<T>;
201
- /**
202
- Optionally filter out any point where this predicate returns
203
- false.
204
- */
205
- filter?: (pos: number, value: T) => boolean;
206
- }): PointSet<T>;
210
+ replace?: readonly Set.Replacement<T>[];
211
+ add?: Set.Source<T>;
212
+ filter?: (value: T, from: number, to: number) => boolean;
213
+ }): this;
207
214
  private modifyInner;
208
215
  /**
209
216
  Compare a range in this set with a range in another set. Call
@@ -239,60 +246,6 @@ declare namespace PointSet {
239
246
  */
240
247
  eq(other: Value): boolean;
241
248
  }
242
- /**
243
- A point source, used to create or extend a point set, is either
244
- an array of `[pos, value]` tuples, or a function that calls its
245
- argument to add a point. Point sources must provide their points
246
- ordered by position and {@link PointSet.Value.side side}.
247
- */
248
- type Source<T extends Value> = Iterable<[number, T]> | ((add: (pos: number, value: T) => void) => void);
249
- /**
250
- Represents a replaced section in a point set.
251
- */
252
- type Replacement<T extends Value> = {
253
- /**
254
- The start of the replacement.
255
- */
256
- from: number;
257
- /**
258
- The end of the replaced range.
259
- */
260
- to: number;
261
- /**
262
- An optional source of points to to this section.
263
- */
264
- add?: PointSet.Source<T>;
265
- };
266
- /**
267
- A cursor over a point set.
268
- */
269
- interface Cursor<T extends Value> {
270
- /**
271
- The value of the current point, or `null` when there are no
272
- more points.
273
- */
274
- value: T | null;
275
- /**
276
- The position of the current point.
277
- */
278
- pos: number;
279
- /**
280
- The side value of the current point.
281
- */
282
- side: number;
283
- /**
284
- Move the cursor to a given position and side.
285
- */
286
- goto(pos: number, side: number): void;
287
- /**
288
- Continue to the next point, if any.
289
- */
290
- next(): void;
291
- /**
292
- The set object that the current point belongs to.
293
- */
294
- set: PointSet<T>;
295
- }
296
249
  }
297
250
 
298
251
  /**
@@ -302,4 +255,4 @@ such element exists) @hidden
302
255
  */
303
256
  declare function findAbove(array: readonly number[], start: number, n: number): number;
304
257
 
305
- export { PointSet, RangeSet, findAbove };
258
+ export { PointSet, RangeSet, Set, findAbove };
package/dist/set.js CHANGED
@@ -1,5 +1,8 @@
1
1
  import { ChangeSet } from 'wordgard/doc';
2
2
 
3
+ class Set {
4
+ }
5
+
3
6
  function findAbove(array, start, n) {
4
7
  let from = start, to = array.length;
5
8
  for (;;) {
@@ -12,6 +15,23 @@ function findAbove(array, start, n) {
12
15
  from = mid + 1;
13
16
  }
14
17
  }
18
+ function addReplacements(changes, replace) {
19
+ let add = [], at = 0, len = changes.newLength;
20
+ for (let repl of replace) {
21
+ if (repl.from < at)
22
+ throw new Error("Replacing ranges must be ordered and non-overlapping");
23
+ if (repl.to > len)
24
+ throw new Error("Replacing range out of bounds");
25
+ if (repl.from > at)
26
+ add.push(repl.from - at, -1);
27
+ add.push(repl.to - repl.from, repl.to - repl.from);
28
+ at = repl.to;
29
+ }
30
+ if (len > at)
31
+ add.push(len - at, -1);
32
+ return ChangeSet.composeSections(changes.sections, add);
33
+ }
34
+
15
35
  function heapBubble(heap, index, cmp) {
16
36
  for (let cur = heap[index];;) {
17
37
  let childIndex = (index << 1) + 1;
@@ -47,21 +67,50 @@ function heapPop(heap, cmp) {
47
67
  heapBubble(heap, 0, cmp);
48
68
  }
49
69
  }
50
- function addReplacements(changes, replace) {
51
- let add = [], at = 0, len = changes.newLength;
52
- for (let repl of replace) {
53
- if (repl.from < at)
54
- throw new Error("Replacing ranges must be ordered and non-overlapping");
55
- if (repl.to > len)
56
- throw new Error("Replacing range out of bounds");
57
- if (repl.from > at)
58
- add.push(repl.from - at, -1);
59
- add.push(repl.to - repl.from, repl.to - repl.from);
60
- at = repl.to;
70
+ class HeapCursor {
71
+ cmp;
72
+ cursors;
73
+ heap = [];
74
+ constructor(cmp, cursors) {
75
+ this.cmp = cmp;
76
+ this.cursors = cursors;
77
+ for (let cur of cursors)
78
+ if (cur.value) {
79
+ this.heap.push(cur);
80
+ heapSink(this.heap, this.heap.length - 1, cmp);
81
+ }
82
+ this.fill();
61
83
  }
62
- if (len > at)
63
- add.push(len - at, -1);
64
- return ChangeSet.composeSections(changes.sections, add);
84
+ fill() {
85
+ if (this.heap.length) {
86
+ ({ from: this.from, to: this.to, value: this.value } = this.heap[0]);
87
+ }
88
+ else {
89
+ this.from = this.to = 1e9;
90
+ this.value = null;
91
+ }
92
+ }
93
+ goto(pos, side) {
94
+ this.heap = [];
95
+ for (let cur of this.cursors) {
96
+ cur.goto(pos, side);
97
+ if (cur.value) {
98
+ this.heap.push(cur);
99
+ heapSink(this.heap, this.heap.length - 1, this.cmp);
100
+ }
101
+ }
102
+ }
103
+ next() {
104
+ if (this.heap.length) {
105
+ this.heap[0].next();
106
+ if (this.heap[0].value)
107
+ heapBubble(this.heap, 0, this.cmp);
108
+ else
109
+ heapPop(this.heap, this.cmp);
110
+ this.fill();
111
+ }
112
+ }
113
+ get set() { return this.heap.length ? this.heap[0].set : null; }
65
114
  }
66
115
 
67
116
  let Chunk$1 = class Chunk {
@@ -105,18 +154,18 @@ let SetBuilder$1 = class SetBuilder {
105
154
  source = add => { for (let [from, to, value] of array)
106
155
  add(from, to, value); };
107
156
  }
108
- source((from, to, value) => {
157
+ source((value, from, to = from) => {
109
158
  if (pre)
110
159
  pre(from, to);
111
- this.addRange(from, to, value);
160
+ this.addRange(value, from, to);
112
161
  });
113
162
  }
114
- addRange(from, to, value) {
163
+ addRange(value, from, to) {
115
164
  if (from >= to)
116
165
  throw new Error("Ranges cannot be empty");
117
- (this.lastTo <= from ? this : this.next).addInner(from, to, value);
166
+ (this.lastTo <= from ? this : this.next).addInner(value, from, to);
118
167
  }
119
- addInner(from, to, value) {
168
+ addInner(value, from, to) {
120
169
  let chunk;
121
170
  if (this.chunks.length) {
122
171
  chunk = this.chunks[this.chunks.length - 1];
@@ -139,12 +188,13 @@ let SetBuilder$1 = class SetBuilder {
139
188
  return RangeSet.new(this.chunks, next);
140
189
  }
141
190
  };
142
- class RangeSet {
191
+ class RangeSet extends Set {
143
192
  chunks;
144
193
  next;
145
194
  constructor(
146
195
  chunks,
147
196
  next) {
197
+ super();
148
198
  this.chunks = chunks;
149
199
  this.next = next;
150
200
  }
@@ -167,20 +217,20 @@ class RangeSet {
167
217
  }
168
218
  cursor(from = 0) {
169
219
  if (!this.next)
170
- return new LayerCursor(this.chunks, from);
220
+ return new LayerCursor(this, this.chunks, from);
171
221
  let cursors = [];
172
222
  for (let layer = this; layer; layer = layer.next)
173
- cursors.push(new LayerCursor(layer.chunks, from));
174
- return new HeapCursor$1(cursors);
223
+ cursors.push(new LayerCursor(this, layer.chunks, from));
224
+ return new HeapCursor(cmpCursor$1, cursors);
175
225
  }
176
226
  static cursor(sets, from = 0) {
177
227
  let cursors = [];
178
228
  for (let set of sets)
179
229
  if (!set.empty) {
180
230
  for (let layer = set; layer; layer = layer.next)
181
- cursors.push(new LayerCursor(layer.chunks, from));
231
+ cursors.push(new LayerCursor(set, layer.chunks, from));
182
232
  }
183
- return cursors.length == 0 ? RangeSet.empty.cursor() : cursors.length == 1 ? cursors[0] : new HeapCursor$1(cursors);
233
+ return cursors.length == 0 ? RangeSet.empty.cursor() : cursors.length == 1 ? cursors[0] : new HeapCursor(cmpCursor$1, cursors);
184
234
  }
185
235
  map(map, replace = []) {
186
236
  let { sections } = map;
@@ -191,7 +241,7 @@ class RangeSet {
191
241
  return this.mapInner(sections, map, replace);
192
242
  }
193
243
  mapInner(sections, map, replace) {
194
- let cursor = new LayerCursor(this.chunks, 0);
244
+ let cursor = new LayerCursor(this, this.chunks, 0);
195
245
  let replI = 0, posA = 0, posB = 0;
196
246
  let build = new SetBuilder$1();
197
247
  for (let i = 0; i < sections.length;) {
@@ -209,7 +259,7 @@ class RangeSet {
209
259
  cursor.next(true);
210
260
  }
211
261
  else if (cursor.to < upto) {
212
- build.addRange(cursor.from + off, cursor.to + off, cursor.value);
262
+ build.addRange(cursor.value, cursor.from + off, cursor.to + off);
213
263
  cursor.next();
214
264
  }
215
265
  else {
@@ -245,7 +295,7 @@ class RangeSet {
245
295
  }
246
296
  modifyInner(add, filter) {
247
297
  let build = new SetBuilder$1();
248
- let cursor = new LayerCursor(this.chunks, 0);
298
+ let cursor = new LayerCursor(this, this.chunks, 0);
249
299
  let advance = (pos) => {
250
300
  for (;;) {
251
301
  let { cur } = cursor;
@@ -259,8 +309,8 @@ class RangeSet {
259
309
  break;
260
310
  }
261
311
  else {
262
- if (!filter || filter(cursor.from, cursor.to, cursor.value))
263
- build.addRange(cursor.from, cursor.to, cursor.value);
312
+ if (!filter || filter(cursor.value, cursor.from, cursor.to))
313
+ build.addRange(cursor.value, cursor.from, cursor.to);
264
314
  cursor.next();
265
315
  }
266
316
  }
@@ -273,7 +323,7 @@ class RangeSet {
273
323
  compareRange(fromA, b, fromB, len, change) {
274
324
  if (this == b)
275
325
  return;
276
- let curA = new LayerCursor(this.chunks, fromA), curB = new LayerCursor(b.chunks, fromB), off = fromB - fromA;
326
+ let curA = new LayerCursor(this, this.chunks, fromA), curB = new LayerCursor(b, b.chunks, fromB), off = fromB - fromA;
277
327
  let end = fromB + len, startA = -1, endA = -1, startB = -1, endB = -1;
278
328
  for (;;) {
279
329
  if (startA >= endA)
@@ -323,16 +373,18 @@ function copyMappedUpto$1(cursor, upto, map, build, replace, replI) {
323
373
  filtered = true;
324
374
  }
325
375
  if (!filtered)
326
- build.addRange(from, to, value);
376
+ build.addRange(value, from, to);
327
377
  cursor.next();
328
378
  }
329
379
  }
330
380
  class LayerCursor {
381
+ set;
331
382
  chunks;
332
383
  chunkI = 0;
333
384
  i = 0;
334
385
  from = 0;
335
- constructor(chunks, start) {
386
+ constructor(set, chunks, start) {
387
+ this.set = set;
336
388
  this.chunks = chunks;
337
389
  this.goto(start);
338
390
  }
@@ -386,48 +438,6 @@ class LayerCursor {
386
438
  let cmpCursor$1 = (a, b) => {
387
439
  return (a.from - b.from) || (a.value.inclusiveStart ? (b.value.inclusiveStart ? 0 : 1) : -1) || (a.to - b.to);
388
440
  };
389
- let HeapCursor$1 = class HeapCursor {
390
- cursors;
391
- heap = [];
392
- constructor(cursors) {
393
- this.cursors = cursors;
394
- for (let cur of cursors)
395
- if (cur.value) {
396
- this.heap.push(cur);
397
- heapSink(this.heap, this.heap.length - 1, cmpCursor$1);
398
- }
399
- this.fill();
400
- }
401
- fill() {
402
- if (this.heap.length) {
403
- ({ from: this.from, to: this.to, value: this.value } = this.heap[0]);
404
- }
405
- else {
406
- this.from = this.to = 1e9;
407
- this.value = null;
408
- }
409
- }
410
- goto(pos) {
411
- this.heap = [];
412
- for (let cur of this.cursors) {
413
- cur.goto(pos);
414
- if (cur.value) {
415
- this.heap.push(cur);
416
- heapSink(this.heap, this.heap.length - 1, cmpCursor$1);
417
- }
418
- }
419
- }
420
- next() {
421
- if (this.heap.length) {
422
- this.heap[0].next();
423
- if (this.heap[0].value)
424
- heapBubble(this.heap, 0, cmpCursor$1);
425
- else
426
- heapPop(this.heap, cmpCursor$1);
427
- this.fill();
428
- }
429
- }
430
- };
431
441
 
432
442
  class Chunk {
433
443
  start;
@@ -463,16 +473,18 @@ class SetBuilder {
463
473
  add(source, pre) {
464
474
  if (typeof source != "function") {
465
475
  let array = source;
466
- source = add => { for (let [pos, value] of array)
467
- add(pos, value); };
476
+ source = add => { for (let [value, from, to] of array)
477
+ add(value, from, to); };
468
478
  }
469
- source((pos, value) => {
479
+ source((value, from, to) => {
480
+ if (to != null && from != to)
481
+ throw new Error("Points cannot cover content");
470
482
  if (pre)
471
- pre(pos, value);
472
- this.addPoint(pos, value);
483
+ pre(value, from);
484
+ this.addPoint(value, from);
473
485
  });
474
486
  }
475
- addPoint(pos, value) {
487
+ addPoint(value, pos) {
476
488
  let chunk;
477
489
  if (this.chunks.length) {
478
490
  chunk = this.chunks[this.chunks.length - 1];
@@ -521,7 +533,7 @@ class PointSet {
521
533
  static new(chunks) { return new PointSet(chunks); }
522
534
  static create(source) {
523
535
  let build = new SetBuilder();
524
- build.add(source, (from, value) => {
536
+ build.add(source, (value, from) => {
525
537
  if ((from - build.lastPos || value.side - build.lastSide) < 0)
526
538
  throw new Error("Points must be added in order");
527
539
  });
@@ -541,7 +553,7 @@ class PointSet {
541
553
  for (let set of sets)
542
554
  if (!set.empty)
543
555
  cursors.push(set.cursor(from, side));
544
- return cursors.length == 0 ? PointSet.empty.cursor() : cursors.length == 1 ? cursors[0] : new HeapCursor(cursors);
556
+ return cursors.length == 0 ? PointSet.empty.cursor() : cursors.length == 1 ? cursors[0] : new HeapCursor(cmpCursor, cursors);
545
557
  }
546
558
  at(pos) {
547
559
  for (let chunk of this.chunks) {
@@ -581,8 +593,8 @@ class PointSet {
581
593
  build.addChunk(chunk.move(chunk.start + off));
582
594
  cursor.next(true);
583
595
  }
584
- else if (cursor.pos < upto) {
585
- build.addPoint(cursor.pos + off, cursor.value);
596
+ else if (cursor.from < upto) {
597
+ build.addPoint(cursor.value, cursor.from + off);
586
598
  cursor.next();
587
599
  }
588
600
  else {
@@ -619,7 +631,7 @@ class PointSet {
619
631
  modifyInner(add, filter) {
620
632
  let build = new SetBuilder();
621
633
  let cursor = new PointCursor(this, 0, -1e9);
622
- let advance = (pos) => {
634
+ let advance = (_, pos) => {
623
635
  for (;;) {
624
636
  let { cur } = cursor;
625
637
  if (!cur)
@@ -628,19 +640,19 @@ class PointSet {
628
640
  build.addChunk(cur);
629
641
  cursor.next(true);
630
642
  }
631
- else if (cursor.pos >= pos) {
643
+ else if (cursor.from >= pos) {
632
644
  break;
633
645
  }
634
646
  else {
635
- if (!filter || filter(cursor.pos, cursor.value))
636
- build.addPoint(cursor.pos, cursor.value);
647
+ if (!filter || filter(cursor.value, cursor.from, cursor.to))
648
+ build.addPoint(cursor.value, cursor.from);
637
649
  cursor.next();
638
650
  }
639
651
  }
640
652
  };
641
653
  if (add)
642
654
  build.add(add, advance);
643
- advance(1e9);
655
+ advance(null, 1e9);
644
656
  return build.finish();
645
657
  }
646
658
  compareRange(fromA, b, fromB, len, change) {
@@ -649,7 +661,7 @@ class PointSet {
649
661
  let curA = new PointCursor(this, fromA, -1e9), curB = new PointCursor(b, fromB, -1e9);
650
662
  let off = fromB - fromA, endB = fromB + len;
651
663
  for (;;) {
652
- let nextA = curA.value ? curA.pos + off : 1e9, nextB = curB.value ? curB.pos : 1e9;
664
+ let nextA = curA.value ? curA.from + off : 1e9, nextB = curB.value ? curB.from : 1e9;
653
665
  if (Math.min(nextA, nextB) > endB)
654
666
  break;
655
667
  let cmp = nextA - nextB || curA.side - curB.side;
@@ -673,9 +685,9 @@ class PointSet {
673
685
  static empty = /*@__PURE__*/(() => new PointSet([]))();
674
686
  }
675
687
  function copyMappedUpto(cursor, upto, map, build, replace, replI) {
676
- while (cursor.value && cursor.pos <= upto) {
688
+ while (cursor.value && cursor.from <= upto) {
677
689
  let value = cursor.value;
678
- let pos = map.mapPos(cursor.pos, value.side < 0 ? -1 : 1, value.trackMode);
690
+ let pos = map.mapPos(cursor.from, value.side < 0 ? -1 : 1, value.trackMode);
679
691
  if (pos != null) {
680
692
  let filtered = false;
681
693
  for (let i = replI; !filtered && i < replace.length && replace[i].from <= pos; i++) {
@@ -683,7 +695,7 @@ function copyMappedUpto(cursor, upto, map, build, replace, replI) {
683
695
  filtered = true;
684
696
  }
685
697
  if (!filtered)
686
- build.addPoint(pos, value);
698
+ build.addPoint(value, pos);
687
699
  }
688
700
  cursor.next();
689
701
  }
@@ -692,14 +704,15 @@ class PointCursor {
692
704
  set;
693
705
  chunkI = 0;
694
706
  i = 0;
695
- pos = -1;
707
+ from = -1;
696
708
  constructor(set, start, side) {
697
709
  this.set = set;
698
710
  this.goto(start, side);
699
711
  }
712
+ get to() { return this.from; }
700
713
  get side() { return this.value ? this.value.side : 1e9; }
701
714
  goto(pos, side) {
702
- let diff = pos - this.pos || side - this.side;
715
+ let diff = pos - this.from || side - this.side;
703
716
  if (diff < 0) {
704
717
  this.chunkI = this.i = 0;
705
718
  }
@@ -715,7 +728,7 @@ class PointCursor {
715
728
  }
716
729
  for (let first = true;;) {
717
730
  if (this.chunkI == this.set.chunks.length) {
718
- this.pos = 1e9;
731
+ this.from = 1e9;
719
732
  this.cur = this.value = null;
720
733
  break;
721
734
  }
@@ -733,7 +746,7 @@ class PointCursor {
733
746
  }
734
747
  else {
735
748
  this.cur = chunk;
736
- this.pos = chunk.pos[this.i] + chunk.start;
749
+ this.from = chunk.pos[this.i] + chunk.start;
737
750
  this.value = chunk.value[this.i];
738
751
  break;
739
752
  }
@@ -757,58 +770,12 @@ class PointCursor {
757
770
  cur = this.cur = this.set.chunks[this.chunkI];
758
771
  }
759
772
  }
760
- this.pos = cur.pos[this.i] + cur.start;
773
+ this.from = cur.pos[this.i] + cur.start;
761
774
  this.value = cur.value[this.i];
762
775
  }
763
776
  }
764
777
  function cmpCursor(a, b) {
765
- return a.pos - b.pos || a.value.side - b.value.side;
766
- }
767
- class HeapCursor {
768
- cursors;
769
- heap = [];
770
- constructor(cursors) {
771
- this.cursors = cursors;
772
- for (let cur of cursors)
773
- if (cur.value) {
774
- this.heap.push(cur);
775
- heapSink(this.heap, this.heap.length - 1, cmpCursor);
776
- }
777
- this.fill();
778
- }
779
- get side() {
780
- return this.value ? this.value.side : 1e9;
781
- }
782
- fill() {
783
- if (this.heap.length) {
784
- ({ pos: this.pos, value: this.value } = this.heap[0]);
785
- }
786
- else {
787
- this.pos = 1e9;
788
- this.value = null;
789
- }
790
- }
791
- goto(pos, side) {
792
- this.heap = [];
793
- for (let cur of this.cursors) {
794
- cur.goto(pos, side);
795
- if (cur.value) {
796
- this.heap.push(cur);
797
- heapSink(this.heap, this.heap.length - 1, cmpCursor);
798
- }
799
- }
800
- }
801
- next() {
802
- if (this.heap.length) {
803
- this.heap[0].next();
804
- if (this.heap[0].value)
805
- heapBubble(this.heap, 0, cmpCursor);
806
- else
807
- heapPop(this.heap, cmpCursor);
808
- this.fill();
809
- }
810
- }
811
- get set() { return this.heap.length ? this.heap[0].set : PointSet.empty; }
778
+ return a.from - b.from || a.value.side - b.value.side;
812
779
  }
813
780
 
814
- export { PointSet, RangeSet, findAbove };
781
+ export { PointSet, RangeSet, Set, findAbove };
package/dist/table.js CHANGED
@@ -237,7 +237,7 @@ const selectedCell = /*@__PURE__*/Decoration.Point.attributes({ class: "wg-selec
237
237
  function getCellDeco(state) {
238
238
  if (!(state.selection instanceof CellSelection))
239
239
  return Decoration.Point.none;
240
- return Decoration.Point.set(state.selection.ranges.map(({ from }) => [from - 1, selectedCell]));
240
+ return Decoration.Point.set(state.selection.ranges.map(({ from }) => [selectedCell, from - 1]));
241
241
  }
242
242
  const tableSelectionFilter = /*@__PURE__*/(() => GardState.prec.low(Transaction.extender.of(tr => {
243
243
  let normalized = CellSelection.normalize(tr.newSelection, tr.newDoc);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nerd-bible/wordgard",
3
- "version": "0.5.3-beta5",
3
+ "version": "0.5.3-beta6",
4
4
  "description": "Semantic rich text editor system",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",