@bigbinary/neeto-editor 1.47.104 → 1.47.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/Editor.js CHANGED
@@ -4,7 +4,7 @@ import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
4
4
  import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
5
5
  import * as React from 'react';
6
6
  import React__default, { memo, useState, useEffect, useRef, useCallback, createElement, forwardRef, useImperativeHandle } from 'react';
7
- import { E as Extension, a as Mark, m as mergeAttributes, b as markInputRule, c as markPasteRule, D as DecorationSet, d as Decoration, g as getMarkAttributes, N as Node, w as wrappingInputRule, t as textblockTypeInputRule, k as keydownHandler, e as callOrReturn, f as getExtensionField, i as isNodeSelection, n as nodeInputRule, h as getNodeType, j as getNodeAtPosition, l as isNodeActive, o as isAtStartOfNode, p as isAtEndOfNode, C as CALLOUT_TYPES, q as NodeViewWrapper, r as NodeViewContent, R as ReactNodeViewRenderer, s as findChildren, u as escapeForRegEx, v as ReactRenderer, x as EmojiPickerMenu, y as emojiPickerApi, z as combineTransactionSteps, A as getChangedRanges, B as findChildrenInRange, F as getMarksBetween, G as getAttributes, I as InputRule, H as highlightFocussedNode, J as resetFocussedNode, K as findParentNodeClosestToPos, P as PasteRule, L as validateUrl, O as BubbleMenu, Q as getLinkPopoverPosition, S as getMarkType, T as getMarkRange, U as useEditor, V as useEditorState, M as Menu$4, W as MenuDynamicVariables, X as EditorContent, Y as MediaUploader, Z as LinkAddPopOver, _ as EditorView } from './chunk-CmM0OmZo.js';
7
+ import { E as Extension, a as Mark, m as mergeAttributes, b as markInputRule, c as markPasteRule, D as DecorationSet, d as Decoration, g as getMarkAttributes, N as Node, w as wrappingInputRule, t as textblockTypeInputRule, k as keydownHandler, e as callOrReturn, f as getExtensionField, i as isNodeSelection, n as nodeInputRule, h as getNodeType, j as getNodeAtPosition, l as isNodeActive, o as isAtStartOfNode, p as isAtEndOfNode, C as CALLOUT_TYPES, q as NodeViewWrapper, r as NodeViewContent, R as ReactNodeViewRenderer, s as findChildren, u as escapeForRegEx, v as ReactRenderer, x as EmojiPickerMenu, y as emojiPickerApi, z as combineTransactionSteps, A as getChangedRanges, B as findChildrenInRange, F as getMarksBetween, G as getAttributes, I as InputRule, H as highlightFocussedNode, J as resetFocussedNode, K as findParentNodeClosestToPos, P as PasteRule, L as validateUrl, O as BubbleMenu, Q as getLinkPopoverPosition, S as getMarkType, T as getMarkRange, U as useEditor, V as useEditorState, M as Menu$4, W as MenuDynamicVariables, X as EditorContent, Y as MediaUploader, Z as LinkAddPopOver, _ as EditorView } from './chunk-CU3LdVPN.js';
8
8
  import classnames from 'classnames';
9
9
  import { D as DIRECT_UPLOAD_ENDPOINT, E as EDITOR_OPTIONS, C as COMBINED_REGEX, a as EDITOR_SIZES } from './chunk-DNMH2cJJ.js';
10
10
  import { isNotPresent, findBy, isNotEmpty, isPresent, noop as noop$1, slugify } from '@bigbinary/neeto-cist';
@@ -8,7 +8,7 @@ import Editor from './Editor.js';
8
8
  import { jsx } from 'react/jsx-runtime';
9
9
  import '@babel/runtime/helpers/toConsumableArray';
10
10
  import '@babel/runtime/helpers/slicedToArray';
11
- import './chunk-CmM0OmZo.js';
11
+ import './chunk-CU3LdVPN.js';
12
12
  import './chunk-DmrvuTKK.js';
13
13
  import 'i18next';
14
14
  import '@bigbinary/neeto-icons/TextH1';
package/dist/Menu.js CHANGED
@@ -3,7 +3,7 @@ import '@babel/runtime/helpers/toConsumableArray';
3
3
  import '@babel/runtime/helpers/slicedToArray';
4
4
  import 'react';
5
5
  import 'ramda';
6
- export { M as default } from './chunk-CmM0OmZo.js';
6
+ export { M as default } from './chunk-CU3LdVPN.js';
7
7
  import './chunk-DxGDZoUl.js';
8
8
  import 'react/jsx-runtime';
