@atlaskit/editor-plugin-block-type 12.1.5 → 12.1.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 +17 -0
- package/dist/cjs/blockTypePlugin.js +1 -2
- package/dist/cjs/pm-plugins/commands/block-type.js +14 -3
- package/dist/cjs/pm-plugins/utils.js +62 -9
- package/dist/es2019/blockTypePlugin.js +1 -2
- package/dist/es2019/pm-plugins/commands/block-type.js +15 -4
- package/dist/es2019/pm-plugins/utils.js +63 -8
- package/dist/esm/blockTypePlugin.js +1 -2
- package/dist/esm/pm-plugins/commands/block-type.js +15 -4
- package/dist/esm/pm-plugins/utils.js +59 -8
- package/dist/types/pm-plugins/types.d.ts +2 -1
- package/dist/types/pm-plugins/utils.d.ts +17 -0
- package/dist/types-ts4.5/pm-plugins/types.d.ts +2 -1
- package/dist/types-ts4.5/pm-plugins/utils.d.ts +17 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-block-type
|
|
2
2
|
|
|
3
|
+
## 12.1.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`9ed32aea2c1d3`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9ed32aea2c1d3) -
|
|
8
|
+
Replace feature experiment util with cross platform alternative for platform_editor_block_menu
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
|
|
11
|
+
## 12.1.6
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [`16f53ab4d1fee`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/16f53ab4d1fee) -
|
|
16
|
+
Fix small text conversion for nested/indented task lists and prevent fontSize mark from leaking to
|
|
17
|
+
sibling lists
|
|
18
|
+
- Updated dependencies
|
|
19
|
+
|
|
3
20
|
## 12.1.5
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -16,7 +16,6 @@ var _quickInsert = require("@atlaskit/editor-common/quick-insert");
|
|
|
16
16
|
var _types = require("@atlaskit/editor-common/types");
|
|
17
17
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
18
18
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
19
|
-
var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
|
|
20
19
|
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
21
20
|
var _blockType = require("./pm-plugins/commands/block-type");
|
|
22
21
|
var _inputRule = _interopRequireDefault(require("./pm-plugins/input-rule"));
|
|
@@ -139,7 +138,7 @@ var blockTypePlugin = exports.blockTypePlugin = function blockTypePlugin(_ref3)
|
|
|
139
138
|
component: primaryToolbarComponent
|
|
140
139
|
});
|
|
141
140
|
}
|
|
142
|
-
if ((0,
|
|
141
|
+
if ((0, _experiments.editorExperiment)('platform_editor_block_menu', true)) {
|
|
143
142
|
var _api$blockMenu;
|
|
144
143
|
api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 || _api$blockMenu.actions.registerBlockMenuComponents((0, _ui.getBlockTypeComponents)(api));
|
|
145
144
|
}
|
|
@@ -145,22 +145,33 @@ function setSmallText() {
|
|
|
145
145
|
}
|
|
146
146
|
var selection = tr.selection;
|
|
147
147
|
if (selection instanceof _editorTables.CellSelection) {
|
|
148
|
+
var mapFrom = tr.steps.length;
|
|
148
149
|
selection.forEachCell(function (cell, pos) {
|
|
149
|
-
|
|
150
|
+
var mappedPos = tr.mapping.slice(mapFrom).map(pos);
|
|
151
|
+
tr.setBlockType(mappedPos, mappedPos + cell.nodeSize, paragraph);
|
|
152
|
+
(0, _utils2.convertTaskItemsToBlockTaskItems)(tr, mappedPos, mappedPos + cell.nodeSize);
|
|
150
153
|
(0, _commands.createToggleBlockMarkOnRangeNext)(fontSize, function () {
|
|
151
154
|
return {
|
|
152
155
|
fontSize: 'small'
|
|
153
156
|
};
|
|
154
|
-
}, [paragraph])(
|
|
157
|
+
}, [paragraph])(mappedPos, mappedPos + cell.nodeSize, tr);
|
|
155
158
|
});
|
|
156
159
|
} else {
|
|
160
|
+
// Step 1. Convert headings to paragraphs (for non-task content)
|
|
157
161
|
tr.setBlockType(selection.from, selection.to, paragraph);
|
|
162
|
+
|
|
163
|
+
// Step 2. Expand the selection range to include full list nodes
|
|
158
164
|
var expandedRange = (0, _utils2.getSelectionRangeExpandedToLists)(tr);
|
|
165
|
+
|
|
166
|
+
// Step 3. Convert taskItems → blockTaskItems so their content can hold the fontSize mark
|
|
167
|
+
(0, _utils2.convertTaskItemsToBlockTaskItems)(tr, expandedRange.from, expandedRange.to);
|
|
168
|
+
|
|
169
|
+
// Step 4. Apply fontSize mark to all paragraphs in range (including those inside new blockTaskItems)
|
|
159
170
|
(0, _commands.createToggleBlockMarkOnRangeNext)(fontSize, function () {
|
|
160
171
|
return {
|
|
161
172
|
fontSize: 'small'
|
|
162
173
|
};
|
|
163
|
-
}, [paragraph])(expandedRange.from, expandedRange.to, tr);
|
|
174
|
+
}, [paragraph])(tr.mapping.map(expandedRange.from, -1), tr.mapping.map(expandedRange.to, 1), tr);
|
|
164
175
|
}
|
|
165
176
|
return tr;
|
|
166
177
|
};
|
|
@@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.areBlockTypesDisabled = areBlockTypesDisabled;
|
|
7
|
-
exports.
|
|
7
|
+
exports.checkFormattingIsPresent = void 0;
|
|
8
|
+
exports.convertTaskItemsToBlockTaskItems = convertTaskItemsToBlockTaskItems;
|
|
9
|
+
exports.createWrappingTextBlockRule = exports.createJoinNodesRule = void 0;
|
|
8
10
|
exports.getSelectionRangeExpandedToLists = getSelectionRangeExpandedToLists;
|
|
9
11
|
exports.isNodeAWrappingBlockNode = exports.hasBlockQuoteInOptions = void 0;
|
|
10
12
|
exports.isSelectionInsideListNode = isSelectionInsideListNode;
|
|
@@ -91,12 +93,10 @@ function areBlockTypesDisabled(state) {
|
|
|
91
93
|
blockquote = _state$schema$nodes2.blockquote,
|
|
92
94
|
bulletList = _state$schema$nodes2.bulletList,
|
|
93
95
|
orderedList = _state$schema$nodes2.orderedList,
|
|
94
|
-
listItem = _state$schema$nodes2.listItem
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
// Note: taskList/taskItem are not excluded here until blockTaskItem conversion is implemented (WI 4).
|
|
99
|
-
var excludedTypes = allowFontSize && (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem] : [panel];
|
|
96
|
+
listItem = _state$schema$nodes2.listItem,
|
|
97
|
+
taskList = _state$schema$nodes2.taskList,
|
|
98
|
+
taskItem = _state$schema$nodes2.taskItem;
|
|
99
|
+
var excludedTypes = allowFontSize && (0, _expValEquals.expValEquals)('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem, taskList, taskItem] : [panel];
|
|
100
100
|
if ((0, _experiments.editorExperiment)('platform_editor_blockquote_in_text_formatting_menu', true)) {
|
|
101
101
|
var hasQuote = false;
|
|
102
102
|
var hasNestedListInQuote = false;
|
|
@@ -206,22 +206,75 @@ function getSelectionRangeExpandedToLists(tr) {
|
|
|
206
206
|
var listNodeTypes = [bulletList, orderedList, taskList];
|
|
207
207
|
var from = selection.from;
|
|
208
208
|
var to = selection.to;
|
|
209
|
+
|
|
210
|
+
// Walk up from the selection start to find the outermost list node.
|
|
211
|
+
// We do NOT break at the first list found because task lists nest differently
|
|
212
|
+
// from bullet/ordered lists:
|
|
213
|
+
// - bullet/ordered: bulletList > listItem > bulletList (nested inside listItem)
|
|
214
|
+
// - task: taskList > taskList (nested as direct children)
|
|
215
|
+
// For task lists, breaking at the first list would only capture the innermost
|
|
216
|
+
// taskList, missing sibling task items in parent lists. By continuing to walk
|
|
217
|
+
// up, we find the outermost list and include all nested content.
|
|
209
218
|
for (var depth = selection.$from.depth; depth > 0; depth--) {
|
|
210
219
|
var node = selection.$from.node(depth);
|
|
211
220
|
if (listNodeTypes.indexOf(node.type) >= 0) {
|
|
212
221
|
from = selection.$from.before(depth);
|
|
213
|
-
break;
|
|
214
222
|
}
|
|
215
223
|
}
|
|
216
224
|
for (var _depth = selection.$to.depth; _depth > 0; _depth--) {
|
|
217
225
|
var _node = selection.$to.node(_depth);
|
|
218
226
|
if (listNodeTypes.indexOf(_node.type) >= 0) {
|
|
219
227
|
to = selection.$to.after(_depth);
|
|
220
|
-
break;
|
|
221
228
|
}
|
|
222
229
|
}
|
|
223
230
|
return {
|
|
224
231
|
from: from,
|
|
225
232
|
to: to
|
|
226
233
|
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Converts all taskItem nodes within the given range to blockTaskItem nodes.
|
|
238
|
+
*
|
|
239
|
+
* taskItem nodes contain inline content directly, which cannot hold block-level
|
|
240
|
+
* marks like fontSize. blockTaskItem nodes wrap content in paragraphs, which can
|
|
241
|
+
* hold block marks. This conversion is needed when applying small text formatting
|
|
242
|
+
* to task lists.
|
|
243
|
+
*
|
|
244
|
+
* The inline content of each taskItem is wrapped in a paragraph node, and the
|
|
245
|
+
* taskItem is replaced with a blockTaskItem that preserves the original attributes
|
|
246
|
+
* (localId, state).
|
|
247
|
+
*
|
|
248
|
+
* Collects taskItem positions in a forward pass over the unmutated document,
|
|
249
|
+
* then applies replacements in reverse document order so positions remain valid
|
|
250
|
+
* without needing remapping or doc snapshots.
|
|
251
|
+
*/
|
|
252
|
+
function convertTaskItemsToBlockTaskItems(tr, from, to) {
|
|
253
|
+
var _tr$doc$type$schema$n2 = tr.doc.type.schema.nodes,
|
|
254
|
+
taskItem = _tr$doc$type$schema$n2.taskItem,
|
|
255
|
+
blockTaskItem = _tr$doc$type$schema$n2.blockTaskItem,
|
|
256
|
+
paragraph = _tr$doc$type$schema$n2.paragraph;
|
|
257
|
+
if (!blockTaskItem || !taskItem) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Collect taskItem positions from the current (unmutated) document
|
|
262
|
+
var taskItemsToConvert = [];
|
|
263
|
+
tr.doc.nodesBetween(from, to, function (node, pos) {
|
|
264
|
+
if (node.type === taskItem) {
|
|
265
|
+
taskItemsToConvert.push({
|
|
266
|
+
pos: pos,
|
|
267
|
+
node: node
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
// Replace in reverse document order so earlier positions remain valid
|
|
273
|
+
for (var i = taskItemsToConvert.length - 1; i >= 0; i--) {
|
|
274
|
+
var _taskItemsToConvert$i = taskItemsToConvert[i],
|
|
275
|
+
pos = _taskItemsToConvert$i.pos,
|
|
276
|
+
node = _taskItemsToConvert$i.node;
|
|
277
|
+
var blockTaskNode = blockTaskItem.create(node.attrs, paragraph.create(null, node.content));
|
|
278
|
+
tr.replaceWith(pos, pos + node.nodeSize, blockTaskNode);
|
|
279
|
+
}
|
|
227
280
|
}
|
|
@@ -7,7 +7,6 @@ import { IconHeading, IconQuote } from '@atlaskit/editor-common/quick-insert';
|
|
|
7
7
|
import { ToolbarSize } from '@atlaskit/editor-common/types';
|
|
8
8
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
9
9
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
10
|
-
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
11
10
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
12
11
|
import { clearFormatting, insertBlockQuoteWithAnalytics, insertBlockQuoteWithAnalyticsCommand, setBlockTypeWithAnalytics } from './pm-plugins/commands/block-type';
|
|
13
12
|
import inputRulePlugin from './pm-plugins/input-rule';
|
|
@@ -128,7 +127,7 @@ const blockTypePlugin = ({
|
|
|
128
127
|
component: primaryToolbarComponent
|
|
129
128
|
});
|
|
130
129
|
}
|
|
131
|
-
if (
|
|
130
|
+
if (editorExperiment('platform_editor_block_menu', true)) {
|
|
132
131
|
var _api$blockMenu;
|
|
133
132
|
api === null || api === void 0 ? void 0 : (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 ? void 0 : _api$blockMenu.actions.registerBlockMenuComponents(getBlockTypeComponents(api));
|
|
134
133
|
}
|
|
@@ -6,7 +6,7 @@ import { liftTarget } from '@atlaskit/editor-prosemirror/transform';
|
|
|
6
6
|
import { CellSelection } from '@atlaskit/editor-tables';
|
|
7
7
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
8
8
|
import { HEADINGS_BY_NAME, NORMAL_TEXT } from '../block-types';
|
|
9
|
-
import { getSelectionRangeExpandedToLists } from '../utils';
|
|
9
|
+
import { convertTaskItemsToBlockTaskItems, getSelectionRangeExpandedToLists } from '../utils';
|
|
10
10
|
import { FORMATTING_NODE_TYPES, FORMATTING_MARK_TYPES, cellSelectionNodesBetween, formatTypes, clearNodeFormattingOnSelection } from './clear-formatting';
|
|
11
11
|
import { wrapSelectionInBlockType } from './wrapSelectionIn';
|
|
12
12
|
export function setBlockType(name) {
|
|
@@ -144,18 +144,29 @@ export function setSmallText() {
|
|
|
144
144
|
selection
|
|
145
145
|
} = tr;
|
|
146
146
|
if (selection instanceof CellSelection) {
|
|
147
|
+
const mapFrom = tr.steps.length;
|
|
147
148
|
selection.forEachCell((cell, pos) => {
|
|
148
|
-
|
|
149
|
+
const mappedPos = tr.mapping.slice(mapFrom).map(pos);
|
|
150
|
+
tr.setBlockType(mappedPos, mappedPos + cell.nodeSize, paragraph);
|
|
151
|
+
convertTaskItemsToBlockTaskItems(tr, mappedPos, mappedPos + cell.nodeSize);
|
|
149
152
|
createToggleBlockMarkOnRangeNext(fontSize, () => ({
|
|
150
153
|
fontSize: 'small'
|
|
151
|
-
}), [paragraph])(
|
|
154
|
+
}), [paragraph])(mappedPos, mappedPos + cell.nodeSize, tr);
|
|
152
155
|
});
|
|
153
156
|
} else {
|
|
157
|
+
// Step 1. Convert headings to paragraphs (for non-task content)
|
|
154
158
|
tr.setBlockType(selection.from, selection.to, paragraph);
|
|
159
|
+
|
|
160
|
+
// Step 2. Expand the selection range to include full list nodes
|
|
155
161
|
const expandedRange = getSelectionRangeExpandedToLists(tr);
|
|
162
|
+
|
|
163
|
+
// Step 3. Convert taskItems → blockTaskItems so their content can hold the fontSize mark
|
|
164
|
+
convertTaskItemsToBlockTaskItems(tr, expandedRange.from, expandedRange.to);
|
|
165
|
+
|
|
166
|
+
// Step 4. Apply fontSize mark to all paragraphs in range (including those inside new blockTaskItems)
|
|
156
167
|
createToggleBlockMarkOnRangeNext(fontSize, () => ({
|
|
157
168
|
fontSize: 'small'
|
|
158
|
-
}), [paragraph])(expandedRange.from, expandedRange.to, tr);
|
|
169
|
+
}), [paragraph])(tr.mapping.map(expandedRange.from, -1), tr.mapping.map(expandedRange.to, 1), tr);
|
|
159
170
|
}
|
|
160
171
|
return tr;
|
|
161
172
|
};
|
|
@@ -79,13 +79,11 @@ export function areBlockTypesDisabled(state, allowFontSize = false) {
|
|
|
79
79
|
blockquote,
|
|
80
80
|
bulletList,
|
|
81
81
|
orderedList,
|
|
82
|
-
listItem
|
|
82
|
+
listItem,
|
|
83
|
+
taskList,
|
|
84
|
+
taskItem
|
|
83
85
|
} = state.schema.nodes;
|
|
84
|
-
|
|
85
|
-
// When the small font size experiment is enabled, allow block type changes inside lists
|
|
86
|
-
// so that users can toggle between Normal text and Small text within list contexts.
|
|
87
|
-
// Note: taskList/taskItem are not excluded here until blockTaskItem conversion is implemented (WI 4).
|
|
88
|
-
const excludedTypes = allowFontSize && expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem] : [panel];
|
|
86
|
+
const excludedTypes = allowFontSize && expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem, taskList, taskItem] : [panel];
|
|
89
87
|
if (editorExperiment('platform_editor_blockquote_in_text_formatting_menu', true)) {
|
|
90
88
|
let hasQuote = false;
|
|
91
89
|
let hasNestedListInQuote = false;
|
|
@@ -199,22 +197,79 @@ export function getSelectionRangeExpandedToLists(tr) {
|
|
|
199
197
|
const listNodeTypes = [bulletList, orderedList, taskList];
|
|
200
198
|
let from = selection.from;
|
|
201
199
|
let to = selection.to;
|
|
200
|
+
|
|
201
|
+
// Walk up from the selection start to find the outermost list node.
|
|
202
|
+
// We do NOT break at the first list found because task lists nest differently
|
|
203
|
+
// from bullet/ordered lists:
|
|
204
|
+
// - bullet/ordered: bulletList > listItem > bulletList (nested inside listItem)
|
|
205
|
+
// - task: taskList > taskList (nested as direct children)
|
|
206
|
+
// For task lists, breaking at the first list would only capture the innermost
|
|
207
|
+
// taskList, missing sibling task items in parent lists. By continuing to walk
|
|
208
|
+
// up, we find the outermost list and include all nested content.
|
|
202
209
|
for (let depth = selection.$from.depth; depth > 0; depth--) {
|
|
203
210
|
const node = selection.$from.node(depth);
|
|
204
211
|
if (listNodeTypes.indexOf(node.type) >= 0) {
|
|
205
212
|
from = selection.$from.before(depth);
|
|
206
|
-
break;
|
|
207
213
|
}
|
|
208
214
|
}
|
|
209
215
|
for (let depth = selection.$to.depth; depth > 0; depth--) {
|
|
210
216
|
const node = selection.$to.node(depth);
|
|
211
217
|
if (listNodeTypes.indexOf(node.type) >= 0) {
|
|
212
218
|
to = selection.$to.after(depth);
|
|
213
|
-
break;
|
|
214
219
|
}
|
|
215
220
|
}
|
|
216
221
|
return {
|
|
217
222
|
from,
|
|
218
223
|
to
|
|
219
224
|
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Converts all taskItem nodes within the given range to blockTaskItem nodes.
|
|
229
|
+
*
|
|
230
|
+
* taskItem nodes contain inline content directly, which cannot hold block-level
|
|
231
|
+
* marks like fontSize. blockTaskItem nodes wrap content in paragraphs, which can
|
|
232
|
+
* hold block marks. This conversion is needed when applying small text formatting
|
|
233
|
+
* to task lists.
|
|
234
|
+
*
|
|
235
|
+
* The inline content of each taskItem is wrapped in a paragraph node, and the
|
|
236
|
+
* taskItem is replaced with a blockTaskItem that preserves the original attributes
|
|
237
|
+
* (localId, state).
|
|
238
|
+
*
|
|
239
|
+
* Collects taskItem positions in a forward pass over the unmutated document,
|
|
240
|
+
* then applies replacements in reverse document order so positions remain valid
|
|
241
|
+
* without needing remapping or doc snapshots.
|
|
242
|
+
*/
|
|
243
|
+
export function convertTaskItemsToBlockTaskItems(tr, from, to) {
|
|
244
|
+
const {
|
|
245
|
+
nodes: {
|
|
246
|
+
taskItem,
|
|
247
|
+
blockTaskItem,
|
|
248
|
+
paragraph
|
|
249
|
+
}
|
|
250
|
+
} = tr.doc.type.schema;
|
|
251
|
+
if (!blockTaskItem || !taskItem) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Collect taskItem positions from the current (unmutated) document
|
|
256
|
+
const taskItemsToConvert = [];
|
|
257
|
+
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
258
|
+
if (node.type === taskItem) {
|
|
259
|
+
taskItemsToConvert.push({
|
|
260
|
+
pos,
|
|
261
|
+
node
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// Replace in reverse document order so earlier positions remain valid
|
|
267
|
+
for (let i = taskItemsToConvert.length - 1; i >= 0; i--) {
|
|
268
|
+
const {
|
|
269
|
+
pos,
|
|
270
|
+
node
|
|
271
|
+
} = taskItemsToConvert[i];
|
|
272
|
+
const blockTaskNode = blockTaskItem.create(node.attrs, paragraph.create(null, node.content));
|
|
273
|
+
tr.replaceWith(pos, pos + node.nodeSize, blockTaskNode);
|
|
274
|
+
}
|
|
220
275
|
}
|
|
@@ -11,7 +11,6 @@ import { IconHeading, IconQuote } from '@atlaskit/editor-common/quick-insert';
|
|
|
11
11
|
import { ToolbarSize } from '@atlaskit/editor-common/types';
|
|
12
12
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
13
13
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
14
|
-
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
15
14
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
16
15
|
import { clearFormatting as _clearFormatting, insertBlockQuoteWithAnalytics, insertBlockQuoteWithAnalyticsCommand, setBlockTypeWithAnalytics } from './pm-plugins/commands/block-type';
|
|
17
16
|
import inputRulePlugin from './pm-plugins/input-rule';
|
|
@@ -132,7 +131,7 @@ var blockTypePlugin = function blockTypePlugin(_ref3) {
|
|
|
132
131
|
component: primaryToolbarComponent
|
|
133
132
|
});
|
|
134
133
|
}
|
|
135
|
-
if (
|
|
134
|
+
if (editorExperiment('platform_editor_block_menu', true)) {
|
|
136
135
|
var _api$blockMenu;
|
|
137
136
|
api === null || api === void 0 || (_api$blockMenu = api.blockMenu) === null || _api$blockMenu === void 0 || _api$blockMenu.actions.registerBlockMenuComponents(getBlockTypeComponents(api));
|
|
138
137
|
}
|
|
@@ -9,7 +9,7 @@ import { liftTarget } from '@atlaskit/editor-prosemirror/transform';
|
|
|
9
9
|
import { CellSelection } from '@atlaskit/editor-tables';
|
|
10
10
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
11
11
|
import { HEADINGS_BY_NAME, NORMAL_TEXT } from '../block-types';
|
|
12
|
-
import { getSelectionRangeExpandedToLists } from '../utils';
|
|
12
|
+
import { convertTaskItemsToBlockTaskItems, getSelectionRangeExpandedToLists } from '../utils';
|
|
13
13
|
import { FORMATTING_NODE_TYPES, FORMATTING_MARK_TYPES, cellSelectionNodesBetween, formatTypes, clearNodeFormattingOnSelection } from './clear-formatting';
|
|
14
14
|
import { wrapSelectionInBlockType } from './wrapSelectionIn';
|
|
15
15
|
export function setBlockType(name) {
|
|
@@ -128,22 +128,33 @@ export function setSmallText() {
|
|
|
128
128
|
}
|
|
129
129
|
var selection = tr.selection;
|
|
130
130
|
if (selection instanceof CellSelection) {
|
|
131
|
+
var mapFrom = tr.steps.length;
|
|
131
132
|
selection.forEachCell(function (cell, pos) {
|
|
132
|
-
|
|
133
|
+
var mappedPos = tr.mapping.slice(mapFrom).map(pos);
|
|
134
|
+
tr.setBlockType(mappedPos, mappedPos + cell.nodeSize, paragraph);
|
|
135
|
+
convertTaskItemsToBlockTaskItems(tr, mappedPos, mappedPos + cell.nodeSize);
|
|
133
136
|
createToggleBlockMarkOnRangeNext(fontSize, function () {
|
|
134
137
|
return {
|
|
135
138
|
fontSize: 'small'
|
|
136
139
|
};
|
|
137
|
-
}, [paragraph])(
|
|
140
|
+
}, [paragraph])(mappedPos, mappedPos + cell.nodeSize, tr);
|
|
138
141
|
});
|
|
139
142
|
} else {
|
|
143
|
+
// Step 1. Convert headings to paragraphs (for non-task content)
|
|
140
144
|
tr.setBlockType(selection.from, selection.to, paragraph);
|
|
145
|
+
|
|
146
|
+
// Step 2. Expand the selection range to include full list nodes
|
|
141
147
|
var expandedRange = getSelectionRangeExpandedToLists(tr);
|
|
148
|
+
|
|
149
|
+
// Step 3. Convert taskItems → blockTaskItems so their content can hold the fontSize mark
|
|
150
|
+
convertTaskItemsToBlockTaskItems(tr, expandedRange.from, expandedRange.to);
|
|
151
|
+
|
|
152
|
+
// Step 4. Apply fontSize mark to all paragraphs in range (including those inside new blockTaskItems)
|
|
142
153
|
createToggleBlockMarkOnRangeNext(fontSize, function () {
|
|
143
154
|
return {
|
|
144
155
|
fontSize: 'small'
|
|
145
156
|
};
|
|
146
|
-
}, [paragraph])(expandedRange.from, expandedRange.to, tr);
|
|
157
|
+
}, [paragraph])(tr.mapping.map(expandedRange.from, -1), tr.mapping.map(expandedRange.to, 1), tr);
|
|
147
158
|
}
|
|
148
159
|
return tr;
|
|
149
160
|
};
|
|
@@ -81,12 +81,10 @@ export function areBlockTypesDisabled(state) {
|
|
|
81
81
|
blockquote = _state$schema$nodes2.blockquote,
|
|
82
82
|
bulletList = _state$schema$nodes2.bulletList,
|
|
83
83
|
orderedList = _state$schema$nodes2.orderedList,
|
|
84
|
-
listItem = _state$schema$nodes2.listItem
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// Note: taskList/taskItem are not excluded here until blockTaskItem conversion is implemented (WI 4).
|
|
89
|
-
var excludedTypes = allowFontSize && expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem] : [panel];
|
|
84
|
+
listItem = _state$schema$nodes2.listItem,
|
|
85
|
+
taskList = _state$schema$nodes2.taskList,
|
|
86
|
+
taskItem = _state$schema$nodes2.taskItem;
|
|
87
|
+
var excludedTypes = allowFontSize && expValEquals('platform_editor_small_font_size', 'isEnabled', true) ? [panel, bulletList, orderedList, listItem, taskList, taskItem] : [panel];
|
|
90
88
|
if (editorExperiment('platform_editor_blockquote_in_text_formatting_menu', true)) {
|
|
91
89
|
var hasQuote = false;
|
|
92
90
|
var hasNestedListInQuote = false;
|
|
@@ -196,22 +194,75 @@ export function getSelectionRangeExpandedToLists(tr) {
|
|
|
196
194
|
var listNodeTypes = [bulletList, orderedList, taskList];
|
|
197
195
|
var from = selection.from;
|
|
198
196
|
var to = selection.to;
|
|
197
|
+
|
|
198
|
+
// Walk up from the selection start to find the outermost list node.
|
|
199
|
+
// We do NOT break at the first list found because task lists nest differently
|
|
200
|
+
// from bullet/ordered lists:
|
|
201
|
+
// - bullet/ordered: bulletList > listItem > bulletList (nested inside listItem)
|
|
202
|
+
// - task: taskList > taskList (nested as direct children)
|
|
203
|
+
// For task lists, breaking at the first list would only capture the innermost
|
|
204
|
+
// taskList, missing sibling task items in parent lists. By continuing to walk
|
|
205
|
+
// up, we find the outermost list and include all nested content.
|
|
199
206
|
for (var depth = selection.$from.depth; depth > 0; depth--) {
|
|
200
207
|
var node = selection.$from.node(depth);
|
|
201
208
|
if (listNodeTypes.indexOf(node.type) >= 0) {
|
|
202
209
|
from = selection.$from.before(depth);
|
|
203
|
-
break;
|
|
204
210
|
}
|
|
205
211
|
}
|
|
206
212
|
for (var _depth = selection.$to.depth; _depth > 0; _depth--) {
|
|
207
213
|
var _node = selection.$to.node(_depth);
|
|
208
214
|
if (listNodeTypes.indexOf(_node.type) >= 0) {
|
|
209
215
|
to = selection.$to.after(_depth);
|
|
210
|
-
break;
|
|
211
216
|
}
|
|
212
217
|
}
|
|
213
218
|
return {
|
|
214
219
|
from: from,
|
|
215
220
|
to: to
|
|
216
221
|
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Converts all taskItem nodes within the given range to blockTaskItem nodes.
|
|
226
|
+
*
|
|
227
|
+
* taskItem nodes contain inline content directly, which cannot hold block-level
|
|
228
|
+
* marks like fontSize. blockTaskItem nodes wrap content in paragraphs, which can
|
|
229
|
+
* hold block marks. This conversion is needed when applying small text formatting
|
|
230
|
+
* to task lists.
|
|
231
|
+
*
|
|
232
|
+
* The inline content of each taskItem is wrapped in a paragraph node, and the
|
|
233
|
+
* taskItem is replaced with a blockTaskItem that preserves the original attributes
|
|
234
|
+
* (localId, state).
|
|
235
|
+
*
|
|
236
|
+
* Collects taskItem positions in a forward pass over the unmutated document,
|
|
237
|
+
* then applies replacements in reverse document order so positions remain valid
|
|
238
|
+
* without needing remapping or doc snapshots.
|
|
239
|
+
*/
|
|
240
|
+
export function convertTaskItemsToBlockTaskItems(tr, from, to) {
|
|
241
|
+
var _tr$doc$type$schema$n2 = tr.doc.type.schema.nodes,
|
|
242
|
+
taskItem = _tr$doc$type$schema$n2.taskItem,
|
|
243
|
+
blockTaskItem = _tr$doc$type$schema$n2.blockTaskItem,
|
|
244
|
+
paragraph = _tr$doc$type$schema$n2.paragraph;
|
|
245
|
+
if (!blockTaskItem || !taskItem) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Collect taskItem positions from the current (unmutated) document
|
|
250
|
+
var taskItemsToConvert = [];
|
|
251
|
+
tr.doc.nodesBetween(from, to, function (node, pos) {
|
|
252
|
+
if (node.type === taskItem) {
|
|
253
|
+
taskItemsToConvert.push({
|
|
254
|
+
pos: pos,
|
|
255
|
+
node: node
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Replace in reverse document order so earlier positions remain valid
|
|
261
|
+
for (var i = taskItemsToConvert.length - 1; i >= 0; i--) {
|
|
262
|
+
var _taskItemsToConvert$i = taskItemsToConvert[i],
|
|
263
|
+
pos = _taskItemsToConvert$i.pos,
|
|
264
|
+
node = _taskItemsToConvert$i.node;
|
|
265
|
+
var blockTaskNode = blockTaskItem.create(node.attrs, paragraph.create(null, node.content));
|
|
266
|
+
tr.replaceWith(pos, pos + node.nodeSize, blockTaskNode);
|
|
267
|
+
}
|
|
217
268
|
}
|
|
@@ -26,10 +26,11 @@ export interface BlockTypePluginOptions {
|
|
|
26
26
|
exclude?: Array<AllowedBlockTypes>;
|
|
27
27
|
};
|
|
28
28
|
/**
|
|
29
|
-
* Add ability to
|
|
29
|
+
* Add ability to toggle paragraph size variations.
|
|
30
30
|
*
|
|
31
31
|
* Note: Feature is in development and logic is under an experiment.
|
|
32
32
|
* Note: `fontSize` mark must be supported in the ADF schema for this feature to work.
|
|
33
|
+
* Note: To support fontSize variatons in tasks, allowBlockTaskItem must be enabled for tasksAndDecisionsPlugin
|
|
33
34
|
*/
|
|
34
35
|
allowFontSize?: boolean;
|
|
35
36
|
includeBlockQuoteAsTextstyleOption?: boolean;
|
|
@@ -32,4 +32,21 @@ export declare function getSelectionRangeExpandedToLists(tr: Transaction): {
|
|
|
32
32
|
from: number;
|
|
33
33
|
to: number;
|
|
34
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Converts all taskItem nodes within the given range to blockTaskItem nodes.
|
|
37
|
+
*
|
|
38
|
+
* taskItem nodes contain inline content directly, which cannot hold block-level
|
|
39
|
+
* marks like fontSize. blockTaskItem nodes wrap content in paragraphs, which can
|
|
40
|
+
* hold block marks. This conversion is needed when applying small text formatting
|
|
41
|
+
* to task lists.
|
|
42
|
+
*
|
|
43
|
+
* The inline content of each taskItem is wrapped in a paragraph node, and the
|
|
44
|
+
* taskItem is replaced with a blockTaskItem that preserves the original attributes
|
|
45
|
+
* (localId, state).
|
|
46
|
+
*
|
|
47
|
+
* Collects taskItem positions in a forward pass over the unmutated document,
|
|
48
|
+
* then applies replacements in reverse document order so positions remain valid
|
|
49
|
+
* without needing remapping or doc snapshots.
|
|
50
|
+
*/
|
|
51
|
+
export declare function convertTaskItemsToBlockTaskItems(tr: Transaction, from: number, to: number): void;
|
|
35
52
|
export {};
|
|
@@ -26,10 +26,11 @@ export interface BlockTypePluginOptions {
|
|
|
26
26
|
exclude?: Array<AllowedBlockTypes>;
|
|
27
27
|
};
|
|
28
28
|
/**
|
|
29
|
-
* Add ability to
|
|
29
|
+
* Add ability to toggle paragraph size variations.
|
|
30
30
|
*
|
|
31
31
|
* Note: Feature is in development and logic is under an experiment.
|
|
32
32
|
* Note: `fontSize` mark must be supported in the ADF schema for this feature to work.
|
|
33
|
+
* Note: To support fontSize variatons in tasks, allowBlockTaskItem must be enabled for tasksAndDecisionsPlugin
|
|
33
34
|
*/
|
|
34
35
|
allowFontSize?: boolean;
|
|
35
36
|
includeBlockQuoteAsTextstyleOption?: boolean;
|
|
@@ -32,4 +32,21 @@ export declare function getSelectionRangeExpandedToLists(tr: Transaction): {
|
|
|
32
32
|
from: number;
|
|
33
33
|
to: number;
|
|
34
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Converts all taskItem nodes within the given range to blockTaskItem nodes.
|
|
37
|
+
*
|
|
38
|
+
* taskItem nodes contain inline content directly, which cannot hold block-level
|
|
39
|
+
* marks like fontSize. blockTaskItem nodes wrap content in paragraphs, which can
|
|
40
|
+
* hold block marks. This conversion is needed when applying small text formatting
|
|
41
|
+
* to task lists.
|
|
42
|
+
*
|
|
43
|
+
* The inline content of each taskItem is wrapped in a paragraph node, and the
|
|
44
|
+
* taskItem is replaced with a blockTaskItem that preserves the original attributes
|
|
45
|
+
* (localId, state).
|
|
46
|
+
*
|
|
47
|
+
* Collects taskItem positions in a forward pass over the unmutated document,
|
|
48
|
+
* then applies replacements in reverse document order so positions remain valid
|
|
49
|
+
* without needing remapping or doc snapshots.
|
|
50
|
+
*/
|
|
51
|
+
export declare function convertTaskItemsToBlockTaskItems(tr: Transaction, from: number, to: number): void;
|
|
35
52
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-block-type",
|
|
3
|
-
"version": "12.1.
|
|
3
|
+
"version": "12.1.7",
|
|
4
4
|
"description": "BlockType plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@atlaskit/prosemirror-history": "^0.2.0",
|
|
51
51
|
"@atlaskit/prosemirror-input-rules": "^3.6.0",
|
|
52
52
|
"@atlaskit/theme": "^22.0.0",
|
|
53
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
53
|
+
"@atlaskit/tmp-editor-statsig": "^43.0.0",
|
|
54
54
|
"@atlaskit/tokens": "^11.1.0",
|
|
55
55
|
"@babel/runtime": "^7.0.0",
|
|
56
56
|
"@compiled/react": "^0.20.0",
|