@atlaskit/editor-plugin-code-block 13.0.1 → 13.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/codeBlockPlugin.js +13 -1
  3. package/dist/cjs/editor-commands/index.js +179 -5
  4. package/dist/cjs/pm-plugins/actions.js +6 -3
  5. package/dist/cjs/pm-plugins/main.js +17 -1
  6. package/dist/cjs/pm-plugins/toolbar.js +19 -2
  7. package/dist/cjs/ui/FormatCodeErrorFlag.js +70 -0
  8. package/dist/cjs/utils/format-code/format-code-state.js +81 -0
  9. package/dist/cjs/utils/format-code/formatter-impl.js +15 -0
  10. package/dist/cjs/utils/format-code/formatter.js +86 -0
  11. package/dist/es2019/codeBlockPlugin.js +12 -2
  12. package/dist/es2019/editor-commands/index.js +176 -0
  13. package/dist/es2019/pm-plugins/actions.js +6 -3
  14. package/dist/es2019/pm-plugins/main.js +18 -1
  15. package/dist/es2019/pm-plugins/toolbar.js +22 -3
  16. package/dist/es2019/ui/FormatCodeErrorFlag.js +62 -0
  17. package/dist/es2019/utils/format-code/format-code-state.js +82 -0
  18. package/dist/es2019/utils/format-code/formatter-impl.js +10 -0
  19. package/dist/es2019/utils/format-code/formatter.js +47 -0
  20. package/dist/esm/codeBlockPlugin.js +13 -1
  21. package/dist/esm/editor-commands/index.js +178 -4
  22. package/dist/esm/pm-plugins/actions.js +6 -3
  23. package/dist/esm/pm-plugins/main.js +17 -1
  24. package/dist/esm/pm-plugins/toolbar.js +20 -3
  25. package/dist/esm/ui/FormatCodeErrorFlag.js +61 -0
  26. package/dist/esm/utils/format-code/format-code-state.js +74 -0
  27. package/dist/esm/utils/format-code/formatter-impl.js +9 -0
  28. package/dist/esm/utils/format-code/formatter.js +75 -0
  29. package/dist/types/codeBlockPluginType.d.ts +3 -0
  30. package/dist/types/editor-commands/index.d.ts +6 -1
  31. package/dist/types/pm-plugins/actions.d.ts +6 -3
  32. package/dist/types/pm-plugins/main-state.d.ts +16 -0
  33. package/dist/types/ui/FormatCodeErrorFlag.d.ts +6 -0
  34. package/dist/types/utils/format-code/format-code-state.d.ts +4 -0
  35. package/dist/types/utils/format-code/formatter-impl.d.ts +5 -0
  36. package/dist/types/utils/format-code/formatter.d.ts +25 -0
  37. package/dist/types-ts4.5/codeBlockPluginType.d.ts +3 -0
  38. package/dist/types-ts4.5/editor-commands/index.d.ts +6 -1
  39. package/dist/types-ts4.5/pm-plugins/actions.d.ts +6 -3
  40. package/dist/types-ts4.5/pm-plugins/main-state.d.ts +16 -0
  41. package/dist/types-ts4.5/ui/FormatCodeErrorFlag.d.ts +6 -0
  42. package/dist/types-ts4.5/utils/format-code/format-code-state.d.ts +4 -0
  43. package/dist/types-ts4.5/utils/format-code/formatter-impl.d.ts +5 -0
  44. package/dist/types-ts4.5/utils/format-code/formatter.d.ts +32 -0
  45. package/package.json +9 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @atlaskit/editor-plugin-code-block
2
2
 
3
+ ## 13.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`44ba0da4e85d7`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/44ba0da4e85d7) -
8
+ Gate the code block formatting button behind platform_editor_code_block_formatting
9
+ - Updated dependencies
10
+
11
+ ## 13.1.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [`75daf19dd12b0`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/75daf19dd12b0) -
16
+ Add format code control for code blocks
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies
21
+
3
22
  ## 13.0.1
4
23
 
5
24
  ### Patch Changes
@@ -15,6 +15,7 @@ var _messages = require("@atlaskit/editor-common/messages");
15
15
  var _quickInsert = require("@atlaskit/editor-common/quick-insert");
16
16
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
17
17
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
18
+ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
18
19
  var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
19
20
  var _editorCommands = require("./editor-commands");
20
21
  var _autoDetect = require("./pm-plugins/auto-detect");
