@atlaskit/editor-plugin-list 0.2.0 → 1.0.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 (181) hide show
  1. package/.eslintrc.js +14 -0
  2. package/CHANGELOG.md +10 -0
  3. package/README.md +1 -1
  4. package/dist/cjs/actions/conversions.js +153 -0
  5. package/dist/cjs/actions/indent-list-items-selected.js +125 -0
  6. package/dist/cjs/actions/indent-list.js +49 -0
  7. package/dist/cjs/actions/join-list-items-forward.js +59 -0
  8. package/dist/cjs/actions/join-list-items-scenarios/index.js +40 -0
  9. package/dist/cjs/actions/join-list-items-scenarios/join-list-item-with-paragraph.js +88 -0
  10. package/dist/cjs/actions/join-list-items-scenarios/join-list-item-with-parent-nested-list.js +85 -0
  11. package/dist/cjs/actions/join-list-items-scenarios/join-nested-list-with-parent-list-item.js +79 -0
  12. package/dist/cjs/actions/join-list-items-scenarios/join-paragraph-with-list.js +45 -0
  13. package/dist/cjs/actions/join-list-items-scenarios/join-sibling-list-items.js +56 -0
  14. package/dist/cjs/actions/merge-lists.js +27 -0
  15. package/dist/cjs/actions/outdent-list-items-selected.js +291 -0
  16. package/dist/cjs/actions/wrap-and-join-lists.js +100 -0
  17. package/dist/cjs/commands/indent-list.js +71 -0
  18. package/dist/cjs/commands/index.js +350 -0
  19. package/dist/cjs/commands/isFirstChildOfParent.js +12 -0
  20. package/dist/cjs/commands/join-list-item-forward.js +61 -0
  21. package/dist/cjs/commands/listBackspace.js +284 -0
  22. package/dist/cjs/commands/outdent-list.js +70 -0
  23. package/dist/cjs/index.js +8 -1
  24. package/dist/cjs/messages.js +37 -0
  25. package/dist/cjs/plugin.js +133 -0
  26. package/dist/cjs/pm-plugins/input-rules/create-list-input-rule.js +63 -0
  27. package/dist/cjs/pm-plugins/input-rules/index.js +38 -0
  28. package/dist/cjs/pm-plugins/input-rules/wrapping-join-rule.js +60 -0
  29. package/dist/cjs/pm-plugins/keymap.js +27 -0
  30. package/dist/cjs/pm-plugins/main.js +166 -0
  31. package/dist/cjs/transforms.js +99 -0
  32. package/dist/cjs/types.js +4 -1
  33. package/dist/cjs/utils/analytics.js +22 -0
  34. package/dist/cjs/utils/find.js +68 -0
  35. package/dist/cjs/utils/indentation.js +22 -0
  36. package/dist/cjs/utils/mark.js +40 -0
  37. package/dist/cjs/utils/node.js +16 -0
  38. package/dist/cjs/utils/selection.js +95 -0
  39. package/dist/es2019/actions/conversions.js +160 -0
  40. package/dist/es2019/actions/indent-list-items-selected.js +124 -0
  41. package/dist/es2019/actions/indent-list.js +44 -0
  42. package/dist/es2019/actions/join-list-items-forward.js +54 -0
  43. package/dist/es2019/actions/join-list-items-scenarios/index.js +5 -0
  44. package/dist/es2019/actions/join-list-items-scenarios/join-list-item-with-paragraph.js +74 -0
  45. package/dist/es2019/actions/join-list-items-scenarios/join-list-item-with-parent-nested-list.js +77 -0
  46. package/dist/es2019/actions/join-list-items-scenarios/join-nested-list-with-parent-list-item.js +71 -0
  47. package/dist/es2019/actions/join-list-items-scenarios/join-paragraph-with-list.js +37 -0
  48. package/dist/es2019/actions/join-list-items-scenarios/join-sibling-list-items.js +48 -0
  49. package/dist/es2019/actions/merge-lists.js +24 -0
  50. package/dist/es2019/actions/outdent-list-items-selected.js +295 -0
  51. package/dist/es2019/actions/wrap-and-join-lists.js +93 -0
  52. package/dist/es2019/commands/indent-list.js +62 -0
  53. package/dist/es2019/commands/index.js +326 -0
  54. package/dist/es2019/commands/isFirstChildOfParent.js +7 -0
  55. package/dist/es2019/commands/join-list-item-forward.js +53 -0
  56. package/dist/es2019/commands/listBackspace.js +276 -0
  57. package/dist/es2019/commands/outdent-list.js +60 -0
  58. package/dist/es2019/index.js +1 -1
  59. package/dist/es2019/messages.js +29 -0
  60. package/dist/es2019/plugin.js +121 -0
  61. package/dist/es2019/pm-plugins/input-rules/create-list-input-rule.js +56 -0
  62. package/dist/es2019/pm-plugins/input-rules/index.js +35 -0
  63. package/dist/es2019/pm-plugins/input-rules/wrapping-join-rule.js +55 -0
  64. package/dist/es2019/pm-plugins/keymap.js +19 -0
  65. package/dist/es2019/pm-plugins/main.js +156 -0
  66. package/dist/es2019/transforms.js +101 -0
  67. package/dist/es2019/types.js +1 -1
  68. package/dist/es2019/utils/analytics.js +12 -0
  69. package/dist/es2019/utils/find.js +61 -0
  70. package/dist/es2019/utils/indentation.js +15 -0
  71. package/dist/es2019/utils/mark.js +30 -0
  72. package/dist/es2019/utils/node.js +12 -0
  73. package/dist/es2019/utils/selection.js +96 -0
  74. package/dist/esm/actions/conversions.js +147 -0
  75. package/dist/esm/actions/indent-list-items-selected.js +117 -0
  76. package/dist/esm/actions/indent-list.js +43 -0
  77. package/dist/esm/actions/join-list-items-forward.js +52 -0
  78. package/dist/esm/actions/join-list-items-scenarios/index.js +5 -0
  79. package/dist/esm/actions/join-list-items-scenarios/join-list-item-with-paragraph.js +81 -0
  80. package/dist/esm/actions/join-list-items-scenarios/join-list-item-with-parent-nested-list.js +78 -0
  81. package/dist/esm/actions/join-list-items-scenarios/join-nested-list-with-parent-list-item.js +72 -0
  82. package/dist/esm/actions/join-list-items-scenarios/join-paragraph-with-list.js +38 -0
  83. package/dist/esm/actions/join-list-items-scenarios/join-sibling-list-items.js +49 -0
  84. package/dist/esm/actions/merge-lists.js +21 -0
  85. package/dist/esm/actions/outdent-list-items-selected.js +283 -0
  86. package/dist/esm/actions/wrap-and-join-lists.js +94 -0
  87. package/dist/esm/commands/indent-list.js +63 -0
  88. package/dist/esm/commands/index.js +324 -0
  89. package/dist/esm/commands/isFirstChildOfParent.js +5 -0
  90. package/dist/esm/commands/join-list-item-forward.js +53 -0
  91. package/dist/esm/commands/listBackspace.js +275 -0
  92. package/dist/esm/commands/outdent-list.js +62 -0
  93. package/dist/esm/index.js +1 -1
  94. package/dist/esm/messages.js +29 -0
  95. package/dist/esm/plugin.js +126 -0
  96. package/dist/esm/pm-plugins/input-rules/create-list-input-rule.js +57 -0
  97. package/dist/esm/pm-plugins/input-rules/index.js +32 -0
  98. package/dist/esm/pm-plugins/input-rules/wrapping-join-rule.js +54 -0
  99. package/dist/esm/pm-plugins/keymap.js +19 -0
  100. package/dist/esm/pm-plugins/main.js +156 -0
  101. package/dist/esm/transforms.js +91 -0
  102. package/dist/esm/types.js +1 -1
  103. package/dist/esm/utils/analytics.js +12 -0
  104. package/dist/esm/utils/find.js +59 -0
  105. package/dist/esm/utils/indentation.js +15 -0
  106. package/dist/esm/utils/mark.js +33 -0
  107. package/dist/esm/utils/node.js +10 -0
  108. package/dist/esm/utils/selection.js +81 -0
  109. package/dist/types/actions/conversions.d.ts +6 -0
  110. package/dist/types/actions/indent-list-items-selected.d.ts +2 -0
  111. package/dist/types/actions/indent-list.d.ts +2 -0
  112. package/dist/types/actions/join-list-items-forward.d.ts +13 -0
  113. package/dist/types/actions/join-list-items-scenarios/index.d.ts +5 -0
  114. package/dist/types/actions/join-list-items-scenarios/join-list-item-with-paragraph.d.ts +9 -0
  115. package/dist/types/actions/join-list-items-scenarios/join-list-item-with-parent-nested-list.d.ts +9 -0
  116. package/dist/types/actions/join-list-items-scenarios/join-nested-list-with-parent-list-item.d.ts +9 -0
  117. package/dist/types/actions/join-list-items-scenarios/join-paragraph-with-list.d.ts +9 -0
  118. package/dist/types/actions/join-list-items-scenarios/join-sibling-list-items.d.ts +9 -0
  119. package/dist/types/actions/merge-lists.d.ts +7 -0
  120. package/dist/types/actions/outdent-list-items-selected.d.ts +3 -0
  121. package/dist/types/actions/wrap-and-join-lists.d.ts +17 -0
  122. package/dist/types/commands/indent-list.d.ts +6 -0
  123. package/dist/types/commands/index.d.ts +16 -0
  124. package/dist/types/commands/isFirstChildOfParent.d.ts +2 -0
  125. package/dist/types/commands/join-list-item-forward.d.ts +3 -0
  126. package/dist/types/commands/listBackspace.d.ts +10 -0
  127. package/dist/types/commands/outdent-list.d.ts +6 -0
  128. package/dist/types/index.d.ts +2 -1
  129. package/dist/types/messages.d.ts +27 -0
  130. package/dist/types/plugin.d.ts +2 -0
  131. package/dist/types/pm-plugins/input-rules/create-list-input-rule.d.ts +11 -0
  132. package/dist/types/pm-plugins/input-rules/index.d.ts +5 -0
  133. package/dist/types/pm-plugins/input-rules/wrapping-join-rule.d.ts +13 -0
  134. package/dist/types/pm-plugins/keymap.d.ts +5 -0
  135. package/dist/types/pm-plugins/main.d.ts +11 -0
  136. package/dist/types/transforms.d.ts +4 -0
  137. package/dist/types/types.d.ts +4 -6
  138. package/dist/types/utils/analytics.d.ts +5 -0
  139. package/dist/types/utils/find.d.ts +10 -0
  140. package/dist/types/utils/indentation.d.ts +2 -0
  141. package/dist/types/utils/mark.d.ts +8 -0
  142. package/dist/types/utils/node.d.ts +2 -0
  143. package/dist/types/utils/selection.d.ts +14 -0
  144. package/dist/types-ts4.5/actions/conversions.d.ts +6 -0
  145. package/dist/types-ts4.5/actions/indent-list-items-selected.d.ts +2 -0
  146. package/dist/types-ts4.5/actions/indent-list.d.ts +2 -0
  147. package/dist/types-ts4.5/actions/join-list-items-forward.d.ts +16 -0
  148. package/dist/types-ts4.5/actions/join-list-items-scenarios/index.d.ts +5 -0
  149. package/dist/types-ts4.5/actions/join-list-items-scenarios/join-list-item-with-paragraph.d.ts +9 -0
  150. package/dist/types-ts4.5/actions/join-list-items-scenarios/join-list-item-with-parent-nested-list.d.ts +9 -0
  151. package/dist/types-ts4.5/actions/join-list-items-scenarios/join-nested-list-with-parent-list-item.d.ts +9 -0
  152. package/dist/types-ts4.5/actions/join-list-items-scenarios/join-paragraph-with-list.d.ts +9 -0
  153. package/dist/types-ts4.5/actions/join-list-items-scenarios/join-sibling-list-items.d.ts +9 -0
  154. package/dist/types-ts4.5/actions/merge-lists.d.ts +7 -0
  155. package/dist/types-ts4.5/actions/outdent-list-items-selected.d.ts +3 -0
  156. package/dist/types-ts4.5/actions/wrap-and-join-lists.d.ts +17 -0
  157. package/dist/types-ts4.5/commands/indent-list.d.ts +6 -0
  158. package/dist/types-ts4.5/commands/index.d.ts +16 -0
  159. package/dist/types-ts4.5/commands/isFirstChildOfParent.d.ts +2 -0
  160. package/dist/types-ts4.5/commands/join-list-item-forward.d.ts +3 -0
  161. package/dist/types-ts4.5/commands/listBackspace.d.ts +13 -0
  162. package/dist/types-ts4.5/commands/outdent-list.d.ts +6 -0
  163. package/dist/types-ts4.5/index.d.ts +2 -1
  164. package/dist/types-ts4.5/messages.d.ts +27 -0
  165. package/dist/types-ts4.5/plugin.d.ts +2 -0
  166. package/dist/types-ts4.5/pm-plugins/input-rules/create-list-input-rule.d.ts +11 -0
  167. package/dist/types-ts4.5/pm-plugins/input-rules/index.d.ts +5 -0
  168. package/dist/types-ts4.5/pm-plugins/input-rules/wrapping-join-rule.d.ts +13 -0
  169. package/dist/types-ts4.5/pm-plugins/keymap.d.ts +5 -0
  170. package/dist/types-ts4.5/pm-plugins/main.d.ts +11 -0
  171. package/dist/types-ts4.5/transforms.d.ts +4 -0
  172. package/dist/types-ts4.5/types.d.ts +4 -6
  173. package/dist/types-ts4.5/utils/analytics.d.ts +5 -0
  174. package/dist/types-ts4.5/utils/find.d.ts +10 -0
  175. package/dist/types-ts4.5/utils/indentation.d.ts +2 -0
  176. package/dist/types-ts4.5/utils/mark.d.ts +8 -0
  177. package/dist/types-ts4.5/utils/node.d.ts +2 -0
  178. package/dist/types-ts4.5/utils/selection.d.ts +14 -0
  179. package/package.json +8 -5
  180. package/report.api.md +6 -2
  181. package/tmp/api-report-tmp.d.ts +4 -1
