@atlaskit/editor-plugin-code-block-advanced 1.0.2 → 1.0.3

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 (49) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/afm-cc/tsconfig.json +6 -0
  3. package/afm-jira/tsconfig.json +6 -0
  4. package/afm-post-office/tsconfig.json +6 -0
  5. package/dist/cjs/nodeviews/codeBlockAdvanced.js +29 -26
  6. package/dist/cjs/nodeviews/codemirrorSync/syncCMWithPM.js +0 -1
  7. package/dist/cjs/nodeviews/extensions/keymap/index.js +23 -3
  8. package/dist/cjs/nodeviews/extensions/manageSelectionMarker.js +28 -0
  9. package/dist/cjs/nodeviews/extensions/prosemirrorDecorations.js +142 -0
  10. package/dist/es2019/nodeviews/codeBlockAdvanced.js +27 -27
  11. package/dist/es2019/nodeviews/codemirrorSync/syncCMWithPM.js +0 -1
  12. package/dist/es2019/nodeviews/extensions/keymap/index.js +23 -3
  13. package/dist/es2019/nodeviews/extensions/manageSelectionMarker.js +22 -0
  14. package/dist/es2019/nodeviews/extensions/prosemirrorDecorations.js +107 -0
  15. package/dist/esm/nodeviews/codeBlockAdvanced.js +30 -27
  16. package/dist/esm/nodeviews/codemirrorSync/syncCMWithPM.js +0 -1
  17. package/dist/esm/nodeviews/extensions/keymap/index.js +23 -3
  18. package/dist/esm/nodeviews/extensions/manageSelectionMarker.js +22 -0
  19. package/dist/esm/nodeviews/extensions/prosemirrorDecorations.js +135 -0
  20. package/dist/types/codeBlockAdvancedPluginType.d.ts +9 -1
  21. package/dist/types/nodeviews/codeBlockAdvanced.d.ts +10 -5
  22. package/dist/types/nodeviews/extensions/keymap/index.d.ts +2 -1
  23. package/dist/types/nodeviews/extensions/manageSelectionMarker.d.ts +10 -0
  24. package/dist/types/nodeviews/extensions/prosemirrorDecorations.d.ts +20 -0
  25. package/dist/types-ts4.5/codeBlockAdvancedPluginType.d.ts +5 -1
  26. package/dist/types-ts4.5/nodeviews/codeBlockAdvanced.d.ts +10 -5
  27. package/dist/types-ts4.5/nodeviews/extensions/keymap/index.d.ts +2 -1
  28. package/dist/types-ts4.5/nodeviews/extensions/manageSelectionMarker.d.ts +10 -0
  29. package/dist/types-ts4.5/nodeviews/extensions/prosemirrorDecorations.d.ts +20 -0
  30. package/package.json +3 -1
  31. package/src/codeBlockAdvancedPluginType.ts +9 -1
  32. package/src/nodeviews/codeBlockAdvanced.ts +31 -30
  33. package/src/nodeviews/codemirrorSync/syncCMWithPM.ts +0 -1
  34. package/src/nodeviews/extensions/keymap/index.ts +31 -1
  35. package/src/nodeviews/extensions/manageSelectionMarker.ts +28 -0
  36. package/src/nodeviews/extensions/prosemirrorDecorations.ts +156 -0
  37. package/tsconfig.app.json +6 -0
  38. package/dist/cjs/nodeviews/extensions/bidiCharWarning.js +0 -83
  39. package/dist/cjs/nodeviews/extensions/copyButtonDecorations.js +0 -22
  40. package/dist/es2019/nodeviews/extensions/bidiCharWarning.js +0 -53
  41. package/dist/es2019/nodeviews/extensions/copyButtonDecorations.js +0 -16
  42. package/dist/esm/nodeviews/extensions/bidiCharWarning.js +0 -77
  43. package/dist/esm/nodeviews/extensions/copyButtonDecorations.js +0 -16
  44. package/dist/types/nodeviews/extensions/bidiCharWarning.d.ts +0 -8
  45. package/dist/types/nodeviews/extensions/copyButtonDecorations.d.ts +0 -1
  46. package/dist/types-ts4.5/nodeviews/extensions/bidiCharWarning.d.ts +0 -8
  47. package/dist/types-ts4.5/nodeviews/extensions/copyButtonDecorations.d.ts +0 -1
  48. package/src/nodeviews/extensions/bidiCharWarning.ts +0 -72
  49. package/src/nodeviews/extensions/copyButtonDecorations.ts +0 -15