@@ -24,9 +25,11 @@ var _ideUx = _interopRequireDefault(require("./pm-plugins/ide-ux"));
24
25
  var _inputRule = require("./pm-plugins/input-rule");
25
26
  var _keymaps = _interopRequireDefault(require("./pm-plugins/keymaps"));
26
27
  var _main = require("./pm-plugins/main");
28
+ var _pluginKey = require("./pm-plugins/plugin-key");
27
29
  var _refreshBrowserSelection = _interopRequireDefault(require("./pm-plugins/refresh-browser-selection"));
28
30
  var _toolbar = require("./pm-plugins/toolbar");
29
31
  var _CodeBlockMenuItem = require("./ui/CodeBlockMenuItem");
32
+ var _FormatCodeErrorFlag = require("./ui/FormatCodeErrorFlag");
30
33
  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; }
31
34
  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; }
32
35
  var CODE_BLOCK_NODE_NAME = 'codeBlock';
@@ -59,11 +62,15 @@ var codeBlockPlugin = function codeBlockPlugin(_ref) {
59
62
  }];
60
63
  },
61
64
  getSharedState: function getSharedState(state) {
65
+ var _codeBlockState$forma, _codeBlockState$pendi;
62
66
  if (!state) {
63
67
  return undefined;
64
68
  }
69
+ var codeBlockState = _pluginKey.pluginKey.getState(state);
65
70
  return {
66
- copyButtonHoverNode: _codeBlockCopySelectionPlugin.copySelectionPluginKey.getState(state).codeBlockNode
71
+ copyButtonHoverNode: _codeBlockCopySelectionPlugin.copySelectionPluginKey.getState(state).codeBlockNode,
72
+ formatCodeErrors: (_codeBlockState$forma = codeBlockState === null || codeBlockState === void 0 ? void 0 : codeBlockState.formatCodeErrors) !== null && _codeBlockState$forma !== void 0 ? _codeBlockState$forma : {},
73
+ pendingFormats: (_codeBlockState$pendi = codeBlockState === null || codeBlockState === void 0 ? void 0 : codeBlockState.pendingFormats) !== null && _codeBlockState$pendi !== void 0 ? _codeBlockState$pendi : {}
67
74
  };
68
75
  },
69
76
  pmPlugins: function pmPlugins() {
@@ -157,6 +164,11 @@ var codeBlockPlugin = function codeBlockPlugin(_ref) {
157
164
  }];
158
165
  },
159
166
  floatingToolbar: (0, _toolbar.getToolbarConfig)(options === null || options === void 0 ? void 0 : options.allowCopyToClipboard, api, options === null || options === void 0 ? void 0 : options.overrideLanguageName)
167
+ },
168
+ contentComponent: function contentComponent() {
169
+ return (0, _expValEqualsNoExposure.expValEqualsNoExposure)('platform_editor_code_block_q4_lovability', 'isEnabled', true) ? /*#__PURE__*/_react.default.createElement(_FormatCodeErrorFlag.FormatCodeErrorFlag, {
170
+ api: api
171
+ }) : null;
160
172
  }
161
173
  };
162
174
  };
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.copyContentToClipboardWithAnalytics = exports.copyContentToClipboard = exports.changeLanguage = void 0;
7
+ exports.createFormatCodeOnClick = exports.copyContentToClipboardWithAnalytics = exports.copyContentToClipboard = exports.changeLanguage = void 0;
8
8
  exports.createInsertCodeBlockTransaction = createInsertCodeBlockTransaction;
9
9
  exports.ignoreFollowingMutations = exports.detectLanguage = void 0;
10
10
  exports.insertCodeBlockWithAnalytics = insertCodeBlockWithAnalytics;
@@ -27,6 +27,7 @@ var _codeBlockCopySelectionPlugin = require("../pm-plugins/codeBlockCopySelectio
27
27
  var _pluginKey = require("../pm-plugins/plugin-key");
28
28
  var _transformToCodeBlock = require("../pm-plugins/transform-to-code-block");
29
29
  var _autoDetectState2 = require("../utils/auto-detect-state");
30
+ var _formatter = require("../utils/format-code/formatter");
30
31
  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; }
31
32
  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; }
32
33
  var removeCodeBlockWithAnalytics = exports.removeCodeBlockWithAnalytics = function removeCodeBlockWithAnalytics(editorAnalyticsAPI) {
@@ -135,6 +136,179 @@ var detectLanguage = exports.detectLanguage = function detectLanguage() {
135
136
  return true;
136
137
  };
137
138
  };
