@atlaskit/editor-core 151.0.0 → 151.2.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 (70) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/cjs/create-editor/create-plugins-list.js +8 -1
  3. package/dist/cjs/labs/next/presets/default.js +3 -1
  4. package/dist/cjs/plugins/code-bidi-warning/index.js +28 -0
  5. package/dist/cjs/plugins/code-bidi-warning/plugin-key.js +11 -0
  6. package/dist/cjs/plugins/code-bidi-warning/pm-plugins/main.js +52 -0
  7. package/dist/cjs/plugins/code-bidi-warning/pm-plugins/plugin-factory.js +128 -0
  8. package/dist/cjs/plugins/code-bidi-warning/pm-plugins/reducer.js +12 -0
  9. package/dist/cjs/plugins/code-bidi-warning/pm-plugins/types.js +5 -0
  10. package/dist/cjs/plugins/code-block/index.js +12 -8
  11. package/dist/cjs/plugins/code-block/nodeviews/highlighting-code-block.js +19 -5
  12. package/dist/cjs/plugins/code-block/pm-plugins/main.js +21 -4
  13. package/dist/cjs/plugins/feature-flags-context/feature-flags-from-props.js +3 -2
  14. package/dist/cjs/plugins/hyperlink/HyperlinkToolbarAppearance.js +2 -2
  15. package/dist/cjs/plugins/index.js +8 -0
  16. package/dist/cjs/plugins/rank.js +1 -1
  17. package/dist/cjs/plugins/status/styles.js +1 -1
  18. package/dist/cjs/version-wrapper.js +1 -1
  19. package/dist/cjs/version.json +1 -1
  20. package/dist/es2019/create-editor/create-plugins-list.js +9 -2
  21. package/dist/es2019/labs/next/presets/default.js +3 -1
  22. package/dist/es2019/plugins/code-bidi-warning/index.js +21 -0
  23. package/dist/es2019/plugins/code-bidi-warning/plugin-key.js +2 -0
  24. package/dist/es2019/plugins/code-bidi-warning/pm-plugins/main.js +41 -0
  25. package/dist/es2019/plugins/code-bidi-warning/pm-plugins/plugin-factory.js +99 -0
  26. package/dist/es2019/plugins/code-bidi-warning/pm-plugins/reducer.js +3 -0
  27. package/dist/es2019/plugins/code-bidi-warning/pm-plugins/types.js +1 -0
  28. package/dist/es2019/plugins/code-block/index.js +8 -2
  29. package/dist/es2019/plugins/code-block/nodeviews/highlighting-code-block.js +19 -4
  30. package/dist/es2019/plugins/code-block/pm-plugins/main.js +58 -39
  31. package/dist/es2019/plugins/feature-flags-context/feature-flags-from-props.js +3 -2
  32. package/dist/es2019/plugins/hyperlink/HyperlinkToolbarAppearance.js +1 -1
  33. package/dist/es2019/plugins/index.js +2 -1
  34. package/dist/es2019/plugins/rank.js +1 -1
  35. package/dist/es2019/plugins/status/styles.js +3 -0
  36. package/dist/es2019/version-wrapper.js +1 -1
  37. package/dist/es2019/version.json +1 -1
  38. package/dist/esm/create-editor/create-plugins-list.js +9 -2
  39. package/dist/esm/labs/next/presets/default.js +3 -1
  40. package/dist/esm/plugins/code-bidi-warning/index.js +20 -0
  41. package/dist/esm/plugins/code-bidi-warning/plugin-key.js +2 -0
  42. package/dist/esm/plugins/code-bidi-warning/pm-plugins/main.js +39 -0
  43. package/dist/esm/plugins/code-bidi-warning/pm-plugins/plugin-factory.js +106 -0
  44. package/dist/esm/plugins/code-bidi-warning/pm-plugins/reducer.js +3 -0
  45. package/dist/esm/plugins/code-bidi-warning/pm-plugins/types.js +1 -0
  46. package/dist/esm/plugins/code-block/index.js +12 -8
  47. package/dist/esm/plugins/code-block/nodeviews/highlighting-code-block.js +19 -5
  48. package/dist/esm/plugins/code-block/pm-plugins/main.js +20 -4
  49. package/dist/esm/plugins/feature-flags-context/feature-flags-from-props.js +3 -2
  50. package/dist/esm/plugins/hyperlink/HyperlinkToolbarAppearance.js +2 -2
  51. package/dist/esm/plugins/index.js +2 -1
  52. package/dist/esm/plugins/rank.js +1 -1
  53. package/dist/esm/plugins/status/styles.js +1 -1
  54. package/dist/esm/version-wrapper.js +1 -1
  55. package/dist/esm/version.json +1 -1
  56. package/dist/types/plugins/code-bidi-warning/index.d.ts +5 -0
  57. package/dist/types/plugins/code-bidi-warning/plugin-key.d.ts +2 -0
  58. package/dist/types/plugins/code-bidi-warning/pm-plugins/main.d.ts +5 -0
  59. package/dist/types/plugins/code-bidi-warning/pm-plugins/plugin-factory.d.ts +8 -0
  60. package/dist/types/plugins/code-bidi-warning/pm-plugins/reducer.d.ts +3 -0
  61. package/dist/types/plugins/code-bidi-warning/pm-plugins/types.d.ts +6 -0
  62. package/dist/types/plugins/code-block/index.d.ts +1 -1
  63. package/dist/types/plugins/code-block/nodeviews/highlighting-code-block.d.ts +22 -2
  64. package/dist/types/plugins/code-block/pm-plugins/main.d.ts +7 -1
  65. package/dist/types/plugins/code-block/types.d.ts +2 -0
  66. package/dist/types/plugins/feature-flags-context/get-enabled-feature-flag-keys.d.ts +1 -1
  67. package/dist/types/plugins/hyperlink/HyperlinkToolbarAppearance.d.ts +1 -1
  68. package/dist/types/plugins/index.d.ts +1 -0
  69. package/dist/types/types/feature-flags.d.ts +9 -0
  70. package/package.json +6 -6
