@atlaskit/editor-plugin-text-formatting 10.1.6 → 10.2.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @atlaskit/editor-plugin-text-formatting
2
2
 
3
+ ## 10.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+
9
+ ## 10.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [`f9107727f48c2`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/f9107727f48c2) -
14
+ Support markdown source view inline formatting toolbar actions
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies
19
+
3
20
  ## 10.1.6
4
21
 
5
22
  ### Patch Changes
@@ -56,7 +56,7 @@ var textFormattingPlugin = exports.textFormattingPlugin = function textFormattin
56
56
  };
57
57
  if (isToolbarAIFCEnabled) {
58
58
  var _api$toolbar;
59
- api === null || api === void 0 || (_api$toolbar = api.toolbar) === null || _api$toolbar === void 0 || _api$toolbar.actions.registerComponents((0, _toolbarComponents.getToolbarComponents)(api));
59
+ api === null || api === void 0 || (_api$toolbar = api.toolbar) === null || _api$toolbar === void 0 || _api$toolbar.actions.registerComponents((0, _toolbarComponents.getToolbarComponents)(api, options));
60
60
  } else {
61
61
  var _api$primaryToolbar;
62
62
  api === null || api === void 0 || (_api$primaryToolbar = api.primaryToolbar) === null || _api$primaryToolbar === void 0 || _api$primaryToolbar.actions.registerComponent({
@@ -7,14 +7,46 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.useComponentInfo = exports.formatOptions = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _reactIntl = require("react-intl");
10
+ var _analytics = require("@atlaskit/editor-common/analytics");
10
11
  var _hooks = require("@atlaskit/editor-common/hooks");
11
12
  var _keymaps = require("@atlaskit/editor-common/keymaps");
12
13
  var _messages = require("@atlaskit/editor-common/messages");
13
14
  var _toolbar = require("@atlaskit/editor-common/toolbar");
14
15
  var _editorToolbar = require("@atlaskit/editor-toolbar");
16
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
17
+ var _expValEqualsNoExposure = require("@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure");
15
18
  var _toggleMark = require("../../../editor-commands/toggle-mark");
16
19
  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; }
17
20
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
21
+ /**
22
+ * Local copy of `@atlassian/editor-plugin-markdown-mode/source-view-utils`'s
23
+ * `SourceViewInlineFormat` union. Kept here so this `@atlaskit/`-published
24
+ * package doesn't depend on the `@atlassian/`-namespaced source-view-utils
25
+ * subpath for type resolution. Must stay in sync with the source-of-truth
26
+ * declaration in markdown-mode.
27
+ */
28
+
29
+ /**
30
+ * Maps the text-formatting plugin's `FormatOptions` keys to their
31
+ * `SourceViewInlineFormat` equivalents for the CM6 source view.
32
+ * Only formats that have a markdown syntax equivalent are included —
33
+ * underline, subscript, and superscript have no GFM equivalent and
34
+ * are left as undefined (they remain PM-only).
35
+ */
36
+ var FORMAT_OPTION_TO_SOURCE_VIEW = {
37
+ strong: 'bold',
38
+ em: 'italic',
39
+ code: 'inlineCode',
40
+ strike: 'strikethrough'
41
+ };
42
+ var SOURCE_VIEW_ANALYTICS_ACTION_SUBJECT_ID = {
43
+ bold: _analytics.ACTION_SUBJECT_ID.FORMAT_STRONG,
44
+ italic: _analytics.ACTION_SUBJECT_ID.FORMAT_ITALIC,
45
+ inlineCode: _analytics.ACTION_SUBJECT_ID.FORMAT_CODE,
46
+ strikethrough: _analytics.ACTION_SUBJECT_ID.FORMAT_STRIKE
47
+ };
48
+ var TEXT_FORMATTING_PLUGIN_STATE_KEYS = ['textFormatting'];
49
+ var TEXT_FORMATTING_MARKDOWN_PLUGIN_STATE_KEYS = ['textFormatting', 'markdownMode'];
18
50
  var FormatMarkSchema = {
19
51
  strong: 'strong',
20
52
  em: 'em',
@@ -32,19 +64,25 @@ var useComponentInfo = exports.useComponentInfo = function useComponentInfo(_ref
32
64
  shortcut = _ref.shortcut,
33
65
  toggleMarkWithAnalyticsCallback = _ref.toggleMarkWithAnalyticsCallback,
34
66
  parents = _ref.parents;
35
- var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['textFormatting'], function (states) {
36
- var _states$textFormattin, _states$textFormattin2, _states$textFormattin3, _states$textFormattin4;
67
+ var isMarkdownBridgeEnabled = (0, _expValEqualsNoExposure.expValEqualsNoExposure)('cc-markdown-mode', 'isEnabled', true) && (0, _platformFeatureFlags.fg)('platform_editor_markdown_compatible_toolbar');
68
+ var pluginStateKeys = isMarkdownBridgeEnabled ? TEXT_FORMATTING_MARKDOWN_PLUGIN_STATE_KEYS : TEXT_FORMATTING_PLUGIN_STATE_KEYS;
69
+ var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, pluginStateKeys, function (states) {
70
+ var _states$textFormattin, _states$textFormattin2, _states$textFormattin3, _states$textFormattin4, _states$markdownModeS, _states$markdownModeS2;
37
71
  return {
38
72
  isActive: (_states$textFormattin = states.textFormattingState) === null || _states$textFormattin === void 0 ? void 0 : _states$textFormattin["".concat(optionType, "Active")],
39
73
  isDisabled: (_states$textFormattin2 = states.textFormattingState) === null || _states$textFormattin2 === void 0 ? void 0 : _states$textFormattin2["".concat(optionType, "Disabled")],
40
74
  isHidden: (_states$textFormattin3 = states.textFormattingState) === null || _states$textFormattin3 === void 0 ? void 0 : _states$textFormattin3["".concat(optionType, "Hidden")],
41
- isPluginInitialised: (_states$textFormattin4 = states.textFormattingState) === null || _states$textFormattin4 === void 0 ? void 0 : _states$textFormattin4.isInitialised
75
+ isPluginInitialised: (_states$textFormattin4 = states.textFormattingState) === null || _states$textFormattin4 === void 0 ? void 0 : _states$textFormattin4.isInitialised,
76
+ markdownModeView: isMarkdownBridgeEnabled ? (_states$markdownModeS = states.markdownModeState) === null || _states$markdownModeS === void 0 ? void 0 : _states$markdownModeS.view : undefined,
77
+ sourceFormatState: isMarkdownBridgeEnabled ? (_states$markdownModeS2 = states.markdownModeState) === null || _states$markdownModeS2 === void 0 ? void 0 : _states$markdownModeS2.sourceInlineFormatState : null
42
78
  };
43
79
  }),
44
80
  isActive = _useSharedPluginState.isActive,
45
81
  isDisabled = _useSharedPluginState.isDisabled,
46
82
  isHidden = _useSharedPluginState.isHidden,
47
- isPluginInitialised = _useSharedPluginState.isPluginInitialised;
83
+ isPluginInitialised = _useSharedPluginState.isPluginInitialised,
84
+ markdownModeView = _useSharedPluginState.markdownModeView,
85
+ sourceFormatState = _useSharedPluginState.sourceFormatState;
48
86
  var hasMarkSchema = api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || (_api$core = _api$core.sharedState.currentState()) === null || _api$core === void 0 || (_api$core = _api$core.schema) === null || _api$core === void 0 ? void 0 : _api$core.marks[FormatMarkSchema[optionType]];
49
87
  var formatOptionState;
50
88
  if (!isPluginInitialised) {
@@ -65,9 +103,89 @@ var useComponentInfo = exports.useComponentInfo = function useComponentInfo(_ref
65
103
  var formatTitle = formatMessage(title);
66
104
  var shortcutContent = (0, _keymaps.tooltip)(shortcut);
67
105
  var ariaLabel = (0, _keymaps.tooltip)(shortcut, formatTitle);
106
+
107
+ // The SourceViewInlineFormat key for this format option, if it has one.
108
+ // undefined for underline, subscript, superscript (no GFM equivalent).
109
+ var sourceViewFormat = FORMAT_OPTION_TO_SOURCE_VIEW[optionType];
110
+
111
+ // The CM6 source view is authoritative when the user has switched to it.
112
+ // We rely on `markdownModeState.view === 'syntax'` (synchronous, set on
113
+ // `setView`) rather than the presence of `sourceFormatState` — the latter
114
+ // is `null` until the CM6 update listener fires for the first time, so
115
+ // using it as the sentinel would let the first toolbar click after entering
116
+ // source view fall through to the PM path and mutate the hidden PM doc.
117
+ var isInSourceView = markdownModeView === 'syntax';
118
+ if (isInSourceView && !sourceViewFormat) {
119
+ // Underline, subscript, superscript have no GFM equivalent. Disable
120
+ // them immediately on entering source view — independent of whether
121
+ // the CM6 update listener has fired yet — so the buttons don't briefly
122
+ // appear active/enabled during that race window.
123
+ formatOptionState = {
124
+ isActive: false,
125
+ isDisabled: true,
126
+ isHidden: false
127
+ };
128
+ } else if (isInSourceView && sourceFormatState && sourceViewFormat) {
129
+ // Map each SourceViewInlineFormat to its isActive field on the snapshot.
130
+ var activeByFormat = {
131
+ bold: sourceFormatState.boldActive,
132
+ italic: sourceFormatState.italicActive,
133
+ inlineCode: sourceFormatState.codeActive,
134
+ strikethrough: sourceFormatState.strikeActive
135
+ };
136
+ formatOptionState = {
137
+ isActive: activeByFormat[sourceViewFormat],
138
+ isDisabled: !sourceFormatState.inlineFormattingAvailable,
139
+ isHidden: false
140
+ };
141
+ } else if (isInSourceView) {
142
+ // Race window: the user has switched to source view but the CM6 update
143
+ // listener hasn't pushed its first format state snapshot yet
144
+ // (`sourceFormatState` is still `null`). Without this branch the
145
+ // button would render stale PM-cursor state (e.g. "Bold active" based
146
+ // on where the PM selection was) until CM6 catches up. Render a
147
+ // neutral, non-disabled state instead.
148
+ formatOptionState = {
149
+ isActive: false,
150
+ isDisabled: false,
151
+ isHidden: false
152
+ };
153
+ }
68
154
  var onClick = function onClick() {
69
- var _api$analytics;
70
- api === null || api === void 0 || api.core.actions.execute(toggleMarkWithAnalyticsCallback(api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions)((0, _toolbar.getInputMethodFromParentKeys)(parents)));
155
+ var _api$markdownMode, _api$markdownMode2, _api$markdownMode3, _api$markdownMode4, _api$analytics2;
156
+ // Route to CM6 when in source view and the format has a CM6 equivalent.
157
+ if (isInSourceView) {
158
+ if (sourceViewFormat) {
159
+ var _api$analytics;
160
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.fireAnalyticsEvent({
161
+ action: _analytics.ACTION.FORMATTED,
162
+ actionSubject: _analytics.ACTION_SUBJECT.TEXT,
163
+ eventType: _analytics.EVENT_TYPE.TRACK,
164
+ actionSubjectId: SOURCE_VIEW_ANALYTICS_ACTION_SUBJECT_ID[sourceViewFormat],
165
+ attributes: {
166
+ inputMethod: (0, _toolbar.getInputMethodFromParentKeys)(parents)
167
+ }
168
+ });
169
+ switch (sourceViewFormat) {
170
+ case 'bold':
171
+ api === null || api === void 0 || (_api$markdownMode = api.markdownMode) === null || _api$markdownMode === void 0 || _api$markdownMode.actions.toggleSourceBold();
172
+ break;
173
+ case 'italic':
174
+ api === null || api === void 0 || (_api$markdownMode2 = api.markdownMode) === null || _api$markdownMode2 === void 0 || _api$markdownMode2.actions.toggleSourceItalic();
175
+ break;
176
+ case 'inlineCode':
177
+ api === null || api === void 0 || (_api$markdownMode3 = api.markdownMode) === null || _api$markdownMode3 === void 0 || _api$markdownMode3.actions.toggleSourceInlineCode();
178
+ break;
179
+ case 'strikethrough':
180
+ api === null || api === void 0 || (_api$markdownMode4 = api.markdownMode) === null || _api$markdownMode4 === void 0 || _api$markdownMode4.actions.toggleSourceStrike();
181
+ break;
182
+ }
183
+ }
184
+ return;
185
+ }
186
+
187
+ // Default PM path.
188
+ api === null || api === void 0 || api.core.actions.execute(toggleMarkWithAnalyticsCallback(api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions)((0, _toolbar.getInputMethodFromParentKeys)(parents)));
71
189
  };
72
190
  return _objectSpread(_objectSpread({}, formatOptionState), {}, {
73
191
  formatTitle: formatTitle,
@@ -11,6 +11,6 @@ var _TextFormattingGroupForInlineToolbar = require("./Toolbar/components/TextFor
11
11
  var _TextFormattingGroups = require("./Toolbar/components/TextFormattingGroups");
12
12
  var _TextFormattingMenuGroup = require("./Toolbar/components/TextFormattingMenuGroup");
13
13
  var _UnderlineButtonGroup = require("./Toolbar/components/UnderlineButtonGroup");
14
- var getToolbarComponents = exports.getToolbarComponents = function getToolbarComponents(api) {
15
- return [].concat((0, _toConsumableArray2.default)((0, _TextFormattingGroups.textFormattingGroupForPrimaryToolbar)(api)), (0, _toConsumableArray2.default)((0, _TextFormattingGroupForInlineToolbar.textFormattingGroupForInlineToolbar)(api)), (0, _toConsumableArray2.default)((0, _BoldButtonGroup.boldButtonGroup)(api)), (0, _toConsumableArray2.default)((0, _UnderlineButtonGroup.underlineButtonGroup)(api)), (0, _toConsumableArray2.default)((0, _TextFormattingMenuGroup.textFormattingMenuGroup)(api)));
14
+ var getToolbarComponents = exports.getToolbarComponents = function getToolbarComponents(api, options) {
15
+ return [].concat((0, _toConsumableArray2.default)((0, _TextFormattingGroups.textFormattingGroupForPrimaryToolbar)(api)), (0, _toConsumableArray2.default)((0, _TextFormattingGroupForInlineToolbar.textFormattingGroupForInlineToolbar)(api)), (0, _toConsumableArray2.default)((0, _BoldButtonGroup.boldButtonGroup)(api)), (0, _toConsumableArray2.default)(options !== null && options !== void 0 && options.disableUnderline ? [] : (0, _UnderlineButtonGroup.underlineButtonGroup)(api)), (0, _toConsumableArray2.default)((0, _TextFormattingMenuGroup.textFormattingMenuGroup)(api)));
16
16
  };
@@ -49,7 +49,7 @@ export const textFormattingPlugin = ({
49
49
  };
50
50
  if (isToolbarAIFCEnabled) {
51
51
  var _api$toolbar;
52
- api === null || api === void 0 ? void 0 : (_api$toolbar = api.toolbar) === null || _api$toolbar === void 0 ? void 0 : _api$toolbar.actions.registerComponents(getToolbarComponents(api));
52
+ api === null || api === void 0 ? void 0 : (_api$toolbar = api.toolbar) === null || _api$toolbar === void 0 ? void 0 : _api$toolbar.actions.registerComponents(getToolbarComponents(api, options));
53
53
  } else {
54
54
  var _api$primaryToolbar;
55
55
  api === null || api === void 0 ? void 0 : (_api$primaryToolbar = api.primaryToolbar) === null || _api$primaryToolbar === void 0 ? void 0 : _api$primaryToolbar.actions.registerComponent({
@@ -1,10 +1,43 @@
1
1
  import { useIntl } from 'react-intl';
2
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
3
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
3
4
  import { toggleBold, toggleCode, toggleItalic, toggleStrikethrough, toggleSubscript, toggleSuperscript, toggleUnderline, tooltip } from '@atlaskit/editor-common/keymaps';
4
5
  import { toolbarMessages } from '@atlaskit/editor-common/messages';
5
6
  import { BOLD_MENU_ITEM, CODE_MENU_ITEM, ITALIC_MENU_ITEM, STRIKE_MENU_ITEM, SUBSCRIPT_MENU_ITEM, SUPERSCRIPT_MENU_ITEM, TEXT_FORMATTING_MENU_SECTION_RANK, UNDERLINE_MENU_ITEM, getInputMethodFromParentKeys } from '@atlaskit/editor-common/toolbar';
6
7
  import { BoldIcon, ItalicIcon, UnderlineIcon, CodeIcon, StrikeThroughIcon, SubscriptIcon, SuperscriptIcon } from '@atlaskit/editor-toolbar';
8
+ import { fg } from '@atlaskit/platform-feature-flags';
9
+ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
7
10
  import { toggleStrongWithAnalytics, toggleEmWithAnalytics, toggleUnderlineWithAnalytics, toggleCodeWithAnalytics, toggleStrikeWithAnalytics, toggleSubscriptWithAnalytics, toggleSuperscriptWithAnalytics } from '../../../editor-commands/toggle-mark';
11
+
12
+ /**
13
+ * Local copy of `@atlassian/editor-plugin-markdown-mode/source-view-utils`'s
14
+ * `SourceViewInlineFormat` union. Kept here so this `@atlaskit/`-published
15
+ * package doesn't depend on the `@atlassian/`-namespaced source-view-utils
16
+ * subpath for type resolution. Must stay in sync with the source-of-truth
17
+ * declaration in markdown-mode.
18
+ */
19
+
20
+ /**
21
+ * Maps the text-formatting plugin's `FormatOptions` keys to their
22
+ * `SourceViewInlineFormat` equivalents for the CM6 source view.
23
+ * Only formats that have a markdown syntax equivalent are included —
24
+ * underline, subscript, and superscript have no GFM equivalent and
25
+ * are left as undefined (they remain PM-only).
26
+ */
27
+ const FORMAT_OPTION_TO_SOURCE_VIEW = {
28
+ strong: 'bold',
29
+ em: 'italic',
30
+ code: 'inlineCode',
31
+ strike: 'strikethrough'
32
+ };
33
+ const SOURCE_VIEW_ANALYTICS_ACTION_SUBJECT_ID = {
34
+ bold: ACTION_SUBJECT_ID.FORMAT_STRONG,
35
+ italic: ACTION_SUBJECT_ID.FORMAT_ITALIC,
36
+ inlineCode: ACTION_SUBJECT_ID.FORMAT_CODE,
37
+ strikethrough: ACTION_SUBJECT_ID.FORMAT_STRIKE
38
+ };
39
+ const TEXT_FORMATTING_PLUGIN_STATE_KEYS = ['textFormatting'];
40
+ const TEXT_FORMATTING_MARKDOWN_PLUGIN_STATE_KEYS = ['textFormatting', 'markdownMode'];
8
41
  const FormatMarkSchema = {
9
42
  strong: 'strong',
10
43
  em: 'em',
@@ -23,18 +56,24 @@ export const useComponentInfo = ({
23
56
  parents
24
57
  }) => {
25
58
  var _api$core, _api$core$sharedState, _api$core$sharedState2;
59
+ const isMarkdownBridgeEnabled = expValEqualsNoExposure('cc-markdown-mode', 'isEnabled', true) && fg('platform_editor_markdown_compatible_toolbar');
60
+ const pluginStateKeys = isMarkdownBridgeEnabled ? TEXT_FORMATTING_MARKDOWN_PLUGIN_STATE_KEYS : TEXT_FORMATTING_PLUGIN_STATE_KEYS;
26
61
  const {
27
62
  isActive,
28
63
  isDisabled,
29
64
  isHidden,
30
- isPluginInitialised
31
- } = useSharedPluginStateWithSelector(api, ['textFormatting'], states => {
32
- var _states$textFormattin, _states$textFormattin2, _states$textFormattin3, _states$textFormattin4;
65
+ isPluginInitialised,
66
+ markdownModeView,
67
+ sourceFormatState
68
+ } = useSharedPluginStateWithSelector(api, pluginStateKeys, states => {
69
+ var _states$textFormattin, _states$textFormattin2, _states$textFormattin3, _states$textFormattin4, _states$markdownModeS, _states$markdownModeS2;
33
70
  return {
34
71
  isActive: (_states$textFormattin = states.textFormattingState) === null || _states$textFormattin === void 0 ? void 0 : _states$textFormattin[`${optionType}Active`],
35
72
  isDisabled: (_states$textFormattin2 = states.textFormattingState) === null || _states$textFormattin2 === void 0 ? void 0 : _states$textFormattin2[`${optionType}Disabled`],
36
73
  isHidden: (_states$textFormattin3 = states.textFormattingState) === null || _states$textFormattin3 === void 0 ? void 0 : _states$textFormattin3[`${optionType}Hidden`],
37
- isPluginInitialised: (_states$textFormattin4 = states.textFormattingState) === null || _states$textFormattin4 === void 0 ? void 0 : _states$textFormattin4.isInitialised
74
+ isPluginInitialised: (_states$textFormattin4 = states.textFormattingState) === null || _states$textFormattin4 === void 0 ? void 0 : _states$textFormattin4.isInitialised,
75
+ markdownModeView: isMarkdownBridgeEnabled ? (_states$markdownModeS = states.markdownModeState) === null || _states$markdownModeS === void 0 ? void 0 : _states$markdownModeS.view : undefined,
76
+ sourceFormatState: isMarkdownBridgeEnabled ? (_states$markdownModeS2 = states.markdownModeState) === null || _states$markdownModeS2 === void 0 ? void 0 : _states$markdownModeS2.sourceInlineFormatState : null
38
77
  };
39
78
  });
40
79
  const hasMarkSchema = api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : (_api$core$sharedState = _api$core.sharedState.currentState()) === null || _api$core$sharedState === void 0 ? void 0 : (_api$core$sharedState2 = _api$core$sharedState.schema) === null || _api$core$sharedState2 === void 0 ? void 0 : _api$core$sharedState2.marks[FormatMarkSchema[optionType]];
@@ -58,9 +97,89 @@ export const useComponentInfo = ({
58
97
  const formatTitle = formatMessage(title);
59
98
  const shortcutContent = tooltip(shortcut);
60
99
  const ariaLabel = tooltip(shortcut, formatTitle);
100
+
101
+ // The SourceViewInlineFormat key for this format option, if it has one.
102
+ // undefined for underline, subscript, superscript (no GFM equivalent).
103
+ const sourceViewFormat = FORMAT_OPTION_TO_SOURCE_VIEW[optionType];
104
+
105
+ // The CM6 source view is authoritative when the user has switched to it.
106
+ // We rely on `markdownModeState.view === 'syntax'` (synchronous, set on
107
+ // `setView`) rather than the presence of `sourceFormatState` — the latter
108
+ // is `null` until the CM6 update listener fires for the first time, so
109
+ // using it as the sentinel would let the first toolbar click after entering
110
+ // source view fall through to the PM path and mutate the hidden PM doc.
111
+ const isInSourceView = markdownModeView === 'syntax';
112
+ if (isInSourceView && !sourceViewFormat) {
113
+ // Underline, subscript, superscript have no GFM equivalent. Disable
114
+ // them immediately on entering source view — independent of whether
115
+ // the CM6 update listener has fired yet — so the buttons don't briefly
116
+ // appear active/enabled during that race window.
117
+ formatOptionState = {
118
+ isActive: false,
119
+ isDisabled: true,
120
+ isHidden: false
121
+ };
122
+ } else if (isInSourceView && sourceFormatState && sourceViewFormat) {
123
+ // Map each SourceViewInlineFormat to its isActive field on the snapshot.
124
+ const activeByFormat = {
125
+ bold: sourceFormatState.boldActive,
126
+ italic: sourceFormatState.italicActive,
127
+ inlineCode: sourceFormatState.codeActive,
128
+ strikethrough: sourceFormatState.strikeActive
129
+ };
130
+ formatOptionState = {
131
+ isActive: activeByFormat[sourceViewFormat],
132
+ isDisabled: !sourceFormatState.inlineFormattingAvailable,
133
+ isHidden: false
134
+ };
135
+ } else if (isInSourceView) {
136
+ // Race window: the user has switched to source view but the CM6 update
137
+ // listener hasn't pushed its first format state snapshot yet
138
+ // (`sourceFormatState` is still `null`). Without this branch the
139
+ // button would render stale PM-cursor state (e.g. "Bold active" based
140
+ // on where the PM selection was) until CM6 catches up. Render a
141
+ // neutral, non-disabled state instead.
142
+ formatOptionState = {
143
+ isActive: false,
144
+ isDisabled: false,
145
+ isHidden: false
146
+ };
147
+ }
61
148
  const onClick = () => {
62
- var _api$analytics;
63
- api === null || api === void 0 ? void 0 : api.core.actions.execute(toggleMarkWithAnalyticsCallback(api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions)(getInputMethodFromParentKeys(parents)));
149
+ var _api$markdownMode, _api$markdownMode2, _api$markdownMode3, _api$markdownMode4, _api$analytics2;
150
+ // Route to CM6 when in source view and the format has a CM6 equivalent.
151
+ if (isInSourceView) {
152
+ if (sourceViewFormat) {
153
+ var _api$analytics;
154
+ api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.fireAnalyticsEvent({
155
+ action: ACTION.FORMATTED,
156
+ actionSubject: ACTION_SUBJECT.TEXT,
157
+ eventType: EVENT_TYPE.TRACK,
158
+ actionSubjectId: SOURCE_VIEW_ANALYTICS_ACTION_SUBJECT_ID[sourceViewFormat],
159
+ attributes: {
160
+ inputMethod: getInputMethodFromParentKeys(parents)
161
+ }
162
+ });
163
+ switch (sourceViewFormat) {
164
+ case 'bold':
165
+ api === null || api === void 0 ? void 0 : (_api$markdownMode = api.markdownMode) === null || _api$markdownMode === void 0 ? void 0 : _api$markdownMode.actions.toggleSourceBold();
166
+ break;
167
+ case 'italic':
168
+ api === null || api === void 0 ? void 0 : (_api$markdownMode2 = api.markdownMode) === null || _api$markdownMode2 === void 0 ? void 0 : _api$markdownMode2.actions.toggleSourceItalic();
169
+ break;
170
+ case 'inlineCode':
171
+ api === null || api === void 0 ? void 0 : (_api$markdownMode3 = api.markdownMode) === null || _api$markdownMode3 === void 0 ? void 0 : _api$markdownMode3.actions.toggleSourceInlineCode();
172
+ break;
173
+ case 'strikethrough':
174
+ api === null || api === void 0 ? void 0 : (_api$markdownMode4 = api.markdownMode) === null || _api$markdownMode4 === void 0 ? void 0 : _api$markdownMode4.actions.toggleSourceStrike();
175
+ break;
176
+ }
177
+ }
178
+ return;
179
+ }
180
+
181
+ // Default PM path.
182
+ api === null || api === void 0 ? void 0 : api.core.actions.execute(toggleMarkWithAnalyticsCallback(api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions)(getInputMethodFromParentKeys(parents)));
64
183
  };
65
184
  return {
66
185
  ...formatOptionState,
@@ -3,6 +3,6 @@ import { textFormattingGroupForInlineToolbar } from './Toolbar/components/TextFo
3
3
  import { textFormattingGroupForPrimaryToolbar } from './Toolbar/components/TextFormattingGroups';
4
4
  import { textFormattingMenuGroup } from './Toolbar/components/TextFormattingMenuGroup';
5
5
  import { underlineButtonGroup } from './Toolbar/components/UnderlineButtonGroup';
6
- export const getToolbarComponents = api => {
7
- return [...textFormattingGroupForPrimaryToolbar(api), ...textFormattingGroupForInlineToolbar(api), ...boldButtonGroup(api), ...underlineButtonGroup(api), ...textFormattingMenuGroup(api)];
6
+ export const getToolbarComponents = (api, options) => {
7
+ return [...textFormattingGroupForPrimaryToolbar(api), ...textFormattingGroupForInlineToolbar(api), ...boldButtonGroup(api), ...(options !== null && options !== void 0 && options.disableUnderline ? [] : underlineButtonGroup(api)), ...textFormattingMenuGroup(api)];
8
8
  };
@@ -50,7 +50,7 @@ export var textFormattingPlugin = function textFormattingPlugin(_ref) {
50
50
  };
51
51
  if (isToolbarAIFCEnabled) {
52
52
  var _api$toolbar;
53
- api === null || api === void 0 || (_api$toolbar = api.toolbar) === null || _api$toolbar === void 0 || _api$toolbar.actions.registerComponents(getToolbarComponents(api));
53
+ api === null || api === void 0 || (_api$toolbar = api.toolbar) === null || _api$toolbar === void 0 || _api$toolbar.actions.registerComponents(getToolbarComponents(api, options));
54
54
  } else {
55
55
  var _api$primaryToolbar;
56
56
  api === null || api === void 0 || (_api$primaryToolbar = api.primaryToolbar) === null || _api$primaryToolbar === void 0 || _api$primaryToolbar.actions.registerComponent({
@@ -2,12 +2,45 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  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; }
3
3
  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) { _defineProperty(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; }
4
4
  import { useIntl } from 'react-intl';
5
+ import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
5
6
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
6
7
  import { toggleBold, toggleCode, toggleItalic, toggleStrikethrough, toggleSubscript, toggleSuperscript, toggleUnderline, tooltip } from '@atlaskit/editor-common/keymaps';
7
8
  import { toolbarMessages } from '@atlaskit/editor-common/messages';
8
9
  import { BOLD_MENU_ITEM, CODE_MENU_ITEM, ITALIC_MENU_ITEM, STRIKE_MENU_ITEM, SUBSCRIPT_MENU_ITEM, SUPERSCRIPT_MENU_ITEM, TEXT_FORMATTING_MENU_SECTION_RANK, UNDERLINE_MENU_ITEM, getInputMethodFromParentKeys } from '@atlaskit/editor-common/toolbar';
9
10
  import { BoldIcon, ItalicIcon, UnderlineIcon, CodeIcon, StrikeThroughIcon, SubscriptIcon, SuperscriptIcon } from '@atlaskit/editor-toolbar';
11
+ import { fg } from '@atlaskit/platform-feature-flags';
12
+ import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
10
13
  import { toggleStrongWithAnalytics, toggleEmWithAnalytics, toggleUnderlineWithAnalytics, toggleCodeWithAnalytics, toggleStrikeWithAnalytics, toggleSubscriptWithAnalytics, toggleSuperscriptWithAnalytics } from '../../../editor-commands/toggle-mark';
14
+
15
+ /**
16
+ * Local copy of `@atlassian/editor-plugin-markdown-mode/source-view-utils`'s
17
+ * `SourceViewInlineFormat` union. Kept here so this `@atlaskit/`-published
18
+ * package doesn't depend on the `@atlassian/`-namespaced source-view-utils
19
+ * subpath for type resolution. Must stay in sync with the source-of-truth
20
+ * declaration in markdown-mode.
21
+ */
22
+
23
+ /**
24
+ * Maps the text-formatting plugin's `FormatOptions` keys to their
25
+ * `SourceViewInlineFormat` equivalents for the CM6 source view.
26
+ * Only formats that have a markdown syntax equivalent are included —
27
+ * underline, subscript, and superscript have no GFM equivalent and
28
+ * are left as undefined (they remain PM-only).
29
+ */
30
+ var FORMAT_OPTION_TO_SOURCE_VIEW = {
31
+ strong: 'bold',
32
+ em: 'italic',
33
+ code: 'inlineCode',
34
+ strike: 'strikethrough'
35
+ };
36
+ var SOURCE_VIEW_ANALYTICS_ACTION_SUBJECT_ID = {
37
+ bold: ACTION_SUBJECT_ID.FORMAT_STRONG,
38
+ italic: ACTION_SUBJECT_ID.FORMAT_ITALIC,
39
+ inlineCode: ACTION_SUBJECT_ID.FORMAT_CODE,
40
+ strikethrough: ACTION_SUBJECT_ID.FORMAT_STRIKE
41
+ };
42
+ var TEXT_FORMATTING_PLUGIN_STATE_KEYS = ['textFormatting'];
43
+ var TEXT_FORMATTING_MARKDOWN_PLUGIN_STATE_KEYS = ['textFormatting', 'markdownMode'];
11
44
  var FormatMarkSchema = {
12
45
  strong: 'strong',
13
46
  em: 'em',
@@ -25,19 +58,25 @@ export var useComponentInfo = function useComponentInfo(_ref) {
25
58
  shortcut = _ref.shortcut,
26
59
  toggleMarkWithAnalyticsCallback = _ref.toggleMarkWithAnalyticsCallback,
27
60
  parents = _ref.parents;
28
- var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['textFormatting'], function (states) {
29
- var _states$textFormattin, _states$textFormattin2, _states$textFormattin3, _states$textFormattin4;
61
+ var isMarkdownBridgeEnabled = expValEqualsNoExposure('cc-markdown-mode', 'isEnabled', true) && fg('platform_editor_markdown_compatible_toolbar');
62
+ var pluginStateKeys = isMarkdownBridgeEnabled ? TEXT_FORMATTING_MARKDOWN_PLUGIN_STATE_KEYS : TEXT_FORMATTING_PLUGIN_STATE_KEYS;
63
+ var _useSharedPluginState = useSharedPluginStateWithSelector(api, pluginStateKeys, function (states) {
64
+ var _states$textFormattin, _states$textFormattin2, _states$textFormattin3, _states$textFormattin4, _states$markdownModeS, _states$markdownModeS2;
30
65
  return {
31
66
  isActive: (_states$textFormattin = states.textFormattingState) === null || _states$textFormattin === void 0 ? void 0 : _states$textFormattin["".concat(optionType, "Active")],
32
67
  isDisabled: (_states$textFormattin2 = states.textFormattingState) === null || _states$textFormattin2 === void 0 ? void 0 : _states$textFormattin2["".concat(optionType, "Disabled")],
33
68
  isHidden: (_states$textFormattin3 = states.textFormattingState) === null || _states$textFormattin3 === void 0 ? void 0 : _states$textFormattin3["".concat(optionType, "Hidden")],
34
- isPluginInitialised: (_states$textFormattin4 = states.textFormattingState) === null || _states$textFormattin4 === void 0 ? void 0 : _states$textFormattin4.isInitialised
69
+ isPluginInitialised: (_states$textFormattin4 = states.textFormattingState) === null || _states$textFormattin4 === void 0 ? void 0 : _states$textFormattin4.isInitialised,
70
+ markdownModeView: isMarkdownBridgeEnabled ? (_states$markdownModeS = states.markdownModeState) === null || _states$markdownModeS === void 0 ? void 0 : _states$markdownModeS.view : undefined,
71
+ sourceFormatState: isMarkdownBridgeEnabled ? (_states$markdownModeS2 = states.markdownModeState) === null || _states$markdownModeS2 === void 0 ? void 0 : _states$markdownModeS2.sourceInlineFormatState : null
35
72
  };
36
73
  }),
37
74
  isActive = _useSharedPluginState.isActive,
38
75
  isDisabled = _useSharedPluginState.isDisabled,
39
76
  isHidden = _useSharedPluginState.isHidden,
40
- isPluginInitialised = _useSharedPluginState.isPluginInitialised;
77
+ isPluginInitialised = _useSharedPluginState.isPluginInitialised,
78
+ markdownModeView = _useSharedPluginState.markdownModeView,
79
+ sourceFormatState = _useSharedPluginState.sourceFormatState;
41
80
  var hasMarkSchema = api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || (_api$core = _api$core.sharedState.currentState()) === null || _api$core === void 0 || (_api$core = _api$core.schema) === null || _api$core === void 0 ? void 0 : _api$core.marks[FormatMarkSchema[optionType]];
42
81
  var formatOptionState;
43
82
  if (!isPluginInitialised) {
@@ -58,9 +97,89 @@ export var useComponentInfo = function useComponentInfo(_ref) {
58
97
  var formatTitle = formatMessage(title);
59
98
  var shortcutContent = tooltip(shortcut);
60
99
  var ariaLabel = tooltip(shortcut, formatTitle);
100
+
101
+ // The SourceViewInlineFormat key for this format option, if it has one.
102
+ // undefined for underline, subscript, superscript (no GFM equivalent).
103
+ var sourceViewFormat = FORMAT_OPTION_TO_SOURCE_VIEW[optionType];
104
+
105
+ // The CM6 source view is authoritative when the user has switched to it.
106
+ // We rely on `markdownModeState.view === 'syntax'` (synchronous, set on
107
+ // `setView`) rather than the presence of `sourceFormatState` — the latter
108
+ // is `null` until the CM6 update listener fires for the first time, so
109
+ // using it as the sentinel would let the first toolbar click after entering
110
+ // source view fall through to the PM path and mutate the hidden PM doc.
111
+ var isInSourceView = markdownModeView === 'syntax';
112
+ if (isInSourceView && !sourceViewFormat) {
113
+ // Underline, subscript, superscript have no GFM equivalent. Disable
114
+ // them immediately on entering source view — independent of whether
115
+ // the CM6 update listener has fired yet — so the buttons don't briefly
116
+ // appear active/enabled during that race window.
117
+ formatOptionState = {
118
+ isActive: false,
119
+ isDisabled: true,
120
+ isHidden: false
121
+ };
122
+ } else if (isInSourceView && sourceFormatState && sourceViewFormat) {
123
+ // Map each SourceViewInlineFormat to its isActive field on the snapshot.
124
+ var activeByFormat = {
125
+ bold: sourceFormatState.boldActive,
126
+ italic: sourceFormatState.italicActive,
127
+ inlineCode: sourceFormatState.codeActive,
128
+ strikethrough: sourceFormatState.strikeActive
129
+ };
130
+ formatOptionState = {
131
+ isActive: activeByFormat[sourceViewFormat],
132
+ isDisabled: !sourceFormatState.inlineFormattingAvailable,
133
+ isHidden: false
134
+ };
135
+ } else if (isInSourceView) {
136
+ // Race window: the user has switched to source view but the CM6 update
137
+ // listener hasn't pushed its first format state snapshot yet
138
+ // (`sourceFormatState` is still `null`). Without this branch the
139
+ // button would render stale PM-cursor state (e.g. "Bold active" based
140
+ // on where the PM selection was) until CM6 catches up. Render a
141
+ // neutral, non-disabled state instead.
142
+ formatOptionState = {
143
+ isActive: false,
144
+ isDisabled: false,
145
+ isHidden: false
146
+ };
147
+ }
61
148
  var onClick = function onClick() {
62
- var _api$analytics;
63
- api === null || api === void 0 || api.core.actions.execute(toggleMarkWithAnalyticsCallback(api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions)(getInputMethodFromParentKeys(parents)));
149
+ var _api$markdownMode, _api$markdownMode2, _api$markdownMode3, _api$markdownMode4, _api$analytics2;
150
+ // Route to CM6 when in source view and the format has a CM6 equivalent.
151
+ if (isInSourceView) {
152
+ if (sourceViewFormat) {
153
+ var _api$analytics;
154
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.fireAnalyticsEvent({
155
+ action: ACTION.FORMATTED,
156
+ actionSubject: ACTION_SUBJECT.TEXT,
157
+ eventType: EVENT_TYPE.TRACK,
158
+ actionSubjectId: SOURCE_VIEW_ANALYTICS_ACTION_SUBJECT_ID[sourceViewFormat],
159
+ attributes: {
160
+ inputMethod: getInputMethodFromParentKeys(parents)
161
+ }
162
+ });
163
+ switch (sourceViewFormat) {
164
+ case 'bold':
165
+ api === null || api === void 0 || (_api$markdownMode = api.markdownMode) === null || _api$markdownMode === void 0 || _api$markdownMode.actions.toggleSourceBold();
166
+ break;
167
+ case 'italic':
168
+ api === null || api === void 0 || (_api$markdownMode2 = api.markdownMode) === null || _api$markdownMode2 === void 0 || _api$markdownMode2.actions.toggleSourceItalic();
169
+ break;
170
+ case 'inlineCode':
171
+ api === null || api === void 0 || (_api$markdownMode3 = api.markdownMode) === null || _api$markdownMode3 === void 0 || _api$markdownMode3.actions.toggleSourceInlineCode();
172
+ break;
173
+ case 'strikethrough':
174
+ api === null || api === void 0 || (_api$markdownMode4 = api.markdownMode) === null || _api$markdownMode4 === void 0 || _api$markdownMode4.actions.toggleSourceStrike();
175
+ break;
176
+ }
177
+ }
178
+ return;
179
+ }
180
+
181
+ // Default PM path.
182
+ api === null || api === void 0 || api.core.actions.execute(toggleMarkWithAnalyticsCallback(api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions)(getInputMethodFromParentKeys(parents)));
64
183
  };
65
184
  return _objectSpread(_objectSpread({}, formatOptionState), {}, {
66
185
  formatTitle: formatTitle,
@@ -4,6 +4,6 @@ import { textFormattingGroupForInlineToolbar } from './Toolbar/components/TextFo
4
4
  import { textFormattingGroupForPrimaryToolbar } from './Toolbar/components/TextFormattingGroups';
5
5
  import { textFormattingMenuGroup } from './Toolbar/components/TextFormattingMenuGroup';
6
6
  import { underlineButtonGroup } from './Toolbar/components/UnderlineButtonGroup';
7
- export var getToolbarComponents = function getToolbarComponents(api) {
8
- return [].concat(_toConsumableArray(textFormattingGroupForPrimaryToolbar(api)), _toConsumableArray(textFormattingGroupForInlineToolbar(api)), _toConsumableArray(boldButtonGroup(api)), _toConsumableArray(underlineButtonGroup(api)), _toConsumableArray(textFormattingMenuGroup(api)));
7
+ export var getToolbarComponents = function getToolbarComponents(api, options) {
8
+ return [].concat(_toConsumableArray(textFormattingGroupForPrimaryToolbar(api)), _toConsumableArray(textFormattingGroupForInlineToolbar(api)), _toConsumableArray(boldButtonGroup(api)), _toConsumableArray(options !== null && options !== void 0 && options.disableUnderline ? [] : underlineButtonGroup(api)), _toConsumableArray(textFormattingMenuGroup(api)));
9
9
  };
@@ -7,6 +7,43 @@ import type { ToolbarPlugin } from '@atlaskit/editor-plugin-toolbar';
7
7
  import type { UserPreferencesPlugin } from '@atlaskit/editor-plugin-user-preferences';
8
8
  import type { ToggleMarkEditorCommand } from './editor-commands/types';
9
9
  export type TextFormattingPluginOptions = CommonTextFormattingOptions;
10
+ /**
11
+ * Minimal duck-typed slice of `@atlassian/editor-plugin-markdown-mode`'s
12
+ * `MarkdownModePlugin` covering only the surface this plugin uses (inline
13
+ * source-view toggle actions + the inline format-state + `view` fields).
14
+ *
15
+ * We avoid importing the real type because `@atlaskit/editor-plugin-text-formatting`
16
+ * publishes to public npm while `@atlassian/editor-plugin-markdown-mode` only
17
+ * publishes to Atlassian's internal registry — re-exporting the cross-namespace
18
+ * type in this package's `.d.ts` would leave the type unresolvable for external
19
+ * consumers. TS structural typing means the real plugin (when loaded by the host)
20
+ * satisfies this stub, so runtime calls are still type-correct.
21
+ *
22
+ * Maintenance: this stub is NOT compile-time checked against the source-of-truth
23
+ * `MarkdownModePlugin` type. If markdown-mode renames, removes, or changes the
24
+ * signature of any of the actions/shared-state fields listed below, the mismatch
25
+ * surfaces only at runtime (stale toolbar state, no-op clicks). Keep the action
26
+ * signatures and `sharedState` fields here in sync with
27
+ * `@atlassian/editor-plugin-markdown-mode/src/markdownModePluginType.ts`.
28
+ */
29
+ type _MarkdownModePluginStub = NextEditorPlugin<'markdownMode', {
30
+ actions: {
31
+ toggleSourceBold: () => boolean;
32
+ toggleSourceInlineCode: () => boolean;
33
+ toggleSourceItalic: () => boolean;
34
+ toggleSourceStrike: () => boolean;
35
+ };
36
+ sharedState: {
37
+ sourceInlineFormatState: {
38
+ boldActive: boolean;
39
+ codeActive: boolean;
40
+ inlineFormattingAvailable: boolean;
41
+ italicActive: boolean;
42
+ strikeActive: boolean;
43
+ } | null;
44
+ view: 'syntax' | 'split-view' | 'preview';
45
+ } | undefined;
46
+ }>;
10
47
  export type TextFormattingPlugin = NextEditorPlugin<'textFormatting', {
11
48
  commands: {
12
49
  toggleCode: ToggleMarkEditorCommand;
@@ -23,8 +60,10 @@ export type TextFormattingPlugin = NextEditorPlugin<'textFormatting', {
23
60
  OptionalPlugin<BasePlugin>,
24
61
  OptionalPlugin<SelectionToolbarPlugin>,
25
62
  OptionalPlugin<UserPreferencesPlugin>,
26
- OptionalPlugin<ToolbarPlugin>
63
+ OptionalPlugin<ToolbarPlugin>,
64
+ OptionalPlugin<_MarkdownModePluginStub>
27
65
  ];
28
66
  pluginConfiguration: TextFormattingPluginOptions | undefined;
29
67
  sharedState: TextFormattingState | undefined;
30
68
  }>;
69
+ export {};
@@ -1,4 +1,4 @@
1
1
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
2
  import type { RegisterComponent } from '@atlaskit/editor-toolbar-model';
3
- import type { TextFormattingPlugin } from '../textFormattingPluginType';
4
- export declare const getToolbarComponents: (api?: ExtractInjectionAPI<TextFormattingPlugin>) => RegisterComponent[];
3
+ import type { TextFormattingPlugin, TextFormattingPluginOptions } from '../textFormattingPluginType';
4
+ export declare const getToolbarComponents: (api?: ExtractInjectionAPI<TextFormattingPlugin>, options?: TextFormattingPluginOptions) => RegisterComponent[];
@@ -7,6 +7,43 @@ import type { ToolbarPlugin } from '@atlaskit/editor-plugin-toolbar';
7
7
  import type { UserPreferencesPlugin } from '@atlaskit/editor-plugin-user-preferences';
8
8
  import type { ToggleMarkEditorCommand } from './editor-commands/types';
9
9
  export type TextFormattingPluginOptions = CommonTextFormattingOptions;
10
+ /**
11
+ * Minimal duck-typed slice of `@atlassian/editor-plugin-markdown-mode`'s
12
+ * `MarkdownModePlugin` covering only the surface this plugin uses (inline
13
+ * source-view toggle actions + the inline format-state + `view` fields).
14
+ *
15
+ * We avoid importing the real type because `@atlaskit/editor-plugin-text-formatting`
16
+ * publishes to public npm while `@atlassian/editor-plugin-markdown-mode` only
17
+ * publishes to Atlassian's internal registry — re-exporting the cross-namespace
18
+ * type in this package's `.d.ts` would leave the type unresolvable for external
19
+ * consumers. TS structural typing means the real plugin (when loaded by the host)
20
+ * satisfies this stub, so runtime calls are still type-correct.
21
+ *
22
+ * Maintenance: this stub is NOT compile-time checked against the source-of-truth
23
+ * `MarkdownModePlugin` type. If markdown-mode renames, removes, or changes the
24
+ * signature of any of the actions/shared-state fields listed below, the mismatch
25
+ * surfaces only at runtime (stale toolbar state, no-op clicks). Keep the action
26
+ * signatures and `sharedState` fields here in sync with
27
+ * `@atlassian/editor-plugin-markdown-mode/src/markdownModePluginType.ts`.
28
+ */
29
+ type _MarkdownModePluginStub = NextEditorPlugin<'markdownMode', {
30
+ actions: {
31
+ toggleSourceBold: () => boolean;
32
+ toggleSourceInlineCode: () => boolean;
33
+ toggleSourceItalic: () => boolean;
34
+ toggleSourceStrike: () => boolean;
35
+ };
36
+ sharedState: {
37
+ sourceInlineFormatState: {
38
+ boldActive: boolean;
39
+ codeActive: boolean;
40
+ inlineFormattingAvailable: boolean;
41
+ italicActive: boolean;
42
+ strikeActive: boolean;
43
+ } | null;
44
+ view: 'syntax' | 'split-view' | 'preview';
45
+ } | undefined;
46
+ }>;
10
47
  export type TextFormattingPlugin = NextEditorPlugin<'textFormatting', {
11
48
  commands: {
12
49
  toggleCode: ToggleMarkEditorCommand;
@@ -23,8 +60,10 @@ export type TextFormattingPlugin = NextEditorPlugin<'textFormatting', {
23
60
  OptionalPlugin<BasePlugin>,
24
61
  OptionalPlugin<SelectionToolbarPlugin>,
25
62
  OptionalPlugin<UserPreferencesPlugin>,
26
- OptionalPlugin<ToolbarPlugin>
63
+ OptionalPlugin<ToolbarPlugin>,
64
+ OptionalPlugin<_MarkdownModePluginStub>
27
65
  ];
28
66
  pluginConfiguration: TextFormattingPluginOptions | undefined;
29
67
  sharedState: TextFormattingState | undefined;
30
68
  }>;
69
+ export {};
@@ -1,4 +1,4 @@
1
1
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
2
2
  import type { RegisterComponent } from '@atlaskit/editor-toolbar-model';
3
- import type { TextFormattingPlugin } from '../textFormattingPluginType';
4
- export declare const getToolbarComponents: (api?: ExtractInjectionAPI<TextFormattingPlugin>) => RegisterComponent[];
3
+ import type { TextFormattingPlugin, TextFormattingPluginOptions } from '../textFormattingPluginType';
4
+ export declare const getToolbarComponents: (api?: ExtractInjectionAPI<TextFormattingPlugin>, options?: TextFormattingPluginOptions) => RegisterComponent[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-text-formatting",
3
- "version": "10.1.6",
3
+ "version": "10.2.1",
4
4
  "description": "Text-formatting plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -32,7 +32,7 @@
32
32
  ],
33
33
  "atlaskit:src": "src/index.ts",
34
34
  "dependencies": {
35
- "@atlaskit/adf-schema": "^52.14.0",
35
+ "@atlaskit/adf-schema": "^52.15.0",
36
36
  "@atlaskit/editor-plugin-analytics": "^10.1.0",
37
37
  "@atlaskit/editor-plugin-base": "^11.1.0",
38
38
  "@atlaskit/editor-plugin-primary-toolbar": "^11.1.0",
@@ -41,18 +41,18 @@
41
41
  "@atlaskit/editor-prosemirror": "^7.3.0",
42
42
  "@atlaskit/editor-shared-styles": "^3.11.0",
43
43
  "@atlaskit/editor-tables": "^2.10.0",
44
- "@atlaskit/editor-toolbar": "^1.7.0",
44
+ "@atlaskit/editor-toolbar": "^1.8.0",
45
45
  "@atlaskit/editor-toolbar-model": "^0.5.0",
46
46
  "@atlaskit/icon": "^35.3.0",
47
47
  "@atlaskit/platform-feature-flags": "^1.1.0",
48
48
  "@atlaskit/prosemirror-input-rules": "^3.7.0",
49
- "@atlaskit/tmp-editor-statsig": "^84.0.0",
50
- "@atlaskit/tokens": "^13.0.0",
49
+ "@atlaskit/tmp-editor-statsig": "^85.0.0",
50
+ "@atlaskit/tokens": "^13.1.0",
51
51
  "@babel/runtime": "^7.0.0",
52
52
  "@emotion/react": "^11.7.1"
53
53
  },
54
54
  "peerDependencies": {
55
- "@atlaskit/editor-common": "^114.47.0",
55
+ "@atlaskit/editor-common": "^114.50.0",
56
56
  "react": "^18.2.0",
57
57
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
58
58
  },
@@ -106,6 +106,9 @@
106
106
  },
107
107
  "platform_editor_use_preferences_plugin": {
108
108
  "type": "boolean"
109
+ },
110
+ "platform_editor_markdown_compatible_toolbar": {
111
+ "type": "boolean"
109
112
  }
110
113
  }
111
114
  }