@atlaskit/editor-plugin-list 8.1.2 → 8.1.3
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,13 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-list
|
|
2
2
|
|
|
3
|
+
## 8.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`8abe663d8d5db`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8abe663d8d5db) -
|
|
8
|
+
Add new list decorations logic
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
|
|
3
11
|
## 8.1.2
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
|
@@ -330,7 +338,6 @@
|
|
|
330
338
|
shared context or singletons.
|
|
331
339
|
|
|
332
340
|
**HOW TO ADJUST:**
|
|
333
|
-
|
|
334
341
|
- Consumers must now explicitly install `@atlaskit/editor-common` in their own project if they use
|
|
335
342
|
any of these editor plugins.
|
|
336
343
|
- Ensure the version you install matches the version required by the plugins.
|
|
@@ -1008,7 +1015,6 @@
|
|
|
1008
1015
|
|
|
1009
1016
|
These are no longer available via `@atlaskit/prosemirror-input-rules` but are available from
|
|
1010
1017
|
`@atlaskit/editor-common/types`:
|
|
1011
|
-
|
|
1012
1018
|
- InputRuleWrapper
|
|
1013
1019
|
- InputRuleHandler
|
|
1014
1020
|
- OnHandlerApply
|
|
@@ -1018,7 +1024,6 @@
|
|
|
1018
1024
|
need to instantiate a `SafePlugin` (ie. `new SafePlugin(createPlugin( ... ))`).
|
|
1019
1025
|
|
|
1020
1026
|
`SafePlugin` exists in `@atlaskit/editor-common/safe-plugin`.
|
|
1021
|
-
|
|
1022
1027
|
- createPlugin
|
|
1023
1028
|
- createInputRulePlugin
|
|
1024
1029
|
|
|
@@ -1229,19 +1234,13 @@
|
|
|
1229
1234
|
auto-join lists together if the order numbers match up.
|
|
1230
1235
|
|
|
1231
1236
|
Eg.
|
|
1232
|
-
|
|
1233
1237
|
1. A list item
|
|
1234
|
-
|
|
1235
1238
|
-
|
|
1236
|
-
|
|
1237
1239
|
50. Another list item
|
|
1238
1240
|
|
|
1239
1241
|
Should NOT auto join to be 1 & 2 in a single list however...
|
|
1240
|
-
|
|
1241
1242
|
49. A list item
|
|
1242
|
-
|
|
1243
1243
|
-
|
|
1244
|
-
|
|
1245
1244
|
50. Another list item
|
|
1246
1245
|
|
|
1247
1246
|
Should join to be 49 & 50 in a single list.
|
|
@@ -1263,7 +1262,6 @@
|
|
|
1263
1262
|
- [#43646](https://bitbucket.org/atlassian/atlassian-frontend/pull-requests/43646)
|
|
1264
1263
|
[`d43f8e9402f`](https://bitbucket.org/atlassian/atlassian-frontend/commits/d43f8e9402f) - Make
|
|
1265
1264
|
feature flags plugin optional in all plugins including:
|
|
1266
|
-
|
|
1267
1265
|
- analytics
|
|
1268
1266
|
- base
|
|
1269
1267
|
- 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.1.
|
|
3
|
+
"version": "8.1.3",
|
|
4
4
|
"description": "List plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,18 +31,19 @@
|
|
|
31
31
|
"@atlaskit/editor-plugin-analytics": "^6.1.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.12.0",
|
|
42
43
|
"@babel/runtime": "^7.0.0"
|
|
43
44
|
},
|
|
44
45
|
"peerDependencies": {
|
|
45
|
-
"@atlaskit/editor-common": "^110.
|
|
46
|
+
"@atlaskit/editor-common": "^110.13.0",
|
|
46
47
|
"react": "^18.2.0",
|
|
47
48
|
"react-intl-next": "npm:react-intl@^5.18.1"
|
|
48
49
|
},
|