@tiptap/extension-list 3.23.6 → 3.25.0

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 (41) hide show
  1. package/dist/index.cjs +192 -68
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +170 -46
  4. package/dist/index.js.map +1 -1
  5. package/dist/item/index.cjs +120 -3
  6. package/dist/item/index.cjs.map +1 -1
  7. package/dist/item/index.js +117 -0
  8. package/dist/item/index.js.map +1 -1
  9. package/dist/keymap/index.cjs +37 -47
  10. package/dist/keymap/index.cjs.map +1 -1
  11. package/dist/keymap/index.js +30 -40
  12. package/dist/keymap/index.js.map +1 -1
  13. package/dist/kit/index.cjs +192 -68
  14. package/dist/kit/index.cjs.map +1 -1
  15. package/dist/kit/index.js +170 -46
  16. package/dist/kit/index.js.map +1 -1
  17. package/dist/ordered-list/index.cjs +8 -1
  18. package/dist/ordered-list/index.cjs.map +1 -1
  19. package/dist/ordered-list/index.js +8 -1
  20. package/dist/ordered-list/index.js.map +1 -1
  21. package/dist/task-item/index.cjs +120 -5
  22. package/dist/task-item/index.cjs.map +1 -1
  23. package/dist/task-item/index.js +115 -0
  24. package/dist/task-item/index.js.map +1 -1
  25. package/dist/task-list/index.cjs +5 -1
  26. package/dist/task-list/index.cjs.map +1 -1
  27. package/dist/task-list/index.js +5 -1
  28. package/dist/task-list/index.js.map +1 -1
  29. package/package.json +19 -20
  30. package/src/helpers/createBranchingListDeleteKeymap.ts +24 -0
  31. package/src/helpers/getBranchingNestedListAtCursor.ts +116 -0
  32. package/src/helpers/handleDeleteBranchingNestedList.ts +25 -0
  33. package/src/helpers/hasBranchingNestedListAfterCursor.ts +30 -0
  34. package/src/helpers/hoistBranchingNestedList.ts +56 -0
  35. package/src/item/list-item.ts +21 -5
  36. package/src/keymap/listHelpers/handleBackspace.ts +3 -22
  37. package/src/keymap/listHelpers/hasListBefore.ts +5 -1
  38. package/src/ordered-list/ordered-list.ts +3 -1
  39. package/src/ordered-list/utils.ts +15 -2
  40. package/src/task-item/task-item.ts +10 -0
  41. package/src/task-list/task-list.ts +5 -1
package/dist/index.cjs CHANGED
@@ -115,7 +115,116 @@ var BulletList = import_core.Node.create({
115
115
  });
116
116
 
117
117
  // src/item/list-item.ts
118
+ var import_core3 = require("@tiptap/core");
119
+
120
+ // src/helpers/createBranchingListDeleteKeymap.ts
118
121
  var import_core2 = require("@tiptap/core");
