@nerd-bible/wordgard 0.5.3-beta5 → 0.5.3-beta7
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 +34 -5
- package/dist/editor.js +153 -40
- package/dist/schema.js +2 -2
- package/dist/set.d.ts +122 -169
- package/dist/set.js +114 -147
- package/dist/table.js +1 -1
- package/package.json +1 -1
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
|
|
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:
|
|
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:
|
|
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
|
@@ -62,7 +62,7 @@ function separateChange(changes, fromB, toB) {
|
|
|
62
62
|
let lenI = 0, dLen = 0;
|
|
63
63
|
for (let posB = 0, done = false, i = 0; i < changes.length;) {
|
|
64
64
|
let len = changes[i++], ins = changes[i++], endB = posB + (ins < 0 ? len : ins);
|
|
65
|
-
if (fromB
|
|
65
|
+
if (fromB >= endB || toB <= posB) {
|
|
66
66
|
result.push(len, ins);
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
@@ -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
|
|
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
|
|
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.
|
|
638
|
+
this.from = this.to = this.points.from;
|
|
639
639
|
this.points.next();
|
|
640
640
|
break;
|
|
641
641
|
}
|
|
@@ -1529,6 +1529,8 @@ class DocTile extends CompositeTile {
|
|
|
1529
1529
|
changes = separated;
|
|
1530
1530
|
}
|
|
1531
1531
|
let builder = new ContentUpdate(state, this, wg, new DecoIterator(state, decoSet), wrapper);
|
|
1532
|
+
if (composition?.target && Tile.get(composition.target))
|
|
1533
|
+
builder.reused.set(Tile.get(composition.target), 2);
|
|
1532
1534
|
for (let i = 0, posB = 0, startCovered = false; i < changes.length;) {
|
|
1533
1535
|
let len = changes[i++], ins = changes[i++];
|
|
1534
1536
|
if (composition && posB == composition.fromB && ins >= 0) {
|
|
@@ -3631,6 +3633,7 @@ class InputState {
|
|
|
3631
3633
|
mouseSelection = null;
|
|
3632
3634
|
draggedContent = null;
|
|
3633
3635
|
notifiedFocused;
|
|
3636
|
+
suppressEvents = false;
|
|
3634
3637
|
pendingInputEvent = null;
|
|
3635
3638
|
domDoc;
|
|
3636
3639
|
_domMapping;
|
|
@@ -3646,6 +3649,8 @@ class InputState {
|
|
|
3646
3649
|
this._domMapping = ChangeSet.empty(this.domDoc.length);
|
|
3647
3650
|
}
|
|
3648
3651
|
handleEvent(event) {
|
|
3652
|
+
if (this.suppressEvents)
|
|
3653
|
+
return;
|
|
3649
3654
|
if (!eventBelongsToEditor(this.wg, event) || this.ignoreDuringComposition(event))
|
|
3650
3655
|
return;
|
|
3651
3656
|
if (event.type == "keydown" && this.keydown(event))
|
|
@@ -3797,8 +3802,11 @@ class InputState {
|
|
|
3797
3802
|
});
|
|
3798
3803
|
}
|
|
3799
3804
|
else if (type == "insertCompositionText") {
|
|
3800
|
-
let compositionStart =
|
|
3801
|
-
wg.inputState.composing
|
|
3805
|
+
let compositionStart = true;
|
|
3806
|
+
if (wg.inputState.composing) {
|
|
3807
|
+
compositionStart = !wg.inputState.composing.changes;
|
|
3808
|
+
wg.inputState.composing.changes++;
|
|
3809
|
+
}
|
|
3802
3810
|
let sel = wg.observer.selectionRange;
|
|
3803
3811
|
if (!sel.focusNode)
|
|
3804
3812
|
return false;
|
|
@@ -3856,6 +3864,57 @@ class InputState {
|
|
|
3856
3864
|
return !tileBefore ? before : !tileAfter ? after : prev == after ? after : before;
|
|
3857
3865
|
}
|
|
3858
3866
|
}
|
|
3867
|
+
getCompositionInfo(wg) {
|
|
3868
|
+
let wrap = this.wrappingComposition;
|
|
3869
|
+
if (wrap) {
|
|
3870
|
+
let sel = wg.state.selection.head;
|
|
3871
|
+
return {
|
|
3872
|
+
fromB: sel, toB: sel,
|
|
3873
|
+
text: "",
|
|
3874
|
+
target: null,
|
|
3875
|
+
wrapCursor: wrap
|
|
3876
|
+
};
|
|
3877
|
+
}
|
|
3878
|
+
let comp = this.composing;
|
|
3879
|
+
if (!comp || !(comp.target = this.findComposition(comp.target)))
|
|
3880
|
+
return null;
|
|
3881
|
+
let value = comp.target.nodeValue;
|
|
3882
|
+
let fromB = this.posAtDOM(comp.target, 0, 1), toB = fromB + value.length;
|
|
3883
|
+
let disrupted = false;
|
|
3884
|
+
this.domMapping.iterChanges((fA, tA, fB, tB) => {
|
|
3885
|
+
if (fB < toB && tB > fromB)
|
|
3886
|
+
disrupted = true;
|
|
3887
|
+
});
|
|
3888
|
+
return disrupted ? null : { fromB, toB, text: value, target: comp.target };
|
|
3889
|
+
}
|
|
3890
|
+
clearComposition() {
|
|
3891
|
+
let comp = this.composing;
|
|
3892
|
+
this.composing = null;
|
|
3893
|
+
this.compositionEndedAt = Date.now();
|
|
3894
|
+
if (!comp.target)
|
|
3895
|
+
return false;
|
|
3896
|
+
let pos = this.posAtDOM(comp.target, 0, 1);
|
|
3897
|
+
this.wg.observer.addDirtyRange(pos, pos + comp.target.nodeValue.length);
|
|
3898
|
+
return true;
|
|
3899
|
+
}
|
|
3900
|
+
abortComposition() {
|
|
3901
|
+
if (!this.composing || !this.wg.hasFocus)
|
|
3902
|
+
return;
|
|
3903
|
+
this.clearComposition();
|
|
3904
|
+
this.wg.win.setTimeout(() => {
|
|
3905
|
+
this.suppressEvents = true;
|
|
3906
|
+
try {
|
|
3907
|
+
getSelection(this.wg.root)?.collapse(document.body, 0);
|
|
3908
|
+
let dummy = this.wg.win.document.body.appendChild(document.createElement("input"));
|
|
3909
|
+
dummy.focus();
|
|
3910
|
+
dummy.remove();
|
|
3911
|
+
this.wg.focus();
|
|
3912
|
+
}
|
|
3913
|
+
finally {
|
|
3914
|
+
this.suppressEvents = false;
|
|
3915
|
+
}
|
|
3916
|
+
}, 0);
|
|
3917
|
+
}
|
|
3859
3918
|
recordTouch(e) {
|
|
3860
3919
|
this.lastTouchTime = Date.now();
|
|
3861
3920
|
this.lastTouchEvent = e;
|
|
@@ -4118,37 +4177,9 @@ function updateForFocusChange(wg) {
|
|
|
4118
4177
|
}
|
|
4119
4178
|
}, 10);
|
|
4120
4179
|
}
|
|
4121
|
-
function getCompositionInfo(wg) {
|
|
4122
|
-
let wrap = wg.inputState.wrappingComposition;
|
|
4123
|
-
if (wrap) {
|
|
4124
|
-
let sel = wg.state.selection.head;
|
|
4125
|
-
return {
|
|
4126
|
-
fromB: sel, toB: sel,
|
|
4127
|
-
text: "",
|
|
4128
|
-
target: null,
|
|
4129
|
-
wrapCursor: wrap
|
|
4130
|
-
};
|
|
4131
|
-
}
|
|
4132
|
-
let comp = wg.inputState.composing;
|
|
4133
|
-
if (!comp || !(comp.target = wg.inputState.findComposition(comp.target)))
|
|
4134
|
-
return null;
|
|
4135
|
-
let value = comp.target.nodeValue;
|
|
4136
|
-
let pos = wg.inputState.posAtDOM(comp.target, 0);
|
|
4137
|
-
return {
|
|
4138
|
-
fromB: pos, toB: pos + value.length,
|
|
4139
|
-
text: value,
|
|
4140
|
-
target: comp.target
|
|
4141
|
-
};
|
|
4142
|
-
}
|
|
4143
4180
|
function compositionEnd(wg) {
|
|
4144
|
-
|
|
4145
|
-
wg.inputState.composing = null;
|
|
4146
|
-
wg.inputState.compositionEndedAt = Date.now();
|
|
4147
|
-
if (comp && comp.target) {
|
|
4148
|
-
let pos = wg.inputState.posAtDOM(comp.target, 0);
|
|
4149
|
-
wg.observer.addDirtyRange(pos, pos + comp.target.nodeValue.length);
|
|
4181
|
+
if (wg.inputState.composing && wg.inputState.clearComposition())
|
|
4150
4182
|
wg.flush();
|
|
4151
|
-
}
|
|
4152
4183
|
}
|
|
4153
4184
|
function compositionUpdate(wg, event) {
|
|
4154
4185
|
if (!wg.inputState.composing) {
|
|
@@ -4789,8 +4820,8 @@ class Wordgard {
|
|
|
4789
4820
|
this.lastFlush = Date.now();
|
|
4790
4821
|
try {
|
|
4791
4822
|
let domChanges = this.observer.takeDirty();
|
|
4792
|
-
this.viewState.flush();
|
|
4793
4823
|
this.observer.ignore(() => this.runUpdate(update, domChanges));
|
|
4824
|
+
this.viewState.flush();
|
|
4794
4825
|
domChanges = null;
|
|
4795
4826
|
for (let i = 0;; i++) {
|
|
4796
4827
|
if (i > 5) {
|
|
@@ -4856,7 +4887,9 @@ class Wordgard {
|
|
|
4856
4887
|
scrollRectIntoView(this.scrollDOM, targetRect, assoc, target.spec.x, target.spec.y, Math.max(Math.min(target.spec.xMargin, offsetWidth), -offsetWidth), Math.max(Math.min(target.spec.yMargin, offsetHeight), -offsetHeight), this.state.textLTR);
|
|
4857
4888
|
}
|
|
4858
4889
|
runUpdate(update, domChanges) {
|
|
4859
|
-
let composition = this.composing ? getCompositionInfo(this) : null;
|
|
4890
|
+
let composition = this.composing ? this.inputState.getCompositionInfo(this) : null;
|
|
4891
|
+
if (this.composing && !composition)
|
|
4892
|
+
this.inputState.abortComposition();
|
|
4860
4893
|
let changes = domChanges ? addUpdated(update.changes.sections, domChanges) : update.changes.sections;
|
|
4861
4894
|
let prevDocTile = this.docTile;
|
|
4862
4895
|
if (!update.empty) {
|
|
@@ -5035,7 +5068,7 @@ class Wordgard {
|
|
|
5035
5068
|
if (this.connected)
|
|
5036
5069
|
this.observer.ignore(() => {
|
|
5037
5070
|
this.contentDOM.focus({ preventScroll: true });
|
|
5038
|
-
if (this.willFlush && this.flushing == 0)
|
|
5071
|
+
if (this.willFlush && this.flushing == 0 && this.viewState.pending.some(tr => tr.docChanged))
|
|
5039
5072
|
this.flush();
|
|
5040
5073
|
setDOMSelection(this);
|
|
5041
5074
|
});
|
|
@@ -5365,6 +5398,86 @@ class PluginInstance {
|
|
|
5365
5398
|
}
|
|
5366
5399
|
}
|
|
5367
5400
|
|
|
5401
|
+
function offset(add, offset) {
|
|
5402
|
+
return (v, from, to) => add(v, from + offset, to == null ? undefined : to + offset);
|
|
5403
|
+
}
|
|
5404
|
+
function init(type, create, source, doc) {
|
|
5405
|
+
return create(add => {
|
|
5406
|
+
doc.iterate((node, pos) => {
|
|
5407
|
+
if (node.isPlot && doc.schema.matchNode(node.type, type))
|
|
5408
|
+
source(node, pos + 1, add);
|
|
5409
|
+
});
|
|
5410
|
+
});
|
|
5411
|
+
}
|
|
5412
|
+
function refreshByPred(type, source, doc, deco, pred) {
|
|
5413
|
+
let recreate = [];
|
|
5414
|
+
doc.iterate((node, pos) => {
|
|
5415
|
+
if (doc.schema.matchNode(node.type, type) && pred(node))
|
|
5416
|
+
recreate.push({
|
|
5417
|
+
from: pos, to: pos + node.length,
|
|
5418
|
+
add: add => source(node, pos + 1, add)
|
|
5419
|
+
});
|
|
5420
|
+
});
|
|
5421
|
+
return recreate.length ? deco.modify({ replace: recreate }) : deco;
|
|
5422
|
+
}
|
|
5423
|
+
function update(config, create, source, deco, tr) {
|
|
5424
|
+
let doc = tr.newDoc;
|
|
5425
|
+
let refresh = config.refresh && config.refresh(tr);
|
|
5426
|
+
if (refresh === true)
|
|
5427
|
+
return init(config.type, create, source, doc);
|
|
5428
|
+
if (refresh)
|
|
5429
|
+
deco = refreshByPred(config.type, source, tr.startState.doc, deco, refresh);
|
|
5430
|
+
if (!tr.docChanged && !refresh)
|
|
5431
|
+
return deco;
|
|
5432
|
+
let recreate = [];
|
|
5433
|
+
let clear = [];
|
|
5434
|
+
tr.changes.iterChangedRanges((fromA, toA, fromB, toB) => {
|
|
5435
|
+
let covered = false;
|
|
5436
|
+
doc.iterate(fromB, toB, (node, pos) => {
|
|
5437
|
+
if (doc.schema.matchNode(node.type, config.type)) {
|
|
5438
|
+
recreate.push({
|
|
5439
|
+
from: pos, to: pos + node.length,
|
|
5440
|
+
add: add => source(node, pos + 1, add)
|
|
5441
|
+
});
|
|
5442
|
+
if (pos < toB && pos + node.length > toB)
|
|
5443
|
+
covered = true;
|
|
5444
|
+
return false;
|
|
5445
|
+
}
|
|
5446
|
+
});
|
|
5447
|
+
if (!covered) {
|
|
5448
|
+
let end = tr.startState.doc.resolve(toA);
|
|
5449
|
+
let open = end.matchingParent(p => doc.schema.matchNode(p.type, config.type));
|
|
5450
|
+
if (open && open.before >= fromA)
|
|
5451
|
+
clear.push({ from: open.before, to: open.after });
|
|
5452
|
+
}
|
|
5453
|
+
});
|
|
5454
|
+
if (clear.length)
|
|
5455
|
+
deco = deco.modify({ replace: clear });
|
|
5456
|
+
deco = deco.map(tr.changes, recreate);
|
|
5457
|
+
return deco;
|
|
5458
|
+
}
|
|
5459
|
+
function decoratePlots(config) {
|
|
5460
|
+
let result = [];
|
|
5461
|
+
let { type, points, ranges } = config;
|
|
5462
|
+
if (points) {
|
|
5463
|
+
let source = (plot, start, add) => points(plot, offset(add, start));
|
|
5464
|
+
let field = GardState.Field.define({
|
|
5465
|
+
create(state) { return init(type, PointSet.create, source, state.doc); },
|
|
5466
|
+
update(value, tr) { return update(config, PointSet.create, source, value, tr); }
|
|
5467
|
+
});
|
|
5468
|
+
result.push(field, Decoration.Point.source.of(s => s.field(field)));
|
|
5469
|
+
}
|
|
5470
|
+
if (ranges) {
|
|
5471
|
+
let source = (plot, start, add) => ranges(plot, offset(add, start));
|
|
5472
|
+
let field = GardState.Field.define({
|
|
5473
|
+
create(state) { return init(type, RangeSet.create, source, state.doc); },
|
|
5474
|
+
update(value, tr) { return update(config, RangeSet.create, source, value, tr); }
|
|
5475
|
+
});
|
|
5476
|
+
result.push(field, Decoration.Range.source.of(s => s.field(field)));
|
|
5477
|
+
}
|
|
5478
|
+
return result;
|
|
5479
|
+
}
|
|
5480
|
+
|
|
5368
5481
|
const panelConfig = /*@__PURE__*/GardState.Facet.define({
|
|
5369
5482
|
combine(configs) {
|
|
5370
5483
|
let topContainer, bottomContainer;
|
|
@@ -7020,7 +7133,7 @@ function showPlaceholder(state) {
|
|
|
7020
7133
|
let shape = state.facet(placeholderShape);
|
|
7021
7134
|
if (!shape.length)
|
|
7022
7135
|
return Decoration.Point.none;
|
|
7023
|
-
return Decoration.Point.set([[
|
|
7136
|
+
return Decoration.Point.set([[Decoration.Point.widget(placeholderWidget.of(shape[0]), { side: 1 }), pos]]);
|
|
7024
7137
|
}
|
|
7025
7138
|
const placeholderField = /*@__PURE__*/GardState.Field.define({
|
|
7026
7139
|
create(state) {
|
|
@@ -7124,4 +7237,4 @@ function dropCursor() {
|
|
|
7124
7237
|
return [dropCursorPos, drawDropCursor];
|
|
7125
7238
|
}
|
|
7126
7239
|
|
|
7127
|
-
export { Decoration, Dialog, InputRule, KeyBinding, Panel, Tooltip, Widget, Wordgard, dropCursor, menuBar, placeholder };
|
|
7240
|
+
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 = [[
|
|
837
|
+
let deco = [[resizeWrapper, target]];
|
|
838
838
|
if (resizing > -1)
|
|
839
|
-
deco.push([
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
implementing {@link RangeSet.Value}.
|
|
4
|
+
The interface shared between {@link RangeSet} and {@link
|
|
5
|
+
PointSet}.
|
|
7
6
|
*/
|
|
8
|
-
declare class
|
|
9
|
-
private constructor();
|
|
7
|
+
declare abstract class Set<T> {
|
|
10
8
|
/**
|
|
11
|
-
|
|
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
|
-
|
|
11
|
+
abstract length: number;
|
|
16
12
|
/**
|
|
17
|
-
|
|
13
|
+
Returns `true` when this set is empty.
|
|
18
14
|
*/
|
|
19
|
-
|
|
15
|
+
abstract empty: boolean;
|
|
20
16
|
/**
|
|
21
|
-
|
|
17
|
+
Create a cursor over this point set, starting at the given
|
|
18
|
+
position and side.
|
|
22
19
|
*/
|
|
23
|
-
|
|
20
|
+
abstract cursor(from?: number): Set.Cursor<T>;
|
|
24
21
|
/**
|
|
25
|
-
|
|
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
|
-
|
|
28
|
+
abstract map(map: ChangeSet, replace?: readonly Set.Replacement<T>[]): this;
|
|
28
29
|
/**
|
|
29
|
-
Create
|
|
30
|
+
Create an updated copy of this set.
|
|
30
31
|
*/
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
47
|
-
optionally add new ranges provided by their `add` property.
|
|
96
|
+
The start of the replacement.
|
|
48
97
|
*/
|
|
49
|
-
|
|
98
|
+
from: number;
|
|
50
99
|
/**
|
|
51
|
-
|
|
100
|
+
The end of the replaced range.
|
|
52
101
|
*/
|
|
53
|
-
|
|
102
|
+
to: number;
|
|
54
103
|
/**
|
|
55
|
-
|
|
56
|
-
`false`.
|
|
104
|
+
An optional source of points to to this section.
|
|
57
105
|
*/
|
|
58
|
-
|
|
59
|
-
}
|
|
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:
|
|
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):
|
|
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):
|
|
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
|
|
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
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
|
157
|
+
source((value, from, to = from) => {
|
|
109
158
|
if (pre)
|
|
110
159
|
pre(from, to);
|
|
111
|
-
this.addRange(from, to
|
|
160
|
+
this.addRange(value, from, to);
|
|
112
161
|
});
|
|
113
162
|
}
|
|
114
|
-
addRange(from, to
|
|
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
|
|
166
|
+
(this.lastTo <= from ? this : this.next).addInner(value, from, to);
|
|
118
167
|
}
|
|
119
|
-
addInner(from, to
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
263
|
-
build.addRange(cursor.
|
|
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
|
|
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 [
|
|
467
|
-
add(
|
|
476
|
+
source = add => { for (let [value, from, to] of array)
|
|
477
|
+
add(value, from, to); };
|
|
468
478
|
}
|
|
469
|
-
source((
|
|
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(
|
|
472
|
-
this.addPoint(
|
|
483
|
+
pre(value, from);
|
|
484
|
+
this.addPoint(value, from);
|
|
473
485
|
});
|
|
474
486
|
}
|
|
475
|
-
addPoint(
|
|
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, (
|
|
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.
|
|
585
|
-
build.addPoint(cursor.
|
|
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.
|
|
643
|
+
else if (cursor.from >= pos) {
|
|
632
644
|
break;
|
|
633
645
|
}
|
|
634
646
|
else {
|
|
635
|
-
if (!filter || filter(cursor.
|
|
636
|
-
build.addPoint(cursor.
|
|
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.
|
|
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.
|
|
688
|
+
while (cursor.value && cursor.from <= upto) {
|
|
677
689
|
let value = cursor.value;
|
|
678
|
-
let pos = map.mapPos(cursor.
|
|
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(
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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);
|