wikilint 2.29.0 → 2.29.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.
@@ -77,7 +77,7 @@ const mw = {
77
77
  },
78
78
  },
79
79
  };
80
- const pkg = "wikilint", version = "2.29.0";
80
+ const pkg = "wikilint", version = "2.29.2";
81
81
  let mwConfig;
82
82
  /**
83
83
  * Get the parser configuration for a Wikimedia Foundation project.
@@ -7,12 +7,14 @@ 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.texvcjs = (() => {
10
- try {
11
- return require('mathoid-texvcjs');
12
- }
13
- catch {
14
- /* istanbul ignore next */
15
- return undefined;
10
+ NPM: { // eslint-disable-line no-unused-labels
11
+ try {
12
+ return require('mathoid-texvcjs');
13
+ }
14
+ catch {
15
+ /* istanbul ignore next */
16
+ return undefined;
17
+ }
16
18
  }
17
19
  })();
18
20
  exports.jsonTags = ['templatedata', 'mapframe', 'maplink'];
@@ -70,12 +72,14 @@ exports.htmlData = (() => {
70
72
  }
71
73
  })();
72
74
  exports.stylelint = (async () => {
73
- try {
74
- return (await import('stylelint')).default;
75
- }
76
- catch {
77
- /* istanbul ignore next */
78
- return undefined;
75
+ NPM: { // eslint-disable-line no-unused-labels
76
+ try {
77
+ return (await import('stylelint')).default;
78
+ }
79
+ catch {
80
+ /* istanbul ignore next */
81
+ return undefined;
82
+ }
79
83
  }
80
84
  })();
81
85
  /** embedded document */
package/dist/lib/lsp.js CHANGED
@@ -21,10 +21,6 @@ const stylelint_util_1 = require("@bhsd/stylelint-util");
21
21
  const search_1 = __importDefault(require("../util/search"));
22
22
  const constants_1 = require("../util/constants");
23
23
  const document_1 = require("./document");
24
- /** @see https://www.npmjs.com/package/stylelint-config-recommended */
25
- const cssRules = { 'block-no-empty': null }, sources = { 'invalid-css': 'css', 'invalid-math': 'texvc' }, jsonSelector = document_1.jsonTags.map(s => `ext#${s}`).join(), scores = new Map();
26
- let colors;
27
- /* NOT FOR BROWSER ONLY END */
28
24
  exports.tasks = new WeakMap();
29
25
  const refTags = new Set(['ref']), referencesTags = new Set(['ref', 'references']), nameAttrs = new Set(['name', 'follow']), groupAttrs = new Set(['group']), renameTypes = new Set([
30
26
  'arg-name',
@@ -231,6 +227,9 @@ const getFixAll = (root, rule) => {
231
227
  ];
232
228
  };
233
229
  /* NOT FOR BROWSER ONLY */
230
+ /** @see https://www.npmjs.com/package/stylelint-config-recommended */
231
+ const cssRules = { 'block-no-empty': null }, sources = { 'invalid-css': 'css', 'invalid-math': 'texvc' }, jsonSelector = document_1.jsonTags.map(s => `ext#${s}`).join(), scores = new Map();
232
+ let colors;
234
233
  /**
235
234
  * Correct the position of an error.
236
235
  * @param height
@@ -249,21 +248,20 @@ const adjustPos = (height, width, line, column) => {
249
248
  }
250
249
  return [line, column];
251
250
  };
252
- /**
253
- * Get the position of a Stylelint error.
254
- * @param rect bounding client rect of the token
255
- * @param bottom bottom of the style block
256
- * @param lineOrCode line number or code string
257
- * @param columnOrOffset column number or offset in the code string
258
- */
259
- const getStylelintPos = (rect, bottom, lineOrCode, columnOrOffset) => {
251
+ function getStylelintPos(rect, bottom, lineOrCode, columnOrOffset) {
252
+ if (Array.isArray(columnOrOffset)) {
253
+ return {
254
+ start: getStylelintPos(rect, bottom, lineOrCode, columnOrOffset[0]),
255
+ end: getStylelintPos(rect, bottom, lineOrCode, columnOrOffset[1]),
256
+ };
257
+ }
260
258
  const { top, left, height, width } = rect, start = bottom - height - 1;
261
259
  if (typeof lineOrCode === 'number') {
262
260
  return (0, lint_1.getEndPos)(top, left, ...adjustPos(height, width, lineOrCode - start, columnOrOffset));
263
261
  }
264
262
  const lines = lineOrCode.slice(0, columnOrOffset).split(/\r?\n/u);
265
263
  return getStylelintPos(rect, bottom, lines.length, lines.at(-1).length);
266
- };
264
+ }
267
265
  /**
268
266
  * Convert LilyPond errors to VSCode diagnostics.
269
267
  * @param root root token
@@ -518,19 +516,21 @@ class LanguageService {
518
516
  this.config ??= index_1.default.getConfig();
519
517
  const { nsid, ext, html, parserFunction: [insensitive, sensitive, ...other], doubleUnderscore, protocol, img, } = this.config, tags = new Set([ext, html].flat(2));
520
518
  const re = new RegExp('(?:' // eslint-disable-line prefer-template
521
- + String.raw `<(\/?\w*)` // tag
519
+ + String.raw `<(\/?\w*)` // tag ($1)
522
520
  + '|'
523
- + String.raw `(\{{2,4}|\[\[)\s*([^|{}<>[\]\s][^|{}<>[\]#]*)?` // braces and brackets
521
+ + String.raw `(\{{2,4}|\[\[)\s*([^|{}<>[\]\s][^|{}<>[\]#]*)?` // braces and brackets ($2, $3)
524
522
  + '|'
525
- + String.raw `(__(?:(?!__)[\p{L}\p{N}_])*)` // behavior switch
523
+ + String.raw `(_(?:_(?:(?!__|_{2})[\p{L}\p{N}_])*)?)` // behavior switch ($4)
526
524
  + '|'
527
- + String.raw `(?<!\[)\[([a-z:/]*)` // protocol
525
+ + String.raw `(_(?:_(?:(?!__|_{2})[\p{L}\p{N}_])*)?)` // Japanese behavior switch ($5)
528
526
  + '|'
529
- + String.raw `\[\[\s*(?:${Object.entries(nsid).filter(([, v]) => v === 6).map(([k]) => k).join('|')})\s*:[^[\]{}<>]+\|([^[\]{}<>|=]*)` // image parameter
527
+ + String.raw `(?<!\[)\[([a-z:/]*)` // protocol ($6)
530
528
  + '|'
531
- // attribute key
532
- + String.raw `<(\w+)(?:\s(?:[^<>{}|=\s]+(?:\s*=\s*(?:[^\s"']\S*|(["']).*?\8))?(?=\s))*)?\s(\w*)`
533
- + ')$', 'iu');
529
+ + String.raw `\[\[\s*(?:${Object.entries(nsid).filter(([, v]) => v === 6).map(([k]) => k).join('|')})\s*:[^[\]{}<>]+\|([^[\]{}<>|=]*)` // image parameter ($7)
530
+ + '|'
531
+ // attribute key ($8, $10)
532
+ + String.raw `<(\w+)(?:\s(?:[^<>{}|=\s]+(?:\s*=\s*(?:[^\s"']\S*|(["']).*?\9))?(?=\s))*)?\s(\w*)`
533
+ + ')$', 'iu'), allSwitches = doubleUnderscore.slice(0, 2).flat();
534
534
  this.#completionConfig = [
535
535
  {
536
536
  re,
@@ -542,9 +542,8 @@ class LanguageService {
542
542
  Array.isArray(sensitive) ? /* istanbul ignore next */ sensitive : Object.keys(sensitive),
543
543
  other,
544
544
  ].flat(2),
545
- switches: doubleUnderscore.slice(0, 2).flat()
546
- .filter(cm_util_1.isUnderscore)
547
- .map(w => `__${w}__`),
545
+ switches: allSwitches.filter(cm_util_1.isUnderscore).map(w => `__${w}__`),
546
+ jaSwitches: allSwitches.filter(w => !(0, cm_util_1.isUnderscore)(w)),
548
547
  protocols: protocol.split('|'),
549
548
  params: Object.keys(img)
550
549
  .filter(k => k.endsWith('$1') || !k.includes('$1'))
@@ -563,17 +562,20 @@ class LanguageService {
563
562
  * @param position position / 位置
564
563
  */
565
564
  async provideCompletionItems(text, position) {
566
- const { re, allTags, functions, switches, protocols, params, tags, ext } = this.#prepareCompletionConfig(), { line, character } = position, curLine = text.split(/\r?\n/u, line + 1)[line], mt = re.exec(curLine?.slice(0, character) ?? ''), [, , iAlias = {}, sAlias = {}] = this.config.doubleUnderscore;
565
+ const { re, allTags, functions, switches, jaSwitches, protocols, params, tags, ext, } = this.#prepareCompletionConfig(), { line, character } = position, curLine = text.split(/\r?\n/u, line + 1)[line], mt = re.exec(curLine?.slice(0, character) ?? ''), [, , iAlias = {}, sAlias = {}] = this.config.doubleUnderscore;
567
566
  if (mt?.[1] !== undefined) { // tag
568
567
  const closing = mt[1].startsWith('/');
569
568
  return getCompletion(allTags, 'Class', mt[1].slice(closing ? 1 : 0), position, closing && !curLine?.slice(character).trim().startsWith('>') ? '>' : '');
570
569
  }
571
- else if (mt?.[4]) { // behavior switch
572
- return getCompletion(switches, 'Constant', mt[4], position, '', name => {
570
+ else if (mt?.[4] || mt?.[5] && jaSwitches.length > 0) { // behavior switch
571
+ const isJa = mt[5] !== undefined;
572
+ return getCompletion(isJa ? jaSwitches : switches, 'Constant', mt[isJa ? 5 : 4], position, '', name => {
573
573
  if (!this.data) {
574
574
  return undefined;
575
575
  }
576
- name = name.slice(2, -2);
576
+ else if (!isJa) {
577
+ name = name.slice(2, -2);
578
+ }
577
579
  if (name in iAlias) {
578
580
  name = iAlias[name];
579
581
  }
@@ -583,8 +585,8 @@ class LanguageService {
583
585
  return this.#getBehaviorSwitch(name.toLowerCase());
584
586
  });
585
587
  }
586
- else if (mt?.[5] !== undefined) { // protocol
587
- return getCompletion(protocols, 'Reference', mt[5], position);
588
+ else if (mt?.[6] !== undefined) { // protocol
589
+ return getCompletion(protocols, 'Reference', mt[6], position);
588
590
  }
589
591
  const root = await this.#queue(text);
590
592
  let cur;
@@ -637,12 +639,12 @@ class LanguageService {
637
639
  ];
638
640
  }
639
641
  let type, parentNode;
640
- if (mt?.[7] === undefined) {
642
+ if (mt?.[8] === undefined) {
641
643
  cur = root.elementFromPoint(character, line);
642
644
  ({ type, parentNode } = cur);
643
645
  }
644
- if (mt?.[6] !== undefined || type === 'image-parameter') { // image parameter
645
- const index = root.indexFromPos(line, character), match = mt?.[6]?.trimStart()
646
+ if (mt?.[7] !== undefined || type === 'image-parameter') { // image parameter
647
+ const index = root.indexFromPos(line, character), match = mt?.[7]?.trimStart()
646
648
  ?? this.#text.slice(cur.getAbsoluteIndex(), index).trimStart(), equal = this.#text[index] === '=';
647
649
  return [
648
650
  ...getCompletion(params, 'Property', match, position)
@@ -652,8 +654,8 @@ class LanguageService {
652
654
  .map(width => width.text()), 'Unit', match, position),
653
655
  ];
654
656
  }
655
- else if (mt?.[7] !== undefined || type === 'attr-key') { // attribute key
656
- const tag = mt?.[7]?.toLowerCase() ?? parentNode.tag, key = mt?.[9]
657
+ else if (mt?.[8] !== undefined || type === 'attr-key') { // attribute key
658
+ const tag = mt?.[8]?.toLowerCase() ?? parentNode.tag, key = mt?.[10]
657
659
  ?? cur.toString().slice(0, character - root.posFromIndex(cur.getAbsoluteIndex()).left);
658
660
  if (!tags.has(tag)) {
659
661
  return undefined;
@@ -787,48 +789,47 @@ class LanguageService {
787
789
  /* eslint-disable @stylistic/operator-linebreak */
788
790
  cssDiagnostics = await document_1.stylelint ?
789
791
  await (async () => {
790
- const tokens = this.findStyleTokens();
791
- if (tokens.length === 0) {
792
- return [];
793
- }
794
- const code = tokens.map(({ type, tag, lastChild }, i) => `${type === 'ext-attr' ? 'div' : tag}#${i}{\n${(0, common_1.sanitizeInlineStyle)(lastChild.toString())}\n}`).join('\n'), cssErrors = await (0, stylelint_util_1.styleLint)((await document_1.stylelint), code, cssRules);
795
- if (cssErrors.length === 0) {
796
- return [];
797
- }
798
- const rects = tokens.map(({ lastChild }) => lastChild.getBoundingClientRect());
799
- let acc = 0;
800
- const bottoms = rects.map(({ height }) => {
801
- acc += height + 2;
802
- return acc;
803
- });
804
- return cssErrors.map(({ rule, text: msg, severity, line, column, endLine = line, endColumn = column, fix, }) => {
805
- const i = (0, search_1.default)(bottoms, line, (bottom, needle) => bottom - needle);
806
- return {
807
- range: {
808
- start: getStylelintPos(rects[i], bottoms[i], line, column - 1),
809
- end: getStylelintPos(rects[i], bottoms[i], endLine, endColumn - 1),
810
- },
811
- severity: severity === 'error' ? 1 : 2,
812
- source: 'Stylelint',
813
- code: rule,
814
- message: msg.slice(0, msg.lastIndexOf('(') - 1),
815
- ...fix
816
- ? {
817
- data: [
818
- {
819
- range: {
820
- start: getStylelintPos(rects[i], bottoms[i], code, fix.range[0]),
821
- end: getStylelintPos(rects[i], bottoms[i], code, fix.range[1]),
792
+ NPM: { // eslint-disable-line no-unused-labels
793
+ const tokens = this.findStyleTokens();
794
+ if (tokens.length === 0) {
795
+ return [];
796
+ }
797
+ const code = tokens.map(({ type, tag, lastChild }, i) => `${type === 'ext-attr' ? 'div' : tag}#${i}{\n${(0, common_1.sanitizeInlineStyle)(lastChild.toString())}\n}`).join('\n'), cssErrors = await (0, stylelint_util_1.styleLint)((await document_1.stylelint), code, cssRules);
798
+ if (cssErrors.length === 0) {
799
+ return [];
800
+ }
801
+ const rects = tokens.map(({ lastChild }) => lastChild.getBoundingClientRect());
802
+ let acc = 0;
803
+ const bottoms = rects.map(({ height }) => {
804
+ acc += height + 2;
805
+ return acc;
806
+ });
807
+ return cssErrors.map(({ rule, text: msg, severity, line, column, endLine = line, endColumn = column, fix, }) => {
808
+ const i = (0, search_1.default)(bottoms, line, (bottom, needle) => bottom - needle);
809
+ return {
810
+ range: {
811
+ start: getStylelintPos(rects[i], bottoms[i], line, column - 1),
812
+ end: getStylelintPos(rects[i], bottoms[i], endLine, endColumn - 1),
813
+ },
814
+ severity: severity === 'error' ? 1 : 2,
815
+ source: 'Stylelint',
816
+ code: rule,
817
+ message: msg.slice(0, msg.lastIndexOf('(') - 1),
818
+ ...fix
819
+ ? {
820
+ data: [
821
+ {
822
+ range: getStylelintPos(rects[i], bottoms[i], code, fix.range),
823
+ newText: fix.text,
824
+ title: `Fix: ${rule}`,
825
+ fix: true,
822
826
  },
823
- newText: fix.text,
824
- title: `Fix: ${rule}`,
825
- fix: true,
826
- },
827
- ],
828
- }
829
- : {},
830
- };
831
- });
827
+ ],
828
+ }
829
+ : {},
830
+ };
831
+ });
832
+ }
832
833
  })() :
833
834
  [], jsonDiagnostics = document_1.jsonLSP ?
834
835
  await Promise.all(root.querySelectorAll(jsonSelector).map(async ({ name, lastChild, selfClosing }) => {
@@ -1029,7 +1030,7 @@ class LanguageService {
1029
1030
  else if (type === 'link-target' && (parentNode.is('link')
1030
1031
  || parentNode.is('redirect-target')
1031
1032
  || parentNode.is('category'))) {
1032
- if (target.startsWith('/')) {
1033
+ if (/^(?:\.\.)?\//u.test(target)) {
1033
1034
  return false;
1034
1035
  }
1035
1036
  target = parentNode.link.getUrl(articlePath);
@@ -1092,7 +1093,8 @@ class LanguageService {
1092
1093
  * @param position position / 位置
1093
1094
  */
1094
1095
  async provideReferences(text, position) {
1095
- 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')
1096
+ const root = await this.#queue(text), { offsetNode, offset } = caretPositionFromWord(root, this.#text, position), element = offsetNode.type === 'text' ? offsetNode.parentNode : offsetNode, node = offset === 0
1097
+ && (element.is('ext-attr-dirty') || element.is('html-attr-dirty'))
1096
1098
  ? element.parentNode.parentNode
1097
1099
  : element, { type } = node, refName = getRefName(node), refGroup = getRefGroup(node);
1098
1100
  if (!refName && !refGroup && !referenceTypes.has(type)) {
package/dist/lib/text.js CHANGED
@@ -9,8 +9,8 @@ const lint_1 = require("../util/lint");
9
9
  const debug_1 = require("../util/debug");
10
10
  const index_1 = __importDefault(require("../index"));
11
11
  const node_1 = require("./node");
12
- const sp = /* #__PURE__ */ (() => String.raw `[${string_1.zs}\t]*`)(), anySp = /* #__PURE__ */ (() => String.raw `[^\S\n]*`)(), source = /* #__PURE__ */ (() => String.raw `<${anySp}(?:/${anySp})?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*?\])|((?:^|\])[^[]*?)\]+|(?:rfc|pmid)(?=[-::]?${sp}\d)|isbn(?=[-::]?${sp}(?:\d(?:${sp}|-)){6})`)();
13
- const errorSyntax = /* #__PURE__ */ (() => new RegExp(String.raw `${source}|https?[:/]/+`, 'giu'))();
12
+ const sp = /* #__PURE__ */ (() => String.raw `[${string_1.zs}\t]*`)(), anySp = /* #__PURE__ */ (() => String.raw `[^\S\n]*`)(), source = /* #__PURE__ */ (() => String.raw `<${anySp}(?:/${anySp})?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*?\])|((?:^|\])[^[]*?)\]+`)();
13
+ const errorSyntax = /* #__PURE__ */ (() => new RegExp(String.raw `${source}|https?[:/]/+|(?:rfc|pmid)(?=[-::]?${sp}\d)|isbn(?=[-::]?${sp}(?:\d(?:${sp}|-)){6})`, 'giu'))();
14
14
  const errorSyntaxUrl = /* #__PURE__ */ new RegExp(source, 'giu'), noLinkTypes = new Set(['attr-value', 'ext-link-text', 'link-text']), regexes = {
15
15
  '[': /[[\]]/u,
16
16
  '{': /[{}]/u,
@@ -86,7 +86,7 @@ class AstText extends node_1.AstNode {
86
86
  if (!parentNode) {
87
87
  throw new Error('An isolated text node cannot be linted!');
88
88
  }
89
- const { type, name, parentNode: grandparent } = parentNode;
89
+ const { type, parentNode: grandparent } = parentNode;
90
90
  if (type === 'attr-value') {
91
91
  const { name: grandName, tag } = grandparent;
92
92
  if (tag === 'ref' && (grandName === 'name' || grandName === 'follow')
@@ -95,13 +95,7 @@ class AstText extends node_1.AstNode {
95
95
  return [];
96
96
  }
97
97
  }
98
- errorRegex ??= type === 'free-ext-link'
99
- || type === 'ext-link-url'
100
- || type === 'ext-link-text'
101
- || type === 'image-parameter' && name === 'link'
102
- || type === 'attr-value'
103
- ? errorSyntaxUrl
104
- : errorSyntax;
98
+ errorRegex ??= parentNode.isPlain() && !noLinkTypes.has(type) ? errorSyntax : errorSyntaxUrl;
105
99
  if (data.search(errorRegex) === -1) {
106
100
  return [];
107
101
  }
@@ -133,8 +127,7 @@ class AstText extends node_1.AstNode {
133
127
  if (char === '<' && !tags.has(tag.toLowerCase())
134
128
  || lbrack && type === 'ext-link-text' && (/&(?:rbrack|#93|#x5[Dd];);/u.test(data.slice(index + 1))
135
129
  || nextSibling?.is('ext') && nextName === 'nowiki'
136
- && nextSibling.innerText?.includes(']'))
137
- || magicLink && (!parentNode.isPlain() || noLinkTypes.has(type))) {
130
+ && nextSibling.innerText?.includes(']'))) {
138
131
  continue;
139
132
  }
140
133
  else if (rbrack && (index || length > 1)) {
@@ -68,7 +68,7 @@ const parseCommentAndExt = (wikitext, config, accum, includeOnly) => {
68
68
  wikitext = wikitext.replace(/<nowiki>[\s\S]*?<\/nowiki>/giu, m => {
69
69
  stack.push(m);
70
70
  return `\0${stack.length - 1}\x7F`;
71
- }).replace(/<translate( nowrap)?>([\s\S]+?)?<\/translate>/gu, (_, p1, p2) => {
71
+ }).replace(/<translate( nowrap)?>([\s\S]*?)<\/translate>/gu, (_, p1, p2) => {
72
72
  const l = accum.length;
73
73
  // @ts-expect-error abstract class
74
74
  new translate_1.TranslateToken(p1, p2 && (0, string_1.restore)(p2, stack), newConfig, accum);
@@ -1,6 +1,6 @@
1
1
  import { Token } from './index';
2
2
  import type { Config } from '../base';
3
- declare const atomTypes: readonly ["arg-name", "attr-key", "attr-value", "ext-attr-dirty", "html-attr-dirty", "table-attr-dirty", "converter-flag", "converter-rule-variant", "converter-rule-to", "converter-rule-from", "invoke-function", "invoke-module", "template-name", "link-target"];
3
+ declare const atomTypes: readonly ["arg-name", "attr-key", "attr-value", "ext-attr-dirty", "html-attr-dirty", "table-attr-dirty", "converter-flag", "converter-rule-variant", "invoke-function", "invoke-module", "template-name", "link-target"];
4
4
  declare type AtomTypes = typeof atomTypes[number];
5
5
  /**
6
6
  * plain Token that will not be parsed further
package/dist/src/atom.js CHANGED
@@ -12,8 +12,6 @@ const atomTypes = [
12
12
  'table-attr-dirty',
13
13
  'converter-flag',
14
14
  'converter-rule-variant',
15
- 'converter-rule-to',
16
- 'converter-rule-from',
17
15
  'invoke-function',
18
16
  'invoke-module',
19
17
  'template-name',
@@ -247,8 +247,10 @@ class AttributeToken extends index_2.Token {
247
247
  }
248
248
  escape() {
249
249
  LSP: { // eslint-disable-line no-unused-labels
250
- this.#equal = '{{=}}';
251
- this.lastChild.escape();
250
+ if (this.type !== 'ext-attr') {
251
+ this.#equal = '{{=}}';
252
+ this.lastChild.escape();
253
+ }
252
254
  }
253
255
  }
254
256
  }
@@ -76,8 +76,7 @@ let ConverterToken = (() => {
76
76
  const [firstRule] = rules, hasColon = firstRule.includes(':'),
77
77
  // @ts-expect-error abstract class
78
78
  firstRuleToken = new converterRule_1.ConverterRuleToken(firstRule, hasColon, config, accum);
79
- if (hasColon && firstRuleToken.length === 1
80
- || !hasColon && rules.length === 2 && !(0, string_1.removeComment)(rules[1]).trim()) {
79
+ if (hasColon ? firstRuleToken.length === 1 : rules.length === 2 && !(0, string_1.removeComment)(rules[1]).trim()) {
81
80
  this.insertAt(
82
81
  // @ts-expect-error abstract class
83
82
  new converterRule_1.ConverterRuleToken(rules.join(';'), false, config, accum));
@@ -6,12 +6,12 @@ import type { ConverterToken, ConverterFlagsToken } from '../internal';
6
6
  * language conversion rule
7
7
  *
8
8
  * 转换规则
9
- * @classdesc `{childNodes: AtomToken[]}`
9
+ * @classdesc `{childNodes: [Token?, AtomToken?, Token]}`
10
10
  */
11
11
  export declare abstract class ConverterRuleToken extends Token {
12
- readonly childNodes: readonly [AtomToken] | readonly [AtomToken, AtomToken] | readonly [AtomToken, AtomToken, AtomToken];
13
- abstract get firstChild(): AtomToken;
14
- abstract get lastChild(): AtomToken;
12
+ readonly childNodes: readonly [Token] | readonly [AtomToken, Token] | readonly [Token, AtomToken, Token];
13
+ abstract get firstChild(): Token;
14
+ abstract get lastChild(): Token;
15
15
  abstract get parentNode(): ConverterToken | undefined;
16
16
  abstract get previousSibling(): ConverterFlagsToken | this | undefined;
17
17
  abstract get nextSibling(): this | undefined;
@@ -4,14 +4,28 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ConverterRuleToken = void 0;
7
+ const constants_1 = require("../util/constants");
7
8
  const index_1 = __importDefault(require("../index"));
8
9
  const index_2 = require("./index");
9
10
  const atom_1 = require("./atom");
11
+ /**
12
+ * 生成转换原文或目标的节点
13
+ * @param text 文本
14
+ * @param type 节点类型
15
+ * @param config
16
+ * @param accum
17
+ */
18
+ const getRuleFromTo = (text, type, config, accum) => {
19
+ const token = new index_2.Token(text, config, accum);
20
+ token.type = `converter-rule-${type}`;
21
+ token.setAttribute('stage', constants_1.MAX_STAGE);
22
+ return token;
23
+ };
10
24
  /**
11
25
  * language conversion rule
12
26
  *
13
27
  * 转换规则
14
- * @classdesc `{childNodes: AtomToken[]}`
28
+ * @classdesc `{childNodes: [Token?, AtomToken?, Token]}`
15
29
  */
16
30
  class ConverterRuleToken extends index_2.Token {
17
31
  get type() {
@@ -22,17 +36,17 @@ class ConverterRuleToken extends index_2.Token {
22
36
  * @param hasColon 是否带有":"
23
37
  */
24
38
  constructor(rule, hasColon = true, config = index_1.default.getConfig(), accum = []) {
25
- super(undefined, config, accum);
39
+ super(undefined, config, accum, {});
26
40
  const i = rule.indexOf(':'), j = rule.slice(0, i).indexOf('=>'), v = j === -1 ? rule.slice(0, i) : rule.slice(j + 2, i);
27
41
  if (hasColon && config.variants.includes(v.trim().toLowerCase())) {
28
42
  super.insertAt(new atom_1.AtomToken(v, 'converter-rule-variant', config, accum));
29
- super.insertAt(new atom_1.AtomToken(rule.slice(i + 1), 'converter-rule-to', config, accum));
43
+ super.insertAt(getRuleFromTo(rule.slice(i + 1), 'to', config, accum));
30
44
  if (j !== -1) {
31
- super.insertAt(new atom_1.AtomToken(rule.slice(0, j), 'converter-rule-from', config, accum), 0);
45
+ super.insertAt(getRuleFromTo(rule.slice(0, j), 'from', config, accum), 0);
32
46
  }
33
47
  }
34
48
  else {
35
- super.insertAt(new atom_1.AtomToken(rule, 'converter-rule-to', config, accum));
49
+ super.insertAt(getRuleFromTo(rule, 'to', config, accum));
36
50
  }
37
51
  }
38
52
  /** @private */
@@ -15,7 +15,12 @@ export declare abstract class ImageParameterToken extends Token {
15
15
  abstract get nextSibling(): this | undefined;
16
16
  abstract get previousSibling(): AtomToken | this | undefined;
17
17
  get type(): 'image-parameter';
18
- /** thumbnail / 缩略图 */
18
+ /**
19
+ * thumbnail
20
+ *
21
+ * 缩略图
22
+ * @since v1.29.0
23
+ */
19
24
  get thumb(): Title | undefined;
20
25
  /** image link / 图片链接 */
21
26
  get link(): string | Title | undefined;
@@ -70,7 +70,12 @@ class ImageParameterToken extends index_2.Token {
70
70
  get type() {
71
71
  return 'image-parameter';
72
72
  }
73
- /** thumbnail / 缩略图 */
73
+ /**
74
+ * thumbnail
75
+ *
76
+ * 缩略图
77
+ * @since v1.29.0
78
+ */
74
79
  get thumb() {
75
80
  LINT: return this.name === 'manualthumb' // eslint-disable-line no-unused-labels
76
81
  ? this.normalizeTitle(`File:${super.text().trim()}`, 6, { page: '' })
@@ -55,40 +55,42 @@ class NowikiToken extends base_1.NowikiBaseToken {
55
55
  }
56
56
  const errors = super.lint(start, getLintRegex(name));
57
57
  /* NOT FOR BROWSER ONLY */
58
- rule = 'invalid-math';
59
- s = lintConfig.getSeverity(rule);
60
- if (s && document_1.texvcjs && constants_1.mathTags.has(name)) {
61
- const isChem = name !== 'math', display = previousSibling?.getAttr('display') ?? 'block';
62
- let tex = innerText, n = 0;
63
- if (isChem) {
64
- tex = String.raw `\ce{${tex}}`;
65
- n = 4;
66
- }
67
- switch (display) {
68
- case 'block':
69
- tex = String.raw `{\displaystyle ${tex}}`;
70
- n += 15;
71
- break;
72
- case 'inline':
73
- tex = String.raw `{\textstyle ${tex}}`;
74
- n += 12;
75
- break;
76
- case 'linebreak':
77
- tex = String.raw `\[ ${tex} \]`;
78
- n += 3;
79
- // no default
80
- }
81
- const result = document_1.texvcjs.check(tex, {
82
- usemhchem: isChem || Boolean(previousSibling?.hasAttr('chem')),
83
- });
84
- if (result.status !== '+') {
85
- const e = (0, lint_1.generateForSelf)(this, { start }, rule, 'chem-required', s);
86
- if (result.status !== 'C') {
87
- const { error: { message, location } } = result, [endIndex, endLine, endCol] = updateLocation(e, location.end, n);
88
- [e.startIndex, e.startLine, e.startCol] = updateLocation(e, location.start, n);
89
- Object.assign(e, { endIndex, endLine, endCol, message });
58
+ NPM: { // eslint-disable-line no-unused-labels
59
+ rule = 'invalid-math';
60
+ s = lintConfig.getSeverity(rule);
61
+ if (s && document_1.texvcjs && constants_1.mathTags.has(name)) {
62
+ const isChem = name !== 'math', display = previousSibling?.getAttr('display') ?? 'block';
63
+ let tex = innerText, n = 0;
64
+ if (isChem) {
65
+ tex = String.raw `\ce{${tex}}`;
66
+ n = 4;
67
+ }
68
+ switch (display) {
69
+ case 'block':
70
+ tex = String.raw `{\displaystyle ${tex}}`;
71
+ n += 15;
72
+ break;
73
+ case 'inline':
74
+ tex = String.raw `{\textstyle ${tex}}`;
75
+ n += 12;
76
+ break;
77
+ case 'linebreak':
78
+ tex = String.raw `\[ ${tex} \]`;
79
+ n += 3;
80
+ // no default
81
+ }
82
+ const result = document_1.texvcjs.check(tex, {
83
+ usemhchem: isChem || Boolean(previousSibling?.hasAttr('chem')),
84
+ });
85
+ if (result.status !== '+') {
86
+ const e = (0, lint_1.generateForSelf)(this, { start }, rule, 'chem-required', s);
87
+ if (result.status !== 'C') {
88
+ const { error: { message, location } } = result, [endIndex, endLine, endCol] = updateLocation(e, location.end, n);
89
+ [e.startIndex, e.startLine, e.startCol] = updateLocation(e, location.start, n);
90
+ Object.assign(e, { endIndex, endLine, endCol, message });
91
+ }
92
+ errors.push(e);
90
93
  }
91
- errors.push(e);
92
94
  }
93
95
  }
94
96
  /* NOT FOR BROWSER ONLY END */
@@ -197,7 +197,7 @@ let HtmlToken = (() => {
197
197
  s = lintConfig.getSeverity(rule, 'opening');
198
198
  const childNodes = parentNode?.childNodes;
199
199
  if (formattingTags.has(name)) {
200
- if (childNodes?.slice(0, childNodes.indexOf(this)).some(tag => tag.type === 'html' && tag.name === name && !tag.findMatchingTag())) {
200
+ if (childNodes?.slice(0, childNodes.indexOf(this)).some(tag => tag.is('html') && tag.name === name && !tag.findMatchingTag())) {
201
201
  error.suggestions = [(0, lint_1.fixByClose)(start + 1, '/')];
202
202
  }
203
203
  if (this.closest('heading-title')) {
@@ -200,8 +200,7 @@ let TranscludeToken = (() => {
200
200
  return false;
201
201
  }
202
202
  const magicWord = lcModifier.slice(0, -1).toLowerCase(), isRaw = raw.includes(magicWord), isSubst = subst.includes(magicWord);
203
- if (this.#raw && isRaw
204
- || !this.#raw && (isSubst || !modifier)
203
+ if ((this.#raw ? isRaw : isSubst || !modifier)
205
204
  || (debug_1.Shadow.running || this.length > 1) && (isRaw || isSubst || !modifier)) {
206
205
  this.setAttribute('modifier', modifier);
207
206
  this.#raw = isRaw;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikilint",
3
- "version": "2.29.0",
3
+ "version": "2.29.2",
4
4
  "description": "A Node.js linter for MediaWiki markup",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -48,7 +48,7 @@
48
48
  "lint:json": "v8r -s config/.schema.json config/*.json && v8r -s data/.schema.json data/*.json && mocha dist/test/json.js",
49
49
  "lint": "npm run lint:ts && npm run lint:json",
50
50
  "prof": "node dist/test/prof.js",
51
- "coverage": "nyc --cache-dir=./.cache/nyc npm test && node dist/script/coverage.js && open coverage/index.html",
51
+ "coverage": "nyc --cache-dir=./.cache/nyc npm run test:ci && node dist/script/coverage.js && open coverage/index.html",
52
52
  "test:unit": "mocha dist/test/test.js",
53
53
  "test:parser": "mocha dist/test/parserTests.js",
54
54
  "test": "npm run test:unit && npm run test:parser",