@bhsd/codemirror-mediawiki 3.11.4 → 3.12.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 +42 -7
- package/dist/closeTags.d.ts +3 -0
- package/dist/closeTags.js +31 -0
- package/dist/codemirror.d.ts +16 -2
- package/dist/codemirror.js +34 -14
- package/dist/fold.js +4 -4
- package/dist/html.js +2 -2
- package/dist/index.d.ts +22 -3
- package/dist/index.js +55 -28
- package/dist/javascript.d.ts +7 -0
- package/dist/javascript.js +8 -0
- package/dist/lint.d.ts +6 -0
- package/dist/lint.js +28 -0
- package/dist/linter.js +3 -2
- package/dist/lua.js +3 -2
- package/dist/main.min.js +37 -37
- package/dist/matchBrackets.d.ts +11 -1
- package/dist/matchBrackets.js +49 -24
- package/dist/matchTag.d.ts +6 -0
- package/dist/matchTag.js +1 -1
- package/dist/mediawiki.d.ts +1 -1
- package/dist/mediawiki.js +7 -2
- package/dist/mw.min.js +39 -39
- package/dist/statusBar.js +12 -4
- package/dist/theme.d.ts +1 -1
- package/dist/theme.js +1 -1
- package/dist/token.d.ts +2 -2
- package/dist/token.js +25 -16
- package/dist/wiki.min.js +39 -39
- package/i18n/en.json +2 -1
- package/i18n/zh-hans.json +2 -1
- package/i18n/zh-hant.json +2 -1
- package/package.json +15 -15
package/README.md
CHANGED
|
@@ -68,6 +68,7 @@ If you are just looking for a CodeMirror 6 language mode and language support ex
|
|
|
68
68
|
- [bidiIsolates](#bidiisolates)
|
|
69
69
|
- [bracketMatching](#bracketmatching)
|
|
70
70
|
- [closeBrackets](#closebrackets)
|
|
71
|
+
- [closeTags](#closetags)
|
|
71
72
|
- [codeFolding](#codefolding)
|
|
72
73
|
- [colorPicker](#colorpicker)
|
|
73
74
|
- [escape](#escape)
|
|
@@ -259,11 +260,11 @@ In addition to the common [extensions](#extensions), here are some HTML-specific
|
|
|
259
260
|
```js
|
|
260
261
|
import {
|
|
261
262
|
registerBracketMatchingForHTML,
|
|
262
|
-
|
|
263
|
+
registerCloseTagsForHTML,
|
|
263
264
|
registerColorPickerForHTML,
|
|
264
265
|
} from '@bhsd/codemirror-mediawiki';
|
|
265
266
|
registerBracketMatchingForHTML();
|
|
266
|
-
|
|
267
|
+
registerCloseTagsForHTML();
|
|
267
268
|
registerColorPickerForHTML();
|
|
268
269
|
```
|
|
269
270
|
|
|
@@ -408,10 +409,10 @@ In addition to the common [extensions](#extensions), here are some Vue-specific
|
|
|
408
409
|
|
|
409
410
|
```js
|
|
410
411
|
import {
|
|
411
|
-
|
|
412
|
+
registerCloseTagsForVue,
|
|
412
413
|
registerColorPickerForVue,
|
|
413
414
|
} from '@bhsd/codemirror-mediawiki';
|
|
414
|
-
|
|
415
|
+
registerCloseTagsForVue();
|
|
415
416
|
registerColorPickerForVue();
|
|
416
417
|
```
|
|
417
418
|
|
|
@@ -722,6 +723,7 @@ cm.prefer([
|
|
|
722
723
|
'autocompletion',
|
|
723
724
|
'bracketMatching',
|
|
724
725
|
'closeBrackets',
|
|
726
|
+
'closeTags',
|
|
725
727
|
'codeFolding',
|
|
726
728
|
'highlightActiveLine',
|
|
727
729
|
'highlightSelectionMatches',
|
|
@@ -746,6 +748,7 @@ cm.prefer({
|
|
|
746
748
|
autocompletion: false,
|
|
747
749
|
bracketMatching: false,
|
|
748
750
|
closeBrackets: false,
|
|
751
|
+
closeTags: false,
|
|
749
752
|
codeFolding: false,
|
|
750
753
|
highlightActiveLine: false,
|
|
751
754
|
highlightSelectionMatches: false,
|
|
@@ -1070,6 +1073,30 @@ registerCloseBrackets();
|
|
|
1070
1073
|
|
|
1071
1074
|
</details>
|
|
1072
1075
|
|
|
1076
|
+
### closeTags
|
|
1077
|
+
|
|
1078
|
+
<details>
|
|
1079
|
+
<summary>Expand</summary>
|
|
1080
|
+
|
|
1081
|
+
*version added: 3.12.0*
|
|
1082
|
+
|
|
1083
|
+
Automatically close HTML/XML tags.
|
|
1084
|
+
|
|
1085
|
+
For granular control over the bundled extensions, you need to register this extension for specific languages([HTML](#html), [MediaWiki](#mediawiki) or [Vue](#vue)):
|
|
1086
|
+
|
|
1087
|
+
```js
|
|
1088
|
+
import {
|
|
1089
|
+
registerCloseTagsForHTML,
|
|
1090
|
+
registerCloseTagsForMediaWiki,
|
|
1091
|
+
registerCloseTagsForVue,
|
|
1092
|
+
} from '@bhsd/codemirror-mediawiki';
|
|
1093
|
+
registerCloseTagsForHTML();
|
|
1094
|
+
registerCloseTagsForMediaWiki();
|
|
1095
|
+
registerCloseTagsForVue();
|
|
1096
|
+
```
|
|
1097
|
+
|
|
1098
|
+
</details>
|
|
1099
|
+
|
|
1073
1100
|
### codeFolding
|
|
1074
1101
|
|
|
1075
1102
|
<details>
|
|
@@ -1105,11 +1132,19 @@ registerCodeFolding();
|
|
|
1105
1132
|
|
|
1106
1133
|
Provide color pickers for CSS and MediaWiki modes.
|
|
1107
1134
|
|
|
1108
|
-
For granular control over the bundled extensions, you
|
|
1135
|
+
For granular control over the bundled extensions, you need to register this extension for specific languages([CSS](#css), [HTML](#html), [MediaWiki](#mediawiki) or [Vue](#vue)):
|
|
1109
1136
|
|
|
1110
1137
|
```js
|
|
1111
|
-
import {
|
|
1112
|
-
|
|
1138
|
+
import {
|
|
1139
|
+
registerColorPickerForCSS,
|
|
1140
|
+
registerColorPickerForHTML,
|
|
1141
|
+
registerColorPickerForMediaWiki,
|
|
1142
|
+
registerColorPickerForVue,
|
|
1143
|
+
} from '@bhsd/codemirror-mediawiki';
|
|
1144
|
+
registerColorPickerForCSS();
|
|
1145
|
+
registerColorPickerForHTML();
|
|
1146
|
+
registerColorPickerForMediaWiki();
|
|
1147
|
+
registerColorPickerForVue();
|
|
1113
1148
|
```
|
|
1114
1149
|
|
|
1115
1150
|
</details>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { EditorView } from '@codemirror/view';
|
|
2
|
+
import { syntaxTree } from '@codemirror/language';
|
|
3
|
+
import { getTag, searchTag } from './matchTag.js';
|
|
4
|
+
import { hasTag } from './mediawiki.js';
|
|
5
|
+
const brackets = ['extTagBracket', 'htmlTagBracket'];
|
|
6
|
+
export default () => EditorView.inputHandler.of((view, from, to, text, insertTransaction) => {
|
|
7
|
+
if (view.composing || view.state.readOnly || from !== to || text !== '>') {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
const base = insertTransaction(), { state } = base, tree = syntaxTree(state), closeTags = state.changeByRange(range => {
|
|
11
|
+
const didType = state.sliceDoc(range.from - 1, range.to) === text, { head } = range, after = tree.resolveInner(head, -1);
|
|
12
|
+
if (didType && hasTag(after.name, brackets) && head === after.from + 1) {
|
|
13
|
+
const tag = getTag(state, after.prevSibling);
|
|
14
|
+
if (tag && !tag.closing && !tag.selfClosing && !searchTag(state, tag)) {
|
|
15
|
+
return {
|
|
16
|
+
range,
|
|
17
|
+
changes: { from: head, to: head, insert: `</${tag.name}>` },
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return { range };
|
|
22
|
+
});
|
|
23
|
+
if (closeTags.changes.empty) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
view.dispatch([
|
|
27
|
+
base,
|
|
28
|
+
state.update(closeTags, { userEvent: 'input.complete', scrollIntoView: true }),
|
|
29
|
+
]);
|
|
30
|
+
return true;
|
|
31
|
+
});
|
package/dist/codemirror.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EditorView } from '@codemirror/view';
|
|
2
|
-
import type { KeyBinding } from '@codemirror/view';
|
|
3
|
-
import type { Extension } from '@codemirror/state';
|
|
2
|
+
import type { ViewPlugin, KeyBinding, DecorationSet } from '@codemirror/view';
|
|
3
|
+
import type { Extension, StateField } from '@codemirror/state';
|
|
4
4
|
import type { SyntaxNode } from '@lezer/common';
|
|
5
5
|
import type { ConfigGetter } from '@bhsd/browser';
|
|
6
6
|
import type { ConfigData } from 'wikiparser-node';
|
|
@@ -20,6 +20,18 @@ declare interface MenuItem {
|
|
|
20
20
|
isActionable(this: void, cm: CodeMirror6): boolean;
|
|
21
21
|
getItems(this: void, cm: CodeMirror6): HTMLElement[];
|
|
22
22
|
}
|
|
23
|
+
declare type LintExtension = [
|
|
24
|
+
unknown,
|
|
25
|
+
ViewPlugin<{
|
|
26
|
+
set: boolean;
|
|
27
|
+
force(): void;
|
|
28
|
+
}>,
|
|
29
|
+
[
|
|
30
|
+
StateField<{
|
|
31
|
+
diagnostics: DecorationSet;
|
|
32
|
+
}>
|
|
33
|
+
]
|
|
34
|
+
];
|
|
23
35
|
declare interface OptionalFunctions {
|
|
24
36
|
statusBar: typeof statusBar;
|
|
25
37
|
detectIndent: typeof detectIndent;
|
|
@@ -82,6 +94,8 @@ export declare class CodeMirror6 {
|
|
|
82
94
|
* @param lintSource function for syntax checking
|
|
83
95
|
*/
|
|
84
96
|
lint(lintSource?: LintSources): void;
|
|
97
|
+
/** @private */
|
|
98
|
+
getLintExtension(): LintExtension | undefined;
|
|
85
99
|
/** Update syntax checking immediately */
|
|
86
100
|
update(): void;
|
|
87
101
|
/**
|
package/dist/codemirror.js
CHANGED
|
@@ -2,11 +2,12 @@ import { EditorView, lineNumbers, keymap, highlightActiveLineGutter } from '@cod
|
|
|
2
2
|
import { EditorSelection, Compartment, EditorState, SelectionRange, } from '@codemirror/state';
|
|
3
3
|
import { syntaxHighlighting, defaultHighlightStyle, indentOnInput, indentUnit, ensureSyntaxTree, syntaxTree, } from '@codemirror/language';
|
|
4
4
|
import { defaultKeymap, historyKeymap, history, redo, indentWithTab, insertNewlineKeepIndent, deleteCharBackwardStrict, } from '@codemirror/commands';
|
|
5
|
-
import { searchKeymap } from '@codemirror/search';
|
|
6
|
-
import { linter, lintGutter
|
|
5
|
+
import { search, searchKeymap } from '@codemirror/search';
|
|
6
|
+
import { linter, lintGutter } from '@codemirror/lint';
|
|
7
7
|
import elt from 'crelt';
|
|
8
8
|
import { base, panelSelector, panelsSelector, diagnosticSelector, noDetectionLangs } from './constants.js';
|
|
9
9
|
import { light } from './theme.js';
|
|
10
|
+
import { nextDiagnostic } from './lint.js';
|
|
10
11
|
export const plain = () => [
|
|
11
12
|
EditorView.contentAttributes.of({ spellcheck: 'true' }),
|
|
12
13
|
keymap.of([
|
|
@@ -32,7 +33,7 @@ export const optionalFunctions = {
|
|
|
32
33
|
return () => { };
|
|
33
34
|
},
|
|
34
35
|
};
|
|
35
|
-
const editExtensions = new Set(['closeBrackets', 'autocompletion', 'signatureHelp', 'escape']);
|
|
36
|
+
const editExtensions = new Set(['closeBrackets', 'closeTags', 'autocompletion', 'signatureHelp', 'escape']);
|
|
36
37
|
const linters = {};
|
|
37
38
|
const phrases = {};
|
|
38
39
|
/**
|
|
@@ -155,6 +156,23 @@ export class CodeMirror6 {
|
|
|
155
156
|
EditorView.editorAttributes.of({ lang: l }),
|
|
156
157
|
lineNumbers(),
|
|
157
158
|
highlightActiveLineGutter(),
|
|
159
|
+
search({
|
|
160
|
+
scrollToMatch(range, view) {
|
|
161
|
+
const scrollRect = view.scrollDOM.getBoundingClientRect(), startCoords = view.coordsAtPos(range.from), endCoords = view.coordsAtPos(range.to), isInViewport = startCoords && startCoords.top >= scrollRect.top
|
|
162
|
+
&& endCoords && endCoords.bottom <= scrollRect.bottom;
|
|
163
|
+
return EditorView.scrollIntoView(range, { y: isInViewport ? 'nearest' : 'center' });
|
|
164
|
+
},
|
|
165
|
+
}),
|
|
166
|
+
EditorView.scrollHandler.of((view, { head }, options) => {
|
|
167
|
+
if (options.x === 'nearest' && options.y === 'center') {
|
|
168
|
+
const { scrollDOM } = view, { clientHeight } = scrollDOM, { top, height } = view.lineBlockAt(head);
|
|
169
|
+
if (height < clientHeight - options.yMargin * 2) {
|
|
170
|
+
scrollDOM.scrollTop = top + (height - clientHeight) / 2;
|
|
171
|
+
}
|
|
172
|
+
options.y = 'nearest';
|
|
173
|
+
}
|
|
174
|
+
return false;
|
|
175
|
+
}),
|
|
158
176
|
keymap.of([
|
|
159
177
|
...defaultKeymap,
|
|
160
178
|
...searchKeymap,
|
|
@@ -196,7 +214,7 @@ export class CodeMirror6 {
|
|
|
196
214
|
if (focusChanged) {
|
|
197
215
|
textarea.dispatchEvent(new FocusEvent(this.#view.hasFocus ? 'focus' : 'blur'));
|
|
198
216
|
}
|
|
199
|
-
if (selectionSet && this.lang === 'mediawiki'
|
|
217
|
+
GH: if (selectionSet && this.lang === 'mediawiki'
|
|
200
218
|
&& ['localhost:8080', 'bhsd-harry.github.io'].includes(location.host)) {
|
|
201
219
|
const tree = syntaxTree(state), { head } = state.selection.main, { name } = tree.resolve(head), innerName = tree.resolveInner(head).name;
|
|
202
220
|
if (name !== innerName) {
|
|
@@ -277,7 +295,7 @@ export class CodeMirror6 {
|
|
|
277
295
|
*/
|
|
278
296
|
lint(lintSource) {
|
|
279
297
|
const lintSources = typeof lintSource === 'function' ? [lintSource] : lintSource;
|
|
280
|
-
const linterExtension = (cm) => lintSources
|
|
298
|
+
const linterExtension = (cm) => lintSources?.length
|
|
281
299
|
? [
|
|
282
300
|
...lintSources.map(source => linter(async ({ state }) => {
|
|
283
301
|
const diagnostics = (await source(state)).map((diagnostic) => ({
|
|
@@ -301,7 +319,7 @@ export class CodeMirror6 {
|
|
|
301
319
|
return diagnostics;
|
|
302
320
|
})),
|
|
303
321
|
lintGutter(),
|
|
304
|
-
keymap.of([{ key: 'F8', run: nextDiagnostic }]),
|
|
322
|
+
keymap.of([{ key: 'F8', run: () => nextDiagnostic(this) }]),
|
|
305
323
|
optionalFunctions.statusBar(cm, lintSources[0].fixer),
|
|
306
324
|
]
|
|
307
325
|
: [];
|
|
@@ -318,15 +336,17 @@ export class CodeMirror6 {
|
|
|
318
336
|
this.#minHeight(Boolean(lintSource));
|
|
319
337
|
}
|
|
320
338
|
}
|
|
339
|
+
/** @private */
|
|
340
|
+
getLintExtension() {
|
|
341
|
+
return this.#view && this.#linter.get(this.#view.state)[0];
|
|
342
|
+
}
|
|
321
343
|
/** Update syntax checking immediately */
|
|
322
344
|
update() {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
plugin.force();
|
|
329
|
-
}
|
|
345
|
+
const extension = this.getLintExtension();
|
|
346
|
+
if (extension) {
|
|
347
|
+
const plugin = this.#view.plugin(extension[1]);
|
|
348
|
+
plugin.set = true;
|
|
349
|
+
plugin.force();
|
|
330
350
|
}
|
|
331
351
|
}
|
|
332
352
|
/**
|
|
@@ -435,7 +455,7 @@ export class CodeMirror6 {
|
|
|
435
455
|
this.#textarea.style.display = '';
|
|
436
456
|
this.#textarea.setSelectionRange(from, to, head === to ? 'forward' : 'backward');
|
|
437
457
|
if (hasFocus) {
|
|
438
|
-
this.#textarea.focus();
|
|
458
|
+
this.#textarea.focus({ preventScroll: true });
|
|
439
459
|
}
|
|
440
460
|
requestAnimationFrame(() => {
|
|
441
461
|
this.#textarea.scrollTop = scrollTop;
|
package/dist/fold.js
CHANGED
|
@@ -5,7 +5,7 @@ import { getRegex } from '@bhsd/common';
|
|
|
5
5
|
import elt from 'crelt';
|
|
6
6
|
import { tokens } from './config.js';
|
|
7
7
|
import { bgDark } from './constants.js';
|
|
8
|
-
import {
|
|
8
|
+
import { searchTag, getTag } from './matchTag.js';
|
|
9
9
|
import { braceStackUpdate, sliceDoc } from './util.js';
|
|
10
10
|
const getExtRegex = /* @__PURE__ */ getRegex(tag => new RegExp(`mw-tag-${tag}(?![a-z])`, 'u'));
|
|
11
11
|
export const updateSelection = (pos, { to }) => Math.max(pos, to), updateAll = (pos, { from, to }) => from <= pos && to > pos ? to : pos;
|
|
@@ -80,10 +80,10 @@ export const foldable = (state, posOrNode, tree, refOnly = false) => {
|
|
|
80
80
|
while (nextSibling && !(isExtBracket(nextSibling) && !regex.test(nextSibling.name))) {
|
|
81
81
|
({ nextSibling } = nextSibling);
|
|
82
82
|
}
|
|
83
|
-
const next = nextSibling?.nextSibling;
|
|
83
|
+
const next = nextSibling?.nextSibling, closing = next && getTag(state, next);
|
|
84
84
|
// The closing bracket of the current extension tag
|
|
85
|
-
if (
|
|
86
|
-
return { from:
|
|
85
|
+
if (closing && (!refOnly || refNames.has(closing.name))) {
|
|
86
|
+
return { from: searchTag(state, closing).to, to: nextSibling.from };
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
return false;
|
package/dist/html.js
CHANGED
|
@@ -6,7 +6,7 @@ import { LanguageSupport } from '@codemirror/language';
|
|
|
6
6
|
import { cssCompletion } from './css.js';
|
|
7
7
|
import { jsCompletion, markGlobalsPlugin } from './javascript.js';
|
|
8
8
|
import { mediawikiBase } from './mediawiki.js';
|
|
9
|
-
import {
|
|
9
|
+
import { lightHighlightStyle } from './theme.js';
|
|
10
10
|
export default (config, cm) => {
|
|
11
11
|
const { language, support } = mediawikiBase(config),
|
|
12
12
|
/** @test */
|
|
@@ -30,7 +30,7 @@ export default (config, cm) => {
|
|
|
30
30
|
jsCompletion,
|
|
31
31
|
cssCompletion(),
|
|
32
32
|
support,
|
|
33
|
-
|
|
33
|
+
lightHighlightStyle,
|
|
34
34
|
markGlobalsPlugin(cm),
|
|
35
35
|
]);
|
|
36
36
|
Object.assign(langSupport, { nestedMWLanguage: language });
|
package/dist/index.d.ts
CHANGED
|
@@ -27,7 +27,10 @@ export declare const registerAllowMultipleSelections: () => void;
|
|
|
27
27
|
export declare const registerAutocompletion: () => void;
|
|
28
28
|
/** Register the `codeFolding` extension */
|
|
29
29
|
export declare const registerCodeFolding: () => void;
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Register the `colorPicker` extension
|
|
32
|
+
* @deprecated This function does nothing and will be removed in a future release
|
|
33
|
+
*/
|
|
31
34
|
export declare const registerColorPicker: () => void;
|
|
32
35
|
/** Register all common extensions */
|
|
33
36
|
export declare const registerCommonExtensions: () => void;
|
|
@@ -78,6 +81,8 @@ export declare const registerColorPickerForMediaWiki: () => void;
|
|
|
78
81
|
export declare const registerBracketMatchingForMediaWiki: () => void;
|
|
79
82
|
/** Register the `codeFolding` extension for MediaWiki */
|
|
80
83
|
export declare const registerCodeFoldingForMediaWiki: () => void;
|
|
84
|
+
/** Register the `closeTags` extension for MediaWiki */
|
|
85
|
+
export declare const registerCloseTagsForMediaWiki: () => void;
|
|
81
86
|
/**
|
|
82
87
|
* Register MediaWiki core language support
|
|
83
88
|
* @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
|
|
@@ -89,14 +94,21 @@ export declare const registerMediaWikiCore: (articlePath?: string, templatedata?
|
|
|
89
94
|
export declare const registerHTML: () => void;
|
|
90
95
|
/** Register the `bracketMatching` extension for mixed MediaWiki-HTML */
|
|
91
96
|
export declare const registerBracketMatchingForHTML: () => void;
|
|
92
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* Register the `closeBrackets` extension for mixed MediaWiki-HTML
|
|
99
|
+
* @deprecated This function does nothing and will be removed in a future release
|
|
100
|
+
*/
|
|
93
101
|
export declare const registerCloseBracketsForHTML: () => void;
|
|
102
|
+
/** Register the `closeTags` extension for mixed MediaWiki-HTML */
|
|
103
|
+
export declare const registerCloseTagsForHTML: () => void;
|
|
94
104
|
/** Register the `colorPicker` extension for mixed MediaWiki-HTML */
|
|
95
105
|
export declare const registerColorPickerForHTML: () => void;
|
|
96
106
|
/** Register mixed MediaWiki-HTML core language support */
|
|
97
107
|
export declare const registerHTMLCore: () => void;
|
|
98
108
|
/** Register JavaScript language support */
|
|
99
109
|
export declare const registerJavaScript: () => void;
|
|
110
|
+
/** Register the `bracketMatching` extension for JavaScript */
|
|
111
|
+
export declare const registerBracketMatchingForJavaScript: () => void;
|
|
100
112
|
/** Register JavaScript core language support */
|
|
101
113
|
export declare const registerJavaScriptCore: () => void;
|
|
102
114
|
/** Register CSS language support */
|
|
@@ -115,8 +127,15 @@ export declare const registerLua: () => void;
|
|
|
115
127
|
export declare const registerLuaCore: () => void;
|
|
116
128
|
/** Register Vue language support */
|
|
117
129
|
export declare const registerVue: () => void;
|
|
118
|
-
/** Register the `
|
|
130
|
+
/** Register the `bracketMatching` extension for Vue */
|
|
131
|
+
export declare const registerBracketMatchingForVue: () => void;
|
|
132
|
+
/**
|
|
133
|
+
* Register the `closeBrackets` extension for Vue
|
|
134
|
+
* @deprecated This function does nothing and will be removed in a future release
|
|
135
|
+
*/
|
|
119
136
|
export declare const registerCloseBracketsForVue: () => void;
|
|
137
|
+
/** Register the `closeTags` extension for Vue */
|
|
138
|
+
export declare const registerCloseTagsForVue: () => void;
|
|
120
139
|
/** Register the `colorPicker` extension for Vue */
|
|
121
140
|
export declare const registerColorPickerForVue: () => void;
|
|
122
141
|
/** Register Vue core language support */
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { abusefilter, analyzer } from '@bhsd/lezer-abusefilter';
|
|
|
8
8
|
import { getLSP } from '@bhsd/browser';
|
|
9
9
|
import { colorPicker } from '@bhsd/codemirror-css-color-picker';
|
|
10
10
|
import bidiIsolates from './bidi.js';
|
|
11
|
+
import closeTags from './closeTags.js';
|
|
11
12
|
import { CodeMirror6, avail, languages, linterRegistry, destroyListeners, plain, optionalFunctions, themes, } from './codemirror.js';
|
|
12
13
|
import mediawikiColorPicker from './color.js';
|
|
13
14
|
import escapeKeymap from './escape.js';
|
|
@@ -27,7 +28,7 @@ import { tagModes, getStaticMwConfig } from './static.js';
|
|
|
27
28
|
import statusBar from './statusBar.js';
|
|
28
29
|
import css from './css.js';
|
|
29
30
|
import html from './html.js';
|
|
30
|
-
import javascript from './javascript.js';
|
|
31
|
+
import javascript, { exclude } from './javascript.js';
|
|
31
32
|
import lua from './lua.js';
|
|
32
33
|
import vue from './vue.js';
|
|
33
34
|
export { CodeMirror6 };
|
|
@@ -70,7 +71,7 @@ export const registerBracketMatching = () => {
|
|
|
70
71
|
};
|
|
71
72
|
/** Register the `closeBrackets` extension */
|
|
72
73
|
export const registerCloseBrackets = () => {
|
|
73
|
-
registerExtension('closeBrackets',
|
|
74
|
+
registerExtension('closeBrackets', closeBrackets);
|
|
74
75
|
};
|
|
75
76
|
/** Register the `scrollPastEnd` extension */
|
|
76
77
|
export const registerScrollPastEnd = () => {
|
|
@@ -100,12 +101,13 @@ export const registerAutocompletion = () => {
|
|
|
100
101
|
export const registerCodeFolding = () => {
|
|
101
102
|
registerExtension('codeFolding', codeFolding);
|
|
102
103
|
};
|
|
103
|
-
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Register the `colorPicker` extension
|
|
106
|
+
* @deprecated This function does nothing and will be removed in a future release
|
|
107
|
+
*/
|
|
108
|
+
export const registerColorPicker = () => { };
|
|
109
|
+
/** Register all common extensions */
|
|
110
|
+
export const registerCommonExtensions = () => {
|
|
109
111
|
registerHighlightSpecialChars();
|
|
110
112
|
registerHighlightActiveLine();
|
|
111
113
|
registerHighlightWhitespace();
|
|
@@ -118,15 +120,15 @@ const registerExtensions = () => {
|
|
|
118
120
|
registerAutocompletion();
|
|
119
121
|
registerCodeFolding();
|
|
120
122
|
};
|
|
121
|
-
/**
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
/**
|
|
124
|
+
* 各语言独立定义的扩展
|
|
125
|
+
* @param e 扩展
|
|
126
|
+
*/
|
|
127
|
+
const langExtension = (e = []) => e;
|
|
126
128
|
function mediawikiOnly(ext) {
|
|
127
129
|
return typeof ext === 'function'
|
|
128
130
|
? [(enable, cm) => enable ? ext(cm) : [], { mediawiki: true }]
|
|
129
|
-
: [
|
|
131
|
+
: [langExtension, { mediawiki: ext }];
|
|
130
132
|
}
|
|
131
133
|
/**
|
|
132
134
|
* 注册特定语言的扩展
|
|
@@ -135,7 +137,7 @@ function mediawikiOnly(ext) {
|
|
|
135
137
|
* @param ext 扩展
|
|
136
138
|
*/
|
|
137
139
|
const registerLangExtension = (lang, name, ext) => {
|
|
138
|
-
avail[name] ??= [
|
|
140
|
+
avail[name] ??= [langExtension];
|
|
139
141
|
const addon = avail[name];
|
|
140
142
|
addon[1] ??= {};
|
|
141
143
|
addon[1][lang] = ext;
|
|
@@ -158,6 +160,7 @@ export const registerMediaWiki = (articlePath, templatedata) => {
|
|
|
158
160
|
registerColorPickerForMediaWiki();
|
|
159
161
|
registerBracketMatchingForMediaWiki();
|
|
160
162
|
registerCodeFoldingForMediaWiki();
|
|
163
|
+
registerCloseTagsForMediaWiki();
|
|
161
164
|
};
|
|
162
165
|
/**
|
|
163
166
|
* 注册MediaWiki专用扩展
|
|
@@ -231,6 +234,10 @@ export const registerCodeFoldingForMediaWiki = () => {
|
|
|
231
234
|
registerLangExtension('mediawiki', 'codeFolding', mediawikiFold);
|
|
232
235
|
optionalFunctions.foldHandler = foldHandler;
|
|
233
236
|
};
|
|
237
|
+
/** Register the `closeTags` extension for MediaWiki */
|
|
238
|
+
export const registerCloseTagsForMediaWiki = () => {
|
|
239
|
+
registerLangExtension('mediawiki', 'closeTags', closeTags());
|
|
240
|
+
};
|
|
234
241
|
/**
|
|
235
242
|
* 注册LintSource
|
|
236
243
|
* @param lang 语言
|
|
@@ -265,19 +272,24 @@ export const registerHTML = () => {
|
|
|
265
272
|
registerCommonExtensions();
|
|
266
273
|
registerHTMLCore();
|
|
267
274
|
registerBracketMatchingForHTML();
|
|
268
|
-
|
|
275
|
+
registerCloseTagsForHTML();
|
|
269
276
|
registerColorPickerForHTML();
|
|
270
277
|
};
|
|
271
278
|
/** Register the `bracketMatching` extension for mixed MediaWiki-HTML */
|
|
272
279
|
export const registerBracketMatchingForHTML = () => {
|
|
273
280
|
registerLangExtension('html', 'bracketMatching', [
|
|
274
|
-
{},
|
|
281
|
+
{ exclude },
|
|
275
282
|
tagMatchingState,
|
|
276
283
|
]);
|
|
277
284
|
};
|
|
278
|
-
/**
|
|
279
|
-
|
|
280
|
-
|
|
285
|
+
/**
|
|
286
|
+
* Register the `closeBrackets` extension for mixed MediaWiki-HTML
|
|
287
|
+
* @deprecated This function does nothing and will be removed in a future release
|
|
288
|
+
*/
|
|
289
|
+
export const registerCloseBracketsForHTML = () => { };
|
|
290
|
+
/** Register the `closeTags` extension for mixed MediaWiki-HTML */
|
|
291
|
+
export const registerCloseTagsForHTML = () => {
|
|
292
|
+
registerLangExtension('html', 'closeTags', autoCloseTags);
|
|
281
293
|
};
|
|
282
294
|
/** Register the `colorPicker` extension for mixed MediaWiki-HTML */
|
|
283
295
|
export const registerColorPickerForHTML = () => {
|
|
@@ -291,8 +303,13 @@ export const registerHTMLCore = () => {
|
|
|
291
303
|
};
|
|
292
304
|
/** Register JavaScript language support */
|
|
293
305
|
export const registerJavaScript = () => {
|
|
294
|
-
|
|
306
|
+
registerCommonExtensions();
|
|
295
307
|
registerJavaScriptCore();
|
|
308
|
+
registerBracketMatchingForJavaScript();
|
|
309
|
+
};
|
|
310
|
+
/** Register the `bracketMatching` extension for JavaScript */
|
|
311
|
+
export const registerBracketMatchingForJavaScript = () => {
|
|
312
|
+
registerLangExtension('javascript', 'bracketMatching', [{ exclude }]);
|
|
296
313
|
};
|
|
297
314
|
/** Register JavaScript core language support */
|
|
298
315
|
export const registerJavaScriptCore = () => {
|
|
@@ -318,7 +335,7 @@ export const registerCSSCore = () => {
|
|
|
318
335
|
};
|
|
319
336
|
/** Register JSON language support */
|
|
320
337
|
export const registerJSON = () => {
|
|
321
|
-
|
|
338
|
+
registerCommonExtensions();
|
|
322
339
|
registerJSONCore();
|
|
323
340
|
};
|
|
324
341
|
/** Register JSON core language support */
|
|
@@ -329,7 +346,7 @@ export const registerJSONCore = () => {
|
|
|
329
346
|
};
|
|
330
347
|
/** Register Lua language support */
|
|
331
348
|
export const registerLua = () => {
|
|
332
|
-
|
|
349
|
+
registerCommonExtensions();
|
|
333
350
|
registerLuaCore();
|
|
334
351
|
};
|
|
335
352
|
/** Register Lua core language support */
|
|
@@ -342,12 +359,22 @@ export const registerLuaCore = () => {
|
|
|
342
359
|
export const registerVue = () => {
|
|
343
360
|
registerCommonExtensions();
|
|
344
361
|
registerVueCore();
|
|
345
|
-
|
|
362
|
+
registerBracketMatchingForVue();
|
|
363
|
+
registerCloseTagsForVue();
|
|
346
364
|
registerColorPickerForVue();
|
|
347
365
|
};
|
|
348
|
-
/** Register the `
|
|
349
|
-
export const
|
|
350
|
-
registerLangExtension('vue', '
|
|
366
|
+
/** Register the `bracketMatching` extension for Vue */
|
|
367
|
+
export const registerBracketMatchingForVue = () => {
|
|
368
|
+
registerLangExtension('vue', 'bracketMatching', [{ exclude }]);
|
|
369
|
+
};
|
|
370
|
+
/**
|
|
371
|
+
* Register the `closeBrackets` extension for Vue
|
|
372
|
+
* @deprecated This function does nothing and will be removed in a future release
|
|
373
|
+
*/
|
|
374
|
+
export const registerCloseBracketsForVue = () => { };
|
|
375
|
+
/** Register the `closeTags` extension for Vue */
|
|
376
|
+
export const registerCloseTagsForVue = () => {
|
|
377
|
+
registerLangExtension('vue', 'closeTags', autoCloseTags);
|
|
351
378
|
};
|
|
352
379
|
/** Register the `colorPicker` extension for Vue */
|
|
353
380
|
export const registerColorPickerForVue = () => {
|
|
@@ -361,7 +388,7 @@ export const registerVueCore = () => {
|
|
|
361
388
|
};
|
|
362
389
|
/** Register AbuseFilter language support */
|
|
363
390
|
export const registerAbuseFilter = () => {
|
|
364
|
-
|
|
391
|
+
registerCommonExtensions();
|
|
365
392
|
registerAbuseFilterCore();
|
|
366
393
|
};
|
|
367
394
|
/** Register AbuseFilter core language support */
|
package/dist/javascript.d.ts
CHANGED
|
@@ -4,6 +4,13 @@ import type { Tree } from '@lezer/common';
|
|
|
4
4
|
import type { DocRange } from './fold';
|
|
5
5
|
import type { CodeMirror6 } from './codemirror';
|
|
6
6
|
export declare const jsCompletion: Extension;
|
|
7
|
+
/**
|
|
8
|
+
* 忽略JavaScript正则表达式中的括号匹配
|
|
9
|
+
* @param state
|
|
10
|
+
* @param pos 位置
|
|
11
|
+
* @test
|
|
12
|
+
*/
|
|
13
|
+
export declare const exclude: (state: EditorState, pos: number) => boolean;
|
|
7
14
|
/**
|
|
8
15
|
* 高亮显示全局变量
|
|
9
16
|
* @ignore
|
package/dist/javascript.js
CHANGED
|
@@ -5,6 +5,14 @@ import { setDiagnosticsEffect } from '@codemirror/lint';
|
|
|
5
5
|
import { builtin } from './javascript-globals.js';
|
|
6
6
|
export const jsCompletion = javascriptLanguage.data.of({ autocomplete: scopeCompletionSource(globalThis) });
|
|
7
7
|
const globalsMark = Decoration.mark({ class: 'cm-globals' }), builtinGlobals = new Set(Object.keys(builtin));
|
|
8
|
+
/**
|
|
9
|
+
* 忽略JavaScript正则表达式中的括号匹配
|
|
10
|
+
* @param state
|
|
11
|
+
* @param pos 位置
|
|
12
|
+
* @test
|
|
13
|
+
*/
|
|
14
|
+
export const exclude = (state, pos) => javascriptLanguage.isActiveAt(state, pos, 0)
|
|
15
|
+
&& syntaxTree(state).resolveInner(pos, 0).name === 'RegExp';
|
|
8
16
|
/**
|
|
9
17
|
* 高亮显示全局变量
|
|
10
18
|
* @ignore
|
package/dist/lint.d.ts
ADDED
package/dist/lint.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const findDiagnostic = (deco, head, anchor = head) => {
|
|
2
|
+
let found;
|
|
3
|
+
deco.between(head, Infinity, (_, __, { spec: { diagnostics } }) => {
|
|
4
|
+
const next = diagnostics.sort((a, b) => a.from - b.from || a.to - b.to)
|
|
5
|
+
.find(({ from, to }) => from > head || from === head && to > anchor);
|
|
6
|
+
if (next) {
|
|
7
|
+
found = next;
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
});
|
|
12
|
+
return found;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* 选中下一个诊断的范围
|
|
16
|
+
* @param cm CodeMirror6 实例
|
|
17
|
+
*/
|
|
18
|
+
export const nextDiagnostic = (cm) => {
|
|
19
|
+
const view = cm.view, { state } = view, { diagnostics } = state.field(cm.getLintExtension()[2][0]), { from, to } = state.selection.main, next = findDiagnostic(diagnostics, from, to) ?? findDiagnostic(diagnostics, 0);
|
|
20
|
+
if (!next || next.from === from && next.to === to) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
view.dispatch({
|
|
24
|
+
selection: { anchor: next.from, head: next.to },
|
|
25
|
+
scrollIntoView: true,
|
|
26
|
+
});
|
|
27
|
+
return true;
|
|
28
|
+
};
|
package/dist/linter.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/** @todo revert df69718ab908966bff162fe51e8cfb4595e6b2ec */
|
|
2
|
-
import { rules as recommended } from '@eslint/js/src/configs/eslint-recommended.js';
|
|
3
1
|
import { sanitizeInlineStyle } from '@bhsd/common';
|
|
4
2
|
import { loadScript, getWikiparse, getLSP } from '@bhsd/browser';
|
|
5
3
|
import { styleLint } from '@bhsd/stylelint-util';
|
|
@@ -131,6 +129,9 @@ export const jsConfig = /* #__PURE__ */ (() => ({
|
|
|
131
129
|
* @test
|
|
132
130
|
*/
|
|
133
131
|
export const getJsLinter = async (cdn = eslintRepo) => {
|
|
132
|
+
/** @todo revert df69718ab908966bff162fe51e8cfb4595e6b2ec */
|
|
133
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
134
|
+
const { rules: recommended } = require('@eslint/js/src/configs/eslint-recommended.js');
|
|
134
135
|
await loadScript(cdn, 'eslint');
|
|
135
136
|
/** @see https://www.npmjs.com/package/@codemirror/lang-javascript */
|
|
136
137
|
const esLinter = new eslint.Linter(), conf = {
|