@bhsd/codemirror-mediawiki 2.31.0 → 3.0.1

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/dist/fold.d.ts CHANGED
@@ -1,11 +1,14 @@
1
- import { StateField } from '@codemirror/state';
2
- import type { EditorView, Tooltip, Command } from '@codemirror/view';
3
- import type { EditorState, Extension } from '@codemirror/state';
1
+ import { GutterMarker, ViewPlugin } from '@codemirror/view';
2
+ import { RangeSet } from '@codemirror/state';
3
+ import type { EditorView, Tooltip, ViewUpdate, BlockInfo, Command } from '@codemirror/view';
4
+ import type { EditorState, StateEffect, Extension } from '@codemirror/state';
4
5
  import type { SyntaxNode, Tree } from '@lezer/common';
5
6
  export interface DocRange {
6
7
  from: number;
7
8
  to: number;
8
9
  }
10
+ declare type AnchorUpdate = (pos: number, range: DocRange) => number;
11
+ export declare const updateSelection: AnchorUpdate;
9
12
  /**
10
13
  * Update the stack of opening (+) or closing (-) brackets
11
14
  * @param state
@@ -20,12 +23,56 @@ export declare const braceStackUpdate: (state: EditorState, node: SyntaxNode) =>
20
23
  * @param refOnly 是否仅检查`<ref>`标签
21
24
  */
22
25
  export declare const foldable: (state: EditorState, posOrNode: number | SyntaxNode, tree?: Tree | null, refOnly?: boolean) => DocRange | false;
26
+ /**
27
+ * 创建折叠提示
28
+ * @param state
29
+ */
30
+ export declare const create: (state: EditorState) => Tooltip | null;
31
+ /**
32
+ * 执行折叠
33
+ * @param view
34
+ * @param effects 折叠
35
+ * @param anchor 光标位置
36
+ */
37
+ export declare const execute: (view: EditorView, effects: StateEffect<DocRange>[], anchor: number) => boolean;
38
+ /**
39
+ * The rightmost position of all selections, to be updated with folding
40
+ * @param state
41
+ */
42
+ export declare const getAnchor: (state: EditorState) => number;
43
+ /**
44
+ * 折叠所有模板
45
+ * @param state
46
+ * @param tree 语法树
47
+ * @param effects 折叠
48
+ * @param node 语法树节点
49
+ * @param end 终止位置
50
+ * @param anchor 光标位置
51
+ * @param update 更新光标位置
52
+ * @param refOnly 是否仅检查`<ref>`标签
53
+ */
54
+ export declare const traverse: (state: EditorState, tree: Tree, effects: StateEffect<DocRange>[], node: SyntaxNode | null, end: number, anchor: number, update: AnchorUpdate, refOnly?: boolean) => number;
55
+ export declare class FoldMarker extends GutterMarker {
56
+ readonly open: boolean;
57
+ constructor(open: boolean);
58
+ eq(other: this): boolean;
59
+ toDOM({ state }: EditorView): HTMLSpanElement;
60
+ }
61
+ export declare const findFold: ({ state }: EditorView, line: BlockInfo) => DocRange | undefined;
23
62
  export declare const foldableLine: ({ state, viewport: { to: end }, viewportLineBlocks }: EditorView, { from: f, to: t }: DocRange) => DocRange | false;
63
+ export declare const markers: ViewPlugin<{
64
+ markers: RangeSet<FoldMarker>;
65
+ update({ docChanged, viewportChanged, startState, state, view }: ViewUpdate): void;
66
+ }, undefined>;
67
+ /**
68
+ * 生成折叠命令
69
+ * @param refOnly 是否仅检查`<ref>`标签
70
+ */
71
+ export declare const foldCommand: (refOnly?: boolean) => Command;
24
72
  export declare const foldRef: Command;
