@atlaskit/editor-plugin-block-menu 1.0.5 → 1.0.7

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 CHANGED
@@ -1,5 +1,21 @@
1
1
  # @atlaskit/editor-plugin-block-menu
2
2
 
3
+ ## 1.0.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [`34871606f04ba`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/34871606f04ba) -
8
+ [ux] Updates unwrapAndConvertToList to support codeBlock to list case and cases where contnent is
9
+ not textblock.
10
+
11
+ ## 1.0.6
12
+
13
+ ### Patch Changes
14
+
15
+ - [`40e6bcca6edd4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/40e6bcca6edd4) -
16
+ [ux] ED-29146: unwrap container to block nodes
17
+ - Updated dependencies
18
+
3
19
  ## 1.0.5
4
20
 
5
21
  ### Patch Changes
@@ -33,7 +33,8 @@ var transformBlockNode = exports.transformBlockNode = function transformBlockNod
33
33
  var transformToBlockNode = function transformToBlockNode(context) {
34
34
  var tr = context.tr,
35
35
  targetNodeType = context.targetNodeType,
36
- targetAttrs = context.targetAttrs;
36
+ targetAttrs = context.targetAttrs,
37
+ sourceNode = context.sourceNode;
37
38
  var selection = tr.selection,
38
39
  doc = tr.doc;
39
40
  var $from = selection.$from,
@@ -44,6 +45,11 @@ var transformToBlockNode = function transformToBlockNode(context) {
44
45
  var node = schema.nodes.codeBlock.createChecked(undefined, textContent);
45
46
  return tr.replaceRangeWith(selection.from, selection.to, node);
46
47
  }
48
+
49
+ // code block acts like a container, we need to unwrap it
50
+ if (sourceNode.type === schema.nodes.codeBlock) {
51
+ return (0, _containerTransforms.unwrapAndConvertToBlockType)(context);
52
+ }
47
53
  tr.setBlockType($from.pos, $to.pos, targetNodeType, targetAttrs);
48
54
  return tr;
49
55
  };
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
7
  exports.unwrapAndConvertToList = exports.unwrapAndConvertToBlockType = exports.transformToContainer = exports.transformContainerNode = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
7
9
  var _model = require("@atlaskit/editor-prosemirror/model");
8
10
  var _utils = require("./utils");
9
11
  var convertInvalidNodeToValidNodeType = function convertInvalidNodeToValidNodeType(sourceContent, sourceNodeType, validNodeType, withMarks) {
@@ -60,7 +62,13 @@ var transformContainerNode = exports.transformContainerNode = function transform
60
62
 
61
63
  // Transform container to block type - unwrap and convert content
62
64
  if ((0, _utils.isBlockNodeType)(targetNodeType)) {
63
- return unwrapAndConvertToBlockType();
65
+ return unwrapAndConvertToBlockType({
66
+ tr: tr,
67
+ sourceNode: sourceNode,
68
+ sourcePos: sourcePos,
69
+ targetNodeType: targetNodeType,
70
+ targetAttrs: targetAttrs
71
+ });
64
72
  }
65
73
 
66
74
  // Transform container to list type
@@ -85,9 +93,73 @@ var transformContainerNode = exports.transformContainerNode = function transform
85
93
  /**
86
94
  * Unwrap container node and convert content to block type
87
95
  */
88
- var unwrapAndConvertToBlockType = exports.unwrapAndConvertToBlockType = function unwrapAndConvertToBlockType() {
89
- // Convert to block type directly
90
- return null;
96
+ var unwrapAndConvertToBlockType = exports.unwrapAndConvertToBlockType = function unwrapAndConvertToBlockType(context) {
97
+ var tr = context.tr,
98
+ targetNodeType = context.targetNodeType,
99
+ targetAttrs = context.targetAttrs,
100
+ sourceNode = context.sourceNode,
101
+ sourcePos = context.sourcePos;
102
+ var selection = tr.selection;
103
+ var schema = selection.$from.doc.type.schema;
104
+ var _schema$nodes = schema.nodes,
105
+ paragraph = _schema$nodes.paragraph,
106
+ heading = _schema$nodes.heading,
107
+ codeBlock = _schema$nodes.codeBlock,
108
+ expand = _schema$nodes.expand;
109
+ var rangeStart = sourcePos !== null ? sourcePos : selection.from;
110
+ var sourceChildren = (0, _toConsumableArray2.default)(sourceNode.children);
111
+ var transformedContent = [];
112
+
113
+ // If the container is expand, we need to extract the title and convert it to a paragraph
114
+ // and add it to the beginning of the content
115
+ if (sourceNode.type === expand) {
116
+ var _sourceNode$attrs;
117
+ var title = (_sourceNode$attrs = sourceNode.attrs) === null || _sourceNode$attrs === void 0 ? void 0 : _sourceNode$attrs.title;
118
+ if (title) {
119
+ var titleContent = schema.text(title);
120
+ sourceChildren.unshift(paragraph.createChecked({}, titleContent));
121
+ }
122
+ }
123
+
124
+ // if the container is a code block, convert text content to multiple paragraphs
125
+ if (sourceNode.type === codeBlock) {
126
+ var codeText = sourceNode.textContent;
127
+ var lines = codeText.split('\n');
128
+ var paragraphNodes = lines.map(function (line) {
129
+ return paragraph.create(null, line ? schema.text(line) : null);
130
+ });
131
+ sourceChildren = paragraphNodes;
132
+ }
133
+
134
+ // if target node is a paragraph, just do unwrap
135
+ if (targetNodeType === paragraph) {
136
+ transformedContent = sourceChildren;
137
+ }
138
+
139
+ // if target node is a headings, do unwrap and convert to heading
140
+ if (targetNodeType === heading && targetAttrs) {
141
+ var targetHeadingLevel = targetAttrs.level;
142
+ sourceChildren.forEach(function (node, index) {
143
+ if (node.isTextblock) {
144
+ var headingNode = heading.create({
145
+ level: targetHeadingLevel
146
+ }, node.content);
147
+ sourceChildren[index] = headingNode;
148
+ }
149
+ });
150
+ transformedContent = sourceChildren;
151
+ }
152
+
153
+ // if target node is code block, do unwrap and convert to code block
154
+ if (targetNodeType === codeBlock) {
155
+ var codeBlockContent = sourceChildren.map(function (node) {
156
+ return node.content.textBetween(0, node.content.size, '\n');
157
+ }).join('\n');
158
+ transformedContent = [codeBlock.createChecked({}, schema.text(codeBlockContent))];
159
+ }
160
+ var slice = new _model.Slice(_model.Fragment.fromArray(transformedContent), 0, 0);
161
+ tr.replaceRange(rangeStart, rangeStart + sourceNode.nodeSize, slice);
162
+ return tr;
91
163
  };
92
164
 
93
165
  /**
@@ -99,18 +171,16 @@ var unwrapAndConvertToList = exports.unwrapAndConvertToList = function unwrapAnd
99
171
  sourcePos = _ref3.sourcePos,
100
172
  targetNodeType = _ref3.targetNodeType,
101
173
  targetAttrs = _ref3.targetAttrs;
102
- if (sourcePos === null) {
103
- return tr;
104
- }
105
174
  var schema = tr.doc.type.schema;
106
- var _schema$nodes = schema.nodes,
107
- listItem = _schema$nodes.listItem,
108
- paragraph = _schema$nodes.paragraph,
109
- taskList = _schema$nodes.taskList,
110
- taskItem = _schema$nodes.taskItem;
175
+ var _schema$nodes2 = schema.nodes,
176
+ listItem = _schema$nodes2.listItem,
177
+ paragraph = _schema$nodes2.paragraph,
178
+ taskList = _schema$nodes2.taskList,
179
+ taskItem = _schema$nodes2.taskItem,
180
+ heading = _schema$nodes2.heading;
111
181
  var isTargetTaskList = targetNodeType === taskList;
112
- var createListItemFromInline = function createListItemFromInline(inlineFrag) {
113
- return isTargetTaskList ? taskItem.create(null, inlineFrag) : listItem.create(null, paragraph.create(null, inlineFrag));
182
+ var createListItemFromInline = function createListItemFromInline(content) {
183
+ return isTargetTaskList ? taskItem.create(null, content) : listItem.create(null, paragraph.create(null, content));
114
184
  };
115
185
  var getInlineContent = function getInlineContent(textblock) {
116
186
  var inlineContent = [];
@@ -119,30 +189,56 @@ var unwrapAndConvertToList = exports.unwrapAndConvertToList = function unwrapAnd
119
189
  });
120
190
  return inlineContent;
121
191
  };
122
- var items = [];
123
-
192
+ var resultContent = [];
193
+ var currentListItems = [];
194
+ var targetListItemType = isTargetTaskList ? taskItem : listItem;
124
195
  // Expand's title should become the first item of the list
125
196
  if (sourceNode.type.name === 'expand') {
126
- var _sourceNode$attrs;
127
- var title = (_sourceNode$attrs = sourceNode.attrs) === null || _sourceNode$attrs === void 0 ? void 0 : _sourceNode$attrs.title;
197
+ var _sourceNode$attrs2;
198
+ var title = (_sourceNode$attrs2 = sourceNode.attrs) === null || _sourceNode$attrs2 === void 0 ? void 0 : _sourceNode$attrs2.title;
128
199
  if (title) {
129
200
  var titleContent = schema.text(title);
130
- items.push(isTargetTaskList ? taskItem.create(null, titleContent) : listItem.create(null, paragraph.create(null, titleContent)));
201
+ currentListItems.push(createListItemFromInline(titleContent));
131
202
  }
132
203
  }
133
- for (var i = 0; i < sourceNode.childCount; i++) {
134
- var node = sourceNode.child(i);
135
-
136
- // Abort early if unsupported content (e.g. table) encounted inside of the container
137
- if (!node.isTextblock) {
138
- return tr;
204
+ var createListAndAddToContent = function createListAndAddToContent() {
205
+ if (currentListItems.length) {
206
+ var currentList = targetNodeType.create(targetAttrs || null, _model.Fragment.from(currentListItems));
207
+ currentListItems = [];
208
+ resultContent.push(currentList);
139
209
  }
140
- var inline = _model.Fragment.from(getInlineContent(node));
141
- items.push(createListItemFromInline(inline));
210
+ };
211
+ if (sourceNode.type.name === 'codeBlock') {
212
+ var codeText = sourceNode.textContent;
213
+ if (codeText) {
214
+ var lines = codeText.split('\n');
215
+ // Remove empty lines
216
+ var nonEmptyLines = lines.filter(function (line) {
217
+ return line.trim().length > 0;
218
+ });
219
+ nonEmptyLines.forEach(function (line) {
220
+ var lineText = schema.text(line);
221
+ currentListItems.push(createListItemFromInline(lineText));
222
+ });
223
+ }
224
+ } else {
225
+ sourceNode.forEach(function (child) {
226
+ if (targetListItemType.validContent(_model.Fragment.from(child))) {
227
+ currentListItems.push(targetListItemType.create(null, child));
228
+ } else if (heading === child.type || isTargetTaskList && paragraph === child.type) {
229
+ var inline = _model.Fragment.from(getInlineContent(child));
230
+ currentListItems.push(createListItemFromInline(inline));
231
+ } else {
232
+ // Create list and add list first
233
+ createListAndAddToContent();
234
+ // Then add content that can't be converted into listItem
235
+ resultContent.push(child);
236
+ }
237
+ });
142
238
  }
143
- if (!items.length) {
144
- return tr;
239
+ if (!resultContent.length && !currentListItems.length) {
240
+ return null;
145
241
  }
146
- var list = targetNodeType.create(targetAttrs || null, _model.Fragment.from(items));
147
- return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, list);
242
+ createListAndAddToContent();
243
+ return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, _model.Fragment.from(resultContent));
148
244
  };
@@ -47,6 +47,11 @@ function transformNodeToTargetType(tr, sourceNode, sourcePos, targetType) {
47
47
  if ((0, _utils.isLayoutNodeType)(targetNodeType)) {
48
48
  return (0, _layoutTransforms.convertToLayout)(transformationContext);
49
49
  }
50
+
51
+ // special case codeblock to listType
52
+ if (sourceNode.type.name === 'codeBlock' && (0, _utils.isListNodeType)(targetNodeType)) {
53
+ return (0, _containerTransforms.unwrapAndConvertToList)(transformationContext);
54
+ }
50
55
  if ((0, _utils.isBlockNode)(sourceNode)) {
51
56
  return (0, _blockTransforms.transformBlockNode)(transformationContext);
52
57
  }
@@ -1,4 +1,4 @@
1
- import { transformToContainer } from './container-transforms';
1
+ import { transformToContainer, unwrapAndConvertToBlockType } from './container-transforms';
2
2
  import { getInlineNodeTextContent } from './inline-node-transforms';
3
3
  import { transformBlockToList } from './list-transforms';
4
4
  import { isListNodeType, isContainerNodeType, isBlockNodeType } from './utils';
@@ -31,7 +31,8 @@ const transformToBlockNode = context => {
31
31
  const {
32
32
  tr,
33
33
  targetNodeType,
34
- targetAttrs
34
+ targetAttrs,
35
+ sourceNode
35
36
  } = context;
36
37
  const {
37
38
  selection,
@@ -47,6 +48,11 @@ const transformToBlockNode = context => {
47
48
  const node = schema.nodes.codeBlock.createChecked(undefined, textContent);
48
49
  return tr.replaceRangeWith(selection.from, selection.to, node);
49
50
  }
51
+
52
+ // code block acts like a container, we need to unwrap it
53
+ if (sourceNode.type === schema.nodes.codeBlock) {
54
+ return unwrapAndConvertToBlockType(context);
55
+ }
50
56
  tr.setBlockType($from.pos, $to.pos, targetNodeType, targetAttrs);
51
57
  return tr;
52
58
  };
@@ -1,4 +1,4 @@
1
- import { Fragment } from '@atlaskit/editor-prosemirror/model';
1
+ import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
2
2
  import { isBlockNodeType, isListNodeType, isContainerNodeType } from './utils';
3
3
  const convertInvalidNodeToValidNodeType = (sourceContent, sourceNodeType, validNodeType, withMarks) => {
4
4
  const validTransformedContent = [];
@@ -56,7 +56,13 @@ export const transformContainerNode = ({
56
56
 
57
57
  // Transform container to block type - unwrap and convert content
58
58
  if (isBlockNodeType(targetNodeType)) {
59
- return unwrapAndConvertToBlockType();
59
+ return unwrapAndConvertToBlockType({
60
+ tr,
61
+ sourceNode,
62
+ sourcePos,
63
+ targetNodeType,
64
+ targetAttrs
65
+ });
60
66
  }
61
67
 
62
68
  // Transform container to list type
@@ -81,9 +87,74 @@ export const transformContainerNode = ({
81
87
  /**
82
88
  * Unwrap container node and convert content to block type
83
89
  */
84
- export const unwrapAndConvertToBlockType = () => {
85
- // Convert to block type directly
86
- return null;
90
+ export const unwrapAndConvertToBlockType = context => {
91
+ const {
92
+ tr,
93
+ targetNodeType,
94
+ targetAttrs,
95
+ sourceNode,
96
+ sourcePos
97
+ } = context;
98
+ const {
99
+ selection
100
+ } = tr;
101
+ const schema = selection.$from.doc.type.schema;
102
+ const {
103
+ paragraph,
104
+ heading,
105
+ codeBlock,
106
+ expand
107
+ } = schema.nodes;
108
+ const rangeStart = sourcePos !== null ? sourcePos : selection.from;
109
+ let sourceChildren = [...sourceNode.children];
110
+ let transformedContent = [];
111
+
112
+ // If the container is expand, we need to extract the title and convert it to a paragraph
113
+ // and add it to the beginning of the content
114
+ if (sourceNode.type === expand) {
115
+ var _sourceNode$attrs;
116
+ const title = (_sourceNode$attrs = sourceNode.attrs) === null || _sourceNode$attrs === void 0 ? void 0 : _sourceNode$attrs.title;
117
+ if (title) {
118
+ const titleContent = schema.text(title);
119
+ sourceChildren.unshift(paragraph.createChecked({}, titleContent));
120
+ }
121
+ }
122
+
123
+ // if the container is a code block, convert text content to multiple paragraphs
124
+ if (sourceNode.type === codeBlock) {
125
+ const codeText = sourceNode.textContent;
126
+ const lines = codeText.split('\n');
127
+ const paragraphNodes = lines.map(line => paragraph.create(null, line ? schema.text(line) : null));
128
+ sourceChildren = paragraphNodes;
129
+ }
130
+
131
+ // if target node is a paragraph, just do unwrap
132
+ if (targetNodeType === paragraph) {
133
+ transformedContent = sourceChildren;
134
+ }
135
+
136
+ // if target node is a headings, do unwrap and convert to heading
137
+ if (targetNodeType === heading && targetAttrs) {
138
+ const targetHeadingLevel = targetAttrs.level;
139
+ sourceChildren.forEach((node, index) => {
140
+ if (node.isTextblock) {
141
+ const headingNode = heading.create({
142
+ level: targetHeadingLevel
143
+ }, node.content);
144
+ sourceChildren[index] = headingNode;
145
+ }
146
+ });
147
+ transformedContent = sourceChildren;
148
+ }
149
+
150
+ // if target node is code block, do unwrap and convert to code block
151
+ if (targetNodeType === codeBlock) {
152
+ const codeBlockContent = sourceChildren.map(node => node.content.textBetween(0, node.content.size, '\n')).join('\n');
153
+ transformedContent = [codeBlock.createChecked({}, schema.text(codeBlockContent))];
154
+ }
155
+ const slice = new Slice(Fragment.fromArray(transformedContent), 0, 0);
156
+ tr.replaceRange(rangeStart, rangeStart + sourceNode.nodeSize, slice);
157
+ return tr;
87
158
  };
88
159
 
89
160
  /**
@@ -96,9 +167,6 @@ export const unwrapAndConvertToList = ({
96
167
  targetNodeType,
97
168
  targetAttrs
98
169
  }) => {
99
- if (sourcePos === null) {
100
- return tr;
101
- }
102
170
  const {
103
171
  schema
104
172
  } = tr.doc.type;
@@ -106,11 +174,12 @@ export const unwrapAndConvertToList = ({
106
174
  listItem,
107
175
  paragraph,
108
176
  taskList,
109
- taskItem
177
+ taskItem,
178
+ heading
110
179
  } = schema.nodes;
111
180
  const isTargetTaskList = targetNodeType === taskList;
112
- const createListItemFromInline = inlineFrag => {
113
- return isTargetTaskList ? taskItem.create(null, inlineFrag) : listItem.create(null, paragraph.create(null, inlineFrag));
181
+ const createListItemFromInline = content => {
182
+ return isTargetTaskList ? taskItem.create(null, content) : listItem.create(null, paragraph.create(null, content));
114
183
  };
115
184
  const getInlineContent = textblock => {
116
185
  const inlineContent = [];
@@ -119,30 +188,54 @@ export const unwrapAndConvertToList = ({
119
188
  });
120
189
  return inlineContent;
121
190
  };
122
- const items = [];
123
-
191
+ const resultContent = [];
192
+ let currentListItems = [];
193
+ const targetListItemType = isTargetTaskList ? taskItem : listItem;
124
194
  // Expand's title should become the first item of the list
125
195
  if (sourceNode.type.name === 'expand') {
126
- var _sourceNode$attrs;
127
- const title = (_sourceNode$attrs = sourceNode.attrs) === null || _sourceNode$attrs === void 0 ? void 0 : _sourceNode$attrs.title;
196
+ var _sourceNode$attrs2;
197
+ const title = (_sourceNode$attrs2 = sourceNode.attrs) === null || _sourceNode$attrs2 === void 0 ? void 0 : _sourceNode$attrs2.title;
128
198
  if (title) {
129
199
  const titleContent = schema.text(title);
130
- items.push(isTargetTaskList ? taskItem.create(null, titleContent) : listItem.create(null, paragraph.create(null, titleContent)));
200
+ currentListItems.push(createListItemFromInline(titleContent));
131
201
  }
132
202
  }
133
- for (let i = 0; i < sourceNode.childCount; i++) {
134
- const node = sourceNode.child(i);
135
-
136
- // Abort early if unsupported content (e.g. table) encounted inside of the container
137
- if (!node.isTextblock) {
138
- return tr;
203
+ const createListAndAddToContent = () => {
204
+ if (currentListItems.length) {
205
+ const currentList = targetNodeType.create(targetAttrs || null, Fragment.from(currentListItems));
206
+ currentListItems = [];
207
+ resultContent.push(currentList);
139
208
  }
140
- const inline = Fragment.from(getInlineContent(node));
141
- items.push(createListItemFromInline(inline));
209
+ };
210
+ if (sourceNode.type.name === 'codeBlock') {
211
+ const codeText = sourceNode.textContent;
212
+ if (codeText) {
213
+ const lines = codeText.split('\n');
214
+ // Remove empty lines
215
+ const nonEmptyLines = lines.filter(line => line.trim().length > 0);
216
+ nonEmptyLines.forEach(line => {
217
+ const lineText = schema.text(line);
218
+ currentListItems.push(createListItemFromInline(lineText));
219
+ });
220
+ }
221
+ } else {
222
+ sourceNode.forEach(child => {
223
+ if (targetListItemType.validContent(Fragment.from(child))) {
224
+ currentListItems.push(targetListItemType.create(null, child));
225
+ } else if (heading === child.type || isTargetTaskList && paragraph === child.type) {
226
+ const inline = Fragment.from(getInlineContent(child));
227
+ currentListItems.push(createListItemFromInline(inline));
228
+ } else {
229
+ // Create list and add list first
230
+ createListAndAddToContent();
231
+ // Then add content that can't be converted into listItem
232
+ resultContent.push(child);
233
+ }
234
+ });
142
235
  }
143
- if (!items.length) {
144
- return tr;
236
+ if (!resultContent.length && !currentListItems.length) {
237
+ return null;
145
238
  }
146
- const list = targetNodeType.create(targetAttrs || null, Fragment.from(items));
147
- return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, list);
239
+ createListAndAddToContent();
240
+ return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, Fragment.from(resultContent));
148
241
  };
@@ -1,8 +1,8 @@
1
1
  import { transformBlockNode } from './block-transforms';
2
- import { transformContainerNode } from './container-transforms';
2
+ import { transformContainerNode, unwrapAndConvertToList } from './container-transforms';
3
3
  import { convertToLayout } from './layout-transforms';
4
4
  import { transformListNode } from './list-transforms';
5
- import { getTargetNodeInfo, isBlockNode, isListNode, isContainerNode, isLayoutNodeType } from './utils';
5
+ import { getTargetNodeInfo, isBlockNode, isListNode, isListNodeType, isContainerNode, isLayoutNodeType } from './utils';
6
6
  export function transformNodeToTargetType(tr, sourceNode, sourcePos, targetType) {
7
7
  const {
8
8
  nodes
@@ -45,6 +45,11 @@ export function transformNodeToTargetType(tr, sourceNode, sourcePos, targetType)
45
45
  if (isLayoutNodeType(targetNodeType)) {
46
46
  return convertToLayout(transformationContext);
47
47
  }
48
+
49
+ // special case codeblock to listType
50
+ if (sourceNode.type.name === 'codeBlock' && isListNodeType(targetNodeType)) {
51
+ return unwrapAndConvertToList(transformationContext);
52
+ }
48
53
  if (isBlockNode(sourceNode)) {
49
54
  return transformBlockNode(transformationContext);
50
55
  }
@@ -1,4 +1,4 @@
1
- import { transformToContainer } from './container-transforms';
1
+ import { transformToContainer, unwrapAndConvertToBlockType } from './container-transforms';
2
2
  import { getInlineNodeTextContent } from './inline-node-transforms';
3
3
  import { transformBlockToList } from './list-transforms';
4
4
  import { isListNodeType, isContainerNodeType, isBlockNodeType } from './utils';
@@ -28,7 +28,8 @@ export var transformBlockNode = function transformBlockNode(context) {
28
28
  var transformToBlockNode = function transformToBlockNode(context) {
29
29
  var tr = context.tr,
30
30
  targetNodeType = context.targetNodeType,
31
- targetAttrs = context.targetAttrs;
31
+ targetAttrs = context.targetAttrs,
32
+ sourceNode = context.sourceNode;
32
33
  var selection = tr.selection,
33
34
  doc = tr.doc;
34
35
  var $from = selection.$from,
@@ -39,6 +40,11 @@ var transformToBlockNode = function transformToBlockNode(context) {
39
40
  var node = schema.nodes.codeBlock.createChecked(undefined, textContent);
40
41
  return tr.replaceRangeWith(selection.from, selection.to, node);
41
42
  }
43
+
44
+ // code block acts like a container, we need to unwrap it
45
+ if (sourceNode.type === schema.nodes.codeBlock) {
46
+ return unwrapAndConvertToBlockType(context);
47
+ }
42
48
  tr.setBlockType($from.pos, $to.pos, targetNodeType, targetAttrs);
43
49
  return tr;
44
50
  };
@@ -1,4 +1,5 @@
1
- import { Fragment } from '@atlaskit/editor-prosemirror/model';
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
2
3
  import { isBlockNodeType, isListNodeType, isContainerNodeType } from './utils';
3
4
  var convertInvalidNodeToValidNodeType = function convertInvalidNodeToValidNodeType(sourceContent, sourceNodeType, validNodeType, withMarks) {
4
5
  var validTransformedContent = [];
@@ -54,7 +55,13 @@ export var transformContainerNode = function transformContainerNode(_ref2) {
54
55
 
55
56
  // Transform container to block type - unwrap and convert content
56
57
  if (isBlockNodeType(targetNodeType)) {
57
- return unwrapAndConvertToBlockType();
58
+ return unwrapAndConvertToBlockType({
59
+ tr: tr,
60
+ sourceNode: sourceNode,
61
+ sourcePos: sourcePos,
62
+ targetNodeType: targetNodeType,
63
+ targetAttrs: targetAttrs
64
+ });
58
65
  }
59
66
 
60
67
  // Transform container to list type
@@ -79,9 +86,73 @@ export var transformContainerNode = function transformContainerNode(_ref2) {
79
86
  /**
80
87
  * Unwrap container node and convert content to block type
81
88
  */
82
- export var unwrapAndConvertToBlockType = function unwrapAndConvertToBlockType() {
83
- // Convert to block type directly
84
- return null;
89
+ export var unwrapAndConvertToBlockType = function unwrapAndConvertToBlockType(context) {
90
+ var tr = context.tr,
91
+ targetNodeType = context.targetNodeType,
92
+ targetAttrs = context.targetAttrs,
93
+ sourceNode = context.sourceNode,
94
+ sourcePos = context.sourcePos;
95
+ var selection = tr.selection;
96
+ var schema = selection.$from.doc.type.schema;
97
+ var _schema$nodes = schema.nodes,
98
+ paragraph = _schema$nodes.paragraph,
99
+ heading = _schema$nodes.heading,
100
+ codeBlock = _schema$nodes.codeBlock,
101
+ expand = _schema$nodes.expand;
102
+ var rangeStart = sourcePos !== null ? sourcePos : selection.from;
103
+ var sourceChildren = _toConsumableArray(sourceNode.children);
104
+ var transformedContent = [];
105
+
106
+ // If the container is expand, we need to extract the title and convert it to a paragraph
107
+ // and add it to the beginning of the content
108
+ if (sourceNode.type === expand) {
109
+ var _sourceNode$attrs;
110
+ var title = (_sourceNode$attrs = sourceNode.attrs) === null || _sourceNode$attrs === void 0 ? void 0 : _sourceNode$attrs.title;
111
+ if (title) {
112
+ var titleContent = schema.text(title);
113
+ sourceChildren.unshift(paragraph.createChecked({}, titleContent));
114
+ }
115
+ }
116
+
117
+ // if the container is a code block, convert text content to multiple paragraphs
118
+ if (sourceNode.type === codeBlock) {
119
+ var codeText = sourceNode.textContent;
120
+ var lines = codeText.split('\n');
121
+ var paragraphNodes = lines.map(function (line) {
122
+ return paragraph.create(null, line ? schema.text(line) : null);
123
+ });
124
+ sourceChildren = paragraphNodes;
125
+ }
126
+
127
+ // if target node is a paragraph, just do unwrap
128
+ if (targetNodeType === paragraph) {
129
+ transformedContent = sourceChildren;
130
+ }
131
+
132
+ // if target node is a headings, do unwrap and convert to heading
133
+ if (targetNodeType === heading && targetAttrs) {
134
+ var targetHeadingLevel = targetAttrs.level;
135
+ sourceChildren.forEach(function (node, index) {
136
+ if (node.isTextblock) {
137
+ var headingNode = heading.create({
138
+ level: targetHeadingLevel
139
+ }, node.content);
140
+ sourceChildren[index] = headingNode;
141
+ }
142
+ });
143
+ transformedContent = sourceChildren;
144
+ }
145
+
146
+ // if target node is code block, do unwrap and convert to code block
147
+ if (targetNodeType === codeBlock) {
148
+ var codeBlockContent = sourceChildren.map(function (node) {
149
+ return node.content.textBetween(0, node.content.size, '\n');
150
+ }).join('\n');
151
+ transformedContent = [codeBlock.createChecked({}, schema.text(codeBlockContent))];
152
+ }
153
+ var slice = new Slice(Fragment.fromArray(transformedContent), 0, 0);
154
+ tr.replaceRange(rangeStart, rangeStart + sourceNode.nodeSize, slice);
155
+ return tr;
85
156
  };
86
157
 
87
158
  /**
@@ -93,18 +164,16 @@ export var unwrapAndConvertToList = function unwrapAndConvertToList(_ref3) {
93
164
  sourcePos = _ref3.sourcePos,
94
165
  targetNodeType = _ref3.targetNodeType,
95
166
  targetAttrs = _ref3.targetAttrs;
96
- if (sourcePos === null) {
97
- return tr;
98
- }
99
167
  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;
168
+ var _schema$nodes2 = schema.nodes,
169
+ listItem = _schema$nodes2.listItem,
170
+ paragraph = _schema$nodes2.paragraph,
171
+ taskList = _schema$nodes2.taskList,
172
+ taskItem = _schema$nodes2.taskItem,
173
+ heading = _schema$nodes2.heading;
105
174
  var isTargetTaskList = targetNodeType === taskList;
106
- var createListItemFromInline = function createListItemFromInline(inlineFrag) {
107
- return isTargetTaskList ? taskItem.create(null, inlineFrag) : listItem.create(null, paragraph.create(null, inlineFrag));
175
+ var createListItemFromInline = function createListItemFromInline(content) {
176
+ return isTargetTaskList ? taskItem.create(null, content) : listItem.create(null, paragraph.create(null, content));
108
177
  };
109
178
  var getInlineContent = function getInlineContent(textblock) {
110
179
  var inlineContent = [];
@@ -113,30 +182,56 @@ export var unwrapAndConvertToList = function unwrapAndConvertToList(_ref3) {
113
182
  });
114
183
  return inlineContent;
115
184
  };
116
- var items = [];
117
-
185
+ var resultContent = [];
186
+ var currentListItems = [];
187
+ var targetListItemType = isTargetTaskList ? taskItem : listItem;
118
188
  // Expand's title should become the first item of the list
119
189
  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;
190
+ var _sourceNode$attrs2;
191
+ var title = (_sourceNode$attrs2 = sourceNode.attrs) === null || _sourceNode$attrs2 === void 0 ? void 0 : _sourceNode$attrs2.title;
122
192
  if (title) {
123
193
  var titleContent = schema.text(title);
124
- items.push(isTargetTaskList ? taskItem.create(null, titleContent) : listItem.create(null, paragraph.create(null, titleContent)));
194
+ currentListItems.push(createListItemFromInline(titleContent));
125
195
  }
126
196
  }
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;
197
+ var createListAndAddToContent = function createListAndAddToContent() {
198
+ if (currentListItems.length) {
199
+ var currentList = targetNodeType.create(targetAttrs || null, Fragment.from(currentListItems));
200
+ currentListItems = [];
201
+ resultContent.push(currentList);
133
202
  }
134
- var inline = Fragment.from(getInlineContent(node));
135
- items.push(createListItemFromInline(inline));
203
+ };
204
+ if (sourceNode.type.name === 'codeBlock') {
205
+ var codeText = sourceNode.textContent;
206
+ if (codeText) {
207
+ var lines = codeText.split('\n');
208
+ // Remove empty lines
209
+ var nonEmptyLines = lines.filter(function (line) {
210
+ return line.trim().length > 0;
211
+ });
212
+ nonEmptyLines.forEach(function (line) {
213
+ var lineText = schema.text(line);
214
+ currentListItems.push(createListItemFromInline(lineText));
215
+ });
216
+ }
217
+ } else {
218
+ sourceNode.forEach(function (child) {
219
+ if (targetListItemType.validContent(Fragment.from(child))) {
220
+ currentListItems.push(targetListItemType.create(null, child));
221
+ } else if (heading === child.type || isTargetTaskList && paragraph === child.type) {
222
+ var inline = Fragment.from(getInlineContent(child));
223
+ currentListItems.push(createListItemFromInline(inline));
224
+ } else {
225
+ // Create list and add list first
226
+ createListAndAddToContent();
227
+ // Then add content that can't be converted into listItem
228
+ resultContent.push(child);
229
+ }
230
+ });
136
231
  }
137
- if (!items.length) {
138
- return tr;
232
+ if (!resultContent.length && !currentListItems.length) {
233
+ return null;
139
234
  }
140
- var list = targetNodeType.create(targetAttrs || null, Fragment.from(items));
141
- return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, list);
235
+ createListAndAddToContent();
236
+ return tr.replaceWith(sourcePos, sourcePos + sourceNode.nodeSize, Fragment.from(resultContent));
142
237
  };
@@ -1,8 +1,8 @@
1
1
  import { transformBlockNode } from './block-transforms';
2
- import { transformContainerNode } from './container-transforms';
2
+ import { transformContainerNode, unwrapAndConvertToList } from './container-transforms';
3
3
  import { convertToLayout } from './layout-transforms';
4
4
  import { transformListNode } from './list-transforms';
5
- import { getTargetNodeInfo, isBlockNode, isListNode, isContainerNode, isLayoutNodeType } from './utils';
5
+ import { getTargetNodeInfo, isBlockNode, isListNode, isListNodeType, isContainerNode, isLayoutNodeType } from './utils';
6
6
  export function transformNodeToTargetType(tr, sourceNode, sourcePos, targetType) {
7
7
  var nodes = tr.doc.type.schema.nodes;
8
8
  var targetNodeInfo = getTargetNodeInfo(targetType, nodes);
@@ -41,6 +41,11 @@ export function transformNodeToTargetType(tr, sourceNode, sourcePos, targetType)
41
41
  if (isLayoutNodeType(targetNodeType)) {
42
42
  return convertToLayout(transformationContext);
43
43
  }
44
+
45
+ // special case codeblock to listType
46
+ if (sourceNode.type.name === 'codeBlock' && isListNodeType(targetNodeType)) {
47
+ return unwrapAndConvertToList(transformationContext);
48
+ }
44
49
  if (isBlockNode(sourceNode)) {
45
50
  return transformBlockNode(transformationContext);
46
51
  }
@@ -10,8 +10,8 @@ export declare const transformContainerNode: TransformFunction;
10
10
  /**
11
11
  * Unwrap container node and convert content to block type
12
12
  */
13
- export declare const unwrapAndConvertToBlockType: () => null;
13
+ export declare const unwrapAndConvertToBlockType: (context: TransformContext) => import("prosemirror-state").Transaction;
14
14
  /**
15
15
  * Unwrap container node and convert content to list
16
16
  */
17
- export declare const unwrapAndConvertToList: ({ tr, sourceNode, sourcePos, targetNodeType, targetAttrs, }: TransformContext) => import("prosemirror-state").Transaction;
17
+ export declare const unwrapAndConvertToList: ({ tr, sourceNode, sourcePos, targetNodeType, targetAttrs, }: TransformContext) => import("prosemirror-state").Transaction | null;
@@ -10,8 +10,8 @@ export declare const transformContainerNode: TransformFunction;
10
10
  /**
11
11
  * Unwrap container node and convert content to block type
12
12
  */
13
- export declare const unwrapAndConvertToBlockType: () => null;
13
+ export declare const unwrapAndConvertToBlockType: (context: TransformContext) => import("prosemirror-state").Transaction;
14
14
  /**
15
15
  * Unwrap container node and convert content to list
16
16
  */
17
- export declare const unwrapAndConvertToList: ({ tr, sourceNode, sourcePos, targetNodeType, targetAttrs, }: TransformContext) => import("prosemirror-state").Transaction;
17
+ export declare const unwrapAndConvertToList: ({ tr, sourceNode, sourcePos, targetNodeType, targetAttrs, }: TransformContext) => import("prosemirror-state").Transaction | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-block-menu",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "BlockMenu plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -46,7 +46,7 @@
46
46
  "@babel/runtime": "^7.0.0"
47
47
  },
48
48
  "peerDependencies": {
49
- "@atlaskit/editor-common": "^108.3.0",
49
+ "@atlaskit/editor-common": "^108.5.0",
50
50
  "react": "^18.2.0",
51
51
  "react-intl-next": "npm:react-intl@^5.18.1"
52
52
  },