@atlaskit/editor-plugin-block-type 4.0.13 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/blockTypePlugin.js +3 -0
  3. package/dist/cjs/pm-plugins/block-types.js +3 -1
  4. package/dist/cjs/pm-plugins/commands/block-type.js +65 -11
  5. package/dist/cjs/pm-plugins/commands/clear-formatting.js +58 -0
  6. package/dist/cjs/pm-plugins/input-rule.js +18 -2
  7. package/dist/cjs/pm-plugins/keymap.js +26 -2
  8. package/dist/cjs/pm-plugins/main.js +14 -4
  9. package/dist/cjs/pm-plugins/ui/FloatingToolbarComponent.js +9 -1
  10. package/dist/cjs/pm-plugins/ui/PrimaryToolbarComponent.js +8 -0
  11. package/dist/cjs/pm-plugins/ui/ToolbarBlockType/blocktype-button.js +4 -1
  12. package/dist/cjs/pm-plugins/ui/ToolbarBlockType/index.js +83 -46
  13. package/dist/cjs/pm-plugins/ui/ToolbarBlockType/styled.js +15 -1
  14. package/dist/cjs/pm-plugins/utils.js +61 -7
  15. package/dist/es2019/blockTypePlugin.js +4 -1
  16. package/dist/es2019/pm-plugins/block-types.js +2 -0
  17. package/dist/es2019/pm-plugins/commands/block-type.js +57 -2
  18. package/dist/es2019/pm-plugins/commands/clear-formatting.js +50 -0
  19. package/dist/es2019/pm-plugins/input-rule.js +18 -2
  20. package/dist/es2019/pm-plugins/keymap.js +25 -2
  21. package/dist/es2019/pm-plugins/main.js +15 -5
  22. package/dist/es2019/pm-plugins/ui/FloatingToolbarComponent.js +9 -1
  23. package/dist/es2019/pm-plugins/ui/PrimaryToolbarComponent.js +8 -0
  24. package/dist/es2019/pm-plugins/ui/ToolbarBlockType/blocktype-button.js +4 -1
  25. package/dist/es2019/pm-plugins/ui/ToolbarBlockType/index.js +84 -49
  26. package/dist/es2019/pm-plugins/ui/ToolbarBlockType/styled.js +14 -0
  27. package/dist/es2019/pm-plugins/utils.js +63 -7
  28. package/dist/esm/blockTypePlugin.js +4 -1
  29. package/dist/esm/pm-plugins/block-types.js +2 -0
  30. package/dist/esm/pm-plugins/commands/block-type.js +62 -10
  31. package/dist/esm/pm-plugins/commands/clear-formatting.js +50 -0
  32. package/dist/esm/pm-plugins/input-rule.js +18 -2
  33. package/dist/esm/pm-plugins/keymap.js +25 -2
  34. package/dist/esm/pm-plugins/main.js +15 -5
  35. package/dist/esm/pm-plugins/ui/FloatingToolbarComponent.js +9 -1
  36. package/dist/esm/pm-plugins/ui/PrimaryToolbarComponent.js +8 -0
  37. package/dist/esm/pm-plugins/ui/ToolbarBlockType/blocktype-button.js +4 -1
  38. package/dist/esm/pm-plugins/ui/ToolbarBlockType/index.js +85 -48
  39. package/dist/esm/pm-plugins/ui/ToolbarBlockType/styled.js +14 -0
  40. package/dist/esm/pm-plugins/utils.js +61 -7
  41. package/dist/types/blockTypePluginType.d.ts +1 -0
  42. package/dist/types/pm-plugins/block-types.d.ts +2 -0
  43. package/dist/types/pm-plugins/commands/block-type.d.ts +1 -0
  44. package/dist/types/pm-plugins/commands/clear-formatting.d.ts +8 -0
  45. package/dist/types/pm-plugins/main.d.ts +2 -7
  46. package/dist/types/pm-plugins/ui/ToolbarBlockType/index.d.ts +1 -0
  47. package/dist/types/pm-plugins/ui/ToolbarBlockType/styled.d.ts +1 -0
  48. package/dist/types/pm-plugins/utils.d.ts +3 -0
  49. package/dist/types-ts4.5/blockTypePluginType.d.ts +1 -0
  50. package/dist/types-ts4.5/pm-plugins/block-types.d.ts +2 -0
  51. package/dist/types-ts4.5/pm-plugins/commands/block-type.d.ts +1 -0
  52. package/dist/types-ts4.5/pm-plugins/commands/clear-formatting.d.ts +8 -0
  53. package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -7
  54. package/dist/types-ts4.5/pm-plugins/ui/ToolbarBlockType/index.d.ts +1 -0
  55. package/dist/types-ts4.5/pm-plugins/ui/ToolbarBlockType/styled.d.ts +1 -0
  56. package/dist/types-ts4.5/pm-plugins/utils.d.ts +3 -0
  57. package/package.json +3 -3
