@bigbinary/neeto-editor 1.45.27 → 1.45.29

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, useEffect, useState, 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 findChildren, j as NodeViewWrapper, l as NodeViewContent, R as ReactNodeViewRenderer, P as PasteRule, v as validateUrl, o as escapeForRegEx, p as ReactRenderer, q as EmojiPickerMenu, r as emojiPickerApi, s as liftTarget, u as combineTransactionSteps, x as getChangedRanges, y as findChildrenInRange, z as getMarksBetween, A as getAttributes, I as InputRule, B as highlightFocussedNode, C as resetFocussedNode, F as findParentNodeClosestToPos, G as BubbleMenu, H as getLinkPopoverPosition, J as getMarkType, K as getMarkRange, L as useEditor, O as useEditorState, M as Menu$3, Q as EditorContent, S as MediaUploader, T as EmbedOption, U as EditorView } from './chunk-B_ypvaUL.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, i as isNodeActive, e as isAtStartOfNode, f as isAtEndOfNode, h as getNodeType, j as getNodeAtPosition, w as wrappingInputRule, t as textblockTypeInputRule, k as keydownHandler, l as callOrReturn, n as getExtensionField, o as isNodeSelection, p as nodeInputRule, q as findChildren, r as NodeViewWrapper, s as NodeViewContent, R as ReactNodeViewRenderer, P as PasteRule, v as validateUrl, u as escapeForRegEx, x as ReactRenderer, y as EmojiPickerMenu, z as emojiPickerApi, A as combineTransactionSteps, B as getChangedRanges, C as findChildrenInRange, F as getMarksBetween, G as getAttributes, I as InputRule, H as highlightFocussedNode, J as resetFocussedNode, K as findParentNodeClosestToPos, L as BubbleMenu, O as getLinkPopoverPosition, Q as getMarkType, S as getMarkRange, T as useEditor, U as useEditorState, M as Menu$3, V as EditorContent, W as MediaUploader, X as EmbedOption, Y as EditorView } from './chunk-C0xZGEez.js';
8
8
  import classnames from 'classnames';
9
9
  import { C as COMBINED_REGEX, D as DIRECT_UPLOAD_ENDPOINT, E as EDITOR_OPTIONS, a as EDITOR_SIZES } from './chunk-FWwP48qR.js';
10
10
  import { isNotPresent, isNotEmpty, isPresent, noop as noop$1, slugify } from '@bigbinary/neeto-cist';
@@ -3008,6 +3008,268 @@ const Highlight = Mark.create({
3008
3008
  },
3009
3009
  });
3010
3010
 
