@bhsd/codemirror-mediawiki 3.12.1 → 3.12.2

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.
@@ -5,7 +5,7 @@ import { defaultKeymap, historyKeymap, history, redo, indentWithTab, insertNewli
5
5
  import { search, searchKeymap } from '@codemirror/search';
6
6
  import { linter, lintGutter } from '@codemirror/lint';
7
7
  import elt from 'crelt';
8
- import { base, panelSelector, panelsSelector, diagnosticSelector, noDetectionLangs } from './constants.js';
8
+ import { baseData, panelSelector, panelsSelector, diagnosticSelector, noDetectionLangs } from './constants.js';
9
9
  import { light } from './theme.js';
10
10
  import { nextDiagnostic } from './lint.js';
11
11
  export const plain = () => [
@@ -62,10 +62,10 @@ export const replaceSelections = (view, func) => {
62
62
  /** CodeMirror 6 editor */
63
63
  export class CodeMirror6 {
64
64
  static get CDN() {
65
- return base.CDN;
65
+ return baseData.CDN;
66
66
  }
67
67
  static set CDN(url) {
68
- base.CDN = url;
68
+ baseData.CDN = url;
69
69
  }
70
70
  #textarea;
71
71
  #language = new Compartment();
@@ -301,10 +301,10 @@ export class CodeMirror6 {
301
301
  const diagnostics = (await source(state)).map((diagnostic) => ({
302
302
  ...diagnostic,
303
303
  renderMessage(view) {
304
- const span = elt('span', { class: diagnosticSelector.slice(1) }, diagnostic.renderMessage?.(view) ?? diagnostic.message);
304
+ const span = elt('span', { class: diagnosticSelector.slice(1) }, diagnostic.renderMessage?.call(this, view) ?? this.message);
305
305
  span.addEventListener('click', () => {
306
306
  view.dispatch({
307
- selection: { anchor: diagnostic.from, head: diagnostic.to },
307
+ selection: { anchor: this.from, head: this.to },
308
308
  });
309
309
  view.focus();
310
310
  });
@@ -1,4 +1,4 @@
1
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
+ export declare const baseData: 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";
3
3
  export declare const isWMF: boolean;
4
4
  export declare const isMac: boolean;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Decoration } from '@codemirror/view';
2
2
  import { wmf } from '@bhsd/common';
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
+ export const baseData = { 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';
4
4
  export const isWMF = /* @__PURE__ */ (() => typeof location === 'object'
5
5
  && new RegExp(String.raw `\.(?:${wmf})\.org$`, 'u').test(location.hostname))();
6
6
  export const isMac = /* @__PURE__ */ (() => {
package/dist/escape.js CHANGED
@@ -3,7 +3,7 @@ import { EditorSelection } from '@codemirror/state';
3
3
  import { indentMore, indentLess } from '@codemirror/commands';
4
4
  import { getLSP } from '@bhsd/browser';
5
5
  import elt from 'crelt';
6
- import { base } from './constants.js';
6
+ import { baseData } from './constants.js';
7
7
  import { replaceSelections, menuRegistry, } from './codemirror.js';
8
8
  import { sliceDoc, toConfigGetter, } from './util.js';
9
9
  const entity = { '"': 'quot', "'": 'apos', '<': 'lt', '>': 'gt', '&': 'amp', ' ': 'nbsp' };
@@ -70,7 +70,7 @@ escapeWiki = async (view, lsp) => {
70
70
  }));
71
71
  };
72
72
  const escapeWikiCommand = (view, getConfig) => {
73
- const lsp = getLSP(view, false, getConfig, base.CDN);
73
+ const lsp = getLSP(view, false, getConfig, baseData.CDN);
74
74
  if (lsp && 'provideRefactoringAction' in lsp && view.state.selection.ranges.some(({ empty }) => !empty)) {
75
75
  void escapeWiki(view, lsp);
76
76
  return true;
@@ -99,7 +99,7 @@ menuRegistry.push({
99
99
  handlerBase(view, e);
100
100
  });
101
101
  items = [btnHTML, btnURI];
102
- const lsp = getLSP(view, false, cm.getWikiConfig, base.CDN);
102
+ const lsp = getLSP(view, false, cm.getWikiConfig, baseData.CDN);
103
103
  if (lsp && 'provideRefactoringAction' in lsp) {
104
104
  const btnWiki = elt('div', 'Escape with magic words');
105
105
  btnWiki.addEventListener('click', e => {
package/dist/fold.d.ts CHANGED
@@ -17,7 +17,7 @@ export declare const updateSelection: AnchorUpdate, updateAll: AnchorUpdate;
17
17
  * @param refOnly 是否仅检查`<ref>`标签
18
18
  * @test
19
19
  */
20
- export declare const foldable: (state: EditorState, posOrNode: number | SyntaxNode, tree?: Tree | null, refOnly?: boolean) => DocRange | false;
20
+ export declare const foldableInline: (state: EditorState, posOrNode: number | SyntaxNode, tree?: Tree | null, refOnly?: boolean) => DocRange | false;
21
21
  /**
22
22
  * 折叠所有模板
23
23
  * @param state
@@ -31,7 +31,7 @@ export declare const foldable: (state: EditorState, posOrNode: number | SyntaxNo
31
31
  * @test
32
32
  */
33
33
  export declare const traverse: (state: EditorState, tree: Tree, effects: StateEffect<DocRange>[], node: SyntaxNode | null, end: number, anchor: number, update: AnchorUpdate, refOnly?: boolean) => number;
34
- declare class FoldMarker extends GutterMarker {
34
+ declare class MyFoldMarker extends GutterMarker {
35
35
  readonly open: boolean;
36
36
  constructor(open: boolean);
37
37
  eq(other: this): boolean;
@@ -48,7 +48,7 @@ export declare const foldableLine: ({ state, viewportLineBlocks }: EditorView, {
48
48
  * @param view
49
49
  * @test
50
50
  */
51
- export declare const buildMarkers: (view: EditorView) => RangeSet<FoldMarker>;
51
+ export declare const buildMarkers: (view: EditorView) => RangeSet<MyFoldMarker>;
52
52
  /**
53
53
  * 生成折叠命令
54
54
  * @param refOnly 是否仅检查`<ref>`标签
@@ -62,7 +62,7 @@ export declare const unfoldRef: Command;
62
62
  * @param view
63
63
  * @test
64
64
  */
65
- export declare const selectedLines: (view: EditorView) => BlockInfo[];
65
+ export declare const mySelectedLines: (view: EditorView) => BlockInfo[];
66
66
  /**
67
67
  * Fold the template at the selection/cursor
68
68
  * @param view
package/dist/fold.js CHANGED
@@ -47,7 +47,7 @@ const refNames = new Set(['ref', 'references']);
47
47
  * @param refOnly 是否仅检查`<ref>`标签
48
48
  * @test
49
49
  */
50
- export const foldable = (state, posOrNode, tree, refOnly = false) => {
50
+ export const foldableInline = (state, posOrNode, tree, refOnly = false) => {
51
51
  if (typeof posOrNode === 'number') {
52
52
  tree = ensureSyntaxTree(state, posOrNode);
53
53
  }
@@ -141,7 +141,7 @@ const foldSelector = '.cm-tooltip-fold';
141
141
  * @param state
142
142
  */
143
143
  const create = (state) => {
144
- const { head } = state.selection.main, range = foldable(state, head);
144
+ const { head } = state.selection.main, range = foldableInline(state, head);
145
145
  if (range) {
146
146
  const { from, to } = range;
147
147
  let folded = false;
@@ -207,7 +207,7 @@ export const traverse = (state, tree, effects, node, end, anchor, update, refOnl
207
207
  while (node && (node.from < end
208
208
  || node.from === end
209
209
  && !(isTemplateBracket(node) && sliceDoc(state, node).startsWith('}}')))) {
210
- const range = foldable(state, node, tree, refOnly);
210
+ const range = foldableInline(state, node, tree, refOnly);
211
211
  if (range) {
212
212
  effects.push(foldEffect.of(range));
213
213
  node = tree.resolve(range.to, 1);
@@ -219,7 +219,7 @@ export const traverse = (state, tree, effects, node, end, anchor, update, refOnl
219
219
  }
220
220
  return anchor;
221
221
  };
222
- class FoldMarker extends GutterMarker {
222
+ class MyFoldMarker extends GutterMarker {
223
223
  constructor(open) {
224
224
  super();
225
225
  this.open = open;
@@ -231,8 +231,8 @@ class FoldMarker extends GutterMarker {
231
231
  return elt('span', { title: state.phrase(this.open ? 'Fold line' : 'Unfold line') }, this.open ? '⌄' : '›');
232
232
  }
233
233
  }
234
- const canFold = /* @__PURE__ */ new FoldMarker(true), canUnfold = /* @__PURE__ */ new FoldMarker(false);
235
- const findFold = ({ state }, line) => {
234
+ const canFold = /* @__PURE__ */ new MyFoldMarker(true), canUnfold = /* @__PURE__ */ new MyFoldMarker(false);
235
+ const myFindFold = ({ state }, line) => {
236
236
  let found;
237
237
  state.field(foldState, false)?.between(line.from, line.to, (from, to) => {
238
238
  if (!found && to === line.to) {
@@ -323,7 +323,7 @@ export const buildMarkers = (view) => {
323
323
  const builder = new RangeSetBuilder();
324
324
  for (const line of view.viewportLineBlocks) {
325
325
  let mark;
326
- if (findFold(view, line)) {
326
+ if (myFindFold(view, line)) {
327
327
  mark = canUnfold;
328
328
  }
329
329
  else if (foldableLine(view, line)) {
@@ -393,7 +393,7 @@ export const unfoldRef = (view) => {
393
393
  * @param view
394
394
  * @test
395
395
  */
396
- export const selectedLines = (view) => {
396
+ export const mySelectedLines = (view) => {
397
397
  const lines = [];
398
398
  for (const { head } of view.state.selection.ranges) {
399
399
  if (lines.some(({ from, to }) => from <= head && to >= head)) {
@@ -403,7 +403,7 @@ export const selectedLines = (view) => {
403
403
  }
404
404
  return lines;
405
405
  };
406
- const foldCode = (view, line) => {
406
+ const myFoldCode = (view, line) => {
407
407
  const range = foldableLine(view, line);
408
408
  if (range) {
409
409
  view.dispatch({ effects: foldEffect.of(range) });
@@ -411,8 +411,8 @@ const foldCode = (view, line) => {
411
411
  }
412
412
  return false;
413
413
  };
414
- const unfoldCode = (view, line) => {
415
- const folded = findFold(view, line);
414
+ const myUnfoldCode = (view, line) => {
415
+ const folded = myFindFold(view, line);
416
416
  return folded && unfoldEffect.of(folded);
417
417
  };
418
418
  /**
@@ -437,8 +437,8 @@ export const foldAt = view => {
437
437
  if (effects.length > 0) {
438
438
  return execute(view, effects, anchor);
439
439
  }
440
- for (const line of selectedLines(view)) {
441
- if (foldCode(view, line)) {
440
+ for (const line of mySelectedLines(view)) {
441
+ if (myFoldCode(view, line)) {
442
442
  return true;
443
443
  }
444
444
  }
@@ -515,8 +515,8 @@ export const mediawikiFold = /* @__PURE__ */ (() => [
515
515
  view.dispatch({ effects, selection });
516
516
  return true;
517
517
  }
518
- for (const line of selectedLines(view)) {
519
- const effect = unfoldCode(view, line);
518
+ for (const line of mySelectedLines(view)) {
519
+ const effect = myUnfoldCode(view, line);
520
520
  if (effect) {
521
521
  effects.push(effect);
522
522
  }
@@ -537,16 +537,16 @@ export const mediawikiFold = /* @__PURE__ */ (() => [
537
537
  return view.plugin(markers)?.markers ?? RangeSet.empty;
538
538
  },
539
539
  initialSpacer() {
540
- return new FoldMarker(false);
540
+ return new MyFoldMarker(false);
541
541
  },
542
542
  domEventHandlers: {
543
543
  click(view, line) {
544
- const effects = unfoldCode(view, line);
544
+ const effects = myUnfoldCode(view, line);
545
545
  if (effects) {
546
546
  view.dispatch({ effects });
547
547
  return true;
548
548
  }
549
- return foldCode(view, line);
549
+ return myFoldCode(view, line);
550
550
  },
551
551
  },
552
552
  }),
package/dist/hover.js CHANGED
@@ -2,7 +2,7 @@ import { hoverTooltip, EditorView } from '@codemirror/view';
2
2
  import { ensureSyntaxTree } from '@codemirror/language';
3
3
  import { getLSP, loadScript, } from '@bhsd/browser';
4
4
  import { tokens } from './config.js';
5
- import { base, hoverSelector, bgDark } from './constants.js';
5
+ import { baseData, hoverSelector, bgDark } from './constants.js';
6
6
  import { indexToPos, posToIndex, createTooltipView, toConfigGetter, escHTML, sliceDoc, findTemplateName, } from './util.js';
7
7
  const code = `${hoverSelector} code`;
8
8
  /**
@@ -58,13 +58,13 @@ export default (articlePath, templatedata) => (cm) => {
58
58
  hoverTooltip(async (view, pos, side) => {
59
59
  const { state } = view, { doc } = state;
60
60
  const { paramSuggest, tags } = cm.langConfig;
61
- let hover = await getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), base.CDN)?.provideHover(doc.toString(), indexToPos(doc, pos));
61
+ let hover = await getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), baseData.CDN)?.provideHover(doc.toString(), indexToPos(doc, pos));
62
62
  if (!hover && paramSuggest && 'templatedata' in tags) {
63
63
  // eslint-disable-next-line require-atomic-updates
64
64
  hover = await getHoverFromApi(state, pos, side, paramSuggest, templatedata);
65
65
  }
66
66
  if (hover) {
67
- const { CDN = '' } = base;
67
+ const { CDN = '' } = baseData;
68
68
  await loadScript(`${CDN}${CDN && '/'}npm/marked/lib/marked.umd.js`, 'marked', true);
69
69
  const { end } = hover.range;
70
70
  return {
package/dist/index.d.ts CHANGED
@@ -159,4 +159,4 @@ export declare const registerLanguage: (name: string, lang: (config?: unknown) =
159
159
  */
160
160
  export declare const registerLanguageCore: (name: string, lang: (config?: unknown) => LanguageSupport, lintSource?: LintSourceGetter) => void;
161
161
  export declare const registerTheme: (name: string, theme: Extension) => void;
162
- export { nord } from './theme.js';
162
+ export { nordDark as nord } from './theme.js';
package/dist/index.js CHANGED
@@ -422,4 +422,4 @@ export const registerLanguageCore = (name, lang, lintSource) => {
422
422
  export const registerTheme = (name, theme) => {
423
423
  themes[name] = theme;
424
424
  };
425
- export { nord } from './theme.js';
425
+ export { nordDark as nord } from './theme.js';
package/dist/inlay.js CHANGED
@@ -2,7 +2,7 @@ import { StateField, StateEffect } from '@codemirror/state';
2
2
  import { Decoration, EditorView, WidgetType, ViewPlugin } from '@codemirror/view';
3
3
  import { getLSP } from '@bhsd/browser';
4
4
  import elt from 'crelt';
5
- import { base } from './constants.js';
5
+ import { baseData } from './constants.js';
6
6
  import { posToIndex, toConfigGetter, } from './util.js';
7
7
  const cls = 'cm-inlay-hint';
8
8
  class InlayHintWidget extends WidgetType {
@@ -54,7 +54,7 @@ export default (articlePath) => (cm) => {
54
54
  field,
55
55
  ViewPlugin.define(view => {
56
56
  const timer = setInterval(() => {
57
- if (getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), base.CDN)) {
57
+ if (getLSP(view, false, toConfigGetter(cm.getWikiConfig, articlePath), baseData.CDN)) {
58
58
  clearInterval(timer);
59
59
  void update({ view, docChanged: true });
60
60
  }
@@ -6,7 +6,7 @@ import { builtin } from './javascript-globals.js';
6
6
  import { doctagMark } from './constants.js';
7
7
  import { markDocTagType, pushDecoration } from './util.js';
8
8
  export const jsCompletion = javascriptLanguage.data.of({ autocomplete: scopeCompletionSource(globalThis) });
9
- const globalsMark = Decoration.mark({ class: 'cm-globals' }), builtinGlobals = new Set(Object.keys(builtin));
9
+ const globalsMark = Decoration.mark({ class: 'cm-globals' }), varMark = Decoration.mark({ class: 'cm-doctag-var' }), builtinGlobals = new Set(Object.keys(builtin));
10
10
  /**
11
11
  * 忽略JavaScript正则表达式中的括号匹配
12
12
  * @param state
@@ -61,14 +61,18 @@ export const markGlobalsAndDocTag = (tree, visibleRanges, state, cm) => {
61
61
  }
62
62
  }
63
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);
64
+ const comment = name.slice(2), pos = f + 2, mtAll = comment.matchAll(/^[ \t]*\*\s*(@[a-z]+)(\s+\{)?|\{(@[a-z]+)/dgimu);
65
65
  for (const mt of mtAll) {
66
66
  if (mt[3]) {
67
67
  const [start, end] = mt.indices[3];
68
- pushDecoration(decorations, doctagMark, f + start + 2, f + end + 2);
68
+ pushDecoration(decorations, doctagMark, pos + start, pos + end);
69
69
  }
70
70
  else {
71
- markDocTagType(decorations, f + 2, mt);
71
+ const index = markDocTagType(decorations, pos, mt), m = /^\s+([a-z_]\w*)\s+-/diu.exec(comment.slice(index));
72
+ if (m) {
73
+ const [start, end] = m.indices[1];
74
+ pushDecoration(decorations, varMark, pos + index + start, pos + index + end);
75
+ }
72
76
  }
73
77
  }
74
78
  }
package/dist/json.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { StreamParser, StringStream } from '@codemirror/language';
2
+ declare interface State {
3
+ tokenize: Tokenizer;
4
+ wb: boolean;
5
+ }
6
+ declare type Tokenizer = (stream: StringStream, state: State) => string;
7
+ export declare const jsonBasic: StreamParser<State>, jsonc: StreamParser<State>;
8
+ export {};
package/dist/json.js ADDED
@@ -0,0 +1,108 @@
1
+ const tokenNumber = (stream, state) => {
2
+ if (stream.match(/^\d+(?:\.\d+)?(?:e[+-]?\d+)?/iu)) {
3
+ state.wb = false;
4
+ return 'number';
5
+ }
6
+ state.wb = true;
7
+ return '';
8
+ };
9
+ const mkJson = (jsoncMode) => {
10
+ // Tokenizer
11
+ const tokenComment = (stream, state) => {
12
+ if (stream.skipTo('*/')) {
13
+ stream.next();
14
+ stream.next();
15
+ state.tokenize = tokenBase;
16
+ }
17
+ else {
18
+ stream.skipToEnd();
19
+ }
20
+ return 'comment';
21
+ };
22
+ const tokenBase = (stream, state) => {
23
+ if (stream.eatSpace()) {
24
+ state.wb = true;
25
+ return '';
26
+ }
27
+ const ch = stream.next();
28
+ switch (ch) {
29
+ case '{':
30
+ case '}':
31
+ state.wb = true;
32
+ return 'brace';
33
+ case '[':
34
+ case ']':
35
+ state.wb = true;
36
+ return 'squareBracket';
37
+ case ':':
38
+ case ',':
39
+ state.wb = true;
40
+ return 'separator';
41
+ case '/':
42
+ state.wb = true;
43
+ if (jsoncMode) {
44
+ if (stream.eat('/')) {
45
+ stream.skipToEnd();
46
+ return 'comment';
47
+ }
48
+ else if (stream.eat('*')) {
49
+ state.tokenize = tokenComment;
50
+ return tokenComment(stream, state);
51
+ }
52
+ }
53
+ return '';
54
+ case '"': {
55
+ state.wb = true;
56
+ let escaped = false, next = stream.next();
57
+ while (next) {
58
+ if (!escaped && next === '"') {
59
+ break;
60
+ }
61
+ escaped = !escaped && next === '\\';
62
+ next = stream.next();
63
+ }
64
+ return stream.match(/^\s*:/u, false) ? 'propertyName.definition' : 'string';
65
+ }
66
+ case '-':
67
+ if (state.wb) {
68
+ return tokenNumber(stream, state);
69
+ }
70
+ state.wb = true;
71
+ return '';
72
+ default:
73
+ if (state.wb) {
74
+ if (ch >= '0' && ch <= '9') {
75
+ stream.backUp(1);
76
+ return tokenNumber(stream, state);
77
+ }
78
+ else if (ch === 'n' && stream.match(/^ull\b/u)) {
79
+ state.wb = false;
80
+ return 'null';
81
+ }
82
+ else if (ch === 't' && stream.match(/^rue\b/u)
83
+ || ch === 'f' && stream.match(/^alse\b/u)) {
84
+ state.wb = false;
85
+ return 'bool';
86
+ }
87
+ }
88
+ state.wb = !/[\w$]/u.test(ch);
89
+ return '';
90
+ }
91
+ };
92
+ // Interface
93
+ return {
94
+ startState() {
95
+ return {
96
+ tokenize: tokenBase,
97
+ wb: true,
98
+ };
99
+ },
100
+ token(stream, state) {
101
+ if (stream.sol()) {
102
+ state.wb = true;
103
+ }
104
+ return state.tokenize(stream, state);
105
+ },
106
+ };
107
+ };
108
+ export const jsonBasic = mkJson(), jsonc = mkJson(true);
package/dist/keymap.d.ts CHANGED
@@ -9,6 +9,6 @@ import type { KeymapConfig } from './keybindings';
9
9
  * @param opt.splitlines 是否分行
10
10
  * @test
11
11
  */
12
- export declare const getKeymap: ({ key, pre, post, splitlines }: KeymapConfig) => KeyBinding;
12
+ export declare const getWikiKeymap: ({ key, pre, post, splitlines }: KeymapConfig) => KeyBinding;
13
13
  declare const _default: KeyBinding[];
14
14
  export default _default;
package/dist/keymap.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { EditorSelection } from '@codemirror/state';
2
+ import { syntaxTree } from '@codemirror/language';
2
3
  import { keybindings, encapsulateLines } from './keybindings.js';
4
+ const reKartographer = /(?:^|_)mw-tag-map(?:link|frame)(?:$|_)/u;
3
5
  /**
4
6
  * 生成keymap
5
7
  * @param opt 快捷键设置
@@ -9,11 +11,24 @@ import { keybindings, encapsulateLines } from './keybindings.js';
9
11
  * @param opt.splitlines 是否分行
10
12
  * @test
11
13
  */
12
- export const getKeymap = ({ key, pre = '', post = '', splitlines }) => ({
14
+ export const getWikiKeymap = ({ key, pre = '', post = '', splitlines }) => ({
13
15
  key,
14
16
  run(view) {
15
- const { state } = view;
17
+ const { state } = view, tree = syntaxTree(state);
16
18
  view.dispatch(state.changeByRange(({ from, to }) => {
19
+ if (key === 'Mod-/'
20
+ && reKartographer.test(tree.resolveInner(from, 1).name)
21
+ && reKartographer.test(tree.resolveInner(to, -1).name)) {
22
+ // JSONC comment
23
+ if (from === to) {
24
+ pre = '//';
25
+ post = '';
26
+ }
27
+ else {
28
+ pre = '/*';
29
+ post = '*/';
30
+ }
31
+ }
17
32
  if (splitlines) {
18
33
  const start = state.doc.lineAt(from).from, end = state.doc.lineAt(to).to, insert = encapsulateLines(state.sliceDoc(start, end), pre, post);
19
34
  return {
@@ -31,4 +46,4 @@ export const getKeymap = ({ key, pre = '', post = '', splitlines }) => ({
31
46
  },
32
47
  preventDefault: true,
33
48
  });
34
- export default keybindings.map(getKeymap);
49
+ export default keybindings.map(getWikiKeymap);
package/dist/lint.js CHANGED
@@ -1,4 +1,4 @@
1
- const findDiagnostic = (deco, head, anchor = head) => {
1
+ const myFindDiagnostic = (deco, head, anchor = head) => {
2
2
  let found;
3
3
  deco.between(head, Infinity, (_, __, { spec: { diagnostics } }) => {
4
4
  const next = diagnostics.sort((a, b) => a.from - b.from || a.to - b.to)
@@ -16,7 +16,7 @@ const findDiagnostic = (deco, head, anchor = head) => {
16
16
  * @param cm CodeMirror6 实例
17
17
  */
18
18
  export const nextDiagnostic = (cm) => {
19
- const view = cm.view, { state } = view, { diagnostics } = state.field(cm.getLintExtension()[2][0]), { from, to } = state.selection.main, next = findDiagnostic(diagnostics, from, to) ?? findDiagnostic(diagnostics, 0);
19
+ const view = cm.view, { state } = view, { diagnostics } = state.field(cm.getLintExtension()[2][0]), { from, to } = state.selection.main, next = myFindDiagnostic(diagnostics, from, to) ?? myFindDiagnostic(diagnostics, 0);
20
20
  if (!next || next.from === from && next.to === to) {
21
21
  return false;
22
22
  }
@@ -4,7 +4,7 @@ import { javascriptLanguage } from '@codemirror/lang-javascript';
4
4
  import { sanitizeInlineStyle, lintJSON } from '@bhsd/common';
5
5
  import { getWikiLinter, getJsLinter, getCssLinter, getLuaLinter, stylelintRepo, eslintRepo, luacheckRepo, isStylelintConfig, } from './linter.js';
6
6
  import { posToIndex, toConfigGetter, } from './util.js';
7
- import { base } from './constants.js';
7
+ import { baseData } from './constants.js';
8
8
  import { vue } from './javascript-globals.js';
9
9
  /**
10
10
  * 获取Linter选项
@@ -67,7 +67,7 @@ const wikiLintSource = async (wikiLint, text, opt, doc, f = 0, t) => (await wiki
67
67
  * @test
68
68
  */
69
69
  export const getWikiLintSource = (articlePath) => async (opt, v) => {
70
- const options = { ...await getOpt(opt), cdn: base.CDN };
70
+ const options = { ...await getOpt(opt), cdn: baseData.CDN };
71
71
  if (articlePath) {
72
72
  options.getConfig = toConfigGetter(options.getConfig, articlePath);
73
73
  }
@@ -113,7 +113,7 @@ const jsLintSource = (esLint, code, opt, doc, f = 0, t) => esLint(code, opt)
113
113
  * @test
114
114
  */
115
115
  export const getJsLintSource = async (opt) => {
116
- const { CDN } = base, esLint = await getJsLinter(CDN && `${CDN}/${eslintRepo}`);
116
+ const { CDN } = baseData, esLint = await getJsLinter(CDN && `${CDN}/${eslintRepo}`);
117
117
  const lintSource = async ({ doc }) => jsLintSource(esLint, doc.toString(), await getOpt(opt), doc);
118
118
  lintSource.fixer = (doc, rule) => esLint.fixer(doc.toString(), rule);
119
119
  Object.defineProperty(lintSource, 'config', {
@@ -156,7 +156,7 @@ const cssLintSource = async (styleLint, code, opt, doc, f = 0, t) => {
156
156
  * @test
157
157
  */
158
158
  export const getCssLintSource = async (opt) => {
159
- const { CDN } = base, styleLint = await getCssLinter(CDN && `${CDN}/${stylelintRepo}`);
159
+ const { CDN } = baseData, styleLint = await getCssLinter(CDN && `${CDN}/${stylelintRepo}`);
160
160
  const lintSource = async ({ doc }) => cssLintSource(styleLint, doc.toString(), await getOpt(opt), doc);
161
161
  lintSource.fixer = async (doc, rule) => styleLint.fixer(doc.toString(), rule);
162
162
  Object.defineProperty(lintSource, 'config', {
@@ -180,7 +180,7 @@ const stylelintConfigVue = /* #__PURE__ */ (() => ({
180
180
  }))();
181
181
  /** @implements */
182
182
  const getVueOrHtmlLintSource = (rules, globals) => async (opt) => {
183
- const { CDN } = base, styleLint = await getCssLinter(CDN && `${CDN}/${stylelintRepo}`), esLint = await getJsLinter(CDN && `${CDN}/${eslintRepo}`);
183
+ const { CDN } = baseData, styleLint = await getCssLinter(CDN && `${CDN}/${stylelintRepo}`), esLint = await getJsLinter(CDN && `${CDN}/${eslintRepo}`);
184
184
  const lintSource = async (state) => {
185
185
  const { doc } = state, option = await getOpt(opt, true) ?? {};
186
186
  let js = option['js'], css = option['css'];
@@ -228,7 +228,7 @@ export const getVueLintSource = /* #__PURE__ */ getVueOrHtmlLintSource(stylelint
228
228
  * @test
229
229
  */
230
230
  export const getHTMLLintSource = async (opt, view, language) => {
231
- const vueLintSource = await getVueOrHtmlLintSource()(opt), wikiLint = await getWikiLinter({ include: false, ...await getOpt(opt), cdn: base.CDN }, view);
231
+ const vueLintSource = await getVueOrHtmlLintSource()(opt), wikiLint = await getWikiLinter({ include: false, ...await getOpt(opt), cdn: baseData.CDN }, view);
232
232
  const lintSource = async (state) => {
233
233
  const { doc } = state, option = await getOpt(opt, true) ?? {}, wiki = option['wiki'];
234
234
  return [
@@ -255,7 +255,7 @@ export const getJsonLintSource = () => ({ doc }) => lintJSON(doc.toString())
255
255
  * @test
256
256
  */
257
257
  export const getLuaLintSource = async () => {
258
- const { CDN } = base, luaLint = await getLuaLinter(CDN && `${CDN}/${luacheckRepo}`);
258
+ const { CDN } = baseData, luaLint = await getLuaLinter(CDN && `${CDN}/${luacheckRepo}`);
259
259
  return async ({ doc }) => (await luaLint(doc.toString()))
260
260
  .map(({ line, column, end_column, msg: message, severity }) => ({
261
261
  source: 'Luacheck',
package/dist/lua.js CHANGED
@@ -218,7 +218,7 @@ const map = {
218
218
  },
219
219
  ext: 4,
220
220
  },
221
- }, builtin = ['false', 'nil', 'true'], builtins = builtin.map(label => ({ label, type: 'constant' })), tables = [
221
+ }, luaBuiltin = ['false', 'nil', 'true'], luaBuiltins = luaBuiltin.map(label => ({ label, type: 'constant' })), tables = [
222
222
  '_G',
223
223
  ...Object.keys(globals),
224
224
  ].map(label => ({ label, type: 'namespace' })), constants = [
@@ -268,7 +268,7 @@ const map = {
268
268
  'do',
269
269
  'until',
270
270
  'goto',
271
- ].map(label => ({ label, type: 'keyword' })), keywords = [
271
+ ].map(label => ({ label, type: 'keyword' })), luaKeywords = [
272
272
  ...[
273
273
  'if',
274
274
  'while',
@@ -306,14 +306,14 @@ const map = {
306
306
  detail: 'in loop',
307
307
  type: 'keyword',
308
308
  }),
309
- ], types = new Set(['variableName', 'variableName.standard', 'keyword']), lang = StreamLanguage.define(lua);
309
+ ], excludedTypes = new Set(['variableName', 'variableName.standard', 'keyword']), lang = StreamLanguage.define(lua);
310
310
  /**
311
311
  * @implements
312
312
  * @test
313
313
  */
314
314
  const source = context => {
315
315
  const { state, pos } = context, node = syntaxTree(state).resolveInner(pos, -1);
316
- if (!types.has(node.name)) {
316
+ if (!excludedTypes.has(node.name)) {
317
317
  return null;
318
318
  }
319
319
  const match = context.matchBefore(/(?:(?:^|\S|\.\.)\s+|^|[^\w\s]|\.\.)\w+$|\.{1,2}$/u);
@@ -382,7 +382,7 @@ const source = context => {
382
382
  case ',':
383
383
  return {
384
384
  from,
385
- options: [...builtins, ...constants, ...tables, ...unary],
385
+ options: [...luaBuiltins, ...constants, ...tables, ...unary],
386
386
  validFor,
387
387
  };
388
388
  case '}':
@@ -397,7 +397,7 @@ const source = context => {
397
397
  case '':
398
398
  return {
399
399
  from,
400
- options: [...keywords, ...blocks, ...unary, ...constants, ...tables, ...builtins],
400
+ options: [...luaKeywords, ...blocks, ...unary, ...constants, ...tables, ...luaBuiltins],
401
401
  validFor,
402
402
  };
403
403
  default:
@@ -406,9 +406,9 @@ const source = context => {
406
406
  return {
407
407
  from,
408
408
  options: prevSibling?.name !== 'keyword'
409
- || builtin.includes(sliceDoc(state, prevSibling))
409
+ || luaBuiltin.includes(sliceDoc(state, prevSibling))
410
410
  ? [...binary, ...blocks]
411
- : [...builtins, ...constants, ...tables, ...unary, ...blocks],
411
+ : [...luaBuiltins, ...constants, ...tables, ...unary, ...blocks],
412
412
  validFor,
413
413
  };
414
414
  }
@@ -455,9 +455,9 @@ export const markDocTag = (tree, visibleRanges, state) => {
455
455
  || firstLine.startsWith('---')
456
456
  && !(firstLine.endsWith('--') && /[^-]/u.test(firstLine))) {
457
457
  while (node.name === 'comment') {
458
- const comment = sliceDoc(state, node), mt = /^\s*(?:-{2,}\s*)?(@[a-z]+)(\s+\{(?!\}))?/diu.exec(comment);
458
+ const comment = sliceDoc(state, node), mt = /^\s*(?:-{2,}\s*)?(@[a-z]+)(\s+\{)?/diu.exec(comment);
459
459
  if (mt) {
460
- markDocTagType(decorations, node.from, mt);
460
+ markDocTagType(decorations, node.from, mt, 1);
461
461
  }
462
462
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
463
463
  const { nextSibling } = node;