25
- declare const _default: [(e?: Extension | undefined) => Extension, {
26
- mediawiki: (Extension | StateField<Tooltip | null>)[];
27
- }];
73
+ declare const _default: [(e?: Extension | undefined) => Extension];
28
74
  export default _default;
75
+ export declare const mediaWikiFold: Extension;
29
76
  /**
30
77
  * 点击提示折叠模板参数
31
78
  * @param view
package/dist/fold.js CHANGED
@@ -4,19 +4,20 @@ import { syntaxTree, ensureSyntaxTree, foldEffect, unfoldEffect, foldedRanges, u
4
4
  import { getRegex } from '@bhsd/common';
5
5
  import { tokens } from './config';
6
6
  import { matchTag, getTag } from './matchTag';
7
- const getExtRegex = getRegex(tag => new RegExp(`mw-tag-${tag}(?![a-z])`, 'u'));
8
- const updateSelection = (pos, { to }) => Math.max(pos, to), updateAll = (pos, { from, to }) => from <= pos && to > pos ? to : pos;
7
+ const getExtRegex = /* @__PURE__ */ getRegex(tag => new RegExp(`mw-tag-${tag}(?![a-z])`, 'u'));
8
+ export const updateSelection = (pos, { to }) => Math.max(pos, to);
9
+ const updateAll = (pos, { from, to }) => from <= pos && to > pos ? to : pos;
9
10
  /**
10
11
  * Check if a SyntaxNode is among the specified components
11
12
  * @param keys The keys of the tokens to check
12
13
  */
13
14
  const isComponent = (keys) => (node) => keys.some(key => node?.name.includes(tokens[key])),
14
15
  /** Check if a SyntaxNode is a template bracket (`{{` or `}}`) */
15
- isTemplateBracket = isComponent(['templateBracket', 'parserFunctionBracket']),
16
+ isTemplateBracket = /* @__PURE__ */ isComponent(['templateBracket', 'parserFunctionBracket']),
16
17
  /** Check if a SyntaxNode is a template name */
17
- isTemplateName = isComponent(['templateName', 'parserFunctionName']),
18
+ isTemplateName = /* @__PURE__ */ isComponent(['templateName', 'parserFunctionName']),
18
19
  /** Check if a SyntaxNode is a template delimiter (`|` or `:`) */
19
- isDelimiter = isComponent(['templateDelimiter', 'parserFunctionDelimiter']),
20
+ isDelimiter = /* @__PURE__ */ isComponent(['templateDelimiter', 'parserFunctionDelimiter']),
20
21
  /**
21
22
  * Check if a SyntaxNode is a template delimiter (`|` or `:`), excluding `subst:` and `safesubst:`
22
23
  * @param node SyntaxNode
@@ -28,7 +29,7 @@ isTemplateDelimiter = (node) => isDelimiter(node) && !isTemplateName(node.nextSi
28
29
  */
29
30
  isTemplate = (node) => /-(?:template|ext)[a-z\d-]+ground/u.test(node.name) && !isTemplateBracket(node),
30
31
  /** Check if a SyntaxNode is an extension tag bracket (`<` or `>`) */
31
- isExtBracket = isComponent(['extTagBracket']),
32
+ isExtBracket = /* @__PURE__ */ isComponent(['extTagBracket']),
32
33
  /**
33
34
  * Check if a SyntaxNode is part of a extension tag
34
35
  * @param node 语法树节点
@@ -144,7 +145,7 @@ export const foldable = (state, posOrNode, tree, refOnly = false) => {
144
145
  * 创建折叠提示
145
146
  * @param state
146
147
  */