3011
+ const findListItemPos = (typeOrName, state) => {
3012
+ const { $from } = state.selection;
3013
+ const nodeType = getNodeType(typeOrName, state.schema);
3014
+ let currentNode = null;
3015
+ let currentDepth = $from.depth;
3016
+ let currentPos = $from.pos;
3017
+ let targetDepth = null;
3018
+ while (currentDepth > 0 && targetDepth === null) {
3019
+ currentNode = $from.node(currentDepth);
3020
+ if (currentNode.type === nodeType) {
3021
+ targetDepth = currentDepth;
3022
+ }
3023
+ else {
3024
+ currentDepth -= 1;
3025
+ currentPos -= 1;
3026
+ }
3027
+ }
3028
+ if (targetDepth === null) {
3029
+ return null;
3030
+ }
3031
+ return { $pos: state.doc.resolve(currentPos), depth: targetDepth };
3032
+ };
3033
+
3034
+ const getNextListDepth = (typeOrName, state) => {
3035
+ const listItemPos = findListItemPos(typeOrName, state);
3036
+ if (!listItemPos) {
3037
+ return false;
3038
+ }
3039
+ const [, depth] = getNodeAtPosition(state, typeOrName, listItemPos.$pos.pos + 4);
3040
+ return depth;
3041
+ };
3042
+
3043
+ const hasListBefore = (editorState, name, parentListTypes) => {
3044
+ const { $anchor } = editorState.selection;
3045
+ const previousNodePos = Math.max(0, $anchor.pos - 2);
3046
+ const previousNode = editorState.doc.resolve(previousNodePos).node();
3047
+ if (!previousNode || !parentListTypes.includes(previousNode.type.name)) {
3048
+ return false;
3049
+ }
3050
+ return true;
3051
+ };
3052
+
3053
+ const hasListItemBefore = (typeOrName, state) => {
3054
+ var _a;
3055
+ const { $anchor } = state.selection;
3056
+ const $targetPos = state.doc.resolve($anchor.pos - 2);
3057
+ if ($targetPos.index() === 0) {
3058
+ return false;
3059
+ }
3060
+ if (((_a = $targetPos.nodeBefore) === null || _a === void 0 ? void 0 : _a.type.name) !== typeOrName) {
3061
+ return false;
3062
+ }
3063
+ return true;
3064
+ };
3065
+
3066
+ const listItemHasSubList = (typeOrName, state, node) => {
3067
+ if (!node) {
3068
+ return false;
3069
+ }
3070
+ const nodeType = getNodeType(typeOrName, state.schema);
3071
+ let hasSubList = false;
3072
+ node.descendants(child => {
3073
+ if (child.type === nodeType) {
3074
+ hasSubList = true;
3075
+ }
3076
+ });
3077
+ return hasSubList;
3078
+ };
3079
+
3080
+ const handleBackspace = (editor, name, parentListTypes) => {
3081
+ // this is required to still handle the undo handling
3082
+ if (editor.commands.undoInputRule()) {
3083
+ return true;
3084
+ }
3085
+ // if the selection is not collapsed
3086
+ // we can rely on the default backspace behavior
3087
+ if (editor.state.selection.from !== editor.state.selection.to) {
3088
+ return false;
3089
+ }
3090
+ // if the current item is NOT inside a list item &
3091
+ // the previous item is a list (orderedList or bulletList)
3092
+ // move the cursor into the list and delete the current item
3093
+ if (!isNodeActive(editor.state, name) && hasListBefore(editor.state, name, parentListTypes)) {
3094
+ const { $anchor } = editor.state.selection;
3095
+ const $listPos = editor.state.doc.resolve($anchor.before() - 1);
3096
+ const listDescendants = [];
3097
+ $listPos.node().descendants((node, pos) => {
3098
+ if (node.type.name === name) {
3099
+ listDescendants.push({ node, pos });
3100
+ }
3101
+ });
3102
+ const lastItem = listDescendants.at(-1);
3103
+ if (!lastItem) {
3104
+ return false;
3105
+ }
3106
+ const $lastItemPos = editor.state.doc.resolve($listPos.start() + lastItem.pos + 1);
3107
+ return editor.chain().cut({ from: $anchor.start() - 1, to: $anchor.end() + 1 }, $lastItemPos.end()).joinForward().run();
3108
+ }
3109
+ // if the cursor is not inside the current node type
3110
+ // do nothing and proceed
3111
+ if (!isNodeActive(editor.state, name)) {
3112
+ return false;
3113
+ }
3114
+ // if the cursor is not at the start of a node
3115
+ // do nothing and proceed
3116
+ if (!isAtStartOfNode(editor.state)) {
3117
+ return false;
3118
+ }
3119
+ const listItemPos = findListItemPos(name, editor.state);
3120
+ if (!listItemPos) {
3121
+ return false;
3122
+ }
3123
+ const $prev = editor.state.doc.resolve(listItemPos.$pos.pos - 2);
3124
+ const prevNode = $prev.node(listItemPos.depth);
3125
+ const previousListItemHasSubList = listItemHasSubList(name, editor.state, prevNode);
3126
+ // if the previous item is a list item and doesn't have a sublist, join the list items
3127
+ if (hasListItemBefore(name, editor.state) && !previousListItemHasSubList) {
3128
+ return editor.commands.joinItemBackward();
3129
+ }
3130
+ // otherwise in the end, a backspace should
3131
+ // always just lift the list item if
3132
+ // joining / merging is not possible
3133
+ return editor.chain().liftListItem(name).run();
3134
+ };
3135
+
3136
+ const nextListIsDeeper = (typeOrName, state) => {
3137
+ const listDepth = getNextListDepth(typeOrName, state);
3138
+ const listItemPos = findListItemPos(typeOrName, state);
3139
+ if (!listItemPos || !listDepth) {
3140
+ return false;
3141
+ }
3142
+ if (listDepth > listItemPos.depth) {
3143
+ return true;
3144
+ }
3145
+ return false;
3146
+ };
3147
+
3148
+ const nextListIsHigher = (typeOrName, state) => {
3149
+ const listDepth = getNextListDepth(typeOrName, state);
3150
+ const listItemPos = findListItemPos(typeOrName, state);
3151
+ if (!listItemPos || !listDepth) {
3152
+ return false;
3153
+ }
3154
+ if (listDepth < listItemPos.depth) {
3155
+ return true;
3156
+ }
3157
+ return false;
3158
+ };
3159
+
3160
+ const handleDelete = (editor, name) => {
3161
+ // if the cursor is not inside the current node type
3162
+ // do nothing and proceed
3163
+ if (!isNodeActive(editor.state, name)) {
3164
+ return false;
3165
+ }
3166
+ // if the cursor is not at the end of a node
3167
+ // do nothing and proceed
3168
+ if (!isAtEndOfNode(editor.state, name)) {
3169
+ return false;
3170
+ }
3171
+ // if the selection is not collapsed, or not within a single node
3172
+ // do nothing and proceed
3173
+ const { selection } = editor.state;
3174
+ const { $from, $to } = selection;
3175
+ if (!selection.empty && $from.sameParent($to)) {
3176
+ return false;
3177
+ }
3178
+ // check if the next node is a list with a deeper depth
3179
+ if (nextListIsDeeper(name, editor.state)) {
3180
+ return editor
3181
+ .chain()
3182
+ .focus(editor.state.selection.from + 4)
3183
+ .lift(name)
3184
+ .joinBackward()
3185
+ .run();
3186
+ }
3187
+ if (nextListIsHigher(name, editor.state)) {
3188
+ return editor.chain()
3189
+ .joinForward()
3190
+ .joinBackward()
3191
+ .run();
3192
+ }
3193
+ return editor.commands.joinItemForward();
3194
+ };
3195
+
3196
+ /**
3197
+ * This extension registers custom keymaps to change the behaviour of the backspace and delete keys.
3198
+ * By default Prosemirror keyhandling will always lift or sink items so paragraphs are joined into
3199
+ * the adjacent or previous list item. This extension will prevent this behaviour and instead will
3200
+ * try to join paragraphs from two list items into a single list item.
3201
+ * @see https://www.tiptap.dev/api/extensions/list-keymap
3202
+ */
3203
+ const ListKeymap = Extension.create({
3204
+ name: 'listKeymap',
3205
+ addOptions() {
3206
+ return {
3207
+ listTypes: [
3208
+ {
3209
+ itemName: 'listItem',
3210
+ wrapperNames: ['bulletList', 'orderedList'],
3211
+ },
3212
+ {
3213
+ itemName: 'taskItem',
3214
+ wrapperNames: ['taskList'],
3215
+ },
3216
+ ],
3217
+ };
3218
+ },
3219
+ addKeyboardShortcuts() {
3220
+ return {
3221
+ Delete: ({ editor }) => {
3222
+ let handled = false;
3223
+ this.options.listTypes.forEach(({ itemName }) => {
3224
+ if (editor.state.schema.nodes[itemName] === undefined) {
3225
+ return;
3226
+ }
3227
+ if (handleDelete(editor, itemName)) {
3228
+ handled = true;
3229
+ }
3230
+ });
3231
+ return handled;
3232
+ },
3233
+ 'Mod-Delete': ({ editor }) => {
3234
+ let handled = false;
3235
+ this.options.listTypes.forEach(({ itemName }) => {
3236
+ if (editor.state.schema.nodes[itemName] === undefined) {
3237
+ return;
3238
+ }
3239
+ if (handleDelete(editor, itemName)) {
3240
+ handled = true;
3241
+ }
3242
+ });
3243
+ return handled;
3244
+ },
3245
+ Backspace: ({ editor }) => {
3246
+ let handled = false;
3247
+ this.options.listTypes.forEach(({ itemName, wrapperNames }) => {
3248
+ if (editor.state.schema.nodes[itemName] === undefined) {
3249
+ return;
3250
+ }
3251
+ if (handleBackspace(editor, itemName, wrapperNames)) {
3252
+ handled = true;
3253
+ }
3254
+ });
3255
+ return handled;
3256
+ },
3257
+ 'Mod-Backspace': ({ editor }) => {
3258
+ let handled = false;
3259
+ this.options.listTypes.forEach(({ itemName, wrapperNames }) => {
3260
+ if (editor.state.schema.nodes[itemName] === undefined) {
3261
+ return;
3262
+ }
3263
+ if (handleBackspace(editor, itemName, wrapperNames)) {
3264
+ handled = true;
3265
+ }
3266
+ });
3267
+ return handled;
3268
+ },
3269
+ };
3270
+ },
3271
+ });
3272
+
3011
3273
  /**
3012
3274
  * This extension allows you to create table cells.
3013
3275
  * @see https://www.tiptap.dev/api/nodes/table-cell
@@ -4987,7 +5249,7 @@ const underscorePasteRegex = /(?:^|\s)(_(?!\s+_)((?:[^_]+))_(?!\s+_))/g;
4987
5249
  * This extension allows you to create italic text.
4988
5250
  * @see https://www.tiptap.dev/api/marks/italic
4989
5251
  */
