@bhsd/codemirror-mediawiki 3.0.3 → 3.2.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 +400 -14
- package/dist/codemirror.d.ts +29 -26
- package/dist/codemirror.js +42 -175
- package/dist/color.d.ts +1 -1
- package/dist/color.js +14 -16
- package/dist/css.d.ts +2 -0
- package/dist/css.js +3 -2
- package/dist/demo.min.js +37 -0
- package/dist/escape.d.ts +3 -2
- package/dist/escape.js +76 -4
- package/dist/fold.d.ts +3 -52
- package/dist/fold.js +11 -12
- package/dist/html.d.ts +4 -0
- package/dist/html.js +31 -0
- package/dist/indent.js +1 -1
- package/dist/index.d.ts +102 -0
- package/dist/index.js +340 -0
- package/dist/linter.js +18 -6
- package/dist/lintsource.d.ts +3 -1
- package/dist/lintsource.js +46 -29
- package/dist/main.min.js +25 -25
- package/dist/mediawiki.d.ts +0 -5
- package/dist/mediawiki.js +0 -75
- package/dist/mw.min.js +30 -30
- package/dist/static.d.ts +0 -4
- package/dist/static.js +0 -4
- package/dist/statusBar.d.ts +2 -1
- package/dist/statusBar.js +59 -38
- package/dist/token.d.ts +0 -3
- package/dist/token.js +1 -12
- package/dist/vue.js +2 -2
- package/dist/wiki.min.js +29 -29
- package/i18n/en.json +3 -3
- package/i18n/zh-hans.json +3 -3
- package/i18n/zh-hant.json +3 -3
- package/package.json +16 -14
package/dist/index.js
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import { keymap, highlightSpecialChars, highlightActiveLine, highlightWhitespace, highlightTrailingWhitespace, scrollPastEnd, drawSelection, rectangularSelection, crosshairCursor, } from '@codemirror/view';
|
|
2
|
+
import { EditorState } from '@codemirror/state';
|
|
3
|
+
import { highlightSelectionMatches } from '@codemirror/search';
|
|
4
|
+
import { closeBrackets, autocompletion, acceptCompletion, completionKeymap, startCompletion, } from '@codemirror/autocomplete';
|
|
5
|
+
import { json } from '@codemirror/lang-json';
|
|
6
|
+
import { autoCloseTags } from '@codemirror/lang-html';
|
|
7
|
+
import { getLSP } from '@bhsd/browser';
|
|
8
|
+
import { colorPicker as cssColorPicker, colorPickerTheme, makeColorPicker } from '@bhsd/codemirror-css-color-picker';
|
|
9
|
+
import colorPicker, { discoverColors } from './color';
|
|
10
|
+
import { mediawiki } from './mediawiki';
|
|
11
|
+
import escape from './escape';
|
|
12
|
+
import codeFolding, { mediaWikiFold, foldHandler } from './fold';
|
|
13
|
+
import tagMatchingState from './matchTag';
|
|
14
|
+
import refHover from './ref';
|
|
15
|
+
import magicWordHover from './hover';
|
|
16
|
+
import signatureHelp from './signature';
|
|
17
|
+
import inlayHints from './inlay';
|
|
18
|
+
import { getWikiLintSource, getJsLintSource, getCssLintSource, getJsonLintSource, getLuaLintSource, getVueLintSource, getHTMLLintSource, } from './lintsource';
|
|
19
|
+
import openLinks from './openLinks';
|
|
20
|
+
import { tagModes, getStaticMwConfig } from './static';
|
|
21
|
+
import bidiIsolation from './bidi';
|
|
22
|
+
import toolKeymap from './keymap';
|
|
23
|
+
import bracketMatching from './matchBrackets';
|
|
24
|
+
import statusBar from './statusBar';
|
|
25
|
+
import { detectIndent } from './indent';
|
|
26
|
+
import javascript from './javascript';
|
|
27
|
+
import css from './css';
|
|
28
|
+
import lua from './lua';
|
|
29
|
+
import vue from './vue';
|
|
30
|
+
import html from './html';
|
|
31
|
+
import { CodeMirror6, avail, languages, linterRegistry, destroyListeners, plain, optionalFunctions } from './codemirror';
|
|
32
|
+
export { CodeMirror6 };
|
|
33
|
+
/**
|
|
34
|
+
* 注册通用扩展
|
|
35
|
+
* @param name 扩展名
|
|
36
|
+
* @param ext 扩展
|
|
37
|
+
*/
|
|
38
|
+
const registerExtension = (name, ext) => {
|
|
39
|
+
avail[name] ??= [];
|
|
40
|
+
const addon = avail[name];
|
|
41
|
+
addon[0] = ext;
|
|
42
|
+
};
|
|
43
|
+
/** Register the `highlightSpecialChars` extension */
|
|
44
|
+
export const registerHighlightSpecialChars = () => {
|
|
45
|
+
registerExtension('highlightSpecialChars', highlightSpecialChars);
|
|
46
|
+
};
|
|
47
|
+
/** Register the `highlightActiveLine` extension */
|
|
48
|
+
export const registerHighlightActiveLine = () => {
|
|
49
|
+
registerExtension('highlightActiveLine', highlightActiveLine);
|
|
50
|
+
};
|
|
51
|
+
/** Register the `highlightWhitespace` extension */
|
|
52
|
+
export const registerHighlightWhitespace = () => {
|
|
53
|
+
registerExtension('highlightWhitespace', highlightWhitespace);
|
|
54
|
+
};
|
|
55
|
+
/** Register the `highlightTrailingWhitespace` extension */
|
|
56
|
+
export const registerHighlightTrailingWhitespace = () => {
|
|
57
|
+
registerExtension('highlightTrailingWhitespace', highlightTrailingWhitespace);
|
|
58
|
+
};
|
|
59
|
+
/** Register the `highlightSelectionMatches` extension */
|
|
60
|
+
export const registerHighlightSelectionMatches = () => {
|
|
61
|
+
registerExtension('highlightSelectionMatches', highlightSelectionMatches);
|
|
62
|
+
};
|
|
63
|
+
/** Register the `bracketMatching` extension */
|
|
64
|
+
export const registerBracketMatching = () => {
|
|
65
|
+
registerExtension('bracketMatching', ([config, e = []] = []) => [
|
|
66
|
+
bracketMatching(config),
|
|
67
|
+
e,
|
|
68
|
+
]);
|
|
69
|
+
};
|
|
70
|
+
/** Register the `closeBrackets` extension */
|
|
71
|
+
export const registerCloseBrackets = () => {
|
|
72
|
+
registerExtension('closeBrackets', (e = []) => [closeBrackets(), e]);
|
|
73
|
+
};
|
|
74
|
+
/** Register the `scrollPastEnd` extension */
|
|
75
|
+
export const registerScrollPastEnd = () => {
|
|
76
|
+
registerExtension('scrollPastEnd', scrollPastEnd);
|
|
77
|
+
};
|
|
78
|
+
/** Register the `allowMultipleSelections` extension */
|
|
79
|
+
export const registerAllowMultipleSelections = () => {
|
|
80
|
+
registerExtension('allowMultipleSelections', () => [
|
|
81
|
+
EditorState.allowMultipleSelections.of(true),
|
|
82
|
+
drawSelection(),
|
|
83
|
+
rectangularSelection(),
|
|
84
|
+
crosshairCursor(),
|
|
85
|
+
]);
|
|
86
|
+
};
|
|
87
|
+
/** Register the `autocompletion` extension */
|
|
88
|
+
export const registerAutocompletion = () => {
|
|
89
|
+
registerExtension('autocompletion', () => [
|
|
90
|
+
autocompletion({ defaultKeymap: false }),
|
|
91
|
+
keymap.of([
|
|
92
|
+
...completionKeymap.filter(({ run }) => run !== startCompletion),
|
|
93
|
+
{ key: 'Shift-Enter', run: startCompletion },
|
|
94
|
+
{ key: 'Tab', run: acceptCompletion },
|
|
95
|
+
]),
|
|
96
|
+
]);
|
|
97
|
+
};
|
|
98
|
+
/** Register the `codeFolding` extension */
|
|
99
|
+
export const registerCodeFolding = () => {
|
|
100
|
+
registerExtension('codeFolding', codeFolding);
|
|
101
|
+
};
|
|
102
|
+
/** Register the `colorPicker` extension */
|
|
103
|
+
export const registerColorPicker = () => {
|
|
104
|
+
registerExtension('colorPicker', colorPicker);
|
|
105
|
+
};
|
|
106
|
+
/** 注册所有通用扩展(除`colorPicker`) */
|
|
107
|
+
const registerExtensions = () => {
|
|
108
|
+
highlightSpecialChars();
|
|
109
|
+
registerHighlightActiveLine();
|
|
110
|
+
registerHighlightWhitespace();
|
|
111
|
+
registerHighlightTrailingWhitespace();
|
|
112
|
+
registerHighlightSelectionMatches();
|
|
113
|
+
registerBracketMatching();
|
|
114
|
+
registerCloseBrackets();
|
|
115
|
+
registerScrollPastEnd();
|
|
116
|
+
registerAllowMultipleSelections();
|
|
117
|
+
registerAutocompletion();
|
|
118
|
+
registerCodeFolding();
|
|
119
|
+
};
|
|
120
|
+
/** Register all common extensions */
|
|
121
|
+
export const registerCommonExtensions = () => {
|
|
122
|
+
registerExtensions();
|
|
123
|
+
registerColorPicker();
|
|
124
|
+
};
|
|
125
|
+
function mediawikiOnly(ext) {
|
|
126
|
+
return typeof ext === 'function'
|
|
127
|
+
? [(enable, cm) => enable ? ext(cm) : [], { mediawiki: true }]
|
|
128
|
+
: [(e = []) => e, { mediawiki: ext }];
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* 注册特定语言的扩展
|
|
132
|
+
* @param lang 语言
|
|
133
|
+
* @param name 扩展名
|
|
134
|
+
* @param ext 扩展
|
|
135
|
+
*/
|
|
136
|
+
const registerLangExtension = (lang, name, ext) => {
|
|
137
|
+
avail[name] ??= [() => []];
|
|
138
|
+
const addon = avail[name];
|
|
139
|
+
addon[1] ??= {};
|
|
140
|
+
addon[1][lang] = ext;
|
|
141
|
+
};
|
|
142
|
+
/** Register MediaWiki language support */
|
|
143
|
+
export const registerMediaWiki = () => {
|
|
144
|
+
registerCommonExtensions();
|
|
145
|
+
registerMediaWikiCore();
|
|
146
|
+
registerOpenLinks();
|
|
147
|
+
registerEscape();
|
|
148
|
+
registerRefHover();
|
|
149
|
+
registerHover();
|
|
150
|
+
registerSignatureHelp();
|
|
151
|
+
registerInlayHints();
|
|
152
|
+
registerColorPickerForMediaWiki();
|
|
153
|
+
registerBracketMatchingForMediaWiki();
|
|
154
|
+
registerCodeFoldingForMediaWiki();
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* 注册MediaWiki专用扩展
|
|
158
|
+
* @param name 扩展名
|
|
159
|
+
* @param ext 扩展
|
|
160
|
+
*/
|
|
161
|
+
const registerExtensionForMediaWiki = (name, ext) => {
|
|
162
|
+
avail[name] ??= mediawikiOnly(ext);
|
|
163
|
+
};
|
|
164
|
+
/** Register the `openLinks` extension */
|
|
165
|
+
export const registerOpenLinks = () => {
|
|
166
|
+
registerExtensionForMediaWiki('openLinks', openLinks);
|
|
167
|
+
};
|
|
168
|
+
/** Register the `escape` extension */
|
|
169
|
+
export const registerEscape = () => {
|
|
170
|
+
registerExtensionForMediaWiki('escape', escape);
|
|
171
|
+
};
|
|
172
|
+
/** Register the `refHover` extension */
|
|
173
|
+
export const registerRefHover = () => {
|
|
174
|
+
registerExtensionForMediaWiki('refHover', refHover);
|
|
175
|
+
};
|
|
176
|
+
/** Register the `hover` extension */
|
|
177
|
+
export const registerHover = () => {
|
|
178
|
+
registerExtensionForMediaWiki('hover', magicWordHover);
|
|
179
|
+
};
|
|
180
|
+
/** Register the `signatureHelp` extension */
|
|
181
|
+
export const registerSignatureHelp = () => {
|
|
182
|
+
registerExtensionForMediaWiki('signatureHelp', signatureHelp);
|
|
183
|
+
};
|
|
184
|
+
/** Register the `inlayHints` extension */
|
|
185
|
+
export const registerInlayHints = () => {
|
|
186
|
+
registerExtensionForMediaWiki('inlayHints', inlayHints);
|
|
187
|
+
};
|
|
188
|
+
/** Register the `colorPicker` extension for MediaWiki */
|
|
189
|
+
export const registerColorPickerForMediaWiki = () => {
|
|
190
|
+
registerLangExtension('mediawiki', 'colorPicker', [
|
|
191
|
+
[makeColorPicker({ discoverColors }), colorPickerTheme],
|
|
192
|
+
{ marginLeft: '0.6ch' },
|
|
193
|
+
]);
|
|
194
|
+
};
|
|
195
|
+
/** Register the `bracketMatching` extension for MediaWiki */
|
|
196
|
+
export const registerBracketMatchingForMediaWiki = () => {
|
|
197
|
+
registerLangExtension('mediawiki', 'bracketMatching', [
|
|
198
|
+
{ brackets: '()[]{}()【】[]{}' },
|
|
199
|
+
tagMatchingState,
|
|
200
|
+
]);
|
|
201
|
+
};
|
|
202
|
+
/** Register the `codeFolding` extension for MediaWiki */
|
|
203
|
+
export const registerCodeFoldingForMediaWiki = () => {
|
|
204
|
+
registerLangExtension('mediawiki', 'codeFolding', mediaWikiFold);
|
|
205
|
+
optionalFunctions.foldHandler = foldHandler;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* 注册LintSource
|
|
209
|
+
* @param lang 语言
|
|
210
|
+
* @param lintSource
|
|
211
|
+
*/
|
|
212
|
+
const registerLintSource = (lang, lintSource) => {
|
|
213
|
+
linterRegistry[lang] = lintSource;
|
|
214
|
+
optionalFunctions.statusBar = statusBar;
|
|
215
|
+
};
|
|
216
|
+
/** Register MediaWiki core language support */
|
|
217
|
+
export const registerMediaWikiCore = () => {
|
|
218
|
+
CodeMirror6.getMwConfig = (config) => getStaticMwConfig(config, tagModes);
|
|
219
|
+
languages['mediawiki'] = (config) => [
|
|
220
|
+
mediawiki(config),
|
|
221
|
+
plain(),
|
|
222
|
+
bidiIsolation,
|
|
223
|
+
toolKeymap,
|
|
224
|
+
];
|
|
225
|
+
registerLintSource('mediawiki', getWikiLintSource);
|
|
226
|
+
destroyListeners.push(view => getLSP(view)?.destroy());
|
|
227
|
+
};
|
|
228
|
+
/** Register mixed MediaWiki-HTML language support */
|
|
229
|
+
export const registerHTML = () => {
|
|
230
|
+
registerCommonExtensions();
|
|
231
|
+
registerHTMLCore();
|
|
232
|
+
registerCloseBracketsForHTML();
|
|
233
|
+
registerColorPickerForHTML();
|
|
234
|
+
};
|
|
235
|
+
/** Register the `closeBrackets` extension for mixed MediaWiki-HTML */
|
|
236
|
+
export const registerCloseBracketsForHTML = () => {
|
|
237
|
+
registerLangExtension('html', 'closeBrackets', autoCloseTags);
|
|
238
|
+
};
|
|
239
|
+
/** Register the `colorPicker` extension for mixed MediaWiki-HTML */
|
|
240
|
+
export const registerColorPickerForHTML = () => {
|
|
241
|
+
registerLangExtension('html', 'colorPicker', [cssColorPicker]);
|
|
242
|
+
};
|
|
243
|
+
/** Register mixed MediaWiki-HTML core language support */
|
|
244
|
+
export const registerHTMLCore = () => {
|
|
245
|
+
languages['html'] = html;
|
|
246
|
+
registerLintSource('html', getHTMLLintSource);
|
|
247
|
+
optionalFunctions.detectIndent = detectIndent;
|
|
248
|
+
};
|
|
249
|
+
/** Register JavaScript language support */
|
|
250
|
+
export const registerJavaScript = () => {
|
|
251
|
+
registerExtensions();
|
|
252
|
+
registerJavaScriptCore();
|
|
253
|
+
};
|
|
254
|
+
/** Register JavaScript core language support */
|
|
255
|
+
export const registerJavaScriptCore = () => {
|
|
256
|
+
languages['javascript'] = javascript;
|
|
257
|
+
registerLintSource('javascript', getJsLintSource);
|
|
258
|
+
optionalFunctions.detectIndent = detectIndent;
|
|
259
|
+
};
|
|
260
|
+
/** Register CSS language support */
|
|
261
|
+
export const registerCSS = () => {
|
|
262
|
+
registerCommonExtensions();
|
|
263
|
+
registerCSSCore();
|
|
264
|
+
registerColorPickerForCSS();
|
|
265
|
+
};
|
|
266
|
+
/** Register the `colorPicker` extension for CSS */
|
|
267
|
+
export const registerColorPickerForCSS = () => {
|
|
268
|
+
registerLangExtension('css', 'colorPicker', [cssColorPicker]);
|
|
269
|
+
};
|
|
270
|
+
/** Register CSS core language support */
|
|
271
|
+
export const registerCSSCore = () => {
|
|
272
|
+
languages['css'] = css;
|
|
273
|
+
registerLintSource('css', getCssLintSource);
|
|
274
|
+
optionalFunctions.detectIndent = detectIndent;
|
|
275
|
+
};
|
|
276
|
+
/** Register JSON language support */
|
|
277
|
+
export const registerJSON = () => {
|
|
278
|
+
registerExtensions();
|
|
279
|
+
registerJSONCore();
|
|
280
|
+
};
|
|
281
|
+
/** Register JSON core language support */
|
|
282
|
+
export const registerJSONCore = () => {
|
|
283
|
+
languages['json'] = json;
|
|
284
|
+
registerLintSource('json', getJsonLintSource);
|
|
285
|
+
optionalFunctions.detectIndent = detectIndent;
|
|
286
|
+
};
|
|
287
|
+
/** Register Lua language support */
|
|
288
|
+
export const registerLua = () => {
|
|
289
|
+
registerExtensions();
|
|
290
|
+
registerLuaCore();
|
|
291
|
+
};
|
|
292
|
+
/** Register Lua core language support */
|
|
293
|
+
export const registerLuaCore = () => {
|
|
294
|
+
languages['lua'] = lua;
|
|
295
|
+
registerLintSource('lua', getLuaLintSource);
|
|
296
|
+
optionalFunctions.detectIndent = detectIndent;
|
|
297
|
+
};
|
|
298
|
+
/** Register Vue language support */
|
|
299
|
+
export const registerVue = () => {
|
|
300
|
+
registerCommonExtensions();
|
|
301
|
+
registerVueCore();
|
|
302
|
+
registerCloseBracketsForVue();
|
|
303
|
+
registerColorPickerForVue();
|
|
304
|
+
};
|
|
305
|
+
/** Register the `closeBrackets` extension for Vue */
|
|
306
|
+
export const registerCloseBracketsForVue = () => {
|
|
307
|
+
registerLangExtension('vue', 'closeBrackets', autoCloseTags);
|
|
308
|
+
};
|
|
309
|
+
/** Register the `colorPicker` extension for Vue */
|
|
310
|
+
export const registerColorPickerForVue = () => {
|
|
311
|
+
registerLangExtension('vue', 'colorPicker', [cssColorPicker]);
|
|
312
|
+
};
|
|
313
|
+
/** Register Vue core language support */
|
|
314
|
+
export const registerVueCore = () => {
|
|
315
|
+
languages['vue'] = vue;
|
|
316
|
+
registerLintSource('vue', getVueLintSource);
|
|
317
|
+
optionalFunctions.detectIndent = detectIndent;
|
|
318
|
+
};
|
|
319
|
+
/**
|
|
320
|
+
* Register a custom language support
|
|
321
|
+
* @param name language name
|
|
322
|
+
* @param lang language support
|
|
323
|
+
* @param lintSource optional linter
|
|
324
|
+
*/
|
|
325
|
+
export const registerLanguage = (name, lang, lintSource) => {
|
|
326
|
+
registerCommonExtensions();
|
|
327
|
+
registerLanguageCore(name, lang, lintSource);
|
|
328
|
+
};
|
|
329
|
+
/**
|
|
330
|
+
* Register a custom language support without common extensions
|
|
331
|
+
* @param name language name
|
|
332
|
+
* @param lang language support
|
|
333
|
+
* @param lintSource optional linter
|
|
334
|
+
*/
|
|
335
|
+
export const registerLanguageCore = (name, lang, lintSource) => {
|
|
336
|
+
languages[name] = lang;
|
|
337
|
+
if (lintSource) {
|
|
338
|
+
registerLintSource(name, lintSource);
|
|
339
|
+
}
|
|
340
|
+
};
|
package/dist/linter.js
CHANGED
|
@@ -34,6 +34,11 @@ const indexToPos = (code, index) => {
|
|
|
34
34
|
const lines = code.slice(0, index).split('\n');
|
|
35
35
|
return { line: lines.length - 1, character: lines[lines.length - 1].length };
|
|
36
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* 判断是否为 Stylelint 设置
|
|
39
|
+
* @param config 设置
|
|
40
|
+
*/
|
|
41
|
+
const isStylelintConfig = (config) => Boolean(config && ('extends' in config || 'rules' in config));
|
|
37
42
|
/**
|
|
38
43
|
* 获取 Wikitext LSP
|
|
39
44
|
* @param opt 选项
|
|
@@ -42,16 +47,21 @@ const indexToPos = (code, index) => {
|
|
|
42
47
|
export const getWikiLinter = async (opt, obj) => {
|
|
43
48
|
await getWikiparse(opt?.['getConfig'], opt?.['i18n']);
|
|
44
49
|
const lsp = getLSP(obj, opt?.['include']), cssLint = await getCssLinter();
|
|
45
|
-
|
|
50
|
+
const linter = async (text, config) => {
|
|
46
51
|
const defaultSeverity = config?.['defaultSeverity'] ?? 2, diagnostics = (await lsp.provideDiagnostics(text)).filter(({ code, severity }) => Number(config?.[code] ?? defaultSeverity) > Number(severity === 2)), tokens = 'findStyleTokens' in lsp && config?.['invalid-css'] !== '0' ? await lsp.findStyleTokens() : [];
|
|
47
52
|
if (tokens.length === 0) {
|
|
48
53
|
return diagnostics;
|
|
49
54
|
}
|
|
50
55
|
const lines = tokens.map((token, i) => `${getPrefix(token, i)}${sanitizeInlineStyle(token.childNodes[1].childNodes[0].data)
|
|
51
|
-
.replace(/\n/gu, ' ')}\n}`);
|
|
56
|
+
.replace(/\n/gu, ' ')}\n}`), cssConfig = config?.['css'], isConfig = isStylelintConfig(cssConfig), rules = {};
|
|
57
|
+
for (const [key, value] of Object.entries((isConfig ? cssConfig.rules : cssConfig) ?? {})) {
|
|
58
|
+
if (!value) {
|
|
59
|
+
rules[key] = value;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
52
62
|
return [
|
|
53
63
|
...diagnostics,
|
|
54
|
-
...(await cssLint(lines.join('\n'),
|
|
64
|
+
...(await cssLint(lines.join('\n'), isConfig ? { ...cssConfig, rules } : rules))
|
|
55
65
|
.map(({ line, column, endLine, endColumn, rule, severity, text: message, fix }) => {
|
|
56
66
|
const i = Math.ceil(line / 3), { length } = getPrefix(tokens[i - 1], i), { range } = tokens[i - 1].childNodes[1].childNodes[0], from = offsetAt(range, line - 3 * i, column - 1), diagnostic = {
|
|
57
67
|
from,
|
|
@@ -79,6 +89,10 @@ export const getWikiLinter = async (opt, obj) => {
|
|
|
79
89
|
}),
|
|
80
90
|
];
|
|
81
91
|
};
|
|
92
|
+
if ('resolveCodeAction' in lsp) {
|
|
93
|
+
linter.fixer = async (_, rule) => (await lsp.resolveCodeAction(rule)).edit.changes[''][0].newText;
|
|
94
|
+
}
|
|
95
|
+
return linter;
|
|
82
96
|
};
|
|
83
97
|
export const jsConfig = /* #__PURE__ */ (() => ({
|
|
84
98
|
env: { browser: true, es2024: true, jquery: true },
|
|
@@ -131,9 +145,7 @@ export const getCssLinter = async (cdn = 'npm/@bhsd/stylelint-browserify') => {
|
|
|
131
145
|
await loadScript(cdn, 'stylelint');
|
|
132
146
|
const linter = async (code, opt) => {
|
|
133
147
|
const warnings = await styleLint(stylelint, code, opt);
|
|
134
|
-
|
|
135
|
-
linter.config = opt;
|
|
136
|
-
}
|
|
148
|
+
linter.config = opt && !isStylelintConfig(opt) ? { rules: opt } : opt;
|
|
137
149
|
return warnings;
|
|
138
150
|
};
|
|
139
151
|
linter.fixer = (code, rule) => {
|
package/dist/lintsource.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { EditorView } from '@codemirror/view';
|
|
2
2
|
import type { EditorState, Text } from '@codemirror/state';
|
|
3
|
+
import type { Language } from '@codemirror/language';
|
|
3
4
|
import type { Diagnostic } from '@codemirror/lint';
|
|
4
5
|
import type { Option, LiveOption } from './linter';
|
|
5
6
|
export type LintSource = ((state: EditorState) => Diagnostic[] | Promise<Diagnostic[]>) & {
|
|
6
7
|
fixer?: (doc: Text, rule?: string) => string | Promise<string>;
|
|
7
8
|
};
|
|
8
|
-
export type LintSourceGetter = (opt?: Option | LiveOption, view?: EditorView) => LintSource | Promise<LintSource>;
|
|
9
|
+
export type LintSourceGetter = (opt?: Option | LiveOption, view?: EditorView, nestedMWLanguage?: Language) => LintSource | Promise<LintSource>;
|
|
9
10
|
export declare const getWikiLintSource: LintSourceGetter;
|
|
10
11
|
export declare const getJsLintSource: LintSourceGetter;
|
|
11
12
|
export declare const getCssLintSource: LintSourceGetter;
|
|
12
13
|
export declare const getVueLintSource: LintSourceGetter;
|
|
14
|
+
export declare const getHTMLLintSource: LintSourceGetter;
|
|
13
15
|
export declare const getJsonLintSource: LintSourceGetter;
|
|
14
16
|
export declare const getLuaLintSource: LintSourceGetter;
|
package/dist/lintsource.js
CHANGED
|
@@ -25,29 +25,6 @@ const pos = (doc, line, column, from = 0) => {
|
|
|
25
25
|
character: (line === 1 ? from - lineDesc.from : 0) + column - 1,
|
|
26
26
|
});
|
|
27
27
|
};
|
|
28
|
-
export const getWikiLintSource = async (opt, v) => {
|
|
29
|
-
const wikiLint = await getWikiLinter(await getOpt(opt), v);
|
|
30
|
-
return async ({ doc }) => (await wikiLint(doc.toString(), await getOpt(opt, true)))
|
|
31
|
-
.map(({ severity, code, message, range: r, from, to, data = [], source }) => ({
|
|
32
|
-
source: source,
|
|
33
|
-
from: from ?? posToIndex(doc, r.start),
|
|
34
|
-
to: to ?? posToIndex(doc, r.end),
|
|
35
|
-
severity: severity === 2 ? 'warning' : 'error',
|
|
36
|
-
message: source === 'Stylelint' ? message : `${message} (${code})`,
|
|
37
|
-
actions: data.map(({ title, range, newText }) => ({
|
|
38
|
-
name: title,
|
|
39
|
-
apply(view) {
|
|
40
|
-
view.dispatch({
|
|
41
|
-
changes: {
|
|
42
|
-
from: posToIndex(doc, range.start),
|
|
43
|
-
to: posToIndex(doc, range.end),
|
|
44
|
-
insert: newText,
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
},
|
|
48
|
-
})),
|
|
49
|
-
}));
|
|
50
|
-
};
|
|
51
28
|
const getRange = (doc, line, column, endLine, endColumn, f = 0, t = Infinity) => {
|
|
52
29
|
const start = pos(doc, line, column, f);
|
|
53
30
|
return {
|
|
@@ -55,6 +32,35 @@ const getRange = (doc, line, column, endLine, endColumn, f = 0, t = Infinity) =>
|
|
|
55
32
|
to: endLine === undefined ? Math.min(t, start + 1) : pos(doc, endLine, endColumn, f),
|
|
56
33
|
};
|
|
57
34
|
};
|
|
35
|
+
const wikiLintSource = async (wikiLint, text, opt, doc, f = 0, t) => (await wikiLint(text, opt))
|
|
36
|
+
.map(({ severity, code, message, range: r, from, to, data = [], source }) => ({
|
|
37
|
+
source: source,
|
|
38
|
+
severity: severity === 2 ? 'warning' : 'error',
|
|
39
|
+
message: source === 'Stylelint' ? message : `${message} (${code})`,
|
|
40
|
+
actions: data.map(({ title, range, newText }) => ({
|
|
41
|
+
name: title,
|
|
42
|
+
apply(view) {
|
|
43
|
+
view.dispatch({
|
|
44
|
+
changes: {
|
|
45
|
+
from: posToIndex(doc, range.start),
|
|
46
|
+
to: posToIndex(doc, range.end),
|
|
47
|
+
insert: newText,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
},
|
|
51
|
+
})),
|
|
52
|
+
...from === undefined
|
|
53
|
+
? getRange(doc, r.start.line + 1, r.start.character + 1, r.end.line + 1, r.end.character + 1, f, t)
|
|
54
|
+
: { from: from + f, to: (to ?? from) + f },
|
|
55
|
+
}));
|
|
56
|
+
export const getWikiLintSource = async (opt, v) => {
|
|
57
|
+
const wikiLint = await getWikiLinter(await getOpt(opt), v);
|
|
58
|
+
const lintSource = async ({ doc }) => wikiLintSource(wikiLint, doc.toString(), await getOpt(opt, true), doc);
|
|
59
|
+
if (wikiLint.fixer) {
|
|
60
|
+
lintSource.fixer = (_, rule) => wikiLint.fixer('', rule);
|
|
61
|
+
}
|
|
62
|
+
return lintSource;
|
|
63
|
+
};
|
|
58
64
|
const jsLintSource = (esLint, code, opt, doc, f = 0, t) => esLint(code, opt)
|
|
59
65
|
.map(({ ruleId, message, severity, line, column, endLine, endColumn, fix, suggestions = [] }) => {
|
|
60
66
|
const diagnostic = {
|
|
@@ -76,6 +82,12 @@ const jsLintSource = (esLint, code, opt, doc, f = 0, t) => esLint(code, opt)
|
|
|
76
82
|
}
|
|
77
83
|
return diagnostic;
|
|
78
84
|
});
|
|
85
|
+
export const getJsLintSource = async (opt) => {
|
|
86
|
+
const esLint = await getJsLinter();
|
|
87
|
+
const lintSource = async ({ doc }) => jsLintSource(esLint, doc.toString(), await getOpt(opt), doc);
|
|
88
|
+
lintSource.fixer = (doc, rule) => esLint.fixer(doc.toString(), rule);
|
|
89
|
+
return lintSource;
|
|
90
|
+
};
|
|
79
91
|
const cssLintSource = async (styleLint, code, opt, doc, f = 0, t) => {
|
|
80
92
|
let option = opt ?? {};
|
|
81
93
|
if (!('extends' in option || 'rules' in option)) {
|
|
@@ -104,12 +116,6 @@ const cssLintSource = async (styleLint, code, opt, doc, f = 0, t) => {
|
|
|
104
116
|
return diagnostic;
|
|
105
117
|
});
|
|
106
118
|
};
|
|
107
|
-
export const getJsLintSource = async (opt) => {
|
|
108
|
-
const esLint = await getJsLinter();
|
|
109
|
-
const lintSource = async ({ doc }) => jsLintSource(esLint, doc.toString(), await getOpt(opt), doc);
|
|
110
|
-
lintSource.fixer = (doc, rule) => esLint.fixer(doc.toString(), rule);
|
|
111
|
-
return lintSource;
|
|
112
|
-
};
|
|
113
119
|
export const getCssLintSource = async (opt) => {
|
|
114
120
|
const styleLint = await getCssLinter();
|
|
115
121
|
const lintSource = async ({ doc }) => cssLintSource(styleLint, doc.toString(), await getOpt(opt), doc);
|
|
@@ -128,6 +134,17 @@ export const getVueLintSource = async (opt) => {
|
|
|
128
134
|
];
|
|
129
135
|
};
|
|
130
136
|
};
|
|
137
|
+
export const getHTMLLintSource = async (opt, view, language) => {
|
|
138
|
+
const vueLintSource = await getVueLintSource(opt), wikiLint = await getWikiLinter({ include: false, ...await getOpt(opt) }, view);
|
|
139
|
+
return async (state) => {
|
|
140
|
+
const { doc } = state, option = await getOpt(opt) ?? {}, wiki = option['wiki'];
|
|
141
|
+
return [
|
|
142
|
+
...await vueLintSource(state),
|
|
143
|
+
...(await Promise.all(language.findRegions(state)
|
|
144
|
+
.map(({ from, to }) => wikiLintSource(wikiLint, state.sliceDoc(from, to), wiki, doc, from, to)))).flat(),
|
|
145
|
+
];
|
|
146
|
+
};
|
|
147
|
+
};
|
|
131
148
|
export const getJsonLintSource = () => {
|
|
132
149
|
const jsonLint = getJsonLinter();
|
|
133
150
|
return ({ doc }) => {
|