147
- const create = (state) => {
148
+ export const create = (state) => {
148
149
  const { selection: { main: { head } } } = state, range = foldable(state, head);
149
150
  if (range) {
150
151
  const { from, to } = range;
@@ -178,7 +179,7 @@ const create = (state) => {
178
179
  * @param effects 折叠
179
180
  * @param anchor 光标位置
180
181
  */
181
- const execute = (view, effects, anchor) => {
182
+ export const execute = (view, effects, anchor) => {
182
183
  if (effects.length > 0) {
183
184
  view.dom.querySelector('.cm-tooltip-fold')?.remove();
184
185
  // Fold the template(s) and update the cursor position
@@ -191,7 +192,7 @@ const execute = (view, effects, anchor) => {
191
192
  * The rightmost position of all selections, to be updated with folding
192
193
  * @param state
193
194
  */
194
- const getAnchor = (state) => Math.max(...state.selection.ranges.map(({ to }) => to));
195
+ export const getAnchor = (state) => Math.max(...state.selection.ranges.map(({ to }) => to));
195
196
  /**
196
197
  * 折叠所有模板
197
198
  * @param state
@@ -203,7 +204,7 @@ const getAnchor = (state) => Math.max(...state.selection.ranges.map(({ to }) =>
203
204
  * @param update 更新光标位置
204
205
  * @param refOnly 是否仅检查`<ref>`标签
205
206
  */
206
- const traverse = (state, tree, effects, node, end, anchor, update, refOnly) => {
207
+ export const traverse = (state, tree, effects, node, end, anchor, update, refOnly) => {
207
208
  while (node && node.from <= end) {
208
209
  /* eslint-disable no-param-reassign */
209
210
  const range = foldable(state, node, tree, refOnly);
@@ -219,7 +220,7 @@ const traverse = (state, tree, effects, node, end, anchor, update, refOnly) => {
219
220
  }
220
221
  return anchor;
221
222
  };
222
- class FoldMarker extends GutterMarker {
223
+ export class FoldMarker extends GutterMarker {
223
224
  constructor(open) {
224
225
  super();
225
226
  this.open = open;
@@ -234,8 +235,8 @@ class FoldMarker extends GutterMarker {
234
235
  return span;
235
236
  }
236
237
  }
237
- const canFold = new FoldMarker(true), canUnfold = new FoldMarker(false);
238
- const findFold = ({ state }, line) => {
238
+ const canFold = /* @__PURE__ */ new FoldMarker(true), canUnfold = /* @__PURE__ */ new FoldMarker(false);
239
+ export const findFold = ({ state }, line) => {
239
240
  let found;
240
241
  state.field(foldState, false)?.between(line.from, line.to, (from, to) => {
241
242
  if (!found && to === line.to) {
@@ -309,7 +310,7 @@ const buildMarkers = (view) => {
309
310
  }
310
311
  return builder.finish();
311
312
  };
312
- const markers = ViewPlugin.fromClass(class {
313
+ export const markers = /* @__PURE__ */ ViewPlugin.fromClass(class {
313
314
  constructor(view) {
314
315
  this.markers = buildMarkers(view);
315
316
  }
@@ -328,129 +329,125 @@ const defaultFoldExtension = [foldGutter(), keymap.of(foldKeymap)];
328
329
  * 生成折叠命令
329
330
  * @param refOnly 是否仅检查`<ref>`标签
330
331
  */
331
- const foldCommand = (refOnly) => view => {
332
+ export const foldCommand = (refOnly) => view => {
332
333
  const { state } = view, tree = syntaxTree(state), effects = [], anchor = traverse(state, tree, effects, tree.topNode.firstChild, Infinity, getAnchor(state), updateAll, refOnly);
333
334
  return execute(view, effects, anchor);
334
335
  };
335
- export const foldRef = foldCommand(true);
336
- export default [
337
- (e = defaultFoldExtension) => e,
338
- {
339
- mediawiki: [
340
- codeFolding({
341
- placeholderDOM(view) {
342
- const element = document.createElement('span');
343
- element.textContent = '';
344
- element.setAttribute('aria-label', 'folded code');
345
- element.title = view.state.phrase('unfold');
346
- element.className = 'cm-foldPlaceholder';
347
- element.addEventListener('click', ({ target }) => {
348
- const pos = view.posAtDOM(target), { state } = view, { selection } = state;
349
- foldedRanges(state).between(pos, pos, (from, to) => {
350
- if (from === pos) {
351
- // Unfold the template and redraw the selections
352
- view.dispatch({ effects: unfoldEffect.of({ from, to }), selection });
353
- }
354
- });
355
- });
356
- return element;
357
- },
358
- }),
359
- /** @see https://codemirror.net/examples/tooltip/ */
360
- StateField.define({
361
- create,
362
- update(tooltip, { state, docChanged, selection }) {
363
- if (docChanged) {
364
- return null;
336
+ export const foldRef = /* @__PURE__ */ foldCommand(true);
337
+ export default [(e = defaultFoldExtension) => e];
338
+ export const mediaWikiFold = /* @__PURE__ */ (() => [
339
+ codeFolding({
340
+ placeholderDOM(view) {
341
+ const element = document.createElement('span');
342
+ element.textContent = '…';
343
+ element.setAttribute('aria-label', 'folded code');
344
+ element.title = view.state.phrase('unfold');
345
+ element.className = 'cm-foldPlaceholder';
346
+ element.addEventListener('click', ({ target }) => {
347
+ const pos = view.posAtDOM(target), { state } = view, { selection } = state;
348
+ foldedRanges(state).between(pos, pos, (from, to) => {
349
+ if (from === pos) {
350
+ // Unfold the template and redraw the selections
351
+ view.dispatch({ effects: unfoldEffect.of({ from, to }), selection });
365
352
  }
366
- return selection ? create(state) : tooltip;
367
- },
368
- provide(f) {
369
- return showTooltip.from(f);
370
- },
371
- }),
372
- keymap.of([
373
- {
374
- // Fold the template at the selection/cursor
375
- key: 'Ctrl-Shift-[',
376
- mac: 'Cmd-Alt-[',
377
- run(view) {
378
- const { state } = view, tree = syntaxTree(state), effects = [];
379
- let anchor = getAnchor(state);
380
- for (const { from, to, empty } of state.selection.ranges) {
381
- let node;
382
- if (empty) {
383
- // No selection, try both sides of the cursor position
384
- node = tree.resolve(from, -1);
385
- }
386
- if (!node || node.name === 'Document') {
387
- node = tree.resolve(from, 1);
388
- }
389
- anchor = traverse(state, tree, effects, node, to, anchor, updateSelection);
390
- }
391
- return execute(view, effects, anchor);
392
- },
393
- },
394
- {
395
- // Fold all templates in the document
396
- key: 'Ctrl-Alt-[',
397
- run: foldCommand(),
398
- },
399
- {
400
- // Fold all `<ref>` tags in the document
401
- key: 'Mod-Alt-,',
402
- run: foldRef,
403
- },
404
- {
405
- // Unfold the template at the selection/cursor
406
- key: 'Ctrl-Shift-]',
407
- mac: 'Cmd-Alt-]',
408
- run(view) {
409
- const { state } = view, { selection } = state, effects = [], folded = foldedRanges(state);
410
- for (const { from, to } of selection.ranges) {
411
- // Unfold any folded range at the selection
412
- folded.between(from, to, (i, j) => {
413
- effects.push(unfoldEffect.of({ from: i, to: j }));
414
- });
415
- }
416
- if (effects.length > 0) {
417
- // Unfold the template(s) and redraw the selections
418
- view.dispatch({ effects, selection });
419
- return true;
420
- }
421
- return false;
422
- },
423
- },
424
- { key: 'Ctrl-Alt-]', run: unfoldAll },
425
- ]),
426
- markers,
427
- gutter({
428
- class: 'cm-foldGutter',
429
- markers(view) {
430
- return view.plugin(markers)?.markers ?? RangeSet.empty;
431
- },
432
- initialSpacer() {
433
- return new FoldMarker(false);
434
- },
435
- domEventHandlers: {
436
- click(view, line) {
437
- const folded = findFold(view, line);
438
- if (folded) {
439
- view.dispatch({ effects: unfoldEffect.of(folded) });
440
- return true;
441
- }
442
- const range = foldableLine(view, line);
443
- if (range) {
444
- view.dispatch({ effects: foldEffect.of(range) });
445
- return true;
446
- }
447
- return false;
448
- },
449
- },
450
- }),
451
- ],
452
- },
453
- ];
353
+ });
354
+ });
355
+ return element;
356
+ },
357
+ }),
358
+ /** @see https://codemirror.net/examples/tooltip/ */
359
+ StateField.define({
360
+ create,
361
+ update(tooltip, { state, docChanged, selection }) {
362
+ if (docChanged) {
363
+ return null;
364
+ }
365
+ return selection ? create(state) : tooltip;
366
+ },
367
+ provide(f) {
368
+ return showTooltip.from(f);
369
+ },
370
+ }),
371
+ keymap.of([
372
+ {
373
+ // Fold the template at the selection/cursor
374
+ key: 'Ctrl-Shift-[',
375
+ mac: 'Cmd-Alt-[',
376
+ run(view) {
377
+ const { state } = view, tree = syntaxTree(state), effects = [];
378
+ let anchor = getAnchor(state);
379
+ for (const { from, to, empty } of state.selection.ranges) {
380
+ let node;
381
+ if (empty) {
382
+ // No selection, try both sides of the cursor position
383
+ node = tree.resolve(from, -1);
384
+ }
385
+ if (!node || node.name === 'Document') {
386
+ node = tree.resolve(from, 1);
387
+ }
388
+ anchor = traverse(state, tree, effects, node, to, anchor, updateSelection);
389
+ }
390
+ return execute(view, effects, anchor);
391
+ },
392
+ },
393
+ {
394
+ // Fold all templates in the document
395
+ key: 'Ctrl-Alt-[',
396
+ run: foldCommand(),
397
+ },
398
+ {
399
+ // Fold all `<ref>` tags in the document
400
+ key: 'Mod-Alt-,',
401
+ run: foldRef,
402
+ },
403
+ {
404
+ // Unfold the template at the selection/cursor
405
+ key: 'Ctrl-Shift-]',
406
+ mac: 'Cmd-Alt-]',
407
+ run(view) {
408
+ const { state } = view, { selection } = state, effects = [], folded = foldedRanges(state);
409
+ for (const { from, to } of selection.ranges) {
410
+ // Unfold any folded range at the selection
411
+ folded.between(from, to, (i, j) => {
412
+ effects.push(unfoldEffect.of({ from: i, to: j }));
413
+ });
414
+ }
415
+ if (effects.length > 0) {
416
+ // Unfold the template(s) and redraw the selections
417
+ view.dispatch({ effects, selection });
418
+ return true;
419
+ }
420
+ return false;
421
+ },
422
+ },
423
+ { key: 'Ctrl-Alt-]', run: unfoldAll },
424
+ ]),
425
+ markers,
426
+ gutter({
427
+ class: 'cm-foldGutter',
428
+ markers(view) {
429
+ return view.plugin(markers)?.markers ?? RangeSet.empty;
430
+ },
431
+ initialSpacer() {
432
+ return new FoldMarker(false);
433
+ },
434
+ domEventHandlers: {
435
+ click(view, line) {
436
+ const folded = findFold(view, line);
437
+ if (folded) {
438
+ view.dispatch({ effects: unfoldEffect.of(folded) });
439
+ return true;
440
+ }
441
+ const range = foldableLine(view, line);
442
+ if (range) {
443
+ view.dispatch({ effects: foldEffect.of(range) });
444
+ return true;
445
+ }
446
+ return false;
447
+ },
448
+ },
449
+ }),
450
+ ])();
454
451
  /**
455
452
  * 点击提示折叠模板参数
456
453
  * @param view
package/dist/indent.d.ts CHANGED
@@ -1,4 +1,8 @@
1
- import type { Text } from '@codemirror/state';
1
+ import type { Text as TextBase } from '@codemirror/state';
2
+ export interface Text extends TextBase {
3
+ children: readonly Text[] | null;
4
+ text?: string[];
5
+ }
2
6
  /**
3
7
  * 检测文本的缩进方式
4
8
  * @param text 文本内容
package/dist/indent.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const noDetectionLangs = new Set(['plain', 'mediawiki', 'html']);
2
+ const getLines = (text) => text.children?.flatMap(getLines) ?? text.text;
2
3
  /**
3
4
  * 检测文本的缩进方式
4
5
  * @param text 文本内容
@@ -9,7 +10,7 @@ export const detectIndent = (text, defaultIndent, lang) => {
9
10
  if (noDetectionLangs.has(lang)) {
10
11
  return defaultIndent;
11
12
  }
12
- const lineSpaces = [], lines = typeof text === 'string' ? text.split('\n') : text.text;
13
+ const lineSpaces = [], lines = typeof text === 'string' ? text.split('\n') : getLines(text);
13
14
  let tabLines = 0;
14
15
  for (const line of lines) {
15
16
  if (!line.trim()) {
@@ -1,3 +1,4 @@
1
1
  import type { Extension } from '@codemirror/state';
2
+ export declare const jsCompletion: Extension;
2
3
  declare const _default: () => Extension;
3
4
  export default _default;
@@ -1,5 +1,3 @@
1
1
  import { javascript as js, javascriptLanguage, scopeCompletionSource } from '@codemirror/lang-javascript';
2
- export default () => [
3
- js(),
4
- javascriptLanguage.data.of({ autocomplete: scopeCompletionSource(globalThis) }),
5
- ];
2
+ export const jsCompletion = javascriptLanguage.data.of({ autocomplete: scopeCompletionSource(globalThis) });
3
+ export default () => [js(), jsCompletion];
@@ -2,6 +2,7 @@ export const keybindings = [
2
2
  { key: 'Ctrl-8', pre: '<blockquote>', post: '</blockquote>', desc: 'blockquote' },
3
3
  { key: 'Mod-.', pre: '<sup>', post: '</sup>', desc: 'sup' },
4
4
  { key: 'Mod-,', pre: '<sub>', post: '</sub>', desc: 'sub' },
5
+ { key: 'Ctrl-,', pre: '<sub>', post: '</sub>', desc: 'sub' },
5
6
  { key: 'Mod-Shift-6', pre: '<code>', post: '</code>', desc: 'code' },
6
7
  { key: 'Ctrl-Shift-5', pre: '<s>', post: '</s>', desc: 's' },
7
8
  { key: 'Mod-u', pre: '<u>', post: '</u>', desc: 'u' },
package/dist/linter.js CHANGED
@@ -5,14 +5,34 @@ import { styleLint } from '@bhsd/stylelint-util';
5
5
  /**
6
6
  * 计算位置
7
7
  * @param range 范围
8
- * @param line 行号
9
- * @param column 列号
8
+ * @param lineOrOffset 行号或相对位置
9
+ * @param columnOrPrefix 列号或前缀
10
10
  */
11
- const offsetAt = (range, line, column) => {
12
- if (line === -2) {
11
+ const offsetAt = (range, lineOrOffset, columnOrPrefix) => {
12
+ if (typeof columnOrPrefix === 'string') {
13
+ return Math.min(range[1], range[0] + Math.max(0, lineOrOffset - columnOrPrefix.length));
14
+ }
15
+ else if (lineOrOffset === -2) {
13
16
  return range[0];
14
17
  }
15
- return line === 0 ? range[1] : range[0] + column;
18
+ return lineOrOffset === 0 ? range[1] : range[0] + columnOrPrefix;
19
+ };
20
+ /**
21
+ * 获取伪CSS代码块的前缀
22
+ * @param token AST 节点
23
+ * @param token.type 节点类型
24
+ * @param token.tag 节点标签
25
+ * @param i 节点序号
26
+ */
27
+ const getPrefix = ({ type, tag }, i) => `${type === 'ext-attr' ? 'div' : tag}#${i}{\n`;
28
+ /**
29
+ * 将偏移量转换为位置
30
+ * @param code 代码字符串
31
+ * @param index 偏移量
32
+ */
33
+ const indexToPos = (code, index) => {
34
+ const lines = code.slice(0, index).split('\n');
35
+ return { line: lines.length - 1, character: lines[lines.length - 1].length };
16
36
  };
17
37
  /**
18
38
  * 获取 Wikitext LSP
@@ -30,9 +50,9 @@ export const getWikiLinter = async (opt, obj) => {
30
50
  const cssLint = await getCssLinter();
31
51
  return [
32
52
  ...diagnostics,
33
- ...(await cssLint(tokens.map(({ childNodes, type, tag }, i) => `${type === 'ext-attr' ? 'div' : tag}#${i}{\n${sanitizeInlineStyle(childNodes[1].childNodes[0].data)
34
- .replace(/\n/gu, ' ')}\n}`).join('\n'), config?.['css'])).map(({ line, column, endLine, endColumn, rule, severity, text: message }) => {
35
- const i = Math.ceil(line / 3), { range } = tokens[i - 1].childNodes[1].childNodes[0], from = offsetAt(range, line - 3 * i, column - 1);
53
+ ...(await cssLint(tokens.map((token, i) => `${getPrefix(token, i)}${sanitizeInlineStyle(token.childNodes[1].childNodes[0].data)
54
+ .replace(/\n/gu, ' ')}\n}`).join('\n'), config?.['css'])).map(({ line, column, endLine, endColumn, rule, severity, text: message, fix }) => {
55
+ const i = Math.ceil(line / 3), prefix = getPrefix(tokens[i - 1], i), { range } = tokens[i - 1].childNodes[1].childNodes[0], from = offsetAt(range, line - 3 * i, column - 1);
36
56
  return {
37
57
  from,
38
58
  to: endLine === undefined ? from : offsetAt(range, endLine - 3 * i, endColumn - 1),
@@ -40,6 +60,21 @@ export const getWikiLinter = async (opt, obj) => {
40
60
  source: 'Stylelint',
41
61
  code: rule,
42
62
  message,
63
+ ...fix
64
+ ? {
65
+ data: [
66
+ {
67
+ range: {
68
+ start: indexToPos(text, offsetAt(range, fix.range[0], prefix)),
69
+ end: indexToPos(text, offsetAt(range, fix.range[1], prefix)),
70
+ },
71
+ newText: fix.text,
72
+ title: 'Fix: Stylelint',
73
+ fix: true,
74
+ },
75
+ ],
76
+ }
77
+ : {},
43
78
  };
44
79
  }),
45
80
  ];
@@ -0,0 +1,14 @@
1
+ import type { EditorView } from '@codemirror/view';
2
+ import type { EditorState, Text } from '@codemirror/state';
3
+ import type { Diagnostic } from '@codemirror/lint';
4
+ import type { Option, LiveOption } from './linter';
5
+ export type LintSource = ((state: EditorState) => Diagnostic[] | Promise<Diagnostic[]>) & {
6
+ fixer?: (doc: Text, rule?: string) => string | Promise<string>;
7
+ };
8
+ export type LintSourceGetter = (opt?: Option | LiveOption, view?: EditorView) => LintSource | Promise<LintSource>;
9
+ export declare const getWikiLintSource: LintSourceGetter;
10
+ export declare const getJsLintSource: LintSourceGetter;
11
+ export declare const getCssLintSource: LintSourceGetter;
12
+ export declare const getVueLintSource: LintSourceGetter;
13
+ export declare const getJsonLintSource: LintSourceGetter;
14
+ export declare const getLuaLintSource: LintSourceGetter;