@atlaskit/editor-plugin-block-menu 1.0.12 → 1.0.13
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 +8 -0
- package/dist/cjs/editor-commands/transforms/block-transforms.js +1 -1
- package/dist/cjs/editor-commands/transforms/inline-node-transforms.js +9 -7
- package/dist/cjs/editor-commands/transforms/layout/utils.js +289 -0
- package/dist/cjs/editor-commands/transforms/layout-transforms.js +40 -2
- package/dist/cjs/editor-commands/transforms/list/transformBetweenListTypes.js +92 -50
- package/dist/cjs/editor-commands/transforms/transformNodeToTargetType.js +3 -0
- package/dist/cjs/editor-commands/transforms/utils.js +7 -1
- package/dist/es2019/editor-commands/transforms/block-transforms.js +2 -2
- package/dist/es2019/editor-commands/transforms/inline-node-transforms.js +8 -6
- package/dist/es2019/editor-commands/transforms/layout/utils.js +272 -0
- package/dist/es2019/editor-commands/transforms/layout-transforms.js +40 -1
- package/dist/es2019/editor-commands/transforms/list/transformBetweenListTypes.js +94 -51
- package/dist/es2019/editor-commands/transforms/transformNodeToTargetType.js +5 -2
- package/dist/es2019/editor-commands/transforms/utils.js +6 -0
- package/dist/esm/editor-commands/transforms/block-transforms.js +2 -2
- package/dist/esm/editor-commands/transforms/inline-node-transforms.js +8 -6
- package/dist/esm/editor-commands/transforms/layout/utils.js +282 -0
- package/dist/esm/editor-commands/transforms/layout-transforms.js +38 -1
- package/dist/esm/editor-commands/transforms/list/transformBetweenListTypes.js +92 -49
- package/dist/esm/editor-commands/transforms/transformNodeToTargetType.js +5 -2
- package/dist/esm/editor-commands/transforms/utils.js +6 -0
- package/dist/types/editor-commands/transforms/inline-node-transforms.d.ts +3 -3
- package/dist/types/editor-commands/transforms/layout/utils.d.ts +5 -0
- package/dist/types/editor-commands/transforms/layout-transforms.d.ts +1 -0
- package/dist/types/editor-commands/transforms/list/transformBetweenListTypes.d.ts +13 -0
- package/dist/types/editor-commands/transforms/utils.d.ts +2 -0
- package/dist/types-ts4.5/editor-commands/transforms/inline-node-transforms.d.ts +3 -3
- package/dist/types-ts4.5/editor-commands/transforms/layout/utils.d.ts +5 -0
- package/dist/types-ts4.5/editor-commands/transforms/layout-transforms.d.ts +1 -0
- package/dist/types-ts4.5/editor-commands/transforms/list/transformBetweenListTypes.d.ts +13 -0
- package/dist/types-ts4.5/editor-commands/transforms/utils.d.ts +2 -0
- package/package.json +2 -2
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
+
import { getInlineNodeTextContent } from '../inline-node-transforms';
|
|
4
|
+
import { transformListRecursively } from '../list/transformBetweenListTypes';
|
|
5
|
+
import { getContentSupportChecker, getSupportedListTypesSet, isBlockNode, isBlockNodeForExtraction, isBlockNodeType, isBulletOrOrderedList, isContainerNode, isContainerNodeType, isHeadingOrParagraphNode, isListNode, isListNodeType, isTaskList } from '../utils';
|
|
6
|
+
export const unwrapLayoutNodesToTextNodes = (context, finalTargetNodeType) => {
|
|
7
|
+
const {
|
|
8
|
+
tr,
|
|
9
|
+
sourceNode,
|
|
10
|
+
targetNodeType,
|
|
11
|
+
targetAttrs
|
|
12
|
+
} = context;
|
|
13
|
+
const schema = tr.doc.type.schema || {};
|
|
14
|
+
const isValid = getContentSupportChecker(finalTargetNodeType);
|
|
15
|
+
const createTextNode = node => {
|
|
16
|
+
const isTextNode = node.type.name === 'text';
|
|
17
|
+
if (isValid(node) && !isTextNode) {
|
|
18
|
+
return node;
|
|
19
|
+
}
|
|
20
|
+
return targetNodeType.createChecked(targetAttrs, isTextNode ? node : node.content, node.marks);
|
|
21
|
+
};
|
|
22
|
+
if (isBlockNode(sourceNode)) {
|
|
23
|
+
// code block acts like a container, we need to unwrap it
|
|
24
|
+
if (sourceNode.type === schema.nodes.codeBlock) {
|
|
25
|
+
const textNodes = sourceNode.textContent.split('\n').map(line => targetNodeType.createChecked(undefined, line ? schema.text(line) : null));
|
|
26
|
+
return textNodes;
|
|
27
|
+
}
|
|
28
|
+
return [createTextNode(sourceNode)];
|
|
29
|
+
}
|
|
30
|
+
if (isContainerNode(sourceNode)) {
|
|
31
|
+
var _sourceNode$attrs;
|
|
32
|
+
const containerNodes = [];
|
|
33
|
+
if (sourceNode.type.name === 'expand' && (_sourceNode$attrs = sourceNode.attrs) !== null && _sourceNode$attrs !== void 0 && _sourceNode$attrs.title) {
|
|
34
|
+
containerNodes.push(createTextNode(schema.text(sourceNode.attrs.title)));
|
|
35
|
+
}
|
|
36
|
+
sourceNode.content.forEach(childNode => {
|
|
37
|
+
if (isHeadingOrParagraphNode(childNode)) {
|
|
38
|
+
containerNodes.push(createTextNode(childNode));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
containerNodes.push(childNode);
|
|
42
|
+
});
|
|
43
|
+
return containerNodes;
|
|
44
|
+
}
|
|
45
|
+
if (isListNode(sourceNode)) {
|
|
46
|
+
if (isBlockNodeType(finalTargetNodeType)) {
|
|
47
|
+
if (sourceNode.type.name === 'taskList') {
|
|
48
|
+
const taskItemsResult = findChildrenByType(sourceNode, schema.nodes.taskItem);
|
|
49
|
+
const taskItems = taskItemsResult.map(item => item.node);
|
|
50
|
+
const taskItemFragments = taskItems.map(taskItem => taskItem.content);
|
|
51
|
+
return taskItemFragments.map(fragment => targetNodeType.createChecked(targetAttrs, fragment.content));
|
|
52
|
+
} else {
|
|
53
|
+
const paragraphs = findChildrenByType(sourceNode, schema.nodes.paragraph);
|
|
54
|
+
const paragraphNodes = paragraphs.map(paragraph => paragraph.node);
|
|
55
|
+
if (targetNodeType === schema.nodes.heading) {
|
|
56
|
+
return paragraphNodes.map(paragraphNode => targetNodeType.createChecked(targetAttrs, paragraphNode.content));
|
|
57
|
+
}
|
|
58
|
+
return paragraphNodes;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return [sourceNode];
|
|
62
|
+
}
|
|
63
|
+
return [sourceNode];
|
|
64
|
+
};
|
|
65
|
+
const transformToBlockNode = (nodes, targetNodeType, schema) => {
|
|
66
|
+
if (targetNodeType === schema.nodes.codeBlock) {
|
|
67
|
+
const newNodes = [];
|
|
68
|
+
nodes.forEach(node => {
|
|
69
|
+
if (node.isTextblock) {
|
|
70
|
+
const inlineTextContent = node.type === schema.nodes.codeBlock ? node.textContent : getInlineNodeTextContent(Fragment.from(node));
|
|
71
|
+
|
|
72
|
+
// For first node, add directly
|
|
73
|
+
if (newNodes.length === 0) {
|
|
74
|
+
newNodes.push({
|
|
75
|
+
canBeTransformed: true,
|
|
76
|
+
content: [inlineTextContent]
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
// Check if last node can also be transformed, if yes then append content
|
|
80
|
+
const lastItem = newNodes[newNodes.length - 1];
|
|
81
|
+
if (lastItem.canBeTransformed) {
|
|
82
|
+
newNodes[newNodes.length - 1] = {
|
|
83
|
+
content: [...lastItem.content, inlineTextContent],
|
|
84
|
+
canBeTransformed: true
|
|
85
|
+
};
|
|
86
|
+
} else {
|
|
87
|
+
newNodes.push({
|
|
88
|
+
content: [inlineTextContent],
|
|
89
|
+
canBeTransformed: true
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
// If not text block, then cannot be transformed
|
|
95
|
+
newNodes.push({
|
|
96
|
+
canBeTransformed: false,
|
|
97
|
+
content: node
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
return newNodes.map(({
|
|
102
|
+
canBeTransformed,
|
|
103
|
+
content
|
|
104
|
+
}) => {
|
|
105
|
+
if (canBeTransformed) {
|
|
106
|
+
const text = content.join('\n');
|
|
107
|
+
if (text === '') {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
return targetNodeType.createChecked(null, schema.text(text));
|
|
111
|
+
} else {
|
|
112
|
+
return content;
|
|
113
|
+
}
|
|
114
|
+
}).filter(Boolean);
|
|
115
|
+
}
|
|
116
|
+
return nodes;
|
|
117
|
+
};
|
|
118
|
+
const transformToContainerNode = (nodes, targetNodeType) => {
|
|
119
|
+
const newNodes = [];
|
|
120
|
+
const isNodeValid = getContentSupportChecker(targetNodeType);
|
|
121
|
+
nodes.forEach(node => {
|
|
122
|
+
// If the node is not supported then we append as is
|
|
123
|
+
if (isBlockNodeForExtraction(node)) {
|
|
124
|
+
newNodes.push({
|
|
125
|
+
node: node,
|
|
126
|
+
canBeTransformed: false
|
|
127
|
+
});
|
|
128
|
+
} else {
|
|
129
|
+
// Remove alignment marks as container nodes don't support them
|
|
130
|
+
const nodeWithValidAttrs = node.mark(node.marks.filter(mark => mark.type.name !== 'alignment'));
|
|
131
|
+
const isSameNodeType = node.type === targetNodeType;
|
|
132
|
+
|
|
133
|
+
// If the node is not valid and not the same type, we cannot transform it
|
|
134
|
+
if (!isNodeValid(nodeWithValidAttrs) && !isSameNodeType) {
|
|
135
|
+
newNodes.push({
|
|
136
|
+
node: node,
|
|
137
|
+
canBeTransformed: false
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const nodes = isSameNodeType ? node.content.content : [nodeWithValidAttrs];
|
|
142
|
+
if (newNodes.length === 0) {
|
|
143
|
+
newNodes.push({
|
|
144
|
+
node: nodes,
|
|
145
|
+
canBeTransformed: true
|
|
146
|
+
});
|
|
147
|
+
} else {
|
|
148
|
+
const lastItem = newNodes[newNodes.length - 1];
|
|
149
|
+
if (lastItem.canBeTransformed) {
|
|
150
|
+
newNodes[newNodes.length - 1] = {
|
|
151
|
+
node: [...lastItem.node, ...nodes],
|
|
152
|
+
canBeTransformed: true
|
|
153
|
+
};
|
|
154
|
+
} else {
|
|
155
|
+
newNodes.push({
|
|
156
|
+
node: nodes,
|
|
157
|
+
canBeTransformed: true
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
return newNodes.map(({
|
|
164
|
+
node,
|
|
165
|
+
canBeTransformed
|
|
166
|
+
}) => {
|
|
167
|
+
if (canBeTransformed) {
|
|
168
|
+
return targetNodeType.createChecked(null, Fragment.fromArray(node));
|
|
169
|
+
} else {
|
|
170
|
+
return node;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
export const transformToListNode = (nodes, targetNodeType, schema) => {
|
|
175
|
+
const isTargetTask = isTaskList(targetNodeType);
|
|
176
|
+
const listItems = [];
|
|
177
|
+
const listItemType = isTargetTask ? schema.nodes.taskItem : schema.nodes.listItem;
|
|
178
|
+
const isValid = getContentSupportChecker(listItemType);
|
|
179
|
+
nodes.forEach(node => {
|
|
180
|
+
// Append unsupported nodes as is
|
|
181
|
+
if (isBlockNodeForExtraction(node)) {
|
|
182
|
+
listItems.push({
|
|
183
|
+
canBeTransformed: false,
|
|
184
|
+
node
|
|
185
|
+
});
|
|
186
|
+
} else {
|
|
187
|
+
let newListItems;
|
|
188
|
+
|
|
189
|
+
// If the node is a list, we may need to transform it
|
|
190
|
+
if (isListNode(node)) {
|
|
191
|
+
const isSourceBulletOrOrdered = isBulletOrOrderedList(node.type);
|
|
192
|
+
const isTargetTask = isTaskList(targetNodeType);
|
|
193
|
+
const isSourceTask = isTaskList(node.type);
|
|
194
|
+
const isTargetBulletOrOrdered = isBulletOrOrderedList(targetNodeType);
|
|
195
|
+
const supportedListTypes = getSupportedListTypesSet(schema.nodes);
|
|
196
|
+
if (node.type === targetNodeType) {
|
|
197
|
+
// For the same list type, we can keep the structure
|
|
198
|
+
newListItems = node.content.content;
|
|
199
|
+
} else {
|
|
200
|
+
const newList = transformListRecursively({
|
|
201
|
+
isSourceBulletOrOrdered,
|
|
202
|
+
isSourceTask,
|
|
203
|
+
isTargetBulletOrOrdered,
|
|
204
|
+
isTargetTask,
|
|
205
|
+
listNode: node,
|
|
206
|
+
schema,
|
|
207
|
+
supportedListTypes,
|
|
208
|
+
targetNodeType
|
|
209
|
+
});
|
|
210
|
+
newListItems = [...newList.content.content];
|
|
211
|
+
}
|
|
212
|
+
} else if (isHeadingOrParagraphNode(node) || isValid(node)) {
|
|
213
|
+
if (isTargetTask) {
|
|
214
|
+
const inlineContent = [...node.content.content];
|
|
215
|
+
if (inlineContent.length > 0) {
|
|
216
|
+
newListItems = [listItemType.create(null, inlineContent)];
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
newListItems = [listItemType.create(null, node)];
|
|
220
|
+
}
|
|
221
|
+
} else if (!isValid(node)) {
|
|
222
|
+
listItems.push({
|
|
223
|
+
canBeTransformed: false,
|
|
224
|
+
node
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
if (newListItems) {
|
|
228
|
+
if (listItems.length === 0) {
|
|
229
|
+
listItems.push({
|
|
230
|
+
canBeTransformed: true,
|
|
231
|
+
node: newListItems
|
|
232
|
+
});
|
|
233
|
+
} else {
|
|
234
|
+
const lastItem = listItems[listItems.length - 1];
|
|
235
|
+
if (lastItem.canBeTransformed) {
|
|
236
|
+
listItems[listItems.length - 1] = {
|
|
237
|
+
node: [...lastItem.node, ...newListItems],
|
|
238
|
+
canBeTransformed: true
|
|
239
|
+
};
|
|
240
|
+
} else {
|
|
241
|
+
listItems.push({
|
|
242
|
+
node: newListItems,
|
|
243
|
+
canBeTransformed: true
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
return listItems.map(({
|
|
251
|
+
node,
|
|
252
|
+
canBeTransformed
|
|
253
|
+
}) => {
|
|
254
|
+
if (canBeTransformed) {
|
|
255
|
+
return targetNodeType.createChecked(null, Fragment.fromArray(node));
|
|
256
|
+
} else {
|
|
257
|
+
return node;
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
};
|
|
261
|
+
export const convertUnwrappedLayoutContent = (nodes, targetNodeType, schema) => {
|
|
262
|
+
if (isBlockNodeType(targetNodeType)) {
|
|
263
|
+
return transformToBlockNode(nodes, targetNodeType, schema);
|
|
264
|
+
}
|
|
265
|
+
if (isContainerNodeType(targetNodeType)) {
|
|
266
|
+
return transformToContainerNode(nodes, targetNodeType);
|
|
267
|
+
}
|
|
268
|
+
if (isListNodeType(targetNodeType)) {
|
|
269
|
+
return transformToListNode(nodes, targetNodeType, schema);
|
|
270
|
+
}
|
|
271
|
+
return [];
|
|
272
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_TWO_COLUMN_LAYOUT_COLUMN_WIDTH } from '@atlaskit/editor-common/styles';
|
|
2
2
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
import { convertUnwrappedLayoutContent, unwrapLayoutNodesToTextNodes } from './layout/utils';
|
|
3
4
|
export const convertToLayout = context => {
|
|
4
5
|
const {
|
|
5
6
|
tr,
|
|
@@ -20,6 +21,44 @@ export const convertToLayout = context => {
|
|
|
20
21
|
const layoutSectionNode = layoutSection.createChecked(undefined, layoutContent);
|
|
21
22
|
|
|
22
23
|
// Replace the original node with the new layout node
|
|
23
|
-
tr.replaceRangeWith(sourcePos
|
|
24
|
+
tr.replaceRangeWith(sourcePos, sourcePos + sourceNode.nodeSize, layoutSectionNode);
|
|
24
25
|
return tr;
|
|
26
|
+
};
|
|
27
|
+
export const transformLayoutNode = context => {
|
|
28
|
+
const {
|
|
29
|
+
tr,
|
|
30
|
+
sourceNode,
|
|
31
|
+
targetNodeType,
|
|
32
|
+
sourcePos,
|
|
33
|
+
targetAttrs
|
|
34
|
+
} = context;
|
|
35
|
+
const schema = tr.doc.type.schema || {};
|
|
36
|
+
const {
|
|
37
|
+
layoutSection,
|
|
38
|
+
layoutColumn,
|
|
39
|
+
paragraph,
|
|
40
|
+
heading
|
|
41
|
+
} = schema.nodes || {};
|
|
42
|
+
const layoutColumnNodes = [];
|
|
43
|
+
const targetTextNodeType = targetNodeType === heading ? heading : paragraph;
|
|
44
|
+
sourceNode.children.forEach(child => {
|
|
45
|
+
if (child.type === layoutColumn) {
|
|
46
|
+
const unwrappedContent = [];
|
|
47
|
+
child.content.forEach(node => {
|
|
48
|
+
// Unwrap all nodes and convert to text nodes
|
|
49
|
+
const context = {
|
|
50
|
+
tr,
|
|
51
|
+
sourceNode: node,
|
|
52
|
+
targetNodeType: targetTextNodeType,
|
|
53
|
+
sourcePos: 0,
|
|
54
|
+
targetAttrs
|
|
55
|
+
};
|
|
56
|
+
const newContent = unwrapLayoutNodesToTextNodes(context, targetNodeType);
|
|
57
|
+
unwrappedContent.push(...newContent);
|
|
58
|
+
});
|
|
59
|
+
const newColumnContent = convertUnwrappedLayoutContent(unwrappedContent, targetNodeType, schema);
|
|
60
|
+
layoutColumnNodes.push(layoutColumn.createChecked(child.attrs, Fragment.fromArray(newColumnContent), child.marks));
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return tr.replaceRangeWith(sourcePos, sourcePos + sourceNode.nodeSize, layoutSection.createChecked(sourceNode.attrs, Fragment.fromArray(layoutColumnNodes), sourceNode.marks));
|
|
25
64
|
};
|
|
@@ -16,6 +16,88 @@ const convertBlockToInlineContent = (node, schema) => {
|
|
|
16
16
|
}
|
|
17
17
|
return [node];
|
|
18
18
|
};
|
|
19
|
+
export const transformListRecursively = props => {
|
|
20
|
+
const transformedItems = [];
|
|
21
|
+
const {
|
|
22
|
+
listNode,
|
|
23
|
+
isSourceBulletOrOrdered,
|
|
24
|
+
isTargetBulletOrOrdered,
|
|
25
|
+
isSourceTask,
|
|
26
|
+
isTargetTask,
|
|
27
|
+
supportedListTypes,
|
|
28
|
+
schema,
|
|
29
|
+
targetNodeType
|
|
30
|
+
} = props;
|
|
31
|
+
const {
|
|
32
|
+
taskList,
|
|
33
|
+
listItem,
|
|
34
|
+
taskItem,
|
|
35
|
+
paragraph
|
|
36
|
+
} = schema.nodes;
|
|
37
|
+
listNode.forEach(child => {
|
|
38
|
+
if (isSourceBulletOrOrdered && isTargetTask) {
|
|
39
|
+
// Convert bullet/ordered => task
|
|
40
|
+
if (child.type === listItem) {
|
|
41
|
+
const inlineContent = [];
|
|
42
|
+
const nestedTaskLists = [];
|
|
43
|
+
child.forEach(grandChild => {
|
|
44
|
+
if (supportedListTypes.has(grandChild.type) && grandChild.type !== taskList) {
|
|
45
|
+
nestedTaskLists.push(transformListRecursively({
|
|
46
|
+
...props,
|
|
47
|
+
listNode: grandChild
|
|
48
|
+
}));
|
|
49
|
+
} else {
|
|
50
|
+
inlineContent.push(...convertBlockToInlineContent(grandChild, schema));
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
if (inlineContent.length > 0) {
|
|
54
|
+
transformedItems.push(taskItem.create(null, inlineContent));
|
|
55
|
+
}
|
|
56
|
+
transformedItems.push(...nestedTaskLists);
|
|
57
|
+
}
|
|
58
|
+
} else if (isSourceTask && isTargetBulletOrOrdered) {
|
|
59
|
+
// Convert task => bullet/ordered
|
|
60
|
+
if (child.type === taskItem) {
|
|
61
|
+
const inlineContent = [...child.content.content];
|
|
62
|
+
if (inlineContent.length > 0) {
|
|
63
|
+
const paragraphNode = paragraph.create(null, inlineContent);
|
|
64
|
+
transformedItems.push(listItem.create(null, [paragraphNode]));
|
|
65
|
+
}
|
|
66
|
+
} else if (child.type === taskList) {
|
|
67
|
+
const transformedNestedList = transformListRecursively({
|
|
68
|
+
...props,
|
|
69
|
+
listNode: child
|
|
70
|
+
});
|
|
71
|
+
const lastItem = transformedItems[transformedItems.length - 1];
|
|
72
|
+
if ((lastItem === null || lastItem === void 0 ? void 0 : lastItem.type) === listItem) {
|
|
73
|
+
// Attach nested list to previous item
|
|
74
|
+
const updatedContent = [...lastItem.content.content, transformedNestedList];
|
|
75
|
+
transformedItems[transformedItems.length - 1] = listItem.create(lastItem.attrs, updatedContent);
|
|
76
|
+
} else {
|
|
77
|
+
// No previous item, flatten nested items
|
|
78
|
+
transformedItems.push(...transformedNestedList.content.content);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} else if (isSourceBulletOrOrdered && isTargetBulletOrOrdered) {
|
|
82
|
+
if (child.type === listItem) {
|
|
83
|
+
const convertedNestedLists = [];
|
|
84
|
+
child.forEach(grandChild => {
|
|
85
|
+
if (supportedListTypes.has(grandChild.type) && grandChild.type !== targetNodeType) {
|
|
86
|
+
const convertedNode = transformListRecursively({
|
|
87
|
+
...props,
|
|
88
|
+
listNode: grandChild
|
|
89
|
+
});
|
|
90
|
+
convertedNestedLists.push(convertedNode);
|
|
91
|
+
} else {
|
|
92
|
+
convertedNestedLists.push(grandChild);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
transformedItems.push(listItem.create(null, convertedNestedLists));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
return targetNodeType.create(null, transformedItems);
|
|
100
|
+
};
|
|
19
101
|
|
|
20
102
|
/**
|
|
21
103
|
* Transform list structure between different list types
|
|
@@ -37,62 +119,23 @@ export const transformListStructure = context => {
|
|
|
37
119
|
node: sourceList,
|
|
38
120
|
pos: listPos
|
|
39
121
|
} = listNode;
|
|
40
|
-
const {
|
|
41
|
-
|
|
42
|
-
listItem,
|
|
43
|
-
taskItem,
|
|
44
|
-
paragraph
|
|
45
|
-
} = nodes;
|
|
122
|
+
// const { taskList, listItem, taskItem, paragraph } = nodes;
|
|
123
|
+
|
|
46
124
|
const isSourceBulletOrOrdered = isBulletOrOrderedList(sourceList.type);
|
|
47
125
|
const isTargetTask = isTaskList(targetNodeType);
|
|
48
126
|
const isSourceTask = isTaskList(sourceList.type);
|
|
49
127
|
const isTargetBulletOrOrdered = isBulletOrOrderedList(targetNodeType);
|
|
50
128
|
const supportedListTypes = getSupportedListTypesSet(nodes);
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
nestedTaskLists.push(transformListRecursively(grandChild));
|
|
62
|
-
} else {
|
|
63
|
-
inlineContent.push(...convertBlockToInlineContent(grandChild, tr.doc.type.schema));
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
if (inlineContent.length > 0) {
|
|
67
|
-
transformedItems.push(taskItem.create(null, inlineContent));
|
|
68
|
-
}
|
|
69
|
-
transformedItems.push(...nestedTaskLists);
|
|
70
|
-
}
|
|
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
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
return targetNodeType.create(null, transformedItems);
|
|
94
|
-
};
|
|
95
|
-
const newList = transformListRecursively(sourceList);
|
|
129
|
+
const newList = transformListRecursively({
|
|
130
|
+
isSourceBulletOrOrdered,
|
|
131
|
+
isSourceTask,
|
|
132
|
+
isTargetBulletOrOrdered,
|
|
133
|
+
isTargetTask,
|
|
134
|
+
listNode: sourceList,
|
|
135
|
+
schema: tr.doc.type.schema,
|
|
136
|
+
supportedListTypes,
|
|
137
|
+
targetNodeType
|
|
138
|
+
});
|
|
96
139
|
tr.replaceWith(listPos, listPos + sourceList.nodeSize, newList);
|
|
97
140
|
return tr;
|
|
98
141
|
} catch {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { transformBlockNode } from './block-transforms';
|
|
2
2
|
import { transformContainerNode, unwrapAndConvertToList } from './container-transforms';
|
|
3
|
-
import { convertToLayout } from './layout-transforms';
|
|
3
|
+
import { convertToLayout, transformLayoutNode } from './layout-transforms';
|
|
4
4
|
import { transformListNode } from './list-transforms';
|
|
5
|
-
import { getTargetNodeInfo, isBlockNode, isListNode, isListNodeType, isContainerNode, isLayoutNodeType } from './utils';
|
|
5
|
+
import { getTargetNodeInfo, isBlockNode, isListNode, isListNodeType, isContainerNode, isLayoutNodeType, isLayoutNode } from './utils';
|
|
6
6
|
export function transformNodeToTargetType(tr, sourceNode, sourcePos, targetType) {
|
|
7
7
|
const {
|
|
8
8
|
nodes
|
|
@@ -50,6 +50,9 @@ export function transformNodeToTargetType(tr, sourceNode, sourcePos, targetType)
|
|
|
50
50
|
if (sourceNode.type.name === 'codeBlock' && isListNodeType(targetNodeType)) {
|
|
51
51
|
return unwrapAndConvertToList(transformationContext);
|
|
52
52
|
}
|
|
53
|
+
if (isLayoutNode(sourceNode)) {
|
|
54
|
+
return transformLayoutNode(transformationContext);
|
|
55
|
+
}
|
|
53
56
|
if (isBlockNode(sourceNode)) {
|
|
54
57
|
return transformBlockNode(transformationContext);
|
|
55
58
|
}
|
|
@@ -91,6 +91,9 @@ export const getTargetNodeInfo = (targetType, nodes) => {
|
|
|
91
91
|
export const isBlockNode = node => {
|
|
92
92
|
return ['paragraph', 'heading', 'codeBlock'].includes(node.type.name);
|
|
93
93
|
};
|
|
94
|
+
export const isHeadingOrParagraphNode = node => {
|
|
95
|
+
return ['paragraph', 'heading'].includes(node.type.name);
|
|
96
|
+
};
|
|
94
97
|
export const isListNode = node => {
|
|
95
98
|
return ['bulletList', 'orderedList', 'taskList'].includes(node.type.name);
|
|
96
99
|
};
|
|
@@ -123,6 +126,9 @@ export const getSupportedListTypesSet = nodes => {
|
|
|
123
126
|
export const isLayoutNodeType = nodeType => {
|
|
124
127
|
return nodeType.name === 'layoutSection';
|
|
125
128
|
};
|
|
129
|
+
export const isLayoutNode = node => {
|
|
130
|
+
return node.type.name === 'layoutSection';
|
|
131
|
+
};
|
|
126
132
|
|
|
127
133
|
/**
|
|
128
134
|
* Check if a node should be extracted as a standalone block node
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { transformToContainer, unwrapAndConvertToBlockType } from './container-transforms';
|
|
2
|
-
import {
|
|
2
|
+
import { getInlineNodeTextNode } from './inline-node-transforms';
|
|
3
3
|
import { transformBlockToList } from './list-transforms';
|
|
4
4
|
import { isListNodeType, isContainerNodeType, isBlockNodeType } from './utils';
|
|
5
5
|
|
|
@@ -36,7 +36,7 @@ var transformToBlockNode = function transformToBlockNode(context) {
|
|
|
36
36
|
$to = selection.$to;
|
|
37
37
|
var schema = doc.type.schema;
|
|
38
38
|
if (targetNodeType === schema.nodes.codeBlock) {
|
|
39
|
-
var textContent =
|
|
39
|
+
var textContent = getInlineNodeTextNode(selection.content().content, schema);
|
|
40
40
|
var node = schema.nodes.codeBlock.createChecked(undefined, textContent);
|
|
41
41
|
return tr.replaceRangeWith(selection.from, selection.to, node);
|
|
42
42
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
export var getInlineNodeTextContent = function getInlineNodeTextContent(sourceContent
|
|
1
|
+
export var getInlineNodeTextContent = function getInlineNodeTextContent(sourceContent) {
|
|
2
2
|
var validTransformedContent = '';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return;
|
|
3
|
+
if (sourceContent.content.length < 1) {
|
|
4
|
+
return '';
|
|
6
5
|
}
|
|
7
6
|
// Headings are not valid inside headings so convert heading nodes to paragraphs
|
|
8
7
|
sourceContent.forEach(function (node) {
|
|
@@ -14,8 +13,11 @@ export var getInlineNodeTextContent = function getInlineNodeTextContent(sourceCo
|
|
|
14
13
|
validTransformedContent += "".concat(inlineNode.textContent);
|
|
15
14
|
}
|
|
16
15
|
});
|
|
17
|
-
validTransformedContent;
|
|
18
16
|
}
|
|
19
17
|
});
|
|
20
|
-
return
|
|
18
|
+
return validTransformedContent;
|
|
19
|
+
};
|
|
20
|
+
export var getInlineNodeTextNode = function getInlineNodeTextNode(sourceContent, schema) {
|
|
21
|
+
var text = getInlineNodeTextContent(sourceContent);
|
|
22
|
+
return schema.text(text);
|
|
21
23
|
};
|