139
+ var setResolveFormatCodeMeta = function setResolveFormatCodeMeta(tr, _ref) {
140
+ var languageSource = _ref.languageSource,
141
+ localId = _ref.localId,
142
+ outcome = _ref.outcome,
143
+ requestId = _ref.requestId,
144
+ errorType = _ref.errorType;
145
+ return tr.setMeta(_pluginKey.pluginKey, {
146
+ type: _actions.ACTIONS.RESOLVE_FORMAT_CODE,
147
+ data: _objectSpread({
148
+ languageSource: languageSource,
149
+ localId: localId,
150
+ outcome: outcome,
151
+ requestId: requestId
152
+ }, errorType ? {
153
+ errorType: errorType
154
+ } : {})
155
+ });
156
+ };
157
+ var replaceCodeBlockText = function replaceCodeBlockText(_ref2) {
158
+ var codeBlockNode = _ref2.codeBlockNode,
159
+ content = _ref2.content,
160
+ pos = _ref2.pos,
161
+ tr = _ref2.tr;
162
+ var from = pos + 1;
163
+ var to = pos + codeBlockNode.nodeSize - 1;
164
+ tr.delete(from, to);
165
+ if (content) {
166
+ tr.insertText(content, from);
167
+ }
168
+
169
+ // The editor scroll plugin scrolls doc-changing transactions by default.
170
+ return tr.setMeta('scrollIntoView', false);
171
+ };
172
+ var attachFormatCodeAnalytics = function attachFormatCodeAnalytics(_ref3) {
173
+ var editorAnalyticsAPI = _ref3.editorAnalyticsAPI,
174
+ languageSource = _ref3.languageSource,
175
+ result = _ref3.result,
176
+ tr = _ref3.tr;
177
+ if (result.status === 'failed') {
178
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
179
+ action: _analytics.ACTION.ERRORED,
180
+ actionSubject: _analytics.ACTION_SUBJECT.CODE_BLOCK,
181
+ attributes: {
182
+ errorType: result.errorType,
183
+ language: result.language,
184
+ languageSource: languageSource
185
+ },
186
+ eventType: _analytics.EVENT_TYPE.TRACK
187
+ })(tr);
188
+ return;
189
+ }
190
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
191
+ action: _analytics.ACTION.FORMATTED,
192
+ actionSubject: _analytics.ACTION_SUBJECT.CODE_BLOCK,
193
+ attributes: {
194
+ language: result.language,
195
+ languageSource: languageSource,
196
+ outcome: result.status
197
+ },
198
+ eventType: _analytics.EVENT_TYPE.TRACK
199
+ })(tr);
200
+ };
201
+ var createResolveFormatCodeTransaction = function createResolveFormatCodeTransaction(_ref4) {
202
+ var editorAnalyticsAPI = _ref4.editorAnalyticsAPI,
203
+ localId = _ref4.localId,
204
+ pendingFormat = _ref4.pendingFormat,
205
+ result = _ref4.result,
206
+ tr = _ref4.tr;
207
+ var languageSource = pendingFormat.languageSource,
208
+ requestId = pendingFormat.requestId;
209
+ var codeBlockNode = tr.doc.nodeAt(pendingFormat.pos);
210
+ var hasMatchingCodeBlock = (codeBlockNode === null || codeBlockNode === void 0 ? void 0 : codeBlockNode.type) === tr.doc.type.schema.nodes.codeBlock && (codeBlockNode === null || codeBlockNode === void 0 ? void 0 : codeBlockNode.attrs.localId) === localId;
211
+ if (!hasMatchingCodeBlock) {
212
+ // Keep failure telemetry even when the target block is no longer available.
213
+ if (result.status === 'failed') {
214
+ attachFormatCodeAnalytics({
215
+ editorAnalyticsAPI: editorAnalyticsAPI,
216
+ languageSource: languageSource,
217
+ result: result,
218
+ tr: tr
219
+ });
220
+ }
221
+ return setResolveFormatCodeMeta(tr, {
222
+ languageSource: languageSource,
223
+ localId: localId,
224
+ outcome: 'unchanged',
225
+ requestId: requestId
226
+ });
227
+ }
228
+ var resultTransaction = tr;
229
+ if (result.status === 'formatted') {
230
+ resultTransaction = replaceCodeBlockText({
231
+ codeBlockNode: codeBlockNode,
232
+ content: result.content,
233
+ pos: pendingFormat.pos,
234
+ tr: tr
235
+ });
236
+ }
237
+ attachFormatCodeAnalytics({
238
+ editorAnalyticsAPI: editorAnalyticsAPI,
239
+ languageSource: languageSource,
240
+ result: result,
241
+ tr: resultTransaction
242
+ });
243
+ return setResolveFormatCodeMeta(resultTransaction, {
244
+ errorType: result.status === 'failed' ? result.errorType : undefined,
245
+ languageSource: languageSource,
246
+ localId: localId,
247
+ outcome: result.status,
248
+ requestId: requestId
249
+ });
250
+ };
251
+ var createFormatCodeOnClick = exports.createFormatCodeOnClick = function createFormatCodeOnClick(_ref5) {
252
+ var api = _ref5.api,
253
+ editorAnalyticsAPI = _ref5.editorAnalyticsAPI;
254
+ return function (state, dispatch) {
255
+ var _autoDetectPluginKey$2, _api$core;
256
+ var currentCodeBlockState = _pluginKey.pluginKey.getState(state);
257
+ var currentPos = currentCodeBlockState === null || currentCodeBlockState === void 0 ? void 0 : currentCodeBlockState.pos;
258
+ if (!currentCodeBlockState || typeof currentPos !== 'number') {
259
+ return false;
260
+ }
261
+ var currentNode = state.doc.nodeAt(currentPos);
262
+ if (!currentNode || currentNode.type !== state.schema.nodes.codeBlock) {
263
+ return false;
264
+ }
265
+ var currentLanguage = currentNode.attrs.language;
266
+ if (!(0, _formatter.isSupportedFormatLanguage)(currentLanguage)) {
267
+ return true;
268
+ }
269
+ var currentLocalId = currentNode.attrs.localId;
270
+ if (currentCodeBlockState.pendingFormats[currentLocalId]) {
271
+ return true;
272
+ }
273
+ var autoDetectEntry = (_autoDetectPluginKey$2 = _autoDetectState.autoDetectPluginKey.getState(state)) === null || _autoDetectPluginKey$2 === void 0 ? void 0 : _autoDetectPluginKey$2.languageDetectionMap[currentLocalId];
274
+ var languageSource = (autoDetectEntry === null || autoDetectEntry === void 0 ? void 0 : autoDetectEntry.autoDetectedLanguage) === currentLanguage ? 'auto-detected' : 'selected';
275
+ var content = currentNode.textContent;
276
+ var requestId = crypto.randomUUID();
277
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref6) {
278
+ var tr = _ref6.tr;
279
+ return tr.setMeta(_pluginKey.pluginKey, {
280
+ type: _actions.ACTIONS.START_FORMAT_CODE,
281
+ data: {
282
+ languageSource: languageSource,
283
+ localId: currentLocalId,
284
+ pos: currentPos,
285
+ requestId: requestId
286
+ }
287
+ });
288
+ });
289
+ void (0, _formatter.formatCode)({
290
+ content: content,
291
+ language: currentLanguage
292
+ }).then(function (result) {
293
+ var _api$codeBlock, _api$core2;
294
+ var pendingFormat = api === null || api === void 0 || (_api$codeBlock = api.codeBlock) === null || _api$codeBlock === void 0 || (_api$codeBlock = _api$codeBlock.sharedState.currentState()) === null || _api$codeBlock === void 0 ? void 0 : _api$codeBlock.pendingFormats[currentLocalId];
295
+ if (!pendingFormat || pendingFormat.requestId !== requestId) {
296
+ return;
297
+ }
298
+ api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref7) {
299
+ var tr = _ref7.tr;
300
+ return createResolveFormatCodeTransaction({
301
+ editorAnalyticsAPI: editorAnalyticsAPI,
302
+ localId: currentLocalId,
303
+ pendingFormat: pendingFormat,
304
+ result: result,
305
+ tr: tr
306
+ });
307
+ });
308
+ });
309
+ return true;
310
+ };
311
+ };
138
312
  var copyContentToClipboardWithAnalytics = exports.copyContentToClipboardWithAnalytics = function copyContentToClipboardWithAnalytics(editorAnalyticsAPI) {
139
313
  return function (state, dispatch) {
140
314
  var nodes = state.schema.nodes,
@@ -238,8 +412,8 @@ var resetShouldIgnoreFollowingMutations = exports.resetShouldIgnoreFollowingMuta
238
412
  * if there is text selected it will wrap the current selection if not it will
239
413
  * append the codeblock to the end of the document.
240
414
  */
241
- function createInsertCodeBlockTransaction(_ref) {
242
- var state = _ref.state;
415
+ function createInsertCodeBlockTransaction(_ref8) {
416
+ var state = _ref8.state;
243
417
  var tr = state.tr;
244
418
  var from = state.selection.from;
245
419
  var codeBlock = state.schema.nodes.codeBlock;
@@ -326,8 +500,8 @@ var toggleWordWrapStateForCodeBlockNode = exports.toggleWordWrapStateForCodeBloc
326
500
  };
327
501
  };
328
502
  var toggleLineNumbersForCodeBlockNodeEditorCommand = exports.toggleLineNumbersForCodeBlockNodeEditorCommand = function toggleLineNumbersForCodeBlockNodeEditorCommand(editorAnalyticsAPI) {
329
- return function (_ref2) {
330
- var tr = _ref2.tr;
503
+ return function (_ref9) {
504
+ var tr = _ref9.tr;
331
505
  var codeBlockType = tr.doc.type.schema.nodes.codeBlock;
332
506
  var codeBlock = (0, _utils.findSelectedNodeOfType)(codeBlockType)(tr.selection) || (0, _utils.findParentNodeOfType)(codeBlockType)(tr.selection);
333
507
  if (!codeBlock) {
@@ -5,9 +5,12 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.ACTIONS = void 0;
7
7
  var ACTIONS = exports.ACTIONS = {
8
+ CLEAR_FORMAT_CODE_ERROR: 'CLEAR_FORMAT_CODE_ERROR',
9
+ REMOVE_AUTO_DETECT_ENTRY: 'REMOVE_AUTO_DETECT_ENTRY',
10
+ RESOLVE_FORMAT_CODE: 'RESOLVE_FORMAT_CODE',
11
+ SET_AUTO_DETECT_ENTRY: 'SET_AUTO_DETECT_ENTRY',
8
12
  SET_COPIED_TO_CLIPBOARD: 'SET_COPIED_TO_CLIPBOARD',
9
- SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS: 'SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS',
10
13
  SET_IS_WRAPPED: 'SET_IS_WRAPPED',
11
- SET_AUTO_DETECT_ENTRY: 'SET_AUTO_DETECT_ENTRY',
12
- REMOVE_AUTO_DETECT_ENTRY: 'REMOVE_AUTO_DETECT_ENTRY'
14
+ SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS: 'SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS',
15
+ START_FORMAT_CODE: 'START_FORMAT_CODE'
13
16
  };
@@ -18,6 +18,7 @@ var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
18
18
  var _editorCommands = require("../editor-commands");
19
19
  var _codeBlock2 = require("../nodeviews/code-block");
20
20
  var _classNames = require("../ui/class-names");
21
+ var _formatCodeState = require("../utils/format-code/format-code-state");
21
22
  var _actions = require("./actions");
22
23
  var _decorators = require("./decorators");
23
24
  var _pluginKey = require("./plugin-key");
@@ -94,7 +95,9 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
94
95
  return {
95
96
  pos: node ? node.pos : null,
96
97
  contentCopied: false,
98
+ formatCodeErrors: {},
97
99
  isNodeSelected: false,
100
+ pendingFormats: {},
98
101
  shouldIgnoreFollowingMutations: false,
99
102
  decorations: _view.DecorationSet.create(state.doc, initialDecorations)
100
103
  };
@@ -127,7 +130,16 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
127
130
  isNodeSelected: tr.selection instanceof _state.NodeSelection,
128
131
  decorations: updatedDecorationSet
129
132
  });
130
- return newPluginState;
133
+ if (!(0, _expValEquals.expValEquals)('platform_editor_code_block_q4_lovability', 'isEnabled', true)) {
134
+ return newPluginState;
135
+ }
136
+
137
+ // Successful format results change the doc and carry format meta.
138
+ var formatCodePluginState = (0, _formatCodeState.applyFormatCodeMeta)(newPluginState, meta);
139
+ return _objectSpread(_objectSpread({}, formatCodePluginState), {}, {
140
+ // Pending format requests can outlive unrelated document edits.
141
+ pendingFormats: (0, _formatCodeState.mapPendingFormats)(formatCodePluginState.pendingFormats, tr, newState)
142
+ });
131
143
  }
132
144
  if (tr.selectionSet) {
133
145
  var _node2 = (0, _transforms.findCodeBlock)(newState, tr.selection);
@@ -146,6 +158,10 @@ var createPlugin = exports.createPlugin = function createPlugin(_ref) {
146
158
  shouldIgnoreFollowingMutations: meta.data
147
159
  });
148
160
  }
161
+ if ((0, _expValEquals.expValEquals)('platform_editor_code_block_q4_lovability', 'isEnabled', true)) {
162
+ // Failed/unchanged format results and dismissals are meta-only.
163
+ return (0, _formatCodeState.applyFormatCodeMeta)(pluginState, meta);
164
+ }
149
165
  return pluginState;
150
166
  }
151
167
  },
