@atlaskit/editor-plugin-list 11.0.0 → 12.0.0
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 +33 -0
- package/dist/cjs/pm-plugins/commands/indent-list.js +2 -2
- package/dist/cjs/pm-plugins/commands/outdent-list.js +2 -2
- package/dist/cjs/pm-plugins/main.js +22 -1
- package/dist/cjs/pm-plugins/transforms.js +162 -0
- package/dist/cjs/ui/BulletedListBlockMenuItem.js +2 -2
- package/dist/cjs/ui/NumberedListBlockMenuItem.js +2 -2
- package/dist/es2019/pm-plugins/commands/indent-list.js +2 -2
- package/dist/es2019/pm-plugins/commands/outdent-list.js +2 -2
- package/dist/es2019/pm-plugins/main.js +20 -1
- package/dist/es2019/pm-plugins/transforms.js +120 -1
- package/dist/es2019/ui/BulletedListBlockMenuItem.js +1 -1
- package/dist/es2019/ui/NumberedListBlockMenuItem.js +1 -1
- package/dist/esm/pm-plugins/commands/indent-list.js +2 -2
- package/dist/esm/pm-plugins/commands/outdent-list.js +2 -2
- package/dist/esm/pm-plugins/main.js +22 -1
- package/dist/esm/pm-plugins/transforms.js +161 -1
- package/dist/esm/ui/BulletedListBlockMenuItem.js +1 -1
- package/dist/esm/ui/NumberedListBlockMenuItem.js +1 -1
- package/dist/types/pm-plugins/main.d.ts +1 -1
- package/dist/types/pm-plugins/transforms.d.ts +18 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/transforms.d.ts +18 -0
- package/package.json +11 -8
- package/report.api.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-list
|
|
2
2
|
|
|
3
|
+
## 12.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [`901c87a57486e`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/901c87a57486e) -
|
|
8
|
+
Removed `react-intl-next` alias and replaced all usages with `react-intl` directly.
|
|
9
|
+
|
|
10
|
+
What changed: The `react-intl-next` npm alias (which resolved to `react-intl@^5`) has been
|
|
11
|
+
removed. All imports now reference `react-intl` directly, and `peerDependencies` have been updated
|
|
12
|
+
to `"^5.25.1 || ^6.0.0 || ^7.0.0"`.
|
|
13
|
+
|
|
14
|
+
How consumer should update their code: Ensure `react-intl` is installed at a version satisfying
|
|
15
|
+
`^5.25.1 || ^6.0.0 || ^7.0.0`. If your application was using `react-intl-next` as an npm alias, it
|
|
16
|
+
can be safely removed. Replace any remaining `react-intl-next` imports with `react-intl`.
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
22
|
+
## 11.0.1
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- [`bae5d569f660c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/bae5d569f660c) -
|
|
27
|
+
Prevent flexible list creation when platform_editor_flexible_list_schema is on but
|
|
28
|
+
platform_editor_flexible_list_indentation is off. Slice normalisation in paste pipeline.
|
|
29
|
+
appendTransaction normaliser in list plugin.
|
|
30
|
+
|
|
31
|
+
Paste plugin detects list-into-list paste and sets a transaction meta to skip closeHistory,
|
|
32
|
+
keeping the paste and normalisation appendTransaction as a single undo step.
|
|
33
|
+
|
|
34
|
+
- Updated dependencies
|
|
35
|
+
|
|
3
36
|
## 11.0.0
|
|
4
37
|
|
|
5
38
|
### Patch Changes
|
|
@@ -11,7 +11,7 @@ var _lists = require("@atlaskit/editor-common/lists");
|
|
|
11
11
|
var _preset = require("@atlaskit/editor-common/preset");
|
|
12
12
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
13
13
|
var _prosemirrorHistory = require("@atlaskit/prosemirror-history");
|
|
14
|
-
var
|
|
14
|
+
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
15
15
|
var _types = require("../../types");
|
|
16
16
|
var _indentListItemsSelected = require("../actions/indent-list-items-selected");
|
|
17
17
|
var _moveSelectedListItems = require("../actions/move-selected-list-items");
|
|
@@ -61,7 +61,7 @@ var indentList = exports.indentList = function indentList(editorAnalyticsAPI) {
|
|
|
61
61
|
(0, _prosemirrorHistory.closeHistory)(tr);
|
|
62
62
|
|
|
63
63
|
// Route to new or original implementation based on feature flag
|
|
64
|
-
if ((0,
|
|
64
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
|
|
65
65
|
return handleIndentListItems(tr, editorAnalyticsAPI, inputMethod);
|
|
66
66
|
}
|
|
67
67
|
var firstListItemSelectedAttributes = (0, _lists.getListItemAttributes)($from);
|
|
@@ -11,7 +11,7 @@ var _lists = require("@atlaskit/editor-common/lists");
|
|
|
11
11
|
var _preset = require("@atlaskit/editor-common/preset");
|
|
12
12
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
13
13
|
var _prosemirrorHistory = require("@atlaskit/prosemirror-history");
|
|
14
|
-
var
|
|
14
|
+
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
15
15
|
var _moveSelectedListItems = require("../actions/move-selected-list-items");
|
|
16
16
|
var _outdentListItemsSelected = require("../actions/outdent-list-items-selected");
|
|
17
17
|
var _analytics2 = require("../utils/analytics");
|
|
@@ -79,7 +79,7 @@ var outdentList = exports.outdentList = function outdentList(editorAnalyticsAPI)
|
|
|
79
79
|
(0, _prosemirrorHistory.closeHistory)(tr);
|
|
80
80
|
|
|
81
81
|
// Route to new or original implementation based on feature flag
|
|
82
|
-
if ((0,
|
|
82
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
|
|
83
83
|
return handleOutdentListItems(tr, editorAnalyticsAPI, inputMethod);
|
|
84
84
|
}
|
|
85
85
|
var actionSubjectId = (0, _utils.isBulletList)(parentListNode.node) ? _analytics.ACTION_SUBJECT_ID.FORMAT_LIST_BULLET : _analytics.ACTION_SUBJECT_ID.FORMAT_LIST_NUMBER;
|
|
@@ -13,6 +13,7 @@ var _utils = require("@atlaskit/editor-common/utils");
|
|
|
13
13
|
var _state2 = require("@atlaskit/editor-prosemirror/state");
|
|
14
14
|
var _utils2 = require("@atlaskit/editor-prosemirror/utils");
|
|
15
15
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
16
|
+
var _transforms = require("./transforms");
|
|
16
17
|
var _selection2 = require("./utils/selection");
|
|
17
18
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
18
19
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
@@ -139,6 +140,25 @@ var createPlugin = exports.createPlugin = function createPlugin(eventDispatch, f
|
|
|
139
140
|
return new _safePlugin.SafePlugin({
|
|
140
141
|
state: createPluginState(eventDispatch, createInitialState(featureFlags, api)),
|
|
141
142
|
key: listPluginKey,
|
|
143
|
+
appendTransaction: function appendTransaction(transactions, _oldState, newState) {
|
|
144
|
+
// The paste plugin sets 'listPasteNormalisation' on the transaction when it detects
|
|
145
|
+
// a list is being pasted into a list (and the flexible list schema flag is on).
|
|
146
|
+
// We use this meta to cheaply trigger normalisation without re-checking flags.
|
|
147
|
+
if (transactions.some(function (t) {
|
|
148
|
+
return t.getMeta('listPasteNormalisation');
|
|
149
|
+
})) {
|
|
150
|
+
var tr = (0, _transforms.applyListNormalisationFixes)({
|
|
151
|
+
tr: newState.tr,
|
|
152
|
+
transactions: transactions,
|
|
153
|
+
doc: newState.doc,
|
|
154
|
+
schema: newState.schema
|
|
155
|
+
});
|
|
156
|
+
if (tr.docChanged) {
|
|
157
|
+
return tr;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return null;
|
|
161
|
+
},
|
|
142
162
|
props: {
|
|
143
163
|
decorations: function decorations(state) {
|
|
144
164
|
var _getPluginState = getPluginState(state),
|
|
@@ -158,7 +178,8 @@ var createPlugin = exports.createPlugin = function createPlugin(eventDispatch, f
|
|
|
158
178
|
if ((nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type) === listItem && (nodeAtPos === null || nodeAtPos === void 0 || (_nodeAtPos$firstChild = nodeAtPos.firstChild) === null || _nodeAtPos$firstChild === void 0 ? void 0 : _nodeAtPos$firstChild.type) === codeBlock) {
|
|
159
179
|
var _document;
|
|
160
180
|
var bufferPx = 50;
|
|
161
|
-
var isCodeBlockNextToListMarker = Boolean(
|
|
181
|
+
var isCodeBlockNextToListMarker = Boolean( // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
182
|
+
(_document = document) === null || _document === void 0 || (_document = _document.elementFromPoint(event.clientX + (_styles.listItemCounterPadding + bufferPx), event.clientY)) === null || _document === void 0 ? void 0 : _document.closest(".".concat(_styles.CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER)));
|
|
162
183
|
if (isCodeBlockNextToListMarker) {
|
|
163
184
|
// +1 needed to put cursor inside li
|
|
164
185
|
// otherwise gap cursor markup will be injected as immediate child of ul resulting in invalid html
|
|
@@ -1,15 +1,25 @@
|
|
|
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
|
});
|
|
7
|
+
exports.applyListNormalisationFixes = applyListNormalisationFixes;
|
|
6
8
|
exports.liftFollowingList = liftFollowingList;
|
|
7
9
|
exports.liftNodeSelectionList = liftNodeSelectionList;
|
|
8
10
|
exports.liftTextSelectionList = liftTextSelectionList;
|
|
11
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
12
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
13
|
+
var _utils = require("@atlaskit/editor-common/utils");
|
|
9
14
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
10
15
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
11
16
|
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
17
|
+
var _utils2 = require("@atlaskit/editor-prosemirror/utils");
|
|
18
|
+
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
12
19
|
var _indentation = require("./utils/indentation");
|
|
20
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
21
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
22
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
13
23
|
function liftListItem(selection, tr) {
|
|
14
24
|
var $from = selection.$from,
|
|
15
25
|
$to = selection.$to;
|
|
@@ -96,4 +106,156 @@ function liftTextSelectionList(selection, tr) {
|
|
|
96
106
|
}
|
|
97
107
|
}
|
|
98
108
|
return tr;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Finds the top-level list nodes (bulletList/orderedList) that contain the positions
|
|
113
|
+
* affected by the given transactions. Returns a map of list node position → list node,
|
|
114
|
+
* so callers can scan only the affected subtrees rather than the entire document.
|
|
115
|
+
*/
|
|
116
|
+
function getAffectedListsFromTransactions(transactions, doc, schema) {
|
|
117
|
+
var _schema$nodes = schema.nodes,
|
|
118
|
+
bulletList = _schema$nodes.bulletList,
|
|
119
|
+
orderedList = _schema$nodes.orderedList;
|
|
120
|
+
var listTypes = [bulletList, orderedList].filter(Boolean);
|
|
121
|
+
if (listTypes.length === 0) {
|
|
122
|
+
return new Map();
|
|
123
|
+
}
|
|
124
|
+
var result = new Map();
|
|
125
|
+
var _iterator = _createForOfIteratorHelper(transactions),
|
|
126
|
+
_step;
|
|
127
|
+
try {
|
|
128
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
129
|
+
var tr = _step.value;
|
|
130
|
+
var _iterator2 = _createForOfIteratorHelper(tr.steps),
|
|
131
|
+
_step2;
|
|
132
|
+
try {
|
|
133
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
134
|
+
var step = _step2.value;
|
|
135
|
+
// ReplaceStep and ReplaceAroundStep both have from/to — other step types are skipped.
|
|
136
|
+
if (!(step instanceof _transform.ReplaceStep) && !(step instanceof _transform.ReplaceAroundStep)) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
// Check both the start and end of each changed range, mapped to post-paste positions.
|
|
140
|
+
for (var _i = 0, _arr = [step.from, step.to]; _i < _arr.length; _i++) {
|
|
141
|
+
var rawPos = _arr[_i];
|
|
142
|
+
var mappedPos = Math.min(tr.mapping.map(rawPos), doc.content.size - 1);
|
|
143
|
+
var $pos = doc.resolve(mappedPos);
|
|
144
|
+
var ancestor = (0, _utils2.findParentNodeOfTypeClosestToPos)($pos, listTypes);
|
|
145
|
+
if (ancestor) {
|
|
146
|
+
result.set(ancestor.pos, ancestor.node);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
} catch (err) {
|
|
151
|
+
_iterator2.e(err);
|
|
152
|
+
} finally {
|
|
153
|
+
_iterator2.f();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
} catch (err) {
|
|
157
|
+
_iterator.e(err);
|
|
158
|
+
} finally {
|
|
159
|
+
_iterator.f();
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Applies list normalisation fixes to the given transaction for all affected list subtrees.
|
|
165
|
+
* Processes nodes in reverse document order so that position offsets from insertions/joins
|
|
166
|
+
* do not affect earlier positions.
|
|
167
|
+
*
|
|
168
|
+
* When platform_editor_flexible_list_indentation is off: inserts an empty paragraph before any listItem whose
|
|
169
|
+
* first child is a list node, and merges adjacent same-type list nodes within a listItem.
|
|
170
|
+
* When platform_editor_flexible_list_indentation is on: only merges adjacent same-type list nodes.
|
|
171
|
+
*/
|
|
172
|
+
function applyListNormalisationFixes(_ref) {
|
|
173
|
+
var tr = _ref.tr,
|
|
174
|
+
transactions = _ref.transactions,
|
|
175
|
+
doc = _ref.doc,
|
|
176
|
+
schema = _ref.schema;
|
|
177
|
+
var affectedLists = getAffectedListsFromTransactions(transactions, doc, schema);
|
|
178
|
+
if (affectedLists.size === 0) {
|
|
179
|
+
return tr;
|
|
180
|
+
}
|
|
181
|
+
var _schema$nodes2 = schema.nodes,
|
|
182
|
+
listItem = _schema$nodes2.listItem,
|
|
183
|
+
paragraph = _schema$nodes2.paragraph;
|
|
184
|
+
if (!listItem) {
|
|
185
|
+
return tr;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Process lists in reverse position order so fixes at higher positions
|
|
189
|
+
// don't shift the positions of fixes at lower positions.
|
|
190
|
+
var sortedEntries = (0, _toConsumableArray2.default)(affectedLists.entries()).sort(function (_ref2, _ref3) {
|
|
191
|
+
var _ref4 = (0, _slicedToArray2.default)(_ref2, 1),
|
|
192
|
+
posA = _ref4[0];
|
|
193
|
+
var _ref5 = (0, _slicedToArray2.default)(_ref3, 1),
|
|
194
|
+
posB = _ref5[0];
|
|
195
|
+
return posB - posA;
|
|
196
|
+
});
|
|
197
|
+
var _iterator3 = _createForOfIteratorHelper(sortedEntries),
|
|
198
|
+
_step3;
|
|
199
|
+
try {
|
|
200
|
+
var _loop = function _loop() {
|
|
201
|
+
var _step3$value = (0, _slicedToArray2.default)(_step3.value, 2),
|
|
202
|
+
listPos = _step3$value[0],
|
|
203
|
+
listNode = _step3$value[1];
|
|
204
|
+
// Collect listItem positions in document order, then process in reverse so that
|
|
205
|
+
// fixes at higher positions don't shift positions of fixes at lower positions.
|
|
206
|
+
var listItemPositions = [];
|
|
207
|
+
listNode.descendants(function (node, offsetPos) {
|
|
208
|
+
if (node.type === listItem) {
|
|
209
|
+
listItemPositions.push(listPos + 1 + offsetPos);
|
|
210
|
+
return false; // Don't descend — inner listItems are handled via their own ancestor list
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
});
|
|
214
|
+
for (var i = listItemPositions.length - 1; i >= 0; i--) {
|
|
215
|
+
var mappedPos = tr.mapping.map(listItemPositions[i]);
|
|
216
|
+
var node = tr.doc.nodeAt(mappedPos);
|
|
217
|
+
if (!node || node.type !== listItem) {
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Merge adjacent same-type list nodes (highest boundary first within the listItem).
|
|
222
|
+
for (var j = node.childCount - 1; j > 0; j--) {
|
|
223
|
+
var child = node.child(j);
|
|
224
|
+
var prevChild = node.child(j - 1);
|
|
225
|
+
if ((0, _utils.isListNode)(child) && child.type === prevChild.type) {
|
|
226
|
+
var offset = 1; // +1 for listItem opening token
|
|
227
|
+
for (var k = 0; k < j; k++) {
|
|
228
|
+
offset += node.child(k).nodeSize;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
tr.join(mappedPos + offset);
|
|
232
|
+
} catch (e) {
|
|
233
|
+
// join may fail if position is invalid after earlier transforms — skip
|
|
234
|
+
// eslint-disable-next-line no-console
|
|
235
|
+
console.warn('[editor-plugin-list] applyListNormalisationFixes: unexpected join failure', e);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Insert empty paragraph before list-first listItems when _indentation is off.
|
|
241
|
+
if (paragraph && !(0, _expValEquals.expValEquals)('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
|
|
242
|
+
var currentNode = tr.doc.nodeAt(mappedPos);
|
|
243
|
+
if (currentNode && currentNode.firstChild && currentNode.firstChild.type !== paragraph) {
|
|
244
|
+
var emptyParagraph = paragraph.createAndFill();
|
|
245
|
+
if (emptyParagraph) {
|
|
246
|
+
tr.insert(mappedPos + 1, emptyParagraph);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
253
|
+
_loop();
|
|
254
|
+
}
|
|
255
|
+
} catch (err) {
|
|
256
|
+
_iterator3.e(err);
|
|
257
|
+
} finally {
|
|
258
|
+
_iterator3.f();
|
|
259
|
+
}
|
|
260
|
+
return tr;
|
|
99
261
|
}
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.createBulletedListBlockMenuItem = void 0;
|
|
8
8
|
var _react = _interopRequireDefault(require("react"));
|
|
9
|
-
var
|
|
9
|
+
var _reactIntl = require("react-intl");
|
|
10
10
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
11
11
|
var _messages = require("@atlaskit/editor-common/messages");
|
|
12
12
|
var _editorToolbar = require("@atlaskit/editor-toolbar");
|
|
@@ -14,7 +14,7 @@ var _listBulleted = _interopRequireDefault(require("@atlaskit/icon/core/list-bul
|
|
|
14
14
|
var NODE_NAME = 'bulletList';
|
|
15
15
|
var BulletedListBlockMenuItem = function BulletedListBlockMenuItem(_ref) {
|
|
16
16
|
var api = _ref.api;
|
|
17
|
-
var _useIntl = (0,
|
|
17
|
+
var _useIntl = (0, _reactIntl.useIntl)(),
|
|
18
18
|
formatMessage = _useIntl.formatMessage;
|
|
19
19
|
var handleClick = function handleClick(event) {
|
|
20
20
|
var triggeredFrom = event.nativeEvent instanceof KeyboardEvent || event.nativeEvent.detail === 0 ? _analytics.INPUT_METHOD.KEYBOARD : _analytics.INPUT_METHOD.MOUSE;
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.createNumberedListBlockMenuItem = void 0;
|
|
8
8
|
var _react = _interopRequireDefault(require("react"));
|
|
9
|
-
var
|
|
9
|
+
var _reactIntl = require("react-intl");
|
|
10
10
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
11
11
|
var _messages = require("@atlaskit/editor-common/messages");
|
|
12
12
|
var _editorToolbar = require("@atlaskit/editor-toolbar");
|
|
@@ -14,7 +14,7 @@ var _listNumbered = _interopRequireDefault(require("@atlaskit/icon/core/list-num
|
|
|
14
14
|
var NODE_NAME = 'orderedList';
|
|
15
15
|
var NumberedListBlockMenuItem = function NumberedListBlockMenuItem(_ref) {
|
|
16
16
|
var api = _ref.api;
|
|
17
|
-
var _useIntl = (0,
|
|
17
|
+
var _useIntl = (0, _reactIntl.useIntl)(),
|
|
18
18
|
formatMessage = _useIntl.formatMessage;
|
|
19
19
|
var handleClick = function handleClick(event) {
|
|
20
20
|
var triggeredFrom = event.nativeEvent instanceof KeyboardEvent || event.nativeEvent.detail === 0 ? _analytics.INPUT_METHOD.KEYBOARD : _analytics.INPUT_METHOD.MOUSE;
|
|
@@ -3,7 +3,7 @@ import { getCommonListAnalyticsAttributes, getListItemAttributes, hasValidListIn
|
|
|
3
3
|
import { PassiveTransaction } from '@atlaskit/editor-common/preset';
|
|
4
4
|
import { isBulletList } from '@atlaskit/editor-common/utils';
|
|
5
5
|
import { closeHistory } from '@atlaskit/prosemirror-history';
|
|
6
|
-
import {
|
|
6
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
7
7
|
import { MAX_NESTED_LIST_INDENTATION } from '../../types';
|
|
8
8
|
import { indentListItemsSelected as indentListAction } from '../actions/indent-list-items-selected';
|
|
9
9
|
import { moveSelectedListItems } from '../actions/move-selected-list-items';
|
|
@@ -59,7 +59,7 @@ export const indentList = editorAnalyticsAPI => (inputMethod = INPUT_METHOD.KEYB
|
|
|
59
59
|
closeHistory(tr);
|
|
60
60
|
|
|
61
61
|
// Route to new or original implementation based on feature flag
|
|
62
|
-
if (
|
|
62
|
+
if (expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
|
|
63
63
|
return handleIndentListItems(tr, editorAnalyticsAPI, inputMethod);
|
|
64
64
|
}
|
|
65
65
|
const firstListItemSelectedAttributes = getListItemAttributes($from);
|
|
@@ -3,7 +3,7 @@ import { getCommonListAnalyticsAttributes } from '@atlaskit/editor-common/lists'
|
|
|
3
3
|
import { PassiveTransaction } from '@atlaskit/editor-common/preset';
|
|
4
4
|
import { isBulletList } from '@atlaskit/editor-common/utils';
|
|
5
5
|
import { closeHistory } from '@atlaskit/prosemirror-history';
|
|
6
|
-
import {
|
|
6
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
7
7
|
import { moveSelectedListItems } from '../actions/move-selected-list-items';
|
|
8
8
|
import { outdentListItemsSelected as outdentListAction } from '../actions/outdent-list-items-selected';
|
|
9
9
|
import { getRestartListsAttributes } from '../utils/analytics';
|
|
@@ -77,7 +77,7 @@ export const outdentList = editorAnalyticsAPI => (inputMethod = INPUT_METHOD.KEY
|
|
|
77
77
|
closeHistory(tr);
|
|
78
78
|
|
|
79
79
|
// Route to new or original implementation based on feature flag
|
|
80
|
-
if (
|
|
80
|
+
if (expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
|
|
81
81
|
return handleOutdentListItems(tr, editorAnalyticsAPI, inputMethod);
|
|
82
82
|
}
|
|
83
83
|
const actionSubjectId = isBulletList(parentListNode.node) ? ACTION_SUBJECT_ID.FORMAT_LIST_BULLET : ACTION_SUBJECT_ID.FORMAT_LIST_NUMBER;
|
|
@@ -5,6 +5,7 @@ import { getItemCounterDigitsSize, isListNode, pluginFactory } from '@atlaskit/e
|
|
|
5
5
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
6
|
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
7
7
|
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
8
|
+
import { applyListNormalisationFixes } from './transforms';
|
|
8
9
|
import { isWrappingPossible } from './utils/selection';
|
|
9
10
|
const listPluginKey = new PluginKey('listPlugin');
|
|
10
11
|
export const pluginKey = listPluginKey;
|
|
@@ -131,6 +132,23 @@ export const createPlugin = (eventDispatch, featureFlags, api) => {
|
|
|
131
132
|
return new SafePlugin({
|
|
132
133
|
state: createPluginState(eventDispatch, createInitialState(featureFlags, api)),
|
|
133
134
|
key: listPluginKey,
|
|
135
|
+
appendTransaction(transactions, _oldState, newState) {
|
|
136
|
+
// The paste plugin sets 'listPasteNormalisation' on the transaction when it detects
|
|
137
|
+
// a list is being pasted into a list (and the flexible list schema flag is on).
|
|
138
|
+
// We use this meta to cheaply trigger normalisation without re-checking flags.
|
|
139
|
+
if (transactions.some(t => t.getMeta('listPasteNormalisation'))) {
|
|
140
|
+
const tr = applyListNormalisationFixes({
|
|
141
|
+
tr: newState.tr,
|
|
142
|
+
transactions,
|
|
143
|
+
doc: newState.doc,
|
|
144
|
+
schema: newState.schema
|
|
145
|
+
});
|
|
146
|
+
if (tr.docChanged) {
|
|
147
|
+
return tr;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
},
|
|
134
152
|
props: {
|
|
135
153
|
decorations(state) {
|
|
136
154
|
const {
|
|
@@ -154,7 +172,8 @@ export const createPlugin = (eventDispatch, featureFlags, api) => {
|
|
|
154
172
|
if ((nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type) === listItem && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : (_nodeAtPos$firstChild = nodeAtPos.firstChild) === null || _nodeAtPos$firstChild === void 0 ? void 0 : _nodeAtPos$firstChild.type) === codeBlock) {
|
|
155
173
|
var _document, _document$elementFrom;
|
|
156
174
|
const bufferPx = 50;
|
|
157
|
-
const isCodeBlockNextToListMarker = Boolean(
|
|
175
|
+
const isCodeBlockNextToListMarker = Boolean( // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
176
|
+
(_document = document) === null || _document === void 0 ? void 0 : (_document$elementFrom = _document.elementFromPoint(event.clientX + (listItemCounterPadding + bufferPx), event.clientY)) === null || _document$elementFrom === void 0 ? void 0 : _document$elementFrom.closest(`.${CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER}`));
|
|
158
177
|
if (isCodeBlockNextToListMarker) {
|
|
159
178
|
// +1 needed to put cursor inside li
|
|
160
179
|
// otherwise gap cursor markup will be injected as immediate child of ul resulting in invalid html
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { isListNode } from '@atlaskit/editor-common/utils';
|
|
1
2
|
import { Fragment, NodeRange, Slice } from '@atlaskit/editor-prosemirror/model';
|
|
2
3
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
-
import { liftTarget, ReplaceAroundStep } from '@atlaskit/editor-prosemirror/transform';
|
|
4
|
+
import { liftTarget, ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
5
|
+
import { findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
6
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
4
7
|
import { getListLiftTarget } from './utils/indentation';
|
|
5
8
|
function liftListItem(selection, tr) {
|
|
6
9
|
const {
|
|
@@ -98,4 +101,120 @@ export function liftTextSelectionList(selection, tr) {
|
|
|
98
101
|
}
|
|
99
102
|
}
|
|
100
103
|
return tr;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Finds the top-level list nodes (bulletList/orderedList) that contain the positions
|
|
108
|
+
* affected by the given transactions. Returns a map of list node position → list node,
|
|
109
|
+
* so callers can scan only the affected subtrees rather than the entire document.
|
|
110
|
+
*/
|
|
111
|
+
function getAffectedListsFromTransactions(transactions, doc, schema) {
|
|
112
|
+
const {
|
|
113
|
+
bulletList,
|
|
114
|
+
orderedList
|
|
115
|
+
} = schema.nodes;
|
|
116
|
+
const listTypes = [bulletList, orderedList].filter(Boolean);
|
|
117
|
+
if (listTypes.length === 0) {
|
|
118
|
+
return new Map();
|
|
119
|
+
}
|
|
120
|
+
const result = new Map();
|
|
121
|
+
for (const tr of transactions) {
|
|
122
|
+
for (const step of tr.steps) {
|
|
123
|
+
// ReplaceStep and ReplaceAroundStep both have from/to — other step types are skipped.
|
|
124
|
+
if (!(step instanceof ReplaceStep) && !(step instanceof ReplaceAroundStep)) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
// Check both the start and end of each changed range, mapped to post-paste positions.
|
|
128
|
+
for (const rawPos of [step.from, step.to]) {
|
|
129
|
+
const mappedPos = Math.min(tr.mapping.map(rawPos), doc.content.size - 1);
|
|
130
|
+
const $pos = doc.resolve(mappedPos);
|
|
131
|
+
const ancestor = findParentNodeOfTypeClosestToPos($pos, listTypes);
|
|
132
|
+
if (ancestor) {
|
|
133
|
+
result.set(ancestor.pos, ancestor.node);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Applies list normalisation fixes to the given transaction for all affected list subtrees.
|
|
142
|
+
* Processes nodes in reverse document order so that position offsets from insertions/joins
|
|
143
|
+
* do not affect earlier positions.
|
|
144
|
+
*
|
|
145
|
+
* When platform_editor_flexible_list_indentation is off: inserts an empty paragraph before any listItem whose
|
|
146
|
+
* first child is a list node, and merges adjacent same-type list nodes within a listItem.
|
|
147
|
+
* When platform_editor_flexible_list_indentation is on: only merges adjacent same-type list nodes.
|
|
148
|
+
*/
|
|
149
|
+
export function applyListNormalisationFixes({
|
|
150
|
+
tr,
|
|
151
|
+
transactions,
|
|
152
|
+
doc,
|
|
153
|
+
schema
|
|
154
|
+
}) {
|
|
155
|
+
const affectedLists = getAffectedListsFromTransactions(transactions, doc, schema);
|
|
156
|
+
if (affectedLists.size === 0) {
|
|
157
|
+
return tr;
|
|
158
|
+
}
|
|
159
|
+
const {
|
|
160
|
+
listItem,
|
|
161
|
+
paragraph
|
|
162
|
+
} = schema.nodes;
|
|
163
|
+
if (!listItem) {
|
|
164
|
+
return tr;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Process lists in reverse position order so fixes at higher positions
|
|
168
|
+
// don't shift the positions of fixes at lower positions.
|
|
169
|
+
const sortedEntries = [...affectedLists.entries()].sort(([posA], [posB]) => posB - posA);
|
|
170
|
+
for (const [listPos, listNode] of sortedEntries) {
|
|
171
|
+
// Collect listItem positions in document order, then process in reverse so that
|
|
172
|
+
// fixes at higher positions don't shift positions of fixes at lower positions.
|
|
173
|
+
const listItemPositions = [];
|
|
174
|
+
listNode.descendants((node, offsetPos) => {
|
|
175
|
+
if (node.type === listItem) {
|
|
176
|
+
listItemPositions.push(listPos + 1 + offsetPos);
|
|
177
|
+
return false; // Don't descend — inner listItems are handled via their own ancestor list
|
|
178
|
+
}
|
|
179
|
+
return true;
|
|
180
|
+
});
|
|
181
|
+
for (let i = listItemPositions.length - 1; i >= 0; i--) {
|
|
182
|
+
const mappedPos = tr.mapping.map(listItemPositions[i]);
|
|
183
|
+
const node = tr.doc.nodeAt(mappedPos);
|
|
184
|
+
if (!node || node.type !== listItem) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Merge adjacent same-type list nodes (highest boundary first within the listItem).
|
|
189
|
+
for (let j = node.childCount - 1; j > 0; j--) {
|
|
190
|
+
const child = node.child(j);
|
|
191
|
+
const prevChild = node.child(j - 1);
|
|
192
|
+
if (isListNode(child) && child.type === prevChild.type) {
|
|
193
|
+
let offset = 1; // +1 for listItem opening token
|
|
194
|
+
for (let k = 0; k < j; k++) {
|
|
195
|
+
offset += node.child(k).nodeSize;
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
tr.join(mappedPos + offset);
|
|
199
|
+
} catch (e) {
|
|
200
|
+
// join may fail if position is invalid after earlier transforms — skip
|
|
201
|
+
// eslint-disable-next-line no-console
|
|
202
|
+
console.warn('[editor-plugin-list] applyListNormalisationFixes: unexpected join failure', e);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Insert empty paragraph before list-first listItems when _indentation is off.
|
|
208
|
+
if (paragraph && !expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
|
|
209
|
+
const currentNode = tr.doc.nodeAt(mappedPos);
|
|
210
|
+
if (currentNode && currentNode.firstChild && currentNode.firstChild.type !== paragraph) {
|
|
211
|
+
const emptyParagraph = paragraph.createAndFill();
|
|
212
|
+
if (emptyParagraph) {
|
|
213
|
+
tr.insert(mappedPos + 1, emptyParagraph);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return tr;
|
|
101
220
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { useIntl } from 'react-intl
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
3
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { listMessages } from '@atlaskit/editor-common/messages';
|
|
5
5
|
import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { useIntl } from 'react-intl
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
3
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { listMessages } from '@atlaskit/editor-common/messages';
|
|
5
5
|
import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
|
|
@@ -6,7 +6,7 @@ import { getCommonListAnalyticsAttributes, getListItemAttributes, hasValidListIn
|
|
|
6
6
|
import { PassiveTransaction } from '@atlaskit/editor-common/preset';
|
|
7
7
|
import { isBulletList } from '@atlaskit/editor-common/utils';
|
|
8
8
|
import { closeHistory } from '@atlaskit/prosemirror-history';
|
|
9
|
-
import {
|
|
9
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
10
10
|
import { MAX_NESTED_LIST_INDENTATION } from '../../types';
|
|
11
11
|
import { indentListItemsSelected as indentListAction } from '../actions/indent-list-items-selected';
|
|
12
12
|
import { moveSelectedListItems } from '../actions/move-selected-list-items';
|
|
@@ -54,7 +54,7 @@ export var indentList = function indentList(editorAnalyticsAPI) {
|
|
|
54
54
|
closeHistory(tr);
|
|
55
55
|
|
|
56
56
|
// Route to new or original implementation based on feature flag
|
|
57
|
-
if (
|
|
57
|
+
if (expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
|
|
58
58
|
return handleIndentListItems(tr, editorAnalyticsAPI, inputMethod);
|
|
59
59
|
}
|
|
60
60
|
var firstListItemSelectedAttributes = getListItemAttributes($from);
|
|
@@ -6,7 +6,7 @@ import { getCommonListAnalyticsAttributes } from '@atlaskit/editor-common/lists'
|
|
|
6
6
|
import { PassiveTransaction } from '@atlaskit/editor-common/preset';
|
|
7
7
|
import { isBulletList } from '@atlaskit/editor-common/utils';
|
|
8
8
|
import { closeHistory } from '@atlaskit/prosemirror-history';
|
|
9
|
-
import {
|
|
9
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
10
10
|
import { moveSelectedListItems } from '../actions/move-selected-list-items';
|
|
11
11
|
import { outdentListItemsSelected as outdentListAction } from '../actions/outdent-list-items-selected';
|
|
12
12
|
import { getRestartListsAttributes } from '../utils/analytics';
|
|
@@ -72,7 +72,7 @@ export var outdentList = function outdentList(editorAnalyticsAPI) {
|
|
|
72
72
|
closeHistory(tr);
|
|
73
73
|
|
|
74
74
|
// Route to new or original implementation based on feature flag
|
|
75
|
-
if (
|
|
75
|
+
if (expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
|
|
76
76
|
return handleOutdentListItems(tr, editorAnalyticsAPI, inputMethod);
|
|
77
77
|
}
|
|
78
78
|
var actionSubjectId = isBulletList(parentListNode.node) ? ACTION_SUBJECT_ID.FORMAT_LIST_BULLET : ACTION_SUBJECT_ID.FORMAT_LIST_NUMBER;
|
|
@@ -8,6 +8,7 @@ import { getItemCounterDigitsSize, isListNode, pluginFactory } from '@atlaskit/e
|
|
|
8
8
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
9
9
|
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
10
10
|
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
11
|
+
import { applyListNormalisationFixes } from './transforms';
|
|
11
12
|
import { isWrappingPossible } from './utils/selection';
|
|
12
13
|
var listPluginKey = new PluginKey('listPlugin');
|
|
13
14
|
export var pluginKey = listPluginKey;
|
|
@@ -132,6 +133,25 @@ export var createPlugin = function createPlugin(eventDispatch, featureFlags, api
|
|
|
132
133
|
return new SafePlugin({
|
|
133
134
|
state: createPluginState(eventDispatch, createInitialState(featureFlags, api)),
|
|
134
135
|
key: listPluginKey,
|
|
136
|
+
appendTransaction: function appendTransaction(transactions, _oldState, newState) {
|
|
137
|
+
// The paste plugin sets 'listPasteNormalisation' on the transaction when it detects
|
|
138
|
+
// a list is being pasted into a list (and the flexible list schema flag is on).
|
|
139
|
+
// We use this meta to cheaply trigger normalisation without re-checking flags.
|
|
140
|
+
if (transactions.some(function (t) {
|
|
141
|
+
return t.getMeta('listPasteNormalisation');
|
|
142
|
+
})) {
|
|
143
|
+
var tr = applyListNormalisationFixes({
|
|
144
|
+
tr: newState.tr,
|
|
145
|
+
transactions: transactions,
|
|
146
|
+
doc: newState.doc,
|
|
147
|
+
schema: newState.schema
|
|
148
|
+
});
|
|
149
|
+
if (tr.docChanged) {
|
|
150
|
+
return tr;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
},
|
|
135
155
|
props: {
|
|
136
156
|
decorations: function decorations(state) {
|
|
137
157
|
var _getPluginState = getPluginState(state),
|
|
@@ -151,7 +171,8 @@ export var createPlugin = function createPlugin(eventDispatch, featureFlags, api
|
|
|
151
171
|
if ((nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type) === listItem && (nodeAtPos === null || nodeAtPos === void 0 || (_nodeAtPos$firstChild = nodeAtPos.firstChild) === null || _nodeAtPos$firstChild === void 0 ? void 0 : _nodeAtPos$firstChild.type) === codeBlock) {
|
|
152
172
|
var _document;
|
|
153
173
|
var bufferPx = 50;
|
|
154
|
-
var isCodeBlockNextToListMarker = Boolean(
|
|
174
|
+
var isCodeBlockNextToListMarker = Boolean( // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage
|
|
175
|
+
(_document = document) === null || _document === void 0 || (_document = _document.elementFromPoint(event.clientX + (listItemCounterPadding + bufferPx), event.clientY)) === null || _document === void 0 ? void 0 : _document.closest(".".concat(CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER)));
|
|
155
176
|
if (isCodeBlockNextToListMarker) {
|
|
156
177
|
// +1 needed to put cursor inside li
|
|
157
178
|
// otherwise gap cursor markup will be injected as immediate child of ul resulting in invalid html
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
4
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
5
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
6
|
+
import { isListNode } from '@atlaskit/editor-common/utils';
|
|
1
7
|
import { Fragment, NodeRange, Slice } from '@atlaskit/editor-prosemirror/model';
|
|
2
8
|
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
-
import { liftTarget, ReplaceAroundStep } from '@atlaskit/editor-prosemirror/transform';
|
|
9
|
+
import { liftTarget, ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
10
|
+
import { findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
|
|
11
|
+
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
4
12
|
import { getListLiftTarget } from './utils/indentation';
|
|
5
13
|
function liftListItem(selection, tr) {
|
|
6
14
|
var $from = selection.$from,
|
|
@@ -88,4 +96,156 @@ export function liftTextSelectionList(selection, tr) {
|
|
|
88
96
|
}
|
|
89
97
|
}
|
|
90
98
|
return tr;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Finds the top-level list nodes (bulletList/orderedList) that contain the positions
|
|
103
|
+
* affected by the given transactions. Returns a map of list node position → list node,
|
|
104
|
+
* so callers can scan only the affected subtrees rather than the entire document.
|
|
105
|
+
*/
|
|
106
|
+
function getAffectedListsFromTransactions(transactions, doc, schema) {
|
|
107
|
+
var _schema$nodes = schema.nodes,
|
|
108
|
+
bulletList = _schema$nodes.bulletList,
|
|
109
|
+
orderedList = _schema$nodes.orderedList;
|
|
110
|
+
var listTypes = [bulletList, orderedList].filter(Boolean);
|
|
111
|
+
if (listTypes.length === 0) {
|
|
112
|
+
return new Map();
|
|
113
|
+
}
|
|
114
|
+
var result = new Map();
|
|
115
|
+
var _iterator = _createForOfIteratorHelper(transactions),
|
|
116
|
+
_step;
|
|
117
|
+
try {
|
|
118
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
119
|
+
var tr = _step.value;
|
|
120
|
+
var _iterator2 = _createForOfIteratorHelper(tr.steps),
|
|
121
|
+
_step2;
|
|
122
|
+
try {
|
|
123
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
124
|
+
var step = _step2.value;
|
|
125
|
+
// ReplaceStep and ReplaceAroundStep both have from/to — other step types are skipped.
|
|
126
|
+
if (!(step instanceof ReplaceStep) && !(step instanceof ReplaceAroundStep)) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
// Check both the start and end of each changed range, mapped to post-paste positions.
|
|
130
|
+
for (var _i = 0, _arr = [step.from, step.to]; _i < _arr.length; _i++) {
|
|
131
|
+
var rawPos = _arr[_i];
|
|
132
|
+
var mappedPos = Math.min(tr.mapping.map(rawPos), doc.content.size - 1);
|
|
133
|
+
var $pos = doc.resolve(mappedPos);
|
|
134
|
+
var ancestor = findParentNodeOfTypeClosestToPos($pos, listTypes);
|
|
135
|
+
if (ancestor) {
|
|
136
|
+
result.set(ancestor.pos, ancestor.node);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
} catch (err) {
|
|
141
|
+
_iterator2.e(err);
|
|
142
|
+
} finally {
|
|
143
|
+
_iterator2.f();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
} catch (err) {
|
|
147
|
+
_iterator.e(err);
|
|
148
|
+
} finally {
|
|
149
|
+
_iterator.f();
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Applies list normalisation fixes to the given transaction for all affected list subtrees.
|
|
155
|
+
* Processes nodes in reverse document order so that position offsets from insertions/joins
|
|
156
|
+
* do not affect earlier positions.
|
|
157
|
+
*
|
|
158
|
+
* When platform_editor_flexible_list_indentation is off: inserts an empty paragraph before any listItem whose
|
|
159
|
+
* first child is a list node, and merges adjacent same-type list nodes within a listItem.
|
|
160
|
+
* When platform_editor_flexible_list_indentation is on: only merges adjacent same-type list nodes.
|
|
161
|
+
*/
|
|
162
|
+
export function applyListNormalisationFixes(_ref) {
|
|
163
|
+
var tr = _ref.tr,
|
|
164
|
+
transactions = _ref.transactions,
|
|
165
|
+
doc = _ref.doc,
|
|
166
|
+
schema = _ref.schema;
|
|
167
|
+
var affectedLists = getAffectedListsFromTransactions(transactions, doc, schema);
|
|
168
|
+
if (affectedLists.size === 0) {
|
|
169
|
+
return tr;
|
|
170
|
+
}
|
|
171
|
+
var _schema$nodes2 = schema.nodes,
|
|
172
|
+
listItem = _schema$nodes2.listItem,
|
|
173
|
+
paragraph = _schema$nodes2.paragraph;
|
|
174
|
+
if (!listItem) {
|
|
175
|
+
return tr;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Process lists in reverse position order so fixes at higher positions
|
|
179
|
+
// don't shift the positions of fixes at lower positions.
|
|
180
|
+
var sortedEntries = _toConsumableArray(affectedLists.entries()).sort(function (_ref2, _ref3) {
|
|
181
|
+
var _ref4 = _slicedToArray(_ref2, 1),
|
|
182
|
+
posA = _ref4[0];
|
|
183
|
+
var _ref5 = _slicedToArray(_ref3, 1),
|
|
184
|
+
posB = _ref5[0];
|
|
185
|
+
return posB - posA;
|
|
186
|
+
});
|
|
187
|
+
var _iterator3 = _createForOfIteratorHelper(sortedEntries),
|
|
188
|
+
_step3;
|
|
189
|
+
try {
|
|
190
|
+
var _loop = function _loop() {
|
|
191
|
+
var _step3$value = _slicedToArray(_step3.value, 2),
|
|
192
|
+
listPos = _step3$value[0],
|
|
193
|
+
listNode = _step3$value[1];
|
|
194
|
+
// Collect listItem positions in document order, then process in reverse so that
|
|
195
|
+
// fixes at higher positions don't shift positions of fixes at lower positions.
|
|
196
|
+
var listItemPositions = [];
|
|
197
|
+
listNode.descendants(function (node, offsetPos) {
|
|
198
|
+
if (node.type === listItem) {
|
|
199
|
+
listItemPositions.push(listPos + 1 + offsetPos);
|
|
200
|
+
return false; // Don't descend — inner listItems are handled via their own ancestor list
|
|
201
|
+
}
|
|
202
|
+
return true;
|
|
203
|
+
});
|
|
204
|
+
for (var i = listItemPositions.length - 1; i >= 0; i--) {
|
|
205
|
+
var mappedPos = tr.mapping.map(listItemPositions[i]);
|
|
206
|
+
var node = tr.doc.nodeAt(mappedPos);
|
|
207
|
+
if (!node || node.type !== listItem) {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Merge adjacent same-type list nodes (highest boundary first within the listItem).
|
|
212
|
+
for (var j = node.childCount - 1; j > 0; j--) {
|
|
213
|
+
var child = node.child(j);
|
|
214
|
+
var prevChild = node.child(j - 1);
|
|
215
|
+
if (isListNode(child) && child.type === prevChild.type) {
|
|
216
|
+
var offset = 1; // +1 for listItem opening token
|
|
217
|
+
for (var k = 0; k < j; k++) {
|
|
218
|
+
offset += node.child(k).nodeSize;
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
tr.join(mappedPos + offset);
|
|
222
|
+
} catch (e) {
|
|
223
|
+
// join may fail if position is invalid after earlier transforms — skip
|
|
224
|
+
// eslint-disable-next-line no-console
|
|
225
|
+
console.warn('[editor-plugin-list] applyListNormalisationFixes: unexpected join failure', e);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Insert empty paragraph before list-first listItems when _indentation is off.
|
|
231
|
+
if (paragraph && !expValEquals('platform_editor_flexible_list_indentation', 'isEnabled', true)) {
|
|
232
|
+
var currentNode = tr.doc.nodeAt(mappedPos);
|
|
233
|
+
if (currentNode && currentNode.firstChild && currentNode.firstChild.type !== paragraph) {
|
|
234
|
+
var emptyParagraph = paragraph.createAndFill();
|
|
235
|
+
if (emptyParagraph) {
|
|
236
|
+
tr.insert(mappedPos + 1, emptyParagraph);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
243
|
+
_loop();
|
|
244
|
+
}
|
|
245
|
+
} catch (err) {
|
|
246
|
+
_iterator3.e(err);
|
|
247
|
+
} finally {
|
|
248
|
+
_iterator3.f();
|
|
249
|
+
}
|
|
250
|
+
return tr;
|
|
91
251
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { useIntl } from 'react-intl
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
3
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { listMessages } from '@atlaskit/editor-common/messages';
|
|
5
5
|
import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { useIntl } from 'react-intl
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
3
|
import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
4
4
|
import { listMessages } from '@atlaskit/editor-common/messages';
|
|
5
5
|
import { ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
|
|
@@ -2,8 +2,8 @@ import type { Dispatch } from '@atlaskit/editor-common/event-dispatcher';
|
|
|
2
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
3
|
import type { ExtractInjectionAPI, FeatureFlags } from '@atlaskit/editor-common/types';
|
|
4
4
|
import type { Node } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
-
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
5
|
import type { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
6
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
7
7
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
8
8
|
import type { ListPlugin } from '../listPluginType';
|
|
9
9
|
import type { ListState } from '../types';
|
|
@@ -1,4 +1,22 @@
|
|
|
1
|
+
import type { Node, Schema } from '@atlaskit/editor-prosemirror/model';
|
|
1
2
|
import type { Selection, Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
3
|
export declare function liftFollowingList(from: number, to: number, rootListDepth: number, tr: Transaction): Transaction;
|
|
3
4
|
export declare function liftNodeSelectionList(selection: Selection, tr: Transaction): Transaction;
|
|
4
5
|
export declare function liftTextSelectionList(selection: Selection, tr: Transaction): Transaction;
|
|
6
|
+
interface ApplyListNormalisationFixesOptions {
|
|
7
|
+
doc: Node;
|
|
8
|
+
schema: Schema;
|
|
9
|
+
tr: Transaction;
|
|
10
|
+
transactions: readonly Transaction[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Applies list normalisation fixes to the given transaction for all affected list subtrees.
|
|
14
|
+
* Processes nodes in reverse document order so that position offsets from insertions/joins
|
|
15
|
+
* do not affect earlier positions.
|
|
16
|
+
*
|
|
17
|
+
* When platform_editor_flexible_list_indentation is off: inserts an empty paragraph before any listItem whose
|
|
18
|
+
* first child is a list node, and merges adjacent same-type list nodes within a listItem.
|
|
19
|
+
* When platform_editor_flexible_list_indentation is on: only merges adjacent same-type list nodes.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyListNormalisationFixes({ tr, transactions, doc, schema, }: ApplyListNormalisationFixesOptions): Transaction;
|
|
22
|
+
export {};
|
|
@@ -2,8 +2,8 @@ import type { Dispatch } from '@atlaskit/editor-common/event-dispatcher';
|
|
|
2
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
3
|
import type { ExtractInjectionAPI, FeatureFlags } from '@atlaskit/editor-common/types';
|
|
4
4
|
import type { Node } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
-
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
5
|
import type { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
6
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
7
7
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
8
8
|
import type { ListPlugin } from '../listPluginType';
|
|
9
9
|
import type { ListState } from '../types';
|
|
@@ -1,4 +1,22 @@
|
|
|
1
|
+
import type { Node, Schema } from '@atlaskit/editor-prosemirror/model';
|
|
1
2
|
import type { Selection, Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
3
|
export declare function liftFollowingList(from: number, to: number, rootListDepth: number, tr: Transaction): Transaction;
|
|
3
4
|
export declare function liftNodeSelectionList(selection: Selection, tr: Transaction): Transaction;
|
|
4
5
|
export declare function liftTextSelectionList(selection: Selection, tr: Transaction): Transaction;
|
|
6
|
+
interface ApplyListNormalisationFixesOptions {
|
|
7
|
+
doc: Node;
|
|
8
|
+
schema: Schema;
|
|
9
|
+
tr: Transaction;
|
|
10
|
+
transactions: readonly Transaction[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Applies list normalisation fixes to the given transaction for all affected list subtrees.
|
|
14
|
+
* Processes nodes in reverse document order so that position offsets from insertions/joins
|
|
15
|
+
* do not affect earlier positions.
|
|
16
|
+
*
|
|
17
|
+
* When platform_editor_flexible_list_indentation is off: inserts an empty paragraph before any listItem whose
|
|
18
|
+
* first child is a list node, and merges adjacent same-type list nodes within a listItem.
|
|
19
|
+
* When platform_editor_flexible_list_indentation is on: only merges adjacent same-type list nodes.
|
|
20
|
+
*/
|
|
21
|
+
export declare function applyListNormalisationFixes({ tr, transactions, doc, schema, }: ApplyListNormalisationFixesOptions): Transaction;
|
|
22
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-list",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "List plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
"atlaskit:src": "src/index.ts",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@atlaskit/adf-schema": "^52.5.0",
|
|
31
|
-
"@atlaskit/editor-plugin-analytics": "^
|
|
32
|
-
"@atlaskit/editor-plugin-block-menu": "^
|
|
33
|
-
"@atlaskit/editor-plugin-feature-flags": "^
|
|
34
|
-
"@atlaskit/editor-plugin-toolbar": "^
|
|
31
|
+
"@atlaskit/editor-plugin-analytics": "^10.0.0",
|
|
32
|
+
"@atlaskit/editor-plugin-block-menu": "^9.0.0",
|
|
33
|
+
"@atlaskit/editor-plugin-feature-flags": "^9.0.0",
|
|
34
|
+
"@atlaskit/editor-plugin-toolbar": "^7.0.0",
|
|
35
35
|
"@atlaskit/editor-prosemirror": "^7.3.0",
|
|
36
|
-
"@atlaskit/editor-toolbar": "^0.
|
|
36
|
+
"@atlaskit/editor-toolbar": "^1.0.0",
|
|
37
37
|
"@atlaskit/icon": "^34.2.0",
|
|
38
38
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
39
39
|
"@atlaskit/prosemirror-history": "^0.2.0",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"@babel/runtime": "^7.0.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@atlaskit/editor-common": "^
|
|
45
|
+
"@atlaskit/editor-common": "^114.0.0",
|
|
46
46
|
"react": "^18.2.0",
|
|
47
|
-
"react-intl
|
|
47
|
+
"react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
|
|
48
48
|
},
|
|
49
49
|
"techstack": {
|
|
50
50
|
"@atlassian/frontend": {
|
|
@@ -93,5 +93,8 @@
|
|
|
93
93
|
"no-unused-dependencies": {
|
|
94
94
|
"checkDevDependencies": true
|
|
95
95
|
}
|
|
96
|
+
},
|
|
97
|
+
"devDependencies": {
|
|
98
|
+
"react-intl": "^6.6.2"
|
|
96
99
|
}
|
|
97
100
|
}
|