@atlaskit/editor-plugin-code-block 3.3.8 → 3.3.10
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 +16 -0
- package/dist/cjs/nodeviews/code-block.js +14 -6
- package/dist/cjs/pm-plugins/decorators.js +110 -5
- package/dist/cjs/pm-plugins/main.js +13 -63
- package/dist/cjs/toolbar.js +0 -1
- package/dist/cjs/utils.js +15 -0
- package/dist/es2019/nodeviews/code-block.js +14 -6
- package/dist/es2019/pm-plugins/decorators.js +106 -3
- package/dist/es2019/pm-plugins/main.js +17 -61
- package/dist/es2019/toolbar.js +0 -1
- package/dist/es2019/utils.js +14 -0
- package/dist/esm/nodeviews/code-block.js +15 -7
- package/dist/esm/pm-plugins/decorators.js +109 -4
- package/dist/esm/pm-plugins/main.js +14 -64
- package/dist/esm/toolbar.js +0 -1
- package/dist/esm/utils.js +14 -0
- package/dist/types/nodeviews/code-block.d.ts +3 -2
- package/dist/types/pm-plugins/decorators.d.ts +32 -4
- package/dist/types/utils.d.ts +3 -1
- package/dist/types-ts4.5/nodeviews/code-block.d.ts +3 -2
- package/dist/types-ts4.5/pm-plugins/decorators.d.ts +32 -4
- package/dist/types-ts4.5/utils.d.ts +3 -1
- package/package.json +3 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-code-block
|
|
2
2
|
|
|
3
|
+
## 3.3.10
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`cbe3b04ebb0b6`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/cbe3b04ebb0b6) -
|
|
8
|
+
ED-24730 - Address bug where word wrap decorator broke on drag and drop. Required some refactoring
|
|
9
|
+
of decoration functions for code block. Moved all of them to decorators.ts and added unit tests.
|
|
10
|
+
|
|
11
|
+
## 3.3.9
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#134918](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/134918)
|
|
16
|
+
[`89e5820ef3ed5`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/89e5820ef3ed5) -
|
|
17
|
+
[ux] ED-24678 adding a11y support for code block
|
|
18
|
+
|
|
3
19
|
## 3.3.8
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -17,7 +17,7 @@ var _actions = require("../actions");
|
|
|
17
17
|
var _mainState = require("../pm-plugins/main-state");
|
|
18
18
|
var _classNames = require("../ui/class-names");
|
|
19
19
|
var MATCH_NEWLINES = new RegExp('\n', 'g');
|
|
20
|
-
var toDOM = function toDOM(node, contentEditable) {
|
|
20
|
+
var toDOM = function toDOM(node, contentEditable, formattedAriaLabel) {
|
|
21
21
|
return ['div', {
|
|
22
22
|
class: 'code-block'
|
|
23
23
|
}, ['div', {
|
|
@@ -34,17 +34,19 @@ var toDOM = function toDOM(node, contentEditable) {
|
|
|
34
34
|
'data-language': node.attrs.language || '',
|
|
35
35
|
spellcheck: 'false',
|
|
36
36
|
contenteditable: (0, _platformFeatureFlags.fg)('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') ? contentEditable ? 'true' : 'false' : 'true',
|
|
37
|
-
'data-testid': 'code-block--code'
|
|
37
|
+
'data-testid': 'code-block--code',
|
|
38
|
+
'aria-label': formattedAriaLabel
|
|
38
39
|
}, 0]]], ['div', {
|
|
39
40
|
class: _classNames.codeBlockClassNames.end,
|
|
40
41
|
contenteditable: 'false'
|
|
41
42
|
}]];
|
|
42
43
|
};
|
|
43
44
|
var CodeBlockView = exports.CodeBlockView = /*#__PURE__*/function () {
|
|
44
|
-
function CodeBlockView(_node, view, getPos, api, cleanupEditorDisabledListener) {
|
|
45
|
+
function CodeBlockView(_node, view, getPos, formattedAriaLabel, api, cleanupEditorDisabledListener) {
|
|
45
46
|
var _this = this,
|
|
46
47
|
_api$editorDisabled;
|
|
47
48
|
(0, _classCallCheck2.default)(this, CodeBlockView);
|
|
49
|
+
(0, _defineProperty2.default)(this, "formattedAriaLabel", '');
|
|
48
50
|
(0, _defineProperty2.default)(this, "ensureLineNumbers", (0, _rafSchd.default)(function () {
|
|
49
51
|
var lines = 1;
|
|
50
52
|
_this.node.forEach(function (node) {
|
|
@@ -75,7 +77,7 @@ var CodeBlockView = exports.CodeBlockView = /*#__PURE__*/function () {
|
|
|
75
77
|
_this.dom.style.setProperty('--lineNumberGutterWidth', "".concat(maxDigits, "ch"));
|
|
76
78
|
});
|
|
77
79
|
this.cleanupEditorDisabledListener = cleanupEditorDisabledListener;
|
|
78
|
-
var _DOMSerializer$render = _model.DOMSerializer.renderSpec(document, toDOM(_node, !(api !== null && api !== void 0 && (_api$editorDisabled = api.editorDisabled) !== null && _api$editorDisabled !== void 0 && (_api$editorDisabled = _api$editorDisabled.sharedState.currentState()) !== null && _api$editorDisabled !== void 0 && _api$editorDisabled.editorDisabled))),
|
|
80
|
+
var _DOMSerializer$render = _model.DOMSerializer.renderSpec(document, toDOM(_node, !(api !== null && api !== void 0 && (_api$editorDisabled = api.editorDisabled) !== null && _api$editorDisabled !== void 0 && (_api$editorDisabled = _api$editorDisabled.sharedState.currentState()) !== null && _api$editorDisabled !== void 0 && _api$editorDisabled.editorDisabled), formattedAriaLabel)),
|
|
79
81
|
dom = _DOMSerializer$render.dom,
|
|
80
82
|
contentDOM = _DOMSerializer$render.contentDOM;
|
|
81
83
|
this.getPos = getPos;
|
|
@@ -87,6 +89,12 @@ var CodeBlockView = exports.CodeBlockView = /*#__PURE__*/function () {
|
|
|
87
89
|
this.api = api;
|
|
88
90
|
if ((0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping')) {
|
|
89
91
|
this.maintainDynamicGutterSize();
|
|
92
|
+
|
|
93
|
+
// Ensure the code block node has a wrapped state.
|
|
94
|
+
// Wrapped state may already exist from breakout's recreating the node.
|
|
95
|
+
if (!_codeBlock.codeBlockWrappedStates.has(_node)) {
|
|
96
|
+
_codeBlock.codeBlockWrappedStates.set(_node, _codeBlock.defaultWordWrapState);
|
|
97
|
+
}
|
|
90
98
|
} else {
|
|
91
99
|
this.ensureLineNumbers();
|
|
92
100
|
}
|
|
@@ -199,6 +207,6 @@ var CodeBlockView = exports.CodeBlockView = /*#__PURE__*/function () {
|
|
|
199
207
|
}]);
|
|
200
208
|
return CodeBlockView;
|
|
201
209
|
}();
|
|
202
|
-
var codeBlockNodeView = exports.codeBlockNodeView = function codeBlockNodeView(node, view, getPos, api) {
|
|
203
|
-
return new CodeBlockView(node, view, getPos, api);
|
|
210
|
+
var codeBlockNodeView = exports.codeBlockNodeView = function codeBlockNodeView(node, view, getPos, formattedAriaLabel, api) {
|
|
211
|
+
return new CodeBlockView(node, view, getPos, formattedAriaLabel, api);
|
|
204
212
|
};
|
|
@@ -4,14 +4,65 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.generateLineAttributesFromNode = exports.createLineNumbersDecorations = exports.createDecorationSetFromLineAttributes = exports.DECORATION_WIDGET_TYPE = void 0;
|
|
7
|
+
exports.validateWordWrappedDecorators = exports.updateDecorationSetWithWordWrappedDecorator = exports.updateDecorationSetWithLineNumberDecorators = exports.updateCodeBlockDecorations = exports.getWordWrapDecoratorsFromNodePos = exports.generateLineAttributesFromNode = exports.generateInitialDecorations = exports.createLineNumbersDecorations = exports.createDecorationSetFromLineAttributes = exports.DECORATION_WRAPPED_BLOCK_NODE_TYPE = exports.DECORATION_WIDGET_TYPE = void 0;
|
|
8
8
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _codeBlock = require("@atlaskit/editor-common/code-block");
|
|
9
10
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
10
11
|
var _classNames = require("../ui/class-names");
|
|
12
|
+
var _utils = require("../utils");
|
|
11
13
|
var DECORATION_WIDGET_TYPE = exports.DECORATION_WIDGET_TYPE = 'decorationWidgetType';
|
|
12
|
-
var
|
|
14
|
+
var DECORATION_WRAPPED_BLOCK_NODE_TYPE = exports.DECORATION_WRAPPED_BLOCK_NODE_TYPE = 'decorationNodeType';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generate the initial decorations for the code block.
|
|
18
|
+
*/
|
|
19
|
+
var generateInitialDecorations = exports.generateInitialDecorations = function generateInitialDecorations(state) {
|
|
20
|
+
var codeBlockNodes = (0, _utils.getAllCodeBlockNodesInDoc)(state);
|
|
21
|
+
return codeBlockNodes.flatMap(function (node) {
|
|
22
|
+
return createLineNumbersDecorations(node);
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Update all the decorations used by the code block.
|
|
28
|
+
*/
|
|
29
|
+
var updateCodeBlockDecorations = exports.updateCodeBlockDecorations = function updateCodeBlockDecorations(tr, state, decorationSet) {
|
|
30
|
+
var updatedDecorationSet = decorationSet;
|
|
31
|
+
var codeBlockNodes = (0, _utils.getAllCodeBlockNodesInDoc)(state);
|
|
32
|
+
|
|
33
|
+
// All the line numbers decorators are refreshed on doc change.
|
|
34
|
+
updatedDecorationSet = updateDecorationSetWithLineNumberDecorators(tr, codeBlockNodes, updatedDecorationSet);
|
|
35
|
+
|
|
36
|
+
// Check to make sure the word wrap decorators are still valid.
|
|
37
|
+
updatedDecorationSet = validateWordWrappedDecorators(tr, codeBlockNodes, updatedDecorationSet);
|
|
38
|
+
return updatedDecorationSet;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Update the decorations set with the line number decorators.
|
|
43
|
+
*/
|
|
44
|
+
var updateDecorationSetWithLineNumberDecorators = exports.updateDecorationSetWithLineNumberDecorators = function updateDecorationSetWithLineNumberDecorators(tr, codeBlockNodes, decorationSet) {
|
|
45
|
+
var updatedDecorationSet = decorationSet;
|
|
46
|
+
// remove all the line number children from the decorations set. 'undefined, undefined' is used to find() the whole doc.
|
|
47
|
+
var children = updatedDecorationSet.find(undefined, undefined, function (spec) {
|
|
48
|
+
return spec.type === DECORATION_WIDGET_TYPE;
|
|
49
|
+
});
|
|
50
|
+
updatedDecorationSet = updatedDecorationSet.remove(children);
|
|
51
|
+
|
|
52
|
+
// regenerate all the line number for the documents code blocks
|
|
53
|
+
var lineNumberDecorators = [];
|
|
54
|
+
codeBlockNodes.forEach(function (node) {
|
|
55
|
+
lineNumberDecorators.push.apply(lineNumberDecorators, (0, _toConsumableArray2.default)(createLineNumbersDecorations(node)));
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// add the newly generated line numbers to the decorations set
|
|
59
|
+
return updatedDecorationSet.add(tr.doc, [].concat(lineNumberDecorators));
|
|
60
|
+
};
|
|
61
|
+
var generateLineAttributesFromNode = exports.generateLineAttributesFromNode = function generateLineAttributesFromNode(node) {
|
|
62
|
+
var innerNode = node.node,
|
|
63
|
+
pos = node.pos;
|
|
13
64
|
// Get content node
|
|
14
|
-
var contentNode =
|
|
65
|
+
var contentNode = innerNode.content;
|
|
15
66
|
|
|
16
67
|
// Get node text content
|
|
17
68
|
var lineAttributes = [];
|
|
@@ -64,6 +115,60 @@ var createDecorationSetFromLineAttributes = exports.createDecorationSetFromLineA
|
|
|
64
115
|
});
|
|
65
116
|
return widgetDecorations;
|
|
66
117
|
};
|
|
67
|
-
var createLineNumbersDecorations = exports.createLineNumbersDecorations = function createLineNumbersDecorations(
|
|
68
|
-
return createDecorationSetFromLineAttributes(generateLineAttributesFromNode(
|
|
118
|
+
var createLineNumbersDecorations = exports.createLineNumbersDecorations = function createLineNumbersDecorations(node) {
|
|
119
|
+
return createDecorationSetFromLineAttributes(generateLineAttributesFromNode(node));
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* There are edge cases like when a user drags and drops a code block node where the decorator breaks and no longer reflects
|
|
124
|
+
* the correct word wrap state. This function validates that the decorator and the state are in line, otherwise it will
|
|
125
|
+
* retrigger the logic to apply the word wrap decorator.
|
|
126
|
+
*/
|
|
127
|
+
var validateWordWrappedDecorators = exports.validateWordWrappedDecorators = function validateWordWrappedDecorators(tr, codeBlockNodes, decorationSet) {
|
|
128
|
+
var updatedDecorationSet = decorationSet;
|
|
129
|
+
codeBlockNodes.forEach(function (node) {
|
|
130
|
+
var isCodeBlockWrappedInState = (0, _codeBlock.isCodeBlockWordWrapEnabled)(node.node);
|
|
131
|
+
var isCodeBlockWrappedByDecorator = getWordWrapDecoratorsFromNodePos(node.pos, decorationSet).length !== 0;
|
|
132
|
+
if (isCodeBlockWrappedInState && !isCodeBlockWrappedByDecorator) {
|
|
133
|
+
updatedDecorationSet = updateDecorationSetWithWordWrappedDecorator(decorationSet, tr, node);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return updatedDecorationSet;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Update the decoration set with the word wrap decorator.
|
|
141
|
+
*/
|
|
142
|
+
var updateDecorationSetWithWordWrappedDecorator = exports.updateDecorationSetWithWordWrappedDecorator = function updateDecorationSetWithWordWrappedDecorator(decorationSet, tr, node) {
|
|
143
|
+
if (!node || node.pos === undefined) {
|
|
144
|
+
return decorationSet;
|
|
145
|
+
}
|
|
146
|
+
var updatedDecorationSet = decorationSet;
|
|
147
|
+
var pos = node.pos,
|
|
148
|
+
innerNode = node.node;
|
|
149
|
+
var isNodeWrapped = (0, _codeBlock.isCodeBlockWordWrapEnabled)(innerNode);
|
|
150
|
+
if (!isNodeWrapped) {
|
|
151
|
+
var currentWrappedBlockDecorationSet = getWordWrapDecoratorsFromNodePos(pos, updatedDecorationSet);
|
|
152
|
+
updatedDecorationSet = updatedDecorationSet.remove(currentWrappedBlockDecorationSet);
|
|
153
|
+
} else {
|
|
154
|
+
var wrappedBlock = _view.Decoration.node(pos, pos + innerNode.nodeSize, {
|
|
155
|
+
class: _classNames.codeBlockClassNames.contentFgWrapped
|
|
156
|
+
}, {
|
|
157
|
+
type: DECORATION_WRAPPED_BLOCK_NODE_TYPE
|
|
158
|
+
} // Allows for quick filtering of decorations while using `find`
|
|
159
|
+
);
|
|
160
|
+
updatedDecorationSet = updatedDecorationSet.add(tr.doc, [wrappedBlock]);
|
|
161
|
+
}
|
|
162
|
+
return updatedDecorationSet;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get the word wrap decorators for the given node position.
|
|
167
|
+
*/
|
|
168
|
+
var getWordWrapDecoratorsFromNodePos = exports.getWordWrapDecoratorsFromNodePos = function getWordWrapDecoratorsFromNodePos(pos, decorationSet) {
|
|
169
|
+
var codeBlockNodePosition = pos + 1; // We need to add 1 to the position to get the start of the node.
|
|
170
|
+
var currentWrappedBlockDecorationSet = decorationSet.find(codeBlockNodePosition, codeBlockNodePosition, function (spec) {
|
|
171
|
+
return spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE;
|
|
172
|
+
});
|
|
173
|
+
return currentWrappedBlockDecorationSet;
|
|
69
174
|
};
|
|
@@ -6,8 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.createPlugin = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
-
var
|
|
10
|
-
var _codeBlock = require("@atlaskit/editor-common/code-block");
|
|
9
|
+
var _messages = require("@atlaskit/editor-common/messages");
|
|
11
10
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
12
11
|
var _selection = require("@atlaskit/editor-common/selection");
|
|
13
12
|
var _utils = require("@atlaskit/editor-common/utils");
|
|
@@ -15,7 +14,7 @@ var _state = require("@atlaskit/editor-prosemirror/state");
|
|
|
15
14
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
16
15
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
17
16
|
var _actions = require("../actions");
|
|
18
|
-
var
|
|
17
|
+
var _codeBlock = require("../nodeviews/code-block");
|
|
19
18
|
var _pluginKey = require("../plugin-key");
|
|
20
19
|
var _classNames = require("../ui/class-names");
|
|
21
20
|
var _utils2 = require("../utils");
|
|
@@ -23,7 +22,6 @@ var _actions2 = require("./actions");
|
|
|
23
22
|
var _decorators = require("./decorators");
|
|
24
23
|
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; }
|
|
25
24
|
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; }
|
|
26
|
-
var DECORATION_WRAPPED_BLOCK_NODE_TYPE = 'decorationNodeType';
|
|
27
25
|
var createPlugin = exports.createPlugin = function createPlugin(_ref) {
|
|
28
26
|
var _ref$useLongPressSele = _ref.useLongPressSelection,
|
|
29
27
|
useLongPressSelection = _ref$useLongPressSele === void 0 ? false : _ref$useLongPressSele,
|
|
@@ -32,57 +30,6 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
|
|
|
32
30
|
allowCompositionInputOverride = _ref$allowComposition === void 0 ? false : _ref$allowComposition,
|
|
33
31
|
api = _ref.api;
|
|
34
32
|
var handleDOMEvents = {};
|
|
35
|
-
var createLineNumberDecoratorsFromDecendants = function createLineNumberDecoratorsFromDecendants(editorState) {
|
|
36
|
-
var lineNumberDecorators = [];
|
|
37
|
-
editorState.doc.descendants(function (node, pos) {
|
|
38
|
-
if (node.type === editorState.schema.nodes.codeBlock) {
|
|
39
|
-
lineNumberDecorators.push.apply(lineNumberDecorators, (0, _toConsumableArray2.default)((0, _decorators.createLineNumbersDecorations)(pos, node)));
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
return true;
|
|
43
|
-
});
|
|
44
|
-
return lineNumberDecorators;
|
|
45
|
-
};
|
|
46
|
-
var createWordWrappedDecoratorPluginState = function createWordWrappedDecoratorPluginState(pluginState, tr, node) {
|
|
47
|
-
var decorationSetFromState = pluginState.decorations;
|
|
48
|
-
if (node) {
|
|
49
|
-
var pos = node.pos,
|
|
50
|
-
innerNode = node.node;
|
|
51
|
-
if (pos !== undefined) {
|
|
52
|
-
var isNodeWrapped = (0, _codeBlock.isCodeBlockWordWrapEnabled)(innerNode);
|
|
53
|
-
if (!isNodeWrapped) {
|
|
54
|
-
// Restricts the range of decorators to the current node while not including the previous nodes position in range
|
|
55
|
-
var codeBlockNodePosition = pos + 1;
|
|
56
|
-
var currentWrappedBlockDecorationSet = decorationSetFromState.find(codeBlockNodePosition, codeBlockNodePosition, function (spec) {
|
|
57
|
-
return spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE;
|
|
58
|
-
});
|
|
59
|
-
decorationSetFromState = decorationSetFromState.remove(currentWrappedBlockDecorationSet);
|
|
60
|
-
} else {
|
|
61
|
-
var wrappedBlock = _view.Decoration.node(pos, pos + innerNode.nodeSize, {
|
|
62
|
-
class: _classNames.codeBlockClassNames.contentFgWrapped
|
|
63
|
-
}, {
|
|
64
|
-
type: DECORATION_WRAPPED_BLOCK_NODE_TYPE
|
|
65
|
-
} // Allows for quick filtering of decorations while using `find`
|
|
66
|
-
);
|
|
67
|
-
decorationSetFromState = decorationSetFromState.add(tr.doc, [wrappedBlock]);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return decorationSetFromState;
|
|
72
|
-
};
|
|
73
|
-
var updateLineDecorationSet = function updateLineDecorationSet(tr, state, decorationSet) {
|
|
74
|
-
// remove all the line number children from the decorations set. 'undefined, undefined' is used to find() the whole doc.
|
|
75
|
-
var children = decorationSet.find(undefined, undefined, function (spec) {
|
|
76
|
-
return spec.type === _decorators.DECORATION_WIDGET_TYPE;
|
|
77
|
-
});
|
|
78
|
-
decorationSet = decorationSet.remove(children);
|
|
79
|
-
|
|
80
|
-
// regenerate all the line number for the documents code blocks
|
|
81
|
-
var lineDecorators = createLineNumberDecoratorsFromDecendants(state);
|
|
82
|
-
|
|
83
|
-
// add the newly generated line numbers to the decorations set
|
|
84
|
-
return decorationSet.add(tr.doc, (0, _toConsumableArray2.default)(lineDecorators));
|
|
85
|
-
};
|
|
86
33
|
|
|
87
34
|
// ME-1599: Composition on mobile was causing the DOM observer to mutate the code block
|
|
88
35
|
// incorrecly and lose content when pressing enter in the middle of a code block line.
|
|
@@ -126,13 +73,13 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
|
|
|
126
73
|
state: {
|
|
127
74
|
init: function init(_, state) {
|
|
128
75
|
var node = (0, _utils2.findCodeBlock)(state, state.selection);
|
|
129
|
-
var
|
|
76
|
+
var initialDecorations = (0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping') ? (0, _decorators.generateInitialDecorations)(state) : [];
|
|
130
77
|
return {
|
|
131
78
|
pos: node ? node.pos : null,
|
|
132
79
|
contentCopied: false,
|
|
133
80
|
isNodeSelected: false,
|
|
134
81
|
shouldIgnoreFollowingMutations: false,
|
|
135
|
-
decorations: _view.DecorationSet.create(state.doc,
|
|
82
|
+
decorations: _view.DecorationSet.create(state.doc, initialDecorations)
|
|
136
83
|
};
|
|
137
84
|
},
|
|
138
85
|
apply: function apply(tr, pluginState, _oldState, newState) {
|
|
@@ -140,18 +87,18 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
|
|
|
140
87
|
if ((meta === null || meta === void 0 ? void 0 : meta.type) === _actions2.ACTIONS.SET_IS_WRAPPED && (0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping')) {
|
|
141
88
|
var node = (0, _utils2.findCodeBlock)(newState, tr.selection);
|
|
142
89
|
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
143
|
-
decorations:
|
|
90
|
+
decorations: (0, _decorators.updateDecorationSetWithWordWrappedDecorator)(pluginState.decorations, tr, node)
|
|
144
91
|
});
|
|
145
92
|
}
|
|
146
93
|
if (tr.docChanged) {
|
|
147
94
|
var _node = (0, _utils2.findCodeBlock)(newState, tr.selection);
|
|
148
95
|
|
|
149
96
|
// Updates mapping position of all existing decorations to new positions
|
|
150
|
-
// specifically used for updating word wrap node decorators
|
|
97
|
+
// specifically used for updating word wrap node decorators (does not cover drag & drop, validateWordWrappedDecorators does).
|
|
151
98
|
var updatedDecorationSet = pluginState.decorations.map(tr.mapping, tr.doc);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
99
|
+
if ((0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping')) {
|
|
100
|
+
updatedDecorationSet = (0, _decorators.updateCodeBlockDecorations)(tr, newState, updatedDecorationSet);
|
|
101
|
+
}
|
|
155
102
|
var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
156
103
|
pos: _node ? _node.pos : null,
|
|
157
104
|
isNodeSelected: tr.selection instanceof _state.NodeSelection,
|
|
@@ -189,7 +136,10 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
|
|
|
189
136
|
},
|
|
190
137
|
nodeViews: {
|
|
191
138
|
codeBlock: function codeBlock(node, view, getPos) {
|
|
192
|
-
|
|
139
|
+
var _getIntl = getIntl(),
|
|
140
|
+
formatMessage = _getIntl.formatMessage;
|
|
141
|
+
var formattedAriaLabel = formatMessage(_messages.blockTypeMessages.codeblock);
|
|
142
|
+
return (0, _codeBlock.codeBlockNodeView)(node, view, getPos, formattedAriaLabel, api);
|
|
193
143
|
}
|
|
194
144
|
},
|
|
195
145
|
handleClickOn: (0, _selection.createSelectionClickHandler)(['codeBlock'], function (target) {
|
package/dist/cjs/toolbar.js
CHANGED
|
@@ -109,7 +109,6 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig() {
|
|
|
109
109
|
supportsViewMode: true,
|
|
110
110
|
icon: _WrapIcon.WrapIcon,
|
|
111
111
|
onClick: (0, _actions.toggleWordWrapStateForCodeBlockNode)(editorAnalyticsAPI),
|
|
112
|
-
// Hooking up here for demo purposes. To be revisited with ED-24222.
|
|
113
112
|
title: isWrapped ? formatMessage(_messages.codeBlockButtonMessages.unwrapCode) : formatMessage(_messages.codeBlockButtonMessages.wrapCode),
|
|
114
113
|
tabIndex: null,
|
|
115
114
|
selected: isWrapped
|
package/dist/cjs/utils.js
CHANGED
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "findCodeBlock", {
|
|
|
9
9
|
return _transforms.findCodeBlock;
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
+
exports.getAllCodeBlockNodesInDoc = getAllCodeBlockNodesInDoc;
|
|
12
13
|
exports.getCursor = getCursor;
|
|
13
14
|
Object.defineProperty(exports, "transformSingleLineCodeBlockToCodeMark", {
|
|
14
15
|
enumerable: true,
|
|
@@ -25,4 +26,18 @@ Object.defineProperty(exports, "transformSliceToJoinAdjacentCodeBlocks", {
|
|
|
25
26
|
var _transforms = require("@atlaskit/editor-common/transforms");
|
|
26
27
|
function getCursor(selection) {
|
|
27
28
|
return selection.$cursor || undefined;
|
|
29
|
+
}
|
|
30
|
+
function getAllCodeBlockNodesInDoc(state) {
|
|
31
|
+
var codeBlockNodes = [];
|
|
32
|
+
state.doc.descendants(function (node, pos) {
|
|
33
|
+
if (node.type === state.schema.nodes.codeBlock) {
|
|
34
|
+
codeBlockNodes.push({
|
|
35
|
+
node: node,
|
|
36
|
+
pos: pos
|
|
37
|
+
});
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
});
|
|
42
|
+
return codeBlockNodes;
|
|
28
43
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import rafSchedule from 'raf-schd';
|
|
3
|
-
import { transferCodeBlockWrappedValue } from '@atlaskit/editor-common/code-block';
|
|
3
|
+
import { codeBlockWrappedStates, defaultWordWrapState, transferCodeBlockWrappedValue } from '@atlaskit/editor-common/code-block';
|
|
4
4
|
import { browser } from '@atlaskit/editor-common/utils';
|
|
5
5
|
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
6
6
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
@@ -8,7 +8,7 @@ import { resetShouldIgnoreFollowingMutations } from '../actions';
|
|
|
8
8
|
import { getPluginState } from '../pm-plugins/main-state';
|
|
9
9
|
import { codeBlockClassNames } from '../ui/class-names';
|
|
10
10
|
const MATCH_NEWLINES = new RegExp('\n', 'g');
|
|
11
|
-
const toDOM = (node, contentEditable) => ['div', {
|
|
11
|
+
const toDOM = (node, contentEditable, formattedAriaLabel) => ['div', {
|
|
12
12
|
class: 'code-block'
|
|
13
13
|
}, ['div', {
|
|
14
14
|
class: codeBlockClassNames.start,
|
|
@@ -24,14 +24,16 @@ const toDOM = (node, contentEditable) => ['div', {
|
|
|
24
24
|
'data-language': node.attrs.language || '',
|
|
25
25
|
spellcheck: 'false',
|
|
26
26
|
contenteditable: fg('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') ? contentEditable ? 'true' : 'false' : 'true',
|
|
27
|
-
'data-testid': 'code-block--code'
|
|
27
|
+
'data-testid': 'code-block--code',
|
|
28
|
+
'aria-label': formattedAriaLabel
|
|
28
29
|
}, 0]]], ['div', {
|
|
29
30
|
class: codeBlockClassNames.end,
|
|
30
31
|
contenteditable: 'false'
|
|
31
32
|
}]];
|
|
32
33
|
export class CodeBlockView {
|
|
33
|
-
constructor(_node, view, getPos, api, cleanupEditorDisabledListener) {
|
|
34
|
+
constructor(_node, view, getPos, formattedAriaLabel, api, cleanupEditorDisabledListener) {
|
|
34
35
|
var _api$editorDisabled, _api$editorDisabled$s;
|
|
36
|
+
_defineProperty(this, "formattedAriaLabel", '');
|
|
35
37
|
_defineProperty(this, "ensureLineNumbers", rafSchedule(() => {
|
|
36
38
|
let lines = 1;
|
|
37
39
|
this.node.forEach(node => {
|
|
@@ -65,7 +67,7 @@ export class CodeBlockView {
|
|
|
65
67
|
const {
|
|
66
68
|
dom,
|
|
67
69
|
contentDOM
|
|
68
|
-
} = DOMSerializer.renderSpec(document, toDOM(_node, !(api !== null && api !== void 0 && (_api$editorDisabled = api.editorDisabled) !== null && _api$editorDisabled !== void 0 && (_api$editorDisabled$s = _api$editorDisabled.sharedState.currentState()) !== null && _api$editorDisabled$s !== void 0 && _api$editorDisabled$s.editorDisabled)));
|
|
70
|
+
} = DOMSerializer.renderSpec(document, toDOM(_node, !(api !== null && api !== void 0 && (_api$editorDisabled = api.editorDisabled) !== null && _api$editorDisabled !== void 0 && (_api$editorDisabled$s = _api$editorDisabled.sharedState.currentState()) !== null && _api$editorDisabled$s !== void 0 && _api$editorDisabled$s.editorDisabled), formattedAriaLabel));
|
|
69
71
|
this.getPos = getPos;
|
|
70
72
|
this.view = view;
|
|
71
73
|
this.node = _node;
|
|
@@ -75,6 +77,12 @@ export class CodeBlockView {
|
|
|
75
77
|
this.api = api;
|
|
76
78
|
if (fg('editor_support_code_block_wrapping')) {
|
|
77
79
|
this.maintainDynamicGutterSize();
|
|
80
|
+
|
|
81
|
+
// Ensure the code block node has a wrapped state.
|
|
82
|
+
// Wrapped state may already exist from breakout's recreating the node.
|
|
83
|
+
if (!codeBlockWrappedStates.has(_node)) {
|
|
84
|
+
codeBlockWrappedStates.set(_node, defaultWordWrapState);
|
|
85
|
+
}
|
|
78
86
|
} else {
|
|
79
87
|
this.ensureLineNumbers();
|
|
80
88
|
}
|
|
@@ -170,4 +178,4 @@ export class CodeBlockView {
|
|
|
170
178
|
this.cleanupEditorDisabledListener = undefined;
|
|
171
179
|
}
|
|
172
180
|
}
|
|
173
|
-
export const codeBlockNodeView = (node, view, getPos, api) => new CodeBlockView(node, view, getPos, api);
|
|
181
|
+
export const codeBlockNodeView = (node, view, getPos, formattedAriaLabel, api) => new CodeBlockView(node, view, getPos, formattedAriaLabel, api);
|
|
@@ -1,9 +1,58 @@
|
|
|
1
|
+
import { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
|
|
1
2
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
2
3
|
import { codeBlockClassNames } from '../ui/class-names';
|
|
4
|
+
import { getAllCodeBlockNodesInDoc } from '../utils';
|
|
3
5
|
export const DECORATION_WIDGET_TYPE = 'decorationWidgetType';
|
|
4
|
-
export const
|
|
6
|
+
export const DECORATION_WRAPPED_BLOCK_NODE_TYPE = 'decorationNodeType';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generate the initial decorations for the code block.
|
|
10
|
+
*/
|
|
11
|
+
export const generateInitialDecorations = state => {
|
|
12
|
+
const codeBlockNodes = getAllCodeBlockNodesInDoc(state);
|
|
13
|
+
return codeBlockNodes.flatMap(node => createLineNumbersDecorations(node));
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Update all the decorations used by the code block.
|
|
18
|
+
*/
|
|
19
|
+
export const updateCodeBlockDecorations = (tr, state, decorationSet) => {
|
|
20
|
+
let updatedDecorationSet = decorationSet;
|
|
21
|
+
const codeBlockNodes = getAllCodeBlockNodesInDoc(state);
|
|
22
|
+
|
|
23
|
+
// All the line numbers decorators are refreshed on doc change.
|
|
24
|
+
updatedDecorationSet = updateDecorationSetWithLineNumberDecorators(tr, codeBlockNodes, updatedDecorationSet);
|
|
25
|
+
|
|
26
|
+
// Check to make sure the word wrap decorators are still valid.
|
|
27
|
+
updatedDecorationSet = validateWordWrappedDecorators(tr, codeBlockNodes, updatedDecorationSet);
|
|
28
|
+
return updatedDecorationSet;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Update the decorations set with the line number decorators.
|
|
33
|
+
*/
|
|
34
|
+
export const updateDecorationSetWithLineNumberDecorators = (tr, codeBlockNodes, decorationSet) => {
|
|
35
|
+
let updatedDecorationSet = decorationSet;
|
|
36
|
+
// remove all the line number children from the decorations set. 'undefined, undefined' is used to find() the whole doc.
|
|
37
|
+
const children = updatedDecorationSet.find(undefined, undefined, spec => spec.type === DECORATION_WIDGET_TYPE);
|
|
38
|
+
updatedDecorationSet = updatedDecorationSet.remove(children);
|
|
39
|
+
|
|
40
|
+
// regenerate all the line number for the documents code blocks
|
|
41
|
+
const lineNumberDecorators = [];
|
|
42
|
+
codeBlockNodes.forEach(node => {
|
|
43
|
+
lineNumberDecorators.push(...createLineNumbersDecorations(node));
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// add the newly generated line numbers to the decorations set
|
|
47
|
+
return updatedDecorationSet.add(tr.doc, [...lineNumberDecorators]);
|
|
48
|
+
};
|
|
49
|
+
export const generateLineAttributesFromNode = node => {
|
|
50
|
+
const {
|
|
51
|
+
node: innerNode,
|
|
52
|
+
pos
|
|
53
|
+
} = node;
|
|
5
54
|
// Get content node
|
|
6
|
-
const contentNode =
|
|
55
|
+
const contentNode = innerNode.content;
|
|
7
56
|
|
|
8
57
|
// Get node text content
|
|
9
58
|
let lineAttributes = [];
|
|
@@ -58,4 +107,58 @@ export const createDecorationSetFromLineAttributes = lineAttributes => {
|
|
|
58
107
|
});
|
|
59
108
|
return widgetDecorations;
|
|
60
109
|
};
|
|
61
|
-
export const createLineNumbersDecorations =
|
|
110
|
+
export const createLineNumbersDecorations = node => createDecorationSetFromLineAttributes(generateLineAttributesFromNode(node));
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* There are edge cases like when a user drags and drops a code block node where the decorator breaks and no longer reflects
|
|
114
|
+
* the correct word wrap state. This function validates that the decorator and the state are in line, otherwise it will
|
|
115
|
+
* retrigger the logic to apply the word wrap decorator.
|
|
116
|
+
*/
|
|
117
|
+
export const validateWordWrappedDecorators = (tr, codeBlockNodes, decorationSet) => {
|
|
118
|
+
let updatedDecorationSet = decorationSet;
|
|
119
|
+
codeBlockNodes.forEach(node => {
|
|
120
|
+
const isCodeBlockWrappedInState = isCodeBlockWordWrapEnabled(node.node);
|
|
121
|
+
const isCodeBlockWrappedByDecorator = getWordWrapDecoratorsFromNodePos(node.pos, decorationSet).length !== 0;
|
|
122
|
+
if (isCodeBlockWrappedInState && !isCodeBlockWrappedByDecorator) {
|
|
123
|
+
updatedDecorationSet = updateDecorationSetWithWordWrappedDecorator(decorationSet, tr, node);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
return updatedDecorationSet;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Update the decoration set with the word wrap decorator.
|
|
131
|
+
*/
|
|
132
|
+
export const updateDecorationSetWithWordWrappedDecorator = (decorationSet, tr, node) => {
|
|
133
|
+
if (!node || node.pos === undefined) {
|
|
134
|
+
return decorationSet;
|
|
135
|
+
}
|
|
136
|
+
let updatedDecorationSet = decorationSet;
|
|
137
|
+
const {
|
|
138
|
+
pos,
|
|
139
|
+
node: innerNode
|
|
140
|
+
} = node;
|
|
141
|
+
const isNodeWrapped = isCodeBlockWordWrapEnabled(innerNode);
|
|
142
|
+
if (!isNodeWrapped) {
|
|
143
|
+
const currentWrappedBlockDecorationSet = getWordWrapDecoratorsFromNodePos(pos, updatedDecorationSet);
|
|
144
|
+
updatedDecorationSet = updatedDecorationSet.remove(currentWrappedBlockDecorationSet);
|
|
145
|
+
} else {
|
|
146
|
+
const wrappedBlock = Decoration.node(pos, pos + innerNode.nodeSize, {
|
|
147
|
+
class: codeBlockClassNames.contentFgWrapped
|
|
148
|
+
}, {
|
|
149
|
+
type: DECORATION_WRAPPED_BLOCK_NODE_TYPE
|
|
150
|
+
} // Allows for quick filtering of decorations while using `find`
|
|
151
|
+
);
|
|
152
|
+
updatedDecorationSet = updatedDecorationSet.add(tr.doc, [wrappedBlock]);
|
|
153
|
+
}
|
|
154
|
+
return updatedDecorationSet;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Get the word wrap decorators for the given node position.
|
|
159
|
+
*/
|
|
160
|
+
export const getWordWrapDecoratorsFromNodePos = (pos, decorationSet) => {
|
|
161
|
+
const codeBlockNodePosition = pos + 1; // We need to add 1 to the position to get the start of the node.
|
|
162
|
+
const currentWrappedBlockDecorationSet = decorationSet.find(codeBlockNodePosition, codeBlockNodePosition, spec => spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE);
|
|
163
|
+
return currentWrappedBlockDecorationSet;
|
|
164
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { blockTypeMessages } from '@atlaskit/editor-common/messages';
|
|
2
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
3
|
import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
|
|
4
4
|
import { browser } from '@atlaskit/editor-common/utils';
|
|
5
5
|
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
6
|
-
import {
|
|
6
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
7
7
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
8
8
|
import { ignoreFollowingMutations, resetShouldIgnoreFollowingMutations } from '../actions';
|
|
9
9
|
import { codeBlockNodeView } from '../nodeviews/code-block';
|
|
@@ -11,8 +11,7 @@ import { pluginKey } from '../plugin-key';
|
|
|
11
11
|
import { codeBlockClassNames } from '../ui/class-names';
|
|
12
12
|
import { findCodeBlock } from '../utils';
|
|
13
13
|
import { ACTIONS } from './actions';
|
|
14
|
-
import {
|
|
15
|
-
const DECORATION_WRAPPED_BLOCK_NODE_TYPE = 'decorationNodeType';
|
|
14
|
+
import { generateInitialDecorations, updateCodeBlockDecorations, updateDecorationSetWithWordWrappedDecorator } from './decorators';
|
|
16
15
|
export const createPlugin = ({
|
|
17
16
|
useLongPressSelection = false,
|
|
18
17
|
getIntl,
|
|
@@ -20,55 +19,6 @@ export const createPlugin = ({
|
|
|
20
19
|
api
|
|
21
20
|
}) => {
|
|
22
21
|
const handleDOMEvents = {};
|
|
23
|
-
const createLineNumberDecoratorsFromDecendants = editorState => {
|
|
24
|
-
let lineNumberDecorators = [];
|
|
25
|
-
editorState.doc.descendants((node, pos) => {
|
|
26
|
-
if (node.type === editorState.schema.nodes.codeBlock) {
|
|
27
|
-
lineNumberDecorators.push(...createLineNumbersDecorations(pos, node));
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
return true;
|
|
31
|
-
});
|
|
32
|
-
return lineNumberDecorators;
|
|
33
|
-
};
|
|
34
|
-
const createWordWrappedDecoratorPluginState = (pluginState, tr, node) => {
|
|
35
|
-
let decorationSetFromState = pluginState.decorations;
|
|
36
|
-
if (node) {
|
|
37
|
-
const {
|
|
38
|
-
pos,
|
|
39
|
-
node: innerNode
|
|
40
|
-
} = node;
|
|
41
|
-
if (pos !== undefined) {
|
|
42
|
-
const isNodeWrapped = isCodeBlockWordWrapEnabled(innerNode);
|
|
43
|
-
if (!isNodeWrapped) {
|
|
44
|
-
// Restricts the range of decorators to the current node while not including the previous nodes position in range
|
|
45
|
-
const codeBlockNodePosition = pos + 1;
|
|
46
|
-
const currentWrappedBlockDecorationSet = decorationSetFromState.find(codeBlockNodePosition, codeBlockNodePosition, spec => spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE);
|
|
47
|
-
decorationSetFromState = decorationSetFromState.remove(currentWrappedBlockDecorationSet);
|
|
48
|
-
} else {
|
|
49
|
-
const wrappedBlock = Decoration.node(pos, pos + innerNode.nodeSize, {
|
|
50
|
-
class: codeBlockClassNames.contentFgWrapped
|
|
51
|
-
}, {
|
|
52
|
-
type: DECORATION_WRAPPED_BLOCK_NODE_TYPE
|
|
53
|
-
} // Allows for quick filtering of decorations while using `find`
|
|
54
|
-
);
|
|
55
|
-
decorationSetFromState = decorationSetFromState.add(tr.doc, [wrappedBlock]);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return decorationSetFromState;
|
|
60
|
-
};
|
|
61
|
-
const updateLineDecorationSet = (tr, state, decorationSet) => {
|
|
62
|
-
// remove all the line number children from the decorations set. 'undefined, undefined' is used to find() the whole doc.
|
|
63
|
-
const children = decorationSet.find(undefined, undefined, spec => spec.type === DECORATION_WIDGET_TYPE);
|
|
64
|
-
decorationSet = decorationSet.remove(children);
|
|
65
|
-
|
|
66
|
-
// regenerate all the line number for the documents code blocks
|
|
67
|
-
const lineDecorators = createLineNumberDecoratorsFromDecendants(state);
|
|
68
|
-
|
|
69
|
-
// add the newly generated line numbers to the decorations set
|
|
70
|
-
return decorationSet.add(tr.doc, [...lineDecorators]);
|
|
71
|
-
};
|
|
72
22
|
|
|
73
23
|
// ME-1599: Composition on mobile was causing the DOM observer to mutate the code block
|
|
74
24
|
// incorrecly and lose content when pressing enter in the middle of a code block line.
|
|
@@ -110,13 +60,13 @@ export const createPlugin = ({
|
|
|
110
60
|
state: {
|
|
111
61
|
init(_, state) {
|
|
112
62
|
const node = findCodeBlock(state, state.selection);
|
|
113
|
-
const
|
|
63
|
+
const initialDecorations = fg('editor_support_code_block_wrapping') ? generateInitialDecorations(state) : [];
|
|
114
64
|
return {
|
|
115
65
|
pos: node ? node.pos : null,
|
|
116
66
|
contentCopied: false,
|
|
117
67
|
isNodeSelected: false,
|
|
118
68
|
shouldIgnoreFollowingMutations: false,
|
|
119
|
-
decorations: DecorationSet.create(state.doc,
|
|
69
|
+
decorations: DecorationSet.create(state.doc, initialDecorations)
|
|
120
70
|
};
|
|
121
71
|
},
|
|
122
72
|
apply(tr, pluginState, _oldState, newState) {
|
|
@@ -125,18 +75,18 @@ export const createPlugin = ({
|
|
|
125
75
|
const node = findCodeBlock(newState, tr.selection);
|
|
126
76
|
return {
|
|
127
77
|
...pluginState,
|
|
128
|
-
decorations:
|
|
78
|
+
decorations: updateDecorationSetWithWordWrappedDecorator(pluginState.decorations, tr, node)
|
|
129
79
|
};
|
|
130
80
|
}
|
|
131
81
|
if (tr.docChanged) {
|
|
132
82
|
const node = findCodeBlock(newState, tr.selection);
|
|
133
83
|
|
|
134
84
|
// Updates mapping position of all existing decorations to new positions
|
|
135
|
-
// specifically used for updating word wrap node decorators
|
|
85
|
+
// specifically used for updating word wrap node decorators (does not cover drag & drop, validateWordWrappedDecorators does).
|
|
136
86
|
let updatedDecorationSet = pluginState.decorations.map(tr.mapping, tr.doc);
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
87
|
+
if (fg('editor_support_code_block_wrapping')) {
|
|
88
|
+
updatedDecorationSet = updateCodeBlockDecorations(tr, newState, updatedDecorationSet);
|
|
89
|
+
}
|
|
140
90
|
const newPluginState = {
|
|
141
91
|
...pluginState,
|
|
142
92
|
pos: node ? node.pos : null,
|
|
@@ -177,7 +127,13 @@ export const createPlugin = ({
|
|
|
177
127
|
return undefined;
|
|
178
128
|
},
|
|
179
129
|
nodeViews: {
|
|
180
|
-
codeBlock: (node, view, getPos) =>
|
|
130
|
+
codeBlock: (node, view, getPos) => {
|
|
131
|
+
const {
|
|
132
|
+
formatMessage
|
|
133
|
+
} = getIntl();
|
|
134
|
+
const formattedAriaLabel = formatMessage(blockTypeMessages.codeblock);
|
|
135
|
+
return codeBlockNodeView(node, view, getPos, formattedAriaLabel, api);
|
|
136
|
+
}
|
|
181
137
|
},
|
|
182
138
|
handleClickOn: createSelectionClickHandler(['codeBlock'], target => fg('editor_support_code_block_wrapping') ? !!(target.classList.contains(codeBlockClassNames.lineNumberWidget) || target.classList.contains(codeBlockClassNames.gutterFg)) : !!(target.closest(`.${codeBlockClassNames.gutter}`) || target.classList.contains(codeBlockClassNames.content)), {
|
|
183
139
|
useLongPressSelection
|
package/dist/es2019/toolbar.js
CHANGED
|
@@ -90,7 +90,6 @@ export const getToolbarConfig = (allowCopyToClipboard = false, api) => (state, {
|
|
|
90
90
|
supportsViewMode: true,
|
|
91
91
|
icon: WrapIcon,
|
|
92
92
|
onClick: toggleWordWrapStateForCodeBlockNode(editorAnalyticsAPI),
|
|
93
|
-
// Hooking up here for demo purposes. To be revisited with ED-24222.
|
|
94
93
|
title: isWrapped ? formatMessage(codeBlockButtonMessages.unwrapCode) : formatMessage(codeBlockButtonMessages.wrapCode),
|
|
95
94
|
tabIndex: null,
|
|
96
95
|
selected: isWrapped
|
package/dist/es2019/utils.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
export { findCodeBlock, transformSliceToJoinAdjacentCodeBlocks, transformSingleLineCodeBlockToCodeMark } from '@atlaskit/editor-common/transforms';
|
|
2
2
|
export function getCursor(selection) {
|
|
3
3
|
return selection.$cursor || undefined;
|
|
4
|
+
}
|
|
5
|
+
export function getAllCodeBlockNodesInDoc(state) {
|
|
6
|
+
const codeBlockNodes = [];
|
|
7
|
+
state.doc.descendants((node, pos) => {
|
|
8
|
+
if (node.type === state.schema.nodes.codeBlock) {
|
|
9
|
+
codeBlockNodes.push({
|
|
10
|
+
node,
|
|
11
|
+
pos
|
|
12
|
+
});
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
});
|
|
17
|
+
return codeBlockNodes;
|
|
4
18
|
}
|
|
@@ -2,7 +2,7 @@ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
|
2
2
|
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
3
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
4
4
|
import rafSchedule from 'raf-schd';
|
|
5
|
-
import { transferCodeBlockWrappedValue } from '@atlaskit/editor-common/code-block';
|
|
5
|
+
import { codeBlockWrappedStates, defaultWordWrapState, transferCodeBlockWrappedValue } from '@atlaskit/editor-common/code-block';
|
|
6
6
|
import { browser } from '@atlaskit/editor-common/utils';
|
|
7
7
|
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
8
8
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
@@ -10,7 +10,7 @@ import { resetShouldIgnoreFollowingMutations } from '../actions';
|
|
|
10
10
|
import { getPluginState } from '../pm-plugins/main-state';
|
|
11
11
|
import { codeBlockClassNames } from '../ui/class-names';
|
|
12
12
|
var MATCH_NEWLINES = new RegExp('\n', 'g');
|
|
13
|
-
var toDOM = function toDOM(node, contentEditable) {
|
|
13
|
+
var toDOM = function toDOM(node, contentEditable, formattedAriaLabel) {
|
|
14
14
|
return ['div', {
|
|
15
15
|
class: 'code-block'
|
|
16
16
|
}, ['div', {
|
|
@@ -27,17 +27,19 @@ var toDOM = function toDOM(node, contentEditable) {
|
|
|
27
27
|
'data-language': node.attrs.language || '',
|
|
28
28
|
spellcheck: 'false',
|
|
29
29
|
contenteditable: fg('platform.editor.live-view.disable-editing-in-view-mode_fi1rx') ? contentEditable ? 'true' : 'false' : 'true',
|
|
30
|
-
'data-testid': 'code-block--code'
|
|
30
|
+
'data-testid': 'code-block--code',
|
|
31
|
+
'aria-label': formattedAriaLabel
|
|
31
32
|
}, 0]]], ['div', {
|
|
32
33
|
class: codeBlockClassNames.end,
|
|
33
34
|
contenteditable: 'false'
|
|
34
35
|
}]];
|
|
35
36
|
};
|
|
36
37
|
export var CodeBlockView = /*#__PURE__*/function () {
|
|
37
|
-
function CodeBlockView(_node, view, getPos, api, cleanupEditorDisabledListener) {
|
|
38
|
+
function CodeBlockView(_node, view, getPos, formattedAriaLabel, api, cleanupEditorDisabledListener) {
|
|
38
39
|
var _this = this,
|
|
39
40
|
_api$editorDisabled;
|
|
40
41
|
_classCallCheck(this, CodeBlockView);
|
|
42
|
+
_defineProperty(this, "formattedAriaLabel", '');
|
|
41
43
|
_defineProperty(this, "ensureLineNumbers", rafSchedule(function () {
|
|
42
44
|
var lines = 1;
|
|
43
45
|
_this.node.forEach(function (node) {
|
|
@@ -68,7 +70,7 @@ export var CodeBlockView = /*#__PURE__*/function () {
|
|
|
68
70
|
_this.dom.style.setProperty('--lineNumberGutterWidth', "".concat(maxDigits, "ch"));
|
|
69
71
|
});
|
|
70
72
|
this.cleanupEditorDisabledListener = cleanupEditorDisabledListener;
|
|
71
|
-
var _DOMSerializer$render = DOMSerializer.renderSpec(document, toDOM(_node, !(api !== null && api !== void 0 && (_api$editorDisabled = api.editorDisabled) !== null && _api$editorDisabled !== void 0 && (_api$editorDisabled = _api$editorDisabled.sharedState.currentState()) !== null && _api$editorDisabled !== void 0 && _api$editorDisabled.editorDisabled))),
|
|
73
|
+
var _DOMSerializer$render = DOMSerializer.renderSpec(document, toDOM(_node, !(api !== null && api !== void 0 && (_api$editorDisabled = api.editorDisabled) !== null && _api$editorDisabled !== void 0 && (_api$editorDisabled = _api$editorDisabled.sharedState.currentState()) !== null && _api$editorDisabled !== void 0 && _api$editorDisabled.editorDisabled), formattedAriaLabel)),
|
|
72
74
|
dom = _DOMSerializer$render.dom,
|
|
73
75
|
contentDOM = _DOMSerializer$render.contentDOM;
|
|
74
76
|
this.getPos = getPos;
|
|
@@ -80,6 +82,12 @@ export var CodeBlockView = /*#__PURE__*/function () {
|
|
|
80
82
|
this.api = api;
|
|
81
83
|
if (fg('editor_support_code_block_wrapping')) {
|
|
82
84
|
this.maintainDynamicGutterSize();
|
|
85
|
+
|
|
86
|
+
// Ensure the code block node has a wrapped state.
|
|
87
|
+
// Wrapped state may already exist from breakout's recreating the node.
|
|
88
|
+
if (!codeBlockWrappedStates.has(_node)) {
|
|
89
|
+
codeBlockWrappedStates.set(_node, defaultWordWrapState);
|
|
90
|
+
}
|
|
83
91
|
} else {
|
|
84
92
|
this.ensureLineNumbers();
|
|
85
93
|
}
|
|
@@ -192,6 +200,6 @@ export var CodeBlockView = /*#__PURE__*/function () {
|
|
|
192
200
|
}]);
|
|
193
201
|
return CodeBlockView;
|
|
194
202
|
}();
|
|
195
|
-
export var codeBlockNodeView = function codeBlockNodeView(node, view, getPos, api) {
|
|
196
|
-
return new CodeBlockView(node, view, getPos, api);
|
|
203
|
+
export var codeBlockNodeView = function codeBlockNodeView(node, view, getPos, formattedAriaLabel, api) {
|
|
204
|
+
return new CodeBlockView(node, view, getPos, formattedAriaLabel, api);
|
|
197
205
|
};
|
|
@@ -1,10 +1,61 @@
|
|
|
1
1
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
2
|
+
import { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
|
|
2
3
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
3
4
|
import { codeBlockClassNames } from '../ui/class-names';
|
|
5
|
+
import { getAllCodeBlockNodesInDoc } from '../utils';
|
|
4
6
|
export var DECORATION_WIDGET_TYPE = 'decorationWidgetType';
|
|
5
|
-
export var
|
|
7
|
+
export var DECORATION_WRAPPED_BLOCK_NODE_TYPE = 'decorationNodeType';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Generate the initial decorations for the code block.
|
|
11
|
+
*/
|
|
12
|
+
export var generateInitialDecorations = function generateInitialDecorations(state) {
|
|
13
|
+
var codeBlockNodes = getAllCodeBlockNodesInDoc(state);
|
|
14
|
+
return codeBlockNodes.flatMap(function (node) {
|
|
15
|
+
return createLineNumbersDecorations(node);
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Update all the decorations used by the code block.
|
|
21
|
+
*/
|
|
22
|
+
export var updateCodeBlockDecorations = function updateCodeBlockDecorations(tr, state, decorationSet) {
|
|
23
|
+
var updatedDecorationSet = decorationSet;
|
|
24
|
+
var codeBlockNodes = getAllCodeBlockNodesInDoc(state);
|
|
25
|
+
|
|
26
|
+
// All the line numbers decorators are refreshed on doc change.
|
|
27
|
+
updatedDecorationSet = updateDecorationSetWithLineNumberDecorators(tr, codeBlockNodes, updatedDecorationSet);
|
|
28
|
+
|
|
29
|
+
// Check to make sure the word wrap decorators are still valid.
|
|
30
|
+
updatedDecorationSet = validateWordWrappedDecorators(tr, codeBlockNodes, updatedDecorationSet);
|
|
31
|
+
return updatedDecorationSet;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Update the decorations set with the line number decorators.
|
|
36
|
+
*/
|
|
37
|
+
export var updateDecorationSetWithLineNumberDecorators = function updateDecorationSetWithLineNumberDecorators(tr, codeBlockNodes, decorationSet) {
|
|
38
|
+
var updatedDecorationSet = decorationSet;
|
|
39
|
+
// remove all the line number children from the decorations set. 'undefined, undefined' is used to find() the whole doc.
|
|
40
|
+
var children = updatedDecorationSet.find(undefined, undefined, function (spec) {
|
|
41
|
+
return spec.type === DECORATION_WIDGET_TYPE;
|
|
42
|
+
});
|
|
43
|
+
updatedDecorationSet = updatedDecorationSet.remove(children);
|
|
44
|
+
|
|
45
|
+
// regenerate all the line number for the documents code blocks
|
|
46
|
+
var lineNumberDecorators = [];
|
|
47
|
+
codeBlockNodes.forEach(function (node) {
|
|
48
|
+
lineNumberDecorators.push.apply(lineNumberDecorators, _toConsumableArray(createLineNumbersDecorations(node)));
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// add the newly generated line numbers to the decorations set
|
|
52
|
+
return updatedDecorationSet.add(tr.doc, [].concat(lineNumberDecorators));
|
|
53
|
+
};
|
|
54
|
+
export var generateLineAttributesFromNode = function generateLineAttributesFromNode(node) {
|
|
55
|
+
var innerNode = node.node,
|
|
56
|
+
pos = node.pos;
|
|
6
57
|
// Get content node
|
|
7
|
-
var contentNode =
|
|
58
|
+
var contentNode = innerNode.content;
|
|
8
59
|
|
|
9
60
|
// Get node text content
|
|
10
61
|
var lineAttributes = [];
|
|
@@ -57,6 +108,60 @@ export var createDecorationSetFromLineAttributes = function createDecorationSetF
|
|
|
57
108
|
});
|
|
58
109
|
return widgetDecorations;
|
|
59
110
|
};
|
|
60
|
-
export var createLineNumbersDecorations = function createLineNumbersDecorations(
|
|
61
|
-
return createDecorationSetFromLineAttributes(generateLineAttributesFromNode(
|
|
111
|
+
export var createLineNumbersDecorations = function createLineNumbersDecorations(node) {
|
|
112
|
+
return createDecorationSetFromLineAttributes(generateLineAttributesFromNode(node));
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* There are edge cases like when a user drags and drops a code block node where the decorator breaks and no longer reflects
|
|
117
|
+
* the correct word wrap state. This function validates that the decorator and the state are in line, otherwise it will
|
|
118
|
+
* retrigger the logic to apply the word wrap decorator.
|
|
119
|
+
*/
|
|
120
|
+
export var validateWordWrappedDecorators = function validateWordWrappedDecorators(tr, codeBlockNodes, decorationSet) {
|
|
121
|
+
var updatedDecorationSet = decorationSet;
|
|
122
|
+
codeBlockNodes.forEach(function (node) {
|
|
123
|
+
var isCodeBlockWrappedInState = isCodeBlockWordWrapEnabled(node.node);
|
|
124
|
+
var isCodeBlockWrappedByDecorator = getWordWrapDecoratorsFromNodePos(node.pos, decorationSet).length !== 0;
|
|
125
|
+
if (isCodeBlockWrappedInState && !isCodeBlockWrappedByDecorator) {
|
|
126
|
+
updatedDecorationSet = updateDecorationSetWithWordWrappedDecorator(decorationSet, tr, node);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return updatedDecorationSet;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Update the decoration set with the word wrap decorator.
|
|
134
|
+
*/
|
|
135
|
+
export var updateDecorationSetWithWordWrappedDecorator = function updateDecorationSetWithWordWrappedDecorator(decorationSet, tr, node) {
|
|
136
|
+
if (!node || node.pos === undefined) {
|
|
137
|
+
return decorationSet;
|
|
138
|
+
}
|
|
139
|
+
var updatedDecorationSet = decorationSet;
|
|
140
|
+
var pos = node.pos,
|
|
141
|
+
innerNode = node.node;
|
|
142
|
+
var isNodeWrapped = isCodeBlockWordWrapEnabled(innerNode);
|
|
143
|
+
if (!isNodeWrapped) {
|
|
144
|
+
var currentWrappedBlockDecorationSet = getWordWrapDecoratorsFromNodePos(pos, updatedDecorationSet);
|
|
145
|
+
updatedDecorationSet = updatedDecorationSet.remove(currentWrappedBlockDecorationSet);
|
|
146
|
+
} else {
|
|
147
|
+
var wrappedBlock = Decoration.node(pos, pos + innerNode.nodeSize, {
|
|
148
|
+
class: codeBlockClassNames.contentFgWrapped
|
|
149
|
+
}, {
|
|
150
|
+
type: DECORATION_WRAPPED_BLOCK_NODE_TYPE
|
|
151
|
+
} // Allows for quick filtering of decorations while using `find`
|
|
152
|
+
);
|
|
153
|
+
updatedDecorationSet = updatedDecorationSet.add(tr.doc, [wrappedBlock]);
|
|
154
|
+
}
|
|
155
|
+
return updatedDecorationSet;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get the word wrap decorators for the given node position.
|
|
160
|
+
*/
|
|
161
|
+
export var getWordWrapDecoratorsFromNodePos = function getWordWrapDecoratorsFromNodePos(pos, decorationSet) {
|
|
162
|
+
var codeBlockNodePosition = pos + 1; // We need to add 1 to the position to get the start of the node.
|
|
163
|
+
var currentWrappedBlockDecorationSet = decorationSet.find(codeBlockNodePosition, codeBlockNodePosition, function (spec) {
|
|
164
|
+
return spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE;
|
|
165
|
+
});
|
|
166
|
+
return currentWrappedBlockDecorationSet;
|
|
62
167
|
};
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
-
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
2
|
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; }
|
|
4
3
|
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) { _defineProperty(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; }
|
|
5
|
-
import {
|
|
4
|
+
import { blockTypeMessages } from '@atlaskit/editor-common/messages';
|
|
6
5
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
7
6
|
import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
|
|
8
7
|
import { browser } from '@atlaskit/editor-common/utils';
|
|
9
8
|
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
10
|
-
import {
|
|
9
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
11
10
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
12
11
|
import { ignoreFollowingMutations, resetShouldIgnoreFollowingMutations } from '../actions';
|
|
13
12
|
import { codeBlockNodeView } from '../nodeviews/code-block';
|
|
@@ -15,8 +14,7 @@ import { pluginKey } from '../plugin-key';
|
|
|
15
14
|
import { codeBlockClassNames } from '../ui/class-names';
|
|
16
15
|
import { findCodeBlock } from '../utils';
|
|
17
16
|
import { ACTIONS } from './actions';
|
|
18
|
-
import {
|
|
19
|
-
var DECORATION_WRAPPED_BLOCK_NODE_TYPE = 'decorationNodeType';
|
|
17
|
+
import { generateInitialDecorations, updateCodeBlockDecorations, updateDecorationSetWithWordWrappedDecorator } from './decorators';
|
|
20
18
|
export var createPlugin = function createPlugin(_ref) {
|
|
21
19
|
var _ref$useLongPressSele = _ref.useLongPressSelection,
|
|
22
20
|
useLongPressSelection = _ref$useLongPressSele === void 0 ? false : _ref$useLongPressSele,
|
|
@@ -25,57 +23,6 @@ export var createPlugin = function createPlugin(_ref) {
|
|
|
25
23
|
allowCompositionInputOverride = _ref$allowComposition === void 0 ? false : _ref$allowComposition,
|
|
26
24
|
api = _ref.api;
|
|
27
25
|
var handleDOMEvents = {};
|
|
28
|
-
var createLineNumberDecoratorsFromDecendants = function createLineNumberDecoratorsFromDecendants(editorState) {
|
|
29
|
-
var lineNumberDecorators = [];
|
|
30
|
-
editorState.doc.descendants(function (node, pos) {
|
|
31
|
-
if (node.type === editorState.schema.nodes.codeBlock) {
|
|
32
|
-
lineNumberDecorators.push.apply(lineNumberDecorators, _toConsumableArray(createLineNumbersDecorations(pos, node)));
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
return true;
|
|
36
|
-
});
|
|
37
|
-
return lineNumberDecorators;
|
|
38
|
-
};
|
|
39
|
-
var createWordWrappedDecoratorPluginState = function createWordWrappedDecoratorPluginState(pluginState, tr, node) {
|
|
40
|
-
var decorationSetFromState = pluginState.decorations;
|
|
41
|
-
if (node) {
|
|
42
|
-
var pos = node.pos,
|
|
43
|
-
innerNode = node.node;
|
|
44
|
-
if (pos !== undefined) {
|
|
45
|
-
var isNodeWrapped = isCodeBlockWordWrapEnabled(innerNode);
|
|
46
|
-
if (!isNodeWrapped) {
|
|
47
|
-
// Restricts the range of decorators to the current node while not including the previous nodes position in range
|
|
48
|
-
var codeBlockNodePosition = pos + 1;
|
|
49
|
-
var currentWrappedBlockDecorationSet = decorationSetFromState.find(codeBlockNodePosition, codeBlockNodePosition, function (spec) {
|
|
50
|
-
return spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE;
|
|
51
|
-
});
|
|
52
|
-
decorationSetFromState = decorationSetFromState.remove(currentWrappedBlockDecorationSet);
|
|
53
|
-
} else {
|
|
54
|
-
var wrappedBlock = Decoration.node(pos, pos + innerNode.nodeSize, {
|
|
55
|
-
class: codeBlockClassNames.contentFgWrapped
|
|
56
|
-
}, {
|
|
57
|
-
type: DECORATION_WRAPPED_BLOCK_NODE_TYPE
|
|
58
|
-
} // Allows for quick filtering of decorations while using `find`
|
|
59
|
-
);
|
|
60
|
-
decorationSetFromState = decorationSetFromState.add(tr.doc, [wrappedBlock]);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return decorationSetFromState;
|
|
65
|
-
};
|
|
66
|
-
var updateLineDecorationSet = function updateLineDecorationSet(tr, state, decorationSet) {
|
|
67
|
-
// remove all the line number children from the decorations set. 'undefined, undefined' is used to find() the whole doc.
|
|
68
|
-
var children = decorationSet.find(undefined, undefined, function (spec) {
|
|
69
|
-
return spec.type === DECORATION_WIDGET_TYPE;
|
|
70
|
-
});
|
|
71
|
-
decorationSet = decorationSet.remove(children);
|
|
72
|
-
|
|
73
|
-
// regenerate all the line number for the documents code blocks
|
|
74
|
-
var lineDecorators = createLineNumberDecoratorsFromDecendants(state);
|
|
75
|
-
|
|
76
|
-
// add the newly generated line numbers to the decorations set
|
|
77
|
-
return decorationSet.add(tr.doc, _toConsumableArray(lineDecorators));
|
|
78
|
-
};
|
|
79
26
|
|
|
80
27
|
// ME-1599: Composition on mobile was causing the DOM observer to mutate the code block
|
|
81
28
|
// incorrecly and lose content when pressing enter in the middle of a code block line.
|
|
@@ -119,13 +66,13 @@ export var createPlugin = function createPlugin(_ref) {
|
|
|
119
66
|
state: {
|
|
120
67
|
init: function init(_, state) {
|
|
121
68
|
var node = findCodeBlock(state, state.selection);
|
|
122
|
-
var
|
|
69
|
+
var initialDecorations = fg('editor_support_code_block_wrapping') ? generateInitialDecorations(state) : [];
|
|
123
70
|
return {
|
|
124
71
|
pos: node ? node.pos : null,
|
|
125
72
|
contentCopied: false,
|
|
126
73
|
isNodeSelected: false,
|
|
127
74
|
shouldIgnoreFollowingMutations: false,
|
|
128
|
-
decorations: DecorationSet.create(state.doc,
|
|
75
|
+
decorations: DecorationSet.create(state.doc, initialDecorations)
|
|
129
76
|
};
|
|
130
77
|
},
|
|
131
78
|
apply: function apply(tr, pluginState, _oldState, newState) {
|
|
@@ -133,18 +80,18 @@ export var createPlugin = function createPlugin(_ref) {
|
|
|
133
80
|
if ((meta === null || meta === void 0 ? void 0 : meta.type) === ACTIONS.SET_IS_WRAPPED && fg('editor_support_code_block_wrapping')) {
|
|
134
81
|
var node = findCodeBlock(newState, tr.selection);
|
|
135
82
|
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
136
|
-
decorations:
|
|
83
|
+
decorations: updateDecorationSetWithWordWrappedDecorator(pluginState.decorations, tr, node)
|
|
137
84
|
});
|
|
138
85
|
}
|
|
139
86
|
if (tr.docChanged) {
|
|
140
87
|
var _node = findCodeBlock(newState, tr.selection);
|
|
141
88
|
|
|
142
89
|
// Updates mapping position of all existing decorations to new positions
|
|
143
|
-
// specifically used for updating word wrap node decorators
|
|
90
|
+
// specifically used for updating word wrap node decorators (does not cover drag & drop, validateWordWrappedDecorators does).
|
|
144
91
|
var updatedDecorationSet = pluginState.decorations.map(tr.mapping, tr.doc);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
92
|
+
if (fg('editor_support_code_block_wrapping')) {
|
|
93
|
+
updatedDecorationSet = updateCodeBlockDecorations(tr, newState, updatedDecorationSet);
|
|
94
|
+
}
|
|
148
95
|
var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
149
96
|
pos: _node ? _node.pos : null,
|
|
150
97
|
isNodeSelected: tr.selection instanceof NodeSelection,
|
|
@@ -182,7 +129,10 @@ export var createPlugin = function createPlugin(_ref) {
|
|
|
182
129
|
},
|
|
183
130
|
nodeViews: {
|
|
184
131
|
codeBlock: function codeBlock(node, view, getPos) {
|
|
185
|
-
|
|
132
|
+
var _getIntl = getIntl(),
|
|
133
|
+
formatMessage = _getIntl.formatMessage;
|
|
134
|
+
var formattedAriaLabel = formatMessage(blockTypeMessages.codeblock);
|
|
135
|
+
return codeBlockNodeView(node, view, getPos, formattedAriaLabel, api);
|
|
186
136
|
}
|
|
187
137
|
},
|
|
188
138
|
handleClickOn: createSelectionClickHandler(['codeBlock'], function (target) {
|
package/dist/esm/toolbar.js
CHANGED
|
@@ -99,7 +99,6 @@ export var getToolbarConfig = function getToolbarConfig() {
|
|
|
99
99
|
supportsViewMode: true,
|
|
100
100
|
icon: WrapIcon,
|
|
101
101
|
onClick: toggleWordWrapStateForCodeBlockNode(editorAnalyticsAPI),
|
|
102
|
-
// Hooking up here for demo purposes. To be revisited with ED-24222.
|
|
103
102
|
title: isWrapped ? formatMessage(codeBlockButtonMessages.unwrapCode) : formatMessage(codeBlockButtonMessages.wrapCode),
|
|
104
103
|
tabIndex: null,
|
|
105
104
|
selected: isWrapped
|
package/dist/esm/utils.js
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
export { findCodeBlock, transformSliceToJoinAdjacentCodeBlocks, transformSingleLineCodeBlockToCodeMark } from '@atlaskit/editor-common/transforms';
|
|
2
2
|
export function getCursor(selection) {
|
|
3
3
|
return selection.$cursor || undefined;
|
|
4
|
+
}
|
|
5
|
+
export function getAllCodeBlockNodesInDoc(state) {
|
|
6
|
+
var codeBlockNodes = [];
|
|
7
|
+
state.doc.descendants(function (node, pos) {
|
|
8
|
+
if (node.type === state.schema.nodes.codeBlock) {
|
|
9
|
+
codeBlockNodes.push({
|
|
10
|
+
node: node,
|
|
11
|
+
pos: pos
|
|
12
|
+
});
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
});
|
|
17
|
+
return codeBlockNodes;
|
|
4
18
|
}
|
|
@@ -10,8 +10,9 @@ export declare class CodeBlockView {
|
|
|
10
10
|
lineNumberGutter: HTMLElement;
|
|
11
11
|
getPos: getPosHandlerNode;
|
|
12
12
|
view: EditorView;
|
|
13
|
+
formattedAriaLabel: string;
|
|
13
14
|
api?: ExtractInjectionAPI<CodeBlockPlugin>;
|
|
14
|
-
constructor(node: Node, view: EditorView, getPos: getPosHandlerNode, api?: ExtractInjectionAPI<CodeBlockPlugin>, cleanupEditorDisabledListener?: (() => void) | undefined);
|
|
15
|
+
constructor(node: Node, view: EditorView, getPos: getPosHandlerNode, formattedAriaLabel: string, api?: ExtractInjectionAPI<CodeBlockPlugin>, cleanupEditorDisabledListener?: (() => void) | undefined);
|
|
15
16
|
handleEditorDisabledChanged(): void;
|
|
16
17
|
updateDOMAndSelection(savedInnerHTML: string, newCursorPosition: number): void;
|
|
17
18
|
coalesceDOMElements(): void;
|
|
@@ -27,4 +28,4 @@ export declare class CodeBlockView {
|
|
|
27
28
|
}): boolean;
|
|
28
29
|
destroy(): void;
|
|
29
30
|
}
|
|
30
|
-
export declare const codeBlockNodeView: (node: Node, view: EditorView, getPos: getPosHandler, api: ExtractInjectionAPI<CodeBlockPlugin> | undefined) => CodeBlockView;
|
|
31
|
+
export declare const codeBlockNodeView: (node: Node, view: EditorView, getPos: getPosHandler, formattedAriaLabel: string, api: ExtractInjectionAPI<CodeBlockPlugin> | undefined) => CodeBlockView;
|
|
@@ -1,7 +1,35 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
1
|
+
import { type EditorState, type ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import { type NodeWithPos } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
+
import { Decoration, type DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
3
4
|
import type { CodeBlockLineAttributes } from '../types';
|
|
4
5
|
export declare const DECORATION_WIDGET_TYPE = "decorationWidgetType";
|
|
5
|
-
export declare const
|
|
6
|
+
export declare const DECORATION_WRAPPED_BLOCK_NODE_TYPE = "decorationNodeType";
|
|
7
|
+
/**
|
|
8
|
+
* Generate the initial decorations for the code block.
|
|
9
|
+
*/
|
|
10
|
+
export declare const generateInitialDecorations: (state: EditorState) => Decoration[];
|
|
11
|
+
/**
|
|
12
|
+
* Update all the decorations used by the code block.
|
|
13
|
+
*/
|
|
14
|
+
export declare const updateCodeBlockDecorations: (tr: ReadonlyTransaction, state: EditorState, decorationSet: DecorationSet) => DecorationSet;
|
|
15
|
+
/**
|
|
16
|
+
* Update the decorations set with the line number decorators.
|
|
17
|
+
*/
|
|
18
|
+
export declare const updateDecorationSetWithLineNumberDecorators: (tr: ReadonlyTransaction, codeBlockNodes: NodeWithPos[], decorationSet: DecorationSet) => DecorationSet;
|
|
19
|
+
export declare const generateLineAttributesFromNode: (node: NodeWithPos) => CodeBlockLineAttributes[];
|
|
6
20
|
export declare const createDecorationSetFromLineAttributes: (lineAttributes: CodeBlockLineAttributes[]) => Decoration[];
|
|
7
|
-
export declare const createLineNumbersDecorations: (
|
|
21
|
+
export declare const createLineNumbersDecorations: (node: NodeWithPos) => Decoration[];
|
|
22
|
+
/**
|
|
23
|
+
* There are edge cases like when a user drags and drops a code block node where the decorator breaks and no longer reflects
|
|
24
|
+
* the correct word wrap state. This function validates that the decorator and the state are in line, otherwise it will
|
|
25
|
+
* retrigger the logic to apply the word wrap decorator.
|
|
26
|
+
*/
|
|
27
|
+
export declare const validateWordWrappedDecorators: (tr: ReadonlyTransaction, codeBlockNodes: NodeWithPos[], decorationSet: DecorationSet) => DecorationSet;
|
|
28
|
+
/**
|
|
29
|
+
* Update the decoration set with the word wrap decorator.
|
|
30
|
+
*/
|
|
31
|
+
export declare const updateDecorationSetWithWordWrappedDecorator: (decorationSet: DecorationSet, tr: ReadonlyTransaction, node: NodeWithPos | undefined) => DecorationSet;
|
|
32
|
+
/**
|
|
33
|
+
* Get the word wrap decorators for the given node position.
|
|
34
|
+
*/
|
|
35
|
+
export declare const getWordWrapDecoratorsFromNodePos: (pos: number, decorationSet: DecorationSet) => Decoration[];
|
package/dist/types/utils.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { findCodeBlock, transformSliceToJoinAdjacentCodeBlocks, transformSingleLineCodeBlockToCodeMark, } from '@atlaskit/editor-common/transforms';
|
|
2
2
|
import type { ResolvedPos } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
-
import type { Selection } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import type { NodeWithPos } from '@atlaskit/editor-prosemirror/utils';
|
|
4
5
|
export declare function getCursor(selection: Selection): ResolvedPos | undefined;
|
|
6
|
+
export declare function getAllCodeBlockNodesInDoc(state: EditorState): NodeWithPos[];
|
|
@@ -10,8 +10,9 @@ export declare class CodeBlockView {
|
|
|
10
10
|
lineNumberGutter: HTMLElement;
|
|
11
11
|
getPos: getPosHandlerNode;
|
|
12
12
|
view: EditorView;
|
|
13
|
+
formattedAriaLabel: string;
|
|
13
14
|
api?: ExtractInjectionAPI<CodeBlockPlugin>;
|
|
14
|
-
constructor(node: Node, view: EditorView, getPos: getPosHandlerNode, api?: ExtractInjectionAPI<CodeBlockPlugin>, cleanupEditorDisabledListener?: (() => void) | undefined);
|
|
15
|
+
constructor(node: Node, view: EditorView, getPos: getPosHandlerNode, formattedAriaLabel: string, api?: ExtractInjectionAPI<CodeBlockPlugin>, cleanupEditorDisabledListener?: (() => void) | undefined);
|
|
15
16
|
handleEditorDisabledChanged(): void;
|
|
16
17
|
updateDOMAndSelection(savedInnerHTML: string, newCursorPosition: number): void;
|
|
17
18
|
coalesceDOMElements(): void;
|
|
@@ -27,4 +28,4 @@ export declare class CodeBlockView {
|
|
|
27
28
|
}): boolean;
|
|
28
29
|
destroy(): void;
|
|
29
30
|
}
|
|
30
|
-
export declare const codeBlockNodeView: (node: Node, view: EditorView, getPos: getPosHandler, api: ExtractInjectionAPI<CodeBlockPlugin> | undefined) => CodeBlockView;
|
|
31
|
+
export declare const codeBlockNodeView: (node: Node, view: EditorView, getPos: getPosHandler, formattedAriaLabel: string, api: ExtractInjectionAPI<CodeBlockPlugin> | undefined) => CodeBlockView;
|
|
@@ -1,7 +1,35 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
1
|
+
import { type EditorState, type ReadonlyTransaction } from '@atlaskit/editor-prosemirror/state';
|
|
2
|
+
import { type NodeWithPos } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
+
import { Decoration, type DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
3
4
|
import type { CodeBlockLineAttributes } from '../types';
|
|
4
5
|
export declare const DECORATION_WIDGET_TYPE = "decorationWidgetType";
|
|
5
|
-
export declare const
|
|
6
|
+
export declare const DECORATION_WRAPPED_BLOCK_NODE_TYPE = "decorationNodeType";
|
|
7
|
+
/**
|
|
8
|
+
* Generate the initial decorations for the code block.
|
|
9
|
+
*/
|
|
10
|
+
export declare const generateInitialDecorations: (state: EditorState) => Decoration[];
|
|
11
|
+
/**
|
|
12
|
+
* Update all the decorations used by the code block.
|
|
13
|
+
*/
|
|
14
|
+
export declare const updateCodeBlockDecorations: (tr: ReadonlyTransaction, state: EditorState, decorationSet: DecorationSet) => DecorationSet;
|
|
15
|
+
/**
|
|
16
|
+
* Update the decorations set with the line number decorators.
|
|
17
|
+
*/
|
|
18
|
+
export declare const updateDecorationSetWithLineNumberDecorators: (tr: ReadonlyTransaction, codeBlockNodes: NodeWithPos[], decorationSet: DecorationSet) => DecorationSet;
|
|
19
|
+
export declare const generateLineAttributesFromNode: (node: NodeWithPos) => CodeBlockLineAttributes[];
|
|
6
20
|
export declare const createDecorationSetFromLineAttributes: (lineAttributes: CodeBlockLineAttributes[]) => Decoration[];
|
|
7
|
-
export declare const createLineNumbersDecorations: (
|
|
21
|
+
export declare const createLineNumbersDecorations: (node: NodeWithPos) => Decoration[];
|
|
22
|
+
/**
|
|
23
|
+
* There are edge cases like when a user drags and drops a code block node where the decorator breaks and no longer reflects
|
|
24
|
+
* the correct word wrap state. This function validates that the decorator and the state are in line, otherwise it will
|
|
25
|
+
* retrigger the logic to apply the word wrap decorator.
|
|
26
|
+
*/
|
|
27
|
+
export declare const validateWordWrappedDecorators: (tr: ReadonlyTransaction, codeBlockNodes: NodeWithPos[], decorationSet: DecorationSet) => DecorationSet;
|
|
28
|
+
/**
|
|
29
|
+
* Update the decoration set with the word wrap decorator.
|
|
30
|
+
*/
|
|
31
|
+
export declare const updateDecorationSetWithWordWrappedDecorator: (decorationSet: DecorationSet, tr: ReadonlyTransaction, node: NodeWithPos | undefined) => DecorationSet;
|
|
32
|
+
/**
|
|
33
|
+
* Get the word wrap decorators for the given node position.
|
|
34
|
+
*/
|
|
35
|
+
export declare const getWordWrapDecoratorsFromNodePos: (pos: number, decorationSet: DecorationSet) => Decoration[];
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { findCodeBlock, transformSliceToJoinAdjacentCodeBlocks, transformSingleLineCodeBlockToCodeMark, } from '@atlaskit/editor-common/transforms';
|
|
2
2
|
import type { ResolvedPos } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
-
import type { Selection } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import type { NodeWithPos } from '@atlaskit/editor-prosemirror/utils';
|
|
4
5
|
export declare function getCursor(selection: Selection): ResolvedPos | undefined;
|
|
6
|
+
export declare function getAllCodeBlockNodesInDoc(state: EditorState): NodeWithPos[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-code-block",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.10",
|
|
4
4
|
"description": "Code block plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -10,8 +10,6 @@
|
|
|
10
10
|
"atlassian": {
|
|
11
11
|
"team": "Editor: Core Experiences",
|
|
12
12
|
"singleton": true,
|
|
13
|
-
"inPublicMirror": false,
|
|
14
|
-
"releaseModel": "continuous",
|
|
15
13
|
"runReact18": false
|
|
16
14
|
},
|
|
17
15
|
"repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
|
|
@@ -34,8 +32,8 @@
|
|
|
34
32
|
},
|
|
35
33
|
"dependencies": {
|
|
36
34
|
"@atlaskit/adf-schema": "^40.9.0",
|
|
37
|
-
"@atlaskit/code": "^15.
|
|
38
|
-
"@atlaskit/editor-common": "^88.
|
|
35
|
+
"@atlaskit/code": "^15.6.0",
|
|
36
|
+
"@atlaskit/editor-common": "^88.5.0",
|
|
39
37
|
"@atlaskit/editor-plugin-analytics": "^1.8.0",
|
|
40
38
|
"@atlaskit/editor-plugin-composition": "^1.2.0",
|
|
41
39
|
"@atlaskit/editor-plugin-decorations": "^1.3.0",
|