9
9
  import './chunk-DmrvuTKK.js';
@@ -482,14 +482,15 @@ function posFromCaret(view, node, offset, coords) {
482
482
  let desc = view.docView.nearestDesc(cur, true);
483
483
  if (!desc)
484
484
  return null;
485
- if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent && !sawBlock || !desc.contentDOM)) {
485
+ if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM)) {
486
486
  let rect = desc.dom.getBoundingClientRect();
487
- if (desc.node.isBlock && desc.parent && !sawBlock) {
488
- sawBlock = true;
489
- if (rect.left > coords.left || rect.top > coords.top)
487
+ if (desc.node.isBlock && desc.parent) {
488
+ // Only apply the horizontal test to the innermost block. Vertical for any parent.
489
+ if (!sawBlock && rect.left > coords.left || rect.top > coords.top)
490
490
  outsideBlock = desc.posBefore;
491
- else if (rect.right < coords.left || rect.bottom < coords.top)
491
+ else if (!sawBlock && rect.right < coords.left || rect.bottom < coords.top)
492
492
  outsideBlock = desc.posAfter;
493
+ sawBlock = true;
493
494
  }
494
495
  if (!desc.contentDOM && outsideBlock < 0 && !desc.node.isText) {
495
496
  // If we are inside a leaf, return the side of the leaf closer to the coords
@@ -744,6 +745,8 @@ function endOfTextblockHorizontal(view, state, dir) {
744
745
  return false;
745
746
  let offset = $head.parentOffset, atStart = !offset, atEnd = offset == $head.parent.content.size;
746
747
  let sel = view.domSelection();
748
+ if (!sel)
749
+ return $head.pos == $head.start() || $head.pos == $head.end();
747
750
  // If the textblock is all LTR, or the browser doesn't support
748
751
  // Selection.modify (Edge), fall back to a primitive approach
749
752
  if (!maybeRTL.test($head.parent.textContent) || !sel.modify)
@@ -1280,7 +1283,7 @@ class MarkViewDesc extends ViewDesc {
1280
1283
  let custom = view.nodeViews[mark.type.name];
1281
1284
  let spec = custom && custom(mark, view, inline);
1282
1285
  if (!spec || !spec.dom)
1283
- spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline));
1286
+ spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline), null, mark.attrs);
1284
1287
  return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom);
1285
1288
  }
