@bhsd/codemirror-mediawiki 3.11.5 → 3.12.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.
@@ -3,14 +3,24 @@ import { ViewPlugin, Decoration } from '@codemirror/view';
3
3
  import { syntaxTree } from '@codemirror/language';
4
4
  import { setDiagnosticsEffect } from '@codemirror/lint';
5
5
  import { builtin } from './javascript-globals.js';
6
+ import { doctagMark } from './constants.js';
7
+ import { markDocTagType, pushDecoration } from './util.js';
6
8
  export const jsCompletion = javascriptLanguage.data.of({ autocomplete: scopeCompletionSource(globalThis) });
7
9
  const globalsMark = Decoration.mark({ class: 'cm-globals' }), builtinGlobals = new Set(Object.keys(builtin));
8
10
  /**
9
- * 高亮显示全局变量
11
+ * 忽略JavaScript正则表达式中的括号匹配
12
+ * @param state
13
+ * @param pos 位置
14
+ * @test
15
+ */
16
+ export const exclude = (state, pos) => javascriptLanguage.isActiveAt(state, pos, 0)
17
+ && syntaxTree(state).resolveInner(pos, 0).name === 'RegExp';
18
+ /**
19
+ * 高亮显示全局变量和JSDoc标签
10
20
  * @ignore
11
21
  * @test
12
22
  */