4990
- const Italic = Mark.create({
5252
+ const Italic$1 = Mark.create({
4991
5253
  name: 'italic',
4992
5254
  addOptions() {
4993
5255
  return {
@@ -5428,7 +5690,7 @@ const StarterKit = Extension.create({
5428
5690
  extensions.push(HorizontalRule.configure((_m = this.options) === null || _m === void 0 ? void 0 : _m.horizontalRule));
5429
5691
  }
5430
5692
  if (this.options.italic !== false) {
5431
- extensions.push(Italic.configure((_o = this.options) === null || _o === void 0 ? void 0 : _o.italic));
5693
+ extensions.push(Italic$1.configure((_o = this.options) === null || _o === void 0 ? void 0 : _o.italic));
5432
5694
  }
5433
5695
  if (this.options.listItem !== false) {
5434
5696
  extensions.push(ListItem$1.configure((_p = this.options) === null || _p === void 0 ? void 0 : _p.listItem));
@@ -10730,6 +10992,12 @@ var FigCaption = Node.create({
10730
10992
  }
10731
10993
  });
10732
10994
 
10995
+ var Italic = Italic$1.extend({
10996
+ addInputRules: function addInputRules() {
10997
+ return [];
10998
+ }
10999
+ });
11000
+
10733
11001
  function ownKeys$9(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
10734
11002
  function _objectSpread$9(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$9(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$9(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
10735
11003
  var KeyboardShortcuts = function KeyboardShortcuts(_ref) {
@@ -10751,51 +11019,16 @@ var KeyboardShortcuts = function KeyboardShortcuts(_ref) {
10751
11019
  return true;
10752
11020
  }
10753
11021
  return false;
10754
- },
10755
- // To fix the issue with backspace on the empty list item moving the focus to the block on top.
10756
- // https://github.com/ueberdosis/tiptap/issues/2829#issuecomment-1511064298
10757
- Backspace: function Backspace() {
10758
- return _this.editor.commands.command(function (_ref2) {
10759
- var tr = _ref2.tr;
10760
- var selection = tr.selection,
10761
- doc = tr.doc;
10762
- var $cursor = selection.$cursor;
10763
- var depth = $cursor === null || $cursor === void 0 ? void 0 : $cursor.depth;
10764
- if ($cursor && depth >= 3 &&
10765
- // At least the structure is doc -> orderedList/bulletList -> listItem -> paragraph
10766
- $cursor.parent.type.name === "paragraph" &&
10767
- // The cursor is inside a paragraph.
10768
- $cursor.parentOffset === 0 &&
10769
- // The cursor is at the beginning of the paragraph.
10770
- $cursor.node(depth - 1).type.name === "listItem" &&
10771
- // The paragraph is inside a listItem.
10772
- $cursor.index(depth - 1) === 0 &&
10773
- // The paragraph is at the beginning of the listItem.
10774
- $cursor.index(depth - 2) === 0 // The listItem is at the beginning of the list.
10775
- ) {
10776
- var listItemNode = $cursor.node(depth - 1);
10777
- var listItemPos = $cursor.before(depth - 1);
10778
- var $contentBegin = doc.resolve(listItemPos + 1);
10779
- var $contentEnd = doc.resolve(listItemPos + listItemNode.nodeSize - 1);
10780
- var range = $contentBegin.blockRange($contentEnd);
10781
- var target = liftTarget(range);
10782
- if (target !== null) {
10783
- tr.lift(range, target);
10784
- return true;
10785
- }
10786
- }
10787
- return false;
10788
- });
10789
11022
  }
10790
11023
  }, shortcuts);
10791
11024
  }
10792
11025
  });
10793
11026
  };
10794
11027
  var KeyboardShortcuts$1 = {
10795
- configure: function configure(_ref3) {
10796
- var onSubmit = _ref3.onSubmit,
10797
- shortcuts = _ref3.shortcuts,
10798
- isBlockQuoteActive = _ref3.isBlockQuoteActive;
11028
+ configure: function configure(_ref2) {
11029
+ var onSubmit = _ref2.onSubmit,
11030
+ shortcuts = _ref2.shortcuts,
11031
+ isBlockQuoteActive = _ref2.isBlockQuoteActive;
10799
11032
  return KeyboardShortcuts({
10800
11033
  onSubmit: onSubmit,
10801
11034
  shortcuts: shortcuts,
@@ -19176,15 +19409,16 @@ var useCustomExtensions = function useCustomExtensions(_ref) {
19176
19409
  bulletList: false,
19177
19410
  blockquote: options.includes(EDITOR_OPTIONS.BLOCKQUOTE),
19178
19411
  orderedList: options.includes(EDITOR_OPTIONS.LIST_ORDERED),
19412
+ italic: false,
19179
19413
  history: !collaborationProvider,
19180
19414
  heading: {
19181
19415
  levels: buildLevelsFromOptions(options)
19182
19416
  }
19183
- }), TextStyle$2, Underline, KeyboardShortcuts$1.configure({
19417
+ }), TextStyle$2, Underline, Italic, KeyboardShortcuts$1.configure({
19184
19418
  onSubmit: onSubmit,
19185
19419
  shortcuts: keyboardShortcuts,
19186
19420
  isBlockQuoteActive: options.includes(EDITOR_OPTIONS.BLOCKQUOTE)
19187
- })];
19421
+ }), ListKeymap];
19188
19422
  if (isVideoEmbedActive) {
19189
19423
  customExtensions.push(Embeds);
19190
19424
  }