@atlaskit/editor-plugin-code-block-advanced 12.0.5 → 12.0.7

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
+ ## 12.0.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [`bf04628c00609`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/bf04628c00609) -
8
+ Add code folding usage analytics
9
+ - Updated dependencies
10
+
11
+ ## 12.0.6
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies
16
+
3
17
  ## 12.0.5
4
18
 
5
19
  ### Patch Changes
@@ -28,6 +28,9 @@
28
28
  {
29
29
  "path": "../../../design-system/code/afm-cc/tsconfig.json"
30
30
  },
31
+ {
32
+ "path": "../../editor-plugin-analytics/afm-cc/tsconfig.json"
33
+ },
31
34
  {
32
35
  "path": "../../editor-plugin-code-block/afm-cc/tsconfig.json"
33
36
  },
@@ -28,6 +28,9 @@
28
28
  {
29
29
  "path": "../../../design-system/code/afm-products/tsconfig.json"
30
30
  },
31
+ {
32
+ "path": "../../editor-plugin-analytics/afm-products/tsconfig.json"
33
+ },
31
34
  {
32
35
  "path": "../../editor-plugin-code-block/afm-products/tsconfig.json"
33
36
  },
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getCodeFoldingAnalyticsPayload = void 0;
7
+ var _analytics = require("@atlaskit/editor-common/analytics");
8
+ var getCodeFoldingAnalyticsPayload = exports.getCodeFoldingAnalyticsPayload = function getCodeFoldingAnalyticsPayload(folded, trigger) {
9
+ return {
10
+ action: _analytics.ACTION.TOGGLE_CODE_FOLDING,
11
+ actionSubject: _analytics.ACTION_SUBJECT.CODE_BLOCK,
12
+ attributes: {
13
+ folded: folded,
14
+ trigger: trigger
15
+ },
16
+ eventType: _analytics.EVENT_TYPE.TRACK
17
+ };
18
+ };
@@ -26,6 +26,7 @@ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
26
26
  var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
27
27
  var _syntaxHighlightingTheme = require("../ui/syntaxHighlightingTheme");
28
28
  var _theme = require("../ui/theme");
29
+ var _analytics = require("./analytics");
29
30
  var _syncCMWithPM = require("./codemirrorSync/syncCMWithPM");
30
31
  var _updateCMSelection = require("./codemirrorSync/updateCMSelection");
31
32
  var _firstCodeBlockInDocument = require("./extensions/firstCodeBlockInDocument");
@@ -61,6 +62,7 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
61
62
  (0, _defineProperty2.default)(this, "pmDecorationsCompartment", new _state.Compartment());
62
63
  (0, _defineProperty2.default)(this, "themeCompartment", new _state.Compartment());
63
64
  (0, _defineProperty2.default)(this, "maybeTryingToReachNodeSelection", false);
65
+ (0, _defineProperty2.default)(this, "mouseDownInBorderArea", false);
64
66
  (0, _defineProperty2.default)(this, "mouseDownInsideCodeMirror", false);
65
67
  (0, _defineProperty2.default)(this, "pmFacet", _state.Facet.define());
66
68
  (0, _defineProperty2.default)(this, "wordWrappingEnabled", false);
@@ -69,22 +71,39 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
69
71
  _this.selectCodeBlockNode(undefined);
70
72
  _this.view.focus();
71
73
  });
74
+ (0, _defineProperty2.default)(this, "fireCodeFoldingAnalytics", function (folded, trigger) {
75
+ var _this$config$api;
76
+ if (!(0, _platformFeatureFlags.fg)('platform_editor_code_block_folding_analytics')) {
77
+ return;
78
+ }
79
+ (_this$config$api = _this.config.api) === null || _this$config$api === void 0 || (_this$config$api = _this$config$api.analytics) === null || _this$config$api === void 0 || _this$config$api.actions.fireAnalyticsEvent((0, _analytics.getCodeFoldingAnalyticsPayload)(folded, trigger));
80
+ });
72
81
  (0, _defineProperty2.default)(this, "handleBorderAreaMouseDown", function (event) {
73
82
  var isBorderArea = _this.isBorderAreaClick(event);
74
- // Later click can follow a drag; remember where the interaction began.
75
- _this.mouseDownInsideCodeMirror = !isBorderArea;
83
+ if ((0, _platformFeatureFlags.fg)('platform_editor_code_block_dogfooding_patch')) {
84
+ _this.mouseDownInBorderArea = isBorderArea;
85
+ } else {
86
+ // Later click can follow a drag; remember where the interaction began.
87
+ _this.mouseDownInsideCodeMirror = !isBorderArea;
88
+ }
76
89
  if (isBorderArea && event.target === _this.cm.scrollDOM) {
77
90
  // Stop CodeMirror from restoring stale inner selection before node selection.
78
91
  event.preventDefault();
79
92
  }
80
93
  });