13
- export const markGlobals = (tree, visibleRanges, state, cm) => {
23
+ export const markGlobalsAndDocTag = (tree, visibleRanges, state, cm) => {
14
24
  const decorations = [];
15
25
  let allGlobals = builtinGlobals;
16
26
  if (cm?.lintSources.length && typeof eslint === 'object' && 'environments' in eslint) {
@@ -41,10 +51,25 @@ export const markGlobals = (tree, visibleRanges, state, cm) => {
41
51
  to,
42
52
  enter({ type, from: f, to: t }) {
43
53
  const name = state.sliceDoc(f, t);
44
- if (type.is('VariableName') && javascriptLanguage.isActiveAt(state, f) && allGlobals.has(name)) {
54
+ if (!javascriptLanguage.isActiveAt(state, f)) {
55
+ //
56
+ }
57
+ else if (type.is('VariableName') && allGlobals.has(name)) {
45
58
  const completions = localCompletionSource({ state, pos: t, explicit: true });
46
59
  if (!completions?.options.some(({ label }) => label === name)) {
47
- decorations.push(globalsMark.range(f, t));
60
+ pushDecoration(decorations, globalsMark, f, t);
61
+ }
62
+ }
63
+ else if (type.is('BlockComment') && /^\/\*{2}(?!\*)/u.test(name)) {
64
+ const comment = name.slice(2), mtAll = comment.matchAll(/^[ \t]*\*\s*(@[a-z]+)(\s+\{(?!\}))?|\{(@[a-z]+)/dgimu);
65
+ for (const mt of mtAll) {
66
+ if (mt[3]) {
67
+ const [start, end] = mt.indices[3];
68
+ pushDecoration(decorations, doctagMark, f + start + 2, f + end + 2);
69
+ }
70
+ else {
71
+ markDocTagType(decorations, f + 2, mt);
72
+ }
48
73
  }
49
74
  }
50
75
  },
@@ -52,10 +77,10 @@ export const markGlobals = (tree, visibleRanges, state, cm) => {
52
77
  }
53
78
  return Decoration.set(decorations);
54
79
  };
55
- export const markGlobalsPlugin = (cm) => ViewPlugin.fromClass(class {
80
+ export const markGlobalsAndDocTagPlugin = (cm) => ViewPlugin.fromClass(class {
56
81
  constructor({ state, visibleRanges }) {
57
82
  this.tree = syntaxTree(state);
58
- this.decorations = markGlobals(this.tree, visibleRanges, state, cm);
83
+ this.decorations = markGlobalsAndDocTag(this.tree, visibleRanges, state, cm);
59
84
  }
60
85
  update({ docChanged, viewportChanged, state, view: { visibleRanges }, transactions }) {
61
86
  const tree = syntaxTree(state);
@@ -68,7 +93,7 @@ export const markGlobalsPlugin = (cm) => ViewPlugin.fromClass(class {
68
93
  flag = transactions.some(tr => tr.effects.some(e => e.is(setDiagnosticsEffect)));
69
94
  }
70
95
  if (flag) {
71
- this.decorations = markGlobals(tree, visibleRanges, state, cm);
96
+ this.decorations = markGlobalsAndDocTag(tree, visibleRanges, state, cm);
72
97
  }
73
98
  }
74
99
  }, {
@@ -79,5 +104,5 @@ export const markGlobalsPlugin = (cm) => ViewPlugin.fromClass(class {
79
104
  export default (_, cm) => [
80
105
  js(),
81
106
  jsCompletion,
82
- markGlobalsPlugin(cm),
107
+ markGlobalsAndDocTagPlugin(cm),
83
108
  ];
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 = {
package/dist/lua.d.ts CHANGED
@@ -1,3 +1,19 @@
1
+ import { ViewPlugin } from '@codemirror/view';
1
2
  import { LanguageSupport } from '@codemirror/language';
3
+ import type { ViewUpdate, DecorationSet } from '@codemirror/view';
4
+ import type { EditorState } from '@codemirror/state';
5
+ import type { Tree } from '@lezer/common';
6
+ import type { DocRange } from './fold';
7
+ /**
8
+ * 高亮显示LDoc标签
9
+ * @ignore
10
+ * @test
11
+ */
12
+ export declare const markDocTag: (tree: Tree, visibleRanges: readonly DocRange[], state: EditorState) => DecorationSet;
13
+ export declare const markDocTagPlugin: ViewPlugin<{
14
+ tree: Tree;
15
+ decorations: DecorationSet;
16
+ update({ docChanged, viewportChanged, state, view: { visibleRanges } }: ViewUpdate): void;
17
+ }, undefined>;
2
18
  declare const _default: () => LanguageSupport;
3
19
  export default _default;
package/dist/lua.js CHANGED
@@ -1,10 +1,11 @@
1
1
  /* eslint-disable no-template-curly-in-string */
2
2
  import { lua } from '@codemirror/legacy-modes/mode/lua';
3
+ import { ViewPlugin, Decoration } from '@codemirror/view';
3
4
  import { syntaxTree, LanguageSupport, StreamLanguage, foldService, HighlightStyle, syntaxHighlighting, } from '@codemirror/language';
4
5
  import { snippetCompletion } from '@codemirror/autocomplete';
5
6
  import { tags } from '@lezer/highlight';
6
- import { leadingSpaces, sliceDoc } from './util.js';
7
- import { getLightHighlightStyle } from './theme.js';
7
+ import { leadingSpaces, sliceDoc, markDocTagType } from './util.js';
8
+ import { lightHighlightStyle } from './theme.js';
8
9
  const map = {
9
10
  1: 'constant',
10
11
  2: 'function',
@@ -130,6 +131,7 @@ const map = {
130
131
  server: 1,
131
132
  siteName: 1,
132
133
  stylePath: 1,
134
+ wikiId: 1,
133
135
  namespaces: 3,
134
136
  contentNamespaces: 3,
135
137
  subjectNamespaces: 3,
@@ -437,10 +439,65 @@ const fold = ({ doc, tabSize }, start, from) => {
437
439
  }
438
440
  return empty || j === number ? null : { from, to: doc.line(j).to };
439
441
  };
442
+ /**
443
+ * 高亮显示LDoc标签
444
+ * @ignore
445
+ * @test
446
+ */
447
+ export const markDocTag = (tree, visibleRanges, state) => {
448
+ const decorations = [];
449
+ for (const { from, to } of visibleRanges) {
450
+ let node = tree.resolveInner(from, 1);
451
+ while (node && node.from < to) {
452
+ if (node.name === 'comment') {
453
+ const firstLine = sliceDoc(state, node), block = firstLine.startsWith('--[[--');
454
+ if (block
455
+ || firstLine.startsWith('---')
456
+ && !(firstLine.endsWith('--') && /[^-]/u.test(firstLine))) {
457
+ while (node.name === 'comment') {
458
+ const comment = sliceDoc(state, node), mt = /^\s*(?:-{2,}\s*)?(@[a-z]+)(\s+\{(?!\}))?/diu.exec(comment);
459
+ if (mt) {
460
+ markDocTagType(decorations, node.from, mt);
461
+ }
462
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
463
+ const { nextSibling } = node;
464
+ if (!nextSibling || (block
465
+ ? comment.endsWith(']]')
466
+ : state.sliceDoc(node.to, nextSibling.from)
467
+ .split('\n', 3).length > 2)) {
468
+ break;
469
+ }
470
+ node = nextSibling;
471
+ }
472
+ }
473
+ }
474
+ node = node.nextSibling;
475
+ }
476
+ }
477
+ return Decoration.set(decorations);
478
+ };
479
+ export const markDocTagPlugin = ViewPlugin.fromClass(class {
480
+ constructor({ state, visibleRanges }) {
481
+ this.tree = syntaxTree(state);
482
+ this.decorations = markDocTag(this.tree, visibleRanges, state);
483
+ }
484
+ update({ docChanged, viewportChanged, state, view: { visibleRanges } }) {
485
+ const tree = syntaxTree(state);
486
+ if (docChanged || viewportChanged || tree !== this.tree) {
487
+ this.tree = tree;
488
+ this.decorations = markDocTag(tree, visibleRanges, state);
489
+ }
490
+ }
491
+ }, {
492
+ decorations(v) {
493
+ return v.decorations;
494
+ },
495
+ });
440
496
  const support = [
441
- getLightHighlightStyle(),
497
+ lightHighlightStyle,
442
498
  syntaxHighlighting(HighlightStyle.define([{ tag: tags.standard(tags.variableName), class: 'cm-globals' }])),
443
499
  lang.data.of({ autocomplete: source }),
444
500
  foldService.of(fold),
501
+ markDocTagPlugin,
445
502
  ];
446
503
  export default () => new LanguageSupport(lang, support);