@@ -0,0 +1,20 @@
1
+ import { Facet } from '@codemirror/state';
2
+ import { ViewPlugin, EditorView as CodeMirror, DecorationSet, ViewUpdate } from '@codemirror/view';
3
+ import type { EditorView, DecorationSource } from '@atlaskit/editor-prosemirror/view';
4
+ /**
5
+ * Creates CodeMirror versions of the decorations provided by ProseMirror.
6
+ *
7
+ * Inline ProseMirror decorations -> Mark CodeMirror decorations
8
+ * Widget ProseMirror decorations -> Widget CodeMirror decorations
9
+ *
10
+ * This way any decorations applied in ProseMirror land should automatically be supported
11
+ * by the CodeMirror editor
12
+ *
13
+ * @param updateDecorationsEffect Facet for the prosemirror decorations
14
+ * @returns CodeMirror extension
15
+ */
16
+ export declare const prosemirrorDecorationPlugin: (updateDecorationsEffect: Facet<DecorationSource>, editorView: EditorView, getPos: () => number | undefined) => ViewPlugin<{
17
+ decorations: DecorationSet;
18
+ updateDecorations(view: CodeMirror): DecorationSet;
19
+ update(update: ViewUpdate): void;
20
+ }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-code-block-advanced",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "CodeBlockAdvanced plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -36,7 +36,9 @@
36
36
  "@atlaskit/editor-common": "^99.5.0",
37
37
  "@atlaskit/editor-plugin-code-block": "^3.6.0",
38
38
  "@atlaskit/editor-plugin-editor-disabled": "^1.3.0",
39
+ "@atlaskit/editor-plugin-find-replace": "^1.7.0",
39
40
  "@atlaskit/editor-plugin-selection": "^1.6.0",
41
+ "@atlaskit/editor-plugin-selection-marker": "^1.6.0",
40
42
  "@atlaskit/editor-prosemirror": "6.2.1",
41
43
  "@atlaskit/tokens": "^3.2.0",
42
44
  "@babel/runtime": "^7.0.0",