81
94
  (0, _defineProperty2.default)(this, "handleBorderAreaClick", function (event) {
82
- // Dragging across lines leaves a CodeMirror selection; keep it instead of selecting the node.
83
- if (_this.mouseDownInsideCodeMirror && _this.hasCodeMirrorTextSelection() || !_this.isBorderAreaClick(event)) {
95
+ if ((0, _platformFeatureFlags.fg)('platform_editor_code_block_dogfooding_patch')) {
96
+ if (!_this.mouseDownInBorderArea) {
97
+ return;
98
+ }
99
+ } else {
100
+ // Dragging across lines leaves a CodeMirror selection; keep it instead of selecting the node.
101
+ if (_this.mouseDownInsideCodeMirror && _this.hasCodeMirrorTextSelection() || !_this.isBorderAreaClick(event)) {
102
+ _this.mouseDownInsideCodeMirror = false;
103
+ return;
104
+ }
84
105
  _this.mouseDownInsideCodeMirror = false;
85
- return;
86
106
  }
87
- _this.mouseDownInsideCodeMirror = false;
88
107
 
89
108
  // Prevent CodeMirror from restoring its inner selection after we hand focus and selection
90
109
  // back to ProseMirror
@@ -163,7 +182,8 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
163
182
  selectNode: this.selectCodeBlockNodeAndFocus,
164
183
  getNode: function getNode() {
165
184
  return _this.node;
166
- }
185
+ },
186
+ onFoldToggled: this.fireCodeFoldingAnalytics
167
187
  })] : [],
168
188
  // With platform_editor_fix_advanced_codeblocks_crlf_patch the lineSeparatorExtension is not needed
169
189
  (0, _expValEquals.expValEquals)('platform_editor_fix_advanced_codeblocks_crlf_patch', 'isEnabled', true) ? [] : [(0, _lineSeparator.lineSeparatorExtension)()]])
@@ -40,7 +40,8 @@ var chevronRight = ['http://www.w3.org/2000/svg svg', {
40
40
  style: 'pointer-events: none;'
41
41
  }]];
42
42
  function foldGutterExtension(_ref) {
43
- var selectNode = _ref.selectNode,
43
+ var onFoldToggled = _ref.onFoldToggled,
44
+ selectNode = _ref.selectNode,
44
45
  getNode = _ref.getNode;
45
46
  return [(0, _language.foldGutter)({
46
47
  foldingChanged: function foldingChanged(update) {
@@ -102,6 +103,11 @@ function foldGutterExtension(_ref) {
102
103
  htmlElement.textContent = '>';
103
104
  }
104
105
  }
106
+
107
+ // CodeMirror passes whether the range is currently open; after click, that becomes folded.
108
+ htmlElement.onclick = function () {
109
+ return onFoldToggled === null || onFoldToggled === void 0 ? void 0 : onFoldToggled(open, 'gutter');
110
+ };
105
111
  return htmlElement;
106
112
  }
107
113
  }), (0, _language.codeFolding)({
@@ -116,7 +122,10 @@ function foldGutterExtension(_ref) {
116
122
  }));
117
123
  htmlElement.textContent = '…';
118
124
  htmlElement.className = 'cm-foldPlaceholder';
119
- htmlElement.onclick = onclick;
125
+ htmlElement.onclick = function (event) {
126
+ onFoldToggled === null || onFoldToggled === void 0 || onFoldToggled(false, 'placeholder');
127
+ onclick(event);
128
+ };
120
129
  return htmlElement;
121
130
  }
122
131
  })];
@@ -0,0 +1,10 @@
1
+ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
+ export const getCodeFoldingAnalyticsPayload = (folded, trigger) => ({
3
+ action: ACTION.TOGGLE_CODE_FOLDING,
4
+ actionSubject: ACTION_SUBJECT.CODE_BLOCK,
5
+ attributes: {
6
+ folded,
7
+ trigger
8
+ },
9
+ eventType: EVENT_TYPE.TRACK
10
+ });
@@ -16,6 +16,7 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
16
16
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
17
17
  import { highlightStyle } from '../ui/syntaxHighlightingTheme';