122
+
123
+ // src/helpers/hoistBranchingNestedList.ts
124
+ var import_model = require("@tiptap/pm/model");
125
+
126
+ // src/helpers/getBranchingNestedListAtCursor.ts
127
+ var getBranchingNestedListAtCursor = (state, itemName, wrapperNames) => {
128
+ const { selection } = state;
129
+ if (!selection.empty) {
130
+ return null;
131
+ }
132
+ const { $from } = selection;
133
+ if (!$from.parent.isTextblock) {
134
+ return null;
135
+ }
136
+ if ($from.parentOffset !== $from.parent.content.size) {
137
+ return null;
138
+ }
139
+ let listItemDepth = -1;
140
+ for (let depth = $from.depth; depth > 0; depth -= 1) {
141
+ if ($from.node(depth).type.name === itemName) {
142
+ listItemDepth = depth;
143
+ break;
144
+ }
145
+ }
146
+ if (listItemDepth < 0) {
147
+ return null;
148
+ }
149
+ const listItem = $from.node(listItemDepth);
150
+ const indexInListItem = $from.index(listItemDepth);
151
+ if (indexInListItem + 1 >= listItem.childCount) {
152
+ return null;
153
+ }
154
+ const nextChild = listItem.child(indexInListItem + 1);
155
+ if (!wrapperNames.includes(nextChild.type.name)) {
156
+ return null;
157
+ }
158
+ const itemType = state.schema.nodes[itemName];
159
+ let hasBranching = false;
160
+ nextChild.forEach((child) => {
161
+ if (child.type === itemType && child.childCount > 1) {
162
+ hasBranching = true;
163
+ }
164
+ });
165
+ if (!hasBranching) {
166
+ return null;
167
+ }
168
+ const nodeAfter = state.doc.resolve($from.after()).nodeAfter;
169
+ if (!nodeAfter || !wrapperNames.includes(nodeAfter.type.name)) {
170
+ return null;
171
+ }
172
+ const items = [];
173
+ nodeAfter.forEach((child) => {
174
+ items.push(child);
175
+ });
176
+ if (items.length === 0) {
177
+ return null;
178
+ }
179
+ return {
180
+ listItemDepth,
181
+ nestedList: nodeAfter,
182
+ nestedListPos: $from.after(),
183
+ insertPos: $from.after(listItemDepth),
184
+ items
185
+ };
186
+ };
187
+
188
+ // src/helpers/hoistBranchingNestedList.ts
189
+ var hoistBranchingNestedList = (state, dispatch, itemName, wrapperNames) => {
190
+ const context = getBranchingNestedListAtCursor(state, itemName, wrapperNames);
191
+ if (!context) {
192
+ return false;
193
+ }
194
+ const { selection } = state;
195
+ const { nestedList, nestedListPos, insertPos, items } = context;
196
+ const tr = state.tr;
197
+ tr.delete(nestedListPos, nestedListPos + nestedList.nodeSize);
198
+ const mappedInsertPos = tr.mapping.map(insertPos);
199
+ tr.insert(mappedInsertPos, import_model.Fragment.from(items));
200
+ tr.setSelection(selection.map(tr.doc, tr.mapping));
201
+ if (dispatch) {
202
+ dispatch(tr);
203
+ }
204
+ return true;
205
+ };
206
+
207
+ // src/helpers/handleDeleteBranchingNestedList.ts
208
+ var handleDeleteBranchingNestedList = (editor, itemName, wrapperNames) => {
209
+ return hoistBranchingNestedList(editor.state, editor.view.dispatch, itemName, wrapperNames);
210
+ };
211
+
212
+ // src/helpers/createBranchingListDeleteKeymap.ts
213
+ var createBranchingListDeleteKeymap = (itemName, wrapperNames) => {
214
+ return import_core2.Extension.create({
215
+ name: `${itemName}BranchingDeleteKeymap`,
216
+ priority: 101,
217
+ addKeyboardShortcuts() {
218
+ const handleDelete2 = () => handleDeleteBranchingNestedList(this.editor, itemName, wrapperNames);
219
+ return {
220
+ Delete: handleDelete2,
221
+ "Mod-Delete": handleDelete2
222
+ };
223
+ }
224
+ });
225
+ };
226
+
227
+ // src/item/list-item.ts
119
228
  function isSameLineOrderedListToken(token) {
120
229
  var _a, _b;
121
230
  const nestedToken = (_a = token.tokens) == null ? void 0 : _a[0];
@@ -135,7 +244,7 @@ function parseSameLineOrderedListText(text, helpers) {
135
244
  }
136
245
  ]);
137
246
  }
