@atlaskit/editor-plugin-block-menu 5.1.3 → 5.1.5
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 +17 -0
- package/dist/cjs/editor-commands/transform-node-utils/flattenListStep.js +108 -0
- package/dist/cjs/editor-commands/transform-node-utils/flattenStep.js +21 -0
- package/dist/cjs/editor-commands/transform-node-utils/transform.js +33 -5
- package/dist/cjs/editor-commands/transform-node-utils/types.js +1 -1
- package/dist/cjs/editor-commands/transform-node-utils/unwrapExpandStep.js +44 -0
- package/dist/cjs/editor-commands/transform-node-utils/unwrapListStep.js +28 -0
- package/dist/cjs/editor-commands/transform-node-utils/unwrapStep.js +20 -0
- package/dist/cjs/editor-commands/transform-node-utils/utils.js +7 -1
- package/dist/cjs/editor-commands/transform-node-utils/wrapIntoLayoutStep.js +23 -0
- package/dist/cjs/editor-commands/transform-node-utils/wrapStep.js +16 -0
- package/dist/cjs/editor-commands/transformNode.js +12 -6
- package/dist/cjs/ui/block-menu.js +20 -7
- package/dist/es2019/editor-commands/transform-node-utils/flattenListStep.js +94 -0
- package/dist/es2019/editor-commands/transform-node-utils/flattenStep.js +15 -0
- package/dist/es2019/editor-commands/transform-node-utils/transform.js +34 -6
- package/dist/es2019/editor-commands/transform-node-utils/types.js +1 -1
- package/dist/es2019/editor-commands/transform-node-utils/unwrapExpandStep.js +38 -0
- package/dist/es2019/editor-commands/transform-node-utils/unwrapListStep.js +18 -0
- package/dist/es2019/editor-commands/transform-node-utils/unwrapStep.js +12 -0
- package/dist/es2019/editor-commands/transform-node-utils/utils.js +6 -0
- package/dist/es2019/editor-commands/transform-node-utils/wrapIntoLayoutStep.js +20 -0
- package/dist/es2019/editor-commands/transform-node-utils/wrapStep.js +12 -0
- package/dist/es2019/editor-commands/transformNode.js +12 -7
- package/dist/es2019/ui/block-menu.js +15 -7
- package/dist/esm/editor-commands/transform-node-utils/flattenListStep.js +102 -0
- package/dist/esm/editor-commands/transform-node-utils/flattenStep.js +15 -0
- package/dist/esm/editor-commands/transform-node-utils/transform.js +33 -5
- package/dist/esm/editor-commands/transform-node-utils/types.js +1 -1
- package/dist/esm/editor-commands/transform-node-utils/unwrapExpandStep.js +37 -0
- package/dist/esm/editor-commands/transform-node-utils/unwrapListStep.js +21 -0
- package/dist/esm/editor-commands/transform-node-utils/unwrapStep.js +13 -0
- package/dist/esm/editor-commands/transform-node-utils/utils.js +6 -0
- package/dist/esm/editor-commands/transform-node-utils/wrapIntoLayoutStep.js +17 -0
- package/dist/esm/editor-commands/transform-node-utils/wrapStep.js +10 -0
- package/dist/esm/editor-commands/transformNode.js +12 -6
- package/dist/esm/ui/block-menu.js +19 -7
- package/dist/types/editor-commands/transform-node-utils/flattenListStep.d.ts +49 -0
- package/dist/types/editor-commands/transform-node-utils/flattenStep.d.ts +2 -0
- package/dist/types/editor-commands/transform-node-utils/transform.d.ts +3 -2
- package/dist/types/editor-commands/transform-node-utils/types.d.ts +1 -1
- package/dist/types/editor-commands/transform-node-utils/unwrapExpandStep.d.ts +8 -0
- package/dist/types/editor-commands/transform-node-utils/unwrapListStep.d.ts +7 -0
- package/dist/types/editor-commands/transform-node-utils/unwrapStep.d.ts +2 -0
- package/dist/types/editor-commands/transform-node-utils/utils.d.ts +2 -0
- package/dist/types/editor-commands/transform-node-utils/wrapIntoLayoutStep.d.ts +2 -0
- package/dist/types/editor-commands/transform-node-utils/wrapStep.d.ts +2 -0
- package/dist/types/editor-commands/transforms/types.d.ts +1 -1
- package/dist/types-ts4.5/editor-commands/transform-node-utils/flattenListStep.d.ts +49 -0
- package/dist/types-ts4.5/editor-commands/transform-node-utils/flattenStep.d.ts +2 -0
- package/dist/types-ts4.5/editor-commands/transform-node-utils/transform.d.ts +3 -2
- package/dist/types-ts4.5/editor-commands/transform-node-utils/types.d.ts +1 -1
- package/dist/types-ts4.5/editor-commands/transform-node-utils/unwrapExpandStep.d.ts +8 -0
- package/dist/types-ts4.5/editor-commands/transform-node-utils/unwrapListStep.d.ts +7 -0
- package/dist/types-ts4.5/editor-commands/transform-node-utils/unwrapStep.d.ts +2 -0
- package/dist/types-ts4.5/editor-commands/transform-node-utils/utils.d.ts +2 -0
- package/dist/types-ts4.5/editor-commands/transform-node-utils/wrapIntoLayoutStep.d.ts +2 -0
- package/dist/types-ts4.5/editor-commands/transform-node-utils/wrapStep.d.ts +2 -0
- package/dist/types-ts4.5/editor-commands/transforms/types.d.ts +1 -1
- package/package.json +3 -3
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
import { getTargetNodeTypeNameInContext } from '../transform-node-utils/utils';
|
|
2
|
+
import { flattenListStep } from './flattenListStep';
|
|
3
|
+
import { flattenStep } from './flattenStep';
|
|
1
4
|
import { stubStep } from './stubStep';
|
|
2
5
|
import { NODE_CATEGORY_BY_TYPE, toNodeTypeValue } from './types';
|
|
6
|
+
import { unwrapExpandStep } from './unwrapExpandStep';
|
|
7
|
+
import { unwrapListStep } from './unwrapListStep';
|
|
8
|
+
import { unwrapStep } from './unwrapStep';
|
|
9
|
+
import { wrapIntoLayoutStep } from './wrapIntoLayoutStep';
|
|
10
|
+
import { wrapStep } from './wrapStep';
|
|
3
11
|
|
|
4
12
|
// Exampled step for overrides:
|
|
5
13
|
// - open Block menu on a paragraph, click 'Panel' in the Turn into'
|
|
@@ -19,15 +27,15 @@ const TRANSFORM_STEPS = {
|
|
|
19
27
|
},
|
|
20
28
|
container: {
|
|
21
29
|
atomic: undefined,
|
|
22
|
-
container: [
|
|
30
|
+
container: [unwrapStep, wrapStep],
|
|
23
31
|
list: undefined,
|
|
24
|
-
text:
|
|
32
|
+
text: [unwrapStep]
|
|
25
33
|
},
|
|
26
34
|
list: {
|
|
27
35
|
atomic: undefined,
|
|
28
36
|
container: [stubStep],
|
|
29
37
|
list: [stubStep],
|
|
30
|
-
text: [
|
|
38
|
+
text: [flattenListStep, unwrapListStep]
|
|
31
39
|
},
|
|
32
40
|
text: {
|
|
33
41
|
atomic: undefined,
|
|
@@ -42,6 +50,23 @@ const TRANSFORM_STEPS = {
|
|
|
42
50
|
const TRANSFORM_STEPS_OVERRIDE = {
|
|
43
51
|
paragraph: {
|
|
44
52
|
panel: [wrapIntoPanelStep]
|
|
53
|
+
},
|
|
54
|
+
panel: {
|
|
55
|
+
layoutSection: [unwrapStep, wrapIntoLayoutStep],
|
|
56
|
+
codeBlock: [unwrapStep, flattenStep, wrapStep]
|
|
57
|
+
},
|
|
58
|
+
expand: {
|
|
59
|
+
panel: [unwrapExpandStep, wrapStep],
|
|
60
|
+
blockquote: [unwrapExpandStep, wrapStep],
|
|
61
|
+
layoutSection: [unwrapExpandStep, wrapIntoLayoutStep],
|
|
62
|
+
paragraph: [unwrapExpandStep],
|
|
63
|
+
codeBlock: [unwrapExpandStep, flattenStep, wrapStep]
|
|
64
|
+
},
|
|
65
|
+
nestedExpand: {
|
|
66
|
+
panel: [unwrapExpandStep, wrapStep],
|
|
67
|
+
blockquote: [unwrapExpandStep, wrapStep],
|
|
68
|
+
paragraph: [unwrapExpandStep],
|
|
69
|
+
codeBlock: [unwrapExpandStep, flattenStep, wrapStep]
|
|
45
70
|
}
|
|
46
71
|
};
|
|
47
72
|
const getTransformStepsForNodeTypes = (selectedNodeTypeName, targetNodeTypeName) => {
|
|
@@ -55,11 +80,13 @@ const getTransformStepsForNodeTypes = (selectedNodeTypeName, targetNodeTypeName)
|
|
|
55
80
|
export const getOutputNodes = ({
|
|
56
81
|
sourceNode,
|
|
57
82
|
targetNodeType,
|
|
58
|
-
schema
|
|
83
|
+
schema,
|
|
84
|
+
isNested
|
|
59
85
|
}) => {
|
|
60
86
|
const nodesToReplace = [sourceNode];
|
|
61
87
|
const selectedNodeTypeName = toNodeTypeValue(sourceNode.type.name);
|
|
62
|
-
|
|
88
|
+
let targetNodeTypeName = toNodeTypeValue(targetNodeType.name);
|
|
89
|
+
targetNodeTypeName = getTargetNodeTypeNameInContext(targetNodeTypeName, isNested);
|
|
63
90
|
if (!selectedNodeTypeName || !targetNodeTypeName) {
|
|
64
91
|
// We may decide to return an empty array or undefined here
|
|
65
92
|
return;
|
|
@@ -74,6 +101,7 @@ export const getOutputNodes = ({
|
|
|
74
101
|
return;
|
|
75
102
|
}
|
|
76
103
|
return steps.reduce((nodes, step) => {
|
|
77
|
-
|
|
104
|
+
const result = step(nodes, context);
|
|
105
|
+
return result;
|
|
78
106
|
}, nodesToReplace);
|
|
79
107
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unwraps an expand/nestedExpand node, converting its title attribute to a paragraph
|
|
3
|
+
* and prepending it to the children.
|
|
4
|
+
*
|
|
5
|
+
* Example: expand({ title: 'title' })(p('b')) → [p('title'), p('b')]
|
|
6
|
+
*/
|
|
7
|
+
export const unwrapExpandStep = (nodes, context) => {
|
|
8
|
+
const {
|
|
9
|
+
schema
|
|
10
|
+
} = context;
|
|
11
|
+
const outputNodes = [];
|
|
12
|
+
nodes.forEach(node => {
|
|
13
|
+
const isExpand = node.type.name === 'expand' || node.type.name === 'nestedExpand';
|
|
14
|
+
if (isExpand) {
|
|
15
|
+
var _node$attrs;
|
|
16
|
+
const title = (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.title;
|
|
17
|
+
|
|
18
|
+
// Create a paragraph from the title if it exists
|
|
19
|
+
if (title) {
|
|
20
|
+
const titleParagraph = schema.nodes.paragraph.createAndFill({}, schema.text(title));
|
|
21
|
+
if (titleParagraph) {
|
|
22
|
+
outputNodes.push(titleParagraph);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Add the children
|
|
27
|
+
outputNodes.push(...node.children);
|
|
28
|
+
} else {
|
|
29
|
+
// Fallback: behave like unwrapStep for non-expand nodes
|
|
30
|
+
if (node.children.length === 0) {
|
|
31
|
+
outputNodes.push(node);
|
|
32
|
+
} else {
|
|
33
|
+
outputNodes.push(...node.children);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return outputNodes;
|
|
38
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Given an array of nodes, returns an array with the flattened children of any list nodes.
|
|
3
|
+
* @param nodes
|
|
4
|
+
* @returns
|
|
5
|
+
*/
|
|
6
|
+
export const unwrapListStep = (nodes, context) => {
|
|
7
|
+
const listTypes = [context.schema.nodes.bulletList, context.schema.nodes.orderedList, context.schema.nodes.taskList];
|
|
8
|
+
return nodes.flatMap(node => {
|
|
9
|
+
if (listTypes.some(type => node.type === type)) {
|
|
10
|
+
const listItems = [];
|
|
11
|
+
node.forEach(listItem => {
|
|
12
|
+
listItems.push(...listItem.children);
|
|
13
|
+
});
|
|
14
|
+
return listItems;
|
|
15
|
+
}
|
|
16
|
+
return node;
|
|
17
|
+
});
|
|
18
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const unwrapStep = nodes => {
|
|
2
|
+
const outputNodes = [];
|
|
3
|
+
nodes.forEach(node => {
|
|
4
|
+
// we may want to just skip the original instead of using it
|
|
5
|
+
if (node.children.length === 0) {
|
|
6
|
+
outputNodes.push(node);
|
|
7
|
+
} else {
|
|
8
|
+
outputNodes.push(...node.children);
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
return outputNodes;
|
|
12
|
+
};
|
|
@@ -43,4 +43,10 @@ export const getSelectedNode = selection => {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
return undefined;
|
|
46
|
+
};
|
|
47
|
+
export const getTargetNodeTypeNameInContext = (nodeTypeName, isNested) => {
|
|
48
|
+
if (nodeTypeName === 'expand' && isNested) {
|
|
49
|
+
return 'nestedExpand';
|
|
50
|
+
}
|
|
51
|
+
return nodeTypeName;
|
|
46
52
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
export const wrapIntoLayoutStep = (nodes, context) => {
|
|
3
|
+
const {
|
|
4
|
+
schema
|
|
5
|
+
} = context;
|
|
6
|
+
const {
|
|
7
|
+
layoutSection,
|
|
8
|
+
layoutColumn
|
|
9
|
+
} = schema.nodes || {};
|
|
10
|
+
const columnOne = layoutColumn.createAndFill({}, Fragment.fromArray(nodes));
|
|
11
|
+
const columnTwo = layoutColumn.createAndFill();
|
|
12
|
+
if (!columnOne || !columnTwo) {
|
|
13
|
+
return nodes;
|
|
14
|
+
}
|
|
15
|
+
const layout = layoutSection.createAndFill({}, Fragment.fromArray([columnOne, columnTwo]));
|
|
16
|
+
if (!layout) {
|
|
17
|
+
return nodes;
|
|
18
|
+
}
|
|
19
|
+
return [layout];
|
|
20
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const wrapStep = (nodes, context) => {
|
|
2
|
+
const {
|
|
3
|
+
schema,
|
|
4
|
+
targetNodeTypeName
|
|
5
|
+
} = context;
|
|
6
|
+
// edge case: nestedExpand
|
|
7
|
+
const outputNode = schema.nodes[targetNodeTypeName].createAndFill({}, nodes);
|
|
8
|
+
if (outputNode) {
|
|
9
|
+
return [outputNode];
|
|
10
|
+
}
|
|
11
|
+
return nodes;
|
|
12
|
+
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { expandToBlockRange } from '@atlaskit/editor-common/selection';
|
|
1
2
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
import { isNestedNode } from '../ui/utils/isNestedNode';
|
|
2
4
|
import { getOutputNodes } from './transform-node-utils/transform';
|
|
3
5
|
import { isListNode } from './transforms/utils';
|
|
4
6
|
export const transformNode = api =>
|
|
@@ -13,25 +15,28 @@ export const transformNode = api =>
|
|
|
13
15
|
return tr;
|
|
14
16
|
}
|
|
15
17
|
const {
|
|
16
|
-
from,
|
|
17
|
-
to
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
$from,
|
|
19
|
+
$to
|
|
20
|
+
} = expandToBlockRange(preservedSelection.$from, preservedSelection.$to);
|
|
21
|
+
const isNested = isNestedNode(preservedSelection, '');
|
|
20
22
|
const selectedParent = $from.parent;
|
|
21
23
|
let fragment = Fragment.empty;
|
|
22
24
|
const isList = isListNode(selectedParent);
|
|
23
|
-
const slice = tr.doc.slice(isList ? from - 1 : from, isList ? to + 1 : to);
|
|
25
|
+
const slice = tr.doc.slice(isList ? $from.pos - 1 : $from.pos, isList ? $to.pos + 1 : $to.pos);
|
|
24
26
|
slice.content.forEach(node => {
|
|
25
27
|
const outputNode = getOutputNodes({
|
|
26
28
|
sourceNode: node,
|
|
27
29
|
targetNodeType: targetType,
|
|
28
|
-
schema: tr.doc.type.schema
|
|
30
|
+
schema: tr.doc.type.schema,
|
|
31
|
+
isNested
|
|
29
32
|
});
|
|
30
33
|
if (outputNode) {
|
|
31
34
|
fragment = fragment.append(Fragment.fromArray(outputNode));
|
|
32
35
|
}
|
|
33
36
|
});
|
|
34
|
-
|
|
37
|
+
|
|
38
|
+
// TODO: ED-12345 - selection is broken post transaction, to fix.
|
|
39
|
+
tr.replaceWith(isList ? $from.pos - 1 : $from.pos, $to.pos, fragment);
|
|
35
40
|
return tr;
|
|
36
41
|
};
|
|
37
42
|
};
|
|
@@ -25,6 +25,7 @@ const styles = {
|
|
|
25
25
|
};
|
|
26
26
|
const DEFAULT_MENU_WIDTH = 230;
|
|
27
27
|
const DRAG_HANDLE_OFFSET_PADDING = 5;
|
|
28
|
+
const FALLBACK_MENU_HEIGHT = 300;
|
|
28
29
|
const PopupWithListeners = withReactEditorViewOuterListeners(Popup);
|
|
29
30
|
const useConditionalBlockMenuEffect = conditionalHooksFactory(() => fg('platform_editor_toolbar_aifc_user_intent_fix'), ({
|
|
30
31
|
api,
|
|
@@ -153,6 +154,15 @@ const BlockMenu = ({
|
|
|
153
154
|
const targetHandleRef = editorView === null || editorView === void 0 ? void 0 : (_editorView$dom = editorView.dom) === null || _editorView$dom === void 0 ? void 0 : _editorView$dom.querySelector(DRAG_HANDLE_SELECTOR);
|
|
154
155
|
const prevIsMenuOpenRef = useRef(false);
|
|
155
156
|
const popupRef = useRef(undefined);
|
|
157
|
+
const [menuHeight, setMenuHeight] = React.useState(0);
|
|
158
|
+
const targetHandleHeightOffset = -((targetHandleRef === null || targetHandleRef === void 0 ? void 0 : targetHandleRef.clientHeight) || 0);
|
|
159
|
+
React.useLayoutEffect(() => {
|
|
160
|
+
var _popupRef$current;
|
|
161
|
+
if (!isMenuOpen) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
setMenuHeight(((_popupRef$current = popupRef.current) === null || _popupRef$current === void 0 ? void 0 : _popupRef$current.clientHeight) || FALLBACK_MENU_HEIGHT);
|
|
165
|
+
}, [isMenuOpen]);
|
|
156
166
|
const hasFocus = (_ref = (editorView === null || editorView === void 0 ? void 0 : editorView.hasFocus()) || document.activeElement === targetHandleRef || popupRef.current && (popupRef.current.contains(document.activeElement) || popupRef.current === document.activeElement)) !== null && _ref !== void 0 ? _ref : false;
|
|
157
167
|
const selectedByShortcutOrDragHandle = !!isSelectedViaDragHandle || !!openedViaKeyboard;
|
|
158
168
|
|
|
@@ -218,8 +228,7 @@ const BlockMenu = ({
|
|
|
218
228
|
fallbackComponent: null
|
|
219
229
|
}, /*#__PURE__*/React.createElement(PopupWithListeners, {
|
|
220
230
|
alignX: 'right',
|
|
221
|
-
alignY: 'start'
|
|
222
|
-
,
|
|
231
|
+
alignY: 'start',
|
|
223
232
|
handleClickOutside: closeMenu,
|
|
224
233
|
handleEscapeKeydown: closeMenu,
|
|
225
234
|
handleBackspaceDeleteKeydown: handleBackspaceDeleteKeydown,
|
|
@@ -229,16 +238,15 @@ const BlockMenu = ({
|
|
|
229
238
|
target: targetHandleRef,
|
|
230
239
|
zIndex: akEditorFloatingOverlapPanelZIndex,
|
|
231
240
|
fitWidth: DEFAULT_MENU_WIDTH,
|
|
232
|
-
|
|
233
|
-
preventOverflow: true
|
|
234
|
-
,
|
|
241
|
+
fitHeight: menuHeight,
|
|
242
|
+
preventOverflow: true,
|
|
235
243
|
stick: true,
|
|
244
|
+
offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, targetHandleHeightOffset],
|
|
236
245
|
focusTrap: openedViaKeyboard ?
|
|
237
246
|
// Only enable focus trap when opened via keyboard to make sure the focus is on the first focusable menu item
|
|
238
247
|
{
|
|
239
248
|
initialFocus: undefined
|
|
240
|
-
} : undefined
|
|
241
|
-
offset: [DRAG_HANDLE_WIDTH + DRAG_HANDLE_OFFSET_PADDING, 0]
|
|
249
|
+
} : undefined
|
|
242
250
|
}, /*#__PURE__*/React.createElement(BlockMenuContent, {
|
|
243
251
|
api: api,
|
|
244
252
|
setRef: setRef
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
var extractNestedLists = function extractNestedLists(node, listTypes, itemTypes) {
|
|
3
|
+
var items = [];
|
|
4
|
+
var _extract = function extract(currentNode) {
|
|
5
|
+
currentNode.forEach(function (child) {
|
|
6
|
+
// list item -> take content without nested lists, then recurse into nested lists
|
|
7
|
+
if (itemTypes.some(function (type) {
|
|
8
|
+
return child.type === type;
|
|
9
|
+
})) {
|
|
10
|
+
// Filter out nested list nodes from the list item's content
|
|
11
|
+
var contentWithoutNestedLists = [];
|
|
12
|
+
var nestedLists = [];
|
|
13
|
+
child.forEach(function (grandChild) {
|
|
14
|
+
if (listTypes.some(function (type) {
|
|
15
|
+
return grandChild.type === type;
|
|
16
|
+
})) {
|
|
17
|
+
// This is a nested list - collect it for later processing
|
|
18
|
+
nestedLists.push(grandChild);
|
|
19
|
+
} else {
|
|
20
|
+
// This is regular content (paragraph, etc.) - keep it
|
|
21
|
+
contentWithoutNestedLists.push(grandChild);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Add the list item with only its non-list content
|
|
26
|
+
items.push(child.copy(Fragment.from(contentWithoutNestedLists)));
|
|
27
|
+
|
|
28
|
+
// Now process nested lists to maintain document order
|
|
29
|
+
nestedLists.forEach(function (nestedList) {
|
|
30
|
+
_extract(nestedList);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
// lists -> keep operating
|
|
34
|
+
else if (listTypes.some(function (type) {
|
|
35
|
+
return child.type === type;
|
|
36
|
+
})) {
|
|
37
|
+
_extract(child);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
_extract(node);
|
|
42
|
+
return items;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Given an array of nodes, returns an array with the flattened children of any list node
|
|
47
|
+
* to it's first ancestor list, maintaining document order.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* Input:
|
|
51
|
+
* - bulletList
|
|
52
|
+
* - listItem "A"
|
|
53
|
+
* - listItem "B"
|
|
54
|
+
* - bulletList
|
|
55
|
+
* - listItem "C"
|
|
56
|
+
* - listItem "D"
|
|
57
|
+
* - listItem "E"
|
|
58
|
+
*
|
|
59
|
+
* Output:
|
|
60
|
+
* - bulletList
|
|
61
|
+
* - listItem "A"
|
|
62
|
+
* - listItem "B"
|
|
63
|
+
* - listItem "C"
|
|
64
|
+
* - listItem "D"
|
|
65
|
+
* - listItem "E"
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* Input (deeply nested):
|
|
69
|
+
* - bulletList
|
|
70
|
+
* - listItem "1"
|
|
71
|
+
* - bulletList
|
|
72
|
+
* - listItem "1.1"
|
|
73
|
+
* - bulletList
|
|
74
|
+
* - listItem "1.1.1"
|
|
75
|
+
* - listItem "1.2"
|
|
76
|
+
* - listItem "2"
|
|
77
|
+
*
|
|
78
|
+
* Output:
|
|
79
|
+
* - bulletList
|
|
80
|
+
* - listItem "1"
|
|
81
|
+
* - listItem "1.1"
|
|
82
|
+
* - listItem "1.1.1"
|
|
83
|
+
* - listItem "1.2"
|
|
84
|
+
* - listItem "2"
|
|
85
|
+
*
|
|
86
|
+
* @param nodes
|
|
87
|
+
* @param context
|
|
88
|
+
* @returns
|
|
89
|
+
*
|
|
90
|
+
* TODO: Lists with mixed types (e.g. bulletList with a taskItem) doesn't full flatten
|
|
91
|
+
*/
|
|
92
|
+
export var flattenListStep = function flattenListStep(nodes, context) {
|
|
93
|
+
var listTypes = [context.schema.nodes.bulletList, context.schema.nodes.orderedList, context.schema.nodes.taskList];
|
|
94
|
+
return nodes.map(function (node) {
|
|
95
|
+
if (listTypes.some(function (type) {
|
|
96
|
+
return node.type === type;
|
|
97
|
+
})) {
|
|
98
|
+
return node.copy(Fragment.from(extractNestedLists(node, listTypes, [context.schema.nodes.listItem, context.schema.nodes.taskItem])));
|
|
99
|
+
}
|
|
100
|
+
return node;
|
|
101
|
+
});
|
|
102
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export var flattenStep = function flattenStep(nodes, context) {
|
|
2
|
+
var schema = context.schema,
|
|
3
|
+
targetNodeTypeName = context.targetNodeTypeName;
|
|
4
|
+
|
|
5
|
+
// TODO: EDITOR-2920 - Implement flattening logic.
|
|
6
|
+
// This is a simplified preliminary approach. We might want to use prosemirror-markdown functions.
|
|
7
|
+
var codeBlockContent = nodes.map(function (node) {
|
|
8
|
+
return node.content.textBetween(0, node.content.size, '\n');
|
|
9
|
+
}).join('\n');
|
|
10
|
+
var outputNode = schema.nodes[targetNodeTypeName].createAndFill({}, schema.text(codeBlockContent));
|
|
11
|
+
if (!outputNode) {
|
|
12
|
+
return nodes;
|
|
13
|
+
}
|
|
14
|
+
return [outputNode];
|
|
15
|
+
};
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
import { getTargetNodeTypeNameInContext } from '../transform-node-utils/utils';
|
|
2
|
+
import { flattenListStep } from './flattenListStep';
|
|
3
|
+
import { flattenStep } from './flattenStep';
|
|
1
4
|
import { stubStep } from './stubStep';
|
|
2
5
|
import { NODE_CATEGORY_BY_TYPE, toNodeTypeValue } from './types';
|
|
6
|
+
import { unwrapExpandStep } from './unwrapExpandStep';
|
|
7
|
+
import { unwrapListStep } from './unwrapListStep';
|
|
8
|
+
import { unwrapStep } from './unwrapStep';
|
|
9
|
+
import { wrapIntoLayoutStep } from './wrapIntoLayoutStep';
|
|
10
|
+
import { wrapStep } from './wrapStep';
|
|
3
11
|
|
|
4
12
|
// Exampled step for overrides:
|
|
5
13
|
// - open Block menu on a paragraph, click 'Panel' in the Turn into'
|
|
@@ -19,15 +27,15 @@ var TRANSFORM_STEPS = {
|
|
|
19
27
|
},
|
|
20
28
|
container: {
|
|
21
29
|
atomic: undefined,
|
|
22
|
-
container: [
|
|
30
|
+
container: [unwrapStep, wrapStep],
|
|
23
31
|
list: undefined,
|
|
24
|
-
text:
|
|
32
|
+
text: [unwrapStep]
|
|
25
33
|
},
|
|
26
34
|
list: {
|
|
27
35
|
atomic: undefined,
|
|
28
36
|
container: [stubStep],
|
|
29
37
|
list: [stubStep],
|
|
30
|
-
text: [
|
|
38
|
+
text: [flattenListStep, unwrapListStep]
|
|
31
39
|
},
|
|
32
40
|
text: {
|
|
33
41
|
atomic: undefined,
|
|
@@ -42,6 +50,23 @@ var TRANSFORM_STEPS = {
|
|
|
42
50
|
var TRANSFORM_STEPS_OVERRIDE = {
|
|
43
51
|
paragraph: {
|
|
44
52
|
panel: [wrapIntoPanelStep]
|
|
53
|
+
},
|
|
54
|
+
panel: {
|
|
55
|
+
layoutSection: [unwrapStep, wrapIntoLayoutStep],
|
|
56
|
+
codeBlock: [unwrapStep, flattenStep, wrapStep]
|
|
57
|
+
},
|
|
58
|
+
expand: {
|
|
59
|
+
panel: [unwrapExpandStep, wrapStep],
|
|
60
|
+
blockquote: [unwrapExpandStep, wrapStep],
|
|
61
|
+
layoutSection: [unwrapExpandStep, wrapIntoLayoutStep],
|
|
62
|
+
paragraph: [unwrapExpandStep],
|
|
63
|
+
codeBlock: [unwrapExpandStep, flattenStep, wrapStep]
|
|
64
|
+
},
|
|
65
|
+
nestedExpand: {
|
|
66
|
+
panel: [unwrapExpandStep, wrapStep],
|
|
67
|
+
blockquote: [unwrapExpandStep, wrapStep],
|
|
68
|
+
paragraph: [unwrapExpandStep],
|
|
69
|
+
codeBlock: [unwrapExpandStep, flattenStep, wrapStep]
|
|
45
70
|
}
|
|
46
71
|
};
|
|
47
72
|
var getTransformStepsForNodeTypes = function getTransformStepsForNodeTypes(selectedNodeTypeName, targetNodeTypeName) {
|
|
@@ -55,10 +80,12 @@ var getTransformStepsForNodeTypes = function getTransformStepsForNodeTypes(selec
|
|
|
55
80
|
export var getOutputNodes = function getOutputNodes(_ref) {
|
|
56
81
|
var sourceNode = _ref.sourceNode,
|
|
57
82
|
targetNodeType = _ref.targetNodeType,
|
|
58
|
-
schema = _ref.schema
|
|
83
|
+
schema = _ref.schema,
|
|
84
|
+
isNested = _ref.isNested;
|
|
59
85
|
var nodesToReplace = [sourceNode];
|
|
60
86
|
var selectedNodeTypeName = toNodeTypeValue(sourceNode.type.name);
|
|
61
87
|
var targetNodeTypeName = toNodeTypeValue(targetNodeType.name);
|
|
88
|
+
targetNodeTypeName = getTargetNodeTypeNameInContext(targetNodeTypeName, isNested);
|
|
62
89
|
if (!selectedNodeTypeName || !targetNodeTypeName) {
|
|
63
90
|
// We may decide to return an empty array or undefined here
|
|
64
91
|
return;
|
|
@@ -73,6 +100,7 @@ export var getOutputNodes = function getOutputNodes(_ref) {
|
|
|
73
100
|
return;
|
|
74
101
|
}
|
|
75
102
|
return steps.reduce(function (nodes, step) {
|
|
76
|
-
|
|
103
|
+
var result = step(nodes, context);
|
|
104
|
+
return result;
|
|
77
105
|
}, nodesToReplace);
|
|
78
106
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
/**
|
|
3
|
+
* Unwraps an expand/nestedExpand node, converting its title attribute to a paragraph
|
|
4
|
+
* and prepending it to the children.
|
|
5
|
+
*
|
|
6
|
+
* Example: expand({ title: 'title' })(p('b')) → [p('title'), p('b')]
|
|
7
|
+
*/
|
|
8
|
+
export var unwrapExpandStep = function unwrapExpandStep(nodes, context) {
|
|
9
|
+
var schema = context.schema;
|
|
10
|
+
var outputNodes = [];
|
|
11
|
+
nodes.forEach(function (node) {
|
|
12
|
+
var isExpand = node.type.name === 'expand' || node.type.name === 'nestedExpand';
|
|
13
|
+
if (isExpand) {
|
|
14
|
+
var _node$attrs;
|
|
15
|
+
var title = (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.title;
|
|
16
|
+
|
|
17
|
+
// Create a paragraph from the title if it exists
|
|
18
|
+
if (title) {
|
|
19
|
+
var titleParagraph = schema.nodes.paragraph.createAndFill({}, schema.text(title));
|
|
20
|
+
if (titleParagraph) {
|
|
21
|
+
outputNodes.push(titleParagraph);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Add the children
|
|
26
|
+
outputNodes.push.apply(outputNodes, _toConsumableArray(node.children));
|
|
27
|
+
} else {
|
|
28
|
+
// Fallback: behave like unwrapStep for non-expand nodes
|
|
29
|
+
if (node.children.length === 0) {
|
|
30
|
+
outputNodes.push(node);
|
|
31
|
+
} else {
|
|
32
|
+
outputNodes.push.apply(outputNodes, _toConsumableArray(node.children));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return outputNodes;
|
|
37
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
/**
|
|
3
|
+
* Given an array of nodes, returns an array with the flattened children of any list nodes.
|
|
4
|
+
* @param nodes
|
|
5
|
+
* @returns
|
|
6
|
+
*/
|
|
7
|
+
export var unwrapListStep = function unwrapListStep(nodes, context) {
|
|
8
|
+
var listTypes = [context.schema.nodes.bulletList, context.schema.nodes.orderedList, context.schema.nodes.taskList];
|
|
9
|
+
return nodes.flatMap(function (node) {
|
|
10
|
+
if (listTypes.some(function (type) {
|
|
11
|
+
return node.type === type;
|
|
12
|
+
})) {
|
|
13
|
+
var listItems = [];
|
|
14
|
+
node.forEach(function (listItem) {
|
|
15
|
+
listItems.push.apply(listItems, _toConsumableArray(listItem.children));
|
|
16
|
+
});
|
|
17
|
+
return listItems;
|
|
18
|
+
}
|
|
19
|
+
return node;
|
|
20
|
+
});
|
|
21
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
export var unwrapStep = function unwrapStep(nodes) {
|
|
3
|
+
var outputNodes = [];
|
|
4
|
+
nodes.forEach(function (node) {
|
|
5
|
+
// we may want to just skip the original instead of using it
|
|
6
|
+
if (node.children.length === 0) {
|
|
7
|
+
outputNodes.push(node);
|
|
8
|
+
} else {
|
|
9
|
+
outputNodes.push.apply(outputNodes, _toConsumableArray(node.children));
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
return outputNodes;
|
|
13
|
+
};
|
|
@@ -42,4 +42,10 @@ export var getSelectedNode = function getSelectedNode(selection) {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
return undefined;
|
|
45
|
+
};
|
|
46
|
+
export var getTargetNodeTypeNameInContext = function getTargetNodeTypeNameInContext(nodeTypeName, isNested) {
|
|
47
|
+
if (nodeTypeName === 'expand' && isNested) {
|
|
48
|
+
return 'nestedExpand';
|
|
49
|
+
}
|
|
50
|
+
return nodeTypeName;
|
|
45
51
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
export var wrapIntoLayoutStep = function wrapIntoLayoutStep(nodes, context) {
|
|
3
|
+
var schema = context.schema;
|
|
4
|
+
var _ref = schema.nodes || {},
|
|
5
|
+
layoutSection = _ref.layoutSection,
|
|
6
|
+
layoutColumn = _ref.layoutColumn;
|
|
7
|
+
var columnOne = layoutColumn.createAndFill({}, Fragment.fromArray(nodes));
|
|
8
|
+
var columnTwo = layoutColumn.createAndFill();
|
|
9
|
+
if (!columnOne || !columnTwo) {
|
|
10
|
+
return nodes;
|
|
11
|
+
}
|
|
12
|
+
var layout = layoutSection.createAndFill({}, Fragment.fromArray([columnOne, columnTwo]));
|
|
13
|
+
if (!layout) {
|
|
14
|
+
return nodes;
|
|
15
|
+
}
|
|
16
|
+
return [layout];
|
|
17
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export var wrapStep = function wrapStep(nodes, context) {
|
|
2
|
+
var schema = context.schema,
|
|
3
|
+
targetNodeTypeName = context.targetNodeTypeName;
|
|
4
|
+
// edge case: nestedExpand
|
|
5
|
+
var outputNode = schema.nodes[targetNodeTypeName].createAndFill({}, nodes);
|
|
6
|
+
if (outputNode) {
|
|
7
|
+
return [outputNode];
|
|
8
|
+
}
|
|
9
|
+
return nodes;
|
|
10
|
+
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { expandToBlockRange } from '@atlaskit/editor-common/selection';
|
|
1
2
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
import { isNestedNode } from '../ui/utils/isNestedNode';
|
|
2
4
|
import { getOutputNodes } from './transform-node-utils/transform';
|
|
3
5
|
import { isListNode } from './transforms/utils';
|
|
4
6
|
export var transformNode = function transformNode(api) {
|
|
@@ -12,24 +14,28 @@ export var transformNode = function transformNode(api) {
|
|
|
12
14
|
if (!preservedSelection) {
|
|
13
15
|
return tr;
|
|
14
16
|
}
|
|
15
|
-
var
|
|
16
|
-
|
|
17
|
-
$
|
|
17
|
+
var _expandToBlockRange = expandToBlockRange(preservedSelection.$from, preservedSelection.$to),
|
|
18
|
+
$from = _expandToBlockRange.$from,
|
|
19
|
+
$to = _expandToBlockRange.$to;
|
|
20
|
+
var isNested = isNestedNode(preservedSelection, '');
|
|
18
21
|
var selectedParent = $from.parent;
|
|
19
22
|
var fragment = Fragment.empty;
|
|
20
23
|
var isList = isListNode(selectedParent);
|
|
21
|
-
var slice = tr.doc.slice(isList ? from - 1 : from, isList ? to + 1 : to);
|
|
24
|
+
var slice = tr.doc.slice(isList ? $from.pos - 1 : $from.pos, isList ? $to.pos + 1 : $to.pos);
|
|
22
25
|
slice.content.forEach(function (node) {
|
|
23
26
|
var outputNode = getOutputNodes({
|
|
24
27
|
sourceNode: node,
|
|
25
28
|
targetNodeType: targetType,
|
|
26
|
-
schema: tr.doc.type.schema
|
|
29
|
+
schema: tr.doc.type.schema,
|
|
30
|
+
isNested: isNested
|
|
27
31
|
});
|
|
28
32
|
if (outputNode) {
|
|
29
33
|
fragment = fragment.append(Fragment.fromArray(outputNode));
|
|
30
34
|
}
|
|
31
35
|
});
|
|
32
|
-
|
|
36
|
+
|
|
37
|
+
// TODO: ED-12345 - selection is broken post transaction, to fix.
|
|
38
|
+
tr.replaceWith(isList ? $from.pos - 1 : $from.pos, $to.pos, fragment);
|
|
33
39
|
return tr;
|
|
34
40
|
};
|
|
35
41
|
}
|