@ni/spright-components 4.3.1 → 4.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29953,6 +29953,7 @@ so this becomes the fallback color for the slot */ ''}
29953
29953
  this.options = options;
29954
29954
  this.isOpen = isOpen;
29955
29955
  this.open = 0;
29956
+ this.localPreserveWS = false;
29956
29957
  let topNode = options.topNode, topContext;
29957
29958
  let topOptions = wsOptionsFor(null, options.preserveWhitespace, 0) | (isOpen ? OPT_OPEN_LEFT : 0);
29958
29959
  if (topNode)
@@ -29979,11 +29980,12 @@ so this becomes the fallback color for the slot */ ''}
29979
29980
  }
29980
29981
  addTextNode(dom, marks) {
29981
29982
  let value = dom.nodeValue;
29982
- let top = this.top;
29983
- if (top.options & OPT_PRESERVE_WS_FULL ||
29983
+ let top = this.top, preserveWS = (top.options & OPT_PRESERVE_WS_FULL) ? "full"
29984
+ : this.localPreserveWS || (top.options & OPT_PRESERVE_WS) > 0;
29985
+ if (preserveWS === "full" ||
29984
29986
  top.inlineContext(dom) ||
29985
29987
  /[^ \t\r\n\u000c]/.test(value)) {
29986
- if (!(top.options & OPT_PRESERVE_WS)) {
29988
+ if (!preserveWS) {
29987
29989
  value = value.replace(/[ \t\r\n\u000c]+/g, " ");
29988
29990
  // If this starts with whitespace, and there is no node before it, or
29989
29991
  // a hard break, or a text node that ends with whitespace, strip the
@@ -29997,7 +29999,7 @@ so this becomes the fallback color for the slot */ ''}
29997
29999
  value = value.slice(1);
29998
30000
  }
29999
30001
  }
30000
- else if (!(top.options & OPT_PRESERVE_WS_FULL)) {
30002
+ else if (preserveWS !== "full") {
30001
30003
  value = value.replace(/\r?\n|\r/g, " ");
30002
30004
  }
30003
30005
  else {
@@ -30014,12 +30016,15 @@ so this becomes the fallback color for the slot */ ''}
30014
30016
  // Try to find a handler for the given tag and use that to parse. If
30015
30017
  // none is found, the element's content nodes are added directly.
30016
30018
  addElement(dom, marks, matchAfter) {
30019
+ let outerWS = this.localPreserveWS, top = this.top;
30020
+ if (dom.tagName == "PRE" || /pre/.test(dom.style && dom.style.whiteSpace))
30021
+ this.localPreserveWS = true;
30017
30022
  let name = dom.nodeName.toLowerCase(), ruleID;
30018
30023
  if (listTags.hasOwnProperty(name) && this.parser.normalizeLists)
30019
30024
  normalizeList(dom);
30020
30025
  let rule = (this.options.ruleFromNode && this.options.ruleFromNode(dom)) ||
30021
30026
  (ruleID = this.parser.matchTag(dom, this, matchAfter));
30022
- if (rule ? rule.ignore : ignoreTags.hasOwnProperty(name)) {
30027
+ out: if (rule ? rule.ignore : ignoreTags.hasOwnProperty(name)) {
30023
30028
  this.findInside(dom);
30024
30029
  this.ignoreFallback(dom, marks);
30025
30030
  }
@@ -30028,7 +30033,7 @@ so this becomes the fallback color for the slot */ ''}
30028
30033
  this.open = Math.max(0, this.open - 1);
30029
30034
  else if (rule && rule.skip.nodeType)
30030
30035
  dom = rule.skip;
30031
- let sync, top = this.top, oldNeedsBlock = this.needsBlock;
30036
+ let sync, oldNeedsBlock = this.needsBlock;
30032
30037
  if (blockTags.hasOwnProperty(name)) {
30033
30038
  if (top.content.length && top.content[0].isInline && this.open) {
30034
30039
  this.open--;
@@ -30040,7 +30045,7 @@ so this becomes the fallback color for the slot */ ''}
30040
30045
  }
30041
30046
  else if (!dom.firstChild) {
30042
30047
  this.leafFallback(dom, marks);
30043
- return;
30048
+ break out;
30044
30049
  }
30045
30050
  let innerMarks = rule && rule.skip ? marks : this.readStyles(dom, marks);
30046
30051
  if (innerMarks)
@@ -30054,6 +30059,7 @@ so this becomes the fallback color for the slot */ ''}
30054
30059
  if (innerMarks)
30055
30060
  this.addElementByRule(dom, rule, innerMarks, rule.consuming === false ? ruleID : undefined);
30056
30061
  }
30062
+ this.localPreserveWS = outerWS;
30057
30063
  }
30058
30064
  // Called for leaf DOM nodes that would otherwise be ignored
30059
30065
  leafFallback(dom, marks) {
@@ -30244,14 +30250,18 @@ so this becomes the fallback color for the slot */ ''}
30244
30250
  finish() {
30245
30251
  this.open = 0;
30246
30252
  this.closeExtra(this.isOpen);
30247
- return this.nodes[0].finish(this.isOpen || this.options.topOpen);
30253
+ return this.nodes[0].finish(!!(this.isOpen || this.options.topOpen));
30248
30254
  }
30249
30255
  sync(to) {
30250
- for (let i = this.open; i >= 0; i--)
30256
+ for (let i = this.open; i >= 0; i--) {
30251
30257
  if (this.nodes[i] == to) {
30252
30258
  this.open = i;
30253
30259
  return true;
30254
30260
  }
30261
+ else if (this.localPreserveWS) {
30262
+ this.nodes[i].options |= OPT_PRESERVE_WS;
30263
+ }
30264
+ }
30255
30265
  return false;
30256
30266
  }
30257
30267
  get currentPos() {
@@ -34161,11 +34171,12 @@ so this becomes the fallback color for the slot */ ''}
34161
34171
  for (let cur = node, sawBlock = false;;) {
34162
34172
  if (cur == view.dom)
34163
34173
  break;
34164
- let desc = view.docView.nearestDesc(cur, true);
34174
+ let desc = view.docView.nearestDesc(cur, true), rect;
34165
34175
  if (!desc)
34166
34176
  return null;
34167
- if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM)) {
34168
- let rect = desc.dom.getBoundingClientRect();
34177
+ if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM) &&
34178
+ // Ignore elements with zero-size bounding rectangles
34179
+ ((rect = desc.dom.getBoundingClientRect()).width || rect.height)) {
34169
34180
  if (desc.node.isBlock && desc.parent) {
34170
34181
  // Only apply the horizontal test to the innermost block. Vertical for any parent.
34171
34182
  if (!sawBlock && rect.left > coords.left || rect.top > coords.top)
@@ -36807,7 +36818,7 @@ so this becomes the fallback color for the slot */ ''}
36807
36818
  this.lastIOSEnterFallbackTimeout = -1;
36808
36819
  this.lastFocus = 0;
36809
36820
  this.lastTouch = 0;
36810
- this.lastAndroidDelete = 0;
36821
+ this.lastChromeDelete = 0;
36811
36822
  this.composing = false;
36812
36823
  this.compositionNode = null;
36813
36824
  this.composingTimeout = -1;
@@ -38784,11 +38795,11 @@ so this becomes the fallback color for the slot */ ''}
38784
38795
  view.domObserver.suppressSelectionUpdates(); // #820