@@ -13,6 +13,7 @@ var _codeBlock = require("@atlaskit/editor-common/code-block");
13
13
  var _messages = _interopRequireWildcard(require("@atlaskit/editor-common/messages"));
14
14
  var _toolbarFlagCheck = require("@atlaskit/editor-common/toolbar-flag-check");
15
15
  var _utils = require("@atlaskit/editor-prosemirror/utils");
16
+ var _angleBrackets = _interopRequireDefault(require("@atlaskit/icon/core/angle-brackets"));
16
17
  var _copy = _interopRequireDefault(require("@atlaskit/icon/core/copy"));
17
18
  var _delete = _interopRequireDefault(require("@atlaskit/icon/core/delete"));
18
19
  var _listNumbered = _interopRequireDefault(require("@atlaskit/icon/core/list-numbered"));
@@ -23,6 +24,7 @@ var _editorCommands = require("../editor-commands");
23
24
  var _CodeBlockLanguagePicker = require("../ui/CodeBlockLanguagePicker");
24
25
  var _WrapIcon = require("../ui/icons/WrapIcon");
25
26
  var _languagePickerOptions = require("../ui/language-picker-options");
27
+ var _formatter = require("../utils/format-code/formatter");
26
28
  var _autoDetectState = require("./auto-detect-state");