@@ -3,12 +3,20 @@ import type { Extension } from '@codemirror/state';
3
3
  import type { NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
4
4
  import type { CodeBlockPlugin } from '@atlaskit/editor-plugin-code-block';
5
5
  import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
6
+ import type { FindReplacePlugin } from '@atlaskit/editor-plugin-find-replace';
6
7
  import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
8
+ import type { SelectionMarkerPlugin } from '@atlaskit/editor-plugin-selection-marker';
7
9
 
8
10
  export type CodeBlockAdvancedPlugin = NextEditorPlugin<
9
11
  'codeBlockAdvanced',
10
12
  {
11
- dependencies: [CodeBlockPlugin, SelectionPlugin, OptionalPlugin<EditorDisabledPlugin>];
13
+ dependencies: [
14
+ CodeBlockPlugin,
15
+ SelectionPlugin,
16
+ OptionalPlugin<EditorDisabledPlugin>,
17
+ OptionalPlugin<SelectionMarkerPlugin>,
18
+ OptionalPlugin<FindReplacePlugin>,
19
+ ];
12
20
  pluginConfiguration:
13
21
  | {
14
22
  extensions?: Extension[];
@@ -1,6 +1,6 @@
1
1
  import { closeBrackets } from '@codemirror/autocomplete';
2
2
  import { syntaxHighlighting, bracketMatching } from '@codemirror/language';
3
- import { Compartment, Extension, EditorSelection } from '@codemirror/state';
3
+ import { Compartment, Extension, EditorSelection, Facet } from '@codemirror/state';
4
4
  import { EditorView as CodeMirror, lineNumbers, ViewUpdate, gutters } from '@codemirror/view';
5
5
 
6
6
  import { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
@@ -13,7 +13,12 @@ import type {
13
13
  import { EditorSelectionAPI } from '@atlaskit/editor-plugin-selection';
14
14
  import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
15
15
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
16
- import type { EditorView, NodeView } from '@atlaskit/editor-prosemirror/view';
16
+ import type {
17
+ Decoration,
18
+ DecorationSource,
19
+ EditorView,
20
+ NodeView,
21
+ } from '@atlaskit/editor-prosemirror/view';
17
22
 
18
23
  import type { CodeBlockAdvancedPlugin } from '../codeBlockAdvancedPluginType';
19
24
  import { highlightStyle } from '../ui/syntaxHighlightingTheme';
@@ -21,9 +26,9 @@ import { cmTheme } from '../ui/theme';
21
26
 
22
27
  import { syncCMWithPM } from './codemirrorSync/syncCMWithPM';
23
28
  import { updateCMSelection } from './codemirrorSync/updateCMSelection';
24
- import { bidiCharWarningExtension } from './extensions/bidiCharWarning';
25
- import { copyButtonDecorations } from './extensions/copyButtonDecorations';
26
29
  import { keymapExtension } from './extensions/keymap';
30
+ import { manageSelectionMarker } from './extensions/manageSelectionMarker';
31
+ import { prosemirrorDecorationPlugin } from './extensions/prosemirrorDecorations';
27
32
  import { LanguageLoader } from './languages/loader';
28
33
 
29
34
  interface ConfigProps {
@@ -39,17 +44,16 @@ class CodeBlockAdvancedNodeView implements NodeView {
39
44
  private lineWrappingCompartment = new Compartment();
40
45
  private languageCompartment = new Compartment();
41
46
  private readOnlyCompartment = new Compartment();
42
- private copyDecoCompartment = new Compartment();
47
+ private pmDecorationsCompartment = new Compartment();
43
48
  private node: PMNode;
44
49
  private getPos: getPosHandlerNode;
45
50
  private cm: CodeMirror;
46
51
  private selectionAPI: EditorSelectionAPI | undefined;
47
52
  private maybeTryingToReachNodeSelection = false;
48
53
  private cleanupDisabledState: (() => void) | undefined;
49
- private cleanupCopyButtonDecoration: (() => void) | undefined;
50
54
  private languageLoader: LanguageLoader;
55
+ private pmFacet = Facet.define<DecorationSource>();
51
56
 
52
- // eslint-disable-next-line @typescript-eslint/max-params
53
57
  constructor(node: PMNode, view: EditorView, getPos: getPosHandlerNode, config: ConfigProps) {
54
58
  this.node = node;
55
59
  this.view = view;
@@ -60,13 +64,6 @@ class CodeBlockAdvancedNodeView implements NodeView {
60
64
  this.cleanupDisabledState = config.api?.editorDisabled?.sharedState.onChange(() => {
61
65
  this.updateReadonlyState();
62
66
  });
63
- this.cleanupCopyButtonDecoration = config.api?.codeBlock?.sharedState.onChange(
64
- ({ nextSharedState, prevSharedState }) => {
65
- if (nextSharedState?.copyButtonHoverNode !== prevSharedState?.copyButtonHoverNode) {
66
- this.addCopyButtonDecoration(nextSharedState?.copyButtonHoverNode);
67
- }
68
- },
69
- );
70
67
  this.languageLoader = new LanguageLoader((lang) => {
71
68
  this.updating = true;
72
69
  this.cm.dispatch({
@@ -81,13 +78,14 @@ class CodeBlockAdvancedNodeView implements NodeView {
81
78
  ...config.extensions,
82
79
  this.lineWrappingCompartment.of([]),
83
80
  this.languageCompartment.of([]),
84
- this.copyDecoCompartment.of([]),
81
+ this.pmDecorationsCompartment.of([]),
85
82
  keymapExtension({
86
83
  view,
87
84
  getPos,
88
85
  getNode,
89
86
  selectCodeBlockNode: this.selectCodeBlockNode.bind(this),
90
87
  onMaybeNodeSelection,
88
+ customFindReplace: Boolean(config.api?.findReplace),
91
89
  }),
92
90
  cmTheme,
93
91
  syntaxHighlighting(highlightStyle),
@@ -100,7 +98,8 @@ class CodeBlockAdvancedNodeView implements NodeView {
100
98
  this.readOnlyCompartment.of(CodeMirror.editable.of(this.view.editable)),
101
99
  closeBrackets(),
102
100
  CodeMirror.editorAttributes.of({ class: 'code-block' }),
103
- bidiCharWarningExtension,
101
+ manageSelectionMarker(config.api),
102
+ prosemirrorDecorationPlugin(this.pmFacet, view, getPos),
104
103
  ],
105
104
  });
106
105
 
@@ -115,7 +114,6 @@ class CodeBlockAdvancedNodeView implements NodeView {
115
114
 
116
115
  destroy() {
117
116
  this.cleanupDisabledState?.();
118
- this.cleanupCopyButtonDecoration?.();
119
117
  }
120
118
 
121
119
  forwardUpdate(update: ViewUpdate) {
@@ -162,18 +160,6 @@ class CodeBlockAdvancedNodeView implements NodeView {
162
160
  }
163
161
  }
164
162
 
165
- private addCopyButtonDecoration(node: PMNode | undefined) {
166
- this.updating = true;
167
- this.cm.dispatch({
168
- effects: [
169
- this.copyDecoCompartment.reconfigure(
170
- node && node === this.node ? copyButtonDecorations : [],
171
- ),
172
- ],
173
- });
174
- this.updating = false;
175
- }
176
-
177
163
  private wordWrappingEnabled = false;
178
164
 
179
165
  private updateWordWrap(node: PMNode) {
@@ -191,7 +177,7 @@ class CodeBlockAdvancedNodeView implements NodeView {
191
177
  }
192
178
  }
193
179
 
194
- update(node: PMNode) {
180
+ update(node: PMNode, _: readonly Decoration[], innerDecorations: DecorationSource) {
195
181
  this.maybeTryingToReachNodeSelection = false;
196
182
 
197
183
  if (node.type !== this.node.type) {
@@ -210,9 +196,24 @@ class CodeBlockAdvancedNodeView implements NodeView {
210
196
  this.cm.dispatch(tr);
211
197
  this.updating = false;
212
198
  });
199
+ this.updateProseMirrorDecorations(innerDecorations);
213
200
  return true;
214
201
  }
215
202
 
203
+ /**
204
+ * Updates a facet which stores information on the prosemirror decorations
205
+ *
206
+ * This then gets translated to codemirror decorations in `prosemirrorDecorationPlugin`
207
+ */
208
+ private updateProseMirrorDecorations(decorationSource: DecorationSource) {
209
+ this.updating = true;
210
+ const computedFacet = this.pmFacet.compute([], () => decorationSource);
211
+ this.cm.dispatch({
212
+ effects: this.pmDecorationsCompartment.reconfigure(computedFacet),
213
+ });
214
+ this.updating = false;
215
+ }
216
+
216
217
  stopEvent(e: Event) {
217
218
  if (e instanceof MouseEvent && e.type === 'mousedown') {
218
219
  // !Warning: Side effect!
@@ -25,7 +25,6 @@ export const syncCMWithPM = ({ view, update, offset }: Props): void => {
25
25
  const pmSel = view.state.selection;
26
26
  if (update.docChanged || pmSel.from !== selFrom || pmSel.to !== selTo) {
27
27
  const tr = view.state.tr;
28
- // eslint-disable-next-line @typescript-eslint/max-params
29
28
  update.changes.iterChanges((fromA, toA, fromB, toB, text) => {
30
29
  if (text.length) {
31
30
  tr.replaceWith(offset + fromA, offset + toA, view.state.schema.text(text.toString()));
@@ -2,6 +2,7 @@ import { defaultKeymap, indentWithTab } from '@codemirror/commands';
2
2
  import { Extension } from '@codemirror/state';
3
3
  import { KeyBinding, keymap as cmKeymap } from '@codemirror/view';
4
4
 
5
+ import { browser } from '@atlaskit/editor-common/browser';
5
6
  import { RelativeSelectionPos } from '@atlaskit/editor-common/selection';
6
7
  import type { getPosHandlerNode } from '@atlaskit/editor-common/types';
7
8
  import { exitCode } from '@atlaskit/editor-prosemirror/commands';
@@ -18,6 +19,7 @@ interface KeymapProps {
18
19
  getPos: getPosHandlerNode;
19
20
  selectCodeBlockNode: (relativeSelectionPos: RelativeSelectionPos | undefined) => void;
20
21
  onMaybeNodeSelection: () => void;
22
+ customFindReplace: boolean;
21
23
  }
22
24
 
23
25
  export const keymapExtension = ({
@@ -26,9 +28,17 @@ export const keymapExtension = ({
26
28
  getPos,
27
29
  selectCodeBlockNode,
28
30
  onMaybeNodeSelection,
31
+ customFindReplace,
29
32
  }: KeymapProps): Extension => {
30
33
  return cmKeymap.of(
31
- codeBlockKeymap({ view, getNode, getPos, selectCodeBlockNode, onMaybeNodeSelection }),
34
+ codeBlockKeymap({
35
+ view,
36
+ getNode,
37
+ getPos,
38
+ selectCodeBlockNode,
39
+ onMaybeNodeSelection,
40
+ customFindReplace,
41
+ }),
32
42
  );
33
43
  };
34
44
 
@@ -38,6 +48,7 @@ const codeBlockKeymap = ({
38
48
  getPos,
39
49
  selectCodeBlockNode,
40
50
  onMaybeNodeSelection,
51
+ customFindReplace,
41
52
  }: KeymapProps): readonly KeyBinding[] => {
42
53
  return [
43
54
  {
@@ -96,6 +107,25 @@ const codeBlockKeymap = ({
96
107
  onMaybeNodeSelection,
97
108
  }),
98
109
  },
110
+ {
111
+ key: 'Ctrl-f',
112
+ mac: 'Cmd-f',
113
+ run: () => {
114
+ // Pass synthetic event to prosemirror
115
+ if (customFindReplace) {
116
+ view.dispatchEvent(
117
+ new KeyboardEvent('keydown', {
118
+ key: 'f',
119
+ code: 'KeyF',
120
+ metaKey: browser.mac ? true : false,
121
+ ctrlKey: browser.mac ? false : true,
122
+ }),
123
+ );
124
+ return true;
125
+ }
126
+ return false;
127
+ },
128
+ },
99
129
  {
100
130
  key: 'Ctrl-Enter',
101
131
  run: () => {
@@ -0,0 +1,28 @@
1
+ import { Extension } from '@codemirror/state';
2
+ import { EditorView as CodeMirror } from '@codemirror/view';
3
+
4
+ import { type ExtractInjectionAPI } from '@atlaskit/editor-common/types';
5
+
6
+ import { CodeBlockAdvancedPlugin } from '../../codeBlockAdvancedPluginType';
7
+
8
+ /**
9
+ * Hides selection marker decoration when focused on codemirror editor and re-enables on blur
10
+ *
11
+ * @param api
12
+ * @returns CodeMirror Extension
13
+ */
14
+ export const manageSelectionMarker = (
15
+ api: ExtractInjectionAPI<CodeBlockAdvancedPlugin> | undefined,
16
+ ): Extension => {
17
+ let decoHide: (() => void) | undefined;
18
+ return CodeMirror.focusChangeEffect.of((_state, focusing) => {
19
+ if (focusing) {
20
+ api?.selectionMarker?.actions.queueHideDecoration((hideDecoration) => {
21
+ decoHide = hideDecoration;
22
+ });
23
+ } else {
24
+ decoHide?.();
25
+ }
26
+ return null;
27
+ });
28
+ };
@@ -0,0 +1,156 @@
1
+ import { Facet } from '@codemirror/state';
2
+ import {
3
+ ViewPlugin,
4
+ WidgetType,
5
+ Decoration as CodeMirrorDecoration,
6
+ EditorView as CodeMirror,
7
+ DecorationSet,
8
+ ViewUpdate,
9
+ } from '@codemirror/view';
10
+
11
+ import type { EditorView, Decoration, DecorationSource } from '@atlaskit/editor-prosemirror/view';
12
+
13
+ class PMWidget extends WidgetType {
14
+ constructor(readonly toDOMElement: HTMLElement) {
15
+ super();
16
+ }
17
+ toDOM() {
18
+ return this.toDOMElement;
19
+ }
20
+ ignoreEvent() {
21
+ return false;
22
+ }
23
+ }
24
+
25
+ // This type is not exposed publically by ProseMirror but we need it to map to CodeMirror
26
+ // See: https://github.com/ProseMirror/prosemirror-view/blob/master/src/decoration.ts
27
+ type WidgetConstructor = ((view: EditorView, getPos: () => number | undefined) => Node) | Node;
28
+
29
+ // This type is not exposed publically by ProseMirror but we need it to map to CodeMirror
30
+ // See: https://github.com/ProseMirror/prosemirror-view/blob/master/src/decoration.ts
31
+ interface ExtendedProseMirrorDecoration extends Decoration {
32
+ inline: boolean;
33
+ widget: boolean;
34
+ type: {
35
+ attrs?: Record<string, string>;
36
+ toDOM?: WidgetConstructor;
37
+ side?: number;
38
+ };
39
+ }
40
+
41
+ // This type is not exposed publically by ProseMirror but we need it to map to CodeMirror
42
+ // See: https://github.com/ProseMirror/prosemirror-view/blob/master/src/decoration.ts
43
+ function isExtendedDecoration(decoration: Decoration): decoration is ExtendedProseMirrorDecoration {
44
+ return (
45
+ (decoration as ExtendedProseMirrorDecoration).inline !== undefined &&
46
+ (decoration as ExtendedProseMirrorDecoration).widget !== undefined &&
47
+ (decoration as ExtendedProseMirrorDecoration).type !== undefined
48
+ );
49
+ }
50
+
51
+ const getHTMLElement = (
52
+ toDOM: WidgetConstructor | undefined,
53
+ view: EditorView,
54
+ getPos: () => number | undefined,
55
+ ): HTMLElement | undefined => {
56
+ if (toDOM instanceof Function) {
57
+ const element = toDOM(view, getPos);
58
+ return element instanceof HTMLElement ? element : undefined;
59
+ } else if (toDOM instanceof HTMLElement) {
60
+ return toDOM;
61
+ }
62
+ };
63
+
64
+ const mapPMDecorationToCMDecoration = (
65
+ decoration: Decoration,
66
+ view: EditorView,
67
+ getPos: () => number | undefined,
68
+ ) => {
69
+ if (!isExtendedDecoration(decoration)) {
70
+ return undefined;
71
+ }
72
+ if (decoration.inline) {
73
+ const markDecoration = CodeMirrorDecoration.mark({
74
+ attributes: decoration.type.attrs,
75
+ });
76
+ return markDecoration.range(decoration.from, decoration.to);
77
+ } else if (decoration.widget) {
78
+ const toDOM = getHTMLElement(decoration?.type?.toDOM, view, getPos);
79
+ if (!toDOM) {
80
+ return undefined;
81
+ }
82
+
83
+ const widgetDecoration = CodeMirrorDecoration.widget({
84
+ widget: new PMWidget(toDOM),
85
+ side: decoration.type.side,
86
+ });
87
+ return widgetDecoration.range(decoration.from, decoration.to);
88
+ }
89
+ };
90
+
91
+ function isDefined<TValue>(value: TValue | undefined): value is TValue {
92
+ return value !== undefined;
93
+ }
94
+
95
+ /**
96
+ * Creates CodeMirror versions of the decorations provided by ProseMirror.
97
+ *
98
+ * Inline ProseMirror decorations -> Mark CodeMirror decorations
99
+ * Widget ProseMirror decorations -> Widget CodeMirror decorations
100
+ *
101
+ * This way any decorations applied in ProseMirror land should automatically be supported
102
+ * by the CodeMirror editor
103
+ *
104
+ * @param updateDecorationsEffect Facet for the prosemirror decorations
105
+ * @returns CodeMirror extension
106
+ */
107
+ export const prosemirrorDecorationPlugin = (
108
+ updateDecorationsEffect: Facet<DecorationSource>,
109
+ editorView: EditorView,
110
+ getPos: () => number | undefined,
111
+ ) =>
112
+ ViewPlugin.fromClass(
113
+ class {
114
+ decorations: DecorationSet;
115
+
116
+ constructor(view: CodeMirror) {
117
+ this.decorations = this.updateDecorations(view);
118
+ }
119
+ updateDecorations(view: CodeMirror) {
120
+ const { from, to } = view.viewport;
121
+
122
+ const innnerDecorations = view.state.facet(updateDecorationsEffect);
123
+ const allDecorations: Decoration[] = [];
124
+ innnerDecorations?.map((source) => {
125
+ // Temporary: this only exists on prosemirror-view@1.34.0. Since post-office is lower it causes an error.
126
+ // Once we do our prosemirror bump (very soon) we should remove this.
127
+ // https://product-fabric.atlassian.net/browse/ED-26398
128
+ // @ts-ignore
129
+ source?.forEachSet((set) => {
130
+ const decorations = set
131
+ .find(from, to)
132
+ // Do not render the code block line decorations
133
+ // Temporary: this only exists on prosemirror-view@1.34.0. Since post-office is lower it causes an error.
134
+ // Once we do our prosemirror bump (very soon) we should remove this.
135
+ // https://product-fabric.atlassian.net/browse/ED-26398
136
+ // @ts-ignore
137
+ .filter((dec) => dec.spec.type !== 'decorationWidgetType');
138
+ allDecorations.push(...decorations);
139
+ });
140
+ });
141
+
142
+ const cmDecorations = allDecorations
143
+ .sort((a, b) => (a.from < b.from ? -1 : 1))
144
+ .map((decoration) => mapPMDecorationToCMDecoration(decoration, editorView, getPos))
145
+ .filter(isDefined);
146
+
147
+ return CodeMirrorDecoration.set(cmDecorations);
148
+ }
149
+ update(update: ViewUpdate) {
150
+ this.decorations = this.updateDecorations(update.view);
151
+ }
152
+ },
153
+ {
154
+ decorations: (v) => v.decorations,
155
+ },
156
+ );
package/tsconfig.app.json CHANGED
@@ -43,9 +43,15 @@
43
43
  {
44
44
  "path": "../editor-plugin-editor-disabled/tsconfig.app.json"
45
45
  },
46
+ {
47
+ "path": "../editor-plugin-find-replace/tsconfig.app.json"
48
+ },
46
49
  {
47
50
  "path": "../editor-plugin-selection/tsconfig.app.json"
48
51
  },
52
+ {
53
+ "path": "../editor-plugin-selection-marker/tsconfig.app.json"
54
+ },
49
55
  {
50
56
  "path": "../../design-system/tokens/tsconfig.app.json"
51
57
  }
@@ -1,83 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
6
- });
7
- exports.bidiCharWarningExtension = void 0;
8
- var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
9
- var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
10
- var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
11
- var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
12
- var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
13
- var _view = require("@codemirror/view");
14
- function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
15
- function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } /**
16
- * Code based on warning from @atlaskit/code
17
- */
18
- var bidiCharacterRegex = /[\u202A-\u202E\u2066-\u2069]/g;
19
- var placeholderMatcher = new _view.MatchDecorator({
20
- regexp: bidiCharacterRegex,
21
- decoration: function decoration(match) {
22
- return _view.Decoration.replace({
23
- widget: new PlaceholderWidget(match[0])
24
- });
25
- }
26
- });
27
- var bidiCharWarningExtension = exports.bidiCharWarningExtension = _view.ViewPlugin.fromClass( /*#__PURE__*/function () {
28
- function _class(view) {
29
- (0, _classCallCheck2.default)(this, _class);
30
- this.placeholders = placeholderMatcher.createDeco(view);
31
- }
32
- return (0, _createClass2.default)(_class, [{
33
- key: "update",
34
- value: function update(_update) {
35
- this.placeholders = placeholderMatcher.updateDeco(_update, this.placeholders);
36
- }
37
- }]);
38
- }(), {
39
- decorations: function decorations(instance) {
40
- return instance.placeholders;
41
- },
42
- provide: function provide(plugin) {
43
- return _view.EditorView.atomicRanges.of(function (view) {
44
- var _view$plugin;
45
- return ((_view$plugin = view.plugin(plugin)) === null || _view$plugin === void 0 ? void 0 : _view$plugin.placeholders) || _view.Decoration.none;
46
- });
47
- }
48
- });
49
- function getBidiCharacterCode(bidiCharacter) {
50
- var _bidiCharacter$codePo;
51
- var bidiCharacterCode = (_bidiCharacter$codePo = bidiCharacter.codePointAt(0)) === null || _bidiCharacter$codePo === void 0 ? void 0 : _bidiCharacter$codePo.toString(16);
52
- return "U+".concat(bidiCharacterCode);
53
- }
54
- var PlaceholderWidget = /*#__PURE__*/function (_WidgetType) {
55
- function PlaceholderWidget(name) {
56
- var _this;
57
- (0, _classCallCheck2.default)(this, PlaceholderWidget);
58
- _this = _callSuper(this, PlaceholderWidget);
59
- _this.name = name;
60
- return _this;
61
- }
62
- (0, _inherits2.default)(PlaceholderWidget, _WidgetType);
63
- return (0, _createClass2.default)(PlaceholderWidget, [{
64
- key: "eq",
65
- value: function eq(other) {
66
- return this.name === other.name;
67
- }
68
- }, {
69
- key: "toDOM",
70
- value: function toDOM() {
71
- var elt = document.createElement('span');
72
- elt.setAttribute('data-bidi-character-code', this.name);
73
- elt.style.cssText = "\n padding: 0 3px;\n color: ".concat("var(--ds-text-warning, #A54800)", ";\n\t\t\tbackground: ", "var(--ds-background-warning, #FFF7D6)", ";\n\t\t\taria-hidden=\"true\"");
74
- elt.textContent = "<".concat(getBidiCharacterCode(this.name), ">");
75
- return elt;
76
- }
77
- }, {
78
- key: "ignoreEvent",
79
- value: function ignoreEvent() {
80
- return false;
81
- }
82
- }]);
83
- }(_view.WidgetType);
@@ -1,22 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.copyButtonDecorations = void 0;
7
- var _state = require("@codemirror/state");
8
- var _view = require("@codemirror/view");
9
- var copyButtonDecorations = exports.copyButtonDecorations = _view.EditorView.decorations.compute([], function (state) {
10
- var allTextDecoration = _view.Decoration.mark({
11
- attributes: {
12
- class: 'ProseMirror-fake-text-selection'
13
- }
14
- });
15
- // Create a set of decorations for the entire document
16
- var builder = new _state.RangeSetBuilder();
17
- for (var i = 0; i < state.doc.lines; i++) {
18
- builder.add(state.doc.line(i + 1).from, state.doc.line(i + 1).to, allTextDecoration);
19
- }
20
- var decorations = builder.finish();
21
- return decorations;
22
- });
@@ -1,53 +0,0 @@
1
- /**
2
- * Code based on warning from @atlaskit/code
3
- */
4
- import { EditorView as CodeMirror, ViewPlugin, Decoration, MatchDecorator, WidgetType } from '@codemirror/view';
5
- const bidiCharacterRegex = /[\u202A-\u202E\u2066-\u2069]/gu;
6
- const placeholderMatcher = new MatchDecorator({
7
- regexp: bidiCharacterRegex,
8
- decoration: match => Decoration.replace({
9
- widget: new PlaceholderWidget(match[0])
10
- })
11
- });
12
- export const bidiCharWarningExtension = ViewPlugin.fromClass(class {
13
- constructor(view) {
14
- this.placeholders = placeholderMatcher.createDeco(view);
15
- }
16
- update(update) {
17
- this.placeholders = placeholderMatcher.updateDeco(update, this.placeholders);
18
- }
19
- }, {
20
- decorations: instance => instance.placeholders,
21
- provide: plugin => CodeMirror.atomicRanges.of(view => {
22
- var _view$plugin;
23
- return ((_view$plugin = view.plugin(plugin)) === null || _view$plugin === void 0 ? void 0 : _view$plugin.placeholders) || Decoration.none;
24
- })
25
- });
26
- function getBidiCharacterCode(bidiCharacter) {
27
- var _bidiCharacter$codePo;
28
- const bidiCharacterCode = (_bidiCharacter$codePo = bidiCharacter.codePointAt(0)) === null || _bidiCharacter$codePo === void 0 ? void 0 : _bidiCharacter$codePo.toString(16);
29
- return `U+${bidiCharacterCode}`;
30
- }
31
- class PlaceholderWidget extends WidgetType {
32
- constructor(name) {
33
- super();
34
- this.name = name;
35
- }
36
- eq(other) {
37
- return this.name === other.name;
38
- }
39
- toDOM() {
40
- const elt = document.createElement('span');
41
- elt.setAttribute('data-bidi-character-code', this.name);
42
- elt.style.cssText = `
43
- padding: 0 3px;
44
- color: ${"var(--ds-text-warning, #A54800)"};
45
- background: ${"var(--ds-background-warning, #FFF7D6)"};
46
- aria-hidden="true"`;
47
- elt.textContent = `<${getBidiCharacterCode(this.name)}>`;
48
- return elt;
49
- }
50
- ignoreEvent() {
51
- return false;
52
- }
53
- }
@@ -1,16 +0,0 @@
1
- import { RangeSetBuilder } from '@codemirror/state';
2
- import { EditorView as CodeMirror, Decoration } from '@codemirror/view';
3
- export const copyButtonDecorations = CodeMirror.decorations.compute([], state => {
4
- const allTextDecoration = Decoration.mark({
5
- attributes: {
6
- class: 'ProseMirror-fake-text-selection'
7
- }
8
- });
9
- // Create a set of decorations for the entire document
10
- const builder = new RangeSetBuilder();
11
- for (let i = 0; i < state.doc.lines; i++) {
12
- builder.add(state.doc.line(i + 1).from, state.doc.line(i + 1).to, allTextDecoration);
13
- }
14
- const decorations = builder.finish();
15
- return decorations;
16
- });