38785
38796
  return;
38786
38797
  }
38787
- // Chrome Android will occasionally, during composition, delete the
38798
+ // Chrome will occasionally, during composition, delete the
38788
38799
  // entire composition and then immediately insert it again. This is
38789
38800
  // used to detect that situation.
38790
- if (chrome && android && change.endB == change.start)
38791
- view.input.lastAndroidDelete = Date.now();
38801
+ if (chrome && change.endB == change.start)
38802
+ view.input.lastChromeDelete = Date.now();
38792
38803
  // This tries to detect Android virtual keyboard
38793
38804
  // enter-and-pick-suggestion action. That sometimes (see issue
38794
38805
  // #1059) first fires a DOM mutation, before moving the selection to
@@ -38839,13 +38850,13 @@ so this becomes the fallback color for the slot */ ''}
38839
38850
  tr = view.state.tr.replace(chFrom, chTo, parse.doc.slice(change.start - parse.from, change.endB - parse.from));
38840
38851
  if (parse.sel) {
38841
38852
  let sel = resolveSelection(view, tr.doc, parse.sel);
38842
- // Chrome Android will sometimes, during composition, report the
38853
+ // Chrome will sometimes, during composition, report the
38843
38854
  // selection in the wrong place. If it looks like that is
38844
38855
  // happening, don't update the selection.
38845
38856
  // Edge just doesn't move the cursor forward when you start typing
38846
38857
  // in an empty block or between br nodes.
38847
- if (sel && !(chrome && android && view.composing && sel.empty &&
38848
- (change.start != change.endB || view.input.lastAndroidDelete < Date.now() - 100) &&
38858
+ if (sel && !(chrome && view.composing && sel.empty &&
38859
+ (change.start != change.endB || view.input.lastChromeDelete < Date.now() - 100) &&
38849
38860
  (sel.head == chFrom || sel.head == tr.mapping.map(chTo) - 1) ||
38850
38861
  ie$1 && sel.empty && sel.head == chFrom))
38851
38862
  tr.setSelection(sel);
@@ -40341,28 +40352,44 @@ so this becomes the fallback color for the slot */ ''}
40341
40352
  function wrapInList$1(listType, attrs = null) {
40342
40353
  return function (state, dispatch) {
40343
40354
  let { $from, $to } = state.selection;
40344
- let range = $from.blockRange($to), doJoin = false, outerRange = range;
40355
+ let range = $from.blockRange($to);
40345
40356
  if (!range)
40346
40357
  return false;
40347
- // This is at the top of an existing list item
40348
- if (range.depth >= 2 && $from.node(range.depth - 1).type.compatibleContent(listType) && range.startIndex == 0) {
40349
- // Don't do anything if this is the top of the list
40350
- if ($from.index(range.depth - 1) == 0)
40351
- return false;
40352
- let $insert = state.doc.resolve(range.start - 2);
40353
- outerRange = new NodeRange($insert, $insert, range.depth);
40354
- if (range.endIndex < range.parent.childCount)
40355
- range = new NodeRange($from, state.doc.resolve($to.end(range.depth)), range.depth);
40356
- doJoin = true;
40357
- }
40358
- let wrap = findWrapping(outerRange, listType, attrs, range);
40359
- if (!wrap)
40358
+ let tr = dispatch ? state.tr : null;
40359
+ if (!wrapRangeInList(tr, range, listType, attrs))
40360
40360
  return false;
40361
40361
  if (dispatch)
40362
- dispatch(doWrapInList(state.tr, range, wrap, doJoin, listType).scrollIntoView());
40362
+ dispatch(tr.scrollIntoView());
40363
40363
  return true;
40364
40364
  };
40365
40365
  }
40366
+ /**
40367
+ Try to wrap the given node range in a list of the given type.
40368
+ Return `true` when this is possible, `false` otherwise. When `tr`
40369
+ is non-null, the wrapping is added to that transaction. When it is
40370
+ `null`, the function only queries whether the wrapping is
40371
+ possible.
40372
+ */
40373
+ function wrapRangeInList(tr, range, listType, attrs = null) {
40374
+ let doJoin = false, outerRange = range, doc = range.$from.doc;
40375
+ // This is at the top of an existing list item
40376
+ if (range.depth >= 2 && range.$from.node(range.depth - 1).type.compatibleContent(listType) && range.startIndex == 0) {
40377
+ // Don't do anything if this is the top of the list
40378
+ if (range.$from.index(range.depth - 1) == 0)
40379
+ return false;
40380
+ let $insert = doc.resolve(range.start - 2);
40381
+ outerRange = new NodeRange($insert, $insert, range.depth);
40382
+ if (range.endIndex < range.parent.childCount)
40383
+ range = new NodeRange(range.$from, doc.resolve(range.$to.end(range.depth)), range.depth);
40384
+ doJoin = true;
40385
+ }
40386
+ let wrap = findWrapping(outerRange, listType, attrs, range);
40387
+ if (!wrap)
40388
+ return false;
40389
+ if (tr)
40390
+ doWrapInList(tr, range, wrap, doJoin, listType);
40391
+ return true;
40392
+ }
40366
40393
  function doWrapInList(tr, range, wrappers, joinBefore, listType) {
40367
40394
  let content = Fragment.empty;
40368
40395
  for (let i = wrappers.length - 1; i >= 0; i--)
@@ -41460,6 +41487,8 @@ so this becomes the fallback color for the slot */ ''}
41460
41487
  const success = handlers.every(handler => handler !== null);
41461
41488
  return success;
41462
41489
  }
41490
+ // When dragging across editors, must get another editor instance to delete selection content.
41491
+ let tiptapDragFromOtherEditor = null;
41463
41492
  const createClipboardPasteEvent = (text) => {
41464
41493
  var _a;
41465
41494
  const event = new ClipboardEvent('paste', {
@@ -41522,11 +41551,21 @@ so this becomes the fallback color for the slot */ ''}
41522
41551
  dragSourceElement = ((_a = view.dom.parentElement) === null || _a === void 0 ? void 0 : _a.contains(event.target))
41523
41552
  ? view.dom.parentElement
41524
41553
  : null;
41554
+ if (dragSourceElement) {
41555
+ tiptapDragFromOtherEditor = editor;
41556
+ }
41557
+ };
41558
+ const handleDragend = () => {
41559
+ if (tiptapDragFromOtherEditor) {
41560
+ tiptapDragFromOtherEditor = null;
41561
+ }
41525
41562
  };
41526
41563
  window.addEventListener('dragstart', handleDragstart);
41564
+ window.addEventListener('dragend', handleDragend);
41527
41565
  return {
41528
41566
  destroy() {
41529
41567
  window.removeEventListener('dragstart', handleDragstart);
41568
+ window.removeEventListener('dragend', handleDragend);
41530
41569
  },
41531
41570
  };
41532
41571
  },
@@ -41535,6 +41574,18 @@ so this becomes the fallback color for the slot */ ''}
41535
41574
  drop: (view, event) => {
41536
41575
  isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement;
41537
41576
  dropEvent = event;
41577
+ if (!isDroppedFromProseMirror) {
41578
+ const dragFromOtherEditor = tiptapDragFromOtherEditor;
41579
+ if (dragFromOtherEditor) {
41580
+ // setTimeout to avoid the wrong content after drop, timeout arg can't be empty or 0
41581
+ setTimeout(() => {
41582
+ const selection = dragFromOtherEditor.state.selection;
41583
+ if (selection) {
41584
+ dragFromOtherEditor.commands.deleteRange({ from: selection.from, to: selection.to });
41585
+ }
41586
+ }, 10);
41587
+ }
41588
+ }
41538
41589
  return false;
41539
41590
  },