18
18
  import { cmTheme, codeFoldingTheme } from '../ui/theme';
19
+ import { getCodeFoldingAnalyticsPayload } from './analytics';
19
20
  import { syncCMWithPM } from './codemirrorSync/syncCMWithPM';
20
21
  import { getCMSelectionChanges } from './codemirrorSync/updateCMSelection';
21
22
  import { firstCodeBlockInDocument } from './extensions/firstCodeBlockInDocument';
@@ -41,6 +42,7 @@ class CodeBlockAdvancedNodeView {
41
42
  _defineProperty(this, "pmDecorationsCompartment", new Compartment());
42
43
  _defineProperty(this, "themeCompartment", new Compartment());
43
44
  _defineProperty(this, "maybeTryingToReachNodeSelection", false);
45
+ _defineProperty(this, "mouseDownInBorderArea", false);
44
46
  _defineProperty(this, "mouseDownInsideCodeMirror", false);
45
47
  _defineProperty(this, "pmFacet", Facet.define());
46
48
  _defineProperty(this, "wordWrappingEnabled", false);
@@ -49,22 +51,39 @@ class CodeBlockAdvancedNodeView {
49
51
  this.selectCodeBlockNode(undefined);
50
52
  this.view.focus();
51
53
  });
54
+ _defineProperty(this, "fireCodeFoldingAnalytics", (folded, trigger) => {
55
+ var _this$config$api, _this$config$api$anal;
56
+ if (!fg('platform_editor_code_block_folding_analytics')) {
57
+ return;
58
+ }
59
+ (_this$config$api = this.config.api) === null || _this$config$api === void 0 ? void 0 : (_this$config$api$anal = _this$config$api.analytics) === null || _this$config$api$anal === void 0 ? void 0 : _this$config$api$anal.actions.fireAnalyticsEvent(getCodeFoldingAnalyticsPayload(folded, trigger));
60
+ });
52
61
  _defineProperty(this, "handleBorderAreaMouseDown", event => {
53
62
  const isBorderArea = this.isBorderAreaClick(event);
54
- // Later click can follow a drag; remember where the interaction began.
55
- this.mouseDownInsideCodeMirror = !isBorderArea;
63
+ if (fg('platform_editor_code_block_dogfooding_patch')) {
64
+ this.mouseDownInBorderArea = isBorderArea;
65
+ } else {
66
+ // Later click can follow a drag; remember where the interaction began.
67
+ this.mouseDownInsideCodeMirror = !isBorderArea;
68
+ }
56
69
  if (isBorderArea && event.target === this.cm.scrollDOM) {
57
70
  // Stop CodeMirror from restoring stale inner selection before node selection.
58
71
  event.preventDefault();
59
72
  }
60
73
  });
61
74
  _defineProperty(this, "handleBorderAreaClick", event => {
62
- // Dragging across lines leaves a CodeMirror selection; keep it instead of selecting the node.
63
- if (this.mouseDownInsideCodeMirror && this.hasCodeMirrorTextSelection() || !this.isBorderAreaClick(event)) {
75
+ if (fg('platform_editor_code_block_dogfooding_patch')) {
76
+ if (!this.mouseDownInBorderArea) {
77
+ return;
78
+ }
79
+ } else {
80
+ // Dragging across lines leaves a CodeMirror selection; keep it instead of selecting the node.
81
+ if (this.mouseDownInsideCodeMirror && this.hasCodeMirrorTextSelection() || !this.isBorderAreaClick(event)) {
82
+ this.mouseDownInsideCodeMirror = false;
83
+ return;
84
+ }
64
85
  this.mouseDownInsideCodeMirror = false;
65
- return;
66
86
  }
67
- this.mouseDownInsideCodeMirror = false;
68
87
 
69
88
  // Prevent CodeMirror from restoring its inner selection after we hand focus and selection
70
89
  // back to ProseMirror
@@ -139,7 +158,8 @@ class CodeBlockAdvancedNodeView {
139
158
  })
140
159
  }), config.allowCodeFolding ? [foldGutterExtension({
141
160
  selectNode: this.selectCodeBlockNodeAndFocus,
142
- getNode: () => this.node
161
+ getNode: () => this.node,
162
+ onFoldToggled: this.fireCodeFoldingAnalytics
143
163
  })] : [],
