@atlaskit/editor-plugin-code-block 3.3.9 → 3.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/cjs/nodeviews/code-block.js +6 -0
- package/dist/cjs/plugin.js +6 -0
- package/dist/cjs/pm-plugins/codeBlockAutoFullStopTransformPlugin.js +65 -0
- package/dist/cjs/pm-plugins/decorators.js +110 -5
- package/dist/cjs/pm-plugins/main.js +9 -63
- package/dist/cjs/toolbar.js +0 -1
- package/dist/cjs/utils.js +15 -0
- package/dist/es2019/nodeviews/code-block.js +7 -1
- package/dist/es2019/plugin.js +4 -0
- package/dist/es2019/pm-plugins/codeBlockAutoFullStopTransformPlugin.js +65 -0
- package/dist/es2019/pm-plugins/decorators.js +106 -3
- package/dist/es2019/pm-plugins/main.js +9 -60
- package/dist/es2019/toolbar.js +0 -1
- package/dist/es2019/utils.js +14 -0
- package/dist/esm/nodeviews/code-block.js +7 -1
- package/dist/esm/plugin.js +6 -0
- package/dist/esm/pm-plugins/codeBlockAutoFullStopTransformPlugin.js +58 -0
- package/dist/esm/pm-plugins/decorators.js +109 -4
- package/dist/esm/pm-plugins/main.js +9 -63
- package/dist/esm/toolbar.js +0 -1
- package/dist/esm/utils.js +14 -0
- package/dist/types/pm-plugins/codeBlockAutoFullStopTransformPlugin.d.ts +4 -0
- package/dist/types/pm-plugins/decorators.d.ts +32 -4
- package/dist/types/utils.d.ts +3 -1
- package/dist/types-ts4.5/pm-plugins/codeBlockAutoFullStopTransformPlugin.d.ts +4 -0
- 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 +5 -4
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
|
|
2
1
|
import { blockTypeMessages } from '@atlaskit/editor-common/messages';
|
|
3
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
4
3
|
import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
|
|
5
4
|
import { browser } from '@atlaskit/editor-common/utils';
|
|
6
5
|
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
7
|
-
import {
|
|
6
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
8
7
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
9
8
|
import { ignoreFollowingMutations, resetShouldIgnoreFollowingMutations } from '../actions';
|
|
10
9
|
import { codeBlockNodeView } from '../nodeviews/code-block';
|
|
@@ -12,8 +11,7 @@ import { pluginKey } from '../plugin-key';
|
|
|
12
11
|
import { codeBlockClassNames } from '../ui/class-names';
|
|
13
12
|
import { findCodeBlock } from '../utils';
|
|
14
13
|
import { ACTIONS } from './actions';
|
|
15
|
-
import {
|
|
16
|
-
const DECORATION_WRAPPED_BLOCK_NODE_TYPE = 'decorationNodeType';
|
|
14
|
+
import { generateInitialDecorations, updateCodeBlockDecorations, updateDecorationSetWithWordWrappedDecorator } from './decorators';
|
|
17
15
|
export const createPlugin = ({
|
|
18
16
|
useLongPressSelection = false,
|
|
19
17
|
getIntl,
|
|
@@ -21,55 +19,6 @@ export const createPlugin = ({
|
|
|
21
19
|
api
|
|
22
20
|
}) => {
|
|
23
21
|
const handleDOMEvents = {};
|
|
24
|
-
const createLineNumberDecoratorsFromDecendants = editorState => {
|
|
25
|
-
let lineNumberDecorators = [];
|
|
26
|
-
editorState.doc.descendants((node, pos) => {
|
|
27
|
-
if (node.type === editorState.schema.nodes.codeBlock) {
|
|
28
|
-
lineNumberDecorators.push(...createLineNumbersDecorations(pos, node));
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
return true;
|
|
32
|
-
});
|
|
33
|
-
return lineNumberDecorators;
|
|
34
|
-
};
|
|
35
|
-
const createWordWrappedDecoratorPluginState = (pluginState, tr, node) => {
|
|
36
|
-
let decorationSetFromState = pluginState.decorations;
|
|
37
|
-
if (node) {
|
|
38
|
-
const {
|
|
39
|
-
pos,
|
|
40
|
-
node: innerNode
|
|
41
|
-
} = node;
|
|
42
|
-
if (pos !== undefined) {
|
|
43
|
-
const isNodeWrapped = isCodeBlockWordWrapEnabled(innerNode);
|
|
44
|
-
if (!isNodeWrapped) {
|
|
45
|
-
// Restricts the range of decorators to the current node while not including the previous nodes position in range
|
|
46
|
-
const codeBlockNodePosition = pos + 1;
|
|
47
|
-
const currentWrappedBlockDecorationSet = decorationSetFromState.find(codeBlockNodePosition, codeBlockNodePosition, spec => spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE);
|
|
48
|
-
decorationSetFromState = decorationSetFromState.remove(currentWrappedBlockDecorationSet);
|
|
49
|
-
} else {
|
|
50
|
-
const wrappedBlock = Decoration.node(pos, pos + innerNode.nodeSize, {
|
|
51
|
-
class: codeBlockClassNames.contentFgWrapped
|
|
52
|
-
}, {
|
|
53
|
-
type: DECORATION_WRAPPED_BLOCK_NODE_TYPE
|
|
54
|
-
} // Allows for quick filtering of decorations while using `find`
|
|
55
|
-
);
|
|
56
|
-
decorationSetFromState = decorationSetFromState.add(tr.doc, [wrappedBlock]);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return decorationSetFromState;
|
|
61
|
-
};
|
|
62
|
-
const updateLineDecorationSet = (tr, state, decorationSet) => {
|
|
63
|
-
// remove all the line number children from the decorations set. 'undefined, undefined' is used to find() the whole doc.
|
|
64
|
-
const children = decorationSet.find(undefined, undefined, spec => spec.type === DECORATION_WIDGET_TYPE);
|
|
65
|
-
decorationSet = decorationSet.remove(children);
|
|
66
|
-
|
|
67
|
-
// regenerate all the line number for the documents code blocks
|
|
68
|
-
const lineDecorators = createLineNumberDecoratorsFromDecendants(state);
|
|
69
|
-
|
|
70
|
-
// add the newly generated line numbers to the decorations set
|
|
71
|
-
return decorationSet.add(tr.doc, [...lineDecorators]);
|
|
72
|
-
};
|
|
73
22
|
|
|
74
23
|
// ME-1599: Composition on mobile was causing the DOM observer to mutate the code block
|
|
75
24
|
// incorrecly and lose content when pressing enter in the middle of a code block line.
|
|
@@ -111,13 +60,13 @@ export const createPlugin = ({
|
|
|
111
60
|
state: {
|
|
112
61
|
init(_, state) {
|
|
113
62
|
const node = findCodeBlock(state, state.selection);
|
|
114
|
-
const
|
|
63
|
+
const initialDecorations = fg('editor_support_code_block_wrapping') ? generateInitialDecorations(state) : [];
|
|
115
64
|
return {
|
|
116
65
|
pos: node ? node.pos : null,
|
|
117
66
|
contentCopied: false,
|
|
118
67
|
isNodeSelected: false,
|
|
119
68
|
shouldIgnoreFollowingMutations: false,
|
|
120
|
-
decorations: DecorationSet.create(state.doc,
|
|
69
|
+
decorations: DecorationSet.create(state.doc, initialDecorations)
|
|
121
70
|
};
|
|
122
71
|
},
|
|
123
72
|
apply(tr, pluginState, _oldState, newState) {
|
|
@@ -126,18 +75,18 @@ export const createPlugin = ({
|
|
|
126
75
|
const node = findCodeBlock(newState, tr.selection);
|
|
127
76
|
return {
|
|
128
77
|
...pluginState,
|
|
129
|
-
decorations:
|
|
78
|
+
decorations: updateDecorationSetWithWordWrappedDecorator(pluginState.decorations, tr, node)
|
|
130
79
|
};
|
|
131
80
|
}
|
|
132
81
|
if (tr.docChanged) {
|
|
133
82
|
const node = findCodeBlock(newState, tr.selection);
|
|
134
83
|
|
|
135
84
|
// Updates mapping position of all existing decorations to new positions
|
|
136
|
-
// specifically used for updating word wrap node decorators
|
|
85
|
+
// specifically used for updating word wrap node decorators (does not cover drag & drop, validateWordWrappedDecorators does).
|
|
137
86
|
let updatedDecorationSet = pluginState.decorations.map(tr.mapping, tr.doc);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
87
|
+
if (fg('editor_support_code_block_wrapping')) {
|
|
88
|
+
updatedDecorationSet = updateCodeBlockDecorations(tr, newState, updatedDecorationSet);
|
|
89
|
+
}
|
|
141
90
|
const newPluginState = {
|
|
142
91
|
...pluginState,
|
|
143
92
|
pos: node ? node.pos : null,
|
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';
|
|
@@ -82,6 +82,12 @@ export var CodeBlockView = /*#__PURE__*/function () {
|
|
|
82
82
|
this.api = api;
|
|
83
83
|
if (fg('editor_support_code_block_wrapping')) {
|
|
84
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
|
+
}
|
|
85
91
|
} else {
|
|
86
92
|
this.ensureLineNumbers();
|
|
87
93
|
}
|
package/dist/esm/plugin.js
CHANGED
|
@@ -7,6 +7,7 @@ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } f
|
|
|
7
7
|
import { blockTypeMessages } from '@atlaskit/editor-common/messages';
|
|
8
8
|
import { IconCode } from '@atlaskit/editor-common/quick-insert';
|
|
9
9
|
import { createInsertCodeBlockTransaction, insertCodeBlockWithAnalytics } from './actions';
|
|
10
|
+
import { codeBlockAutoFullStopTransformPlugin } from './pm-plugins/codeBlockAutoFullStopTransformPlugin';
|
|
10
11
|
import { codeBlockCopySelectionPlugin } from './pm-plugins/codeBlockCopySelectionPlugin';
|
|
11
12
|
import ideUX from './pm-plugins/ide-ux';
|
|
12
13
|
import { createCodeBlockInputRule } from './pm-plugins/input-rule';
|
|
@@ -58,6 +59,11 @@ var codeBlockPlugin = function codeBlockPlugin(_ref) {
|
|
|
58
59
|
plugin: function plugin() {
|
|
59
60
|
return codeBlockCopySelectionPlugin();
|
|
60
61
|
}
|
|
62
|
+
}, {
|
|
63
|
+
name: 'codeBlockAutoFullStopTransform',
|
|
64
|
+
plugin: function plugin() {
|
|
65
|
+
return codeBlockAutoFullStopTransformPlugin();
|
|
66
|
+
}
|
|
61
67
|
}];
|
|
62
68
|
},
|
|
63
69
|
// Workaround for a firefox issue where dom selection is off sync
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import { browser } from '@atlaskit/editor-common/utils';
|
|
3
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
5
|
+
import { findCodeBlock } from '../utils';
|
|
6
|
+
export var codeBlockAutoFullStopTransformPluginKey = new PluginKey('codeBlockAutoFullStopTransformPluginKey');
|
|
7
|
+
export function codeBlockAutoFullStopTransformPlugin() {
|
|
8
|
+
return new SafePlugin({
|
|
9
|
+
key: codeBlockAutoFullStopTransformPluginKey,
|
|
10
|
+
appendTransaction: function appendTransaction(_transactions, oldState, newState) {
|
|
11
|
+
if (!fg('editor_support_code_block_wrapping') || !fg('code_block_auto_insertion_bug_fix')) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// We need to compare the old and new state to isloate auto insertion of fullstop on mac
|
|
16
|
+
var trNew = newState.tr;
|
|
17
|
+
var trOld = oldState.tr;
|
|
18
|
+
var fromOld = trOld.selection.from;
|
|
19
|
+
var _trNew$selection = trNew.selection,
|
|
20
|
+
fromNew = _trNew$selection.from,
|
|
21
|
+
toNew = _trNew$selection.to;
|
|
22
|
+
var isCodeBlock = !!findCodeBlock(oldState, trOld.selection) && !!findCodeBlock(newState, trNew.selection);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Mac will auto insert a fullstop when the user double taps the space key after some content.
|
|
26
|
+
* Line number decorators are assumed content so on new lines the fullstop is inserted.
|
|
27
|
+
*
|
|
28
|
+
* - When a fulltop is auto inserted the new states selection is the same, the old state selection is one position less
|
|
29
|
+
* - The text returned for the old state returns as a space with the selection from - 1
|
|
30
|
+
* - The text returned for the new state returns as a fullstop with the selection from - 2 to from -1
|
|
31
|
+
*
|
|
32
|
+
* This is enough conditional logic to isoloate the auto insertion of the fullstop on mac
|
|
33
|
+
*
|
|
34
|
+
* There are some solutions to this problem in codemirror which can be read further here
|
|
35
|
+
* https://discuss.codemirror.net/t/dot-being-added-when-pressing-space-repeatedly/3899
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
// both selections must be of code block early exit
|
|
39
|
+
if (browser.mac && fromNew === toNew && fromNew === fromOld + 1 && isCodeBlock) {
|
|
40
|
+
// detect when '.' is inserted when the previous state was a space ' '
|
|
41
|
+
try {
|
|
42
|
+
var textBetweenBefore = trOld.doc.textBetween(fromOld - 1, fromOld); // ' '
|
|
43
|
+
var textBetweenAfter = trNew.doc.textBetween(fromNew - 2, fromNew - 1); // '.'
|
|
44
|
+
if (textBetweenBefore === ' ' && textBetweenAfter === '.') {
|
|
45
|
+
trNew.delete(fromNew - 2, fromNew); // remove the fullstop
|
|
46
|
+
trNew.insertText(' ', fromNew - 2); // insert double space
|
|
47
|
+
|
|
48
|
+
return trNew;
|
|
49
|
+
}
|
|
50
|
+
} catch (error) {
|
|
51
|
+
// if for some reason textBetween fails, just return the new transaction as is by defaut.
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
@@ -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,14 +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 { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
|
|
6
4
|
import { blockTypeMessages } from '@atlaskit/editor-common/messages';
|
|
7
5
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
8
6
|
import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
|
|
9
7
|
import { browser } from '@atlaskit/editor-common/utils';
|
|
10
8
|
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
11
|
-
import {
|
|
9
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
12
10
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
13
11
|
import { ignoreFollowingMutations, resetShouldIgnoreFollowingMutations } from '../actions';
|
|
14
12
|
import { codeBlockNodeView } from '../nodeviews/code-block';
|
|
@@ -16,8 +14,7 @@ import { pluginKey } from '../plugin-key';
|
|
|
16
14
|
import { codeBlockClassNames } from '../ui/class-names';
|
|
17
15
|
import { findCodeBlock } from '../utils';
|
|
18
16
|
import { ACTIONS } from './actions';
|
|
19
|
-
import {
|
|
20
|
-
var DECORATION_WRAPPED_BLOCK_NODE_TYPE = 'decorationNodeType';
|
|
17
|
+
import { generateInitialDecorations, updateCodeBlockDecorations, updateDecorationSetWithWordWrappedDecorator } from './decorators';
|
|
21
18
|
export var createPlugin = function createPlugin(_ref) {
|
|
22
19
|
var _ref$useLongPressSele = _ref.useLongPressSelection,
|
|
23
20
|
useLongPressSelection = _ref$useLongPressSele === void 0 ? false : _ref$useLongPressSele,
|
|
@@ -26,57 +23,6 @@ export var createPlugin = function createPlugin(_ref) {
|
|
|
26
23
|
allowCompositionInputOverride = _ref$allowComposition === void 0 ? false : _ref$allowComposition,
|
|
27
24
|
api = _ref.api;
|
|
28
25
|
var handleDOMEvents = {};
|
|
29
|
-
var createLineNumberDecoratorsFromDecendants = function createLineNumberDecoratorsFromDecendants(editorState) {
|
|
30
|
-
var lineNumberDecorators = [];
|
|
31
|
-
editorState.doc.descendants(function (node, pos) {
|
|
32
|
-
if (node.type === editorState.schema.nodes.codeBlock) {
|
|
33
|
-
lineNumberDecorators.push.apply(lineNumberDecorators, _toConsumableArray(createLineNumbersDecorations(pos, node)));
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
return true;
|
|
37
|
-
});
|
|
38
|
-
return lineNumberDecorators;
|
|
39
|
-
};
|
|
40
|
-
var createWordWrappedDecoratorPluginState = function createWordWrappedDecoratorPluginState(pluginState, tr, node) {
|
|
41
|
-
var decorationSetFromState = pluginState.decorations;
|
|
42
|
-
if (node) {
|
|
43
|
-
var pos = node.pos,
|
|
44
|
-
innerNode = node.node;
|
|
45
|
-
if (pos !== undefined) {
|
|
46
|
-
var isNodeWrapped = isCodeBlockWordWrapEnabled(innerNode);
|
|
47
|
-
if (!isNodeWrapped) {
|
|
48
|
-
// Restricts the range of decorators to the current node while not including the previous nodes position in range
|
|
49
|
-
var codeBlockNodePosition = pos + 1;
|
|
50
|
-
var currentWrappedBlockDecorationSet = decorationSetFromState.find(codeBlockNodePosition, codeBlockNodePosition, function (spec) {
|
|
51
|
-
return spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE;
|
|
52
|
-
});
|
|
53
|
-
decorationSetFromState = decorationSetFromState.remove(currentWrappedBlockDecorationSet);
|
|
54
|
-
} else {
|
|
55
|
-
var wrappedBlock = Decoration.node(pos, pos + innerNode.nodeSize, {
|
|
56
|
-
class: codeBlockClassNames.contentFgWrapped
|
|
57
|
-
}, {
|
|
58
|
-
type: DECORATION_WRAPPED_BLOCK_NODE_TYPE
|
|
59
|
-
} // Allows for quick filtering of decorations while using `find`
|
|
60
|
-
);
|
|
61
|
-
decorationSetFromState = decorationSetFromState.add(tr.doc, [wrappedBlock]);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return decorationSetFromState;
|
|
66
|
-
};
|
|
67
|
-
var updateLineDecorationSet = function updateLineDecorationSet(tr, state, decorationSet) {
|
|
68
|
-
// remove all the line number children from the decorations set. 'undefined, undefined' is used to find() the whole doc.
|
|
69
|
-
var children = decorationSet.find(undefined, undefined, function (spec) {
|
|
70
|
-
return spec.type === DECORATION_WIDGET_TYPE;
|
|
71
|
-
});
|
|
72
|
-
decorationSet = decorationSet.remove(children);
|
|
73
|
-
|
|
74
|
-
// regenerate all the line number for the documents code blocks
|
|
75
|
-
var lineDecorators = createLineNumberDecoratorsFromDecendants(state);
|
|
76
|
-
|
|
77
|
-
// add the newly generated line numbers to the decorations set
|
|
78
|
-
return decorationSet.add(tr.doc, _toConsumableArray(lineDecorators));
|
|
79
|
-
};
|
|
80
26
|
|
|
81
27
|
// ME-1599: Composition on mobile was causing the DOM observer to mutate the code block
|
|
82
28
|
// incorrecly and lose content when pressing enter in the middle of a code block line.
|
|
@@ -120,13 +66,13 @@ export var createPlugin = function createPlugin(_ref) {
|
|
|
120
66
|
state: {
|
|
121
67
|
init: function init(_, state) {
|
|
122
68
|
var node = findCodeBlock(state, state.selection);
|
|
123
|
-
var
|
|
69
|
+
var initialDecorations = fg('editor_support_code_block_wrapping') ? generateInitialDecorations(state) : [];
|
|
124
70
|
return {
|
|
125
71
|
pos: node ? node.pos : null,
|
|
126
72
|
contentCopied: false,
|
|
127
73
|
isNodeSelected: false,
|
|
128
74
|
shouldIgnoreFollowingMutations: false,
|
|
129
|
-
decorations: DecorationSet.create(state.doc,
|
|
75
|
+
decorations: DecorationSet.create(state.doc, initialDecorations)
|
|
130
76
|
};
|
|
131
77
|
},
|
|
132
78
|
apply: function apply(tr, pluginState, _oldState, newState) {
|
|
@@ -134,18 +80,18 @@ export var createPlugin = function createPlugin(_ref) {
|
|
|
134
80
|
if ((meta === null || meta === void 0 ? void 0 : meta.type) === ACTIONS.SET_IS_WRAPPED && fg('editor_support_code_block_wrapping')) {
|
|
135
81
|
var node = findCodeBlock(newState, tr.selection);
|
|
136
82
|
return _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
137
|
-
decorations:
|
|
83
|
+
decorations: updateDecorationSetWithWordWrappedDecorator(pluginState.decorations, tr, node)
|
|
138
84
|
});
|
|
139
85
|
}
|
|
140
86
|
if (tr.docChanged) {
|
|
141
87
|
var _node = findCodeBlock(newState, tr.selection);
|
|
142
88
|
|
|
143
89
|
// Updates mapping position of all existing decorations to new positions
|
|
144
|
-
// specifically used for updating word wrap node decorators
|
|
90
|
+
// specifically used for updating word wrap node decorators (does not cover drag & drop, validateWordWrappedDecorators does).
|
|
145
91
|
var updatedDecorationSet = pluginState.decorations.map(tr.mapping, tr.doc);
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
92
|
+
if (fg('editor_support_code_block_wrapping')) {
|
|
93
|
+
updatedDecorationSet = updateCodeBlockDecorations(tr, newState, updatedDecorationSet);
|
|
94
|
+
}
|
|
149
95
|
var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
|
|
150
96
|
pos: _node ? _node.pos : null,
|
|
151
97
|
isNodeSelected: tr.selection instanceof NodeSelection,
|
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
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
export declare const codeBlockAutoFullStopTransformPluginKey: PluginKey<any>;
|
|
4
|
+
export declare function codeBlockAutoFullStopTransformPlugin(): SafePlugin<any>;
|
|
@@ -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[];
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
|
+
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
export declare const codeBlockAutoFullStopTransformPluginKey: PluginKey<any>;
|
|
4
|
+
export declare function codeBlockAutoFullStopTransformPlugin(): SafePlugin<any>;
|
|
@@ -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[];
|