@@ -8,13 +8,16 @@ import React from 'react';
8
8
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
9
9
  import { jsx } from '@emotion/react';
10
10
  import { injectIntl } from 'react-intl-next';
11
- import { findKeymapByDescription, getAriaKeyshortcuts, tooltip } from '@atlaskit/editor-common/keymaps';
11
+ import { findKeymapByDescription, tooltip, clearFormatting } from '@atlaskit/editor-common/keymaps';
12
+ import { toolbarMessages } from '@atlaskit/editor-common/messages';
12
13
  import { separatorStyles, wrapperStyle } from '@atlaskit/editor-common/styles';
13
14
  import { DropdownMenuWithKeyboardNavigation as DropdownMenu } from '@atlaskit/editor-common/ui-menu';
14
15
  import { akEditorMenuZIndex } from '@atlaskit/editor-shared-styles';
16
+ import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
15
17
  import { ThemeMutationObserver } from '@atlaskit/tokens';
18
+ import { NORMAL_TEXT } from '../../block-types';
16
19
  import { BlockTypeButton } from './blocktype-button';
17
- import { blockTypeMenuItemStyle, keyboardShortcut, keyboardShortcutSelect } from './styled';
20
+ import { blockTypeMenuItemStyle, keyboardShortcut, keyboardShortcutSelect, floatingToolbarWrapperStyle } from './styled';
18
21
  // eslint-disable-next-line @repo/internal/react/no-class-components
