@bhsd/codemirror-mediawiki 3.12.0 → 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.
package/LICENSE CHANGED
@@ -1,3 +1,22 @@
1
+ @bhsd/codemirror-mediawiki
2
+ Copyright (C) 2022 Bhsd
3
+
4
+ This program is free software; you can redistribute it and/or modify
5
+ it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation; either version 2 of the License, or
7
+ (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License along
15
+ with this program; if not, write to the Free Software Foundation, Inc.,
16
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
+
18
+
19
+
1
20
  GNU GENERAL PUBLIC LICENSE
2
21
  Version 2, June 1991
3
22
 
package/dist/bidi.js CHANGED
@@ -4,10 +4,11 @@
4
4
  * @see https://gerrit.wikimedia.org/g/mediawiki/extensions/CodeMirror
5
5
  */
6
6
  import { EditorView, Direction, ViewPlugin, Decoration } from '@codemirror/view';
7
- import { Prec, RangeSetBuilder } from '@codemirror/state';
7
+ import { Prec } from '@codemirror/state';
8
8
  import { syntaxTree } from '@codemirror/language';
9
9
  import { tokens } from './config.js';
10
10
  import { getTag } from './matchTag.js';
11
+ import { pushDecoration } from './util.js';
11
12
  const isolateSelector = '.cm-bidi-isolate', ltrSelector = '.cm-bidi-ltr', cls = isolateSelector.slice(1), isolateLTR = Decoration.mark({
12
13
  class: `${cls} ${ltrSelector.slice(1)}`,
13
14
  bidiIsolate: Direction.LTR,
@@ -18,7 +19,7 @@ const isolateSelector = '.cm-bidi-isolate', ltrSelector = '.cm-bidi-ltr', cls =
18
19
  * @test
19
20
  */
20
21
  export const computeIsolates = ({ visibleRanges, state, textDirection }) => {
21
- const set = new RangeSetBuilder();
22
+ const set = [];
22
23
  if (textDirection === Direction.RTL) {
23
24
  for (const { from, to } of visibleRanges) {
24
25
  let node = syntaxTree(state).resolve(from, 1), td = 0, table = 0, parameter = 0;
@@ -27,13 +28,13 @@ export const computeIsolates = ({ visibleRanges, state, textDirection }) => {
27
28
  if (/-(?:ext|html)tag-bracket/u.test(name) && state.sliceDoc(f, t).includes('<')) {
28
29
  const tag = getTag(state, nextSibling);
29
30
  if (tag) {
30
- set.add(tag.from, tag.to, isolateLTR);
31
+ pushDecoration(set, isolateLTR, tag);
31
32
  }
32
33
  }
33
34
  else if (!td && !table && name.includes(tokens.tableDefinition)) {
34
35
  if (/-html-(?:table|tr)/u.test(name)) {
35
36
  table = state.doc.lineAt(f).to;
36
- set.add(f, table, isolateLTR);
37
+ pushDecoration(set, isolateLTR, f, table);
37
38
  }
38
39
  else {
39
40
  td = f;
@@ -43,18 +44,18 @@ export const computeIsolates = ({ visibleRanges, state, textDirection }) => {
43
44
  table = 0;
44
45
  }
45
46
  else if (td && name.includes(tokens.tableDelimiter2)) {
46
- set.add(td, f, isolateLTR);
47
+ pushDecoration(set, isolateLTR, td, f);
47
48
  td = 0;
48
49
  }
49
50
  else if (/-(?:template|parserfunction)-delimiter/u.test(name)) {
50
51
  if (parameter) {
51
- set.add(parameter, f, isolate);
52
+ pushDecoration(set, isolate, parameter, f);
52
53
  }
53
54
  parameter = t;
54
55
  }
55
56
  else if (parameter && /-(?:template|parserfunction)-bracket/u.test(name)) {
56
57
  if (state.sliceDoc(f, f + 1) === '}') {
57
- set.add(parameter, f, isolate);
58
+ pushDecoration(set, isolate, parameter, f);
58
59
  }
59
60
  parameter = 0;
60
61
  }
@@ -62,7 +63,7 @@ export const computeIsolates = ({ visibleRanges, state, textDirection }) => {
62
63
  }
63
64
  }
64
65
  }
65
- return set.finish();
66
+ return Decoration.set(set, true);
66
67
  };
67
68
  export default [
68
69
  ViewPlugin.fromClass(class {
@@ -1,3 +1,4 @@
1
- export declare const base: Record<'CDN', string | undefined>, hoverSelector = ".cm-tooltip-hover-mw", diagnosticSelector = ".cm-diagnosticText-clickable", panelSelector = ".cm-panel", panelsSelector = ".cm-panels", actionSelector = ".cm-diagnosticAction", noDetectionLangs: Set<string>, bgDark = "#4c566a", matchingCls = "cm-matchingTag", nonmatchingCls = "cm-nonmatchingTag";
1
+ import { Decoration } from '@codemirror/view';
2
+ export declare const base: Record<'CDN', string | undefined>, hoverSelector = ".cm-tooltip-hover-mw", diagnosticSelector = ".cm-diagnosticText-clickable", panelSelector = ".cm-panel", panelsSelector = ".cm-panels", actionSelector = ".cm-diagnosticAction", doctagMark: Decoration, typeMark: Decoration, noDetectionLangs: Set<string>, bgDark = "#4c566a", matchingCls = "cm-matchingTag", nonmatchingCls = "cm-nonmatchingTag";
2
3
  export declare const isWMF: boolean;
3
4
  export declare const isMac: boolean;
package/dist/constants.js CHANGED
@@ -1,5 +1,6 @@
1
+ import { Decoration } from '@codemirror/view';
1
2
  import { wmf } from '@bhsd/common';
2
- export const base = { CDN: undefined }, hoverSelector = '.cm-tooltip-hover-mw', diagnosticSelector = '.cm-diagnosticText-clickable', panelSelector = '.cm-panel', panelsSelector = '.cm-panels', actionSelector = '.cm-diagnosticAction', noDetectionLangs = new Set(['plain', 'mediawiki']), bgDark = '#4c566a', matchingCls = 'cm-matchingTag', nonmatchingCls = 'cm-nonmatchingTag';
3
+ export const base = { CDN: undefined }, hoverSelector = '.cm-tooltip-hover-mw', diagnosticSelector = '.cm-diagnosticText-clickable', panelSelector = '.cm-panel', panelsSelector = '.cm-panels', actionSelector = '.cm-diagnosticAction', doctagMark = /* @__PURE__ */ Decoration.mark({ class: 'cm-doctag' }), typeMark = /* @__PURE__ */ Decoration.mark({ class: 'cm-doctag-type' }), noDetectionLangs = new Set(['plain', 'mediawiki']), bgDark = '#4c566a', matchingCls = 'cm-matchingTag', nonmatchingCls = 'cm-nonmatchingTag';
3
4
  export const isWMF = /* @__PURE__ */ (() => typeof location === 'object'
4
5
  && new RegExp(String.raw `\.(?:${wmf})\.org$`, 'u').test(location.hostname))();
5
6
  export const isMac = /* @__PURE__ */ (() => {
package/dist/fold.js CHANGED
@@ -337,14 +337,17 @@ export const buildMarkers = (view) => {
337
337
  };
338
338
  const markers = /* @__PURE__ */ ViewPlugin.fromClass(class {
339
339
  constructor(view) {
340
+ this.tree = syntaxTree(view.state);
340
341
  this.markers = buildMarkers(view);
341
342
  }
342
343
  update({ docChanged, viewportChanged, startState, state, view }) {
344
+ const tree = syntaxTree(state);
343
345
  if (docChanged
344
346
  || viewportChanged
345
347
  || startState.facet(language) !== state.facet(language)
346
348
  || startState.field(foldState, false) !== state.field(foldState, false)
347
- || syntaxTree(startState) !== syntaxTree(state)) {
349
+ || tree !== this.tree) {
350
+ this.tree = tree;
348
351
  this.markers = buildMarkers(view);
349
352
  }
350
353
  }
package/dist/html.js CHANGED
@@ -4,7 +4,7 @@ import { javascript, javascriptLanguage } from '@codemirror/lang-javascript';
4
4
  import { cssLanguage } from '@codemirror/lang-css';
5
5
  import { LanguageSupport } from '@codemirror/language';
6
6
  import { cssCompletion } from './css.js';
7
- import { jsCompletion, markGlobalsPlugin } from './javascript.js';
7
+ import { jsCompletion, markGlobalsAndDocTagPlugin } from './javascript.js';
8
8
  import { mediawikiBase } from './mediawiki.js';
9
9
  import { lightHighlightStyle } from './theme.js';
10
10
  export default (config, cm) => {
@@ -31,7 +31,7 @@ export default (config, cm) => {
31
31
  cssCompletion(),
32
32
  support,
33
33
  lightHighlightStyle,
34
- markGlobalsPlugin(cm),
34
+ markGlobalsAndDocTagPlugin(cm),
35
35
  ]);
36
36
  Object.assign(langSupport, { nestedMWLanguage: language });
37
37
  return langSupport;
@@ -12,11 +12,11 @@ export declare const jsCompletion: Extension;
12
12
  */
13
13
  export declare const exclude: (state: EditorState, pos: number) => boolean;
14
14
  /**
15
- * 高亮显示全局变量
15
+ * 高亮显示全局变量和JSDoc标签
16
16
  * @ignore
17
17
  * @test
18
18
  */
19
- export declare const markGlobals: (tree: Tree, visibleRanges: readonly DocRange[], state: EditorState, cm?: CodeMirror6) => DecorationSet;
20
- export declare const markGlobalsPlugin: (cm?: CodeMirror6) => Extension;
19
+ export declare const markGlobalsAndDocTag: (tree: Tree, visibleRanges: readonly DocRange[], state: EditorState, cm?: CodeMirror6) => DecorationSet;
20
+ export declare const markGlobalsAndDocTagPlugin: (cm?: CodeMirror6) => Extension;
21
21
  declare const _default: (_?: unknown, cm?: CodeMirror6) => Extension;
22
22
  export default _default;
@@ -3,6 +3,8 @@ 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
  /**
@@ -14,11 +16,11 @@ const globalsMark = Decoration.mark({ class: 'cm-globals' }), builtinGlobals = n
14
16
  export const exclude = (state, pos) => javascriptLanguage.isActiveAt(state, pos, 0)
15
17
  && syntaxTree(state).resolveInner(pos, 0).name === 'RegExp';
16
18
  /**
17
- * 高亮显示全局变量
19
+ * 高亮显示全局变量和JSDoc标签
18
20
  * @ignore
19
21
  * @test
20
22
  */
21
- export const markGlobals = (tree, visibleRanges, state, cm) => {
23
+ export const markGlobalsAndDocTag = (tree, visibleRanges, state, cm) => {
22
24
  const decorations = [];
23
25
  let allGlobals = builtinGlobals;
24
26
  if (cm?.lintSources.length && typeof eslint === 'object' && 'environments' in eslint) {
@@ -49,10 +51,25 @@ export const markGlobals = (tree, visibleRanges, state, cm) => {
49
51
  to,
50
52
  enter({ type, from: f, to: t }) {
51
53
  const name = state.sliceDoc(f, t);
52
- 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)) {
53
58
  const completions = localCompletionSource({ state, pos: t, explicit: true });
54
59
  if (!completions?.options.some(({ label }) => label === name)) {
55
- 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
+ }
56
73
  }
57
74
  }
58
75
  },
@@ -60,10 +77,10 @@ export const markGlobals = (tree, visibleRanges, state, cm) => {
60
77
  }
61
78
  return Decoration.set(decorations);
62
79
  };
63
- export const markGlobalsPlugin = (cm) => ViewPlugin.fromClass(class {
80
+ export const markGlobalsAndDocTagPlugin = (cm) => ViewPlugin.fromClass(class {
64
81
  constructor({ state, visibleRanges }) {
65
82
  this.tree = syntaxTree(state);
66
- this.decorations = markGlobals(this.tree, visibleRanges, state, cm);
83
+ this.decorations = markGlobalsAndDocTag(this.tree, visibleRanges, state, cm);
67
84
  }
68
85
  update({ docChanged, viewportChanged, state, view: { visibleRanges }, transactions }) {
69
86
  const tree = syntaxTree(state);
@@ -76,7 +93,7 @@ export const markGlobalsPlugin = (cm) => ViewPlugin.fromClass(class {
76
93
  flag = transactions.some(tr => tr.effects.some(e => e.is(setDiagnosticsEffect)));
77
94
  }
78
95
  if (flag) {
79
- this.decorations = markGlobals(tree, visibleRanges, state, cm);
96
+ this.decorations = markGlobalsAndDocTag(tree, visibleRanges, state, cm);
80
97
  }
81
98
  }
82
99
  }, {
@@ -87,5 +104,5 @@ export const markGlobalsPlugin = (cm) => ViewPlugin.fromClass(class {
87
104
  export default (_, cm) => [
88
105
  js(),
89
106
  jsCompletion,
90
- markGlobalsPlugin(cm),
107
+ markGlobalsAndDocTagPlugin(cm),
91
108
  ];
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,9 +1,10 @@
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 { leadingSpaces, sliceDoc, markDocTagType } from './util.js';
7
8
  import { lightHighlightStyle } from './theme.js';
8
9
  const map = {
9
10
  1: 'constant',
@@ -438,10 +439,65 @@ const fold = ({ doc, tabSize }, start, from) => {
438
439
  }
439
440
  return empty || j === number ? null : { from, to: doc.line(j).to };
440
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
+ });
441
496
  const support = [
442
497
  lightHighlightStyle,
443
498
  syntaxHighlighting(HighlightStyle.define([{ tag: tags.standard(tags.variableName), class: 'cm-globals' }])),
444
499
  lang.data.of({ autocomplete: source }),
445
500
  foldService.of(fold),
501
+ markDocTagPlugin,
446
502
  ];
447
503
  export default () => new LanguageSupport(lang, support);