@bhsd/codemirror-mediawiki 3.9.1 → 3.10.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 +71 -11
- package/dist/bidi.d.ts +4 -8
- package/dist/bidi.js +33 -23
- package/dist/codemirror.js +15 -9
- package/dist/color.d.ts +1 -1
- package/dist/color.js +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +1 -0
- package/dist/constants.d.ts +3 -2
- package/dist/constants.js +3 -2
- package/dist/css.js +9 -6
- package/dist/escape.d.ts +1 -1
- package/dist/escape.js +4 -3
- package/dist/fold.d.ts +2 -2
- package/dist/fold.js +113 -40
- package/dist/hover.d.ts +2 -2
- package/dist/hover.js +74 -62
- package/dist/index.d.ts +54 -16
- package/dist/index.js +91 -38
- package/dist/inlay.d.ts +1 -1
- package/dist/inlay.js +26 -25
- package/dist/javascript.js +45 -2
- package/dist/linter.d.ts +15 -2
- package/dist/linter.js +2 -2
- package/dist/lintsource.d.ts +15 -3
- package/dist/lintsource.js +13 -7
- package/dist/lua.d.ts +0 -2
- package/dist/lua.js +32 -26
- package/dist/main.min.js +31 -29
- package/dist/matchTag.js +4 -3
- package/dist/mediawiki.d.ts +4 -2
- package/dist/mediawiki.js +56 -44
- package/dist/mw.min.js +33 -37
- package/dist/mwConfig.js +2 -2
- package/dist/openLinks.d.ts +4 -2
- package/dist/openLinks.js +56 -54
- package/dist/ref.d.ts +1 -1
- package/dist/ref.js +92 -93
- package/dist/signature.d.ts +1 -1
- package/dist/signature.js +50 -49
- package/dist/statusBar.js +31 -9
- package/dist/theme.js +10 -23
- package/dist/token.d.ts +20 -6
- package/dist/token.js +26 -17
- package/dist/util.d.ts +17 -2
- package/dist/util.js +39 -1
- package/dist/wiki.min.js +32 -36
- package/i18n/en.json +2 -2
- package/i18n/zh-hans.json +2 -2
- package/i18n/zh-hant.json +2 -2
- package/package.json +14 -12
package/dist/index.js
CHANGED
|
@@ -4,13 +4,14 @@ import { highlightSelectionMatches } from '@codemirror/search';
|
|
|
4
4
|
import { autocompletion, closeBrackets, acceptCompletion, completionKeymap, startCompletion, } from '@codemirror/autocomplete';
|
|
5
5
|
import { json } from '@codemirror/lang-json';
|
|
6
6
|
import { autoCloseTags } from '@codemirror/lang-html';
|
|
7
|
+
import { abusefilter, analyzer } from '@bhsd/lezer-abusefilter';
|
|
7
8
|
import { getLSP } from '@bhsd/browser';
|
|
8
9
|
import { colorPicker } from '@bhsd/codemirror-css-color-picker';
|
|
9
|
-
import
|
|
10
|
+
import bidiIsolates from './bidi.js';
|
|
10
11
|
import { CodeMirror6, avail, languages, linterRegistry, destroyListeners, plain, optionalFunctions, themes, } from './codemirror.js';
|
|
11
12
|
import mediawikiColorPicker from './color.js';
|
|
12
13
|
import escapeKeymap from './escape.js';
|
|
13
|
-
import codeFolding, {
|
|
14
|
+
import codeFolding, { mediawikiFold, foldHandler } from './fold.js';
|
|
14
15
|
import magicWordHover from './hover.js';
|
|
15
16
|
import { detectIndent } from './indent.js';
|
|
16
17
|
import inlayHints from './inlay.js';
|
|
@@ -18,10 +19,10 @@ import formatKeymap from './keymap.js';
|
|
|
18
19
|
import { getWikiLintSource, getJsLintSource, getCssLintSource, getJsonLintSource, getLuaLintSource, getVueLintSource, getHTMLLintSource, } from './lintsource.js';
|
|
19
20
|
import bracketMatchingBase from './matchBrackets.js';
|
|
20
21
|
import tagMatchingState from './matchTag.js';
|
|
21
|
-
import { mediawikiBase } from './mediawiki.js';
|
|
22
|
+
import { mediawikiBase, } from './mediawiki.js';
|
|
22
23
|
import openLinks from './openLinks.js';
|
|
23
24
|
import refHover from './ref.js';
|
|
24
|
-
import
|
|
25
|
+
import signatureHelpBase from './signature.js';
|
|
25
26
|
import { tagModes, getStaticMwConfig } from './static.js';
|
|
26
27
|
import statusBar from './statusBar.js';
|
|
27
28
|
import css from './css.js';
|
|
@@ -139,16 +140,21 @@ const registerLangExtension = (lang, name, ext) => {
|
|
|
139
140
|
addon[1] ??= {};
|
|
140
141
|
addon[1][lang] = ext;
|
|
141
142
|
};
|
|
142
|
-
/**
|
|
143
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Register MediaWiki language support
|
|
145
|
+
* @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
|
|
146
|
+
* @param templatedata whether to use [Extension:TemplateData](https://www.mediawiki.org/wiki/Extension:TemplateData)
|
|
147
|
+
* for template hover information; enabled by default
|
|
148
|
+
*/
|
|
149
|
+
export const registerMediaWiki = (articlePath, templatedata) => {
|
|
144
150
|
registerCommonExtensions();
|
|
145
|
-
registerMediaWikiCore();
|
|
146
|
-
registerOpenLinks();
|
|
147
|
-
registerEscape();
|
|
148
|
-
registerRefHover();
|
|
149
|
-
registerHover();
|
|
150
|
-
registerSignatureHelp();
|
|
151
|
-
registerInlayHints();
|
|
151
|
+
registerMediaWikiCore(articlePath, templatedata);
|
|
152
|
+
registerOpenLinks(articlePath);
|
|
153
|
+
registerEscape(articlePath);
|
|
154
|
+
registerRefHover(articlePath);
|
|
155
|
+
registerHover(articlePath, templatedata);
|
|
156
|
+
registerSignatureHelp(articlePath);
|
|
157
|
+
registerInlayHints(articlePath);
|
|
152
158
|
registerColorPickerForMediaWiki();
|
|
153
159
|
registerBracketMatchingForMediaWiki();
|
|
154
160
|
registerCodeFoldingForMediaWiki();
|
|
@@ -161,33 +167,57 @@ export const registerMediaWiki = () => {
|
|
|
161
167
|
const registerExtensionForMediaWiki = (name, ext) => {
|
|
162
168
|
avail[name] ??= mediawikiOnly(ext);
|
|
163
169
|
};
|
|
164
|
-
/**
|
|
165
|
-
|
|
166
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Register the `openLinks` extension
|
|
172
|
+
* @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
|
|
173
|
+
*/
|
|
174
|
+
export const registerOpenLinks = (articlePath) => {
|
|
175
|
+
registerExtensionForMediaWiki('openLinks', openLinks(articlePath));
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Register the `escape` extension
|
|
179
|
+
* @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
|
|
180
|
+
*/
|
|
181
|
+
export const registerEscape = (articlePath) => {
|
|
182
|
+
registerExtensionForMediaWiki('escape', escapeKeymap(articlePath));
|
|
167
183
|
};
|
|
168
|
-
/**
|
|
169
|
-
|
|
170
|
-
|
|
184
|
+
/**
|
|
185
|
+
* Register the `refHover` extension
|
|
186
|
+
* @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
|
|
187
|
+
*/
|
|
188
|
+
export const registerRefHover = (articlePath) => {
|
|
189
|
+
registerExtensionForMediaWiki('refHover', refHover(articlePath));
|
|
171
190
|
};
|
|
172
|
-
/**
|
|
173
|
-
|
|
174
|
-
|
|
191
|
+
/**
|
|
192
|
+
* Register the `hover` extension
|
|
193
|
+
* @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
|
|
194
|
+
* @param templatedata whether to use [Extension:TemplateData](https://www.mediawiki.org/wiki/Extension:TemplateData)
|
|
195
|
+
* for template information; enabled by default
|
|
196
|
+
*/
|
|
197
|
+
export const registerHover = (articlePath, templatedata) => {
|
|
198
|
+
registerExtensionForMediaWiki('hover', magicWordHover(articlePath, templatedata));
|
|
175
199
|
};
|
|
176
|
-
/**
|
|
177
|
-
|
|
178
|
-
|
|
200
|
+
/**
|
|
201
|
+
* Register the `signatureHelp` extension
|
|
202
|
+
* @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
|
|
203
|
+
*/
|
|
204
|
+
export const registerSignatureHelp = (articlePath) => {
|
|
205
|
+
registerExtensionForMediaWiki('signatureHelp', signatureHelpBase(articlePath));
|
|
179
206
|
};
|
|
180
|
-
/**
|
|
181
|
-
|
|
182
|
-
|
|
207
|
+
/**
|
|
208
|
+
* Register the `inlayHints` extension
|
|
209
|
+
* @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
|
|
210
|
+
*/
|
|
211
|
+
export const registerInlayHints = (articlePath) => {
|
|
212
|
+
registerExtensionForMediaWiki('inlayHints', inlayHints(articlePath));
|
|
183
213
|
};
|
|
184
|
-
/** Register the `
|
|
185
|
-
export const
|
|
186
|
-
registerExtensionForMediaWiki('
|
|
214
|
+
/** Register the `bidiIsolates` extension */
|
|
215
|
+
export const registerBidiIsolates = () => {
|
|
216
|
+
registerExtensionForMediaWiki('bidiIsolates', bidiIsolates);
|
|
187
217
|
};
|
|
188
218
|
/** Register the `colorPicker` extension for MediaWiki */
|
|
189
219
|
export const registerColorPickerForMediaWiki = () => {
|
|
190
|
-
registerLangExtension('mediawiki', 'colorPicker', mediawikiColorPicker
|
|
220
|
+
registerLangExtension('mediawiki', 'colorPicker', mediawikiColorPicker);
|
|
191
221
|
};
|
|
192
222
|
/** Register the `bracketMatching` extension for MediaWiki */
|
|
193
223
|
export const registerBracketMatchingForMediaWiki = () => {
|
|
@@ -198,7 +228,7 @@ export const registerBracketMatchingForMediaWiki = () => {
|
|
|
198
228
|
};
|
|
199
229
|
/** Register the `codeFolding` extension for MediaWiki */
|
|
200
230
|
export const registerCodeFoldingForMediaWiki = () => {
|
|
201
|
-
registerLangExtension('mediawiki', 'codeFolding',
|
|
231
|
+
registerLangExtension('mediawiki', 'codeFolding', mediawikiFold);
|
|
202
232
|
optionalFunctions.foldHandler = foldHandler;
|
|
203
233
|
};
|
|
204
234
|
/**
|
|
@@ -210,16 +240,20 @@ const registerLintSource = (lang, lintSource) => {
|
|
|
210
240
|
linterRegistry[lang] = lintSource;
|
|
211
241
|
optionalFunctions.statusBar = statusBar;
|
|
212
242
|
};
|
|
213
|
-
/**
|
|
214
|
-
|
|
243
|
+
/**
|
|
244
|
+
* Register MediaWiki core language support
|
|
245
|
+
* @param articlePath article path (e.g., 'https://www.mediawiki.org/wiki/')
|
|
246
|
+
* @param templatedata whether to use [Extension:TemplateData](https://www.mediawiki.org/wiki/Extension:TemplateData)
|
|
247
|
+
* for template parameter autocompletion
|
|
248
|
+
*/
|
|
249
|
+
export const registerMediaWikiCore = (articlePath, templatedata) => {
|
|
215
250
|
CodeMirror6.getMwConfig = (config) => getStaticMwConfig(config, tagModes);
|
|
216
251
|
languages['mediawiki'] = (config) => [
|
|
217
|
-
mediawikiBase(config),
|
|
252
|
+
mediawikiBase(config, templatedata),
|
|
218
253
|
plain(),
|
|
219
|
-
bidiIsolation,
|
|
220
254
|
keymap.of(formatKeymap),
|
|
221
255
|
];
|
|
222
|
-
registerLintSource('mediawiki', getWikiLintSource);
|
|
256
|
+
registerLintSource('mediawiki', getWikiLintSource(articlePath));
|
|
223
257
|
destroyListeners.push(view => {
|
|
224
258
|
if (typeof wikiparse === 'object' && wikiparse.LanguageService) {
|
|
225
259
|
getLSP(view)?.destroy();
|
|
@@ -230,9 +264,17 @@ export const registerMediaWikiCore = () => {
|
|
|
230
264
|
export const registerHTML = () => {
|
|
231
265
|
registerCommonExtensions();
|
|
232
266
|
registerHTMLCore();
|
|
267
|
+
registerBracketMatchingForHTML();
|
|
233
268
|
registerCloseBracketsForHTML();
|
|
234
269
|
registerColorPickerForHTML();
|
|
235
270
|
};
|
|
271
|
+
/** Register the `bracketMatching` extension for mixed MediaWiki-HTML */
|
|
272
|
+
export const registerBracketMatchingForHTML = () => {
|
|
273
|
+
registerLangExtension('html', 'bracketMatching', [
|
|
274
|
+
{},
|
|
275
|
+
tagMatchingState,
|
|
276
|
+
]);
|
|
277
|
+
};
|
|
236
278
|
/** Register the `closeBrackets` extension for mixed MediaWiki-HTML */
|
|
237
279
|
export const registerCloseBracketsForHTML = () => {
|
|
238
280
|
registerLangExtension('html', 'closeBrackets', autoCloseTags);
|
|
@@ -317,6 +359,17 @@ export const registerVueCore = () => {
|
|
|
317
359
|
registerLintSource('vue', getVueLintSource);
|
|
318
360
|
optionalFunctions.detectIndent = detectIndent;
|
|
319
361
|
};
|
|
362
|
+
/** Register AbuseFilter language support */
|
|
363
|
+
export const registerAbuseFilter = () => {
|
|
364
|
+
registerExtensions();
|
|
365
|
+
registerAbuseFilterCore();
|
|
366
|
+
};
|
|
367
|
+
/** Register AbuseFilter core language support */
|
|
368
|
+
export const registerAbuseFilterCore = () => {
|
|
369
|
+
languages['abusefilter'] = abusefilter;
|
|
370
|
+
registerLintSource('abusefilter', () => state => analyzer({ state }));
|
|
371
|
+
optionalFunctions.detectIndent = detectIndent;
|
|
372
|
+
};
|
|
320
373
|
/**
|
|
321
374
|
* Register a custom language support
|
|
322
375
|
* @param name language name
|
package/dist/inlay.d.ts
CHANGED
package/dist/inlay.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Decoration, EditorView, WidgetType, ViewPlugin } from '@codemirror/view
|
|
|
3
3
|
import { getLSP } from '@bhsd/browser';
|
|
4
4
|
import elt from 'crelt';
|
|
5
5
|
import { base } from './constants.js';
|
|
6
|
-
import { posToIndex, } from './util.js';
|
|
6
|
+
import { posToIndex, toConfigGetter, } from './util.js';
|
|
7
7
|
const cls = 'cm-inlay-hint';
|
|
8
8
|
class InlayHintWidget extends WidgetType {
|
|
9
9
|
constructor(label) {
|
|
@@ -25,10 +25,9 @@ const stateEffect = StateEffect.define(), field = StateField.define({
|
|
|
25
25
|
const { value: { text, inlayHints } } = effect;
|
|
26
26
|
if (str === text) {
|
|
27
27
|
return inlayHints
|
|
28
|
-
? Decoration.set(inlayHints.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
.map(([index, label]) => Decoration.widget({ widget: new InlayHintWidget(label) }).range(index)))
|
|
28
|
+
? Decoration.set(inlayHints.map(({ position, label }) => Decoration.widget({
|
|
29
|
+
widget: new InlayHintWidget(label),
|
|
30
|
+
}).range(posToIndex(doc, position))), true)
|
|
32
31
|
: Decoration.none;
|
|
33
32
|
}
|
|
34
33
|
}
|
|
@@ -50,23 +49,25 @@ const update = async ({ view, docChanged }) => {
|
|
|
50
49
|
});
|
|
51
50
|
}
|
|
52
51
|
};
|
|
53
|
-
export default (cm) =>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
52
|
+
export default (articlePath) => (cm) => {
|
|
53
|
+
return [
|
|
54
|
+
field,
|
|
55
|
+
ViewPlugin.define(view => {
|
|
56
|
+
const timer = setInterval(() => {
|
|
57
|
+
if (getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), base.CDN)) {
|
|
58
|
+
clearInterval(timer);
|
|
59
|
+
void update({ view, docChanged: true });
|
|
60
|
+
}
|
|
61
|
+
}, 100);
|
|
62
|
+
return { update };
|
|
63
|
+
}),
|
|
64
|
+
EditorView.theme({
|
|
65
|
+
[`.${cls}`]: {
|
|
66
|
+
color: '#969696',
|
|
67
|
+
fontStyle: 'italic',
|
|
68
|
+
'-webkitUserSelect': 'none',
|
|
69
|
+
userSelect: 'none',
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
];
|
|
73
|
+
};
|
package/dist/javascript.js
CHANGED
|
@@ -1,3 +1,46 @@
|
|
|
1
|
-
import { javascript as js, javascriptLanguage, scopeCompletionSource } from '@codemirror/lang-javascript';
|
|
1
|
+
import { javascript as js, javascriptLanguage, scopeCompletionSource, localCompletionSource, } from '@codemirror/lang-javascript';
|
|
2
|
+
import { ViewPlugin, Decoration } from '@codemirror/view';
|
|
3
|
+
import { syntaxTree } from '@codemirror/language';
|
|
4
|
+
import { builtin } from 'globals/globals.json';
|
|
2
5
|
export const jsCompletion = javascriptLanguage.data.of({ autocomplete: scopeCompletionSource(globalThis) });
|
|
3
|
-
|
|
6
|
+
const globals = Decoration.mark({ class: 'cm-globals' });
|
|
7
|
+
const markGlobals = (tree, visibleRanges, state) => {
|
|
8
|
+
const decorations = [];
|
|
9
|
+
for (const { from, to } of visibleRanges) {
|
|
10
|
+
tree.iterate({
|
|
11
|
+
from,
|
|
12
|
+
to,
|
|
13
|
+
enter({ type, from: f, to: t }) {
|
|
14
|
+
const name = state.sliceDoc(f, t);
|
|
15
|
+
if (type.is('VariableName') && name in builtin) {
|
|
16
|
+
const completions = localCompletionSource({ state, pos: t, explicit: true });
|
|
17
|
+
if (!completions?.options.some(({ label }) => label === name)) {
|
|
18
|
+
decorations.push(globals.range(f, t));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return Decoration.set(decorations);
|
|
25
|
+
};
|
|
26
|
+
export default () => [
|
|
27
|
+
js(),
|
|
28
|
+
jsCompletion,
|
|
29
|
+
ViewPlugin.fromClass(class {
|
|
30
|
+
constructor({ state, visibleRanges }) {
|
|
31
|
+
this.tree = syntaxTree(state);
|
|
32
|
+
this.decorations = markGlobals(this.tree, visibleRanges, state);
|
|
33
|
+
}
|
|
34
|
+
update({ docChanged, viewportChanged, state, view: { visibleRanges } }) {
|
|
35
|
+
const tree = syntaxTree(state);
|
|
36
|
+
if (docChanged || viewportChanged || tree !== this.tree) {
|
|
37
|
+
this.tree = tree;
|
|
38
|
+
this.decorations = markGlobals(tree, visibleRanges, state);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}, {
|
|
42
|
+
decorations(v) {
|
|
43
|
+
return v.decorations;
|
|
44
|
+
},
|
|
45
|
+
}),
|
|
46
|
+
];
|
package/dist/linter.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Diagnostic as DiagnosticBase, Range } from 'vscode-languageserver-types';
|
|
1
|
+
import type { Diagnostic as DiagnosticBase, Range, Position } from 'vscode-languageserver-types';
|
|
2
2
|
import type { Linter } from 'eslint';
|
|
3
|
-
import type { Warning } from 'stylelint';
|
|
3
|
+
import type { Warning } from 'stylelint/types/stylelint';
|
|
4
4
|
import type { Diagnostic } from 'luacheck-browserify';
|
|
5
5
|
export type Option = Record<string, unknown> | null | undefined;
|
|
6
6
|
export type LiveOption = (runtime?: boolean) => Option | Promise<Option>;
|
|
@@ -20,6 +20,19 @@ declare interface MixedDiagnostic extends Omit<DiagnosticBase, 'range'> {
|
|
|
20
20
|
}
|
|
21
21
|
export declare const stylelintRepo = "npm/@bhsd/stylelint-browserify";
|
|
22
22
|
export declare const eslintRepo = "npm/@bhsd/eslint-browserify", luacheckRepo = "npm/luacheck-browserify";
|
|
23
|
+
/**
|
|
24
|
+
* 计算位置
|
|
25
|
+
* @param range 范围
|
|
26
|
+
* @param lineOrOffset 行号或相对位置
|
|
27
|
+
* @param column 列号
|
|
28
|
+
*/
|
|
29
|
+
export declare const offsetAt: (range: [number, number], lineOrOffset: number, column?: number) => number;
|
|
30
|
+
/**
|
|
31
|
+
* 将偏移量转换为位置
|
|
32
|
+
* @param code 代码字符串
|
|
33
|
+
* @param index 偏移量
|
|
34
|
+
*/
|
|
35
|
+
export declare const indexToPos: (code: string, index: number) => Position;
|
|
23
36
|
/**
|
|
24
37
|
* 获取 Wikitext LSP
|
|
25
38
|
* @param opt 选项
|
package/dist/linter.js
CHANGED
|
@@ -9,7 +9,7 @@ export const eslintRepo = 'npm/@bhsd/eslint-browserify', luacheckRepo = 'npm/lua
|
|
|
9
9
|
* @param lineOrOffset 行号或相对位置
|
|
10
10
|
* @param column 列号
|
|
11
11
|
*/
|
|
12
|
-
const offsetAt = (range, lineOrOffset, column) => {
|
|
12
|
+
export const offsetAt = (range, lineOrOffset, column) => {
|
|
13
13
|
if (column === undefined) {
|
|
14
14
|
return Math.min(range[1], range[0] + Math.max(0, lineOrOffset));
|
|
15
15
|
}
|
|
@@ -31,7 +31,7 @@ const getPrefix = ({ type, tag }, i) => `${type === 'ext-attr' ? 'div' : tag}#${
|
|
|
31
31
|
* @param code 代码字符串
|
|
32
32
|
* @param index 偏移量
|
|
33
33
|
*/
|
|
34
|
-
const indexToPos = (code, index) => {
|
|
34
|
+
export const indexToPos = (code, index) => {
|
|
35
35
|
const lines = code.slice(0, index).split('\n');
|
|
36
36
|
return { line: lines.length - 1, character: lines[lines.length - 1].length };
|
|
37
37
|
};
|
package/dist/lintsource.d.ts
CHANGED
|
@@ -3,10 +3,10 @@ import type { Text, EditorState } from '@codemirror/state';
|
|
|
3
3
|
import type { Language } from '@codemirror/language';
|
|
4
4
|
import type { Diagnostic, Action } from '@codemirror/lint';
|
|
5
5
|
import type { Option, LiveOption } from './linter';
|
|
6
|
-
export type LintSource = ((state: EditorState) => Diagnostic[] | Promise<Diagnostic[]>) & {
|
|
6
|
+
export type LintSource = ((state: EditorState) => readonly Diagnostic[] | Promise<readonly Diagnostic[]>) & {
|
|
7
7
|
fixer?: (doc: Text, rule?: string) => string | Promise<string>;
|
|
8
8
|
};
|
|
9
|
-
export type LintSources = LintSource | [LintSource
|
|
9
|
+
export type LintSources = LintSource | [LintSource, ...LintSource[]];
|
|
10
10
|
export type LintSourceGetter = (opt?: Option | LiveOption, view?: EditorView, nestedMWLanguage?: Language) => LintSource | Promise<LintSource>;
|
|
11
11
|
export interface ExtendedAction extends Action {
|
|
12
12
|
tooltip: string | undefined;
|
|
@@ -17,7 +17,19 @@ export interface ExtendedAction extends Action {
|
|
|
17
17
|
* @param runtime 是否为运行时选项
|
|
18
18
|
*/
|
|
19
19
|
export declare const getOpt: (opt: Option | LiveOption, runtime?: boolean) => Option | Promise<Option>;
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* 获取指定行列的位置
|
|
22
|
+
* @param doc 文档
|
|
23
|
+
* @param line 行号
|
|
24
|
+
* @param column 列号
|
|
25
|
+
* @param from 子语言起始位置
|
|
26
|
+
*/
|
|
27
|
+
export declare const pos: (doc: Text, line: number, column: number, from?: number) => number;
|
|
28
|
+
export declare const getRange: (doc: Text, line: number, column: number, endLine?: number, endColumn?: number, f?: number, t?: number) => {
|
|
29
|
+
from: number;
|
|
30
|
+
to: number;
|
|
31
|
+
};
|
|
32
|
+
export declare const getWikiLintSource: (articlePath?: string) => LintSourceGetter;
|
|
21
33
|
export declare const getJsLintSource: LintSourceGetter;
|
|
22
34
|
export declare const getCssLintSource: LintSourceGetter;
|
|
23
35
|
export declare const getVueLintSource: LintSourceGetter;
|
package/dist/lintsource.js
CHANGED
|
@@ -3,7 +3,7 @@ import { cssLanguage } from '@codemirror/lang-css';
|
|
|
3
3
|
import { javascriptLanguage } from '@codemirror/lang-javascript';
|
|
4
4
|
import { sanitizeInlineStyle, lintJSON } from '@bhsd/common';
|
|
5
5
|
import { getWikiLinter, getJsLinter, getCssLinter, getLuaLinter, stylelintRepo, eslintRepo, luacheckRepo, } from './linter.js';
|
|
6
|
-
import { posToIndex, } from './util.js';
|
|
6
|
+
import { posToIndex, toConfigGetter, } from './util.js';
|
|
7
7
|
import { base } from './constants.js';
|
|
8
8
|
/**
|
|
9
9
|
* 获取Linter选项
|
|
@@ -18,7 +18,7 @@ export const getOpt = (opt, runtime) => typeof opt === 'function' ? opt(runtime)
|
|
|
18
18
|
* @param column 列号
|
|
19
19
|
* @param from 子语言起始位置
|
|
20
20
|
*/
|
|
21
|
-
const pos = (doc, line, column, from = 0) => {
|
|
21
|
+
export const pos = (doc, line, column, from = 0) => {
|
|
22
22
|
if (from === 0) {
|
|
23
23
|
return posToIndex(doc, { line: line - 1, character: column - 1 });
|
|
24
24
|
}
|
|
@@ -28,7 +28,7 @@ const pos = (doc, line, column, from = 0) => {
|
|
|
28
28
|
character: (line === 1 ? from - lineDesc.from : 0) + column - 1,
|
|
29
29
|
});
|
|
30
30
|
};
|
|
31
|
-
const getRange = (doc, line, column, endLine, endColumn, f = 0, t = Infinity) => {
|
|
31
|
+
export const getRange = (doc, line, column, endLine, endColumn, f = 0, t = Infinity) => {
|
|
32
32
|
const start = pos(doc, line, column, f);
|
|
33
33
|
return {
|
|
34
34
|
from: start,
|
|
@@ -56,9 +56,15 @@ const wikiLintSource = async (wikiLint, text, opt, doc, f = 0, t) => (await wiki
|
|
|
56
56
|
? getRange(doc, r.start.line + 1, r.start.character + 1, r.end.line + 1, r.end.character + 1, f, t)
|
|
57
57
|
: { from: from + f, to: (to ?? from) + f },
|
|
58
58
|
}));
|
|
59
|
-
export const getWikiLintSource = async (opt, v) => {
|
|
60
|
-
const
|
|
61
|
-
|
|
59
|
+
export const getWikiLintSource = (articlePath) => async (opt, v) => {
|
|
60
|
+
const options = { ...await getOpt(opt), cdn: base.CDN };
|
|
61
|
+
if (articlePath) {
|
|
62
|
+
options.getConfig = toConfigGetter(options.getConfig, articlePath);
|
|
63
|
+
}
|
|
64
|
+
const wikiLint = await getWikiLinter(options, v);
|
|
65
|
+
const lintSource = async ({ doc }) => {
|
|
66
|
+
return wikiLintSource(wikiLint, doc.toString(), await getOpt(opt, true), doc);
|
|
67
|
+
};
|
|
62
68
|
if (wikiLint.fixer) {
|
|
63
69
|
lintSource.fixer = (_, rule) => wikiLint.fixer('', rule);
|
|
64
70
|
}
|
|
@@ -166,7 +172,7 @@ export const getHTMLLintSource = async (opt, view, language) => {
|
|
|
166
172
|
};
|
|
167
173
|
};
|
|
168
174
|
export const getJsonLintSource = () => ({ doc }) => lintJSON(doc.toString())
|
|
169
|
-
.map(({ message,
|
|
175
|
+
.map(({ message, from, to = from, severity }) => ({ message, severity, from, to }));
|
|
170
176
|
export const getLuaLintSource = async () => {
|
|
171
177
|
const { CDN } = base, luaLint = await getLuaLinter(CDN && `${CDN}/${luacheckRepo}`);
|
|
172
178
|
return async ({ doc }) => (await luaLint(doc.toString()))
|
package/dist/lua.d.ts
CHANGED
package/dist/lua.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* eslint-disable no-template-curly-in-string */
|
|
2
2
|
import { lua } from '@codemirror/legacy-modes/mode/lua';
|
|
3
|
-
import { syntaxTree, LanguageSupport, StreamLanguage, foldService } from '@codemirror/language';
|
|
3
|
+
import { syntaxTree, LanguageSupport, StreamLanguage, foldService, HighlightStyle, syntaxHighlighting, } from '@codemirror/language';
|
|
4
4
|
import { snippetCompletion } from '@codemirror/autocomplete';
|
|
5
|
-
import {
|
|
5
|
+
import { tags } from '@lezer/highlight';
|
|
6
|
+
import { leadingSpaces, sliceDoc } from './util.js';
|
|
6
7
|
const map = {
|
|
7
8
|
1: 'constant',
|
|
8
9
|
2: 'function',
|
|
@@ -84,7 +85,9 @@ const map = {
|
|
|
84
85
|
addWarning: 2,
|
|
85
86
|
allToString: 2,
|
|
86
87
|
clone: 2,
|
|
88
|
+
getContentLanguage: 2,
|
|
87
89
|
getCurrentFrame: 2,
|
|
90
|
+
getLanguage: 2,
|
|
88
91
|
incrementExpensiveFunctionCount: 2,
|
|
89
92
|
isSubsting: 2,
|
|
90
93
|
loadData: 2,
|
|
@@ -300,8 +303,8 @@ const map = {
|
|
|
300
303
|
detail: 'in loop',
|
|
301
304
|
type: 'keyword',
|
|
302
305
|
}),
|
|
303
|
-
], types = new Set(['variableName', 'variableName.standard', 'keyword']);
|
|
304
|
-
|
|
306
|
+
], types = new Set(['variableName', 'variableName.standard', 'keyword']), lang = StreamLanguage.define(lua);
|
|
307
|
+
const source = context => {
|
|
305
308
|
const { state, pos } = context, node = syntaxTree(state).resolveInner(pos, -1);
|
|
306
309
|
if (!types.has(node.name)) {
|
|
307
310
|
return null;
|
|
@@ -396,7 +399,7 @@ lua.languageData['autocomplete'] = (context => {
|
|
|
396
399
|
return {
|
|
397
400
|
from,
|
|
398
401
|
options: prevSibling?.name !== 'keyword'
|
|
399
|
-
|| builtin.includes(
|
|
402
|
+
|| builtin.includes(sliceDoc(state, prevSibling))
|
|
400
403
|
? [...binary, ...blocks]
|
|
401
404
|
: [...builtins, ...constants, ...tables, ...unary, ...blocks],
|
|
402
405
|
validFor,
|
|
@@ -404,26 +407,29 @@ lua.languageData['autocomplete'] = (context => {
|
|
|
404
407
|
}
|
|
405
408
|
}
|
|
406
409
|
return null;
|
|
407
|
-
}
|
|
408
|
-
const support =
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
410
|
+
};
|
|
411
|
+
const support = [
|
|
412
|
+
syntaxHighlighting(HighlightStyle.define([{ tag: tags.standard(tags.variableName), class: 'cm-globals' }])),
|
|
413
|
+
lang.data.of({ autocomplete: source }),
|
|
414
|
+
foldService.of(({ doc, tabSize }, start, from) => {
|
|
415
|
+
const { text, number } = doc.lineAt(start);
|
|
416
|
+
if (!text.trim()) {
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
const getIndent = (line) => leadingSpaces(line).replace(/\t/gu, ' '.repeat(tabSize)).length;
|
|
420
|
+
const indent = getIndent(text);
|
|
421
|
+
let j = number, empty = true;
|
|
422
|
+
for (; j < doc.lines; j++) {
|
|
423
|
+
const { text: next } = doc.line(j + 1);
|
|
424
|
+
if (next.trim()) {
|
|
425
|
+
const nextIndent = getIndent(next);
|
|
426
|
+
if (indent >= nextIndent) {
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
empty = false;
|
|
422
430
|
}
|
|
423
|
-
empty = false;
|
|
424
431
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
export default () => new LanguageSupport(
|
|
429
|
-
export { lua };
|
|
432
|
+
return empty || j === number ? null : { from, to: doc.line(j).to };
|
|
433
|
+
}),
|
|
434
|
+
];
|
|
435
|
+
export default () => new LanguageSupport(lang, support);
|