27
29
  var _codeBlockCopySelectionPlugin = require("./codeBlockCopySelectionPlugin");
28
30
  var _languageList = require("./language-list");
@@ -96,7 +98,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig() {
96
98
  var language = node === null || node === void 0 || (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.language;
97
99
  var localId = node === null || node === void 0 || (_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.localId;
98
100
  var autoDetectState = _autoDetectState.autoDetectPluginKey.getState(state);
99
-
101
+ var isFormatCodePending = typeof localId === 'string' && Boolean(codeBlockState.pendingFormats[localId]);
100
102
  // Keep fresh option objects for the legacy toolbar select so reopening it
101
103
  // continues to start from the top rather than preserving the previously
102
104
  // focused option by reference.
@@ -246,6 +248,21 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig() {
246
248
  tabIndex: null,
247
249
  selected: areLineNumbersVisible
248
250
  };
251
+ var canFormatCode = node.textContent.length > 0 && (0, _formatter.isSupportedFormatLanguage)(language);
252
+ var formatCodeButton = {
253
+ id: 'editor.codeBlock.formatCode',
254
+ type: 'button',
255
+ supportsViewMode: false,
256
+ disabled: !canFormatCode || isFormatCodePending,
257
+ icon: _angleBrackets.default,
258
+ onClick: (0, _editorCommands.createFormatCodeOnClick)({
259
+ api: api,
260
+ editorAnalyticsAPI: editorAnalyticsAPI
261
+ }),
262
+ onFocus: (0, _formatter.preloadFormatterOnIntent)(),
263
+ onMouseEnter: (0, _formatter.preloadFormatterOnIntent)(),
264
+ title: formatMessage(canFormatCode ? _messages.codeBlockButtonMessages.formatCode : _messages.codeBlockButtonMessages.formatCodeUnavailable)
265
+ };
249
266
  return {
250
267
  title: 'CodeBlock floating controls',
251
268
  // Ignored via go/ees005
@@ -254,7 +271,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig() {
254
271
  return (0, _utils.findDomRefAtPos)(pos, view.domAtPos.bind(view));
255
272
  },
256
273
  nodeType: nodeType,
257
- items: [languagePicker !== null && languagePicker !== void 0 ? languagePicker : languageSelect].concat((0, _toConsumableArray2.default)(areAnyNewToolbarFlagsEnabled ? [] : [separator]), [codeBlockWrapButton], (0, _toConsumableArray2.default)((0, _expValEquals.expValEquals)('platform_editor_code_block_q4_lovability', 'isEnabled', true) && (0, _platformFeatureFlags.fg)('platform_editor_code_block_add_line_number_button') ? [codeBlockLineNumbersButton] : []), (0, _toConsumableArray2.default)(copyAndDeleteButtonMenuItems)),
274
+ items: [languagePicker !== null && languagePicker !== void 0 ? languagePicker : languageSelect].concat((0, _toConsumableArray2.default)(areAnyNewToolbarFlagsEnabled ? [] : [separator]), [codeBlockWrapButton], (0, _toConsumableArray2.default)((0, _expValEquals.expValEquals)('platform_editor_code_block_q4_lovability', 'isEnabled', true) && (0, _platformFeatureFlags.fg)('platform_editor_code_block_add_line_number_button') ? [codeBlockLineNumbersButton] : []), (0, _toConsumableArray2.default)((0, _expValEquals.expValEquals)('platform_editor_code_block_q4_lovability', 'isEnabled', true) && (0, _platformFeatureFlags.fg)('platform_editor_code_block_add_line_number_button') && (0, _platformFeatureFlags.fg)('platform_editor_code_block_formatting') ? [formatCodeButton] : []), (0, _toConsumableArray2.default)(copyAndDeleteButtonMenuItems)),
258
275
  scrollable: true
259
276
  };
260
277
  };
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.FormatCodeErrorFlag = void 0;
9
+ var _react = _interopRequireWildcard(require("react"));
10
+ var _reactIntl = require("react-intl");
11
+ var _hooks = require("@atlaskit/editor-common/hooks");
12
+ var _messages = require("@atlaskit/editor-common/messages");
13
+ var _flag = _interopRequireWildcard(require("@atlaskit/flag"));
14
+ var _statusError = _interopRequireDefault(require("@atlaskit/icon/core/status-error"));
15
+ var _actions = require("../pm-plugins/actions");
16
+ var _pluginKey = require("../pm-plugins/plugin-key");
17
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
18
+ var FormatCodeErrorFlagItem = function FormatCodeErrorFlagItem(_ref) {
19
+ var formatCodeError = _ref.formatCodeError;
20
+ var _useIntl = (0, _reactIntl.useIntl)(),
21
+ formatMessage = _useIntl.formatMessage;
22
+ return /*#__PURE__*/_react.default.createElement(_flag.default, {
23
+ description: formatMessage(formatCodeError.languageSource === 'auto-detected' ? _messages.codeBlockButtonMessages.formatCodeFailedAutoDetectedDescription : _messages.codeBlockButtonMessages.formatCodeFailedDescription),
24
+ icon: /*#__PURE__*/_react.default.createElement(_statusError.default, {
25
+ color: "var(--ds-icon-danger, #C9372C)",
26
+ label: ""
27
+ }),
28
+ id: formatCodeError.localId,
29
+ title: formatMessage(_messages.codeBlockButtonMessages.formatCodeFailed)
30
+ });
31
+ };
32
+ var FormatCodeErrorFlag = exports.FormatCodeErrorFlag = function FormatCodeErrorFlag(_ref2) {
33
+ var api = _ref2.api;
34
+ var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['codeBlock'], function (states) {
35
+ var _states$codeBlockStat, _states$codeBlockStat2;
36
+ return {
37
+ formatCodeErrors: (_states$codeBlockStat = (_states$codeBlockStat2 = states.codeBlockState) === null || _states$codeBlockStat2 === void 0 ? void 0 : _states$codeBlockStat2.formatCodeErrors) !== null && _states$codeBlockStat !== void 0 ? _states$codeBlockStat : {}
38
+ };
39
+ }),
40
+ formatCodeErrors = _useSharedPluginState.formatCodeErrors;
41
+ var onDismissed = (0, _react.useCallback)(function (localId) {
42
+ var _api$core, _api$core2;
43
+ api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref3) {
44
+ var tr = _ref3.tr;
45
+ tr.setMeta(_pluginKey.pluginKey, {
46
+ type: _actions.ACTIONS.CLEAR_FORMAT_CODE_ERROR,
47
+ data: {
48
+ localId: localId
49
+ }
50
+ });
51
+ return tr;
52
+ });
53
+ api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.focus();
54
+ }, [api]);
55
+ var onFlagGroupDismissed = (0, _react.useCallback)(function (localId) {
56
+ return onDismissed(String(localId));
57
+ }, [onDismissed]);
58
+ var activeFormatCodeErrors = Object.values(formatCodeErrors);
59
+ if (activeFormatCodeErrors.length === 0) {
60
+ return null;
61
+ }
62
+ return /*#__PURE__*/_react.default.createElement(_flag.FlagGroup, {
63
+ onDismissed: onFlagGroupDismissed
64
+ }, activeFormatCodeErrors.map(function (formatCodeError) {
65
+ return /*#__PURE__*/_react.default.createElement(FormatCodeErrorFlagItem, {
66
+ formatCodeError: formatCodeError,
67
+ key: formatCodeError.localId
68
+ });
69
+ }));
70
+ };
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.mapPendingFormats = exports.applyFormatCodeMeta = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
+ var _actions = require("../../pm-plugins/actions");
11
+ 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; }
12
+ 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; }
13
+ var mapPendingFormats = exports.mapPendingFormats = function mapPendingFormats(pendingFormats, tr, newState) {
14
+ var entries = Object.entries(pendingFormats);
15
+ if (entries.length === 0) {
16
+ return pendingFormats;
17
+ }
18
+ var nextPendingFormats = pendingFormats;
19
+ entries.forEach(function (_ref) {
20
+ var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
21
+ localId = _ref2[0],
22
+ pendingFormat = _ref2[1];
23
+ var _tr$mapping$mapResult = tr.mapping.mapResult(pendingFormat.pos, 1),
24
+ deleted = _tr$mapping$mapResult.deleted,
25
+ pos = _tr$mapping$mapResult.pos;
26
+ var codeBlockNode = newState.doc.nodeAt(pos);
27
+ var shouldRemovePendingFormat = deleted || (codeBlockNode === null || codeBlockNode === void 0 ? void 0 : codeBlockNode.type) !== newState.schema.nodes.codeBlock || (codeBlockNode === null || codeBlockNode === void 0 ? void 0 : codeBlockNode.attrs.localId) !== localId;
28
+ var shouldUpdatePendingFormat = pos !== pendingFormat.pos;
29
+ if (shouldRemovePendingFormat || shouldUpdatePendingFormat) {
30
+ if (nextPendingFormats === pendingFormats) {
31
+ nextPendingFormats = _objectSpread({}, pendingFormats);
32
+ }
33
+ }
34
+ if (shouldRemovePendingFormat) {
35
+ delete nextPendingFormats[localId];
36
+ return;
37
+ }
38
+ if (shouldUpdatePendingFormat) {
39
+ nextPendingFormats[localId] = _objectSpread(_objectSpread({}, pendingFormat), {}, {
40
+ pos: pos
41
+ });
42
+ }
43
+ });
44
+ return nextPendingFormats;
45
+ };
46
+ function removeRecordEntry(record, key) {
47
+ var nextRecord = _objectSpread({}, record);
48
+ delete nextRecord[key];
49
+ return nextRecord;
50
+ }
51
+ var applyFormatCodeMeta = exports.applyFormatCodeMeta = function applyFormatCodeMeta(pluginState, meta) {
52
+ switch (meta === null || meta === void 0 ? void 0 : meta.type) {
53
+ case _actions.ACTIONS.START_FORMAT_CODE:
54
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
55
+ pendingFormats: _objectSpread(_objectSpread({}, pluginState.pendingFormats), {}, (0, _defineProperty2.default)({}, meta.data.localId, {
56
+ languageSource: meta.data.languageSource,
57
+ pos: meta.data.pos,
58
+ requestId: meta.data.requestId
59
+ }))
60
+ });
61
+ case _actions.ACTIONS.RESOLVE_FORMAT_CODE:
62
+ {
63
+ var pendingFormats = removeRecordEntry(pluginState.pendingFormats, meta.data.localId);
64
+ var formatCodeErrors = removeRecordEntry(pluginState.formatCodeErrors, meta.data.localId);
65
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
66
+ formatCodeErrors: meta.data.outcome === 'failed' ? _objectSpread(_objectSpread({}, formatCodeErrors), {}, (0, _defineProperty2.default)({}, meta.data.localId, {
67
+ errorType: meta.data.errorType,
68
+ localId: meta.data.localId,
69
+ languageSource: meta.data.languageSource
70
+ })) : formatCodeErrors,
71
+ pendingFormats: pendingFormats
72
+ });
73
+ }
74
+ case _actions.ACTIONS.CLEAR_FORMAT_CODE_ERROR:
75
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
76
+ formatCodeErrors: removeRecordEntry(pluginState.formatCodeErrors, meta.data.localId)
77
+ });
78
+ default:
79
+ return pluginState;
80
+ }
81
+ };
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.formatCode = void 0;
7
+ var formatCode = exports.formatCode = function formatCode(_ref) {
8
+ var content = _ref.content,
9
+ language = _ref.language;
10
+ return Promise.resolve({
11
+ content: content,
12
+ language: language,
13
+ status: 'unchanged'
14
+ });
15
+ };