@ni/ok-components 1.10.0 → 1.10.2

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.
@@ -20872,18 +20872,27 @@ Defines an interaction area clip-path that leaves out the severity text so it is
20872
20872
  }
20873
20873
 
20874
20874
  .icon {
20875
- width: 48px;
20876
- display: flex;
20877
- justify-content: center;
20878
- margin-top: 8px;
20875
+ display: none;
20876
+ margin: 8px ${smallPadding} 0 ${standardPadding};
20879
20877
  flex: 0 0 auto;
20880
20878
  opacity: 0.6;
20881
20879
  }
20882
20880
 
20881
+ :host([severity='error']) .icon,
20882
+ :host([severity='warning']) .icon,
20883
+ :host([severity='information']) .icon {
20884
+ display: flex;
20885
+ }
20886
+
20883
20887
  .text {
20884
20888
  display: inline;
20885
- margin-top: 7px;
20886
- margin-bottom: 7px;
20889
+ margin: 7px 0 7px ${standardPadding};
20890
+ }
20891
+
20892
+ :host([severity='error']) .text,
20893
+ :host([severity='warning']) .text,
20894
+ :host([severity='information']) .text {
20895
+ margin-left: 0;
20887
20896
  }
20888
20897
 
20889
20898
  slot[name='title'] {
@@ -20914,14 +20923,20 @@ Defines an interaction area clip-path that leaves out the severity text so it is
20914
20923
  white-space: nowrap;
20915
20924
  }
20916
20925
 
20926
+ :host([prevent-dismiss]) slot[name='action'] {
20927
+ margin-right: 12px;
20928
+ }
20929
+
20917
20930
  slot[name='action']::slotted(nimble-anchor) {
20918
20931
  font-size: 12.8px;
20919
20932
  }
20920
20933
 
20921
20934
  .dismiss {
20922
- width: 48px;
20923
- display: flex;
20924
- justify-content: center;
20935
+ margin: 0 12px 0 ${standardPadding};
20936
+ }
20937
+
20938
+ :host([prevent-dismiss]) .dismiss {
20939
+ display: none;
20925
20940
  }
20926
20941
  `.withBehaviors(themeBehavior(Theme.light, css `
20927
20942
  :host {
@@ -29805,7 +29820,6 @@ so this becomes the fallback color for the slot */ ''}
29805
29820
  if (!type)
29806
29821
  throw new RangeError(`There is no mark type ${json.type} in this schema`);
29807
29822
  let mark = type.create(json.attrs);
29808
- type.checkAttrs(mark.attrs);
29809
29823
  return mark;
29810
29824
  }
29811
29825
  /**
@@ -30785,11 +30799,11 @@ so this becomes the fallback color for the slot */ ''}
30785
30799
  */
30786
30800
  check() {
30787
30801
  this.type.checkContent(this.content);
30788
- this.type.checkAttrs(this.attrs);
30802
+ checkAttrs(this.type.attrs, this.attrs, "node", this.type.name);
30789
30803
  let copy = Mark$1.none;
30790
30804
  for (let i = 0; i < this.marks.length; i++) {
30791
30805
  let mark = this.marks[i];
30792
- mark.type.checkAttrs(mark.attrs);
30806
+ checkAttrs(mark.type.attrs, mark.attrs, "mark", mark.type.name);
30793
30807
  copy = mark.addToSet(copy);
30794
30808
  }
30795
30809
  if (!Mark$1.sameSet(copy, this.marks))
@@ -30830,7 +30844,6 @@ so this becomes the fallback color for the slot */ ''}
30830
30844
  }
30831
30845
  let content = Fragment.fromJSON(schema, json.content);
30832
30846
  let node = schema.nodeType(json.type).create(json.attrs, content, marks);
30833
- node.type.checkAttrs(node.attrs);
30834
30847
  return node;
30835
30848
  }
30836
30849
  };
@@ -30880,6 +30893,15 @@ so this becomes the fallback color for the slot */ ''}
30880
30893
  str = marks[i].type.name + "(" + str + ")";
30881
30894
  return str;
30882
30895
  }
30896
+ function checkAttrs(attrs, values, type, name) {
30897
+ for (let attr in values)
30898
+ if (!(attr in attrs))
30899
+ throw new RangeError(`Unsupported attribute ${attr} for ${type} of type ${name}`);
30900
+ for (let attr in attrs) {
30901
+ if (attrs[attr].validate)
30902
+ attrs[attr].validate(values[attr]);
30903
+ }
30904
+ }
30883
30905
 
30884
30906
  /**
30885
30907
  Instances of this class represent a match state of a node type's
@@ -31334,27 +31356,21 @@ so this becomes the fallback color for the slot */ ''}
31334
31356
  function computeAttrs(attrs, value) {
31335
31357
  let built = Object.create(null);
31336
31358
  for (let name in attrs) {
31359
+ let attr = attrs[name];
31337
31360
  let given = value && value[name];
31338
31361
  if (given === undefined) {
31339
- let attr = attrs[name];
31340
31362
  if (attr.hasDefault)
31341
31363
  given = attr.default;
31342
31364
  else
31343
31365
  throw new RangeError("No value supplied for attribute " + name);
31344
31366
  }
31367
+ else if (attr.validate) {
31368
+ attr.validate(given);
31369
+ }
31345
31370
  built[name] = given;
31346
31371
  }
31347
31372
  return built;
31348
31373
  }
31349
- function checkAttrs(attrs, values, type, name) {
31350
- for (let attr in values)
31351
- if (!(attr in attrs))
31352
- throw new RangeError(`Unsupported attribute ${attr} for ${type} of type ${name}`);
31353
- for (let attr in attrs) {
31354
- if (attrs[attr].validate)
31355
- attrs[attr].validate(values[attr]);
31356
- }
31357
- }
31358
31374
  function initAttrs(typeName, attrs) {
31359
31375
  let result = Object.create(null);
31360
31376
  if (attrs)
@@ -31526,11 +31542,9 @@ so this becomes the fallback color for the slot */ ''}
31526
31542
  throw new RangeError(`Invalid content for node ${this.name}: ${content.toString().slice(0, 50)}`);
31527
31543
  }
31528
31544
  /**
31529
- @internal
31545
+ @internal no longer useful, but called by old prosemirror-view versions
31530
31546
  */
31531
- checkAttrs(attrs) {
31532
- checkAttrs(this.attrs, attrs, "node", this.name);
31533
- }
31547
+ checkAttrs(attrs) { }
31534
31548
  /**
31535
31549
  Check whether the given mark type is allowed in this node.
31536
31550
  */
@@ -31677,12 +31691,6 @@ so this becomes the fallback color for the slot */ ''}
31677
31691
  return set[i];
31678
31692
  }
31679
31693
  /**
31680
- @internal
31681
- */
31682
- checkAttrs(attrs) {
31683
- checkAttrs(this.attrs, attrs, "mark", this.name);
31684
- }
31685
- /**
31686
31694
  Queries whether a given mark type is
31687
31695
  [excluded](https://prosemirror.net/docs/ref/#model.MarkSpec.excludes) by this one.
31688
31696
  */
@@ -32873,9 +32881,12 @@ so this becomes the fallback color for the slot */ ''}
32873
32881
  if (simple)
32874
32882
  return result;
32875
32883
  let recover = pos == (assoc < 0 ? start : end) ? null : makeRecover(i / 3, pos - start);
32876
- let del = pos == start ? DEL_AFTER : pos == end ? DEL_BEFORE : DEL_ACROSS;
32877
- if (assoc < 0 ? pos != start : pos != end)
32878
- del |= DEL_SIDE;
32884
+ let del = 0;
32885
+ if (oldSize) {
32886
+ del |= pos == start ? DEL_AFTER : pos == end ? DEL_BEFORE : DEL_ACROSS;
32887
+ if (assoc < 0 ? pos != start : pos != end)
32888
+ del |= DEL_SIDE;
32889
+ }
32879
32890
  return new MapResult(result, del, recover);
32880
32891
  }
32881
32892
  diff += newSize - oldSize;
@@ -36813,15 +36824,15 @@ so this becomes the fallback color for the slot */ ''}
36813
36824
  return true;
36814
36825
  if (off == (dir < 0 ? 0 : nodeSize(node))) {
36815
36826
  let parent = node.parentNode;
36816
- if (!parent || parent.nodeType != 1 || hasBlockDesc(node) || atomElements.test(node.nodeName) ||
36827
+ if (!parent || !isElt(parent) || hasBlockDesc(node) || atomElements.test(node.nodeName) ||
36817
36828
  node.contentEditable == "false")
36818
36829
  return false;
36819
36830
  off = domIndex(node) + (dir < 0 ? 0 : 1);
36820
36831
  node = parent;
36821
36832
  }
36822
- else if (node.nodeType == 1) {
36833
+ else if (isElt(node)) {
36823
36834
  let child = node.childNodes[off + (dir < 0 ? -1 : 0)];
36824
- if (child.nodeType == 1 && child.contentEditable == "false") {
36835
+ if (isElt(child) && child.contentEditable == "false") {
36825
36836
  if ((_a = child.pmViewDesc) === null || _a === void 0 ? void 0 : _a.ignoreForSelection)
36826
36837
  off += dir;
36827
36838
  else
@@ -36840,11 +36851,16 @@ so this becomes the fallback color for the slot */ ''}
36840
36851
  function nodeSize(node) {
36841
36852
  return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
36842
36853
  }
36854
+ function isElt(node) { return node.nodeType == 1; }
36855
+ function isText(node) { return node.nodeType == 3; }
36856
+ function contains(parent, child) {
36857
+ return child ? parent.contains(isElt(child) ? child : child.parentNode) : false;
36858
+ }
36843
36859
  function textNodeBefore$1(node, offset) {
36844
36860
  for (;;) {
36845
- if (node.nodeType == 3 && offset)
36861
+ if (isText(node) && offset)
36846
36862
  return node;
36847
- if (node.nodeType == 1 && offset > 0) {
36863
+ if (isElt(node) && offset > 0) {
36848
36864
  if (node.contentEditable == "false")
36849
36865
  return null;
36850
36866
  node = node.childNodes[offset - 1];
@@ -36861,9 +36877,9 @@ so this becomes the fallback color for the slot */ ''}
36861
36877
  }
36862
36878
  function textNodeAfter$1(node, offset) {
36863
36879
  for (;;) {
36864
- if (node.nodeType == 3 && offset < node.nodeValue.length)
36880
+ if (isText(node) && offset < node.nodeValue.length)
36865
36881
  return node;
36866
- if (node.nodeType == 1 && offset < node.childNodes.length) {
36882
+ if (isElt(node) && offset < node.childNodes.length) {
36867
36883
  if (node.contentEditable == "false")
36868
36884
  return null;
36869
36885
  node = node.childNodes[offset];
@@ -36987,13 +37003,12 @@ so this becomes the fallback color for the slot */ ''}
36987
37003
  for (let parent = startDOM || view.dom;;) {
36988
37004
  if (!parent)
36989
37005
  break;
36990
- if (parent.nodeType != 1) {
37006
+ if (!isElt(parent)) {
36991
37007
  parent = parentNode(parent);
36992
37008
  continue;
36993
37009
  }
36994
- let elt = parent;
36995
- let atTop = elt == doc.body;
36996
- let bounding = atTop ? windowRect(doc) : clientRect(elt);
37010
+ let atTop = parent == doc.body;
37011
+ let bounding = atTop ? windowRect(doc) : clientRect(parent);
36997
37012
  let moveX = 0, moveY = 0;
36998
37013
  if (rect.top < bounding.top + getSide$1(scrollThreshold, "top"))
36999
37014
  moveY = -(bounding.top - rect.top + getSide$1(scrollMargin, "top"));
@@ -37010,12 +37025,12 @@ so this becomes the fallback color for the slot */ ''}
37010
37025
  doc.defaultView.scrollBy(moveX, moveY);
37011
37026
  }
37012
37027
  else {
37013
- let startX = elt.scrollLeft, startY = elt.scrollTop;
37028
+ let startX = parent.scrollLeft, startY = parent.scrollTop;
37014
37029
  if (moveY)
37015
- elt.scrollTop += moveY;
37030
+ parent.scrollTop += moveY;
37016
37031
  if (moveX)
37017
- elt.scrollLeft += moveX;
37018
- let dX = elt.scrollLeft - startX, dY = elt.scrollTop - startY;
37032
+ parent.scrollLeft += moveX;
37033
+ let dX = parent.scrollLeft - startX, dY = parent.scrollTop - startY;
37019
37034
  rect = { left: rect.left - dX, top: rect.top - dY, right: rect.right - dX, bottom: rect.bottom - dY };
37020
37035
  }
37021
37036
  }
@@ -37090,14 +37105,15 @@ so this becomes the fallback color for the slot */ ''}
37090
37105
  }
37091
37106
  }
37092
37107
  function findOffsetInNode(node, coords) {
37093
- let closest, dxClosest = 2e8, coordsClosest, offset = 0;
37108
+ let closest;
37109
+ let dxClosest = 2e8, coordsClosest, offset = 0;
37094
37110
  let rowBot = coords.top, rowTop = coords.top;
37095
37111
  let firstBelow, coordsBelow;
37096
37112
  for (let child = node.firstChild, childIndex = 0; child; child = child.nextSibling, childIndex++) {
37097
37113
  let rects;
37098
- if (child.nodeType == 1)
37114
+ if (isElt(child))
37099
37115
  rects = child.getClientRects();
37100
- else if (child.nodeType == 3)
37116
+ else if (isText(child))
37101
37117
  rects = textRange(child).getClientRects();
37102
37118
  else
37103
37119
  continue;
@@ -37111,11 +37127,11 @@ so this becomes the fallback color for the slot */ ''}
37111
37127
  if (dx < dxClosest) {
37112
37128
  closest = child;
37113
37129
  dxClosest = dx;
37114
- coordsClosest = dx && closest.nodeType == 3 ? {
37130
+ coordsClosest = dx && isText(closest) ? {
37115
37131
  left: rect.right < coords.left ? rect.right : rect.left,
37116
37132
  top: coords.top
37117
37133
  } : coords;
37118
- if (child.nodeType == 1 && dx)
37134
+ if (isElt(child) && dx)
37119
37135
  offset = childIndex + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0);
37120
37136
  continue;
37121
37137
  }
@@ -37134,9 +37150,9 @@ so this becomes the fallback color for the slot */ ''}
37134
37150
  coordsClosest = coordsBelow;
37135
37151
  dxClosest = 0;
37136
37152
  }
37137
- if (closest && closest.nodeType == 3)
37153
+ if (closest && isText(closest))
37138
37154
  return findOffsetInText(closest, coordsClosest);
37139
- if (!closest || (dxClosest && closest.nodeType == 1))
37155
+ if (!closest || dxClosest)
37140
37156
  return { node, offset };
37141
37157
  return findOffsetInNode(closest, coordsClosest);
37142
37158
  }
@@ -37169,7 +37185,7 @@ so this becomes the fallback color for the slot */ ''}
37169
37185
  }
37170
37186
  function posFromElement(view, elt, coords) {
37171
37187
  let { node, offset } = findOffsetInNode(elt, coords), bias = -1;
37172
- if (node.nodeType == 1 && !node.firstChild) {
37188
+ if (isElt(node) && !node.firstChild) {
37173
37189
  let rect = node.getBoundingClientRect();
37174
37190
  bias = rect.left != rect.right && coords.left > (rect.left + rect.right) / 2 ? 1 : -1;
37175
37191
  }
@@ -37189,7 +37205,7 @@ so this becomes the fallback color for the slot */ ''}
37189
37205
  let desc = view.docView.nearestDesc(cur, true), rect;
37190
37206
  if (!desc)
37191
37207
  return null;
37192
- if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM) &&
37208
+ if (isElt(desc.dom) && (desc.node.isBlock && desc.parent || !desc.contentDOM) &&
37193
37209
  // Ignore elements with zero-size bounding rectangles
37194
37210
  ((rect = desc.dom.getBoundingClientRect()).width || rect.height)) {
37195
37211
  if (desc.node.isBlock && desc.parent && !/^T(R|BODY|HEAD|FOOT)$/.test(desc.dom.nodeName)) {
@@ -37216,7 +37232,7 @@ so this becomes the fallback color for the slot */ ''}
37216
37232
  if (len && box.top < box.bottom) {
37217
37233
  for (let startI = Math.max(0, Math.min(len - 1, Math.floor(len * (coords.top - box.top) / (box.bottom - box.top)) - 2)), i = startI;;) {
37218
37234
  let child = element.childNodes[i];
37219
- if (child.nodeType == 1) {
37235
+ if (isElt(child)) {
37220
37236
  let rects = child.getClientRects();
37221
37237
  for (let j = 0; j < rects.length; j++) {
37222
37238
  let rect = rects[j];
@@ -37239,7 +37255,7 @@ so this becomes the fallback color for the slot */ ''}
37239
37255
  let elt = (view.root.elementFromPoint ? view.root : doc)
37240
37256
  .elementFromPoint(coords.left, coords.top);
37241
37257
  let pos;
37242
- if (!elt || !view.dom.contains(elt.nodeType != 1 ? elt.parentNode : elt)) {
37258
+ if (!elt || !view.dom.contains(elt)) {
37243
37259
  let box = view.dom.getBoundingClientRect();
37244
37260
  if (!inRect(coords, box))
37245
37261
  return null;
@@ -37255,7 +37271,7 @@ so this becomes the fallback color for the slot */ ''}
37255
37271
  }
37256
37272
  elt = targetKludge(elt, coords);
37257
37273
  if (node) {
37258
- if (gecko && node.nodeType == 1) {
37274
+ if (gecko && isElt(node)) {
37259
37275
  // Firefox will sometimes return offsets into <input> nodes, which
37260
37276
  // have no actual children, from caretPositionFromPoint (#953)
37261
37277
  offset = Math.min(offset, node.childNodes.length);
@@ -37270,18 +37286,18 @@ so this becomes the fallback color for the slot */ ''}
37270
37286
  }
37271
37287
  let prev;
37272
37288
  // When clicking above the right side of an uneditable node, Chrome will report a cursor position after that node.
37273
- if (webkit && offset && node.nodeType == 1 && (prev = node.childNodes[offset - 1]).nodeType == 1 &&
37289
+ if (webkit && offset && isElt(node) && isElt(prev = node.childNodes[offset - 1]) &&
37274
37290
  prev.contentEditable == "false" && prev.getBoundingClientRect().top >= coords.top)
37275
37291
  offset--;
37276
37292
  // Suspiciously specific kludge to work around caret*FromPoint
37277
37293
  // never returning a position at the end of the document
37278
- if (node == view.dom && offset == node.childNodes.length - 1 && node.lastChild.nodeType == 1 &&
37294
+ if (node == view.dom && offset == node.childNodes.length - 1 && isElt(node.lastChild) &&
37279
37295
  coords.top > node.lastChild.getBoundingClientRect().bottom)
37280
37296
  pos = view.state.doc.content.size;
37281
37297
  // Ignore positions directly after a BR, since caret*FromPoint
37282
37298
  // 'round up' positions that would be more accurately placed
37283
37299
  // before the BR node.
37284
- else if (offset == 0 || node.nodeType != 1 || node.childNodes[offset - 1].nodeName != "BR")
37300
+ else if (offset == 0 || !isElt(node) || node.childNodes[offset - 1].nodeName != "BR")
37285
37301
  pos = posFromCaret(view, node, offset, coords);
37286
37302
  }
37287
37303
  if (pos == null)
@@ -37307,7 +37323,7 @@ so this becomes the fallback color for the slot */ ''}
37307
37323
  function coordsAtPos(view, pos, side) {
37308
37324
  let { node, offset, atom } = view.docView.domFromPos(pos, side < 0 ? -1 : 1);
37309
37325
  let supportEmptyRange = webkit || gecko;
37310
- if (node.nodeType == 3) {
37326
+ if (isText(node)) {
37311
37327
  // These browsers support querying empty text ranges. Prefer that in
37312
37328
  // bidi context or when at the end of a node.
37313
37329
  if (supportEmptyRange && (BIDI.test(node.nodeValue) || (side < 0 ? !offset : offset == node.nodeValue.length))) {
@@ -37349,12 +37365,12 @@ so this becomes the fallback color for the slot */ ''}
37349
37365
  if (!$dom.parent.inlineContent) {
37350
37366
  if (atom == null && offset && (side < 0 || offset == nodeSize(node))) {
37351
37367
  let before = node.childNodes[offset - 1];
37352
- if (before.nodeType == 1)
37368
+ if (isElt(before))
37353
37369
  return flattenH(before.getBoundingClientRect(), false);
37354
37370
  }
37355
37371
  if (atom == null && offset < nodeSize(node)) {
37356
37372
  let after = node.childNodes[offset];
37357
- if (after.nodeType == 1)
37373
+ if (isElt(after))
37358
37374
  return flattenH(after.getBoundingClientRect(), true);
37359
37375
  }
37360
37376
  return flattenH(node.getBoundingClientRect(), side >= 0);
@@ -37362,10 +37378,10 @@ so this becomes the fallback color for the slot */ ''}
37362
37378
  // Inline, not in text node (this is not Bidi-safe)
37363
37379
  if (atom == null && offset && (side < 0 || offset == nodeSize(node))) {
37364
37380
  let before = node.childNodes[offset - 1];
37365
- let target = before.nodeType == 3 ? textRange(before, nodeSize(before) - (supportEmptyRange ? 0 : 1))
37381
+ let target = isText(before) ? textRange(before, nodeSize(before) - (supportEmptyRange ? 0 : 1))
37366
37382
  // BR nodes tend to only return the rectangle before them.
37367
37383
  // Only use them if they are the last element in their parent
37368
- : before.nodeType == 1 && (before.nodeName != "BR" || !before.nextSibling) ? before : null;
37384
+ : isElt(before) && (before.nodeName != "BR" || !before.nextSibling) ? before : null;
37369
37385
  if (target)
37370
37386
  return flattenV(singleRect(target, 1), false);
37371
37387
  }
@@ -37373,13 +37389,13 @@ so this becomes the fallback color for the slot */ ''}
37373
37389
  let after = node.childNodes[offset];
37374
37390
  while (after.pmViewDesc && after.pmViewDesc.ignoreForCoords)
37375
37391
  after = after.nextSibling;
37376
- let target = !after ? null : after.nodeType == 3 ? textRange(after, 0, (supportEmptyRange ? 0 : 1))
37377
- : after.nodeType == 1 ? after : null;
37392
+ let target = !after ? null : isText(after) ? textRange(after, 0, (supportEmptyRange ? 0 : 1))
37393
+ : isElt(after) ? after : null;
37378
37394
  if (target)
37379
37395
  return flattenV(singleRect(target, -1), true);
37380
37396
  }
37381
37397
  // All else failed, just try to get a rectangle for the target node
37382
- return flattenV(singleRect(node.nodeType == 3 ? textRange(node) : node, -side), side >= 0);
37398
+ return flattenV(singleRect(isText(node) ? textRange(node) : node, -side), side >= 0);
37383
37399
  }
37384
37400
  function flattenV(rect, left) {
37385
37401
  if (rect.width == 0)
@@ -37429,9 +37445,9 @@ so this becomes the fallback color for the slot */ ''}
37429
37445
  let coords = coordsAtPos(view, $pos.pos, 1);
37430
37446
  for (let child = dom.firstChild; child; child = child.nextSibling) {
37431
37447
  let boxes;
37432
- if (child.nodeType == 1)
37448
+ if (isElt(child))
37433
37449
  boxes = child.getClientRects();
37434
- else if (child.nodeType == 3)
37450
+ else if (isText(child))
37435
37451
  boxes = textRange(child, 0, child.nodeValue.length).getClientRects();
37436
37452
  else
37437
37453
  continue;
@@ -37471,8 +37487,7 @@ so this becomes the fallback color for the slot */ ''}
37471
37487
  sel.modify("move", dir, "character");
37472
37488
  let parentDOM = $head.depth ? view.docView.domAfterPos($head.before()) : view.dom;
37473
37489
  let { focusNode: newNode, focusOffset: newOff } = view.domSelectionRange();
37474
- let result = newNode && !parentDOM.contains(newNode.nodeType == 1 ? newNode : newNode.parentNode) ||
37475
- (oldNode == newNode && oldOff == newOff);
37490
+ let result = newNode && !contains(parentDOM, newNode) || (oldNode == newNode && oldOff == newOff);
37476
37491
  // Restore the previous selection
37477
37492
  try {
37478
37493
  sel.collapse(anchorNode, anchorOffset);
@@ -37580,7 +37595,7 @@ so this becomes the fallback color for the slot */ ''}
37580
37595
  localPosFromDOM(dom, offset, bias) {
37581
37596
  // If the DOM position is in the content, use the child desc after
37582
37597
  // it to figure out a position.
37583
- if (this.contentDOM && this.contentDOM.contains(dom.nodeType == 1 ? dom : dom.parentNode)) {
37598
+ if (this.contentDOM && contains(this.contentDOM, dom)) {
37584
37599
  if (bias < 0) {
37585
37600
  let domBefore, desc;
37586
37601
  if (dom == this.contentDOM) {
@@ -37618,7 +37633,7 @@ so this becomes the fallback color for the slot */ ''}
37618
37633
  atEnd = offset > domIndex(this.contentDOM);
37619
37634
  }
37620
37635
  else if (this.contentDOM && this.contentDOM != this.dom && this.dom.contains(this.contentDOM)) {
37621
- atEnd = dom.compareDocumentPosition(this.contentDOM) & 2;
37636
+ atEnd = !!(dom.compareDocumentPosition(this.contentDOM) & 4);
37622
37637
  }
37623
37638
  else if (this.dom.firstChild) {
37624
37639
  if (offset == 0)
@@ -37648,7 +37663,7 @@ so this becomes the fallback color for the slot */ ''}
37648
37663
  if (desc && (!onlyNodes || desc.node)) {
37649
37664
  // If dom is outside of this desc's nodeDOM, don't count it.
37650
37665
  if (first && (nodeDOM = desc.nodeDOM) &&
37651
- !(nodeDOM.nodeType == 1 ? nodeDOM.contains(dom.nodeType == 1 ? dom : dom.parentNode) : nodeDOM == dom))
37666
+ !(isElt(nodeDOM) ? contains(nodeDOM, dom) : nodeDOM == dom))
37652
37667
  first = false;
37653
37668
  else
37654
37669
  return desc;
@@ -37698,7 +37713,7 @@ so this becomes the fallback color for the slot */ ''}
37698
37713
  let i = 0, offset = 0;
37699
37714
  for (let curPos = 0; i < this.children.length; i++) {
37700
37715
  let child = this.children[i], end = curPos + child.size;
37701
- if (end > pos || child instanceof TrailingHackViewDesc) {
37716
+ if (end > pos) {
37702
37717
  offset = pos - curPos;
37703
37718
  break;
37704
37719
  }
@@ -37708,7 +37723,11 @@ so this becomes the fallback color for the slot */ ''}
37708
37723
  if (offset)
37709
37724
  return this.children[i].domFromPos(offset - this.children[i].border, side);
37710
37725
  // Go back if there were any zero-length widgets with side >= 0 before this point
37711
- for (let prev; i && !(prev = this.children[i - 1]).size && prev instanceof WidgetViewDesc && prev.side >= 0; i--) { }
37726
+ for (; i > 0; i--) {
37727
+ let prev = this.children[i - 1];
37728
+ if (prev.size || !(prev instanceof BufferHackViewDesc || prev instanceof WidgetViewDesc && prev.side >= 0))
37729
+ break;
37730
+ }
37712
37731
  // Scan towards the first useable node
37713
37732
  if (side <= 0) {
37714
37733
  let prev, enter = true;
@@ -37785,7 +37804,7 @@ so this becomes the fallback color for the slot */ ''}
37785
37804
  }
37786
37805
  domAfterPos(pos) {
37787
37806
  let { node, offset } = this.domFromPos(pos, 0);
37788
- if (node.nodeType != 1 || offset == node.childNodes.length)
37807
+ if (!isElt(node) || offset == node.childNodes.length)
37789
37808
  throw new RangeError("No node after pos " + pos);
37790
37809
  return node.childNodes[offset];
37791
37810
  }
@@ -37814,7 +37833,7 @@ so this becomes the fallback color for the slot */ ''}
37814
37833
  // reported position in such situations (#1092).
37815
37834
  if ((gecko || safari) && anchor == head) {
37816
37835
  let { node, offset } = anchorDOM;
37817
- if (node.nodeType == 3) {
37836
+ if (isText(node)) {
37818
37837
  brKludge = !!(offset && node.nodeValue[offset - 1] == "\n");
37819
37838
  // Issue #1128
37820
37839
  if (brKludge && offset == node.nodeValue.length) {
@@ -37837,7 +37856,7 @@ so this becomes the fallback color for the slot */ ''}
37837
37856
  }
37838
37857
  // Firefox can act strangely when the selection is in front of an
37839
37858
  // uneditable node. See #1163 and https://bugzilla.mozilla.org/show_bug.cgi?id=1709536
37840
- if (gecko && selRange.focusNode && selRange.focusNode != headDOM.node && selRange.focusNode.nodeType == 1) {
37859
+ if (gecko && selRange.focusNode && selRange.focusNode != headDOM.node && isElt(selRange.focusNode)) {
37841
37860
  let after = selRange.focusNode.childNodes[selRange.focusOffset];
37842
37861
  if (after && after.contentEditable == "false")
37843
37862
  force = true;
@@ -37936,14 +37955,12 @@ so this becomes the fallback color for the slot */ ''}
37936
37955
  return self.parent.posBeforeChild(self);
37937
37956
  });
37938
37957
  if (!widget.type.spec.raw) {
37939
- if (dom.nodeType != 1) {
37940
- let wrap = document.createElement("span");
37941
- wrap.appendChild(dom);
37942
- dom = wrap;
37943
- }
37944
- if (!dom.hasAttribute("contenteditable"))
37945
- dom.contentEditable = "false";
37946
- dom.classList.add("ProseMirror-widget");
37958
+ let elt = isElt(dom) ? dom : document.createElement("span");
37959
+ if (elt != dom)
37960
+ elt.appendChild(dom);
37961
+ if (!elt.hasAttribute("contenteditable"))
37962
+ elt.contentEditable = "false";
37963
+ elt.classList.add("ProseMirror-widget");
37947
37964
  }
37948
37965
  super(parent, [], dom, null);
37949
37966
  this.widget = widget;
@@ -38079,7 +38096,7 @@ so this becomes the fallback color for the slot */ ''}
38079
38096
  if (node.isText) {
38080
38097
  if (!dom)
38081
38098
  dom = document.createTextNode(node.text);
38082
- else if (dom.nodeType != 3)
38099
+ else if (!isText(dom))
38083
38100
  throw new RangeError("Text must be rendered as a DOM text node");
38084
38101
  }
38085
38102
  else if (!dom) {
@@ -38131,7 +38148,7 @@ so this becomes the fallback color for the slot */ ''}
38131
38148
  }
38132
38149
  if (!rule.contentElement) {
38133
38150
  let found = addedNodes &&
38134
- addedNodes.find(n => n.nodeType == 1 && addedNodes.indexOf(n.parentNode) < 0 && this.dom.contains(n));
38151
+ addedNodes.find(n => isElt(n) && addedNodes.indexOf(n.parentNode) < 0 && this.dom.contains(n));
38135
38152
  if (found)
38136
38153
  rule.contentElement = found;
38137
38154
  else
@@ -38156,6 +38173,7 @@ so this becomes the fallback color for the slot */ ''}
38156
38173
  let localComposition = composition && composition.pos > -1 ? composition : null;
38157
38174
  let compositionInChild = composition && composition.pos < 0;
38158
38175
  let updater = new ViewTreeUpdater(this, localComposition && localComposition.node, view);
38176
+ let addBuffers = this.node.inlineContent, atBufferPos = addBuffers && this.node.isBlock;
38159
38177
  iterDeco(this.node, this.innerDeco, (widget, i, insideNode) => {
38160
38178
  if (widget.spec.marks)
38161
38179
  updater.syncToMarks(widget.spec.marks, inline, view, i);
@@ -38167,6 +38185,8 @@ so this becomes the fallback color for the slot */ ''}
38167
38185
  }, (child, outerDeco, innerDeco, i) => {
38168
38186
  // Make sure the wrapping mark descs match the node's marks.
38169
38187
  updater.syncToMarks(child.marks, inline, view, i);
38188
+ if (atBufferPos && child.isAtom && !child.isText)
38189
+ updater.addHackNode("IMG", updater.top);
38170
38190
  // Try several strategies for drawing this node
38171
38191
  let compIndex;
38172
38192
  if (updater.findNodeMatch(child, outerDeco, innerDeco, i)) ;
@@ -38180,6 +38200,8 @@ so this becomes the fallback color for the slot */ ''}
38180
38200
  updater.addNode(child, outerDeco, innerDeco, view, off);
38181
38201
  }
38182
38202
  off += child.nodeSize;
38203
+ if (addBuffers)
38204
+ atBufferPos = child.isAtom && !child.isText;
38183
38205
  });
38184
38206
  // Drop all remaining descs after the current position.
38185
38207
  updater.syncToMarks([], inline, view, 0);
@@ -38258,7 +38280,7 @@ so this becomes the fallback color for the slot */ ''}
38258
38280
  updateOuterDeco(outerDeco) {
38259
38281
  if (sameOuterDeco(outerDeco, this.outerDeco))
38260
38282
  return;
38261
- let needsWrap = this.nodeDOM.nodeType != 1;
38283
+ let needsWrap = !isElt(this.nodeDOM);
38262
38284
  let oldDOM = this.dom;
38263
38285
  this.dom = patchOuterDeco(this.dom, this.nodeDOM, computeOuterDeco(this.outerDeco, this.node, needsWrap), computeOuterDeco(outerDeco, this.node, needsWrap));
38264
38286
  if (this.dom != oldDOM) {
@@ -38269,7 +38291,7 @@ so this becomes the fallback color for the slot */ ''}
38269
38291
  }
38270
38292
  // Mark this node as being the selected node.
38271
38293
  selectNode() {
38272
- if (this.nodeDOM.nodeType == 1) {
38294
+ if (isElt(this.nodeDOM)) {
38273
38295
  this.nodeDOM.classList.add("ProseMirror-selectednode");
38274
38296
  if (this.contentDOM || !this.node.type.spec.draggable)
38275
38297
  this.nodeDOM.draggable = true;
@@ -38277,7 +38299,7 @@ so this becomes the fallback color for the slot */ ''}
38277
38299
  }
38278
38300
  // Remove selected node marking from this node.
38279
38301
  deselectNode() {
38280
- if (this.nodeDOM.nodeType == 1) {
38302
+ if (isElt(this.nodeDOM)) {
38281
38303
  this.nodeDOM.classList.remove("ProseMirror-selectednode");
38282
38304
  if (this.contentDOM || !this.node.type.spec.draggable)
38283
38305
  this.nodeDOM.removeAttribute("draggable");
@@ -38348,9 +38370,9 @@ so this becomes the fallback color for the slot */ ''}
38348
38370
  get domAtom() { return false; }
38349
38371
  isText(text) { return this.node.text == text; }
38350
38372
  }
38351
- // A dummy desc used to tag trailing BR or IMG nodes created to work
38373
+ // A dummy desc used to tag extra BR or IMG nodes created to work
38352
38374
  // around contentEditable terribleness.
38353
- class TrailingHackViewDesc extends ViewDesc {
38375
+ class BufferHackViewDesc extends ViewDesc {
38354
38376
  parseRule() { return { ignore: true }; }
38355
38377
  matchesHack(nodeName) { return this.dirty == NOT_DIRTY && this.dom.nodeName == nodeName; }
38356
38378
  get domAtom() { return true; }
@@ -38523,7 +38545,7 @@ so this becomes the fallback color for the slot */ ''}
38523
38545
  }
38524
38546
  }
38525
38547
  function applyOuterDeco(dom, deco, node) {
38526
- return patchOuterDeco(dom, dom, noDeco, computeOuterDeco(deco, node, dom.nodeType != 1));
38548
+ return patchOuterDeco(dom, dom, noDeco, computeOuterDeco(deco, node, !isElt(dom)));
38527
38549
  }
38528
38550
  function sameOuterDeco(a, b) {
38529
38551
  if (a.length != b.length)
@@ -38786,7 +38808,7 @@ so this becomes the fallback color for the slot */ ''}
38786
38808
  }
38787
38809
  if (nodeName == "BR")
38788
38810
  dom.className = "ProseMirror-trailingBreak";
38789
- let hack = new TrailingHackViewDesc(this.top, [], dom, null);
38811
+ let hack = new BufferHackViewDesc(this.top, [], dom, null);
38790
38812
  if (parent != this.top)
38791
38813
  parent.children.push(hack);
38792
38814
  else
@@ -38795,7 +38817,7 @@ so this becomes the fallback color for the slot */ ''}
38795
38817
  }
38796
38818
  }