19
22
  class ToolbarBlockType extends React.PureComponent {
20
23
  constructor(...args) {
@@ -56,23 +59,22 @@ class ToolbarBlockType extends React.PureComponent {
56
59
  } = this.props;
57
60
  const {
58
61
  currentBlockType,
59
- availableBlockTypesInDropdown
62
+ availableBlockTypesInDropdown,
63
+ formattingIsPresent
60
64
  } = this.props.pluginState;
61
65
  const items = availableBlockTypesInDropdown.map((blockType, index) => {
62
66
  const isActive = currentBlockType === blockType;
63
67
  const tagName = blockType.tagName || 'p';
64
68
  const Tag = tagName;
65
69
  const keyMap = findKeymapByDescription(blockType.title.defaultMessage);
66
- return {
70
+ const item = {
67
71
  content:
68
72
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
69
73
  jsx("div", {
70
74
  css: blockTypeMenuItemStyle(tagName, isActive, this.state.typographyTheme)
71
75
  }, jsx(Tag, null, formatMessage(blockType.title))),
72
76
  value: blockType,
73
- label: formatMessage(blockType.title),
74
77
  'aria-label': tooltip(keyMap, formatMessage(blockType.title)),
75
- keyShortcuts: getAriaKeyshortcuts(keyMap),
76
78
  key: `${blockType.name}-${index}`,
77
79
  elemAfter:
78
80
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
@@ -81,7 +83,30 @@ class ToolbarBlockType extends React.PureComponent {
81
83
  }, tooltip(keyMap)),
82
84
  isActive
83
85
  };
86
+ return item;
84
87
  });
88
+ if (availableBlockTypesInDropdown.map(blockType => blockType.name).includes('blockquote')) {
89
+ const clearFormattingItem = {
90
+ content: jsx("div", null, jsx("p", null, toolbarMessages.clearFormatting.defaultMessage)),
91
+ value: {
92
+ name: 'clearFormatting'
93
+ },
94
+ 'aria-label': tooltip(clearFormatting, toolbarMessages.clearFormatting.defaultMessage),
95
+ key: 'clear-formatting',
96
+ elemAfter:
97
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
98
+ jsx("div", {
99
+ css: [keyboardShortcut]
100
+ }, tooltip(clearFormatting)),
101
+ isActive: false,
102
+ isDisabled: currentBlockType === NORMAL_TEXT && !formattingIsPresent
103
+ };
104
+ return [{
105
+ items
106
+ }, {
107
+ items: [clearFormattingItem]
108
+ }];
109
+ }
85
110
  return [{
86
111
  items
87
112
  }];
@@ -94,8 +119,12 @@ class ToolbarBlockType extends React.PureComponent {
94
119
  if (blockType.name === 'blockquote') {
95
120
  this.props.wrapBlockQuote(blockType.name);
96
121
  } else {
97
- const fromBlockQuote = this.props.pluginState.currentBlockType.name === 'blockquote';
98
- this.props.setTextLevel(blockType.name, fromBlockQuote);
122
+ if (blockType.name === 'clearFormatting') {
123
+ this.props.clearFormatting();
124
+ } else {
125
+ const fromBlockQuote = this.props.pluginState.currentBlockType.name === 'blockquote';
126
+ this.props.setTextLevel(blockType.name, fromBlockQuote);
127
+ }
99
128
  }
100
129
  if (shouldCloseMenu) {
101
130
  this.setState({
@@ -152,50 +181,56 @@ class ToolbarBlockType extends React.PureComponent {
152
181
  return null;
153
182
  }
154
183
  const blockTypeTitles = availableBlockTypesInDropdown.filter(blockType => blockType.name === currentBlockType.name).map(blockType => blockType.title);
155
- if (!this.props.isDisabled && (!blockTypesDisabled || currentBlockType.name === 'blockquote')) {
184
+ if (!this.props.isDisabled && !blockTypesDisabled) {
156
185
  const items = this.createItems();
157
- return (
186
+ return jsx("span", {
187
+ css: editorExperiment('platform_editor_blockquote_in_text_formatting_menu', true) ?
188
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
189
+ [wrapperStyle, floatingToolbarWrapperStyle] :
158
190
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
159
- jsx("span", {
160
- css: wrapperStyle
161
- }, jsx(DropdownMenu, {
162
- items: items,
163
- onOpenChange: this.onOpenChange,
164
- onItemActivated: this.handleSelectBlockType,
165
- isOpen: active,
166
- mountTo: popupsMountPoint,
167
- boundariesElement: popupsBoundariesElement,
168
- scrollableElement: popupsScrollableElement,
169
- zIndex: akEditorMenuZIndex,
170
- fitHeight: 360,
171
- fitWidth: 106,
172
- shouldUseDefaultRole: shouldUseDefaultRole,
173
- shouldFocusFirstItem: () => {
174
- if (isOpenedByKeyboard) {
175
- // eslint-disable-next-line @repo/internal/react/no-set-state-inside-render
176
- this.setState({
177
- ...this.state,
178
- isOpenedByKeyboard: false
179
- });
180
- }
181
- return isOpenedByKeyboard;
191
+ wrapperStyle
192
+ }, jsx(DropdownMenu, {
193
+ items: items,
194
+ onOpenChange: this.onOpenChange,
195
+ onItemActivated: this.handleSelectBlockType,
196
+ isOpen: active,
197
+ mountTo: popupsMountPoint,
198
+ boundariesElement: popupsBoundariesElement,
199
+ scrollableElement: popupsScrollableElement,
200
+ zIndex: akEditorMenuZIndex,
201
+ fitHeight: 360,
202
+ fitWidth: 106,
203
+ section: {
204
+ hasSeparator: true
205
+ },
206
+ shouldUseDefaultRole: shouldUseDefaultRole
207
+ // hasSeparator={true}
208
+ ,
209
+ shouldFocusFirstItem: () => {
210
+ if (isOpenedByKeyboard) {
211
+ // eslint-disable-next-line @repo/internal/react/no-set-state-inside-render
212
+ this.setState({
213
+ ...this.state,
214
+ isOpenedByKeyboard: false
215
+ });
182
216
  }
183
- }, jsx(BlockTypeButton, {
184
- isSmall: isSmall,
185
- isReducedSpacing: isReducedSpacing,
186
- selected: active,
187
- disabled: false,
188
- title: blockTypeTitles[0],
189
- onClick: this.handleTriggerClick,
190
- onKeyDown: this.handleTriggerByKeyboard,
191
- formatMessage: formatMessage,
192
- "aria-expanded": active,
193
- blockTypeName: currentBlockType.name
194
- })), !(api !== null && api !== void 0 && api.primaryToolbar) && jsx("span", {
195
- // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
196
- css: separatorStyles
197
- }))
198
- );
217
+ return isOpenedByKeyboard;
218
+ }
219
+ }, jsx(BlockTypeButton, {
220
+ isSmall: isSmall,
221
+ isReducedSpacing: isReducedSpacing,
222
+ selected: active,
223
+ disabled: false,
224
+ title: blockTypeTitles[0],
225
+ onClick: this.handleTriggerClick,
226
+ onKeyDown: this.handleTriggerByKeyboard,
227
+ formatMessage: formatMessage,
228
+ "aria-expanded": active,
229
+ blockTypeName: currentBlockType.name
230
+ })), !(api !== null && api !== void 0 && api.primaryToolbar) && jsx("span", {
231
+ // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
232
+ css: separatorStyles
233
+ }));
199
234
  }
200
235
  return (
201
236
  // eslint-disable-next-line @atlaskit/design-system/consistent-css-prop-usage, @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766
@@ -18,6 +18,12 @@ export const blockTypeMenuItemStyle = (tagName, selected, typographyTheme) => {
18
18
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
19
19
  'h1, h2, h3, h4, h5, h6': {
20
20
  marginTop: 0
21
+ },
22
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors -- Ignored via go/DSP-18766
23
+ blockquote: {
24
+ paddingTop: 0,
25
+ paddingBottom: 0,
26
+ marginTop: 0
21
27
  }
22
28
  }
23
29
  },
@@ -45,4 +51,12 @@ export const wrapperSmallStyle = css({
45
51
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles -- Ignored via go/DSP-18766
46
52
  export const expandIconWrapperStyle = css({
47
53
  marginLeft: "var(--ds-space-negative-100, -8px)"
54
+ });
55
+
56
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-exported-styles
57
+ export const floatingToolbarWrapperStyle = css({
58
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
59
+ "[data-role='droplistContent']": {
60
+ maxHeight: '90vh'
61
+ }
48
62
  });
@@ -1,7 +1,8 @@
1
+ import { anyMarkActive } from '@atlaskit/editor-common/mark';
1
2
  import { createRule, createWrappingJoinRule } from '@atlaskit/editor-common/utils';
2
3
  import { fg } from '@atlaskit/platform-feature-flags';
3
4
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
4
- import { WRAPPER_BLOCK_TYPES } from './block-types';
5
+ import { WRAPPER_BLOCK_TYPES, FORMATTING_NODE_TYPES, FORMATTING_MARK_TYPES } from './block-types';
5
6
  export const isNodeAWrappingBlockNode = node => {
6
7
  if (!node) {
7
8
  return false;
@@ -21,7 +22,10 @@ export const createWrappingTextBlockRule = ({
21
22
  nodeType,
22
23
  getAttrs
23
24
  }) => {
24
- const handler = (state, match, start, end) => {
25
+ const handler = (state, match, start, end
26
+ // Ignored via go/ees005
27
+ // eslint-disable-next-line @typescript-eslint/max-params
28
+ ) => {
25
29
  const fixedStart = Math.max(start, 1);
26
30
  const $start = state.doc.resolve(fixedStart);
27
31
  const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs;
@@ -77,19 +81,71 @@ export function areBlockTypesDisabled(state) {
77
81
  const nodesTypes = getSelectedWrapperNodes(state);
78
82
  const {
79
83
  panel,
80
- blockquote
84
+ blockquote,
85
+ bulletList,
86
+ orderedList
81
87
  } = state.schema.nodes;
82
88
  if (editorExperiment('platform_editor_blockquote_in_text_formatting_menu', true)) {
83
89
  let hasQuote = false;
90
+ let hasNestedListInQuote = false;
84
91
  const {
85
92
  $from,
86
93
  $to
87
94
  } = state.selection;
88
95
  state.doc.nodesBetween($from.pos, $to.pos, node => {
89
- hasQuote = node.type === blockquote;
90
- return !hasQuote;
96
+ if (node.type === blockquote) {
97
+ hasQuote = true;
98
+ node.descendants(child => {
99
+ if (child.type === bulletList || child.type === orderedList) {
100
+ hasNestedListInQuote = true;
101
+ return false;
102
+ }
103
+ return true;
104
+ });
105
+ }
106
+ return !hasNestedListInQuote;
91
107
  });
92
- return nodesTypes.filter(type => type !== panel).length > 0 || hasQuote;
108
+ return nodesTypes.filter(type => type !== panel).length > 0 && (!hasQuote || hasNestedListInQuote);
93
109
  }
94
110
  return nodesTypes.filter(type => type !== panel).length > 0;
95
- }
111
+ }
112
+ const blockStylingIsPresent = state => {
113
+ const {
114
+ from,
115
+ to
116
+ } = state.selection;
117
+ let isBlockStyling = false;
118
+ state.doc.nodesBetween(from, to, node => {
119
+ if (FORMATTING_NODE_TYPES.indexOf(node.type.name) !== -1) {
120
+ isBlockStyling = true;
121
+ return false;
122
+ }
123
+ return true;
124
+ });
125
+ return isBlockStyling;
126
+ };
127
+ const marksArePresent = state => {
128
+ const activeMarkTypes = FORMATTING_MARK_TYPES.filter(mark => {
129
+ if (!!state.schema.marks[mark]) {
130
+ const {
131
+ $from,
132
+ empty
133
+ } = state.selection;
134
+ const {
135
+ marks
136
+ } = state.schema;
137
+ if (empty) {
138
+ return !!marks[mark].isInSet(state.storedMarks || $from.marks());
139
+ }
140
+ return anyMarkActive(state, marks[mark]);
141
+ }
142
+ return false;
143
+ });
144
+ return activeMarkTypes.length > 0;
145
+ };
146
+ export const checkFormattingIsPresent = state => {
147
+ return marksArePresent(state) || blockStylingIsPresent(state);
148
+ };
149
+ export const hasBlockQuoteInOptions = dropdownOptions => {
150
+ return !!dropdownOptions.find(blockType => blockType.name === 'blockquote');
151
+ };
@@ -8,7 +8,7 @@ import { IconHeading, IconQuote } from '@atlaskit/editor-common/quick-insert';
8
8
  import { ToolbarSize } from '@atlaskit/editor-common/types';
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
10
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
11
- import { setBlockTypeWithAnalytics, insertBlockQuoteWithAnalytics, insertBlockQuoteWithAnalyticsCommand } from './pm-plugins/commands/block-type';
11
+ import { setBlockTypeWithAnalytics, insertBlockQuoteWithAnalytics, insertBlockQuoteWithAnalyticsCommand, clearFormatting as _clearFormatting } from './pm-plugins/commands/block-type';
12
12
  import inputRulePlugin from './pm-plugins/input-rule';
13
13
  import keymapPlugin from './pm-plugins/keymap';
14
14
  import { createPlugin, pluginKey } from './pm-plugins/main';
@@ -184,6 +184,9 @@ var blockTypePlugin = function blockTypePlugin(_ref3) {
184
184
  insertBlockQuote: function insertBlockQuote(inputMethod) {
185
185
  var _api$analytics5;
186
186
  return insertBlockQuoteWithAnalyticsCommand(inputMethod, api === null || api === void 0 || (_api$analytics5 = api.analytics) === null || _api$analytics5 === void 0 ? void 0 : _api$analytics5.actions);
187
+ },
188
+ clearFormatting: function clearFormatting() {
189
+ return _clearFormatting();
187
190
  }
188
191
  },
189
192
  getSharedState: function getSharedState(editorState) {
@@ -70,6 +70,8 @@ export var OTHER = {
70
70
  nodeName: ''
71
71
  };
72
72
  export var TEXT_BLOCK_TYPES = [NORMAL_TEXT, HEADING_1, HEADING_2, HEADING_3, HEADING_4, HEADING_5, HEADING_6];
73
+ export var FORMATTING_NODE_TYPES = ['heading', 'blockquote'];
74
+ export var FORMATTING_MARK_TYPES = ['em', 'code', 'strike', 'strong', 'underline', 'textColor', 'subsup', 'backgroundColor'];
73
75
  export var WRAPPER_BLOCK_TYPES = [BLOCK_QUOTE, CODE_BLOCK, PANEL];
74
76
  export var ALL_BLOCK_TYPES = TEXT_BLOCK_TYPES.concat(WRAPPER_BLOCK_TYPES);
75
77
  export var getBlockTypesInDropdown = function getBlockTypesInDropdown(includeBlockQuoteAsTextstyleOption) {
@@ -7,6 +7,7 @@ import { filterChildrenBetween, wrapSelectionIn } from '@atlaskit/editor-common/
7
7
  import { Slice, Fragment } from '@atlaskit/editor-prosemirror/model';
8
8
  import { CellSelection } from '@atlaskit/editor-tables';
9
9
  import { HEADINGS_BY_NAME, NORMAL_TEXT } from '../block-types';
10
+ import { FORMATTING_NODE_TYPES, FORMATTING_MARK_TYPES, cellSelectionNodesBetween, formatTypes, clearNodeFormattingOnSelection } from './clear-formatting';
10
11
  import { wrapSelectionInBlockType } from './wrapSelectionIn';
11
12
  export function setBlockType(name) {
12
13
  return function (_ref) {
@@ -55,6 +56,9 @@ export function setHeading(level, fromBlockQuote) {
55
56
  return tr;
56
57
  };
57
58
  }
59
+
60
+ // Ignored via go/ees005
61
+ // eslint-disable-next-line @typescript-eslint/max-params
58
62
  export function setBlockTypeWithAnalytics(name, inputMethod, editorAnalyticsApi, fromBlockQuote) {
59
63
  return function (_ref4) {
60
64
  var tr = _ref4.tr;
@@ -95,9 +99,54 @@ export function setNormalText(fromBlockQuote) {
95
99
  return tr;
96
100
  };
97
101
  }
98
- function withCurrentHeadingLevel(fn) {
102
+ export function clearFormatting() {
99
103
  return function (_ref7) {
100
104
  var tr = _ref7.tr;
105
+ var formattingCleared = [];
106
+ var schema = tr.doc.type.schema;
107
+ FORMATTING_MARK_TYPES.forEach(function (mark) {
108
+ var _tr$selection = tr.selection,
109
+ from = _tr$selection.from,
110
+ to = _tr$selection.to;
111
+ var markType = schema.marks[mark];
112
+ if (!markType) {
113
+ return;
114
+ }
115
+ if (tr.selection instanceof CellSelection) {
116
+ cellSelectionNodesBetween(tr.selection, tr.doc, function (node, pos) {
117
+ var isTableCell = node.type === schema.nodes.tableCell || node.type === schema.nodes.tableHeader;
118
+ if (!isTableCell) {
119
+ return true;
120
+ }
121
+ if (tr.doc.rangeHasMark(pos, pos + node.nodeSize, markType)) {
122
+ formattingCleared.push(formatTypes[mark]);
123
+ tr.removeMark(pos, pos + node.nodeSize, markType);
124
+ }
125
+ return false;
126
+ });
127
+ } else if (tr.doc.rangeHasMark(from, to, markType)) {
128
+ formattingCleared.push(formatTypes[mark]);
129
+ tr.removeMark(from, to, markType);
130
+ }
131
+ });
132
+ FORMATTING_NODE_TYPES.forEach(function (nodeName) {
133
+ var formattedNodeType = schema.nodes[nodeName];
134
+ var _tr$selection2 = tr.selection,
135
+ $from = _tr$selection2.$from,
136
+ $to = _tr$selection2.$to;
137
+ if (tr.selection instanceof CellSelection) {
138
+ cellSelectionNodesBetween(tr.selection, tr.doc, clearNodeFormattingOnSelection(schema, tr, formattedNodeType, nodeName, formattingCleared));
139
+ } else {
140
+ tr.doc.nodesBetween($from.pos, $to.pos, clearNodeFormattingOnSelection(schema, tr, formattedNodeType, nodeName, formattingCleared));
141
+ }
142
+ });
143
+ tr.setStoredMarks([]);
144
+ return tr;
145
+ };
146
+ }
147
+ function withCurrentHeadingLevel(fn) {
148
+ return function (_ref8) {
149
+ var tr = _ref8.tr;
101
150
  // Find all headings and paragraphs of text
102
151
  var _tr$doc$type$schema$n = tr.doc.type.schema.nodes,
103
152
  heading = _tr$doc$type$schema$n.heading,
@@ -134,8 +183,8 @@ function withCurrentHeadingLevel(fn) {
134
183
  }
135
184
  export function setNormalTextWithAnalytics(inputMethod, editorAnalyticsApi, fromBlockQuote) {
136
185
  return withCurrentHeadingLevel(function (previousHeadingLevel) {
137
- return function (_ref8) {
138
- var tr = _ref8.tr;
186
+ return function (_ref9) {
187
+ var tr = _ref9.tr;
139
188
  editorAnalyticsApi === null || editorAnalyticsApi === void 0 || editorAnalyticsApi.attachAnalyticsEvent({
140
189
  action: ACTION.FORMATTED,
141
190
  actionSubject: ACTION_SUBJECT.TEXT,
@@ -153,10 +202,13 @@ export function setNormalTextWithAnalytics(inputMethod, editorAnalyticsApi, from
153
202
  };
154
203
  });
155
204
  }
156
- export var setHeadingWithAnalytics = function setHeadingWithAnalytics(newHeadingLevel, inputMethod, editorAnalyticsApi, fromBlockQuote) {
205
+ export var setHeadingWithAnalytics = function setHeadingWithAnalytics(newHeadingLevel, inputMethod, editorAnalyticsApi, fromBlockQuote
206
+ // Ignored via go/ees005
207
+ // eslint-disable-next-line @typescript-eslint/max-params
208
+ ) {
157
209
  return withCurrentHeadingLevel(function (previousHeadingLevel) {
158
- return function (_ref9) {
159
- var tr = _ref9.tr;
210
+ return function (_ref10) {
211
+ var tr = _ref10.tr;
160
212
  editorAnalyticsApi === null || editorAnalyticsApi === void 0 || editorAnalyticsApi.attachAnalyticsEvent({
161
213
  action: ACTION.FORMATTED,
162
214
  actionSubject: ACTION_SUBJECT.TEXT,
@@ -205,8 +257,8 @@ export var insertBlockQuoteWithAnalytics = function insertBlockQuoteWithAnalytic
205
257
  };
206
258
  export function insertBlockQuoteWithAnalyticsCommand(inputMethod, editorAnalyticsApi) {
207
259
  return withCurrentHeadingLevel(function (previousHeadingLevel) {
208
- return function (_ref10) {
209
- var tr = _ref10.tr;
260
+ return function (_ref11) {
261
+ var tr = _ref11.tr;
210
262
  var nodes = tr.doc.type.schema.nodes;
211
263
 
212
264
  // TODO: analytics event
@@ -228,8 +280,8 @@ export function insertBlockQuoteWithAnalyticsCommand(inputMethod, editorAnalytic
228
280
  });
229
281
  }
230
282
  export var cleanUpAtTheStartOfDocument = function cleanUpAtTheStartOfDocument(state, dispatch) {
231
- var _ref11 = state.selection,
232
- $cursor = _ref11.$cursor;
283
+ var _ref12 = state.selection,
284
+ $cursor = _ref12.$cursor;
233
285
  if ($cursor && !$cursor.nodeBefore && !$cursor.nodeAfter && $cursor.pos === 1) {
234
286
  var tr = state.tr,
235
287
  schema = state.schema;
@@ -0,0 +1,50 @@
1
+ import { ACTION_SUBJECT_ID } from '@atlaskit/editor-common/analytics';
2
+ import { liftTarget } from '@atlaskit/editor-prosemirror/transform';
3
+ // Functions duplicated from platform/packages/editor/editor-plugin-text-formatting/src/editor-commands/clear-formatting.ts
4
+ // TODO: Refactor to avoid duplication if platform_editor_blockquote_in_text_formatting_menu experiment is productionalised
5
+ export var FORMATTING_NODE_TYPES = ['heading', 'blockquote'];
6
+ export var FORMATTING_MARK_TYPES = ['em', 'code', 'strike', 'strong', 'underline', 'textColor', 'subsup', 'backgroundColor'];
7
+ export var formatTypes = {
8
+ em: ACTION_SUBJECT_ID.FORMAT_ITALIC,
9
+ code: ACTION_SUBJECT_ID.FORMAT_CODE,
10
+ strike: ACTION_SUBJECT_ID.FORMAT_STRIKE,
11
+ strong: ACTION_SUBJECT_ID.FORMAT_STRONG,
12
+ underline: ACTION_SUBJECT_ID.FORMAT_UNDERLINE,
13
+ textColor: ACTION_SUBJECT_ID.FORMAT_COLOR,
14
+ subsup: 'subsup',
15
+ backgroundColor: ACTION_SUBJECT_ID.FORMAT_BACKGROUND_COLOR
16
+ };
17
+ export var cellSelectionNodesBetween = function cellSelectionNodesBetween(selection, doc, f, startPos
18
+ // eslint-disable-next-line @typescript-eslint/max-params
19
+ ) {
20
+ selection.forEachCell(function (cell, cellPos) {
21
+ doc.nodesBetween(cellPos, cellPos + cell.nodeSize, f, startPos);
22
+ });
23
+ };
24
+
25
+ // eslint-disable-next-line @typescript-eslint/max-params
26
+ export function clearNodeFormattingOnSelection(schema, tr, formattedNodeType, nodeName, formattingCleared) {
27
+ return function (node, pos) {
28
+ if (node.type === formattedNodeType) {
29
+ if (formattedNodeType.isTextblock) {
30
+ tr.setNodeMarkup(pos, schema.nodes.paragraph);
31
+ formattingCleared.push(nodeName);
32
+ return false;
33
+ } else {
34
+ // In case of panel or blockquote
35
+ var fromPos = tr.doc.resolve(pos + 1);
36
+ var toPos = tr.doc.resolve(pos + node.nodeSize - 1);
37
+ var nodeRange = fromPos.blockRange(toPos);
38
+ if (nodeRange) {
39
+ var targetLiftDepth = liftTarget(nodeRange);
40
+ if (targetLiftDepth || targetLiftDepth === 0) {
41
+ formattingCleared.push(nodeName);
42
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
43
+ tr.lift(nodeRange, targetLiftDepth);
44
+ }
45
+ }
46
+ }
47
+ }
48
+ return true;
49
+ };
50
+ }
@@ -13,12 +13,16 @@ function getHeadingLevel(match) {
13
13
  }
14
14
  function headingRule(nodeType, maxLevel) {
15
15
  return createWrappingTextBlockRule({
16
+ // Ignored via go/ees005
17
+ // eslint-disable-next-line require-unicode-regexp
16
18
  match: new RegExp('^(#{1,' + maxLevel + '})\\s$'),
17
19
  nodeType: nodeType,
18
20
  getAttrs: getHeadingLevel
19
21
  });
20
22
  }
21
23
  function blockQuoteRule(nodeType) {
24
+ // Ignored via go/ees005
25
+ // eslint-disable-next-line require-unicode-regexp
22
26
  return createJoinNodesRule(/^\s*>\s$/, nodeType);
23
27
  }
24
28
 
@@ -31,7 +35,13 @@ function blockQuoteRule(nodeType) {
31
35
  function getHeadingRules(editorAnalyticsAPI, schema) {
32
36
  // '# ' for h1, '## ' for h2 and etc
33
37
  var hashRule = headingRule(schema.nodes.heading, MAX_HEADING_LEVEL);
34
- var leftNodeReplacementHashRule = createRule(new RegExp("".concat(leafNodeReplacementCharacter, "(#{1,6})\\s$")), function (state, match, start, end) {
38
+ var leftNodeReplacementHashRule = createRule(
39
+ // Ignored via go/ees005
40
+ // eslint-disable-next-line require-unicode-regexp
41
+ new RegExp("".concat(leafNodeReplacementCharacter, "(#{1,6})\\s$")),
42
+ // Ignored via go/ees005
43
+ // eslint-disable-next-line @typescript-eslint/max-params
44
+ function (state, match, start, end) {
35
45
  var level = match[1].length;
36
46
  return insertBlock(state, schema.nodes.heading, start, end, {
37
47
  level: level
@@ -63,7 +73,13 @@ function getHeadingRules(editorAnalyticsAPI, schema) {
63
73
  function getBlockQuoteRules(editorAnalyticsAPI, schema) {
64
74
  // '> ' for blockquote
65
75
  var greatherThanRule = blockQuoteRule(schema.nodes.blockquote);
66
- var leftNodeReplacementGreatherRule = createRule(new RegExp("".concat(leafNodeReplacementCharacter, "\\s*>\\s$")), function (state, _match, start, end) {
76
+ var leftNodeReplacementGreatherRule = createRule(
77
+ // Ignored via go/ees005
78
+ // eslint-disable-next-line require-unicode-regexp
79
+ new RegExp("".concat(leafNodeReplacementCharacter, "\\s*>\\s$")),
80
+ // Ignored via go/ees005
81
+ // eslint-disable-next-line @typescript-eslint/max-params
82
+ function (state, _match, start, end) {
67
83
  return insertBlock(state, schema.nodes.blockquote, start, end);
68
84
  });
69
85
 
@@ -3,6 +3,8 @@ import { backspace, bindKeymapWithCommand, deleteKey, findKeyMapForBrowser, find
3
3
  import { createNewParagraphAbove, createNewParagraphBelow, deleteEmptyParagraphAndMoveBlockUp, insertNewLineWithAnalytics } from '@atlaskit/editor-common/utils';
4
4
  import { chainCommands } from '@atlaskit/editor-prosemirror/commands';
5
5
  import { redo, undo } from '@atlaskit/editor-prosemirror/history';
6
+ // Ignored via go/ees005
7
+ // eslint-disable-next-line import/no-namespace
6
8
  import * as blockTypes from './block-types';
7
9
  import { cleanUpAtTheStartOfDocument, insertBlockQuoteWithAnalytics } from './commands/block-type';
8
10
  import { deleteAndMoveCursor } from './commands/delete-and-move-cursor';
@@ -12,16 +14,37 @@ var backspaceCommand = chainCommands(cleanUpAtTheStartOfDocument, deleteBlockCon
12
14
  var del = chainCommands(deleteEmptyParagraphAndMoveBlockUp(isNodeAWrappingBlockNode), deleteBlockContent(isNodeAWrappingBlockNode), deleteAndMoveCursor);
13
15
  export default function keymapPlugin(editorAnalyticsApi, schema, _featureFlags) {
14
16
  var list = {};
15
- bindKeymapWithCommand(insertNewLine.common, insertNewLineWithAnalytics(editorAnalyticsApi), list);
17
+ bindKeymapWithCommand(
18
+ // Ignored via go/ees005
19
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20
+ insertNewLine.common, insertNewLineWithAnalytics(editorAnalyticsApi), list);
21
+ // Ignored via go/ees005
22
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
16
23
  bindKeymapWithCommand(moveUp.common, createNewParagraphAbove, list);
24
+ // Ignored via go/ees005
25
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
17
26
  bindKeymapWithCommand(moveDown.common, createNewParagraphBelow, list);
27
+ // Ignored via go/ees005
28
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
18
29
  bindKeymapWithCommand(findKeyMapForBrowser(redoKeymap), redo, list);
30
+
31
+ // Ignored via go/ees005
32
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
19
33
  bindKeymapWithCommand(undoKeymap.common, undo, list);
34
+
35
+ // Ignored via go/ees005
36
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
20
37
  bindKeymapWithCommand(backspace.common, backspaceCommand, list);
38
+
39
+ // Ignored via go/ees005
40
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
21
41
  bindKeymapWithCommand(deleteKey.common, del, list);
22
42
  bindKeymapWithCommand(forwardDelete.mac, del, list);
23
43
  if (schema.nodes[blockTypes.BLOCK_QUOTE.nodeName]) {
24
- bindKeymapWithCommand(findShortcutByKeymap(toggleBlockQuote), insertBlockQuoteWithAnalytics(INPUT_METHOD.KEYBOARD, editorAnalyticsApi), list);
44
+ bindKeymapWithCommand(
45
+ // Ignored via go/ees005
46
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
47
+ findShortcutByKeymap(toggleBlockQuote), insertBlockQuoteWithAnalytics(INPUT_METHOD.KEYBOARD, editorAnalyticsApi), list);
25
48
  }
26
49
  return keymap(list);
27
50
  }