144
164
  // With platform_editor_fix_advanced_codeblocks_crlf_patch the lineSeparatorExtension is not needed
145
165
  expValEquals('platform_editor_fix_advanced_codeblocks_crlf_patch', 'isEnabled', true) ? [] : [lineSeparatorExtension()]]
@@ -30,6 +30,7 @@ const chevronRight = ['http://www.w3.org/2000/svg svg', {
30
30
  style: 'pointer-events: none;'
31
31
  }]];
32
32
  export function foldGutterExtension({
33
+ onFoldToggled,
33
34
  selectNode,
34
35
  getNode
35
36
  }) {
@@ -95,6 +96,9 @@ export function foldGutterExtension({
95
96
  htmlElement.textContent = '>';
96
97
  }
97
98
  }
99
+
100
+ // CodeMirror passes whether the range is currently open; after click, that becomes folded.
101
+ htmlElement.onclick = () => onFoldToggled === null || onFoldToggled === void 0 ? void 0 : onFoldToggled(open, 'gutter');
98
102
  return htmlElement;
99
103
  }
100
104
  }), codeFolding({
@@ -109,7 +113,10 @@ export function foldGutterExtension({
109
113
  }));
110
114
  htmlElement.textContent = '…';
111
115
  htmlElement.className = 'cm-foldPlaceholder';
112
- htmlElement.onclick = onclick;
116
+ htmlElement.onclick = event => {
117
+ onFoldToggled === null || onFoldToggled === void 0 ? void 0 : onFoldToggled(false, 'placeholder');
118
+ onclick(event);
119
+ };
113
120
  return htmlElement;
114
121
  }
115
122
  })];
@@ -0,0 +1,12 @@
1
+ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
+ export var getCodeFoldingAnalyticsPayload = function getCodeFoldingAnalyticsPayload(folded, trigger) {
3
+ return {
4
+ action: ACTION.TOGGLE_CODE_FOLDING,
5
+ actionSubject: ACTION_SUBJECT.CODE_BLOCK,
6
+ attributes: {
7
+ folded: folded,
8
+ trigger: trigger
9
+ },
10
+ eventType: EVENT_TYPE.TRACK
11
+ };
12
+ };
@@ -24,6 +24,7 @@ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
24
24
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
25
25
  import { highlightStyle } from '../ui/syntaxHighlightingTheme';
26
26
  import { cmTheme, codeFoldingTheme } from '../ui/theme';
27
+ import { getCodeFoldingAnalyticsPayload } from './analytics';
27
28
  import { syncCMWithPM } from './codemirrorSync/syncCMWithPM';
28
29
  import { getCMSelectionChanges } from './codemirrorSync/updateCMSelection';
29
30
  import { firstCodeBlockInDocument } from './extensions/firstCodeBlockInDocument';
@@ -55,6 +56,7 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
55
56
  _defineProperty(this, "pmDecorationsCompartment", new Compartment());
56
57
  _defineProperty(this, "themeCompartment", new Compartment());
57
58
  _defineProperty(this, "maybeTryingToReachNodeSelection", false);
59
+ _defineProperty(this, "mouseDownInBorderArea", false);
58
60
  _defineProperty(this, "mouseDownInsideCodeMirror", false);
59
61
  _defineProperty(this, "pmFacet", Facet.define());
60
62
  _defineProperty(this, "wordWrappingEnabled", false);
@@ -63,22 +65,39 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
63
65
  _this.selectCodeBlockNode(undefined);
64
66
  _this.view.focus();
65
67
  });
68
+ _defineProperty(this, "fireCodeFoldingAnalytics", function (folded, trigger) {
69
+ var _this$config$api;
70
+ if (!fg('platform_editor_code_block_folding_analytics')) {
71
+ return;
72
+ }
73
+ (_this$config$api = _this.config.api) === null || _this$config$api === void 0 || (_this$config$api = _this$config$api.analytics) === null || _this$config$api === void 0 || _this$config$api.actions.fireAnalyticsEvent(getCodeFoldingAnalyticsPayload(folded, trigger));
74
+ });
66
75
  _defineProperty(this, "handleBorderAreaMouseDown", function (event) {
67
76
  var isBorderArea = _this.isBorderAreaClick(event);
68
- // Later click can follow a drag; remember where the interaction began.
69
- _this.mouseDownInsideCodeMirror = !isBorderArea;
77
+ if (fg('platform_editor_code_block_dogfooding_patch')) {
78
+ _this.mouseDownInBorderArea = isBorderArea;
79
+ } else {
80
+ // Later click can follow a drag; remember where the interaction began.
81
+ _this.mouseDownInsideCodeMirror = !isBorderArea;
82
+ }
70
83
  if (isBorderArea && event.target === _this.cm.scrollDOM) {
71
84
  // Stop CodeMirror from restoring stale inner selection before node selection.
72
85
  event.preventDefault();
73
86
  }
74
87
  });