38797
38819
  isLocked(node) {
38798
- return this.lock && (node == this.lock || node.nodeType == 1 && node.contains(this.lock.parentNode));
38820
+ return this.lock && (node == this.lock || isElt(node) && node.contains(this.lock.parentNode));
38799
38821
  }
38800
38822
  }
38801
38823
  // Iterate from the end of the fragment and array of descs to find
@@ -38997,12 +39019,27 @@ so this becomes the fallback color for the slot */ ''}
38997
39019
  anchor = head;
38998
39020
  while (nearestDesc && !nearestDesc.node)
38999
39021
  nearestDesc = nearestDesc.parent;
39000
- let nearestDescNode = nearestDesc.node;
39001
- if (nearestDesc && nearestDescNode.isAtom && NodeSelection.isSelectable(nearestDescNode) && nearestDesc.parent
39002
- && !(nearestDescNode.isInline && isOnEdge(domSel.focusNode, domSel.focusOffset, nearestDesc.dom))) {
39022
+ if (nearestDesc && nearestDesc.node.isAtom && NodeSelection.isSelectable(nearestDesc.node) &&
39023
+ nearestDesc.parent &&
39024
+ !(nearestDesc.node.isInline && isOnEdge(domSel.focusNode, domSel.focusOffset, nearestDesc.dom))) {
39003
39025
  let pos = nearestDesc.posBefore;
39004
39026
  selection = new NodeSelection(head == pos ? $head : doc.resolve(pos));
39005
39027
  }
39028
+ else if (gecko && origin == "key" && head > view.state.selection.to &&
39029
+ isElt(domSel.focusNode) && domSel.focusOffset == domSel.focusNode.childNodes.length &&
39030
+ nearestDesc && nearestDesc.posAtStart > view.state.selection.to) {
39031
+ // Firefox will jump across scrollable wrapper nodes on keyboard
39032
+ // cursor motion (#1594). This tries to detect this situation
39033
+ // and work around it.
39034
+ for (let scan = domSel.focusNode;; scan = scan.parentNode) {
39035
+ if (getComputedStyle(scan).overflow != "visible") {
39036
+ selection = Selection$2.findFrom(doc.resolve(nearestDesc.posAtStart), 1);
39037
+ break;
39038
+ }
39039
+ if (scan == nearestDesc.dom || scan.nextSibling || !scan.parentNode || !isElt(scan.parentNode))
39040
+ break;
39041
+ }
39042
+ }
39006
39043
  }
39007
39044
  else {
39008
39045
  if (domSel instanceof view.dom.ownerDocument.defaultView.Selection && domSel.rangeCount > 1) {
@@ -39188,8 +39225,7 @@ so this becomes the fallback color for the slot */ ''}
39188
39225
  // Firefox will raise 'permission denied' errors when accessing
39189
39226
  // properties of `sel.anchorNode` when it's in a generated CSS
39190
39227
  // element.
39191
- return view.dom.contains(sel.anchorNode.nodeType == 3 ? sel.anchorNode.parentNode : sel.anchorNode) &&
39192
- (view.editable || view.dom.contains(sel.focusNode.nodeType == 3 ? sel.focusNode.parentNode : sel.focusNode));
39228
+ return contains(view.dom, sel.anchorNode) && (view.editable || contains(view.dom, sel.focusNode));
39193
39229
  }
39194
39230
  catch (_) {
39195
39231
  return false;
@@ -39240,15 +39276,14 @@ so this becomes the fallback color for the slot */ ''}
39240
39276
  if (NodeSelection.isSelectable(node)) {
39241
39277
  return apply(view, new NodeSelection(dir < 0 ? view.state.doc.resolve($head.pos - node.nodeSize) : $head));
39242
39278
  }
39243
- else if (webkit) {
39279
+ else {
39244
39280
  // Chrome and Safari will introduce extra pointless cursor
39245
- // positions around inline uneditable nodes, so we have to
39246
- // take over and move the cursor past them (#937)
39281
+ // positions around inline uneditable nodes (#937), and
39282
+ // Firefox will sometimes just plain refuse to move across
39283
+ // them (#1592), so in this situation we move the cursor
39284
+ // ourselves.
39247
39285
  return apply(view, new TextSelection(view.state.doc.resolve(dir < 0 ? nodePos : nodePos + node.nodeSize)));
39248
39286
  }
39249
- else {
39250
- return false;
39251
- }
39252
39287
  }
39253
39288
  }
39254
39289
  else if (sel instanceof NodeSelection && sel.node.isInline) {
@@ -39261,12 +39296,10 @@ so this becomes the fallback color for the slot */ ''}
39261
39296
  return false;
39262
39297
  }
39263
39298
  }
39264
- function nodeLen(node) {
39265
- return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
39266
- }
39267
39299
  function isIgnorable(dom, dir) {
39268
39300
  let desc = dom.pmViewDesc;
39269
- return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR");
39301
+ return desc ? desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR")
39302
+ : isElt(dom) && dom.contentEditable == "false";
39270
39303
  }
39271
39304
  function skipIgnoredNodes(view, dir) {
39272
39305
  return dir < 0 ? skipIgnoredNodesBefore(view) : skipIgnoredNodesAfter(view);
@@ -39282,25 +39315,23 @@ so this becomes the fallback color for the slot */ ''}
39282
39315
  // Gecko will do odd things when the selection is directly in front
39283
39316
  // of a non-editable node, so in that case, move it into the next
39284
39317
  // node if possible. Issue prosemirror/prosemirror#832.
39285
- if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset], -1))
39318
+ if (gecko && isElt(node) && offset < nodeSize(node) && isIgnorable(node.childNodes[offset], -1))
39286
39319
  force = true;
39287
39320
  for (;;) {
39288
39321
  if (offset > 0) {
39289
- if (node.nodeType != 1) {
39322
+ if (!isElt(node))
39290
39323
  break;
39324
+ let before = node.childNodes[offset - 1];
39325
+ if (isIgnorable(before, -1)) {
39326
+ moveNode = node;
39327
+ moveOffset = --offset;
39328
+ }
39329
+ else if (isText(before)) {
39330
+ node = before;
39331
+ offset = node.nodeValue.length;
39291
39332
  }
39292
39333
  else {
39293
- let before = node.childNodes[offset - 1];
39294
- if (isIgnorable(before, -1)) {
39295
- moveNode = node;
39296
- moveOffset = --offset;
39297
- }
39298
- else if (before.nodeType == 3) {
39299
- node = before;
39300
- offset = node.nodeValue.length;
39301
- }
39302
- else
39303
- break;
39334
+ break;
39304
39335
  }
39305
39336
  }
39306
39337
  else if (isBlockNode(node)) {
@@ -39321,7 +39352,7 @@ so this becomes the fallback color for the slot */ ''}
39321
39352
  }
39322
39353
  else {
39323
39354
  node = prev;
39324
- offset = nodeLen(node);
39355
+ offset = nodeSize(node);
39325
39356
  }
39326
39357
  }
39327
39358
  }
@@ -39337,19 +39368,20 @@ so this becomes the fallback color for the slot */ ''}
39337
39368
  let node = sel.focusNode, offset = sel.focusOffset;
39338
39369
  if (!node)
39339
39370
  return;
39340
- let len = nodeLen(node);
39371
+ let len = nodeSize(node);
39341
39372
  let moveNode, moveOffset;
39342
39373
  for (;;) {
39343
39374
  if (offset < len) {
39344
- if (node.nodeType != 1)
39375
+ if (!isElt(node))
39345
39376
  break;
39346
39377
  let after = node.childNodes[offset];
39347
39378
  if (isIgnorable(after, 1)) {
39348
39379
  moveNode = node;
39349
39380
  moveOffset = ++offset;
39350
39381
  }
39351
- else
39382
+ else {
39352
39383
  break;
39384
+ }
39353
39385
  }
39354
39386
  else if (isBlockNode(node)) {
39355
39387
  break;
@@ -39370,7 +39402,7 @@ so this becomes the fallback color for the slot */ ''}
39370
39402
  else {
39371
39403
  node = next;
39372
39404
  offset = 0;
39373
- len = nodeLen(node);
39405
+ len = nodeSize(node);
39374
39406
  }
39375
39407
  }
39376
39408
  }
@@ -39388,9 +39420,9 @@ so this becomes the fallback color for the slot */ ''}
39388
39420
  }
39389
39421
  while (node && offset < node.childNodes.length) {
39390
39422
  let next = node.childNodes[offset];
39391
- if (next.nodeType == 3)
39423
+ if (isText(next))
39392
39424
  return next;
39393
- if (next.nodeType == 1 && next.contentEditable == "false")
39425
+ if (isElt(next) && next.contentEditable == "false")
39394
39426
  break;
39395
39427
  node = next;
39396
39428
  offset = 0;
@@ -39403,16 +39435,16 @@ so this becomes the fallback color for the slot */ ''}
39403
39435
  }
39404
39436
  while (node && offset) {
39405
39437
  let next = node.childNodes[offset - 1];
39406
- if (next.nodeType == 3)
39438
+ if (isText(next))
39407
39439
  return next;
39408
- if (next.nodeType == 1 && next.contentEditable == "false")
39440
+ if (isElt(next) && next.contentEditable == "false")
39409
39441
  break;
39410
39442
  node = next;
39411
39443
  offset = node.childNodes.length;
39412
39444
  }
39413
39445
  }
