@difizen/libro-codemirror 0.0.0-snapshot-20241017072317

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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +0 -0
  3. package/es/auto-complete/closebrackets.d.ts +12 -0
  4. package/es/auto-complete/closebrackets.d.ts.map +1 -0
  5. package/es/auto-complete/closebrackets.js +409 -0
  6. package/es/auto-complete/completion.d.ts +57 -0
  7. package/es/auto-complete/completion.d.ts.map +1 -0
  8. package/es/auto-complete/completion.js +267 -0
  9. package/es/auto-complete/config.d.ts +22 -0
  10. package/es/auto-complete/config.d.ts.map +1 -0
  11. package/es/auto-complete/config.js +44 -0
  12. package/es/auto-complete/filter.d.ts +13 -0
  13. package/es/auto-complete/filter.d.ts.map +1 -0
  14. package/es/auto-complete/filter.js +190 -0
  15. package/es/auto-complete/index.d.ts +17 -0
  16. package/es/auto-complete/index.d.ts.map +1 -0
  17. package/es/auto-complete/index.js +107 -0
  18. package/es/auto-complete/snippet.d.ts +14 -0
  19. package/es/auto-complete/snippet.d.ts.map +1 -0
  20. package/es/auto-complete/snippet.js +445 -0
  21. package/es/auto-complete/state.d.ts +63 -0
  22. package/es/auto-complete/state.d.ts.map +1 -0
  23. package/es/auto-complete/state.js +448 -0
  24. package/es/auto-complete/theme.d.ts +6 -0
  25. package/es/auto-complete/theme.d.ts.map +1 -0
  26. package/es/auto-complete/theme.js +150 -0
  27. package/es/auto-complete/tooltip.d.ts +5 -0
  28. package/es/auto-complete/tooltip.d.ts.map +1 -0
  29. package/es/auto-complete/tooltip.js +365 -0
  30. package/es/auto-complete/view.d.ts +38 -0
  31. package/es/auto-complete/view.d.ts.map +1 -0
  32. package/es/auto-complete/view.js +368 -0
  33. package/es/auto-complete/word.d.ts +3 -0
  34. package/es/auto-complete/word.d.ts.map +1 -0
  35. package/es/auto-complete/word.js +119 -0
  36. package/es/completion.d.ts +6 -0
  37. package/es/completion.d.ts.map +1 -0
  38. package/es/completion.js +84 -0
  39. package/es/config.d.ts +189 -0
  40. package/es/config.d.ts.map +1 -0
  41. package/es/config.js +482 -0
  42. package/es/editor-contribution.d.ts +9 -0
  43. package/es/editor-contribution.d.ts.map +1 -0
  44. package/es/editor-contribution.js +35 -0
  45. package/es/editor.d.ts +397 -0
  46. package/es/editor.d.ts.map +1 -0
  47. package/es/editor.js +1338 -0
  48. package/es/factory.d.ts +4 -0
  49. package/es/factory.d.ts.map +1 -0
  50. package/es/factory.js +24 -0
  51. package/es/hyperlink.d.ts +15 -0
  52. package/es/hyperlink.d.ts.map +1 -0
  53. package/es/hyperlink.js +120 -0
  54. package/es/indent.d.ts +8 -0
  55. package/es/indent.d.ts.map +1 -0
  56. package/es/indent.js +58 -0
  57. package/es/indentation-markers/config.d.ts +17 -0
  58. package/es/indentation-markers/config.d.ts.map +1 -0
  59. package/es/indentation-markers/config.js +10 -0
  60. package/es/indentation-markers/index.d.ts +3 -0
  61. package/es/indentation-markers/index.d.ts.map +1 -0
  62. package/es/indentation-markers/index.js +160 -0
  63. package/es/indentation-markers/map.d.ts +77 -0
  64. package/es/indentation-markers/map.d.ts.map +1 -0
  65. package/es/indentation-markers/map.js +265 -0
  66. package/es/indentation-markers/utils.d.ts +27 -0
  67. package/es/indentation-markers/utils.d.ts.map +1 -0
  68. package/es/indentation-markers/utils.js +91 -0
  69. package/es/index.d.ts +13 -0
  70. package/es/index.d.ts.map +1 -0
  71. package/es/index.js +12 -0
  72. package/es/libro-icon.d.ts +3 -0
  73. package/es/libro-icon.d.ts.map +1 -0
  74. package/es/libro-icon.js +2 -0
  75. package/es/lsp/completion.d.ts +5 -0
  76. package/es/lsp/completion.d.ts.map +1 -0
  77. package/es/lsp/completion.js +245 -0
  78. package/es/lsp/format.d.ts +7 -0
  79. package/es/lsp/format.d.ts.map +1 -0
  80. package/es/lsp/format.js +193 -0
  81. package/es/lsp/index.d.ts +7 -0
  82. package/es/lsp/index.d.ts.map +1 -0
  83. package/es/lsp/index.js +6 -0
  84. package/es/lsp/lint.d.ts +3 -0
  85. package/es/lsp/lint.d.ts.map +1 -0
  86. package/es/lsp/lint.js +113 -0
  87. package/es/lsp/protocol.d.ts +7 -0
  88. package/es/lsp/protocol.d.ts.map +1 -0
  89. package/es/lsp/protocol.js +1 -0
  90. package/es/lsp/tooltip.d.ts +3 -0
  91. package/es/lsp/tooltip.d.ts.map +1 -0
  92. package/es/lsp/tooltip.js +113 -0
  93. package/es/lsp/util.d.ts +15 -0
  94. package/es/lsp/util.d.ts.map +1 -0
  95. package/es/lsp/util.js +57 -0
  96. package/es/mimetype.d.ts +22 -0
  97. package/es/mimetype.d.ts.map +1 -0
  98. package/es/mimetype.js +59 -0
  99. package/es/mode.d.ts +86 -0
  100. package/es/mode.d.ts.map +1 -0
  101. package/es/mode.js +280 -0
  102. package/es/module.d.ts +3 -0
  103. package/es/module.d.ts.map +1 -0
  104. package/es/module.js +4 -0
  105. package/es/monitor.d.ts +32 -0
  106. package/es/monitor.d.ts.map +1 -0
  107. package/es/monitor.js +129 -0
  108. package/es/python-lang.d.ts +3 -0
  109. package/es/python-lang.d.ts.map +1 -0
  110. package/es/python-lang.js +7 -0
  111. package/es/style/base.css +129 -0
  112. package/es/style/theme.css +12 -0
  113. package/es/style/variables.css +405 -0
  114. package/es/theme.d.ts +35 -0
  115. package/es/theme.d.ts.map +1 -0
  116. package/es/theme.js +223 -0
  117. package/es/tooltip.d.ts +10 -0
  118. package/es/tooltip.d.ts.map +1 -0
  119. package/es/tooltip.js +168 -0
  120. package/package.json +74 -0
  121. package/src/auto-complete/README.md +71 -0
  122. package/src/auto-complete/closebrackets.ts +423 -0
  123. package/src/auto-complete/completion.ts +345 -0
  124. package/src/auto-complete/config.ts +101 -0
  125. package/src/auto-complete/filter.ts +214 -0
  126. package/src/auto-complete/index.ts +112 -0
  127. package/src/auto-complete/snippet.ts +392 -0
  128. package/src/auto-complete/state.ts +465 -0
  129. package/src/auto-complete/theme.ts +127 -0
  130. package/src/auto-complete/tooltip.ts +386 -0
  131. package/src/auto-complete/view.ts +339 -0
  132. package/src/auto-complete/word.ts +118 -0
  133. package/src/completion.ts +61 -0
  134. package/src/config.ts +701 -0
  135. package/src/editor-contribution.ts +22 -0
  136. package/src/editor.ts +1287 -0
  137. package/src/factory.ts +31 -0
  138. package/src/hyperlink.ts +95 -0
  139. package/src/indent.ts +69 -0
  140. package/src/indentation-markers/config.ts +31 -0
  141. package/src/indentation-markers/index.ts +192 -0
  142. package/src/indentation-markers/map.ts +273 -0
  143. package/src/indentation-markers/utils.ts +84 -0
  144. package/src/index.spec.ts +12 -0
  145. package/src/index.ts +14 -0
  146. package/src/libro-icon.tsx +4 -0
  147. package/src/lsp/completion.ts +175 -0
  148. package/src/lsp/format.ts +144 -0
  149. package/src/lsp/index.ts +6 -0
  150. package/src/lsp/lint.ts +125 -0
  151. package/src/lsp/protocol.ts +8 -0
  152. package/src/lsp/tooltip.ts +76 -0
  153. package/src/lsp/util.ts +69 -0
  154. package/src/mimetype.ts +49 -0
  155. package/src/mode.ts +265 -0
  156. package/src/module.ts +8 -0
  157. package/src/monitor.ts +105 -0
  158. package/src/python-lang.ts +7 -0
  159. package/src/style/base.css +129 -0
  160. package/src/style/theme.css +12 -0
  161. package/src/style/variables.css +405 -0
  162. package/src/theme.ts +231 -0
  163. package/src/tooltip.ts +143 -0