138
- var ListItem = import_core2.Node.create({
247
+ var ListItem = import_core3.Node.create({
139
248
  name: "listItem",
140
249
  addOptions() {
141
250
  return {
@@ -154,7 +263,7 @@ var ListItem = import_core2.Node.create({
154
263
  ];
155
264
  },
156
265
  renderHTML({ HTMLAttributes }) {
157
- return ["li", (0, import_core2.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes), 0];
266
+ return ["li", (0, import_core3.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes), 0];
158
267
  },
159
268
  markdownTokenName: "list_item",
160
269
  parseMarkdown: (token, helpers) => {
@@ -213,7 +322,7 @@ var ListItem = import_core2.Node.create({
213
322
  };
214
323
  },
215
324
  renderMarkdown: (node, h, ctx) => {
216
- return (0, import_core2.renderNestedMarkdownContent)(
325
+ return (0, import_core3.renderNestedMarkdownContent)(
217
326
  node,
218
327
  h,
219
328
  (context) => {
@@ -230,6 +339,14 @@ var ListItem = import_core2.Node.create({
230
339
  ctx
231
340
  );
232
341
  },
342
+ addExtensions() {
343
+ return [
344
+ createBranchingListDeleteKeymap(this.name, [
345
+ this.options.bulletListTypeName,
346
+ this.options.orderedListTypeName
347
+ ])
348
+ ];
349
+ },
233
350
  addKeyboardShortcuts() {
234
351
  return {
235
352
  Enter: () => this.editor.commands.splitListItem(this.name),
@@ -240,7 +357,7 @@ var ListItem = import_core2.Node.create({
240
357
  });
241
358
 
242
359
  // src/keymap/list-keymap.ts
243
- var import_core8 = require("@tiptap/core");
360
+ var import_core9 = require("@tiptap/core");
244
361
 
245
362
  // src/keymap/listHelpers/index.ts
246
363
  var listHelpers_exports = {};
@@ -258,10 +375,10 @@ __export(listHelpers_exports, {
258
375
  });
259
376
 
260
377
  // src/keymap/listHelpers/findListItemPos.ts
261
- var import_core3 = require("@tiptap/core");
378
+ var import_core4 = require("@tiptap/core");
262
379
  var findListItemPos = (typeOrName, state) => {
263
380
  const { $from } = state.selection;
264
- const nodeType = (0, import_core3.getNodeType)(typeOrName, state.schema);
381
+ const nodeType = (0, import_core4.getNodeType)(typeOrName, state.schema);
265
382
  let currentNode = null;
266
383
  let currentDepth = $from.depth;
267
384
  let currentPos = $from.pos;
@@ -282,13 +399,13 @@ var findListItemPos = (typeOrName, state) => {
282
399
  };
283
400
 
284
401
  // src/keymap/listHelpers/getNextListDepth.ts
285
- var import_core4 = require("@tiptap/core");
402
+ var import_core5 = require("@tiptap/core");
286
403
  var getNextListDepth = (typeOrName, state) => {
287
404
  const listItemPos = findListItemPos(typeOrName, state);
288
405
  if (!listItemPos) {
289
406
  return false;
290
407
  }
291
- const [, depth] = (0, import_core4.getNodeAtPosition)(state, typeOrName, listItemPos.$pos.pos + 4);
408
+ const [, depth] = (0, import_core5.getNodeAtPosition)(state, typeOrName, listItemPos.$pos.pos + 4);
292
409
  return depth;
293
410
  };
294
411
 
@@ -306,36 +423,6 @@ var hasListBefore = (editorState, name, parentListTypes) => {
306
423
  return true;
307
424
  };
308
425
 
309
- // src/keymap/listHelpers/hasListItemBefore.ts
310
- var hasListItemBefore = (typeOrName, state) => {
311
- var _a;
312
- const { $anchor } = state.selection;
313
- const $targetPos = state.doc.resolve($anchor.pos - 2);
314
- if ($targetPos.index() === 0) {
315
- return false;
316
- }
317
- if (((_a = $targetPos.nodeBefore) == null ? void 0 : _a.type.name) !== typeOrName) {
318
- return false;
319
- }
320
- return true;
321
- };
322
-
323
- // src/keymap/listHelpers/listItemHasSubList.ts
324
- var import_core5 = require("@tiptap/core");
325
- var listItemHasSubList = (typeOrName, state, node) => {
326
- if (!node) {
327
- return false;
328
- }
329
- const nodeType = (0, import_core5.getNodeType)(typeOrName, state.schema);
330
- let hasSubList = false;
331
- node.descendants((child) => {
332
- if (child.type === nodeType) {
333
- hasSubList = true;
334
- }
335
- });
336
- return hasSubList;
337
- };
338
-
339
426
  // src/keymap/listHelpers/handleBackspace.ts
340
427
  var handleBackspace = (editor, name, parentListTypes) => {
341
428
  if (editor.commands.undoInputRule()) {
@@ -366,16 +453,6 @@ var handleBackspace = (editor, name, parentListTypes) => {
366
453
  if (!(0, import_core6.isAtStartOfNode)(editor.state)) {
367
454
  return false;
368
455
  }
369
- const listItemPos = findListItemPos(name, editor.state);
370
- if (!listItemPos) {
371
- return false;
372
- }
373
- const $prev = editor.state.doc.resolve(listItemPos.$pos.pos - 2);
374
- const prevNode = $prev.node(listItemPos.depth);
375
- const previousListItemHasSubList = listItemHasSubList(name, editor.state, prevNode);
376
- if (hasListItemBefore(name, editor.state) && !previousListItemHasSubList) {
377
- return editor.commands.joinItemBackward();
378
- }
379
456
  return editor.chain().liftListItem(name).run();
380
457
  };
381
458
 
@@ -444,8 +521,38 @@ var hasListItemAfter = (typeOrName, state) => {
444
521
  return true;
445
522
  };
446
523
 
524
+ // src/keymap/listHelpers/hasListItemBefore.ts
525
+ var hasListItemBefore = (typeOrName, state) => {
526
+ var _a;
527
+ const { $anchor } = state.selection;
528
+ const $targetPos = state.doc.resolve($anchor.pos - 2);
529
+ if ($targetPos.index() === 0) {
530
+ return false;
531
+ }
532
+ if (((_a = $targetPos.nodeBefore) == null ? void 0 : _a.type.name) !== typeOrName) {
533
+ return false;
534
+ }
535
+ return true;
536
+ };
537
+
538
+ // src/keymap/listHelpers/listItemHasSubList.ts
539
+ var import_core8 = require("@tiptap/core");
540
+ var listItemHasSubList = (typeOrName, state, node) => {
541
+ if (!node) {
542
+ return false;
543
+ }
544
+ const nodeType = (0, import_core8.getNodeType)(typeOrName, state.schema);
545
+ let hasSubList = false;
546
+ node.descendants((child) => {
547
+ if (child.type === nodeType) {
548
+ hasSubList = true;
549
+ }
550
+ });
551
+ return hasSubList;
552
+ };
553
+
447
554
  // src/keymap/list-keymap.ts
448
- var ListKeymap = import_core8.Extension.create({
555
+ var ListKeymap = import_core9.Extension.create({
449
556
  name: "listKeymap",
450
557
  addOptions() {
451
558
  return {
@@ -516,17 +623,24 @@ var ListKeymap = import_core8.Extension.create({
516
623
  });
517
624
 
518
625
  // src/kit/index.ts
519
- var import_core12 = require("@tiptap/core");
626
+ var import_core13 = require("@tiptap/core");
520
627
 
521
628
  // src/ordered-list/ordered-list.ts
522
- var import_core9 = require("@tiptap/core");
629
+ var import_core10 = require("@tiptap/core");
523
630
 
524
631
  // src/ordered-list/utils.ts
525
632
  var ORDERED_LIST_ITEM_REGEX = /^(\s*)(\d+)\.\s+(.*)$/;
526
633
  var INDENTED_LINE_REGEX = /^\s/;
527
634
  function isBlockContentLine(line) {
528
635
  const trimmedLine = line.trimStart();
529
- return /^[-+*]\s+/.test(trimmedLine) || /^\d+\.\s+/.test(trimmedLine) || /^>\s?/.test(trimmedLine) || /^```/.test(trimmedLine) || /^~~~/.test(trimmedLine);
636
+ return (
637
+ // oxlint-disable-next-line prefer-string-starts-ends-with
638
+ /^[-+*]\s+/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
639
+ /^\d+\.\s+/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
640
+ /^>\s?/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
641
+ /^```/.test(trimmedLine) || // oxlint-disable-next-line prefer-string-starts-ends-with
642
+ /^~~~/.test(trimmedLine)
643
+ );
530
644
  }
531
645
  function splitItemContent(contentLines) {
532
646
  const paragraphLines = [];
@@ -691,7 +805,7 @@ function parseListItems(items, helpers) {
691
805
  var ListItemName2 = "listItem";
692
806
  var TextStyleName2 = "textStyle";
693
807
  var orderedListInputRegex = /^(\d+)\.\s$/;
694
- var OrderedList = import_core9.Node.create({
808
+ var OrderedList = import_core10.Node.create({
695
809
  name: "orderedList",
696
810
  addOptions() {
697
811
  return {
@@ -728,7 +842,7 @@ var OrderedList = import_core9.Node.create({
728
842
  },
729
843
  renderHTML({ HTMLAttributes }) {
730
844
  const { start, ...attributesWithoutStart } = HTMLAttributes;
731
- return start === 1 ? ["ol", (0, import_core9.mergeAttributes)(this.options.HTMLAttributes, attributesWithoutStart), 0] : ["ol", (0, import_core9.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes), 0];
845
+ return start === 1 ? ["ol", (0, import_core10.mergeAttributes)(this.options.HTMLAttributes, attributesWithoutStart), 0] : ["ol", (0, import_core10.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes), 0];
732
846
  },
733
847
  markdownTokenName: "list",
734
848
  parseMarkdown: (token, helpers) => {
@@ -803,14 +917,14 @@ var OrderedList = import_core9.Node.create({
803
917
  };
804
918
  },
805
919
  addInputRules() {
806
- let inputRule = (0, import_core9.wrappingInputRule)({
920
+ let inputRule = (0, import_core10.wrappingInputRule)({
807
921
  find: orderedListInputRegex,
808
922
  type: this.type,
809
923
  getAttributes: (match) => ({ start: +match[1] }),
810
924
  joinPredicate: (match, node) => node.childCount + node.attrs.start === +match[1]
811
925
  });
812
926
  if (this.options.keepMarks || this.options.keepAttributes) {
813
- inputRule = (0, import_core9.wrappingInputRule)({
927
+ inputRule = (0, import_core10.wrappingInputRule)({
814
928
  find: orderedListInputRegex,
815
929
  type: this.type,
816
930
  keepMarks: this.options.keepMarks,
@@ -825,9 +939,9 @@ var OrderedList = import_core9.Node.create({
825
939
  });
826
940
 
827
941
  // src/task-item/task-item.ts
828
- var import_core10 = require("@tiptap/core");
942
+ var import_core11 = require("@tiptap/core");
829
943
  var inputRegex = /^\s*(\[([( |x])?\])\s$/;
830
- var TaskItem = import_core10.Node.create({
944
+ var TaskItem = import_core11.Node.create({
831
945
  name: "taskItem",
832
946
  addOptions() {
833
947
  return {
@@ -867,7 +981,7 @@ var TaskItem = import_core10.Node.create({
867
981
  renderHTML({ node, HTMLAttributes }) {
868
982
  return [
869
983
  "li",
870
- (0, import_core10.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, {
984
+ (0, import_core11.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, {
871
985
  "data-type": this.name
872
986
  }),
873
987
  [
@@ -903,7 +1017,13 @@ var TaskItem = import_core10.Node.create({
903
1017
  var _a;
904
1018
  const checkedChar = ((_a = node.attrs) == null ? void 0 : _a.checked) ? "x" : " ";
905
1019
  const prefix = `- [${checkedChar}] `;
906
- return (0, import_core10.renderNestedMarkdownContent)(node, h, prefix);
1020
+ return (0, import_core11.renderNestedMarkdownContent)(node, h, prefix);
1021
+ },
1022
+ addExtensions() {
1023
+ if (!this.options.nested) {
1024
+ return [];
1025
+ }
1026
+ return [createBranchingListDeleteKeymap(this.name, [this.options.taskListTypeName])];
907
1027
  },
908
1028
  addKeyboardShortcuts() {
909
1029
  const shortcuts = {
@@ -981,7 +1101,7 @@ var TaskItem = import_core10.Node.create({
981
1101
  checkbox.checked = updatedNode.attrs.checked;
982
1102
  updateA11Y(updatedNode);
983
1103
  const extensionAttributes = editor.extensionManager.attributes;
984
- const newHTMLAttributes = (0, import_core10.getRenderedAttributes)(updatedNode, extensionAttributes);
1104
+ const newHTMLAttributes = (0, import_core11.getRenderedAttributes)(updatedNode, extensionAttributes);
985
1105
  const newKeys = new Set(Object.keys(newHTMLAttributes));
986
1106
  const staticAttrs = this.options.HTMLAttributes;
987
1107
  prevRenderedAttributeKeys.forEach((key) => {
@@ -1012,7 +1132,7 @@ var TaskItem = import_core10.Node.create({
1012
1132
  },
1013
1133
  addInputRules() {
1014
1134
  return [
1015
- (0, import_core10.wrappingInputRule)({
1135
+ (0, import_core11.wrappingInputRule)({
1016
1136
  find: inputRegex,
1017
1137
  type: this.type,
1018
1138
  getAttributes: (match) => ({
@@ -1024,8 +1144,8 @@ var TaskItem = import_core10.Node.create({
1024
1144
  });
1025
1145
 
1026
1146
  // src/task-list/task-list.ts
1027
- var import_core11 = require("@tiptap/core");
1028
- var TaskList = import_core11.Node.create({
1147
+ var import_core12 = require("@tiptap/core");
1148
+ var TaskList = import_core12.Node.create({
1029
1149
  name: "taskList",
1030
1150
  addOptions() {
1031
1151
  return {
@@ -1046,7 +1166,11 @@ var TaskList = import_core11.Node.create({
1046
1166
  ];
1047
1167
  },
1048
1168
  renderHTML({ HTMLAttributes }) {
1049
- return ["ul", (0, import_core11.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, { "data-type": this.name }), 0];
1169
+ return [
1170
+ "ul",
1171
+ (0, import_core12.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes, { "data-type": this.name }),
1172
+ 0
1173
+ ];
1050
1174
  },
1051
1175
  parseMarkdown: (token, h) => {
1052
1176
  return h.createNode("taskList", {}, h.parseChildren(token.items || []));
@@ -1067,7 +1191,7 @@ var TaskList = import_core11.Node.create({
1067
1191
  },
1068
1192
  tokenize(src, tokens, lexer) {
1069
1193
  const parseTaskListContent = (content) => {
1070
- const nestedResult = (0, import_core11.parseIndentedBlocks)(
1194
+ const nestedResult = (0, import_core12.parseIndentedBlocks)(
1071
1195
  content,
1072
1196
  {
1073
1197
  itemPattern: /^(\s*)([-+*])\s+\[([ xX])\]\s+(.*)$/,
@@ -1102,7 +1226,7 @@ var TaskList = import_core11.Node.create({
1102
1226
  }
1103
1227
  return lexer.blockTokens(content);
1104
1228
  };
1105
- const result = (0, import_core11.parseIndentedBlocks)(
1229
+ const result = (0, import_core12.parseIndentedBlocks)(
1106
1230
  src,
1107
1231
  {
1108
1232
  itemPattern: /^(\s*)([-+*])\s+\[([ xX])\]\s+(.*)$/,
@@ -1154,7 +1278,7 @@ var TaskList = import_core11.Node.create({
1154
1278
  });
1155
1279
 
1156
1280
  // src/kit/index.ts
1157
- var ListKit = import_core12.Extension.create({
1281
+ var ListKit = import_core13.Extension.create({
1158
1282
  name: "listKit",
1159
1283
  addExtensions() {
1160
1284
  const extensions = [];