@@ -0,0 +1,61 @@
1
+ import { isListItemNode, isListNode } from '@atlaskit/editor-common/utils';
2
+ import { findParentNodeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
3
+ export function findFirstParentListNode($pos) {
4
+ const currentNode = $pos.doc.nodeAt($pos.pos);
5
+ let listNodePosition = null;
6
+ if (isListNode(currentNode)) {
7
+ listNodePosition = $pos.pos;
8
+ } else {
9
+ const result = findParentNodeClosestToPos($pos, isListNode);
10
+ listNodePosition = result && result.pos;
11
+ }
12
+ if (listNodePosition == null) {
13
+ return null;
14
+ }
15
+ const node = $pos.doc.nodeAt(listNodePosition);
16
+ if (!node) {
17
+ return null;
18
+ }
19
+ return {
20
+ node,
21
+ pos: listNodePosition
22
+ };
23
+ }
24
+ export function findFirstParentListItemNode($pos) {
25
+ const currentNode = $pos.doc.nodeAt($pos.pos);
26
+ const listItemNodePosition = isListItemNode(currentNode) ? $pos : findParentNodeClosestToPos($pos, isListItemNode);
27
+ if (!listItemNodePosition || listItemNodePosition.pos === null) {
28
+ return null;
29
+ }
30
+ const node = $pos.doc.nodeAt(listItemNodePosition.pos);
31
+ if (!node) {
32
+ return null;
33
+ }
34
+ return {
35
+ node: node,
36
+ pos: listItemNodePosition.pos
37
+ };
38
+ }
39
+ export const findRootParentListNode = $pos => {
40
+ const {
41
+ doc
42
+ } = $pos;
43
+ if ($pos.pos + 1 > doc.content.size) {
44
+ return null;
45
+ }
46
+ if ($pos.depth === 0) {
47
+ return doc.resolve($pos.pos + 1);
48
+ }
49
+ const currentNode = doc.nodeAt($pos.pos);
50
+ const beforePosition = $pos.before();
51
+ const nodeBefore = doc.nodeAt(beforePosition);
52
+ if (isListNode(currentNode) && !isListItemNode(nodeBefore)) {
53
+ return doc.resolve($pos.pos + 1);
54
+ }
55
+ const parentList = findParentNodeClosestToPos($pos, isListNode);
56
+ if (!parentList) {
57
+ return null;
58
+ }
59
+ const listNodePosition = doc.resolve(parentList.pos);
60
+ return findRootParentListNode(listNodePosition);
61
+ };
@@ -0,0 +1,15 @@
1
+ import { isListItemNode, isListNode } from '@atlaskit/editor-common/utils';
2
+ // This will return (depth - 1) for root list parent of a list.
3
+ export const getListLiftTarget = resPos => {
4
+ let target = resPos.depth;
5
+ for (let i = resPos.depth; i > 0; i--) {
6
+ const node = resPos.node(i);
7
+ if (isListNode(node)) {
8
+ target = i;
9
+ }
10
+ if (!isListItemNode(node) && !isListNode(node)) {
11
+ break;
12
+ }
13
+ }
14
+ return target - 1;
15
+ };
@@ -0,0 +1,30 @@
1
+ export const sanitiseMarksInSelection = (tr, newParentType) => {
2
+ const {
3
+ from,
4
+ to
5
+ } = tr.selection;
6
+ const nodesSanitized = [];
7
+ tr.doc.nodesBetween(from, to, (node, pos, parent) => {
8
+ if (node.isText) {
9
+ return false;
10
+ }
11
+ // Skip expands and layouts if they are outside selection
12
+ // but continue to iterate over their children.
13
+ if (['expand', 'layoutSection'].includes(node.type.name) && (pos < from || pos > to)) {
14
+ return true;
15
+ }
16
+ node.marks.forEach(mark => {
17
+ if (!(parent !== null && parent !== void 0 && parent.type.allowsMarkType(mark.type)) || newParentType && !newParentType.allowsMarkType(mark.type)) {
18
+ const filteredMarks = node.marks.filter(m => m.type !== mark.type);
19
+ const position = pos > 0 ? pos : 0;
20
+ const marksRemoved = node.marks.filter(m => m.type === mark.type);
21
+ nodesSanitized.push({
22
+ node,
23
+ marksRemoved
24
+ });
25
+ tr.setNodeMarkup(position, undefined, node.attrs, filteredMarks);
26
+ }
27
+ });
28
+ });
29
+ return nodesSanitized;
30
+ };
@@ -0,0 +1,12 @@
1
+ import { isListItemNode } from '@atlaskit/editor-common/utils';
2
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
3
+ export function isListNodeValidContent(node) {
4
+ const {
5
+ bulletList
6
+ } = node.type.schema.nodes;
7
+ if (!bulletList) {
8
+ return false;
9
+ }
10
+ const listFragment = Fragment.from(bulletList.createAndFill());
11
+ return !isListItemNode(node) && node.type.validContent(listFragment);
12
+ }
@@ -0,0 +1,96 @@
1
+ import { GapCursorSelection } from '@atlaskit/editor-common/selection';
2
+ import { isListItemNode, isListNode, isParagraphNode } from '@atlaskit/editor-common/utils';
3
+ import { findWrapping } from '@atlaskit/editor-prosemirror/transform';
4
+ import { findParentNodeOfType, hasParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
5
+ export const isPosInsideParagraph = $pos => {
6
+ return $pos.parent.type.name === 'paragraph';
7
+ };
8
+ export const isPosInsideList = $pos => {
9
+ const posGrandParent = $pos.node(-1);
10
+ return isListItemNode($pos.parent) || isListNode($pos.parent) || isListItemNode(posGrandParent);
11
+ };
12
+ export const isWrappingPossible = (nodeType, selection) => {
13
+ const {
14
+ $from,
15
+ $to
16
+ } = selection;
17
+ let range;
18
+ if (selection instanceof GapCursorSelection && $from.nodeAfter) {
19
+ const nodeSize = $from.nodeAfter.nodeSize || 1;
20
+ range = $from.blockRange($from.doc.resolve($from.pos + nodeSize));
21
+ } else {
22
+ range = $from.blockRange($to);
23
+ }
24
+ if (!range) {
25
+ return false;
26
+ }
27
+ const wrap = findWrapping(range, nodeType);
28
+ if (!wrap) {
29
+ return false;
30
+ }
31
+ return true;
32
+ };
33
+
34
+ // canOutdent
35
+ export const isInsideListItem = state => {
36
+ const {
37
+ parent
38
+ } = state.selection.$from;
39
+ const {
40
+ listItem
41
+ } = state.schema.nodes;
42
+ if (state.selection instanceof GapCursorSelection) {
43
+ return isListItemNode(parent);
44
+ }
45
+ return hasParentNodeOfType(listItem)(state.selection) && isParagraphNode(parent);
46
+ };
47
+ export const isInsideTableCell = state => {
48
+ const {
49
+ tableCell,
50
+ tableHeader
51
+ } = state.schema.nodes;
52
+ return !!findParentNodeOfType([tableCell, tableHeader])(state.selection);
53
+ };
54
+ export const canJoinToPreviousListItem = state => {
55
+ const {
56
+ $from
57
+ } = state.selection;
58
+ const $before = state.doc.resolve($from.pos - 1);
59
+ let nodeBefore = $before ? $before.nodeBefore : null;
60
+ if (state.selection instanceof GapCursorSelection) {
61
+ nodeBefore = $from.nodeBefore;
62
+ }
63
+ return isListNode(nodeBefore);
64
+ };
65
+ export const selectionContainsList = tr => {
66
+ const {
67
+ selection: {
68
+ from,
69
+ to
70
+ }
71
+ } = tr;
72
+ let foundListNode = null;
73
+ tr.doc.nodesBetween(from, to, node => {
74
+ if (isListNode(node)) {
75
+ foundListNode = node;
76
+ }
77
+ if (foundListNode) {
78
+ return false;
79
+ }
80
+ return true;
81
+ });
82
+ return foundListNode;
83
+ };
84
+ export const createListNodeRange = ({
85
+ selection
86
+ }) => {
87
+ const {
88
+ $from,
89
+ $to
90
+ } = selection;
91
+ const range = $from.blockRange($to, isListNode);
92
+ if (!range) {
93
+ return null;
94
+ }
95
+ return range;
96
+ };
@@ -0,0 +1,147 @@
1
+ import { joinSiblingLists } from '@atlaskit/editor-common/lists';
2
+ import { GapCursorSelection } from '@atlaskit/editor-common/selection';
3
+ import { isEmptyParagraph, isListNode } from '@atlaskit/editor-common/utils';
4
+ import { NodeRange } from '@atlaskit/editor-prosemirror/model';
5
+ import { TextSelection } from '@atlaskit/editor-prosemirror/state';
6
+ import { findWrapping } from '@atlaskit/editor-prosemirror/transform';
7
+ import { findParentNodeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
8
+ import { findFirstParentListNode } from '../utils/find';
9
+ export function convertListType(_ref) {
10
+ var tr = _ref.tr,
11
+ nextListNodeType = _ref.nextListNodeType;
12
+ var doc = tr.doc,
13
+ _tr$selection = tr.selection,
14
+ $from = _tr$selection.$from,
15
+ $to = _tr$selection.$to;
16
+ var listRange;
17
+ if (tr.selection instanceof GapCursorSelection) {
18
+ var _$from$nodeAfter;
19
+ var nodeSize = ((_$from$nodeAfter = $from.nodeAfter) === null || _$from$nodeAfter === void 0 ? void 0 : _$from$nodeAfter.nodeSize) || 1;
20
+ listRange = $from.blockRange($from.doc.resolve($from.pos + nodeSize));
21
+ } else {
22
+ listRange = $from.blockRange($to, isListNode);
23
+ }
24
+ if (listRange) {
25
+ return convertSelectedList({
26
+ tr: tr,
27
+ nextListNodeType: nextListNodeType
28
+ });
29
+ }
30
+ var nodeRangeAroundList = $from.blockRange($to);
31
+ if (!nodeRangeAroundList) {
32
+ return;
33
+ }
34
+ var parentNode = nodeRangeAroundList.parent;
35
+ var startIndex = nodeRangeAroundList.startIndex,
36
+ endIndex = nodeRangeAroundList.endIndex,
37
+ depth = nodeRangeAroundList.depth;
38
+
39
+ // Checking for invalid nodes to prevent conversion
40
+ // eg. a panel cannot be wrapped in a list so return
41
+ // It will skip this check if the selection begins within a list
42
+ // This is to match the behaviour of the toolbar buttons being disabled
43
+ if (!findFirstParentListNode($from)) {
44
+ for (var i = startIndex; i < endIndex; i++) {
45
+ var position = nodeRangeAroundList.$from.posAtIndex(i, depth);
46
+ var resolvedPosition = doc.resolve(position);
47
+ var currentChild = parentNode.child(i);
48
+ var currentNodeRange = resolvedPosition.blockRange(tr.doc.resolve(position + currentChild.nodeSize));
49
+ if (currentNodeRange && !isListNode(currentChild) && !findWrapping(currentNodeRange, nextListNodeType)) {
50
+ return;
51
+ }
52
+ }
53
+ }
54
+
55
+ // Checking for any non list nodes and wrapping them in a list
56
+ // so they can be converted
57
+ tr.doc.nodesBetween(nodeRangeAroundList.start, nodeRangeAroundList.end, function (node, pos) {
58
+ // Skip over any nodes that are part of a list
59
+ if (findFirstParentListNode(tr.doc.resolve(tr.mapping.map(pos)))) {
60
+ return false;
61
+ }
62
+
63
+ // The following applies to suitable nodes that are not within a list
64
+ var currentNodeNotWrappedInList = node;
65
+ var isNotAnEmptyParagraphAndIsParagraphOrLeafNode = !isEmptyParagraph(currentNodeNotWrappedInList) && (!node.type.isBlock || node.type.name === 'paragraph');
66
+ if (isNotAnEmptyParagraphAndIsParagraphOrLeafNode && nodeRangeAroundList) {
67
+ var remainingNodeRange = new NodeRange(tr.doc.resolve(tr.mapping.map(pos)), tr.doc.resolve(tr.mapping.map(pos) + currentNodeNotWrappedInList.nodeSize), nodeRangeAroundList.depth);
68
+ convertAroundList({
69
+ tr: tr,
70
+ nextListNodeType: nextListNodeType,
71
+ nodeRange: remainingNodeRange
72
+ });
73
+ return false;
74
+ }
75
+ });
76
+ convertSelectedList({
77
+ tr: tr,
78
+ nextListNodeType: nextListNodeType
79
+ });
80
+ if (tr.docChanged) {
81
+ joinSiblingLists({
82
+ tr: tr,
83
+ forceListType: nextListNodeType
84
+ });
85
+ }
86
+ }
87
+ var convertSelectedList = function convertSelectedList(_ref2) {
88
+ var tr = _ref2.tr,
89
+ nextListNodeType = _ref2.nextListNodeType;
90
+ var selection = tr.selection,
91
+ _tr$selection2 = tr.selection,
92
+ from = _tr$selection2.from,
93
+ to = _tr$selection2.to;
94
+ var codeBlock = tr.doc.type.schema.nodes.codeBlock;
95
+ // get the positions of all the leaf nodes within the selection
96
+ var nodePositions = [];
97
+ if (selection instanceof TextSelection && selection.$cursor || selection instanceof GapCursorSelection) {
98
+ nodePositions.push(from);
99
+ } else {
100
+ // nodesBetween doesn't return leaf nodes that are outside of from and to
101
+ tr.doc.nodesBetween(from, to, function (node, pos) {
102
+ // isLeaf is false for empty codeBlock so adding additional check for childCount
103
+ if (!node.isLeaf && !(node.type === codeBlock && node.childCount === 0)) {
104
+ return true;
105
+ }
106
+ nodePositions.push(pos);
107
+ });
108
+ }
109
+
110
+ // use those positions to get the closest parent list nodes
111
+ nodePositions.reduce(function (acc, pos) {
112
+ var closestParentListNode = findParentNodeClosestToPos(tr.doc.resolve(pos), isListNode);
113
+ if (!closestParentListNode) {
114
+ return acc;
115
+ }
116
+
117
+ // don't add duplicates if the parent has already been added into the array
118
+ var existingParent = acc.find(function (node) {
119
+ return node.pos === closestParentListNode.pos && node.start === closestParentListNode.start && node.depth === closestParentListNode.depth;
120
+ });
121
+ if (!existingParent) {
122
+ acc.push(closestParentListNode);
123
+ }
124
+ return acc;
125
+ }, []).forEach(function (item) {
126
+ tr.setNodeMarkup(item.pos, nextListNodeType);
127
+ });
128
+ };
129
+ var convertAroundList = function convertAroundList(_ref3) {
130
+ var tr = _ref3.tr,
131
+ nextListNodeType = _ref3.nextListNodeType,
132
+ nodeRange = _ref3.nodeRange;
133
+ for (var i = nodeRange.endIndex - 1; i >= nodeRange.startIndex; i--) {
134
+ // @ts-ignore posAtIndex is a public API but has no type yet
135
+ var position = nodeRange.$from.posAtIndex(i, nodeRange.depth);
136
+ var resolvedPos = tr.doc.resolve(position + 1);
137
+ var range = resolvedPos.blockRange(resolvedPos);
138
+ if (!range) {
139
+ return;
140
+ }
141
+ var wrappings = findWrapping(range, nextListNodeType);
142
+ if (!range || !wrappings) {
143
+ return;
144
+ }
145
+ tr.wrap(range, wrappings);
146
+ }
147
+ };
@@ -0,0 +1,117 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { normalizeListItemsSelection } from '@atlaskit/editor-common/lists';
3
+ import { GapCursorSelection } from '@atlaskit/editor-common/selection';
4
+ import { isListItemNode, isListNode } from '@atlaskit/editor-common/utils';
5
+ import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
6
+ import { NodeSelection, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
7
+ import { findFirstParentListItemNode } from '../utils/find';
8
+ export var indentListItemsSelected = function indentListItemsSelected(tr) {
9
+ var originalSelection = tr.selection;
10
+ var normalizedSelection = normalizeListItemsSelection({
11
+ selection: originalSelection,
12
+ doc: tr.doc
13
+ });
14
+ var $from = normalizedSelection.$from,
15
+ $to = normalizedSelection.$to;
16
+ var range = calculateRange({
17
+ selection: normalizedSelection
18
+ });
19
+ if (!range) {
20
+ return false;
21
+ }
22
+ var listItemsSelected = {
23
+ from: findFirstParentListItemNode($from),
24
+ to: findFirstParentListItemNode($to)
25
+ };
26
+ if (listItemsSelected.from === null || listItemsSelected.to === null) {
27
+ return null;
28
+ }
29
+ var resolvedPos = tr.doc.resolve(listItemsSelected.from.pos);
30
+ var listItemIndex = resolvedPos.index();
31
+ // @ts-ignore
32
+ var positionListItemPosition = resolvedPos.posAtIndex(listItemIndex - 1);
33
+ var previousListItem = tr.doc.nodeAt(positionListItemPosition);
34
+ if (!previousListItem || !isListItemNode(previousListItem)) {
35
+ return null;
36
+ }
37
+ if (isListItemNode(previousListItem) && listItemIndex === 0) {
38
+ return null;
39
+ }
40
+ var listItemSelectedCommonParent = range.parent;
41
+ var previousNestedList = isListNode(previousListItem.lastChild) ? previousListItem.lastChild : null;
42
+ var listNodeType = previousNestedList ? previousNestedList.type : listItemSelectedCommonParent.type;
43
+ var nestedList = listItemsSelected.to.node.lastChild;
44
+ var nestedItemsOffset = nestedList && isListNode(nestedList) ? nestedList.nodeSize : 0;
45
+ var from = listItemsSelected.from.pos;
46
+ var to = listItemsSelected.to.pos + listItemsSelected.to.node.nodeSize - nestedItemsOffset;
47
+ var _createIndentedListIt = createIndentedListItemsSlice({
48
+ tr: tr,
49
+ listNodeType: listNodeType,
50
+ range: range,
51
+ from: from,
52
+ to: to
53
+ }),
54
+ _createIndentedListIt2 = _slicedToArray(_createIndentedListIt, 2),
55
+ sliceSelected = _createIndentedListIt2[0],
56
+ nestedListItemsLeftover = _createIndentedListIt2[1];
57
+ var hasPreviousNestedList = Boolean(previousNestedList);
58
+ var start = from - 1;
59
+ tr.replaceRange(hasPreviousNestedList ? start - 1 : start, range.end, sliceSelected);
60
+ var leftoverContentPosition = tr.mapping.map(to) - 2;
61
+ if (nestedListItemsLeftover.openStart === 0) {
62
+ tr.insert(leftoverContentPosition, nestedListItemsLeftover.content);
63
+ } else {
64
+ tr.replace(leftoverContentPosition - nestedListItemsLeftover.openStart, leftoverContentPosition - nestedListItemsLeftover.openStart, nestedListItemsLeftover);
65
+ }
66
+ var nextSelection = calculateNewSelection({
67
+ originalSelection: originalSelection,
68
+ normalizedSelection: normalizedSelection,
69
+ tr: tr,
70
+ hasPreviousNestedList: hasPreviousNestedList
71
+ });
72
+ tr.setSelection(nextSelection);
73
+ };
74
+ var calculateRange = function calculateRange(_ref) {
75
+ var selection = _ref.selection;
76
+ var $from = selection.$from,
77
+ $to = selection.$to;
78
+ var range = $from.blockRange($to, isListNode);
79
+ if (!range) {
80
+ return null;
81
+ }
82
+ return range;
83
+ };
84
+ var calculateNewSelection = function calculateNewSelection(_ref2) {
85
+ var tr = _ref2.tr,
86
+ normalizedSelection = _ref2.normalizedSelection,
87
+ originalSelection = _ref2.originalSelection,
88
+ hasPreviousNestedList = _ref2.hasPreviousNestedList;
89
+ var offset = hasPreviousNestedList ? 2 : 0;
90
+ var $from = normalizedSelection.$from,
91
+ $to = normalizedSelection.$to;
92
+ if (normalizedSelection instanceof GapCursorSelection) {
93
+ var _nextSelectionFrom = tr.doc.resolve($from.pos - offset);
94
+ return new GapCursorSelection(_nextSelectionFrom, normalizedSelection.side);
95
+ }
96
+ if (originalSelection instanceof NodeSelection) {
97
+ return NodeSelection.create(tr.doc, $from.pos - offset);
98
+ }
99
+ var _Selection$near = Selection.near(tr.doc.resolve($from.pos - offset)),
100
+ nextSelectionFrom = _Selection$near.$from;
101
+ var _Selection$near2 = Selection.near(tr.doc.resolve($to.pos - offset), -1),
102
+ nextSelectionTo = _Selection$near2.$to;
103
+ return new TextSelection(nextSelectionFrom, nextSelectionTo);
104
+ };
105
+ var createIndentedListItemsSlice = function createIndentedListItemsSlice(_ref3) {
106
+ var tr = _ref3.tr,
107
+ from = _ref3.from,
108
+ to = _ref3.to,
109
+ listNodeType = _ref3.listNodeType,
110
+ range = _ref3.range;
111
+ var listItemsSlice = tr.doc.slice(from, to - 2);
112
+ var listFragment = Fragment.from(listNodeType.create(null, listItemsSlice.content));
113
+ var nonSelectedListItemsSlice = tr.doc.slice(to, range.end - 2);
114
+ var openStart = tr.doc.slice(from - 1, range.end).openStart;
115
+ var slice = new Slice(listFragment, openStart, 0);
116
+ return [slice, nonSelectedListItemsSlice];
117
+ };
@@ -0,0 +1,43 @@
1
+ import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
2
+ import { ReplaceAroundStep } from '@atlaskit/editor-prosemirror/transform';
3
+
4
+ // adapted from https://github.com/ProseMirror/prosemirror-schema-list/blob/master/src/schema-list.js#L206:L231
5
+ export var indentList = function indentList(tr) {
6
+ var _tr$selection = tr.selection,
7
+ $from = _tr$selection.$from,
8
+ $to = _tr$selection.$to;
9
+ var listItem = tr.doc.type.schema.nodes.listItem;
10
+ var range = $from.blockRange($to, function (node) {
11
+ return !!node.childCount && !!node.firstChild && node.firstChild.type === listItem;
12
+ });
13
+ if (!range) {
14
+ return false;
15
+ }
16
+
17
+ // get the index of the selected list item in the list it is part of
18
+ var startIndex = range.startIndex;
19
+ if (startIndex === 0) {
20
+ return false;
21
+ }
22
+
23
+ // get the parent list of the list item(s) in the selected range
24
+ var parent = range.parent;
25
+
26
+ // get the list immediately before the selection start
27
+ var previousListItem = parent.child(startIndex - 1);
28
+ if (previousListItem.type !== listItem) {
29
+ return false;
30
+ }
31
+
32
+ // if that list was nested, join the selected list items into the same
33
+ // nested list; if not, create a new child list of the same type and
34
+ // nest it under the current level
35
+ var isPreviousListNested = previousListItem.lastChild && ['bulletList', 'orderedList'].includes(previousListItem.lastChild.type.name);
36
+ var inner = Fragment.from(isPreviousListNested ? listItem.create() : undefined);
37
+ var nextListNodeType = isPreviousListNested ? previousListItem.lastChild.type : parent.type;
38
+ var nextListNodeContent = Fragment.from(nextListNodeType.create(null, inner));
39
+ var slice = new Slice(Fragment.from(listItem.create(null, nextListNodeContent)), isPreviousListNested ? 3 : 1, 0);
40
+ var before = range.start;
41
+ var after = range.end;
42
+ tr.step(new ReplaceAroundStep(before - (isPreviousListNested ? 3 : 1), after, before, after, slice, 1, true));
43
+ };
@@ -0,0 +1,52 @@
1
+ import { LIST_TEXT_SCENARIOS } from '@atlaskit/editor-common/analytics';
2
+ import { isListItemNode, isListNode, isParagraphNode } from '@atlaskit/editor-common/utils';
3
+ import { isPosInsideList, isPosInsideParagraph } from '../utils/selection';
4
+ import { joinListItemWithParagraph, joinListItemWithParentNestedList, joinNestedListWithParentListItem, joinParagrapWithList, joinSiblingListItems } from './join-list-items-scenarios';
5
+ export var calcJoinListScenario = function calcJoinListScenario(walkNode, $head) {
6
+ var $next = walkNode.$pos,
7
+ nextFoundNode = walkNode.foundNode;
8
+ var headParent = $head.parent;
9
+ var headGrandParent = $head.node(-1);
10
+ var headInList = isPosInsideList($head);
11
+ var headInParagraph = isPosInsideParagraph($head);
12
+ var headInLastNonListChild = headGrandParent && headGrandParent.lastChild && (headGrandParent.lastChild === headParent || headGrandParent.childCount > 1 && headGrandParent.child(headGrandParent.childCount - 2) === headParent &&
13
+ //find the second last child if a list item may be the last child
14
+ isListNode(headGrandParent.lastChild));
15
+ var nextInList = isPosInsideList($next);
16
+ var nextInParagraph = isPosInsideParagraph($next);
17
+ if (!headInList && headInParagraph && nextInList) {
18
+ return [LIST_TEXT_SCENARIOS.JOIN_LIST_ITEM_WITH_PARAGRAPH, joinListItemWithParagraph];
19
+ }
20
+ if (!nextFoundNode || !headInList || !headInParagraph || !headInLastNonListChild) {
21
+ return false;
22
+ }
23
+ if (!nextInList && nextInParagraph) {
24
+ return [LIST_TEXT_SCENARIOS.JOIN_PARAGRAPH_WITH_LIST, joinParagrapWithList];
25
+ }
26
+ if (!nextInList) {
27
+ return false;
28
+ }
29
+ var nextNodeAfter = $next.nodeAfter;
30
+ var nextGrandParent = $next.node(-1);
31
+ var headGreatGrandParent = $head.node(-2);
32
+ var nextInListItem = isListItemNode($next.parent);
33
+ var nextNodeAfterListItem = isListItemNode(nextNodeAfter);
34
+ var nextListItemHasFirstChildParagraph = nextNodeAfter &&
35
+ //Redundant check but the linter complains otherwise
36
+ nextNodeAfterListItem && isParagraphNode(nextNodeAfter.firstChild);
37
+ if (!nextInListItem && nextListItemHasFirstChildParagraph) {
38
+ return [LIST_TEXT_SCENARIOS.JOIN_DESCENDANT_TO_PARENT, joinNestedListWithParentListItem];
39
+ }
40
+ if (!nextInListItem) {
41
+ return false;
42
+ }
43
+ var nextParentSiblingOfHeadParent = nextGrandParent && nextGrandParent === headGreatGrandParent;
44
+ var nextNodeAfterIsParagraph = isParagraphNode(nextNodeAfter);
45
+ if (!nextNodeAfterIsParagraph) {
46
+ return false;
47
+ }
48
+ if (nextParentSiblingOfHeadParent) {
49
+ return [LIST_TEXT_SCENARIOS.JOIN_SIBLINGS, joinSiblingListItems];
50
+ }
51
+ return [LIST_TEXT_SCENARIOS.JOIN_PARENT_SIBLING_TO_PARENT_CHILD, joinListItemWithParentNestedList];
52
+ };
@@ -0,0 +1,5 @@
1
+ export { joinParagrapWithList } from './join-paragraph-with-list';
2
+ export { joinSiblingListItems } from './join-sibling-list-items';
3
+ export { joinNestedListWithParentListItem } from './join-nested-list-with-parent-list-item';
4
+ export { joinListItemWithParentNestedList } from './join-list-item-with-parent-nested-list';
5
+ export { joinListItemWithParagraph } from './join-list-item-with-paragraph';
@@ -0,0 +1,81 @@
1
+ import { insertContentDeleteRange, isListNode } from '@atlaskit/editor-common/utils';
2
+ import { Fragment } from '@atlaskit/editor-prosemirror/model';
3
+ // Case for when a users selection is at the end of a paragraph, the paragraph
4
+ // is followed by a list, and they delete forward
5
+ export var joinListItemWithParagraph = function joinListItemWithParagraph(_ref) {
6
+ var tr = _ref.tr,
7
+ $next = _ref.$next,
8
+ $head = _ref.$head;
9
+ // For empty paragraphs before a list
10
+ if ($head.parent.content.size < 1) {
11
+ insertContentDeleteRange(tr, function (tr) {
12
+ return tr.doc.resolve($head.pos);
13
+ }, [], [[$head.pos - 1, $head.pos]]);
14
+ return true;
15
+ }
16
+ var paragraphPosition = $head.pos;
17
+ var list = tr.doc.nodeAt($next.pos - 1);
18
+ var firstListItem = tr.doc.nodeAt($next.pos);
19
+ if (!list || !firstListItem) {
20
+ return false;
21
+ }
22
+ var firstChildNodeOfFirstListItem = firstListItem.firstChild;
23
+ if (!firstChildNodeOfFirstListItem) {
24
+ return false;
25
+ }
26
+ var lastChildOfFirstListItem = firstListItem.lastChild;
27
+ var firstGrandchildOfFirstListItem = firstChildNodeOfFirstListItem.firstChild;
28
+ var firstListItemHasOneChildWithNoNestedLists = hasSingleChild(firstListItem) && firstChildNodeOfFirstListItem.childCount < 2 && $next.nodeAfter;
29
+ var firstListItemContainsParagraphAndNestedList = !hasSingleChild(firstListItem) && lastChildOfFirstListItem && isListNode(lastChildOfFirstListItem);
30
+ var insertions = [];
31
+ var deletions = [];
32
+
33
+ // For lists that only have one list item with no children - need to remove remaining list
34
+ if (hasSingleChild(list) && hasSingleChild(firstListItem) && $next.nodeAfter) {
35
+ deletions.push([tr.mapping.map($next.pos - 1), tr.mapping.map($next.pos + $next.nodeAfter.nodeSize + 1)]);
36
+ }
37
+
38
+ // For first list items that have a paragraph and a list
39
+ if (firstListItemContainsParagraphAndNestedList) {
40
+ var firstListItemNestedList = Fragment.from(lastChildOfFirstListItem.content);
41
+ insertions.push([firstListItemNestedList, tr.mapping.map($next.pos)]);
42
+ }
43
+
44
+ // For first list item has one child & no nested lists OR first list items that have a paragraph and a list
45
+ if (firstListItemHasOneChildWithNoNestedLists || firstListItemContainsParagraphAndNestedList) {
46
+ deletions.push([tr.mapping.map($next.pos), tr.mapping.map($next.pos + firstListItem.nodeSize - 1)]);
47
+ var firstListItemText = Fragment.from(firstChildNodeOfFirstListItem.content);
48
+ insertions.push([firstListItemText, paragraphPosition]);
49
+ insertContentDeleteRange(tr, function (tr) {
50
+ return tr.doc.resolve($head.pos);
51
+ }, insertions, deletions);
52
+ return true;
53
+ }
54
+
55
+ // For any first list items that have multiple children (eg. multiple paragraphs)
56
+ if (firstListItem.childCount > 1) {
57
+ insertions.push([Fragment.from(firstChildNodeOfFirstListItem.content), paragraphPosition]);
58
+ deletions.push([tr.mapping.map($next.pos + 1), tr.mapping.map($next.pos + firstChildNodeOfFirstListItem.nodeSize + 1)]);
59
+ insertContentDeleteRange(tr, function (tr) {
60
+ return tr.doc.resolve($head.pos);
61
+ }, insertions, deletions);
62
+ return true;
63
+ }
64
+
65
+ // For any remaining first list items that have a single child (eg. single paragraph, multiple lines of text)
66
+ if (firstGrandchildOfFirstListItem && firstGrandchildOfFirstListItem.type.name === 'hardBreak') {
67
+ var nodeSizeOfGrandchild = firstGrandchildOfFirstListItem ? firstGrandchildOfFirstListItem.nodeSize : 0;
68
+ deletions.push([tr.mapping.map($next.pos + 2), tr.mapping.map($next.pos + 2 + nodeSizeOfGrandchild)]);
69
+ } else {
70
+ insertions.push([Fragment.from(firstChildNodeOfFirstListItem.content), paragraphPosition]);
71
+ var nodeSizeOfFirstChild = firstChildNodeOfFirstListItem.nodeSize;
72
+ deletions.push([tr.mapping.map($next.pos), tr.mapping.map($next.pos + 2 + nodeSizeOfFirstChild)]);
73
+ }
74
+ insertContentDeleteRange(tr, function (tr) {
75
+ return tr.doc.resolve($head.pos);
76
+ }, insertions, deletions);
77
+ return true;
78
+ };
79
+ var hasSingleChild = function hasSingleChild(node) {
80
+ return node.childCount === 1;
81
+ };