@atlaskit/editor-plugin-block-menu 1.0.2 → 1.0.4
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/CHANGELOG.md +18 -0
- package/dist/cjs/editor-commands/formatNode.js +2 -2
- package/dist/cjs/editor-commands/transforms/container-transforms.js +60 -4
- package/dist/cjs/editor-commands/transforms/list/transformBetweenListTypes.js +69 -71
- package/dist/cjs/editor-commands/transforms/list/transformToTaskList.js +44 -0
- package/dist/cjs/editor-commands/transforms/list-transforms.js +40 -30
- package/dist/cjs/editor-commands/transforms/utils.js +16 -2
- package/dist/cjs/ui/block-menu-components.js +2 -1
- package/dist/es2019/editor-commands/formatNode.js +2 -2
- package/dist/es2019/editor-commands/transforms/container-transforms.js +64 -4
- package/dist/es2019/editor-commands/transforms/list/transformBetweenListTypes.js +73 -70
- package/dist/es2019/editor-commands/transforms/list/transformToTaskList.js +38 -0
- package/dist/es2019/editor-commands/transforms/list-transforms.js +38 -28
- package/dist/es2019/editor-commands/transforms/utils.js +15 -1
- package/dist/es2019/ui/block-menu-components.js +2 -1
- package/dist/esm/editor-commands/formatNode.js +2 -2
- package/dist/esm/editor-commands/transforms/container-transforms.js +60 -4
- package/dist/esm/editor-commands/transforms/list/transformBetweenListTypes.js +70 -71
- package/dist/esm/editor-commands/transforms/list/transformToTaskList.js +37 -0
- package/dist/esm/editor-commands/transforms/list-transforms.js +37 -27
- package/dist/esm/editor-commands/transforms/utils.js +15 -1
- package/dist/esm/ui/block-menu-components.js +2 -1
- package/dist/types/editor-commands/transforms/container-transforms.d.ts +1 -1
- package/dist/types/editor-commands/transforms/list/transformBetweenListTypes.d.ts +3 -7
- package/dist/types/editor-commands/transforms/list/transformToTaskList.d.ts +10 -0
- package/dist/types/editor-commands/transforms/list-transforms.d.ts +1 -1
- package/dist/types/editor-commands/transforms/transformNodeToTargetType.d.ts +1 -1
- package/dist/types/editor-commands/transforms/types.d.ts +1 -1
- package/dist/types/editor-commands/transforms/utils.d.ts +4 -0
- package/dist/types-ts4.5/editor-commands/transforms/container-transforms.d.ts +1 -1
- package/dist/types-ts4.5/editor-commands/transforms/list/transformBetweenListTypes.d.ts +3 -7
- package/dist/types-ts4.5/editor-commands/transforms/list/transformToTaskList.d.ts +10 -0
- package/dist/types-ts4.5/editor-commands/transforms/list-transforms.d.ts +1 -1
- package/dist/types-ts4.5/editor-commands/transforms/transformNodeToTargetType.d.ts +1 -1
- package/dist/types-ts4.5/editor-commands/transforms/types.d.ts +1 -1
- package/dist/types-ts4.5/editor-commands/transforms/utils.d.ts +4 -0
- package/package.json +6 -6
|
@@ -1,96 +1,99 @@
|
|
|
1
|
+
import { getSupportedListTypesSet, isBulletOrOrderedList, isTaskList } from '../utils';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* Convert a block node to inline content suitable for task items
|
|
3
5
|
*/
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const convertBlockToInlineContent = (node, schema) => {
|
|
7
|
+
const {
|
|
8
|
+
paragraph
|
|
9
|
+
} = schema.nodes;
|
|
10
|
+
if (node.type === paragraph) {
|
|
11
|
+
return [...node.content.content];
|
|
12
|
+
}
|
|
13
|
+
if (node.isBlock) {
|
|
14
|
+
const textContent = node.textContent;
|
|
15
|
+
return textContent ? [schema.text(textContent)] : [];
|
|
8
16
|
}
|
|
9
|
-
return
|
|
17
|
+
return [node];
|
|
10
18
|
};
|
|
11
19
|
|
|
12
20
|
/**
|
|
13
|
-
* Transform list structure
|
|
21
|
+
* Transform list structure between different list types
|
|
14
22
|
*/
|
|
15
|
-
export const transformListStructure =
|
|
23
|
+
export const transformListStructure = context => {
|
|
24
|
+
const {
|
|
25
|
+
tr,
|
|
26
|
+
sourceNode,
|
|
27
|
+
sourcePos,
|
|
28
|
+
targetNodeType
|
|
29
|
+
} = context;
|
|
30
|
+
const nodes = tr.doc.type.schema.nodes;
|
|
16
31
|
try {
|
|
32
|
+
const listNode = {
|
|
33
|
+
node: sourceNode,
|
|
34
|
+
pos: sourcePos
|
|
35
|
+
};
|
|
17
36
|
const {
|
|
18
37
|
node: sourceList,
|
|
19
38
|
pos: listPos
|
|
20
39
|
} = listNode;
|
|
21
40
|
const {
|
|
22
|
-
bulletList,
|
|
23
|
-
orderedList,
|
|
24
41
|
taskList,
|
|
25
42
|
listItem,
|
|
26
43
|
taskItem,
|
|
27
44
|
paragraph
|
|
28
45
|
} = nodes;
|
|
29
|
-
const isSourceBulletOrOrdered = sourceList.type
|
|
30
|
-
const isTargetTask = targetNodeType
|
|
31
|
-
const isSourceTask = sourceList.type
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// Extract all inline content from all child nodes
|
|
49
|
-
for (let i = 0; i < node.childCount; i++) {
|
|
50
|
-
const child = node.child(i);
|
|
51
|
-
if (child.type === paragraph) {
|
|
52
|
-
// Extract inline content from paragraphs
|
|
53
|
-
inlineContent.push(...extractInlineContent(child));
|
|
54
|
-
} else if (child.isBlock) {
|
|
55
|
-
// For other block content types eg. codeBlock, extract their text content and create text nodes
|
|
56
|
-
const textContent = child.textContent;
|
|
57
|
-
if (textContent) {
|
|
58
|
-
const textNode = tr.doc.type.schema.text(textContent);
|
|
59
|
-
inlineContent.push(textNode);
|
|
46
|
+
const isSourceBulletOrOrdered = isBulletOrOrderedList(sourceList.type);
|
|
47
|
+
const isTargetTask = isTaskList(targetNodeType);
|
|
48
|
+
const isSourceTask = isTaskList(sourceList.type);
|
|
49
|
+
const isTargetBulletOrOrdered = isBulletOrOrderedList(targetNodeType);
|
|
50
|
+
const supportedListTypes = getSupportedListTypesSet(nodes);
|
|
51
|
+
const transformListRecursively = listNode => {
|
|
52
|
+
const transformedItems = [];
|
|
53
|
+
listNode.forEach(child => {
|
|
54
|
+
if (isSourceBulletOrOrdered && isTargetTask) {
|
|
55
|
+
// Convert bullet/ordered => task
|
|
56
|
+
if (child.type === listItem) {
|
|
57
|
+
const inlineContent = [];
|
|
58
|
+
const nestedTaskLists = [];
|
|
59
|
+
child.forEach(grandChild => {
|
|
60
|
+
if (supportedListTypes.has(grandChild.type) && grandChild.type !== taskList) {
|
|
61
|
+
nestedTaskLists.push(transformListRecursively(grandChild));
|
|
62
|
+
} else {
|
|
63
|
+
inlineContent.push(...convertBlockToInlineContent(grandChild, tr.doc.type.schema));
|
|
60
64
|
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
});
|
|
66
|
+
if (inlineContent.length > 0) {
|
|
67
|
+
transformedItems.push(taskItem.create(null, inlineContent));
|
|
64
68
|
}
|
|
69
|
+
transformedItems.push(...nestedTaskLists);
|
|
65
70
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
71
|
+
} else if (isSourceTask && isTargetBulletOrOrdered) {
|
|
72
|
+
// Convert task => bullet/ordered
|
|
73
|
+
if (child.type === taskItem) {
|
|
74
|
+
const inlineContent = [...child.content.content];
|
|
75
|
+
if (inlineContent.length > 0) {
|
|
76
|
+
const paragraphNode = paragraph.create(null, inlineContent);
|
|
77
|
+
transformedItems.push(listItem.create(null, [paragraphNode]));
|
|
78
|
+
}
|
|
79
|
+
} else if (child.type === taskList) {
|
|
80
|
+
const transformedNestedList = transformListRecursively(child);
|
|
81
|
+
const lastItem = transformedItems[transformedItems.length - 1];
|
|
82
|
+
if ((lastItem === null || lastItem === void 0 ? void 0 : lastItem.type) === listItem) {
|
|
83
|
+
// Attach nested list to previous item
|
|
84
|
+
const updatedContent = [...lastItem.content.content, transformedNestedList];
|
|
85
|
+
transformedItems[transformedItems.length - 1] = listItem.create(lastItem.attrs, updatedContent);
|
|
86
|
+
} else {
|
|
87
|
+
// No previous item, flatten nested items
|
|
88
|
+
transformedItems.push(...transformedNestedList.content.content);
|
|
89
|
+
}
|
|
80
90
|
}
|
|
81
91
|
}
|
|
82
|
-
}
|
|
83
|
-
return
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Create new list with transformed items
|
|
90
|
-
const newList = targetNodeType.create(null, newListItems);
|
|
91
|
-
|
|
92
|
-
// Replace the entire list
|
|
93
|
-
tr.replaceWith(listStart, listEnd, newList);
|
|
92
|
+
});
|
|
93
|
+
return targetNodeType.create(null, transformedItems);
|
|
94
|
+
};
|
|
95
|
+
const newList = transformListRecursively(sourceList);
|
|
96
|
+
tr.replaceWith(listPos, listPos + sourceList.nodeSize, newList);
|
|
94
97
|
return tr;
|
|
95
98
|
} catch {
|
|
96
99
|
return tr;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transform selection to task list
|
|
3
|
+
* Handles the special structure where taskItem contains text directly (no paragraph wrapper)
|
|
4
|
+
*/
|
|
5
|
+
export const transformToTaskList = (tr, range, targetNodeType, targetAttrs, nodes) => {
|
|
6
|
+
try {
|
|
7
|
+
const {
|
|
8
|
+
taskItem
|
|
9
|
+
} = nodes;
|
|
10
|
+
const listItems = [];
|
|
11
|
+
|
|
12
|
+
// Process each block in the range
|
|
13
|
+
tr.doc.nodesBetween(range.start, range.end, node => {
|
|
14
|
+
if (node.isBlock) {
|
|
15
|
+
// For block nodes like paragraphs, directly use their inline content
|
|
16
|
+
const inlineContent = [...node.content.content];
|
|
17
|
+
if (inlineContent.length > 0) {
|
|
18
|
+
// Create task item with inline content directly
|
|
19
|
+
const listItem = taskItem.create(targetAttrs, inlineContent);
|
|
20
|
+
listItems.push(listItem);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return false; // Don't traverse into children
|
|
24
|
+
});
|
|
25
|
+
if (listItems.length === 0) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Create the new task list
|
|
30
|
+
const newList = targetNodeType.create(targetAttrs, listItems);
|
|
31
|
+
|
|
32
|
+
// Replace the range with the new list
|
|
33
|
+
tr.replaceWith(range.start, range.end, newList);
|
|
34
|
+
return tr;
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { findWrapping } from '@atlaskit/editor-prosemirror/transform';
|
|
2
|
-
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
3
2
|
import { transformListStructure } from './list/transformBetweenListTypes';
|
|
4
3
|
import { transformOrderedUnorderedListToBlockNodes } from './list/transformOrderedUnorderedListToBlockNodes';
|
|
5
4
|
import { transformTaskListToBlockNodes } from './list/transformTaskListToBlockNodes';
|
|
6
|
-
import {
|
|
5
|
+
import { transformToTaskList } from './list/transformToTaskList';
|
|
6
|
+
import { getSupportedListTypesSet, isBulletOrOrderedList, isBlockNodeType, isContainerNodeType, isListNodeType, isTaskList } from './utils';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Transform selection to list type
|
|
@@ -11,6 +11,7 @@ import { isBlockNodeType, isContainerNodeType, isListNodeType } from './utils';
|
|
|
11
11
|
export const transformBlockToList = context => {
|
|
12
12
|
const {
|
|
13
13
|
tr,
|
|
14
|
+
sourceNode,
|
|
14
15
|
targetNodeType,
|
|
15
16
|
targetAttrs
|
|
16
17
|
} = context;
|
|
@@ -25,16 +26,14 @@ export const transformBlockToList = context => {
|
|
|
25
26
|
const {
|
|
26
27
|
nodes
|
|
27
28
|
} = tr.doc.type.schema;
|
|
28
|
-
const isTargetTask = targetNodeType
|
|
29
|
+
const isTargetTask = isTaskList(targetNodeType);
|
|
29
30
|
|
|
30
31
|
// Handle task lists differently due to their structure
|
|
31
|
-
// TODO: ED-29152 - Implement task list transformation
|
|
32
32
|
if (isTargetTask) {
|
|
33
|
-
return
|
|
33
|
+
return transformToTaskList(tr, range, targetNodeType, targetAttrs, nodes);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
// For headings, convert to paragraph first since headings cannot be direct children of list items
|
|
37
|
-
const sourceNode = tr.doc.nodeAt(range.start);
|
|
38
37
|
if (sourceNode && sourceNode.type.name.startsWith('heading')) {
|
|
39
38
|
tr.setBlockType(range.start, range.end, nodes.paragraph);
|
|
40
39
|
}
|
|
@@ -102,41 +101,52 @@ export const liftListToBlockType = () => {
|
|
|
102
101
|
/**
|
|
103
102
|
* Transform between different list types
|
|
104
103
|
*/
|
|
105
|
-
export const transformBetweenListTypes =
|
|
106
|
-
tr,
|
|
107
|
-
targetNodeType
|
|
108
|
-
}) => {
|
|
104
|
+
export const transformBetweenListTypes = context => {
|
|
109
105
|
const {
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
tr,
|
|
107
|
+
sourceNode,
|
|
108
|
+
sourcePos,
|
|
109
|
+
targetNodeType
|
|
110
|
+
} = context;
|
|
112
111
|
const {
|
|
113
112
|
nodes
|
|
114
113
|
} = tr.doc.type.schema;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
if (!listNode) {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
const sourceListType = listNode.node.type;
|
|
124
|
-
const isSourceBulletOrOrdered = sourceListType === nodes.bulletList || sourceListType === nodes.orderedList;
|
|
125
|
-
const isTargetTask = targetNodeType === nodes.taskList;
|
|
126
|
-
const isSourceTask = sourceListType === nodes.taskList;
|
|
127
|
-
const isTargetBulletOrOrdered = targetNodeType === nodes.bulletList || targetNodeType === nodes.orderedList;
|
|
114
|
+
const sourceListType = sourceNode.type;
|
|
115
|
+
const isSourceBulletOrOrdered = isBulletOrOrderedList(sourceListType);
|
|
116
|
+
const isTargetTask = isTaskList(targetNodeType);
|
|
117
|
+
const isSourceTask = isTaskList(sourceListType);
|
|
118
|
+
const isTargetBulletOrOrdered = isBulletOrOrderedList(targetNodeType);
|
|
128
119
|
|
|
129
120
|
// Check if we need structure transformation
|
|
130
121
|
const needsStructureTransform = isSourceBulletOrOrdered && isTargetTask || isSourceTask && isTargetBulletOrOrdered;
|
|
131
122
|
try {
|
|
132
123
|
if (!needsStructureTransform) {
|
|
133
124
|
// Simple type change for same structure lists (bullet <-> ordered)
|
|
134
|
-
|
|
125
|
+
// Apply to the main list
|
|
126
|
+
tr.setNodeMarkup(sourcePos, targetNodeType);
|
|
127
|
+
|
|
128
|
+
// Apply to nested lists
|
|
129
|
+
const listStart = sourcePos;
|
|
130
|
+
const listEnd = sourcePos + sourceNode.nodeSize;
|
|
131
|
+
const supportedListTypesSet = getSupportedListTypesSet(nodes);
|
|
132
|
+
tr.doc.nodesBetween(listStart, listEnd, (node, pos, parent) => {
|
|
133
|
+
// Only process nested lists (not the root list we already handled)
|
|
134
|
+
if (supportedListTypesSet.has(node.type) && pos !== sourcePos) {
|
|
135
|
+
const isNestedList = parent && (supportedListTypesSet.has(parent.type) || parent.type === nodes.listItem);
|
|
136
|
+
if (isNestedList) {
|
|
137
|
+
const shouldTransformNode = node.type === sourceListType || isBulletOrOrderedList(node.type) && isTargetBulletOrOrdered;
|
|
138
|
+
if (shouldTransformNode) {
|
|
139
|
+
tr.setNodeMarkup(pos, targetNodeType);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return true; // Continue traversing
|
|
144
|
+
});
|
|
145
|
+
return tr;
|
|
135
146
|
} else {
|
|
136
|
-
|
|
147
|
+
return transformListStructure(context);
|
|
137
148
|
}
|
|
138
149
|
} catch {
|
|
139
150
|
return null;
|
|
140
151
|
}
|
|
141
|
-
return tr;
|
|
142
152
|
};
|
|
@@ -87,7 +87,7 @@ export const isBlockNode = node => {
|
|
|
87
87
|
return ['paragraph', 'heading', 'codeBlock'].includes(node.type.name);
|
|
88
88
|
};
|
|
89
89
|
export const isListNode = node => {
|
|
90
|
-
return ['bulletList', 'orderedList', 'taskList'
|
|
90
|
+
return ['bulletList', 'orderedList', 'taskList'].includes(node.type.name);
|
|
91
91
|
};
|
|
92
92
|
export const isContainerNode = node => {
|
|
93
93
|
return ['panel', 'expand', 'blockquote'].includes(node.type.name);
|
|
@@ -100,4 +100,18 @@ export const isListNodeType = nodeType => {
|
|
|
100
100
|
};
|
|
101
101
|
export const isContainerNodeType = nodeType => {
|
|
102
102
|
return ['panel', 'expand', 'blockquote'].includes(nodeType.name);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// List type utilities
|
|
106
|
+
export const isBulletOrOrderedList = nodeType => {
|
|
107
|
+
return nodeType.name === 'bulletList' || nodeType.name === 'orderedList';
|
|
108
|
+
};
|
|
109
|
+
export const isTaskList = nodeType => {
|
|
110
|
+
return nodeType.name === 'taskList';
|
|
111
|
+
};
|
|
112
|
+
export const getSupportedListTypes = nodes => {
|
|
113
|
+
return [nodes.bulletList, nodes.orderedList, nodes.taskList].filter(Boolean);
|
|
114
|
+
};
|
|
115
|
+
export const getSupportedListTypesSet = nodes => {
|
|
116
|
+
return new Set(getSupportedListTypes(nodes));
|
|
103
117
|
};
|
|
@@ -12,7 +12,7 @@ export var formatNode = function formatNode(targetType) {
|
|
|
12
12
|
|
|
13
13
|
// Find the node to format from the current selection
|
|
14
14
|
var nodeToFormat;
|
|
15
|
-
var nodePos =
|
|
15
|
+
var nodePos = selection.from;
|
|
16
16
|
|
|
17
17
|
// Try to find the current node from selection
|
|
18
18
|
var selectedNode = findSelectedNodeOfType([nodes.paragraph, nodes.heading, nodes.blockquote, nodes.panel, nodes.expand, nodes.codeBlock, nodes.bulletList, nodes.orderedList, nodes.taskList, nodes.layoutSection])(selection);
|
|
@@ -34,7 +34,7 @@ export var formatNode = function formatNode(targetType) {
|
|
|
34
34
|
nodeToFormat = listParent.node;
|
|
35
35
|
nodePos = listParent.pos;
|
|
36
36
|
}
|
|
37
|
-
} else if (paragraphOrHeadingNode) {
|
|
37
|
+
} else if (parentNode.node.type !== nodes.blockquote && paragraphOrHeadingNode) {
|
|
38
38
|
nodeToFormat = paragraphOrHeadingNode.node;
|
|
39
39
|
nodePos = paragraphOrHeadingNode.pos;
|
|
40
40
|
}
|
|
@@ -44,6 +44,7 @@ export var transformToContainer = function transformToContainer(_ref) {
|
|
|
44
44
|
*/
|
|
45
45
|
export var transformContainerNode = function transformContainerNode(_ref2) {
|
|
46
46
|
var tr = _ref2.tr,
|
|
47
|
+
sourceNode = _ref2.sourceNode,
|
|
47
48
|
sourcePos = _ref2.sourcePos,
|
|
48
49
|
targetNodeType = _ref2.targetNodeType,
|
|
49
50
|
targetAttrs = _ref2.targetAttrs;
|
|
@@ -58,7 +59,13 @@ export var transformContainerNode = function transformContainerNode(_ref2) {
|
|
|
58
59
|
|
|
59
60
|
// Transform container to list type
|
|
60
61
|
if (isListNodeType(targetNodeType)) {
|
|
61
|
-
return unwrapAndConvertToList(
|
|
62
|
+
return unwrapAndConvertToList({
|
|
63
|
+
tr: tr,
|
|
64
|
+
sourceNode: sourceNode,
|
|
65
|
+
sourcePos: sourcePos,
|
|
66
|
+
targetNodeType: targetNodeType,
|
|
67
|
+
targetAttrs: targetAttrs
|
|
68
|
+
});
|
|
62
69
|
}
|
|
63
70
|
|
|
64
71
|
// Transform between container types
|
|
@@ -80,7 +87,56 @@ export var unwrapAndConvertToBlockType = function unwrapAndConvertToBlockType()
|
|
|
80
87
|
/**
|
|
81
88
|
* Unwrap container node and convert content to list
|
|
82
89
|
*/
|
|
83
|
-
export var unwrapAndConvertToList = function unwrapAndConvertToList() {
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
export var unwrapAndConvertToList = function unwrapAndConvertToList(_ref3) {
|
|
91
|
+
var tr = _ref3.tr,
|
|
92
|
+
sourceNode = _ref3.sourceNode,
|
|
93
|
+
sourcePos = _ref3.sourcePos,
|
|
94
|
+
targetNodeType = _ref3.targetNodeType,
|
|
95
|
+
targetAttrs = _ref3.targetAttrs;
|
|
96
|
+
if (sourcePos === null) {
|
|
97
|
+
return tr;
|
|
98
|
+
}
|
|
99
|
+
var schema = tr.doc.type.schema;
|
|
100
|
+
var _schema$nodes = schema.nodes,
|
|
101
|
+
listItem = _schema$nodes.listItem,
|
|
102
|
+
paragraph = _schema$nodes.paragraph,
|
|
103
|
+
taskList = _schema$nodes.taskList,
|
|
104
|
+
taskItem = _schema$nodes.taskItem;
|
|
105
|
+
var isTargetTaskList = targetNodeType === taskList;
|
|
106
|
+
var createListItemFromInline = function createListItemFromInline(inlineFrag) {
|
|
107
|
+
return isTargetTaskList ? taskItem.create(null, inlineFrag) : listItem.create(null, paragraph.create(null, inlineFrag));
|
|
108
|
+
};
|
|
109
|
+
var getInlineContent = function getInlineContent(textblock) {
|
|
110
|
+
var inlineContent = [];
|
|
111
|
+
textblock.forEach(function (inline) {
|
|
112
|
+
inlineContent.push(inline);
|
|
113
|
+
});
|
|
114
|
+
return inlineContent;
|
|
115
|
+
};
|
|
116
|
+
var items = [];
|
|
117
|
+
|
|
118
|
+
// Expand's title should become the first item of the list
|
|
119
|
+
if (sourceNode.type.name === 'expand') {
|
|
120
|
+
var _sourceNode$attrs;
|
|
121
|
+
var title = (_sourceNode$attrs = sourceNode.attrs) === null || _sourceNode$attrs === void 0 ? void 0 : _sourceNode$attrs.title;
|
|
122
|
+
if (title) {
|
|
123
|
+
var titleContent = schema.text(title);
|
|
124
|
+
items.push(isTargetTaskList ? taskItem.create(null, titleContent) : listItem.create(null, paragraph.create(null, titleContent)));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
for (var i = 0; i < sourceNode.childCount; i++) {
|
|
128
|
+
var node = sourceNode.child(i);
|
|
129
|
+
|
|
130
|
+
// Abort early if unsupported content (e.g. table) encounted inside of the container
|
|
131
|
+
if (!node.isTextblock) {
|
|
132
|
+
return tr;
|
|
133
|
+
}
|
|
134
|
+
var inline = Fragment.from(getInlineContent(node));
|
|
135
|
+
items.push(createListItemFromInline(inline));
|
|
136
|
+
}
|
|
137
|
+
if (!items.length) {
|
|
138
|
+
return tr;
|
|
139
|
+
}
|
|
140
|
+
var list = targetNodeType.create(targetAttrs || null, Fragment.from(items));
|
|
141
|
+
return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, list);
|
|
86
142
|
};
|
|
@@ -1,93 +1,92 @@
|
|
|
1
1
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
import { getSupportedListTypesSet, isBulletOrOrderedList, isTaskList } from '../utils';
|
|
3
|
+
|
|
2
4
|
/**
|
|
3
|
-
*
|
|
5
|
+
* Convert a block node to inline content suitable for task items
|
|
4
6
|
*/
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
var convertBlockToInlineContent = function convertBlockToInlineContent(node, schema) {
|
|
8
|
+
var paragraph = schema.nodes.paragraph;
|
|
9
|
+
if (node.type === paragraph) {
|
|
10
|
+
return _toConsumableArray(node.content.content);
|
|
11
|
+
}
|
|
12
|
+
if (node.isBlock) {
|
|
13
|
+
var textContent = node.textContent;
|
|
14
|
+
return textContent ? [schema.text(textContent)] : [];
|
|
9
15
|
}
|
|
10
|
-
return
|
|
16
|
+
return [node];
|
|
11
17
|
};
|
|
12
18
|
|
|
13
19
|
/**
|
|
14
|
-
* Transform list structure
|
|
20
|
+
* Transform list structure between different list types
|
|
15
21
|
*/
|
|
16
|
-
export var transformListStructure = function transformListStructure(
|
|
22
|
+
export var transformListStructure = function transformListStructure(context) {
|
|
23
|
+
var tr = context.tr,
|
|
24
|
+
sourceNode = context.sourceNode,
|
|
25
|
+
sourcePos = context.sourcePos,
|
|
26
|
+
targetNodeType = context.targetNodeType;
|
|
27
|
+
var nodes = tr.doc.type.schema.nodes;
|
|
17
28
|
try {
|
|
29
|
+
var listNode = {
|
|
30
|
+
node: sourceNode,
|
|
31
|
+
pos: sourcePos
|
|
32
|
+
};
|
|
18
33
|
var sourceList = listNode.node,
|
|
19
34
|
listPos = listNode.pos;
|
|
20
|
-
var
|
|
21
|
-
orderedList = nodes.orderedList,
|
|
22
|
-
taskList = nodes.taskList,
|
|
35
|
+
var taskList = nodes.taskList,
|
|
23
36
|
listItem = nodes.listItem,
|
|
24
37
|
taskItem = nodes.taskItem,
|
|
25
38
|
paragraph = nodes.paragraph;
|
|
26
|
-
var isSourceBulletOrOrdered = sourceList.type
|
|
27
|
-
var isTargetTask = targetNodeType
|
|
28
|
-
var isSourceTask = sourceList.type
|
|
29
|
-
var
|
|
30
|
-
var
|
|
31
|
-
var
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// Extract all inline content from all child nodes
|
|
46
|
-
for (var i = 0; i < node.childCount; i++) {
|
|
47
|
-
var child = node.child(i);
|
|
48
|
-
if (child.type === paragraph) {
|
|
49
|
-
// Extract inline content from paragraphs
|
|
50
|
-
inlineContent.push.apply(inlineContent, _toConsumableArray(extractInlineContent(child)));
|
|
51
|
-
} else if (child.isBlock) {
|
|
52
|
-
// For other block content types eg. codeBlock, extract their text content and create text nodes
|
|
53
|
-
var textContent = child.textContent;
|
|
54
|
-
if (textContent) {
|
|
55
|
-
var textNode = tr.doc.type.schema.text(textContent);
|
|
56
|
-
inlineContent.push(textNode);
|
|
39
|
+
var isSourceBulletOrOrdered = isBulletOrOrderedList(sourceList.type);
|
|
40
|
+
var isTargetTask = isTaskList(targetNodeType);
|
|
41
|
+
var isSourceTask = isTaskList(sourceList.type);
|
|
42
|
+
var isTargetBulletOrOrdered = isBulletOrOrderedList(targetNodeType);
|
|
43
|
+
var supportedListTypes = getSupportedListTypesSet(nodes);
|
|
44
|
+
var _transformListRecursively = function transformListRecursively(listNode) {
|
|
45
|
+
var transformedItems = [];
|
|
46
|
+
listNode.forEach(function (child) {
|
|
47
|
+
if (isSourceBulletOrOrdered && isTargetTask) {
|
|
48
|
+
// Convert bullet/ordered => task
|
|
49
|
+
if (child.type === listItem) {
|
|
50
|
+
var inlineContent = [];
|
|
51
|
+
var nestedTaskLists = [];
|
|
52
|
+
child.forEach(function (grandChild) {
|
|
53
|
+
if (supportedListTypes.has(grandChild.type) && grandChild.type !== taskList) {
|
|
54
|
+
nestedTaskLists.push(_transformListRecursively(grandChild));
|
|
55
|
+
} else {
|
|
56
|
+
inlineContent.push.apply(inlineContent, _toConsumableArray(convertBlockToInlineContent(grandChild, tr.doc.type.schema)));
|
|
57
57
|
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
});
|
|
59
|
+
if (inlineContent.length > 0) {
|
|
60
|
+
transformedItems.push(taskItem.create(null, inlineContent));
|
|
61
61
|
}
|
|
62
|
+
transformedItems.push.apply(transformedItems, nestedTaskLists);
|
|
62
63
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
64
|
+
} else if (isSourceTask && isTargetBulletOrOrdered) {
|
|
65
|
+
// Convert task => bullet/ordered
|
|
66
|
+
if (child.type === taskItem) {
|
|
67
|
+
var _inlineContent = _toConsumableArray(child.content.content);
|
|
68
|
+
if (_inlineContent.length > 0) {
|
|
69
|
+
var paragraphNode = paragraph.create(null, _inlineContent);
|
|
70
|
+
transformedItems.push(listItem.create(null, [paragraphNode]));
|
|
71
|
+
}
|
|
72
|
+
} else if (child.type === taskList) {
|
|
73
|
+
var transformedNestedList = _transformListRecursively(child);
|
|
74
|
+
var lastItem = transformedItems[transformedItems.length - 1];
|
|
75
|
+
if ((lastItem === null || lastItem === void 0 ? void 0 : lastItem.type) === listItem) {
|
|
76
|
+
// Attach nested list to previous item
|
|
77
|
+
var updatedContent = [].concat(_toConsumableArray(lastItem.content.content), [transformedNestedList]);
|
|
78
|
+
transformedItems[transformedItems.length - 1] = listItem.create(lastItem.attrs, updatedContent);
|
|
79
|
+
} else {
|
|
80
|
+
// No previous item, flatten nested items
|
|
81
|
+
transformedItems.push.apply(transformedItems, _toConsumableArray(transformedNestedList.content.content));
|
|
82
|
+
}
|
|
77
83
|
}
|
|
78
84
|
}
|
|
79
|
-
}
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Create new list with transformed items
|
|
87
|
-
var newList = targetNodeType.create(null, newListItems);
|
|
88
|
-
|
|
89
|
-
// Replace the entire list
|
|
90
|
-
tr.replaceWith(listStart, listEnd, newList);
|
|
85
|
+
});
|
|
86
|
+
return targetNodeType.create(null, transformedItems);
|
|
87
|
+
};
|
|
88
|
+
var newList = _transformListRecursively(sourceList);
|
|
89
|
+
tr.replaceWith(listPos, listPos + sourceList.nodeSize, newList);
|
|
91
90
|
return tr;
|
|
92
91
|
} catch (_unused) {
|
|
93
92
|
return tr;
|