@@ -0,0 +1,69 @@
1
+ import type { Text } from '@codemirror/state';
2
+ import hljs from 'highlight.js';
3
+ import MarkdownIt from 'markdown-it';
4
+ import type * as lsp from 'vscode-languageserver-protocol';
5
+ import 'highlight.js/styles/github.css';
6
+
7
+ export function posToOffset(doc: Text, pos: { line: number; character: number }) {
8
+ if (pos.line >= doc.lines) {
9
+ return;
10
+ }
11
+ const offset = doc.line(pos.line + 1).from + pos.character;
12
+ if (offset > doc.length) {
13
+ return;
14
+ }
15
+ return offset;
16
+ }
17
+
18
+ export function offsetToPos(doc: Text, offset: number) {
19
+ const line = doc.lineAt(offset);
20
+ return {
21
+ line: line.number - 1,
22
+ character: offset - line.from,
23
+ };
24
+ }
25
+
26
+ export function formatContents(
27
+ contents: lsp.MarkupContent | lsp.MarkedString | lsp.MarkedString[],
28
+ ): string {
29
+ if (Array.isArray(contents)) {
30
+ return contents.map((c) => formatContents(c) + '\n\n').join('');
31
+ } else if (typeof contents === 'string') {
32
+ return contents;
33
+ } else {
34
+ return contents.value;
35
+ }
36
+ }
37
+
38
+ export const renderMarkdownContent = (val: string) => {
39
+ const render = new MarkdownIt({
40
+ html: true,
41
+ linkify: true,
42
+ breaks: true,
43
+ highlight: function (str, lang) {
44
+ if (lang && hljs.getLanguage(lang)) {
45
+ try {
46
+ const hl = hljs.highlight(lang, str).value;
47
+ return hl;
48
+ } catch (__) {
49
+ //
50
+ }
51
+ }
52
+
53
+ return ''; // use external default escaping
54
+ },
55
+ });
56
+
57
+ return render.render(val);
58
+ };
59
+
60
+ export const renderMarkupContent = (
61
+ contents: lsp.MarkupContent | lsp.MarkedString | lsp.MarkedString[],
62
+ ) => {
63
+ const dom = document.createElement('div');
64
+ dom.classList.add('documentation');
65
+
66
+ const res = renderMarkdownContent(formatContents(contents));
67
+ dom.innerHTML = res;
68
+ return dom;
69
+ };
@@ -0,0 +1,49 @@
1
+ import type { IEditorMimeTypeService } from '@difizen/libro-code-editor';
2
+ import { defaultMimeType } from '@difizen/libro-code-editor';
3
+ import type { ILanguageInfoMetadata } from '@difizen/libro-common';
4
+
5
+ import { findBest, findByFileName } from './mode.js';
6
+
7
+ const extname = (path: string) => {
8
+ return path.split('.').pop();
9
+ };
10
+
11
+ /**
12
+ * The mime type service for CodeMirror.
13
+ */
14
+ export class CodeMirrorMimeTypeService implements IEditorMimeTypeService {
15
+ /**
16
+ * Returns a mime type for the given language info.
17
+ *
18
+ * #### Notes
19
+ * If a mime type cannot be found returns the default mime type `text/plain`, never `null`.
20
+ */
21
+ getMimeTypeByLanguage(info: ILanguageInfoMetadata): string {
22
+ const ext = info.file_extension || '';
23
+ const mode = findBest(
24
+ (info.codemirror_mode as any) || {
25
+ mimetype: info.mimetype,
26
+ name: info.name,
27
+ ext: [ext.split('.').slice(-1)[0]],
28
+ },
29
+ );
30
+ return mode ? (mode.mime as string) : defaultMimeType;
31
+ }
32
+
33
+ /**
34
+ * Returns a mime type for the given file path.
35
+ *
36
+ * #### Notes
37
+ * If a mime type cannot be found returns the default mime type `text/plain`, never `null`.
38
+ */
39
+ getMimeTypeByFilePath(path: string): string {
40
+ const ext = extname(path);
41
+ if (ext === '.ipy') {
42
+ return 'text/x-python';
43
+ } else if (ext === '.md') {
44
+ return 'text/x-ipythongfm';
45
+ }
46
+ const mode = findByFileName(path) || findBest('');
47
+ return mode ? (mode.mime as string) : defaultMimeType;
48
+ }
49
+ }
package/src/mode.ts ADDED
@@ -0,0 +1,265 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ import { markdown } from '@codemirror/lang-markdown';
3
+ import type { LanguageSupport } from '@codemirror/language';
4
+ import { LanguageDescription } from '@codemirror/language';
5
+ import { defaultMimeType } from '@difizen/libro-code-editor';
6
+ import { PathExt } from '@difizen/libro-common';
7
+ import { highlightTree } from '@lezer/highlight';
8
+
9
+ import { python } from './python-lang.js';
10
+ import { jupyterHighlightStyle } from './theme.js';
11
+
12
+ /**
13
+ * The interface of a codemirror language spec.
14
+ */
15
+ export interface ISpec {
16
+ name: string;
17
+ alias?: readonly string[];
18
+ mime: string | readonly string[];
19
+ load?: () => Promise<LanguageSupport>;
20
+ extensions?: readonly string[];
21
+ filename?: RegExp;
22
+ support?: LanguageSupport;
23
+ }
24
+
25
+ // Code mirror uses two similar structures, a plain object with optional fields,
26
+ // and a class with the same fields but all mandatory. Maybe adopting the same
27
+ // pattern would be less confusing (although far more verbose)
28
+ function makeSpec(spec: ISpec): ISpec {
29
+ const res = LanguageDescription.of(spec) as unknown as ISpec;
30
+ res.mime = spec.mime;
31
+ return res;
32
+ }
33
+
34
+ const modeList: ISpec[] = [
35
+ makeSpec({
36
+ name: 'Python',
37
+ mime: 'text/x-python',
38
+ extensions: ['BUILD', 'bzl', 'py', 'pyw'],
39
+ filename: /^(BUCK|BUILD)$/,
40
+ load() {
41
+ return Promise.resolve(python());
42
+ },
43
+ }),
44
+ makeSpec({
45
+ name: 'Markdown',
46
+ mime: 'text/x-markdown',
47
+ extensions: ['md', 'markdown', 'mkd'],
48
+ async load() {
49
+ return Promise.resolve(markdown());
50
+ },
51
+ }),
52
+ ];
53
+
54
+ /**
55
+ * Get the raw list of available modes specs.
56
+ *
57
+ * @alpha
58
+ * @returns The available modes
59
+ */
60
+ export function getModeInfo(): ISpec[] {
61
+ return modeList;
62
+ }
63
+
64
+ /**
65
+ * Find a codemirror mode by MIME.
66
+ *
67
+ * @alpha
68
+ * @param mime Mime type to look for
69
+ * @returns The mode or null
70
+ */
71
+ export function findByMIME(mime: string | readonly string[]): ISpec | null {
72
+ if (Array.isArray(mime)) {
73
+ for (let i = 0; i < mime.length; i++) {
74
+ const spec = findByMIME(mime[i]);
75
+ if (spec) {
76
+ return spec;
77
+ }
78
+ }
79
+ return null;
80
+ }
81
+ const _mime = (mime as string).toLowerCase();
82
+ for (let i = 0; i < modeList.length; i++) {
83
+ const info = modeList[i];
84
+ if (Array.isArray(info.mime)) {
85
+ for (let j = 0; j < info.mime.length; j++) {
86
+ if (info.mime[j] === _mime) {
87
+ return info;
88
+ }
89
+ }
90
+ } else if (info.mime === _mime) {
91
+ return info;
92
+ }
93
+ }
94
+ if (/\+xml$/.test(_mime)) {
95
+ return findByMIME('application/xml');
96
+ }
97
+ if (/\+json$/.test(_mime)) {
98
+ return findByMIME('application/json');
99
+ }
100
+ return null;
101
+ }
102
+
103
+ /**
104
+ * Find a codemirror mode by name.
105
+ *
106
+ * @alpha
107
+ * @param name The mode name
108
+ * @returns The mode or null
109
+ */
110
+ export function findByName(name: string): ISpec | null {
111
+ const _name = name.toLowerCase();
112
+ for (let i = 0; i < modeList.length; i++) {
113
+ const info = modeList[i];
114
+ if (info.name.toLowerCase() === _name) {
115
+ return info;
116
+ }
117
+ if (info.alias) {
118
+ for (let j = 0; j < info.alias.length; j++) {
119
+ if (info.alias[j].toLowerCase() === _name) {
120
+ return info;
121
+ }
122
+ }
123
+ }
124
+ }
125
+ return null;
126
+ }
127
+
128
+ /**
129
+ * Find a codemirror mode by extension.
130
+ *
131
+ * @alpha
132
+ * @param ext The extension name
133
+ * @returns The mode or null
134
+ */
135
+ export function findByExtension(ext: string | readonly string[]): ISpec | null {
136
+ if (Array.isArray(ext)) {
137
+ for (let i = 0; i < ext.length; i++) {
138
+ const spec = findByExtension(ext[i]);
139
+ if (spec) {
140
+ return spec;
141
+ }
142
+ }
143
+ return null;
144
+ }
145
+ const _ext = (ext as string).toLowerCase();
146
+ for (let i = 0; i < modeList.length; i++) {
147
+ const info = modeList[i];
148
+ for (let j = 0; j < info.extensions!.length; j++) {
149
+ if (info.extensions![j].toLowerCase() === _ext) {
150
+ return info;
151
+ }
152
+ }
153
+ }
154
+ return null;
155
+ }
156
+
157
+ /**
158
+ * Find a codemirror mode by filename.
159
+ *
160
+ * @param name File name
161
+ * @returns The mode or null
162
+ */
163
+ export function findByFileName(name: string): ISpec | null {
164
+ const basename = PathExt.basename(name);
165
+ for (let i = 0; i < modeList.length; i++) {
166
+ const info = modeList[i];
167
+ if (info.filename && info.filename.test(basename)) {
168
+ return info;
169
+ }
170
+ }
171
+ const dot = basename.lastIndexOf('.');
172
+ const ext = dot > -1 && basename.substring(dot + 1, basename.length);
173
+ if (ext) {
174
+ return findByExtension(ext);
175
+ }
176
+ return null;
177
+ }
178
+
179
+ /**
180
+ * Find a codemirror mode by name or CodeMirror spec.
181
+ *
182
+ * @alpha
183
+ * @param mode The CodeMirror mode
184
+ * @param fallback Whether to fallback to default mimetype spec or not
185
+ * @returns The mode or null
186
+ */
187
+ export function findBest(mode: string | ISpec, fallback = true): ISpec | null {
188
+ const modename = typeof mode === 'string' ? mode : mode.name;
189
+ const mimetype = typeof mode !== 'string' ? mode.mime : modename;
190
+ const ext = typeof mode !== 'string' ? (mode.extensions ?? []) : [];
191
+
192
+ return (
193
+ (modename ? findByName(modename) : null) ??
194
+ (mimetype ? findByMIME(mimetype) : null) ??
195
+ findByExtension(ext) ??
196
+ (fallback ? findByMIME(defaultMimeType) : null)
197
+ );
198
+ }
199
+
200
+ /**
201
+ * Ensure a codemirror mode is available by name or Codemirror spec.
202
+ *
203
+ * @param mode - The mode to ensure. If it is a string, uses [findBest]
204
+ * to get the appropriate spec.
205
+ *
206
+ * @returns A promise that resolves when the mode is available.
207
+ */
208
+ export async function ensure(mode: string | ISpec): Promise<ISpec | null> {
209
+ const spec = findBest(mode);
210
+ if (spec) {
211
+ spec.support = await spec.load!();
212
+ return spec;
213
+ }
214
+ return null;
215
+ }
216
+
217
+ /**
218
+ * Register a new mode for CodeMirror
219
+ *
220
+ * @alpha
221
+ * @param mode Mode to register
222
+ */
223
+ export function registerModeInfo(mode: ISpec): void {
224
+ const info = findBest(mode, false);
225
+ if (info) {
226
+ throw new Error(`${mode.mime} already registered`);
227
+ }
228
+ modeList.push(makeSpec(mode));
229
+ }
230
+
231
+ /**
232
+ * Parse and style a string.
233
+ *
234
+ * @alpha
235
+ * @param code Code to highlight
236
+ * @param mode Code mode
237
+ * @param el HTML element into which the highlighted code will be inserted
238
+ */
239
+ export function run(code: string, mode: ISpec, el: HTMLElement): void {
240
+ const language = mode.support?.language;
241
+ if (!language) {
242
+ return;
243
+ }
244
+
245
+ const tree = language.parser.parse(code);
246
+ // position state required because unstyled tokens are not emitted
247
+ // in highlightTree
248
+ let pos = 0;
249
+ highlightTree(tree, jupyterHighlightStyle, (from, to, classes) => {
250
+ if (from > pos) {
251
+ // No style applied to the token between pos and from
252
+ el.appendChild(document.createTextNode(code.slice(pos, from)));
253
+ }
254
+ const sp = el.appendChild(document.createElement('span'));
255
+ sp.className = classes;
256
+ sp.appendChild(document.createTextNode(code.slice(from, to)));
257
+ pos = to;
258
+ });
259
+
260
+ if (pos < tree.length - 1) {
261
+ // No style applied on the trailing text
262
+ el.appendChild(document.createTextNode(code.slice(pos, tree.length)));
263
+ }
264
+ }
265
+ // }
package/src/module.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { CodeEditorModule } from '@difizen/libro-code-editor';
2
+ import { ManaModule } from '@difizen/mana-app';
3
+
4
+ import { CodeMirrorEditorContribution } from './editor-contribution.js';
5
+
6
+ export const CodeMirrorEditorModule = ManaModule.create()
7
+ .register(CodeMirrorEditorContribution)
8
+ .dependOn(CodeEditorModule);
package/src/monitor.ts ADDED
@@ -0,0 +1,105 @@
1
+ import { EditorView, hasHoverTooltips } from '@codemirror/view';
2
+ import { Emitter } from '@difizen/mana-app';
3
+
4
+ import {
5
+ closeCompletionEffect,
6
+ setSelectedEffect,
7
+ startCompletionEffect,
8
+ } from './auto-complete/state.js';
9
+
10
+ interface DocStatus {
11
+ source: string[];
12
+ cursor: number;
13
+ changes?: string;
14
+ }
15
+
16
+ interface CompletionChange {
17
+ start?: DocStatus;
18
+ accept?: DocStatus;
19
+ close?: DocStatus;
20
+ selectIndex?: number;
21
+ }
22
+
23
+ export class CompletionMonitor {
24
+ protected static instance: CompletionMonitor;
25
+
26
+ static getInstance() {
27
+ if (!CompletionMonitor.instance) {
28
+ CompletionMonitor.instance = new CompletionMonitor();
29
+ }
30
+ return CompletionMonitor.instance;
31
+ }
32
+
33
+ protected completionChangeEmitter: Emitter<CompletionChange> = new Emitter();
34
+
35
+ get compeltionChange() {
36
+ return this.completionChangeEmitter.event;
37
+ }
38
+
39
+ protected tooltipChangeEmitter: Emitter<boolean> = new Emitter();
40
+
41
+ get onTooltipChange() {
42
+ return this.tooltipChangeEmitter.event;
43
+ }
44
+
45
+ protected currentChange: CompletionChange | undefined;
46
+
47
+ start(doc: DocStatus) {
48
+ this.currentChange = { start: doc, selectIndex: 0 };
49
+ }
50
+
51
+ accept(doc: DocStatus) {
52
+ this.currentChange = { ...this.currentChange, ...{ accept: doc } };
53
+ this.emitChange(this.currentChange);
54
+ }
55
+
56
+ close(doc: DocStatus) {
57
+ this.currentChange = { ...this.currentChange, ...{ close: doc, selectIndex: -1 } };
58
+ this.emitChange(this.currentChange);
59
+ }
60
+
61
+ updateIndex(index: number) {
62
+ this.currentChange = { ...this.currentChange, ...{ selectIndex: index } };
63
+ }
64
+
65
+ emitChange(change: CompletionChange) {
66
+ this.completionChangeEmitter.fire(change);
67
+ }
68
+ }
69
+
70
+ export interface MonitorPluginOptions {
71
+ onTooltipChange?: (visible: boolean) => void;
72
+ }
73
+
74
+ export const monitorPlugin = (options: MonitorPluginOptions) =>
75
+ EditorView.updateListener.of((update) => {
76
+ for (const trans of update.transactions) {
77
+ const { effects } = trans;
78
+
79
+ options?.onTooltipChange?.(hasHoverTooltips(update.state));
80
+
81
+ if (trans.isUserEvent('input.complete')) {
82
+ CompletionMonitor.getInstance().accept({
83
+ changes: JSON.stringify(trans.changes.toJSON()),
84
+ cursor: update.state.selection.main.head,
85
+ source: update.state.doc.toJSON(),
86
+ });
87
+ }
88
+ for (const effect of effects) {
89
+ if (effect.is(startCompletionEffect)) {
90
+ CompletionMonitor.getInstance().start({
91
+ cursor: update.state.selection.main.head,
92
+ source: update.state.doc.toJSON(),
93
+ });
94
+ } else if (effect.is(closeCompletionEffect)) {
95
+ CompletionMonitor.getInstance().close({
96
+ cursor: update.state.selection.main.head,
97
+ source: update.state.doc.toJSON(),
98
+ });
99
+ } else if (effect.is(setSelectedEffect)) {
100
+ CompletionMonitor.getInstance().updateIndex(effect.value);
101
+ }
102
+ }
103
+ }
104
+ return null;
105
+ });
@@ -0,0 +1,7 @@
1
+ import { pythonLanguage } from '@codemirror/lang-python';
2
+ import { LanguageSupport } from '@codemirror/language';
3
+
4
+ /// Python language support. 去掉了默认内置的代码提示
5
+ export function python() {
6
+ return new LanguageSupport(pythonLanguage, []);
7
+ }
@@ -0,0 +1,129 @@
1
+ /* stylelint-disable function-url-quotes */
2
+ .cm-editor {
3
+ line-height: var(--jp-code-line-height);
4
+ font-size: var(--jp-code-font-size);
5
+ font-family: var(--jp-code-font-family);
6
+ border: 0;
7
+ border-radius: 4px;
8
+ height: auto;
9
+ background: var(--mana-libro-input-background);
10
+ padding: 12px 0 18px;
11
+
12
+ /* Changed to auto to autogrow */
13
+ }
14
+
15
+ .cm-editor pre {
16
+ padding: 0 var(--jp-code-padding);
17
+ }
18
+
19
+ .cm-selectionMatch {
20
+ background-color: #e3ebff !important;
21
+ }
22
+
23
+ .jp-CodeMirrorEditor[data-type='inline'] .cm-dialog {
24
+ background-color: var(--jp-layout-color0);
25
+ color: var(--jp-content-font-color1);
26
+ }
27
+
28
+ .jp-CodeMirrorEditor {
29
+ cursor: text;
30
+ }
31
+
32
+ /* When zoomed out 67% and 33% on a screen of 1440 width x 900 height */
33
+ @media screen and (min-width: 2138px) and (max-width: 4319px) {
34
+ .jp-CodeMirrorEditor[data-type='inline'] .cm-cursor {
35
+ border-left: var(--jp-code-cursor-width1) solid var(--jp-editor-cursor-color);
36
+ }
37
+ }
38
+
39
+ /* When zoomed out less than 33% */
40
+ @media screen and (min-width: 4320px) {
41
+ .jp-CodeMirrorEditor[data-type='inline'] .cm-cursor {
42
+ border-left: var(--jp-code-cursor-width2) solid var(--jp-editor-cursor-color);
43
+ }
44
+ }
45
+
46
+ .cm-editor.jp-mod-readOnly .cm-cursor {
47
+ display: none;
48
+ }
49
+
50
+ .jp-CollaboratorCursor {
51
+ border-left: 5px solid transparent;
52
+ border-right: 5px solid transparent;
53
+ border-top: none;
54
+ border-bottom: 3px solid;
55
+ background-clip: content-box;
56
+ margin-left: -5px;
57
+ margin-right: -5px;
58
+ }
59
+
60
+ .cm-searching,
61
+ .cm-searching span {
62
+ background-color: var(--jp-search-unselected-match-background-color);
63
+ color: var(--jp-search-unselected-match-color);
64
+ }
65
+
66
+ .cm-searching span::selection {
67
+ background-color: var(--jp-search-selected-match-background-color) !important;
68
+ color: var(--jp-search-selected-match-color) !important;
69
+ }
70
+
71
+ .cm-trailingspace {
72
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAsElEQVQIHQGlAFr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7+r3zKmT0/+pk9P/7+r3zAAAAAAAAAAABAAAAAAAAAAA6OPzM+/q9wAAAAAA6OPzMwAAAAAAAAAAAgAAAAAAAAAAGR8NiRQaCgAZIA0AGR8NiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQyoYJ/SY80UAAAAASUVORK5CYII=);
73
+ background-position: center left;
74
+ background-repeat: repeat-x;
75
+ }
76
+
77
+ .jp-CollaboratorCursor-hover {
78
+ position: absolute;
79
+ z-index: 1;
80
+ transform: translateX(-50%);
81
+ color: white;
82
+ border-radius: 3px;
83
+ padding: 1px 4px;
84
+ text-align: center;
85
+ font-size: var(--jp-ui-font-size1);
86
+ white-space: nowrap;
87
+ }
88
+
89
+ .jp-CodeMirror-ruler {
90
+ border-left: 1px dashed var(--jp-border-color2);
91
+ }
92
+
93
+ /* Styles for shared cursors (remote cursor locations and selected ranges) */
94
+ .jp-CodeMirrorEditor .remote-caret {
95
+ position: relative;
96
+ border-left: 2px solid black;
97
+ margin-left: -1px;
98
+ margin-right: -1px;
99
+ box-sizing: border-box;
100
+ }
101
+
102
+ .jp-CodeMirrorEditor .remote-caret > div {
103
+ white-space: nowrap;
104
+ position: absolute;
105
+ top: -1.15em;
106
+ padding-bottom: 0.05em;
107
+ left: -2px;
108
+ font-size: 0.95em;
109
+ background-color: rgb(250, 129, 0);
110
+ font-family: var(--jp-ui-font-family);
111
+ font-weight: bold;
112
+ line-height: normal;
113
+ user-select: none;
114
+ color: white;
115
+ padding-left: 2px;
116
+ padding-right: 2px;
117
+ z-index: 3;
118
+ transition: opacity 0.3s ease-in-out;
119
+ }
120
+
121
+ .jp-CodeMirrorEditor .remote-caret.hide-name > div {
122
+ transition-delay: 0.7s;
123
+ opacity: 0;
124
+ }
125
+
126
+ .jp-CodeMirrorEditor .remote-caret:hover > div {
127
+ opacity: 1;
128
+ transition-delay: 0s;
129
+ }
@@ -0,0 +1,12 @@
1
+ @import './variables.css';
2
+
3
+ /* Set the default typography for monospace elements */
4
+ tt,
5
+ code,
6
+ kbd,
7
+ samp,
8
+ pre {
9
+ font-family: var(--jp-code-font-family);
10
+ font-size: var(--jp-code-font-size);
11
+ line-height: var(--jp-code-line-height);
12
+ }