@atlaskit/editor-plugin-list 8.1.2 → 8.2.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
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-list
|
|
2
2
|
|
|
3
|
+
## 8.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`5167552fe1a93`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/5167552fe1a93) -
|
|
8
|
+
[EDITOR-2339] Bump @atlaskit/adf-schema to 51.3.0
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
|
|
14
|
+
## 8.1.3
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- [`8abe663d8d5db`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8abe663d8d5db) -
|
|
19
|
+
Add new list decorations logic
|
|
20
|
+
- Updated dependencies
|
|
21
|
+
|
|
3
22
|
## 8.1.2
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
|
@@ -330,7 +349,6 @@
|
|
|
330
349
|
shared context or singletons.
|
|
331
350
|
|
|
332
351
|
**HOW TO ADJUST:**
|
|
333
|
-
|
|
334
352
|
- Consumers must now explicitly install `@atlaskit/editor-common` in their own project if they use
|
|
335
353
|
any of these editor plugins.
|
|
336
354
|
- Ensure the version you install matches the version required by the plugins.
|
|
@@ -1008,7 +1026,6 @@
|
|
|
1008
1026
|
|
|
1009
1027
|
These are no longer available via `@atlaskit/prosemirror-input-rules` but are available from
|
|
1010
1028
|
`@atlaskit/editor-common/types`:
|
|
1011
|
-
|
|
1012
1029
|
- InputRuleWrapper
|
|
1013
1030
|
- InputRuleHandler
|
|
1014
1031
|
- OnHandlerApply
|
|
@@ -1018,7 +1035,6 @@
|
|
|
1018
1035
|
need to instantiate a `SafePlugin` (ie. `new SafePlugin(createPlugin( ... ))`).
|
|
1019
1036
|
|
|
1020
1037
|
`SafePlugin` exists in `@atlaskit/editor-common/safe-plugin`.
|
|
1021
|
-
|
|
1022
1038
|
- createPlugin
|
|
1023
1039
|
- createInputRulePlugin
|
|
1024
1040
|
|
|
@@ -1229,19 +1245,12 @@
|
|
|
1229
1245
|
auto-join lists together if the order numbers match up.
|
|
1230
1246
|
|
|
1231
1247
|
Eg.
|
|
1232
|
-
|
|
1233
1248
|
1. A list item
|
|
1234
|
-
|
|
1235
1249
|
-
|
|
1236
|
-
|
|
1237
1250
|
50. Another list item
|
|
1238
1251
|
|
|
1239
|
-
Should NOT auto join to be 1 & 2 in a single list however...
|
|
1240
|
-
|
|
1241
|
-
49. A list item
|
|
1242
|
-
|
|
1252
|
+
Should NOT auto join to be 1 & 2 in a single list however... 49. A list item
|
|
1243
1253
|
-
|
|
1244
|
-
|
|
1245
1254
|
50. Another list item
|
|
1246
1255
|
|
|
1247
1256
|
Should join to be 49 & 50 in a single list.
|
|
@@ -1263,7 +1272,6 @@
|
|
|
1263
1272
|
- [#43646](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43646)
|
|
1264
1273
|
[`d43f8e9402f`](https://bitbucket.org/atlassian/atlassian-frontend/commits/d43f8e9402f) - Make
|
|
1265
1274
|
feature flags plugin optional in all plugins including:
|
|
1266
|
-
|
|
1267
1275
|
- analytics
|
|
1268
1276
|
- base
|
|
1269
1277
|
- card
|
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.pluginKey = exports.getDecorations = exports.createPlugin = void 0;
|
|
7
|
+
exports.updateListDecorations = exports.pluginKey = exports.getDecorations = exports.createPlugin = exports.computeListDecorations = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
10
10
|
var _selection = require("@atlaskit/editor-common/selection");
|
|
@@ -13,6 +13,7 @@ var _utils = require("@atlaskit/editor-common/utils");
|
|
|
13
13
|
var _state = 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 _insm = require("@atlaskit/insm");
|
|
16
17
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
17
18
|
var _selection2 = require("./utils/selection");
|
|
18
19
|
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; }
|
|
@@ -26,6 +27,79 @@ var initialState = {
|
|
|
26
27
|
orderedListDisabled: false,
|
|
27
28
|
decorationSet: _view.DecorationSet.empty
|
|
28
29
|
};
|
|
30
|
+
var computeListDecorations = exports.computeListDecorations = function computeListDecorations(doc) {
|
|
31
|
+
var from = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
32
|
+
var to = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : doc.content.size;
|
|
33
|
+
var decorations = [];
|
|
34
|
+
|
|
35
|
+
// this stack keeps track of each (nested) list to calculate the indentation level
|
|
36
|
+
var processedListsStack = [];
|
|
37
|
+
doc.nodesBetween(from, to, function (node, currentNodeStartPos) {
|
|
38
|
+
if (processedListsStack.length > 0) {
|
|
39
|
+
var isOutsideLastList = true;
|
|
40
|
+
while (isOutsideLastList && processedListsStack.length > 0) {
|
|
41
|
+
var lastList = processedListsStack[processedListsStack.length - 1];
|
|
42
|
+
var lastListEndPos = lastList.startPos + lastList.node.nodeSize;
|
|
43
|
+
isOutsideLastList = currentNodeStartPos >= lastListEndPos;
|
|
44
|
+
// once we finish iterating over each innermost list, pop the stack to
|
|
45
|
+
// decrease the indent level attribute accordingly
|
|
46
|
+
if (isOutsideLastList) {
|
|
47
|
+
processedListsStack.pop();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if ((0, _utils.isListNode)(node)) {
|
|
52
|
+
processedListsStack.push({
|
|
53
|
+
node: node,
|
|
54
|
+
startPos: currentNodeStartPos
|
|
55
|
+
});
|
|
56
|
+
var _from = currentNodeStartPos;
|
|
57
|
+
var _to = currentNodeStartPos + node.nodeSize;
|
|
58
|
+
var depth = processedListsStack.length;
|
|
59
|
+
decorations.push(_view.Decoration.node(_from, _to, {
|
|
60
|
+
'data-indent-level': "".concat(depth)
|
|
61
|
+
}));
|
|
62
|
+
if (node.type.name === 'orderedList') {
|
|
63
|
+
var _node$attrs;
|
|
64
|
+
// If a numbered list has item counters numbering >= 100, we'll need to add special
|
|
65
|
+
// spacing to account for the extra digit chars
|
|
66
|
+
var digitsSize = (0, _utils.getItemCounterDigitsSize)({
|
|
67
|
+
itemsCount: node === null || node === void 0 ? void 0 : node.childCount,
|
|
68
|
+
order: node === null || node === void 0 || (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.order
|
|
69
|
+
});
|
|
70
|
+
if (digitsSize && digitsSize > 1) {
|
|
71
|
+
decorations.push(_view.Decoration.node(_from, _to, {
|
|
72
|
+
style: (0, _styles.getOrderedListInlineStyles)(digitsSize, 'string')
|
|
73
|
+
}));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return decorations;
|
|
79
|
+
};
|
|
80
|
+
var updateListDecorations = exports.updateListDecorations = function updateListDecorations(decorationSet, tr) {
|
|
81
|
+
var nextDecorationSet = decorationSet.map(tr.mapping, tr.doc);
|
|
82
|
+
tr.mapping.maps.forEach(function (stepMap, index) {
|
|
83
|
+
stepMap.forEach(function (oldStart, oldEnd) {
|
|
84
|
+
var start = tr.mapping.slice(index).map(oldStart, -1);
|
|
85
|
+
var end = tr.mapping.slice(index).map(oldEnd);
|
|
86
|
+
|
|
87
|
+
// Remove decorations in this range
|
|
88
|
+
var decorationsToRemove = nextDecorationSet.find(start, end);
|
|
89
|
+
nextDecorationSet = nextDecorationSet.remove(decorationsToRemove);
|
|
90
|
+
|
|
91
|
+
// Recompute decorations for this range
|
|
92
|
+
// Expand the range by 1 on each side to catch adjacent list nodes
|
|
93
|
+
var from = Math.max(0, start - 1);
|
|
94
|
+
var to = Math.min(tr.doc.content.size, end + 1);
|
|
95
|
+
var decorationsToAdd = computeListDecorations(tr.doc, from, to);
|
|
96
|
+
nextDecorationSet = nextDecorationSet.add(tr.doc, decorationsToAdd);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
return nextDecorationSet;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// delete getDecorations during platform_editor_new_list_decorations_logic experiment clean up
|
|
29
103
|
var getDecorations = exports.getDecorations = function getDecorations(doc, state, featureFlags) {
|
|
30
104
|
var decorations = [];
|
|
31
105
|
|
|
@@ -57,12 +131,12 @@ var getDecorations = exports.getDecorations = function getDecorations(doc, state
|
|
|
57
131
|
'data-indent-level': "".concat(depth)
|
|
58
132
|
}));
|
|
59
133
|
if (node.type.name === 'orderedList') {
|
|
60
|
-
var _node$
|
|
134
|
+
var _node$attrs2;
|
|
61
135
|
// If a numbered list has item counters numbering >= 100, we'll need to add special
|
|
62
136
|
// spacing to account for the extra digit chars
|
|
63
137
|
var digitsSize = (0, _utils.getItemCounterDigitsSize)({
|
|
64
138
|
itemsCount: node === null || node === void 0 ? void 0 : node.childCount,
|
|
65
|
-
order: node === null || node === void 0 || (_node$
|
|
139
|
+
order: node === null || node === void 0 || (_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.order
|
|
66
140
|
});
|
|
67
141
|
if (digitsSize && digitsSize > 1) {
|
|
68
142
|
decorations.push(_view.Decoration.node(from, to, {
|
|
@@ -125,8 +199,15 @@ var reducer = function reducer() {
|
|
|
125
199
|
var createInitialState = function createInitialState(featureFlags, api) {
|
|
126
200
|
return function (state) {
|
|
127
201
|
var isToolbarAIFCEnabled = Boolean(api === null || api === void 0 ? void 0 : api.toolbar);
|
|
202
|
+
var getInitialDecorations = function getInitialDecorations() {
|
|
203
|
+
var _insm$session, _insm$session2;
|
|
204
|
+
(_insm$session = _insm.insm.session) === null || _insm$session === void 0 || _insm$session.startFeature('listDecorationsInit');
|
|
205
|
+
var decorations = computeListDecorations(state.doc);
|
|
206
|
+
(_insm$session2 = _insm.insm.session) === null || _insm$session2 === void 0 || _insm$session2.endFeature('listDecorationsInit');
|
|
207
|
+
return decorations;
|
|
208
|
+
};
|
|
128
209
|
return _objectSpread(_objectSpread({}, isToolbarAIFCEnabled && (0, _expValEquals.expValEquals)('platform_editor_toolbar_aifc_patch_3', 'isEnabled', true) ? getListState(state.doc, state.selection) : initialState), {}, {
|
|
129
|
-
decorationSet: getDecorations(state.doc, state, featureFlags)
|
|
210
|
+
decorationSet: (0, _expValEquals.expValEquals)('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? _view.DecorationSet.empty.add(state.doc, getInitialDecorations()) : getDecorations(state.doc, state, featureFlags)
|
|
130
211
|
});
|
|
131
212
|
};
|
|
132
213
|
};
|
|
@@ -137,13 +218,39 @@ var createPlugin = exports.createPlugin = function createPlugin(eventDispatch, f
|
|
|
137
218
|
}),
|
|
138
219
|
getPluginState = _pluginFactory.getPluginState,
|
|
139
220
|
createPluginState = _pluginFactory.createPluginState;
|
|
221
|
+
var pluginState = createPluginState(eventDispatch, createInitialState(featureFlags, api));
|
|
222
|
+
var pluginStateInit = function pluginStateInit(_, state) {
|
|
223
|
+
return createInitialState(featureFlags)(state);
|
|
224
|
+
};
|
|
225
|
+
var pluginStateApply = function pluginStateApply(tr, oldPluginState, _oldEditorState, _newEditorState) {
|
|
226
|
+
var nextPluginState = oldPluginState;
|
|
227
|
+
if (tr.docChanged) {
|
|
228
|
+
var _insm$session3, _insm$session4;
|
|
229
|
+
nextPluginState = handleSelectionChanged(tr, nextPluginState);
|
|
230
|
+
(_insm$session3 = _insm.insm.session) === null || _insm$session3 === void 0 || _insm$session3.startFeature('listDecorationUpdate');
|
|
231
|
+
var nextDecorationSet = updateListDecorations(nextPluginState.decorationSet, tr);
|
|
232
|
+
(_insm$session4 = _insm.insm.session) === null || _insm$session4 === void 0 || _insm$session4.endFeature('listDecorationUpdate');
|
|
233
|
+
nextPluginState = _objectSpread(_objectSpread({}, nextPluginState), {}, {
|
|
234
|
+
decorationSet: nextDecorationSet
|
|
235
|
+
});
|
|
236
|
+
} else if (tr.selectionSet) {
|
|
237
|
+
nextPluginState = handleSelectionChanged(tr, nextPluginState);
|
|
238
|
+
}
|
|
239
|
+
if (nextPluginState !== oldPluginState) {
|
|
240
|
+
eventDispatch(listPluginKey, nextPluginState);
|
|
241
|
+
}
|
|
242
|
+
return nextPluginState;
|
|
243
|
+
};
|
|
140
244
|
return new _safePlugin.SafePlugin({
|
|
141
|
-
state:
|
|
245
|
+
state: {
|
|
246
|
+
init: (0, _expValEquals.expValEquals)('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateInit : pluginState.init,
|
|
247
|
+
apply: (0, _expValEquals.expValEquals)('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateApply : pluginState.apply
|
|
248
|
+
},
|
|
142
249
|
key: listPluginKey,
|
|
143
250
|
props: {
|
|
144
251
|
decorations: function decorations(state) {
|
|
145
|
-
var
|
|
146
|
-
decorationSet =
|
|
252
|
+
var _ref = (0, _expValEquals.expValEquals)('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? listPluginKey.getState(state) : getPluginState(state),
|
|
253
|
+
decorationSet = _ref.decorationSet;
|
|
147
254
|
return decorationSet;
|
|
148
255
|
},
|
|
149
256
|
handleClick: function handleClick(view, pos, event) {
|
|
@@ -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 { insm } from '@atlaskit/insm';
|
|
8
9
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
9
10
|
import { isWrappingPossible } from './utils/selection';
|
|
10
11
|
const listPluginKey = new PluginKey('listPlugin');
|
|
@@ -16,12 +17,12 @@ const initialState = {
|
|
|
16
17
|
orderedListDisabled: false,
|
|
17
18
|
decorationSet: DecorationSet.empty
|
|
18
19
|
};
|
|
19
|
-
export const
|
|
20
|
+
export const computeListDecorations = (doc, from = 0, to = doc.content.size) => {
|
|
20
21
|
const decorations = [];
|
|
21
22
|
|
|
22
23
|
// this stack keeps track of each (nested) list to calculate the indentation level
|
|
23
24
|
const processedListsStack = [];
|
|
24
|
-
doc.nodesBetween(
|
|
25
|
+
doc.nodesBetween(from, to, (node, currentNodeStartPos) => {
|
|
25
26
|
if (processedListsStack.length > 0) {
|
|
26
27
|
let isOutsideLastList = true;
|
|
27
28
|
while (isOutsideLastList && processedListsStack.length > 0) {
|
|
@@ -62,6 +63,77 @@ export const getDecorations = (doc, state, featureFlags) => {
|
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
});
|
|
66
|
+
return decorations;
|
|
67
|
+
};
|
|
68
|
+
export const updateListDecorations = (decorationSet, tr) => {
|
|
69
|
+
let nextDecorationSet = decorationSet.map(tr.mapping, tr.doc);
|
|
70
|
+
tr.mapping.maps.forEach((stepMap, index) => {
|
|
71
|
+
stepMap.forEach((oldStart, oldEnd) => {
|
|
72
|
+
const start = tr.mapping.slice(index).map(oldStart, -1);
|
|
73
|
+
const end = tr.mapping.slice(index).map(oldEnd);
|
|
74
|
+
|
|
75
|
+
// Remove decorations in this range
|
|
76
|
+
const decorationsToRemove = nextDecorationSet.find(start, end);
|
|
77
|
+
nextDecorationSet = nextDecorationSet.remove(decorationsToRemove);
|
|
78
|
+
|
|
79
|
+
// Recompute decorations for this range
|
|
80
|
+
// Expand the range by 1 on each side to catch adjacent list nodes
|
|
81
|
+
const from = Math.max(0, start - 1);
|
|
82
|
+
const to = Math.min(tr.doc.content.size, end + 1);
|
|
83
|
+
const decorationsToAdd = computeListDecorations(tr.doc, from, to);
|
|
84
|
+
nextDecorationSet = nextDecorationSet.add(tr.doc, decorationsToAdd);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
return nextDecorationSet;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// delete getDecorations during platform_editor_new_list_decorations_logic experiment clean up
|
|
91
|
+
export const getDecorations = (doc, state, featureFlags) => {
|
|
92
|
+
const decorations = [];
|
|
93
|
+
|
|
94
|
+
// this stack keeps track of each (nested) list to calculate the indentation level
|
|
95
|
+
const processedListsStack = [];
|
|
96
|
+
doc.nodesBetween(0, doc.content.size, (node, currentNodeStartPos) => {
|
|
97
|
+
if (processedListsStack.length > 0) {
|
|
98
|
+
let isOutsideLastList = true;
|
|
99
|
+
while (isOutsideLastList && processedListsStack.length > 0) {
|
|
100
|
+
const lastList = processedListsStack[processedListsStack.length - 1];
|
|
101
|
+
const lastListEndPos = lastList.startPos + lastList.node.nodeSize;
|
|
102
|
+
isOutsideLastList = currentNodeStartPos >= lastListEndPos;
|
|
103
|
+
// once we finish iterating over each innermost list, pop the stack to
|
|
104
|
+
// decrease the indent level attribute accordingly
|
|
105
|
+
if (isOutsideLastList) {
|
|
106
|
+
processedListsStack.pop();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (isListNode(node)) {
|
|
111
|
+
processedListsStack.push({
|
|
112
|
+
node,
|
|
113
|
+
startPos: currentNodeStartPos
|
|
114
|
+
});
|
|
115
|
+
const from = currentNodeStartPos;
|
|
116
|
+
const to = currentNodeStartPos + node.nodeSize;
|
|
117
|
+
const depth = processedListsStack.length;
|
|
118
|
+
decorations.push(Decoration.node(from, to, {
|
|
119
|
+
'data-indent-level': `${depth}`
|
|
120
|
+
}));
|
|
121
|
+
if (node.type.name === 'orderedList') {
|
|
122
|
+
var _node$attrs2;
|
|
123
|
+
// If a numbered list has item counters numbering >= 100, we'll need to add special
|
|
124
|
+
// spacing to account for the extra digit chars
|
|
125
|
+
const digitsSize = getItemCounterDigitsSize({
|
|
126
|
+
itemsCount: node === null || node === void 0 ? void 0 : node.childCount,
|
|
127
|
+
order: node === null || node === void 0 ? void 0 : (_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.order
|
|
128
|
+
});
|
|
129
|
+
if (digitsSize && digitsSize > 1) {
|
|
130
|
+
decorations.push(Decoration.node(from, to, {
|
|
131
|
+
style: getOrderedListInlineStyles(digitsSize, 'string')
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
65
137
|
return DecorationSet.empty.add(doc, decorations);
|
|
66
138
|
};
|
|
67
139
|
const getListState = (doc, selection) => {
|
|
@@ -114,11 +186,18 @@ const reducer = () => state => {
|
|
|
114
186
|
};
|
|
115
187
|
const createInitialState = (featureFlags, api) => state => {
|
|
116
188
|
const isToolbarAIFCEnabled = Boolean(api === null || api === void 0 ? void 0 : api.toolbar);
|
|
189
|
+
const getInitialDecorations = () => {
|
|
190
|
+
var _insm$session, _insm$session2;
|
|
191
|
+
(_insm$session = insm.session) === null || _insm$session === void 0 ? void 0 : _insm$session.startFeature('listDecorationsInit');
|
|
192
|
+
const decorations = computeListDecorations(state.doc);
|
|
193
|
+
(_insm$session2 = insm.session) === null || _insm$session2 === void 0 ? void 0 : _insm$session2.endFeature('listDecorationsInit');
|
|
194
|
+
return decorations;
|
|
195
|
+
};
|
|
117
196
|
return {
|
|
118
197
|
// When plugin is initialised, editor state is defined with selection
|
|
119
198
|
// hence returning the list state based on the selection to avoid list button in primary toolbar flickering during initial load
|
|
120
199
|
...(isToolbarAIFCEnabled && expValEquals('platform_editor_toolbar_aifc_patch_3', 'isEnabled', true) ? getListState(state.doc, state.selection) : initialState),
|
|
121
|
-
decorationSet: getDecorations(state.doc, state, featureFlags)
|
|
200
|
+
decorationSet: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? DecorationSet.empty.add(state.doc, getInitialDecorations()) : getDecorations(state.doc, state, featureFlags)
|
|
122
201
|
};
|
|
123
202
|
};
|
|
124
203
|
export const createPlugin = (eventDispatch, featureFlags, api) => {
|
|
@@ -129,14 +208,41 @@ export const createPlugin = (eventDispatch, featureFlags, api) => {
|
|
|
129
208
|
onDocChanged: handleDocChanged(featureFlags),
|
|
130
209
|
onSelectionChanged: handleSelectionChanged
|
|
131
210
|
});
|
|
211
|
+
const pluginState = createPluginState(eventDispatch, createInitialState(featureFlags, api));
|
|
212
|
+
const pluginStateInit = (_, state) => {
|
|
213
|
+
return createInitialState(featureFlags)(state);
|
|
214
|
+
};
|
|
215
|
+
const pluginStateApply = (tr, oldPluginState, _oldEditorState, _newEditorState) => {
|
|
216
|
+
let nextPluginState = oldPluginState;
|
|
217
|
+
if (tr.docChanged) {
|
|
218
|
+
var _insm$session3, _insm$session4;
|
|
219
|
+
nextPluginState = handleSelectionChanged(tr, nextPluginState);
|
|
220
|
+
(_insm$session3 = insm.session) === null || _insm$session3 === void 0 ? void 0 : _insm$session3.startFeature('listDecorationUpdate');
|
|
221
|
+
const nextDecorationSet = updateListDecorations(nextPluginState.decorationSet, tr);
|
|
222
|
+
(_insm$session4 = insm.session) === null || _insm$session4 === void 0 ? void 0 : _insm$session4.endFeature('listDecorationUpdate');
|
|
223
|
+
nextPluginState = {
|
|
224
|
+
...nextPluginState,
|
|
225
|
+
decorationSet: nextDecorationSet
|
|
226
|
+
};
|
|
227
|
+
} else if (tr.selectionSet) {
|
|
228
|
+
nextPluginState = handleSelectionChanged(tr, nextPluginState);
|
|
229
|
+
}
|
|
230
|
+
if (nextPluginState !== oldPluginState) {
|
|
231
|
+
eventDispatch(listPluginKey, nextPluginState);
|
|
232
|
+
}
|
|
233
|
+
return nextPluginState;
|
|
234
|
+
};
|
|
132
235
|
return new SafePlugin({
|
|
133
|
-
state:
|
|
236
|
+
state: {
|
|
237
|
+
init: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateInit : pluginState.init,
|
|
238
|
+
apply: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateApply : pluginState.apply
|
|
239
|
+
},
|
|
134
240
|
key: listPluginKey,
|
|
135
241
|
props: {
|
|
136
242
|
decorations(state) {
|
|
137
243
|
const {
|
|
138
244
|
decorationSet
|
|
139
|
-
} = getPluginState(state);
|
|
245
|
+
} = expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? listPluginKey.getState(state) : getPluginState(state);
|
|
140
246
|
return decorationSet;
|
|
141
247
|
},
|
|
142
248
|
handleClick: (view, pos, event) => {
|
|
@@ -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 { insm } from '@atlaskit/insm';
|
|
11
12
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
12
13
|
import { isWrappingPossible } from './utils/selection';
|
|
13
14
|
var listPluginKey = new PluginKey('listPlugin');
|
|
@@ -19,6 +20,79 @@ var initialState = {
|
|
|
19
20
|
orderedListDisabled: false,
|
|
20
21
|
decorationSet: DecorationSet.empty
|
|
21
22
|
};
|
|
23
|
+
export var computeListDecorations = function computeListDecorations(doc) {
|
|
24
|
+
var from = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
25
|
+
var to = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : doc.content.size;
|
|
26
|
+
var decorations = [];
|
|
27
|
+
|
|
28
|
+
// this stack keeps track of each (nested) list to calculate the indentation level
|
|
29
|
+
var processedListsStack = [];
|
|
30
|
+
doc.nodesBetween(from, to, function (node, currentNodeStartPos) {
|
|
31
|
+
if (processedListsStack.length > 0) {
|
|
32
|
+
var isOutsideLastList = true;
|
|
33
|
+
while (isOutsideLastList && processedListsStack.length > 0) {
|
|
34
|
+
var lastList = processedListsStack[processedListsStack.length - 1];
|
|
35
|
+
var lastListEndPos = lastList.startPos + lastList.node.nodeSize;
|
|
36
|
+
isOutsideLastList = currentNodeStartPos >= lastListEndPos;
|
|
37
|
+
// once we finish iterating over each innermost list, pop the stack to
|
|
38
|
+
// decrease the indent level attribute accordingly
|
|
39
|
+
if (isOutsideLastList) {
|
|
40
|
+
processedListsStack.pop();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (isListNode(node)) {
|
|
45
|
+
processedListsStack.push({
|
|
46
|
+
node: node,
|
|
47
|
+
startPos: currentNodeStartPos
|
|
48
|
+
});
|
|
49
|
+
var _from = currentNodeStartPos;
|
|
50
|
+
var _to = currentNodeStartPos + node.nodeSize;
|
|
51
|
+
var depth = processedListsStack.length;
|
|
52
|
+
decorations.push(Decoration.node(_from, _to, {
|
|
53
|
+
'data-indent-level': "".concat(depth)
|
|
54
|
+
}));
|
|
55
|
+
if (node.type.name === 'orderedList') {
|
|
56
|
+
var _node$attrs;
|
|
57
|
+
// If a numbered list has item counters numbering >= 100, we'll need to add special
|
|
58
|
+
// spacing to account for the extra digit chars
|
|
59
|
+
var digitsSize = getItemCounterDigitsSize({
|
|
60
|
+
itemsCount: node === null || node === void 0 ? void 0 : node.childCount,
|
|
61
|
+
order: node === null || node === void 0 || (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.order
|
|
62
|
+
});
|
|
63
|
+
if (digitsSize && digitsSize > 1) {
|
|
64
|
+
decorations.push(Decoration.node(_from, _to, {
|
|
65
|
+
style: getOrderedListInlineStyles(digitsSize, 'string')
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return decorations;
|
|
72
|
+
};
|
|
73
|
+
export var updateListDecorations = function updateListDecorations(decorationSet, tr) {
|
|
74
|
+
var nextDecorationSet = decorationSet.map(tr.mapping, tr.doc);
|
|
75
|
+
tr.mapping.maps.forEach(function (stepMap, index) {
|
|
76
|
+
stepMap.forEach(function (oldStart, oldEnd) {
|
|
77
|
+
var start = tr.mapping.slice(index).map(oldStart, -1);
|
|
78
|
+
var end = tr.mapping.slice(index).map(oldEnd);
|
|
79
|
+
|
|
80
|
+
// Remove decorations in this range
|
|
81
|
+
var decorationsToRemove = nextDecorationSet.find(start, end);
|
|
82
|
+
nextDecorationSet = nextDecorationSet.remove(decorationsToRemove);
|
|
83
|
+
|
|
84
|
+
// Recompute decorations for this range
|
|
85
|
+
// Expand the range by 1 on each side to catch adjacent list nodes
|
|
86
|
+
var from = Math.max(0, start - 1);
|
|
87
|
+
var to = Math.min(tr.doc.content.size, end + 1);
|
|
88
|
+
var decorationsToAdd = computeListDecorations(tr.doc, from, to);
|
|
89
|
+
nextDecorationSet = nextDecorationSet.add(tr.doc, decorationsToAdd);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
return nextDecorationSet;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// delete getDecorations during platform_editor_new_list_decorations_logic experiment clean up
|
|
22
96
|
export var getDecorations = function getDecorations(doc, state, featureFlags) {
|
|
23
97
|
var decorations = [];
|
|
24
98
|
|
|
@@ -50,12 +124,12 @@ export var getDecorations = function getDecorations(doc, state, featureFlags) {
|
|
|
50
124
|
'data-indent-level': "".concat(depth)
|
|
51
125
|
}));
|
|
52
126
|
if (node.type.name === 'orderedList') {
|
|
53
|
-
var _node$
|
|
127
|
+
var _node$attrs2;
|
|
54
128
|
// If a numbered list has item counters numbering >= 100, we'll need to add special
|
|
55
129
|
// spacing to account for the extra digit chars
|
|
56
130
|
var digitsSize = getItemCounterDigitsSize({
|
|
57
131
|
itemsCount: node === null || node === void 0 ? void 0 : node.childCount,
|
|
58
|
-
order: node === null || node === void 0 || (_node$
|
|
132
|
+
order: node === null || node === void 0 || (_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.order
|
|
59
133
|
});
|
|
60
134
|
if (digitsSize && digitsSize > 1) {
|
|
61
135
|
decorations.push(Decoration.node(from, to, {
|
|
@@ -118,8 +192,15 @@ var reducer = function reducer() {
|
|
|
118
192
|
var createInitialState = function createInitialState(featureFlags, api) {
|
|
119
193
|
return function (state) {
|
|
120
194
|
var isToolbarAIFCEnabled = Boolean(api === null || api === void 0 ? void 0 : api.toolbar);
|
|
195
|
+
var getInitialDecorations = function getInitialDecorations() {
|
|
196
|
+
var _insm$session, _insm$session2;
|
|
197
|
+
(_insm$session = insm.session) === null || _insm$session === void 0 || _insm$session.startFeature('listDecorationsInit');
|
|
198
|
+
var decorations = computeListDecorations(state.doc);
|
|
199
|
+
(_insm$session2 = insm.session) === null || _insm$session2 === void 0 || _insm$session2.endFeature('listDecorationsInit');
|
|
200
|
+
return decorations;
|
|
201
|
+
};
|
|
121
202
|
return _objectSpread(_objectSpread({}, isToolbarAIFCEnabled && expValEquals('platform_editor_toolbar_aifc_patch_3', 'isEnabled', true) ? getListState(state.doc, state.selection) : initialState), {}, {
|
|
122
|
-
decorationSet: getDecorations(state.doc, state, featureFlags)
|
|
203
|
+
decorationSet: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? DecorationSet.empty.add(state.doc, getInitialDecorations()) : getDecorations(state.doc, state, featureFlags)
|
|
123
204
|
});
|
|
124
205
|
};
|
|
125
206
|
};
|
|
@@ -130,13 +211,39 @@ export var createPlugin = function createPlugin(eventDispatch, featureFlags, api
|
|
|
130
211
|
}),
|
|
131
212
|
getPluginState = _pluginFactory.getPluginState,
|
|
132
213
|
createPluginState = _pluginFactory.createPluginState;
|
|
214
|
+
var pluginState = createPluginState(eventDispatch, createInitialState(featureFlags, api));
|
|
215
|
+
var pluginStateInit = function pluginStateInit(_, state) {
|
|
216
|
+
return createInitialState(featureFlags)(state);
|
|
217
|
+
};
|
|
218
|
+
var pluginStateApply = function pluginStateApply(tr, oldPluginState, _oldEditorState, _newEditorState) {
|
|
219
|
+
var nextPluginState = oldPluginState;
|
|
220
|
+
if (tr.docChanged) {
|
|
221
|
+
var _insm$session3, _insm$session4;
|
|
222
|
+
nextPluginState = handleSelectionChanged(tr, nextPluginState);
|
|
223
|
+
(_insm$session3 = insm.session) === null || _insm$session3 === void 0 || _insm$session3.startFeature('listDecorationUpdate');
|
|
224
|
+
var nextDecorationSet = updateListDecorations(nextPluginState.decorationSet, tr);
|
|
225
|
+
(_insm$session4 = insm.session) === null || _insm$session4 === void 0 || _insm$session4.endFeature('listDecorationUpdate');
|
|
226
|
+
nextPluginState = _objectSpread(_objectSpread({}, nextPluginState), {}, {
|
|
227
|
+
decorationSet: nextDecorationSet
|
|
228
|
+
});
|
|
229
|
+
} else if (tr.selectionSet) {
|
|
230
|
+
nextPluginState = handleSelectionChanged(tr, nextPluginState);
|
|
231
|
+
}
|
|
232
|
+
if (nextPluginState !== oldPluginState) {
|
|
233
|
+
eventDispatch(listPluginKey, nextPluginState);
|
|
234
|
+
}
|
|
235
|
+
return nextPluginState;
|
|
236
|
+
};
|
|
133
237
|
return new SafePlugin({
|
|
134
|
-
state:
|
|
238
|
+
state: {
|
|
239
|
+
init: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateInit : pluginState.init,
|
|
240
|
+
apply: expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? pluginStateApply : pluginState.apply
|
|
241
|
+
},
|
|
135
242
|
key: listPluginKey,
|
|
136
243
|
props: {
|
|
137
244
|
decorations: function decorations(state) {
|
|
138
|
-
var
|
|
139
|
-
decorationSet =
|
|
245
|
+
var _ref = expValEquals('platform_editor_new_list_decorations_logic', 'isEnabled', true) ? listPluginKey.getState(state) : getPluginState(state),
|
|
246
|
+
decorationSet = _ref.decorationSet;
|
|
140
247
|
return decorationSet;
|
|
141
248
|
},
|
|
142
249
|
handleClick: function handleClick(view, pos, event) {
|
|
@@ -3,10 +3,12 @@ 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
5
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
|
-
import type { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
-
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
6
|
+
import type { EditorState, ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
+
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
8
8
|
import type { ListPlugin } from '../listPluginType';
|
|
9
9
|
import type { ListState } from '../types';
|
|
10
10
|
export declare const pluginKey: PluginKey<ListState>;
|
|
11
|
+
export declare const computeListDecorations: (doc: Node, from?: number, to?: number) => Decoration[];
|
|
12
|
+
export declare const updateListDecorations: (decorationSet: DecorationSet, tr: ReadonlyTransaction) => DecorationSet;
|
|
11
13
|
export declare const getDecorations: (doc: Node, state: EditorState, featureFlags: FeatureFlags) => DecorationSet;
|
|
12
14
|
export declare const createPlugin: (eventDispatch: Dispatch, featureFlags: FeatureFlags, api?: ExtractInjectionAPI<ListPlugin>) => SafePlugin;
|
|
@@ -3,10 +3,12 @@ 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
5
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
|
-
import type { EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
-
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
6
|
+
import type { EditorState, ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
+
import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
8
8
|
import type { ListPlugin } from '../listPluginType';
|
|
9
9
|
import type { ListState } from '../types';
|
|
10
10
|
export declare const pluginKey: PluginKey<ListState>;
|
|
11
|
+
export declare const computeListDecorations: (doc: Node, from?: number, to?: number) => Decoration[];
|
|
12
|
+
export declare const updateListDecorations: (decorationSet: DecorationSet, tr: ReadonlyTransaction) => DecorationSet;
|
|
11
13
|
export declare const getDecorations: (doc: Node, state: EditorState, featureFlags: FeatureFlags) => DecorationSet;
|
|
12
14
|
export declare const createPlugin: (eventDispatch: Dispatch, featureFlags: FeatureFlags, api?: ExtractInjectionAPI<ListPlugin>) => SafePlugin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-list",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.2.0",
|
|
4
4
|
"description": "List plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -27,22 +27,23 @@
|
|
|
27
27
|
"sideEffects": false,
|
|
28
28
|
"atlaskit:src": "src/index.ts",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@atlaskit/adf-schema": "^51.
|
|
31
|
-
"@atlaskit/editor-plugin-analytics": "^6.
|
|
30
|
+
"@atlaskit/adf-schema": "^51.3.0",
|
|
31
|
+
"@atlaskit/editor-plugin-analytics": "^6.2.0",
|
|
32
32
|
"@atlaskit/editor-plugin-block-menu": "^4.0.0",
|
|
33
33
|
"@atlaskit/editor-plugin-feature-flags": "^5.0.0",
|
|
34
|
-
"@atlaskit/editor-plugin-toolbar": "^3.
|
|
34
|
+
"@atlaskit/editor-plugin-toolbar": "^3.3.0",
|
|
35
35
|
"@atlaskit/editor-prosemirror": "7.0.0",
|
|
36
36
|
"@atlaskit/editor-toolbar": "^0.15.0",
|
|
37
37
|
"@atlaskit/icon": "^28.5.0",
|
|
38
|
+
"@atlaskit/insm": "^0.1.0",
|
|
38
39
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
39
40
|
"@atlaskit/prosemirror-history": "^0.2.0",
|
|
40
41
|
"@atlaskit/prosemirror-input-rules": "^3.5.0",
|
|
41
|
-
"@atlaskit/tmp-editor-statsig": "^13.
|
|
42
|
+
"@atlaskit/tmp-editor-statsig": "^13.13.0",
|
|
42
43
|
"@babel/runtime": "^7.0.0"
|
|
43
44
|
},
|
|
44
45
|
"peerDependencies": {
|
|
45
|
-
"@atlaskit/editor-common": "^110.
|
|
46
|
+
"@atlaskit/editor-common": "^110.14.0",
|
|
46
47
|
"react": "^18.2.0",
|
|
47
48
|
"react-intl-next": "npm:react-intl@^5.18.1"
|
|
48
49
|
},
|