@lstsystems/ckeditor5-source-editing-codemirror 47.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +339 -0
- package/README.md +83 -0
- package/Sample/index.html +19 -0
- package/Sample/main.js +21 -0
- package/Sample/main.ts +33 -0
- package/dist/index.d.ts +3 -0
- package/dist/sourceediting-codemirror.css +1 -0
- package/dist/sourceediting-codemirror.d.ts +10 -0
- package/dist/sourceediting-codemirror.js +261 -0
- package/index.d.ts +4 -0
- package/package.json +40 -0
- package/playwright/global.d.ts +7 -0
- package/playwright/source-editing-code-mirror.spec.js +50 -0
- package/playwright/source-editing-code-mirror.spec.ts +67 -0
- package/playwright.config.js +13 -0
- package/playwright.config.ts +14 -0
- package/src/index.js +3 -0
- package/src/index.ts +5 -0
- package/src/sourceediting-codemirror.css +18 -0
- package/src/sourceediting-codemirror.js +114 -0
- package/src/sourceediting-codemirror.ts +146 -0
- package/tsconfig.build.json +17 -0
- package/tsconfig.json +13 -0
- package/vite.config.js +50 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Plugin } from 'ckeditor5';
|
|
2
|
+
|
|
3
|
+
// CodeMirror 6 imports
|
|
4
|
+
import {
|
|
5
|
+
EditorView,
|
|
6
|
+
lineNumbers,
|
|
7
|
+
highlightActiveLine,
|
|
8
|
+
highlightActiveLineGutter
|
|
9
|
+
} from '@codemirror/view';
|
|
10
|
+
|
|
11
|
+
import { EditorState, type Extension } from '@codemirror/state';
|
|
12
|
+
import { html } from '@codemirror/lang-html';
|
|
13
|
+
import {
|
|
14
|
+
syntaxHighlighting,
|
|
15
|
+
defaultHighlightStyle,
|
|
16
|
+
indentOnInput,
|
|
17
|
+
indentUnit
|
|
18
|
+
} from '@codemirror/language';
|
|
19
|
+
import { indentSelection } from '@codemirror/commands';
|
|
20
|
+
|
|
21
|
+
// Prettier 3 imports
|
|
22
|
+
import prettier from "prettier/standalone";
|
|
23
|
+
import * as prettierHtml from "prettier/plugins/html";
|
|
24
|
+
import * as prettierCss from "prettier/plugins/postcss";
|
|
25
|
+
import * as prettierTs from "prettier/plugins/typescript";
|
|
26
|
+
import * as prettierMarkdown from "prettier/plugins/markdown";
|
|
27
|
+
import * as prettierYaml from "prettier/plugins/yaml";
|
|
28
|
+
|
|
29
|
+
interface CodeMirrorConfig {
|
|
30
|
+
extensions?: Extension[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default class SourceEditingCodeMirror extends Plugin {
|
|
34
|
+
public static get pluginName() {
|
|
35
|
+
return 'SourceEditingCodeMirror' as const;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public static get requires() {
|
|
39
|
+
return [ 'SourceEditing' ] as const;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private view: EditorView | null = null;
|
|
43
|
+
|
|
44
|
+
// Prettier 3 formatter
|
|
45
|
+
private async formatWithPrettier(code: string): Promise<string> {
|
|
46
|
+
return await prettier.format(code, {
|
|
47
|
+
parser: "html",
|
|
48
|
+
plugins: [
|
|
49
|
+
prettierHtml,
|
|
50
|
+
prettierCss,
|
|
51
|
+
prettierTs,
|
|
52
|
+
prettierMarkdown,
|
|
53
|
+
prettierYaml
|
|
54
|
+
],
|
|
55
|
+
tabWidth: 4,
|
|
56
|
+
useTabs: false
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Listen to SourceEditing mode changes
|
|
61
|
+
public afterInit(): void {
|
|
62
|
+
const editor = this.editor;
|
|
63
|
+
const sourceEditing = editor.plugins.get('SourceEditing');
|
|
64
|
+
|
|
65
|
+
this.listenTo(
|
|
66
|
+
sourceEditing,
|
|
67
|
+
'change:isSourceEditingMode',
|
|
68
|
+
async (_evt, _name, isOn: boolean) => {
|
|
69
|
+
if (isOn) {
|
|
70
|
+
await this.enableCodeMirror();
|
|
71
|
+
} else {
|
|
72
|
+
this.disableCodeMirror();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
// Enable CodeMirror with Prettier formatting
|
|
78
|
+
private async enableCodeMirror(): Promise<void> {
|
|
79
|
+
const editor = this.editor;
|
|
80
|
+
const sourceEditing = editor.plugins.get('SourceEditing');
|
|
81
|
+
|
|
82
|
+
// Sync CKEditor → source view
|
|
83
|
+
sourceEditing.updateEditorData();
|
|
84
|
+
|
|
85
|
+
// Format HTML using Prettier 3
|
|
86
|
+
const htmlData = await this.formatWithPrettier(editor.getData());
|
|
87
|
+
|
|
88
|
+
const container = document.querySelector('.ck-source-editing-area');
|
|
89
|
+
if (!container) return;
|
|
90
|
+
|
|
91
|
+
const textarea = container.querySelector('textarea') as HTMLTextAreaElement | null;
|
|
92
|
+
if (textarea) textarea.style.display = 'none';
|
|
93
|
+
|
|
94
|
+
const cmDiv = document.createElement('div');
|
|
95
|
+
cmDiv.classList.add('cm-wrapper');
|
|
96
|
+
container.appendChild(cmDiv);
|
|
97
|
+
|
|
98
|
+
const cmExtensions: Extension[] = [
|
|
99
|
+
lineNumbers(),
|
|
100
|
+
highlightActiveLine(),
|
|
101
|
+
highlightActiveLineGutter(),
|
|
102
|
+
syntaxHighlighting(defaultHighlightStyle),
|
|
103
|
+
indentOnInput(),
|
|
104
|
+
indentUnit.of(' ')
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
const config = editor.config.get('sourceEditingCodeMirror') as CodeMirrorConfig;
|
|
108
|
+
const extraExtensions = config?.extensions ?? [];
|
|
109
|
+
|
|
110
|
+
this.view = new EditorView({
|
|
111
|
+
state: EditorState.create({
|
|
112
|
+
doc: htmlData,
|
|
113
|
+
extensions: [
|
|
114
|
+
...cmExtensions,
|
|
115
|
+
html(),
|
|
116
|
+
...extraExtensions,
|
|
117
|
+
EditorView.updateListener.of(update => {
|
|
118
|
+
if (update.docChanged) {
|
|
119
|
+
editor.setData(update.state.doc.toString());
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
]
|
|
123
|
+
}),
|
|
124
|
+
parent: cmDiv
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Select entire document
|
|
128
|
+
this.view.dispatch({
|
|
129
|
+
selection: { anchor: 0, head: this.view.state.doc.length }
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Indent entire document (after Prettier formatting)
|
|
133
|
+
indentSelection(this.view);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Disable CodeMirror and show original textarea
|
|
137
|
+
private disableCodeMirror(): void {
|
|
138
|
+
if (this.view) {
|
|
139
|
+
this.view.destroy();
|
|
140
|
+
this.view = null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const textarea = document.querySelector('.ck-source-editing-area textarea') as HTMLTextAreaElement | null;
|
|
144
|
+
if (textarea) textarea.style.display = '';
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Node",
|
|
6
|
+
"lib": ["ES2020", "DOM"],
|
|
7
|
+
"strict": false,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"declaration": true,
|
|
11
|
+
"emitDeclarationOnly": true,
|
|
12
|
+
"noEmit": false,
|
|
13
|
+
"outDir": "./dist",
|
|
14
|
+
"declarationMap": false
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*"]
|
|
17
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Node",
|
|
6
|
+
"lib": ["ES2020", "DOM"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"allowSyntheticDefaultImports": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["./**/*.ts"]
|
|
13
|
+
}
|
package/vite.config.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
root: 'Sample',
|
|
6
|
+
|
|
7
|
+
build: {
|
|
8
|
+
// Build from project root, not Sample/
|
|
9
|
+
outDir: '../dist',
|
|
10
|
+
emptyOutDir: false,
|
|
11
|
+
lib: {
|
|
12
|
+
entry: path.resolve(__dirname, 'src/index.ts'),
|
|
13
|
+
name: 'SourceEditingCodeMirror',
|
|
14
|
+
fileName: 'sourceediting-codemirror',
|
|
15
|
+
formats: ['es'] // You only need ESM for CKEditor
|
|
16
|
+
},
|
|
17
|
+
rollupOptions: {
|
|
18
|
+
external: [
|
|
19
|
+
'ckeditor5',
|
|
20
|
+
'@codemirror/view',
|
|
21
|
+
'@codemirror/state',
|
|
22
|
+
'@codemirror/language',
|
|
23
|
+
'@codemirror/lang-html',
|
|
24
|
+
'prettier/standalone',
|
|
25
|
+
'prettier/plugins/html',
|
|
26
|
+
'prettier/plugins/postcss',
|
|
27
|
+
'prettier/plugins/typescript',
|
|
28
|
+
'prettier/plugins/markdown',
|
|
29
|
+
'prettier/plugins/yaml'
|
|
30
|
+
],
|
|
31
|
+
output: {
|
|
32
|
+
globals: {
|
|
33
|
+
'ckeditor5': 'CKEditor',
|
|
34
|
+
'@codemirror/view': 'CodeMirrorView',
|
|
35
|
+
'@codemirror/state': 'CodeMirrorState',
|
|
36
|
+
'@codemirror/language': 'CodeMirrorLanguage',
|
|
37
|
+
'@codemirror/lang-html': 'CodeMirrorHtml',
|
|
38
|
+
'prettier/standalone': 'prettier',
|
|
39
|
+
'prettier/plugins/html': 'prettierHtml',
|
|
40
|
+
'prettier/plugins/postcss': 'prettierPostCss',
|
|
41
|
+
'prettier/plugins/typescript': 'prettierTs',
|
|
42
|
+
'prettier/plugins/markdown': 'prettierMarkdown',
|
|
43
|
+
'prettier/plugins/yaml': 'prettierYaml'
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
});
|