@@ -0,0 +1,41 @@
1
+ import { Plugin } from 'prosemirror-state';
2
+ import { codeBidiWarningMessages } from '@atlaskit/editor-common/messages';
3
+ import { codeBidiWarningPluginKey } from '../plugin-key';
4
+ import { createBidiWarningsDecorationSetFromDoc, createPluginState, getPluginState } from './plugin-factory';
5
+ export const createPlugin = ({
6
+ dispatch,
7
+ reactContext
8
+ }, {
9
+ appearance
10
+ }) => {
11
+ const intl = reactContext().intl;
12
+ const codeBidiWarningLabel = intl.formatMessage(codeBidiWarningMessages.label);
13
+ return new Plugin({
14
+ key: codeBidiWarningPluginKey,
15
+ state: createPluginState(dispatch, state => {
16
+ // The appearance being mobile indicates we are in an editor being
17
+ // rendered by mobile bridge in a web view.
18
+ // The tooltip is likely to have unexpected behaviour there, with being cut
19
+ // off, so we disable it. This is also to keep the behaviour consistent with
20
+ // the rendering in the mobile Native Renderer.
21
+ const tooltipEnabled = appearance !== 'mobile';
22
+ return {
23
+ decorationSet: createBidiWarningsDecorationSetFromDoc({
24
+ doc: state.doc,
25
+ codeBidiWarningLabel,
26
+ tooltipEnabled
27
+ }),
28
+ codeBidiWarningLabel,
29
+ tooltipEnabled
30
+ };
31
+ }),
32
+ props: {
33
+ decorations: state => {
34
+ const {
35
+ decorationSet
36
+ } = getPluginState(state);
37
+ return decorationSet;
38
+ }
39
+ }
40
+ });
41
+ };
@@ -0,0 +1,99 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import { Decoration, DecorationSet } from 'prosemirror-view';
4
+ import CodeBidiWarning from '@atlaskit/code/bidi-warning';
5
+ import codeBidiWarningDecorator from '@atlaskit/code/bidi-warning-decorator';
6
+ import { pluginFactory } from '../../../utils/plugin-state-factory';
7
+ import { stepHasSlice } from '../../../utils/step';
8
+ import { codeBidiWarningPluginKey } from '../plugin-key';
9
+ import reducer from './reducer';
10
+ export const {
11
+ createPluginState,
12
+ getPluginState
13
+ } = pluginFactory(codeBidiWarningPluginKey, reducer, {
14
+ onDocChanged: (tr, pluginState) => {
15
+ if (!tr.steps.find(stepHasSlice)) {
16
+ return pluginState;
17
+ }
18
+
19
+ const newBidiWarningsDecorationSet = createBidiWarningsDecorationSetFromDoc({
20
+ doc: tr.doc,
21
+ codeBidiWarningLabel: pluginState.codeBidiWarningLabel,
22
+ tooltipEnabled: pluginState.tooltipEnabled
23
+ });
24
+ return { ...pluginState,
25
+ decorationSet: newBidiWarningsDecorationSet
26
+ };
27
+ }
28
+ });
29
+ export function createBidiWarningsDecorationSetFromDoc({
30
+ doc,
31
+ codeBidiWarningLabel,
32
+ tooltipEnabled
33
+ }) {
34
+ const bidiCharactersAndTheirPositions = [];
35
+ doc.descendants((node, pos) => {
36
+ const isTextWithCodeMark = node.type.name === 'text' && node.marks && node.marks.some(mark => mark.type.name === 'code');
37
+
38
+ if (isTextWithCodeMark) {
39
+ codeBidiWarningDecorator(node.textContent, ({
40
+ bidiCharacter,
41
+ index
42
+ }) => {
43
+ bidiCharactersAndTheirPositions.push({
44
+ position: pos + index,
45
+ bidiCharacter
46
+ });
47
+ });
48
+ return false;
49
+ }
50
+
51
+ const isCodeBlock = node.type.name === 'codeBlock';
52
+
53
+ if (isCodeBlock) {
54
+ codeBidiWarningDecorator(node.textContent, ({
55
+ bidiCharacter,
56
+ index
57
+ }) => {
58
+ bidiCharactersAndTheirPositions.push({
59
+ position: pos + index + 1,
60
+ bidiCharacter
61
+ });
62
+ });
63
+ }
64
+ }); // Bidi characters are not expected to commonly appear in code snippets, so recreating the decoration set
65
+ // for documents rather than reusing existing decorations seems a reasonable performance/complexity tradeoff.
66
+
67
+ if (bidiCharactersAndTheirPositions.length === 0) {
68
+ return DecorationSet.empty;
69
+ }
70
+
71
+ const newBidiWarningsDecorationSet = DecorationSet.create(doc, bidiCharactersAndTheirPositions.map(({
72
+ position,
73
+ bidiCharacter
74
+ }) => {
75
+ return Decoration.widget(position, () => renderDOM({
76
+ bidiCharacter,
77
+ codeBidiWarningLabel,
78
+ tooltipEnabled
79
+ }));
80
+ }));
81
+ return newBidiWarningsDecorationSet;
82
+ }
83
+
84
+ function renderDOM({
85
+ bidiCharacter,
86
+ codeBidiWarningLabel,
87
+ tooltipEnabled
88
+ }) {
89
+ const element = document.createElement('span'); // Note: we use this pattern elsewhere (see highlighting code block, and drop cursor widget decoration)
90
+ // we should investigate if there is a memory leak with such usage.
91
+
92
+ ReactDOM.render( /*#__PURE__*/React.createElement(CodeBidiWarning, {
93
+ bidiCharacter: bidiCharacter,
94
+ skipChildren: true,
95
+ label: codeBidiWarningLabel,
96
+ tooltipEnabled: tooltipEnabled
97
+ }), element);
98
+ return element;
99
+ }
@@ -0,0 +1,3 @@
1
+ export default ((pluginState, action) => {
2
+ return pluginState;
3
+ });
@@ -9,7 +9,7 @@ import { IconCode } from '../quick-insert/assets';
9
9
  import { messages } from '../block-type/messages';
