wikilint 2.17.1 → 2.18.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.
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /* eslint-disable n/no-process-exit */
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const assert_1 = __importDefault(require("assert"));
10
+ const cm_1 = require("@bhsd/common/dist/cm");
11
+ const { argv } = process, [, , site, , force, old] = argv;
12
+ let [, , , url] = argv;
13
+ if (!site || !url) {
14
+ console.error('Usage: npx getParserConfig <site> <script path> [force]');
15
+ process.exit(1);
16
+ }
17
+ else if (/(?:\.php|\/)$/u.test(url)) {
18
+ url = url.slice(0, url.lastIndexOf('/'));
19
+ }
20
+ let mwConfig;
21
+ const mw = {
22
+ loader: {
23
+ /** @ignore */
24
+ impl(callback) {
25
+ Object.entries(callback()[1].files).find(([k]) => k.endsWith('.data.js'))[1]();
26
+ },
27
+ /** @ignore */
28
+ implement(_, callback) {
29
+ callback();
30
+ },
31
+ },
32
+ config: {
33
+ /** @ignore */
34
+ set({ extCodeMirrorConfig }) {
35
+ mwConfig = extCodeMirrorConfig;
36
+ },
37
+ },
38
+ };
39
+ /**
40
+ * Converts an array to an object.
41
+ * @param config parser configuration
42
+ * @param config.articlePath article path
43
+ */
44
+ const arrToObj = ({ articlePath, ...obj }) => {
45
+ for (const [k, v] of Object.entries(obj)) {
46
+ if (Array.isArray(v) && v.every(x => typeof x === 'string')) {
47
+ Object.assign(obj, { [k]: Object.fromEntries(v.map(x => [x, true])) });
48
+ }
49
+ }
50
+ return obj;
51
+ };
52
+ /**
53
+ * Gets the aliases of magic words.
54
+ * @param magicwords magic words
55
+ * @param targets magic word names
56
+ */
57
+ const getAliases = (magicwords, targets) => magicwords
58
+ .filter(({ name }) => targets.has(name))
59
+ .flatMap(({ aliases }) => aliases.map(s => s.replace(/:$/u, '').toLowerCase()));
60
+ /**
61
+ * Filters out gadget-related namespaces.
62
+ * @param id namespace ID
63
+ */
64
+ const filterGadget = (id) => {
65
+ const n = Number(id);
66
+ return n < 2300 || n > 2303; // Gadget, Gadget talk, Gadget definition, Gadget definition talk
67
+ };
68
+ (async () => {
69
+ const m = await (await fetch(`${url}/load.php?modules=ext.CodeMirror${old ? '.data' : ''}`)).text(), params = {
70
+ action: 'query',
71
+ meta: 'siteinfo',
72
+ siprop: `general|magicwords|namespaces|namespacealiases${old ? '|variables' : ''}`,
73
+ format: 'json',
74
+ formatversion: '2',
75
+ }, { query: { general: { variants }, magicwords, namespaces, namespacealiases, variables } } = await (await fetch(`${url}/api.php?${new URLSearchParams(params).toString()}`)).json();
76
+ eval(m); // eslint-disable-line no-eval
77
+ const dir = path_1.default.join('..', '..', 'config'), ns = Object.entries(namespaces).filter(([id]) => filterGadget(id))
78
+ .flatMap(([id, { name, canonical = '' }]) => [
79
+ [id, name],
80
+ ...name === canonical ? [] : [[id, canonical]],
81
+ ]), config = {
82
+ ...(0, cm_1.getParserConfig)(require(path_1.default.join(dir, 'minimum')), mwConfig),
83
+ ...(0, cm_1.getKeywords)(magicwords),
84
+ variants: (0, cm_1.getVariants)(variants),
85
+ namespaces: Object.fromEntries(ns),
86
+ nsid: Object.fromEntries([
87
+ ...ns.map(([id, canonical]) => [canonical.toLowerCase(), Number(id)]),
88
+ ...namespacealiases.filter(({ id }) => filterGadget(id)).map(({ id, alias }) => [alias.toLowerCase(), id]),
89
+ ]),
90
+ ...old && { variable: [...variables, '='] },
91
+ articlePath: '/wiki/$1',
92
+ };
93
+ config.doubleUnderscore[0] = [];
94
+ config.doubleUnderscore[1] = [];
95
+ Object.assign(config.parserFunction[0], (0, cm_1.getConfig)(magicwords, ({ name }) => name === 'msgnw'));
96
+ if ('#choose' in config.parserFunction[0]) {
97
+ delete config.parserFunction[0]['choose'];
98
+ const i = config.variable.indexOf('choose');
99
+ if (i !== -1) {
100
+ config.variable.splice(i, 1);
101
+ }
102
+ }
103
+ config.parserFunction[2] = getAliases(magicwords, new Set(['msg', 'raw']));
104
+ config.parserFunction[3] = getAliases(magicwords, new Set(['subst', 'safesubst']));
105
+ const file = path_1.default.join(__dirname, dir, `${site}.json`), exists = fs_1.default.existsSync(file);
106
+ if (exists) {
107
+ assert_1.default.deepStrictEqual(arrToObj(require(file)), arrToObj(config));
108
+ }
109
+ if (force || !exists) {
110
+ fs_1.default.writeFileSync(file, `${JSON.stringify(config, null, '\t')}\n`);
111
+ }
112
+ })();
@@ -5,7 +5,8 @@ import type { LanguageService as CSSLanguageService, Stylesheet } from 'vscode-c
5
5
  import type { PublicApi } from 'stylelint';
