@atlaskit/editor-plugin-code-block 3.3.0 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @atlaskit/editor-plugin-code-block
2
2
 
3
+ ## 3.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#127940](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/127940)
8
+ [`7f340ec35b8a4`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/7f340ec35b8a4) -
9
+ [ux] ED-24320 Hook up decorators for toggled on and toggled off wrapping states in floating
10
+ toolbar
11
+
3
12
  ## 3.3.0
4
13
 
5
14
  ### Minor Changes
@@ -219,12 +219,12 @@ var toggleWordWrapStateForCodeBlockNode = exports.toggleWordWrapStateForCodeBloc
219
219
  }
220
220
  var updatedToggleState = !(0, _codeBlock.isCodeBlockWordWrapEnabled)(codeBlockNode);
221
221
  _codeBlock.codeBlockWrappedStates.set(codeBlockNode, updatedToggleState);
222
-
223
- // TODO: Remove in ED-24222. Leaving here for demo purposes.
224
- // eslint-disable-next-line no-console
225
- console.log("Code Block Word Wrap: Updating codeBlockWrappedStates with: ".concat(updatedToggleState));
222
+ tr.setMeta(_pluginKey.pluginKey, {
223
+ type: _actions.ACTIONS.SET_IS_WRAPPED,
224
+ data: updatedToggleState
225
+ });
226
226
  if (dispatch) {
227
- var payload = {
227
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
228
228
  action: _analytics.ACTION.TOGGLE_CODE_BLOCK_WRAP,
229
229
  actionSubject: _analytics.ACTION_SUBJECT.CODE_BLOCK,
230
230
  attributes: {
@@ -233,10 +233,7 @@ var toggleWordWrapStateForCodeBlockNode = exports.toggleWordWrapStateForCodeBloc
233
233
  wordWrapEnabled: updatedToggleState
234
234
  },
235
235
  eventType: _analytics.EVENT_TYPE.TRACK
236
- };
237
-
238
- // TODO: ED-24320 should convert this to attachAnalyticsEvent if it is dispatching a transaction here.
239
- editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.fireAnalyticsEvent(payload);
236
+ })(tr);
240
237
  dispatch(tr);
241
238
  }
242
239
  return true;
@@ -6,5 +6,6 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.ACTIONS = void 0;
7
7
  var ACTIONS = exports.ACTIONS = {
8
8
  SET_COPIED_TO_CLIPBOARD: 'SET_COPIED_TO_CLIPBOARD',
9
- SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS: 'SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS'
9
+ SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS: 'SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS',
10
+ SET_IS_WRAPPED: 'SET_IS_WRAPPED'
10
11
  };
@@ -8,6 +8,7 @@ exports.generateTextPositionsFromNode = exports.createLineNumbersDecorations = e
8
8
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
9
  var _view = require("@atlaskit/editor-prosemirror/view");
10
10
  var _classNames = require("../ui/class-names");
11
+ var DECORATION_INLINE_TYPE = 'decorationInlineType';
11
12
  var generateTextPositionsFromNode = exports.generateTextPositionsFromNode = function generateTextPositionsFromNode(pos, node) {
12
13
  // Get content node
13
14
  var contentNode = node.content;
@@ -40,6 +41,8 @@ var createDecorationSetFromTextPositions = exports.createDecorationSetFromTextPo
40
41
  lineEnd = textPosition.lineEnd;
41
42
  return _view.Decoration.inline(lineStart, lineEnd, {
42
43
  class: _classNames.codeBlockClassNames.lineNumberWrapped
44
+ }, {
45
+ type: DECORATION_INLINE_TYPE
43
46
  });
44
47
  });
45
48
  return decorations;
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.createPlugin = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
+ var _codeBlock = require("@atlaskit/editor-common/code-block");
9
11
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
10
12
  var _selection = require("@atlaskit/editor-common/selection");
11
13
  var _utils = require("@atlaskit/editor-common/utils");
@@ -13,7 +15,7 @@ var _state = require("@atlaskit/editor-prosemirror/state");
13
15
  var _view = require("@atlaskit/editor-prosemirror/view");
14
16
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
17
  var _actions = require("../actions");
16
- var _codeBlock = require("../nodeviews/code-block");
18
+ var _codeBlock2 = require("../nodeviews/code-block");
17
19
  var _pluginKey = require("../plugin-key");
18
20
  var _classNames = require("../ui/class-names");
19
21
  var _utils2 = require("../utils");
@@ -21,16 +23,57 @@ var _actions2 = require("./actions");
21
23
  var _decorators = require("./decorators");
22
24
  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; }
23
25
  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';