1286
1289
  parseRule() {
@@ -1352,7 +1355,8 @@ class NodeViewDesc extends ViewDesc {
1352
1355
  throw new RangeError("Text must be rendered as a DOM text node");
1353
1356
  }
1354
1357
  else if (!dom) {
1355
- ({ dom, contentDOM } = DOMSerializer.renderSpec(document, node.type.spec.toDOM(node)));
1358
+ let spec = DOMSerializer.renderSpec(document, node.type.spec.toDOM(node), null, node.attrs);
1359
+ ({ dom, contentDOM } = spec);
1356
1360
  }
1357
1361
  if (!contentDOM && !node.isText && dom.nodeName != "BR") { // Chrome gets confused by <br contenteditable=false>
1358
1362
  if (!dom.hasAttribute("contenteditable"))
@@ -1538,10 +1542,11 @@ class NodeViewDesc extends ViewDesc {
1538
1542
  }
1539
1543
  // Remove selected node marking from this node.
1540
1544
  deselectNode() {
1541
- if (this.nodeDOM.nodeType == 1)
1545
+ if (this.nodeDOM.nodeType == 1) {
1542
1546
  this.nodeDOM.classList.remove("ProseMirror-selectednode");
1543
- if (this.contentDOM || !this.node.type.spec.draggable)
1544
- this.dom.removeAttribute("draggable");
1547
+ if (this.contentDOM || !this.node.type.spec.draggable)
1548
+ this.dom.removeAttribute("draggable");
1549
+ }
1545
1550
  }
1546
1551
  get domAtom() { return this.node.isAtom; }
1547
1552
  }
@@ -2364,12 +2369,14 @@ function removeClassOnSelectionChange(view) {
2364
2369
  }
2365
2370
  function selectCursorWrapper(view) {
2366
2371
  let domSel = view.domSelection(), range = document.createRange();
2372
+ if (!domSel)
2373
+ return;
2367
2374
  let node = view.cursorWrapper.dom, img = node.nodeName == "IMG";
2368
2375
  if (img)
2369
- range.setEnd(node.parentNode, domIndex(node) + 1);
2376
+ range.setStart(node.parentNode, domIndex(node) + 1);
2370
2377
  else
2371
- range.setEnd(node, 0);
2372
- range.collapse(false);
2378
+ range.setStart(node, 0);
2379
+ range.collapse(true);
2373
2380
  domSel.removeAllRanges();
2374
2381
  domSel.addRange(range);
2375
2382
  // Kludge to kill 'control selection' in IE11 when selecting an
@@ -2657,6 +2664,8 @@ function setSelFocus(view, node, offset) {
2657
2664
  }
2658
2665
  }
2659
2666
  let sel = view.domSelection();
2667
+ if (!sel)
2668
+ return;
2660
2669
  if (selectionCollapsed(sel)) {
2661
2670
  let range = document.createRange();
2662
2671
  range.setEnd(node, offset);
@@ -2839,7 +2848,7 @@ function serializeForClipboard(view, slice) {
2839
2848
  firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd}${wrappers ? ` -${wrappers}` : ""} ${JSON.stringify(context)}`);
2840
2849
  let text = view.someProp("clipboardTextSerializer", f => f(slice, view)) ||
2841
2850
  slice.content.textBetween(0, slice.content.size, "\n\n");
2842
- return { dom: wrap, text };
2851
+ return { dom: wrap, text, slice };
2843
2852
  }
2844
2853
  // Read a slice of content from the clipboard (or drop data).
2845
2854
  function parseFromClipboard(view, text, html, plainText, $context) {
@@ -3223,6 +3232,8 @@ function runHandlerOnContext(view, propName, pos, inside, event) {
3223
3232
  function updateSelection(view, selection, origin) {
3224
3233
  if (!view.focused)
3225
3234
  view.focus();
3235
+ if (view.state.selection.eq(selection))
3236
+ return;
3226
3237
  let tr = view.state.tr.setSelection(selection);
3227
3238
  tr.setMeta("pointer", true);
3228
3239
  view.dispatch(tr);
@@ -3355,7 +3366,7 @@ class MouseDown {
3355
3366
  }
3356
3367
  const target = flushed ? null : event.target;
3357
3368
  const targetDesc = target ? view.docView.nearestDesc(target, true) : null;
3358
- this.target = targetDesc ? targetDesc.dom : null;
3369
+ this.target = targetDesc && targetDesc.dom.nodeType == 1 ? targetDesc.dom : null;
3359
3370
  let { selection } = view.state;
3360
3371
  if (event.button == 0 &&
3361
3372
  targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
@@ -3476,8 +3487,8 @@ const timeoutComposition = android ? 5000 : -1;
3476
3487
  editHandlers.compositionstart = editHandlers.compositionupdate = view => {
3477
3488
  if (!view.composing) {
3478
3489
  view.domObserver.flush();
3479
- let { state } = view, $pos = state.selection.$from;
3480
- if (state.selection.empty &&
3490
+ let { state } = view, $pos = state.selection.$to;
3491
+ if (state.selection instanceof TextSelection &&
3481
3492
  (state.storedMarks ||
3482
3493
  (!$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some(m => m.type.spec.inclusive === false)))) {
3483
3494
  // Need to wrap the cursor in mark nodes different from the ones in the DOM context
@@ -3486,7 +3497,7 @@ editHandlers.compositionstart = editHandlers.compositionupdate = view => {
3486
3497
  view.markCursor = null;
3487
3498
  }
3488
3499
  else {
3489
- endComposition(view);
3500
+ endComposition(view, !state.selection.empty);
3490
3501
  // In firefox, if the cursor is after but outside a marked node,
3491
3502
  // the inserted text won't inherit the marks. So this moves it
3492
3503
  // inside if necessary.
@@ -3497,7 +3508,9 @@ editHandlers.compositionstart = editHandlers.compositionupdate = view => {
3497
3508
  if (!before)
3498
3509
  break;
3499
3510
  if (before.nodeType == 3) {
3500
- view.domSelection().collapse(before, before.nodeValue.length);
3511
+ let sel = view.domSelection();
3512
+ if (sel)
3513
+ sel.collapse(before, before.nodeValue.length);
3501
3514
  break;
3502
3515
  }
3503
3516
  else {
@@ -3543,7 +3556,9 @@ function findCompositionNode(view) {
3543
3556
  let textBefore = textNodeBefore$1(sel.focusNode, sel.focusOffset);
3544
3557
  let textAfter = textNodeAfter$1(sel.focusNode, sel.focusOffset);
3545
3558
  if (textBefore && textAfter && textBefore != textAfter) {
3546
- let descAfter = textAfter.pmViewDesc;
3559
+ let descAfter = textAfter.pmViewDesc, lastChanged = view.domObserver.lastChangedTextNode;
3560
+ if (textBefore == lastChanged || textAfter == lastChanged)
3561
+ return lastChanged;
3547
3562
  if (!descAfter || !descAfter.isText(textAfter.nodeValue)) {
3548
3563
  return textAfter;
3549
3564
  }
@@ -3553,7 +3568,7 @@ function findCompositionNode(view) {
3553
3568
  return textAfter;
3554
3569
  }
3555
3570
  }
3556
- return textBefore;
3571
+ return textBefore || textAfter;
3557
3572
  }
3558
3573
  function timestampFromCustomEvent() {
3559
3574
  let event = document.createEvent("Event");
@@ -3563,15 +3578,17 @@ function timestampFromCustomEvent() {
3563
3578
  /**
3564
3579
  @internal
3565
3580
  */
3566
- function endComposition(view, forceUpdate = false) {
3581
+ function endComposition(view, restarting = false) {
3567
3582
  if (android && view.domObserver.flushingSoon >= 0)
3568
3583
  return;
3569
3584
  view.domObserver.forceFlush();
3570
3585
  clearComposition(view);
3571
- if (forceUpdate || view.docView && view.docView.dirty) {
3586
+ if (restarting || view.docView && view.docView.dirty) {
3572
3587
  let sel = selectionFromDOM(view);
3573
3588
  if (sel && !sel.eq(view.state.selection))
3574
3589
  view.dispatch(view.state.tr.setSelection(sel));
3590
+ else if ((view.markCursor || restarting) && !view.state.selection.empty)
3591
+ view.dispatch(view.state.tr.deleteSelection());
3575
3592
  else
3576
3593
  view.updateState(view.state);
3577
3594
  return true;
@@ -3710,8 +3727,11 @@ handlers.dragstart = (view, _event) => {
3710
3727
  if (desc && desc.node.type.spec.draggable && desc != view.docView)
3711
3728
  node = NodeSelection.create(view.state.doc, desc.posBefore);
3712
3729
  }
3713
- let slice = (node || view.state.selection).content(), { dom, text } = serializeForClipboard(view, slice);
3714
- event.dataTransfer.clearData();
3730
+ let draggedSlice = (node || view.state.selection).content();
3731
+ let { dom, text, slice } = serializeForClipboard(view, draggedSlice);
3732
+ // Pre-120 Chrome versions clear files when calling `clearData` (#1472)
3733
+ if (!event.dataTransfer.files.length || !chrome || chrome_version > 120)
3734
+ event.dataTransfer.clearData();
3715
3735
  event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
3716
3736
  // See https://github.com/ProseMirror/prosemirror/issues/1156
3717
3737
  event.dataTransfer.effectAllowed = "copyMove";
@@ -4554,6 +4574,7 @@ class DOMObserver {
4554
4574
  this.currentSelection = new SelectionState;
4555
4575
  this.onCharData = null;
4556
4576
  this.suppressingSelectionUpdates = false;
4577
+ this.lastChangedTextNode = null;
4557
4578
  this.observer = window.MutationObserver &&
4558
4579
  new window.MutationObserver(mutations => {
4559
4580
  for (let i = 0; i < mutations.length; i++)
@@ -4686,15 +4707,23 @@ class DOMObserver {
4686
4707
  }
4687
4708
  }
4688
4709
  }
4689
- if (gecko && added.length > 1) {
4710
+ if (gecko && added.length) {
4690
4711
  let brs = added.filter(n => n.nodeName == "BR");
4691
4712
  if (brs.length == 2) {
4692
- let a = brs[0], b = brs[1];
4713
+ let [a, b] = brs;
4693
4714
  if (a.parentNode && a.parentNode.parentNode == b.parentNode)
4694
4715
  b.remove();
4695
4716
  else
4696
4717
  a.remove();
4697
4718
  }
4719
+ else {
4720
+ let { focusNode } = this.currentSelection;
4721
+ for (let br of brs) {
4722
+ let parent = br.parentNode;
4723
+ if (parent && parent.nodeName == "LI" && (!focusNode || blockParent(view, focusNode) != parent))
4724
+ br.remove();
4725
+ }
4726
+ }
4698
4727
  }
4699
4728
  let readSel = null;
4700
4729
  // If it looks like the browser has reset the selection to the
@@ -4735,8 +4764,12 @@ class DOMObserver {
4735
4764
  if (!desc || desc.ignoreMutation(mut))
4736
4765
  return null;
4737
4766
  if (mut.type == "childList") {
4738
- for (let i = 0; i < mut.addedNodes.length; i++)
4739
- added.push(mut.addedNodes[i]);
4767
+ for (let i = 0; i < mut.addedNodes.length; i++) {
4768
+ let node = mut.addedNodes[i];
4769
+ added.push(node);
4770
+ if (node.nodeType == 3)
4771
+ this.lastChangedTextNode = node;
4772
+ }
4740
4773
  if (desc.contentDOM && desc.contentDOM != desc.dom && !desc.contentDOM.contains(mut.target))
4741
4774
  return { from: desc.posBefore, to: desc.posAfter };
4742
4775
  let prev = mut.previousSibling, next = mut.nextSibling;
@@ -4763,6 +4796,7 @@ class DOMObserver {
4763
4796
  return { from: desc.posAtStart - desc.border, to: desc.posAtEnd + desc.border };
4764
4797
  }
4765
4798
  else { // "characterData"
4799
+ this.lastChangedTextNode = mut.target;
4766
4800
  return {
4767
4801
  from: desc.posAtStart,
4768
4802
  to: desc.posAtEnd,
@@ -4824,6 +4858,14 @@ function safariShadowSelectionRange(view, selection) {
4824
4858
  view.dom.removeEventListener("beforeinput", read, true);
4825
4859
  return found ? rangeToSelectionRange(view, found) : null;
4826
4860
  }
4861
+ function blockParent(view, node) {
4862
+ for (let p = node.parentNode; p && p != view.dom; p = p.parentNode) {
4863
+ let desc = view.docView.nearestDesc(p, true);
4864
+ if (desc && desc.node.isBlock)
4865
+ return p;
4866
+ }
4867
+ return null;
4868
+ }
4827
4869
 
4828
4870
  // Note that all referencing and parsing is done with the
4829
4871
  // start-of-operation selection and document, since that's the one
@@ -5688,6 +5730,8 @@ class EditorView {
5688
5730
  */
5689
5731
  domSelectionRange() {
5690
5732
  let sel = this.domSelection();
5733
+ if (!sel)
5734
+ return { focusNode: null, focusOffset: 0, anchorNode: null, anchorOffset: 0 };
5691
5735
  return safari && this.root.nodeType === 11 &&
5692
5736
  deepActiveElement(this.dom.ownerDocument) == this.dom && safariShadowSelectionRange(this, sel) || sel;
5693
5737
  }
@@ -5725,7 +5769,7 @@ function updateCursorWrapper(view) {
5725
5769
  dom.className = "ProseMirror-separator";
5726
5770
  dom.setAttribute("mark-placeholder", "true");
5727
5771
  dom.setAttribute("alt", "");
5728
- view.cursorWrapper = { dom, deco: Decoration.widget(view.state.selection.head, dom, { raw: true, marks: view.markCursor }) };
5772
+ view.cursorWrapper = { dom, deco: Decoration.widget(view.state.selection.from, dom, { raw: true, marks: view.markCursor }) };
5729
5773
  }
5730
5774
  else {
5731
5775
  view.cursorWrapper = null;
@@ -18906,4 +18950,4 @@ var Menu = function Menu(props) {
18906
18950
  };
18907
18951
 
18908
18952
  export { getChangedRanges as A, findChildrenInRange as B, CALLOUT_TYPES as C, DecorationSet as D, Extension as E, getMarksBetween as F, getAttributes as G, highlightFocussedNode as H, InputRule as I, resetFocussedNode as J, findParentNodeClosestToPos as K, validateUrl as L, Menu as M, Node as N, BubbleMenu as O, PasteRule as P, getLinkPopoverPosition as Q, ReactNodeViewRenderer as R, getMarkType as S, getMarkRange as T, useEditor as U, useEditorState$1 as V, MenuDynamicVariables as W, EditorContent as X, MediaUploader as Y, LinkAddPopOver as Z, EditorView as _, Mark as a, markInputRule as b, markPasteRule as c, Decoration as d, callOrReturn as e, getExtensionField as f, getMarkAttributes as g, getNodeType as h, isNodeSelection as i, getNodeAtPosition as j, keydownHandler as k, isNodeActive as l, mergeAttributes as m, nodeInputRule as n, isAtStartOfNode as o, isAtEndOfNode as p, NodeViewWrapper as q, NodeViewContent as r, findChildren as s, textblockTypeInputRule as t, escapeForRegEx as u, ReactRenderer as v, wrappingInputRule as w, EmojiPickerMenu as x, emojiPickerApi as y, combineTransactionSteps as z };
18909
- //# sourceMappingURL=chunk-CmM0OmZo.js.map
18953
+ //# sourceMappingURL=chunk-CU3LdVPN.js.map