markupeditor 0.9.42 → 0.9.44

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.
Files changed (2) hide show
  1. package/dist/markup-editor.js +775 -308
  2. package/package.json +1 -1
@@ -769,8 +769,11 @@ function findDiffStart(a, b, pos) {
769
769
  if (!childA.sameMarkup(childB))
770
770
  return pos;
771
771
  if (childA.isText && childA.text != childB.text) {
772
- for (let j = 0; childA.text[j] == childB.text[j]; j++)
772
+ let tA = childA.text, tB = childB.text, j = 0;
773
+ for (; tA[j] == tB[j]; j++)
773
774
  pos++;
775
+ if (j && j < tA.length && j < tB.length && surrogateHigh(tA.charCodeAt(j - 1)) && surrogateLow(tA.charCodeAt(j)))
776
+ pos--;
774
777
  return pos;
775
778
  }
776
779
  if (childA.content.size || childB.content.size) {
@@ -794,12 +797,17 @@ function findDiffEnd(a, b, posA, posB) {
794
797
  if (!childA.sameMarkup(childB))
795
798
  return { a: posA, b: posB };
796
799
  if (childA.isText && childA.text != childB.text) {
797
- let same = 0, minSize = Math.min(childA.text.length, childB.text.length);
798
- while (same < minSize && childA.text[childA.text.length - same - 1] == childB.text[childB.text.length - same - 1]) {
799
- same++;
800
+ let tA = childA.text, tB = childB.text, iA = tA.length, iB = tB.length;
801
+ while (iA > 0 && iB > 0 && tA[iA - 1] == tB[iB - 1]) {
802
+ iA--;
803
+ iB--;
800
804
  posA--;
801
805
  posB--;
802
806
  }
807
+ if (iA && iB && iA < tA.length && surrogateHigh(tA.charCodeAt(iA - 1)) && surrogateLow(tA.charCodeAt(iA))) {
808
+ posA++;
809
+ posB++;
810
+ }
803
811
  return { a: posA, b: posB };
804
812
  }
805
813
  if (childA.content.size || childB.content.size) {
@@ -811,6 +819,8 @@ function findDiffEnd(a, b, posA, posB) {
811
819
  posB -= size;
812
820
  }
813
821
  }
822
+ function surrogateLow(ch) { return ch >= 0xDC00 && ch < 0xE000; }
823
+ function surrogateHigh(ch) { return ch >= 0xD800 && ch < 0xDC00; }
814
824
 
815
825
  /**
816
826
  A fragment represents a node's collection of child nodes.
@@ -1068,7 +1078,7 @@ class Fragment {
1068
1078
  return Fragment.empty;
1069
1079
  if (!Array.isArray(value))
1070
1080
  throw new RangeError("Invalid input for Fragment.fromJSON");
1071
- return new Fragment(value.map(schema.nodeFromJSON));
1081
+ return Fragment.fromArray(value.map(schema.nodeFromJSON));
1072
1082
  }
1073
1083
  /**
1074
1084
  Build a fragment from an array of nodes. Ensures that adjacent
@@ -1302,17 +1312,6 @@ given an invalid replacement.
1302
1312
  */
1303
1313
  class ReplaceError extends Error {
1304
1314
  }
1305
- /*
1306
- ReplaceError = function(this: any, message: string) {
1307
- let err = Error.call(this, message)
1308
- ;(err as any).__proto__ = ReplaceError.prototype
1309
- return err
1310
- } as any
1311
-
1312
- ReplaceError.prototype = Object.create(Error.prototype)
1313
- ReplaceError.prototype.constructor = ReplaceError
1314
- ReplaceError.prototype.name = "ReplaceError"
1315
- */
1316
1315
  /**
1317
1316
  A slice represents a piece cut out of a larger document. It
1318
1317
  stores not only a fragment, but also the depth up to which nodes on
@@ -1358,7 +1357,7 @@ class Slice {
1358
1357
  @internal
1359
1358
  */
1360
1359
  insertAt(pos, fragment) {
1361
- let content = insertInto(this.content, pos + this.openStart, fragment);
1360
+ let content = insertInto(this.content, pos + this.openStart, fragment, this.openStart + 1, this.openEnd + 1);
1362
1361
  return content && new Slice(content, this.openStart, this.openEnd);
1363
1362
  }
1364
1363
  /**
@@ -1432,14 +1431,14 @@ function removeRange(content, from, to) {
1432
1431
  throw new RangeError("Removing non-flat range");
1433
1432
  return content.replaceChild(index, child.copy(removeRange(child.content, from - offset - 1, to - offset - 1)));
1434
1433
  }
1435
- function insertInto(content, dist, insert, parent) {
1434
+ function insertInto(content, dist, insert, openStart, openEnd, parent) {
1436
1435
  let { index, offset } = content.findIndex(dist), child = content.maybeChild(index);
1437
1436
  if (offset == dist || child.isText) {
1438
- if (parent && !parent.canReplace(index, index, insert))
1437
+ if (parent && openStart <= 0 && openEnd <= 0 && !parent.canReplace(index, index, insert))
1439
1438
  return null;
1440
1439
  return content.cut(0, dist).append(insert).append(content.cut(dist));
1441
1440
  }
1442
- let inner = insertInto(child.content, dist - offset - 1, insert, child);
1441
+ let inner = insertInto(child.content, dist - offset - 1, insert, index == 0 ? openStart - 1 : 0, index == content.childCount - 1 ? openEnd - 1 : 0, child);
1443
1442
  return inner && content.replaceChild(index, child.copy(inner));
1444
1443
  }
1445
1444
  function replace($from, $to, slice) {
@@ -1502,7 +1501,8 @@ function addRange($start, $end, depth, target) {
1502
1501
  addNode($end.nodeBefore, target);
1503
1502
  }
1504
1503
  function close(node, content) {
1505
- node.type.checkContent(content);
1504
+ if (!node.type.validContent(content))
1505
+ throw new ReplaceError("Invalid content for node " + node.type.name);
1506
1506
  return node.copy(content);
1507
1507
  }
1508
1508
  function replaceThreeWay($from, $start, $end, $to, depth) {
@@ -1969,10 +1969,11 @@ let Node$1 = class Node {
1969
1969
  */
1970
1970
  forEach(f) { this.content.forEach(f); }
1971
1971
  /**
1972
- Invoke a callback for all descendant nodes recursively between
1972
+ Invoke a callback for all descendant nodes recursively overlapping
1973
1973
  the given two positions that are relative to start of this
1974
- node's content. The callback is invoked with the node, its
1975
- position relative to the original node (method receiver),
1974
+ node's content. This includes all ancestors of the nodes
1975
+ containing the two positions. The callback is invoked with the
1976
+ node, its position relative to the original node (method receiver),
1976
1977
  its parent node, and its child index. When the callback returns
1977
1978
  false for a given node, that node's children will not be
1978
1979
  recursed over. The last parameter can be used to specify a
@@ -2812,13 +2813,12 @@ function computeAttrs(attrs, value) {
2812
2813
  return built;
2813
2814
  }
2814
2815
  function checkAttrs(attrs, values, type, name) {
2815
- for (let name in values)
2816
- if (!(name in attrs))
2817
- throw new RangeError(`Unsupported attribute ${name} for ${type} of type ${name}`);
2818
- for (let name in attrs) {
2819
- let attr = attrs[name];
2820
- if (attr.validate)
2821
- attr.validate(values[name]);
2816
+ for (let attr in values)
2817
+ if (!(attr in attrs))
2818
+ throw new RangeError(`Unsupported attribute ${attr} for ${type} of type ${name}`);
2819
+ for (let attr in attrs) {
2820
+ if (attrs[attr].validate)
2821
+ attrs[attr].validate(values[attr]);
2822
2822
  }
2823
2823
  }
2824
2824
  function initAttrs(typeName, attrs) {
@@ -3438,7 +3438,7 @@ class DOMParser {
3438
3438
  }
3439
3439
  }
3440
3440
  const blockTags = {
3441
- address: true, article: true, aside: true, blockquote: true, canvas: true,
3441
+ address: true, article: true, aside: true, blockquote: true, body: true, canvas: true,
3442
3442
  dd: true, div: true, dl: true, fieldset: true, figcaption: true, figure: true,
3443
3443
  footer: true, form: true, h1: true, h2: true, h3: true, h4: true, h5: true,
3444
3444
  h6: true, header: true, hgroup: true, hr: true, li: true, noscript: true, ol: true,
@@ -4060,6 +4060,8 @@ class DOMSerializer {
4060
4060
  @internal
4061
4061
  */
4062
4062
  serializeNodeInner(node, options) {
4063
+ if (node.isText)
4064
+ return doc$1(options).createTextNode(node.text);
4063
4065
  let { dom, contentDOM } = renderSpec(doc$1(options), this.nodes[node.type.name](node), null, node.attrs);
4064
4066
  if (contentDOM) {
4065
4067
  if (node.isLeaf)
@@ -4094,6 +4096,9 @@ class DOMSerializer {
4094
4096
  return toDOM && renderSpec(doc$1(options), toDOM(mark, inline), null, mark.attrs);
4095
4097
  }
4096
4098
  static renderSpec(doc, structure, xmlNS = null, blockArraysIn) {
4099
+ // Kludge for backwards-compatibility with accidental original behavious
4100
+ if (typeof structure == "string")
4101
+ return { dom: doc.createTextNode(structure) };
4097
4102
  return renderSpec(doc, structure, xmlNS, blockArraysIn);
4098
4103
  }
4099
4104
  /**
@@ -4165,11 +4170,9 @@ function suspiciousAttributesInner(attrs) {
4165
4170
  return result;
4166
4171
  }
4167
4172
  function renderSpec(doc, structure, xmlNS, blockArraysIn) {
4168
- if (typeof structure == "string")
4169
- return { dom: doc.createTextNode(structure) };
4170
- if (structure.nodeType != null)
4173
+ if (structure.nodeType == 1)
4171
4174
  return { dom: structure };
4172
- if (structure.dom && structure.dom.nodeType != null)
4175
+ if (structure.dom && structure.dom.nodeType == 1)
4173
4176
  return structure;
4174
4177
  let tagName = structure[0], suspicious;
4175
4178
  if (typeof tagName != "string")
@@ -4205,6 +4208,9 @@ function renderSpec(doc, structure, xmlNS, blockArraysIn) {
4205
4208
  throw new RangeError("Content hole must be the only child of its parent node");
4206
4209
  return { dom, contentDOM: dom };
4207
4210
  }
4211
+ else if (typeof child == "string") {
4212
+ dom.appendChild(doc.createTextNode(child));
4213
+ }
4208
4214
  else {
4209
4215
  let { dom: inner, contentDOM: innerContent } = renderSpec(doc, child, xmlNS, blockArraysIn);
4210
4216
  dom.appendChild(inner);
@@ -4929,7 +4935,8 @@ class ReplaceStep extends Step {
4929
4935
  return new ReplaceStep(this.from, this.from + this.slice.size, doc.slice(this.from, this.to));
4930
4936
  }
4931
4937
  map(mapping) {
4932
- let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
4938
+ let to = mapping.mapResult(this.to, -1);
4939
+ let from = this.from == this.to && ReplaceStep.MAP_BIAS < 0 ? to : mapping.mapResult(this.from, 1);
4933
4940
  if (from.deletedAcross && to.deletedAcross)
4934
4941
  return null;
4935
4942
  return new ReplaceStep(from.pos, Math.max(from.pos, to.pos), this.slice, this.structure);
@@ -4968,6 +4975,15 @@ class ReplaceStep extends Step {
4968
4975
  return new ReplaceStep(json.from, json.to, Slice.fromJSON(schema, json.slice), !!json.structure);
4969
4976
  }
4970
4977
  }
4978
+ /**
4979
+ By default, for backwards compatibility, an inserting step
4980
+ mapped over an insertion at that same position fill move after
4981
+ the inserted content. In a collaborative editing situation, that
4982
+ can make redone insertions appear in unexpected places. You can
4983
+ set this to -1 to make such mapping keep the step before the
4984
+ insertion instead.
4985
+ */
4986
+ ReplaceStep.MAP_BIAS = 1;
4971
4987
  Step.jsonID("replace", ReplaceStep);
4972
4988
  /**
4973
4989
  Replace a part of the document with a slice of content, but
@@ -5924,6 +5940,26 @@ function replaceRangeWith(tr, from, to, node) {
5924
5940
  }
5925
5941
  function deleteRange(tr, from, to) {
5926
5942
  let $from = tr.doc.resolve(from), $to = tr.doc.resolve(to);
5943
+ // When the deleted range spans from the start of one textblock to
5944
+ // the start of another one, move out of the start of both blocks.
5945
+ if ($from.parent.isTextblock && $to.parent.isTextblock && $from.start() != $to.start() &&
5946
+ $from.parentOffset == 0 && $to.parentOffset == 0) {
5947
+ let shared = $from.sharedDepth(to), isolated = false;
5948
+ for (let d = $from.depth; d > shared; d--)
5949
+ if ($from.node(d).type.spec.isolating)
5950
+ isolated = true;
5951
+ for (let d = $to.depth; d > shared; d--)
5952
+ if ($to.node(d).type.spec.isolating)
5953
+ isolated = true;
5954
+ if (!isolated) {
5955
+ for (let d = $from.depth; d > 0 && from == $from.start(d); d--)
5956
+ from = $from.before(d);
5957
+ for (let d = $to.depth; d > 0 && to == $to.start(d); d--)
5958
+ to = $to.before(d);
5959
+ $from = tr.doc.resolve(from);
5960
+ $to = tr.doc.resolve(to);
5961
+ }
5962
+ }
5927
5963
  let covered = coveredDepths($from, $to);
5928
5964
  for (let i = 0; i < covered.length; i++) {
5929
5965
  let depth = covered[i], last = i == covered.length - 1;
@@ -6134,6 +6170,27 @@ class Transform {
6134
6170
  return this.steps.length > 0;
6135
6171
  }
6136
6172
  /**
6173
+ Return a single range, in post-transform document positions,
6174
+ that covers all content changed by this transform. Returns null
6175
+ if no replacements are made. Note that this will ignore changes
6176
+ that add/remove marks without replacing the underlying content.
6177
+ */
6178
+ changedRange() {
6179
+ let from = 1e9, to = -1e9;
6180
+ for (let i = 0; i < this.mapping.maps.length; i++) {
6181
+ let map = this.mapping.maps[i];
6182
+ if (i) {
6183
+ from = map.map(from, 1);
6184
+ to = map.map(to, -1);
6185
+ }
6186
+ map.forEach((_f, _t, fromB, toB) => {
6187
+ from = Math.min(from, fromB);
6188
+ to = Math.max(to, toB);
6189
+ });
6190
+ }
6191
+ return from == 1e9 ? null : { from, to };
6192
+ }
6193
+ /**
6137
6194
  @internal
6138
6195
  */
6139
6196
  addStep(step, doc) {
@@ -7548,6 +7605,9 @@ function clientRect(node) {
7548
7605
  top: rect.top, bottom: rect.top + node.clientHeight * scaleY };
7549
7606
  }
7550
7607
  function scrollRectIntoView(view, rect, startDOM) {
7608
+ // Skip empty rects with all sides at 0, for example, when the element has no CSS box (display: none)
7609
+ if (!nonZero(rect) && rect.left == 0)
7610
+ return;
7551
7611
  let scrollThreshold = view.someProp("scrollThreshold") || 0, scrollMargin = view.someProp("scrollMargin") || 5;
7552
7612
  let doc = view.dom.ownerDocument;
7553
7613
  for (let parent = startDOM || view.dom;;) {
@@ -8102,7 +8162,7 @@ class ViewDesc {
8102
8162
  // When parsing in-editor content (in domchange.js), we allow
8103
8163
  // descriptions to determine the parse rules that should be used to
8104
8164
  // parse them.
8105
- parseRule() { return null; }
8165
+ parseRule(addedNodes) { return null; }
8106
8166
  // Used by the editor's event handler to ignore events that come
8107
8167
  // from certain descs.
8108
8168
  stopEvent(event) { return false; }
@@ -8507,7 +8567,8 @@ class WidgetViewDesc extends ViewDesc {
8507
8567
  wrap.appendChild(dom);
8508
8568
  dom = wrap;
8509
8569
  }
8510
- dom.contentEditable = "false";
8570
+ if (!dom.hasAttribute("contenteditable"))
8571
+ dom.contentEditable = "false";
8511
8572
  dom.classList.add("ProseMirror-widget");
8512
8573
  }
8513
8574
  super(parent, [], dom, null);
@@ -8614,7 +8675,7 @@ class MarkViewDesc extends ViewDesc {
8614
8675
  // correspond to an actual node in the document. Unlike mark descs,
8615
8676
  // they populate their child array themselves.
8616
8677
  class NodeViewDesc extends ViewDesc {
8617
- constructor(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, view, pos) {
8678
+ constructor(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM) {
8618
8679
  super(parent, [], dom, contentDOM);
8619
8680
  this.node = node;
8620
8681
  this.outerDeco = outerDeco;
@@ -8660,13 +8721,13 @@ class NodeViewDesc extends ViewDesc {
8660
8721
  let nodeDOM = dom;
8661
8722
  dom = applyOuterDeco(dom, outerDeco, node);
8662
8723
  if (spec)
8663
- return descObj = new CustomNodeViewDesc(parent, node, outerDeco, innerDeco, dom, contentDOM || null, nodeDOM, spec, view, pos + 1);
8724
+ return descObj = new CustomNodeViewDesc(parent, node, outerDeco, innerDeco, dom, contentDOM || null, nodeDOM, spec);
8664
8725
  else if (node.isText)
8665
- return new TextViewDesc(parent, node, outerDeco, innerDeco, dom, nodeDOM, view);
8726
+ return new TextViewDesc(parent, node, outerDeco, innerDeco, dom, nodeDOM);
8666
8727
  else
8667
- return new NodeViewDesc(parent, node, outerDeco, innerDeco, dom, contentDOM || null, nodeDOM, view, pos + 1);
8728
+ return new NodeViewDesc(parent, node, outerDeco, innerDeco, dom, contentDOM || null, nodeDOM);
8668
8729
  }
8669
- parseRule() {
8730
+ parseRule(addedNodes) {
8670
8731
  // Experimental kludge to allow opt-in re-parsing of nodes
8671
8732
  if (this.node.type.spec.reparseInView)
8672
8733
  return null;
@@ -8694,8 +8755,14 @@ class NodeViewDesc extends ViewDesc {
8694
8755
  break;
8695
8756
  }
8696
8757
  }
8697
- if (!rule.contentElement)
8698
- rule.getContent = () => Fragment.empty;
8758
+ if (!rule.contentElement) {
8759
+ let found = addedNodes &&
8760
+ addedNodes.find(n => n.nodeType == 1 && addedNodes.indexOf(n.parentNode) < 0 && this.dom.contains(n));
8761
+ if (found)
8762
+ rule.contentElement = found;
8763
+ else
8764
+ rule.getContent = () => Fragment.empty;
8765
+ }
8699
8766
  }
8700
8767
  return rule;
8701
8768
  }
@@ -8717,15 +8784,15 @@ class NodeViewDesc extends ViewDesc {
8717
8784
  let updater = new ViewTreeUpdater(this, localComposition && localComposition.node, view);
8718
8785
  iterDeco(this.node, this.innerDeco, (widget, i, insideNode) => {
8719
8786
  if (widget.spec.marks)
8720
- updater.syncToMarks(widget.spec.marks, inline, view);
8787
+ updater.syncToMarks(widget.spec.marks, inline, view, i);
8721
8788
  else if (widget.type.side >= 0 && !insideNode)
8722
- updater.syncToMarks(i == this.node.childCount ? Mark.none : this.node.child(i).marks, inline, view);
8789
+ updater.syncToMarks(i == this.node.childCount ? Mark.none : this.node.child(i).marks, inline, view, i);
8723
8790
  // If the next node is a desc matching this widget, reuse it,
8724
8791
  // otherwise insert the widget as a new view desc.
8725
8792
  updater.placeWidget(widget, view, off);
8726
8793
  }, (child, outerDeco, innerDeco, i) => {
8727
8794
  // Make sure the wrapping mark descs match the node's marks.
8728
- updater.syncToMarks(child.marks, inline, view);
8795
+ updater.syncToMarks(child.marks, inline, view, i);
8729
8796
  // Try several strategies for drawing this node
8730
8797
  let compIndex;
8731
8798
  if (updater.findNodeMatch(child, outerDeco, innerDeco, i)) ;
@@ -8741,7 +8808,7 @@ class NodeViewDesc extends ViewDesc {
8741
8808
  off += child.nodeSize;
8742
8809
  });
8743
8810
  // Drop all remaining descs after the current position.
8744
- updater.syncToMarks([], inline, view);
8811
+ updater.syncToMarks([], inline, view, 0);
8745
8812
  if (this.node.isTextblock)
8746
8813
  updater.addTextblockHacks();
8747
8814
  updater.destroyRest();
@@ -8848,14 +8915,14 @@ class NodeViewDesc extends ViewDesc {
8848
8915
  // and used by the view class.
8849
8916
  function docViewDesc(doc, outerDeco, innerDeco, dom, view) {
8850
8917
  applyOuterDeco(dom, outerDeco, doc);
8851
- let docView = new NodeViewDesc(undefined, doc, outerDeco, innerDeco, dom, dom, dom, view, 0);
8918
+ let docView = new NodeViewDesc(undefined, doc, outerDeco, innerDeco, dom, dom, dom);
8852
8919
  if (docView.contentDOM)
8853
8920
  docView.updateChildren(view, 0);
8854
8921
  return docView;
8855
8922
  }
8856
8923
  class TextViewDesc extends NodeViewDesc {
8857
- constructor(parent, node, outerDeco, innerDeco, dom, nodeDOM, view) {
8858
- super(parent, node, outerDeco, innerDeco, dom, null, nodeDOM, view, 0);
8924
+ constructor(parent, node, outerDeco, innerDeco, dom, nodeDOM) {
8925
+ super(parent, node, outerDeco, innerDeco, dom, null, nodeDOM);
8859
8926
  }
8860
8927
  parseRule() {
8861
8928
  let skip = this.nodeDOM.parentNode;
@@ -8895,9 +8962,9 @@ class TextViewDesc extends NodeViewDesc {
8895
8962
  ignoreMutation(mutation) {
8896
8963
  return mutation.type != "characterData" && mutation.type != "selection";
8897
8964
  }
8898
- slice(from, to, view) {
8965
+ slice(from, to, _view) {
8899
8966
  let node = this.node.cut(from, to), dom = document.createTextNode(node.text);
8900
- return new TextViewDesc(this.parent, node, this.outerDeco, this.innerDeco, dom, dom, view);
8967
+ return new TextViewDesc(this.parent, node, this.outerDeco, this.innerDeco, dom, dom);
8901
8968
  }
8902
8969
  markDirty(from, to) {
8903
8970
  super.markDirty(from, to);
@@ -8919,8 +8986,8 @@ class TrailingHackViewDesc extends ViewDesc {
8919
8986
  // extra checks only have to be made for nodes that are actually
8920
8987
  // customized.
8921
8988
  class CustomNodeViewDesc extends NodeViewDesc {
8922
- constructor(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, spec, view, pos) {
8923
- super(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, view, pos);
8989
+ constructor(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, spec) {
8990
+ super(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM);
8924
8991
  this.spec = spec;
8925
8992
  }
8926
8993
  // A custom `update` method gets to decide whether the update goes
@@ -9131,7 +9198,7 @@ class ViewTreeUpdater {
9131
9198
  }
9132
9199
  // Sync the current stack of mark descs with the given array of
9133
9200
  // marks, reusing existing mark descs when possible.
9134
- syncToMarks(marks, inline, view) {
9201
+ syncToMarks(marks, inline, view, parentIndex) {
9135
9202
  let keep = 0, depth = this.stack.length >> 1;
9136
9203
  let maxKeep = Math.min(depth, marks.length);
9137
9204
  while (keep < maxKeep &&
@@ -9147,14 +9214,29 @@ class ViewTreeUpdater {
9147
9214
  }
9148
9215
  while (depth < marks.length) {
9149
9216
  this.stack.push(this.top, this.index + 1);
9150
- let found = -1;
9151
- for (let i = this.index; i < Math.min(this.index + 3, this.top.children.length); i++) {
9217
+ let found = -1, scanTo = this.top.children.length;
9218
+ if (parentIndex < this.preMatch.index)
9219
+ scanTo = Math.min(this.index + 3, scanTo);
9220
+ for (let i = this.index; i < scanTo; i++) {
9152
9221
  let next = this.top.children[i];
9153
9222
  if (next.matchesMark(marks[depth]) && !this.isLocked(next.dom)) {
9154
9223
  found = i;
9155
9224
  break;
9156
9225
  }
9157
9226
  }
9227
+ // When nothing matches, try to update the mark view at this position
9228
+ // in place, so a custom mark view can adapt to a changed mark without
9229
+ // re-creating its DOM.
9230
+ if (found < 0 && this.index < this.top.children.length) {
9231
+ let cur = this.top.children[this.index];
9232
+ if (cur instanceof MarkViewDesc && cur.dirty != NODE_DIRTY &&
9233
+ cur.mark.type == marks[depth].type && cur.spec.update &&
9234
+ !this.isLocked(cur.dom) && cur.spec.update(marks[depth])) {
9235
+ cur.mark = marks[depth];
9236
+ found = this.index;
9237
+ this.changed = true;
9238
+ }
9239
+ }
9158
9240
  if (found > -1) {
9159
9241
  if (found > this.index) {
9160
9242
  this.changed = true;
@@ -9344,9 +9426,7 @@ class ViewTreeUpdater {
9344
9426
  }
9345
9427
  // Iterate from the end of the fragment and array of descs to find
9346
9428
  // directly matching ones, in order to avoid overeagerly reusing those
9347
- // for other nodes. Returns the fragment index of the first node that
9348
- // is part of the sequence of matched nodes at the end of the
9349
- // fragment.
9429
+ // for other nodes.
9350
9430
  function preMatch(frag, parentDesc) {
9351
9431
  let curDesc = parentDesc, descI = curDesc.children.length;
9352
9432
  let fI = frag.childCount, matched = new Map, matches = [];
@@ -9369,7 +9449,6 @@ function preMatch(frag, parentDesc) {
9369
9449
  break outer;
9370
9450
  }
9371
9451
  else {
9372
- // FIXME
9373
9452
  descI = curDesc.parent.children.indexOf(curDesc);
9374
9453
  curDesc = curDesc.parent;
9375
9454
  }
@@ -9586,14 +9665,14 @@ function selectionToDOM(view, force = false) {
9586
9665
  syncNodeSelection(view, sel);
9587
9666
  if (!editorOwnsSelection(view))
9588
9667
  return;
9589
- // The delayed drag selection causes issues with Cell Selections
9590
- // in Safari. And the drag selection delay is to workarond issues
9591
- // which only present in Chrome.
9592
- if (!force && view.input.mouseDown && view.input.mouseDown.allowDefault && chrome) {
9668
+ // Need to delay selection normalization during a native selection
9669
+ // drag on Chrome, or it will cause further dragging to glitch.
9670
+ let mouseDown = view.input.mouseDown;
9671
+ if (!force && chrome && mouseDown) {
9593
9672
  let domSel = view.domSelectionRange(), curSel = view.domObserver.currentSelection;
9594
9673
  if (domSel.anchorNode && curSel.anchorNode &&
9595
- isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset, curSel.anchorNode, curSel.anchorOffset)) {
9596
- view.input.mouseDown.delayedSelectionSync = true;
9674
+ isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset, curSel.anchorNode, curSel.anchorOffset) &&
9675
+ mouseDown.delaySelUpdate()) {
9597
9676
  view.domObserver.setCurSelection();
9598
9677
  return;
9599
9678
  }
@@ -10326,9 +10405,8 @@ const wrapMap = {
10326
10405
  td: ["table", "tbody", "tr"],
10327
10406
  th: ["table", "tbody", "tr"]
10328
10407
  };
10329
- let _detachedDoc = null;
10330
10408
  function detachedDoc() {
10331
- return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"));
10409
+ return document.implementation.createHTMLDocument("title");
10332
10410
  }
10333
10411
  let _policy = null;
10334
10412
  function maybeWrapTrusted(html) {
@@ -10338,15 +10416,21 @@ function maybeWrapTrusted(html) {
10338
10416
  // With the require-trusted-types-for CSP, Chrome will block
10339
10417
  // innerHTML, even on a detached document. This wraps the string in
10340
10418
  // a way that makes the browser allow us to use its parser again.
10341
- if (!_policy)
10342
- _policy = trustedTypes.defaultPolicy || trustedTypes.createPolicy("ProseMirrorClipboard", { createHTML: (s) => s });
10419
+ if (!_policy) {
10420
+ if (_policy = trustedTypes.defaultPolicy)
10421
+ try {
10422
+ return _policy.createHTML(html);
10423
+ }
10424
+ catch (_a) { }
10425
+ _policy = trustedTypes.createPolicy("ProseMirrorClipboard", { createHTML: (s) => s });
10426
+ }
10343
10427
  return _policy.createHTML(html);
10344
10428
  }
10345
10429
  function readHTML(html) {
10346
10430
  let metas = /^(\s*<meta [^>]*>)*/.exec(html);
10347
10431
  if (metas)
10348
10432
  html = html.slice(metas[0].length);
10349
- let elt = detachedDoc().createElement("div");
10433
+ let doc = detachedDoc(), elt = doc.body;
10350
10434
  let firstTag = /<([a-z][^>\s]+)/i.exec(html), wrap;
10351
10435
  if (wrap = firstTag && wrapMap[firstTag[1].toLowerCase()])
10352
10436
  html = wrap.map(n => "<" + n + ">").join("") + html + wrap.map(n => "</" + n + ">").reverse().join("");
@@ -10354,6 +10438,18 @@ function readHTML(html) {
10354
10438
  if (wrap)
10355
10439
  for (let i = 0; i < wrap.length; i++)
10356
10440
  elt = elt.querySelector(wrap[i]) || elt;
10441
+ // Inline styles defined in the pasted content, so that parse rules pick them up
10442
+ for (let i = 0; i < doc.styleSheets.length; i++) {
10443
+ let style = doc.styleSheets[i];
10444
+ for (let j = 0; j < style.rules.length; j++) {
10445
+ let rule = style.rules[j];
10446
+ if (rule instanceof CSSStyleRule) {
10447
+ let matches = elt.querySelectorAll(rule.selectorText);
10448
+ for (let k = 0; k < matches.length; k++)
10449
+ matches[k].style.cssText += rule.style.cssText;
10450
+ }
10451
+ }
10452
+ }
10357
10453
  return elt;
10358
10454
  }
10359
10455
  // Webkit browsers do some hard-to-predict replacement of regular
@@ -10384,6 +10480,12 @@ function addContext(slice, context) {
10384
10480
  let type = schema.nodes[array[i]];
10385
10481
  if (!type || type.hasRequiredAttrs())
10386
10482
  break;
10483
+ try {
10484
+ type.checkAttrs(array[i + 1]);
10485
+ }
10486
+ catch (e) {
10487
+ break;
10488
+ }
10387
10489
  content = Fragment.from(type.create(array[i + 1], content));
10388
10490
  openStart++;
10389
10491
  openEnd++;
@@ -10416,6 +10518,7 @@ class InputState {
10416
10518
  this.compositionNodes = [];
10417
10519
  this.compositionEndedAt = -2e8;
10418
10520
  this.compositionID = 1;
10521
+ this.badSafariComposition = false;
10419
10522
  // Set to a composition ID when there are pending changes at compositionend
10420
10523
  this.compositionPendingChanges = 0;
10421
10524
  this.domChangeCount = 0;
@@ -10444,6 +10547,8 @@ function setSelectionOrigin(view, origin) {
10444
10547
  view.input.lastSelectionTime = Date.now();
10445
10548
  }
10446
10549
  function destroyInput(view) {
10550
+ if (view.input.mouseDown)
10551
+ view.input.mouseDown.done();
10447
10552
  view.domObserver.stop();
10448
10553
  for (let type in view.input.eventHandlers)
10449
10554
  view.dom.removeEventListener(type, view.input.eventHandlers[type]);
@@ -10482,7 +10587,7 @@ function dispatchEvent(view, event) {
10482
10587
  editHandlers.keydown = (view, _event) => {
10483
10588
  let event = _event;
10484
10589
  view.input.shiftKey = event.keyCode == 16 || event.shiftKey;
10485
- if (inOrNearComposition(view, event))
10590
+ if (inOrNearComposition(view))
10486
10591
  return;
10487
10592
  view.input.lastKeyCode = event.keyCode;
10488
10593
  view.input.lastKeyCodeTime = Date.now();
@@ -10520,7 +10625,7 @@ editHandlers.keyup = (view, event) => {
10520
10625
  };
10521
10626
  editHandlers.keypress = (view, _event) => {
10522
10627
  let event = _event;
10523
- if (inOrNearComposition(view, event) || !event.charCode ||
10628
+ if (inOrNearComposition(view) || !event.charCode ||
10524
10629
  event.ctrlKey && !event.altKey || mac$3 && event.metaKey)
10525
10630
  return;
10526
10631
  if (view.someProp("handleKeyPress", f => f(view, event))) {
@@ -10614,26 +10719,28 @@ function handleTripleClick(view, pos, inside, event) {
10614
10719
  function defaultTripleClick(view, inside, event) {
10615
10720
  if (event.button != 0)
10616
10721
  return false;
10617
- let doc = view.state.doc;
10618
- if (inside == -1) {
10619
- if (doc.inlineContent) {
10620
- updateSelection(view, TextSelection.create(doc, 0, doc.content.size));
10621
- return true;
10622
- }
10722
+ let selection = selectionForTripleClick(view, inside, true), doc = view.state.doc;
10723
+ if (!selection)
10623
10724
  return false;
10624
- }
10725
+ updateSelection(view, selection);
10726
+ if (selection instanceof TextSelection && doc.eq(view.state.doc))
10727
+ view.input.mouseDown = new TripleClickDrag(view, selection);
10728
+ return true;
10729
+ }
10730
+ function selectionForTripleClick(view, inside, selectNodes) {
10731
+ let doc = view.state.doc;
10732
+ if (inside == -1)
10733
+ return doc.inlineContent ? TextSelection.create(doc, 0, doc.content.size) : null;
10625
10734
  let $pos = doc.resolve(inside);
10626
10735
  for (let i = $pos.depth + 1; i > 0; i--) {
10627
10736
  let node = i > $pos.depth ? $pos.nodeAfter : $pos.node(i);
10628
10737
  let nodePos = $pos.before(i);
10629
10738
  if (node.inlineContent)
10630
- updateSelection(view, TextSelection.create(doc, nodePos + 1, nodePos + 1 + node.content.size));
10631
- else if (NodeSelection.isSelectable(node))
10632
- updateSelection(view, NodeSelection.create(doc, nodePos));
10633
- else
10634
- continue;
10635
- return true;
10739
+ return TextSelection.create(doc, nodePos + 1, nodePos + 1 + node.content.size);
10740
+ else if (selectNodes && NodeSelection.isSelectable(node))
10741
+ return NodeSelection.create(doc, nodePos);
10636
10742
  }
10743
+ return null;
10637
10744
  }
10638
10745
  function forceDOMFlush(view) {
10639
10746
  return endComposition(view);
@@ -10652,13 +10759,13 @@ handlers.mousedown = (view, _event) => {
10652
10759
  type = "tripleClick";
10653
10760
  }
10654
10761
  view.input.lastClick = { time: now, x: event.clientX, y: event.clientY, type, button: event.button };
10762
+ if (view.input.mouseDown)
10763
+ view.input.mouseDown.done();
10655
10764
  let pos = view.posAtCoords(eventCoords(event));
10656
10765
  if (!pos)
10657
10766
  return;
10658
10767
  if (type == "singleClick") {
10659
- if (view.input.mouseDown)
10660
- view.input.mouseDown.done();
10661
- view.input.mouseDown = new MouseDown(view, pos, event, !!flushed);
10768
+ view.input.mouseDown = new LeftMouseDown(view, pos, event, !!flushed);
10662
10769
  }
10663
10770
  else if ((type == "doubleClick" ? handleDoubleClick : handleTripleClick)(view, pos.pos, pos.inside, event)) {
10664
10771
  event.preventDefault();
@@ -10668,13 +10775,34 @@ handlers.mousedown = (view, _event) => {
10668
10775
  }
10669
10776
  };
10670
10777
  class MouseDown {
10671
- constructor(view, pos, event, flushed) {
10778
+ constructor(view) {
10672
10779
  this.view = view;
10780
+ this.mightDrag = null;
10781
+ view.root.addEventListener("mouseup", this.up = this.up.bind(this));
10782
+ view.root.addEventListener("mousemove", this.move = this.move.bind(this));
10783
+ }
10784
+ up(event) {
10785
+ this.done();
10786
+ }
10787
+ move(event) {
10788
+ if (event.buttons == 0)
10789
+ this.done();
10790
+ }
10791
+ done() {
10792
+ this.view.root.removeEventListener("mouseup", this.up);
10793
+ this.view.root.removeEventListener("mousemove", this.move);
10794
+ if (this.view.input.mouseDown == this)
10795
+ this.view.input.mouseDown = null;
10796
+ }
10797
+ delaySelUpdate() { return false; }
10798
+ }
10799
+ class LeftMouseDown extends MouseDown {
10800
+ constructor(view, pos, event, flushed) {
10801
+ super(view);
10673
10802
  this.pos = pos;
10674
10803
  this.event = event;
10675
10804
  this.flushed = flushed;
10676
10805
  this.delayedSelectionSync = false;
10677
- this.mightDrag = null;
10678
10806
  this.startDoc = view.state.doc;
10679
10807
  this.selectNode = !!event[selectNodeModifier];
10680
10808
  this.allowDefault = event.shiftKey;
@@ -10693,8 +10821,8 @@ class MouseDown {
10693
10821
  this.target = targetDesc && targetDesc.nodeDOM.nodeType == 1 ? targetDesc.nodeDOM : null;
10694
10822
  let { selection } = view.state;
10695
10823
  if (event.button == 0 &&
10696
- targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
10697
- selection instanceof NodeSelection && selection.from <= targetPos && selection.to > targetPos)
10824
+ (targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
10825
+ selection instanceof NodeSelection && selection.from <= targetPos && selection.to > targetPos))
10698
10826
  this.mightDrag = {
10699
10827
  node: targetNode,
10700
10828
  pos: targetPos,
@@ -10712,13 +10840,10 @@ class MouseDown {
10712
10840
  }, 20);
10713
10841
  this.view.domObserver.start();
10714
10842
  }
10715
- view.root.addEventListener("mouseup", this.up = this.up.bind(this));
10716
- view.root.addEventListener("mousemove", this.move = this.move.bind(this));
10717
10843
  setSelectionOrigin(view, "pointer");
10718
10844
  }
10719
10845
  done() {
10720
- this.view.root.removeEventListener("mouseup", this.up);
10721
- this.view.root.removeEventListener("mousemove", this.move);
10846
+ super.done();
10722
10847
  if (this.mightDrag && this.target) {
10723
10848
  this.view.domObserver.stop();
10724
10849
  if (this.mightDrag.addAttr)
@@ -10728,8 +10853,10 @@ class MouseDown {
10728
10853
  this.view.domObserver.start();
10729
10854
  }
10730
10855
  if (this.delayedSelectionSync)
10731
- setTimeout(() => selectionToDOM(this.view));
10732
- this.view.input.mouseDown = null;
10856
+ setTimeout(() => {
10857
+ if (!this.view.isDestroyed)
10858
+ selectionToDOM(this.view);
10859
+ });
10733
10860
  }
10734
10861
  up(event) {
10735
10862
  this.done();
@@ -10768,14 +10895,41 @@ class MouseDown {
10768
10895
  move(event) {
10769
10896
  this.updateAllowDefault(event);
10770
10897
  setSelectionOrigin(this.view, "pointer");
10771
- if (event.buttons == 0)
10772
- this.done();
10898
+ super.move(event);
10773
10899
  }
10774
10900
  updateAllowDefault(event) {
10775
10901
  if (!this.allowDefault && (Math.abs(this.event.x - event.clientX) > 4 ||
10776
10902
  Math.abs(this.event.y - event.clientY) > 4))
10777
10903
  this.allowDefault = true;
10778
10904
  }
10905
+ delaySelUpdate() {
10906
+ if (!this.allowDefault)
10907
+ return false;
10908
+ this.delayedSelectionSync = true;
10909
+ return true;
10910
+ }
10911
+ }
10912
+ class TripleClickDrag extends MouseDown {
10913
+ constructor(view, startSelection) {
10914
+ super(view);
10915
+ this.startSelection = startSelection;
10916
+ this.startDoc = view.state.doc;
10917
+ }
10918
+ move(event) {
10919
+ if (event.buttons == 0 || this.view.isDestroyed || !this.view.state.doc.eq(this.startDoc)) {
10920
+ this.done();
10921
+ return;
10922
+ }
10923
+ event.preventDefault();
10924
+ setSelectionOrigin(this.view, "pointer");
10925
+ let pos = this.view.posAtCoords(eventCoords(event));
10926
+ let target = pos && selectionForTripleClick(this.view, pos.inside, false);
10927
+ if (!target)
10928
+ return;
10929
+ let { doc } = this.view.state, start = this.startSelection;
10930
+ let [anchor, head] = target.from < start.from ? [start.to, target.from] : [start.from, target.to];
10931
+ updateSelection(this.view, TextSelection.create(doc, anchor, head));
10932
+ }
10779
10933
  }
10780
10934
  handlers.touchstart = view => {
10781
10935
  view.input.lastTouch = Date.now();
@@ -10800,7 +10954,7 @@ function inOrNearComposition(view, event) {
10800
10954
  // This guards against the case where compositionend is triggered without the keyboard
10801
10955
  // (e.g. character confirmation may be done with the mouse), and keydown is triggered
10802
10956
  // afterwards- we wouldn't want to ignore the keydown event in this case.
10803
- if (safari && Math.abs(event.timeStamp - view.input.compositionEndedAt) < 500) {
10957
+ if (safari && Math.abs(Date.now() - view.input.compositionEndedAt) < 500) {
10804
10958
  view.input.compositionEndedAt = -2e8;
10805
10959
  return true;
10806
10960
  }
@@ -10859,10 +11013,12 @@ function selectionBeforeUneditable(view) {
10859
11013
  editHandlers.compositionend = (view, event) => {
10860
11014
  if (view.composing) {
10861
11015
  view.input.composing = false;
10862
- view.input.compositionEndedAt = event.timeStamp;
11016
+ view.input.compositionEndedAt = Date.now();
10863
11017
  view.input.compositionPendingChanges = view.domObserver.pendingRecords().length ? view.input.compositionID : 0;
10864
11018
  view.input.compositionNode = null;
10865
- if (view.input.compositionPendingChanges)
11019
+ if (view.input.badSafariComposition)
11020
+ view.domObserver.forceFlush();
11021
+ else if (view.input.compositionPendingChanges)
10866
11022
  Promise.resolve().then(() => view.domObserver.flush());
10867
11023
  view.input.compositionID++;
10868
11024
  scheduleComposeEnd(view, 20);
@@ -10876,7 +11032,7 @@ function scheduleComposeEnd(view, delay) {
10876
11032
  function clearComposition(view) {
10877
11033
  if (view.composing) {
10878
11034
  view.input.composing = false;
10879
- view.input.compositionEndedAt = timestampFromCustomEvent();
11035
+ view.input.compositionEndedAt = Date.now();
10880
11036
  }
10881
11037
  while (view.input.compositionNodes.length > 0)
10882
11038
  view.input.compositionNodes.pop().markParentsDirty();
@@ -10902,11 +11058,6 @@ function findCompositionNode(view) {
10902
11058
  }
10903
11059
  return textBefore || textAfter;
10904
11060
  }
10905
- function timestampFromCustomEvent() {
10906
- let event = document.createEvent("Event");
10907
- event.initEvent("event", true, true);
10908
- return event.timeStamp;
10909
- }
10910
11061
  /**
10911
11062
  @internal
10912
11063
  */
@@ -11041,8 +11192,9 @@ class Dragging {
11041
11192
  }
11042
11193
  const dragCopyModifier = mac$3 ? "altKey" : "ctrlKey";
11043
11194
  function dragMoves(view, event) {
11044
- let moves = view.someProp("dragCopies", test => !test(event));
11045
- return moves != null ? moves : !event[dragCopyModifier];
11195
+ let copy;
11196
+ view.someProp("dragCopies", test => { copy = copy || test(event); });
11197
+ return copy != null ? !copy : !event[dragCopyModifier];
11046
11198
  }
11047
11199
  handlers.dragstart = (view, _event) => {
11048
11200
  let event = _event;
@@ -11069,7 +11221,7 @@ handlers.dragstart = (view, _event) => {
11069
11221
  if (!event.dataTransfer.files.length || !chrome || chrome_version > 120)
11070
11222
  event.dataTransfer.clearData();
11071
11223
  event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
11072
- // See https://github.com/ProseMirror/prosemirror/issues/1156
11224
+ // See https://code.haverbeke.berlin/prosemirror/prosemirror/issues/1156
11073
11225
  event.dataTransfer.effectAllowed = "copyMove";
11074
11226
  if (!brokenClipboardAPI)
11075
11227
  event.dataTransfer.setData("text/plain", text);
@@ -11175,8 +11327,8 @@ handlers.beforeinput = (view, _event) => {
11175
11327
  // We should probably do more with beforeinput events, but support
11176
11328
  // is so spotty that I'm still waiting to see where they are going.
11177
11329
  // Very specific hack to deal with backspace sometimes failing on
11178
- // Chrome Android when after an uneditable node.
11179
- if (chrome && android && event.inputType == "deleteContentBackward") {
11330
+ // Chrome and Firefox Android when after an uneditable node.
11331
+ if (android && event.inputType == "deleteContentBackward") {
11180
11332
  view.domObserver.flushSoon();
11181
11333
  let { domChangeCount } = view.input;
11182
11334
  setTimeout(() => {
@@ -11925,15 +12077,24 @@ class DOMObserver {
11925
12077
  new window.MutationObserver(mutations => {
11926
12078
  for (let i = 0; i < mutations.length; i++)
11927
12079
  this.queue.push(mutations[i]);
11928
- // IE11 will sometimes (on backspacing out a single character
11929
- // text node after a BR node) call the observer callback
11930
- // before actually updating the DOM, which will cause
11931
- // ProseMirror to miss the change (see #930)
11932
12080
  if (ie$1 && ie_version <= 11 && mutations.some(m => m.type == "childList" && m.removedNodes.length ||
11933
- m.type == "characterData" && m.oldValue.length > m.target.nodeValue.length))
12081
+ m.type == "characterData" && m.oldValue.length > m.target.nodeValue.length)) {
12082
+ // IE11 will sometimes (on backspacing out a single character
12083
+ // text node after a BR node) call the observer callback
12084
+ // before actually updating the DOM, which will cause
12085
+ // ProseMirror to miss the change (see #930)
11934
12086
  this.flushSoon();
11935
- else
12087
+ }
12088
+ else if (safari && view.composing && mutations.some(m => m.type == "childList" && m.target.nodeName == "TR")) {
12089
+ // Safari does weird stuff when finishing a composition in a
12090
+ // table cell, which tends to involve inserting inappropriate
12091
+ // nodes in the table row.
12092
+ view.input.badSafariComposition = true;
12093
+ this.flushSoon();
12094
+ }
12095
+ else {
11936
12096
  this.flush();
12097
+ }
11937
12098
  });
11938
12099
  if (useCharData) {
11939
12100
  this.onCharData = e => {
@@ -12053,7 +12214,25 @@ class DOMObserver {
12053
12214
  }
12054
12215
  }
12055
12216
  }
12056
- if (gecko && added.length) {
12217
+ if (added.some(n => n.nodeName == "BR") &&
12218
+ (view.input.lastKeyCode == 8 || view.input.lastKeyCode == 46 ||
12219
+ chrome && (view.composing || view.input.compositionEndedAt > Date.now() - 50) &&
12220
+ mutations.some(m => m.type == "childList" && m.removedNodes.length))) {
12221
+ // Browsers sometimes insert a bogus break node if you
12222
+ // backspace out the last bit of text before an inline-flex node (#1552)
12223
+ for (let node of added)
12224
+ if (node.nodeName == "BR" && node.parentNode) {
12225
+ let after = node.nextSibling;
12226
+ while (after && after.nodeType == 1) {
12227
+ if (after.contentEditable == "false") {
12228
+ node.parentNode.removeChild(node);
12229
+ break;
12230
+ }
12231
+ after = after.firstChild;
12232
+ }
12233
+ }
12234
+ }
12235
+ else if (gecko && added.length) {
12057
12236
  let brs = added.filter(n => n.nodeName == "BR");
12058
12237
  if (brs.length == 2) {
12059
12238
  let [a, b] = brs;
@@ -12071,17 +12250,6 @@ class DOMObserver {
12071
12250
  }
12072
12251
  }
12073
12252
  }
12074
- else if ((chrome || safari) && added.some(n => n.nodeName == "BR") &&
12075
- (view.input.lastKeyCode == 8 || view.input.lastKeyCode == 46)) {
12076
- // Chrome/Safari sometimes insert a bogus break node if you
12077
- // backspace out the last bit of text before an inline-flex node (#1552)
12078
- for (let node of added)
12079
- if (node.nodeName == "BR" && node.parentNode) {
12080
- let after = node.nextSibling;
12081
- if (after && after.nodeType == 1 && after.contentEditable == "false")
12082
- node.parentNode.removeChild(node);
12083
- }
12084
- }
12085
12253
  let readSel = null;
12086
12254
  // If it looks like the browser has reset the selection to the
12087
12255
  // start of the document after focus, restore the selection from
@@ -12100,6 +12268,10 @@ class DOMObserver {
12100
12268
  view.docView.markDirty(from, to);
12101
12269
  checkCSS(view);
12102
12270
  }
12271
+ if (view.input.badSafariComposition) {
12272
+ view.input.badSafariComposition = false;
12273
+ fixUpBadSafariComposition(view, added);
12274
+ }
12103
12275
  this.handleDOMChange(from, to, typeOver, added);
12104
12276
  if (view.docView && view.docView.dirty)
12105
12277
  view.updateState(view.state);
@@ -12223,13 +12395,44 @@ function blockParent(view, node) {
12223
12395
  }
12224
12396
  return null;
12225
12397
  }
12398
+ // Kludge for a Safari bug where, on ending a composition in an
12399
+ // otherwise empty table cell, it randomly moves the composed text
12400
+ // into the table row around that cell, greatly confusing everything
12401
+ // (#188).
12402
+ function fixUpBadSafariComposition(view, addedNodes) {
12403
+ var _a;
12404
+ let { focusNode, focusOffset } = view.domSelectionRange();
12405
+ for (let node of addedNodes) {
12406
+ if (((_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.nodeName) == "TR") {
12407
+ let nextCell = node.nextSibling;
12408
+ while (nextCell && (nextCell.nodeName != "TD" && nextCell.nodeName != "TH"))
12409
+ nextCell = nextCell.nextSibling;
12410
+ if (nextCell) {
12411
+ let parent = nextCell;
12412
+ for (;;) {
12413
+ let first = parent.firstChild;
12414
+ if (!first || first.nodeType != 1 || first.contentEditable == "false" ||
12415
+ /^(BR|IMG)$/.test(first.nodeName))
12416
+ break;
12417
+ parent = first;
12418
+ }
12419
+ parent.insertBefore(node, parent.firstChild);
12420
+ if (focusNode == node)
12421
+ view.domSelection().collapse(node, focusOffset);
12422
+ }
12423
+ else {
12424
+ node.parentNode.removeChild(node);
12425
+ }
12426
+ }
12427
+ }
12428
+ }
12226
12429
 
12227
12430
  // Note that all referencing and parsing is done with the
12228
12431
  // start-of-operation selection and document, since that's the one
12229
12432
  // that the DOM represents. If any changes came in in the meantime,
12230
12433
  // the modification is mapped over those before it is applied, in
12231
12434
  // readDOMChange.
12232
- function parseBetween(view, from_, to_) {
12435
+ function parseBetween(view, from_, to_, addedNodes) {
12233
12436
  let { node: parent, fromOffset, toOffset, from, to } = view.docView.parseRange(from_, to_);
12234
12437
  let domSel = view.domSelectionRange();
12235
12438
  let find;
@@ -12263,7 +12466,7 @@ function parseBetween(view, from_, to_) {
12263
12466
  to: toOffset,
12264
12467
  preserveWhitespace: $from.parent.type.whitespace == "pre" ? "full" : true,
12265
12468
  findPositions: find,
12266
- ruleFromNode,
12469
+ ruleFromNode: ruleFromNode(addedNodes),
12267
12470
  context: $from
12268
12471
  });
12269
12472
  if (find && find[0].pos != null) {
@@ -12274,10 +12477,10 @@ function parseBetween(view, from_, to_) {
12274
12477
  }
12275
12478
  return { doc, sel, from, to };
12276
12479
  }
12277
- function ruleFromNode(dom) {
12480
+ const ruleFromNode = (added) => (dom) => {
12278
12481
  let desc = dom.pmViewDesc;
12279
12482
  if (desc) {
12280
- return desc.parseRule();
12483
+ return desc.parseRule(added);
12281
12484
  }
12282
12485
  else if (dom.nodeName == "BR" && dom.parentNode) {
12283
12486
  // Safari replaces the list item or table cell with a BR
@@ -12296,7 +12499,7 @@ function ruleFromNode(dom) {
12296
12499
  return { ignore: true };
12297
12500
  }
12298
12501
  return null;
12299
- }
12502
+ };
12300
12503
  const isInline = /^(a|abbr|acronym|b|bd[io]|big|br|button|cite|code|data(list)?|del|dfn|em|i|img|ins|kbd|label|map|mark|meter|output|q|ruby|s|samp|small|span|strong|su[bp]|time|u|tt|var)$/i;
12301
12504
  function readDOMChange(view, from, to, typeOver, addedNodes) {
12302
12505
  let compositionID = view.input.compositionPendingChanges || (view.composing ? view.input.compositionID : 0);
@@ -12325,7 +12528,7 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
12325
12528
  from = $before.before(shared + 1);
12326
12529
  to = view.state.doc.resolve(to).after(shared + 1);
12327
12530
  let sel = view.state.selection;
12328
- let parse = parseBetween(view, from, to);
12531
+ let parse = parseBetween(view, from, to, addedNodes);
12329
12532
  let doc = view.state.doc, compare = doc.slice(parse.from, parse.to);
12330
12533
  let preferredPos, preferredSide;
12331
12534
  // Prefer anchoring to end when Backspace is pressed
@@ -12570,38 +12773,28 @@ function skipClosingAndOpening($pos, fromEnd, mayOpen) {
12570
12773
  return end;
12571
12774
  }
12572
12775
  function findDiff(a, b, pos, preferredPos, preferredSide) {
12573
- let start = a.findDiffStart(b, pos);
12776
+ let start = a.findDiffStart(b, pos), lenA = pos + a.size, lenB = pos + b.size;
12574
12777
  if (start == null)
12575
12778
  return null;
12576
- let { a: endA, b: endB } = a.findDiffEnd(b, pos + a.size, pos + b.size);
12779
+ let { a: endA, b: endB } = a.findDiffEnd(b, lenA, lenB);
12577
12780
  if (preferredSide == "end") {
12578
12781
  let adjust = Math.max(0, start - Math.min(endA, endB));
12579
12782
  preferredPos -= endA + adjust - start;
12580
12783
  }
12581
- if (endA < start && a.size < b.size) {
12784
+ if (endA < start && lenA < lenB) {
12582
12785
  let move = preferredPos <= start && preferredPos >= endA ? start - preferredPos : 0;
12583
12786
  start -= move;
12584
- if (start && start < b.size && isSurrogatePair(b.textBetween(start - 1, start + 1)))
12585
- start += move ? 1 : -1;
12586
12787
  endB = start + (endB - endA);
12587
12788
  endA = start;
12588
12789
  }
12589
12790
  else if (endB < start) {
12590
12791
  let move = preferredPos <= start && preferredPos >= endB ? start - preferredPos : 0;
12591
12792
  start -= move;
12592
- if (start && start < a.size && isSurrogatePair(a.textBetween(start - 1, start + 1)))
12593
- start += move ? 1 : -1;
12594
12793
  endA = start + (endA - endB);
12595
12794
  endB = start;
12596
12795
  }
12597
12796
  return { start, endA, endB };
12598
12797
  }
12599
- function isSurrogatePair(str) {
12600
- if (str.length != 2)
12601
- return false;
12602
- let a = str.charCodeAt(0), b = str.charCodeAt(1);
12603
- return a >= 0xDC00 && a <= 0xDFFF && b >= 0xD800 && b <= 0xDBFF;
12604
- }
12605
12798
 
12606
12799
  /**
12607
12800
  @internal
@@ -12655,7 +12848,7 @@ class EditorView {
12655
12848
  this.pluginViews = [];
12656
12849
  /**
12657
12850
  Holds `true` when a hack node is needed in Firefox to prevent the
12658
- [space is eaten issue](https://github.com/ProseMirror/prosemirror/issues/651)
12851
+ [space is eaten issue](https://code.haverbeke.berlin/prosemirror/prosemirror/issues/651)
12659
12852
  @internal
12660
12853
  */
12661
12854
  this.requiresGeckoHackNode = false;
@@ -12795,16 +12988,17 @@ class EditorView {
12795
12988
  this.docView.destroy();
12796
12989
  this.docView = docViewDesc(state.doc, outerDeco, innerDeco, this.dom, this);
12797
12990
  }
12798
- if (chromeKludge && !this.trackWrites)
12991
+ if (chromeKludge && (!this.trackWrites || !this.dom.contains(this.trackWrites)))
12799
12992
  forceSelUpdate = true;
12800
12993
  }
12801
12994
  // Work around for an issue where an update arriving right between
12802
12995
  // a DOM selection change and the "selectionchange" event for it
12803
12996
  // can cause a spurious DOM selection update, disrupting mouse
12804
12997
  // drag selection.
12998
+ let mouseDown = this.input.mouseDown;
12805
12999
  if (forceSelUpdate ||
12806
- !(this.input.mouseDown && this.domObserver.currentSelection.eq(this.domSelectionRange()) &&
12807
- anchorInRightPlace(this))) {
13000
+ !(mouseDown && this.domObserver.currentSelection.eq(this.domSelectionRange()) &&
13001
+ anchorInRightPlace(this) && mouseDown.delaySelUpdate())) {
12808
13002
  selectionToDOM(this, forceSelUpdate);
12809
13003
  }
12810
13004
  else {
@@ -12873,12 +13067,12 @@ class EditorView {
12873
13067
  }
12874
13068
  updateDraggedNode(dragging, prev) {
12875
13069
  let sel = dragging.node, found = -1;
12876
- if (this.state.doc.nodeAt(sel.from) == sel.node) {
13070
+ if (sel.from < this.state.doc.content.size && this.state.doc.nodeAt(sel.from) == sel.node) {
12877
13071
  found = sel.from;
12878
13072
  }
12879
13073
  else {
12880
13074
  let movedPos = sel.from + (this.state.doc.content.size - prev.doc.content.size);
12881
- let moved = movedPos > 0 && this.state.doc.nodeAt(movedPos);
13075
+ let moved = movedPos > 0 && movedPos < this.state.doc.content.size && this.state.doc.nodeAt(movedPos);
12882
13076
  if (moved == sel.node)
12883
13077
  found = movedPos;
12884
13078
  }
@@ -15545,16 +15739,20 @@ a custom function to determine the type of the newly split off block.
15545
15739
  */
15546
15740
  function splitBlockAs(splitNode) {
15547
15741
  return (state, dispatch) => {
15548
- let { $from, $to } = state.selection;
15549
15742
  if (state.selection instanceof NodeSelection && state.selection.node.isBlock) {
15743
+ let { $from } = state.selection;
15550
15744
  if (!$from.parentOffset || !canSplit(state.doc, $from.pos))
15551
15745
  return false;
15552
15746
  if (dispatch)
15553
15747
  dispatch(state.tr.split($from.pos).scrollIntoView());
15554
15748
  return true;
15555
15749
  }
15556
- if (!$from.depth)
15750
+ if (!state.selection.$from.depth)
15557
15751
  return false;
15752
+ let tr = state.tr;
15753
+ if (!state.selection.empty && (state.selection instanceof TextSelection || state.selection instanceof AllSelection))
15754
+ tr.deleteSelection();
15755
+ let { $from } = tr.selection, mapFrom = tr.steps.length;
15558
15756
  let types = [];
15559
15757
  let splitDepth, deflt, atEnd = false, atStart = false;
15560
15758
  for (let d = $from.depth;; d--) {
@@ -15573,10 +15771,7 @@ function splitBlockAs(splitNode) {
15573
15771
  types.unshift(null);
15574
15772
  }
15575
15773
  }
15576
- let tr = state.tr;
15577
- if (state.selection instanceof TextSelection || state.selection instanceof AllSelection)
15578
- tr.deleteSelection();
15579
- let splitPos = tr.mapping.map($from.pos);
15774
+ let splitPos = $from.pos;
15580
15775
  let can = canSplit(tr.doc, splitPos, types.length, types);
15581
15776
  if (!can) {
15582
15777
  types[0] = deflt ? { type: deflt } : null;
@@ -15586,9 +15781,10 @@ function splitBlockAs(splitNode) {
15586
15781
  return false;
15587
15782
  tr.split(splitPos, types.length, types);
15588
15783
  if (!atEnd && atStart && $from.node(splitDepth).type != deflt) {
15589
- let first = tr.mapping.map($from.before(splitDepth)), $first = tr.doc.resolve(first);
15784
+ let mapping = tr.mapping.slice(mapFrom);
15785
+ let first = mapping.map($from.before(splitDepth)), $first = tr.doc.resolve(first);
15590
15786
  if (deflt && $from.node(splitDepth - 1).canReplaceWith($first.index(), $first.index() + 1, deflt))
15591
- tr.setNodeMarkup(tr.mapping.map($from.before(splitDepth)), deflt);
15787
+ tr.setNodeMarkup(mapping.map($from.before(splitDepth)), deflt);
15592
15788
  }
15593
15789
  if (dispatch)
15594
15790
  dispatch(tr.scrollIntoView());
@@ -17035,14 +17231,17 @@ function requireCore () {
17035
17231
  return match && match.index === 0;
17036
17232
  }
17037
17233
 
17038
- // BACKREF_RE matches an open parenthesis or backreference. To avoid
17039
- // an incorrect parse, it additionally matches the following:
17040
- // - [...] elements, where the meaning of parentheses and escapes change
17041
- // - other escape sequences, so we do not misparse escape sequences as
17042
- // interesting elements
17043
- // - non-matching or lookahead parentheses, which do not capture. These
17044
- // follow the '(' with a '?'.
17045
- const BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
17234
+ // BACKREF_RE matches an open parenthesis or backreference. To avoid an
17235
+ // incorrect parse, it also matches the constructs where the meaning of
17236
+ // parentheses, escapes, or capture counting changes.
17237
+ const BACKREF_RE = new RegExp(either(
17238
+ /\[(?:[^\\\]]|\\.)*\]/, // a character class, inside which ( and \ lose their meaning
17239
+ /\(\?<(?![=!])[^>]+>/, // a named capture group `(?<name>` (not a lookbehind `(?<=` / `(?<!`)
17240
+ /\(\?'[^']+'/, // a named capture group `(?'name'`
17241
+ /\(\??/, // an opening parenthesis, capturing or non-capturing / lookahead
17242
+ /\\([1-9][0-9]*)/, // a backreference like `\1`
17243
+ /\\./ // any other escape sequence
17244
+ ));
17046
17245
 
17047
17246
  // **INTERNAL** Not intended for outside usage
17048
17247
  // join logically computes regexps.join(separator), but fixes the
@@ -17077,7 +17276,7 @@ function requireCore () {
17077
17276
  out += '\\' + String(Number(match[1]) + offset);
17078
17277
  } else {
17079
17278
  out += match[0];
17080
- if (match[0] === '(') {
17279
+ if (match[0] === '(' || /^\(\?[<']/.test(match[0])) {
17081
17280
  numCaptures++;
17082
17281
  }
17083
17282
  }
@@ -18119,7 +18318,7 @@ function requireCore () {
18119
18318
  return mode;
18120
18319
  }
18121
18320
 
18122
- var version = "11.11.1";
18321
+ var version = "11.12.0";
18123
18322
 
18124
18323
  class HTMLInjectionError extends Error {
18125
18324
  constructor(reason, html) {
@@ -18641,12 +18840,15 @@ function requireCore () {
18641
18840
  }
18642
18841
  }
18643
18842
 
18644
- // edge case for when illegal matches $ (end of line) which is technically
18843
+ // edge case for when illegal matches $ (end of line/text) which is technically
18645
18844
  // a 0 width match but not a begin/end match so it's not caught by the
18646
- // first handler (when ignoreIllegals is true)
18845
+ // first handler (when `ignoreIllegals` is true)
18647
18846
  if (match.type === "illegal" && lexeme === "") {
18648
- // advance so we aren't stuck in an infinite loop
18649
- modeBuffer += "\n";
18847
+ if (match.index === codeToHighlight.length) ; else {
18848
+ // matched literal `\n` (with `$`) so we must manually add the newline
18849
+ // itself to the modeBuffer so it is not lost when we advance the cursor
18850
+ modeBuffer += "\n";
18851
+ }
18650
18852
  return 1;
18651
18853
  }
18652
18854
 
@@ -19336,10 +19538,7 @@ function requireXml () {
19336
19538
  starts: {
19337
19539
  end: /<\/style>/,
19338
19540
  returnEnd: true,
19339
- subLanguage: [
19340
- 'css',
19341
- 'xml'
19342
- ]
19541
+ subLanguage: 'css'
19343
19542
  }
19344
19543
  },
19345
19544
  {
@@ -19352,11 +19551,7 @@ function requireXml () {
19352
19551
  starts: {
19353
19552
  end: /<\/script>/,
19354
19553
  returnEnd: true,
19355
- subLanguage: [
19356
- 'javascript',
19357
- 'handlebars',
19358
- 'xml'
19359
- ]
19554
+ subLanguage: 'javascript'
19360
19555
  }
19361
19556
  },
19362
19557
  // we need this for now for jSX
@@ -19864,11 +20059,53 @@ function requireC () {
19864
20059
  + ')';
19865
20060
 
19866
20061
 
20062
+ // C11 <stdatomic.h> atomic type names. This is an explicit whitelist so that
20063
+ // C11 atomic *functions* (atomic_init, atomic_store, atomic_load,
20064
+ // atomic_fetch_add, ...) are not mistakenly highlighted as types. See #3837.
20065
+ const ATOMIC_TYPES = regex.concat(/\batomic_/, regex.either(
20066
+ 'bool',
20067
+ 'char',
20068
+ 'schar',
20069
+ 'uchar',
20070
+ 'short',
20071
+ 'ushort',
20072
+ 'int',
20073
+ 'uint',
20074
+ 'long',
20075
+ 'ulong',
20076
+ 'llong',
20077
+ 'ullong',
20078
+ 'char16_t',
20079
+ 'char32_t',
20080
+ 'wchar_t',
20081
+ 'int_least8_t',
20082
+ 'uint_least8_t',
20083
+ 'int_least16_t',
20084
+ 'uint_least16_t',
20085
+ 'int_least32_t',
20086
+ 'uint_least32_t',
20087
+ 'int_least64_t',
20088
+ 'uint_least64_t',
20089
+ 'int_fast8_t',
20090
+ 'uint_fast8_t',
20091
+ 'int_fast16_t',
20092
+ 'uint_fast16_t',
20093
+ 'int_fast32_t',
20094
+ 'uint_fast32_t',
20095
+ 'int_fast64_t',
20096
+ 'uint_fast64_t',
20097
+ 'intptr_t',
20098
+ 'uintptr_t',
20099
+ 'size_t',
20100
+ 'ptrdiff_t',
20101
+ 'intmax_t',
20102
+ 'uintmax_t'
20103
+ ), /\b/);
19867
20104
  const TYPES = {
19868
20105
  className: 'type',
19869
20106
  variants: [
19870
20107
  { begin: '\\b[a-z\\d_]*_t\\b' },
19871
- { match: /\batomic_[a-z]{3,6}\b/ }
20108
+ { match: ATOMIC_TYPES }
19872
20109
  ]
19873
20110
 
19874
20111
  };
@@ -19890,9 +20127,13 @@ function requireC () {
19890
20127
  end: '\'',
19891
20128
  illegal: '.'
19892
20129
  },
20130
+ // https://en.cppreference.com/w/cpp/language/string_literal
20131
+ // a d-char-sequence never contains parentheses, backslashes or whitespace;
20132
+ // quotes are excluded as well so the closing delimiter cannot swallow the
20133
+ // quote that actually terminates the literal
19893
20134
  hljs.END_SAME_AS_BEGIN({
19894
- begin: /(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,
19895
- end: /\)([^()\\ ]{0,16})"/
20135
+ begin: /(?:u8?|U|L)?R"([^()\\\s"]{0,16})\(/,
20136
+ end: /\)([^()\\\s"]{0,16})"/
19896
20137
  })
19897
20138
  ]
19898
20139
  };
@@ -19908,6 +20149,32 @@ function requireC () {
19908
20149
  relevance: 0
19909
20150
  };
19910
20151
 
20152
+ // `#include` is the only preprocessor directive that takes an angle-bracket
20153
+ // quoted header (`#include <header>`). Scoping that rule to `#include` keeps
20154
+ // the greedy `<...>` match from eating a `>` that belongs to the body of
20155
+ // another directive (e.g. `#define what do { cout << ">"; } while (0)`),
20156
+ // which would otherwise leave an unbalanced `"` and break highlighting for
20157
+ // the rest of the file. See issue #3505.
20158
+ const PREPROCESSOR_INCLUDE = {
20159
+ scope: 'meta',
20160
+ begin: /#\s*include\b/,
20161
+ end: /$/,
20162
+ keywords: { keyword: 'include' },
20163
+ contains: [
20164
+ {
20165
+ // the `\` at the end of a line signaling continuation
20166
+ begin: /\\\n/,
20167
+ },
20168
+ STRINGS,
20169
+ {
20170
+ scope: 'string',
20171
+ begin: /<.*?>/
20172
+ },
20173
+ C_LINE_COMMENT_MODE,
20174
+ hljs.C_BLOCK_COMMENT_MODE
20175
+ ]
20176
+ };
20177
+
19911
20178
  const PREPROCESSOR = {
19912
20179
  className: 'meta',
19913
20180
  begin: /#\s*[a-z]+\b/,
@@ -19921,15 +20188,16 @@ function requireC () {
19921
20188
  relevance: 0
19922
20189
  },
19923
20190
  hljs.inherit(STRINGS, { className: 'string' }),
19924
- {
19925
- className: 'string',
19926
- begin: /<.*?>/
19927
- },
19928
20191
  C_LINE_COMMENT_MODE,
19929
20192
  hljs.C_BLOCK_COMMENT_MODE
19930
20193
  ]
19931
20194
  };
19932
20195
 
20196
+ const PREPROCESSORS = [
20197
+ PREPROCESSOR_INCLUDE,
20198
+ PREPROCESSOR
20199
+ ];
20200
+
19933
20201
  const TITLE_MODE = {
19934
20202
  className: 'title',
19935
20203
  begin: regex.optional(NAMESPACE_RE) + hljs.IDENT_RE,
@@ -19937,6 +20205,11 @@ function requireC () {
19937
20205
  };
19938
20206
 
19939
20207
  const FUNCTION_TITLE = regex.optional(NAMESPACE_RE) + hljs.IDENT_RE + '\\s*\\(';
20208
+ // Bounded on purpose: an unbounded quantifier here consumes an arbitrarily
20209
+ // long run of words, and when no function title follows it the engine retries
20210
+ // the title at every token boundary of that run - quadratic in the size of
20211
+ // the document. See #4362.
20212
+ const MAX_FUNCTION_TYPE_TOKENS = 12;
19940
20213
 
19941
20214
  const C_KEYWORDS = [
19942
20215
  "asm",
@@ -20037,7 +20310,7 @@ function requireC () {
20037
20310
  };
20038
20311
 
20039
20312
  const EXPRESSION_CONTAINS = [
20040
- PREPROCESSOR,
20313
+ ...PREPROCESSORS,
20041
20314
  TYPES,
20042
20315
  C_LINE_COMMENT_MODE,
20043
20316
  hljs.C_BLOCK_COMMENT_MODE,
@@ -20077,7 +20350,7 @@ function requireC () {
20077
20350
  };
20078
20351
 
20079
20352
  const FUNCTION_DECLARATION = {
20080
- begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE,
20353
+ begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+){1,' + MAX_FUNCTION_TYPE_TOKENS + '}' + FUNCTION_TITLE,
20081
20354
  returnBegin: true,
20082
20355
  end: /[{;=]/,
20083
20356
  excludeEnd: true,
@@ -20133,7 +20406,7 @@ function requireC () {
20133
20406
  TYPES,
20134
20407
  C_LINE_COMMENT_MODE,
20135
20408
  hljs.C_BLOCK_COMMENT_MODE,
20136
- PREPROCESSOR
20409
+ ...PREPROCESSORS
20137
20410
  ]
20138
20411
  };
20139
20412
 
@@ -20150,7 +20423,7 @@ function requireC () {
20150
20423
  FUNCTION_DECLARATION,
20151
20424
  EXPRESSION_CONTAINS,
20152
20425
  [
20153
- PREPROCESSOR,
20426
+ ...PREPROCESSORS,
20154
20427
  {
20155
20428
  begin: hljs.IDENT_RE + '::',
20156
20429
  keywords: KEYWORDS
@@ -20227,9 +20500,13 @@ function requireCpp () {
20227
20500
  end: '\'',
20228
20501
  illegal: '.'
20229
20502
  },
20503
+ // https://en.cppreference.com/w/cpp/language/string_literal
20504
+ // a d-char-sequence never contains parentheses, backslashes or whitespace;
20505
+ // quotes are excluded as well so the closing delimiter cannot swallow the
20506
+ // quote that actually terminates the literal
20230
20507
  hljs.END_SAME_AS_BEGIN({
20231
- begin: /(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,
20232
- end: /\)([^()\\ ]{0,16})"/
20508
+ begin: /(?:u8?|U|L)?R"([^()\\\s"]{0,16})\(/,
20509
+ end: /\)([^()\\\s"]{0,16})"/
20233
20510
  })
20234
20511
  ]
20235
20512
  };
@@ -20242,12 +20519,12 @@ function requireCpp () {
20242
20519
  "[+-]?(?:" // Leading sign.
20243
20520
  // Decimal.
20244
20521
  + "(?:"
20245
- +"[0-9](?:'?[0-9])*\\.(?:[0-9](?:'?[0-9])*)?"
20522
+ + "\\b[0-9](?:'?[0-9])*\\.(?:[0-9](?:'?[0-9])*)?"
20246
20523
  + "|\\.[0-9](?:'?[0-9])*"
20247
20524
  + ")(?:[Ee][+-]?[0-9](?:'?[0-9])*)?"
20248
- + "|[0-9](?:'?[0-9])*[Ee][+-]?[0-9](?:'?[0-9])*"
20525
+ + "|\\b[0-9](?:'?[0-9])*[Ee][+-]?[0-9](?:'?[0-9])*"
20249
20526
  // Hexadecimal.
20250
- + "|0[Xx](?:"
20527
+ + "|\\b0[Xx](?:"
20251
20528
  +"[0-9A-Fa-f](?:'?[0-9A-Fa-f])*(?:\\.(?:[0-9A-Fa-f](?:'?[0-9A-Fa-f])*)?)?"
20252
20529
  + "|\\.[0-9A-Fa-f](?:'?[0-9A-Fa-f])*"
20253
20530
  + ")[Pp][+-]?[0-9](?:'?[0-9])*"
@@ -20279,6 +20556,32 @@ function requireCpp () {
20279
20556
  relevance: 0
20280
20557
  };
20281
20558
 
20559
+ // `#include` is the only preprocessor directive that takes an angle-bracket
20560
+ // quoted header (`#include <header>`). Scoping that rule to `#include` keeps
20561
+ // the greedy `<...>` match from eating a `>` that belongs to the body of
20562
+ // another directive (e.g. `#define what do { cout << ">"; } while (0)`),
20563
+ // which would otherwise leave an unbalanced `"` and break highlighting for
20564
+ // the rest of the file. See issue #3505.
20565
+ const PREPROCESSOR_INCLUDE = {
20566
+ scope: 'meta',
20567
+ begin: /#\s*include\b/,
20568
+ end: /$/,
20569
+ keywords: { keyword: 'include' },
20570
+ contains: [
20571
+ {
20572
+ // the `\` at the end of a line signaling continuation
20573
+ begin: /\\\n/,
20574
+ },
20575
+ STRINGS,
20576
+ {
20577
+ scope: 'string',
20578
+ begin: /<.*?>/
20579
+ },
20580
+ C_LINE_COMMENT_MODE,
20581
+ hljs.C_BLOCK_COMMENT_MODE
20582
+ ]
20583
+ };
20584
+
20282
20585
  const PREPROCESSOR = {
20283
20586
  className: 'meta',
20284
20587
  begin: /#\s*[a-z]+\b/,
@@ -20292,15 +20595,16 @@ function requireCpp () {
20292
20595
  relevance: 0
20293
20596
  },
20294
20597
  hljs.inherit(STRINGS, { className: 'string' }),
20295
- {
20296
- className: 'string',
20297
- begin: /<.*?>/
20298
- },
20299
20598
  C_LINE_COMMENT_MODE,
20300
20599
  hljs.C_BLOCK_COMMENT_MODE
20301
20600
  ]
20302
20601
  };
20303
20602
 
20603
+ const PREPROCESSORS = [
20604
+ PREPROCESSOR_INCLUDE,
20605
+ PREPROCESSOR
20606
+ ];
20607
+
20304
20608
  const TITLE_MODE = {
20305
20609
  className: 'title',
20306
20610
  begin: regex.optional(NAMESPACE_RE) + hljs.IDENT_RE,
@@ -20308,6 +20612,11 @@ function requireCpp () {
20308
20612
  };
20309
20613
 
20310
20614
  const FUNCTION_TITLE = regex.optional(NAMESPACE_RE) + hljs.IDENT_RE + '\\s*\\(';
20615
+ // Bounded on purpose: an unbounded quantifier here consumes an arbitrarily
20616
+ // long run of words, and when no function title follows it the engine retries
20617
+ // the title at every token boundary of that run - quadratic in the size of
20618
+ // the document. See #4362.
20619
+ const MAX_FUNCTION_TYPE_TOKENS = 12;
20311
20620
 
20312
20621
  // https://en.cppreference.com/w/cpp/keyword
20313
20622
  const RESERVED_KEYWORDS = [
@@ -20610,18 +20919,14 @@ function requireCpp () {
20610
20919
  _hint: FUNCTION_HINTS },
20611
20920
  begin: regex.concat(
20612
20921
  /\b/,
20613
- /(?!decltype)/,
20614
- /(?!if)/,
20615
- /(?!for)/,
20616
- /(?!switch)/,
20617
- /(?!while)/,
20922
+ `(?!${RESERVED_KEYWORDS.join('|')})`,
20618
20923
  hljs.IDENT_RE,
20619
20924
  regex.lookahead(/(<[^<>]+>|)\s*\(/))
20620
20925
  };
20621
20926
 
20622
20927
  const EXPRESSION_CONTAINS = [
20623
20928
  FUNCTION_DISPATCH,
20624
- PREPROCESSOR,
20929
+ ...PREPROCESSORS,
20625
20930
  CPP_PRIMITIVE_TYPES,
20626
20931
  C_LINE_COMMENT_MODE,
20627
20932
  hljs.C_BLOCK_COMMENT_MODE,
@@ -20662,7 +20967,7 @@ function requireCpp () {
20662
20967
 
20663
20968
  const FUNCTION_DECLARATION = {
20664
20969
  className: 'function',
20665
- begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+)+' + FUNCTION_TITLE,
20970
+ begin: '(' + FUNCTION_TYPE_RE + '[\\*&\\s]+){1,' + MAX_FUNCTION_TYPE_TOKENS + '}' + FUNCTION_TITLE,
20666
20971
  returnBegin: true,
20667
20972
  end: /[{;=]/,
20668
20973
  excludeEnd: true,
@@ -20733,7 +21038,7 @@ function requireCpp () {
20733
21038
  CPP_PRIMITIVE_TYPES,
20734
21039
  C_LINE_COMMENT_MODE,
20735
21040
  hljs.C_BLOCK_COMMENT_MODE,
20736
- PREPROCESSOR
21041
+ ...PREPROCESSORS
20737
21042
  ]
20738
21043
  };
20739
21044
 
@@ -20757,7 +21062,7 @@ function requireCpp () {
20757
21062
  FUNCTION_DISPATCH,
20758
21063
  EXPRESSION_CONTAINS,
20759
21064
  [
20760
- PREPROCESSOR,
21065
+ ...PREPROCESSORS,
20761
21066
  { // containers: ie, `vector <int> rooms (9);`
20762
21067
  begin: '\\b(deque|list|queue|priority_queue|pair|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array|tuple|optional|variant|function|flat_map|flat_set)\\s*<(?!<)',
20763
21068
  end: '>',
@@ -20960,12 +21265,18 @@ function requireCsharp () {
20960
21265
  literal: LITERAL_KEYWORDS
20961
21266
  };
20962
21267
  const TITLE_MODE = hljs.inherit(hljs.TITLE_MODE, { begin: '[a-zA-Z](\\.?\\w)*' });
21268
+ // https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types
21269
+ // https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types
21270
+ // `_` separators sit between digits, and may also follow the `0x`/`0b` prefix
21271
+ const DIGITS = '\\d(_*\\d)*';
21272
+ const INTEGER_SUFFIX = '([uU][lL]?|[lL][uU]?)?';
21273
+ const REAL_SUFFIX = '([fFdDmM]|[uU][lL]?|[lL][uU]?)?';
20963
21274
  const NUMBERS = {
20964
21275
  className: 'number',
20965
21276
  variants: [
20966
- { begin: '\\b(0b[01\']+)' },
20967
- { begin: '(-?)\\b([\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)(u|U|l|L|ul|UL|f|F|b|B)' },
20968
- { begin: '(-?)(\\b0[xX][a-fA-F0-9\']+|(\\b[\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)([eE][-+]?[\\d\']+)?)' }
21277
+ { begin: '\\b0[bB]_*[01](_*[01])*' + INTEGER_SUFFIX },
21278
+ { begin: '(-?)\\b0[xX]_*[a-fA-F0-9](_*[a-fA-F0-9])*' + INTEGER_SUFFIX },
21279
+ { begin: '(-?)(\\b' + DIGITS + '(\\.(' + DIGITS + ')?)?|\\.' + DIGITS + ')([eE][-+]?' + DIGITS + ')?' + REAL_SUFFIX }
20969
21280
  ],
20970
21281
  relevance: 0
20971
21282
  };
@@ -21229,6 +21540,10 @@ function requireCss () {
21229
21540
  scope: 'number',
21230
21541
  begin: /#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/
21231
21542
  },
21543
+ UNICODE_RANGE: {
21544
+ scope: 'number',
21545
+ begin: /\b[Uu]\+[0-9A-Fa-f][0-9A-Fa-f?]{0,5}(-[0-9A-Fa-f][0-9A-Fa-f]{0,5})?/
21546
+ },
21232
21547
  FUNCTION_DISPATCH: {
21233
21548
  className: "built_in",
21234
21549
  begin: /[\w-]+(?=\()/
@@ -21662,6 +21977,11 @@ function requireCss () {
21662
21977
  'container-type',
21663
21978
  'content',
21664
21979
  'content-visibility',
21980
+ 'corner-bottom-left-shape',
21981
+ 'corner-bottom-right-shape',
21982
+ 'corner-shape',
21983
+ 'corner-top-left-shape',
21984
+ 'corner-top-right-shape',
21665
21985
  'counter-increment',
21666
21986
  'counter-reset',
21667
21987
  'counter-set',
@@ -21997,6 +22317,7 @@ function requireCss () {
21997
22317
  'transition-timing-function',
21998
22318
  'translate',
21999
22319
  'unicode-bidi',
22320
+ 'unicode-range',
22000
22321
  'user-modify',
22001
22322
  'user-select',
22002
22323
  'vector-effect',
@@ -22103,9 +22424,10 @@ function requireCss () {
22103
22424
  modes.HEXCOLOR,
22104
22425
  modes.IMPORTANT,
22105
22426
  modes.CSS_NUMBER_MODE,
22427
+ modes.UNICODE_RANGE,
22106
22428
  ...STRINGS,
22107
22429
  // needed to highlight these as strings and to avoid issues with
22108
- // illegal characters that might be inside urls that would tigger the
22430
+ // illegal characters that might be inside urls that would trigger the
22109
22431
  // languages illegal stack
22110
22432
  {
22111
22433
  begin: /(url|data-uri)\(/,
@@ -22192,10 +22514,10 @@ function requireMarkdown () {
22192
22514
  subLanguage: 'xml',
22193
22515
  relevance: 0
22194
22516
  };
22195
- const HORIZONTAL_RULE = {
22196
- begin: '^[-\\*]{3,}',
22197
- end: '$'
22198
- };
22517
+ // https://spec.commonmark.org/0.31.2/#thematic-breaks
22518
+ // three or more `-`, `*` or `_`, all the same character, optionally
22519
+ // separated and followed by spaces or tabs, and nothing else on the line
22520
+ const HORIZONTAL_RULE = { match: /^ {0,3}([-*_])[ \t]*(?:\1[ \t]*){2,}$/ };
22199
22521
  const CODE = {
22200
22522
  className: 'code',
22201
22523
  variants: [
@@ -22411,11 +22733,13 @@ function requireMarkdown () {
22411
22733
  HEADER,
22412
22734
  INLINE_HTML,
22413
22735
  LIST,
22736
+ // must come before BOLD/ITALIC so that a `***` or `___` thematic break
22737
+ // isn't mistaken for the start of bold text
22738
+ HORIZONTAL_RULE,
22414
22739
  BOLD,
22415
22740
  ITALIC,
22416
22741
  BLOCKQUOTE,
22417
22742
  CODE,
22418
- HORIZONTAL_RULE,
22419
22743
  LINK,
22420
22744
  LINK_REFERENCE,
22421
22745
  ENTITY
@@ -22452,7 +22776,10 @@ function requireDiff () {
22452
22776
  className: 'meta',
22453
22777
  relevance: 10,
22454
22778
  match: regex.either(
22455
- /^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,
22779
+ /^@@ +-\d+,\d+ +\+\d+,\d+ +@@/, // @@ -1,2 +1,2 @@
22780
+ /^@@ +-\d+ +\+\d+,\d+ +@@/, // @@ -1 +1,2 @@
22781
+ /^@@ +-\d+,\d+ +\+\d+ +@@/, // @@ -1,2 +1 @@
22782
+ /^@@ +-\d+ +\+\d+ +@@/, // @@ -1 +1 @@
22456
22783
  /^\*\*\* +\d+,\d+ +\*\*\*\*$/,
22457
22784
  /^--- +\d+,\d+ +----$/
22458
22785
  )
@@ -22831,8 +23158,9 @@ function requireRuby () {
22831
23158
  CLASS_REFERENCE,
22832
23159
  METHOD_DEFINITION,
22833
23160
  {
22834
- // swallow namespace qualifiers before symbols
22835
- begin: hljs.IDENT_RE + '::' },
23161
+ // swallow the scope resolution operator so `::` is not read as a symbol
23162
+ begin: '::'
23163
+ },
22836
23164
  {
22837
23165
  className: 'symbol',
22838
23166
  begin: hljs.UNDERSCORE_IDENT_RE + '(!|\\?)?:',
@@ -23083,6 +23411,10 @@ function requireGo () {
23083
23411
  match: /-?\b0[oO](_?[0-7])*i?/, // leading 0o octal
23084
23412
  relevance: 0
23085
23413
  },
23414
+ {
23415
+ match: /-?\b0[bB](_?[01])*i?/, // leading 0b binary
23416
+ relevance: 0
23417
+ },
23086
23418
  {
23087
23419
  match: /-?\.\d(_?\d)*([eE][+-]?\d(_?\d)*)?i?/, // decimal without a present digit before . (making a digit afterwards required)
23088
23420
  relevance: 0
@@ -23408,9 +23740,27 @@ function requireJava () {
23408
23740
  /** @type LanguageFn */
23409
23741
  function java(hljs) {
23410
23742
  const regex = hljs.regex;
23743
+
23744
+ // A Java identifier consisting of letters, digits, underscore or dollar sign, not beginning with a digit
23411
23745
  const JAVA_IDENT_RE = '[\u00C0-\u02B8a-zA-Z_$][\u00C0-\u02B8a-zA-Z_$0-9]*';
23412
- const GENERIC_IDENT_RE = JAVA_IDENT_RE
23413
- + recurRegex('(?:<' + JAVA_IDENT_RE + '~~~(?:\\s*,\\s*' + JAVA_IDENT_RE + '~~~)*>)?', /~~~/g, 2);
23746
+
23747
+ // Optional 1..n pairs of square brackets identifying an array type
23748
+ const ARRAY_BRACKETS_OPTIONAL_RE = '(?:(?:\\s*\\[\\s*])+)?';
23749
+
23750
+ // A simple Java type: a type name, optionally followed by type arguments and/or array brackets
23751
+ // '<@@@>' is replaced with the pattern for optional type arguments by recurRegex below.
23752
+ const SIMPLE_TYPE_RE = JAVA_IDENT_RE + '<@@@>' + ARRAY_BRACKETS_OPTIONAL_RE;
23753
+
23754
+ // A bounded (? extends Number) or unbounded (?) wildcard type
23755
+ const WILDCARD_TYPE_RE = '\\?(?:\\s+(?:extends|super)\\s+' + SIMPLE_TYPE_RE + ')?';
23756
+
23757
+ // A Java type argument, consisting of a wildcard or simple type
23758
+ const TYPE_ARG_RE = '(?:' + WILDCARD_TYPE_RE + '|' + SIMPLE_TYPE_RE + ')';
23759
+
23760
+ // Pattern for optional generic type arguments in angle brackets with up to 2 levels of nested type arguments
23761
+ const TYPE_ARGS_OPTIONAL_RE = recurRegex('(?:\\s*<\\s*' + TYPE_ARG_RE + '(?:\\s*,\\s*' + TYPE_ARG_RE + ')*\\s*>)?',
23762
+ /<@@@>/g, 2);
23763
+
23414
23764
  const MAIN_KEYWORDS = [
23415
23765
  'synchronized',
23416
23766
  'abstract',
@@ -23564,18 +23914,25 @@ function requireJava () {
23564
23914
  match: /non-sealed/,
23565
23915
  scope: "keyword"
23566
23916
  },
23917
+ {
23918
+ // Expression keywords prevent keyword-led expressions from being
23919
+ // recognized as variable or method declarations.
23920
+ beginKeywords: 'new throw return else yield assert',
23921
+ relevance: 0
23922
+ },
23567
23923
  {
23568
23924
  begin: [
23569
- regex.concat(/(?!else)/, JAVA_IDENT_RE),
23570
- /\s+/,
23571
23925
  JAVA_IDENT_RE,
23572
- /\s+/,
23926
+ regex.concat(TYPE_ARGS_OPTIONAL_RE, ARRAY_BRACKETS_OPTIONAL_RE, /\s+/),
23927
+ JAVA_IDENT_RE,
23928
+ ARRAY_BRACKETS_OPTIONAL_RE,
23929
+ /\s*/,
23573
23930
  /=(?!=)/
23574
23931
  ],
23575
23932
  className: {
23576
23933
  1: "type",
23577
23934
  3: "variable",
23578
- 5: "operator"
23935
+ 6: "operator"
23579
23936
  }
23580
23937
  },
23581
23938
  {
@@ -23594,19 +23951,17 @@ function requireJava () {
23594
23951
  hljs.C_BLOCK_COMMENT_MODE
23595
23952
  ]
23596
23953
  },
23597
- {
23598
- // Expression keywords prevent 'keyword Name(...)' from being
23599
- // recognized as a function definition
23600
- beginKeywords: 'new throw return else',
23601
- relevance: 0
23602
- },
23603
23954
  {
23604
23955
  begin: [
23605
- '(?:' + GENERIC_IDENT_RE + '\\s+)',
23606
- hljs.UNDERSCORE_IDENT_RE,
23956
+ JAVA_IDENT_RE,
23957
+ regex.concat(TYPE_ARGS_OPTIONAL_RE, ARRAY_BRACKETS_OPTIONAL_RE, /\s+/),
23958
+ JAVA_IDENT_RE,
23607
23959
  /\s*(?=\()/
23608
23960
  ],
23609
- className: { 2: "title.function" },
23961
+ className: {
23962
+ 1: "type",
23963
+ 3: "title.function"
23964
+ },
23610
23965
  keywords: KEYWORDS,
23611
23966
  contains: [
23612
23967
  {
@@ -23644,6 +23999,7 @@ function requireJavascript () {
23644
23999
  if (hasRequiredJavascript) return javascript_1;
23645
24000
  hasRequiredJavascript = 1;
23646
24001
  const IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
24002
+
23647
24003
  const KEYWORDS = [
23648
24004
  "as", // for exports
23649
24005
  "in",
@@ -23794,6 +24150,7 @@ function requireJavascript () {
23794
24150
  "localStorage",
23795
24151
  "sessionStorage",
23796
24152
  "module",
24153
+ "self",
23797
24154
  "global" // Node.js
23798
24155
  ];
23799
24156
 
@@ -24191,7 +24548,8 @@ function requireJavascript () {
24191
24548
  noneOf([
24192
24549
  ...BUILT_IN_GLOBALS,
24193
24550
  "super",
24194
- "import"
24551
+ "import",
24552
+ "await",
24195
24553
  ].map(x => `${x}\\s*\\(`)),
24196
24554
  IDENT_RE$1, regex.lookahead(/\s*\(/)),
24197
24555
  className: "title.function",
@@ -24260,7 +24618,7 @@ function requireJavascript () {
24260
24618
  keywords: KEYWORDS$1,
24261
24619
  // this will be extended by TypeScript
24262
24620
  exports: { PARAMS_CONTAINS, CLASS_REFERENCE },
24263
- illegal: /#(?![$_A-z])/,
24621
+ illegal: /#(?![$_A-Za-z])/,
24264
24622
  contains: [
24265
24623
  hljs.SHEBANG({
24266
24624
  label: "shebang",
@@ -24415,24 +24773,32 @@ function requireJavascript () {
24415
24773
  return javascript_1;
24416
24774
  }
24417
24775
 
24418
- /*
24419
- Language: JSON
24420
- Description: JSON (JavaScript Object Notation) is a lightweight data-interchange format.
24421
- Author: Ivan Sagalaev <maniac@softwaremaniacs.org>
24422
- Website: http://www.json.org
24423
- Category: common, protocols, web
24424
- */
24425
-
24426
24776
  var json_1;
24427
24777
  var hasRequiredJson;
24428
24778
 
24429
24779
  function requireJson () {
24430
24780
  if (hasRequiredJson) return json_1;
24431
24781
  hasRequiredJson = 1;
24782
+ const EXTENDED_NUMBER_RE = '([-+]?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)|NaN|[-+]?Infinity'; // 0x..., 0..., decimal, float
24783
+
24784
+ const EXTENDED_NUMBER_MODE = {
24785
+ scope: 'number',
24786
+ match: EXTENDED_NUMBER_RE,
24787
+ relevance: 0
24788
+ };
24789
+
24790
+ /*
24791
+ Language: JSON
24792
+ Description: JSON (JavaScript Object Notation) is a lightweight data-interchange format.
24793
+ Websites: http://www.json.org, https://www.json5.org
24794
+ Category: common, protocols, web
24795
+ */
24796
+
24797
+
24432
24798
  function json(hljs) {
24433
24799
  const ATTRIBUTE = {
24434
24800
  className: 'attr',
24435
- begin: /"(\\.|[^\\"\r\n])*"(?=\s*:)/,
24801
+ begin: /(("(\\.|[^\\"\r\n])*")|('(\\.|[^\\'\r\n])*'))(?=\s*:)/,
24436
24802
  relevance: 1.01
24437
24803
  };
24438
24804
  const PUNCTUATION = {
@@ -24457,16 +24823,17 @@ function requireJson () {
24457
24823
 
24458
24824
  return {
24459
24825
  name: 'JSON',
24460
- aliases: ['jsonc'],
24826
+ aliases: ['jsonc', 'json5'],
24461
24827
  keywords:{
24462
24828
  literal: LITERALS,
24463
24829
  },
24464
24830
  contains: [
24465
24831
  ATTRIBUTE,
24466
24832
  PUNCTUATION,
24833
+ hljs.APOS_STRING_MODE,
24467
24834
  hljs.QUOTE_STRING_MODE,
24468
24835
  LITERALS_MODE,
24469
- hljs.C_NUMBER_MODE,
24836
+ EXTENDED_NUMBER_MODE,
24470
24837
  hljs.C_LINE_COMMENT_MODE,
24471
24838
  hljs.C_BLOCK_COMMENT_MODE
24472
24839
  ],
@@ -24647,7 +25014,9 @@ function requireKotlin () {
24647
25014
  name: 'Kotlin',
24648
25015
  aliases: [
24649
25016
  'kt',
24650
- 'kts'
25017
+ 'kts',
25018
+ 'ktm',
25019
+ 'ktx'
24651
25020
  ],
24652
25021
  keywords: KEYWORDS,
24653
25022
  contains: [
@@ -24790,6 +25159,10 @@ function requireLess () {
24790
25159
  scope: 'number',
24791
25160
  begin: /#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/
24792
25161
  },
25162
+ UNICODE_RANGE: {
25163
+ scope: 'number',
25164
+ begin: /\b[Uu]\+[0-9A-Fa-f][0-9A-Fa-f?]{0,5}(-[0-9A-Fa-f][0-9A-Fa-f]{0,5})?/
25165
+ },
24793
25166
  FUNCTION_DISPATCH: {
24794
25167
  className: "built_in",
24795
25168
  begin: /[\w-]+(?=\()/
@@ -25223,6 +25596,11 @@ function requireLess () {
25223
25596
  'container-type',
25224
25597
  'content',
25225
25598
  'content-visibility',
25599
+ 'corner-bottom-left-shape',
25600
+ 'corner-bottom-right-shape',
25601
+ 'corner-shape',
25602
+ 'corner-top-left-shape',
25603
+ 'corner-top-right-shape',
25226
25604
  'counter-increment',
25227
25605
  'counter-reset',
25228
25606
  'counter-set',
@@ -25558,6 +25936,7 @@ function requireLess () {
25558
25936
  'transition-timing-function',
25559
25937
  'translate',
25560
25938
  'unicode-bidi',
25939
+ 'unicode-range',
25561
25940
  'user-modify',
25562
25941
  'user-select',
25563
25942
  'vector-effect',
@@ -25662,6 +26041,7 @@ function requireLess () {
25662
26041
  excludeEnd: true
25663
26042
  }
25664
26043
  },
26044
+ modes.UNICODE_RANGE,
25665
26045
  modes.HEXCOLOR,
25666
26046
  PARENS_MODE,
25667
26047
  IDENT_MODE('variable', '@@?' + IDENT_RE, 10),
@@ -25772,7 +26152,7 @@ function requireLess () {
25772
26152
  MIXIN_GUARD_MODE,
25773
26153
  IDENT_MODE('keyword', 'all\\b'),
25774
26154
  IDENT_MODE('variable', '@\\{' + IDENT_RE + '\\}'), // otherwise it’s identified as tag
25775
-
26155
+
25776
26156
  {
25777
26157
  begin: '\\b(' + TAGS.join('|') + ')\\b',
25778
26158
  className: 'selector-tag'
@@ -25871,7 +26251,7 @@ function requireLua () {
25871
26251
  keywords: {
25872
26252
  $pattern: hljs.UNDERSCORE_IDENT_RE,
25873
26253
  literal: "true false nil",
25874
- keyword: "and break do else elseif end for goto if in local not or repeat return then until while",
26254
+ keyword: "and break do else elseif end for goto if in local global not or repeat return then until while",
25875
26255
  built_in:
25876
26256
  // Metatags and globals:
25877
26257
  '_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len '
@@ -26800,6 +27180,10 @@ Language: PHP
26800
27180
  Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
26801
27181
  Contributors: Evgeny Stepanischev <imbolk@gmail.com>, Ivan Sagalaev <maniac@softwaremaniacs.org>
26802
27182
  Website: https://www.php.net
27183
+ Description: Use this for plain PHP code, i.e. code that does not include the
27184
+ surrounding `<?php ... ?>` tags. If your snippet mixes PHP with
27185
+ HTML markup and the opening/closing tags, use `php-template`
27186
+ instead.
26803
27187
  Category: common
26804
27188
  */
26805
27189
 
@@ -27217,6 +27601,8 @@ function requirePhp () {
27217
27601
  VARIABLE,
27218
27602
  LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON,
27219
27603
  hljs.C_BLOCK_COMMENT_MODE,
27604
+ hljs.C_LINE_COMMENT_MODE,
27605
+ hljs.HASH_COMMENT_MODE,
27220
27606
  STRING,
27221
27607
  NUMBER,
27222
27608
  CONSTRUCTOR_CALL,
@@ -27241,6 +27627,8 @@ function requirePhp () {
27241
27627
  NAMED_ARGUMENT,
27242
27628
  LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON,
27243
27629
  hljs.C_BLOCK_COMMENT_MODE,
27630
+ hljs.C_LINE_COMMENT_MODE,
27631
+ hljs.HASH_COMMENT_MODE,
27244
27632
  STRING,
27245
27633
  NUMBER,
27246
27634
  CONSTRUCTOR_CALL,
@@ -27369,6 +27757,8 @@ function requirePhp () {
27369
27757
  VARIABLE,
27370
27758
  LEFT_AND_RIGHT_SIDE_OF_DOUBLE_COLON,
27371
27759
  hljs.C_BLOCK_COMMENT_MODE,
27760
+ hljs.C_LINE_COMMENT_MODE,
27761
+ hljs.HASH_COMMENT_MODE,
27372
27762
  STRING,
27373
27763
  NUMBER
27374
27764
  ]
@@ -27434,6 +27824,9 @@ Language: PHP Template
27434
27824
  Requires: xml.js, php.js
27435
27825
  Author: Josh Goebel <hello@joshgoebel.com>
27436
27826
  Website: https://www.php.net
27827
+ Description: Use this for HTML (or other markup) with embedded PHP, i.e. code
27828
+ that includes the `<?php ... ?>` (or `<?= ... ?>`) tags. For
27829
+ plain PHP code without the surrounding tags, use `php` instead.
27437
27830
  Category: common
27438
27831
  */
27439
27832
 
@@ -27560,6 +27953,7 @@ function requirePython () {
27560
27953
  'in',
27561
27954
  'is',
27562
27955
  'lambda',
27956
+ 'lazy',
27563
27957
  'match',
27564
27958
  'nonlocal|10',
27565
27959
  'not',
@@ -27576,7 +27970,9 @@ function requirePython () {
27576
27970
  const BUILT_INS = [
27577
27971
  '__import__',
27578
27972
  'abs',
27973
+ 'aiter',
27579
27974
  'all',
27975
+ 'anext',
27580
27976
  'any',
27581
27977
  'ascii',
27582
27978
  'bin',
@@ -27599,6 +27995,7 @@ function requirePython () {
27599
27995
  'filter',
27600
27996
  'float',
27601
27997
  'format',
27998
+ 'frozendict',
27602
27999
  'frozenset',
27603
28000
  'getattr',
27604
28001
  'globals',
@@ -27631,6 +28028,7 @@ function requirePython () {
27631
28028
  'repr',
27632
28029
  'reversed',
27633
28030
  'round',
28031
+ 'sentinel',
27634
28032
  'set',
27635
28033
  'setattr',
27636
28034
  'slice',
@@ -27722,7 +28120,7 @@ function requirePython () {
27722
28120
  relevance: 10
27723
28121
  },
27724
28122
  {
27725
- begin: /([fF][rR]|[rR][fF]|[fF])'''/,
28123
+ begin: /([fFtT][rR]|[rR][fFtT]|[fFtT])'''/,
27726
28124
  end: /'''/,
27727
28125
  contains: [
27728
28126
  hljs.BACKSLASH_ESCAPE,
@@ -27732,7 +28130,7 @@ function requirePython () {
27732
28130
  ]
27733
28131
  },
27734
28132
  {
27735
- begin: /([fF][rR]|[rR][fF]|[fF])"""/,
28133
+ begin: /([fFtT][rR]|[rR][fFtT]|[fFtT])"""/,
27736
28134
  end: /"""/,
27737
28135
  contains: [
27738
28136
  hljs.BACKSLASH_ESCAPE,
@@ -27760,7 +28158,7 @@ function requirePython () {
27760
28158
  end: /"/
27761
28159
  },
27762
28160
  {
27763
- begin: /([fF][rR]|[rR][fF]|[fF])'/,
28161
+ begin: /([fFtT][rR]|[rR][fFtT]|[fFtT])'/,
27764
28162
  end: /'/,
27765
28163
  contains: [
27766
28164
  hljs.BACKSLASH_ESCAPE,
@@ -27769,7 +28167,7 @@ function requirePython () {
27769
28167
  ]
27770
28168
  },
27771
28169
  {
27772
- begin: /([fF][rR]|[rR][fF]|[fF])"/,
28170
+ begin: /([fFtT][rR]|[rR][fFtT]|[fFtT])"/,
27773
28171
  end: /"/,
27774
28172
  contains: [
27775
28173
  hljs.BACKSLASH_ESCAPE,
@@ -28297,15 +28695,15 @@ function requireRust () {
28297
28695
  const IDENT_RE = regex.concat(RAW_IDENTIFIER, hljs.IDENT_RE);
28298
28696
  // ============================================
28299
28697
  const FUNCTION_INVOKE = {
28300
- className: "title.function.invoke",
28698
+ scope: "title.function.invoke",
28301
28699
  relevance: 0,
28302
28700
  begin: regex.concat(
28303
28701
  /\b/,
28304
- /(?!let|for|while|if|else|match\b)/,
28702
+ /(?!(?:let|for|while|if|else|match)\b)/,
28305
28703
  IDENT_RE,
28306
28704
  regex.lookahead(/\s*\(/))
28307
28705
  };
28308
- const NUMBER_SUFFIX = '([ui](8|16|32|64|128|size)|f(32|64))\?';
28706
+ const NUMBER_SUFFIX = '([ui](8|16|32|64|128|size)|f(16|32|64|128))\?';
28309
28707
  const KEYWORDS = [
28310
28708
  "abstract",
28311
28709
  "as",
@@ -28339,6 +28737,7 @@ function requireRust () {
28339
28737
  "override",
28340
28738
  "priv",
28341
28739
  "pub",
28740
+ "raw",
28342
28741
  "ref",
28343
28742
  "return",
28344
28743
  "self",
@@ -28449,8 +28848,10 @@ function requireRust () {
28449
28848
  "u64",
28450
28849
  "u128",
28451
28850
  "usize",
28851
+ "f16",
28452
28852
  "f32",
28453
28853
  "f64",
28854
+ "f128",
28454
28855
  "str",
28455
28856
  "char",
28456
28857
  "bool",
@@ -28479,7 +28880,7 @@ function requireRust () {
28479
28880
  illegal: null
28480
28881
  }),
28481
28882
  {
28482
- className: 'symbol',
28883
+ scope: 'symbol',
28483
28884
  // negative lookahead to avoid matching `'`
28484
28885
  begin: /'[a-zA-Z_][a-zA-Z0-9_]*(?!')/
28485
28886
  },
@@ -28493,14 +28894,14 @@ function requireRust () {
28493
28894
  contains: [
28494
28895
  {
28495
28896
  scope: "char.escape",
28496
- match: /\\('|\w|x\w{2}|u\w{4}|U\w{8})/
28897
+ match: /\\('|"|\\|\w|x\w{2}|u\w{4}|U\w{8})/
28497
28898
  }
28498
28899
  ]
28499
28900
  }
28500
28901
  ]
28501
28902
  },
28502
28903
  {
28503
- className: 'number',
28904
+ scope: 'number',
28504
28905
  variants: [
28505
28906
  { begin: '\\b0b([01_]+)' + NUMBER_SUFFIX },
28506
28907
  { begin: '\\b0o([0-7_]+)' + NUMBER_SUFFIX },
@@ -28510,24 +28911,35 @@ function requireRust () {
28510
28911
  ],
28511
28912
  relevance: 0
28512
28913
  },
28914
+ {
28915
+ begin: [
28916
+ /\bsafe/,
28917
+ /\s+/,
28918
+ /extern/,
28919
+ ],
28920
+ scope: {
28921
+ 1: "keyword",
28922
+ 3: "keyword",
28923
+ }
28924
+ },
28513
28925
  {
28514
28926
  begin: [
28515
28927
  /fn/,
28516
28928
  /\s+/,
28517
28929
  UNDERSCORE_IDENT_RE
28518
28930
  ],
28519
- className: {
28931
+ scope: {
28520
28932
  1: "keyword",
28521
28933
  3: "title.function"
28522
28934
  }
28523
28935
  },
28524
28936
  {
28525
- className: 'meta',
28937
+ scope: 'meta',
28526
28938
  begin: '#!?\\[',
28527
28939
  end: '\\]',
28528
28940
  contains: [
28529
28941
  {
28530
- className: 'string',
28942
+ scope: 'string',
28531
28943
  begin: /"/,
28532
28944
  end: /"/,
28533
28945
  contains: [
@@ -28543,7 +28955,7 @@ function requireRust () {
28543
28955
  /(?:mut\s+)?/,
28544
28956
  UNDERSCORE_IDENT_RE
28545
28957
  ],
28546
- className: {
28958
+ scope: {
28547
28959
  1: "keyword",
28548
28960
  3: "keyword",
28549
28961
  4: "variable"
@@ -28558,7 +28970,7 @@ function requireRust () {
28558
28970
  /\s+/,
28559
28971
  /in/
28560
28972
  ],
28561
- className: {
28973
+ scope: {
28562
28974
  1: "keyword",
28563
28975
  3: "variable",
28564
28976
  5: "keyword"
@@ -28570,7 +28982,7 @@ function requireRust () {
28570
28982
  /\s+/,
28571
28983
  UNDERSCORE_IDENT_RE
28572
28984
  ],
28573
- className: {
28985
+ scope: {
28574
28986
  1: "keyword",
28575
28987
  3: "title.class"
28576
28988
  }
@@ -28581,7 +28993,7 @@ function requireRust () {
28581
28993
  /\s+/,
28582
28994
  UNDERSCORE_IDENT_RE
28583
28995
  ],
28584
- className: {
28996
+ scope: {
28585
28997
  1: "keyword",
28586
28998
  3: "title.class"
28587
28999
  }
@@ -28595,7 +29007,7 @@ function requireRust () {
28595
29007
  }
28596
29008
  },
28597
29009
  {
28598
- className: "punctuation",
29010
+ scope: "punctuation",
28599
29011
  begin: '->'
28600
29012
  },
28601
29013
  FUNCTION_INVOKE
@@ -28624,6 +29036,10 @@ function requireScss () {
28624
29036
  scope: 'number',
28625
29037
  begin: /#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/
28626
29038
  },
29039
+ UNICODE_RANGE: {
29040
+ scope: 'number',
29041
+ begin: /\b[Uu]\+[0-9A-Fa-f][0-9A-Fa-f?]{0,5}(-[0-9A-Fa-f][0-9A-Fa-f]{0,5})?/
29042
+ },
28627
29043
  FUNCTION_DISPATCH: {
28628
29044
  className: "built_in",
28629
29045
  begin: /[\w-]+(?=\()/
@@ -29057,6 +29473,11 @@ function requireScss () {
29057
29473
  'container-type',
29058
29474
  'content',
29059
29475
  'content-visibility',
29476
+ 'corner-bottom-left-shape',
29477
+ 'corner-bottom-right-shape',
29478
+ 'corner-shape',
29479
+ 'corner-top-left-shape',
29480
+ 'corner-top-right-shape',
29060
29481
  'counter-increment',
29061
29482
  'counter-reset',
29062
29483
  'counter-set',
@@ -29392,6 +29813,7 @@ function requireScss () {
29392
29813
  'transition-timing-function',
29393
29814
  'translate',
29394
29815
  'unicode-bidi',
29816
+ 'unicode-range',
29395
29817
  'user-modify',
29396
29818
  'user-select',
29397
29819
  'vector-effect',
@@ -29505,6 +29927,7 @@ function requireScss () {
29505
29927
  VARIABLE,
29506
29928
  modes.HEXCOLOR,
29507
29929
  modes.CSS_NUMBER_MODE,
29930
+ modes.UNICODE_RANGE,
29508
29931
  hljs.QUOTE_STRING_MODE,
29509
29932
  hljs.APOS_STRING_MODE,
29510
29933
  modes.IMPORTANT,
@@ -29583,7 +30006,7 @@ function requireShell () {
29583
30006
  // We cannot add \s (spaces) in the regular expression otherwise it will be too broad and produce unexpected result.
29584
30007
  // For instance, in the following example, it would match "echo /path/to/home >" as a prompt:
29585
30008
  // echo /path/to/home > t.exe
29586
- begin: /^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,
30009
+ begin: /^\s{0,3}[./~\w\d[\]()@-]*[>%$#][ ]?/,
29587
30010
  starts: {
29588
30011
  end: /[^\\](?=\s*$)/,
29589
30012
  subLanguage: 'bash'
@@ -30371,6 +30794,18 @@ function requireSwift () {
30371
30794
  return joined;
30372
30795
  }
30373
30796
 
30797
+ // BACKREF_RE matches an open parenthesis or backreference. To avoid an
30798
+ // incorrect parse, it also matches the constructs where the meaning of
30799
+ // parentheses, escapes, or capture counting changes.
30800
+ new RegExp(either(
30801
+ /\[(?:[^\\\]]|\\.)*\]/, // a character class, inside which ( and \ lose their meaning
30802
+ /\(\?<(?![=!])[^>]+>/, // a named capture group `(?<name>` (not a lookbehind `(?<=` / `(?<!`)
30803
+ /\(\?'[^']+'/, // a named capture group `(?'name'`
30804
+ /\(\??/, // an opening parenthesis, capturing or non-capturing / lookahead
30805
+ /\\([1-9][0-9]*)/, // a backreference like `\1`
30806
+ /\\./ // any other escape sequence
30807
+ ));
30808
+
30374
30809
  const keywordWrapper = keyword => concat(
30375
30810
  /\b/,
30376
30811
  keyword,
@@ -31510,6 +31945,7 @@ function requireTypescript () {
31510
31945
  if (hasRequiredTypescript) return typescript_1;
31511
31946
  hasRequiredTypescript = 1;
31512
31947
  const IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
31948
+
31513
31949
  const KEYWORDS = [
31514
31950
  "as", // for exports
31515
31951
  "in",
@@ -31660,6 +32096,7 @@ function requireTypescript () {
31660
32096
  "localStorage",
31661
32097
  "sessionStorage",
31662
32098
  "module",
32099
+ "self",
31663
32100
  "global" // Node.js
31664
32101
  ];
31665
32102
 
@@ -32057,7 +32494,8 @@ function requireTypescript () {
32057
32494
  noneOf([
32058
32495
  ...BUILT_IN_GLOBALS,
32059
32496
  "super",
32060
- "import"
32497
+ "import",
32498
+ "await",
32061
32499
  ].map(x => `${x}\\s*\\(`)),
32062
32500
  IDENT_RE$1, regex.lookahead(/\s*\(/)),
32063
32501
  className: "title.function",
@@ -32126,7 +32564,7 @@ function requireTypescript () {
32126
32564
  keywords: KEYWORDS$1,
32127
32565
  // this will be extended by TypeScript
32128
32566
  exports: { PARAMS_CONTAINS, CLASS_REFERENCE },
32129
- illegal: /#(?![$_A-z])/,
32567
+ illegal: /#(?![$_A-Za-z])/,
32130
32568
  contains: [
32131
32569
  hljs.SHEBANG({
32132
32570
  label: "shebang",
@@ -34078,6 +34516,8 @@ function setStyle(style) {
34078
34516
  function setStyleCommand(style) {
34079
34517
  let commandAdapter = (viewState, dispatch, view) => {
34080
34518
  let state = view?.state ?? viewState;
34519
+ const delegate = activeConfig()?.delegate;
34520
+ if (delegate?.canStyle && !delegate.canStyle(isTableSelected(state))) return false;
34081
34521
  const protonode = _nodeFor(style, state.schema);
34082
34522
  const doc = state.doc;
34083
34523
  const selection = state.selection;
@@ -34182,6 +34622,8 @@ function setCodeLanguageCommand(language) {
34182
34622
  }
34183
34623
  return true
34184
34624
  }
34625
+ const delegate = activeConfig()?.delegate;
34626
+ if (delegate?.canStyle && !delegate.canStyle(isTableSelected(state))) return false;
34185
34627
  const codeBlockType = state.schema.nodes.code_block;
34186
34628
  const doc = state.doc;
34187
34629
  const selection = state.selection;
@@ -34374,6 +34816,8 @@ function wrapInListCommand(schema, targetNodeType, attrs) {
34374
34816
  const listItemTypes = [targetListItemType];
34375
34817
 
34376
34818
  const commandAdapter = (state, dispatch, view) => {
34819
+ const delegate = activeConfig()?.delegate;
34820
+ if (delegate?.canList && !delegate.canList(isTableSelected(state))) return false;
34377
34821
  const inTargetNodeType = getListType(state) === listTypeFor(targetNodeType, state.schema);
34378
34822
  const command = inTargetNodeType ? liftListItem(state.schema.nodes.list_item) : wrapInList(targetNodeType, attrs);
34379
34823
  if (command(state)) {
@@ -34527,6 +34971,7 @@ function indent$1() {
34527
34971
  function indentCommand() {
34528
34972
  let commandAdapter = (viewState, dispatch, view) => {
34529
34973
  let state = view?.state ?? viewState;
34974
+ if (isTableSelected(state)) return false; // Indenting wraps/re-nests blocks, which corrupts a table's structure
34530
34975
  let blockquote = state.schema.nodes.blockquote;
34531
34976
  let li = state.schema.nodes.list_item;
34532
34977
  let ul = state.schema.nodes.bullet_list;
@@ -34642,6 +35087,7 @@ function outdent$1() {
34642
35087
  function outdentCommand() {
34643
35088
  let commandAdapter = (viewState, dispatch, view) => {
34644
35089
  let state = view?.state ?? viewState;
35090
+ if (isTableSelected(state)) return false; // Outdenting lifts/re-nests blocks, which corrupts a table's structure
34645
35091
  const { $from, $to } = state.selection;
34646
35092
  let tr = state.tr;
34647
35093
  let willLift = false;
@@ -35912,10 +36358,14 @@ function insertHRule() {
35912
36358
  }
35913
36359
  function insertHRuleCommand() {
35914
36360
  const commandAdapter = (state, dispatch, view) => {
35915
- const hRuleNode = view.state.schema.nodes.horizontal_rule.create();
35916
- const transaction = view.state.tr.replaceSelectionWith(hRuleNode, true);
35917
- view.dispatch(transaction);
35918
- stateChanged(view);
36361
+ const delegate = activeConfig()?.delegate;
36362
+ if (delegate?.canInsertHRule && !delegate.canInsertHRule(isTableSelected(state))) return false;
36363
+ if (dispatch) {
36364
+ const hRuleNode = state.schema.nodes.horizontal_rule.create();
36365
+ const transaction = state.tr.replaceSelectionWith(hRuleNode, true);
36366
+ dispatch(transaction);
36367
+ stateChanged(view);
36368
+ }
35919
36369
  return true;
35920
36370
  };
35921
36371
 
@@ -37452,6 +37902,7 @@ class DropCursorView {
37452
37902
  this.cursorPos = null;
37453
37903
  this.element = null;
37454
37904
  this.timeout = -1;
37905
+ this.lastDragEvent = null;
37455
37906
  this.width = (_a = options.width) !== null && _a !== void 0 ? _a : 1;
37456
37907
  this.color = options.color === false ? undefined : (options.color || "black");
37457
37908
  this.class = options.class;
@@ -37466,10 +37917,18 @@ class DropCursorView {
37466
37917
  }
37467
37918
  update(editorView, prevState) {
37468
37919
  if (this.cursorPos != null && prevState.doc != editorView.state.doc) {
37469
- if (this.cursorPos > editorView.state.doc.content.size)
37470
- this.setCursor(null);
37471
- else
37920
+ // if we currently have an on-going drag event
37921
+ // we need to update the cursor position again and update the overlay
37922
+ if (this.lastDragEvent) {
37923
+ let target = this.computeTarget(this.lastDragEvent);
37924
+ if (target == this.cursorPos)
37925
+ this.updateOverlay();
37926
+ else
37927
+ this.setCursor(target);
37928
+ }
37929
+ else {
37472
37930
  this.updateOverlay();
37931
+ }
37473
37932
  }
37474
37933
  }
37475
37934
  setCursor(pos) {
@@ -37540,22 +37999,29 @@ class DropCursorView {
37540
37999
  clearTimeout(this.timeout);
37541
38000
  this.timeout = setTimeout(() => this.setCursor(null), timeout);
37542
38001
  }
37543
- dragover(event) {
37544
- if (!this.editorView.editable)
37545
- return;
38002
+ computeTarget(event) {
37546
38003
  let pos = this.editorView.posAtCoords({ left: event.clientX, top: event.clientY });
37547
38004
  let node = pos && pos.inside >= 0 && this.editorView.state.doc.nodeAt(pos.inside);
37548
38005
  let disableDropCursor = node && node.type.spec.disableDropCursor;
37549
38006
  let disabled = typeof disableDropCursor == "function"
37550
38007
  ? disableDropCursor(this.editorView, pos, event)
37551
38008
  : disableDropCursor;
37552
- if (pos && !disabled) {
37553
- let target = pos.pos;
37554
- if (this.editorView.dragging && this.editorView.dragging.slice) {
37555
- let point = dropPoint(this.editorView.state.doc, target, this.editorView.dragging.slice);
37556
- if (point != null)
37557
- target = point;
37558
- }
38009
+ if (!pos || disabled)
38010
+ return null;
38011
+ let target = pos.pos;
38012
+ if (this.editorView.dragging && this.editorView.dragging.slice) {
38013
+ let point = dropPoint(this.editorView.state.doc, target, this.editorView.dragging.slice);
38014
+ if (point != null)
38015
+ target = point;
38016
+ }
38017
+ return target;
38018
+ }
38019
+ dragover(event) {
38020
+ if (!this.editorView.editable)
38021
+ return;
38022
+ this.lastDragEvent = event;
38023
+ let target = this.computeTarget(event);
38024
+ if (target != null) {
37559
38025
  this.setCursor(target);
37560
38026
  this.scheduleRemoval(5000);
37561
38027
  }
@@ -37611,7 +38077,7 @@ class GapCursor extends Selection {
37611
38077
  */
37612
38078
  static valid($pos) {
37613
38079
  let parent = $pos.parent;
37614
- if (parent.isTextblock || !closedBefore($pos) || !closedAfter($pos))
38080
+ if (parent.inlineContent || !closedBefore($pos) || !closedAfter($pos))
37615
38081
  return false;
37616
38082
  let override = parent.type.spec.allowGapCursor;
37617
38083
  if (override != null)
@@ -37838,7 +38304,7 @@ class SearchQuery {
37838
38304
  let result = this.impl.findNext(state, from, to);
37839
38305
  if (!result || this.checkResult(state, result))
37840
38306
  return result;
37841
- from = result.from + 1;
38307
+ from = Math.max(from, result.from) + 1;
37842
38308
  }
37843
38309
  }
37844
38310
  /**
@@ -37852,7 +38318,7 @@ class SearchQuery {
37852
38318
  let result = this.impl.findPrev(state, from, to);
37853
38319
  if (!result || this.checkResult(state, result))
37854
38320
  return result;
37855
- from = result.to - 1;
38321
+ from = Math.min(from, result.to) - 1;
37856
38322
  }
37857
38323
  }
37858
38324
  /**
@@ -38095,7 +38561,8 @@ function buildMatchDeco(state, query, range) {
38095
38561
  break;
38096
38562
  let cls = next.from == sel.from && next.to == sel.to ? "ProseMirror-active-search-match" : "ProseMirror-search-match";
38097
38563
  deco.push(Decoration.inline(next.from, next.to, { class: cls }));
38098
- pos = next.to;
38564
+ // Avoid infinite loop on zero-length matches.
38565
+ pos = Math.max(next.to, pos + 1);
38099
38566
  }
38100
38567
  return DecorationSet.create(state.doc, deco);
38101
38568
  }
@@ -40516,7 +40983,7 @@ function hRuleItem(config) {
40516
40983
  icon: icon,
40517
40984
  title: title,
40518
40985
  active: (state) => { return isHRuleSelected(state) },
40519
- enable: () => { return true } // TODO: should be conditional?
40986
+ enable: true
40520
40987
  };
40521
40988
  return cmdItem(insertHRuleCommand(), options)
40522
40989
  }