6
6
  import type { Token } from '../internal';
7
7
  export declare const jsonTags: string[];
8
- declare let jsonLSP: JSONLanguageService | undefined, cssLSP: CSSLanguageService | undefined, stylelint: Promise<PublicApi> | undefined;
8
+ declare let jsonLSP: JSONLanguageService | undefined, cssLSP: CSSLanguageService | undefined;
9
+ declare const stylelint: Promise<PublicApi | undefined>;
9
10
  export { jsonLSP, cssLSP, stylelint };
10
11
  /** embedded document */
11
12
  declare class EmbeddedDocument implements TextDocument {
@@ -7,7 +7,7 @@ exports.EmbeddedCSSDocument = exports.EmbeddedJSONDocument = exports.stylelint =
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const common_1 = require("@bhsd/common");
9
9
  exports.jsonTags = ['templatedata', 'mapframe', 'maplink'];
10
- let jsonLSP, cssLSP, stylelint;
10
+ let jsonLSP, cssLSP;
11
11
  try {
12
12
  exports.jsonLSP = jsonLSP = require('vscode-json-languageservice')
13
13
  .getLanguageService({
@@ -39,10 +39,15 @@ try {
39
39
  .getCSSLanguageService();
40
40
  }
41
41
  catch { }
42
- try {
43
- exports.stylelint = stylelint = eval('(async () => (await import("stylelint")).default)()'); // eslint-disable-line no-eval
44
- }
45
- catch { }
42
+ const stylelint = (async () => {
43
+ try {
44
+ return (await import('stylelint')).default;
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ })();
50
+ exports.stylelint = stylelint;
46
51
  /** embedded document */
47
52
  class EmbeddedDocument {
48
53
  uri = '';
package/dist/lib/lsp.d.ts CHANGED
@@ -11,6 +11,8 @@ export declare const tasks: WeakMap<object, Parser.LanguageService>;
11
11
  export declare class LanguageService implements LanguageServiceBase {
12
12
  #private;
13
13
  include: boolean;
14
+ lilypond: string;
15
+ lilypondData: string[];
14
16
  /** @param uri 任务标识 */
15
17
  constructor(uri: object);
16
18
  /** @implements */
package/dist/lib/lsp.js CHANGED
@@ -10,15 +10,18 @@ const lint_1 = require("../util/lint");
10
10
  const string_1 = require("../util/string");
11
11
  const index_1 = __importDefault(require("../index"));
12
12
  /* NOT FOR BROWSER ONLY */
13
+ const fs_1 = __importDefault(require("fs"));
13
14
  const path_1 = __importDefault(require("path"));
15
+ const util_1 = __importDefault(require("util"));
16
+ const child_process_1 = require("child_process");
17
+ const crypto_1 = require("crypto");
14
18
  const stylelint_1 = require("@bhsd/common/dist/stylelint");
15
19
  const document_1 = require("./document");
16
- /* NOT FOR BROWSER ONLY */
17
20
  /** @see https://www.npmjs.com/package/stylelint-config-recommended */
18
21
  const cssRules = {
19
22
  'block-no-empty': null,
20
23
  'property-no-unknown': null,
21
- }, jsonSelector = document_1.jsonTags.map(s => `ext-inner#${s}`).join();
24
+ }, jsonSelector = document_1.jsonTags.map(s => `ext-inner#${s}`).join(), scores = new Map();
22
25
  /* NOT FOR BROWSER ONLY END */
23
26
  exports.tasks = new WeakMap();
24
27
  const refTags = new Set(['ref']), referencesTags = new Set(['ref', 'references']), nameAttrs = new Set(['name', 'extends', 'follow']), groupAttrs = new Set(['group']), renameTypes = new Set([
@@ -80,28 +83,39 @@ const createNodeRange = (token) => {
80
83
  * @param pos.line line number
81
84
  * @param pos.character character number
82
85
  * @param extra extra text
86
+ * @param getDoc documentation method
83
87
  */
84
- const getCompletion = (words, kind, mt, { line, character }, extra) => [...new Set(words)].map((w) => ({
85
- label: w,
86
- kind,
87
- textEdit: {
88
- range: {
89
- start: { line, character: character - mt.length },
90
- end: { line, character },
88
+ const getCompletion = (words, kind, mt, { line, character }, extra, getDoc) => [...new Set(words)].map((w) => {
89
+ const doc = getDoc?.(w)?.description;
90
+ return {
91
+ label: w,
92
+ kind,
93
+ textEdit: {
94
+ range: {
95
+ start: { line, character: character - mt.length },
96
+ end: { line, character },
97
+ },
98
+ newText: w + (extra ?? ''),
91
99
  },
92
- newText: w + (extra ?? ''),
93
- },
94
- }));
100
+ ...doc && {
101
+ documentation: {
102
+ kind: 'markdown',
103
+ value: doc,
104
+ },
105
+ },
106
+ };
107
+ });
95
108
  /**
96
109
  * Get the caret position at the position from a word.
97
110
  * @param root root token
111
+ * @param text source code
98
112
  * @param pos position
99
113
  * @param pos.line line number
100
114
  * @param pos.character character number
101
115
  */
102
- const caretPositionFromWord = (root, { line, character }) => {
116
+ const caretPositionFromWord = (root, text, { line, character }) => {
103
117
  const index = root.indexFromPos(line, character);
104
- return root.caretPositionFromIndex(index + Number(/\w/u.test(root.toString().charAt(index))));
118
+ return root.caretPositionFromIndex(index + Number(/\w/u.test(text.charAt(index))));
105
119
  };
106
120
  /**
107
121
  * Get the attribute of a `<ref>` tag.
@@ -167,15 +181,13 @@ const getQuickFix = (root, fix, preferred = false) => ({
167
181
  });
168
182
  /* NOT FOR BROWSER ONLY */
169
183
  /**
170
- * Get the position of a Stylelint error
171
- * @param rect bounding client rect of the token
172
- * @param bottom bottom of the style block
173
- * @param line line number
174
- * @param column column number
184
+ * Correct the position of an error.
185
+ * @param height
186
+ * @param width
187
+ * @param line 0-based line number
188
+ * @param column 0-based column number
175
189
  */
176
- const getStylelintPos = (rect, bottom, line, column) => {
177
- const { top, left, height, width } = rect, start = bottom - height - 1;
178
- line -= start;
190
+ const adjustPos = (height, width, line, column) => {
179
191
  if (line === 0) {
180
192
  line = 1;
181
193
  column = 0;
@@ -184,8 +196,38 @@ const getStylelintPos = (rect, bottom, line, column) => {
184
196
  line = height;
185
197
  column = width;
186
198
  }
199
+ return [line, column];
200
+ };
201
+ /**
202
+ * Get the position of a Stylelint error.
203
+ * @param rect bounding client rect of the token
204
+ * @param bottom bottom of the style block
205
+ * @param line line number
206
+ * @param column column number
207
+ */
208
+ const getStylelintPos = (rect, bottom, line, column) => {
209
+ const { top, left, height, width } = rect, start = bottom - height - 1;
210
+ line -= start;
211
+ [line, column] = adjustPos(height, width, line, column);
187
212
  return (0, lint_1.getEndPos)(top, left, line, column);
188
213
  };
214
+ /**
215
+ * Convert LilyPond errors to VSCode diagnostics.
216
+ * @param token `<score>` extension token
217
+ * @param errors LilyPond errors
218
+ */
219
+ const getLilyPondDiagnostics = (token, errors) => {
220
+ const { top, left } = token.lastChild.getBoundingClientRect();
221
+ return errors.map(({ line, col, message }) => {
222
+ const pos = (0, lint_1.getEndPos)(top, left, line, col);
223
+ return {
224
+ range: { start: pos, end: pos },
225
+ severity: 1,
226
+ source: 'LilyPond',
227
+ message,
228
+ };
229
+ });
230
+ };
189
231
  /**
190
232
  * Get the end position of a section.
191
233
  * @param section section
@@ -213,18 +255,38 @@ class LanguageService {
213
255
  include = true;
214
256
  /** @private */
215
257
  data;
258
+ /* NOT FOR BROWSER ONLY */
259
+ lilypond;
260
+ lilypondData;
261
+ /* NOT FOR BROWSER ONLY END */
216
262
  /** @param uri 任务标识 */
217
263
  constructor(uri) {
218
264
  exports.tasks.set(uri, this);
219
265
  /* NOT FOR BROWSER ONLY */
220
- Object.defineProperty(this, 'data', {
221
- value: require(path_1.default.join('..', '..', 'data', 'signatures')),
222
- enumerable: false,
266
+ Object.defineProperties(this, {
267
+ data: {
268
+ value: require(path_1.default.join('..', '..', 'data', 'signatures')),
269
+ enumerable: false,
270
+ },
271
+ lilypondData: {
272
+ value: require(path_1.default.join('..', '..', 'data', 'ext', 'score')),
273
+ enumerable: false,
274
+ },
223
275
  });
224
276
  }
225
277
  /** @implements */
226
278
  destroy() {
227
279
  Object.setPrototypeOf(this, null);
280
+ /* NOT FOR BROWSER ONLY */
281
+ const dir = path_1.default.join(__dirname, 'lilypond');
282
+ if (fs_1.default.existsSync(dir)) {
283
+ for (const file of fs_1.default.readdirSync(dir)) {
284
+ try {
285
+ void fs_1.default.promises.unlink(path_1.default.join(dir, file));
286
+ }
287
+ catch { }
288
+ }
289
+ }
228
290
  }
229
291
  /** 检查解析设置有无更新 */
230
292
  #checkConfig() {
@@ -409,7 +471,7 @@ class LanguageService {
409
471
  return getCompletion(allTags, 'Class', mt[1].slice(closing ? 1 : 0), position, closing && !curLine?.slice(character).trim().startsWith('>') ? '>' : '');
410
472
  }
411
473
  else if (mt?.[4]) { // behavior switch
412
- return getCompletion(switches, 'Constant', mt[4], position);
474
+ return getCompletion(switches, 'Constant', mt[4], position, '', name => this.data && this.#getBehaviorSwitch(name.slice(2, -2)));
413
475
  }
414
476
  else if (mt?.[5] !== undefined) { // protocol
415
477
  return getCompletion(protocols, 'Reference', mt[5], position);
@@ -428,7 +490,7 @@ class LanguageService {
428
490
  ? getCompletion(// link
429
491
  root.querySelectorAll('link,file,category,redirect-target').filter(token => token !== cur).map(({ name }) => name), 'Folder', str, position)
430
492
  : [
431
- ...getCompletion(functions, 'Function', match, position),
493
+ ...getCompletion(functions, 'Function', match, position, '', name => this.data && this.#getParserFunction(name.replace(/^#/u, '').toLowerCase())),
432
494
  ...match.startsWith('#')
433
495
  ? []
434
496
  : getCompletion(root.querySelectorAll('template').filter(token => token !== cur)
@@ -519,6 +581,27 @@ class LanguageService {
519
581
  else if (document_1.jsonLSP && type === 'ext-inner' && document_1.jsonTags.includes(cur.name)) {
520
582
  const textDoc = new document_1.EmbeddedJSONDocument(root, cur);
521
583
  return (await document_1.jsonLSP.doComplete(textDoc, position, textDoc.jsonDoc))?.items;
584
+ }
585
+ else if (type === 'ext-inner' && cur.name === 'score') {
586
+ const lang = parentNode.getAttr('lang');
587
+ if (lang !== undefined && lang !== 'lilypond') {
588
+ return undefined;
589
+ }
590
+ const j = root.indexFromPos(line, character), i = cur.getAbsoluteIndex(), before = this.#text.slice(i, j), comment = before.lastIndexOf('%');
591
+ if (comment !== -1
592
+ && (before.charAt(comment + 1) === '{' || !before.slice(comment).includes('\n'))) {
593
+ return undefined;
594
+ }
595
+ const word = /\\?\b(?:\w|\b(?:->?|\.)|\bly:)+$/u.exec(curLine.slice(0, character))?.[0];
596
+ if (word) {
597
+ const { lilypondData } = this;
598
+ return word.startsWith('\\')
599
+ ? getCompletion(lilypondData.filter(w => w.startsWith('\\')), 'Function', word, position)
600
+ : [
601
+ ...getCompletion(lilypondData.filter(w => /^[a-z]/u.test(w)), 'Variable', word, position),
602
+ ...getCompletion(lilypondData.filter(w => /^[A-Z]/u.test(w)), 'Class', word, position),
603
+ ];
604
+ }
522
605
  /* NOT FOR BROWSER ONLY END */
523
606
  }
524
607
  return undefined;
@@ -554,13 +637,13 @@ class LanguageService {
554
637
  ],
555
638
  })),
556
639
  /* eslint-disable @stylistic/operator-linebreak */
557
- cssDiagnostics = document_1.stylelint ?
640
+ cssDiagnostics = await document_1.stylelint ?
558
641
  await (async () => {
559
642
  const tokens = this.findStyleTokens();
560
643
  if (tokens.length === 0) {
561
644
  return [];
562
645
  }
563
- const cssErrors = await (0, stylelint_1.styleLint)(await document_1.stylelint, tokens.map(({ type, tag, lastChild }, i) => `${type === 'ext-attr' ? 'div' : tag}#${i}{\n${(0, common_1.sanitizeInlineStyle)(lastChild.toString())}\n}`).join('\n'), cssRules);
646
+ const cssErrors = await (0, stylelint_1.styleLint)((await document_1.stylelint), tokens.map(({ type, tag, lastChild }, i) => `${type === 'ext-attr' ? 'div' : tag}#${i}{\n${(0, common_1.sanitizeInlineStyle)(lastChild.toString())}\n}`).join('\n'), cssRules);
564
647
  if (cssErrors.length === 0) {
565
648
  return [];
566
649
  }
@@ -597,7 +680,58 @@ class LanguageService {
597
680
  })) :
598
681
  [];
599
682
  /* eslint-enable @stylistic/operator-linebreak */
600
- return [diagnostics, cssDiagnostics, jsonDiagnostics].flat(2);
683
+ /* NOT FOR BROWSER ONLY */
684
+ let lilypondDiagnostics = [];
685
+ if (this.lilypond) {
686
+ const tokens = root.querySelectorAll('ext#score').filter(token => {
687
+ const lang = token.getAttr('lang');
688
+ return (lang === undefined || lang === 'lilypond') && token.innerText;
689
+ });
690
+ if (tokens.length > 0) {
691
+ const dir = path_1.default.join(__dirname, 'lilypond');
692
+ if (!fs_1.default.existsSync(dir)) {
693
+ fs_1.default.mkdirSync(dir);
694
+ }
695
+ lilypondDiagnostics = await Promise.all(tokens.map(async (token) => {
696
+ const { innerText } = token, score = `showLastLength = R1${token.getAttr('raw') === undefined ? ` \\score {\n${innerText}\n}` : `\n${innerText}`}`;
697
+ if (scores.has(score)) {
698
+ return getLilyPondDiagnostics(token, scores.get(score));
699
+ }
700
+ const hash = (0, crypto_1.createHash)('sha256');
701
+ hash.update(score);
702
+ const file = path_1.default.join(dir, `${hash.digest('hex')}.ly`);
703
+ fs_1.default.writeFileSync(file, score);
704
+ try {
705
+ await util_1.default.promisify(child_process_1.execFile)(this.lilypond, ['-s', '-o', dir, file]);
706
+ scores.set(score, []);
707
+ }
708
+ catch (e) {
709
+ const { stderr } = e;
710
+ if (stderr) {
711
+ const re = new RegExp(String.raw `^${file}:(\d+):(\d+): error: (.+)$`, 'gmu'), lilypondErrors = [...stderr.matchAll(re)].map(([, line, col, msg]) => {
712
+ const { offsetHeight, offsetWidth } = token.lastChild, pos = adjustPos(offsetHeight, offsetWidth, Number(line) - 1, Number(col) - 1);
713
+ return {
714
+ line: pos[0],
715
+ col: pos[1],
716
+ message: msg,
717
+ };
718
+ });
719
+ scores.set(score, lilypondErrors);
720
+ return getLilyPondDiagnostics(token, lilypondErrors);
721
+ }
722
+ }
723
+ return [];
724
+ }));
725
+ }
726
+ }
727
+ /* NOT FOR BROWSER ONLY END */
728
+ return [
729
+ diagnostics,
730
+ cssDiagnostics,
731
+ jsonDiagnostics,
732
+ /* NOT FOR BROWSER ONLY */
733
+ lilypondDiagnostics,
734
+ ].flat(2);
601
735
  }
602
736
  /**
603
737
  * Provide folding ranges
@@ -750,7 +884,7 @@ class LanguageService {
750
884
  * @param position 位置
751
885
  */
752
886
  async provideReferences(text, position) {
753
- const root = await this.#queue(text), { offsetNode, offset } = caretPositionFromWord(root, position), element = offsetNode.type === 'text' ? offsetNode.parentNode : offsetNode, node = offset === 0 && (element.type === 'ext-attr-dirty' || element.type === 'html-attr-dirty')
887
+ const root = await this.#queue(text), { offsetNode, offset } = caretPositionFromWord(root, this.#text, position), element = offsetNode.type === 'text' ? offsetNode.parentNode : offsetNode, node = offset === 0 && (element.type === 'ext-attr-dirty' || element.type === 'html-attr-dirty')
754
888
  ? element.parentNode.parentNode
755
889
  : element, { type } = node, refName = getRefName(node), refGroup = getRefGroup(node);
756
890
  if (!refName && !refGroup && !referenceTypes.has(type)) {
@@ -830,6 +964,13 @@ class LanguageService {
830
964
  },
831
965
  };
832
966
  }
967
+ /**
968
+ * 检索状态开关
969
+ * @param name 魔术字名
970
+ */
971
+ #getBehaviorSwitch(name) {
972
+ return this.data.behaviorSwitches.find(({ aliases }) => aliases.includes(name));
973
+ }
833
974
  /**
834
975
  * 检索解析器函数
835
976
  * @param name 函数名
@@ -850,10 +991,10 @@ class LanguageService {
850
991
  if (!this.data) {
851
992
  return undefined;
852
993
  }
853
- const root = await this.#queue(text), { offsetNode, offset } = caretPositionFromWord(root, position), token = offsetNode.type === 'text' ? offsetNode.parentNode : offsetNode, { type, parentNode, length, name } = token;
994
+ const root = await this.#queue(text), { offsetNode, offset } = caretPositionFromWord(root, this.#text, position), token = offsetNode.type === 'text' ? offsetNode.parentNode : offsetNode, { type, parentNode, length, name } = token;
854
995
  let info, f, range;
855
996
  if (token.is('double-underscore') && offset > 0) {
856
- info = this.data.behaviorSwitches.find(({ aliases }) => aliases.includes(token.innerText.toLowerCase()));
997
+ info = this.#getBehaviorSwitch(token.innerText.toLowerCase());
857
998
  }
858
999
  else if (type === 'magic-word-name') {
859
1000
  info = this.#getParserFunction(parentNode.name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikilint",
3
- "version": "2.17.1",
3
+ "version": "2.18.0",
4
4
  "description": "A Node.js linter for MediaWiki markup",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -20,14 +20,14 @@
20
20
  "/data/",
21
21
  "/i18n/",
22
22
  "/coverage/badge.svg",
23
- "/bin/cli.js",
23
+ "/bin/*.js",
24
24
  "/dist/",
25
- "!/dist/test/",
26
- "!/dist/bin/coverage.js",
27
- "!/dist/bin/declaration.js"
25
+ "!/dist/script/",
26
+ "!/dist/test/"
28
27
  ],
29
28
  "bin": {
30
- "wikilint": "bin/cli.js"
29
+ "wikilint": "bin/cli.js",
30
+ "getParserConfig": "bin/config.js"
31
31
  },
32
32
  "main": "./dist/index.js",
33
33
  "types": "./dist/index.d.ts",
@@ -37,7 +37,7 @@
37
37
  "url": "git+https://github.com/bhsd-harry/wikiparser-node.git"
38
38
  },
39
39
  "scripts": {
40
- "declaration": "grep -rl --include='*.d.ts' '@private' dist/ | xargs bash sed.sh -i -E '/^\\s+\\/\\*\\* @private/,+1d'; grep -rl --include='*.d.ts' '/util/' dist/ | xargs bash sed.sh -i -E '/^import .+\\/util\\//d'; bash sed.sh -i -E 's/abstract (lint|print|text)\\b/\\1/' dist/lib/node.d.ts; node dist/bin/declaration.js",
40
+ "declaration": "grep -rl --include='*.d.ts' '@private' dist/ | xargs bash sed.sh -i -E '/^\\s+\\/\\*\\* @private/,+1d'; grep -rl --include='*.d.ts' '/util/' dist/ | xargs bash sed.sh -i -E '/^import .+\\/util\\//d'; bash sed.sh -i -E 's/abstract (lint|print|text)\\b/\\1/' dist/lib/node.d.ts; node dist/script/declaration.js",
41
41
  "prepublishOnly": "npm run build:core",
42
42
  "build:core": "bash build.sh",
43
43
  "build": "npm run build:core",
@@ -47,7 +47,7 @@
47
47
  "lint:json": "v8r -s config/.schema.json config/*.json && v8r -s data/.schema.json data/*.json && node dist/test/json.js",
48
48
  "lint": "npm run lint:ts && npm run lint:json",
49
49
  "prof": "node dist/test/prof.js",
50
- "coverage": "nyc --cache-dir=./.cache/nyc npm test && node dist/bin/coverage.js && open coverage/index.html",
50
+ "coverage": "nyc --cache-dir=./.cache/nyc npm test && node dist/script/coverage.js && open coverage/index.html",
51
51
  "test:unit": "mocha dist/test/test.js",
52
52
  "test:parser": "mocha dist/test/parserTests.js",
53
53
  "test": "npm run test:unit && npm run test:parser",
@@ -65,7 +65,7 @@
65
65
  ]
66
66
  },
67
67
  "dependencies": {
68
- "@bhsd/common": "^0.7.0",
68
+ "@bhsd/common": "^0.8.0",
69
69
  "vscode-languageserver-types": "^3.17.5"
70
70
  },
71
71
  "optionalDependencies": {
@@ -74,8 +74,7 @@
74
74
  "minimatch": "^10.0.1",
75
75
  "stylelint": "^16.14.1",
76
76
  "vscode-css-languageservice": "^6.3.2",
77
- "vscode-json-languageservice": "^5.4.3",
78
- "vscode-languageserver-textdocument": "^1.0.12"
77
+ "vscode-json-languageservice": "^5.4.3"
79
78
  },
80
79
  "devDependencies": {
81
80
  "@stylistic/eslint-plugin": "^3.1.0",
@@ -102,7 +101,8 @@
102
101
  "nyc": "^17.1.0",
103
102
  "stylelint-config-recommended": "^15.0.0",
104
103
  "typescript": "^5.7.3",
105
- "v8r": "^4.2.1"
104
+ "v8r": "^4.2.1",
105
+ "vscode-languageserver-textdocument": "^1.0.12"
106
106
  },
107
107
  "engines": {
108
108
  "node": ">=18.17.0"
@@ -1 +0,0 @@
1
- export declare const commonHtmlAttrs: Set<string>, htmlAttrs: Record<string, Set<string>>, extAttrs: Record<string, Set<string>>, obsoleteAttrs: Record<string, Set<string>>;