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

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,27 @@
1
1
  # @atlaskit/editor-plugin-code-block
2
2
 
3
+ ## 3.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#128347](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/128347)
8
+ [`e33566cebd5d1`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/e33566cebd5d1) -
9
+ [ED-24175] bump @atlaskit/adf-schema to 40.8.1 and @atlassian/adf-schema-json to 1.22.0 to
10
+ promotecodeblocks & media in quotes, and nested expands in expands to full schema, and allow
11
+ quotes in panels and decisions in lists in stage0 schema, and a validator spec change
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies
16
+
17
+ ## 3.2.5
18
+
19
+ ### Patch Changes
20
+
21
+ - [#127369](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/127369)
22
+ [`95ff22b16d347`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/95ff22b16d347) -
23
+ [ux] ED-24374 Add support for dynamic line number positions on code block nodeview
24
+
3
25
  ## 3.2.4
4
26
 
5
27
  ### Patch Changes
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) {
@@ -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 +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
@@ -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
  };
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) {
@@ -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
  };
@@ -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
  };
@@ -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.4",
3
+ "version": "3.3.0",
4
4
  "description": "Code block plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -33,15 +33,15 @@
33
33
  ".": "./src/index.ts"
34
34
  },
35
35
  "dependencies": {
36
- "@atlaskit/adf-schema": "^40.3.0",
36
+ "@atlaskit/adf-schema": "^40.8.1",
37
37
  "@atlaskit/code": "^15.4.0",
38
- "@atlaskit/editor-common": "^87.3.0",
39
- "@atlaskit/editor-plugin-analytics": "^1.6.0",
38
+ "@atlaskit/editor-common": "^87.6.0",
39
+ "@atlaskit/editor-plugin-analytics": "^1.7.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.10.0",
44
+ "@atlaskit/icon": "^22.11.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",