@jupyterlab/codemirror 4.0.0-alpha.8 → 4.0.0-beta.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/lib/codemirror-ipythongfm.d.ts +9 -3
- package/lib/codemirror-ipythongfm.js +52 -30
- package/lib/codemirror-ipythongfm.js.map +1 -1
- package/lib/commands.d.ts +13 -0
- package/lib/commands.js +32 -0
- package/lib/commands.js.map +1 -0
- package/lib/editor.d.ts +48 -273
- package/lib/editor.js +220 -819
- package/lib/editor.js.map +1 -1
- package/lib/extension.d.ts +236 -0
- package/lib/extension.js +696 -0
- package/lib/extension.js.map +1 -0
- package/lib/extensions/customStyle.d.ts +25 -0
- package/lib/extensions/customStyle.js +51 -0
- package/lib/extensions/customStyle.js.map +1 -0
- package/lib/extensions/index.d.ts +3 -0
- package/lib/extensions/index.js +8 -0
- package/lib/extensions/index.js.map +1 -0
- package/lib/extensions/rulers.d.ts +8 -0
- package/lib/extensions/rulers.js +85 -0
- package/lib/extensions/rulers.js.map +1 -0
- package/lib/extensions/ybinding.d.ts +129 -0
- package/lib/extensions/ybinding.js +229 -0
- package/lib/extensions/ybinding.js.map +1 -0
- package/lib/factory.d.ts +15 -5
- package/lib/factory.js +53 -24
- package/lib/factory.js.map +1 -1
- package/lib/index.d.ts +7 -19
- package/lib/index.js +7 -23
- package/lib/index.js.map +1 -1
- package/lib/language.d.ts +96 -0
- package/lib/language.js +1687 -0
- package/lib/language.js.map +1 -0
- package/lib/mimetype.d.ts +3 -0
- package/lib/mimetype.js +16 -5
- package/lib/mimetype.js.map +1 -1
- package/lib/searchprovider.d.ts +219 -0
- package/lib/searchprovider.js +640 -0
- package/lib/searchprovider.js.map +1 -0
- package/lib/theme.d.ts +57 -0
- package/lib/theme.js +194 -0
- package/lib/theme.js.map +1 -0
- package/lib/token.d.ts +375 -0
- package/lib/token.js +18 -0
- package/lib/token.js.map +1 -0
- package/package.json +45 -41
- package/src/codemirror-ipythongfm.ts +109 -0
- package/src/commands.ts +34 -0
- package/src/editor.ts +783 -0
- package/src/extension.ts +890 -0
- package/src/extensions/customStyle.ts +79 -0
- package/src/extensions/index.ts +8 -0
- package/src/extensions/rulers.ts +112 -0
- package/src/extensions/ybinding.ts +295 -0
- package/src/factory.ts +100 -0
- package/src/index.ts +17 -0
- package/src/language.ts +1726 -0
- package/src/mimetype.ts +54 -0
- package/src/searchprovider.ts +813 -0
- package/src/theme.ts +219 -0
- package/src/token.ts +436 -0
- package/src/typings.d.ts +13 -0
- package/style/base.css +33 -187
- package/style/index.css +1 -7
- package/style/index.js +1 -7
- package/lib/codemirror-ipython.d.ts +0 -2
- package/lib/codemirror-ipython.js +0 -30
- package/lib/codemirror-ipython.js.map +0 -1
- package/lib/mode.d.ts +0 -82
- package/lib/mode.js +0 -150
- package/lib/mode.js.map +0 -1
- package/lib/syntaxstatus.d.ts +0 -67
- package/lib/syntaxstatus.js +0 -140
- package/lib/syntaxstatus.js.map +0 -1
- package/lib/tokens.d.ts +0 -18
- package/lib/tokens.js +0 -8
- package/lib/tokens.js.map +0 -1
- package/typings/codemirror/codemirror.d.ts +0 -227
package/lib/extension.js
ADDED
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
import { closeBrackets } from '@codemirror/autocomplete';
|
|
4
|
+
import { defaultKeymap, indentLess } from '@codemirror/commands';
|
|
5
|
+
import { bracketMatching, foldGutter, indentOnInput, indentUnit } from '@codemirror/language';
|
|
6
|
+
import { Compartment, EditorState, StateEffect } from '@codemirror/state';
|
|
7
|
+
import { drawSelection, EditorView, highlightActiveLine, highlightTrailingWhitespace, highlightWhitespace, keymap, lineNumbers, scrollPastEnd } from '@codemirror/view';
|
|
8
|
+
import { nullTranslator } from '@jupyterlab/translation';
|
|
9
|
+
import { JSONExt } from '@lumino/coreutils';
|
|
10
|
+
import { Signal } from '@lumino/signaling';
|
|
11
|
+
import { StateCommands } from './commands';
|
|
12
|
+
import { customTheme, rulers } from './extensions';
|
|
13
|
+
/**
|
|
14
|
+
* The class name added to read only editor widgets.
|
|
15
|
+
*/
|
|
16
|
+
const READ_ONLY_CLASS = 'jp-mod-readOnly';
|
|
17
|
+
/**
|
|
18
|
+
* Editor configuration handler
|
|
19
|
+
*
|
|
20
|
+
* It stores the editor configuration and the editor extensions.
|
|
21
|
+
* It also allows to inject new extensions into an editor.
|
|
22
|
+
*/
|
|
23
|
+
export class ExtensionsHandler {
|
|
24
|
+
constructor({ baseConfiguration, config, defaultExtensions } = {}) {
|
|
25
|
+
this._configChanged = new Signal(this);
|
|
26
|
+
this._disposed = new Signal(this);
|
|
27
|
+
this._isDisposed = false;
|
|
28
|
+
this._immutables = new Set();
|
|
29
|
+
this._baseConfig = baseConfiguration !== null && baseConfiguration !== void 0 ? baseConfiguration : {};
|
|
30
|
+
this._config = config !== null && config !== void 0 ? config : {};
|
|
31
|
+
this._configurableBuilderMap = new Map(defaultExtensions);
|
|
32
|
+
const configurables = Object.keys(this._config).concat(Object.keys(this._baseConfig));
|
|
33
|
+
this._immutables = new Set([...this._configurableBuilderMap.keys()].filter(key => !configurables.includes(key)));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Signal triggered when the editor configuration changes.
|
|
37
|
+
* It provides the mapping of the new configuration (only those that changed).
|
|
38
|
+
*
|
|
39
|
+
* It should result in a call to `IExtensionsHandler.reconfigureExtensions`.
|
|
40
|
+
*/
|
|
41
|
+
get configChanged() {
|
|
42
|
+
return this._configChanged;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A signal emitted when the object is disposed.
|
|
46
|
+
*/
|
|
47
|
+
get disposed() {
|
|
48
|
+
return this._disposed;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Tests whether the object is disposed.
|
|
52
|
+
*/
|
|
53
|
+
get isDisposed() {
|
|
54
|
+
return this._isDisposed;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Dispose of the resources held by the object.
|
|
58
|
+
*/
|
|
59
|
+
dispose() {
|
|
60
|
+
if (this.isDisposed) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this._isDisposed = true;
|
|
64
|
+
this._disposed.emit();
|
|
65
|
+
Signal.clearData(this);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get a config option for the editor.
|
|
69
|
+
*/
|
|
70
|
+
getOption(option) {
|
|
71
|
+
var _a;
|
|
72
|
+
return (_a = this._config[option]) !== null && _a !== void 0 ? _a : this._baseConfig[option];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Whether the option exists or not.
|
|
76
|
+
*/
|
|
77
|
+
hasOption(option) {
|
|
78
|
+
return (Object.keys(this._config).includes(option) ||
|
|
79
|
+
Object.keys(this._baseConfig).includes(option));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Set a config option for the editor.
|
|
83
|
+
*
|
|
84
|
+
* You will need to reconfigure the editor extensions by listening
|
|
85
|
+
* to `IExtensionsHandler.configChanged`.
|
|
86
|
+
*/
|
|
87
|
+
setOption(option, value) {
|
|
88
|
+
// Don't bother setting the option if it is already the same.
|
|
89
|
+
if (this._config[option] !== value) {
|
|
90
|
+
this._config[option] = value;
|
|
91
|
+
this._configChanged.emit({ [option]: value });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Set a base config option for the editor.
|
|
96
|
+
*
|
|
97
|
+
* You will need to reconfigure the editor extensions by listening
|
|
98
|
+
* to `IExtensionsHandler.configChanged`.
|
|
99
|
+
*/
|
|
100
|
+
setBaseOptions(options) {
|
|
101
|
+
const changed = this._getChangedOptions(options, this._baseConfig);
|
|
102
|
+
if (changed.length > 0) {
|
|
103
|
+
this._baseConfig = options;
|
|
104
|
+
const customizedKeys = Object.keys(this._config);
|
|
105
|
+
const notOverridden = changed.filter(k => !customizedKeys.includes(k));
|
|
106
|
+
if (notOverridden.length > 0) {
|
|
107
|
+
this._configChanged.emit(notOverridden.reduce((agg, key) => {
|
|
108
|
+
agg[key] = this._baseConfig[key];
|
|
109
|
+
return agg;
|
|
110
|
+
}, {}));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Set config options for the editor.
|
|
116
|
+
*
|
|
117
|
+
* You will need to reconfigure the editor extensions by listening
|
|
118
|
+
* to `EditorHandler.configChanged`.
|
|
119
|
+
*
|
|
120
|
+
* This method is preferred when setting several options. The
|
|
121
|
+
* options are set within an operation, which only performs
|
|
122
|
+
* the costly update at the end, and not after every option
|
|
123
|
+
* is set.
|
|
124
|
+
*/
|
|
125
|
+
setOptions(options) {
|
|
126
|
+
const changed = this._getChangedOptions(options, this._config);
|
|
127
|
+
if (changed.length > 0) {
|
|
128
|
+
this._config = { ...options };
|
|
129
|
+
this._configChanged.emit(changed.reduce((agg, key) => {
|
|
130
|
+
var _a;
|
|
131
|
+
agg[key] = (_a = this._config[key]) !== null && _a !== void 0 ? _a : this._baseConfig[key];
|
|
132
|
+
return agg;
|
|
133
|
+
}, {}));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Reconfigures the extension mapped with key with the provided value.
|
|
138
|
+
*
|
|
139
|
+
* @param view Editor view
|
|
140
|
+
* @param key Parameter unique key
|
|
141
|
+
* @param value Parameter value to be applied
|
|
142
|
+
*/
|
|
143
|
+
reconfigureExtension(view, key, value) {
|
|
144
|
+
const effect = this.getEffect(view.state, key, value);
|
|
145
|
+
if (effect) {
|
|
146
|
+
view.dispatch({
|
|
147
|
+
effects: [effect]
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Reconfigures all the extensions mapped with the options from the
|
|
153
|
+
* provided partial configuration.
|
|
154
|
+
*
|
|
155
|
+
* @param view Editor view
|
|
156
|
+
* @param configuration Editor configuration
|
|
157
|
+
*/
|
|
158
|
+
reconfigureExtensions(view, configuration) {
|
|
159
|
+
const effects = Object.keys(configuration)
|
|
160
|
+
.filter(key => this.has(key))
|
|
161
|
+
.map(key => this.getEffect(view.state, key, configuration[key]));
|
|
162
|
+
view.dispatch({
|
|
163
|
+
effects: effects.filter(effect => effect !== null)
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Appends extensions to the top-level configuration of the
|
|
168
|
+
* editor.
|
|
169
|
+
*
|
|
170
|
+
* Injected extension cannot be removed.
|
|
171
|
+
*
|
|
172
|
+
* ### Notes
|
|
173
|
+
* You should prefer registering a IEditorExtensionFactory instead
|
|
174
|
+
* of this feature.
|
|
175
|
+
*
|
|
176
|
+
* @alpha
|
|
177
|
+
* @param view Editor view
|
|
178
|
+
* @param extension Editor extension to inject
|
|
179
|
+
*/
|
|
180
|
+
injectExtension(view, extension) {
|
|
181
|
+
view.dispatch({
|
|
182
|
+
effects: StateEffect.appendConfig.of(extension)
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Returns the list of initial extensions of an editor
|
|
187
|
+
* based on the configuration.
|
|
188
|
+
*
|
|
189
|
+
* @returns The initial editor extensions
|
|
190
|
+
*/
|
|
191
|
+
getInitialExtensions() {
|
|
192
|
+
const configuration = { ...this._baseConfig, ...this._config };
|
|
193
|
+
const extensions = [...this._immutables]
|
|
194
|
+
.map(key => { var _a; return (_a = this.get(key)) === null || _a === void 0 ? void 0 : _a.instance(undefined); })
|
|
195
|
+
.filter(ext => ext);
|
|
196
|
+
for (const k of Object.keys(configuration)) {
|
|
197
|
+
const builder = this.get(k);
|
|
198
|
+
if (builder) {
|
|
199
|
+
const value = configuration[k];
|
|
200
|
+
extensions.push(builder.instance(value));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return extensions;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Get a extension builder
|
|
207
|
+
* @param key Extension unique identifier
|
|
208
|
+
* @returns The extension builder
|
|
209
|
+
*/
|
|
210
|
+
get(key) {
|
|
211
|
+
return this._configurableBuilderMap.get(key);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Whether the editor has an extension for the identifier.
|
|
215
|
+
*
|
|
216
|
+
* @param key Extension unique identifier
|
|
217
|
+
* @returns Extension existence
|
|
218
|
+
*/
|
|
219
|
+
has(key) {
|
|
220
|
+
return this._configurableBuilderMap.has(key);
|
|
221
|
+
}
|
|
222
|
+
getEffect(state, key, value) {
|
|
223
|
+
var _a;
|
|
224
|
+
const builder = this.get(key);
|
|
225
|
+
return (_a = builder === null || builder === void 0 ? void 0 : builder.reconfigure(value)) !== null && _a !== void 0 ? _a : null;
|
|
226
|
+
}
|
|
227
|
+
_getChangedOptions(newConfig, oldConfig) {
|
|
228
|
+
const changed = new Array();
|
|
229
|
+
const newKeys = new Array();
|
|
230
|
+
for (const [key, value] of Object.entries(newConfig)) {
|
|
231
|
+
newKeys.push(key);
|
|
232
|
+
if (oldConfig[key] !== value) {
|
|
233
|
+
changed.push(key);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// Add removed old keys
|
|
237
|
+
changed.push(...Object.keys(oldConfig).filter(k => !newKeys.includes(k)));
|
|
238
|
+
return changed;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* CodeMirror extensions registry
|
|
243
|
+
*/
|
|
244
|
+
export class EditorExtensionRegistry {
|
|
245
|
+
constructor() {
|
|
246
|
+
this.configurationBuilder = new Map();
|
|
247
|
+
this.configurationSchema = {};
|
|
248
|
+
this.defaultOptions = {};
|
|
249
|
+
this.handlers = new Set();
|
|
250
|
+
this.immutableExtensions = new Set();
|
|
251
|
+
this._baseConfiguration = {};
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Base editor configuration
|
|
255
|
+
*
|
|
256
|
+
* This is the default configuration optionally modified by the user;
|
|
257
|
+
* e.g. through user settings.
|
|
258
|
+
*/
|
|
259
|
+
get baseConfiguration() {
|
|
260
|
+
return { ...this.defaultOptions, ...this._baseConfiguration };
|
|
261
|
+
}
|
|
262
|
+
set baseConfiguration(v) {
|
|
263
|
+
if (!JSONExt.deepEqual(v, this._baseConfiguration)) {
|
|
264
|
+
this._baseConfiguration = v;
|
|
265
|
+
for (const handler of this.handlers) {
|
|
266
|
+
handler.setBaseOptions(this.baseConfiguration);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Default editor configuration
|
|
272
|
+
*
|
|
273
|
+
* This is the default configuration as defined when extensions
|
|
274
|
+
* are registered.
|
|
275
|
+
*/
|
|
276
|
+
get defaultConfiguration() {
|
|
277
|
+
// Only options with schema should be JSON serializable
|
|
278
|
+
// So we cannot use `JSONExt.deepCopy` on the default options.
|
|
279
|
+
return Object.freeze({ ...this.defaultOptions });
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Editor configuration JSON schema
|
|
283
|
+
*/
|
|
284
|
+
get settingsSchema() {
|
|
285
|
+
return Object.freeze(JSONExt.deepCopy(this.configurationSchema));
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Add a default editor extension
|
|
289
|
+
*
|
|
290
|
+
* @template T Extension parameter type
|
|
291
|
+
* @param factory Extension factory
|
|
292
|
+
*/
|
|
293
|
+
addExtension(factory) {
|
|
294
|
+
var _a;
|
|
295
|
+
if (this.configurationBuilder.has(factory.name)) {
|
|
296
|
+
throw new Error(`Extension named ${factory.name} is already registered.`);
|
|
297
|
+
}
|
|
298
|
+
this.configurationBuilder.set(factory.name, factory);
|
|
299
|
+
if (typeof factory.default != 'undefined') {
|
|
300
|
+
this.defaultOptions[factory.name] = factory.default;
|
|
301
|
+
}
|
|
302
|
+
if (factory.schema) {
|
|
303
|
+
this.configurationSchema[factory.name] = {
|
|
304
|
+
default: (_a = factory.default) !== null && _a !== void 0 ? _a : null,
|
|
305
|
+
...factory.schema
|
|
306
|
+
};
|
|
307
|
+
this.defaultOptions[factory.name] =
|
|
308
|
+
this.configurationSchema[factory.name].default;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Create a new extensions handler for an editor
|
|
313
|
+
*
|
|
314
|
+
* @param options Extensions options and initial editor configuration
|
|
315
|
+
*/
|
|
316
|
+
createNew(options) {
|
|
317
|
+
const configuration = new Array();
|
|
318
|
+
for (const [key, builder] of this.configurationBuilder.entries()) {
|
|
319
|
+
const extension = builder.factory(options);
|
|
320
|
+
if (extension) {
|
|
321
|
+
configuration.push([key, extension]);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const handler = new ExtensionsHandler({
|
|
325
|
+
baseConfiguration: this.baseConfiguration,
|
|
326
|
+
config: options.config,
|
|
327
|
+
defaultExtensions: configuration
|
|
328
|
+
});
|
|
329
|
+
this.handlers.add(handler);
|
|
330
|
+
handler.disposed.connect(() => {
|
|
331
|
+
this.handlers.delete(handler);
|
|
332
|
+
});
|
|
333
|
+
return handler;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Editor extension registry namespace
|
|
338
|
+
*/
|
|
339
|
+
(function (EditorExtensionRegistry) {
|
|
340
|
+
/**
|
|
341
|
+
* Dynamically configurable editor extension.
|
|
342
|
+
*/
|
|
343
|
+
class ConfigurableExtension {
|
|
344
|
+
/**
|
|
345
|
+
* Create a dynamic editor extension.
|
|
346
|
+
*
|
|
347
|
+
* @param builder Extension builder
|
|
348
|
+
*/
|
|
349
|
+
constructor(builder) {
|
|
350
|
+
this._compartment = new Compartment();
|
|
351
|
+
this._builder = builder;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Create an editor extension for the provided value.
|
|
355
|
+
*
|
|
356
|
+
* @param value Editor extension parameter value
|
|
357
|
+
* @returns The editor extension
|
|
358
|
+
*/
|
|
359
|
+
instance(value) {
|
|
360
|
+
return this._compartment.of(this._builder(value));
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Reconfigure an editor extension.
|
|
364
|
+
*
|
|
365
|
+
* @param value Editor extension value
|
|
366
|
+
* @returns Editor state effect
|
|
367
|
+
*/
|
|
368
|
+
reconfigure(value) {
|
|
369
|
+
return this._compartment.reconfigure(this._builder(value));
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Immutable editor extension class
|
|
374
|
+
*/
|
|
375
|
+
class ImmutableExtension {
|
|
376
|
+
/**
|
|
377
|
+
* Create an immutable editor extension.
|
|
378
|
+
*
|
|
379
|
+
* @param extension Extension
|
|
380
|
+
*/
|
|
381
|
+
constructor(extension) {
|
|
382
|
+
this._extension = extension;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Create an editor extension.
|
|
386
|
+
*
|
|
387
|
+
* @returns The editor extension
|
|
388
|
+
*/
|
|
389
|
+
instance() {
|
|
390
|
+
return this._extension;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Reconfigure an editor extension.
|
|
394
|
+
*
|
|
395
|
+
* This is a no-op
|
|
396
|
+
*/
|
|
397
|
+
reconfigure() {
|
|
398
|
+
// This is a no-op
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Creates a dynamically configurable editor extension.
|
|
404
|
+
*
|
|
405
|
+
* @param builder Extension builder
|
|
406
|
+
* @return The extension
|
|
407
|
+
*/
|
|
408
|
+
function createConfigurableExtension(builder) {
|
|
409
|
+
return new ConfigurableExtension(builder);
|
|
410
|
+
}
|
|
411
|
+
EditorExtensionRegistry.createConfigurableExtension = createConfigurableExtension;
|
|
412
|
+
/**
|
|
413
|
+
* Creates a configurable extension returning
|
|
414
|
+
* one of two extensions depending on a boolean value.
|
|
415
|
+
*
|
|
416
|
+
* @param truthy Extension to apply when the parameter is true
|
|
417
|
+
* @param falsy Extension to apply when the parameter is false
|
|
418
|
+
* @return The extension
|
|
419
|
+
*/
|
|
420
|
+
function createConditionalExtension(truthy, falsy = []) {
|
|
421
|
+
return new ConfigurableExtension(value => value ? truthy : falsy);
|
|
422
|
+
}
|
|
423
|
+
EditorExtensionRegistry.createConditionalExtension = createConditionalExtension;
|
|
424
|
+
/**
|
|
425
|
+
* Creates an immutable extension.
|
|
426
|
+
*
|
|
427
|
+
* @param extension Immutable extension
|
|
428
|
+
* @return The extension
|
|
429
|
+
*/
|
|
430
|
+
function createImmutableExtension(extension) {
|
|
431
|
+
return new ImmutableExtension(extension);
|
|
432
|
+
}
|
|
433
|
+
EditorExtensionRegistry.createImmutableExtension = createImmutableExtension;
|
|
434
|
+
/**
|
|
435
|
+
* Get the default editor extensions.
|
|
436
|
+
*
|
|
437
|
+
* @returns CodeMirror 6 extension factories
|
|
438
|
+
*/
|
|
439
|
+
function getDefaultExtensions(options = {}) {
|
|
440
|
+
const { themes, translator } = options;
|
|
441
|
+
const trans = (translator !== null && translator !== void 0 ? translator : nullTranslator).load('jupyter');
|
|
442
|
+
const extensions = [
|
|
443
|
+
Object.freeze({
|
|
444
|
+
name: 'autoClosingBrackets',
|
|
445
|
+
default: false,
|
|
446
|
+
factory: () => createConditionalExtension(closeBrackets()),
|
|
447
|
+
schema: {
|
|
448
|
+
type: 'boolean',
|
|
449
|
+
title: trans.__('Auto Closing Brackets')
|
|
450
|
+
}
|
|
451
|
+
}),
|
|
452
|
+
Object.freeze({
|
|
453
|
+
name: 'codeFolding',
|
|
454
|
+
default: false,
|
|
455
|
+
factory: () => createConditionalExtension(foldGutter()),
|
|
456
|
+
schema: {
|
|
457
|
+
type: 'boolean',
|
|
458
|
+
title: trans.__('Code Folding')
|
|
459
|
+
}
|
|
460
|
+
}),
|
|
461
|
+
Object.freeze({
|
|
462
|
+
name: 'cursorBlinkRate',
|
|
463
|
+
default: 1200,
|
|
464
|
+
factory: () => createConfigurableExtension((value) => drawSelection({ cursorBlinkRate: value })),
|
|
465
|
+
schema: {
|
|
466
|
+
type: 'number',
|
|
467
|
+
title: trans.__('Cursor blinking rate'),
|
|
468
|
+
description: trans.__('Half-period in milliseconds used for cursor blinking. The default blink rate is 1200ms. By setting this to zero, blinking can be disabled.')
|
|
469
|
+
}
|
|
470
|
+
}),
|
|
471
|
+
Object.freeze({
|
|
472
|
+
name: 'highlightActiveLine',
|
|
473
|
+
default: false,
|
|
474
|
+
factory: () => createConditionalExtension(highlightActiveLine()),
|
|
475
|
+
schema: {
|
|
476
|
+
type: 'boolean',
|
|
477
|
+
title: trans.__('Highlight the active line')
|
|
478
|
+
}
|
|
479
|
+
}),
|
|
480
|
+
Object.freeze({
|
|
481
|
+
name: 'highlightTrailingWhitespace',
|
|
482
|
+
default: false,
|
|
483
|
+
factory: () => createConditionalExtension(highlightTrailingWhitespace()),
|
|
484
|
+
schema: {
|
|
485
|
+
type: 'boolean',
|
|
486
|
+
title: trans.__('Highlight trailing white spaces')
|
|
487
|
+
}
|
|
488
|
+
}),
|
|
489
|
+
Object.freeze({
|
|
490
|
+
name: 'highlightWhitespace',
|
|
491
|
+
default: false,
|
|
492
|
+
factory: () => createConditionalExtension(highlightWhitespace()),
|
|
493
|
+
schema: {
|
|
494
|
+
type: 'boolean',
|
|
495
|
+
title: trans.__('Highlight white spaces')
|
|
496
|
+
}
|
|
497
|
+
}),
|
|
498
|
+
Object.freeze({
|
|
499
|
+
name: 'indentUnit',
|
|
500
|
+
default: '2',
|
|
501
|
+
factory: () => createConfigurableExtension((value) => value == 'Tab'
|
|
502
|
+
? indentUnit.of('\t')
|
|
503
|
+
: indentUnit.of(' '.repeat(parseInt(value, 10)))),
|
|
504
|
+
schema: {
|
|
505
|
+
type: 'string',
|
|
506
|
+
title: trans.__('Indentation unit'),
|
|
507
|
+
description: trans.__('The indentation is a `Tab` or the number of spaces. This defaults to 2 spaces.'),
|
|
508
|
+
enum: ['Tab', '1', '2', '4', '8']
|
|
509
|
+
}
|
|
510
|
+
}),
|
|
511
|
+
// Default keyboard shortcuts
|
|
512
|
+
// TODO at some point we may want to get this configurable
|
|
513
|
+
Object.freeze({
|
|
514
|
+
name: 'keymap',
|
|
515
|
+
default: [
|
|
516
|
+
...defaultKeymap,
|
|
517
|
+
{
|
|
518
|
+
key: 'Tab',
|
|
519
|
+
run: StateCommands.indentMoreOrInsertTab,
|
|
520
|
+
shift: indentLess
|
|
521
|
+
}
|
|
522
|
+
],
|
|
523
|
+
factory: () => createConfigurableExtension(value => keymap.of(value))
|
|
524
|
+
}),
|
|
525
|
+
Object.freeze({
|
|
526
|
+
name: 'lineNumbers',
|
|
527
|
+
default: true,
|
|
528
|
+
factory: () => createConditionalExtension(lineNumbers()),
|
|
529
|
+
schema: {
|
|
530
|
+
type: 'boolean',
|
|
531
|
+
title: trans.__('Line Numbers')
|
|
532
|
+
}
|
|
533
|
+
}),
|
|
534
|
+
Object.freeze({
|
|
535
|
+
name: 'lineWrap',
|
|
536
|
+
factory: () => createConditionalExtension(EditorView.lineWrapping),
|
|
537
|
+
default: true,
|
|
538
|
+
schema: {
|
|
539
|
+
type: 'boolean',
|
|
540
|
+
title: trans.__('Line Wrap')
|
|
541
|
+
}
|
|
542
|
+
}),
|
|
543
|
+
Object.freeze({
|
|
544
|
+
name: 'matchBrackets',
|
|
545
|
+
default: true,
|
|
546
|
+
factory: () => createConditionalExtension(bracketMatching()),
|
|
547
|
+
schema: {
|
|
548
|
+
type: 'boolean',
|
|
549
|
+
title: trans.__('Match Brackets')
|
|
550
|
+
}
|
|
551
|
+
}),
|
|
552
|
+
Object.freeze({
|
|
553
|
+
name: 'readOnly',
|
|
554
|
+
default: false,
|
|
555
|
+
factory: () => createConfigurableExtension((value) => [
|
|
556
|
+
EditorState.readOnly.of(value),
|
|
557
|
+
value
|
|
558
|
+
? EditorView.editorAttributes.of({ class: READ_ONLY_CLASS })
|
|
559
|
+
: []
|
|
560
|
+
])
|
|
561
|
+
}),
|
|
562
|
+
Object.freeze({
|
|
563
|
+
name: 'rulers',
|
|
564
|
+
default: [],
|
|
565
|
+
factory: () => createConfigurableExtension((value) => value.length > 0 ? rulers(value) : []),
|
|
566
|
+
schema: {
|
|
567
|
+
type: 'array',
|
|
568
|
+
title: trans.__('Rulers'),
|
|
569
|
+
items: {
|
|
570
|
+
type: 'number',
|
|
571
|
+
minimum: 0
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}),
|
|
575
|
+
Object.freeze({
|
|
576
|
+
name: 'scrollPastEnd',
|
|
577
|
+
default: false,
|
|
578
|
+
factory: (options) => options.inline ? null : createConditionalExtension(scrollPastEnd())
|
|
579
|
+
}),
|
|
580
|
+
Object.freeze({
|
|
581
|
+
name: 'smartIndent',
|
|
582
|
+
default: true,
|
|
583
|
+
factory: () => createConditionalExtension(indentOnInput()),
|
|
584
|
+
schema: {
|
|
585
|
+
type: 'boolean',
|
|
586
|
+
title: trans.__('Smart Indentation')
|
|
587
|
+
}
|
|
588
|
+
}),
|
|
589
|
+
Object.freeze({
|
|
590
|
+
name: 'tabSize',
|
|
591
|
+
default: 4,
|
|
592
|
+
factory: () => createConfigurableExtension((value) => EditorState.tabSize.of(value)),
|
|
593
|
+
schema: {
|
|
594
|
+
type: 'number',
|
|
595
|
+
title: trans.__('Tab size')
|
|
596
|
+
}
|
|
597
|
+
}),
|
|
598
|
+
Object.freeze({
|
|
599
|
+
name: 'allowMultipleSelections',
|
|
600
|
+
default: true,
|
|
601
|
+
factory: () => createConfigurableExtension((value) => EditorState.allowMultipleSelections.of(value)),
|
|
602
|
+
schema: {
|
|
603
|
+
type: 'boolean',
|
|
604
|
+
title: trans.__('Multiple selections')
|
|
605
|
+
}
|
|
606
|
+
}),
|
|
607
|
+
Object.freeze({
|
|
608
|
+
name: 'customStyles',
|
|
609
|
+
factory: () => createConfigurableExtension(config => customTheme(config)),
|
|
610
|
+
default: {
|
|
611
|
+
fontFamily: null,
|
|
612
|
+
fontSize: null,
|
|
613
|
+
lineHeight: null
|
|
614
|
+
},
|
|
615
|
+
schema: {
|
|
616
|
+
title: trans.__('Custom editor styles'),
|
|
617
|
+
type: 'object',
|
|
618
|
+
properties: {
|
|
619
|
+
fontFamily: {
|
|
620
|
+
type: ['string', 'null'],
|
|
621
|
+
title: trans.__('Font Family')
|
|
622
|
+
},
|
|
623
|
+
fontSize: {
|
|
624
|
+
type: ['number', 'null'],
|
|
625
|
+
minimum: 1,
|
|
626
|
+
maximum: 100,
|
|
627
|
+
title: trans.__('Font Size')
|
|
628
|
+
},
|
|
629
|
+
lineHeight: {
|
|
630
|
+
type: ['number', 'null'],
|
|
631
|
+
title: trans.__('Line Height')
|
|
632
|
+
}
|
|
633
|
+
},
|
|
634
|
+
additionalProperties: false
|
|
635
|
+
}
|
|
636
|
+
})
|
|
637
|
+
];
|
|
638
|
+
if (themes) {
|
|
639
|
+
extensions.push(Object.freeze({
|
|
640
|
+
name: 'theme',
|
|
641
|
+
default: 'jupyter',
|
|
642
|
+
factory: () => createConfigurableExtension(value => themes.getTheme(value)),
|
|
643
|
+
schema: {
|
|
644
|
+
type: 'string',
|
|
645
|
+
title: trans.__('Theme'),
|
|
646
|
+
description: trans.__('CodeMirror theme')
|
|
647
|
+
}
|
|
648
|
+
}));
|
|
649
|
+
}
|
|
650
|
+
if (translator) {
|
|
651
|
+
extensions.push(Object.freeze({
|
|
652
|
+
name: 'translation',
|
|
653
|
+
// The list of internal strings is available at https://codemirror.net/examples/translate/
|
|
654
|
+
default: {
|
|
655
|
+
// @codemirror/view
|
|
656
|
+
'Control character': trans.__('Control character'),
|
|
657
|
+
// @codemirror/commands
|
|
658
|
+
'Selection deleted': trans.__('Selection deleted'),
|
|
659
|
+
// @codemirror/language
|
|
660
|
+
'Folded lines': trans.__('Folded lines'),
|
|
661
|
+
'Unfolded lines': trans.__('Unfolded lines'),
|
|
662
|
+
to: trans.__('to'),
|
|
663
|
+
'folded code': trans.__('folded code'),
|
|
664
|
+
unfold: trans.__('unfold'),
|
|
665
|
+
'Fold line': trans.__('Fold line'),
|
|
666
|
+
'Unfold line': trans.__('Unfold line'),
|
|
667
|
+
// @codemirror/search
|
|
668
|
+
'Go to line': trans.__('Go to line'),
|
|
669
|
+
go: trans.__('go'),
|
|
670
|
+
Find: trans.__('Find'),
|
|
671
|
+
Replace: trans.__('Replace'),
|
|
672
|
+
next: trans.__('next'),
|
|
673
|
+
previous: trans.__('previous'),
|
|
674
|
+
all: trans.__('all'),
|
|
675
|
+
'match case': trans.__('match case'),
|
|
676
|
+
replace: trans.__('replace'),
|
|
677
|
+
'replace all': trans.__('replace all'),
|
|
678
|
+
close: trans.__('close'),
|
|
679
|
+
'current match': trans.__('current match'),
|
|
680
|
+
'replaced $ matches': trans.__('replaced $ matches'),
|
|
681
|
+
'replaced match on line $': trans.__('replaced match on line $'),
|
|
682
|
+
'on line': trans.__('on line'),
|
|
683
|
+
// @codemirror/autocomplete
|
|
684
|
+
Completions: trans.__('Completions'),
|
|
685
|
+
// @codemirror/lint
|
|
686
|
+
Diagnostics: trans.__('Diagnostics'),
|
|
687
|
+
'No diagnostics': trans.__('No diagnostics')
|
|
688
|
+
},
|
|
689
|
+
factory: () => createConfigurableExtension(value => EditorState.phrases.of(value))
|
|
690
|
+
}));
|
|
691
|
+
}
|
|
692
|
+
return extensions;
|
|
693
|
+
}
|
|
694
|
+
EditorExtensionRegistry.getDefaultExtensions = getDefaultExtensions;
|
|
695
|
+
})(EditorExtensionRegistry || (EditorExtensionRegistry = {}));
|
|
696
|
+
//# sourceMappingURL=extension.js.map
|