@atlaskit/editor-plugin-code-block 3.2.3 → 3.2.5

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/actions.js +34 -15
  3. package/dist/cjs/index.js +14 -1
  4. package/dist/cjs/nodeviews/code-block.js +14 -13
  5. package/dist/cjs/pm-plugins/decorators.js +49 -0
  6. package/dist/cjs/pm-plugins/main.js +20 -3
  7. package/dist/cjs/toolbar.js +1 -1
  8. package/dist/cjs/ui/class-names.js +3 -1
  9. package/dist/es2019/actions.js +24 -5
  10. package/dist/es2019/index.js +2 -1
  11. package/dist/es2019/nodeviews/code-block.js +13 -12
  12. package/dist/es2019/pm-plugins/decorators.js +41 -0
  13. package/dist/es2019/pm-plugins/main.js +20 -3
  14. package/dist/es2019/toolbar.js +1 -1
  15. package/dist/es2019/ui/class-names.js +3 -1
  16. package/dist/esm/actions.js +35 -16
  17. package/dist/esm/index.js +2 -1
  18. package/dist/esm/nodeviews/code-block.js +14 -13
  19. package/dist/esm/pm-plugins/decorators.js +42 -0
  20. package/dist/esm/pm-plugins/main.js +20 -3
  21. package/dist/esm/toolbar.js +1 -1
  22. package/dist/esm/ui/class-names.js +3 -1
  23. package/dist/types/actions.d.ts +1 -1
  24. package/dist/types/index.d.ts +1 -0
  25. package/dist/types/nodeviews/code-block.d.ts +2 -3
  26. package/dist/types/pm-plugins/decorators.d.ts +6 -0
  27. package/dist/types/pm-plugins/main-state.d.ts +2 -0
  28. package/dist/types/pm-plugins/main.d.ts +2 -0
  29. package/dist/types/types.d.ts +4 -0
  30. package/dist/types/ui/class-names.d.ts +2 -0
  31. package/dist/types-ts4.5/actions.d.ts +1 -1
  32. package/dist/types-ts4.5/index.d.ts +1 -0
  33. package/dist/types-ts4.5/nodeviews/code-block.d.ts +2 -3
  34. package/dist/types-ts4.5/pm-plugins/decorators.d.ts +6 -0
  35. package/dist/types-ts4.5/pm-plugins/main-state.d.ts +2 -0
  36. package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -0
  37. package/dist/types-ts4.5/types.d.ts +4 -0
  38. package/dist/types-ts4.5/ui/class-names.d.ts +2 -0
  39. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @atlaskit/editor-plugin-code-block
2
2
 