10
10
  import refreshBrowserSelectionOnChange from './refresh-browser-selection';
11
11
 
12
- const codeBlockPlugin = (options = {}) => ({
12
+ const codeBlockPlugin = options => ({
13
13
  name: 'codeBlock',
14
14
 
15
15
  nodes() {
@@ -22,7 +22,13 @@ const codeBlockPlugin = (options = {}) => ({
22
22
  pmPlugins() {
23
23
  return [{
24
24
  name: 'codeBlock',
25
- plugin: () => createPlugin(options.useLongPressSelection)
25
+ plugin: ({
26
+ reactContext
27
+ }) => createPlugin({
28
+ useLongPressSelection: options.useLongPressSelection,
29
+ reactContext,
30
+ appearance: options.appearance
31
+ })
26
32
  }, {
27
33
  name: 'codeBlockIDEKeyBindings',
28
34
  plugin: () => ideUX
@@ -28,7 +28,7 @@ const toDOM = node => ['div', {
28
28
  }]]];
29
29
 
30
30
  export class CodeBlockView {
31
- constructor(_node, view, getPos) {
31
+ constructor(_node, view, getPos, codeBidiWarningOptions) {
32
32
  _defineProperty(this, "highlighting", null);
33
33
 
34
34
  _defineProperty(this, "highlighter", null);
@@ -57,6 +57,7 @@ export class CodeBlockView {
57
57
  dom,
58
58
  contentDOM
59
59
  } = DOMSerializer.renderSpec(document, toDOM(_node));
60
+ this.codeBidiWarningOptions = codeBidiWarningOptions;
60
61
  this.getPos = getPos;
61
62
  this.view = view;
62
63
  this.node = _node;
@@ -99,7 +100,10 @@ export class CodeBlockView {
99
100
  ReactDOM.render( /*#__PURE__*/React.createElement(CodeBlock, {
100
101
  text: node.textContent,
101
102
  language: node.attrs.language,
102
- showLineNumbers: false
103
+ showLineNumbers: false,
104
+ codeBidiWarnings: this.codeBidiWarningOptions.enabled,
105
+ codeBidiWarningLabel: this.codeBidiWarningOptions.label,
106
+ codeBidiWarningTooltipEnabled: this.codeBidiWarningOptions.tooltipEnabled
103
107
  }), highlighting);
104
108
  this.measure(performance.now() - start);
105
109
  content === null || content === void 0 ? void 0 : content.setAttribute('data-debounce', 'false');
@@ -130,8 +134,19 @@ export class CodeBlockView {
130
134
  ignoreMutation(record) {
131
135
  var _this$highlighting$co, _this$highlighting;
132
136
 
133
- return record.target === this.lineNumberGutter || record.target.parentNode === this.lineNumberGutter || ((_this$highlighting$co = (_this$highlighting = this.highlighting) === null || _this$highlighting === void 0 ? void 0 : _this$highlighting.contains(record.target)) !== null && _this$highlighting$co !== void 0 ? _this$highlighting$co : false);
137
+ const lineNumberChanges = record.target === this.lineNumberGutter || record.target.parentNode === this.lineNumberGutter;
138
+ const outsideTheCodeBlockChanges = (_this$highlighting$co = (_this$highlighting = this.highlighting) === null || _this$highlighting === void 0 ? void 0 : _this$highlighting.contains(record.target)) !== null && _this$highlighting$co !== void 0 ? _this$highlighting$co : false;
139
+ const codeBidiWarningDecorationChanges = record.type === 'attributes' && record.attributeName === 'aria-describedby';
140
+ return lineNumberChanges || outsideTheCodeBlockChanges || codeBidiWarningDecorationChanges;
134
141
  }
135
142
 
136
143
  }
137
- export const highlightingCodeBlockNodeView = () => (node, view, getPos) => new CodeBlockView(node, view, getPos);
144
+ export const highlightingCodeBlockNodeView = ({
145
+ codeBidiWarnings,
146
+ codeBidiWarningLabel,
147
+ codeBidiWarningTooltipEnabled
148
+ }) => (node, view, getPos) => new CodeBlockView(node, view, getPos, {
149
+ label: codeBidiWarningLabel,
150
+ enabled: codeBidiWarnings,
151
+ tooltipEnabled: codeBidiWarningTooltipEnabled
152
+ });
@@ -1,4 +1,5 @@
1
1
  import { Plugin, NodeSelection } from 'prosemirror-state';
2
+ import { codeBidiWarningMessages } from '@atlaskit/editor-common/messages';
2
3
  import { codeBlockNodeView } from '../nodeviews/code-block';
3
4
  import { highlightingCodeBlockNodeView } from '../nodeviews/highlighting-code-block';
4
5
  import { createSelectionClickHandler } from '../../selection/utils';
@@ -7,51 +8,69 @@ import { ACTIONS } from './actions';
7
8
  import { findCodeBlock } from '../utils';
8
9
  import { codeBlockClassNames } from '../ui/class-names';
9
10
  import { getFeatureFlags } from '../../feature-flags-context';
10
- export const createPlugin = (useLongPressSelection = false) => new Plugin({
11
- state: {
12
- init(_, state) {
13
- const node = findCodeBlock(state, state.selection);
14
- return {
15
- pos: node ? node.pos : null,
16
- contentCopied: false,
17
- isNodeSelected: false
18
- };
19
- },
20
-
21
- apply(tr, pluginState, _oldState, newState) {
22
- if (tr.docChanged || tr.selectionSet) {
23
- const node = findCodeBlock(newState, tr.selection);
24
- const newPluginState = { ...pluginState,
11
+ export const createPlugin = ({
12
+ useLongPressSelection = false,
13
+ reactContext,
14
+ appearance
15
+ }) => {
16
+ const intl = reactContext().intl;
17
+ const codeBidiWarningLabel = intl.formatMessage(codeBidiWarningMessages.label);
18
+ return new Plugin({
19
+ state: {
20
+ init(_, state) {
21
+ const node = findCodeBlock(state, state.selection);
22
+ return {
25
23
  pos: node ? node.pos : null,
26
- isNodeSelected: tr.selection instanceof NodeSelection
24
+ contentCopied: false,
25
+ isNodeSelected: false
27
26
  };
28
- return newPluginState;
29
- }
27
+ },
30
28
 
31
- const meta = tr.getMeta(pluginKey);
29
+ apply(tr, pluginState, _oldState, newState) {
30
+ if (tr.docChanged || tr.selectionSet) {
31
+ const node = findCodeBlock(newState, tr.selection);
32
+ const newPluginState = { ...pluginState,
33
+ pos: node ? node.pos : null,
34
+ isNodeSelected: tr.selection instanceof NodeSelection
35
+ };
36
+ return newPluginState;
37
+ }
32
38
 
33
- if ((meta === null || meta === void 0 ? void 0 : meta.type) === ACTIONS.SET_COPIED_TO_CLIPBOARD) {
34
- return { ...pluginState,
35
- contentCopied: meta.data
36
- };
37
- }
39
+ const meta = tr.getMeta(pluginKey);
38
40
 
39
- return pluginState;
40
- }
41
+ if ((meta === null || meta === void 0 ? void 0 : meta.type) === ACTIONS.SET_COPIED_TO_CLIPBOARD) {
42
+ return { ...pluginState,
43
+ contentCopied: meta.data
44
+ };
45
+ }
41
46
 
42
- },
43
- key: pluginKey,
44
- props: {
45
- nodeViews: {
46
- codeBlock(node, view, getPos) {
47
- const featureFlags = getFeatureFlags(view.state);
48
- const createCodeBlockNodeView = featureFlags !== null && featureFlags !== void 0 && featureFlags.codeBlockSyntaxHighlighting ? highlightingCodeBlockNodeView() : codeBlockNodeView();
49
- return createCodeBlockNodeView(node, view, getPos);
47
+ return pluginState;
50
48
  }
51
49
 
52
50
  },
53
- handleClickOn: createSelectionClickHandler(['codeBlock'], target => !!(target.closest(`.${codeBlockClassNames.gutter}`) || target.classList.contains(codeBlockClassNames.content)), {
54
- useLongPressSelection
55
- })
56
- }
57
- });
51
+ key: pluginKey,
52
+ props: {
53
+ nodeViews: {
54
+ codeBlock(node, view, getPos) {
55
+ const featureFlags = getFeatureFlags(view.state); // The appearance being mobile indicates we are in an editor being
56
+ // rendered by mobile bridge in a web view.
57
+ // The tooltip is likely to have unexpected behaviour there, with being cut
58
+ // off, so we disable it. This is also to keep the behaviour consistent with
59
+ // the rendering in the mobile Native Renderer.
60
+
61
+ const codeBidiWarningTooltipEnabled = appearance !== 'mobile';
62
+ const createCodeBlockNodeView = featureFlags !== null && featureFlags !== void 0 && featureFlags.codeBlockSyntaxHighlighting ? highlightingCodeBlockNodeView({
63
+ codeBidiWarnings: featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.codeBidiWarnings,
64
+ codeBidiWarningLabel,
65
+ codeBidiWarningTooltipEnabled: codeBidiWarningTooltipEnabled
66
+ }) : codeBlockNodeView();
67
+ return createCodeBlockNodeView(node, view, getPos);
68
+ }
69
+
70
+ },
71
+ handleClickOn: createSelectionClickHandler(['codeBlock'], target => !!(target.closest(`.${codeBlockClassNames.gutter}`) || target.classList.contains(codeBlockClassNames.content)), {
72
+ useLongPressSelection
73
+ })
74
+ }
75
+ });
76
+ };
@@ -6,7 +6,7 @@ import { browser } from '@atlaskit/editor-common';
6
6
  */
7
7
 
8
8
  export function createFeatureFlagsFromProps(props) {
9
- var _props$allowTextColor, _props$performanceTra, _props$performanceTra2, _props$featureFlags, _props$featureFlags2, _props$featureFlags3, _props$allowTables, _props$featureFlags4, _props$featureFlags5, _props$allowTables2, _props$featureFlags6, _props$featureFlags7, _props$allowTables3, _props$featureFlags8, _props$featureFlags9, _props$allowTables4, _props$featureFlags10, _props$featureFlags11, _props$allowTables5, _props$allowExtension, _props$featureFlags12, _props$featureFlags13, _props$featureFlags14, _props$featureFlags15, _props$featureFlags16, _props$featureFlags17, _props$featureFlags18, _props$featureFlags19, _props$featureFlags20, _props$featureFlags21, _props$featureFlags22, _props$featureFlags23, _props$featureFlags24, _props$featureFlags25, _props$featureFlags26, _props$featureFlags27;
9
+ var _props$allowTextColor, _props$performanceTra, _props$performanceTra2, _props$featureFlags, _props$featureFlags2, _props$featureFlags3, _props$allowTables, _props$featureFlags4, _props$featureFlags5, _props$allowTables2, _props$featureFlags6, _props$featureFlags7, _props$allowTables3, _props$featureFlags8, _props$featureFlags9, _props$allowTables4, _props$featureFlags10, _props$featureFlags11, _props$allowTables5, _props$allowExtension, _props$featureFlags12, _props$featureFlags13, _props$featureFlags14, _props$featureFlags15, _props$featureFlags16, _props$featureFlags17, _props$featureFlags18, _props$featureFlags19, _props$featureFlags20, _props$featureFlags21, _props$featureFlags22, _props$featureFlags23, _props$featureFlags24, _props$featureFlags25, _props$featureFlags26, _props$featureFlags27, _props$featureFlags28, _props$featureFlags29;
10
10
 
11
11
  const normalizedFeatureFlags = normalizeFeatureFlags(props.featureFlags);
12
12
  return { ...normalizedFeatureFlags,
@@ -36,6 +36,7 @@ export function createFeatureFlagsFromProps(props) {
36
36
  enableViewUpdateSubscription: Boolean(typeof ((_props$featureFlags22 = props.featureFlags) === null || _props$featureFlags22 === void 0 ? void 0 : _props$featureFlags22.enableViewUpdateSubscription) === 'boolean' ? !!((_props$featureFlags23 = props.featureFlags) !== null && _props$featureFlags23 !== void 0 && _props$featureFlags23.enableViewUpdateSubscription) : false),
37
37
  collabAvatarScroll: Boolean(typeof ((_props$featureFlags24 = props.featureFlags) === null || _props$featureFlags24 === void 0 ? void 0 : _props$featureFlags24.collabAvatarScroll) === 'boolean' ? !!((_props$featureFlags25 = props.featureFlags) !== null && _props$featureFlags25 !== void 0 && _props$featureFlags25.collabAvatarScroll) : false),
38
38
  ufo: Boolean(typeof ((_props$featureFlags26 = props.featureFlags) === null || _props$featureFlags26 === void 0 ? void 0 : _props$featureFlags26.ufo) === 'boolean' ? !!((_props$featureFlags27 = props.featureFlags) !== null && _props$featureFlags27 !== void 0 && _props$featureFlags27.ufo) : false),
39
- codeBlockSyntaxHighlighting: Boolean(typeof normalizedFeatureFlags.codeBlockSyntaxHighlighting === 'boolean' ? !!normalizedFeatureFlags.codeBlockSyntaxHighlighting && !browser.safari : false)
39
+ codeBlockSyntaxHighlighting: Boolean(typeof normalizedFeatureFlags.codeBlockSyntaxHighlighting === 'boolean' ? !!normalizedFeatureFlags.codeBlockSyntaxHighlighting && !browser.safari : false),
40
+ codeBidiWarnings: Boolean(typeof ((_props$featureFlags28 = props.featureFlags) === null || _props$featureFlags28 === void 0 ? void 0 : _props$featureFlags28.codeBidiWarnings) === 'boolean' ? !!((_props$featureFlags29 = props.featureFlags) !== null && _props$featureFlags29 !== void 0 && _props$featureFlags29.codeBidiWarnings) : true)
40
41
  };
41
42
  }
@@ -59,7 +59,7 @@ export class HyperlinkToolbarAppearance extends Component {
59
59
 
60
60
  // needed so we display the right state on the Toolbar while the same Toolbar
61
61
  // instance is visible and we click other link
62
- componentWillReceiveProps(nextProps) {
62
+ UNSAFE_componentWillReceiveProps(nextProps) {
63
63
  if (nextProps.url !== this.props.url) {
64
64
  this.resolveUrl(nextProps.url);
65
65
  }
@@ -60,4 +60,5 @@ export { default as mobileSelectionPlugin } from './mobile-selection';
60
60
  export { default as clipboardPlugin } from './clipboard';
61
61
  export { default as undoRedoPlugin } from './undo-redo';
62
62
  export { default as avatarGroupPlugin } from './avatar-group';
63
- export { default as viewUpdateSubscriptionPlugin } from './view-update-subscription';
63
+ export { default as viewUpdateSubscriptionPlugin } from './view-update-subscription';
64
+ export { default as codeBidiWarningPlugin } from './code-bidi-warning';
@@ -6,7 +6,7 @@ export default {
6
6
  // https://product-fabric.atlassian.net/wiki/spaces/E/pages/1113098008/Selection+Guide#Special-Cases
7
7
  'expandKeymap', 'tableSelectionKeymap', 'tableKeymap', 'captionKeymap', // selection keymap needs to be above gap cursor keymap so it can set node selections from
8
8
  // left/right arrows
9
- 'selectionKeymap', 'gapCursorKeymap', 'gapCursor', 'syncUrlText', 'fakeCursorToolbarPlugin', 'hyperLink', 'table', 'tableDecorations', 'hyperlinkInputRule', 'tablePMColResizing', 'hyperlinkKeymap', 'tableColResizing', 'undoRedoKeyMap', 'blockTypeKeyMap', 'tableEditing', 'filterStepsPlugin', 'pmCollab', 'collab', 'ruleInputRule', 'ruleKeymap', 'panel', 'media', 'mediaKeymap', 'mediaSingleKeymap', 'mediaEditor', 'unsupportedContent', 'jiraIssue', 'fakeTextCursor', 'helpDialog', 'helpDialogKeymap', 'macro', 'expand', 'extension', 'layout', 'contextPanel', 'floatingToolbar', 'clearMarksOnChange', 'reactNodeView', 'history', 'undoRedoPlugin', 'codeBlockIndent', 'placeholder', 'width', 'maxContentSize', 'multilineContent', 'grid', 'mobileDimensions', 'scrollGutterPlugin', 'analytics', 'findReplace', 'selection', 'avatarGroup', 'viewUpdateSubscription'],
9
+ 'selectionKeymap', 'gapCursorKeymap', 'gapCursor', 'syncUrlText', 'fakeCursorToolbarPlugin', 'hyperLink', 'table', 'tableDecorations', 'hyperlinkInputRule', 'tablePMColResizing', 'hyperlinkKeymap', 'tableColResizing', 'undoRedoKeyMap', 'blockTypeKeyMap', 'tableEditing', 'filterStepsPlugin', 'pmCollab', 'collab', 'ruleInputRule', 'ruleKeymap', 'panel', 'media', 'mediaKeymap', 'mediaSingleKeymap', 'mediaEditor', 'unsupportedContent', 'jiraIssue', 'fakeTextCursor', 'helpDialog', 'helpDialogKeymap', 'macro', 'expand', 'extension', 'layout', 'contextPanel', 'floatingToolbar', 'clearMarksOnChange', 'reactNodeView', 'history', 'undoRedoPlugin', 'codeBlockIndent', 'placeholder', 'width', 'maxContentSize', 'multilineContent', 'grid', 'mobileDimensions', 'scrollGutterPlugin', 'analytics', 'findReplace', 'selection', 'avatarGroup', 'viewUpdateSubscription', 'inlineCode'],
10
10
  nodes: ['doc', 'paragraph', 'text', 'bulletList', 'orderedList', 'listItem', 'heading', 'blockquote', 'codeBlock', 'rule', 'panel', 'mention', 'confluenceUnsupportedBlock', 'confluenceUnsupportedInline', 'unsupportedBlock', 'unsupportedInline', 'confluenceJiraIssue', 'hardBreak', 'emoji', 'placeholder', 'mediaSingle', 'mediaGroup', 'table', 'expand', 'nestedExpand', 'media', 'tableHeader', 'decisionList', 'tableRow', 'decisionItem', 'tableCell', 'taskList', 'taskItem', 'extension', 'bodiedExtension', 'inlineExtension', 'layoutSection', 'layoutColumn', 'inlineCard', 'blockCard', 'embedCard'],
11
11
  marks: [// Inline marks
12
12
  'link', 'em', 'strong', 'textColor', 'strike', 'subsup', 'underline', 'code', 'typeAheadQuery', // Block marks
@@ -3,7 +3,10 @@ import { StatusSharedCssClassName } from '@atlaskit/editor-common';
3
3
  import { SelectionStyle, getSelectionStyles, akEditorDeleteBackgroundWithOpacity, akEditorDeleteBorder, akEditorSelectedBorderSize, akEditorSelectedNodeClassName } from '@atlaskit/editor-shared-styles';
4
4
  export const statusStyles = css`
5
5
  .${StatusSharedCssClassName.STATUS_CONTAINER} {
6
+ // these two styles can be removed when displayInlineBlockForInlineNodes is enabled by default
7
+ // as it will make all inline nodes inline-block by default
6
8
  display: inline-block;
9
+ user-select: all;
7
10
 
8
11
  > span {
9
12
  display: inline-block;
@@ -1,5 +1,5 @@
1
1
  export const name = "@atlaskit/editor-core";
2
- export const version = "151.0.0";
2
+ export const version = "151.2.0";
3
3
  export const nextMajorVersion = () => {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-core",
3
- "version": "151.0.0",
3
+ "version": "151.2.0",
4
4
  "sideEffects": false
5
5
  }
@@ -5,7 +5,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
5
5
 
6
6
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
7
7
 
8
- import { breakoutPlugin, collabEditPlugin, dataConsumerMarkPlugin, datePlugin, emojiPlugin, extensionPlugin, helpDialogPlugin, imageUploadPlugin, insertBlockPlugin, jiraIssuePlugin, layoutPlugin, listPlugin, macroPlugin, maxContentSizePlugin, mediaPlugin, mentionsPlugin, panelPlugin, placeholderTextPlugin, rulePlugin, saveOnEnterPlugin, tablesPlugin, tasksAndDecisionsPlugin, textColorPlugin, cardPlugin, gridPlugin, statusPlugin, alignmentPlugin, indentationPlugin, analyticsPlugin, customAutoformatPlugin, feedbackDialogPlugin, historyPlugin, expandPlugin, isExpandInsertionEnabled, scrollIntoViewPlugin, mobileDimensionsPlugin, findReplacePlugin, contextPanelPlugin, mobileSelectionPlugin, annotationPlugin, captionPlugin, avatarGroupPlugin, viewUpdateSubscriptionPlugin } from '../plugins';
8
+ import { breakoutPlugin, collabEditPlugin, dataConsumerMarkPlugin, datePlugin, emojiPlugin, extensionPlugin, helpDialogPlugin, imageUploadPlugin, insertBlockPlugin, jiraIssuePlugin, layoutPlugin, listPlugin, macroPlugin, maxContentSizePlugin, mediaPlugin, mentionsPlugin, panelPlugin, placeholderTextPlugin, rulePlugin, saveOnEnterPlugin, tablesPlugin, tasksAndDecisionsPlugin, textColorPlugin, cardPlugin, gridPlugin, statusPlugin, alignmentPlugin, indentationPlugin, analyticsPlugin, customAutoformatPlugin, feedbackDialogPlugin, historyPlugin, expandPlugin, isExpandInsertionEnabled, scrollIntoViewPlugin, mobileDimensionsPlugin, findReplacePlugin, contextPanelPlugin, mobileSelectionPlugin, annotationPlugin, captionPlugin, avatarGroupPlugin, viewUpdateSubscriptionPlugin, codeBidiWarningPlugin } from '../plugins';
9
9
  import { isFullPage as fullPageCheck } from '../utils/is-full-page';
10
10
  import { GUTTER_SIZE_MOBILE_IN_PX } from '../plugins/base/pm-plugins/scroll-gutter';
11
11
  import { createFeatureFlagsFromProps } from '../plugins/feature-flags-context/feature-flags-from-props';
@@ -96,7 +96,8 @@ export function getDefaultPresetOptionsFromEditorProps(props, createAnalyticsEve
96
96
  },
97
97
  cardOptions: props.smartLinks || props.UNSAFE_cards,
98
98
  codeBlock: _objectSpread(_objectSpread({}, props.codeBlock), {}, {
99
- useLongPressSelection: false
99
+ useLongPressSelection: false,
100
+ appearance: props.appearance
100
101
  })
101
102
  };
102
103
  }
@@ -393,6 +394,12 @@ export default function createPluginsList(props, prevProps, createAnalyticsEvent
393
394
  preset.add([viewUpdateSubscriptionPlugin]);
394
395
  }
395
396
 
397
+ if (featureFlags.codeBidiWarnings) {
398
+ preset.add([codeBidiWarningPlugin, {
399
+ appearance: props.appearance
400
+ }]);
401
+ }
402
+
396
403
  var excludes = new Set();
397
404
 
398
405
  if (!isCodeBlockAllowed({
@@ -63,7 +63,9 @@ export function createDefaultPreset(options) {
63
63
  preset.add(floatingToolbarPlugin);
64
64
  preset.add([featureFlagsContextPlugin, options.featureFlags || {}]);
65
65
  preset.add([selectionPlugin, options.selection]);
66
- preset.add([codeBlockPlugin, options.codeBlock]);
66
+ preset.add([codeBlockPlugin, options.codeBlock || {
67
+ appearance: 'full-page'
68
+ }]);
67
69
  return preset;
68
70
  }
69
71
  export function useDefaultPreset(props) {
@@ -0,0 +1,20 @@
1
+ import { createPlugin } from './pm-plugins/main';
2
+
3
+ var codeBidiWarning = function codeBidiWarning(_ref) {
4
+ var appearance = _ref.appearance;
5
+ return {
6
+ name: 'codeBidiWarning',
7
+ pmPlugins: function pmPlugins() {
8
+ return [{
9
+ name: 'codeBidiWarning',
10
+ plugin: function plugin(options) {
11
+ return createPlugin(options, {
12
+ appearance: appearance
13
+ });
14
+ }
15
+ }];
16
+ }
17
+ };
18
+ };
19
+
20
+ export default codeBidiWarning;
@@ -0,0 +1,2 @@
1
+ import { PluginKey } from 'prosemirror-state';
2
+ export var codeBidiWarningPluginKey = new PluginKey('codeBidiWarningPlugin');
@@ -0,0 +1,39 @@
1
+ import { Plugin } from 'prosemirror-state';
2
+ import { codeBidiWarningMessages } from '@atlaskit/editor-common/messages';
3
+ import { codeBidiWarningPluginKey } from '../plugin-key';
4
+ import { createBidiWarningsDecorationSetFromDoc, createPluginState, getPluginState } from './plugin-factory';
5
+ export var createPlugin = function createPlugin(_ref, _ref2) {
6
+ var dispatch = _ref.dispatch,
7
+ reactContext = _ref.reactContext;
8
+ var appearance = _ref2.appearance;
9
+ var intl = reactContext().intl;
10
+ var codeBidiWarningLabel = intl.formatMessage(codeBidiWarningMessages.label);
11
+ return new Plugin({
12
+ key: codeBidiWarningPluginKey,
13
+ state: createPluginState(dispatch, function (state) {
14
+ // The appearance being mobile indicates we are in an editor being
15
+ // rendered by mobile bridge in a web view.
16
+ // The tooltip is likely to have unexpected behaviour there, with being cut
17
+ // off, so we disable it. This is also to keep the behaviour consistent with
18
+ // the rendering in the mobile Native Renderer.
19
+ var tooltipEnabled = appearance !== 'mobile';
20
+ return {
21
+ decorationSet: createBidiWarningsDecorationSetFromDoc({
22
+ doc: state.doc,
23
+ codeBidiWarningLabel: codeBidiWarningLabel,
24
+ tooltipEnabled: tooltipEnabled
25
+ }),
26
+ codeBidiWarningLabel: codeBidiWarningLabel,
27
+ tooltipEnabled: tooltipEnabled
28
+ };
29
+ }),
30
+ props: {
31
+ decorations: function decorations(state) {
32
+ var _getPluginState = getPluginState(state),
33
+ decorationSet = _getPluginState.decorationSet;
34
+
35
+ return decorationSet;
36
+ }
37
+ }
38
+ });
39
+ };
@@ -0,0 +1,106 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+
3
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
4
+
5
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
6
+
7
+ import React from 'react';
8
+ import ReactDOM from 'react-dom';
9
+ import { Decoration, DecorationSet } from 'prosemirror-view';
10
+ import CodeBidiWarning from '@atlaskit/code/bidi-warning';
11
+ import codeBidiWarningDecorator from '@atlaskit/code/bidi-warning-decorator';
12
+ import { pluginFactory } from '../../../utils/plugin-state-factory';
13
+ import { stepHasSlice } from '../../../utils/step';
14
+ import { codeBidiWarningPluginKey } from '../plugin-key';
15
+ import reducer from './reducer';
16
+
17
+ var _pluginFactory = pluginFactory(codeBidiWarningPluginKey, reducer, {
18
+ onDocChanged: function onDocChanged(tr, pluginState) {
19
+ if (!tr.steps.find(stepHasSlice)) {
20
+ return pluginState;
21
+ }
22
+
23
+ var newBidiWarningsDecorationSet = createBidiWarningsDecorationSetFromDoc({
24
+ doc: tr.doc,
25
+ codeBidiWarningLabel: pluginState.codeBidiWarningLabel,
26
+ tooltipEnabled: pluginState.tooltipEnabled
27
+ });
28
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
29
+ decorationSet: newBidiWarningsDecorationSet
30
+ });
31
+ }
32
+ }),
33
+ createPluginState = _pluginFactory.createPluginState,
34
+ getPluginState = _pluginFactory.getPluginState;
35
+
36
+ export { createPluginState, getPluginState };
37
+ export function createBidiWarningsDecorationSetFromDoc(_ref) {
38
+ var doc = _ref.doc,
39
+ codeBidiWarningLabel = _ref.codeBidiWarningLabel,
40
+ tooltipEnabled = _ref.tooltipEnabled;
41
+ var bidiCharactersAndTheirPositions = [];
42
+ doc.descendants(function (node, pos) {
43
+ var isTextWithCodeMark = node.type.name === 'text' && node.marks && node.marks.some(function (mark) {
44
+ return mark.type.name === 'code';
45
+ });
46
+
47
+ if (isTextWithCodeMark) {
48
+ codeBidiWarningDecorator(node.textContent, function (_ref2) {
49
+ var bidiCharacter = _ref2.bidiCharacter,
50
+ index = _ref2.index;
51
+ bidiCharactersAndTheirPositions.push({
52
+ position: pos + index,
53
+ bidiCharacter: bidiCharacter
54
+ });
55
+ });
56
+ return false;
57
+ }
58
+
59
+ var isCodeBlock = node.type.name === 'codeBlock';
60
+
61
+ if (isCodeBlock) {
62
+ codeBidiWarningDecorator(node.textContent, function (_ref3) {
63
+ var bidiCharacter = _ref3.bidiCharacter,
64
+ index = _ref3.index;
65
+ bidiCharactersAndTheirPositions.push({
66
+ position: pos + index + 1,
67
+ bidiCharacter: bidiCharacter
68
+ });
69
+ });
70
+ }
71
+ }); // Bidi characters are not expected to commonly appear in code snippets, so recreating the decoration set
72
+ // for documents rather than reusing existing decorations seems a reasonable performance/complexity tradeoff.
73
+
74
+ if (bidiCharactersAndTheirPositions.length === 0) {
75
+ return DecorationSet.empty;
76
+ }
77
+
78
+ var newBidiWarningsDecorationSet = DecorationSet.create(doc, bidiCharactersAndTheirPositions.map(function (_ref4) {
79
+ var position = _ref4.position,
80
+ bidiCharacter = _ref4.bidiCharacter;
81
+ return Decoration.widget(position, function () {
82
+ return renderDOM({
83
+ bidiCharacter: bidiCharacter,
84
+ codeBidiWarningLabel: codeBidiWarningLabel,
85
+ tooltipEnabled: tooltipEnabled
86
+ });
87
+ });
88
+ }));
89
+ return newBidiWarningsDecorationSet;
90
+ }
91
+
92
+ function renderDOM(_ref5) {
93
+ var bidiCharacter = _ref5.bidiCharacter,
94
+ codeBidiWarningLabel = _ref5.codeBidiWarningLabel,
95
+ tooltipEnabled = _ref5.tooltipEnabled;
96
+ var element = document.createElement('span'); // Note: we use this pattern elsewhere (see highlighting code block, and drop cursor widget decoration)
97
+ // we should investigate if there is a memory leak with such usage.
98
+
99
+ ReactDOM.render( /*#__PURE__*/React.createElement(CodeBidiWarning, {
100
+ bidiCharacter: bidiCharacter,
101
+ skipChildren: true,
102
+ label: codeBidiWarningLabel,
103
+ tooltipEnabled: tooltipEnabled
104
+ }), element);
105
+ return element;
106
+ }
@@ -0,0 +1,3 @@
1
+ export default (function (pluginState, action) {
2
+ return pluginState;
3
+ });