75
88
  _defineProperty(this, "handleBorderAreaClick", function (event) {
76
- // Dragging across lines leaves a CodeMirror selection; keep it instead of selecting the node.
77
- if (_this.mouseDownInsideCodeMirror && _this.hasCodeMirrorTextSelection() || !_this.isBorderAreaClick(event)) {
89
+ if (fg('platform_editor_code_block_dogfooding_patch')) {
90
+ if (!_this.mouseDownInBorderArea) {
91
+ return;
92
+ }
93
+ } else {
94
+ // Dragging across lines leaves a CodeMirror selection; keep it instead of selecting the node.
95
+ if (_this.mouseDownInsideCodeMirror && _this.hasCodeMirrorTextSelection() || !_this.isBorderAreaClick(event)) {
96
+ _this.mouseDownInsideCodeMirror = false;
97
+ return;
98
+ }
78
99
  _this.mouseDownInsideCodeMirror = false;
79
- return;
80
100
  }
81
- _this.mouseDownInsideCodeMirror = false;
82
101
 
83
102
  // Prevent CodeMirror from restoring its inner selection after we hand focus and selection
84
103
  // back to ProseMirror
@@ -157,7 +176,8 @@ var CodeBlockAdvancedNodeView = /*#__PURE__*/function () {
157
176
  selectNode: this.selectCodeBlockNodeAndFocus,
158
177
  getNode: function getNode() {
159
178
  return _this.node;
160
- }
179
+ },
180
+ onFoldToggled: this.fireCodeFoldingAnalytics
161
181
  })] : [],
162
182
  // With platform_editor_fix_advanced_codeblocks_crlf_patch the lineSeparatorExtension is not needed
163
183
  expValEquals('platform_editor_fix_advanced_codeblocks_crlf_patch', 'isEnabled', true) ? [] : [lineSeparatorExtension()]])
@@ -33,7 +33,8 @@ var chevronRight = ['http://www.w3.org/2000/svg svg', {
33
33
  style: 'pointer-events: none;'
34
34
  }]];
35
35
  export function foldGutterExtension(_ref) {
36
- var selectNode = _ref.selectNode,
36
+ var onFoldToggled = _ref.onFoldToggled,
37
+ selectNode = _ref.selectNode,
37
38
  getNode = _ref.getNode;
38
39
  return [foldGutter({
39
40
  foldingChanged: function foldingChanged(update) {
@@ -95,6 +96,11 @@ export function foldGutterExtension(_ref) {
95
96
  htmlElement.textContent = '>';
96
97
  }
97
98
  }
99
+
100
+ // CodeMirror passes whether the range is currently open; after click, that becomes folded.
101
+ htmlElement.onclick = function () {
102
+ return onFoldToggled === null || onFoldToggled === void 0 ? void 0 : onFoldToggled(open, 'gutter');
103
+ };
98
104
  return htmlElement;
99
105
  }
100
106
  }), codeFolding({
@@ -109,7 +115,10 @@ export function foldGutterExtension(_ref) {
109
115
  }));
110
116
  htmlElement.textContent = '…';
111
117
  htmlElement.className = 'cm-foldPlaceholder';
112
- htmlElement.onclick = onclick;
118
+ htmlElement.onclick = function (event) {
119
+ onFoldToggled === null || onFoldToggled === void 0 || onFoldToggled(false, 'placeholder');
120
+ onclick(event);
121
+ };
113
122
  return htmlElement;
114
123
  }
115
124
  })];
@@ -1,5 +1,6 @@
1
1
  import type { Extension } from '@codemirror/state';