24
27
  var createPlugin = exports.createPlugin = function createPlugin(_ref) {
25
28
  var _ref$useLongPressSele = _ref.useLongPressSelection,
26
29
  useLongPressSelection = _ref$useLongPressSele === void 0 ? false : _ref$useLongPressSele,
27
30
  getIntl = _ref.getIntl,
28
31
  _ref$allowComposition = _ref.allowCompositionInputOverride,
29
32
  allowCompositionInputOverride = _ref$allowComposition === void 0 ? false : _ref$allowComposition,
30
- api = _ref.api,
31
- _ref$isWrapped = _ref.isWrapped,
32
- isWrapped = _ref$isWrapped === void 0 ? false : _ref$isWrapped;
33
+ api = _ref.api;
33
34
  var handleDOMEvents = {};
35
+ var createWordWrappedDecoratorPluginState = function createWordWrappedDecoratorPluginState(pluginState, tr, node) {
36
+ var decorationSetFromState = pluginState.decorations;
37
+ if (node) {
38
+ var pos = node.pos,
39
+ innerNode = node.node;
40
+ if (pos !== undefined) {
41
+ var isNodeWrapped = (0, _codeBlock.isCodeBlockWordWrapEnabled)(innerNode);
42
+ if (!isNodeWrapped) {
43
+ // Restricts the range of decorators to the current node while not including the previous nodes position in range
44
+ var codeBlockNodePosition = pos + 1;
45
+ var currentWrappedBlockDecorationSet = decorationSetFromState.find(codeBlockNodePosition, codeBlockNodePosition, function (spec) {
46
+ return spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE;
47
+ });
48
+ decorationSetFromState = decorationSetFromState.remove(currentWrappedBlockDecorationSet);
49
+ } else {
50
+ var wrappedBlock = _view.Decoration.node(pos, pos + innerNode.nodeSize, {
51
+ class: _classNames.codeBlockClassNames.wrapped
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
+ var createLineDecoratorPluginState = function createLineDecoratorPluginState(pluginState, tr, node) {
63
+ var decorationSetFromState = pluginState.decorations;
64
+ if (node) {
65
+ var pos = node.pos,
66
+ innerNode = node.node;
67
+ if (pos !== undefined) {
68
+ // Reset the decorations for the children of the code block node. Wipes all line number decorations.
69
+ // @ts-ignore
70
+ decorationSetFromState.children = [];
71
+ var lineDecorators = (0, _decorators.createLineNumbersDecorations)(pos, innerNode);
72
+ decorationSetFromState = decorationSetFromState.add(tr.doc, (0, _toConsumableArray2.default)(lineDecorators));
73
+ }
74
+ }
75
+ return decorationSetFromState;
76
+ };
34
77
 
35
78
  // ME-1599: Composition on mobile was causing the DOM observer to mutate the code block
36
79
  // incorrecly and lose content when pressing enter in the middle of a code block line.
@@ -83,22 +126,30 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
83
126
  };
84
127
  },
85
128
  apply: function apply(tr, pluginState, _oldState, newState) {
86
- if (tr.docChanged || tr.selectionSet) {
129
+ var meta = tr.getMeta(_pluginKey.pluginKey);
130
+ if ((meta === null || meta === void 0 ? void 0 : meta.type) === _actions2.ACTIONS.SET_IS_WRAPPED && (0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping')) {
87
131
  var node = (0, _utils2.findCodeBlock)(newState, tr.selection);
88
- var lineNumberDecorators = [];
89
- if ((0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping')) {
90
- if (node && node.pos !== undefined) {
91
- lineNumberDecorators = (0, _decorators.createLineNumbersDecorations)(node.pos, node.node);
92
- }
93
- }
132
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
133
+ decorations: createWordWrappedDecoratorPluginState(pluginState, tr, node)
134
+ });
135
+ }
136
+ if (tr.docChanged) {
137
+ var _node = (0, _utils2.findCodeBlock)(newState, tr.selection);
94
138
  var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
95
- pos: node ? node.pos : null,
139
+ pos: _node ? _node.pos : null,
96
140
  isNodeSelected: tr.selection instanceof _state.NodeSelection,
97
- decorations: (0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping') ? _view.DecorationSet.create(tr.doc, lineNumberDecorators) : _view.DecorationSet.empty
141
+ decorations: (0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping') ? createLineDecoratorPluginState(pluginState, tr, _node) : _view.DecorationSet.empty
98
142
  });
99
143
  return newPluginState;
100
144
  }
101
- var meta = tr.getMeta(_pluginKey.pluginKey);
145
+ if (tr.selectionSet) {
146
+ var _node2 = (0, _utils2.findCodeBlock)(newState, tr.selection);
147
+ var _newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
148
+ pos: _node2 ? _node2.pos : null,
149
+ isNodeSelected: tr.selection instanceof _state.NodeSelection
150
+ });
151
+ return _newPluginState;
152
+ }
102
153
  if ((meta === null || meta === void 0 ? void 0 : meta.type) === _actions2.ACTIONS.SET_COPIED_TO_CLIPBOARD) {
103
154
  return _objectSpread(_objectSpread({}, pluginState), {}, {
104
155
  contentCopied: meta.data
@@ -121,7 +172,7 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
121
172
  },
122
173
  nodeViews: {
123
174
  codeBlock: function codeBlock(node, view, getPos) {
124
- return (0, _codeBlock.codeBlockNodeView)(node, view, getPos, api);
175
+ return (0, _codeBlock2.codeBlockNodeView)(node, view, getPos, api);
125
176
  }
126
177
  },
127
178
  handleClickOn: (0, _selection.createSelectionClickHandler)(['codeBlock'], function (target) {
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.languageListFilter = exports.getToolbarConfig = void 0;
9
+ var _codeBlock = require("@atlaskit/editor-common/code-block");
9
10
  var _messages = _interopRequireWildcard(require("@atlaskit/editor-common/messages"));
10
11
  var _utils = require("@atlaskit/editor-prosemirror/utils");
11
12
  var _copy = _interopRequireDefault(require("@atlaskit/icon/glyph/copy"));
@@ -38,6 +39,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig() {
38
39
  if ((node === null || node === void 0 ? void 0 : node.type) !== nodeType) {
39
40
  return;
40
41
  }
42
+ var isWrapped = (0, _codeBlock.isCodeBlockWordWrapEnabled)(node);
41
43
  var language = node === null || node === void 0 || (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.language;
42
44
  var options = languageList.map(function (lang) {
43
45
  return {
@@ -107,8 +109,9 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig() {
107
109
  icon: _WrapIcon.WrapIcon,
108
110
  onClick: (0, _actions.toggleWordWrapStateForCodeBlockNode)(editorAnalyticsAPI),
109
111
  // Hooking up here for demo purposes. To be revisited with ED-24222.
110
- title: formatMessage(_messages.codeBlockButtonMessages.wrapCode),
111
- tabIndex: null
112
+ title: isWrapped ? formatMessage(_messages.codeBlockButtonMessages.unwrapCode) : formatMessage(_messages.codeBlockButtonMessages.wrapCode),
113
+ tabIndex: null,
114
+ selected: isWrapped
112
115
  };
113
116
  return {
114
117
  title: 'CodeBlock floating controls',
@@ -14,5 +14,6 @@ var codeBlockClassNames = exports.codeBlockClassNames = {
14
14
  gutterFgWrap: _styles.CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER_FG_WRAP,
15
15
  content: _styles.CodeBlockSharedCssClassName.CODEBLOCK_CONTENT,
16
16
  contentWrapped: _styles.CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPED,
17
- lineNumberWrapped: _styles.CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER_LINE_NUMBER_WRAPPED
17
+ lineNumberWrapped: _styles.CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER_LINE_NUMBER_WRAPPED,
18
+ wrapped: _styles.CodeBlockSharedCssClassName.CODEBLOCK_WRAPPED
18
19
  };
@@ -230,12 +230,12 @@ export const toggleWordWrapStateForCodeBlockNode = editorAnalyticsAPI => (state,
230
230
  }
231
231
  const updatedToggleState = !isCodeBlockWordWrapEnabled(codeBlockNode);
232
232
  codeBlockWrappedStates.set(codeBlockNode, updatedToggleState);
233
-
234
- // TODO: Remove in ED-24222. Leaving here for demo purposes.
235
- // eslint-disable-next-line no-console
236
- console.log(`Code Block Word Wrap: Updating codeBlockWrappedStates with: ${updatedToggleState}`);
233
+ tr.setMeta(pluginKey, {
234
+ type: ACTIONS.SET_IS_WRAPPED,
235
+ data: updatedToggleState
236
+ });
237
237
  if (dispatch) {
238
- const payload = {
238
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent({
239
239
  action: ACTION.TOGGLE_CODE_BLOCK_WRAP,
240
240
  actionSubject: ACTION_SUBJECT.CODE_BLOCK,
241
241
  attributes: {
@@ -244,10 +244,7 @@ export const toggleWordWrapStateForCodeBlockNode = editorAnalyticsAPI => (state,
244
244
  wordWrapEnabled: updatedToggleState
245
245
  },
246
246
  eventType: EVENT_TYPE.TRACK
247
- };
248
-
249
- // TODO: ED-24320 should convert this to attachAnalyticsEvent if it is dispatching a transaction here.
250
- editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.fireAnalyticsEvent(payload);
247
+ })(tr);
251
248
  dispatch(tr);
252
249
  }
253
250
  return true;
@@ -1,4 +1,5 @@
1
1
  export const ACTIONS = {
2
2
  SET_COPIED_TO_CLIPBOARD: 'SET_COPIED_TO_CLIPBOARD',
3
- SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS: 'SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS'
3
+ SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS: 'SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS',
4
+ SET_IS_WRAPPED: 'SET_IS_WRAPPED'
4
5
  };
@@ -1,5 +1,6 @@
1
1
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
2
  import { codeBlockClassNames } from '../ui/class-names';
3
+ const DECORATION_INLINE_TYPE = 'decorationInlineType';
3
4
  export const generateTextPositionsFromNode = (pos, node) => {
4
5
  // Get content node
5
6
  const contentNode = node.content;
@@ -34,6 +35,8 @@ export const createDecorationSetFromTextPositions = textPositions => {
34
35
  } = textPosition;
35
36
  return Decoration.inline(lineStart, lineEnd, {
36
37
  class: codeBlockClassNames.lineNumberWrapped
38
+ }, {
39
+ type: DECORATION_INLINE_TYPE
37
40
  });
38
41
  });
39
42
  return decorations;
@@ -1,8 +1,9 @@
1
+ import { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
1
2
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
3
  import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
3
4
  import { browser } from '@atlaskit/editor-common/utils';
4
5
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
5
- import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
+ import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
7
  import { fg } from '@atlaskit/platform-feature-flags';
7
8
  import { ignoreFollowingMutations, resetShouldIgnoreFollowingMutations } from '../actions';
8
9
  import { codeBlockNodeView } from '../nodeviews/code-block';
@@ -11,14 +12,58 @@ import { codeBlockClassNames } from '../ui/class-names';
11
12
  import { findCodeBlock } from '../utils';
12
13
  import { ACTIONS } from './actions';
13
14
  import { createLineNumbersDecorations } from './decorators';
15
+ const DECORATION_WRAPPED_BLOCK_NODE_TYPE = 'decorationNodeType';
14
16
  export const createPlugin = ({
15
17
  useLongPressSelection = false,
16
18
  getIntl,
17
19
  allowCompositionInputOverride = false,
18
- api,
19
- isWrapped = false
20
+ api
20
21
  }) => {
21
22
  const handleDOMEvents = {};
23
+ const createWordWrappedDecoratorPluginState = (pluginState, tr, node) => {
24
+ let decorationSetFromState = pluginState.decorations;
25
+ if (node) {
26
+ const {
27
+ pos,
28
+ node: innerNode
29
+ } = node;
30
+ if (pos !== undefined) {
31
+ const isNodeWrapped = isCodeBlockWordWrapEnabled(innerNode);
32
+ if (!isNodeWrapped) {
33
+ // Restricts the range of decorators to the current node while not including the previous nodes position in range
34
+ const codeBlockNodePosition = pos + 1;
35
+ const currentWrappedBlockDecorationSet = decorationSetFromState.find(codeBlockNodePosition, codeBlockNodePosition, spec => spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE);
36
+ decorationSetFromState = decorationSetFromState.remove(currentWrappedBlockDecorationSet);
37
+ } else {
38
+ const wrappedBlock = Decoration.node(pos, pos + innerNode.nodeSize, {
39
+ class: codeBlockClassNames.wrapped
40
+ }, {
41
+ type: DECORATION_WRAPPED_BLOCK_NODE_TYPE
42
+ } // Allows for quick filtering of decorations while using `find`
43
+ );
44
+ decorationSetFromState = decorationSetFromState.add(tr.doc, [wrappedBlock]);
45
+ }
46
+ }
47
+ }
48
+ return decorationSetFromState;
49
+ };
50
+ const createLineDecoratorPluginState = (pluginState, tr, node) => {
51
+ let decorationSetFromState = pluginState.decorations;
52
+ if (node) {
53
+ const {
54
+ pos,
55
+ node: innerNode
56
+ } = node;
57
+ if (pos !== undefined) {
58
+ // Reset the decorations for the children of the code block node. Wipes all line number decorations.
59
+ // @ts-ignore
60
+ decorationSetFromState.children = [];
61
+ const lineDecorators = createLineNumbersDecorations(pos, innerNode);
62
+ decorationSetFromState = decorationSetFromState.add(tr.doc, [...lineDecorators]);
63
+ }
64
+ }
65
+ return decorationSetFromState;
66
+ };
22
67
 
23
68
  // ME-1599: Composition on mobile was causing the DOM observer to mutate the code block
24
69
  // incorrecly and lose content when pressing enter in the middle of a code block line.
@@ -69,23 +114,33 @@ export const createPlugin = ({
69
114
  };
70
115
  },
71
116
  apply(tr, pluginState, _oldState, newState) {
72
- if (tr.docChanged || tr.selectionSet) {
117
+ const meta = tr.getMeta(pluginKey);
118
+ if ((meta === null || meta === void 0 ? void 0 : meta.type) === ACTIONS.SET_IS_WRAPPED && fg('editor_support_code_block_wrapping')) {
119
+ const node = findCodeBlock(newState, tr.selection);
120
+ return {
121
+ ...pluginState,
122
+ decorations: createWordWrappedDecoratorPluginState(pluginState, tr, node)
123
+ };
124
+ }
125
+ if (tr.docChanged) {
73
126
  const node = findCodeBlock(newState, tr.selection);
74
- let lineNumberDecorators = [];
75
- if (fg('editor_support_code_block_wrapping')) {
76
- if (node && node.pos !== undefined) {
77
- lineNumberDecorators = createLineNumbersDecorations(node.pos, node.node);
78
- }
79
- }
80
127
  const newPluginState = {
81
128
  ...pluginState,
82
129
  pos: node ? node.pos : null,
83
130
  isNodeSelected: tr.selection instanceof NodeSelection,
84
- decorations: fg('editor_support_code_block_wrapping') ? DecorationSet.create(tr.doc, lineNumberDecorators) : DecorationSet.empty
131
+ decorations: fg('editor_support_code_block_wrapping') ? createLineDecoratorPluginState(pluginState, tr, node) : DecorationSet.empty
132
+ };
133
+ return newPluginState;
134
+ }
135
+ if (tr.selectionSet) {
136
+ const node = findCodeBlock(newState, tr.selection);
137
+ const newPluginState = {
138
+ ...pluginState,
139
+ pos: node ? node.pos : null,
140
+ isNodeSelected: tr.selection instanceof NodeSelection
85
141
  };
86
142
  return newPluginState;
87
143
  }
88
- const meta = tr.getMeta(pluginKey);
89
144
  if ((meta === null || meta === void 0 ? void 0 : meta.type) === ACTIONS.SET_COPIED_TO_CLIPBOARD) {
90
145
  return {
91
146
  ...pluginState,
@@ -1,3 +1,4 @@
1
+ import { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
1
2
  import commonMessages, { codeBlockButtonMessages } from '@atlaskit/editor-common/messages';
2
3
  import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
3
4
  import CopyIcon from '@atlaskit/icon/glyph/copy';
@@ -27,6 +28,7 @@ export const getToolbarConfig = (allowCopyToClipboard = false, api) => (state, {
27
28
  if ((node === null || node === void 0 ? void 0 : node.type) !== nodeType) {
28
29
  return;
29
30
  }
31
+ const isWrapped = isCodeBlockWordWrapEnabled(node);
30
32
  const language = node === null || node === void 0 ? void 0 : (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.language;
31
33
  const options = languageList.map(lang => ({
32
34
  label: lang.name,
@@ -88,8 +90,9 @@ export const getToolbarConfig = (allowCopyToClipboard = false, api) => (state, {
88
90
  icon: WrapIcon,
89
91
  onClick: toggleWordWrapStateForCodeBlockNode(editorAnalyticsAPI),
90
92
  // Hooking up here for demo purposes. To be revisited with ED-24222.
91
- title: formatMessage(codeBlockButtonMessages.wrapCode),
92
- tabIndex: null
93
+ title: isWrapped ? formatMessage(codeBlockButtonMessages.unwrapCode) : formatMessage(codeBlockButtonMessages.wrapCode),
94
+ tabIndex: null,
95
+ selected: isWrapped
93
96
  };
94
97
  return {
95
98
  title: 'CodeBlock floating controls',
@@ -8,5 +8,6 @@ export const codeBlockClassNames = {
8
8
  gutterFgWrap: CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER_FG_WRAP,
9
9
  content: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT,
10
10
  contentWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPED,
11
- lineNumberWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER_LINE_NUMBER_WRAPPED
11
+ lineNumberWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER_LINE_NUMBER_WRAPPED,
12
+ wrapped: CodeBlockSharedCssClassName.CODEBLOCK_WRAPPED
12
13
  };
@@ -209,12 +209,12 @@ export var toggleWordWrapStateForCodeBlockNode = function toggleWordWrapStateFor
209
209
  }
210
210
  var updatedToggleState = !isCodeBlockWordWrapEnabled(codeBlockNode);
211
211
  codeBlockWrappedStates.set(codeBlockNode, updatedToggleState);
212
-
213
- // TODO: Remove in ED-24222. Leaving here for demo purposes.
214
- // eslint-disable-next-line no-console
215
- console.log("Code Block Word Wrap: Updating codeBlockWrappedStates with: ".concat(updatedToggleState));
212
+ tr.setMeta(pluginKey, {
213
+ type: ACTIONS.SET_IS_WRAPPED,
214
+ data: updatedToggleState
215
+ });
216
216
  if (dispatch) {
217
- var payload = {
217
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
218
218
  action: ACTION.TOGGLE_CODE_BLOCK_WRAP,
219
219
  actionSubject: ACTION_SUBJECT.CODE_BLOCK,
220
220
  attributes: {
@@ -223,10 +223,7 @@ export var toggleWordWrapStateForCodeBlockNode = function toggleWordWrapStateFor
223
223
  wordWrapEnabled: updatedToggleState
224
224
  },
225
225
  eventType: EVENT_TYPE.TRACK
226
- };
227
-
228
- // TODO: ED-24320 should convert this to attachAnalyticsEvent if it is dispatching a transaction here.
229
- editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.fireAnalyticsEvent(payload);
226
+ })(tr);
230
227
  dispatch(tr);
231
228
  }
232
229
  return true;
@@ -1,4 +1,5 @@
1
1
  export var ACTIONS = {
2
2
  SET_COPIED_TO_CLIPBOARD: 'SET_COPIED_TO_CLIPBOARD',
3
- SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS: 'SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS'
3
+ SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS: 'SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS',
4
+ SET_IS_WRAPPED: 'SET_IS_WRAPPED'
4
5
  };
@@ -1,6 +1,7 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
3
  import { codeBlockClassNames } from '../ui/class-names';
4
+ var DECORATION_INLINE_TYPE = 'decorationInlineType';
4
5
  export var generateTextPositionsFromNode = function generateTextPositionsFromNode(pos, node) {
5
6
  // Get content node
6
7
  var contentNode = node.content;
@@ -33,6 +34,8 @@ export var createDecorationSetFromTextPositions = function createDecorationSetFr
33
34
  lineEnd = textPosition.lineEnd;
34
35
  return Decoration.inline(lineStart, lineEnd, {
35
36
  class: codeBlockClassNames.lineNumberWrapped
37
+ }, {
38
+ type: DECORATION_INLINE_TYPE
36
39
  });
37
40
  });
38
41
  return decorations;
@@ -1,11 +1,13 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
3
  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; }
3
4
  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';
4
6
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
5
7
  import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
6
8
  import { browser } from '@atlaskit/editor-common/utils';
7
9
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
8
- import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
10
+ import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
9
11
  import { fg } from '@atlaskit/platform-feature-flags';
10
12
  import { ignoreFollowingMutations, resetShouldIgnoreFollowingMutations } from '../actions';
11
13
  import { codeBlockNodeView } from '../nodeviews/code-block';
@@ -14,16 +16,57 @@ import { codeBlockClassNames } from '../ui/class-names';
14
16
  import { findCodeBlock } from '../utils';
15
17
  import { ACTIONS } from './actions';
16
18
  import { createLineNumbersDecorations } from './decorators';
19
+ var DECORATION_WRAPPED_BLOCK_NODE_TYPE = 'decorationNodeType';
17
20
  export var createPlugin = function createPlugin(_ref) {
18
21
  var _ref$useLongPressSele = _ref.useLongPressSelection,
19
22
  useLongPressSelection = _ref$useLongPressSele === void 0 ? false : _ref$useLongPressSele,
20
23
  getIntl = _ref.getIntl,
21
24
  _ref$allowComposition = _ref.allowCompositionInputOverride,
22
25
  allowCompositionInputOverride = _ref$allowComposition === void 0 ? false : _ref$allowComposition,
23
- api = _ref.api,
24
- _ref$isWrapped = _ref.isWrapped,
25
- isWrapped = _ref$isWrapped === void 0 ? false : _ref$isWrapped;
26
+ api = _ref.api;
26
27
  var handleDOMEvents = {};
28
+ var createWordWrappedDecoratorPluginState = function createWordWrappedDecoratorPluginState(pluginState, tr, node) {
29
+ var decorationSetFromState = pluginState.decorations;
30
+ if (node) {
31
+ var pos = node.pos,
32
+ innerNode = node.node;
33
+ if (pos !== undefined) {
34
+ var isNodeWrapped = isCodeBlockWordWrapEnabled(innerNode);
35
+ if (!isNodeWrapped) {
36
+ // Restricts the range of decorators to the current node while not including the previous nodes position in range
37
+ var codeBlockNodePosition = pos + 1;
38
+ var currentWrappedBlockDecorationSet = decorationSetFromState.find(codeBlockNodePosition, codeBlockNodePosition, function (spec) {
39
+ return spec.type === DECORATION_WRAPPED_BLOCK_NODE_TYPE;
40
+ });
41
+ decorationSetFromState = decorationSetFromState.remove(currentWrappedBlockDecorationSet);
42
+ } else {
43
+ var wrappedBlock = Decoration.node(pos, pos + innerNode.nodeSize, {
44
+ class: codeBlockClassNames.wrapped
45
+ }, {
46
+ type: DECORATION_WRAPPED_BLOCK_NODE_TYPE
47
+ } // Allows for quick filtering of decorations while using `find`
48
+ );
49
+ decorationSetFromState = decorationSetFromState.add(tr.doc, [wrappedBlock]);
50
+ }
51
+ }
52
+ }
53
+ return decorationSetFromState;
54
+ };
55
+ var createLineDecoratorPluginState = function createLineDecoratorPluginState(pluginState, tr, node) {
56
+ var decorationSetFromState = pluginState.decorations;
57
+ if (node) {
58
+ var pos = node.pos,
59
+ innerNode = node.node;
60
+ if (pos !== undefined) {
61
+ // Reset the decorations for the children of the code block node. Wipes all line number decorations.
62
+ // @ts-ignore
63
+ decorationSetFromState.children = [];
64
+ var lineDecorators = createLineNumbersDecorations(pos, innerNode);
65
+ decorationSetFromState = decorationSetFromState.add(tr.doc, _toConsumableArray(lineDecorators));
66
+ }
67
+ }
68
+ return decorationSetFromState;
69
+ };
27
70
 
28
71
  // ME-1599: Composition on mobile was causing the DOM observer to mutate the code block
29
72
  // incorrecly and lose content when pressing enter in the middle of a code block line.
@@ -76,22 +119,30 @@ export var createPlugin = function createPlugin(_ref) {
76
119
  };
77
120
  },
78
121
  apply: function apply(tr, pluginState, _oldState, newState) {
79
- if (tr.docChanged || tr.selectionSet) {
122
+ var meta = tr.getMeta(pluginKey);
123
+ if ((meta === null || meta === void 0 ? void 0 : meta.type) === ACTIONS.SET_IS_WRAPPED && fg('editor_support_code_block_wrapping')) {
80
124
  var node = findCodeBlock(newState, tr.selection);
81
- var lineNumberDecorators = [];
82
- if (fg('editor_support_code_block_wrapping')) {
83
- if (node && node.pos !== undefined) {
84
- lineNumberDecorators = createLineNumbersDecorations(node.pos, node.node);
85
- }
86
- }
125
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
126
+ decorations: createWordWrappedDecoratorPluginState(pluginState, tr, node)
127
+ });
128
+ }
129
+ if (tr.docChanged) {
130
+ var _node = findCodeBlock(newState, tr.selection);
87
131
  var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
88
- pos: node ? node.pos : null,
132
+ pos: _node ? _node.pos : null,
89
133
  isNodeSelected: tr.selection instanceof NodeSelection,
90
- decorations: fg('editor_support_code_block_wrapping') ? DecorationSet.create(tr.doc, lineNumberDecorators) : DecorationSet.empty
134
+ decorations: fg('editor_support_code_block_wrapping') ? createLineDecoratorPluginState(pluginState, tr, _node) : DecorationSet.empty
91
135
  });
92
136
  return newPluginState;
93
137
  }
94
- var meta = tr.getMeta(pluginKey);
138
+ if (tr.selectionSet) {
139
+ var _node2 = findCodeBlock(newState, tr.selection);
140
+ var _newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
141
+ pos: _node2 ? _node2.pos : null,
142
+ isNodeSelected: tr.selection instanceof NodeSelection
143
+ });
144
+ return _newPluginState;
145
+ }
95
146
  if ((meta === null || meta === void 0 ? void 0 : meta.type) === ACTIONS.SET_COPIED_TO_CLIPBOARD) {
96
147
  return _objectSpread(_objectSpread({}, pluginState), {}, {
97
148
  contentCopied: meta.data
@@ -1,3 +1,4 @@
1
+ import { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
1
2
  import commonMessages, { codeBlockButtonMessages } from '@atlaskit/editor-common/messages';
2
3
  import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
3
4
  import CopyIcon from '@atlaskit/icon/glyph/copy';
@@ -28,6 +29,7 @@ export var getToolbarConfig = function getToolbarConfig() {
28
29
  if ((node === null || node === void 0 ? void 0 : node.type) !== nodeType) {
29
30
  return;
30
31
  }
32
+ var isWrapped = isCodeBlockWordWrapEnabled(node);
31
33
  var language = node === null || node === void 0 || (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.language;
32
34
  var options = languageList.map(function (lang) {
33
35
  return {
@@ -97,8 +99,9 @@ export var getToolbarConfig = function getToolbarConfig() {
97
99
  icon: WrapIcon,
98
100
  onClick: toggleWordWrapStateForCodeBlockNode(editorAnalyticsAPI),
99
101
  // Hooking up here for demo purposes. To be revisited with ED-24222.
100
- title: formatMessage(codeBlockButtonMessages.wrapCode),
101
- tabIndex: null
102
+ title: isWrapped ? formatMessage(codeBlockButtonMessages.unwrapCode) : formatMessage(codeBlockButtonMessages.wrapCode),
103
+ tabIndex: null,
104
+ selected: isWrapped
102
105
  };
103
106
  return {
104
107
  title: 'CodeBlock floating controls',
@@ -8,5 +8,6 @@ export var codeBlockClassNames = {
8
8
  gutterFgWrap: CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER_FG_WRAP,
9
9
  content: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT,
10
10
  contentWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPED,
11
- lineNumberWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER_LINE_NUMBER_WRAPPED
11
+ lineNumberWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER_LINE_NUMBER_WRAPPED,
12
+ wrapped: CodeBlockSharedCssClassName.CODEBLOCK_WRAPPED
12
13
  };
@@ -1,4 +1,5 @@
1
1
  export declare const ACTIONS: {
2
2
  SET_COPIED_TO_CLIPBOARD: string;
3
3
  SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS: string;
4
+ SET_IS_WRAPPED: string;
4
5
  };
@@ -4,7 +4,7 @@ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
4
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
5
5
  import type { CodeBlockPlugin } from '../index';
6
6
  import { type CodeBlockState } from './main-state';
7
- export declare const createPlugin: ({ useLongPressSelection, getIntl, allowCompositionInputOverride, api, isWrapped, }: {
7
+ export declare const createPlugin: ({ useLongPressSelection, getIntl, allowCompositionInputOverride, api, }: {
8
8
  useLongPressSelection?: boolean | undefined;
9
9
  getIntl: () => IntlShape;
10
10
  allowCompositionInputOverride?: boolean | undefined;
@@ -37,6 +37,5 @@ export declare const createPlugin: ({ useLongPressSelection, getIntl, allowCompo
37
37
  insertCodeBlock: (inputMethod: import("@atlaskit/editor-common/analytics").INPUT_METHOD) => import("@atlaskit/editor-common/types").Command;
38
38
  };
39
39
  }> | undefined;
40
- isWrapped?: boolean | undefined;
41
40
  decorations?: DecorationSet | undefined;
42
41
  }) => SafePlugin<CodeBlockState>;
@@ -8,4 +8,5 @@ export declare const codeBlockClassNames: {
8
8
  content: string;
9
9
  contentWrapped: string;
10
10
  lineNumberWrapped: string;
11
+ wrapped: string;
11
12
  };
@@ -1,4 +1,5 @@
1
1
  export declare const ACTIONS: {
2
2
  SET_COPIED_TO_CLIPBOARD: string;
3
3
  SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS: string;
4
+ SET_IS_WRAPPED: string;
4
5
  };
@@ -4,7 +4,7 @@ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
4
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
5
5
  import type { CodeBlockPlugin } from '../index';
6
6
  import { type CodeBlockState } from './main-state';
7
- export declare const createPlugin: ({ useLongPressSelection, getIntl, allowCompositionInputOverride, api, isWrapped, }: {
7
+ export declare const createPlugin: ({ useLongPressSelection, getIntl, allowCompositionInputOverride, api, }: {
8
8
  useLongPressSelection?: boolean | undefined;
9
9
  getIntl: () => IntlShape;
10
10
  allowCompositionInputOverride?: boolean | undefined;
@@ -44,6 +44,5 @@ export declare const createPlugin: ({ useLongPressSelection, getIntl, allowCompo
44
44
  insertCodeBlock: (inputMethod: import("@atlaskit/editor-common/analytics").INPUT_METHOD) => import("@atlaskit/editor-common/types").Command;
45
45
  };
46
46
  }> | undefined;
47
- isWrapped?: boolean | undefined;
48
47
  decorations?: DecorationSet | undefined;
49
48
  }) => SafePlugin<CodeBlockState>;
@@ -8,4 +8,5 @@ export declare const codeBlockClassNames: {
8
8
  content: string;
9
9
  contentWrapped: string;
10
10
  lineNumberWrapped: string;
11
+ wrapped: string;
11
12
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-code-block",
3
- "version": "3.3.0",
3
+ "version": "3.3.1",
4
4
  "description": "Code block plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",