@bhsd/codemirror-mediawiki 2.30.3 → 3.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/README.md +177 -27
- package/dist/codemirror.d.ts +74 -48
- package/dist/codemirror.js +180 -229
- package/dist/color.d.ts +1 -6
- package/dist/color.js +1 -8
- package/dist/config.js +5 -6
- package/dist/escape.js +2 -2
- package/dist/fold.d.ts +53 -6
- package/dist/fold.js +140 -136
- package/dist/hover.js +1 -1
- package/dist/indent.d.ts +5 -1
- package/dist/indent.js +2 -1
- package/dist/inlay.js +1 -1
- package/dist/javascript.d.ts +1 -0
- package/dist/javascript.js +2 -4
- package/dist/keybindings.js +1 -0
- package/dist/linter.d.ts +1 -1
- package/dist/linter.js +47 -11
- package/dist/lintsource.d.ts +14 -0
- package/dist/lintsource.js +159 -0
- package/dist/lsp.d.ts +3 -0
- package/dist/lsp.js +34 -0
- package/dist/main.min.js +25 -24
- package/dist/matchBrackets.d.ts +1 -1
- package/dist/matchTag.js +2 -2
- package/dist/mediawiki.js +3 -2
- package/dist/mw.min.js +30 -29
- package/dist/mwConfig.js +2 -5
- package/dist/ref.js +1 -1
- package/dist/signature.js +1 -1
- package/dist/statusBar.d.ts +1 -1
- package/dist/token.d.ts +14 -12
- package/dist/token.js +83 -62
- package/dist/vue.d.ts +3 -0
- package/dist/vue.js +14 -0
- package/dist/wiki.min.js +29 -28
- package/i18n/en.json +2 -3
- package/i18n/zh-hans.json +2 -3
- package/i18n/zh-hant.json +2 -3
- package/package.json +21 -12
package/dist/codemirror.js
CHANGED
|
@@ -6,17 +6,20 @@ import { searchKeymap, highlightSelectionMatches } from '@codemirror/search';
|
|
|
6
6
|
import { linter, lintGutter, lintKeymap } from '@codemirror/lint';
|
|
7
7
|
import { closeBrackets, autocompletion, acceptCompletion, completionKeymap, startCompletion, } from '@codemirror/autocomplete';
|
|
8
8
|
import { json } from '@codemirror/lang-json';
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
9
|
+
import { autoCloseTags } from '@codemirror/lang-html';
|
|
10
|
+
import { css as cssParser } from '@codemirror/legacy-modes/mode/css';
|
|
11
|
+
import { getLSP } from '@bhsd/browser';
|
|
12
|
+
import { colorPicker as cssColorPicker, colorPickerTheme, makeColorPicker } from '@bhsd/codemirror-css-color-picker';
|
|
13
|
+
import colorPicker, { discoverColors } from './color';
|
|
14
|
+
import { mediawiki, html, FullMediaWiki } from './mediawiki';
|
|
12
15
|
import escapeKeymap from './escape';
|
|
13
|
-
import codeFolding, { foldHandler } from './fold';
|
|
16
|
+
import codeFolding, { foldHandler, mediaWikiFold } from './fold';
|
|
14
17
|
import tagMatchingState from './matchTag';
|
|
15
18
|
import refHover from './ref';
|
|
16
|
-
import magicWordHover
|
|
19
|
+
import magicWordHover from './hover';
|
|
17
20
|
import signatureHelp from './signature';
|
|
18
21
|
import inlayHints from './inlay';
|
|
19
|
-
import {
|
|
22
|
+
import { getWikiLintSource, getJsLintSource, getCssLintSource, getJsonLintSource, getLuaLintSource, getVueLintSource, } from './lintsource';
|
|
20
23
|
import openLinks from './openLinks';
|
|
21
24
|
import { tagModes, getStaticMwConfig } from './static';
|
|
22
25
|
import bidiIsolation from './bidi';
|
|
@@ -24,27 +27,14 @@ import toolKeymap from './keymap';
|
|
|
24
27
|
import statusBar from './statusBar';
|
|
25
28
|
import { detectIndent } from './indent';
|
|
26
29
|
import bracketMatching from './matchBrackets';
|
|
30
|
+
import wikitextLSP from './lsp';
|
|
27
31
|
import javascript from './javascript';
|
|
28
32
|
import css from './css';
|
|
29
33
|
import lua from './lua';
|
|
34
|
+
import vue from './vue';
|
|
30
35
|
const plain = () => EditorView.contentAttributes.of({ spellcheck: 'true' });
|
|
31
36
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
-
const languages = {
|
|
33
|
-
plain,
|
|
34
|
-
mediawiki(config) {
|
|
35
|
-
return [
|
|
36
|
-
mediawiki(config),
|
|
37
|
-
plain(),
|
|
38
|
-
bidiIsolation,
|
|
39
|
-
toolKeymap,
|
|
40
|
-
];
|
|
41
|
-
},
|
|
42
|
-
html,
|
|
43
|
-
javascript,
|
|
44
|
-
css,
|
|
45
|
-
json,
|
|
46
|
-
lua,
|
|
47
|
-
};
|
|
37
|
+
const languages = { plain };
|
|
48
38
|
function mediawikiOnly(ext) {
|
|
49
39
|
return typeof ext === 'function'
|
|
50
40
|
? [(enable, cm) => enable ? ext(cm) : [], { mediawiki: true }]
|
|
@@ -52,15 +42,19 @@ function mediawikiOnly(ext) {
|
|
|
52
42
|
}
|
|
53
43
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
54
44
|
const avail = {
|
|
55
|
-
highlightSpecialChars: [highlightSpecialChars
|
|
56
|
-
highlightActiveLine: [highlightActiveLine
|
|
57
|
-
highlightWhitespace: [highlightWhitespace
|
|
58
|
-
highlightTrailingWhitespace: [highlightTrailingWhitespace
|
|
59
|
-
highlightSelectionMatches: [highlightSelectionMatches
|
|
60
|
-
bracketMatching: [
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
45
|
+
highlightSpecialChars: [highlightSpecialChars],
|
|
46
|
+
highlightActiveLine: [highlightActiveLine],
|
|
47
|
+
highlightWhitespace: [highlightWhitespace],
|
|
48
|
+
highlightTrailingWhitespace: [highlightTrailingWhitespace],
|
|
49
|
+
highlightSelectionMatches: [highlightSelectionMatches],
|
|
50
|
+
bracketMatching: [
|
|
51
|
+
([config, e = []] = []) => [
|
|
52
|
+
bracketMatching(config),
|
|
53
|
+
e,
|
|
54
|
+
],
|
|
55
|
+
],
|
|
56
|
+
closeBrackets: [(e = []) => [closeBrackets(), e]],
|
|
57
|
+
scrollPastEnd: [scrollPastEnd],
|
|
64
58
|
allowMultipleSelections: [
|
|
65
59
|
() => [
|
|
66
60
|
EditorState.allowMultipleSelections.of(true),
|
|
@@ -68,7 +62,6 @@ const avail = {
|
|
|
68
62
|
rectangularSelection(),
|
|
69
63
|
crosshairCursor(),
|
|
70
64
|
],
|
|
71
|
-
{},
|
|
72
65
|
],
|
|
73
66
|
autocompletion: [
|
|
74
67
|
() => [
|
|
@@ -79,27 +72,104 @@ const avail = {
|
|
|
79
72
|
{ key: 'Tab', run: acceptCompletion },
|
|
80
73
|
]),
|
|
81
74
|
],
|
|
82
|
-
{},
|
|
83
75
|
],
|
|
84
76
|
codeFolding,
|
|
85
77
|
colorPicker,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
signatureHelp: mediawikiOnly(signatureHelp),
|
|
91
|
-
inlayHints: mediawikiOnly(inlayHints),
|
|
92
|
-
}, editExtensions = new Set(['closeBrackets', 'autocompletion', 'signatureHelp']);
|
|
78
|
+
};
|
|
79
|
+
const linterRegistry = {};
|
|
80
|
+
const destroyListeners = [];
|
|
81
|
+
const editExtensions = new Set(['closeBrackets', 'autocompletion', 'signatureHelp']);
|
|
93
82
|
const linters = {};
|
|
94
83
|
const phrases = {};
|
|
95
84
|
/**
|
|
96
|
-
*
|
|
97
|
-
* @param
|
|
98
|
-
* @param
|
|
99
|
-
* @param
|
|
85
|
+
* 注册特定语言的扩展
|
|
86
|
+
* @param lang 语言
|
|
87
|
+
* @param name 扩展名
|
|
88
|
+
* @param ext 扩展
|
|
100
89
|
*/
|
|
101
|
-
const
|
|
102
|
-
|
|
90
|
+
const registerLangExtension = (lang, name, ext) => {
|
|
91
|
+
const addon = avail[name];
|
|
92
|
+
addon[1] ??= {};
|
|
93
|
+
addon[1][lang] = ext;
|
|
94
|
+
};
|
|
95
|
+
/** Register MediaWiki language support */
|
|
96
|
+
export const registerMediaWiki = () => {
|
|
97
|
+
languages['mediawiki'] = (config) => [
|
|
98
|
+
mediawiki(config),
|
|
99
|
+
plain(),
|
|
100
|
+
bidiIsolation,
|
|
101
|
+
toolKeymap,
|
|
102
|
+
];
|
|
103
|
+
registerLangExtension('mediawiki', 'colorPicker', [
|
|
104
|
+
[makeColorPicker({ discoverColors }), colorPickerTheme],
|
|
105
|
+
{ marginLeft: '0.6ch' },
|
|
106
|
+
]);
|
|
107
|
+
registerLangExtension('mediawiki', 'bracketMatching', [
|
|
108
|
+
{ brackets: '()[]{}()【】[]{}' },
|
|
109
|
+
tagMatchingState,
|
|
110
|
+
]);
|
|
111
|
+
registerLangExtension('mediawiki', 'codeFolding', mediaWikiFold);
|
|
112
|
+
Object.assign(avail, {
|
|
113
|
+
openLinks: mediawikiOnly(openLinks),
|
|
114
|
+
escape: mediawikiOnly(keymap.of(escapeKeymap)),
|
|
115
|
+
refHover: mediawikiOnly(refHover),
|
|
116
|
+
hover: mediawikiOnly(magicWordHover),
|
|
117
|
+
signatureHelp: mediawikiOnly(signatureHelp),
|
|
118
|
+
inlayHints: mediawikiOnly(inlayHints),
|
|
119
|
+
});
|
|
120
|
+
linterRegistry['mediawiki'] = getWikiLintSource;
|
|
121
|
+
destroyListeners.push(view => getLSP(view)?.destroy());
|
|
122
|
+
};
|
|
123
|
+
/** Register mixed MediaWiki-HTML language support */
|
|
124
|
+
export const registerHTML = () => {
|
|
125
|
+
Object.assign(FullMediaWiki.prototype, {
|
|
126
|
+
css() {
|
|
127
|
+
return cssParser;
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
languages['html'] = html;
|
|
131
|
+
};
|
|
132
|
+
/** Register JavaScript language support */
|
|
133
|
+
export const registerJavaScript = () => {
|
|
134
|
+
languages['javascript'] = javascript;
|
|
135
|
+
linterRegistry['javascript'] = getJsLintSource;
|
|
136
|
+
};
|
|
137
|
+
/** Register CSS language support */
|
|
138
|
+
export const registerCSS = () => {
|
|
139
|
+
languages['css'] = css;
|
|
140
|
+
registerLangExtension('css', 'colorPicker', [cssColorPicker]);
|
|
141
|
+
linterRegistry['css'] = getCssLintSource;
|
|
142
|
+
};
|
|
143
|
+
/** Register JSON language support */
|
|
144
|
+
export const registerJSON = () => {
|
|
145
|
+
languages['json'] = json;
|
|
146
|
+
linterRegistry['json'] = getJsonLintSource;
|
|
147
|
+
};
|
|
148
|
+
/** Register Lua language support */
|
|
149
|
+
export const registerLua = () => {
|
|
150
|
+
languages['lua'] = lua;
|
|
151
|
+
linterRegistry['lua'] = getLuaLintSource;
|
|
152
|
+
};
|
|
153
|
+
/** Register Vue language support */
|
|
154
|
+
export const registerVue = () => {
|
|
155
|
+
languages['vue'] = vue;
|
|
156
|
+
registerLangExtension('vue', 'closeBrackets', autoCloseTags);
|
|
157
|
+
registerLangExtension('vue', 'colorPicker', [cssColorPicker]);
|
|
158
|
+
linterRegistry['vue'] = getVueLintSource;
|
|
159
|
+
};
|
|
160
|
+
/**
|
|
161
|
+
* Register a custom language support
|
|
162
|
+
* @param name language name
|
|
163
|
+
* @param lang language support
|
|
164
|
+
* @param lintSource optional linter
|
|
165
|
+
*/
|
|
166
|
+
export const registerLanguage = (name, lang, lintSource) => {
|
|
167
|
+
languages[name] = lang;
|
|
168
|
+
if (lintSource) {
|
|
169
|
+
linterRegistry[name] = lintSource;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
/** CodeMirror 6 editor */
|
|
103
173
|
export class CodeMirror6 {
|
|
104
174
|
#textarea;
|
|
105
175
|
#language = new Compartment();
|
|
@@ -115,23 +185,27 @@ export class CodeMirror6 {
|
|
|
115
185
|
#visible = false;
|
|
116
186
|
#preferred = new Set();
|
|
117
187
|
#indentStr = '\t';
|
|
188
|
+
/** textarea element */
|
|
118
189
|
get textarea() {
|
|
119
190
|
return this.#textarea;
|
|
120
191
|
}
|
|
192
|
+
/** EditorView instance */
|
|
121
193
|
get view() {
|
|
122
194
|
return this.#view;
|
|
123
195
|
}
|
|
196
|
+
/** language */
|
|
124
197
|
get lang() {
|
|
125
198
|
return this.#lang;
|
|
126
199
|
}
|
|
200
|
+
/** whether the editor view is visible */
|
|
127
201
|
get visible() {
|
|
128
202
|
return this.#visible && this.textarea.isConnected;
|
|
129
203
|
}
|
|
130
204
|
/**
|
|
131
|
-
* @param textarea
|
|
132
|
-
* @param lang
|
|
133
|
-
* @param config
|
|
134
|
-
* @param init
|
|
205
|
+
* @param textarea textarea element
|
|
206
|
+
* @param lang language
|
|
207
|
+
* @param config language configuration
|
|
208
|
+
* @param init whether to initialize the editor immediately
|
|
135
209
|
*/
|
|
136
210
|
constructor(textarea, lang = 'plain', config, init = true) {
|
|
137
211
|
this.#textarea = textarea;
|
|
@@ -141,8 +215,8 @@ export class CodeMirror6 {
|
|
|
141
215
|
}
|
|
142
216
|
}
|
|
143
217
|
/**
|
|
144
|
-
*
|
|
145
|
-
* @param config
|
|
218
|
+
* Initialize the editor
|
|
219
|
+
* @param config language configuration
|
|
146
220
|
*/
|
|
147
221
|
initialize(config) {
|
|
148
222
|
let timer;
|
|
@@ -245,15 +319,21 @@ export class CodeMirror6 {
|
|
|
245
319
|
return this.#linter.get(this.#view.state)[0];
|
|
246
320
|
}
|
|
247
321
|
/**
|
|
248
|
-
*
|
|
249
|
-
* @param lang
|
|
250
|
-
* @param config
|
|
322
|
+
* Set language
|
|
323
|
+
* @param lang language
|
|
324
|
+
* @param config language configuration
|
|
251
325
|
*/
|
|
252
|
-
setLanguage(lang = 'plain', config) {
|
|
326
|
+
async setLanguage(lang = 'plain', config) {
|
|
253
327
|
this.#lang = lang;
|
|
254
328
|
if (this.#view) {
|
|
329
|
+
let ext = (languages[lang] ?? plain)(config);
|
|
330
|
+
ws: { // eslint-disable-line no-unused-labels
|
|
331
|
+
if (lang === 'mediawiki') {
|
|
332
|
+
ext = [ext, await wikitextLSP()];
|
|
333
|
+
}
|
|
334
|
+
}
|
|
255
335
|
this.#effects([
|
|
256
|
-
this.#language.reconfigure(
|
|
336
|
+
this.#language.reconfigure(ext),
|
|
257
337
|
this.#linter.reconfigure(linters[lang] ?? []),
|
|
258
338
|
]);
|
|
259
339
|
this.#minHeight(Boolean(linters[lang]));
|
|
@@ -261,15 +341,15 @@ export class CodeMirror6 {
|
|
|
261
341
|
}
|
|
262
342
|
}
|
|
263
343
|
/**
|
|
264
|
-
*
|
|
265
|
-
* @param lintSource
|
|
344
|
+
* Start syntax checking
|
|
345
|
+
* @param lintSource function for syntax checking
|
|
266
346
|
*/
|
|
267
347
|
lint(lintSource) {
|
|
268
348
|
const linterExtension = lintSource
|
|
269
349
|
? [
|
|
270
|
-
linter(async ({ state
|
|
271
|
-
const diagnostics = await lintSource(
|
|
272
|
-
if (readOnly) {
|
|
350
|
+
linter(async ({ state }) => {
|
|
351
|
+
const diagnostics = await lintSource(state);
|
|
352
|
+
if (state.readOnly) {
|
|
273
353
|
for (const diagnostic of diagnostics) {
|
|
274
354
|
delete diagnostic.actions;
|
|
275
355
|
}
|
|
@@ -292,7 +372,7 @@ export class CodeMirror6 {
|
|
|
292
372
|
this.#minHeight(Boolean(lintSource));
|
|
293
373
|
}
|
|
294
374
|
}
|
|
295
|
-
/**
|
|
375
|
+
/** Update syntax checking immediately */
|
|
296
376
|
update() {
|
|
297
377
|
if (this.#view) {
|
|
298
378
|
const extension = this.#getLintExtension();
|
|
@@ -304,16 +384,16 @@ export class CodeMirror6 {
|
|
|
304
384
|
}
|
|
305
385
|
}
|
|
306
386
|
/**
|
|
307
|
-
*
|
|
308
|
-
* @param names
|
|
387
|
+
* Add extensions
|
|
388
|
+
* @param names extension names
|
|
309
389
|
*/
|
|
310
390
|
prefer(names) {
|
|
311
391
|
if (Array.isArray(names)) {
|
|
312
|
-
this.#preferred = new Set(names.filter(name => avail
|
|
392
|
+
this.#preferred = new Set(names.filter(name => Object.prototype.hasOwnProperty.call(avail, name)));
|
|
313
393
|
}
|
|
314
394
|
else {
|
|
315
395
|
for (const [name, enable] of Object.entries(names)) {
|
|
316
|
-
if (enable && avail
|
|
396
|
+
if (enable && Object.prototype.hasOwnProperty.call(avail, name)) {
|
|
317
397
|
this.#preferred.add(name);
|
|
318
398
|
}
|
|
319
399
|
else {
|
|
@@ -324,14 +404,14 @@ export class CodeMirror6 {
|
|
|
324
404
|
if (this.#view) {
|
|
325
405
|
const { readOnly } = this.#view.state;
|
|
326
406
|
this.#effects(this.#extensions.reconfigure([...this.#preferred].filter(name => !readOnly || !editExtensions.has(name)).map(name => {
|
|
327
|
-
const [extension, configs] = avail[name];
|
|
407
|
+
const [extension, configs = {}] = avail[name];
|
|
328
408
|
return extension(configs[this.#lang], this);
|
|
329
409
|
})));
|
|
330
410
|
}
|
|
331
411
|
}
|
|
332
412
|
/**
|
|
333
|
-
*
|
|
334
|
-
* @param indent
|
|
413
|
+
* Set text indentation
|
|
414
|
+
* @param indent indentation string
|
|
335
415
|
*/
|
|
336
416
|
setIndent(indent) {
|
|
337
417
|
if (this.#view) {
|
|
@@ -342,8 +422,8 @@ export class CodeMirror6 {
|
|
|
342
422
|
}
|
|
343
423
|
}
|
|
344
424
|
/**
|
|
345
|
-
*
|
|
346
|
-
* @param wrapping
|
|
425
|
+
* Set line wrapping
|
|
426
|
+
* @param wrapping whether to enable line wrapping
|
|
347
427
|
*/
|
|
348
428
|
setLineWrapping(wrapping) {
|
|
349
429
|
if (this.#view) {
|
|
@@ -351,160 +431,28 @@ export class CodeMirror6 {
|
|
|
351
431
|
}
|
|
352
432
|
}
|
|
353
433
|
/**
|
|
354
|
-
*
|
|
355
|
-
* @param opt
|
|
434
|
+
* Get default linter
|
|
435
|
+
* @param opt linter options
|
|
356
436
|
*/
|
|
357
437
|
async getLinter(opt) {
|
|
358
|
-
|
|
359
|
-
switch (this.#lang) {
|
|
360
|
-
case 'mediawiki': {
|
|
361
|
-
const wikiLint = await getWikiLinter(getOpt(), this.#view);
|
|
362
|
-
return async (doc) => (await wikiLint(doc.toString(), getOpt(true)))
|
|
363
|
-
.map(({ severity, code, message, range: r, from, to, data = [], source }) => ({
|
|
364
|
-
source: source,
|
|
365
|
-
from: from ?? posToIndex(doc, r.start),
|
|
366
|
-
to: to ?? posToIndex(doc, r.end),
|
|
367
|
-
severity: severity === 2 ? 'warning' : 'error',
|
|
368
|
-
message: source === 'Stylelint' ? message : `${message} (${code})`,
|
|
369
|
-
actions: data.map(({ title, range, newText }) => ({
|
|
370
|
-
name: title,
|
|
371
|
-
apply(view) {
|
|
372
|
-
view.dispatch({
|
|
373
|
-
changes: {
|
|
374
|
-
from: posToIndex(doc, range.start),
|
|
375
|
-
to: posToIndex(doc, range.end),
|
|
376
|
-
insert: newText,
|
|
377
|
-
},
|
|
378
|
-
});
|
|
379
|
-
},
|
|
380
|
-
})),
|
|
381
|
-
}));
|
|
382
|
-
}
|
|
383
|
-
case 'javascript': {
|
|
384
|
-
const esLint = await getJsLinter();
|
|
385
|
-
const lintSource = doc => esLint(doc.toString(), getOpt())
|
|
386
|
-
.map(({ ruleId, message, severity, line, column, endLine, endColumn, fix, suggestions = [] }) => {
|
|
387
|
-
const start = pos(doc, line, column), diagnostic = {
|
|
388
|
-
source: 'ESLint',
|
|
389
|
-
message: message + (ruleId ? ` (${ruleId})` : ''),
|
|
390
|
-
severity: severity === 1 ? 'warning' : 'error',
|
|
391
|
-
from: start,
|
|
392
|
-
to: endLine === undefined ? start + 1 : pos(doc, endLine, endColumn),
|
|
393
|
-
};
|
|
394
|
-
if (fix || suggestions.length > 0) {
|
|
395
|
-
diagnostic.actions = [
|
|
396
|
-
...fix ? [{ name: 'fix', fix }] : [],
|
|
397
|
-
...suggestions.map(suggestion => ({ name: 'suggestion', fix: suggestion.fix })),
|
|
398
|
-
].map(({ name, fix: { range: [from, to], text } }) => ({
|
|
399
|
-
name,
|
|
400
|
-
apply(view) {
|
|
401
|
-
view.dispatch({ changes: { from, to, insert: text } });
|
|
402
|
-
},
|
|
403
|
-
}));
|
|
404
|
-
}
|
|
405
|
-
return diagnostic;
|
|
406
|
-
});
|
|
407
|
-
lintSource.fixer = (doc, rule) => esLint.fixer(doc.toString(), rule);
|
|
408
|
-
return lintSource;
|
|
409
|
-
}
|
|
410
|
-
case 'css': {
|
|
411
|
-
const styleLint = await getCssLinter();
|
|
412
|
-
let option = getOpt() ?? {};
|
|
413
|
-
if (!('extends' in option || 'rules' in option)) {
|
|
414
|
-
option = { rules: option };
|
|
415
|
-
}
|
|
416
|
-
if (this.dialect === 'sanitized-css') {
|
|
417
|
-
const rules = option['rules'];
|
|
418
|
-
option = {
|
|
419
|
-
...option,
|
|
420
|
-
rules: {
|
|
421
|
-
...rules,
|
|
422
|
-
'property-no-vendor-prefix': [
|
|
423
|
-
true,
|
|
424
|
-
{
|
|
425
|
-
ignoreProperties: ['user-select'],
|
|
426
|
-
},
|
|
427
|
-
],
|
|
428
|
-
'property-disallowed-list': [
|
|
429
|
-
...rules?.['property-disallowed-list'] ?? [],
|
|
430
|
-
'/^--/',
|
|
431
|
-
],
|
|
432
|
-
},
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
const lintSource = async (doc) => (await styleLint(doc.toString(), option))
|
|
436
|
-
.map(({ text, severity, line, column, endLine, endColumn, fix }) => {
|
|
437
|
-
const diagnostic = {
|
|
438
|
-
source: 'Stylelint',
|
|
439
|
-
message: text,
|
|
440
|
-
severity,
|
|
441
|
-
from: pos(doc, line, column),
|
|
442
|
-
to: endLine === undefined ? doc.line(line).to : pos(doc, endLine, endColumn),
|
|
443
|
-
};
|
|
444
|
-
if (fix) {
|
|
445
|
-
diagnostic.actions = [
|
|
446
|
-
{
|
|
447
|
-
name: 'fix',
|
|
448
|
-
apply(view) {
|
|
449
|
-
view.dispatch({
|
|
450
|
-
changes: { from: fix.range[0], to: fix.range[1], insert: fix.text },
|
|
451
|
-
});
|
|
452
|
-
},
|
|
453
|
-
},
|
|
454
|
-
];
|
|
455
|
-
}
|
|
456
|
-
return diagnostic;
|
|
457
|
-
});
|
|
458
|
-
lintSource.fixer = async (doc, rule) => styleLint.fixer(doc.toString(), rule);
|
|
459
|
-
return lintSource;
|
|
460
|
-
}
|
|
461
|
-
case 'lua': {
|
|
462
|
-
const luaLint = await getLuaLinter();
|
|
463
|
-
return async (doc) => (await luaLint(doc.toString()))
|
|
464
|
-
.map(({ line, column, end_column: endColumn, msg: message, severity }) => ({
|
|
465
|
-
source: 'Luacheck',
|
|
466
|
-
message,
|
|
467
|
-
severity: severity === 1 ? 'warning' : 'error',
|
|
468
|
-
from: pos(doc, line, column),
|
|
469
|
-
to: pos(doc, line, endColumn + 1),
|
|
470
|
-
}));
|
|
471
|
-
}
|
|
472
|
-
case 'json': {
|
|
473
|
-
const jsonLint = getJsonLinter();
|
|
474
|
-
return doc => {
|
|
475
|
-
const [e] = jsonLint(doc.toString());
|
|
476
|
-
if (e) {
|
|
477
|
-
const { message, severity, line, column, position } = e;
|
|
478
|
-
let from = 0;
|
|
479
|
-
if (position) {
|
|
480
|
-
from = Number(position);
|
|
481
|
-
}
|
|
482
|
-
else if (line && column) {
|
|
483
|
-
from = pos(doc, Number(line), Number(column));
|
|
484
|
-
}
|
|
485
|
-
return [{ message, severity, from, to: from }];
|
|
486
|
-
}
|
|
487
|
-
return [];
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
default:
|
|
491
|
-
return undefined;
|
|
492
|
-
}
|
|
438
|
+
return linterRegistry[this.#lang]?.(opt, this.#view);
|
|
493
439
|
}
|
|
494
440
|
/**
|
|
495
|
-
*
|
|
496
|
-
* @param insert
|
|
441
|
+
* Set content
|
|
442
|
+
* @param insert new content
|
|
443
|
+
* @param force whether to forcefully replace the content
|
|
497
444
|
*/
|
|
498
|
-
setContent(insert) {
|
|
445
|
+
setContent(insert, force) {
|
|
499
446
|
if (this.#view) {
|
|
500
447
|
this.#view.dispatch({
|
|
501
448
|
changes: { from: 0, to: this.#view.state.doc.length, insert },
|
|
449
|
+
filter: !force,
|
|
502
450
|
});
|
|
503
451
|
}
|
|
504
452
|
}
|
|
505
453
|
/**
|
|
506
|
-
*
|
|
507
|
-
* @param show
|
|
454
|
+
* Switch between textarea and editor view
|
|
455
|
+
* @param show whether to show the editor view
|
|
508
456
|
*/
|
|
509
457
|
toggle(show = !this.#visible) {
|
|
510
458
|
if (!this.#view) {
|
|
@@ -541,20 +489,22 @@ export class CodeMirror6 {
|
|
|
541
489
|
}
|
|
542
490
|
this.#visible = show;
|
|
543
491
|
}
|
|
544
|
-
/**
|
|
492
|
+
/** Destroy the editor */
|
|
545
493
|
destroy() {
|
|
546
494
|
if (this.visible) {
|
|
547
495
|
this.toggle(false);
|
|
548
496
|
}
|
|
549
497
|
if (this.#view) {
|
|
550
|
-
|
|
498
|
+
for (const listener of destroyListeners) {
|
|
499
|
+
listener(this.#view);
|
|
500
|
+
}
|
|
551
501
|
this.#view.destroy();
|
|
552
502
|
}
|
|
553
503
|
Object.setPrototypeOf(this, null);
|
|
554
504
|
}
|
|
555
505
|
/**
|
|
556
|
-
*
|
|
557
|
-
* @param keys
|
|
506
|
+
* Define extra key bindings
|
|
507
|
+
* @param keys key bindings
|
|
558
508
|
*/
|
|
559
509
|
extraKeys(keys) {
|
|
560
510
|
if (this.#view) {
|
|
@@ -562,8 +512,8 @@ export class CodeMirror6 {
|
|
|
562
512
|
}
|
|
563
513
|
}
|
|
564
514
|
/**
|
|
565
|
-
*
|
|
566
|
-
* @param messages
|
|
515
|
+
* Set translation messages
|
|
516
|
+
* @param messages translation messages
|
|
567
517
|
*/
|
|
568
518
|
localize(messages) {
|
|
569
519
|
Object.assign(phrases, messages);
|
|
@@ -572,15 +522,15 @@ export class CodeMirror6 {
|
|
|
572
522
|
}
|
|
573
523
|
}
|
|
574
524
|
/**
|
|
575
|
-
*
|
|
576
|
-
* @param position
|
|
525
|
+
* Get the syntax node at the specified position
|
|
526
|
+
* @param position position
|
|
577
527
|
*/
|
|
578
528
|
getNodeAt(position) {
|
|
579
529
|
return this.#view && ensureSyntaxTree(this.#view.state, position)?.resolve(position, 1);
|
|
580
530
|
}
|
|
581
531
|
/**
|
|
582
|
-
*
|
|
583
|
-
* @param position
|
|
532
|
+
* Scroll to the specified position
|
|
533
|
+
* @param position position or selection range
|
|
584
534
|
*/
|
|
585
535
|
scrollTo(position) {
|
|
586
536
|
if (this.#view) {
|
|
@@ -592,9 +542,9 @@ export class CodeMirror6 {
|
|
|
592
542
|
}
|
|
593
543
|
}
|
|
594
544
|
/**
|
|
595
|
-
*
|
|
596
|
-
* @param view
|
|
597
|
-
* @param func
|
|
545
|
+
* Replace the current selection with the result of a function
|
|
546
|
+
* @param view EditorView instance
|
|
547
|
+
* @param func function to produce the replacement text
|
|
598
548
|
*/
|
|
599
549
|
static replaceSelections(view, func) {
|
|
600
550
|
const { state } = view;
|
|
@@ -614,8 +564,9 @@ export class CodeMirror6 {
|
|
|
614
564
|
}));
|
|
615
565
|
}
|
|
616
566
|
/**
|
|
617
|
-
*
|
|
618
|
-
*
|
|
567
|
+
* Convert a [WikiParser-Node](https://npmjs.com/package/wikiparser-node) configuration
|
|
568
|
+
* to a CodeMirror-MediaWiki configuration
|
|
569
|
+
* @param config WikiParser-Node configuration
|
|
619
570
|
*/
|
|
620
571
|
static getMwConfig(config) {
|
|
621
572
|
return getStaticMwConfig(config, tagModes);
|
package/dist/color.d.ts
CHANGED
|
@@ -3,10 +3,5 @@ import type { Tree } from '@lezer/common';
|
|
|
3
3
|
import type { StyleSpec } from 'style-mod';
|
|
4
4
|
import type { WidgetOptions } from '@bhsd/codemirror-css-color-picker';
|
|
5
5
|
export declare const discoverColors: (_: Tree, from: number, to: number, type: string, doc: Text) => WidgetOptions[] | null;
|
|
6
|
-
declare const _default: [([e, style]?: [Extension?, StyleSpec?]) => Extension
|
|
7
|
-
css: [Extension];
|
|
8
|
-
mediawiki: [Extension[], {
|
|
9
|
-
marginLeft: string;
|
|
10
|
-
}];
|
|
11
|
-
}];
|
|
6
|
+
declare const _default: [([e, style]?: [Extension?, StyleSpec?]) => Extension];
|
|
12
7
|
export default _default;
|
package/dist/color.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { splitColors, numToHex } from '@bhsd/common';
|
|
2
2
|
import { EditorView } from '@codemirror/view';
|
|
3
|
-
import { parseCallExpression, parseColorLiteral, ColorType,
|
|
3
|
+
import { parseCallExpression, parseColorLiteral, ColorType, wrapperClassName } from '@bhsd/codemirror-css-color-picker';
|
|
4
4
|
export const discoverColors = (_, from, to, type, doc) => {
|
|
5
5
|
if (!/mw-(?:(?:ext|html)tag-attribute-value|table-definition)/u.test(type)
|
|
6
6
|
&& (!/mw-(?:template|parserfunction)(?:$|_)/u.test(type)
|
|
@@ -42,11 +42,4 @@ export default [
|
|
|
42
42
|
}),
|
|
43
43
|
]
|
|
44
44
|
: [],
|
|
45
|
-
{
|
|
46
|
-
css: [colorPicker],
|
|
47
|
-
mediawiki: [
|
|
48
|
-
[makeColorPicker({ discoverColors }), colorPickerTheme],
|
|
49
|
-
{ marginLeft: '0.6ch' },
|
|
50
|
-
],
|
|
51
|
-
},
|
|
52
45
|
];
|
package/dist/config.js
CHANGED
|
@@ -68,8 +68,7 @@ var html = [
|
|
|
68
68
|
"wbr",
|
|
69
69
|
"hr",
|
|
70
70
|
"meta",
|
|
71
|
-
"link"
|
|
72
|
-
"img"
|
|
71
|
+
"link"
|
|
73
72
|
]
|
|
74
73
|
];
|
|
75
74
|
|
|
@@ -80,9 +79,9 @@ var html = [
|
|
|
80
79
|
* @license GPL-2.0-or-later
|
|
81
80
|
* @see https://gerrit.wikimedia.org/g/mediawiki/extensions/CodeMirror
|
|
82
81
|
*/
|
|
83
|
-
var htmlTags = html.flat();
|
|
84
|
-
var voidHtmlTags = html[2];
|
|
85
|
-
var selfClosingTags = html[1];
|
|
82
|
+
var htmlTags = /* @__PURE__ */ html.flat();
|
|
83
|
+
var voidHtmlTags = /* @__PURE__ */ (() => html[2])();
|
|
84
|
+
var selfClosingTags = /* @__PURE__ */ (() => html[1])();
|
|
86
85
|
var tokens = {
|
|
87
86
|
apostrophes: "mw-apostrophes",
|
|
88
87
|
comment: "mw-comment",
|
|
@@ -150,7 +149,7 @@ var tokens = {
|
|
|
150
149
|
templateVariableDelimiter: "mw-templatevariable-delimiter",
|
|
151
150
|
templateVariableName: "mw-templatevariable-name"
|
|
152
151
|
};
|
|
153
|
-
var tokenTable = (() => {
|
|
152
|
+
var tokenTable = /* @__PURE__ */ (() => {
|
|
154
153
|
const table = {
|
|
155
154
|
variable: tags.variableName,
|
|
156
155
|
"variable-2": tags.special(tags.variableName),
|
package/dist/escape.js
CHANGED
|
@@ -29,7 +29,7 @@ export const escapeHTML = (str) => [...str].map(c => {
|
|
|
29
29
|
}
|
|
30
30
|
return encodeURIComponent(str);
|
|
31
31
|
};
|
|
32
|
-
export default [
|
|
32
|
+
export default /* @__PURE__ */ (() => [
|
|
33
33
|
{ key: 'Mod-[', run: convert(escapeHTML, indentLess) },
|
|
34
34
|
{ key: 'Mod-]', run: convert(escapeURI, indentMore) },
|
|
35
|
-
];
|
|
35
|
+
])();
|