39414
39446
  function setSelFocus(view, node, offset) {
39415
- if (node.nodeType != 3) {
39447
+ if (!isText(node)) {
39416
39448
  let before, after;
39417
39449
  if (after = textNodeAfter(node, offset)) {
39418
39450
  node = after;
@@ -39522,8 +39554,8 @@ so this becomes the fallback color for the slot */ ''}
39522
39554
  if (!safari || view.state.selection.$head.parentOffset > 0)
39523
39555
  return false;
39524
39556
  let { focusNode, focusOffset } = view.domSelectionRange();
39525
- if (focusNode && focusNode.nodeType == 1 && focusOffset == 0 &&
39526
- focusNode.firstChild && focusNode.firstChild.contentEditable == "false") {
39557
+ if (focusNode && isElt(focusNode) && focusOffset == 0 &&
39558
+ focusNode.firstChild && isElt(focusNode.firstChild) && focusNode.firstChild.contentEditable == "false") {
39527
39559
  let child = focusNode.firstChild;
39528
39560
  switchEditable(view, child, "true");
39529
39561
  setTimeout(() => switchEditable(view, child, "false"), 20);
@@ -39594,7 +39626,7 @@ so this becomes the fallback color for the slot */ ''}
39594
39626
  let doc = detachedDoc(), wrap = doc.createElement("div");
39595
39627
  wrap.appendChild(serializer.serializeFragment(content, { document: doc }));
39596
39628
  let firstChild = wrap.firstChild, needsWrap, wrappers = 0;
39597
- while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
39629
+ while (firstChild && isElt(firstChild) && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
39598
39630
  for (let i = needsWrap.length - 1; i >= 0; i--) {
39599
39631
  let wrapper = doc.createElement(needsWrap[i]);
39600
39632
  while (wrap.firstChild)
@@ -39604,7 +39636,7 @@ so this becomes the fallback color for the slot */ ''}
39604
39636
  }
39605
39637
  firstChild = wrap.firstChild;
39606
39638
  }
39607
- if (firstChild && firstChild.nodeType == 1)
39639
+ if (firstChild && isElt(firstChild))
39608
39640
  firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd}${wrappers ? ` -${wrappers}` : ""} ${JSON.stringify(context)}`);
39609
39641
  let text = view.someProp("clipboardTextSerializer", f => f(slice, view)) ||
39610
39642
  slice.content.textBetween(0, slice.content.size, "\n\n");
@@ -39650,7 +39682,7 @@ so this becomes the fallback color for the slot */ ''}
39650
39682
  if (sliceData && sliceData[3])
39651
39683
  for (let i = +sliceData[3]; i > 0; i--) {
39652
39684
  let child = dom.firstChild;
39653
- while (child && child.nodeType != 1)
39685
+ while (child && !isElt(child))
39654
39686
  child = child.nextSibling;
39655
39687
  if (!child)
39656
39688
  break;
@@ -39855,12 +39887,11 @@ so this becomes the fallback color for the slot */ ''}
39855
39887
  if (!type || type.hasRequiredAttrs())
39856
39888
  break;
39857
39889
  try {
39858
- type.checkAttrs(array[i + 1]);
39890
+ content = Fragment.from(type.create(array[i + 1], content));
39859
39891
  }
39860
39892
  catch (e) {
39861
39893
  break;
39862
39894
  }
39863
- content = Fragment.from(type.create(array[i + 1], content));
39864
39895
  openStart++;
39865
39896
  openEnd++;
39866
39897
  }
@@ -40192,7 +40223,7 @@ so this becomes the fallback color for the slot */ ''}
40192
40223
  }
40193
40224
  const target = flushed ? null : event.target;
40194
40225
  const targetDesc = target ? view.docView.nearestDesc(target, true) : null;
40195
- this.target = targetDesc && targetDesc.nodeDOM.nodeType == 1 ? targetDesc.nodeDOM : null;
40226
+ this.target = targetDesc && isElt(targetDesc.nodeDOM) ? targetDesc.nodeDOM : null;
40196
40227
  let { selection } = view.state;
40197
40228
  if (event.button == 0 &&
40198
40229
  (targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
@@ -40340,7 +40371,7 @@ so this becomes the fallback color for the slot */ ''}
40340
40371
  if (!view.composing) {
40341
40372
  view.domObserver.flush();
40342
40373
  let { state } = view, $pos = state.selection.$to;
40343
- if (state.selection instanceof TextSelection &&
40374
+ if (state.selection instanceof TextSelection && state.selection.empty &&
40344
40375
  (state.storedMarks ||
40345
40376
  (!$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some(m => m.type.spec.inclusive === false)) ||
40346
40377
  chrome && windows$1 && selectionBeforeUneditable(view))) { // Issue #1500
@@ -40356,11 +40387,11 @@ so this becomes the fallback color for the slot */ ''}
40356
40387
  // inside if necessary.
40357
40388
  if (gecko && state.selection.empty && $pos.parentOffset && !$pos.textOffset && $pos.nodeBefore.marks.length) {
40358
40389
  let sel = view.domSelectionRange();
40359
- for (let node = sel.focusNode, offset = sel.focusOffset; node && node.nodeType == 1 && offset != 0;) {
40390
+ for (let node = sel.focusNode, offset = sel.focusOffset; node && isElt(node) && offset != 0;) {
40360
40391
  let before = offset < 0 ? node.lastChild : node.childNodes[offset - 1];
40361
40392
  if (!before)
40362
40393
  break;
40363
- if (before.nodeType == 3) {
40394
+ if (isText(before)) {
40364
40395
  let sel = view.domSelection();
40365
40396
  if (sel)
40366
40397
  sel.collapse(before, before.nodeValue.length);
@@ -40379,10 +40410,10 @@ so this becomes the fallback color for the slot */ ''}
40379
40410
  };
40380
40411
  function selectionBeforeUneditable(view) {
40381
40412
  let { focusNode, focusOffset } = view.domSelectionRange();
40382
- if (!focusNode || focusNode.nodeType != 1 || focusOffset >= focusNode.childNodes.length)
40413
+ if (!focusNode || !isElt(focusNode) || focusOffset >= focusNode.childNodes.length)
40383
40414
  return false;
40384
40415
  let next = focusNode.childNodes[focusOffset];
40385
- return next.nodeType == 1 && next.contentEditable == "false";
40416
+ return isElt(next) && next.contentEditable == "false";
40386
40417
  }
40387
40418
  editHandlers.compositionend = (view, event) => {
40388
40419
  if (view.composing) {
@@ -40584,7 +40615,7 @@ so this becomes the fallback color for the slot */ ''}
40584
40615
  else if (mouseDown && mouseDown.mightDrag) {
40585
40616
  node = NodeSelection.create(view.state.doc, mouseDown.mightDrag.pos);
40586
40617
  }
40587
- else if (event.target && event.target.nodeType == 1) {
40618
+ else if (event.target && isElt(event.target)) {
40588
40619
  let desc = view.docView.nearestDesc(event.target, true);
40589
40620
  if (desc && desc.node.type.spec.draggable && desc != view.docView)
40590
40621
  node = NodeSelection.create(view.state.doc, desc.posBefore);
@@ -41555,7 +41586,7 @@ so this becomes the fallback color for the slot */ ''}
41555
41586
  let desc = container && this.view.docView.nearestDesc(container);
41556
41587
  if (desc && desc.ignoreMutation({
41557
41588
  type: "selection",
41558
- target: container.nodeType == 3 ? container.parentNode : container
41589
+ target: isText(container) ? container.parentNode : container
41559
41590
  })) {
41560
41591
  this.setCurSelection();
41561
41592
  return true;
@@ -41597,7 +41628,7 @@ so this becomes the fallback color for the slot */ ''}
41597
41628
  for (let node of added)
41598
41629
  if (node.nodeName == "BR" && node.parentNode) {
41599
41630
  let after = node.nextSibling;
41600
- while (after && after.nodeType == 1) {
41631
+ while (after && isElt(after)) {
41601
41632
  if (after.contentEditable == "false") {
41602
41633
  node.parentNode.removeChild(node);
41603
41634
  break;
@@ -41670,7 +41701,7 @@ so this becomes the fallback color for the slot */ ''}
41670
41701
  for (let i = 0; i < mut.addedNodes.length; i++) {
41671
41702
  let node = mut.addedNodes[i];
41672
41703
  added.push(node);
41673
- if (node.nodeType == 3)
41704
+ if (isText(node))
41674
41705
  this.lastChangedTextNode = node;
41675
41706
  }
41676
41707
  if (desc.contentDOM && desc.contentDOM != desc.dom && !desc.contentDOM.contains(mut.target))
@@ -41785,8 +41816,7 @@ so this becomes the fallback color for the slot */ ''}
41785
41816
  let parent = nextCell;
41786
41817
  for (;;) {
41787
41818
  let first = parent.firstChild;
41788
- if (!first || first.nodeType != 1 || first.contentEditable == "false" ||
41789
- /^(BR|IMG)$/.test(first.nodeName))
41819
+ if (!first || !isElt(first) || first.contentEditable == "false" || /^(BR|IMG)$/.test(first.nodeName))
41790
41820
  break;
41791
41821
  parent = first;
41792
41822
  }
@@ -41811,7 +41841,7 @@ so this becomes the fallback color for the slot */ ''}
41811
41841
  let domSel = view.domSelectionRange();
41812
41842
  let find;
41813
41843
  let anchor = domSel.anchorNode;
41814
- if (anchor && view.dom.contains(anchor.nodeType == 1 ? anchor : anchor.parentNode)) {
41844
+ if (anchor && contains(view.dom, anchor)) {
41815
41845
  find = [{ node: anchor, offset: domSel.anchorOffset }];
41816
41846
  if (!selectionCollapsed(domSel))
41817
41847
  find.push({ node: domSel.focusNode, offset: domSel.focusOffset });
@@ -41919,7 +41949,7 @@ so this becomes the fallback color for the slot */ ''}
41919
41949
  if (change)
41920
41950
  view.input.domChangeCount++;
41921
41951
  if ((ios && view.input.lastIOSEnter > Date.now() - 225 || android) &&
41922
- addedNodes.some(n => n.nodeType == 1 && !isInline.test(n.nodeName)) &&
41952
+ addedNodes.some(n => isElt(n) && !isInline.test(n.nodeName)) &&
41923
41953
  (!change || change.endA >= change.endB) &&
41924
41954
  view.someProp("handleKeyDown", f => f(view, keyEvent(13, "Enter")))) {
41925
41955
  view.input.lastIOSEnter = 0;
@@ -41977,9 +42007,7 @@ so this becomes the fallback color for the slot */ ''}
41977
42007
  // as being an iOS enter press), just dispatch an Enter key instead.
41978
42008
  if (((ios && view.input.lastIOSEnter > Date.now() - 225 &&
41979
42009
  (!inlineChange || addedNodes.some(n => n.nodeName == "DIV" || n.nodeName == "P"))) ||
41980
- (!inlineChange && $from.pos < parse.doc.content.size &&
41981
- (!$from.sameParent($to) || !$from.parent.inlineContent) &&
41982
- $from.pos < $to.pos && !/\S/.test(parse.doc.textBetween($from.pos, $to.pos, "", "")))) &&
42010
+ (!inlineChange && looksLikeEnter(parse.doc, $from.pos, $to.pos))) &&
41983
42011
  view.someProp("handleKeyDown", f => f(view, keyEvent(13, "Enter")))) {
41984
42012
  view.input.lastIOSEnter = 0;
41985
42013
  return;
@@ -42130,6 +42158,16 @@ so this becomes the fallback color for the slot */ ''}
42130
42158
  // The fragments after the join point must match
42131
42159
  return $newStart.parent.content.cut($newStart.parentOffset).eq($next.parent.content);
42132
42160
  }
42161
+ function looksLikeEnter(content, from, to) {
42162
+ let newTextlines = 0, newLeaves = 0;
42163
+ content.nodesBetween(from, to, (node, pos) => {
42164
+ if (node.isTextblock && pos >= from && pos < to)
42165
+ newTextlines++;
42166
+ else if (node.isText ? /\S/.test(node.text.slice(Math.max(0, from - pos), Math.min(node.nodeSize, to - pos))) : node.isLeaf)
42167
+ newLeaves++;
42168
+ });
42169
+ return newLeaves == 0 && newTextlines == 1;
42170
+ }
42133
42171
  function skipClosingAndOpening($pos, fromEnd, mayOpen) {
42134
42172
  let depth = $pos.depth, end = fromEnd ? $pos.end() : $pos.pos;
42135
42173
  while (depth > 0 && (fromEnd || $pos.indexAfter(depth) == $pos.node(depth).childCount)) {
@@ -42390,11 +42428,11 @@ so this becomes the fallback color for the slot */ ''}
42390
42428
  */
42391
42429
  scrollToSelection() {
42392
42430
  let startDOM = this.domSelectionRange().focusNode;
42393
- if (!startDOM || !this.dom.contains(startDOM.nodeType == 1 ? startDOM : startDOM.parentNode)) ;
42431
+ if (!startDOM || !contains(this.dom, startDOM)) ;
42394
42432
  else if (this.someProp("handleScrollToSelection", f => f(this))) ;
42395
42433
  else if (this.state.selection instanceof NodeSelection) {
42396
42434
  let target = this.docView.domAfterPos(this.state.selection.from);
42397
- if (target.nodeType == 1)
42435
+ if (isElt(target))
42398
42436
  scrollRectIntoView(this, target.getBoundingClientRect(), startDOM);
42399
42437
  }
42400
42438
  else {
@@ -42659,7 +42697,7 @@ so this becomes the fallback color for the slot */ ''}
42659
42697
  @internal
42660
42698
  */
42661
42699
  domSelectionRange() {
42662
- let sel = this.domSelection();
42700
+ let sel = this.dom.isConnected !== false && this.domSelection();
42663
42701
  if (!sel)
42664
42702
  return { focusNode: null, focusOffset: 0, anchorNode: null, anchorOffset: 0 };
42665
42703
  return safari && this.root.nodeType === 11 &&
@@ -42990,382 +43028,1013 @@ so this becomes the fallback color for the slot */ ''}
42990
43028
  };
42991
43029
  }
42992
43030
 
42993
- //#region src/helpers/createChainableState.ts
42994
- /**
42995
- * Takes a Transaction & Editor State and turns it into a chainable state object
42996
- * @param config The transaction and state to create the chainable state from
42997
- * @returns A chainable Editor state object
42998
- */
42999
- function createChainableState(config) {
43000
- const { state, transaction } = config;
43001
- let { selection } = transaction;
43002
- let { doc } = transaction;
43003
- let { storedMarks } = transaction;
43004
- return {
43005
- ...state,
43006
- apply: state.apply.bind(state),
43007
- applyTransaction: state.applyTransaction.bind(state),
43008
- plugins: state.plugins,
43009
- schema: state.schema,
43010
- reconfigure: state.reconfigure.bind(state),
43011
- toJSON: state.toJSON.bind(state),
43012
- get storedMarks() {
43013
- return storedMarks;
43014
- },
43015
- get selection() {
43016
- return selection;
43017
- },
43018
- get doc() {
43019
- return doc;
43020
- },
43021
- get tr() {
43022
- selection = transaction.selection;
43023
- doc = transaction.doc;
43024
- storedMarks = transaction.storedMarks;
43025
- return transaction;
43026
- }
43027
- };
43028
- }
43029
- //#endregion
43030
- //#region src/CommandManager.ts
43031
- var CommandManager = class CommandManager {
43032
- constructor(props) {
43033
- this.editor = props.editor;
43034
- this.rawCommands = this.editor.extensionManager.commands;
43035
- this.customState = props.state;
43036
- }
43037
- get hasCustomState() {
43038
- return !!this.customState;
43039
- }
43040
- get state() {
43041
- return this.customState || this.editor.state;
43042
- }
43043
- get commands() {
43044
- const { rawCommands, editor, state } = this;
43045
- const { view } = editor;
43046
- const { tr } = state;
43047
- const props = this.buildProps(tr);
43048
- return Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
43049
- const method = (...args) => {
43050
- const callback = command(...args)(props);
43051
- if (!tr.getMeta("preventDispatch") && !this.hasCustomState) view.dispatch(tr);
43052
- return callback;
43053
- };
43054
- return [name, method];
43055
- }));
43056
- }
43057
- get chain() {
43058
- return () => this.createChain();
43059
- }
43060
- get can() {
43061
- return () => this.createCan();
43062
- }
43063
- createChain(startTr, shouldDispatch = true) {
43064
- const { rawCommands, editor, state } = this;
43065
- const { view } = editor;
43066
- const callbacks = [];
43067
- const hasStartTransaction = !!startTr;
43068
- const tr = startTr || state.tr;
43069
- const run = () => {
43070
- if (!hasStartTransaction && shouldDispatch && !tr.getMeta("preventDispatch") && !this.hasCustomState) view.dispatch(tr);
43071
- return callbacks.every((callback) => callback === true);
43072
- };
43073
- const chain = {
43074
- ...Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
43075
- const chainedCommand = (...args) => {
43076
- const props = this.buildProps(tr, shouldDispatch);
43077
- const callback = command(...args)(props);
43078
- callbacks.push(callback);
43079
- return chain;
43080
- };
43081
- return [name, chainedCommand];
43082
- })),
43083
- run
43084
- };
43085
- return chain;
43086
- }
43087
- /**
43088
- * Creates a chain that safely returns `false` when run.
43089
- * @returns A non-dispatching command chain.
43090
- * @example
43091
- * const chain = CommandManager.createFakeChain()
43092
- * chain.focus().run() // false
43093
- */
43094
- static createFakeChain() {
43095
- const chain = new Proxy({}, { get: (_target, property) => {
43096
- if (property === "then") return;
43097
- if (property === "run") return () => false;
43098
- return () => chain;
43099
- } });
43100
- return chain;
43101
- }
43102
- createCan(startTr) {
43103
- const { rawCommands, state } = this;
43104
- const dispatch = false;
43105
- const tr = startTr || state.tr;
43106
- const props = this.buildProps(tr, dispatch);
43107
- return {
43108
- ...Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
43109
- return [name, (...args) => command(...args)({
43110
- ...props,
43111
- dispatch: void 0
43112
- })];
43113
- })),
43114
- chain: () => this.createChain(tr, dispatch)
43115
- };
43116
- }
43117
- /**
43118
- * Creates capability checks that safely return `false`.
43119
- * @returns A non-dispatching capability checker.
43120
- * @example
43121
- * const can = CommandManager.createFallbackCan()
43122
- * can.focus() // false
43123
- */
43124
- static createFallbackCan() {
43125
- const chain = CommandManager.createFakeChain();
43126
- return new Proxy({ chain: () => chain }, { get: (target, property) => {
43127
- if (property === "then") return;
43128
- if (property === "chain") return target.chain;
43129
- return () => false;
43130
- } });
43131
- }
43132
- buildProps(tr, shouldDispatch = true) {
43133
- const { rawCommands, editor, state } = this;
43134
- const { view } = editor;
43135
- const props = {
43136
- tr,
43137
- editor,
43138
- view,
43139
- state: createChainableState({
43140
- state,
43141
- transaction: tr
43142
- }),
43143
- dispatch: shouldDispatch ? () => void 0 : void 0,
43144
- chain: () => this.createChain(tr, shouldDispatch),
43145
- can: () => this.createCan(tr),
43146
- get commands() {
43147
- return Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
43148
- return [name, (...args) => command(...args)(props)];
43149
- }));
43150
- }
43151
- };
43152
- return props;
43153
- }
43154
- };
43155
- //#endregion
43156
- //#region src/commands/blur.ts
43157
- const blur = () => ({ editor, view }) => {
43158
- requestAnimationFrame(() => {
43159
- if (!editor.isDestroyed) {
43160
- var _window;
43161
- view.dom.blur();
43162
- (_window = window) === null || _window === void 0 || (_window = _window.getSelection()) === null || _window === void 0 || _window.removeAllRanges();
43163
- }
43164
- });
43165
- return true;
43166
- };
43167
- //#endregion
43168
- //#region src/commands/clearContent.ts
43169
- const clearContent = (emitUpdate = true) => ({ commands }) => {
43170
- return commands.setContent("", { emitUpdate });
43171
- };
43172
- //#endregion
43173
- //#region src/commands/clearNodes.ts
43174
- const clearNodes = () => ({ state, tr, dispatch }) => {
43175
- const { selection } = tr;
43176
- const { ranges } = selection;
43177
- if (!dispatch) return true;
43178
- ranges.forEach(({ $from, $to }) => {
43179
- state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
43180
- if (node.type.isText) return;
43181
- const { doc, mapping } = tr;
43182
- const $mappedFrom = doc.resolve(mapping.map(pos));
43183
- const $mappedTo = doc.resolve(mapping.map(pos + node.nodeSize));
43184
- const nodeRange = $mappedFrom.blockRange($mappedTo);
43185
- if (!nodeRange) return;
43186
- const targetLiftDepth = liftTarget(nodeRange);
43187
- if (node.type.isTextblock) {
43188
- const { defaultType } = $mappedFrom.parent.contentMatchAt($mappedFrom.index());
43189
- tr.setNodeMarkup(nodeRange.start, defaultType);
43190
- }
43191
- if (targetLiftDepth || targetLiftDepth === 0) tr.lift(nodeRange, targetLiftDepth);
43192
- });
43193
- });
43194
- return true;
43195
- };
43196
- //#endregion
43197
- //#region src/commands/command.ts
43198
- const command = (fn) => (props) => {
43199
- return fn(props);
43200
- };
43201
- //#endregion
43202
- //#region src/commands/createParagraphNear.ts
43203
- const createParagraphNear$1 = () => ({ state, dispatch }) => {
43204
- return createParagraphNear(state, dispatch);
43205
- };
43206
- //#endregion
43207
- //#region src/commands/cut.ts
43208
- const cut = (originRange, targetPos) => ({ editor, tr }) => {
43209
- const { state } = editor;
43210
- const contentSlice = state.doc.slice(originRange.from, originRange.to);
43211
- tr.deleteRange(originRange.from, originRange.to);
43212
- const newPos = tr.mapping.map(targetPos);
43213
- tr.insert(newPos, contentSlice.content);
43214
- tr.setSelection(new TextSelection(tr.doc.resolve(Math.max(newPos - 1, 0))));
43215
- return true;
43216
- };
43217
- //#endregion
43218
- //#region src/commands/deleteCurrentNode.ts
43219
- const deleteCurrentNode = () => ({ tr, dispatch }) => {
43220
- const { selection } = tr;
43221
- const currentNode = selection.$anchor.node();
43222
- if (currentNode.content.size > 0) return false;
43223
- const $pos = tr.selection.$anchor;
43224
- for (let depth = $pos.depth; depth > 0; depth -= 1) if ($pos.node(depth).type === currentNode.type) {
43225
- if (dispatch) {
43226
- const from = $pos.before(depth);
43227
- const to = $pos.after(depth);
43228
- tr.delete(from, to).scrollIntoView();
43229
- }
43230
- return true;
43231
- }
43232
- return false;
43233
- };
43234
- //#endregion
43235
- //#region src/helpers/getNodeType.ts
43236
- function getNodeType(nameOrType, schema) {
43237
- if (typeof nameOrType === "string") {
43238
- if (!schema.nodes[nameOrType]) throw Error(`There is no node type named '${nameOrType}'. Maybe you forgot to add the extension?`);
43239
- return schema.nodes[nameOrType];
43240
- }
43241
- return nameOrType;
43242
- }
43243
- //#endregion
43244
- //#region src/commands/deleteNode.ts
43245
- const deleteNode = (typeOrName) => ({ tr, state, dispatch }) => {
43246
- const type = getNodeType(typeOrName, state.schema);
43247
- const $pos = tr.selection.$anchor;
43248
- for (let depth = $pos.depth; depth > 0; depth -= 1) if ($pos.node(depth).type === type) {
43249
- if (dispatch) {
43250
- const from = $pos.before(depth);
43251
- const to = $pos.after(depth);
43252
- tr.delete(from, to).scrollIntoView();
43253
- }
43254
- return true;
43255
- }
43256
- return false;
43031
+ var GOOD_LEAF_SIZE = 200;
43032
+
43033
+ // :: class<T> A rope sequence is a persistent sequence data structure
43034
+ // that supports appending, prepending, and slicing without doing a
43035
+ // full copy. It is represented as a mostly-balanced tree.
43036
+ var RopeSequence = function RopeSequence () {};
43037
+
43038
+ RopeSequence.prototype.append = function append (other) {
43039
+ if (!other.length) { return this }
43040
+ other = RopeSequence.from(other);
43041
+
43042
+ return (!this.length && other) ||
43043
+ (other.length < GOOD_LEAF_SIZE && this.leafAppend(other)) ||
43044
+ (this.length < GOOD_LEAF_SIZE && other.leafPrepend(this)) ||
43045
+ this.appendInner(other)
43257
43046
  };
43258
- //#endregion
43259
- //#region src/commands/deleteRange.ts
43260
- const deleteRange = (range) => ({ tr, dispatch }) => {
43261
- const { from, to } = range;
43262
- if (dispatch) tr.delete(from, to);
43263
- return true;
43047
+
43048
+ // :: (union<[T], RopeSequence<T>>) → RopeSequence<T>
43049
+ // Prepend an array or other rope to this one, returning a new rope.
43050
+ RopeSequence.prototype.prepend = function prepend (other) {
43051
+ if (!other.length) { return this }
43052
+ return RopeSequence.from(other).append(this)
43264
43053
  };
43265
- //#endregion
43266
- //#region src/commands/deleteSelection.ts
43267
- /**
43268
- * Check if a node has text content based on its content specification.
43269
- * Returns true if the node's content spec matches text* or text+ patterns.
43270
- */
43271
- const hasTextContent = (nodeSpec) => {
43272
- if (!nodeSpec.content) return false;
43273
- return /^text(\*|\+)/.test(nodeSpec.content);
43054
+
43055
+ RopeSequence.prototype.appendInner = function appendInner (other) {
43056
+ return new Append(this, other)
43274
43057
  };
43275
- /**
43276
- * Expand selection position for a specific side (left or right) to handle inline text nodes.
43277
- * This function checks if the position is within an inline node with text content and
43278
- * expands it to include the entire node boundaries for proper deletion.
43279
- * @param $pos - The resolved position to expand
43280
- * @param schema - The ProseMirror schema
43281
- * @param side - Which side to expand ('left' or 'right')
43282
- * @returns The expanded position for deletion
43283
- */
43284
- const expandSelectionForSide = ($pos, schema, side) => {
43285
- if (!$pos.parent.isInline) return $pos.pos;
43286
- if (side === "left" && $pos.pos > $pos.start() || side === "right" && $pos.pos < $pos.end()) return $pos.pos;
43287
- const parentContent = schema.nodes[$pos.parent.type.name].spec;
43288
- if (!hasTextContent(parentContent)) return $pos.pos;
43289
- return side === "left" ? $pos.start() - 1 : $pos.end() + 1;
43058
+
43059
+ // :: (?number, ?number) → RopeSequence<T>
43060
+ // Create a rope repesenting a sub-sequence of this rope.
43061
+ RopeSequence.prototype.slice = function slice (from, to) {
43062
+ if ( from === void 0 ) from = 0;
43063
+ if ( to === void 0 ) to = this.length;
43064
+
43065
+ if (from >= to) { return RopeSequence.empty }
43066
+ return this.sliceInner(Math.max(0, from), Math.min(this.length, to))
43290
43067
  };
43291
- /**
43292
- * Expand selection range to properly handle deletion of inline text nodes.
43293
- * Inline text nodes don't collapse correctly when text inside is deleted,
43294
- * so we need to expand the selection to include the entire node.
43295
- * See: https://code.haverbeke.berlin/prosemirror/prosemirror/issues/1365
43296
- */
43297
- const expandSelectionForInlineText = ($from, $to, schema) => {
43298
- return {
43299
- from: expandSelectionForSide($from, schema, "left"),
43300
- to: expandSelectionForSide($to, schema, "right")
43301
- };
43068
+
43069
+ // :: (number) → T
43070
+ // Retrieve the element at the given position from this rope.
43071
+ RopeSequence.prototype.get = function get (i) {
43072
+ if (i < 0 || i >= this.length) { return undefined }
43073
+ return this.getInner(i)
43302
43074
  };
43303
- const deleteSelection = () => ({ state, dispatch }) => {
43304
- if (state.selection.empty) return false;
43305
- if (dispatch) {
43306
- const tr = state.tr;
43307
- const { ranges } = state.selection;
43308
- const mapFrom = tr.steps.length;
43309
- ranges.forEach((range) => {
43310
- const mapping = tr.mapping.slice(mapFrom);
43311
- const $from = tr.doc.resolve(mapping.map(range.$from.pos));
43312
- const $to = tr.doc.resolve(mapping.map(range.$to.pos));
43313
- const { from, to } = expandSelectionForInlineText($from, $to, state.schema);
43314
- tr.deleteRange(from, to);
43315
- });
43316
- if (!tr.selection.empty) tr.setSelection(TextSelection.near(tr.doc.resolve(tr.selection.from)));
43317
- tr.scrollIntoView();
43318
- dispatch(tr);
43319
- }
43320
- return true;
43075
+
43076
+ // :: ((element: T, index: number) → ?bool, ?number, ?number)
43077
+ // Call the given function for each element between the given
43078
+ // indices. This tends to be more efficient than looping over the
43079
+ // indices and calling `get`, because it doesn't have to descend the
43080
+ // tree for every element.
43081
+ RopeSequence.prototype.forEach = function forEach (f, from, to) {
43082
+ if ( from === void 0 ) from = 0;
43083
+ if ( to === void 0 ) to = this.length;
43084
+
43085
+ if (from <= to)
43086
+ { this.forEachInner(f, from, to, 0); }
43087
+ else
43088
+ { this.forEachInvertedInner(f, from, to, 0); }
43321
43089
  };
43322
- //#endregion
43323
- //#region src/commands/enter.ts
43324
- const enter = () => ({ commands }) => {
43325
- return commands.keyboardShortcut("Enter");
43090
+
43091
+ // :: ((element: T, index: number) → U, ?number, ?number) → [U]
43092
+ // Map the given functions over the elements of the rope, producing
43093
+ // a flat array.
43094
+ RopeSequence.prototype.map = function map (f, from, to) {
43095
+ if ( from === void 0 ) from = 0;
43096
+ if ( to === void 0 ) to = this.length;
43097
+
43098
+ var result = [];
43099
+ this.forEach(function (elt, i) { return result.push(f(elt, i)); }, from, to);
43100
+ return result
43326
43101
  };
43327
- //#endregion
43328
- //#region src/commands/exitCode.ts
43329
- const exitCode$1 = () => ({ state, dispatch }) => {
43330
- return exitCode(state, dispatch);
43102
+
43103
+ // :: (?union<[T], RopeSequence<T>>) → RopeSequence<T>
43104
+ // Create a rope representing the given array, or return the rope
43105
+ // itself if a rope was given.
43106
+ RopeSequence.from = function from (values) {
43107
+ if (values instanceof RopeSequence) { return values }
43108
+ return values && values.length ? new Leaf(values) : RopeSequence.empty
43331
43109
  };
43332
- //#endregion
43333
- //#region src/utilities/isRegExp.ts
43334
- function isRegExp$1(value) {
43335
- return Object.prototype.toString.call(value) === "[object RegExp]";
43336
- }
43337
- //#endregion
43338
- //#region src/utilities/objectIncludes.ts
43339
- /**
43340
- * Check if object1 includes object2
43341
- * @param object1 Object
43342
- * @param object2 Object
43343
- */
43344
- function objectIncludes(object1, object2, options = { strict: true }) {
43345
- const keys = Object.keys(object2);
43346
- if (!keys.length) return true;
43347
- return keys.every((key) => {
43348
- if (options.strict) return object2[key] === object1[key];
43349
- if (isRegExp$1(object2[key])) return object2[key].test(object1[key]);
43350
- return object2[key] === object1[key];
43351
- });
43352
- }
43353
- //#endregion
43354
- //#region src/helpers/getMarkRange.ts
43355
- function findMarkInSet(marks, type, attributes = {}) {
43356
- return marks.find((item) => {
43357
- return item.type === type && objectIncludes(Object.fromEntries(Object.keys(attributes).map((k) => [k, item.attrs[k]])), attributes);
43358
- });
43359
- }
43360
- function isMarkInSet(marks, type, attributes = {}) {
43361
- return !!findMarkInSet(marks, type, attributes);
43362
- }
43363
- /**
43364
- * Get the range of a mark at a resolved position.
43365
- */
43366
- function getMarkRange($pos, type, attributes) {
43367
- if (!$pos || !type) return;
43368
- let start = $pos.parent.childAfter($pos.parentOffset);
43110
+
43111
+ var Leaf = /*@__PURE__*/(function (RopeSequence) {
43112
+ function Leaf(values) {
43113
+ RopeSequence.call(this);
43114
+ this.values = values;
43115
+ }
43116
+
43117
+ if ( RopeSequence ) Leaf.__proto__ = RopeSequence;
43118
+ Leaf.prototype = Object.create( RopeSequence && RopeSequence.prototype );
43119
+ Leaf.prototype.constructor = Leaf;
43120
+
43121
+ var prototypeAccessors = { length: { configurable: true },depth: { configurable: true } };
43122
+
43123
+ Leaf.prototype.flatten = function flatten () {
43124
+ return this.values
43125
+ };
43126
+
43127
+ Leaf.prototype.sliceInner = function sliceInner (from, to) {
43128
+ if (from == 0 && to == this.length) { return this }
43129
+ return new Leaf(this.values.slice(from, to))
43130
+ };
43131
+
43132
+ Leaf.prototype.getInner = function getInner (i) {
43133
+ return this.values[i]
43134
+ };
43135
+
43136
+ Leaf.prototype.forEachInner = function forEachInner (f, from, to, start) {
43137
+ for (var i = from; i < to; i++)
43138
+ { if (f(this.values[i], start + i) === false) { return false } }
43139
+ };
43140
+
43141
+ Leaf.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) {
43142
+ for (var i = from - 1; i >= to; i--)
43143
+ { if (f(this.values[i], start + i) === false) { return false } }
43144
+ };
43145
+
43146
+ Leaf.prototype.leafAppend = function leafAppend (other) {
43147
+ if (this.length + other.length <= GOOD_LEAF_SIZE)
43148
+ { return new Leaf(this.values.concat(other.flatten())) }
43149
+ };
43150
+
43151
+ Leaf.prototype.leafPrepend = function leafPrepend (other) {
43152
+ if (this.length + other.length <= GOOD_LEAF_SIZE)
43153
+ { return new Leaf(other.flatten().concat(this.values)) }
43154
+ };
43155
+
43156
+ prototypeAccessors.length.get = function () { return this.values.length };
43157
+
43158
+ prototypeAccessors.depth.get = function () { return 0 };
43159
+
43160
+ Object.defineProperties( Leaf.prototype, prototypeAccessors );
43161
+
43162
+ return Leaf;
43163
+ }(RopeSequence));
43164
+
43165
+ // :: RopeSequence
43166
+ // The empty rope sequence.
43167
+ RopeSequence.empty = new Leaf([]);
43168
+
43169
+ var Append = /*@__PURE__*/(function (RopeSequence) {
43170
+ function Append(left, right) {
43171
+ RopeSequence.call(this);
43172
+ this.left = left;
43173
+ this.right = right;
43174
+ this.length = left.length + right.length;
43175
+ this.depth = Math.max(left.depth, right.depth) + 1;
43176
+ }
43177
+
43178
+ if ( RopeSequence ) Append.__proto__ = RopeSequence;
43179
+ Append.prototype = Object.create( RopeSequence && RopeSequence.prototype );
43180
+ Append.prototype.constructor = Append;
43181
+
43182
+ Append.prototype.flatten = function flatten () {
43183
+ return this.left.flatten().concat(this.right.flatten())
43184
+ };
43185
+
43186
+ Append.prototype.getInner = function getInner (i) {
43187
+ return i < this.left.length ? this.left.get(i) : this.right.get(i - this.left.length)
43188
+ };
43189
+
43190
+ Append.prototype.forEachInner = function forEachInner (f, from, to, start) {
43191
+ var leftLen = this.left.length;
43192
+ if (from < leftLen &&
43193
+ this.left.forEachInner(f, from, Math.min(to, leftLen), start) === false)
43194
+ { return false }
43195
+ if (to > leftLen &&
43196
+ this.right.forEachInner(f, Math.max(from - leftLen, 0), Math.min(this.length, to) - leftLen, start + leftLen) === false)
43197
+ { return false }
43198
+ };
43199
+
43200
+ Append.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) {
43201
+ var leftLen = this.left.length;
43202
+ if (from > leftLen &&
43203
+ this.right.forEachInvertedInner(f, from - leftLen, Math.max(to, leftLen) - leftLen, start + leftLen) === false)
43204
+ { return false }
43205
+ if (to < leftLen &&
43206
+ this.left.forEachInvertedInner(f, Math.min(from, leftLen), to, start) === false)
43207
+ { return false }
43208
+ };
43209
+
43210
+ Append.prototype.sliceInner = function sliceInner (from, to) {
43211
+ if (from == 0 && to == this.length) { return this }
43212
+ var leftLen = this.left.length;
43213
+ if (to <= leftLen) { return this.left.slice(from, to) }
43214
+ if (from >= leftLen) { return this.right.slice(from - leftLen, to - leftLen) }
43215
+ return this.left.slice(from, leftLen).append(this.right.slice(0, to - leftLen))
43216
+ };
43217
+
43218
+ Append.prototype.leafAppend = function leafAppend (other) {
43219
+ var inner = this.right.leafAppend(other);
43220
+ if (inner) { return new Append(this.left, inner) }
43221
+ };
43222
+
43223
+ Append.prototype.leafPrepend = function leafPrepend (other) {
43224
+ var inner = this.left.leafPrepend(other);
43225
+ if (inner) { return new Append(inner, this.right) }
43226
+ };
43227
+
43228
+ Append.prototype.appendInner = function appendInner (other) {
43229
+ if (this.left.depth >= Math.max(this.right.depth, other.depth) + 1)
43230
+ { return new Append(this.left, new Append(this.right, other)) }
43231
+ return new Append(this, other)
43232
+ };
43233
+
43234
+ return Append;
43235
+ }(RopeSequence));
43236
+
43237
+ // ProseMirror's history isn't simply a way to roll back to a previous
43238
+ // state, because ProseMirror supports applying changes without adding
43239
+ // them to the history (for example during collaboration).
43240
+ //
43241
+ // To this end, each 'Branch' (one for the undo history and one for
43242
+ // the redo history) keeps an array of 'Items', which can optionally
43243
+ // hold a step (an actual undoable change), and always hold a position
43244
+ // map (which is needed to move changes below them to apply to the
43245
+ // current document).
43246
+ //
43247
+ // An item that has both a step and a selection bookmark is the start
43248
+ // of an 'event' — a group of changes that will be undone or redone at
43249
+ // once. (It stores only the bookmark, since that way we don't have to
43250
+ // provide a document until the selection is actually applied, which
43251
+ // is useful when compressing.)
43252
+ // Used to schedule history compression
43253
+ const max_empty_items = 500;
43254
+ class Branch {
43255
+ constructor(items, eventCount) {
43256
+ this.items = items;
43257
+ this.eventCount = eventCount;
43258
+ }
43259
+ // Pop the latest event off the branch's history and apply it
43260
+ // to a document transform.
43261
+ popEvent(state, preserveItems) {
43262
+ if (this.eventCount == 0)
43263
+ return null;
43264
+ let end = this.items.length;
43265
+ for (;; end--) {
43266
+ let next = this.items.get(end - 1);
43267
+ if (next.selection) {
43268
+ --end;
43269
+ break;
43270
+ }
43271
+ }
43272
+ let remap, mapFrom;
43273
+ if (preserveItems) {
43274
+ remap = this.remapping(end, this.items.length);
43275
+ mapFrom = remap.maps.length;
43276
+ }
43277
+ let transform = state.tr;
43278
+ let selection, remaining;
43279
+ let addAfter = [], addBefore = [];
43280
+ this.items.forEach((item, i) => {
43281
+ if (!item.step) {
43282
+ if (!remap) {
43283
+ remap = this.remapping(end, i + 1);
43284
+ mapFrom = remap.maps.length;
43285
+ }
43286
+ mapFrom--;
43287
+ addBefore.push(item);
43288
+ return;
43289
+ }
43290
+ if (remap) {
43291
+ addBefore.push(new Item(item.map));
43292
+ let step = item.step.map(remap.slice(mapFrom)), map;
43293
+ if (step && transform.maybeStep(step).doc) {
43294
+ map = transform.mapping.maps[transform.mapping.maps.length - 1];
43295
+ addAfter.push(new Item(map, undefined, undefined, addAfter.length + addBefore.length));
43296
+ }
43297
+ mapFrom--;
43298
+ if (map)
43299
+ remap.appendMap(map, mapFrom);
43300
+ }
43301
+ else {
43302
+ transform.maybeStep(item.step);
43303
+ }
43304
+ if (item.selection) {
43305
+ selection = remap ? item.selection.map(remap.slice(mapFrom)) : item.selection;
43306
+ remaining = new Branch(this.items.slice(0, end).append(addBefore.reverse().concat(addAfter)), this.eventCount - 1);
43307
+ return false;
43308
+ }
43309
+ }, this.items.length, 0);
43310
+ return { remaining: remaining, transform, selection: selection };
43311
+ }
43312
+ // Create a new branch with the given transform added.
43313
+ addTransform(transform, selection, histOptions, preserveItems) {
43314
+ let newItems = [], eventCount = this.eventCount;
43315
+ let oldItems = this.items, lastItem = !preserveItems && oldItems.length ? oldItems.get(oldItems.length - 1) : null;
43316
+ for (let i = 0; i < transform.steps.length; i++) {
43317
+ let step = transform.steps[i].invert(transform.docs[i]);
43318
+ let item = new Item(transform.mapping.maps[i], step, selection), merged;
43319
+ if (merged = lastItem && lastItem.merge(item)) {
43320
+ item = merged;
43321
+ if (i)
43322
+ newItems.pop();
43323
+ else
43324
+ oldItems = oldItems.slice(0, oldItems.length - 1);
43325
+ }
43326
+ newItems.push(item);
43327
+ if (selection) {
43328
+ eventCount++;
43329
+ selection = undefined;
43330
+ }
43331
+ if (!preserveItems)
43332
+ lastItem = item;
43333
+ }
43334
+ let overflow = eventCount - histOptions.depth;
43335
+ if (overflow > DEPTH_OVERFLOW) {
43336
+ oldItems = cutOffEvents(oldItems, overflow);
43337
+ eventCount -= overflow;
43338
+ }
43339
+ return new Branch(oldItems.append(newItems), eventCount);
43340
+ }
43341
+ remapping(from, to) {
43342
+ let maps = new Mapping;
43343
+ this.items.forEach((item, i) => {
43344
+ let mirrorPos = item.mirrorOffset != null && i - item.mirrorOffset >= from
43345
+ ? maps.maps.length - item.mirrorOffset : undefined;
43346
+ maps.appendMap(item.map, mirrorPos);
43347
+ }, from, to);
43348
+ return maps;
43349
+ }
43350
+ addMaps(array) {
43351
+ if (this.eventCount == 0)
43352
+ return this;
43353
+ return new Branch(this.items.append(array.map(map => new Item(map))), this.eventCount);
43354
+ }
43355
+ // When the collab module receives remote changes, the history has
43356
+ // to know about those, so that it can adjust the steps that were
43357
+ // rebased on top of the remote changes, and include the position
43358
+ // maps for the remote changes in its array of items.
43359
+ rebased(rebasedTransform, rebasedCount) {
43360
+ if (!this.eventCount)
43361
+ return this;
43362
+ rebasedCount = Math.min(this.items.length, rebasedCount);
43363
+ let rebasedItems = [], start = this.items.length - rebasedCount;
43364
+ let mapping = rebasedTransform.mapping;
43365
+ let newUntil = rebasedTransform.steps.length;
43366
+ let eventCount = this.eventCount;
43367
+ this.items.forEach(item => { if (item.selection)
43368
+ eventCount--; }, start);
43369
+ let iRebased = rebasedCount;
43370
+ this.items.forEach(item => {
43371
+ let pos = mapping.getMirror(--iRebased);
43372
+ if (pos == null)
43373
+ return;
43374
+ newUntil = Math.min(newUntil, pos);
43375
+ let map = mapping.maps[pos];
43376
+ if (item.step) {
43377
+ let step = rebasedTransform.steps[pos].invert(rebasedTransform.docs[pos]);
43378
+ let selection = item.selection && item.selection.map(mapping.slice(iRebased + 1, pos));
43379
+ if (selection)
43380
+ eventCount++;
43381
+ rebasedItems.push(new Item(map, step, selection));
43382
+ }
43383
+ else {
43384
+ rebasedItems.push(new Item(map));
43385
+ }
43386
+ }, start);
43387
+ let newMaps = [];
43388
+ for (let i = rebasedCount; i < newUntil; i++)
43389
+ newMaps.push(new Item(mapping.maps[i]));
43390
+ let items = this.items.slice(0, start).append(newMaps).append(rebasedItems);
43391
+ let branch = new Branch(items, eventCount);
43392
+ if (branch.emptyItemCount() > max_empty_items)
43393
+ branch = branch.compress(this.items.length - rebasedItems.length);
43394
+ return branch;
43395
+ }
43396
+ emptyItemCount() {
43397
+ let count = 0;
43398
+ this.items.forEach(item => { if (!item.step)
43399
+ count++; });
43400
+ return count;
43401
+ }
43402
+ // Compressing a branch means rewriting it to push the air (map-only
43403
+ // items) out. During collaboration, these naturally accumulate
43404
+ // because each remote change adds one. The `upto` argument is used
43405
+ // to ensure that only the items below a given level are compressed,
43406
+ // because `rebased` relies on a clean, untouched set of items in
43407
+ // order to associate old items with rebased steps.
43408
+ compress(upto = this.items.length) {
43409
+ let remap = this.remapping(0, upto), mapFrom = remap.maps.length;
43410
+ let items = [], events = 0;
43411
+ this.items.forEach((item, i) => {
43412
+ if (i >= upto) {
43413
+ items.push(item);
43414
+ if (item.selection)
43415
+ events++;
43416
+ }
43417
+ else if (item.step) {
43418
+ let step = item.step.map(remap.slice(mapFrom)), map = step && step.getMap();
43419
+ mapFrom--;
43420
+ if (map)
43421
+ remap.appendMap(map, mapFrom);
43422
+ if (step) {
43423
+ let selection = item.selection && item.selection.map(remap.slice(mapFrom));
43424
+ if (selection)
43425
+ events++;
43426
+ let newItem = new Item(map.invert(), step, selection), merged, last = items.length - 1;
43427
+ if (merged = items.length && items[last].merge(newItem))
43428
+ items[last] = merged;
43429
+ else
43430
+ items.push(newItem);
43431
+ }
43432
+ }
43433
+ else if (item.map) {
43434
+ mapFrom--;
43435
+ }
43436
+ }, this.items.length, 0);
43437
+ return new Branch(RopeSequence.from(items.reverse()), events);
43438
+ }
43439
+ }
43440
+ Branch.empty = new Branch(RopeSequence.empty, 0);
43441
+ function cutOffEvents(items, n) {
43442
+ let cutPoint;
43443
+ items.forEach((item, i) => {
43444
+ if (item.selection && (n-- == 0)) {
43445
+ cutPoint = i;
43446
+ return false;
43447
+ }
43448
+ });
43449
+ return items.slice(cutPoint);
43450
+ }
43451
+ class Item {
43452
+ constructor(
43453
+ // The (forward) step map for this item.
43454
+ map,
43455
+ // The inverted step
43456
+ step,
43457
+ // If this is non-null, this item is the start of a group, and
43458
+ // this selection is the starting selection for the group (the one
43459
+ // that was active before the first step was applied)
43460
+ selection,
43461
+ // If this item is the inverse of a previous mapping on the stack,
43462
+ // this points at the inverse's offset
43463
+ mirrorOffset) {
43464
+ this.map = map;
43465
+ this.step = step;
43466
+ this.selection = selection;
43467
+ this.mirrorOffset = mirrorOffset;
43468
+ }
43469
+ merge(other) {
43470
+ if (this.step && other.step && !other.selection) {
43471
+ let step = other.step.merge(this.step);
43472
+ if (step)
43473
+ return new Item(step.getMap().invert(), step, this.selection);
43474
+ }
43475
+ }
43476
+ }
43477
+ // The value of the state field that tracks undo/redo history for that
43478
+ // state. Will be stored in the plugin state when the history plugin
43479
+ // is active.
43480
+ class HistoryState {
43481
+ constructor(done, undone, prevRanges, prevTime, prevComposition) {
43482
+ this.done = done;
43483
+ this.undone = undone;
43484
+ this.prevRanges = prevRanges;
43485
+ this.prevTime = prevTime;
43486
+ this.prevComposition = prevComposition;
43487
+ }
43488
+ }
43489
+ const DEPTH_OVERFLOW = 20;
43490
+ // Record a transformation in undo history.
43491
+ function applyTransaction(history, state, tr, options) {
43492
+ let historyTr = tr.getMeta(historyKey), rebased;
43493
+ if (historyTr)
43494
+ return historyTr.historyState;
43495
+ if (tr.getMeta(closeHistoryKey))
43496
+ history = new HistoryState(history.done, history.undone, null, 0, -1);
43497
+ let appended = tr.getMeta("appendedTransaction");
43498
+ if (tr.steps.length == 0) {
43499
+ return history;
43500
+ }
43501
+ else if (appended && appended.getMeta(historyKey)) {
43502
+ if (appended.getMeta(historyKey).redo)
43503
+ return new HistoryState(history.done.addTransform(tr, undefined, options, mustPreserveItems(state)), history.undone, rangesFor(tr.mapping.maps), history.prevTime, history.prevComposition);
43504
+ else
43505
+ return new HistoryState(history.done, history.undone.addTransform(tr, undefined, options, mustPreserveItems(state)), null, history.prevTime, history.prevComposition);
43506
+ }
43507
+ else if (tr.getMeta("addToHistory") !== false && !(appended && appended.getMeta("addToHistory") === false)) {
43508
+ // Group transforms that occur in quick succession into one event.
43509
+ let composition = tr.getMeta("composition");
43510
+ let newGroup = history.prevTime == 0 ||
43511
+ (!appended && history.prevComposition != composition &&
43512
+ (history.prevTime < (tr.time || 0) - options.newGroupDelay || !isAdjacentTo(tr, history.prevRanges)));
43513
+ let prevRanges = appended ? mapRanges(history.prevRanges, tr.mapping) : rangesFor(tr.mapping.maps);
43514
+ return new HistoryState(history.done.addTransform(tr, newGroup ? state.selection.getBookmark() : undefined, options, mustPreserveItems(state)), Branch.empty, prevRanges, tr.time, composition == null ? history.prevComposition : composition);
43515
+ }
43516
+ else if (rebased = tr.getMeta("rebased")) {
43517
+ // Used by the collab module to tell the history that some of its
43518
+ // content has been rebased.
43519
+ return new HistoryState(history.done.rebased(tr, rebased), history.undone.rebased(tr, rebased), mapRanges(history.prevRanges, tr.mapping), history.prevTime, history.prevComposition);
43520
+ }
43521
+ else {
43522
+ return new HistoryState(history.done.addMaps(tr.mapping.maps), history.undone.addMaps(tr.mapping.maps), mapRanges(history.prevRanges, tr.mapping), history.prevTime, history.prevComposition);
43523
+ }
43524
+ }
43525
+ function isAdjacentTo(transform, prevRanges) {
43526
+ if (!prevRanges)
43527
+ return false;
43528
+ if (!transform.docChanged)
43529
+ return true;
43530
+ let adjacent = false;
43531
+ transform.mapping.maps[0].forEach((start, end) => {
43532
+ for (let i = 0; i < prevRanges.length; i += 2)
43533
+ if (start <= prevRanges[i + 1] && end >= prevRanges[i])
43534
+ adjacent = true;
43535
+ });
43536
+ return adjacent;
43537
+ }
43538
+ function rangesFor(maps) {
43539
+ let result = [];
43540
+ for (let i = maps.length - 1; i >= 0 && result.length == 0; i--)
43541
+ maps[i].forEach((_from, _to, from, to) => result.push(from, to));
43542
+ return result;
43543
+ }
43544
+ function mapRanges(ranges, mapping) {
43545
+ if (!ranges)
43546
+ return null;
43547
+ let result = [];
43548
+ for (let i = 0; i < ranges.length; i += 2) {
43549
+ let from = mapping.map(ranges[i], 1), to = mapping.map(ranges[i + 1], -1);
43550
+ if (from <= to)
43551
+ result.push(from, to);
43552
+ }
43553
+ return result;
43554
+ }
43555
+ // Apply the latest event from one branch to the document and shift the event
43556
+ // onto the other branch.
43557
+ function histTransaction(history, state, redo) {
43558
+ let preserveItems = mustPreserveItems(state);
43559
+ let histOptions = historyKey.get(state).spec.config;
43560
+ let pop = (redo ? history.undone : history.done).popEvent(state, preserveItems);
43561
+ if (!pop)
43562
+ return null;
43563
+ let selection = pop.selection.resolve(pop.transform.doc);
43564
+ let added = (redo ? history.done : history.undone).addTransform(pop.transform, state.selection.getBookmark(), histOptions, preserveItems);
43565
+ let newHist = new HistoryState(redo ? added : pop.remaining, redo ? pop.remaining : added, null, 0, -1);
43566
+ return pop.transform.setSelection(selection).setMeta(historyKey, { redo, historyState: newHist });
43567
+ }
43568
+ let cachedPreserveItems = false, cachedPreserveItemsPlugins = null;
43569
+ // Check whether any plugin in the given state has a
43570
+ // `historyPreserveItems` property in its spec, in which case we must
43571
+ // preserve steps exactly as they came in, so that they can be
43572
+ // rebased.
43573
+ function mustPreserveItems(state) {
43574
+ let plugins = state.plugins;
43575
+ if (cachedPreserveItemsPlugins != plugins) {
43576
+ cachedPreserveItems = false;
43577
+ cachedPreserveItemsPlugins = plugins;
43578
+ for (let i = 0; i < plugins.length; i++)
43579
+ if (plugins[i].spec.historyPreserveItems) {
43580
+ cachedPreserveItems = true;
43581
+ break;
43582
+ }
43583
+ }
43584
+ return cachedPreserveItems;
43585
+ }
43586
+ /**
43587
+ Set a flag on the given transaction that will prevent further steps
43588
+ from being appended to an existing history event (so that they
43589
+ require a separate undo command to undo).
43590
+ */
43591
+ function closeHistory(tr) {
43592
+ return tr.setMeta(closeHistoryKey, true);
43593
+ }
43594
+ const historyKey = new PluginKey("history");
43595
+ const closeHistoryKey = new PluginKey("closeHistory");
43596
+ /**
43597
+ Returns a plugin that enables the undo history for an editor. The
43598
+ plugin will track undo and redo stacks, which can be used with the
43599
+ [`undo`](https://prosemirror.net/docs/ref/#history.undo) and [`redo`](https://prosemirror.net/docs/ref/#history.redo) commands.
43600
+
43601
+ You can set an `"addToHistory"` [metadata
43602
+ property](https://prosemirror.net/docs/ref/#state.Transaction.setMeta) of `false` on a transaction
43603
+ to prevent it from being rolled back by undo.
43604
+ */
43605
+ function history(config = {}) {
43606
+ config = { depth: config.depth || 100,
43607
+ newGroupDelay: config.newGroupDelay || 500 };
43608
+ return new Plugin({
43609
+ key: historyKey,
43610
+ state: {
43611
+ init() {
43612
+ return new HistoryState(Branch.empty, Branch.empty, null, 0, -1);
43613
+ },
43614
+ apply(tr, hist, state) {
43615
+ return applyTransaction(hist, state, tr, config);
43616
+ }
43617
+ },
43618
+ config,
43619
+ props: {
43620
+ handleDOMEvents: {
43621
+ beforeinput(view, e) {
43622
+ let inputType = e.inputType;
43623
+ let command = inputType == "historyUndo" ? undo : inputType == "historyRedo" ? redo : null;
43624
+ if (!command || !view.editable)
43625
+ return false;
43626
+ e.preventDefault();
43627
+ return command(view.state, view.dispatch);
43628
+ }
43629
+ }
43630
+ }
43631
+ });
43632
+ }
43633
+ function buildCommand(redo, scroll) {
43634
+ return (state, dispatch) => {
43635
+ let hist = historyKey.getState(state);
43636
+ if (!hist || (redo ? hist.undone : hist.done).eventCount == 0)
43637
+ return false;
43638
+ if (dispatch) {
43639
+ let tr = histTransaction(hist, state, redo);
43640
+ if (tr)
43641
+ dispatch(scroll ? tr.scrollIntoView() : tr);
43642
+ }
43643
+ return true;
43644
+ };
43645
+ }
43646
+ /**
43647
+ A command function that undoes the last change, if any.
43648
+ */
43649
+ const undo = buildCommand(false, true);
43650
+ /**
43651
+ A command function that redoes the last undone change, if any.
43652
+ */
43653
+ const redo = buildCommand(true, true);
43654
+ /**
43655
+ Returns true if the given transaction was generated by the history
43656
+ plugin.
43657
+ */
43658
+ function isHistoryTransaction(tr) {
43659
+ return tr.getMeta(historyKey) != null;
43660
+ }
43661
+
43662
+ //#region src/helpers/createChainableState.ts
43663
+ /**
43664
+ * Takes a Transaction & Editor State and turns it into a chainable state object
43665
+ * @param config The transaction and state to create the chainable state from
43666
+ * @returns A chainable Editor state object
43667
+ */
43668
+ function createChainableState(config) {
43669
+ const { state, transaction } = config;
43670
+ let { selection } = transaction;
43671
+ let { doc } = transaction;
43672
+ let { storedMarks } = transaction;
43673
+ return {
43674
+ ...state,
43675
+ apply: state.apply.bind(state),
43676
+ applyTransaction: state.applyTransaction.bind(state),
43677
+ plugins: state.plugins,
43678
+ schema: state.schema,
43679
+ reconfigure: state.reconfigure.bind(state),
43680
+ toJSON: state.toJSON.bind(state),
43681
+ get storedMarks() {
43682
+ return storedMarks;
43683
+ },
43684
+ get selection() {
43685
+ return selection;
43686
+ },
43687
+ get doc() {
43688
+ return doc;
43689
+ },
43690
+ get tr() {
43691
+ selection = transaction.selection;
43692
+ doc = transaction.doc;
43693
+ storedMarks = transaction.storedMarks;
43694
+ return transaction;
43695
+ }
43696
+ };
43697
+ }
43698
+ //#endregion
43699
+ //#region src/CommandManager.ts
43700
+ var CommandManager = class CommandManager {
43701
+ constructor(props) {
43702
+ this.editor = props.editor;
43703
+ this.rawCommands = this.editor.extensionManager.commands;
43704
+ this.customState = props.state;
43705
+ }
43706
+ get hasCustomState() {
43707
+ return !!this.customState;
43708
+ }
43709
+ get state() {
43710
+ return this.customState || this.editor.state;
43711
+ }
43712
+ get commands() {
43713
+ const { rawCommands, editor, state } = this;
43714
+ const { view } = editor;
43715
+ const { tr } = state;
43716
+ const props = this.buildProps(tr);
43717
+ return Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
43718
+ const method = (...args) => {
43719
+ const callback = command(...args)(props);
43720
+ if (!tr.getMeta("preventDispatch") && !this.hasCustomState) view.dispatch(tr);
43721
+ return callback;
43722
+ };
43723
+ return [name, method];
43724
+ }));
43725
+ }
43726
+ get chain() {
43727
+ return () => this.createChain();
43728
+ }
43729
+ get can() {
43730
+ return () => this.createCan();
43731
+ }
43732
+ createChain(startTr, shouldDispatch = true) {
43733
+ const { rawCommands, editor, state } = this;
43734
+ const { view } = editor;
43735
+ const callbacks = [];
43736
+ const hasStartTransaction = !!startTr;
43737
+ const tr = startTr || state.tr;
43738
+ const run = () => {
43739
+ if (!hasStartTransaction && shouldDispatch && !tr.getMeta("preventDispatch") && !this.hasCustomState) view.dispatch(tr);
43740
+ return callbacks.every((callback) => callback === true);
43741
+ };
43742
+ const chain = {
43743
+ ...Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
43744
+ const chainedCommand = (...args) => {
43745
+ const props = this.buildProps(tr, shouldDispatch);
43746
+ const callback = command(...args)(props);
43747
+ callbacks.push(callback);
43748
+ return chain;
43749
+ };
43750
+ return [name, chainedCommand];
43751
+ })),
43752
+ run
43753
+ };
43754
+ return chain;
43755
+ }
43756
+ /**
43757
+ * Creates a chain that safely returns `false` when run.
43758
+ * @returns A non-dispatching command chain.
43759
+ * @example
43760
+ * const chain = CommandManager.createFakeChain()
43761
+ * chain.focus().run() // false
43762
+ */
43763
+ static createFakeChain() {
43764
+ const chain = new Proxy({}, { get: (_target, property) => {
43765
+ if (property === "then") return;
43766
+ if (property === "run") return () => false;
43767
+ return () => chain;
43768
+ } });
43769
+ return chain;
43770
+ }
43771
+ createCan(startTr) {
43772
+ const { rawCommands, state } = this;
43773
+ const dispatch = false;
43774
+ const tr = startTr || state.tr;
43775
+ const props = this.buildProps(tr, dispatch);
43776
+ return {
43777
+ ...Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
43778
+ return [name, (...args) => command(...args)({
43779
+ ...props,
43780
+ dispatch: void 0
43781
+ })];
43782
+ })),
43783
+ chain: () => this.createChain(tr, dispatch)
43784
+ };
43785
+ }
43786
+ /**
43787
+ * Creates capability checks that safely return `false`.
43788
+ * @returns A non-dispatching capability checker.
43789
+ * @example
43790
+ * const can = CommandManager.createFallbackCan()
43791
+ * can.focus() // false
43792
+ */
43793
+ static createFallbackCan() {
43794
+ const chain = CommandManager.createFakeChain();
43795
+ return new Proxy({ chain: () => chain }, { get: (target, property) => {
43796
+ if (property === "then") return;
43797
+ if (property === "chain") return target.chain;
43798
+ return () => false;
43799
+ } });
43800
+ }
43801
+ buildProps(tr, shouldDispatch = true) {
43802
+ const { rawCommands, editor, state } = this;
43803
+ const { view } = editor;
43804
+ const props = {
43805
+ tr,
43806
+ editor,
43807
+ view,
43808
+ state: createChainableState({
43809
+ state,
43810
+ transaction: tr
43811
+ }),
43812
+ dispatch: shouldDispatch ? () => void 0 : void 0,
43813
+ chain: () => this.createChain(tr, shouldDispatch),
43814
+ can: () => this.createCan(tr),
43815
+ get commands() {
43816
+ return Object.fromEntries(Object.entries(rawCommands).map(([name, command]) => {
43817
+ return [name, (...args) => command(...args)(props)];
43818
+ }));
43819
+ }
43820
+ };
43821
+ return props;
43822
+ }
43823
+ };
43824
+ //#endregion
43825
+ //#region src/commands/blur.ts
43826
+ const blur = () => ({ editor, view }) => {
43827
+ requestAnimationFrame(() => {
43828
+ if (!editor.isDestroyed) {
43829
+ var _window;
43830
+ view.dom.blur();
43831
+ (_window = window) === null || _window === void 0 || (_window = _window.getSelection()) === null || _window === void 0 || _window.removeAllRanges();
43832
+ }
43833
+ });
43834
+ return true;
43835
+ };
43836
+ //#endregion
43837
+ //#region src/commands/clearContent.ts
43838
+ const clearContent = (emitUpdate = true) => ({ commands }) => {
43839
+ return commands.setContent("", { emitUpdate });
43840
+ };
43841
+ //#endregion
43842
+ //#region src/commands/clearNodes.ts
43843
+ const clearNodes = () => ({ state, tr, dispatch }) => {
43844
+ const { selection } = tr;
43845
+ const { ranges } = selection;
43846
+ if (!dispatch) return true;
43847
+ ranges.forEach(({ $from, $to }) => {
43848
+ state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
43849
+ if (node.type.isText) return;
43850
+ const { doc, mapping } = tr;
43851
+ const $mappedFrom = doc.resolve(mapping.map(pos));
43852
+ const $mappedTo = doc.resolve(mapping.map(pos + node.nodeSize));
43853
+ const nodeRange = $mappedFrom.blockRange($mappedTo);
43854
+ if (!nodeRange) return;
43855
+ const targetLiftDepth = liftTarget(nodeRange);
43856
+ if (node.type.isTextblock) {
43857
+ const { defaultType } = $mappedFrom.parent.contentMatchAt($mappedFrom.index());
43858
+ tr.setNodeMarkup(nodeRange.start, defaultType);
43859
+ }
43860
+ if (targetLiftDepth || targetLiftDepth === 0) tr.lift(nodeRange, targetLiftDepth);
43861
+ });
43862
+ });
43863
+ return true;
43864
+ };
43865
+ //#endregion
43866
+ //#region src/commands/command.ts
43867
+ const command = (fn) => (props) => {
43868
+ return fn(props);
43869
+ };
43870
+ //#endregion
43871
+ //#region src/commands/createParagraphNear.ts
43872
+ const createParagraphNear$1 = () => ({ state, dispatch }) => {
43873
+ return createParagraphNear(state, dispatch);
43874
+ };
43875
+ //#endregion
43876
+ //#region src/commands/cut.ts
43877
+ const cut = (originRange, targetPos) => ({ editor, tr }) => {
43878
+ const { state } = editor;
43879
+ const contentSlice = state.doc.slice(originRange.from, originRange.to);
43880
+ tr.deleteRange(originRange.from, originRange.to);
43881
+ const newPos = tr.mapping.map(targetPos);
43882
+ tr.insert(newPos, contentSlice.content);
43883
+ tr.setSelection(new TextSelection(tr.doc.resolve(Math.max(newPos - 1, 0))));
43884
+ return true;
43885
+ };
43886
+ //#endregion
43887
+ //#region src/commands/deleteCurrentNode.ts
43888
+ const deleteCurrentNode = () => ({ tr, dispatch }) => {
43889
+ const { selection } = tr;
43890
+ const currentNode = selection.$anchor.node();
43891
+ if (currentNode.content.size > 0) return false;
43892
+ const $pos = tr.selection.$anchor;
43893
+ for (let depth = $pos.depth; depth > 0; depth -= 1) if ($pos.node(depth).type === currentNode.type) {
43894
+ if (dispatch) {
43895
+ const from = $pos.before(depth);
43896
+ const to = $pos.after(depth);
43897
+ tr.delete(from, to).scrollIntoView();
43898
+ }
43899
+ return true;
43900
+ }
43901
+ return false;
43902
+ };
43903
+ //#endregion
43904
+ //#region src/helpers/getNodeType.ts
43905
+ function getNodeType(nameOrType, schema) {
43906
+ if (typeof nameOrType === "string") {
43907
+ if (!schema.nodes[nameOrType]) throw Error(`There is no node type named '${nameOrType}'. Maybe you forgot to add the extension?`);
43908
+ return schema.nodes[nameOrType];
43909
+ }
43910
+ return nameOrType;
43911
+ }
43912
+ //#endregion
43913
+ //#region src/commands/deleteNode.ts
43914
+ const deleteNode = (typeOrName) => ({ tr, state, dispatch }) => {
43915
+ const type = getNodeType(typeOrName, state.schema);
43916
+ const $pos = tr.selection.$anchor;
43917
+ for (let depth = $pos.depth; depth > 0; depth -= 1) if ($pos.node(depth).type === type) {
43918
+ if (dispatch) {
43919
+ const from = $pos.before(depth);
43920
+ const to = $pos.after(depth);
43921
+ tr.delete(from, to).scrollIntoView();
43922
+ }
43923
+ return true;
43924
+ }
43925
+ return false;
43926
+ };
43927
+ //#endregion
43928
+ //#region src/commands/deleteRange.ts
43929
+ const deleteRange = (range) => ({ tr, dispatch }) => {
43930
+ const { from, to } = range;
43931
+ if (dispatch) tr.delete(from, to);
43932
+ return true;
43933
+ };
43934
+ //#endregion
43935
+ //#region src/commands/deleteSelection.ts
43936
+ /**
43937
+ * Check if a node has text content based on its content specification.
43938
+ * Returns true if the node's content spec matches text* or text+ patterns.
43939
+ */
43940
+ const hasTextContent = (nodeSpec) => {
43941
+ if (!nodeSpec.content) return false;
43942
+ return /^text(\*|\+)/.test(nodeSpec.content);
43943
+ };
43944
+ /**
43945
+ * Expand selection position for a specific side (left or right) to handle inline text nodes.
43946
+ * This function checks if the position is within an inline node with text content and
43947
+ * expands it to include the entire node boundaries for proper deletion.
43948
+ * @param $pos - The resolved position to expand
43949
+ * @param schema - The ProseMirror schema
43950
+ * @param side - Which side to expand ('left' or 'right')
43951
+ * @returns The expanded position for deletion
43952
+ */
43953
+ const expandSelectionForSide = ($pos, schema, side) => {
43954
+ if (!$pos.parent.isInline) return $pos.pos;
43955
+ if (side === "left" && $pos.pos > $pos.start() || side === "right" && $pos.pos < $pos.end()) return $pos.pos;
43956
+ const parentContent = schema.nodes[$pos.parent.type.name].spec;
43957
+ if (!hasTextContent(parentContent)) return $pos.pos;
43958
+ return side === "left" ? $pos.start() - 1 : $pos.end() + 1;
43959
+ };
43960
+ /**
43961
+ * Expand selection range to properly handle deletion of inline text nodes.
43962
+ * Inline text nodes don't collapse correctly when text inside is deleted,
43963
+ * so we need to expand the selection to include the entire node.
43964
+ * See: https://code.haverbeke.berlin/prosemirror/prosemirror/issues/1365
43965
+ */
43966
+ const expandSelectionForInlineText = ($from, $to, schema) => {
43967
+ return {
43968
+ from: expandSelectionForSide($from, schema, "left"),
43969
+ to: expandSelectionForSide($to, schema, "right")
43970
+ };
43971
+ };
43972
+ const deleteSelection = () => ({ state, dispatch }) => {
43973
+ if (state.selection.empty) return false;
43974
+ if (dispatch) {
43975
+ const tr = state.tr;
43976
+ const { ranges } = state.selection;
43977
+ const mapFrom = tr.steps.length;
43978
+ ranges.forEach((range) => {
43979
+ const mapping = tr.mapping.slice(mapFrom);
43980
+ const $from = tr.doc.resolve(mapping.map(range.$from.pos));
43981
+ const $to = tr.doc.resolve(mapping.map(range.$to.pos));
43982
+ const { from, to } = expandSelectionForInlineText($from, $to, state.schema);
43983
+ tr.deleteRange(from, to);
43984
+ });
43985
+ if (!tr.selection.empty) tr.setSelection(TextSelection.near(tr.doc.resolve(tr.selection.from)));
43986
+ tr.scrollIntoView();
43987
+ dispatch(tr);
43988
+ }
43989
+ return true;
43990
+ };
43991
+ //#endregion
43992
+ //#region src/commands/enter.ts
43993
+ const enter = () => ({ commands }) => {
43994
+ return commands.keyboardShortcut("Enter");
43995
+ };
43996
+ //#endregion
43997
+ //#region src/commands/exitCode.ts
43998
+ const exitCode$1 = () => ({ state, dispatch }) => {
43999
+ return exitCode(state, dispatch);
44000
+ };
44001
+ //#endregion
44002
+ //#region src/utilities/isRegExp.ts
44003
+ function isRegExp$1(value) {
44004
+ return Object.prototype.toString.call(value) === "[object RegExp]";
44005
+ }
44006
+ //#endregion
44007
+ //#region src/utilities/objectIncludes.ts
44008
+ /**
44009
+ * Check if object1 includes object2
44010
+ * @param object1 Object
44011
+ * @param object2 Object
44012
+ */
44013
+ function objectIncludes(object1, object2, options = { strict: true }) {
44014
+ const keys = Object.keys(object2);
44015
+ if (!keys.length) return true;
44016
+ return keys.every((key) => {
44017
+ if (options.strict) return object2[key] === object1[key];
44018
+ if (isRegExp$1(object2[key])) return object2[key].test(object1[key]);
44019
+ return object2[key] === object1[key];
44020
+ });
44021
+ }
44022
+ //#endregion
44023
+ //#region src/helpers/getMarkRange.ts
44024
+ function findMarkInSet(marks, type, attributes = {}) {
44025
+ return marks.find((item) => {
44026
+ return item.type === type && objectIncludes(Object.fromEntries(Object.keys(attributes).map((k) => [k, item.attrs[k]])), attributes);
44027
+ });
44028
+ }
44029
+ function isMarkInSet(marks, type, attributes = {}) {
44030
+ return !!findMarkInSet(marks, type, attributes);
44031
+ }
44032
+ /**
44033
+ * Get the range of a mark at a resolved position.
44034
+ */
44035
+ function getMarkRange($pos, type, attributes) {
44036
+ if (!$pos || !type) return;
44037
+ let start = $pos.parent.childAfter($pos.parentOffset);
43369
44038
  if (!start.node || !start.node.marks.some((mark) => mark.type === type)) start = $pos.parent.childBefore($pos.parentOffset);
43370
44039
  if (!start.node || !start.node.marks.some((mark) => mark.type === type)) return;
43371
44040
  if (!attributes) {
@@ -43792,11 +44461,21 @@ so this becomes the fallback color for the slot */ ''}
43792
44461
  return joinForward(state, dispatch);
43793
44462
  };
43794
44463
  //#endregion
44464
+ //#region src/commands/canJoinItemsAt.ts
44465
+ const canJoinItemsAt = (doc, pos) => {
44466
+ const $pos = doc.resolve(pos);
44467
+ const before = $pos.nodeBefore;
44468
+ const after = $pos.nodeAfter;
44469
+ if (!before || !after) return false;
44470
+ return !before.type.spec.isolating && !after.type.spec.isolating;
44471
+ };
44472
+ //#endregion
43795
44473
  //#region src/commands/joinItemBackward.ts
43796
44474
  const joinItemBackward = () => ({ state, dispatch, tr }) => {
43797
44475
  try {
43798
44476
  const point = joinPoint(state.doc, state.selection.$from.pos, -1);
43799
44477
  if (point === null || point === void 0) return false;
44478
+ if (!canJoinItemsAt(state.doc, point)) return false;
43800
44479
  tr.join(point, 2);
43801
44480
  if (dispatch) dispatch(tr);
43802
44481
  return true;
@@ -43810,6 +44489,7 @@ so this becomes the fallback color for the slot */ ''}
43810
44489
  try {
43811
44490
  const point = joinPoint(state.doc, state.selection.$from.pos, 1);
43812
44491
  if (point === null || point === void 0) return false;
44492
+ if (!canJoinItemsAt(state.doc, point)) return false;
43813
44493
  tr.join(point, 2);
43814
44494
  if (dispatch) dispatch(tr);
43815
44495
  return true;
@@ -45216,8 +45896,14 @@ so this becomes the fallback color for the slot */ ''}
45216
45896
  type: deflt,
45217
45897
  attrs: newAttributes
45218
45898
  }] : void 0;
45219
- let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types);
45220
- if (!types && !can && canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : void 0)) {
45899
+ const deletedTr = selection instanceof TextSelection && !selection.empty ? EditorState.create({
45900
+ doc: tr.doc,
45901
+ selection
45902
+ }).tr.deleteSelection() : null;
45903
+ const splitDoc = deletedTr ? deletedTr.doc : tr.doc;
45904
+ const splitPos = deletedTr ? deletedTr.mapping.map($from.pos) : $from.pos;
45905
+ let can = canSplit(splitDoc, splitPos, 1, types);
45906
+ if (!types && !can && canSplit(splitDoc, splitPos, 1, deflt ? [{ type: deflt }] : void 0)) {
45221
45907
  can = true;
45222
45908
  types = deflt ? [{
45223
45909
  type: deflt,
@@ -45226,12 +45912,13 @@ so this becomes the fallback color for the slot */ ''}
45226
45912
  }
45227
45913
  if (dispatch) {
45228
45914
  if (can) {
45915
+ const mapFrom = tr.steps.length;
45229
45916
  if (selection instanceof TextSelection) tr.deleteSelection();
45230
- tr.split(tr.mapping.map($from.pos), 1, types);
45917
+ tr.split(tr.mapping.slice(mapFrom).map($from.pos), 1, types);
45231
45918
  if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
45232
- const first = tr.mapping.map($from.before());
45919
+ const first = tr.mapping.slice(mapFrom).map($from.before());
45233
45920
  const $first = tr.doc.resolve(first);
45234
- if ($from.node(-1).canReplaceWith($first.index(), $first.index() + 1, deflt)) tr.setNodeMarkup(tr.mapping.map($from.before()), deflt);
45921
+ if ($from.node(-1).canReplaceWith($first.index(), $first.index() + 1, deflt)) tr.setNodeMarkup(tr.mapping.slice(mapFrom).map($from.before()), deflt);
45235
45922
  }
45236
45923
  }
45237
45924
  if (keepMarks) ensureMarks(state, editor.extensionManager.splittableMarks);
@@ -45284,16 +45971,19 @@ so this becomes the fallback color for the slot */ ''}
45284
45971
  ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
45285
45972
  ...overrideAttrs
45286
45973
  };
45974
+ const splitsAtStartOfItem = $from.parentOffset === 0 && $from.index(-1) === 0;
45975
+ const itemStart = $from.before(-1);
45287
45976
  tr.delete($from.pos, $to.pos);
45977
+ const trailingTypeAttributes = splitsAtStartOfItem ? grandParent.attrs : newTypeAttributes;
45288
45978
  const types = nextType ? [{
45289
45979
  type,
45290
- attrs: newTypeAttributes
45980
+ attrs: trailingTypeAttributes
45291
45981
  }, {
45292
45982
  type: nextType,
45293
45983
  attrs: newNextTypeAttributes
45294
45984
  }] : [{
45295
45985
  type,
45296
- attrs: newTypeAttributes
45986
+ attrs: trailingTypeAttributes
45297
45987
  }];
45298
45988
  if (!canSplit(tr.doc, $from.pos, 2)) return false;
45299
45989
  if (dispatch) {
@@ -45301,6 +45991,7 @@ so this becomes the fallback color for the slot */ ''}
45301
45991
  const { splittableMarks } = editor.extensionManager;
45302
45992
  const marks = storedMarks || selection.$to.parentOffset && selection.$from.marks();
45303
45993
  tr.split($from.pos, 2, types).scrollIntoView();
45994
+ if (splitsAtStartOfItem) tr.setNodeMarkup(itemStart, void 0, newTypeAttributes);
45304
45995
  if (!marks || !dispatch) return true;
45305
45996
  const filteredMarks = marks.filter((mark) => splittableMarks.includes(mark.type.name));
45306
45997
  tr.ensureMarks(filteredMarks);
@@ -46833,55 +47524,106 @@ so this becomes the fallback color for the slot */ ''}
46833
47524
  }
46834
47525
  return result;
46835
47526
  };
47527
+ /**
47528
+ * Prepares the typed text so the rule handler can inspect the resulting document.
47529
+ */
47530
+ function createRuleTransaction(config) {
47531
+ const { editor, from, to, text, insertText } = config;
47532
+ if (!insertText) return {
47533
+ inputTransaction: null,
47534
+ tr: editor.view.state.tr
47535
+ };
47536
+ const inputTransaction = editor.view.state.tr.insertText(text, from, to);
47537
+ return {
47538
+ inputTransaction,
47539
+ tr: EditorState.create({
47540
+ doc: inputTransaction.doc,
47541
+ selection: inputTransaction.selection,
47542
+ storedMarks: inputTransaction.storedMarks
47543
+ }).tr
47544
+ };
47545
+ }
47546
+ /**
47547
+ * Runs a matching rule and dispatches the typed text before its conversion.
47548
+ */
47549
+ function applyRule(config) {
47550
+ const { editor, from, to, text, rule, match, plugin, insertText } = config;
47551
+ const { view } = editor;
47552
+ const { inputTransaction, tr } = createRuleTransaction({
47553
+ editor,
47554
+ from,
47555
+ to,
47556
+ text,
47557
+ insertText
47558
+ });
47559
+ const inputEnd = inputTransaction ? from + text.length : to;
47560
+ const state = createChainableState({
47561
+ state: view.state,
47562
+ transaction: tr
47563
+ });
47564
+ const range = {
47565
+ from: from - (match[0].length - text.length),
47566
+ to: inputEnd
47567
+ };
47568
+ const { commands, chain, can } = new CommandManager({
47569
+ editor,
47570
+ state
47571
+ });
47572
+ if (rule.handler({
47573
+ state,
47574
+ range,
47575
+ match,
47576
+ commands,
47577
+ chain,
47578
+ can
47579
+ }) === null || !tr.steps.length) return false;
47580
+ if (inputTransaction) {
47581
+ view.dispatch(inputTransaction);
47582
+ if (!view.state.doc.eq(inputTransaction.doc)) return true;
47583
+ }
47584
+ closeHistory(tr);
47585
+ tr.setMeta("inputRule", true);
47586
+ if (rule.undoable) tr.setMeta(plugin, {
47587
+ transform: tr,
47588
+ from,
47589
+ to: inputEnd,
47590
+ text
47591
+ });
47592
+ view.dispatch(tr);
47593
+ return true;
47594
+ }
47595
+ /**
47596
+ * Checks that the part of a match already in the document has matching positions.
47597
+ */
47598
+ function matchesDocument($from, match, text) {
47599
+ const matchedDocLength = match[0].length - text.length;
47600
+ if (matchedDocLength <= 0) return true;
47601
+ const matchStartOffset = $from.parentOffset - matchedDocLength;
47602
+ return matchStartOffset >= 0 && $from.parent.textBetween(matchStartOffset, $from.parentOffset) === match[0].slice(0, matchedDocLength);
47603
+ }
46836
47604
  function run$1$1(config) {
46837
47605
  var _ref;
46838
- const { editor, from, to, text, rules, plugin } = config;
47606
+ const { editor, from, to, text, rules, plugin, insertText } = config;
46839
47607
  const { view } = editor;
46840
47608
  if (view.composing) return false;
46841
47609
  const $from = view.state.doc.resolve(from);
46842
47610
  if ($from.parent.type.spec.code || !!((_ref = $from.nodeBefore || $from.nodeAfter) === null || _ref === void 0 ? void 0 : _ref.marks.find((mark) => mark.type.spec.code))) return false;
46843
- let matched = false;
46844
47611
  const textBefore = getTextContentFromNodes($from) + text;
46845
- rules.forEach((rule) => {
46846
- if (matched) return;
47612
+ for (const rule of rules) {
46847
47613
  const match = inputRuleMatcherHandler(textBefore, rule.find);
46848
- if (!match) return;
46849
- const matchedDocLength = match[0].length - text.length;
46850
- if (matchedDocLength > 0) {
46851
- const matchStartOffset = $from.parentOffset - matchedDocLength;
46852
- if (matchStartOffset < 0 || $from.parent.textBetween(matchStartOffset, $from.parentOffset) !== match[0].slice(0, matchedDocLength)) return;
46853
- }
46854
- const tr = view.state.tr;
46855
- const state = createChainableState({
46856
- state: view.state,
46857
- transaction: tr
46858
- });
46859
- const range = {
46860
- from: from - (match[0].length - text.length),
46861
- to
46862
- };
46863
- const { commands, chain, can } = new CommandManager({
47614
+ if (!match || !matchesDocument($from, match, text)) continue;
47615
+ if (applyRule({
46864
47616
  editor,
46865
- state
46866
- });
46867
- if (rule.handler({
46868
- state,
46869
- range,
46870
- match,
46871
- commands,
46872
- chain,
46873
- can
46874
- }) === null || !tr.steps.length) return;
46875
- if (rule.undoable) tr.setMeta(plugin, {
46876
- transform: tr,
46877
47617
  from,
46878
47618
  to,
46879
- text
46880
- });
46881
- view.dispatch(tr);
46882
- matched = true;
46883
- });
46884
- return matched;
47619
+ text,
47620
+ rule,
47621
+ match,
47622
+ plugin,
47623
+ insertText
47624
+ })) return true;
47625
+ }
47626
+ return false;
46885
47627
  }
46886
47628
  /**
46887
47629
  * Create an input rules plugin. When enabled, it will cause text
@@ -46925,7 +47667,8 @@ so this becomes the fallback color for the slot */ ''}
46925
47667
  to,
46926
47668
  text,
46927
47669
  rules,
46928
- plugin
47670
+ plugin,
47671
+ insertText: true
46929
47672
  });
46930
47673
  },
46931
47674
  handleDOMEvents: { compositionend: (view) => {
@@ -47161,6 +47904,9 @@ so this becomes the fallback color for the slot */ ''}
47161
47904
  pasteEvent = typeof ClipboardEvent !== "undefined" ? new ClipboardEvent("paste") : null;
47162
47905
  return tr;
47163
47906
  };
47907
+ editor.on("destroy", () => {
47908
+ if (tiptapDragFromOtherEditor === editor) tiptapDragFromOtherEditor = null;
47909
+ });
47164
47910
  return rules.map((rule) => {
47165
47911
  return new Plugin({
47166
47912
  view(view) {
@@ -47186,6 +47932,7 @@ so this becomes the fallback color for the slot */ ''}
47186
47932
  if (!isDroppedFromProseMirror) {
47187
47933
  const dragFromOtherEditor = tiptapDragFromOtherEditor;
47188
47934
  if (dragFromOtherEditor === null || dragFromOtherEditor === void 0 ? void 0 : dragFromOtherEditor.isEditable) setTimeout(() => {
47935
+ if (dragFromOtherEditor.isDestroyed) return;
47189
47936
  const selection = dragFromOtherEditor.state.selection;
47190
47937
  if (selection) dragFromOtherEditor.commands.deleteRange({
47191
47938
  from: selection.from,
@@ -48355,7 +49102,10 @@ img.ProseMirror-separator {
48355
49102
  ...options
48356
49103
  };
48357
49104
  if (!this.editorView || !this.state || this.isDestroyed) return;
48358
- if (this.options.editorProps) this.view.setProps(this.options.editorProps);
49105
+ if (this.options.editorProps) this.view.setProps({
49106
+ ...this.options.editorProps,
49107
+ attributes: this.getEditorViewAttributes()
49108
+ });
48359
49109
  this.view.updateState(this.state);
48360
49110
  }
48361
49111
  /**
@@ -48511,6 +49261,23 @@ img.ProseMirror-separator {
48511
49261
  return doc;
48512
49262
  }
48513
49263
  /**
49264
+ * Returns the attributes for the editor element.
49265
+ * Merges the default `role="textbox"` with the attributes from `editorProps`,
49266
+ * so the role is kept no matter when the props are applied.
49267
+ */
49268
+ getEditorViewAttributes() {
49269
+ var _this$options$editorP;
49270
+ const attributes = (_this$options$editorP = this.options.editorProps) === null || _this$options$editorP === void 0 ? void 0 : _this$options$editorP.attributes;
49271
+ if (isFunction$3(attributes)) return (state) => ({
49272
+ role: "textbox",
49273
+ ...attributes(state)
49274
+ });
49275
+ return {
49276
+ role: "textbox",
49277
+ ...attributes
49278
+ };
49279
+ }
49280
+ /**
48514
49281
  * Creates a ProseMirror view.
48515
49282
  */
48516
49283
  createView(element) {
@@ -48521,10 +49288,7 @@ img.ProseMirror-separator {
48521
49288
  const transformPastedHTML = this.extensionManager.transformPastedHTML(baseTransformPastedHTML);
48522
49289
  this.editorView = new EditorView(element, {
48523
49290
  ...editorProps,
48524
- attributes: {
48525
- role: "textbox",
48526
- ...editorProps === null || editorProps === void 0 ? void 0 : editorProps.attributes
48527
- },
49291
+ attributes: this.getEditorViewAttributes(),
48528
49292
  dispatchTransaction: dispatch,
48529
49293
  transformPastedHTML,
48530
49294
  state: this.editorState,
@@ -58227,7 +58991,7 @@ img.ProseMirror-separator {
58227
58991
  toDOM() { return ["div", ["hr"]]; }
58228
58992
  },
58229
58993
  heading: {
58230
- attrs: { level: { default: 1 } },
58994
+ attrs: { level: { default: 1, validate: "number" } },
58231
58995
  content: "(text | image)*",
58232
58996
  group: "block",
58233
58997
  defining: true,
@@ -58237,7 +59001,7 @@ img.ProseMirror-separator {
58237
59001
  { tag: "h4", attrs: { level: 4 } },
58238
59002
  { tag: "h5", attrs: { level: 5 } },
58239
59003
  { tag: "h6", attrs: { level: 6 } }],
58240
- toDOM(node) { return ["h" + node.attrs.level, 0]; }
59004
+ toDOM(node) { return ["h" + +node.attrs.level, 0]; }
58241
59005
  },
58242
59006
  code_block: {
58243
59007
  content: "text*",
@@ -61734,8 +62498,27 @@ img.ProseMirror-separator {
61734
62498
  const UNICODE_WHITESPACE_PATTERN = "[\0- \xA0 ᠎ -\u2029  ]";
61735
62499
  const UNICODE_WHITESPACE_REGEX = new RegExp(UNICODE_WHITESPACE_PATTERN);
61736
62500
  const UNICODE_WHITESPACE_REGEX_END = new RegExp(`${UNICODE_WHITESPACE_PATTERN}$`);
62501
+ const UNICODE_WHITESPACE_REGEX_TRAILING = new RegExp(`${UNICODE_WHITESPACE_PATTERN}+$`);
61737
62502
  const UNICODE_WHITESPACE_REGEX_GLOBAL = new RegExp(UNICODE_WHITESPACE_PATTERN, "g");
61738
62503
  //#endregion
62504
+ //#region src/helpers/unlinkTrailingWhitespace.ts
62505
+ function unlinkTrailingWhitespace(tr, range, type) {
62506
+ var _rangeEnd$nodeBefore, _insertedText$match;
62507
+ const rangeEnd = tr.doc.resolve(range.to);
62508
+ if (!((_rangeEnd$nodeBefore = rangeEnd.nodeBefore) === null || _rangeEnd$nodeBefore === void 0 ? void 0 : _rangeEnd$nodeBefore.isText)) return;
62509
+ const trailingWhitespace = (_insertedText$match = tr.doc.textBetween(range.from, range.to, "", "").match(UNICODE_WHITESPACE_REGEX_TRAILING)) === null || _insertedText$match === void 0 ? void 0 : _insertedText$match[0];
62510
+ if (!trailingWhitespace) return;
62511
+ const whitespaceFrom = range.to - trailingWhitespace.length;
62512
+ const linkMarks = getMarksBetween(whitespaceFrom, range.to, tr.doc).filter((item) => item.mark.type === type);
62513
+ if (!linkMarks.length) return;
62514
+ const { nodeAfter } = rangeEnd;
62515
+ if (!!nodeAfter && linkMarks.some((item) => item.mark.isInSet(nodeAfter.marks))) return;
62516
+ const storedMarks = tr.storedMarks;
62517
+ tr.removeMark(whitespaceFrom, range.to, type);
62518
+ tr.setStoredMarks(storedMarks);
62519
+ if (tr.selection.empty && tr.selection.from === range.to) tr.removeStoredMark(type);
62520
+ }
62521
+ //#endregion
61739
62522
  //#region src/helpers/autolink.ts
61740
62523
  /**
61741
62524
  * Check if the provided tokens form a valid link structure, which can either be a single link token
@@ -61776,6 +62559,21 @@ img.ProseMirror-separator {
61776
62559
  if (!docChanges || preventAutolink) return;
61777
62560
  const { tr } = newState;
61778
62561
  const transform = combineTransactionSteps(oldState.doc, [...transactions]);
62562
+ if (!transactions.some(isHistoryTransaction)) {
62563
+ const insertedRanges = [];
62564
+ transform.steps.forEach((step, index) => {
62565
+ if (!(step instanceof ReplaceStep) || !step.slice.size) return;
62566
+ const mapping = transform.mapping.slice(index + 1);
62567
+ const from = mapping.map(step.from, 1);
62568
+ const to = mapping.map(step.from + step.slice.size, -1);
62569
+ if (from < to) insertedRanges.push({
62570
+ from,
62571
+ to
62572
+ });
62573
+ });
62574
+ insertedRanges.sort((left, right) => right.to - left.to);
62575
+ insertedRanges.forEach((range) => unlinkTrailingWhitespace(tr, range, options.type));
62576
+ }
61779
62577
  getChangedRanges(transform).forEach(({ newRange }) => {
61780
62578
  const nodesInChangedRanges = findChildrenInRange(newState.doc, newRange, (node) => node.isTextblock);
61781
62579
  let textBlock;
@@ -63162,6 +63960,54 @@ img.ProseMirror-separator {
63162
63960
  });
63163
63961
  }
63164
63962
  //#endregion
63963
+ //#region src/ordered-list/collectOrderedListItemsFromSource.ts
63964
+ const ORDERED_LIST_SCAN_WINDOW = 64;
63965
+ function takeLines(source, max) {
63966
+ const lines = [];
63967
+ let start = 0;
63968
+ while (lines.length < max) {
63969
+ const lineEnd = source.indexOf("\n", start);
63970
+ if (lineEnd === -1) {
63971
+ lines.push(source.slice(start));
63972
+ return lines;
63973
+ }
63974
+ lines.push(source.slice(start, lineEnd));
63975
+ start = lineEnd + 1;
63976
+ }
63977
+ return lines;
63978
+ }
63979
+ /**
63980
+ * Collect ordered list items from the start of `source`, reading only the lines the list needs.
63981
+ *
63982
+ * @param source Markdown beginning at a block boundary.
63983
+ * @returns The items, how many lines they consumed, and the lines that were read.
63984
+ * @example
63985
+ * collectOrderedListItemsFromSource('1. one\n2. two\n\nAfter')
63986
+ * // → [[item, item], 3, ['1. one', '2. two', '', 'After']]
63987
+ */
63988
+ function collectOrderedListItemsFromSource(source) {
63989
+ const firstLineEnd = source.indexOf("\n");
63990
+ const firstLine = firstLineEnd === -1 ? source : source.slice(0, firstLineEnd);
63991
+ if (!ORDERED_LIST_ITEM_REGEX.test(firstLine)) return [
63992
+ [],
63993
+ 0,
63994
+ []
63995
+ ];
63996
+ let windowSize = ORDERED_LIST_SCAN_WINDOW;
63997
+ let lines = takeLines(source, windowSize);
63998
+ let collected = collectOrderedListItems(lines);
63999
+ while (collected[1] === lines.length && lines.length === windowSize) {
64000
+ windowSize *= 2;
64001
+ lines = takeLines(source, windowSize);
64002
+ collected = collectOrderedListItems(lines);
64003
+ }
64004
+ return [
64005
+ collected[0],
64006
+ collected[1],
64007
+ lines
64008
+ ];
64009
+ }
64010
+ //#endregion
63165
64011
  //#region src/ordered-list/ordered-list.ts
63166
64012
  const ListItemName = "listItem";
63167
64013
  const TextStyleName = "textStyle";
@@ -63280,8 +64126,7 @@ img.ProseMirror-separator {
63280
64126
  start: () => -1,
63281
64127
  tokenize: (src, _tokens, lexer) => {
63282
64128
  var _listItems$, _listItems$2;
63283
- const lines = src.split("\n");
63284
- const [listItems, consumed] = collectOrderedListItems(lines);
64129
+ const [listItems, consumed, lines] = collectOrderedListItemsFromSource(src);
63285
64130
  if (listItems.length === 0) return;
63286
64131
  const items = buildNestedStructure(listItems, listItems[0].indent, lexer);
63287
64132
  if (items.length === 0) return;
@@ -66054,1026 +66899,412 @@ img.ProseMirror-separator {
66054
66899
  * This extension allows you to create text nodes.
66055
66900
  * @see https://www.tiptap.dev/api/nodes/text
66056
66901
  */
66057
- const Text = Node$1.create({
66058
- name: "text",
66059
- group: "inline",
66060
- parseMarkdown: (token) => {
66061
- return {
66062
- type: "text",
66063
- text: token.text || ""
66064
- };
66065
- },
66066
- renderMarkdown: (node) => node.text || ""
66067
- });
66068
- //#endregion
66069
- //#region src/index.ts
66070
- var src_default = Text;
66071
-
66072
- /**
66073
- Create a plugin that, when added to a ProseMirror instance,
66074
- causes a decoration to show up at the drop position when something
66075
- is dragged over the editor.
66076
-
66077
- Nodes may add a `disableDropCursor` property to their spec to
66078
- control the showing of a drop cursor inside them. This may be a
66079
- boolean or a function, which will be called with a view and a
66080
- position, and should return a boolean.
66081
- */
66082
- function dropCursor(options = {}) {
66083
- return new Plugin({
66084
- view(editorView) { return new DropCursorView(editorView, options); }
66085
- });
66086
- }
66087
- class DropCursorView {
66088
- constructor(editorView, options) {
66089
- var _a;
66090
- this.editorView = editorView;
66091
- this.cursorPos = null;
66092
- this.element = null;
66093
- this.timeout = -1;
66094
- this.lastDragEvent = null;
66095
- this.width = (_a = options.width) !== null && _a !== void 0 ? _a : 1;
66096
- this.color = options.color === false ? undefined : (options.color || "black");
66097
- this.class = options.class;
66098
- this.handlers = ["dragover", "dragend", "drop", "dragleave"].map(name => {
66099
- let handler = (e) => { this[name](e); };
66100
- editorView.dom.addEventListener(name, handler);
66101
- return { name, handler };
66102
- });
66103
- }
66104
- destroy() {
66105
- this.handlers.forEach(({ name, handler }) => this.editorView.dom.removeEventListener(name, handler));
66106
- }
66107
- update(editorView, prevState) {
66108
- if (this.cursorPos != null && prevState.doc != editorView.state.doc) {
66109
- // if we currently have an on-going drag event
66110
- // we need to update the cursor position again and update the overlay
66111
- if (this.lastDragEvent) {
66112
- let target = this.computeTarget(this.lastDragEvent);
66113
- if (target == this.cursorPos)
66114
- this.updateOverlay();
66115
- else
66116
- this.setCursor(target);
66117
- }
66118
- else {
66119
- this.updateOverlay();
66120
- }
66121
- }
66122
- }
66123
- setCursor(pos) {
66124
- if (pos == this.cursorPos)
66125
- return;
66126
- this.cursorPos = pos;
66127
- if (pos == null) {
66128
- this.element.parentNode.removeChild(this.element);
66129
- this.element = null;
66130
- }
66131
- else {
66132
- this.updateOverlay();
66133
- }
66134
- }
66135
- updateOverlay() {
66136
- let $pos = this.editorView.state.doc.resolve(this.cursorPos);
66137
- let isBlock = !$pos.parent.inlineContent, rect;
66138
- let editorDOM = this.editorView.dom, editorRect = editorDOM.getBoundingClientRect();
66139
- let scaleX = editorRect.width / editorDOM.offsetWidth, scaleY = editorRect.height / editorDOM.offsetHeight;
66140
- if (isBlock) {
66141
- let before = $pos.nodeBefore, after = $pos.nodeAfter;
66142
- if (before || after) {
66143
- let node = this.editorView.nodeDOM(this.cursorPos - (before ? before.nodeSize : 0));
66144
- if (node) {
66145
- let nodeRect = node.getBoundingClientRect();
66146
- let top = before ? nodeRect.bottom : nodeRect.top;
66147
- if (before && after)
66148
- top = (top + this.editorView.nodeDOM(this.cursorPos).getBoundingClientRect().top) / 2;
66149
- let halfWidth = (this.width / 2) * scaleY;
66150
- rect = { left: nodeRect.left, right: nodeRect.right, top: top - halfWidth, bottom: top + halfWidth };
66151
- }
66152
- }
66153
- }
66154
- if (!rect) {
66155
- let coords = this.editorView.coordsAtPos(this.cursorPos);
66156
- let halfWidth = (this.width / 2) * scaleX;
66157
- rect = { left: coords.left - halfWidth, right: coords.left + halfWidth, top: coords.top, bottom: coords.bottom };
66158
- }
66159
- let parent = this.editorView.dom.offsetParent;
66160
- if (!this.element) {
66161
- this.element = parent.appendChild(document.createElement("div"));
66162
- if (this.class)
66163
- this.element.className = this.class;
66164
- this.element.style.cssText = "position: absolute; z-index: 50; pointer-events: none;";
66165
- if (this.color) {
66166
- this.element.style.backgroundColor = this.color;
66167
- }
66168
- }
66169
- this.element.classList.toggle("prosemirror-dropcursor-block", isBlock);
66170
- this.element.classList.toggle("prosemirror-dropcursor-inline", !isBlock);
66171
- let parentLeft, parentTop;
66172
- if (!parent || parent == document.body && getComputedStyle(parent).position == "static") {
66173
- parentLeft = -pageXOffset;
66174
- parentTop = -pageYOffset;
66175
- }
66176
- else {
66177
- let rect = parent.getBoundingClientRect();
66178
- let parentScaleX = rect.width / parent.offsetWidth, parentScaleY = rect.height / parent.offsetHeight;
66179
- parentLeft = rect.left - parent.scrollLeft * parentScaleX;
66180
- parentTop = rect.top - parent.scrollTop * parentScaleY;
66181
- }
66182
- this.element.style.left = (rect.left - parentLeft) / scaleX + "px";
66183
- this.element.style.top = (rect.top - parentTop) / scaleY + "px";
66184
- this.element.style.width = (rect.right - rect.left) / scaleX + "px";
66185
- this.element.style.height = (rect.bottom - rect.top) / scaleY + "px";
66186
- }
66187
- scheduleRemoval(timeout) {
66188
- clearTimeout(this.timeout);
66189
- this.timeout = setTimeout(() => this.setCursor(null), timeout);
66190
- }
66191
- computeTarget(event) {
66192
- let pos = this.editorView.posAtCoords({ left: event.clientX, top: event.clientY });
66193
- let node = pos && pos.inside >= 0 && this.editorView.state.doc.nodeAt(pos.inside);
66194
- let disableDropCursor = node && node.type.spec.disableDropCursor;
66195
- let disabled = typeof disableDropCursor == "function"
66196
- ? disableDropCursor(this.editorView, pos, event)
66197
- : disableDropCursor;
66198
- if (!pos || disabled)
66199
- return null;
66200
- let target = pos.pos;
66201
- if (this.editorView.dragging && this.editorView.dragging.slice) {
66202
- let point = dropPoint(this.editorView.state.doc, target, this.editorView.dragging.slice);
66203
- if (point != null)
66204
- target = point;
66205
- }
66206
- return target;
66207
- }
66208
- dragover(event) {
66209
- if (!this.editorView.editable)
66210
- return;
66211
- this.lastDragEvent = event;
66212
- let target = this.computeTarget(event);
66213
- if (target != null) {
66214
- this.setCursor(target);
66215
- this.scheduleRemoval(5000);
66216
- }
66217
- }
66218
- dragend() {
66219
- this.scheduleRemoval(20);
66220
- }
66221
- drop() {
66222
- this.scheduleRemoval(20);
66223
- }
66224
- dragleave(event) {
66225
- if (!this.editorView.dom.contains(event.relatedTarget))
66226
- this.setCursor(null);
66227
- }
66228
- }
66229
-
66230
- /**
66231
- Gap cursor selections are represented using this class. Its
66232
- `$anchor` and `$head` properties both point at the cursor position.
66233
- */
66234
- class GapCursor extends Selection$2 {
66235
- /**
66236
- Create a gap cursor.
66237
- */
66238
- constructor($pos) {
66239
- super($pos, $pos);
66240
- }
66241
- map(doc, mapping) {
66242
- let $pos = doc.resolve(mapping.map(this.head));
66243
- return GapCursor.valid($pos) ? new GapCursor($pos) : Selection$2.near($pos);
66244
- }
66245
- content() { return Slice.empty; }
66246
- eq(other) {
66247
- return other instanceof GapCursor && other.head == this.head;
66248
- }
66249
- toJSON() {
66250
- return { type: "gapcursor", pos: this.head };
66251
- }
66252
- /**
66253
- @internal
66254
- */
66255
- static fromJSON(doc, json) {
66256
- if (typeof json.pos != "number")
66257
- throw new RangeError("Invalid input for GapCursor.fromJSON");
66258
- return new GapCursor(doc.resolve(json.pos));
66259
- }
66260
- /**
66261
- @internal
66262
- */
66263
- getBookmark() { return new GapBookmark(this.anchor); }
66264
- /**
66265
- @internal
66266
- */
66267
- static valid($pos) {
66268
- let parent = $pos.parent;
66269
- if (parent.inlineContent || !closedBefore($pos) || !closedAfter($pos))
66270
- return false;
66271
- let override = parent.type.spec.allowGapCursor;
66272
- if (override != null)
66273
- return override;
66274
- let deflt = parent.contentMatchAt($pos.index()).defaultType;
66275
- return deflt && deflt.isTextblock;
66276
- }
66277
- /**
66278
- @internal
66279
- */
66280
- static findGapCursorFrom($pos, dir, mustMove = false) {
66281
- search: for (;;) {
66282
- if (!mustMove && GapCursor.valid($pos))
66283
- return $pos;
66284
- let pos = $pos.pos, next = null;
66285
- // Scan up from this position
66286
- for (let d = $pos.depth;; d--) {
66287
- let parent = $pos.node(d);
66288
- if (dir > 0 ? $pos.indexAfter(d) < parent.childCount : $pos.index(d) > 0) {
66289
- next = parent.child(dir > 0 ? $pos.indexAfter(d) : $pos.index(d) - 1);
66290
- break;
66291
- }
66292
- else if (d == 0) {
66293
- return null;
66294
- }
66295
- pos += dir;
66296
- let $cur = $pos.doc.resolve(pos);
66297
- if (GapCursor.valid($cur))
66298
- return $cur;
66299
- }
66300
- // And then down into the next node
66301
- for (;;) {
66302
- let inside = dir > 0 ? next.firstChild : next.lastChild;
66303
- if (!inside) {
66304
- if (next.isAtom && !next.isText && !NodeSelection.isSelectable(next)) {
66305
- $pos = $pos.doc.resolve(pos + next.nodeSize * dir);
66306
- mustMove = false;
66307
- continue search;
66308
- }
66309
- break;
66310
- }
66311
- next = inside;
66312
- pos += dir;
66313
- let $cur = $pos.doc.resolve(pos);
66314
- if (GapCursor.valid($cur))
66315
- return $cur;
66316
- }
66317
- return null;
66318
- }
66319
- }
66320
- }
66321
- GapCursor.prototype.visible = false;
66322
- GapCursor.findFrom = GapCursor.findGapCursorFrom;
66323
- Selection$2.jsonID("gapcursor", GapCursor);
66324
- class GapBookmark {
66325
- constructor(pos) {
66326
- this.pos = pos;
66327
- }
66328
- map(mapping) {
66329
- return new GapBookmark(mapping.map(this.pos));
66330
- }
66331
- resolve(doc) {
66332
- let $pos = doc.resolve(this.pos);
66333
- return GapCursor.valid($pos) ? new GapCursor($pos) : Selection$2.near($pos);
66334
- }
66335
- }
66336
- function needsGap(type) {
66337
- return type.isAtom || type.spec.isolating || type.spec.createGapCursor;
66338
- }
66339
- function closedBefore($pos) {
66340
- for (let d = $pos.depth; d >= 0; d--) {
66341
- let index = $pos.index(d), parent = $pos.node(d);
66342
- // At the start of this parent, look at next one
66343
- if (index == 0) {
66344
- if (parent.type.spec.isolating)
66345
- return true;
66346
- continue;
66347
- }
66348
- // See if the node before (or its first ancestor) is closed
66349
- for (let before = parent.child(index - 1);; before = before.lastChild) {
66350
- if ((before.childCount == 0 && !before.inlineContent) || needsGap(before.type))
66351
- return true;
66352
- if (before.inlineContent)
66353
- return false;
66354
- }
66355
- }
66356
- // Hit start of document
66357
- return true;
66358
- }
66359
- function closedAfter($pos) {
66360
- for (let d = $pos.depth; d >= 0; d--) {
66361
- let index = $pos.indexAfter(d), parent = $pos.node(d);
66362
- if (index == parent.childCount) {
66363
- if (parent.type.spec.isolating)
66364
- return true;
66365
- continue;
66366
- }
66367
- for (let after = parent.child(index);; after = after.firstChild) {
66368
- if ((after.childCount == 0 && !after.inlineContent) || needsGap(after.type))
66369
- return true;
66370
- if (after.inlineContent)
66371
- return false;
66372
- }
66373
- }
66374
- return true;
66375
- }
66902
+ const Text = Node$1.create({
66903
+ name: "text",
66904
+ group: "inline",
66905
+ parseMarkdown: (token) => {
66906
+ return {
66907
+ type: "text",
66908
+ text: token.text || ""
66909
+ };
66910
+ },
66911
+ renderMarkdown: (node) => node.text || ""
66912
+ });
66913
+ //#endregion
66914
+ //#region src/index.ts
66915
+ var src_default = Text;
66376
66916
 
66377
66917
  /**
66378
- Create a gap cursor plugin. When enabled, this will capture clicks
66379
- near and arrow-key-motion past places that don't have a normally
66380
- selectable position nearby, and create a gap cursor selection for
66381
- them. The cursor is drawn as an element with class
66382
- `ProseMirror-gapcursor`. You can either include
66383
- `style/gapcursor.css` from the package's directory or add your own
66384
- styles to make it visible.
66918
+ Create a plugin that, when added to a ProseMirror instance,
66919
+ causes a decoration to show up at the drop position when something
66920
+ is dragged over the editor.
66921
+
66922
+ Nodes may add a `disableDropCursor` property to their spec to
66923
+ control the showing of a drop cursor inside them. This may be a
66924
+ boolean or a function, which will be called with a view and a
66925
+ position, and should return a boolean.
66385
66926
  */
66386
- function gapCursor() {
66927
+ function dropCursor(options = {}) {
66387
66928
  return new Plugin({
66388
- props: {
66389
- decorations: drawGapCursor,
66390
- createSelectionBetween(_view, $anchor, $head) {
66391
- return $anchor.pos == $head.pos && GapCursor.valid($head) ? new GapCursor($head) : null;
66392
- },
66393
- handleClick,
66394
- handleKeyDown,
66395
- handleDOMEvents: { beforeinput: beforeinput }
66396
- }
66929
+ view(editorView) { return new DropCursorView(editorView, options); }
66397
66930
  });
66398
66931
  }
66399
- const handleKeyDown = keydownHandler({
66400
- "ArrowLeft": arrow("horiz", -1),
66401
- "ArrowRight": arrow("horiz", 1),
66402
- "ArrowUp": arrow("vert", -1),
66403
- "ArrowDown": arrow("vert", 1)
66404
- });
66405
- function arrow(axis, dir) {
66406
- const dirStr = axis == "vert" ? (dir > 0 ? "down" : "up") : (dir > 0 ? "right" : "left");
66407
- return function (state, dispatch, view) {
66408
- let sel = state.selection;
66409
- let $start = dir > 0 ? sel.$to : sel.$from, mustMove = sel.empty;
66410
- if (sel instanceof TextSelection) {
66411
- if (!view.endOfTextblock(dirStr) || $start.depth == 0)
66412
- return false;
66413
- mustMove = false;
66414
- $start = state.doc.resolve(dir > 0 ? $start.after() : $start.before());
66415
- }
66416
- let $found = GapCursor.findGapCursorFrom($start, dir, mustMove);
66417
- if (!$found)
66418
- return false;
66419
- if (dispatch)
66420
- dispatch(state.tr.setSelection(new GapCursor($found)));
66421
- return true;
66422
- };
66423
- }
66424
- function handleClick(view, pos, event) {
66425
- if (!view || !view.editable)
66426
- return false;
66427
- let $pos = view.state.doc.resolve(pos);
66428
- if (!GapCursor.valid($pos))
66429
- return false;
66430
- let clickPos = view.posAtCoords({ left: event.clientX, top: event.clientY });
66431
- if (clickPos && clickPos.inside > -1 && NodeSelection.isSelectable(view.state.doc.nodeAt(clickPos.inside)))
66432
- return false;
66433
- view.dispatch(view.state.tr.setSelection(new GapCursor($pos)));
66434
- return true;
66435
- }
66436
- // This is a hack that, when a composition starts while a gap cursor
66437
- // is active, quickly creates an inline context for the composition to
66438
- // happen in, to avoid it being aborted by the DOM selection being
66439
- // moved into a valid position.
66440
- function beforeinput(view, event) {
66441
- if (event.inputType != "insertCompositionText" || !(view.state.selection instanceof GapCursor))
66442
- return false;
66443
- let { $from } = view.state.selection;
66444
- let insert = $from.parent.contentMatchAt($from.index()).findWrapping(view.state.schema.nodes.text);
66445
- if (!insert)
66446
- return false;
66447
- let frag = Fragment.empty;
66448
- for (let i = insert.length - 1; i >= 0; i--)
66449
- frag = Fragment.from(insert[i].createAndFill(null, frag));
66450
- let tr = view.state.tr.replace($from.pos, $from.pos, new Slice(frag, 0, 0));
66451
- tr.setSelection(TextSelection.near(tr.doc.resolve($from.pos + 1)));
66452
- view.dispatch(tr);
66453
- return false;
66454
- }
66455
- function drawGapCursor(state) {
66456
- if (!(state.selection instanceof GapCursor))
66457
- return null;
66458
- let node = document.createElement("div");
66459
- node.className = "ProseMirror-gapcursor";
66460
- return DecorationSet.create(state.doc, [Decoration.widget(state.selection.head, node, { key: "gapcursor" })]);
66461
- }
66462
-
66463
- var GOOD_LEAF_SIZE = 200;
66464
-
66465
- // :: class<T> A rope sequence is a persistent sequence data structure
66466
- // that supports appending, prepending, and slicing without doing a
66467
- // full copy. It is represented as a mostly-balanced tree.
66468
- var RopeSequence = function RopeSequence () {};
66469
-
66470
- RopeSequence.prototype.append = function append (other) {
66471
- if (!other.length) { return this }
66472
- other = RopeSequence.from(other);
66473
-
66474
- return (!this.length && other) ||
66475
- (other.length < GOOD_LEAF_SIZE && this.leafAppend(other)) ||
66476
- (this.length < GOOD_LEAF_SIZE && other.leafPrepend(this)) ||
66477
- this.appendInner(other)
66478
- };
66479
-
66480
- // :: (union<[T], RopeSequence<T>>) → RopeSequence<T>
66481
- // Prepend an array or other rope to this one, returning a new rope.
66482
- RopeSequence.prototype.prepend = function prepend (other) {
66483
- if (!other.length) { return this }
66484
- return RopeSequence.from(other).append(this)
66485
- };
66486
-
66487
- RopeSequence.prototype.appendInner = function appendInner (other) {
66488
- return new Append(this, other)
66489
- };
66490
-
66491
- // :: (?number, ?number) → RopeSequence<T>
66492
- // Create a rope repesenting a sub-sequence of this rope.
66493
- RopeSequence.prototype.slice = function slice (from, to) {
66494
- if ( from === void 0 ) from = 0;
66495
- if ( to === void 0 ) to = this.length;
66496
-
66497
- if (from >= to) { return RopeSequence.empty }
66498
- return this.sliceInner(Math.max(0, from), Math.min(this.length, to))
66499
- };
66500
-
66501
- // :: (number) → T
66502
- // Retrieve the element at the given position from this rope.
66503
- RopeSequence.prototype.get = function get (i) {
66504
- if (i < 0 || i >= this.length) { return undefined }
66505
- return this.getInner(i)
66506
- };
66507
-
66508
- // :: ((element: T, index: number) → ?bool, ?number, ?number)
66509
- // Call the given function for each element between the given
66510
- // indices. This tends to be more efficient than looping over the
66511
- // indices and calling `get`, because it doesn't have to descend the
66512
- // tree for every element.
66513
- RopeSequence.prototype.forEach = function forEach (f, from, to) {
66514
- if ( from === void 0 ) from = 0;
66515
- if ( to === void 0 ) to = this.length;
66516
-
66517
- if (from <= to)
66518
- { this.forEachInner(f, from, to, 0); }
66519
- else
66520
- { this.forEachInvertedInner(f, from, to, 0); }
66521
- };
66522
-
66523
- // :: ((element: T, index: number) → U, ?number, ?number) → [U]
66524
- // Map the given functions over the elements of the rope, producing
66525
- // a flat array.
66526
- RopeSequence.prototype.map = function map (f, from, to) {
66527
- if ( from === void 0 ) from = 0;
66528
- if ( to === void 0 ) to = this.length;
66529
-
66530
- var result = [];
66531
- this.forEach(function (elt, i) { return result.push(f(elt, i)); }, from, to);
66532
- return result
66533
- };
66534
-
66535
- // :: (?union<[T], RopeSequence<T>>) → RopeSequence<T>
66536
- // Create a rope representing the given array, or return the rope
66537
- // itself if a rope was given.
66538
- RopeSequence.from = function from (values) {
66539
- if (values instanceof RopeSequence) { return values }
66540
- return values && values.length ? new Leaf(values) : RopeSequence.empty
66541
- };
66542
-
66543
- var Leaf = /*@__PURE__*/(function (RopeSequence) {
66544
- function Leaf(values) {
66545
- RopeSequence.call(this);
66546
- this.values = values;
66547
- }
66548
-
66549
- if ( RopeSequence ) Leaf.__proto__ = RopeSequence;
66550
- Leaf.prototype = Object.create( RopeSequence && RopeSequence.prototype );
66551
- Leaf.prototype.constructor = Leaf;
66552
-
66553
- var prototypeAccessors = { length: { configurable: true },depth: { configurable: true } };
66554
-
66555
- Leaf.prototype.flatten = function flatten () {
66556
- return this.values
66557
- };
66558
-
66559
- Leaf.prototype.sliceInner = function sliceInner (from, to) {
66560
- if (from == 0 && to == this.length) { return this }
66561
- return new Leaf(this.values.slice(from, to))
66562
- };
66563
-
66564
- Leaf.prototype.getInner = function getInner (i) {
66565
- return this.values[i]
66566
- };
66567
-
66568
- Leaf.prototype.forEachInner = function forEachInner (f, from, to, start) {
66569
- for (var i = from; i < to; i++)
66570
- { if (f(this.values[i], start + i) === false) { return false } }
66571
- };
66572
-
66573
- Leaf.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) {
66574
- for (var i = from - 1; i >= to; i--)
66575
- { if (f(this.values[i], start + i) === false) { return false } }
66576
- };
66577
-
66578
- Leaf.prototype.leafAppend = function leafAppend (other) {
66579
- if (this.length + other.length <= GOOD_LEAF_SIZE)
66580
- { return new Leaf(this.values.concat(other.flatten())) }
66581
- };
66582
-
66583
- Leaf.prototype.leafPrepend = function leafPrepend (other) {
66584
- if (this.length + other.length <= GOOD_LEAF_SIZE)
66585
- { return new Leaf(other.flatten().concat(this.values)) }
66586
- };
66587
-
66588
- prototypeAccessors.length.get = function () { return this.values.length };
66589
-
66590
- prototypeAccessors.depth.get = function () { return 0 };
66591
-
66592
- Object.defineProperties( Leaf.prototype, prototypeAccessors );
66593
-
66594
- return Leaf;
66595
- }(RopeSequence));
66596
-
66597
- // :: RopeSequence
66598
- // The empty rope sequence.
66599
- RopeSequence.empty = new Leaf([]);
66600
-
66601
- var Append = /*@__PURE__*/(function (RopeSequence) {
66602
- function Append(left, right) {
66603
- RopeSequence.call(this);
66604
- this.left = left;
66605
- this.right = right;
66606
- this.length = left.length + right.length;
66607
- this.depth = Math.max(left.depth, right.depth) + 1;
66608
- }
66609
-
66610
- if ( RopeSequence ) Append.__proto__ = RopeSequence;
66611
- Append.prototype = Object.create( RopeSequence && RopeSequence.prototype );
66612
- Append.prototype.constructor = Append;
66613
-
66614
- Append.prototype.flatten = function flatten () {
66615
- return this.left.flatten().concat(this.right.flatten())
66616
- };
66617
-
66618
- Append.prototype.getInner = function getInner (i) {
66619
- return i < this.left.length ? this.left.get(i) : this.right.get(i - this.left.length)
66620
- };
66621
-
66622
- Append.prototype.forEachInner = function forEachInner (f, from, to, start) {
66623
- var leftLen = this.left.length;
66624
- if (from < leftLen &&
66625
- this.left.forEachInner(f, from, Math.min(to, leftLen), start) === false)
66626
- { return false }
66627
- if (to > leftLen &&
66628
- this.right.forEachInner(f, Math.max(from - leftLen, 0), Math.min(this.length, to) - leftLen, start + leftLen) === false)
66629
- { return false }
66630
- };
66631
-
66632
- Append.prototype.forEachInvertedInner = function forEachInvertedInner (f, from, to, start) {
66633
- var leftLen = this.left.length;
66634
- if (from > leftLen &&
66635
- this.right.forEachInvertedInner(f, from - leftLen, Math.max(to, leftLen) - leftLen, start + leftLen) === false)
66636
- { return false }
66637
- if (to < leftLen &&
66638
- this.left.forEachInvertedInner(f, Math.min(from, leftLen), to, start) === false)
66639
- { return false }
66640
- };
66641
-
66642
- Append.prototype.sliceInner = function sliceInner (from, to) {
66643
- if (from == 0 && to == this.length) { return this }
66644
- var leftLen = this.left.length;
66645
- if (to <= leftLen) { return this.left.slice(from, to) }
66646
- if (from >= leftLen) { return this.right.slice(from - leftLen, to - leftLen) }
66647
- return this.left.slice(from, leftLen).append(this.right.slice(0, to - leftLen))
66648
- };
66649
-
66650
- Append.prototype.leafAppend = function leafAppend (other) {
66651
- var inner = this.right.leafAppend(other);
66652
- if (inner) { return new Append(this.left, inner) }
66653
- };
66654
-
66655
- Append.prototype.leafPrepend = function leafPrepend (other) {
66656
- var inner = this.left.leafPrepend(other);
66657
- if (inner) { return new Append(inner, this.right) }
66658
- };
66659
-
66660
- Append.prototype.appendInner = function appendInner (other) {
66661
- if (this.left.depth >= Math.max(this.right.depth, other.depth) + 1)
66662
- { return new Append(this.left, new Append(this.right, other)) }
66663
- return new Append(this, other)
66664
- };
66665
-
66666
- return Append;
66667
- }(RopeSequence));
66668
-
66669
- // ProseMirror's history isn't simply a way to roll back to a previous
66670
- // state, because ProseMirror supports applying changes without adding
66671
- // them to the history (for example during collaboration).
66672
- //
66673
- // To this end, each 'Branch' (one for the undo history and one for
66674
- // the redo history) keeps an array of 'Items', which can optionally
66675
- // hold a step (an actual undoable change), and always hold a position
66676
- // map (which is needed to move changes below them to apply to the
66677
- // current document).
66678
- //
66679
- // An item that has both a step and a selection bookmark is the start
66680
- // of an 'event' — a group of changes that will be undone or redone at
66681
- // once. (It stores only the bookmark, since that way we don't have to
66682
- // provide a document until the selection is actually applied, which
66683
- // is useful when compressing.)
66684
- // Used to schedule history compression
66685
- const max_empty_items = 500;
66686
- class Branch {
66687
- constructor(items, eventCount) {
66688
- this.items = items;
66689
- this.eventCount = eventCount;
66690
- }
66691
- // Pop the latest event off the branch's history and apply it
66692
- // to a document transform.
66693
- popEvent(state, preserveItems) {
66694
- if (this.eventCount == 0)
66695
- return null;
66696
- let end = this.items.length;
66697
- for (;; end--) {
66698
- let next = this.items.get(end - 1);
66699
- if (next.selection) {
66700
- --end;
66701
- break;
66702
- }
66703
- }
66704
- let remap, mapFrom;
66705
- if (preserveItems) {
66706
- remap = this.remapping(end, this.items.length);
66707
- mapFrom = remap.maps.length;
66708
- }
66709
- let transform = state.tr;
66710
- let selection, remaining;
66711
- let addAfter = [], addBefore = [];
66712
- this.items.forEach((item, i) => {
66713
- if (!item.step) {
66714
- if (!remap) {
66715
- remap = this.remapping(end, i + 1);
66716
- mapFrom = remap.maps.length;
66717
- }
66718
- mapFrom--;
66719
- addBefore.push(item);
66720
- return;
66721
- }
66722
- if (remap) {
66723
- addBefore.push(new Item(item.map));
66724
- let step = item.step.map(remap.slice(mapFrom)), map;
66725
- if (step && transform.maybeStep(step).doc) {
66726
- map = transform.mapping.maps[transform.mapping.maps.length - 1];
66727
- addAfter.push(new Item(map, undefined, undefined, addAfter.length + addBefore.length));
66728
- }
66729
- mapFrom--;
66730
- if (map)
66731
- remap.appendMap(map, mapFrom);
66732
- }
66733
- else {
66734
- transform.maybeStep(item.step);
66735
- }
66736
- if (item.selection) {
66737
- selection = remap ? item.selection.map(remap.slice(mapFrom)) : item.selection;
66738
- remaining = new Branch(this.items.slice(0, end).append(addBefore.reverse().concat(addAfter)), this.eventCount - 1);
66739
- return false;
66740
- }
66741
- }, this.items.length, 0);
66742
- return { remaining: remaining, transform, selection: selection };
66743
- }
66744
- // Create a new branch with the given transform added.
66745
- addTransform(transform, selection, histOptions, preserveItems) {
66746
- let newItems = [], eventCount = this.eventCount;
66747
- let oldItems = this.items, lastItem = !preserveItems && oldItems.length ? oldItems.get(oldItems.length - 1) : null;
66748
- for (let i = 0; i < transform.steps.length; i++) {
66749
- let step = transform.steps[i].invert(transform.docs[i]);
66750
- let item = new Item(transform.mapping.maps[i], step, selection), merged;
66751
- if (merged = lastItem && lastItem.merge(item)) {
66752
- item = merged;
66753
- if (i)
66754
- newItems.pop();
66755
- else
66756
- oldItems = oldItems.slice(0, oldItems.length - 1);
66757
- }
66758
- newItems.push(item);
66759
- if (selection) {
66760
- eventCount++;
66761
- selection = undefined;
66762
- }
66763
- if (!preserveItems)
66764
- lastItem = item;
66765
- }
66766
- let overflow = eventCount - histOptions.depth;
66767
- if (overflow > DEPTH_OVERFLOW) {
66768
- oldItems = cutOffEvents(oldItems, overflow);
66769
- eventCount -= overflow;
66770
- }
66771
- return new Branch(oldItems.append(newItems), eventCount);
66772
- }
66773
- remapping(from, to) {
66774
- let maps = new Mapping;
66775
- this.items.forEach((item, i) => {
66776
- let mirrorPos = item.mirrorOffset != null && i - item.mirrorOffset >= from
66777
- ? maps.maps.length - item.mirrorOffset : undefined;
66778
- maps.appendMap(item.map, mirrorPos);
66779
- }, from, to);
66780
- return maps;
66781
- }
66782
- addMaps(array) {
66783
- if (this.eventCount == 0)
66784
- return this;
66785
- return new Branch(this.items.append(array.map(map => new Item(map))), this.eventCount);
66786
- }
66787
- // When the collab module receives remote changes, the history has
66788
- // to know about those, so that it can adjust the steps that were
66789
- // rebased on top of the remote changes, and include the position
66790
- // maps for the remote changes in its array of items.
66791
- rebased(rebasedTransform, rebasedCount) {
66792
- if (!this.eventCount)
66793
- return this;
66794
- let rebasedItems = [], start = Math.max(0, this.items.length - rebasedCount);
66795
- let mapping = rebasedTransform.mapping;
66796
- let newUntil = rebasedTransform.steps.length;
66797
- let eventCount = this.eventCount;
66798
- this.items.forEach(item => { if (item.selection)
66799
- eventCount--; }, start);
66800
- let iRebased = rebasedCount;
66801
- this.items.forEach(item => {
66802
- let pos = mapping.getMirror(--iRebased);
66803
- if (pos == null)
66804
- return;
66805
- newUntil = Math.min(newUntil, pos);
66806
- let map = mapping.maps[pos];
66807
- if (item.step) {
66808
- let step = rebasedTransform.steps[pos].invert(rebasedTransform.docs[pos]);
66809
- let selection = item.selection && item.selection.map(mapping.slice(iRebased + 1, pos));
66810
- if (selection)
66811
- eventCount++;
66812
- rebasedItems.push(new Item(map, step, selection));
66813
- }
66814
- else {
66815
- rebasedItems.push(new Item(map));
66816
- }
66817
- }, start);
66818
- let newMaps = [];
66819
- for (let i = rebasedCount; i < newUntil; i++)
66820
- newMaps.push(new Item(mapping.maps[i]));
66821
- let items = this.items.slice(0, start).append(newMaps).append(rebasedItems);
66822
- let branch = new Branch(items, eventCount);
66823
- if (branch.emptyItemCount() > max_empty_items)
66824
- branch = branch.compress(this.items.length - rebasedItems.length);
66825
- return branch;
66932
+ class DropCursorView {
66933
+ constructor(editorView, options) {
66934
+ var _a;
66935
+ this.editorView = editorView;
66936
+ this.cursorPos = null;
66937
+ this.element = null;
66938
+ this.timeout = -1;
66939
+ this.lastDragEvent = null;
66940
+ this.width = (_a = options.width) !== null && _a !== void 0 ? _a : 1;
66941
+ this.color = options.color === false ? undefined : (options.color || "black");
66942
+ this.class = options.class;
66943
+ this.handlers = ["dragover", "dragend", "drop", "dragleave"].map(name => {
66944
+ let handler = (e) => { this[name](e); };
66945
+ editorView.dom.addEventListener(name, handler);
66946
+ return { name, handler };
66947
+ });
66826
66948
  }
66827
- emptyItemCount() {
66828
- let count = 0;
66829
- this.items.forEach(item => { if (!item.step)
66830
- count++; });
66831
- return count;
66949
+ destroy() {
66950
+ this.setCursor(null);
66951
+ this.handlers.forEach(({ name, handler }) => this.editorView.dom.removeEventListener(name, handler));
66832
66952
  }
66833
- // Compressing a branch means rewriting it to push the air (map-only
66834
- // items) out. During collaboration, these naturally accumulate
66835
- // because each remote change adds one. The `upto` argument is used
66836
- // to ensure that only the items below a given level are compressed,
66837
- // because `rebased` relies on a clean, untouched set of items in
66838
- // order to associate old items with rebased steps.
66839
- compress(upto = this.items.length) {
66840
- let remap = this.remapping(0, upto), mapFrom = remap.maps.length;
66841
- let items = [], events = 0;
66842
- this.items.forEach((item, i) => {
66843
- if (i >= upto) {
66844
- items.push(item);
66845
- if (item.selection)
66846
- events++;
66953
+ update(editorView, prevState) {
66954
+ if (this.cursorPos != null && prevState.doc != editorView.state.doc) {
66955
+ // if we currently have an on-going drag event
66956
+ // we need to update the cursor position again and update the overlay
66957
+ if (this.lastDragEvent) {
66958
+ let target = this.computeTarget(this.lastDragEvent);
66959
+ if (target == this.cursorPos)
66960
+ this.updateOverlay();
66961
+ else
66962
+ this.setCursor(target);
66847
66963
  }
66848
- else if (item.step) {
66849
- let step = item.step.map(remap.slice(mapFrom)), map = step && step.getMap();
66850
- mapFrom--;
66851
- if (map)
66852
- remap.appendMap(map, mapFrom);
66853
- if (step) {
66854
- let selection = item.selection && item.selection.map(remap.slice(mapFrom));
66855
- if (selection)
66856
- events++;
66857
- let newItem = new Item(map.invert(), step, selection), merged, last = items.length - 1;
66858
- if (merged = items.length && items[last].merge(newItem))
66859
- items[last] = merged;
66860
- else
66861
- items.push(newItem);
66964
+ else {
66965
+ this.updateOverlay();
66966
+ }
66967
+ }
66968
+ }
66969
+ setCursor(pos) {
66970
+ if (pos == this.cursorPos)
66971
+ return;
66972
+ this.cursorPos = pos;
66973
+ if (pos == null) {
66974
+ this.element.parentNode.removeChild(this.element);
66975
+ this.element = null;
66976
+ }
66977
+ else {
66978
+ this.updateOverlay();
66979
+ }
66980
+ }
66981
+ updateOverlay() {
66982
+ let $pos = this.editorView.state.doc.resolve(this.cursorPos);
66983
+ let isBlock = !$pos.parent.inlineContent, rect;
66984
+ let editorDOM = this.editorView.dom, editorRect = editorDOM.getBoundingClientRect();
66985
+ let scaleX = editorRect.width / editorDOM.offsetWidth, scaleY = editorRect.height / editorDOM.offsetHeight;
66986
+ if (isBlock) {
66987
+ let before = $pos.nodeBefore, after = $pos.nodeAfter;
66988
+ if (before || after) {
66989
+ let node = this.editorView.nodeDOM(this.cursorPos - (before ? before.nodeSize : 0));
66990
+ if (node) {
66991
+ let nodeRect = node.getBoundingClientRect();
66992
+ let top = before ? nodeRect.bottom : nodeRect.top;
66993
+ if (before && after)
66994
+ top = (top + this.editorView.nodeDOM(this.cursorPos).getBoundingClientRect().top) / 2;
66995
+ let halfWidth = (this.width / 2) * scaleY;
66996
+ rect = { left: nodeRect.left, right: nodeRect.right, top: top - halfWidth, bottom: top + halfWidth };
66862
66997
  }
66863
66998
  }
66864
- else if (item.map) {
66865
- mapFrom--;
66999
+ }
67000
+ if (!rect) {
67001
+ let coords = this.editorView.coordsAtPos(this.cursorPos);
67002
+ let halfWidth = (this.width / 2) * scaleX;
67003
+ rect = { left: coords.left - halfWidth, right: coords.left + halfWidth, top: coords.top, bottom: coords.bottom };
67004
+ }
67005
+ let parent = this.editorView.dom.offsetParent;
67006
+ if (!this.element) {
67007
+ this.element = parent.appendChild(document.createElement("div"));
67008
+ if (this.class)
67009
+ this.element.className = this.class;
67010
+ this.element.style.cssText = "position: absolute; z-index: 50; pointer-events: none;";
67011
+ if (this.color) {
67012
+ this.element.style.backgroundColor = this.color;
66866
67013
  }
66867
- }, this.items.length, 0);
66868
- return new Branch(RopeSequence.from(items.reverse()), events);
67014
+ }
67015
+ this.element.classList.toggle("prosemirror-dropcursor-block", isBlock);
67016
+ this.element.classList.toggle("prosemirror-dropcursor-inline", !isBlock);
67017
+ let parentLeft, parentTop;
67018
+ if (!parent || parent == document.body && getComputedStyle(parent).position == "static") {
67019
+ parentLeft = -pageXOffset;
67020
+ parentTop = -pageYOffset;
67021
+ }
67022
+ else {
67023
+ let rect = parent.getBoundingClientRect();
67024
+ let parentScaleX = rect.width / parent.offsetWidth, parentScaleY = rect.height / parent.offsetHeight;
67025
+ parentLeft = rect.left - parent.scrollLeft * parentScaleX;
67026
+ parentTop = rect.top - parent.scrollTop * parentScaleY;
67027
+ }
67028
+ this.element.style.left = (rect.left - parentLeft) / scaleX + "px";
67029
+ this.element.style.top = (rect.top - parentTop) / scaleY + "px";
67030
+ this.element.style.width = (rect.right - rect.left) / scaleX + "px";
67031
+ this.element.style.height = (rect.bottom - rect.top) / scaleY + "px";
66869
67032
  }
66870
- }
66871
- Branch.empty = new Branch(RopeSequence.empty, 0);
66872
- function cutOffEvents(items, n) {
66873
- let cutPoint;
66874
- items.forEach((item, i) => {
66875
- if (item.selection && (n-- == 0)) {
66876
- cutPoint = i;
66877
- return false;
67033
+ scheduleRemoval(timeout) {
67034
+ clearTimeout(this.timeout);
67035
+ this.timeout = setTimeout(() => this.setCursor(null), timeout);
67036
+ }
67037
+ computeTarget(event) {
67038
+ let pos = this.editorView.posAtCoords({ left: event.clientX, top: event.clientY });
67039
+ let node = pos && pos.inside >= 0 && this.editorView.state.doc.nodeAt(pos.inside);
67040
+ let disableDropCursor = node && node.type.spec.disableDropCursor;
67041
+ let disabled = typeof disableDropCursor == "function"
67042
+ ? disableDropCursor(this.editorView, pos, event)
67043
+ : disableDropCursor;
67044
+ if (!pos || disabled)
67045
+ return null;
67046
+ let target = pos.pos;
67047
+ if (this.editorView.dragging && this.editorView.dragging.slice) {
67048
+ let point = dropPoint(this.editorView.state.doc, target, this.editorView.dragging.slice);
67049
+ if (point != null)
67050
+ target = point;
66878
67051
  }
66879
- });
66880
- return items.slice(cutPoint);
66881
- }
66882
- class Item {
66883
- constructor(
66884
- // The (forward) step map for this item.
66885
- map,
66886
- // The inverted step
66887
- step,
66888
- // If this is non-null, this item is the start of a group, and
66889
- // this selection is the starting selection for the group (the one
66890
- // that was active before the first step was applied)
66891
- selection,
66892
- // If this item is the inverse of a previous mapping on the stack,
66893
- // this points at the inverse's offset
66894
- mirrorOffset) {
66895
- this.map = map;
66896
- this.step = step;
66897
- this.selection = selection;
66898
- this.mirrorOffset = mirrorOffset;
67052
+ return target;
66899
67053
  }
66900
- merge(other) {
66901
- if (this.step && other.step && !other.selection) {
66902
- let step = other.step.merge(this.step);
66903
- if (step)
66904
- return new Item(step.getMap().invert(), step, this.selection);
67054
+ dragover(event) {
67055
+ if (!this.editorView.editable)
67056
+ return;
67057
+ this.lastDragEvent = event;
67058
+ let target = this.computeTarget(event);
67059
+ if (target != null) {
67060
+ this.setCursor(target);
67061
+ this.scheduleRemoval(5000);
66905
67062
  }
66906
67063
  }
66907
- }
66908
- // The value of the state field that tracks undo/redo history for that
66909
- // state. Will be stored in the plugin state when the history plugin
66910
- // is active.
66911
- class HistoryState {
66912
- constructor(done, undone, prevRanges, prevTime, prevComposition) {
66913
- this.done = done;
66914
- this.undone = undone;
66915
- this.prevRanges = prevRanges;
66916
- this.prevTime = prevTime;
66917
- this.prevComposition = prevComposition;
67064
+ dragend() {
67065
+ this.scheduleRemoval(20);
67066
+ }
67067
+ drop() {
67068
+ this.scheduleRemoval(20);
67069
+ }
67070
+ dragleave(event) {
67071
+ if (!this.editorView.dom.contains(event.relatedTarget))
67072
+ this.setCursor(null);
66918
67073
  }
66919
67074
  }
66920
- const DEPTH_OVERFLOW = 20;
66921
- // Record a transformation in undo history.
66922
- function applyTransaction(history, state, tr, options) {
66923
- let historyTr = tr.getMeta(historyKey), rebased;
66924
- if (historyTr)
66925
- return historyTr.historyState;
66926
- if (tr.getMeta(closeHistoryKey))
66927
- history = new HistoryState(history.done, history.undone, null, 0, -1);
66928
- let appended = tr.getMeta("appendedTransaction");
66929
- if (tr.steps.length == 0) {
66930
- return history;
67075
+
67076
+ /**
67077
+ Gap cursor selections are represented using this class. Its
67078
+ `$anchor` and `$head` properties both point at the cursor position.
67079
+ */
67080
+ class GapCursor extends Selection$2 {
67081
+ /**
67082
+ Create a gap cursor.
67083
+ */
67084
+ constructor($pos) {
67085
+ super($pos, $pos);
66931
67086
  }
66932
- else if (appended && appended.getMeta(historyKey)) {
66933
- if (appended.getMeta(historyKey).redo)
66934
- return new HistoryState(history.done.addTransform(tr, undefined, options, mustPreserveItems(state)), history.undone, rangesFor(tr.mapping.maps), history.prevTime, history.prevComposition);
66935
- else
66936
- return new HistoryState(history.done, history.undone.addTransform(tr, undefined, options, mustPreserveItems(state)), null, history.prevTime, history.prevComposition);
67087
+ map(doc, mapping) {
67088
+ let $pos = doc.resolve(mapping.map(this.head));
67089
+ return GapCursor.valid($pos) ? new GapCursor($pos) : Selection$2.near($pos);
66937
67090
  }
66938
- else if (tr.getMeta("addToHistory") !== false && !(appended && appended.getMeta("addToHistory") === false)) {
66939
- // Group transforms that occur in quick succession into one event.
66940
- let composition = tr.getMeta("composition");
66941
- let newGroup = history.prevTime == 0 ||
66942
- (!appended && history.prevComposition != composition &&
66943
- (history.prevTime < (tr.time || 0) - options.newGroupDelay || !isAdjacentTo(tr, history.prevRanges)));
66944
- let prevRanges = appended ? mapRanges(history.prevRanges, tr.mapping) : rangesFor(tr.mapping.maps);
66945
- return new HistoryState(history.done.addTransform(tr, newGroup ? state.selection.getBookmark() : undefined, options, mustPreserveItems(state)), Branch.empty, prevRanges, tr.time, composition == null ? history.prevComposition : composition);
67091
+ content() { return Slice.empty; }
67092
+ eq(other) {
67093
+ return other instanceof GapCursor && other.head == this.head;
66946
67094
  }
66947
- else if (rebased = tr.getMeta("rebased")) {
66948
- // Used by the collab module to tell the history that some of its
66949
- // content has been rebased.
66950
- return new HistoryState(history.done.rebased(tr, rebased), history.undone.rebased(tr, rebased), mapRanges(history.prevRanges, tr.mapping), history.prevTime, history.prevComposition);
67095
+ toJSON() {
67096
+ return { type: "gapcursor", pos: this.head };
66951
67097
  }
66952
- else {
66953
- return new HistoryState(history.done.addMaps(tr.mapping.maps), history.undone.addMaps(tr.mapping.maps), mapRanges(history.prevRanges, tr.mapping), history.prevTime, history.prevComposition);
67098
+ /**
67099
+ @internal
67100
+ */
67101
+ static fromJSON(doc, json) {
67102
+ if (typeof json.pos != "number")
67103
+ throw new RangeError("Invalid input for GapCursor.fromJSON");
67104
+ return new GapCursor(doc.resolve(json.pos));
67105
+ }
67106
+ /**
67107
+ @internal
67108
+ */
67109
+ getBookmark() { return new GapBookmark(this.anchor); }
67110
+ /**
67111
+ @internal
67112
+ */
67113
+ static valid($pos) {
67114
+ let parent = $pos.parent;
67115
+ if (parent.inlineContent || !closedBefore($pos) || !closedAfter($pos))
67116
+ return false;
67117
+ let override = parent.type.spec.allowGapCursor;
67118
+ if (override != null)
67119
+ return override;
67120
+ let deflt = parent.contentMatchAt($pos.index()).defaultType;
67121
+ return deflt && deflt.isTextblock;
67122
+ }
67123
+ /**
67124
+ @internal
67125
+ */
67126
+ static findGapCursorFrom($pos, dir, mustMove = false) {
67127
+ search: for (;;) {
67128
+ if (!mustMove && GapCursor.valid($pos))
67129
+ return $pos;
67130
+ let pos = $pos.pos, next = null;
67131
+ // Scan up from this position
67132
+ for (let d = $pos.depth;; d--) {
67133
+ let parent = $pos.node(d);
67134
+ if (dir > 0 ? $pos.indexAfter(d) < parent.childCount : $pos.index(d) > 0) {
67135
+ next = parent.child(dir > 0 ? $pos.indexAfter(d) : $pos.index(d) - 1);
67136
+ break;
67137
+ }
67138
+ else if (d == 0) {
67139
+ return null;
67140
+ }
67141
+ pos += dir;
67142
+ let $cur = $pos.doc.resolve(pos);
67143
+ if (GapCursor.valid($cur))
67144
+ return $cur;
67145
+ }
67146
+ // And then down into the next node
67147
+ for (;;) {
67148
+ let inside = dir > 0 ? next.firstChild : next.lastChild;
67149
+ if (!inside) {
67150
+ if (next.isAtom && !next.isText && !NodeSelection.isSelectable(next)) {
67151
+ $pos = $pos.doc.resolve(pos + next.nodeSize * dir);
67152
+ mustMove = false;
67153
+ continue search;
67154
+ }
67155
+ break;
67156
+ }
67157
+ next = inside;
67158
+ pos += dir;
67159
+ let $cur = $pos.doc.resolve(pos);
67160
+ if (GapCursor.valid($cur))
67161
+ return $cur;
67162
+ }
67163
+ return null;
67164
+ }
66954
67165
  }
66955
67166
  }
66956
- function isAdjacentTo(transform, prevRanges) {
66957
- if (!prevRanges)
66958
- return false;
66959
- if (!transform.docChanged)
66960
- return true;
66961
- let adjacent = false;
66962
- transform.mapping.maps[0].forEach((start, end) => {
66963
- for (let i = 0; i < prevRanges.length; i += 2)
66964
- if (start <= prevRanges[i + 1] && end >= prevRanges[i])
66965
- adjacent = true;
66966
- });
66967
- return adjacent;
67167
+ GapCursor.prototype.visible = false;
67168
+ GapCursor.findFrom = GapCursor.findGapCursorFrom;
67169
+ Selection$2.jsonID("gapcursor", GapCursor);
67170
+ class GapBookmark {
67171
+ constructor(pos) {
67172
+ this.pos = pos;
67173
+ }
67174
+ map(mapping) {
67175
+ return new GapBookmark(mapping.map(this.pos));
67176
+ }
67177
+ resolve(doc) {
67178
+ let $pos = doc.resolve(this.pos);
67179
+ return GapCursor.valid($pos) ? new GapCursor($pos) : Selection$2.near($pos);
67180
+ }
66968
67181
  }
66969
- function rangesFor(maps) {
66970
- let result = [];
66971
- for (let i = maps.length - 1; i >= 0 && result.length == 0; i--)
66972
- maps[i].forEach((_from, _to, from, to) => result.push(from, to));
66973
- return result;
67182
+ function needsGap(type) {
67183
+ return type.isAtom || type.spec.isolating || type.spec.createGapCursor;
66974
67184
  }
66975
- function mapRanges(ranges, mapping) {
66976
- if (!ranges)
66977
- return null;
66978
- let result = [];
66979
- for (let i = 0; i < ranges.length; i += 2) {
66980
- let from = mapping.map(ranges[i], 1), to = mapping.map(ranges[i + 1], -1);
66981
- if (from <= to)
66982
- result.push(from, to);
67185
+ function closedBefore($pos) {
67186
+ for (let d = $pos.depth; d >= 0; d--) {
67187
+ let index = $pos.index(d), parent = $pos.node(d);
67188
+ // At the start of this parent, look at next one
67189
+ if (index == 0) {
67190
+ if (parent.type.spec.isolating)
67191
+ return true;
67192
+ continue;
67193
+ }
67194
+ // See if the node before (or its first ancestor) is closed
67195
+ for (let before = parent.child(index - 1);; before = before.lastChild) {
67196
+ if ((before.childCount == 0 && !before.inlineContent) || needsGap(before.type))
67197
+ return true;
67198
+ if (before.inlineContent)
67199
+ return false;
67200
+ }
66983
67201
  }
66984
- return result;
66985
- }
66986
- // Apply the latest event from one branch to the document and shift the event
66987
- // onto the other branch.
66988
- function histTransaction(history, state, redo) {
66989
- let preserveItems = mustPreserveItems(state);
66990
- let histOptions = historyKey.get(state).spec.config;
66991
- let pop = (redo ? history.undone : history.done).popEvent(state, preserveItems);
66992
- if (!pop)
66993
- return null;
66994
- let selection = pop.selection.resolve(pop.transform.doc);
66995
- let added = (redo ? history.done : history.undone).addTransform(pop.transform, state.selection.getBookmark(), histOptions, preserveItems);
66996
- let newHist = new HistoryState(redo ? added : pop.remaining, redo ? pop.remaining : added, null, 0, -1);
66997
- return pop.transform.setSelection(selection).setMeta(historyKey, { redo, historyState: newHist });
67202
+ // Hit start of document
67203
+ return true;
66998
67204
  }
66999
- let cachedPreserveItems = false, cachedPreserveItemsPlugins = null;
67000
- // Check whether any plugin in the given state has a
67001
- // `historyPreserveItems` property in its spec, in which case we must
67002
- // preserve steps exactly as they came in, so that they can be
67003
- // rebased.
67004
- function mustPreserveItems(state) {
67005
- let plugins = state.plugins;
67006
- if (cachedPreserveItemsPlugins != plugins) {
67007
- cachedPreserveItems = false;
67008
- cachedPreserveItemsPlugins = plugins;
67009
- for (let i = 0; i < plugins.length; i++)
67010
- if (plugins[i].spec.historyPreserveItems) {
67011
- cachedPreserveItems = true;
67012
- break;
67013
- }
67205
+ function closedAfter($pos) {
67206
+ for (let d = $pos.depth; d >= 0; d--) {
67207
+ let index = $pos.indexAfter(d), parent = $pos.node(d);
67208
+ if (index == parent.childCount) {
67209
+ if (parent.type.spec.isolating)
67210
+ return true;
67211
+ continue;
67212
+ }
67213
+ for (let after = parent.child(index);; after = after.firstChild) {
67214
+ if ((after.childCount == 0 && !after.inlineContent) || needsGap(after.type))
67215
+ return true;
67216
+ if (after.inlineContent)
67217
+ return false;
67218
+ }
67014
67219
  }
67015
- return cachedPreserveItems;
67220
+ return true;
67016
67221
  }
67017
- const historyKey = new PluginKey("history");
67018
- const closeHistoryKey = new PluginKey("closeHistory");
67019
- /**
67020
- Returns a plugin that enables the undo history for an editor. The
67021
- plugin will track undo and redo stacks, which can be used with the
67022
- [`undo`](https://prosemirror.net/docs/ref/#history.undo) and [`redo`](https://prosemirror.net/docs/ref/#history.redo) commands.
67023
67222
 
67024
- You can set an `"addToHistory"` [metadata
67025
- property](https://prosemirror.net/docs/ref/#state.Transaction.setMeta) of `false` on a transaction
67026
- to prevent it from being rolled back by undo.
67223
+ /**
67224
+ Create a gap cursor plugin. When enabled, this will capture clicks
67225
+ near and arrow-key-motion past places that don't have a normally
67226
+ selectable position nearby, and create a gap cursor selection for
67227
+ them. The cursor is drawn as an element with class
67228
+ `ProseMirror-gapcursor`. You can either include
67229
+ `style/gapcursor.css` from the package's directory or add your own
67230
+ styles to make it visible.
67027
67231
  */
67028
- function history(config = {}) {
67029
- config = { depth: config.depth || 100,
67030
- newGroupDelay: config.newGroupDelay || 500 };
67232
+ function gapCursor() {
67031
67233
  return new Plugin({
67032
- key: historyKey,
67033
- state: {
67034
- init() {
67035
- return new HistoryState(Branch.empty, Branch.empty, null, 0, -1);
67036
- },
67037
- apply(tr, hist, state) {
67038
- return applyTransaction(hist, state, tr, config);
67039
- }
67040
- },
67041
- config,
67042
67234
  props: {
67043
- handleDOMEvents: {
67044
- beforeinput(view, e) {
67045
- let inputType = e.inputType;
67046
- let command = inputType == "historyUndo" ? undo : inputType == "historyRedo" ? redo : null;
67047
- if (!command || !view.editable)
67048
- return false;
67049
- e.preventDefault();
67050
- return command(view.state, view.dispatch);
67051
- }
67052
- }
67235
+ decorations: drawGapCursor,
67236
+ createSelectionBetween(_view, $anchor, $head) {
67237
+ return $anchor.pos == $head.pos && GapCursor.valid($head) ? new GapCursor($head) : null;
67238
+ },
67239
+ handleClick,
67240
+ handleKeyDown,
67241
+ handleDOMEvents: { beforeinput: beforeinput }
67053
67242
  }
67054
67243
  });
67055
67244
  }
67056
- function buildCommand(redo, scroll) {
67057
- return (state, dispatch) => {
67058
- let hist = historyKey.getState(state);
67059
- if (!hist || (redo ? hist.undone : hist.done).eventCount == 0)
67060
- return false;
67061
- if (dispatch) {
67062
- let tr = histTransaction(hist, state, redo);
67063
- if (tr)
67064
- dispatch(scroll ? tr.scrollIntoView() : tr);
67245
+ const handleKeyDown = keydownHandler({
67246
+ "ArrowLeft": arrow("horiz", -1),
67247
+ "ArrowRight": arrow("horiz", 1),
67248
+ "ArrowUp": arrow("vert", -1),
67249
+ "ArrowDown": arrow("vert", 1)
67250
+ });
67251
+ function arrow(axis, dir) {
67252
+ const dirStr = axis == "vert" ? (dir > 0 ? "down" : "up") : (dir > 0 ? "right" : "left");
67253
+ return function (state, dispatch, view) {
67254
+ let sel = state.selection;
67255
+ let $start = dir > 0 ? sel.$to : sel.$from, mustMove = sel.empty;
67256
+ if (sel instanceof TextSelection) {
67257
+ if (!view.endOfTextblock(dirStr) || $start.depth == 0)
67258
+ return false;
67259
+ mustMove = false;
67260
+ $start = state.doc.resolve(dir > 0 ? $start.after() : $start.before());
67065
67261
  }
67262
+ let $found = GapCursor.findGapCursorFrom($start, dir, mustMove);
67263
+ if (!$found)
67264
+ return false;
67265
+ if (dispatch)
67266
+ dispatch(state.tr.setSelection(new GapCursor($found)));
67066
67267
  return true;
67067
67268
  };
67068
67269
  }
67069
- /**
67070
- A command function that undoes the last change, if any.
67071
- */
67072
- const undo = buildCommand(false, true);
67073
- /**
67074
- A command function that redoes the last undone change, if any.
67075
- */
67076
- const redo = buildCommand(true, true);
67270
+ function handleClick(view, pos, event) {
67271
+ if (!view || !view.editable)
67272
+ return false;
67273
+ let $pos = view.state.doc.resolve(pos);
67274
+ if (!GapCursor.valid($pos))
67275
+ return false;
67276
+ let clickPos = view.posAtCoords({ left: event.clientX, top: event.clientY });
67277
+ if (clickPos && clickPos.inside > -1 && NodeSelection.isSelectable(view.state.doc.nodeAt(clickPos.inside)))
67278
+ return false;
67279
+ view.dispatch(view.state.tr.setSelection(new GapCursor($pos)));
67280
+ return true;
67281
+ }
67282
+ // This is a hack that, when a composition starts while a gap cursor
67283
+ // is active, quickly creates an inline context for the composition to
67284
+ // happen in, to avoid it being aborted by the DOM selection being
67285
+ // moved into a valid position.
67286
+ function beforeinput(view, event) {
67287
+ if (event.inputType != "insertCompositionText" || !(view.state.selection instanceof GapCursor))
67288
+ return false;
67289
+ let { $from } = view.state.selection;
67290
+ let insert = $from.parent.contentMatchAt($from.index()).findWrapping(view.state.schema.nodes.text);
67291
+ if (!insert)
67292
+ return false;
67293
+ let frag = Fragment.empty;
67294
+ for (let i = insert.length - 1; i >= 0; i--)
67295
+ frag = Fragment.from(insert[i].createAndFill(null, frag));
67296
+ let tr = view.state.tr.replace($from.pos, $from.pos, new Slice(frag, 0, 0));
67297
+ tr.setSelection(TextSelection.near(tr.doc.resolve($from.pos + 1)));
67298
+ view.dispatch(tr);
67299
+ return false;
67300
+ }
67301
+ function drawGapCursor(state) {
67302
+ if (!(state.selection instanceof GapCursor))
67303
+ return null;
67304
+ let node = document.createElement("div");
67305
+ node.className = "ProseMirror-gapcursor";
67306
+ return DecorationSet.create(state.doc, [Decoration.widget(state.selection.head, node, { key: "gapcursor" })]);
67307
+ }
67077
67308
 
67078
67309
  //#region src/character-count/character-count.ts
67079
67310
  /**
@@ -97669,12 +97900,12 @@ focus outline in that case.
97669
97900
  toDOMStream(options) {
97670
97901
  return streamAdapters.toDOMStream((this._closedPromiseResolve || this._error)
97671
97902
  ? this
97672
- : this._values, options);
97903
+ : this._values);
97673
97904
  }
97674
97905
  toNodeStream(options) {
97675
97906
  return streamAdapters.toNodeStream((this._closedPromiseResolve || this._error)
97676
97907
  ? this
97677
- : this._values, options);
97908
+ : this._values);
97678
97909
  }
97679
97910
  throw(_) {
97680
97911
  return __awaiter(this, void 0, void 0, function* () { yield this.abort(_); return ITERATOR_DONE; });
@@ -100065,7 +100296,7 @@ focus outline in that case.
100065
100296
  toNodeStream() {
100066
100297
  return streamAdapters.toNodeStream((this.isSync()
100067
100298
  ? { [Symbol.iterator]: () => this }
100068
- : { [Symbol.asyncIterator]: () => this }), { objectMode: true });
100299
+ : { [Symbol.asyncIterator]: () => this }));
100069
100300
  }
100070
100301
  /** @nocollapse */
100071
100302
  // @ts-ignore
@@ -106734,15 +106965,17 @@ focus outline in that case.
106734
106965
  id="${(_, c) => `${c.parent.menuId}-option-${c.index}`}"
106735
106966
  class="chip-selector-option"
106736
106967
  data-option-value="${x => x}"
106968
+ aria-selected="${(_, c) => String(c.index === c.parent.activeOptionIndex)}"
106737
106969
  >
106738
106970
  ${x => x}
106739
106971
  </${menuItemTag}>
106740
- `)}
106972
+ `, { positioning: true })}
106741
106973
  ${when(x => x.customValueCandidate.length > 0, html `
106742
106974
  <${menuItemTag}
106743
106975
  id="${x => `${x.menuId}-option-create`}"
106744
106976
  class="chip-selector-option chip-selector-create-option"
106745
106977
  data-option-value="${x => x.customValueCandidate}"
106978
+ aria-selected="${x => String(x.activeOptionIndex === x.visibleOptionList.length)}"
106746
106979
  >
106747
106980
  ${x => x.createOptionLabel}
106748
106981
  </${menuItemTag}>
@@ -107007,10 +107240,6 @@ focus outline in that case.
107007
107240
  }
107008
107241
  }
107009
107242
  syncActiveOption() {
107010
- const options = Array.from(this.shadowRoot?.querySelectorAll('.chip-selector-option') ?? []);
107011
- options.forEach((option, index) => {
107012
- option.setAttribute('aria-selected', String(index === this.activeOptionIndex));
107013
- });
107014
107243
  if (this.activeOptionIndex < 0) {
107015
107244
  this.activeOptionId = null;
107016
107245
  }