@atlaskit/editor-plugin-code-block-advanced 1.0.1 → 1.0.2

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,19 @@
1
1
  # @atlaskit/editor-plugin-code-block-advanced
2
2
 
3
+ ## 1.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [#105726](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/105726)
8
+ [`2eb0f22c4b065`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/2eb0f22c4b065) -
9
+ [ux] Fix toDOM implementation whitespace with 100+ lines of code
10
+ - [#103918](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/103918)
11
+ [`29844093c6ab4`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/29844093c6ab4) -
12
+ Expose new shared state for code block plugin which indicates the current node that the copy text
13
+ button is hovered for. Display highlight decorations for the copy text button in the advanced code
14
+ block plugin.
15
+ - Updated dependencies
16
+
3
17
  ## 1.0.1
4
18
 
5
19
  ### Patch Changes
@@ -20,6 +20,7 @@ var _theme = require("../ui/theme");
20
20
  var _syncCMWithPM = require("./codemirrorSync/syncCMWithPM");
21
21
  var _updateCMSelection = require("./codemirrorSync/updateCMSelection");
22
22
  var _bidiCharWarning = require("./extensions/bidiCharWarning");
23
+ var _copyButtonDecorations = require("./extensions/copyButtonDecorations");
23
24
  var _keymap = require("./extensions/keymap");
24
25
  var _loader = require("./languages/loader");
25
26
  // Based on: https://prosemirror.net/examples/codemirror/
@@ -28,11 +29,13 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
28
29
  function CodeBlockAdvancedNodeView(node, view, getPos, config) {
29
30
  var _config$api,
30
31
  _this = this,
31
- _config$api2;
32
+ _config$api2,
33
+ _config$api3;
32
34
  (0, _classCallCheck2.default)(this, CodeBlockAdvancedNodeView);
33
35
  (0, _defineProperty2.default)(this, "lineWrappingCompartment", new _state.Compartment());
34
36
  (0, _defineProperty2.default)(this, "languageCompartment", new _state.Compartment());
35
37
  (0, _defineProperty2.default)(this, "readOnlyCompartment", new _state.Compartment());
38
+ (0, _defineProperty2.default)(this, "copyDecoCompartment", new _state.Compartment());
36
39
  (0, _defineProperty2.default)(this, "maybeTryingToReachNodeSelection", false);
37
40
  (0, _defineProperty2.default)(this, "wordWrappingEnabled", false);
38
41
  this.node = node;
@@ -48,6 +51,13 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
48
51
  this.cleanupDisabledState = (_config$api2 = config.api) === null || _config$api2 === void 0 || (_config$api2 = _config$api2.editorDisabled) === null || _config$api2 === void 0 ? void 0 : _config$api2.sharedState.onChange(function () {
49
52
  _this.updateReadonlyState();
50
53
  });
54
+ this.cleanupCopyButtonDecoration = (_config$api3 = config.api) === null || _config$api3 === void 0 || (_config$api3 = _config$api3.codeBlock) === null || _config$api3 === void 0 ? void 0 : _config$api3.sharedState.onChange(function (_ref) {
55
+ var nextSharedState = _ref.nextSharedState,
56
+ prevSharedState = _ref.prevSharedState;
57
+ if ((nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.copyButtonHoverNode) !== (prevSharedState === null || prevSharedState === void 0 ? void 0 : prevSharedState.copyButtonHoverNode)) {
58
+ _this.addCopyButtonDecoration(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.copyButtonHoverNode);
59
+ }
60
+ });
51
61
  this.languageLoader = new _loader.LanguageLoader(function (lang) {
52
62
  _this.updating = true;
53
63
  _this.cm.dispatch({
@@ -57,13 +67,13 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
57
67
  });
58
68
  this.cm = new _view.EditorView({
59
69
  doc: this.node.textContent,
60
- extensions: [].concat((0, _toConsumableArray2.default)(config.extensions), [this.lineWrappingCompartment.of([]), this.languageCompartment.of([]), (0, _keymap.keymapExtension)({
70
+ extensions: [].concat((0, _toConsumableArray2.default)(config.extensions), [this.lineWrappingCompartment.of([]), this.languageCompartment.of([]), this.copyDecoCompartment.of([]), (0, _keymap.keymapExtension)({
61
71
  view: view,
62
72
  getPos: getPos,
63
73
  getNode: getNode,
64
74
  selectCodeBlockNode: this.selectCodeBlockNode.bind(this),
65
75
  onMaybeNodeSelection: onMaybeNodeSelection
66
- }), _theme.cmTheme, (0, _language.syntaxHighlighting)(_syntaxHighlightingTheme.highlightStyle), (0, _view.lineNumbers)(),
76
+ }), _theme.cmTheme, (0, _language.syntaxHighlighting)(_syntaxHighlightingTheme.highlightStyle), (0, _language.bracketMatching)(), (0, _view.lineNumbers)(),
67
77
  // Explicitly disable "sticky" positioning on line numbers to match
68
78
  // Renderer behaviour
69
79
  (0, _view.gutters)({
@@ -86,8 +96,9 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
86
96
  return (0, _createClass2.default)(CodeBlockAdvancedNodeView, [{
87
97
  key: "destroy",
88
98
  value: function destroy() {
89
- var _this$cleanupDisabled;
99
+ var _this$cleanupDisabled, _this$cleanupCopyButt;
90
100
  (_this$cleanupDisabled = this.cleanupDisabledState) === null || _this$cleanupDisabled === void 0 || _this$cleanupDisabled.call(this);
101
+ (_this$cleanupCopyButt = this.cleanupCopyButtonDecoration) === null || _this$cleanupCopyButt === void 0 || _this$cleanupCopyButt.call(this);
91
102
  }
92
103
  }, {
93
104
  key: "forwardUpdate",
@@ -144,6 +155,15 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
144
155
  this.view.dispatch(tr);
145
156
  }
146
157
  }
158
+ }, {
159
+ key: "addCopyButtonDecoration",
160
+ value: function addCopyButtonDecoration(node) {
161
+ this.updating = true;
162
+ this.cm.dispatch({
163
+ effects: [this.copyDecoCompartment.reconfigure(node && node === this.node ? _copyButtonDecorations.copyButtonDecorations : [])]
164
+ });
165
+ this.updating = false;
166
+ }
147
167
  }, {
148
168
  key: "updateWordWrap",
149
169
  value: function updateWordWrap(node) {
@@ -60,7 +60,8 @@ var _toDOM = function toDOM(node, formattedAriaLabel) {
60
60
  style: (0, _lazyNodeView.convertToInlineCss)({
61
61
  textAlign: 'right',
62
62
  color: "var(--ds-text-subtlest, #626F86)",
63
- fontFamily: "var(--ds-font-family-code, ui-monospace, Menlo, \"Segoe UI Mono\", \"Ubuntu Mono\", monospace)"
63
+ fontFamily: "var(--ds-font-family-code, ui-monospace, Menlo, \"Segoe UI Mono\", \"Ubuntu Mono\", monospace)",
64
+ whiteSpace: 'pre-wrap'
64
65
  }),
65
66
  'data-label': content
66
67
  }]], ['div', {
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.copyButtonDecorations = void 0;
7
+ var _state = require("@codemirror/state");
8
+ var _view = require("@codemirror/view");
9
+ var copyButtonDecorations = exports.copyButtonDecorations = _view.EditorView.decorations.compute([], function (state) {
10
+ var allTextDecoration = _view.Decoration.mark({
11
+ attributes: {
12
+ class: 'ProseMirror-fake-text-selection'
13
+ }
14
+ });
15
+ // Create a set of decorations for the entire document
16
+ var builder = new _state.RangeSetBuilder();
17
+ for (var i = 0; i < state.doc.lines; i++) {
18
+ builder.add(state.doc.line(i + 1).from, state.doc.line(i + 1).to, allTextDecoration);
19
+ }
20
+ var decorations = builder.finish();
21
+ return decorations;
22
+ });
@@ -1,6 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { closeBrackets } from '@codemirror/autocomplete';
3
- import { syntaxHighlighting } from '@codemirror/language';
3
+ import { syntaxHighlighting, bracketMatching } from '@codemirror/language';
4
4
  import { Compartment, EditorSelection } from '@codemirror/state';
5
5
  import { EditorView as CodeMirror, lineNumbers, gutters } from '@codemirror/view';
6
6
  import { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
@@ -10,16 +10,18 @@ import { cmTheme } from '../ui/theme';
10
10
  import { syncCMWithPM } from './codemirrorSync/syncCMWithPM';
11
11
  import { updateCMSelection } from './codemirrorSync/updateCMSelection';
12
12
  import { bidiCharWarningExtension } from './extensions/bidiCharWarning';
13
+ import { copyButtonDecorations } from './extensions/copyButtonDecorations';
13
14
  import { keymapExtension } from './extensions/keymap';
14
15
  import { LanguageLoader } from './languages/loader';
15
16
  // Based on: https://prosemirror.net/examples/codemirror/
16
17
  class CodeBlockAdvancedNodeView {
17
18
  // eslint-disable-next-line @typescript-eslint/max-params
18
19
  constructor(node, view, getPos, config) {
19
- var _config$api, _config$api$selection, _config$api2, _config$api2$editorDi;
20
+ var _config$api, _config$api$selection, _config$api2, _config$api2$editorDi, _config$api3, _config$api3$codeBloc;
20
21
  _defineProperty(this, "lineWrappingCompartment", new Compartment());
21
22
  _defineProperty(this, "languageCompartment", new Compartment());
22
23
  _defineProperty(this, "readOnlyCompartment", new Compartment());
24
+ _defineProperty(this, "copyDecoCompartment", new Compartment());
23
25
  _defineProperty(this, "maybeTryingToReachNodeSelection", false);
24
26
  _defineProperty(this, "wordWrappingEnabled", false);
25
27
  this.node = node;
@@ -31,6 +33,14 @@ class CodeBlockAdvancedNodeView {
31
33
  this.cleanupDisabledState = (_config$api2 = config.api) === null || _config$api2 === void 0 ? void 0 : (_config$api2$editorDi = _config$api2.editorDisabled) === null || _config$api2$editorDi === void 0 ? void 0 : _config$api2$editorDi.sharedState.onChange(() => {
32
34
  this.updateReadonlyState();
33
35
  });
36
+ this.cleanupCopyButtonDecoration = (_config$api3 = config.api) === null || _config$api3 === void 0 ? void 0 : (_config$api3$codeBloc = _config$api3.codeBlock) === null || _config$api3$codeBloc === void 0 ? void 0 : _config$api3$codeBloc.sharedState.onChange(({
37
+ nextSharedState,
38
+ prevSharedState
39
+ }) => {
40
+ if ((nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.copyButtonHoverNode) !== (prevSharedState === null || prevSharedState === void 0 ? void 0 : prevSharedState.copyButtonHoverNode)) {
41
+ this.addCopyButtonDecoration(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.copyButtonHoverNode);
42
+ }
43
+ });
34
44
  this.languageLoader = new LanguageLoader(lang => {
35
45
  this.updating = true;
36
46
  this.cm.dispatch({
@@ -40,13 +50,13 @@ class CodeBlockAdvancedNodeView {
40
50
  });
41
51
  this.cm = new CodeMirror({
42
52
  doc: this.node.textContent,
43
- extensions: [...config.extensions, this.lineWrappingCompartment.of([]), this.languageCompartment.of([]), keymapExtension({
53
+ extensions: [...config.extensions, this.lineWrappingCompartment.of([]), this.languageCompartment.of([]), this.copyDecoCompartment.of([]), keymapExtension({
44
54
  view,
45
55
  getPos,
46
56
  getNode,
47
57
  selectCodeBlockNode: this.selectCodeBlockNode.bind(this),
48
58
  onMaybeNodeSelection
49
- }), cmTheme, syntaxHighlighting(highlightStyle), lineNumbers(),
59
+ }), cmTheme, syntaxHighlighting(highlightStyle), bracketMatching(), lineNumbers(),
50
60
  // Explicitly disable "sticky" positioning on line numbers to match
51
61
  // Renderer behaviour
52
62
  gutters({
@@ -65,8 +75,9 @@ class CodeBlockAdvancedNodeView {
65
75
  this.updateLanguage();
66
76
  }
67
77
  destroy() {
68
- var _this$cleanupDisabled;
78
+ var _this$cleanupDisabled, _this$cleanupCopyButt;
69
79
  (_this$cleanupDisabled = this.cleanupDisabledState) === null || _this$cleanupDisabled === void 0 ? void 0 : _this$cleanupDisabled.call(this);
80
+ (_this$cleanupCopyButt = this.cleanupCopyButtonDecoration) === null || _this$cleanupCopyButt === void 0 ? void 0 : _this$cleanupCopyButt.call(this);
70
81
  }
71
82
  forwardUpdate(update) {
72
83
  var _this$getPos, _this$getPos2;
@@ -113,6 +124,13 @@ class CodeBlockAdvancedNodeView {
113
124
  this.view.dispatch(tr);
114
125
  }
115
126
  }
127
+ addCopyButtonDecoration(node) {
128
+ this.updating = true;
129
+ this.cm.dispatch({
130
+ effects: [this.copyDecoCompartment.reconfigure(node && node === this.node ? copyButtonDecorations : [])]
131
+ });
132
+ this.updating = false;
133
+ }
116
134
  updateWordWrap(node) {
117
135
  if (this.wordWrappingEnabled !== isCodeBlockWordWrapEnabled(node)) {
118
136
  this.updating = true;
@@ -48,7 +48,8 @@ const toDOM = (node, formattedAriaLabel) => {
48
48
  style: convertToInlineCss({
49
49
  textAlign: 'right',
50
50
  color: "var(--ds-text-subtlest, #626F86)",
51
- fontFamily: "var(--ds-font-family-code, ui-monospace, Menlo, \"Segoe UI Mono\", \"Ubuntu Mono\", monospace)"
51
+ fontFamily: "var(--ds-font-family-code, ui-monospace, Menlo, \"Segoe UI Mono\", \"Ubuntu Mono\", monospace)",
52
+ whiteSpace: 'pre-wrap'
52
53
  }),
53
54
  'data-label': content
54
55
  }]], ['div', {
@@ -0,0 +1,16 @@
1
+ import { RangeSetBuilder } from '@codemirror/state';
2
+ import { EditorView as CodeMirror, Decoration } from '@codemirror/view';
3
+ export const copyButtonDecorations = CodeMirror.decorations.compute([], state => {
4
+ const allTextDecoration = Decoration.mark({
5
+ attributes: {
6
+ class: 'ProseMirror-fake-text-selection'
7
+ }
8
+ });
9
+ // Create a set of decorations for the entire document
10
+ const builder = new RangeSetBuilder();
11
+ for (let i = 0; i < state.doc.lines; i++) {
12
+ builder.add(state.doc.line(i + 1).from, state.doc.line(i + 1).to, allTextDecoration);
13
+ }
14
+ const decorations = builder.finish();
15
+ return decorations;
16
+ });
@@ -3,7 +3,7 @@ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
3
  import _createClass from "@babel/runtime/helpers/createClass";
4
4
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
5
5
  import { closeBrackets } from '@codemirror/autocomplete';
6
- import { syntaxHighlighting } from '@codemirror/language';
6
+ import { syntaxHighlighting, bracketMatching } from '@codemirror/language';
7
7
  import { Compartment, EditorSelection } from '@codemirror/state';
8
8
  import { EditorView as CodeMirror, lineNumbers, gutters } from '@codemirror/view';
9
9
  import { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
@@ -13,6 +13,7 @@ import { cmTheme } from '../ui/theme';
13
13
  import { syncCMWithPM } from './codemirrorSync/syncCMWithPM';
14
14
  import { updateCMSelection } from './codemirrorSync/updateCMSelection';
15
15
  import { bidiCharWarningExtension } from './extensions/bidiCharWarning';
16
+ import { copyButtonDecorations } from './extensions/copyButtonDecorations';
16
17
  import { keymapExtension } from './extensions/keymap';
17
18
  import { LanguageLoader } from './languages/loader';
18
19
  // Based on: https://prosemirror.net/examples/codemirror/
@@ -21,11 +22,13 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
21
22
  function CodeBlockAdvancedNodeView(node, view, getPos, config) {
22
23
  var _config$api,
23
24
  _this = this,
24
- _config$api2;
25
+ _config$api2,
26
+ _config$api3;
25
27
  _classCallCheck(this, CodeBlockAdvancedNodeView);
26
28
  _defineProperty(this, "lineWrappingCompartment", new Compartment());
27
29
  _defineProperty(this, "languageCompartment", new Compartment());
28
30
  _defineProperty(this, "readOnlyCompartment", new Compartment());
31
+ _defineProperty(this, "copyDecoCompartment", new Compartment());
29
32
  _defineProperty(this, "maybeTryingToReachNodeSelection", false);
30
33
  _defineProperty(this, "wordWrappingEnabled", false);
31
34
  this.node = node;
@@ -41,6 +44,13 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
41
44
  this.cleanupDisabledState = (_config$api2 = config.api) === null || _config$api2 === void 0 || (_config$api2 = _config$api2.editorDisabled) === null || _config$api2 === void 0 ? void 0 : _config$api2.sharedState.onChange(function () {
42
45
  _this.updateReadonlyState();
43
46
  });
47
+ this.cleanupCopyButtonDecoration = (_config$api3 = config.api) === null || _config$api3 === void 0 || (_config$api3 = _config$api3.codeBlock) === null || _config$api3 === void 0 ? void 0 : _config$api3.sharedState.onChange(function (_ref) {
48
+ var nextSharedState = _ref.nextSharedState,
49
+ prevSharedState = _ref.prevSharedState;
50
+ if ((nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.copyButtonHoverNode) !== (prevSharedState === null || prevSharedState === void 0 ? void 0 : prevSharedState.copyButtonHoverNode)) {
51
+ _this.addCopyButtonDecoration(nextSharedState === null || nextSharedState === void 0 ? void 0 : nextSharedState.copyButtonHoverNode);
52
+ }
53
+ });
44
54
  this.languageLoader = new LanguageLoader(function (lang) {
45
55
  _this.updating = true;
46
56
  _this.cm.dispatch({
@@ -50,13 +60,13 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
50
60
  });
51
61
  this.cm = new CodeMirror({
52
62
  doc: this.node.textContent,
53
- extensions: [].concat(_toConsumableArray(config.extensions), [this.lineWrappingCompartment.of([]), this.languageCompartment.of([]), keymapExtension({
63
+ extensions: [].concat(_toConsumableArray(config.extensions), [this.lineWrappingCompartment.of([]), this.languageCompartment.of([]), this.copyDecoCompartment.of([]), keymapExtension({
54
64
  view: view,
55
65
  getPos: getPos,
56
66
  getNode: getNode,
57
67
  selectCodeBlockNode: this.selectCodeBlockNode.bind(this),
58
68
  onMaybeNodeSelection: onMaybeNodeSelection
59
- }), cmTheme, syntaxHighlighting(highlightStyle), lineNumbers(),
69
+ }), cmTheme, syntaxHighlighting(highlightStyle), bracketMatching(), lineNumbers(),
60
70
  // Explicitly disable "sticky" positioning on line numbers to match
61
71
  // Renderer behaviour
62
72
  gutters({
@@ -79,8 +89,9 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
79
89
  return _createClass(CodeBlockAdvancedNodeView, [{
80
90
  key: "destroy",
81
91
  value: function destroy() {
82
- var _this$cleanupDisabled;
92
+ var _this$cleanupDisabled, _this$cleanupCopyButt;
83
93
  (_this$cleanupDisabled = this.cleanupDisabledState) === null || _this$cleanupDisabled === void 0 || _this$cleanupDisabled.call(this);
94
+ (_this$cleanupCopyButt = this.cleanupCopyButtonDecoration) === null || _this$cleanupCopyButt === void 0 || _this$cleanupCopyButt.call(this);
84
95
  }
85
96
  }, {
86
97
  key: "forwardUpdate",
@@ -137,6 +148,15 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
137
148
  this.view.dispatch(tr);
138
149
  }
139
150
  }
151
+ }, {
152
+ key: "addCopyButtonDecoration",
153
+ value: function addCopyButtonDecoration(node) {
154
+ this.updating = true;
155
+ this.cm.dispatch({
156
+ effects: [this.copyDecoCompartment.reconfigure(node && node === this.node ? copyButtonDecorations : [])]
157
+ });
158
+ this.updating = false;
159
+ }
140
160
  }, {
141
161
  key: "updateWordWrap",
142
162
  value: function updateWordWrap(node) {
@@ -53,7 +53,8 @@ var _toDOM = function toDOM(node, formattedAriaLabel) {
53
53
  style: convertToInlineCss({
54
54
  textAlign: 'right',
55
55
  color: "var(--ds-text-subtlest, #626F86)",
56
- fontFamily: "var(--ds-font-family-code, ui-monospace, Menlo, \"Segoe UI Mono\", \"Ubuntu Mono\", monospace)"
56
+ fontFamily: "var(--ds-font-family-code, ui-monospace, Menlo, \"Segoe UI Mono\", \"Ubuntu Mono\", monospace)",
57
+ whiteSpace: 'pre-wrap'
57
58
  }),
58
59
  'data-label': content
59
60
  }]], ['div', {
@@ -0,0 +1,16 @@
1
+ import { RangeSetBuilder } from '@codemirror/state';
2
+ import { EditorView as CodeMirror, Decoration } from '@codemirror/view';
3
+ export var copyButtonDecorations = CodeMirror.decorations.compute([], function (state) {
4
+ var allTextDecoration = Decoration.mark({
5
+ attributes: {
6
+ class: 'ProseMirror-fake-text-selection'
7
+ }
8
+ });
9
+ // Create a set of decorations for the entire document
10
+ var builder = new RangeSetBuilder();
11
+ for (var i = 0; i < state.doc.lines; i++) {
12
+ builder.add(state.doc.line(i + 1).from, state.doc.line(i + 1).to, allTextDecoration);
13
+ }
14
+ var decorations = builder.finish();
15
+ return decorations;
16
+ });
@@ -15,12 +15,14 @@ declare class CodeBlockAdvancedNodeView implements NodeView {
15
15
  private lineWrappingCompartment;
16
16
  private languageCompartment;
17
17
  private readOnlyCompartment;
18
+ private copyDecoCompartment;
18
19
  private node;
19
20
  private getPos;
20
21
  private cm;
21
22
  private selectionAPI;
22
23
  private maybeTryingToReachNodeSelection;
23
24
  private cleanupDisabledState;
25
+ private cleanupCopyButtonDecoration;
24
26
  private languageLoader;
25
27
  constructor(node: PMNode, view: EditorView, getPos: getPosHandlerNode, config: ConfigProps);
26
28
  destroy(): void;
@@ -29,6 +31,7 @@ declare class CodeBlockAdvancedNodeView implements NodeView {
29
31
  private updateReadonlyState;
30
32
  private updateLanguage;
31
33
  private selectCodeBlockNode;
34
+ private addCopyButtonDecoration;
32
35
  private wordWrappingEnabled;
33
36
  private updateWordWrap;
34
37
  update(node: PMNode): boolean;
@@ -0,0 +1 @@
1
+ export declare const copyButtonDecorations: import("@codemirror/state").Extension;
@@ -15,12 +15,14 @@ declare class CodeBlockAdvancedNodeView implements NodeView {
15
15
  private lineWrappingCompartment;
16
16
  private languageCompartment;
17
17
  private readOnlyCompartment;
18
+ private copyDecoCompartment;
18
19
  private node;
19
20
  private getPos;
20
21
  private cm;
21
22
  private selectionAPI;
22
23
  private maybeTryingToReachNodeSelection;
23
24
  private cleanupDisabledState;
25
+ private cleanupCopyButtonDecoration;
24
26
  private languageLoader;
25
27
  constructor(node: PMNode, view: EditorView, getPos: getPosHandlerNode, config: ConfigProps);
26
28
  destroy(): void;
@@ -29,6 +31,7 @@ declare class CodeBlockAdvancedNodeView implements NodeView {
29
31
  private updateReadonlyState;
30
32
  private updateLanguage;
31
33
  private selectCodeBlockNode;
34
+ private addCopyButtonDecoration;
32
35
  private wordWrappingEnabled;
33
36
  private updateWordWrap;
34
37
  update(node: PMNode): boolean;
@@ -0,0 +1 @@
1
+ export declare const copyButtonDecorations: import("@codemirror/state").Extension;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-code-block-advanced",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "CodeBlockAdvanced plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -33,12 +33,12 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@atlaskit/adf-schema": "^46.1.0",
36
- "@atlaskit/editor-common": "^99.4.0",
37
- "@atlaskit/editor-plugin-code-block": "^3.5.0",
36
+ "@atlaskit/editor-common": "^99.5.0",
37
+ "@atlaskit/editor-plugin-code-block": "^3.6.0",
38
38
  "@atlaskit/editor-plugin-editor-disabled": "^1.3.0",
39
39
  "@atlaskit/editor-plugin-selection": "^1.6.0",
40
40
  "@atlaskit/editor-prosemirror": "6.2.1",
41
- "@atlaskit/tokens": "^3.1.0",
41
+ "@atlaskit/tokens": "^3.2.0",
42
42
  "@babel/runtime": "^7.0.0",
43
43
  "@codemirror/autocomplete": "6.18.4",
44
44
  "@codemirror/commands": "6.7.1",
@@ -1,5 +1,5 @@
1
1
  import { closeBrackets } from '@codemirror/autocomplete';
2
- import { syntaxHighlighting } from '@codemirror/language';
2
+ import { syntaxHighlighting, bracketMatching } from '@codemirror/language';
3
3
  import { Compartment, Extension, EditorSelection } from '@codemirror/state';
4
4
  import { EditorView as CodeMirror, lineNumbers, ViewUpdate, gutters } from '@codemirror/view';
5
5
 
@@ -22,6 +22,7 @@ import { cmTheme } from '../ui/theme';
22
22
  import { syncCMWithPM } from './codemirrorSync/syncCMWithPM';
23
23
  import { updateCMSelection } from './codemirrorSync/updateCMSelection';
24
24
  import { bidiCharWarningExtension } from './extensions/bidiCharWarning';
25
+ import { copyButtonDecorations } from './extensions/copyButtonDecorations';
25
26
  import { keymapExtension } from './extensions/keymap';
26
27
  import { LanguageLoader } from './languages/loader';
27
28
 
@@ -38,12 +39,14 @@ class CodeBlockAdvancedNodeView implements NodeView {
38
39
  private lineWrappingCompartment = new Compartment();
39
40
  private languageCompartment = new Compartment();
40
41
  private readOnlyCompartment = new Compartment();
42
+ private copyDecoCompartment = new Compartment();
41
43
  private node: PMNode;
42
44
  private getPos: getPosHandlerNode;
43
45
  private cm: CodeMirror;
44
46
  private selectionAPI: EditorSelectionAPI | undefined;
45
47
  private maybeTryingToReachNodeSelection = false;
46
48
  private cleanupDisabledState: (() => void) | undefined;
49
+ private cleanupCopyButtonDecoration: (() => void) | undefined;
47
50
  private languageLoader: LanguageLoader;
48
51
 
49
52
  // eslint-disable-next-line @typescript-eslint/max-params
@@ -57,6 +60,13 @@ class CodeBlockAdvancedNodeView implements NodeView {
57
60
  this.cleanupDisabledState = config.api?.editorDisabled?.sharedState.onChange(() => {
58
61
  this.updateReadonlyState();
59
62
  });
63
+ this.cleanupCopyButtonDecoration = config.api?.codeBlock?.sharedState.onChange(
64
+ ({ nextSharedState, prevSharedState }) => {
65
+ if (nextSharedState?.copyButtonHoverNode !== prevSharedState?.copyButtonHoverNode) {
66
+ this.addCopyButtonDecoration(nextSharedState?.copyButtonHoverNode);
67
+ }
68
+ },
69
+ );
60
70
  this.languageLoader = new LanguageLoader((lang) => {
61
71
  this.updating = true;
62
72
  this.cm.dispatch({
@@ -71,6 +81,7 @@ class CodeBlockAdvancedNodeView implements NodeView {
71
81
  ...config.extensions,
72
82
  this.lineWrappingCompartment.of([]),
73
83
  this.languageCompartment.of([]),
84
+ this.copyDecoCompartment.of([]),
74
85
  keymapExtension({
75
86
  view,
76
87
  getPos,
@@ -80,6 +91,7 @@ class CodeBlockAdvancedNodeView implements NodeView {
80
91
  }),
81
92
  cmTheme,
82
93
  syntaxHighlighting(highlightStyle),
94
+ bracketMatching(),
83
95
  lineNumbers(),
84
96
  // Explicitly disable "sticky" positioning on line numbers to match
85
97
  // Renderer behaviour
@@ -103,6 +115,7 @@ class CodeBlockAdvancedNodeView implements NodeView {
103
115
 
104
116
  destroy() {
105
117
  this.cleanupDisabledState?.();
118
+ this.cleanupCopyButtonDecoration?.();
106
119
  }
107
120
 
108
121
  forwardUpdate(update: ViewUpdate) {
@@ -149,6 +162,18 @@ class CodeBlockAdvancedNodeView implements NodeView {
149
162
  }
150
163
  }
151
164
 
165
+ private addCopyButtonDecoration(node: PMNode | undefined) {
166
+ this.updating = true;
167
+ this.cm.dispatch({
168
+ effects: [
169
+ this.copyDecoCompartment.reconfigure(
170
+ node && node === this.node ? copyButtonDecorations : [],
171
+ ),
172
+ ],
173
+ });
174
+ this.updating = false;
175
+ }
176
+
152
177
  private wordWrappingEnabled = false;
153
178
 
154
179
  private updateWordWrap(node: PMNode) {
@@ -69,6 +69,7 @@ const toDOM = (node: Node, formattedAriaLabel: string): DOMOutputSpec => {
69
69
  textAlign: 'right',
70
70
  color: token('color.text.subtlest'),
71
71
  fontFamily: token('font.family.code'),
72
+ whiteSpace: 'pre-wrap',
72
73
  }),
73
74
  'data-label': content,
74
75
  },
@@ -0,0 +1,15 @@
1
+ import { RangeSetBuilder } from '@codemirror/state';
2
+ import { EditorView as CodeMirror, Decoration } from '@codemirror/view';
3
+
4
+ export const copyButtonDecorations = CodeMirror.decorations.compute([], (state) => {
5
+ const allTextDecoration = Decoration.mark({
6
+ attributes: { class: 'ProseMirror-fake-text-selection' },
7
+ });
8
+ // Create a set of decorations for the entire document
9
+ const builder = new RangeSetBuilder<Decoration>();
10
+ for (let i = 0; i < state.doc.lines; i++) {
11
+ builder.add(state.doc.line(i + 1).from, state.doc.line(i + 1).to, allTextDecoration);
12
+ }
13
+ const decorations = builder.finish();
14
+ return decorations;
15
+ });