2
2
  import type { NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
3
+ import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
3
4
  import type { CodeBlockPlugin } from '@atlaskit/editor-plugin-code-block';
4
5
  import type { ContentFormatPlugin } from '@atlaskit/editor-plugin-content-format';
5
6
  import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
@@ -9,6 +10,7 @@ import type { SelectionMarkerPlugin } from '@atlaskit/editor-plugin-selection-ma
9
10
  export type CodeBlockAdvancedPlugin = NextEditorPlugin<'codeBlockAdvanced', {
10
11
  dependencies: [
11
12
  OptionalPlugin<CodeBlockPlugin>,
13
+ OptionalPlugin<AnalyticsPlugin>,
12
14
  SelectionPlugin,
13
15
  OptionalPlugin<EditorDisabledPlugin>,
14
16
  OptionalPlugin<SelectionMarkerPlugin>,
@@ -0,0 +1,3 @@
1
+ import type { AnalyticsEventPayload } from '@atlaskit/editor-common/analytics';
2
+ export type CodeFoldingTrigger = 'gutter' | 'placeholder';
3
+ export declare const getCodeFoldingAnalyticsPayload: (folded: boolean, trigger: CodeFoldingTrigger) => AnalyticsEventPayload;
@@ -27,6 +27,7 @@ declare class CodeBlockAdvancedNodeView implements NodeView {
27
27
  private contentMode;
28
28
  private selectionAPI;
29
29
  private maybeTryingToReachNodeSelection;
30
+ private mouseDownInBorderArea;
30
31
  private mouseDownInsideCodeMirror;
31
32
  private cleanupDisabledState;
32
33
  private languageLoader;
@@ -49,6 +50,7 @@ declare class CodeBlockAdvancedNodeView implements NodeView {
49
50
  private wordWrappingEnabled;
50
51
  private lineNumbersHidden;
51
52
  private selectCodeBlockNodeAndFocus;
53
+ private fireCodeFoldingAnalytics;
52
54
  private getLineNumberExtensions;
53
55
  private getLineNumberVisibilityExtensions;
54
56
  private getLineNumbersEffects;
@@ -1,8 +1,10 @@
1
1
  import type { Extension, StateEffect } from '@codemirror/state';
2
2
  import type { EditorView as CodeMirror } from '@codemirror/view';
3
3
  import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
4
- export declare function foldGutterExtension({ selectNode, getNode, }: {
4
+ import type { CodeFoldingTrigger } from '../analytics';
5
+ export declare function foldGutterExtension({ onFoldToggled, selectNode, getNode, }: {
5
6
  getNode: () => PMNode;
7
+ onFoldToggled?: (folded: boolean, trigger: CodeFoldingTrigger) => void;
6
8
  selectNode: () => void;
7
9
  }): Extension[];
8
10
  export declare function getCodeBlockFoldStateEffects({ node, cm, }: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-code-block-advanced",
3
- "version": "12.0.5",
3
+ "version": "12.0.7",
4
4
  "description": "CodeBlockAdvanced plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -22,6 +22,7 @@
22
22
  "dependencies": {
23
23
  "@atlaskit/adf-schema": "^56.0.0",
24
24
  "@atlaskit/code": "^18.0.0",
25
+ "@atlaskit/editor-plugin-analytics": "^12.0.0",
25
26
  "@atlaskit/editor-plugin-code-block": "^14.0.0",
26
27
  "@atlaskit/editor-plugin-editor-disabled": "^12.0.0",
27
28
  "@atlaskit/editor-plugin-find-replace": "^12.0.0",
@@ -30,7 +31,7 @@
30
31
  "@atlaskit/editor-prosemirror": "^8.0.0",
31
32
  "@atlaskit/platform-feature-flags": "^2.0.0",
32
33
  "@atlaskit/prosemirror-history": "^1.0.0",
33
- "@atlaskit/tmp-editor-statsig": "^108.3.0",
34
+ "@atlaskit/tmp-editor-statsig": "^109.0.0",
34
35
  "@atlaskit/tokens": "^14.0.0",
35
36
  "@babel/runtime": "^7.0.0",
36
37
  "@codemirror/autocomplete": "6.18.4",
@@ -48,7 +49,7 @@
48
49
  "codemirror-lang-elixir": "4.0.0"
49
50
  },
50
51
  "peerDependencies": {
51
- "@atlaskit/editor-common": "^116.4.0",
52
+ "@atlaskit/editor-common": "^116.7.0",
52
53
  "react": "^18.2.0",
53
54
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
54
55
  },
@@ -94,6 +95,12 @@
94
95
  },
95
96
  "platform_editor_content_mode_button_mvp": {
96
97
  "type": "boolean"
98
+ },
99
+ "platform_editor_code_block_folding_analytics": {
100
+ "type": "boolean"
101
+ },
102
+ "platform_editor_code_block_dogfooding_patch": {
103
+ "type": "boolean"
97
104
  }
98
105
  },
99
106
  "devDependencies": {
@@ -1,6 +1,7 @@
1
1
  import type { Extension } from '@codemirror/state';
2
2
 
3
3
  import type { NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
4
+ import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
4
5
  import type { CodeBlockPlugin } from '@atlaskit/editor-plugin-code-block';
5
6
  import type { ContentFormatPlugin } from '@atlaskit/editor-plugin-content-format';
6
7
  import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
@@ -13,6 +14,7 @@ export type CodeBlockAdvancedPlugin = NextEditorPlugin<
13
14
  {
14
15
  dependencies: [
15
16
  OptionalPlugin<CodeBlockPlugin>,
17
+ OptionalPlugin<AnalyticsPlugin>,
16
18
  SelectionPlugin,
17
19
  OptionalPlugin<EditorDisabledPlugin>,
18
20
  OptionalPlugin<SelectionMarkerPlugin>,
@@ -0,0 +1,17 @@
1
+ import type { AnalyticsEventPayload } from '@atlaskit/editor-common/analytics';
2
+ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
3
+
4
+ export type CodeFoldingTrigger = 'gutter' | 'placeholder';
5
+
6
+ export const getCodeFoldingAnalyticsPayload = (
7
+ folded: boolean,
8
+ trigger: CodeFoldingTrigger,
9
+ ): AnalyticsEventPayload => ({
10
+ action: ACTION.TOGGLE_CODE_FOLDING,
11
+ actionSubject: ACTION_SUBJECT.CODE_BLOCK,
12
+ attributes: {
13
+ folded,
14
+ trigger,
15
+ },
16
+ eventType: EVENT_TYPE.TRACK,
17
+ });
@@ -44,6 +44,7 @@ import type { CodeBlockAdvancedPlugin } from '../codeBlockAdvancedPluginType';
44
44
  import { highlightStyle } from '../ui/syntaxHighlightingTheme';
45
45
  import { cmTheme, codeFoldingTheme } from '../ui/theme';
46
46
 
47
+ import { getCodeFoldingAnalyticsPayload, type CodeFoldingTrigger } from './analytics';
47
48
  import { syncCMWithPM } from './codemirrorSync/syncCMWithPM';
48
49
  import { getCMSelectionChanges } from './codemirrorSync/updateCMSelection';
49
50
  import { firstCodeBlockInDocument } from './extensions/firstCodeBlockInDocument';
@@ -83,6 +84,7 @@ class CodeBlockAdvancedNodeView implements NodeView {
83
84
  private contentMode: EditorContentMode | undefined;
84
85
  private selectionAPI: EditorSelectionAPI | undefined;
85
86
  private maybeTryingToReachNodeSelection = false;
87
+ private mouseDownInBorderArea = false;
86
88
  private mouseDownInsideCodeMirror = false;
87
89
  private cleanupDisabledState: (() => void) | undefined;
88
90
  private languageLoader: LanguageLoader;
@@ -209,6 +211,7 @@ class CodeBlockAdvancedNodeView implements NodeView {
209
211
  foldGutterExtension({
210
212
  selectNode: this.selectCodeBlockNodeAndFocus,
211
213
  getNode: () => this.node,
214
+ onFoldToggled: this.fireCodeFoldingAnalytics,
212
215
  }),
213
216
  ]
214
217
  : [],
@@ -429,6 +432,16 @@ class CodeBlockAdvancedNodeView implements NodeView {
429
432
  this.view.focus();
430
433
  };
431
434
 
435
+ private fireCodeFoldingAnalytics = (folded: boolean, trigger: CodeFoldingTrigger) => {
436
+ if (!fg('platform_editor_code_block_folding_analytics')) {
437
+ return;
438
+ }
439
+
440
+ this.config.api?.analytics?.actions.fireAnalyticsEvent(
441
+ getCodeFoldingAnalyticsPayload(folded, trigger),
442
+ );
443
+ };
444
+
432
445
  private getLineNumberExtensions(): Extension[] {
433
446
  return [
434
447
  lineNumbers({
@@ -552,8 +565,13 @@ class CodeBlockAdvancedNodeView implements NodeView {
552
565
 
553
566
  private handleBorderAreaMouseDown = (event: MouseEvent) => {
554
567
  const isBorderArea = this.isBorderAreaClick(event);
555
- // Later click can follow a drag; remember where the interaction began.
556
- this.mouseDownInsideCodeMirror = !isBorderArea;
568
+
569
+ if (fg('platform_editor_code_block_dogfooding_patch')) {
570
+ this.mouseDownInBorderArea = isBorderArea;
571
+ } else {
572
+ // Later click can follow a drag; remember where the interaction began.
573
+ this.mouseDownInsideCodeMirror = !isBorderArea;
574
+ }
557
575
 
558
576
  if (isBorderArea && event.target === this.cm.scrollDOM) {
559
577
  // Stop CodeMirror from restoring stale inner selection before node selection.
@@ -562,15 +580,21 @@ class CodeBlockAdvancedNodeView implements NodeView {
562
580
  };
563
581
 
564
582
  private handleBorderAreaClick = (event: MouseEvent) => {
565
- // Dragging across lines leaves a CodeMirror selection; keep it instead of selecting the node.
566
- if (
567
- (this.mouseDownInsideCodeMirror && this.hasCodeMirrorTextSelection()) ||
568
- !this.isBorderAreaClick(event)
569
- ) {
583
+ if (fg('platform_editor_code_block_dogfooding_patch')) {
584
+ if (!this.mouseDownInBorderArea) {
585
+ return;
586
+ }
587
+ } else {
588
+ // Dragging across lines leaves a CodeMirror selection; keep it instead of selecting the node.
589
+ if (
590
+ (this.mouseDownInsideCodeMirror && this.hasCodeMirrorTextSelection()) ||
591
+ !this.isBorderAreaClick(event)
592
+ ) {
593
+ this.mouseDownInsideCodeMirror = false;
594
+ return;
595
+ }
570
596
  this.mouseDownInsideCodeMirror = false;
571
- return;
572
597
  }
573
- this.mouseDownInsideCodeMirror = false;
574
598
 
575
599
  // Prevent CodeMirror from restoring its inner selection after we hand focus and selection
576
600
  // back to ProseMirror
@@ -9,6 +9,8 @@ import type { DOMOutputSpec, Node as PMNode } from '@atlaskit/editor-prosemirror
9
9
  import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
10
10
  import { token } from '@atlaskit/tokens';
11
11
 
12
+ import type { CodeFoldingTrigger } from '../analytics';
13
+
12
14
  // Based on platform/packages/design-system/icon/svgs/utility/add.svg
13
15
  const chevronDown: DOMOutputSpec = [
14
16
  'http://www.w3.org/2000/svg svg',
@@ -53,10 +55,12 @@ const chevronRight: DOMOutputSpec = [
53
55
  ];
54
56
 
55
57
  export function foldGutterExtension({
58
+ onFoldToggled,
56
59
  selectNode,
57
60
  getNode,
58
61
  }: {
59
62
  getNode: () => PMNode;
63
+ onFoldToggled?: (folded: boolean, trigger: CodeFoldingTrigger) => void;
60
64
  selectNode: () => void;
61
65
  }): Extension[] {
62
66
  return [
@@ -128,6 +132,9 @@ export function foldGutterExtension({
128
132
  }
129
133
  }
130
134
 
135
+ // CodeMirror passes whether the range is currently open; after click, that becomes folded.
136
+ htmlElement.onclick = () => onFoldToggled?.(open, 'gutter');
137
+
131
138
  return htmlElement;
132
139
  },
133
140
  }),
@@ -146,7 +153,10 @@ export function foldGutterExtension({
146
153
  );
147
154
  htmlElement.textContent = '…';
148
155
  htmlElement.className = 'cm-foldPlaceholder';
149
- htmlElement.onclick = onclick;
156
+ htmlElement.onclick = (event) => {
157
+ onFoldToggled?.(false, 'placeholder');
158
+ onclick(event);
159
+ };
150
160
  return htmlElement;
151
161
  },
152
162
  }),
package/tsconfig.app.json CHANGED
@@ -42,6 +42,9 @@
42
42
  {
43
43
  "path": "../editor-common/tsconfig.app.json"
44
44
  },
45
+ {
46
+ "path": "../editor-plugin-analytics/tsconfig.app.json"
47
+ },
45
48
  {
46
49
  "path": "../editor-plugin-code-block/tsconfig.app.json"
47
50
  },