@atlaskit/editor-plugin-code-block-advanced 1.0.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.
- package/CHANGELOG.md +13 -0
- package/LICENSE.md +11 -0
- package/README.md +1 -0
- package/afm-cc/tsconfig.json +36 -0
- package/build/tsconfig.json +17 -0
- package/dist/cjs/codeBlockAdvancedPlugin.js +33 -0
- package/dist/cjs/codeBlockAdvancedPluginType.js +5 -0
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/nodeviews/codeBlockAdvanced.js +212 -0
- package/dist/cjs/nodeviews/codeBlockNodeWithToDOMFixed.js +55 -0
- package/dist/cjs/nodeviews/codemirrorSync/syncCMWithPM.js +38 -0
- package/dist/cjs/nodeviews/codemirrorSync/updateCMSelection.js +36 -0
- package/dist/cjs/nodeviews/extensions/bidiCharWarning.js +83 -0
- package/dist/cjs/nodeviews/extensions/keymap/backspace.js +33 -0
- package/dist/cjs/nodeviews/extensions/keymap/index.js +129 -0
- package/dist/cjs/nodeviews/extensions/keymap/maybeEscape.js +63 -0
- package/dist/cjs/nodeviews/languages/languageMap.js +100 -0
- package/dist/cjs/nodeviews/languages/loader.js +50 -0
- package/dist/cjs/nodeviews/lazyCodeBlockAdvanced.js +29 -0
- package/dist/cjs/pm-plugins/main.js +17 -0
- package/dist/cjs/ui/syntaxHighlightingTheme.js +76 -0
- package/dist/cjs/ui/theme.js +55 -0
- package/dist/es2019/codeBlockAdvancedPlugin.js +26 -0
- package/dist/es2019/codeBlockAdvancedPluginType.js +1 -0
- package/dist/es2019/index.js +4 -0
- package/dist/es2019/nodeviews/codeBlockAdvanced.js +170 -0
- package/dist/es2019/nodeviews/codeBlockNodeWithToDOMFixed.js +42 -0
- package/dist/es2019/nodeviews/codemirrorSync/syncCMWithPM.js +35 -0
- package/dist/es2019/nodeviews/codemirrorSync/updateCMSelection.js +30 -0
- package/dist/es2019/nodeviews/extensions/bidiCharWarning.js +53 -0
- package/dist/es2019/nodeviews/extensions/keymap/backspace.js +28 -0
- package/dist/es2019/nodeviews/extensions/keymap/index.js +107 -0
- package/dist/es2019/nodeviews/extensions/keymap/maybeEscape.js +57 -0
- package/dist/es2019/nodeviews/languages/languageMap.js +82 -0
- package/dist/es2019/nodeviews/languages/loader.js +37 -0
- package/dist/es2019/nodeviews/lazyCodeBlockAdvanced.js +18 -0
- package/dist/es2019/pm-plugins/main.js +11 -0
- package/dist/es2019/ui/syntaxHighlightingTheme.js +70 -0
- package/dist/es2019/ui/theme.js +49 -0
- package/dist/esm/codeBlockAdvancedPlugin.js +27 -0
- package/dist/esm/codeBlockAdvancedPluginType.js +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/nodeviews/codeBlockAdvanced.js +205 -0
- package/dist/esm/nodeviews/codeBlockNodeWithToDOMFixed.js +48 -0
- package/dist/esm/nodeviews/codemirrorSync/syncCMWithPM.js +32 -0
- package/dist/esm/nodeviews/codemirrorSync/updateCMSelection.js +30 -0
- package/dist/esm/nodeviews/extensions/bidiCharWarning.js +77 -0
- package/dist/esm/nodeviews/extensions/keymap/backspace.js +27 -0
- package/dist/esm/nodeviews/extensions/keymap/index.js +122 -0
- package/dist/esm/nodeviews/extensions/keymap/maybeEscape.js +56 -0
- package/dist/esm/nodeviews/languages/languageMap.js +86 -0
- package/dist/esm/nodeviews/languages/loader.js +44 -0
- package/dist/esm/nodeviews/lazyCodeBlockAdvanced.js +17 -0
- package/dist/esm/pm-plugins/main.js +11 -0
- package/dist/esm/ui/syntaxHighlightingTheme.js +70 -0
- package/dist/esm/ui/theme.js +49 -0
- package/dist/types/codeBlockAdvancedPlugin.d.ts +2 -0
- package/dist/types/codeBlockAdvancedPluginType.d.ts +11 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/nodeviews/codeBlockAdvanced.d.ts +38 -0
- package/dist/types/nodeviews/codeBlockNodeWithToDOMFixed.d.ts +2 -0
- package/dist/types/nodeviews/codemirrorSync/syncCMWithPM.d.ts +17 -0
- package/dist/types/nodeviews/codemirrorSync/updateCMSelection.d.ts +11 -0
- package/dist/types/nodeviews/extensions/bidiCharWarning.d.ts +8 -0
- package/dist/types/nodeviews/extensions/keymap/backspace.d.ts +12 -0
- package/dist/types/nodeviews/extensions/keymap/index.d.ts +14 -0
- package/dist/types/nodeviews/extensions/keymap/maybeEscape.d.ts +17 -0
- package/dist/types/nodeviews/languages/languageMap.d.ts +5 -0
- package/dist/types/nodeviews/languages/loader.d.ts +11 -0
- package/dist/types/nodeviews/lazyCodeBlockAdvanced.d.ts +9 -0
- package/dist/types/pm-plugins/main.d.ts +10 -0
- package/dist/types/ui/syntaxHighlightingTheme.d.ts +2 -0
- package/dist/types/ui/theme.d.ts +1 -0
- package/dist/types-ts4.5/codeBlockAdvancedPlugin.d.ts +2 -0
- package/dist/types-ts4.5/codeBlockAdvancedPluginType.d.ts +15 -0
- package/dist/types-ts4.5/index.d.ts +2 -0
- package/dist/types-ts4.5/nodeviews/codeBlockAdvanced.d.ts +38 -0
- package/dist/types-ts4.5/nodeviews/codeBlockNodeWithToDOMFixed.d.ts +2 -0
- package/dist/types-ts4.5/nodeviews/codemirrorSync/syncCMWithPM.d.ts +17 -0
- package/dist/types-ts4.5/nodeviews/codemirrorSync/updateCMSelection.d.ts +11 -0
- package/dist/types-ts4.5/nodeviews/extensions/bidiCharWarning.d.ts +8 -0
- package/dist/types-ts4.5/nodeviews/extensions/keymap/backspace.d.ts +12 -0
- package/dist/types-ts4.5/nodeviews/extensions/keymap/index.d.ts +14 -0
- package/dist/types-ts4.5/nodeviews/extensions/keymap/maybeEscape.d.ts +17 -0
- package/dist/types-ts4.5/nodeviews/languages/languageMap.d.ts +5 -0
- package/dist/types-ts4.5/nodeviews/languages/loader.d.ts +12 -0
- package/dist/types-ts4.5/nodeviews/lazyCodeBlockAdvanced.d.ts +9 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +10 -0
- package/dist/types-ts4.5/ui/syntaxHighlightingTheme.d.ts +2 -0
- package/dist/types-ts4.5/ui/theme.d.ts +1 -0
- package/docs/0-intro.tsx +56 -0
- package/package.json +96 -0
- package/src/codeBlockAdvancedPlugin.tsx +25 -0
- package/src/codeBlockAdvancedPluginType.ts +18 -0
- package/src/index.ts +5 -0
- package/src/nodeviews/codeBlockAdvanced.ts +223 -0
- package/src/nodeviews/codeBlockNodeWithToDOMFixed.ts +59 -0
- package/src/nodeviews/codemirrorSync/syncCMWithPM.ts +40 -0
- package/src/nodeviews/codemirrorSync/updateCMSelection.ts +40 -0
- package/src/nodeviews/extensions/bidiCharWarning.ts +72 -0
- package/src/nodeviews/extensions/keymap/backspace.ts +47 -0
- package/src/nodeviews/extensions/keymap/index.ts +118 -0
- package/src/nodeviews/extensions/keymap/maybeEscape.ts +69 -0
- package/src/nodeviews/languages/languageMap.ts +91 -0
- package/src/nodeviews/languages/loader.ts +44 -0
- package/src/nodeviews/lazyCodeBlockAdvanced.ts +32 -0
- package/src/pm-plugins/main.ts +22 -0
- package/src/ui/syntaxHighlightingTheme.ts +50 -0
- package/src/ui/theme.ts +52 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Extension } from '@codemirror/state';
|
|
2
|
+
import type { NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
|
|
3
|
+
import type { CodeBlockPlugin } from '@atlaskit/editor-plugin-code-block';
|
|
4
|
+
import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
|
|
5
|
+
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
|
|
6
|
+
export type CodeBlockAdvancedPlugin = NextEditorPlugin<'codeBlockAdvanced', {
|
|
7
|
+
dependencies: [
|
|
8
|
+
CodeBlockPlugin,
|
|
9
|
+
SelectionPlugin,
|
|
10
|
+
OptionalPlugin<EditorDisabledPlugin>
|
|
11
|
+
];
|
|
12
|
+
pluginConfiguration: {
|
|
13
|
+
extensions?: Extension[];
|
|
14
|
+
} | undefined;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Extension } from '@codemirror/state';
|
|
2
|
+
import { ViewUpdate } from '@codemirror/view';
|
|
3
|
+
import type { getPosHandler, getPosHandlerNode, ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
4
|
+
import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
+
import type { EditorView, NodeView } from '@atlaskit/editor-prosemirror/view';
|
|
6
|
+
import type { CodeBlockAdvancedPlugin } from '../codeBlockAdvancedPluginType';
|
|
7
|
+
interface ConfigProps {
|
|
8
|
+
api: ExtractInjectionAPI<CodeBlockAdvancedPlugin> | undefined;
|
|
9
|
+
extensions: Extension[];
|
|
10
|
+
}
|
|
11
|
+
declare class CodeBlockAdvancedNodeView implements NodeView {
|
|
12
|
+
dom: Node;
|
|
13
|
+
private updating;
|
|
14
|
+
private view;
|
|
15
|
+
private lineWrappingCompartment;
|
|
16
|
+
private languageCompartment;
|
|
17
|
+
private readOnlyCompartment;
|
|
18
|
+
private node;
|
|
19
|
+
private getPos;
|
|
20
|
+
private cm;
|
|
21
|
+
private selectionAPI;
|
|
22
|
+
private maybeTryingToReachNodeSelection;
|
|
23
|
+
private cleanupDisabledState;
|
|
24
|
+
private languageLoader;
|
|
25
|
+
constructor(node: PMNode, view: EditorView, getPos: getPosHandlerNode, config: ConfigProps);
|
|
26
|
+
destroy(): void;
|
|
27
|
+
forwardUpdate(update: ViewUpdate): void;
|
|
28
|
+
setSelection(anchor: number, head: number): void;
|
|
29
|
+
private updateReadonlyState;
|
|
30
|
+
private updateLanguage;
|
|
31
|
+
private selectCodeBlockNode;
|
|
32
|
+
private wordWrappingEnabled;
|
|
33
|
+
private updateWordWrap;
|
|
34
|
+
update(node: PMNode): boolean;
|
|
35
|
+
stopEvent(e: Event): boolean;
|
|
36
|
+
}
|
|
37
|
+
export declare const getCodeBlockAdvancedNodeView: (props: ConfigProps) => (node: PMNode, view: EditorView, getPos: getPosHandler) => CodeBlockAdvancedNodeView;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ViewUpdate } from '@codemirror/view';
|
|
2
|
+
import { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
interface Props {
|
|
4
|
+
view: EditorView;
|
|
5
|
+
update: ViewUpdate;
|
|
6
|
+
offset: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* Synchronises the CodeMirror update changes with the Prosemirror editor
|
|
11
|
+
*
|
|
12
|
+
* @param props.view EditorView - Prosemirror EditorView
|
|
13
|
+
* @param props.update ViewUpdate - CodeMirror ViewUpdate
|
|
14
|
+
* @param props.offset number - position where the code block starts in prosemirror
|
|
15
|
+
*/
|
|
16
|
+
export declare const syncCMWithPM: ({ view, update, offset }: Props) => void;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { TransactionSpec as CMTransactionSpec } from '@codemirror/state';
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* Compares the updated text with the current to determine the transaction to fire
|
|
5
|
+
* in the CodeMirror editor.
|
|
6
|
+
*
|
|
7
|
+
* @param curText string - the current CodeMirror text
|
|
8
|
+
* @param newText string - the new CodeMirror text
|
|
9
|
+
* @param updateCallback Callback to process the CodeMirror transaction
|
|
10
|
+
*/
|
|
11
|
+
export declare const updateCMSelection: (curText: string, newText: string, updateCallback: (value: CMTransactionSpec) => void) => void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { EditorView as CodeMirror } from '@codemirror/view';
|
|
2
|
+
import type { getPosHandlerNode } from '@atlaskit/editor-common/types';
|
|
3
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
4
|
+
import { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
5
|
+
interface BackspaceProps {
|
|
6
|
+
view: EditorView;
|
|
7
|
+
cm: CodeMirror;
|
|
8
|
+
getPos: getPosHandlerNode;
|
|
9
|
+
getNode: () => PMNode;
|
|
10
|
+
}
|
|
11
|
+
export declare const backspaceKeymap: ({ cm, view, getPos, getNode }: BackspaceProps) => boolean;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Extension } from '@codemirror/state';
|
|
2
|
+
import { RelativeSelectionPos } from '@atlaskit/editor-common/selection';
|
|
3
|
+
import type { getPosHandlerNode } from '@atlaskit/editor-common/types';
|
|
4
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
+
import { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
6
|
+
interface KeymapProps {
|
|
7
|
+
view: EditorView;
|
|
8
|
+
getNode: () => PMNode;
|
|
9
|
+
getPos: getPosHandlerNode;
|
|
10
|
+
selectCodeBlockNode: (relativeSelectionPos: RelativeSelectionPos | undefined) => void;
|
|
11
|
+
onMaybeNodeSelection: () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare const keymapExtension: ({ view, getNode, getPos, selectCodeBlockNode, onMaybeNodeSelection, }: KeymapProps) => Extension;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EditorView as CodeMirror } from '@codemirror/view';
|
|
2
|
+
import { RelativeSelectionPos } from '@atlaskit/editor-common/selection';
|
|
3
|
+
import type { getPosHandlerNode } from '@atlaskit/editor-common/types';
|
|
4
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
+
import { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
6
|
+
interface MaybeEscapeProps {
|
|
7
|
+
unit: 'line' | 'char';
|
|
8
|
+
dir: -1 | 1;
|
|
9
|
+
view: EditorView;
|
|
10
|
+
cm: CodeMirror;
|
|
11
|
+
getPos: getPosHandlerNode;
|
|
12
|
+
getNode: () => PMNode;
|
|
13
|
+
onMaybeNodeSelection: () => void;
|
|
14
|
+
selectCodeBlockNode: (relativeSelectionPos: RelativeSelectionPos | undefined) => void;
|
|
15
|
+
}
|
|
16
|
+
export declare const maybeEscapeKeymap: ({ unit, dir, view, cm, getPos, getNode, onMaybeNodeSelection, selectCodeBlockNode, }: MaybeEscapeProps) => boolean;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { LanguageDescription } from '@codemirror/language';
|
|
2
|
+
import type { LanguageAlias } from '@atlaskit/code';
|
|
3
|
+
type LanguageAliasValue = LanguageAlias[0];
|
|
4
|
+
export declare const mapLanguageToCodeMirror: (language: LanguageAliasValue) => LanguageDescription | undefined;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LanguageSupport } from '@codemirror/language';
|
|
2
|
+
/**
|
|
3
|
+
* Manages loading the languages (for syntax highlighting, etc.)
|
|
4
|
+
* from CodeMirror and updating the language in the CodeMirror view
|
|
5
|
+
*/
|
|
6
|
+
export declare class LanguageLoader {
|
|
7
|
+
private updateLanguageCompartment;
|
|
8
|
+
private languageName;
|
|
9
|
+
constructor(updateLanguageCompartment: (value: LanguageSupport | [
|
|
10
|
+
]) => void);
|
|
11
|
+
updateLanguage(languageName: string): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Extension } from '@codemirror/state';
|
|
2
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
3
|
+
import type { CodeBlockAdvancedPlugin } from '../codeBlockAdvancedPluginType';
|
|
4
|
+
interface Props {
|
|
5
|
+
api: ExtractInjectionAPI<CodeBlockAdvancedPlugin> | undefined;
|
|
6
|
+
extensions: Extension[];
|
|
7
|
+
}
|
|
8
|
+
export declare const lazyCodeBlockView: (props: Props) => import("@atlaskit/editor-common/lazy-node-view").NodeViewConstructor;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Extension } from '@codemirror/state';
|
|
2
|
+
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
3
|
+
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
4
|
+
import type { CodeBlockAdvancedPlugin } from '../codeBlockAdvancedPluginType';
|
|
5
|
+
interface Props {
|
|
6
|
+
api: ExtractInjectionAPI<CodeBlockAdvancedPlugin> | undefined;
|
|
7
|
+
extensions: Extension[];
|
|
8
|
+
}
|
|
9
|
+
export declare const createPlugin: (props: Props) => SafePlugin<any>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const cmTheme: import("@codemirror/state").Extension;
|
package/docs/0-intro.tsx
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
import { AtlassianInternalWarning, code, md } from '@atlaskit/docs';
|
|
4
|
+
// eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
5
|
+
import { createEditorUseOnlyNotice } from '@atlaskit/editor-common/doc-utils';
|
|
6
|
+
import { token } from '@atlaskit/tokens';
|
|
7
|
+
|
|
8
|
+
export default md`
|
|
9
|
+
|
|
10
|
+
${createEditorUseOnlyNotice('Editor Plugin Code Block Advanced', [
|
|
11
|
+
{ name: 'Editor Core', link: '/packages/editor/editor-core' },
|
|
12
|
+
])}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
${
|
|
16
|
+
(
|
|
17
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766
|
|
18
|
+
<div style={{ marginTop: token('space.100', '8px') }}>
|
|
19
|
+
<AtlassianInternalWarning />
|
|
20
|
+
</div>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
This package includes the code block advanced plugin used by \`@atlaskit/editor-core\`.
|
|
25
|
+
|
|
26
|
+
This can be used to extend \`@atlaskit/editor-plugin-code-block\` by using a CodeMirror editor for
|
|
27
|
+
the nodeview to use rich functionality. Extensions can be injected via its configuration.
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
The \`dependencies\`, \`configuration\`, \`state\`, \`actions\`, and \`commands\` of the plugin are defined
|
|
33
|
+
below:
|
|
34
|
+
|
|
35
|
+
${code`
|
|
36
|
+
type CodeBlockAdvancedPlugin = NextEditorPlugin<
|
|
37
|
+
'codeBlockAdvanced',
|
|
38
|
+
{
|
|
39
|
+
dependencies: [CodeBlockPlugin];
|
|
40
|
+
pluginConfiguration:
|
|
41
|
+
| {
|
|
42
|
+
extensions?: Extension[];
|
|
43
|
+
}
|
|
44
|
+
| undefined;
|
|
45
|
+
}
|
|
46
|
+
>;
|
|
47
|
+
`}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
## Support
|
|
51
|
+
---
|
|
52
|
+
For internal Atlassian, visit the slack channel [#help-editor](https://atlassian.slack.com/archives/CFG3PSQ9E) for support or visit [go/editor-help](https://go/editor-help) to submit a bug.
|
|
53
|
+
## License
|
|
54
|
+
---
|
|
55
|
+
Please see [Atlassian Frontend - License](https://hello.atlassian.net/wiki/spaces/AF/pages/2589099144/Documentation#License) for more licensing information.
|
|
56
|
+
`;
|
package/package.json
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/editor-plugin-code-block-advanced",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CodeBlockAdvanced plugin for @atlaskit/editor-core",
|
|
5
|
+
"author": "Atlassian Pty Ltd",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"registry": "https://registry.npmjs.org/"
|
|
9
|
+
},
|
|
10
|
+
"atlassian": {
|
|
11
|
+
"team": "Editor: Lego",
|
|
12
|
+
"releaseModel": "continuous",
|
|
13
|
+
"singleton": true,
|
|
14
|
+
"runReact18": true
|
|
15
|
+
},
|
|
16
|
+
"repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
|
|
17
|
+
"main": "dist/cjs/index.js",
|
|
18
|
+
"module": "dist/esm/index.js",
|
|
19
|
+
"module:es2019": "dist/es2019/index.js",
|
|
20
|
+
"types": "dist/types/index.d.ts",
|
|
21
|
+
"typesVersions": {
|
|
22
|
+
">=4.5 <4.9": {
|
|
23
|
+
"*": [
|
|
24
|
+
"dist/types-ts4.5/*",
|
|
25
|
+
"dist/types-ts4.5/index.d.ts"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"atlaskit:src": "src/index.ts",
|
|
31
|
+
"af:exports": {
|
|
32
|
+
".": "./src/index.ts"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@atlaskit/adf-schema": "^46.1.0",
|
|
36
|
+
"@atlaskit/editor-common": "^99.1.0",
|
|
37
|
+
"@atlaskit/editor-plugin-code-block": "^3.5.0",
|
|
38
|
+
"@atlaskit/editor-plugin-editor-disabled": "^1.3.0",
|
|
39
|
+
"@atlaskit/editor-plugin-selection": "^1.6.0",
|
|
40
|
+
"@atlaskit/editor-prosemirror": "6.2.1",
|
|
41
|
+
"@atlaskit/tokens": "^3.0.0",
|
|
42
|
+
"@babel/runtime": "^7.0.0",
|
|
43
|
+
"@codemirror/autocomplete": "6.18.4",
|
|
44
|
+
"@codemirror/commands": "6.7.1",
|
|
45
|
+
"@codemirror/language": "6.10.8",
|
|
46
|
+
"@codemirror/language-data": "6.5.1",
|
|
47
|
+
"@codemirror/state": "6.5.1",
|
|
48
|
+
"@codemirror/view": "6.36.2",
|
|
49
|
+
"@lezer/highlight": "1.2.1",
|
|
50
|
+
"cm6-graphql": "0.2.0",
|
|
51
|
+
"codemirror-lang-elixir": "4.0.0"
|
|
52
|
+
},
|
|
53
|
+
"peerDependencies": {
|
|
54
|
+
"react": "^16.8.0 || ^17.0.0 || ~18.2.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@atlaskit/code": "^15.6.0",
|
|
58
|
+
"typescript": "~5.4.2"
|
|
59
|
+
},
|
|
60
|
+
"techstack": {
|
|
61
|
+
"@atlassian/frontend": {
|
|
62
|
+
"code-structure": [
|
|
63
|
+
"editor-plugin"
|
|
64
|
+
],
|
|
65
|
+
"import-structure": [
|
|
66
|
+
"atlassian-conventions"
|
|
67
|
+
],
|
|
68
|
+
"circular-dependencies": [
|
|
69
|
+
"file-and-folder-level"
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
"@repo/internal": {
|
|
73
|
+
"dom-events": "use-bind-event-listener",
|
|
74
|
+
"analytics": [
|
|
75
|
+
"analytics-next"
|
|
76
|
+
],
|
|
77
|
+
"design-tokens": [
|
|
78
|
+
"color"
|
|
79
|
+
],
|
|
80
|
+
"theming": [
|
|
81
|
+
"react-context"
|
|
82
|
+
],
|
|
83
|
+
"ui-components": [
|
|
84
|
+
"lite-mode"
|
|
85
|
+
],
|
|
86
|
+
"deprecation": "no-deprecated-imports",
|
|
87
|
+
"styling": [
|
|
88
|
+
"emotion",
|
|
89
|
+
"emotion"
|
|
90
|
+
],
|
|
91
|
+
"imports": [
|
|
92
|
+
"import-no-extraneous-disable-for-examples-and-docs"
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { CodeBlockAdvancedPlugin } from './codeBlockAdvancedPluginType';
|
|
2
|
+
import { codeBlockNodeWithFixedToDOM } from './nodeviews/codeBlockNodeWithToDOMFixed';
|
|
3
|
+
import { createPlugin } from './pm-plugins/main';
|
|
4
|
+
|
|
5
|
+
export const codeBlockAdvancedPlugin: CodeBlockAdvancedPlugin = ({ api, config }) => ({
|
|
6
|
+
name: 'codeBlockAdvanced',
|
|
7
|
+
|
|
8
|
+
nodes() {
|
|
9
|
+
return [
|
|
10
|
+
{
|
|
11
|
+
name: 'codeBlock',
|
|
12
|
+
node: codeBlockNodeWithFixedToDOM(),
|
|
13
|
+
},
|
|
14
|
+
];
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
pmPlugins() {
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
name: 'codeBlockAdvancedPlugin',
|
|
21
|
+
plugin: () => createPlugin({ api, extensions: config?.extensions ?? [] }),
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Extension } from '@codemirror/state';
|
|
2
|
+
|
|
3
|
+
import type { NextEditorPlugin, OptionalPlugin } from '@atlaskit/editor-common/types';
|
|
4
|
+
import type { CodeBlockPlugin } from '@atlaskit/editor-plugin-code-block';
|
|
5
|
+
import type { EditorDisabledPlugin } from '@atlaskit/editor-plugin-editor-disabled';
|
|
6
|
+
import type { SelectionPlugin } from '@atlaskit/editor-plugin-selection';
|
|
7
|
+
|
|
8
|
+
export type CodeBlockAdvancedPlugin = NextEditorPlugin<
|
|
9
|
+
'codeBlockAdvanced',
|
|
10
|
+
{
|
|
11
|
+
dependencies: [CodeBlockPlugin, SelectionPlugin, OptionalPlugin<EditorDisabledPlugin>];
|
|
12
|
+
pluginConfiguration:
|
|
13
|
+
| {
|
|
14
|
+
extensions?: Extension[];
|
|
15
|
+
}
|
|
16
|
+
| undefined;
|
|
17
|
+
}
|
|
18
|
+
>;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { closeBrackets } from '@codemirror/autocomplete';
|
|
2
|
+
import { syntaxHighlighting } from '@codemirror/language';
|
|
3
|
+
import { Compartment, Extension, EditorSelection } from '@codemirror/state';
|
|
4
|
+
import { EditorView as CodeMirror, lineNumbers, ViewUpdate } from '@codemirror/view';
|
|
5
|
+
|
|
6
|
+
import { isCodeBlockWordWrapEnabled } from '@atlaskit/editor-common/code-block';
|
|
7
|
+
import { RelativeSelectionPos } from '@atlaskit/editor-common/selection';
|
|
8
|
+
import type {
|
|
9
|
+
getPosHandler,
|
|
10
|
+
getPosHandlerNode,
|
|
11
|
+
ExtractInjectionAPI,
|
|
12
|
+
} from '@atlaskit/editor-common/types';
|
|
13
|
+
import { EditorSelectionAPI } from '@atlaskit/editor-plugin-selection';
|
|
14
|
+
import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
15
|
+
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
16
|
+
import type { EditorView, NodeView } from '@atlaskit/editor-prosemirror/view';
|
|
17
|
+
|
|
18
|
+
import type { CodeBlockAdvancedPlugin } from '../codeBlockAdvancedPluginType';
|
|
19
|
+
import { highlightStyle } from '../ui/syntaxHighlightingTheme';
|
|
20
|
+
import { cmTheme } from '../ui/theme';
|
|
21
|
+
|
|
22
|
+
import { syncCMWithPM } from './codemirrorSync/syncCMWithPM';
|
|
23
|
+
import { updateCMSelection } from './codemirrorSync/updateCMSelection';
|
|
24
|
+
import { bidiCharWarningExtension } from './extensions/bidiCharWarning';
|
|
25
|
+
import { keymapExtension } from './extensions/keymap';
|
|
26
|
+
import { LanguageLoader } from './languages/loader';
|
|
27
|
+
|
|
28
|
+
interface ConfigProps {
|
|
29
|
+
api: ExtractInjectionAPI<CodeBlockAdvancedPlugin> | undefined;
|
|
30
|
+
extensions: Extension[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Based on: https://prosemirror.net/examples/codemirror/
|
|
34
|
+
class CodeBlockAdvancedNodeView implements NodeView {
|
|
35
|
+
dom: Node;
|
|
36
|
+
private updating: boolean;
|
|
37
|
+
private view: EditorView;
|
|
38
|
+
private lineWrappingCompartment = new Compartment();
|
|
39
|
+
private languageCompartment = new Compartment();
|
|
40
|
+
private readOnlyCompartment = new Compartment();
|
|
41
|
+
private node: PMNode;
|
|
42
|
+
private getPos: getPosHandlerNode;
|
|
43
|
+
private cm: CodeMirror;
|
|
44
|
+
private selectionAPI: EditorSelectionAPI | undefined;
|
|
45
|
+
private maybeTryingToReachNodeSelection = false;
|
|
46
|
+
private cleanupDisabledState: (() => void) | undefined;
|
|
47
|
+
private languageLoader: LanguageLoader;
|
|
48
|
+
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/max-params
|
|
50
|
+
constructor(node: PMNode, view: EditorView, getPos: getPosHandlerNode, config: ConfigProps) {
|
|
51
|
+
this.node = node;
|
|
52
|
+
this.view = view;
|
|
53
|
+
this.getPos = getPos;
|
|
54
|
+
this.selectionAPI = config.api?.selection?.actions;
|
|
55
|
+
const getNode = () => this.node;
|
|
56
|
+
const onMaybeNodeSelection = () => (this.maybeTryingToReachNodeSelection = true);
|
|
57
|
+
this.cleanupDisabledState = config.api?.editorDisabled?.sharedState.onChange(() => {
|
|
58
|
+
this.updateReadonlyState();
|
|
59
|
+
});
|
|
60
|
+
this.languageLoader = new LanguageLoader((lang) => {
|
|
61
|
+
this.updating = true;
|
|
62
|
+
this.cm.dispatch({
|
|
63
|
+
effects: this.languageCompartment.reconfigure(lang),
|
|
64
|
+
});
|
|
65
|
+
this.updating = false;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
this.cm = new CodeMirror({
|
|
69
|
+
doc: this.node.textContent,
|
|
70
|
+
extensions: [
|
|
71
|
+
...config.extensions,
|
|
72
|
+
this.lineWrappingCompartment.of([]),
|
|
73
|
+
this.languageCompartment.of([]),
|
|
74
|
+
keymapExtension({
|
|
75
|
+
view,
|
|
76
|
+
getPos,
|
|
77
|
+
getNode,
|
|
78
|
+
selectCodeBlockNode: this.selectCodeBlockNode.bind(this),
|
|
79
|
+
onMaybeNodeSelection,
|
|
80
|
+
}),
|
|
81
|
+
cmTheme,
|
|
82
|
+
syntaxHighlighting(highlightStyle),
|
|
83
|
+
lineNumbers(),
|
|
84
|
+
CodeMirror.updateListener.of((update) => this.forwardUpdate(update)),
|
|
85
|
+
this.readOnlyCompartment.of(CodeMirror.editable.of(this.view.editable)),
|
|
86
|
+
closeBrackets(),
|
|
87
|
+
CodeMirror.editorAttributes.of({ class: 'code-block' }),
|
|
88
|
+
bidiCharWarningExtension,
|
|
89
|
+
],
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// The editor's outer node is our DOM representation
|
|
93
|
+
this.dom = this.cm.dom;
|
|
94
|
+
|
|
95
|
+
// This flag is used to avoid an update loop between the outer and
|
|
96
|
+
// inner editor
|
|
97
|
+
this.updating = false;
|
|
98
|
+
this.updateLanguage();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
destroy() {
|
|
102
|
+
this.cleanupDisabledState?.();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
forwardUpdate(update: ViewUpdate) {
|
|
106
|
+
if (this.updating || !this.cm.hasFocus) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const offset = (this.getPos?.() ?? 0) + 1;
|
|
110
|
+
|
|
111
|
+
syncCMWithPM({
|
|
112
|
+
view: this.view,
|
|
113
|
+
update,
|
|
114
|
+
offset,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
setSelection(anchor: number, head: number) {
|
|
119
|
+
if (!this.maybeTryingToReachNodeSelection) {
|
|
120
|
+
this.cm.focus();
|
|
121
|
+
}
|
|
122
|
+
this.updating = true;
|
|
123
|
+
this.cm.dispatch({ selection: { anchor, head } });
|
|
124
|
+
this.updating = false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private updateReadonlyState() {
|
|
128
|
+
this.updating = true;
|
|
129
|
+
this.cm.dispatch({
|
|
130
|
+
effects: this.readOnlyCompartment.reconfigure(CodeMirror.editable.of(this.view.editable)),
|
|
131
|
+
});
|
|
132
|
+
this.updating = false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private updateLanguage() {
|
|
136
|
+
this.languageLoader.updateLanguage(this.node.attrs.language);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private selectCodeBlockNode(relativeSelectionPos: RelativeSelectionPos | undefined) {
|
|
140
|
+
const tr = this.selectionAPI?.selectNearNode({
|
|
141
|
+
selectionRelativeToNode: relativeSelectionPos,
|
|
142
|
+
selection: NodeSelection.create(this.view.state.doc, this.getPos?.() ?? 0),
|
|
143
|
+
})(this.view.state);
|
|
144
|
+
if (tr) {
|
|
145
|
+
this.view.dispatch(tr);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private wordWrappingEnabled = false;
|
|
150
|
+
|
|
151
|
+
private updateWordWrap(node: PMNode) {
|
|
152
|
+
if (this.wordWrappingEnabled !== isCodeBlockWordWrapEnabled(node)) {
|
|
153
|
+
this.updating = true;
|
|
154
|
+
this.cm.dispatch({
|
|
155
|
+
effects: [
|
|
156
|
+
this.lineWrappingCompartment.reconfigure(
|
|
157
|
+
isCodeBlockWordWrapEnabled(node) ? CodeMirror.lineWrapping : [],
|
|
158
|
+
),
|
|
159
|
+
],
|
|
160
|
+
});
|
|
161
|
+
this.updating = false;
|
|
162
|
+
this.wordWrappingEnabled = !this.wordWrappingEnabled;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
update(node: PMNode) {
|
|
167
|
+
this.maybeTryingToReachNodeSelection = false;
|
|
168
|
+
|
|
169
|
+
if (node.type !== this.node.type) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
this.updateWordWrap(node);
|
|
173
|
+
this.node = node;
|
|
174
|
+
if (this.updating) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
this.updateLanguage();
|
|
178
|
+
const newText = node.textContent,
|
|
179
|
+
curText = this.cm.state.doc.toString();
|
|
180
|
+
updateCMSelection(curText, newText, (tr) => {
|
|
181
|
+
this.updating = true;
|
|
182
|
+
this.cm.dispatch(tr);
|
|
183
|
+
this.updating = false;
|
|
184
|
+
});
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
stopEvent(e: Event) {
|
|
189
|
+
if (e instanceof MouseEvent && e.type === 'mousedown') {
|
|
190
|
+
// !Warning: Side effect!
|
|
191
|
+
// CodeMirror on blur updates the dom observer with a `setTimeout(..., 10);`
|
|
192
|
+
// We need to select the nodeview after this has taken place to ensure
|
|
193
|
+
// ProseMirror takes over
|
|
194
|
+
// https://github.com/codemirror/view/commit/70a9a253df04a57004247b9463198c17832f92f4#diff-cb8cbffa623ff0975389e7e8c315e69d5e10345239ffe2c9b4b7986a56ad95efR720
|
|
195
|
+
setTimeout(() => {
|
|
196
|
+
// Ensure the CM selection is reset - if we have a ranged selection when we do node selection can
|
|
197
|
+
// cause funky behaviour
|
|
198
|
+
this.updating = true;
|
|
199
|
+
this.cm.dispatch({
|
|
200
|
+
selection: EditorSelection.create([EditorSelection.cursor(0)], 0),
|
|
201
|
+
});
|
|
202
|
+
this.updating = false;
|
|
203
|
+
this.selectCodeBlockNode(undefined);
|
|
204
|
+
this.view.focus();
|
|
205
|
+
}, 20);
|
|
206
|
+
}
|
|
207
|
+
// If we have selected the node we should not stop these events
|
|
208
|
+
if (
|
|
209
|
+
e instanceof KeyboardEvent &&
|
|
210
|
+
this.view.state.selection instanceof NodeSelection &&
|
|
211
|
+
this.view.state.selection.from === this.getPos?.()
|
|
212
|
+
) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export const getCodeBlockAdvancedNodeView =
|
|
220
|
+
(props: ConfigProps) =>
|
|
221
|
+
(node: PMNode, view: EditorView, getPos: getPosHandler): CodeBlockAdvancedNodeView => {
|
|
222
|
+
return new CodeBlockAdvancedNodeView(node, view, getPos as getPosHandlerNode, props);
|
|
223
|
+
};
|