3
+ ## 3.2.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [#127369](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/127369)
8
+ [`95ff22b16d347`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/95ff22b16d347) -
9
+ [ux] ED-24374 Add support for dynamic line number positions on code block nodeview
10
+
11
+ ## 3.2.4
12
+
13
+ ### Patch Changes
14
+
15
+ - [#126818](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/126818)
16
+ [`197b047fbe6e6`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/197b047fbe6e6) -
17
+ ED-24245 - Adding analytics TRACK event that is triggered when the user clicks the toggle word
18
+ wrap button on the code block floating toolbar.
19
+
3
20
  ## 3.2.3
4
21
 
5
22
  ### Patch Changes
@@ -206,20 +206,39 @@ function insertCodeBlockWithAnalytics(inputMethod, analyticsAPI) {
206
206
  /**
207
207
  * Add the given node to the codeBlockWrappedStates WeakMap with the toggle boolean value.
208
208
  */
209
- var toggleWordWrapStateForCodeBlockNode = exports.toggleWordWrapStateForCodeBlockNode = function toggleWordWrapStateForCodeBlockNode(state) {
210
- var _findCodeBlock;
211
- if (!(0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping')) {
212
- return false;
213
- }
214
- var codeBlockNode = (_findCodeBlock = (0, _utils2.findCodeBlock)(state)) === null || _findCodeBlock === void 0 ? void 0 : _findCodeBlock.node;
215
- if (!_codeBlock.codeBlockWrappedStates || !codeBlockNode) {
216
- return false;
217
- }
218
- var currentValue = (0, _codeBlock.isCodeBlockWordWrapEnabled)(codeBlockNode);
219
- _codeBlock.codeBlockWrappedStates.set(codeBlockNode, !currentValue);
209
+ var toggleWordWrapStateForCodeBlockNode = exports.toggleWordWrapStateForCodeBlockNode = function toggleWordWrapStateForCodeBlockNode(editorAnalyticsAPI) {
210
+ return function (state, dispatch) {
211
+ var _findCodeBlock;
212
+ if (!(0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping')) {
213
+ return false;
214
+ }
215
+ var codeBlockNode = (_findCodeBlock = (0, _utils2.findCodeBlock)(state)) === null || _findCodeBlock === void 0 ? void 0 : _findCodeBlock.node;
216
+ var tr = state.tr;
217
+ if (!_codeBlock.codeBlockWrappedStates || !codeBlockNode) {
218
+ return false;
219
+ }
220
+ var updatedToggleState = !(0, _codeBlock.isCodeBlockWordWrapEnabled)(codeBlockNode);
221
+ _codeBlock.codeBlockWrappedStates.set(codeBlockNode, updatedToggleState);
220
222
 
221
- // TODO: Remove in ED-24222. Leaving here for demo purposes.
222
- // eslint-disable-next-line no-console
223
- console.log("Code Block Word Wrap: Updating codeBlockWrappedStates with: ".concat(_codeBlock.codeBlockWrappedStates.get(codeBlockNode)));
224
- return true;
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));
226
+ if (dispatch) {
227
+ var payload = {
228
+ action: _analytics.ACTION.TOGGLE_CODE_BLOCK_WRAP,
229
+ actionSubject: _analytics.ACTION_SUBJECT.CODE_BLOCK,
230
+ attributes: {
231
+ platform: _analytics.PLATFORMS.WEB,
232
+ mode: _analytics.MODE.EDITOR,
233
+ wordWrapEnabled: updatedToggleState
234
+ },
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);
240
+ dispatch(tr);
241
+ }
242
+ return true;
243
+ };
225
244
  };
package/dist/cjs/index.js CHANGED
@@ -10,4 +10,17 @@ Object.defineProperty(exports, "codeBlockPlugin", {
10
10
  return _plugin.default;
11
11
  }
12
12
  });
13
- var _plugin = _interopRequireDefault(require("./plugin"));
13
+ Object.defineProperty(exports, "createDecorationSetFromTextPositions", {
14
+ enumerable: true,
15
+ get: function get() {
16
+ return _decorators.createDecorationSetFromTextPositions;
17
+ }
18
+ });
19
+ Object.defineProperty(exports, "generateTextPositionsFromNode", {
20
+ enumerable: true,
21
+ get: function get() {
22
+ return _decorators.generateTextPositionsFromNode;
23
+ }
24
+ });
25
+ var _plugin = _interopRequireDefault(require("./plugin"));
26
+ var _decorators = require("./pm-plugins/decorators");
@@ -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, isWrapped) {
20
+ var toDOM = function toDOM(node, contentEditable) {
21
21
  return ['div', {
22
22
  class: 'code-block'
23
23
  }, ['div', {
@@ -26,11 +26,9 @@ var toDOM = function toDOM(node, contentEditable, isWrapped) {
26
26
  }], ['div', {
27
27
  class: _classNames.codeBlockClassNames.contentWrapper
28
28
  }, ['div', {
29
- class: _classNames.codeBlockClassNames.gutter,
29
+ class: (0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping') ? _classNames.codeBlockClassNames.gutterFgWrap : _classNames.codeBlockClassNames.gutter,
30
30
  contenteditable: 'false'
31
- }], ['div', isWrapped && (0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping') ? {
32
- class: "".concat(_classNames.codeBlockClassNames.content, " ").concat(_classNames.codeBlockClassNames.contentWrapped)
33
- } : {
31
+ }], ['div', {
34
32
  class: _classNames.codeBlockClassNames.content
35
33
  }, ['code', {
36
34
  'data-language': node.attrs.language || '',
@@ -43,7 +41,7 @@ var toDOM = function toDOM(node, contentEditable, isWrapped) {
43
41
  }]];
44
42
  };
45
43
  var CodeBlockView = exports.CodeBlockView = /*#__PURE__*/function () {
46
- function CodeBlockView(_node, view, getPos, api, isWrapped, cleanupEditorDisabledListener) {
44
+ function CodeBlockView(_node, view, getPos, api, cleanupEditorDisabledListener) {
47
45
  var _this = this,
48
46
  _api$editorDisabled;
49
47
  (0, _classCallCheck2.default)(this, CodeBlockView);
@@ -63,7 +61,7 @@ var CodeBlockView = exports.CodeBlockView = /*#__PURE__*/function () {
63
61
  }
64
62
  }));
65
63
  this.cleanupEditorDisabledListener = cleanupEditorDisabledListener;
66
- 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), isWrapped)),
64
+ 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))),
67
65
  dom = _DOMSerializer$render.dom,
68
66
  contentDOM = _DOMSerializer$render.contentDOM;
69
67
  this.getPos = getPos;
@@ -71,10 +69,11 @@ var CodeBlockView = exports.CodeBlockView = /*#__PURE__*/function () {
71
69
  this.node = _node;
72
70
  this.dom = dom;
73
71
  this.contentDOM = contentDOM;
74
- this.lineNumberGutter = this.dom.querySelector(".".concat(_classNames.codeBlockClassNames.gutter));
72
+ this.lineNumberGutter = this.dom.querySelector(".".concat((0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping') ? _classNames.codeBlockClassNames.gutterFgWrap : _classNames.codeBlockClassNames.gutter));
75
73
  this.api = api;
76
- this.isWrapped = isWrapped;
77
- this.ensureLineNumbers();
74
+ if (!(0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping')) {
75
+ this.ensureLineNumbers();
76
+ }
78
77
  this.handleEditorDisabledChanged();
79
78
  }
80
79
  (0, _createClass2.default)(CodeBlockView, [{
@@ -150,7 +149,9 @@ var CodeBlockView = exports.CodeBlockView = /*#__PURE__*/function () {
150
149
  this.contentDOM.setAttribute('data-language', node.attrs.language || '');
151
150
  }
152
151
  this.node = node;
153
- this.ensureLineNumbers();
152
+ if (!(0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping')) {
153
+ this.ensureLineNumbers();
154
+ }
154
155
  if (_utils.browser.android) {
155
156
  this.coalesceDOMElements();
156
157
  (0, _actions.resetShouldIgnoreFollowingMutations)(this.view.state, this.view.dispatch);
@@ -180,6 +181,6 @@ var CodeBlockView = exports.CodeBlockView = /*#__PURE__*/function () {
180
181
  }]);
181
182
  return CodeBlockView;
182
183
  }();
183
- var codeBlockNodeView = exports.codeBlockNodeView = function codeBlockNodeView(node, view, getPos, api, isWrapped) {
184
- return new CodeBlockView(node, view, getPos, api, isWrapped);
184
+ var codeBlockNodeView = exports.codeBlockNodeView = function codeBlockNodeView(node, view, getPos, api) {
185
+ return new CodeBlockView(node, view, getPos, api);
185
186
  };
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.generateTextPositionsFromNode = exports.createLineNumbersDecorations = exports.createDecorationSetFromTextPositions = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _view = require("@atlaskit/editor-prosemirror/view");
10
+ var _classNames = require("../ui/class-names");
11
+ var generateTextPositionsFromNode = exports.generateTextPositionsFromNode = function generateTextPositionsFromNode(pos, node) {
12
+ // Get content node
13
+ var contentNode = node.content;
14
+
15
+ // Get node text content
16
+ var textPositions = [];
17
+ contentNode.forEach(function (child) {
18
+ var nodeTextContent = child.textContent;
19
+ var nodeStartPos = pos;
20
+ var lineStartIndex = nodeStartPos;
21
+ var newLinePositions = nodeTextContent.split('\n').map(function (line) {
22
+ var lineLength = line.length;
23
+ var lineStart = lineStartIndex + 1;
24
+ var lineEnd = lineStart + lineLength;
25
+
26
+ // Include the newline character and increment to keep tabs on line position
27
+ lineStartIndex += lineLength + 1;
28
+ return {
29
+ lineStart: lineStart,
30
+ lineEnd: lineEnd
31
+ };
32
+ });
33
+ textPositions = [].concat((0, _toConsumableArray2.default)(textPositions), (0, _toConsumableArray2.default)(newLinePositions));
34
+ });
35
+ return textPositions;
36
+ };
37
+ var createDecorationSetFromTextPositions = exports.createDecorationSetFromTextPositions = function createDecorationSetFromTextPositions(textPositions) {
38
+ var decorations = textPositions.map(function (textPosition) {
39
+ var lineStart = textPosition.lineStart,
40
+ lineEnd = textPosition.lineEnd;
41
+ return _view.Decoration.inline(lineStart, lineEnd, {
42
+ class: _classNames.codeBlockClassNames.lineNumberWrapped
43
+ });
44
+ });
45
+ return decorations;
46
+ };
47
+ var createLineNumbersDecorations = exports.createLineNumbersDecorations = function createLineNumbersDecorations(pos, node) {
48
+ return createDecorationSetFromTextPositions(generateTextPositionsFromNode(pos, node));
49
+ };
@@ -10,12 +10,15 @@ var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
10
10
  var _selection = require("@atlaskit/editor-common/selection");
11
11
  var _utils = require("@atlaskit/editor-common/utils");
12
12
  var _state = require("@atlaskit/editor-prosemirror/state");
13
+ var _view = require("@atlaskit/editor-prosemirror/view");
14
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
13
15
  var _actions = require("../actions");
14
16
  var _codeBlock = require("../nodeviews/code-block");
15
17
  var _pluginKey = require("../plugin-key");
16
18
  var _classNames = require("../ui/class-names");
17
19
  var _utils2 = require("../utils");
18
20
  var _actions2 = require("./actions");
21
+ var _decorators = require("./decorators");
19
22
  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; }
20
23
  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; }
21
24
  var createPlugin = exports.createPlugin = function createPlugin(_ref) {
@@ -75,15 +78,23 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
75
78
  pos: node ? node.pos : null,
76
79
  contentCopied: false,
77
80
  isNodeSelected: false,
78
- shouldIgnoreFollowingMutations: false
81
+ shouldIgnoreFollowingMutations: false,
82
+ decorations: _view.DecorationSet.empty
79
83
  };
80
84
  },
81
85
  apply: function apply(tr, pluginState, _oldState, newState) {
82
86
  if (tr.docChanged || tr.selectionSet) {
83
87
  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
+ }
84
94
  var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
85
95
  pos: node ? node.pos : null,
86
- isNodeSelected: tr.selection instanceof _state.NodeSelection
96
+ 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
87
98
  });
88
99
  return newPluginState;
89
100
  }
@@ -102,9 +113,15 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
102
113
  },
103
114
  key: _pluginKey.pluginKey,
104
115
  props: {
116
+ decorations: function decorations(state) {
117
+ if ((0, _platformFeatureFlags.fg)('editor_support_code_block_wrapping')) {
118
+ return _pluginKey.pluginKey.getState(state).decorations || _view.DecorationSet.empty;
119
+ }
120
+ return undefined;
121
+ },
105
122
  nodeViews: {
106
123
  codeBlock: function codeBlock(node, view, getPos) {
107
- return (0, _codeBlock.codeBlockNodeView)(node, view, getPos, api, isWrapped);
124
+ return (0, _codeBlock.codeBlockNodeView)(node, view, getPos, api);
108
125
  }
109
126
  },
110
127
  handleClickOn: (0, _selection.createSelectionClickHandler)(['codeBlock'], function (target) {
@@ -105,7 +105,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig() {
105
105
  id: 'editor.codeBlock.wrap',
106
106
  type: 'button',
107
107
  icon: _WrapIcon.WrapIcon,
108
- onClick: _actions.toggleWordWrapStateForCodeBlockNode,
108
+ onClick: (0, _actions.toggleWordWrapStateForCodeBlockNode)(editorAnalyticsAPI),
109
109
  // Hooking up here for demo purposes. To be revisited with ED-24222.
110
110
  title: formatMessage(_messages.codeBlockButtonMessages.wrapCode),
111
111
  tabIndex: null
@@ -11,6 +11,8 @@ var codeBlockClassNames = exports.codeBlockClassNames = {
11
11
  end: _styles.CodeBlockSharedCssClassName.CODEBLOCK_END,
12
12
  contentWrapper: _styles.CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPER,
13
13
  gutter: _styles.CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER,
14
+ gutterFgWrap: _styles.CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER_FG_WRAP,
14
15
  content: _styles.CodeBlockSharedCssClassName.CODEBLOCK_CONTENT,
15
- contentWrapped: _styles.CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPED
16
+ contentWrapped: _styles.CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPED,
17
+ lineNumberWrapped: _styles.CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER_LINE_NUMBER_WRAPPED
16
18
  };
@@ -1,4 +1,4 @@
1
- import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
1
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, MODE, PLATFORMS } from '@atlaskit/editor-common/analytics';
2
2
  import { copyToClipboard } from '@atlaskit/editor-common/clipboard';
3
3
  import { codeBlockWrappedStates, isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
4
4
  import { withAnalytics } from '@atlaskit/editor-common/editor-analytics';
@@ -216,20 +216,39 @@ export function insertCodeBlockWithAnalytics(inputMethod, analyticsAPI) {
216
216
  /**
217
217
  * Add the given node to the codeBlockWrappedStates WeakMap with the toggle boolean value.
218
218
  */
219
- export const toggleWordWrapStateForCodeBlockNode = state => {
219
+ export const toggleWordWrapStateForCodeBlockNode = editorAnalyticsAPI => (state, dispatch) => {
220
220
  var _findCodeBlock;
221
221
  if (!fg('editor_support_code_block_wrapping')) {
222
222
  return false;
223
223
  }
224
224
  const codeBlockNode = (_findCodeBlock = findCodeBlock(state)) === null || _findCodeBlock === void 0 ? void 0 : _findCodeBlock.node;
225
+ const {
226
+ tr
227
+ } = state;
225
228
  if (!codeBlockWrappedStates || !codeBlockNode) {
226
229
  return false;
227
230
  }
228
- const currentValue = isCodeBlockWordWrapEnabled(codeBlockNode);
229
- codeBlockWrappedStates.set(codeBlockNode, !currentValue);
231
+ const updatedToggleState = !isCodeBlockWordWrapEnabled(codeBlockNode);
232
+ codeBlockWrappedStates.set(codeBlockNode, updatedToggleState);
230
233
 
231
234
  // TODO: Remove in ED-24222. Leaving here for demo purposes.
232
235
  // eslint-disable-next-line no-console
233
- console.log(`Code Block Word Wrap: Updating codeBlockWrappedStates with: ${codeBlockWrappedStates.get(codeBlockNode)}`);
236
+ console.log(`Code Block Word Wrap: Updating codeBlockWrappedStates with: ${updatedToggleState}`);
237
+ if (dispatch) {
238
+ const payload = {
239
+ action: ACTION.TOGGLE_CODE_BLOCK_WRAP,
240
+ actionSubject: ACTION_SUBJECT.CODE_BLOCK,
241
+ attributes: {
242
+ platform: PLATFORMS.WEB,
243
+ mode: MODE.EDITOR,
244
+ wordWrapEnabled: updatedToggleState
245
+ },
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);
251
+ dispatch(tr);
252
+ }
234
253
  return true;
235
254
  };
@@ -1 +1,2 @@
1
- export { default as codeBlockPlugin } from './plugin';
1
+ export { default as codeBlockPlugin } from './plugin';
2
+ export { createDecorationSetFromTextPositions, generateTextPositionsFromNode } from './pm-plugins/decorators';
@@ -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, isWrapped) => ['div', {
11
+ const toDOM = (node, contentEditable) => ['div', {
12
12
  class: 'code-block'
13
13
  }, ['div', {
14
14
  class: codeBlockClassNames.start,
@@ -16,11 +16,9 @@ const toDOM = (node, contentEditable, isWrapped) => ['div', {
16
16
  }], ['div', {
17
17
  class: codeBlockClassNames.contentWrapper
18
18
  }, ['div', {
19
- class: codeBlockClassNames.gutter,
19
+ class: fg('editor_support_code_block_wrapping') ? codeBlockClassNames.gutterFgWrap : codeBlockClassNames.gutter,
20
20
  contenteditable: 'false'
21
- }], ['div', isWrapped && fg('editor_support_code_block_wrapping') ? {
22
- class: `${codeBlockClassNames.content} ${codeBlockClassNames.contentWrapped}`
23
- } : {
21
+ }], ['div', {
24
22
  class: codeBlockClassNames.content
25
23
  }, ['code', {
26
24
  'data-language': node.attrs.language || '',
@@ -32,7 +30,7 @@ const toDOM = (node, contentEditable, isWrapped) => ['div', {
32
30
  contenteditable: 'false'
33
31
  }]];
34
32
  export class CodeBlockView {
35
- constructor(_node, view, getPos, api, isWrapped, cleanupEditorDisabledListener) {
33
+ constructor(_node, view, getPos, api, cleanupEditorDisabledListener) {
36
34
  var _api$editorDisabled, _api$editorDisabled$s;
37
35
  _defineProperty(this, "ensureLineNumbers", rafSchedule(() => {
38
36
  let lines = 1;
@@ -53,16 +51,17 @@ export class CodeBlockView {
53
51
  const {
54
52
  dom,
55
53
  contentDOM
56
- } = 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), isWrapped));
54
+ } = 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)));
57
55
  this.getPos = getPos;
58
56
  this.view = view;
59
57
  this.node = _node;
60
58
  this.dom = dom;
61
59
  this.contentDOM = contentDOM;
62
- this.lineNumberGutter = this.dom.querySelector(`.${codeBlockClassNames.gutter}`);
60
+ this.lineNumberGutter = this.dom.querySelector(`.${fg('editor_support_code_block_wrapping') ? codeBlockClassNames.gutterFgWrap : codeBlockClassNames.gutter}`);
63
61
  this.api = api;
64
- this.isWrapped = isWrapped;
65
- this.ensureLineNumbers();
62
+ if (!fg('editor_support_code_block_wrapping')) {
63
+ this.ensureLineNumbers();
64
+ }
66
65
  this.handleEditorDisabledChanged();
67
66
  }
68
67
  handleEditorDisabledChanged() {
@@ -127,7 +126,9 @@ export class CodeBlockView {
127
126
  this.contentDOM.setAttribute('data-language', node.attrs.language || '');
128
127
  }
129
128
  this.node = node;
130
- this.ensureLineNumbers();
129
+ if (!fg('editor_support_code_block_wrapping')) {
130
+ this.ensureLineNumbers();
131
+ }
131
132
  if (browser.android) {
132
133
  this.coalesceDOMElements();
133
134
  resetShouldIgnoreFollowingMutations(this.view.state, this.view.dispatch);
@@ -151,4 +152,4 @@ export class CodeBlockView {
151
152
  this.cleanupEditorDisabledListener = undefined;
152
153
  }
153
154
  }
154
- export const codeBlockNodeView = (node, view, getPos, api, isWrapped) => new CodeBlockView(node, view, getPos, api, isWrapped);
155
+ export const codeBlockNodeView = (node, view, getPos, api) => new CodeBlockView(node, view, getPos, api);
@@ -0,0 +1,41 @@
1
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
+ import { codeBlockClassNames } from '../ui/class-names';
3
+ export const generateTextPositionsFromNode = (pos, node) => {
4
+ // Get content node
5
+ const contentNode = node.content;
6
+
7
+ // Get node text content
8
+ let textPositions = [];
9
+ contentNode.forEach(child => {
10
+ const nodeTextContent = child.textContent;
11
+ const nodeStartPos = pos;
12
+ let lineStartIndex = nodeStartPos;
13
+ const newLinePositions = nodeTextContent.split('\n').map(line => {
14
+ const lineLength = line.length;
15
+ const lineStart = lineStartIndex + 1;
16
+ const lineEnd = lineStart + lineLength;
17
+
18
+ // Include the newline character and increment to keep tabs on line position
19
+ lineStartIndex += lineLength + 1;
20
+ return {
21
+ lineStart,
22
+ lineEnd
23
+ };
24
+ });
25
+ textPositions = [...textPositions, ...newLinePositions];
26
+ });
27
+ return textPositions;
28
+ };
29
+ export const createDecorationSetFromTextPositions = textPositions => {
30
+ const decorations = textPositions.map(textPosition => {
31
+ const {
32
+ lineStart,
33
+ lineEnd
34
+ } = textPosition;
35
+ return Decoration.inline(lineStart, lineEnd, {
36
+ class: codeBlockClassNames.lineNumberWrapped
37
+ });
38
+ });
39
+ return decorations;
40
+ };
41
+ export const createLineNumbersDecorations = (pos, node) => createDecorationSetFromTextPositions(generateTextPositionsFromNode(pos, node));
@@ -2,12 +2,15 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
3
3
  import { browser } from '@atlaskit/editor-common/utils';
4
4
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
5
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
+ import { fg } from '@atlaskit/platform-feature-flags';
5
7
  import { ignoreFollowingMutations, resetShouldIgnoreFollowingMutations } from '../actions';
6
8
  import { codeBlockNodeView } from '../nodeviews/code-block';
7
9
  import { pluginKey } from '../plugin-key';
8
10
  import { codeBlockClassNames } from '../ui/class-names';
9
11
  import { findCodeBlock } from '../utils';
10
12
  import { ACTIONS } from './actions';
13
+ import { createLineNumbersDecorations } from './decorators';
11
14
  export const createPlugin = ({
12
15
  useLongPressSelection = false,
13
16
  getIntl,
@@ -61,16 +64,24 @@ export const createPlugin = ({
61
64
  pos: node ? node.pos : null,
62
65
  contentCopied: false,
63
66
  isNodeSelected: false,
64
- shouldIgnoreFollowingMutations: false
67
+ shouldIgnoreFollowingMutations: false,
68
+ decorations: DecorationSet.empty
65
69
  };
66
70
  },
67
71
  apply(tr, pluginState, _oldState, newState) {
68
72
  if (tr.docChanged || tr.selectionSet) {
69
73
  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
+ }
70
80
  const newPluginState = {
71
81
  ...pluginState,
72
82
  pos: node ? node.pos : null,
73
- isNodeSelected: tr.selection instanceof NodeSelection
83
+ isNodeSelected: tr.selection instanceof NodeSelection,
84
+ decorations: fg('editor_support_code_block_wrapping') ? DecorationSet.create(tr.doc, lineNumberDecorators) : DecorationSet.empty
74
85
  };
75
86
  return newPluginState;
76
87
  }
@@ -91,8 +102,14 @@ export const createPlugin = ({
91
102
  },
92
103
  key: pluginKey,
93
104
  props: {
105
+ decorations(state) {
106
+ if (fg('editor_support_code_block_wrapping')) {
107
+ return pluginKey.getState(state).decorations || DecorationSet.empty;
108
+ }
109
+ return undefined;
110
+ },
94
111
  nodeViews: {
95
- codeBlock: (node, view, getPos) => codeBlockNodeView(node, view, getPos, api, isWrapped)
112
+ codeBlock: (node, view, getPos) => codeBlockNodeView(node, view, getPos, api)
96
113
  },
97
114
  handleClickOn: createSelectionClickHandler(['codeBlock'], target => !!(target.closest(`.${codeBlockClassNames.gutter}`) || target.classList.contains(codeBlockClassNames.content)), {
98
115
  useLongPressSelection
@@ -86,7 +86,7 @@ export const getToolbarConfig = (allowCopyToClipboard = false, api) => (state, {
86
86
  id: 'editor.codeBlock.wrap',
87
87
  type: 'button',
88
88
  icon: WrapIcon,
89
- onClick: toggleWordWrapStateForCodeBlockNode,
89
+ onClick: toggleWordWrapStateForCodeBlockNode(editorAnalyticsAPI),
90
90
  // Hooking up here for demo purposes. To be revisited with ED-24222.
91
91
  title: formatMessage(codeBlockButtonMessages.wrapCode),
92
92
  tabIndex: null
@@ -5,6 +5,8 @@ export const codeBlockClassNames = {
5
5
  end: CodeBlockSharedCssClassName.CODEBLOCK_END,
6
6
  contentWrapper: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPER,
7
7
  gutter: CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER,
8
+ gutterFgWrap: CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER_FG_WRAP,
8
9
  content: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT,
9
- contentWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPED
10
+ contentWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPED,
11
+ lineNumberWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER_LINE_NUMBER_WRAPPED
10
12
  };
@@ -1,4 +1,4 @@
1
- import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
1
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, MODE, PLATFORMS } from '@atlaskit/editor-common/analytics';
2
2
  import { copyToClipboard } from '@atlaskit/editor-common/clipboard';
3
3
  import { codeBlockWrappedStates, isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
4
4
  import { withAnalytics } from '@atlaskit/editor-common/editor-analytics';
@@ -196,20 +196,39 @@ export function insertCodeBlockWithAnalytics(inputMethod, analyticsAPI) {
196
196
  /**
197
197
  * Add the given node to the codeBlockWrappedStates WeakMap with the toggle boolean value.
198
198
  */
199
- export var toggleWordWrapStateForCodeBlockNode = function toggleWordWrapStateForCodeBlockNode(state) {
200
- var _findCodeBlock;
201
- if (!fg('editor_support_code_block_wrapping')) {
202
- return false;
203
- }
204
- var codeBlockNode = (_findCodeBlock = findCodeBlock(state)) === null || _findCodeBlock === void 0 ? void 0 : _findCodeBlock.node;
205
- if (!codeBlockWrappedStates || !codeBlockNode) {
206
- return false;
207
- }
208
- var currentValue = isCodeBlockWordWrapEnabled(codeBlockNode);
209
- codeBlockWrappedStates.set(codeBlockNode, !currentValue);
199
+ export var toggleWordWrapStateForCodeBlockNode = function toggleWordWrapStateForCodeBlockNode(editorAnalyticsAPI) {
200
+ return function (state, dispatch) {
201
+ var _findCodeBlock;
202
+ if (!fg('editor_support_code_block_wrapping')) {
203
+ return false;
204
+ }
205
+ var codeBlockNode = (_findCodeBlock = findCodeBlock(state)) === null || _findCodeBlock === void 0 ? void 0 : _findCodeBlock.node;
206
+ var tr = state.tr;
207
+ if (!codeBlockWrappedStates || !codeBlockNode) {
208
+ return false;
209
+ }
210
+ var updatedToggleState = !isCodeBlockWordWrapEnabled(codeBlockNode);
211
+ codeBlockWrappedStates.set(codeBlockNode, updatedToggleState);
210
212
 
211
- // TODO: Remove in ED-24222. Leaving here for demo purposes.
212
- // eslint-disable-next-line no-console
213
- console.log("Code Block Word Wrap: Updating codeBlockWrappedStates with: ".concat(codeBlockWrappedStates.get(codeBlockNode)));
214
- return true;
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));
216
+ if (dispatch) {
217
+ var payload = {
218
+ action: ACTION.TOGGLE_CODE_BLOCK_WRAP,
219
+ actionSubject: ACTION_SUBJECT.CODE_BLOCK,
220
+ attributes: {
221
+ platform: PLATFORMS.WEB,
222
+ mode: MODE.EDITOR,
223
+ wordWrapEnabled: updatedToggleState
224
+ },
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);
230
+ dispatch(tr);
231
+ }
232
+ return true;
233
+ };
215
234
  };
package/dist/esm/index.js CHANGED
@@ -1 +1,2 @@
1
- export { default as codeBlockPlugin } from './plugin';
1
+ export { default as codeBlockPlugin } from './plugin';
2
+ export { createDecorationSetFromTextPositions, generateTextPositionsFromNode } from './pm-plugins/decorators';
@@ -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, isWrapped) {
13
+ var toDOM = function toDOM(node, contentEditable) {
14
14
  return ['div', {
15
15
  class: 'code-block'
16
16
  }, ['div', {
@@ -19,11 +19,9 @@ var toDOM = function toDOM(node, contentEditable, isWrapped) {
19
19
  }], ['div', {
20
20
  class: codeBlockClassNames.contentWrapper
21
21
  }, ['div', {
22
- class: codeBlockClassNames.gutter,
22
+ class: fg('editor_support_code_block_wrapping') ? codeBlockClassNames.gutterFgWrap : codeBlockClassNames.gutter,
23
23
  contenteditable: 'false'
24
- }], ['div', isWrapped && fg('editor_support_code_block_wrapping') ? {
25
- class: "".concat(codeBlockClassNames.content, " ").concat(codeBlockClassNames.contentWrapped)
26
- } : {
24
+ }], ['div', {
27
25
  class: codeBlockClassNames.content
28
26
  }, ['code', {
29
27
  'data-language': node.attrs.language || '',
@@ -36,7 +34,7 @@ var toDOM = function toDOM(node, contentEditable, isWrapped) {
36
34
  }]];
37
35
  };
38
36
  export var CodeBlockView = /*#__PURE__*/function () {
39
- function CodeBlockView(_node, view, getPos, api, isWrapped, cleanupEditorDisabledListener) {
37
+ function CodeBlockView(_node, view, getPos, api, cleanupEditorDisabledListener) {
40
38
  var _this = this,
41
39
  _api$editorDisabled;
42
40
  _classCallCheck(this, CodeBlockView);
@@ -56,7 +54,7 @@ export var CodeBlockView = /*#__PURE__*/function () {
56
54
  }
57
55
  }));
58
56
  this.cleanupEditorDisabledListener = cleanupEditorDisabledListener;
59
- 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), isWrapped)),
57
+ 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))),
60
58
  dom = _DOMSerializer$render.dom,
61
59
  contentDOM = _DOMSerializer$render.contentDOM;
62
60
  this.getPos = getPos;
@@ -64,10 +62,11 @@ export var CodeBlockView = /*#__PURE__*/function () {
64
62
  this.node = _node;
65
63
  this.dom = dom;
66
64
  this.contentDOM = contentDOM;
67
- this.lineNumberGutter = this.dom.querySelector(".".concat(codeBlockClassNames.gutter));
65
+ this.lineNumberGutter = this.dom.querySelector(".".concat(fg('editor_support_code_block_wrapping') ? codeBlockClassNames.gutterFgWrap : codeBlockClassNames.gutter));
68
66
  this.api = api;
69
- this.isWrapped = isWrapped;
70
- this.ensureLineNumbers();
67
+ if (!fg('editor_support_code_block_wrapping')) {
68
+ this.ensureLineNumbers();
69
+ }
71
70
  this.handleEditorDisabledChanged();
72
71
  }
73
72
  _createClass(CodeBlockView, [{
@@ -143,7 +142,9 @@ export var CodeBlockView = /*#__PURE__*/function () {
143
142
  this.contentDOM.setAttribute('data-language', node.attrs.language || '');
144
143
  }
145
144
  this.node = node;
146
- this.ensureLineNumbers();
145
+ if (!fg('editor_support_code_block_wrapping')) {
146
+ this.ensureLineNumbers();
147
+ }
147
148
  if (browser.android) {
148
149
  this.coalesceDOMElements();
149
150
  resetShouldIgnoreFollowingMutations(this.view.state, this.view.dispatch);
@@ -173,6 +174,6 @@ export var CodeBlockView = /*#__PURE__*/function () {
173
174
  }]);
174
175
  return CodeBlockView;
175
176
  }();
176
- export var codeBlockNodeView = function codeBlockNodeView(node, view, getPos, api, isWrapped) {
177
- return new CodeBlockView(node, view, getPos, api, isWrapped);
177
+ export var codeBlockNodeView = function codeBlockNodeView(node, view, getPos, api) {
178
+ return new CodeBlockView(node, view, getPos, api);
178
179
  };
@@ -0,0 +1,42 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
+ import { codeBlockClassNames } from '../ui/class-names';
4
+ export var generateTextPositionsFromNode = function generateTextPositionsFromNode(pos, node) {
5
+ // Get content node
6
+ var contentNode = node.content;
7
+
8
+ // Get node text content
9
+ var textPositions = [];
10
+ contentNode.forEach(function (child) {
11
+ var nodeTextContent = child.textContent;
12
+ var nodeStartPos = pos;
13
+ var lineStartIndex = nodeStartPos;
14
+ var newLinePositions = nodeTextContent.split('\n').map(function (line) {
15
+ var lineLength = line.length;
16
+ var lineStart = lineStartIndex + 1;
17
+ var lineEnd = lineStart + lineLength;
18
+
19
+ // Include the newline character and increment to keep tabs on line position
20
+ lineStartIndex += lineLength + 1;
21
+ return {
22
+ lineStart: lineStart,
23
+ lineEnd: lineEnd
24
+ };
25
+ });
26
+ textPositions = [].concat(_toConsumableArray(textPositions), _toConsumableArray(newLinePositions));
27
+ });
28
+ return textPositions;
29
+ };
30
+ export var createDecorationSetFromTextPositions = function createDecorationSetFromTextPositions(textPositions) {
31
+ var decorations = textPositions.map(function (textPosition) {
32
+ var lineStart = textPosition.lineStart,
33
+ lineEnd = textPosition.lineEnd;
34
+ return Decoration.inline(lineStart, lineEnd, {
35
+ class: codeBlockClassNames.lineNumberWrapped
36
+ });
37
+ });
38
+ return decorations;
39
+ };
40
+ export var createLineNumbersDecorations = function createLineNumbersDecorations(pos, node) {
41
+ return createDecorationSetFromTextPositions(generateTextPositionsFromNode(pos, node));
42
+ };
@@ -5,12 +5,15 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
5
5
  import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
6
6
  import { browser } from '@atlaskit/editor-common/utils';
7
7
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
8
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
9
+ import { fg } from '@atlaskit/platform-feature-flags';
8
10
  import { ignoreFollowingMutations, resetShouldIgnoreFollowingMutations } from '../actions';
9
11
  import { codeBlockNodeView } from '../nodeviews/code-block';
10
12
  import { pluginKey } from '../plugin-key';
11
13
  import { codeBlockClassNames } from '../ui/class-names';
12
14
  import { findCodeBlock } from '../utils';
13
15
  import { ACTIONS } from './actions';
16
+ import { createLineNumbersDecorations } from './decorators';
14
17
  export var createPlugin = function createPlugin(_ref) {
15
18
  var _ref$useLongPressSele = _ref.useLongPressSelection,
16
19
  useLongPressSelection = _ref$useLongPressSele === void 0 ? false : _ref$useLongPressSele,
@@ -68,15 +71,23 @@ export var createPlugin = function createPlugin(_ref) {
68
71
  pos: node ? node.pos : null,
69
72
  contentCopied: false,
70
73
  isNodeSelected: false,
71
- shouldIgnoreFollowingMutations: false
74
+ shouldIgnoreFollowingMutations: false,
75
+ decorations: DecorationSet.empty
72
76
  };
73
77
  },
74
78
  apply: function apply(tr, pluginState, _oldState, newState) {
75
79
  if (tr.docChanged || tr.selectionSet) {
76
80
  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
+ }
77
87
  var newPluginState = _objectSpread(_objectSpread({}, pluginState), {}, {
78
88
  pos: node ? node.pos : null,
79
- isNodeSelected: tr.selection instanceof NodeSelection
89
+ isNodeSelected: tr.selection instanceof NodeSelection,
90
+ decorations: fg('editor_support_code_block_wrapping') ? DecorationSet.create(tr.doc, lineNumberDecorators) : DecorationSet.empty
80
91
  });
81
92
  return newPluginState;
82
93
  }
@@ -95,9 +106,15 @@ export var createPlugin = function createPlugin(_ref) {
95
106
  },
96
107
  key: pluginKey,
97
108
  props: {
109
+ decorations: function decorations(state) {
110
+ if (fg('editor_support_code_block_wrapping')) {
111
+ return pluginKey.getState(state).decorations || DecorationSet.empty;
112
+ }
113
+ return undefined;
114
+ },
98
115
  nodeViews: {
99
116
  codeBlock: function codeBlock(node, view, getPos) {
100
- return codeBlockNodeView(node, view, getPos, api, isWrapped);
117
+ return codeBlockNodeView(node, view, getPos, api);
101
118
  }
102
119
  },
103
120
  handleClickOn: createSelectionClickHandler(['codeBlock'], function (target) {
@@ -95,7 +95,7 @@ export var getToolbarConfig = function getToolbarConfig() {
95
95
  id: 'editor.codeBlock.wrap',
96
96
  type: 'button',
97
97
  icon: WrapIcon,
98
- onClick: toggleWordWrapStateForCodeBlockNode,
98
+ onClick: toggleWordWrapStateForCodeBlockNode(editorAnalyticsAPI),
99
99
  // Hooking up here for demo purposes. To be revisited with ED-24222.
100
100
  title: formatMessage(codeBlockButtonMessages.wrapCode),
101
101
  tabIndex: null
@@ -5,6 +5,8 @@ export var codeBlockClassNames = {
5
5
  end: CodeBlockSharedCssClassName.CODEBLOCK_END,
6
6
  contentWrapper: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPER,
7
7
  gutter: CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER,
8
+ gutterFgWrap: CodeBlockSharedCssClassName.CODEBLOCK_LINE_NUMBER_GUTTER_FG_WRAP,
8
9
  content: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT,
9
- contentWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPED
10
+ contentWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTENT_WRAPPED,
11
+ lineNumberWrapped: CodeBlockSharedCssClassName.CODEBLOCK_CONTAINER_LINE_NUMBER_WRAPPED
10
12
  };
@@ -19,4 +19,4 @@ export declare function insertCodeBlockWithAnalytics(inputMethod: INPUT_METHOD,
19
19
  /**
20
20
  * Add the given node to the codeBlockWrappedStates WeakMap with the toggle boolean value.
21
21
  */
22
- export declare const toggleWordWrapStateForCodeBlockNode: Command;
22
+ export declare const toggleWordWrapStateForCodeBlockNode: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => Command;
@@ -1,3 +1,4 @@
1
1
  export { default as codeBlockPlugin } from './plugin';
2
2
  export type { CodeBlockPlugin } from './plugin';
3
3
  export type { CodeBlockOptions } from './types';
4
+ export { createDecorationSetFromTextPositions, generateTextPositionsFromNode, } from './pm-plugins/decorators';
@@ -11,8 +11,7 @@ export declare class CodeBlockView {
11
11
  getPos: getPosHandlerNode;
12
12
  view: EditorView;
13
13
  api?: ExtractInjectionAPI<CodeBlockPlugin>;
14
- isWrapped?: boolean;
15
- constructor(node: Node, view: EditorView, getPos: getPosHandlerNode, api?: ExtractInjectionAPI<CodeBlockPlugin>, isWrapped?: boolean, cleanupEditorDisabledListener?: (() => void) | undefined);
14
+ constructor(node: Node, view: EditorView, getPos: getPosHandlerNode, api?: ExtractInjectionAPI<CodeBlockPlugin>, cleanupEditorDisabledListener?: (() => void) | undefined);
16
15
  handleEditorDisabledChanged(): void;
17
16
  updateDOMAndSelection(savedInnerHTML: string, newCursorPosition: number): void;
18
17
  coalesceDOMElements(): void;
@@ -24,4 +23,4 @@ export declare class CodeBlockView {
24
23
  }): boolean;
25
24
  destroy(): void;
26
25
  }
27
- export declare const codeBlockNodeView: (node: Node, view: EditorView, getPos: getPosHandler, api: ExtractInjectionAPI<CodeBlockPlugin> | undefined, isWrapped: boolean | undefined) => CodeBlockView;
26
+ export declare const codeBlockNodeView: (node: Node, view: EditorView, getPos: getPosHandler, api: ExtractInjectionAPI<CodeBlockPlugin> | undefined) => CodeBlockView;
@@ -0,0 +1,6 @@
1
+ import type { Node } from '@atlaskit/editor-prosemirror/model';
2
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
+ import type { CodeBlockTextPosition } from '../types';
4
+ export declare const generateTextPositionsFromNode: (pos: number, node: Node) => CodeBlockTextPosition[];
5
+ export declare const createDecorationSetFromTextPositions: (textPositions: CodeBlockTextPosition[]) => Decoration[];
6
+ export declare const createLineNumbersDecorations: (pos: number, node: Node) => Decoration[];
@@ -1,8 +1,10 @@
1
1
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
2
+ import type { DecorationSet } from '@atlaskit/editor-prosemirror/view';
2
3
  export type CodeBlockState = {
3
4
  pos: number | null;
4
5
  contentCopied: boolean;
5
6
  isNodeSelected: boolean;
6
7
  shouldIgnoreFollowingMutations: boolean;
8
+ decorations: DecorationSet;
7
9
  };
8
10
  export declare const getPluginState: (state: EditorState) => CodeBlockState;
@@ -1,6 +1,7 @@
1
1
  import type { IntlShape } from 'react-intl-next';
2
2
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
3
3
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
4
5
  import type { CodeBlockPlugin } from '../index';
5
6
  import { type CodeBlockState } from './main-state';
6
7
  export declare const createPlugin: ({ useLongPressSelection, getIntl, allowCompositionInputOverride, api, isWrapped, }: {
@@ -37,4 +38,5 @@ export declare const createPlugin: ({ useLongPressSelection, getIntl, allowCompo
37
38
  };
38
39
  }> | undefined;
39
40
  isWrapped?: boolean | undefined;
41
+ decorations?: DecorationSet | undefined;
40
42
  }) => SafePlugin<CodeBlockState>;
@@ -3,3 +3,7 @@ export interface CodeBlockOptions extends LongPressSelectionPluginOptions {
3
3
  allowCopyToClipboard?: boolean;
4
4
  allowCompositionInputOverride?: boolean;
5
5
  }
6
+ export type CodeBlockTextPosition = {
7
+ lineStart: number;
8
+ lineEnd: number;
9
+ };
@@ -4,6 +4,8 @@ export declare const codeBlockClassNames: {
4
4
  end: string;
5
5
  contentWrapper: string;
6
6
  gutter: string;
7
+ gutterFgWrap: string;
7
8
  content: string;
8
9
  contentWrapped: string;
10
+ lineNumberWrapped: string;
9
11
  };
@@ -19,4 +19,4 @@ export declare function insertCodeBlockWithAnalytics(inputMethod: INPUT_METHOD,
19
19
  /**
20
20
  * Add the given node to the codeBlockWrappedStates WeakMap with the toggle boolean value.
21
21
  */
22
- export declare const toggleWordWrapStateForCodeBlockNode: Command;
22
+ export declare const toggleWordWrapStateForCodeBlockNode: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => Command;
@@ -1,3 +1,4 @@
1
1
  export { default as codeBlockPlugin } from './plugin';
2
2
  export type { CodeBlockPlugin } from './plugin';
3
3
  export type { CodeBlockOptions } from './types';
4
+ export { createDecorationSetFromTextPositions, generateTextPositionsFromNode, } from './pm-plugins/decorators';
@@ -11,8 +11,7 @@ export declare class CodeBlockView {
11
11
  getPos: getPosHandlerNode;
12
12
  view: EditorView;
13
13
  api?: ExtractInjectionAPI<CodeBlockPlugin>;
14
- isWrapped?: boolean;
15
- constructor(node: Node, view: EditorView, getPos: getPosHandlerNode, api?: ExtractInjectionAPI<CodeBlockPlugin>, isWrapped?: boolean, cleanupEditorDisabledListener?: (() => void) | undefined);
14
+ constructor(node: Node, view: EditorView, getPos: getPosHandlerNode, api?: ExtractInjectionAPI<CodeBlockPlugin>, cleanupEditorDisabledListener?: (() => void) | undefined);
16
15
  handleEditorDisabledChanged(): void;
17
16
  updateDOMAndSelection(savedInnerHTML: string, newCursorPosition: number): void;
18
17
  coalesceDOMElements(): void;
@@ -24,4 +23,4 @@ export declare class CodeBlockView {
24
23
  }): boolean;
25
24
  destroy(): void;
26
25
  }
27
- export declare const codeBlockNodeView: (node: Node, view: EditorView, getPos: getPosHandler, api: ExtractInjectionAPI<CodeBlockPlugin> | undefined, isWrapped: boolean | undefined) => CodeBlockView;
26
+ export declare const codeBlockNodeView: (node: Node, view: EditorView, getPos: getPosHandler, api: ExtractInjectionAPI<CodeBlockPlugin> | undefined) => CodeBlockView;
@@ -0,0 +1,6 @@
1
+ import type { Node } from '@atlaskit/editor-prosemirror/model';
2
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
+ import type { CodeBlockTextPosition } from '../types';
4
+ export declare const generateTextPositionsFromNode: (pos: number, node: Node) => CodeBlockTextPosition[];
5
+ export declare const createDecorationSetFromTextPositions: (textPositions: CodeBlockTextPosition[]) => Decoration[];
6
+ export declare const createLineNumbersDecorations: (pos: number, node: Node) => Decoration[];
@@ -1,8 +1,10 @@
1
1
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
2
+ import type { DecorationSet } from '@atlaskit/editor-prosemirror/view';
2
3
  export type CodeBlockState = {
3
4
  pos: number | null;
4
5
  contentCopied: boolean;
5
6
  isNodeSelected: boolean;
6
7
  shouldIgnoreFollowingMutations: boolean;
8
+ decorations: DecorationSet;
7
9
  };
8
10
  export declare const getPluginState: (state: EditorState) => CodeBlockState;
@@ -1,6 +1,7 @@
1
1
  import type { IntlShape } from 'react-intl-next';
2
2
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
3
3
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
4
5
  import type { CodeBlockPlugin } from '../index';
5
6
  import { type CodeBlockState } from './main-state';
6
7
  export declare const createPlugin: ({ useLongPressSelection, getIntl, allowCompositionInputOverride, api, isWrapped, }: {
@@ -44,4 +45,5 @@ export declare const createPlugin: ({ useLongPressSelection, getIntl, allowCompo
44
45
  };
45
46
  }> | undefined;
46
47
  isWrapped?: boolean | undefined;
48
+ decorations?: DecorationSet | undefined;
47
49
  }) => SafePlugin<CodeBlockState>;
@@ -3,3 +3,7 @@ export interface CodeBlockOptions extends LongPressSelectionPluginOptions {
3
3
  allowCopyToClipboard?: boolean;
4
4
  allowCompositionInputOverride?: boolean;
5
5
  }
6
+ export type CodeBlockTextPosition = {
7
+ lineStart: number;
8
+ lineEnd: number;
9
+ };
@@ -4,6 +4,8 @@ export declare const codeBlockClassNames: {
4
4
  end: string;
5
5
  contentWrapper: string;
6
6
  gutter: string;
7
+ gutterFgWrap: string;
7
8
  content: string;
8
9
  contentWrapped: string;
10
+ lineNumberWrapped: string;
9
11
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-code-block",
3
- "version": "3.2.3",
3
+ "version": "3.2.5",
4
4
  "description": "Code block plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -35,13 +35,13 @@
35
35
  "dependencies": {
36
36
  "@atlaskit/adf-schema": "^40.3.0",
37
37
  "@atlaskit/code": "^15.4.0",
38
- "@atlaskit/editor-common": "^87.0.0",
38
+ "@atlaskit/editor-common": "^87.4.0",
39
39
  "@atlaskit/editor-plugin-analytics": "^1.6.0",
40
40
  "@atlaskit/editor-plugin-composition": "^1.2.0",
41
41
  "@atlaskit/editor-plugin-decorations": "^1.2.0",
42
42
  "@atlaskit/editor-plugin-editor-disabled": "^1.2.0",
43
43
  "@atlaskit/editor-prosemirror": "5.0.1",
44
- "@atlaskit/icon": "^22.8.0",
44
+ "@atlaskit/icon": "^22.10.0",
45
45
  "@atlaskit/platform-feature-flags": "^0.3.0",
46
46
  "@atlaskit/prosemirror-input-rules": "^3.2.0",
47
47
  "@babel/runtime": "^7.0.0",