41540
41591
  paste: (_view, event) => {
@@ -42293,30 +42344,13 @@ so this becomes the fallback color for the slot */ ''}
42293
42344
  return TextSelection.create(doc, minMax(position, minPos, maxPos), minMax(position, minPos, maxPos));
42294
42345
  }
42295
42346
 
42296
- function isiOS() {
42297
- return [
42298
- 'iPad Simulator',
42299
- 'iPhone Simulator',
42300
- 'iPod Simulator',
42301
- 'iPad',
42302
- 'iPhone',
42303
- 'iPod',
42304
- ].includes(navigator.platform)
42305
- // iPad on iOS 13 detection
42306
- || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
42307
- }
42308
-
42309
42347
  const focus = (position = null, options = {}) => ({ editor, view, tr, dispatch, }) => {
42310
42348
  options = {
42311
42349
  scrollIntoView: true,
42312
42350
  ...options,
42313
42351
  };
42314
42352
  const delayedFocus = () => {
42315
- // focus within `requestAnimationFrame` breaks focus on iOS
42316
- // so we have to call this
42317
- if (isiOS()) {
42318
- view.dom.focus();
42319
- }
42353
+ view.dom.focus();
42320
42354
  // For React we have to focus asynchronously. Otherwise wild things happen.
42321
42355
  // see: https://github.com/ueberdosis/tiptap/issues/1520
42322
42356
  requestAnimationFrame(() => {
@@ -42647,6 +42681,19 @@ so this becomes the fallback color for the slot */ ''}
42647
42681
  return joinTextblockForward$1(state, dispatch);
42648
42682
  };
42649
42683
 
42684
+ function isiOS() {
42685
+ return [
42686
+ 'iPad Simulator',
42687
+ 'iPhone Simulator',
42688
+ 'iPod Simulator',
42689
+ 'iPad',
42690
+ 'iPhone',
42691
+ 'iPod',
42692
+ ].includes(navigator.platform)
42693
+ // iPad on iOS 13 detection
42694
+ || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
42695
+ }
42696
+
42650
42697
  function isMacOS() {
42651
42698
  return typeof navigator !== 'undefined'
42652
42699
  ? /Mac/.test(navigator.platform)
@@ -42857,11 +42904,12 @@ so this becomes the fallback color for the slot */ ''}
42857
42904
  return true;
42858
42905
  };
42859
42906
 
42860
- const selectAll = () => ({ tr, commands }) => {
42861
- return commands.setTextSelection({
42862
- from: 0,
42863
- to: tr.doc.content.size,
42864
- });
42907
+ const selectAll = () => ({ tr, dispatch }) => {
42908
+ if (dispatch) {
42909
+ const selection = new AllSelection(tr.doc);
42910
+ tr.setSelection(selection);
42911
+ }
42912
+ return true;
42865
42913
  };
42866
42914
 
42867
42915
  const selectNodeBackward = () => ({ state, dispatch }) => {
@@ -56143,8 +56191,8 @@ img.ProseMirror-separator {
56143
56191
  this.values = values;
56144
56192
  }
56145
56193
 
56146
- if ( RopeSequence ) Leaf.__proto__ = RopeSequence;
56147
- Leaf.prototype = Object.create( RopeSequence && RopeSequence.prototype );
56194
+ Leaf.__proto__ = RopeSequence;
56195
+ Leaf.prototype = Object.create( RopeSequence.prototype );
56148
56196
  Leaf.prototype.constructor = Leaf;
56149
56197
 
56150
56198
  var prototypeAccessors = { length: { configurable: true },depth: { configurable: true } };
@@ -56204,8 +56252,8 @@ img.ProseMirror-separator {
56204
56252
  this.depth = Math.max(left.depth, right.depth) + 1;
56205
56253
  }
56206
56254
 
56207
- if ( RopeSequence ) Append.__proto__ = RopeSequence;
56208
- Append.prototype = Object.create( RopeSequence && RopeSequence.prototype );
56255
+ Append.__proto__ = RopeSequence;
56256
+ Append.prototype = Object.create( RopeSequence.prototype );
56209
56257
  Append.prototype.constructor = Append;
56210
56258
 
56211
56259
  Append.prototype.flatten = function flatten () {
@@ -57165,6 +57213,8 @@ img.ProseMirror-separator {
57165
57213
  // A valid web domain token
57166
57214
  const WORD = 'WORD'; // only contains a-z
57167
57215
  const UWORD = 'UWORD'; // contains letters other than a-z, used for IDN
57216
+ const ASCIINUMERICAL = 'ASCIINUMERICAL'; // contains a-z, 0-9
57217
+ const ALPHANUMERICAL = 'ALPHANUMERICAL'; // contains numbers and letters other than a-z, used for IDN
57168
57218
 
57169
57219
  // Special case of word
57170
57220
  const LOCALHOST = 'LOCALHOST';
@@ -57192,7 +57242,7 @@ img.ProseMirror-separator {
57192
57242
  const WS = 'WS';
57193
57243
 
57194
57244
  // New line (unix style)
57195
- const NL$1 = 'NL'; // \n
57245
+ const NL = 'NL'; // \n
57196
57246
 
57197
57247
  // Opening/closing bracket classes
57198
57248
  // TODO: Rename OPEN -> LEFT and CLOSE -> RIGHT in v5 to fit with Unicode names
@@ -57252,6 +57302,8 @@ img.ProseMirror-separator {
57252
57302
  __proto__: null,
57253
57303
  WORD: WORD,
57254
57304
  UWORD: UWORD,
57305
+ ASCIINUMERICAL: ASCIINUMERICAL,
57306
+ ALPHANUMERICAL: ALPHANUMERICAL,
57255
57307
  LOCALHOST: LOCALHOST,
57256
57308
  TLD: TLD,
57257
57309
  UTLD: UTLD,
@@ -57259,7 +57311,7 @@ img.ProseMirror-separator {
57259
57311
  SLASH_SCHEME: SLASH_SCHEME,
57260
57312
  NUM: NUM,
57261
57313
  WS: WS,
57262
- NL: NL$1,
57314
+ NL: NL,
57263
57315
  OPENBRACE: OPENBRACE,
57264
57316
  CLOSEBRACE: CLOSEBRACE,
57265
57317
  OPENBRACKET: OPENBRACKET,
@@ -57316,9 +57368,11 @@ img.ProseMirror-separator {
57316
57368
  The scanner provides an interface that takes a string of text as input, and
57317
57369
  outputs an array of tokens instances that can be used for easy URL parsing.
57318
57370
  */
57319
- const NL = '\n'; // New line character
57371
+ const CR = '\r'; // carriage-return character
57372
+ const LF = '\n'; // line-feed character
57320
57373
  const EMOJI_VARIATION = '\ufe0f'; // Variation selector, follows heart and others
57321
57374
  const EMOJI_JOINER = '\u200d'; // zero-width joiner
57375
+ const OBJECT_REPLACEMENT = '\ufffc'; // whitespace placeholder that sometimes appears in rich text editors
57322
57376
 
57323
57377
  let tlds = null,
57324
57378
  utlds = null; // don't change so only have to be computed once
@@ -57404,49 +57458,73 @@ img.ProseMirror-separator {
57404
57458
  [numeric]: true
57405
57459
  });
57406
57460
  tr(Num, DIGIT, Num);
57461
+ const Asciinumeric = tr(Num, ASCII_LETTER, ASCIINUMERICAL, {
57462
+ [asciinumeric]: true
57463
+ });
57464
+ const Alphanumeric = tr(Num, LETTER, ALPHANUMERICAL, {
57465
+ [alphanumeric$1]: true
57466
+ });
57407
57467
 
57408
57468
  // State which emits a word token
57409
57469
  const Word = tr(Start, ASCII_LETTER, WORD, {
57410
57470
  [ascii]: true
57411
57471
  });
57472
+ tr(Word, DIGIT, Asciinumeric);
57412
57473
  tr(Word, ASCII_LETTER, Word);
57474
+ tr(Asciinumeric, DIGIT, Asciinumeric);
57475
+ tr(Asciinumeric, ASCII_LETTER, Asciinumeric);
57413
57476
 
57414
57477
  // Same as previous, but specific to non-fsm.ascii alphabet words
57415
57478
  const UWord = tr(Start, LETTER, UWORD, {
57416
57479
  [alpha]: true
57417
57480
  });
57418
57481
  tr(UWord, ASCII_LETTER); // Non-accepting
57482
+ tr(UWord, DIGIT, Alphanumeric);
57419
57483
  tr(UWord, LETTER, UWord);
57484
+ tr(Alphanumeric, DIGIT, Alphanumeric);
57485
+ tr(Alphanumeric, ASCII_LETTER); // Non-accepting
57486
+ tr(Alphanumeric, LETTER, Alphanumeric); // Non-accepting
57420
57487
 
57421
57488
  // Whitespace jumps
57422
57489
  // Tokens of only non-newline whitespace are arbitrarily long
57423
57490
  // If any whitespace except newline, more whitespace!
57424
- const Ws = tr(Start, SPACE, WS, {
57491
+ const Nl = tt(Start, LF, NL, {
57492
+ [whitespace]: true
57493
+ });
57494
+ const Cr = tt(Start, CR, WS, {
57425
57495
  [whitespace]: true
57426
57496
  });
57427
- tt(Start, NL, NL$1, {
57497
+ const Ws = tr(Start, SPACE, WS, {
57428
57498
  [whitespace]: true
57429
57499
  });
57430
- tt(Ws, NL); // non-accepting state to avoid mixing whitespaces
57500
+ tt(Start, OBJECT_REPLACEMENT, Ws);
57501
+ tt(Cr, LF, Nl); // \r\n
57502
+ tt(Cr, OBJECT_REPLACEMENT, Ws);
57503
+ tr(Cr, SPACE, Ws);
57504
+ tt(Ws, CR); // non-accepting state to avoid mixing whitespaces
57505
+ tt(Ws, LF); // non-accepting state to avoid mixing whitespaces
57431
57506
  tr(Ws, SPACE, Ws);
57507
+ tt(Ws, OBJECT_REPLACEMENT, Ws);
57432
57508
 
57433
57509
  // Emoji tokens. They are not grouped by the scanner except in cases where a
57434
57510
  // zero-width joiner is present
57435
57511
  const Emoji = tr(Start, EMOJI, EMOJI$1, {
57436
57512
  [emoji]: true
57437
57513
  });
57514
+ tt(Emoji, '#'); // no transition, emoji regex seems to match #
57438
57515
  tr(Emoji, EMOJI, Emoji);
57439
57516
  tt(Emoji, EMOJI_VARIATION, Emoji);
57440
57517
  // tt(Start, EMOJI_VARIATION, Emoji); // This one is sketchy
57441
57518
 
57442
57519
  const EmojiJoiner = tt(Emoji, EMOJI_JOINER);
57520
+ tt(EmojiJoiner, '#');
57443
57521
  tr(EmojiJoiner, EMOJI, Emoji);
57444
57522
  // tt(EmojiJoiner, EMOJI_VARIATION, Emoji); // also sketchy
57445
57523
 
57446
57524
  // Generates states for top-level domains
57447
57525
  // Note that this is most accurate when tlds are in alphabetical order
57448
- const wordjr = [[ASCII_LETTER, Word]];
57449
- const uwordjr = [[ASCII_LETTER, null], [LETTER, UWord]];
57526
+ const wordjr = [[ASCII_LETTER, Word], [DIGIT, Asciinumeric]];
57527
+ const uwordjr = [[ASCII_LETTER, null], [LETTER, UWord], [DIGIT, Alphanumeric]];
57450
57528
  for (let i = 0; i < tlds.length; i++) {
57451
57529
  fastts(Start, tlds[i], TLD, WORD, wordjr);
57452
57530
  }
@@ -58135,7 +58213,7 @@ img.ProseMirror-separator {
58135
58213
  // Types of tokens that can follow a URL and be part of the query string
58136
58214
  // but cannot be the very last characters
58137
58215
  // Characters that cannot appear in the URL at all should be excluded
58138
- const qsNonAccepting = [APOSTROPHE, COLON, COMMA, DOT, EXCLAMATION, QUERY, QUOTE, SEMI, OPENANGLEBRACKET, CLOSEANGLEBRACKET, OPENBRACE, CLOSEBRACE, CLOSEBRACKET, OPENBRACKET, OPENPAREN, CLOSEPAREN, FULLWIDTHLEFTPAREN, FULLWIDTHRIGHTPAREN, LEFTCORNERBRACKET, RIGHTCORNERBRACKET, LEFTWHITECORNERBRACKET, RIGHTWHITECORNERBRACKET, FULLWIDTHLESSTHAN, FULLWIDTHGREATERTHAN];
58216
+ const qsNonAccepting = [COLON, COMMA, DOT, EXCLAMATION, PERCENT, QUERY, QUOTE, SEMI, OPENANGLEBRACKET, CLOSEANGLEBRACKET, OPENBRACE, CLOSEBRACE, CLOSEBRACKET, OPENBRACKET, OPENPAREN, CLOSEPAREN, FULLWIDTHLEFTPAREN, FULLWIDTHRIGHTPAREN, LEFTCORNERBRACKET, RIGHTCORNERBRACKET, LEFTWHITECORNERBRACKET, RIGHTWHITECORNERBRACKET, FULLWIDTHLESSTHAN, FULLWIDTHGREATERTHAN];
58139
58217
 
58140
58218
  // For addresses without the mailto prefix
58141
58219
  // Tokens allowed in the localpart of the email
@@ -58180,6 +58258,7 @@ img.ProseMirror-separator {
58180
58258
 
58181
58259
  // Hyphen can jump back to a domain name
58182
58260
  const EmailDomainHyphen = tt(EmailDomain, HYPHEN); // parsed string starts with local email info + @ with a potential domain name
58261
+ tt(EmailDomainHyphen, HYPHEN, EmailDomainHyphen);
58183
58262
  ta(EmailDomainHyphen, groups.domain, EmailDomain);
58184
58263
  ta(Email$1, groups.domain, EmailDomain);
58185
58264
  tt(Email$1, DOT, EmailDomainDot);
@@ -58194,6 +58273,7 @@ img.ProseMirror-separator {
58194
58273
  // (but not TLDs)
58195
58274
  const DomainHyphen = tt(Domain, HYPHEN); // domain followed by hyphen
58196
58275
  const DomainDot = tt(Domain, DOT); // domain followed by DOT
58276
+ tt(DomainHyphen, HYPHEN, DomainHyphen);
58197
58277
  ta(DomainHyphen, groups.domain, Domain);
58198
58278
  ta(DomainDot, localpartAccepting, Localpart);
58199
58279
  ta(DomainDot, groups.domain, Domain);
@@ -58244,6 +58324,7 @@ img.ProseMirror-separator {
58244
58324
  // Force URL with scheme prefix followed by anything sane
58245
58325
  ta(SchemeColon, groups.domain, Url$1);
58246
58326
  tt(SchemeColon, SLASH, Url$1);
58327
+ tt(SchemeColon, QUERY, Url$1);
58247
58328
  ta(UriPrefix, groups.domain, Url$1);
58248
58329
  ta(UriPrefix, qsAccepting, Url$1);
58249
58330
  tt(UriPrefix, SLASH, Url$1);
@@ -58292,7 +58373,7 @@ img.ProseMirror-separator {
58292
58373
  tt(UrlOpenSyms, CLOSE, Url$1);
58293
58374
  }
58294
58375
  tt(Start, LOCALHOST, DomainDotTld); // localhost is a valid URL state
58295
- tt(Start, NL$1, Nl); // single new line
58376
+ tt(Start, NL, Nl); // single new line
58296
58377
 
58297
58378
  return {
58298
58379
  start: Start,
@@ -58447,7 +58528,7 @@ img.ProseMirror-separator {
58447
58528
  * Detect URLs with the following additional protocol. Anything with format
58448
58529
  * "protocol://..." will be considered a link. If `optionalSlashSlash` is set to
58449
58530
  * `true`, anything with format "protocol:..." will be considered a link.
58450
- * @param {string} protocol
58531
+ * @param {string} scheme
58451
58532
  * @param {boolean} [optionalSlashSlash]
58452
58533
  */
58453
58534
  function registerCustomProtocol(scheme, optionalSlashSlash = false) {
@@ -58841,9 +58922,25 @@ img.ProseMirror-separator {
58841
58922
  addCommands() {
58842
58923
  return {
58843
58924
  setLink: attributes => ({ chain }) => {
58925
+ const { href } = attributes;
58926
+ if (!this.options.isAllowedUri(href, {
58927
+ defaultValidate: url => !!isAllowedUri(url, this.options.protocols),
58928
+ protocols: this.options.protocols,
58929
+ defaultProtocol: this.options.defaultProtocol,
58930
+ })) {
58931
+ return false;
58932
+ }
58844
58933
  return chain().setMark(this.name, attributes).setMeta('preventAutolink', true).run();
58845
58934
  },
58846
58935
  toggleLink: attributes => ({ chain }) => {
58936
+ const { href } = attributes;
58937
+ if (!this.options.isAllowedUri(href, {
58938
+ defaultValidate: url => !!isAllowedUri(url, this.options.protocols),
58939
+ protocols: this.options.protocols,
58940
+ defaultProtocol: this.options.defaultProtocol,
58941
+ })) {
58942
+ return false;
58943
+ }
58847
58944
  return chain()
58848
58945
  .toggleMark(this.name, attributes, { extendEmptyMarkRange: true })
58849
58946
  .setMeta('preventAutolink', true)
@@ -58959,13 +59056,15 @@ img.ProseMirror-separator {
58959
59056
 
58960
59057
  function findSuggestionMatch(config) {
58961
59058
  var _a;
58962
- const { char, allowSpaces, allowedPrefixes, startOfLine, $position, } = config;
59059
+ const { char, allowSpaces: allowSpacesOption, allowToIncludeChar, allowedPrefixes, startOfLine, $position, } = config;
59060
+ const allowSpaces = allowSpacesOption && !allowToIncludeChar;
58963
59061
  const escapedChar = escapeForRegEx(char);
58964
59062
  const suffix = new RegExp(`\\s${escapedChar}$`);
58965
59063
  const prefix = startOfLine ? '^' : '';
59064
+ const finalEscapedChar = allowToIncludeChar ? '' : escapedChar;
58966
59065
  const regexp = allowSpaces
58967
- ? new RegExp(`${prefix}${escapedChar}.*?(?=\\s${escapedChar}|$)`, 'gm')
58968
- : new RegExp(`${prefix}(?:^)?${escapedChar}[^\\s${escapedChar}]*`, 'gm');
59066
+ ? new RegExp(`${prefix}${escapedChar}.*?(?=\\s${finalEscapedChar}|$)`, 'gm')
59067
+ : new RegExp(`${prefix}(?:^)?${escapedChar}[^\\s${finalEscapedChar}]*`, 'gm');
58969
59068
  const text = ((_a = $position.nodeBefore) === null || _a === void 0 ? void 0 : _a.isText) && $position.nodeBefore.text;
58970
59069
  if (!text) {
58971
59070
  return null;
@@ -59010,7 +59109,7 @@ img.ProseMirror-separator {
59010
59109
  * This utility allows you to create suggestions.
59011
59110
  * @see https://tiptap.dev/api/utilities/suggestion
59012
59111
  */
59013
- function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allowSpaces = false, allowedPrefixes = [' '], startOfLine = false, decorationTag = 'span', decorationClass = 'suggestion', command = () => null, items = () => [], render = () => ({}), allow = () => true, findSuggestionMatch: findSuggestionMatch$1 = findSuggestionMatch, }) {
59112
+ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allowSpaces = false, allowToIncludeChar = false, allowedPrefixes = [' '], startOfLine = false, decorationTag = 'span', decorationClass = 'suggestion', command = () => null, items = () => [], render = () => ({}), allow = () => true, findSuggestionMatch: findSuggestionMatch$1 = findSuggestionMatch, }) {
59014
59113
  let props;
59015
59114
  const renderer = render === null || render === void 0 ? void 0 : render();
59016
59115
  const plugin = new Plugin({
@@ -59127,6 +59226,7 @@ img.ProseMirror-separator {
59127
59226
  const match = findSuggestionMatch$1({
59128
59227
  char,
59129
59228
  allowSpaces,
59229
+ allowToIncludeChar,
59130
59230
  allowedPrefixes,
59131
59231
  startOfLine,
59132
59232
  $position: selection.$from,
@@ -68290,20 +68390,12 @@ focus outline in that case.
68290
68390
  const size = this.getSize();
68291
68391
  const scrollOffset = this.getScrollOffset();
68292
68392
  if (align === "auto") {
68293
- if (toOffset <= scrollOffset) {
68294
- align = "start";
68295
- } else if (toOffset >= scrollOffset + size) {
68393
+ if (toOffset >= scrollOffset + size) {
68296
68394
  align = "end";
68297
- } else {
68298
- align = "start";
68299
68395
  }
68300
68396
  }
68301
- if (align === "start") {
68302
- toOffset = toOffset;
68303
- } else if (align === "end") {
68304
- toOffset = toOffset - size;
68305
- } else if (align === "center") {
68306
- toOffset = toOffset - size / 2;
68397
+ if (align === "end") {
68398
+ toOffset -= size;
68307
68399
  }
68308
68400
  const scrollSizeProp = this.options.horizontal ? "scrollWidth" : "scrollHeight";
68309
68401
  const scrollSize = this.scrollElement ? "document" in this.scrollElement ? this.scrollElement.document.documentElement[scrollSizeProp] : this.scrollElement[scrollSizeProp] : 0;
@@ -68327,8 +68419,27 @@ focus outline in that case.
68327
68419
  return [scrollOffset, align];
68328
68420
  }
68329
68421
  }
68330
- const toOffset = align === "end" ? item.end + this.options.scrollPaddingEnd : item.start - this.options.scrollPaddingStart;
68331
- return [this.getOffsetForAlignment(toOffset, align), align];
68422
+ const centerOffset = item.start - this.options.scrollPaddingStart + (item.size - size) / 2;
68423
+ switch (align) {
68424
+ case "center":
68425
+ return [this.getOffsetForAlignment(centerOffset, align), align];
68426
+ case "end":
68427
+ return [
68428
+ this.getOffsetForAlignment(
68429
+ item.end + this.options.scrollPaddingEnd,
68430
+ align
68431
+ ),
68432
+ align
68433
+ ];
68434
+ default:
68435
+ return [
68436
+ this.getOffsetForAlignment(
68437
+ item.start - this.options.scrollPaddingStart,
68438
+ align
68439
+ ),
68440
+ align
68441
+ ];
68442
+ }
68332
68443
  };
68333
68444
  this.isDynamicMode = () => this.elementsCache.size > 0;
68334
68445
  this.cancelScrollToIndex = () => {