@nerd-bible/wordgard 0.6.2-beta1 → 0.6.2-beta10

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.js CHANGED
@@ -132,6 +132,7 @@ function joinRanges(ranges) {
132
132
  }
133
133
  }
134
134
 
135
+ var Mark_ = Mark;
135
136
  class Widget {
136
137
  value;
137
138
  constructor(type,
@@ -198,6 +199,16 @@ class Widget {
198
199
  render() {
199
200
  let img = document.createElement("img");
200
201
  img.className = "wg-buffer";
202
+ img.alt = "";
203
+ return img;
204
+ },
205
+ editable: true
206
+ });
207
+ Widget.blockImg = Widget.create({
208
+ render() {
209
+ let img = document.createElement("img");
210
+ img.className = "wg-blockBuffer";
211
+ img.alt = "";
201
212
  return img;
202
213
  },
203
214
  editable: true
@@ -278,15 +289,15 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
278
289
  }
279
290
  Tag.attribute = attribute;
280
291
  })(Decoration.Tag || (Decoration.Tag = {}));
281
- (function (Mark$1) {
292
+ (function (Mark) {
282
293
  function shape(type, shape) {
283
- if (type instanceof Mark)
294
+ if (type instanceof Mark_)
284
295
  type = type.type;
285
296
  if (type.spanning && !("element" in shape))
286
297
  throw new Error("Spanning marks must have an element shape");
287
- return markShape.of({ type, modified: Mark.Type.define(type.name, { ...type.spec, shape }) });
298
+ return markShape.of({ type, modified: Mark_.Type.define(type.name, { ...type.spec, shape }) });
288
299
  }
289
- Mark$1.shape = shape;
300
+ Mark.shape = shape;
290
301
  })(Decoration.Mark || (Decoration.Mark = {}));
291
302
  class Point {
292
303
  constructor() { }
@@ -305,6 +316,7 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
305
316
  return new WrapperDecoration(wrapper, spec?.target ? Elt.Selector.parse(spec.target) : null);
306
317
  }
307
318
  static source = GardState.Facet.define({
319
+ name: "pointDecorations",
308
320
  combine: sources => sources.concat(nodeSelection)
309
321
  });
310
322
  static set(source) { return PointSet.create(source); }
@@ -329,19 +341,21 @@ const Decoration = /*@__PURE__*/(function (Decoration) {
329
341
  static attribute(attr, value, options = {}) {
330
342
  return new AttributeRangeDecoration(attr, value, options);
331
343
  }
332
- static source = GardState.Facet.define();
344
+ static source = GardState.Facet.define({ name: "rangeDecorations" });
333
345
  static set(source) { return RangeSet.create(source); }
334
346
  static none = RangeSet.empty;
335
347
  }
336
348
  Decoration.Range = Range;
337
349
  ;return Decoration})({});
338
350
  const tagShape = /*@__PURE__*/GardState.Facet.define({
351
+ name: "tagShape",
339
352
  combine: shapes => new Map(shapes.map(s => [s.type, s.shape]).reverse())
340
353
  });
341
- const tagWrapper = /*@__PURE__*/GardState.Facet.define();
342
- const tagWidget = /*@__PURE__*/GardState.Facet.define();
343
- const tagAttribute = /*@__PURE__*/GardState.Facet.define();
354
+ const tagWrapper = /*@__PURE__*/GardState.Facet.define({ name: "tagWrapper" });
355
+ const tagWidget = /*@__PURE__*/GardState.Facet.define({ name: "tagWidget" });
356
+ const tagAttribute = /*@__PURE__*/GardState.Facet.define({ name: "tagAttribute" });
344
357
  const markShape = /*@__PURE__*/GardState.Facet.define({
358
+ name: "markShape",
345
359
  combine: shapes => new Map(shapes.map(s => [s.type, s.modified]).reverse())
346
360
  });
347
361
  function memo(f) {
@@ -517,7 +531,6 @@ const globalDecoFacets = [tagShape, tagWidget, tagWrapper, tagAttribute, markSha
517
531
  function findChangedRanges(prevState, prevDeco, state, deco, sections) {
518
532
  let result = [];
519
533
  let globalChange = globalDecoFacets.some(facet => prevState.facet(facet) !== state.facet(facet));
520
- let shapeChanges = [];
521
534
  for (let i = 0, posA = 0, posB = 0; i < sections.length;) {
522
535
  let len = sections[i++], ins = sections[i++];
523
536
  if (ins == -1 && globalChange) {
@@ -540,11 +553,6 @@ function findChangedRanges(prevState, prevDeco, state, deco, sections) {
540
553
  compareDecoSet(prevDeco.points, deco.points, (a, b) => {
541
554
  (a || PointSet.empty).compareRange(posA, b || PointSet.empty, posB, len, (pos, val) => {
542
555
  add(pos, Math.min(pos + (val instanceof WidgetDecoration ? 0 : 1), endB));
543
- if (val instanceof ShapeDecoration && !globalChange) {
544
- let idx = findAbove(shapeChanges, 0, pos - 1);
545
- if (idx == shapeChanges.length || shapeChanges[idx] != pos)
546
- shapeChanges.splice(idx, 0, pos);
547
- }
548
556
  });
549
557
  });
550
558
  let joined = joinRanges(ranges), pos = posB, end = pos + len, j = 0;
@@ -573,34 +581,8 @@ function findChangedRanges(prevState, prevDeco, state, deco, sections) {
573
581
  addSection(result, len, ins);
574
582
  }
575
583
  }
576
- if (shapeChanges.length)
577
- return addAtomicityChanges(result, prevState, shapeChanges);
578
584
  return result;
579
585
  }
580
- function addAtomicityChanges(changes, prev, nodes) {
581
- let added = [];
582
- let scan = prev.doc.resolve(0), sectionPos = 0, sectionI = 0, off = 0;
583
- for (let posB of nodes) {
584
- while (posB >= sectionPos) {
585
- let len = changes[sectionI++], ins = changes[sectionI++];
586
- if (ins < 0) {
587
- sectionPos += len;
588
- }
589
- else {
590
- sectionPos += ins;
591
- off += len - ins;
592
- }
593
- }
594
- let posA = posB - off;
595
- if (scan.pos < posA)
596
- scan = scan.advance(posA - scan.pos);
597
- let node = scan.nodeAfter;
598
- if (!node)
599
- continue;
600
- added.push(posA, posA + node.length);
601
- }
602
- return added.length ? addUpdated(changes, added) : changes;
603
- }
604
586
  class SpanIterator {
605
587
  ranges;
606
588
  points;
@@ -756,7 +738,7 @@ class DecoIterator {
756
738
  let pos = this.pos.advance(from - this.pos.pos), started = inclusiveStart;
757
739
  let atomParent;
758
740
  for (let p = pos.parent; p; p = p.parent)
759
- if (this.state.isAtom(p.node.type))
741
+ if (!p.node.isDoc && (this.state.isAtom(p.node.type) || this.hasAtomShape(p.before)))
760
742
  atomParent = p;
761
743
  let pendingDeco = [], pendingPos = -1;
762
744
  let pendingShape = null, pendingShapeSet = null;
@@ -767,7 +749,7 @@ class DecoIterator {
767
749
  else
768
750
  started = true;
769
751
  let hasPending = pendingPos == pos && !node.isText;
770
- let shape = hasPending && pendingShape ? pendingShape.shape : this.tagShape(node.tag, iter.active);
752
+ let shape = this.tagShape(node.tag, iter.active, hasPending ? pendingShape : null);
771
753
  if (hasPending)
772
754
  for (let deco of pendingDeco)
773
755
  shape = applyDeco(shape, deco, node.tag);
@@ -781,22 +763,23 @@ class DecoIterator {
781
763
  this.widgets(node.tag, 0, walker);
782
764
  else
783
765
  started = true;
784
- let shape = pendingShape && pendingPos == pos ? pendingShape.shape
785
- : this.tagShape(node.tag, iter.active);
766
+ let shape = this.tagShape(node.tag, iter.active, pendingShape && pendingPos == pos ? pendingShape : null);
786
767
  if (pendingPos == pos)
787
768
  for (let deco of pendingDeco)
788
769
  shape = applyDeco(shape, deco, node.tag);
789
770
  let wrappers = this.nodeWrappers(node.tag, iter.active, !shape.hasContent);
790
771
  let atom = !shape.hasContent;
791
- if (atom)
772
+ if (atom) {
792
773
  walker.node(node, shape, wrappers, pos + node.length > to ? to - pos : undefined);
793
- else
774
+ }
775
+ else {
794
776
  walker.enter(node, shape, wrappers);
795
- this.widgets(node.tag, 2, walker);
777
+ this.widgets(node.tag, 2, walker);
778
+ }
796
779
  return !atom;
797
780
  },
798
781
  leavePlot: tag => {
799
- if (started)
782
+ if (started && !atomParent)
800
783
  this.widgets(tag, 3, walker);
801
784
  else
802
785
  started = true;
@@ -804,7 +787,7 @@ class DecoIterator {
804
787
  this.widgets(tag, 1, walker);
805
788
  }
806
789
  };
807
- if (inclusiveStart) {
790
+ if (inclusiveStart && !atomParent) {
808
791
  let before = pos.nodeBefore;
809
792
  if (before)
810
793
  this.widgets(before.tag, 1, walker);
@@ -816,9 +799,10 @@ class DecoIterator {
816
799
  let end = Math.min(to, atomParent.after), done = atomParent.after <= to;
817
800
  walker.nodePart(atomParent.node, end - pos.pos, done);
818
801
  pos = pos.advance(end - pos.pos);
819
- if (done)
802
+ if (done) {
820
803
  this.widgets(atomParent.node.tag, 1, walker);
821
- atomParent = undefined;
804
+ atomParent = undefined;
805
+ }
822
806
  while (iter.point && iter.from < end)
823
807
  iter.next();
824
808
  }
@@ -861,9 +845,8 @@ class DecoIterator {
861
845
  }
862
846
  this.pos = pos;
863
847
  }
864
- tagShape(tag, active) {
865
- let override = this.tagShapes.get(tag.type);
866
- let shape = override ? override(tag) : baseTagShape(tag);
848
+ tagShape(tag, active, fromPoint) {
849
+ let shape = fromPoint ? fromPoint.shape : this.tagShapes.get(tag.type)?.(tag) ?? baseTagShape(tag);
867
850
  if (tag.marks.length)
868
851
  shape = addMarkAttributes(this.markShapes, shape, tag);
869
852
  let add;
@@ -892,6 +875,15 @@ class DecoIterator {
892
875
  }
893
876
  return shape;
894
877
  }
878
+ atomCache = new Map();
879
+ hasAtomShape(pos) {
880
+ let has = this.atomCache.get(pos);
881
+ if (has == null) {
882
+ has = this.pointSets.some(s => s.at(pos, d => d instanceof ShapeDecoration && !d.shape.hasContent));
883
+ this.atomCache.set(pos, has);
884
+ }
885
+ return has;
886
+ }
895
887
  }
896
888
  function compareSetPrec(setA, setB, array) {
897
889
  if (setA != setB)
@@ -916,7 +908,7 @@ function eqArray(a, b) {
916
908
  return false;
917
909
  return true;
918
910
  }
919
- const exceptionSink = /*@__PURE__*/GardState.Facet.define();
911
+ const exceptionSink = /*@__PURE__*/GardState.Facet.define({ name: "exceptionSink" });
920
912
  function logException(state, exception, context) {
921
913
  let handler = state.facet(exceptionSink);
922
914
  if (handler.length)
@@ -929,6 +921,28 @@ function logException(state, exception, context) {
929
921
  console.error(exception);
930
922
  }
931
923
 
924
+ let nav = typeof navigator != "undefined" ? navigator : { userAgent: "", vendor: "", platform: "" };
925
+ let doc = typeof document != "undefined" ? document : { documentElement: { style: {} } };
926
+ const edge = /*@__PURE__*/(() => /Edge\/(\d+)/.exec(nav.userAgent))();
927
+ const gecko = /*@__PURE__*/(() => !edge && /gecko\/(\d+)/i.test(nav.userAgent))();
928
+ const chrome = /*@__PURE__*/(() => !edge && /Chrome\/(\d+)/.exec(nav.userAgent))();
929
+ const webkit = /*@__PURE__*/(() => "webkitFontSmoothing" in doc.documentElement.style)();
930
+ const safari = /*@__PURE__*/(() => !edge && /Apple Computer/.test(nav.vendor))();
931
+ const ios = /*@__PURE__*/(() => safari && (/Mobile\/\w+/.test(nav.userAgent) || nav.maxTouchPoints > 2))();
932
+ var browser = /*@__PURE__*/(() => ({
933
+ mac: ios || /Mac/.test(nav.platform),
934
+ windows: /Win/.test(nav.platform),
935
+ linux: /Linux|X11/.test(nav.platform),
936
+ gecko_version: gecko ? +(/Firefox\/(\d+)/.exec(nav.userAgent) || [0, 0])[1] : 0,
937
+ chrome: !!chrome,
938
+ chrome_version: chrome ? +chrome[1] : 0,
939
+ ios,
940
+ android: /Android\b/.test(nav.userAgent),
941
+ webkit,
942
+ webkit_version: webkit ? +(/\bAppleWebKit\/(\d+)/.exec(nav.userAgent) || [0, 0])[1] : 0,
943
+ safari,
944
+ safari_version: safari ? +(/\bVersion\/(\d+(\.\d+)?)/.exec(nav.userAgent) || [0, 0])[1] : 0}))();
945
+
932
946
  function getSelection(root) {
933
947
  let target;
934
948
  if (root.nodeType == 11) { target = root.getSelection ? root : root.ownerDocument;
@@ -938,6 +952,17 @@ function getSelection(root) {
938
952
  }
939
953
  return target.getSelection();
940
954
  }
955
+ function getSelectionRange(root) {
956
+ let sel = getSelection(root);
957
+ if (!sel)
958
+ return null;
959
+ if (browser.safari && root.nodeType == 11) {
960
+ let range = sel.getComposedRanges(root)[0];
961
+ if (range)
962
+ return range;
963
+ }
964
+ return new StaticRange(sel.getRangeAt(0));
965
+ }
941
966
  function hasSelection(dom, selection) {
942
967
  if (!selection.focusNode)
943
968
  return false;
@@ -1307,12 +1332,6 @@ class Tile {
1307
1332
  let last = this.children.length - 1;
1308
1333
  return last < 0 ? null : this.children[last];
1309
1334
  }
1310
- get nodeParent() {
1311
- let tile = this;
1312
- while (!tile.tag)
1313
- tile = tile.parent;
1314
- return tile;
1315
- }
1316
1335
  ignoreEvent(event) { return false; }
1317
1336
  get ignoreMutations() { return false; }
1318
1337
  toString() { return this.dom.nodeName + (this.children.length ? `(${this.children})` : ""); }
@@ -1332,8 +1351,8 @@ class Tile {
1332
1351
  return tile;
1333
1352
  }
1334
1353
  markDirty() {
1335
- if (!(this.flags & 8192)) {
1336
- this.flags |= 8192;
1354
+ if (!(this.flags & 16384)) {
1355
+ this.flags |= 16384;
1337
1356
  this.parent?.markDirty();
1338
1357
  }
1339
1358
  }
@@ -1344,10 +1363,10 @@ class Tile {
1344
1363
  static get(node) { return node.wgTile; }
1345
1364
  }
1346
1365
  function checkSync(tile) {
1347
- if ((tile.flags & 256) && !(tile.flags & 8192))
1366
+ if ((tile.flags & 256) && !(tile.flags & 16384))
1348
1367
  return false;
1349
1368
  tile.flags |= 256;
1350
- tile.flags &= -8193;
1369
+ tile.flags &= -16385;
1351
1370
  return true;
1352
1371
  }
1353
1372
  class CompositeTile extends Tile {
@@ -1355,9 +1374,9 @@ class CompositeTile extends Tile {
1355
1374
  addChild(child) {
1356
1375
  if (this.flags & 256)
1357
1376
  throw new Error("Cannot add to a synced tile");
1358
- if ((this.flags & 4096) && !(child.flags & 2048)) {
1377
+ if ((this.flags & 8192) && !(child.flags & 4096)) {
1359
1378
  let i = this.children.length;
1360
- while (i > 0 && (this.children[i - 1].flags & 2048))
1379
+ while (i > 0 && (this.children[i - 1].flags & 4096))
1361
1380
  i--;
1362
1381
  this.children.splice(i, 0, child);
1363
1382
  }
@@ -1366,6 +1385,10 @@ class CompositeTile extends Tile {
1366
1385
  }
1367
1386
  child.parent = this;
1368
1387
  }
1388
+ putChild(child, index) {
1389
+ this.children.splice(index, 0, child);
1390
+ child.parent = this;
1391
+ }
1369
1392
  sync() {
1370
1393
  if (!checkSync(this))
1371
1394
  return;
@@ -1563,8 +1586,7 @@ class DocTile extends CompositeTile {
1563
1586
  builder.update(0, true);
1564
1587
  }
1565
1588
  else if (ins == -1) {
1566
- builder.keep(len, !startCovered, i == changes.length);
1567
- startCovered = false;
1589
+ startCovered = builder.keep(len, !startCovered, i == changes.length);
1568
1590
  }
1569
1591
  else if (ins == -2) {
1570
1592
  builder.update(len, !startCovered);
@@ -1657,7 +1679,7 @@ class DocTile extends CompositeTile {
1657
1679
  parentBefore = before;
1658
1680
  before = before.children[beforeI = before.children.length - 1];
1659
1681
  }
1660
- if (before.isNodeInner && (before.flags & 2048) || (before.flags & 64)) {
1682
+ if (before.isNodeInner && (before.flags & 4096) || (before.flags & 64)) {
1661
1683
  parent = parentBefore;
1662
1684
  i = beforeI;
1663
1685
  continue adjust;
@@ -1669,7 +1691,7 @@ class DocTile extends CompositeTile {
1669
1691
  parentAfter = after;
1670
1692
  after = after.children[afterI = 0];
1671
1693
  }
1672
- if (after.isNodeInner && !(after.flags & 2048) || (after.flags & 32)) {
1694
+ if (after.isNodeInner && !(after.flags & 4096) || (after.flags & 32)) {
1673
1695
  parent = parentAfter;
1674
1696
  i = afterI + 1;
1675
1697
  continue adjust;
@@ -1788,20 +1810,20 @@ class EltTile extends CompositeTile {
1788
1810
  get boundary() { return this._tag && !(this.flags & 512) ? 1 : 0; }
1789
1811
  get tag() { return this._tag; }
1790
1812
  get contentTile() {
1791
- if (!(this.flags & 1024))
1813
+ if (!(this.flags & 2048))
1792
1814
  return null;
1793
1815
  for (let ch of this.children)
1794
- if (ch.isNodeInner && (ch.flags & 1024))
1816
+ if (ch.isNodeInner && (ch.flags & 2048))
1795
1817
  return ch.contentTile;
1796
1818
  return this;
1797
1819
  }
1798
1820
  static of(elt, tag, flags, length, dom) {
1799
1821
  if (elt.hasContent) {
1800
- flags |= 1024;
1822
+ flags |= 2048;
1801
1823
  if (elt.children.length > 1) {
1802
1824
  let zero = elt.children.indexOf(0);
1803
1825
  if (zero > -1 && zero < elt.children.length - 1)
1804
- flags |= 4096;
1826
+ flags |= 8192;
1805
1827
  }
1806
1828
  }
1807
1829
  return new EltTile(elt, tag, flags, length, dom || elt.outerDOM());
@@ -1813,8 +1835,13 @@ function setUneditable(dom) {
1813
1835
  span.appendChild(dom);
1814
1836
  dom = span;
1815
1837
  }
1816
- if (dom.contentEditable == "inherit" && !/^(br|hr|img|input|wbr)$/i.test(dom.nodeName))
1817
- dom.contentEditable = "false";
1838
+ let cur = dom.contentEditable;
1839
+ if (cur == "false")
1840
+ return true;
1841
+ if (cur != "inherit" || !/^(br|hr|img|input|wbr)$/i.test(dom.nodeName))
1842
+ return false;
1843
+ dom.contentEditable = "false";
1844
+ return true;
1818
1845
  }
1819
1846
  class WidgetTile extends Tile {
1820
1847
  widget;
@@ -1973,7 +2000,12 @@ class TilePointer {
1973
2000
  let { tile, index } = this;
1974
2001
  if (tile.isAtom)
1975
2002
  return tile;
1976
- return index < tile.children.length ? tile.children[index] : null;
2003
+ for (; index < tile.children.length; index++) {
2004
+ let next = tile.children[index];
2005
+ if (!(next instanceof WidgetTile && (next.widget == Widget.blockImg || next.widget == Widget.br)))
2006
+ return next;
2007
+ }
2008
+ return null;
1977
2009
  }
1978
2010
  matchingWrapper(elt, spanning, reused) {
1979
2011
  let best, bestScore = 0;
@@ -2011,7 +2043,7 @@ class TilePointer {
2011
2043
  if (!before.isPoint)
2012
2044
  break;
2013
2045
  if (!reused.has(before) && before instanceof WidgetTile && before.widget.eq(widget) &&
2014
- (before.flags & 96) == sideFlag && !(before.flags & 8192)) {
2046
+ (before.flags & 96) == sideFlag && !(before.flags & 16384)) {
2015
2047
  reused.set(before, 1);
2016
2048
  return before;
2017
2049
  }
@@ -2043,11 +2075,9 @@ class ContentUpdate {
2043
2075
  if (span) {
2044
2076
  this.new = span;
2045
2077
  }
2046
- else {
2047
- this.reused.set(tile, 2);
2048
- let inner = EltTile.of(tile.elt, tile.tag, tile.flags, tile.boundary * 2, tile.dom);
2049
- this.new.addChild(inner);
2050
- this.new = inner;
2078
+ else if (!tile.isNodeInner) { let copy = this.copyEltStructure(tile);
2079
+ this.new.addChild(copy);
2080
+ this.new = copy.contentTile;
2051
2081
  }
2052
2082
  },
2053
2083
  leave: tile => {
@@ -2071,7 +2101,8 @@ class ContentUpdate {
2071
2101
  }
2072
2102
  },
2073
2103
  skip: (tile, from, to) => {
2074
- if (!(tile instanceof TextTile)) {
2104
+ if (tile.isNodeInner) ;
2105
+ else if (!(tile instanceof TextTile)) {
2075
2106
  if (!from && to == tile.length) {
2076
2107
  this.reused.set(tile, 1);
2077
2108
  this.new.addChild(tile);
@@ -2093,12 +2124,15 @@ class ContentUpdate {
2093
2124
  this.partialNode = null;
2094
2125
  this.new.addChild(this.buildNodeShape(tag, length + (to - from), shape, reuse));
2095
2126
  }
2127
+ else {
2128
+ this.partialNode.length += to - from;
2129
+ }
2096
2130
  }
2097
2131
  }
2098
2132
  else if (this.new.lastChild instanceof TextTile && !this.new.lastChild.isComposition) {
2099
2133
  this.addText(tile.text.slice(from, to));
2100
2134
  }
2101
- else if (!from && to == tile.text.length && !(tile.flags & 8192) && !this.reused.has(tile)) {
2135
+ else if (!from && to == tile.text.length && !(tile.flags & 16384) && !this.reused.has(tile)) {
2102
2136
  this.reused.set(tile, 1);
2103
2137
  this.new.addChild(tile);
2104
2138
  }
@@ -2113,6 +2147,20 @@ class ContentUpdate {
2113
2147
  };
2114
2148
  }
2115
2149
  keep(len, includeStart, includeEnd) {
2150
+ if (!!this.partialNode != (this.old.tile.isAtom && !this.old.tile.isText)) {
2151
+ let dist = Math.min(len, this.partialNode
2152
+ ? this.state.doc.nodeAt(this.posB - this.partialNode.length).length - this.partialNode.length
2153
+ : this.old.tile.length - this.old.index);
2154
+ this.replace(dist, dist, includeStart);
2155
+ if (dist == len)
2156
+ return true;
2157
+ includeStart = false;
2158
+ len -= dist;
2159
+ }
2160
+ this.keepCheckEnd(len, includeStart, includeEnd);
2161
+ return includeEnd;
2162
+ }
2163
+ keepCheckEnd(len, includeStart, includeEnd) {
2116
2164
  let cut = [], end = this.posB + len;
2117
2165
  if (this.deco.endWidgets)
2118
2166
  for (let nw = this.new, { tile, index, parent } = this.old, pos = this.posB; pos < end;) {
@@ -2253,7 +2301,7 @@ class ContentUpdate {
2253
2301
  if (!(next instanceof TextTile) || this.reused.has(next)) {
2254
2302
  this.addText(node.param);
2255
2303
  }
2256
- else if (next.text == node.param && !(next.flags & 8192)) {
2304
+ else if (next.text == node.param && !(next.flags & 16384)) {
2257
2305
  this.reused.set(next, 1);
2258
2306
  this.new.addChild(next);
2259
2307
  }
@@ -2292,6 +2340,9 @@ class ContentUpdate {
2292
2340
  for (let i = 0; i < wrappers; i++)
2293
2341
  this.up();
2294
2342
  }
2343
+ else {
2344
+ this.partialNode.length += length;
2345
+ }
2295
2346
  },
2296
2347
  widget: (widget, side) => {
2297
2348
  let sideFlag = side < 0 ? 32 : side > 0 ? 64 : 0;
@@ -2301,9 +2352,10 @@ class ContentUpdate {
2301
2352
  : null;
2302
2353
  if (!tile) {
2303
2354
  let dom = widget.render(this.wg);
2304
- if (!widget.type.editable)
2305
- setUneditable(dom);
2306
- tile = new WidgetTile(widget, null, 16 | sideFlag, dom);
2355
+ let flags = 16 | sideFlag;
2356
+ if (!widget.type.editable && setUneditable(dom))
2357
+ flags |= 1024;
2358
+ tile = new WidgetTile(widget, null, flags, dom);
2307
2359
  if (widget.type.connect)
2308
2360
  this.toConnect.push(tile);
2309
2361
  }
@@ -2340,27 +2392,33 @@ class ContentUpdate {
2340
2392
  }
2341
2393
  buildNodeShape(tag, length, shape, reuse, inEditable = true, afterContent = 0) {
2342
2394
  if (shape instanceof Elt) {
2395
+ let flags = (tag ? (shape.hasContent ? 0 : 512)
2396
+ : 1 | (shape.hasContent ? 0 : 16)) | afterContent;
2343
2397
  if (inEditable && !shape.hasContent) {
2344
- if (Attributes.get(shape.attrs, "contenteditable") == null && !/^(br|hr|img|input|wbr)$/i.test(shape.tagName))
2398
+ let contentEd = Attributes.get(shape.attrs, "contenteditable");
2399
+ if (contentEd == null && !/^(br|hr|img|input|wbr)$/i.test(shape.tagName)) {
2345
2400
  shape = Elt.create(shape.tagName, Attributes.merge(shape.attrs, ["contenteditable", "false"]), shape.children);
2401
+ flags |= 1024;
2402
+ }
2403
+ else if (contentEd == "false") {
2404
+ flags |= 1024;
2405
+ }
2346
2406
  inEditable = false;
2347
2407
  }
2348
2408
  let reusable, dom, strict = true;
2349
2409
  if (reusable = this.findReusableTile(shape, reuse, strict) || this.findReusableTile(shape, reuse, strict = false)) {
2350
2410
  this.reused.set(reusable, 2);
2351
2411
  dom = reusable.dom;
2352
- if (reusable.flags & 8192)
2412
+ if (reusable.flags & 16384)
2353
2413
  updateAttributes(dom, takeAttributes(reusable.dom), shape.attrs);
2354
2414
  else if (!strict)
2355
2415
  updateAttributes(dom, reusable.elt.attrs, shape.attrs);
2356
2416
  }
2357
- let flags = (tag ? (shape.hasContent ? 0 : 512)
2358
- : 1 | (shape.hasContent ? 0 : 16)) | afterContent;
2359
2417
  let tile = EltTile.of(shape, tag, flags, tag ? length : 0, dom);
2360
2418
  let afterContentInner = 0;
2361
2419
  for (let ch of shape.children) {
2362
2420
  if (ch === 0) {
2363
- afterContentInner = 2048;
2421
+ afterContentInner = 4096;
2364
2422
  tile.flags |= 2;
2365
2423
  }
2366
2424
  else {
@@ -2369,8 +2427,7 @@ class ContentUpdate {
2369
2427
  }
2370
2428
  return tile;
2371
2429
  }
2372
- else {
2373
- let reusable, dom;
2430
+ else { let reusable, dom;
2374
2431
  if (reusable = this.findReusableTile(shape, reuse, false)) {
2375
2432
  this.reused.set(reusable, 2);
2376
2433
  dom = reusable.dom;
@@ -2378,30 +2435,41 @@ class ContentUpdate {
2378
2435
  else {
2379
2436
  dom = shape.render(this.wg);
2380
2437
  }
2381
- if (inEditable && !shape.type.editable)
2382
- setUneditable(dom);
2383
2438
  let flags = (tag ? 512 : 16 | 1) | afterContent;
2439
+ if (inEditable && !shape.type.editable && setUneditable(dom))
2440
+ flags |= 1024;
2384
2441
  let tile = new WidgetTile(shape, tag, flags, dom, tag ? length : 0);
2385
2442
  if (shape.type.connect)
2386
2443
  this.toConnect.push(tile);
2387
2444
  return tile;
2388
2445
  }
2389
2446
  }
2390
- ensureHackNode() {
2391
- let tile = this.new;
2392
- if (!tile.isPlotContent)
2393
- return;
2394
- while (tile.isNodeInner)
2395
- tile = tile.parent;
2396
- let tag = tile.tag;
2397
- if (!tag || !tag.isPlot || !(tag.isTextblock || tag.type.isInline))
2398
- return;
2447
+ copyEltStructure(tile) {
2448
+ this.reused.set(tile, 2);
2449
+ let copy = EltTile.of(tile.elt, tile.tag, tile.flags, tile.boundary * 2, tile.dom);
2450
+ if (tile.isNodeOuter)
2451
+ for (let child of tile.children)
2452
+ if (child.isNodeInner) {
2453
+ copy.addChild((child.flags & 2048) ? this.copyEltStructure(child) : child);
2454
+ }
2455
+ return copy;
2456
+ }
2457
+ ensureHackNodes() {
2458
+ if (this.new.isPlotContent || this.new.isWrapper) {
2459
+ let { tag } = this.new.nearestNode();
2460
+ if (this.new.isPlotContent && tag.isPlot && (tag.isTextblock || tag.type.isInline))
2461
+ this.ensureTrailingHackNode(this.new);
2462
+ if (tag.isPlot && !tag.inlineContent)
2463
+ this.ensureBlockSeparators(this.new);
2464
+ }
2465
+ }
2466
+ ensureTrailingHackNode(target) {
2399
2467
  let hasHack = -1, needsHack = true;
2400
- for (let parent = this.new, i = parent.children.length;;) {
2468
+ for (let parent = target, i = parent.children.length;;) {
2401
2469
  if (i > 0) {
2402
2470
  let next = parent.children[--i];
2403
2471
  if (next.isNodeInner || next instanceof WidgetTile && !next.widget.type.inFlow) ;
2404
- else if (next instanceof WidgetTile && next.widget == Widget.br && parent == this.new) {
2472
+ else if (next instanceof WidgetTile && next.widget == Widget.br && parent == target) {
2405
2473
  hasHack = i;
2406
2474
  }
2407
2475
  else if (next.dom.nodeName == "BR") {
@@ -2416,7 +2484,7 @@ class ContentUpdate {
2416
2484
  break;
2417
2485
  }
2418
2486
  }
2419
- else if (parent == this.new) {
2487
+ else if (parent == target) {
2420
2488
  break;
2421
2489
  }
2422
2490
  else {
@@ -2426,14 +2494,32 @@ class ContentUpdate {
2426
2494
  }
2427
2495
  if (hasHack > -1) {
2428
2496
  if (!needsHack)
2429
- this.new.children.splice(hasHack, 1);
2497
+ target.children.splice(hasHack, 1);
2430
2498
  }
2431
2499
  else if (needsHack) {
2432
- this.new.addChild(new WidgetTile(Widget.br, null, 16 | 64, Widget.br.render(this.wg)));
2500
+ target.addChild(new WidgetTile(Widget.br, null, 16 | 64, Widget.br.render(this.wg)));
2501
+ }
2502
+ }
2503
+ ensureBlockSeparators(target) {
2504
+ for (let i = 0, prev = null;; i++) {
2505
+ let next = i == target.children.length ? null : target.children[i];
2506
+ if (next && next.isNodeInner)
2507
+ continue;
2508
+ if (!next && !prev)
2509
+ break;
2510
+ if ((next || prev) &&
2511
+ (!next || ((next.flags & 1024) && !(next.flags & 32))) &&
2512
+ (!prev || ((prev.flags & 1024) && !(prev.flags & 64)))) {
2513
+ let widget = new WidgetTile(Widget.blockImg, null, 16 | 64, Widget.blockImg.render(this.wg));
2514
+ target.putChild(widget, i++);
2515
+ }
2516
+ if (!next)
2517
+ break;
2518
+ prev = next;
2433
2519
  }
2434
2520
  }
2435
2521
  up() {
2436
- this.ensureHackNode();
2522
+ this.ensureHackNodes();
2437
2523
  this.new = this.new.parent;
2438
2524
  }
2439
2525
  leaveNode() {
@@ -2492,8 +2578,10 @@ class ContentUpdate {
2492
2578
  prev = copy;
2493
2579
  prev.parent = cur;
2494
2580
  }
2495
- for (let j = i + 1; j < cur.children.length; j++)
2581
+ for (let j = i + 1; j < cur.children.length; j++) {
2496
2582
  prev.addChild(cur.children[j]);
2583
+ cur.children.splice(j, 1);
2584
+ }
2497
2585
  return prev;
2498
2586
  }
2499
2587
  return null;
@@ -2516,7 +2604,7 @@ class ContentUpdate {
2516
2604
  finish() {
2517
2605
  while (!(this.new instanceof DocTile))
2518
2606
  this.up();
2519
- this.ensureHackNode();
2607
+ this.ensureHackNodes();
2520
2608
  return this.new;
2521
2609
  }
2522
2610
  }
@@ -2635,36 +2723,28 @@ function flattenH(rect, top) {
2635
2723
  return rect.height ? new DOMRect(rect.left, top ? rect.top : rect.bottom, rect.width, 0) : rect;
2636
2724
  }
2637
2725
 
2638
- let nav = typeof navigator != "undefined" ? navigator : { userAgent: "", vendor: "", platform: "" };
2639
- let doc = typeof document != "undefined" ? document : { documentElement: { style: {} } };
2640
- const edge = /*@__PURE__*/(() => /Edge\/(\d+)/.exec(nav.userAgent))();
2641
- const gecko = /*@__PURE__*/(() => !edge && /gecko\/(\d+)/i.test(nav.userAgent))();
2642
- const chrome = /*@__PURE__*/(() => !edge && /Chrome\/(\d+)/.exec(nav.userAgent))();
2643
- const webkit = /*@__PURE__*/(() => "webkitFontSmoothing" in doc.documentElement.style)();
2644
- const safari = /*@__PURE__*/(() => !edge && /Apple Computer/.test(nav.vendor))();
2645
- const ios = /*@__PURE__*/(() => safari && (/Mobile\/\w+/.test(nav.userAgent) || nav.maxTouchPoints > 2))();
2646
- var browser = /*@__PURE__*/(() => ({
2647
- mac: ios || /Mac/.test(nav.platform),
2648
- windows: /Win/.test(nav.platform),
2649
- linux: /Linux|X11/.test(nav.platform),
2650
- gecko_version: gecko ? +(/Firefox\/(\d+)/.exec(nav.userAgent) || [0, 0])[1] : 0,
2651
- chrome: !!chrome,
2652
- chrome_version: chrome ? +chrome[1] : 0,
2653
- ios,
2654
- android: /Android\b/.test(nav.userAgent),
2655
- webkit,
2656
- webkit_version: webkit ? +(/\bAppleWebKit\/(\d+)/.exec(nav.userAgent) || [0, 0])[1] : 0,
2657
- safari,
2658
- safari_version: safari ? +(/\bVersion\/(\d+(\.\d+)?)/.exec(nav.userAgent) || [0, 0])[1] : 0}))();
2659
-
2660
- const clipboardOutputFilter = /*@__PURE__*/GardState.Facet.define();
2661
- const clipboardOutputHTMLFilter = /*@__PURE__*/GardState.Facet.define();
2662
- const clipboardTextSerializer = /*@__PURE__*/GardState.Facet.define();
2663
- const clipboardOutputTextFilter = /*@__PURE__*/GardState.Facet.define();
2664
- const clipboardInputFilter = /*@__PURE__*/GardState.Facet.define();
2665
- const clipboardInputHTMLFilter = /*@__PURE__*/GardState.Facet.define();
2666
- const clipboardTextParser = /*@__PURE__*/GardState.Facet.define();
2667
- const clipboardInputTextFilter = /*@__PURE__*/GardState.Facet.define();
2726
+ const clipboardOutputFilter = /*@__PURE__*/GardState.Facet.define({
2727
+ name: "clipboardOutputFilter"
2728
+ });
2729
+ const clipboardOutputHTMLFilter = /*@__PURE__*/GardState.Facet.define({
2730
+ name: "clipboardOutputHTMLFilter"
2731
+ });
2732
+ const clipboardTextSerializer = /*@__PURE__*/GardState.Facet.define({ name: "clipboardTextSerializer" });
2733
+ const clipboardOutputTextFilter = /*@__PURE__*/GardState.Facet.define({
2734
+ name: "clipboardOutputTextFilter"
2735
+ });
2736
+ const clipboardInputFilter = /*@__PURE__*/GardState.Facet.define({
2737
+ name: "clipboardInputFilter"
2738
+ });
2739
+ const clipboardInputHTMLFilter = /*@__PURE__*/GardState.Facet.define({
2740
+ name: "clipboardInputHTMLFilter"
2741
+ });
2742
+ const clipboardTextParser = /*@__PURE__*/GardState.Facet.define({
2743
+ name: "clipboardTextParser"
2744
+ });
2745
+ const clipboardInputTextFilter = /*@__PURE__*/GardState.Facet.define({
2746
+ name: "clipboardInputTextFilter"
2747
+ });
2668
2748
  function writeClipboard(state, slice, data) {
2669
2749
  for (let filter of state.facet(clipboardOutputFilter))
2670
2750
  slice = filter(slice, state);
@@ -2712,9 +2792,7 @@ function writeClipboard(state, slice, data) {
2712
2792
  function isOpen(elt) {
2713
2793
  return (elt.getAttribute("wg-open") || null);
2714
2794
  }
2715
- function readClipboard(state, data, targetContext, plain) {
2716
- let html = data.getData("text/html");
2717
- let text = data.getData("text/plain") || data.getData("Text") || data.getData("text/uri-list").replace(/\r?\n/g, " ");
2795
+ function readClipboard(state, html, text, targetContext, plain) {
2718
2796
  let slice;
2719
2797
  if (text && (targetContext.parent.node.type.hasRole(Node.Role.Code) || !html || plain)) {
2720
2798
  for (let filter of state.facet(clipboardInputTextFilter))
@@ -2812,8 +2890,12 @@ function restoreReplacedSpaces(dom) {
2812
2890
  }
2813
2891
  }
2814
2892
 
2815
- const theme$1 = /*@__PURE__*/GardState.Facet.define({ combine: strs => strs.join(" ") });
2893
+ const theme$1 = /*@__PURE__*/GardState.Facet.define({
2894
+ name: "theme",
2895
+ combine: strs => strs.join(" ")
2896
+ });
2816
2897
  const colorScheme = /*@__PURE__*/GardState.Facet.define({
2898
+ name: "colorScheme",
2817
2899
  combine: values => values.length ? values[0] : "light"
2818
2900
  });
2819
2901
  const styleID = /*@__PURE__*/StyleModule.newName(), baseLightID = /*@__PURE__*/StyleModule.newName(), baseDarkID = /*@__PURE__*/StyleModule.newName();
@@ -2841,7 +2923,7 @@ const baseStyles = /*@__PURE__*/buildTheme("." + styleID, {
2841
2923
  flexDirection: "column",
2842
2924
  border: "1px solid var(--wg-border-color)"
2843
2925
  },
2844
- "&:has(> wg-scroller > wg-content:focus)": {
2926
+ "&.wg-focused": {
2845
2927
  outline: "1px solid var(--wg-highlight-color)",
2846
2928
  "& > wg-scroller > wg-cursor-layer": {
2847
2929
  animation: "steps(1) wg-blink 1.2s infinite"
@@ -2918,6 +3000,9 @@ const baseStyles = /*@__PURE__*/buildTheme("." + styleID, {
2918
3000
  verticalAlign: "bottom",
2919
3001
  height: "1em",
2920
3002
  },
3003
+ ".wg-blockBuffer": {
3004
+ position: "absolute"
3005
+ },
2921
3006
  "wg-placeholder": {
2922
3007
  opacity: "0.6",
2923
3008
  display: "inline-block",
@@ -3068,15 +3153,15 @@ function rangeForClick(wg, pos, type) {
3068
3153
  if (target && target.type.isSelectable && wg.state.isAtom(target.type))
3069
3154
  return GardSelection.node(pos.target, target);
3070
3155
  }
3071
- if (type == 1) { return GardSelection.near(wg.state, pos.pos, pos.side || -1);
3156
+ if (type == 1) { return GardSelection.near(wg.state, pos.pos, pos.side);
3072
3157
  }
3073
- else if (type == 2) { return wg.state.wordAt(pos.pos, pos.side || 1);
3158
+ else if (type == 2) { return wg.state.wordAt(pos.pos, pos.side) || GardSelection.near(wg.state, pos.pos, pos.side);
3074
3159
  }
3075
3160
  else { let cx = wg.state.doc.resolve(pos.pos), block = cx.textblockParent;
3076
3161
  if (block)
3077
3162
  return GardSelection.undirectionalRange(block.start, block.end);
3078
3163
  else
3079
- return GardSelection.near(wg.state, pos.pos, pos.side || -1);
3164
+ return GardSelection.near(wg.state, pos.pos, pos.side);
3080
3165
  }
3081
3166
  }
3082
3167
  const Y_STEP = 2;
@@ -3361,6 +3446,7 @@ class DOMObserver {
3361
3446
  clear() {
3362
3447
  this.takeRecords();
3363
3448
  this.readSelectionRange();
3449
+ this.selectionChanged = false;
3364
3450
  }
3365
3451
  takeRecords() {
3366
3452
  for (let mut of this.observer.takeRecords())
@@ -3390,7 +3476,14 @@ class DOMObserver {
3390
3476
  return null;
3391
3477
  }
3392
3478
  else if (tile.dom == record.target) {
3393
- return [tile.posBefore, tile.posAfter];
3479
+ if (!tile.isNodeInner)
3480
+ return [tile.posBefore, tile.posAfter];
3481
+ while (tile.parent && tile.isNodeInner)
3482
+ tile = tile.parent;
3483
+ if (tile.isDoc)
3484
+ return null;
3485
+ let nodePos = tile.posBefore;
3486
+ return [nodePos, nodePos + 1];
3394
3487
  }
3395
3488
  else {
3396
3489
  return childRange(tile, record);
@@ -3444,6 +3537,7 @@ class KeyBinding {
3444
3537
  this.extension = KeyBinding.source.of(this);
3445
3538
  }
3446
3539
  static of(spec) { return new KeyBinding(spec); }
3540
+ toString() { return `KeyBinding:${this.spec.key || this.spec.char || "??"}`; }
3447
3541
  }
3448
3542
  ;KeyBinding = /*@__PURE__*/(function (KeyBinding) {
3449
3543
  function handle(wg, event) {
@@ -3456,9 +3550,11 @@ class KeyBinding {
3456
3550
  return s.facet(KeyBinding.useDefaultKeymap) ? bindings.concat(KeyBinding.defaultKeymap) : bindings;
3457
3551
  });
3458
3552
  KeyBinding.source = GardState.Facet.define({
3553
+ name: "keyBinding",
3459
3554
  enables: KeyBinding.keymap
3460
3555
  });
3461
3556
  KeyBinding.useDefaultKeymap = GardState.Facet.define({
3557
+ name: "useDefaultKeymap",
3462
3558
  combine: input => input.length ? input[0] : true
3463
3559
  });
3464
3560
  class Group {
@@ -3615,7 +3711,7 @@ class NormalizedBinding {
3615
3711
  }
3616
3712
  const keymapCache = /*@__PURE__*/(() => new WeakMap())();
3617
3713
  function getKeymap(state) {
3618
- let bindings = state.field(KeyBinding.keymap);
3714
+ let bindings = state.field(KeyBinding.keymap, false);
3619
3715
  let found = keymapCache.get(bindings);
3620
3716
  if (!found)
3621
3717
  keymapCache.set(bindings, found = buildKeymap(bindings, currentPlatform));
@@ -3704,6 +3800,7 @@ function buildCharKeyCodes() {
3704
3800
  const charKeyCodes = /*@__PURE__*/buildCharKeyCodes();
3705
3801
 
3706
3802
  const eventHandler = /*@__PURE__*/GardState.Facet.define({
3803
+ name: "eventHandler",
3707
3804
  combine: handlers => {
3708
3805
  let result = Object.create(null);
3709
3806
  for (let { event, handler } of handlers)
@@ -3712,6 +3809,7 @@ const eventHandler = /*@__PURE__*/GardState.Facet.define({
3712
3809
  }
3713
3810
  });
3714
3811
  const eventObserver = /*@__PURE__*/GardState.Facet.define({
3812
+ name: "eventObserver",
3715
3813
  combine: observers => {
3716
3814
  let result = Object.create(null);
3717
3815
  for (let { event, observer } of observers)
@@ -3899,22 +3997,18 @@ class InputState {
3899
3997
  Command.dispatch(wg, insertText, { from, to, insert, userEvent: "input.type" });
3900
3998
  }
3901
3999
  else if (type == "insertFromPaste") {
3902
- let { from, to } = this.unflushedSelection ? wg.state.selection.replacementRange : range;
3903
- let slice = readClipboard(wg.state, event.dataTransfer, wg.state.doc.resolve(from), wg.inputState.shiftKey);
3904
- let isSel = from == wg.state.selection.replacementRange.from && to == wg.state.selection.replacementRange.to;
3905
- if (isSel && wg.state.facet(pasteHandler).some(h => h(wg, event, slice || Slice.empty)))
3906
- return;
3907
- if (slice) {
3908
- wg.dispatch({
3909
- changes: { from, to, insert: slice, fit: true },
3910
- selection: isSel ? (cx, changes) => GardSelection.near(cx, changes.mapPos(to, 1), -1) : undefined,
3911
- userEvent: "input.paste",
3912
- scrollIntoView: isSel
3913
- });
4000
+ let isSel = this.unflushedSelection;
4001
+ if (!isSel) {
4002
+ let r = data.domRange.range, domSel = getSelectionRange(wg.root);
4003
+ isSel = !!domSel && isEquivalentPosition(r.startContainer, r.startOffset, domSel.startContainer, domSel.startOffset) &&
4004
+ isEquivalentPosition(r.endContainer, r.endOffset, domSel.endContainer, domSel.endOffset);
3914
4005
  }
4006
+ let transfer = event.dataTransfer;
4007
+ doPaste(wg, getHTML(transfer), getText(transfer), isSel ? null : range, event);
3915
4008
  }
3916
4009
  else if ((type == "insertReplacementText" || type == "insertFromYank")) {
3917
- let read = readClipboard(wg.state, event.dataTransfer, wg.state.sel.head, true);
4010
+ let transfer = event.dataTransfer;
4011
+ let read = readClipboard(wg.state, getHTML(transfer), getText(transfer), wg.state.sel.head, true);
3918
4012
  let { from, to } = this.unflushedSelection ? wg.state.selection : range;
3919
4013
  let sel = wg.state.selection, touchesSel = from <= sel.to && to >= sel.from;
3920
4014
  if (read)
@@ -4054,6 +4148,12 @@ class InputState {
4054
4148
  this.mouseSelection.disconnect();
4055
4149
  }
4056
4150
  }
4151
+ function getHTML(data) {
4152
+ return data.getData("text/html");
4153
+ }
4154
+ function getText(data) {
4155
+ return data.getData("text/plain") || data.getData("Text") || data.getData("text/uri-list").replace(/\r?\n/g, " ");
4156
+ }
4057
4157
  function isSingleChar(doc, from, to) {
4058
4158
  if (to > from + 10)
4059
4159
  return false;
@@ -4092,8 +4192,22 @@ function computeHandlers(state) {
4092
4192
  record(type).observers.push(baseObservers[type]);
4093
4193
  return result;
4094
4194
  }
4195
+ function doPaste(wg, html, text, targetRange, event) {
4196
+ let { from, to } = targetRange || wg.state.selection.replacementRange;
4197
+ let slice = readClipboard(wg.state, html, text, wg.state.doc.resolve(from), wg.inputState.shiftKey);
4198
+ if (!targetRange && wg.state.facet(pasteHandler).some(h => h(wg, event, slice || Slice.empty, text, html)))
4199
+ return;
4200
+ if (slice) {
4201
+ wg.dispatch({
4202
+ changes: { correct: { from, to, insert: slice, fit: true }, local: true },
4203
+ selection: targetRange ? undefined : (cx, changes) => GardSelection.near(cx, changes.mapPos(to, 1), -1),
4204
+ userEvent: "input.paste",
4205
+ scrollIntoView: !targetRange
4206
+ });
4207
+ }
4208
+ }
4095
4209
  const dragScrollMargin = 6;
4096
- const mouseSelectionStyle = /*@__PURE__*/GardState.Facet.define();
4210
+ const mouseSelectionStyle = /*@__PURE__*/GardState.Facet.define({ name: "mouseSelectionStyle" });
4097
4211
  function dragScrollSpeed(dist) {
4098
4212
  return Math.max(0, dist) * 0.7 + 8;
4099
4213
  }
@@ -4207,7 +4321,7 @@ class MouseSelection {
4207
4321
  setTimeout(() => this.select(this.lastEvent), 20);
4208
4322
  }
4209
4323
  }
4210
- const dragBehavior = /*@__PURE__*/GardState.Facet.define();
4324
+ const dragBehavior = /*@__PURE__*/GardState.Facet.define({ name: "dragBehavior" });
4211
4325
  function dragMovesSelection(wg, event) {
4212
4326
  let facet = wg.state.facet(dragBehavior);
4213
4327
  return facet.length ? facet[0](event) : browser.mac ? !event.altKey : !event.ctrlKey;
@@ -4283,8 +4397,8 @@ function basicMouseSelection(wg, event) {
4283
4397
  }
4284
4398
  };
4285
4399
  }
4286
- const dropHandler = /*@__PURE__*/GardState.Facet.define();
4287
- const pasteHandler = /*@__PURE__*/GardState.Facet.define();
4400
+ const dropHandler = /*@__PURE__*/GardState.Facet.define({ name: "dropHandler" });
4401
+ const pasteHandler = /*@__PURE__*/GardState.Facet.define({ name: "pasteHandler" });
4288
4402
  function copy(wg, event) {
4289
4403
  let { state } = wg;
4290
4404
  if (!state.selection.empty && event.clipboardData) {
@@ -4300,7 +4414,7 @@ function copy(wg, event) {
4300
4414
  }
4301
4415
  return true;
4302
4416
  }
4303
- const isFocusChange = /*@__PURE__*/Transaction.Annotation.define();
4417
+ const isFocusChange = /*@__PURE__*/Transaction.Annotation.define("focusChange");
4304
4418
  function updateForFocusChange(wg) {
4305
4419
  setTimeout(() => {
4306
4420
  let focus = wg.hasFocus;
@@ -4434,18 +4548,19 @@ const baseHandlers = {
4434
4548
  copy,
4435
4549
  cut: copy,
4436
4550
  drop(wg, event) {
4437
- if (!event.dataTransfer || wg.state.readOnly)
4551
+ let data = event.dataTransfer;
4552
+ if (!data || wg.state.readOnly)
4438
4553
  return true;
4439
- let slice = readClipboard(wg.state, event.dataTransfer, wg.state.sel.head, false);
4554
+ let slice = readClipboard(wg.state, getHTML(data), getText(data), wg.state.sel.head, false);
4440
4555
  if (!slice)
4441
4556
  return false;
4442
4557
  let dropPos = wg.posAtCoords({ x: event.clientX, y: event.clientY }).pos;
4443
4558
  let { draggedContent } = wg.inputState;
4444
4559
  let del = draggedContent && dragMovesSelection(wg, event)
4445
- ? { from: draggedContent.from, to: draggedContent.to } : null;
4446
- if (wg.state.facet(dropHandler).some(f => f(wg, event, dropPos, del, slice)))
4560
+ ? { correct: { from: draggedContent.from, to: draggedContent.to }, local: true } : null;
4561
+ if (wg.state.facet(dropHandler).some(f => f(wg, event, dropPos, del ? del.correct : null, slice)))
4447
4562
  return true;
4448
- let ins = { from: dropPos, insert: slice, fit: true };
4563
+ let ins = { correct: { from: dropPos, insert: slice, fit: true }, local: true };
4449
4564
  let changes = ChangeSet.create(wg.state.doc, del ? [del, ins] : ins);
4450
4565
  wg.focus();
4451
4566
  wg.dispatch({
@@ -4471,7 +4586,7 @@ const baseHandlers = {
4471
4586
  if (ranges.length) {
4472
4587
  let r = ranges[0], empty = r.collapsed;
4473
4588
  let from = wg.inputState.getDOMPos(r.startContainer, r.startOffset);
4474
- data.domRange = { from, to: empty ? from : wg.inputState.getDOMPos(r.endContainer, r.endOffset) };
4589
+ data.domRange = { from, to: empty ? from : wg.inputState.getDOMPos(r.endContainer, r.endOffset), range: r };
4475
4590
  editable = inEditableDOM(wg, r.startContainer) && (empty || inEditableDOM(wg, r.endContainer));
4476
4591
  }
4477
4592
  wg.inputState.beforeInput(event, wg.inputState.pendingInputEvent = data);
@@ -4488,7 +4603,8 @@ const baseHandlers = {
4488
4603
  wg.inputState.pendingInputEvent = null;
4489
4604
  let change;
4490
4605
  if (compositionInputTypes.has(event.inputType) || event.inputType == "insertText") {
4491
- change = { from: pending.domRange.from, to: pending.domRange.to, insert: [Leaf.text(pending.data || "")] };
4606
+ let text = pending.data || "";
4607
+ change = { from: pending.domRange.from, to: pending.domRange.to, insert: text ? [Leaf.text(text)] : undefined };
4492
4608
  }
4493
4609
  else if (isDeletionInputEvent(event.inputType)) {
4494
4610
  change = { from: pending.domRange.from, to: pending.domRange.to };
@@ -4527,7 +4643,10 @@ const baseObservers = {
4527
4643
  }
4528
4644
  };
4529
4645
 
4530
- const scrollIntoView = /*@__PURE__*/Transaction.Effect.define({ map: (t, ch) => t.map(ch) });
4646
+ const scrollIntoView = /*@__PURE__*/Transaction.Effect.define({
4647
+ name: "scrollIntoView",
4648
+ map: (t, ch) => t.map(ch)
4649
+ });
4531
4650
  const selectionScrollSpec = {
4532
4651
  x: "nearest",
4533
4652
  y: "nearest",
@@ -4629,6 +4748,7 @@ class ViewState {
4629
4748
  }
4630
4749
 
4631
4750
  const cursorBlinkRate = /*@__PURE__*/GardState.Facet.define({
4751
+ name: "cursorBlinkRate",
4632
4752
  combine: inputs => inputs.length ? Math.min(...inputs) : 1200
4633
4753
  });
4634
4754
  class CursorStyle {
@@ -4815,7 +4935,7 @@ function setBlinkRate(state, dom) {
4815
4935
  dom.style.animationDuration = state.facet(cursorBlinkRate) + "ms";
4816
4936
  }
4817
4937
 
4818
- const dirCompartment = /*@__PURE__*/GardState.Compartment.define();
4938
+ const dirCompartment = /*@__PURE__*/GardState.Compartment.define("direction");
4819
4939
  class Wordgard {
4820
4940
  static create(spec) { return new Wordgard(spec); }
4821
4941
  get state() { return this.viewState.state; }
@@ -5053,12 +5173,12 @@ class Wordgard {
5053
5173
  }
5054
5174
  for (let i = 0; i < this.plugins.length; i++)
5055
5175
  this.plugins[i].update(this);
5056
- if (configChange)
5176
+ if (update.state.facet(eventHandler) != update.startState.facet(eventHandler))
5057
5177
  this.inputState.ensureHandlers(update.state);
5058
5178
  }
5059
5179
  updateAttrs() {
5060
5180
  let editorAttrs = attrsFromFacet(this, Wordgard.editorAttributes, [
5061
- "class", this.themeClasses
5181
+ "class", this.themeClasses + (this.inputState.notifiedFocused ? " wg-focused" : "")
5062
5182
  ]);
5063
5183
  let contentAttrs = attrsFromFacet(this, Wordgard.contentAttributes, [
5064
5184
  "aria-multiline", "true",
@@ -5202,7 +5322,7 @@ class Wordgard {
5202
5322
  }));
5203
5323
  }
5204
5324
  static label(label) {
5205
- return Wordgard.editorAttributes.of(typeof label == "string" ? { "aria-label": label }
5325
+ return Wordgard.contentAttributes.of(typeof label == "string" ? { "aria-label": label }
5206
5326
  : (wg => ({ "aria-label": label(wg.state) })));
5207
5327
  }
5208
5328
  static clipboardOutputFilter = clipboardOutputFilter;
@@ -5214,18 +5334,21 @@ class Wordgard {
5214
5334
  static clipboardTextParser = clipboardTextParser;
5215
5335
  static clipboardInputTextFilter = clipboardInputTextFilter;
5216
5336
  static pasteHandler = pasteHandler;
5337
+ paste(html, text) { doPaste(this, html, text || "", null, null); }
5217
5338
  static dropHandler = dropHandler;
5218
5339
  static isFocusChange = isFocusChange;
5219
- static styleModule = /*@__PURE__*/GardState.Facet.define();
5340
+ static styleModule = /*@__PURE__*/GardState.Facet.define({ name: "styleModule" });
5220
5341
  static domEventHandler(event, handler) {
5221
5342
  return eventHandler.of({ event, handler: handler });
5222
5343
  }
5223
5344
  static domEventObserver(event, observer) {
5224
5345
  return eventObserver.of({ event, observer: observer });
5225
5346
  }
5226
- static scrollHandler = /*@__PURE__*/GardState.Facet.define();
5347
+ static scrollHandler = /*@__PURE__*/GardState.Facet.define({ name: "scrollHandler" });
5227
5348
  static exceptionSink = exceptionSink;
5228
- static transactionListener = /*@__PURE__*/GardState.Facet.define();
5349
+ static transactionListener = /*@__PURE__*/GardState.Facet.define({
5350
+ name: "transactionListener"
5351
+ });
5229
5352
  runTransactionListeners(trs) {
5230
5353
  for (let l of this.state.facet(Wordgard.transactionListener)) {
5231
5354
  let has = this.pendingTransactionListeners.get(l);
@@ -5240,8 +5363,11 @@ class Wordgard {
5240
5363
  next.value(trs, this);
5241
5364
  }
5242
5365
  }
5243
- static updateListener = /*@__PURE__*/GardState.Facet.define();
5244
- static editable = /*@__PURE__*/GardState.Facet.define({ combine: values => values.length ? values[0] : true });
5366
+ static updateListener = /*@__PURE__*/GardState.Facet.define({ name: "updateListener" });
5367
+ static editable = /*@__PURE__*/GardState.Facet.define({
5368
+ name: "editable",
5369
+ combine: values => values.length ? values[0] : true
5370
+ });
5245
5371
  static cursorBlinkRate = cursorBlinkRate;
5246
5372
  static mouseSelectionStyle = mouseSelectionStyle;
5247
5373
  static dragMovesSelection = dragBehavior;
@@ -5289,12 +5415,19 @@ class Wordgard {
5289
5415
  }
5290
5416
  });
5291
5417
  }
5292
- static cspNonce = /*@__PURE__*/GardState.Facet.define({ combine: values => values.length ? values[0] : "" });
5293
- static contentAttributes = /*@__PURE__*/GardState.Facet.define();
5294
- static editorAttributes = /*@__PURE__*/GardState.Facet.define();
5295
- static announce = /*@__PURE__*/Transaction.Effect.define();
5418
+ static cspNonce = /*@__PURE__*/GardState.Facet.define({
5419
+ name: "cspNonce",
5420
+ combine: values => values.length ? values[0] : ""
5421
+ });
5422
+ static contentAttributes = /*@__PURE__*/GardState.Facet.define({ name: "contentAttributes" });
5423
+ static editorAttributes = /*@__PURE__*/GardState.Facet.define({ name: "editorAttributes" });
5424
+ static announce = /*@__PURE__*/Transaction.Effect.define({ name: "announce" });
5296
5425
  static DocTile = DocTile;
5297
- static coveredMargins = /*@__PURE__*/GardState.Facet.define();
5426
+ static coveredMargins = /*@__PURE__*/GardState.Facet.define({ name: "coveredMargins" });
5427
+ static findFromDOM(elt) {
5428
+ let wg = elt.wg;
5429
+ return wg instanceof Wordgard ? wg : null;
5430
+ }
5298
5431
  }
5299
5432
  let _wrapElement = null;
5300
5433
  function wrapElementConstructor() {
@@ -5416,7 +5549,7 @@ function attrsFromFacet(wg, facet, base) {
5416
5549
  }
5417
5550
  Wordgard.Update = Update;
5418
5551
  ;return Wordgard})(Wordgard);
5419
- const editorPlugin = /*@__PURE__*/GardState.Facet.define();
5552
+ const editorPlugin = /*@__PURE__*/GardState.Facet.define({ name: "editorPlugin" });
5420
5553
  const cursorPlugin = /*@__PURE__*/Wordgard.Plugin.fromClass(CursorLayer);
5421
5554
  class PluginInstance {
5422
5555
  spec;
@@ -5579,6 +5712,7 @@ class TooltipViewManager {
5579
5712
  }
5580
5713
  }
5581
5714
  const tooltipConfig = /*@__PURE__*/GardState.Facet.define({
5715
+ name: "tooltipConfig",
5582
5716
  combine: values => ({
5583
5717
  position: browser.ios ? "absolute" : values.find(conf => conf.position)?.position || "fixed",
5584
5718
  parent: values.find(conf => conf.parent)?.parent || null,
@@ -5890,13 +6024,14 @@ const styles = /*@__PURE__*/Wordgard.styles({
5890
6024
  },
5891
6025
  },
5892
6026
  });
5893
- const closeHoverTooltipEffect = /*@__PURE__*/Transaction.Effect.define();
6027
+ const closeHoverTooltipEffect = /*@__PURE__*/Transaction.Effect.define({ name: "closeHover" });
5894
6028
  const Tooltip = /*@__PURE__*/(function (Tooltip) {
5895
6029
  function configure(config = {}) {
5896
6030
  return tooltipConfig.of(config);
5897
6031
  }
5898
6032
  Tooltip.configure = configure;
5899
6033
  Tooltip.show = GardState.Facet.define({
6034
+ name: "tooltip",
5900
6035
  enables: [tooltipPlugin, styles]
5901
6036
  });
5902
6037
  function get(wg, tooltip) {
@@ -5968,6 +6103,7 @@ const Tooltip = /*@__PURE__*/(function (Tooltip) {
5968
6103
  ;return Tooltip})({});
5969
6104
  const noOffset = { x: 0, y: 0 };
5970
6105
  const showHoverTooltip = /*@__PURE__*/GardState.Facet.define({
6106
+ name: "showHoverTooltip",
5971
6107
  combine: inputs => inputs.reduce((a, i) => a.concat(i), [])
5972
6108
  });
5973
6109
  class HoverTooltipHost {
@@ -6320,9 +6456,10 @@ class OpenDialog {
6320
6456
  this.offset = offset;
6321
6457
  }
6322
6458
  }
6323
- const openDialog = /*@__PURE__*/Transaction.Effect.define();
6324
- const closeDialog = /*@__PURE__*/Transaction.Effect.define();
6459
+ const openDialog = /*@__PURE__*/Transaction.Effect.define({ name: "openDialog" });
6460
+ const closeDialog = /*@__PURE__*/Transaction.Effect.define({ name: "closeDialog" });
6325
6461
  const dialogs = /*@__PURE__*/GardState.Field.define({
6462
+ name: "dialogs",
6326
6463
  create: () => [],
6327
6464
  update: (value, tr) => {
6328
6465
  for (let e of tr.effects) {
@@ -6613,6 +6750,7 @@ function decoratePlots(config) {
6613
6750
  }
6614
6751
 
6615
6752
  const panelConfig = /*@__PURE__*/GardState.Facet.define({
6753
+ name: "panelConfig",
6616
6754
  combine(configs) {
6617
6755
  let topContainer, bottomContainer;
6618
6756
  for (let c of configs) {
@@ -6704,6 +6842,7 @@ const panelPlugin = /*@__PURE__*/Wordgard.Plugin.fromClass(class {
6704
6842
  }));
6705
6843
  const Panel = /*@__PURE__*/(function (Panel) {
6706
6844
  Panel.show = GardState.Facet.define({
6845
+ name: "panel",
6707
6846
  enables: panelPlugin
6708
6847
  });
6709
6848
  function get(wg, constructor) {
@@ -7318,6 +7457,7 @@ const theme = /*@__PURE__*/Wordgard.styles({
7318
7457
  },
7319
7458
  });
7320
7459
  const barTemplate = /*@__PURE__*/GardState.Facet.define({
7460
+ name: "menuBarTemplate",
7321
7461
  combine: inputs => inputs.length ? inputs[0] : [Menu.Group.top.template()]
7322
7462
  });
7323
7463
  function menuBar(config = {}) {
@@ -7327,7 +7467,7 @@ function menuBar(config = {}) {
7327
7467
  return extensions;
7328
7468
  }
7329
7469
 
7330
- const inputRule = /*@__PURE__*/GardState.Facet.define();
7470
+ const inputRule = /*@__PURE__*/GardState.Facet.define({ name: "inputRule" });
7331
7471
  const appender = /*@__PURE__*/Transaction.appender.of(applyInputRules);
7332
7472
  class InputRule {
7333
7473
  expr;
@@ -7383,13 +7523,14 @@ class InputRule {
7383
7523
  lookahead: empty ? /^$/ : undefined
7384
7524
  });
7385
7525
  }
7526
+ toString() { return `InputRule(${this.expr})`; }
7386
7527
  }
7387
7528
  ;InputRule = /*@__PURE__*/(function (InputRule) {
7388
7529
  InputRule.emDash = InputRule.define({ expr: /--$/, apply: "—" });
7389
7530
  InputRule.ellipsis = InputRule.define({ expr: /\.\.\.$/, apply: "…" });
7390
- InputRule.openDoubleQuote = InputRule.define({ expr: /(?:^|[\s\{\[\(\<'"\u2018\u201C])(")$/, apply: "“" });
7531
+ InputRule.openDoubleQuote = InputRule.define({ expr: /(?<=^|[\s\{\[\(\<'"\u2018\u201C])"$/, apply: "“" });
7391
7532
  InputRule.closeDoubleQuote = InputRule.define({ expr: /"$/, apply: "”" });
7392
- InputRule.openSingleQuote = InputRule.define({ expr: /(?:^|[\s\{\[\(\<'"\u2018\u201C])(')$/, apply: "‘" });
7533
+ InputRule.openSingleQuote = InputRule.define({ expr: /(?<=^|[\s\{\[\(\<'"\u2018\u201C])'$/, apply: "‘" });
7393
7534
  InputRule.closeSingleQuote = InputRule.define({ expr: /'$/, apply: "’" });
7394
7535
  InputRule.smartQuotes = [InputRule.openDoubleQuote, InputRule.closeDoubleQuote, InputRule.openSingleQuote, InputRule.closeSingleQuote];
7395
7536
  ;return InputRule})(InputRule);
@@ -7401,7 +7542,7 @@ function ensureAnchor(regexp) {
7401
7542
  }
7402
7543
  function applyString(text) {
7403
7544
  return (state, match) => ({
7404
- changes: { from: match[0].from.pos, to: match[0].to.pos, insert: [Leaf.text(text)] },
7545
+ changes: { from: match[0].from.pos, to: match[0].to.pos, insert: text ? [Leaf.text(text)] : undefined },
7405
7546
  annotations: history.isolate.of(true)
7406
7547
  });
7407
7548
  }
@@ -7473,7 +7614,7 @@ const placeholderWidget = /*@__PURE__*/Widget.define({
7473
7614
  return elt;
7474
7615
  }
7475
7616
  });
7476
- const placeholderShape = /*@__PURE__*/GardState.Facet.define();
7617
+ const placeholderShape = /*@__PURE__*/GardState.Facet.define({ name: "placeholderShape" });
7477
7618
  function showPlaceholder(state) {
7478
7619
  let pos = -1;
7479
7620
  if (state.doc.length == 0)
@@ -7488,6 +7629,7 @@ function showPlaceholder(state) {
7488
7629
  return Decoration.Point.set([[Decoration.Point.widget(placeholderWidget.of(shape[0]), { side: 1 }), pos]]);
7489
7630
  }
7490
7631
  const placeholderField = /*@__PURE__*/GardState.Field.define({
7632
+ name: "placeholder",
7491
7633
  create(state) {
7492
7634
  return showPlaceholder(state);
7493
7635
  },
@@ -7504,9 +7646,11 @@ function placeholder(content) {
7504
7646
  }
7505
7647
 
7506
7648
  const setDropCursorPos = /*@__PURE__*/Transaction.Effect.define({
7649
+ name: "setDropCursorPos",
7507
7650
  map(pos, mapping) { return pos == null ? null : { pos: mapping.mapPos(pos.pos), side: pos.side }; }
7508
7651
  });
7509
7652
  const dropCursorPos = /*@__PURE__*/GardState.Field.define({
7653
+ name: "dropCursorPos",
7510
7654
  create() { return null; },
7511
7655
  update(pos, tr) {
7512
7656
  if (pos != null)