wikilint 2.21.0 → 2.21.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.
@@ -672,6 +672,7 @@
672
672
  "urlエンコード": "urlencode",
673
673
  "urlエンコード:": "urlencode",
674
674
  "urlencode": "urlencode",
675
+ "#urlencode": "urlencode",
675
676
  "小写首字": "lcfirst",
676
677
  "先頭小文字": "lcfirst",
677
678
  "lcfirst": "lcfirst",
@@ -105,6 +105,7 @@
105
105
  "servername": "servername",
106
106
  "scriptpath": "scriptpath",
107
107
  "stylepath": "stylepath",
108
+ "#urlencode": "urlencode",
108
109
  "#language": "language",
109
110
  "#special": "special",
110
111
  "#speciale": "speciale",
@@ -435,6 +435,7 @@
435
435
  "nse": "nse",
436
436
  "url编码": "urlencode",
437
437
  "urlencode": "urlencode",
438
+ "#urlencode": "urlencode",
438
439
  "小写首字": "lcfirst",
439
440
  "lcfirst": "lcfirst",
440
441
  "大写首字": "ucfirst",
@@ -40,7 +40,7 @@ const parseList = (wikitext, state, config, accum) => {
40
40
  if (!dt) {
41
41
  return text;
42
42
  }
43
- const { html: [normalTags] } = config, fullRegex = /:+|-\{|\0\d+[xq]\x7F/gu;
43
+ const { html: [normalTags, , voidTags] } = config, fullRegex = /:+|-\{|\0\d+[xq]\x7F/gu;
44
44
  let regex = fullRegex, ex = regex.exec(text), lt = 0, lb = false, li = false, lc = 0;
45
45
  /**
46
46
  * 创建`DdToken`
@@ -84,7 +84,7 @@ const parseList = (wikitext, state, config, accum) => {
84
84
  }
85
85
  else if (syntax.endsWith('x\x7F')) {
86
86
  const { name, closing, selfClosing } = accum[Number(syntax.slice(1, -2))];
87
- if (!selfClosing || normalTags.includes(name)) {
87
+ if (normalTags.includes(name) || !selfClosing && !voidTags.includes(name)) {
88
88
  update(closing);
89
89
  }
90
90
  }
@@ -96,17 +96,13 @@ class AttributeToken extends index_2.Token {
96
96
  getGaps() {
97
97
  return this.#equal ? this.#equal.length + (this.#quotes[0]?.length ?? 0) : 0;
98
98
  }
99
- /** @private */
100
- lint(start = this.getAbsoluteIndex(), re) {
101
- const errors = super.lint(start, re), { balanced, firstChild, lastChild, type, name, tag } = this, value = this.getValue(), rect = new rect_1.BoundingRect(this, start);
102
- if (!balanced) {
103
- const e = (0, lint_1.generateForChild)(lastChild, rect, 'unclosed-quote', index_1.default.msg('unclosed $1', 'quotes'), 'warning');
104
- e.startIndex--;
105
- e.startCol--;
106
- e.suggestions = [{ range: [e.endIndex, e.endIndex], text: this.#quotes[0], desc: 'close' }];
107
- errors.push(e);
108
- }
109
- const attrs = sharable_1.extAttrs[tag], attrs2 = sharable_1.htmlAttrs[tag], { length } = this.toString();
99
+ /**
100
+ * 判定无效的属性名或值
101
+ * @param start 起始位置
102
+ * @param rect 位置
103
+ */
104
+ #lint(start, rect) {
105
+ const { firstChild, lastChild, type, name, tag } = this, value = this.getValue(), attrs = sharable_1.extAttrs[tag], attrs2 = sharable_1.htmlAttrs[tag], { length } = this.toString();
110
106
  if (!attrs?.has(name)
111
107
  && !attrs2?.has(name)
112
108
  // 不是未定义的扩展标签或包含嵌入的HTML标签
@@ -116,10 +112,10 @@ class AttributeToken extends index_2.Token {
116
112
  && (tag === 'meta' || tag === 'link' || !sharable_1.commonHtmlAttrs.has(name)))) {
117
113
  const e = (0, lint_1.generateForChild)(firstChild, rect, 'illegal-attr', 'illegal attribute name');
118
114
  e.suggestions = [{ desc: 'remove', range: [start, start + length], text: '' }];
119
- errors.push(e);
115
+ return e;
120
116
  }
121
117
  else if (name === 'style' && typeof value === 'string' && insecureStyle.test(value)) {
122
- errors.push((0, lint_1.generateForChild)(lastChild, rect, 'insecure-style', 'insecure style'));
118
+ return (0, lint_1.generateForChild)(lastChild, rect, 'insecure-style', 'insecure style');
123
119
  }
124
120
  else if (name === 'tabindex' && typeof value === 'string' && value !== '0') {
125
121
  const e = (0, lint_1.generateForChild)(lastChild, rect, 'illegal-attr', 'nonzero tabindex');
@@ -127,14 +123,30 @@ class AttributeToken extends index_2.Token {
127
123
  { desc: 'remove', range: [start, start + length], text: '' },
128
124
  { desc: '0 tabindex', range: [e.startIndex, e.endIndex], text: '0' },
129
125
  ];
130
- errors.push(e);
126
+ return e;
131
127
  }
132
128
  else if (type !== 'ext-attr' && !lastChild.childNodes.some(({ type: t }) => complexTypes.has(t))) {
133
129
  const data = (0, lint_1.provideValues)(tag, name), v = String(value).toLowerCase();
134
130
  if (data.length > 0 && data.every(n => n !== v)) {
135
- errors.push((0, lint_1.generateForChild)(lastChild, rect, 'illegal-attr', 'illegal attribute value', 'warning'));
131
+ return (0, lint_1.generateForChild)(lastChild, rect, 'illegal-attr', 'illegal attribute value', 'warning');
136
132
  }
137
133
  }
134
+ return false;
135
+ }
136
+ /** @private */
137
+ lint(start = this.getAbsoluteIndex(), re) {
138
+ const errors = super.lint(start, re), { balanced, firstChild, lastChild, name, tag } = this, rect = new rect_1.BoundingRect(this, start);
139
+ if (!balanced) {
140
+ const e = (0, lint_1.generateForChild)(lastChild, rect, 'unclosed-quote', index_1.default.msg('unclosed $1', 'quotes'), 'warning');
141
+ e.startIndex--;
142
+ e.startCol--;
143
+ e.suggestions = [{ range: [e.endIndex, e.endIndex], text: this.#quotes[0], desc: 'close' }];
144
+ errors.push(e);
145
+ }
146
+ const e = this.#lint(start, rect);
147
+ if (e) {
148
+ errors.push(e);
149
+ }
138
150
  if (sharable_1.obsoleteAttrs[tag]?.has(name)) {
139
151
  errors.push((0, lint_1.generateForChild)(firstChild, rect, 'obsolete-attr', 'obsolete attribute', 'warning'));
140
152
  }
@@ -114,10 +114,15 @@ class AttributesToken extends index_2.Token {
114
114
  getAttr(key) {
115
115
  return this.getAttrToken(key)?.getValue();
116
116
  }
117
+ /** 是否位于闭合标签内 */
118
+ #lint() {
119
+ const { parentNode } = this;
120
+ return parentNode?.type === 'html' && parentNode.closing && this.text().trim() !== '';
121
+ }
117
122
  /** @private */
118
123
  lint(start = this.getAbsoluteIndex(), re) {
119
124
  const errors = super.lint(start, re), { parentNode, childNodes } = this, attrs = new Map(), duplicated = new Set(), rect = new rect_1.BoundingRect(this, start);
120
- if (parentNode?.type === 'html' && parentNode.closing && this.text().trim()) {
125
+ if (this.#lint()) {
121
126
  const e = (0, lint_1.generateForSelf)(this, rect, 'no-ignored', 'attributes of a closing tag'), index = parentNode.getAbsoluteIndex();
122
127
  e.suggestions = [
123
128
  { desc: 'remove', range: [start, e.endIndex], text: '' },
@@ -102,6 +102,12 @@ let ConverterFlagsToken = (() => {
102
102
  return new Set(this.#flags.filter(flag => variants.has(flag)));
103
103
  }
104
104
  /** @private */
105
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
106
+ isInvalidFlag(flag, variant, unknown, valid) {
107
+ // @ts-expect-error flag is string
108
+ return Boolean(flag) && !variant.has(flag) && !unknown.has(flag) && (variant.size > 0 || !valid.has(flag));
109
+ }
110
+ /** @private */
105
111
  lint(start = this.getAbsoluteIndex(), re) {
106
112
  const variantFlags = this.getVariantFlags(), unknownFlags = this.getUnknownFlags(), validFlags = new Set(this.#flags.filter(flag => definedFlags.has(flag))), emptyFlagCount = this.#flags.filter(flag => !flag).length, knownFlagCount = this.#flags.length - unknownFlags.size - emptyFlagCount, errors = super.lint(start, re);
107
113
  if (variantFlags.size === knownFlagCount || validFlags.size === knownFlagCount) {
@@ -110,10 +116,7 @@ let ConverterFlagsToken = (() => {
110
116
  const rect = new rect_1.BoundingRect(this, start);
111
117
  for (let i = 0; i < this.length; i++) {
112
118
  const child = this.childNodes[i], flag = child.text().trim();
113
- if (flag
114
- && !variantFlags.has(flag)
115
- && !unknownFlags.has(flag)
116
- && (variantFlags.size > 0 || !validFlags.has(flag))) {
119
+ if (this.isInvalidFlag(flag, variantFlags, unknownFlags, validFlags)) {
117
120
  const e = (0, lint_1.generateForChild)(child, rect, 'no-ignored', 'invalid conversion flag');
118
121
  if (variantFlags.size === 0 && definedFlags.has(flag.toUpperCase())) {
119
122
  e.fix = { range: [e.startIndex, e.endIndex], text: flag.toUpperCase(), desc: 'uppercase' };
@@ -62,7 +62,7 @@ class HeadingToken extends index_2.Token {
62
62
  }
63
63
  /** @private */
64
64
  lint(start = this.getAbsoluteIndex(), re) {
65
- const errors = super.lint(start, re), { firstChild, level } = this, innerStr = firstChild.toString(), unbalancedStart = innerStr.startsWith('='), unbalanced = unbalancedStart || innerStr.endsWith('='), quotes = firstChild.childNodes.filter((0, debug_1.isToken)('quote')), boldQuotes = quotes.filter(({ bold }) => bold), italicQuotes = quotes.filter(({ italic }) => italic), rect = new rect_1.BoundingRect(this, start);
65
+ const errors = super.lint(start, re), { firstChild, level } = this, innerStr = firstChild.toString(), unbalancedStart = innerStr.startsWith('='), unbalanced = unbalancedStart || innerStr.endsWith('='), quotes = firstChild.childNodes.filter((0, debug_1.isToken)('quote')), boldQuotes = quotes.filter(({ bold }) => bold), italicQuotes = quotes.filter(({ italic }) => italic), rect = new rect_1.BoundingRect(this, start), s = this.inHtmlAttrs();
66
66
  if (this.level === 1) {
67
67
  const e = (0, lint_1.generateForChild)(firstChild, rect, 'h1', '<h1>');
68
68
  if (!unbalanced) {
@@ -91,8 +91,8 @@ class HeadingToken extends index_2.Token {
91
91
  }
92
92
  errors.push(e);
93
93
  }
94
- if (this.closest('html-attrs,table-attrs')) {
95
- errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'section header in an HTML tag'));
94
+ if (s) {
95
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'section header in an HTML tag', s));
96
96
  }
97
97
  const rootStr = this.getRootNode().toString();
98
98
  if (boldQuotes.length % 2) {
package/dist/src/html.js CHANGED
@@ -134,15 +134,17 @@ let HtmlToken = (() => {
134
134
  }
135
135
  /** @private */
136
136
  lint(start = this.getAbsoluteIndex(), re) {
137
- const errors = super.lint(start, re), { name, parentNode, closing, selfClosing } = this, rect = new rect_1.BoundingRect(this, start);
137
+ const errors = super.lint(start, re), { name, parentNode, closing, selfClosing } = this, rect = new rect_1.BoundingRect(this, start), s = this.inTableAttrs();
138
138
  if (name === 'h1' && !closing) {
139
139
  const e = (0, lint_1.generateForSelf)(this, rect, 'h1', '<h1>');
140
140
  e.suggestions = [{ desc: 'h2', range: [start + 2, start + 3], text: '2' }];
141
141
  errors.push(e);
142
142
  }
143
- if (this.closest('table-attrs')) {
144
- const e = (0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'HTML tag in table attributes');
145
- e.fix = { desc: 'remove', range: [start, e.endIndex], text: '' };
143
+ if (s) {
144
+ const e = (0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'HTML tag in table attributes', s);
145
+ if (s === 'error') {
146
+ e.fix = { desc: 'remove', range: [start, e.endIndex], text: '' };
147
+ }
146
148
  errors.push(e);
147
149
  }
148
150
  if (obsoleteTags.has(name)) {
package/dist/src/index.js CHANGED
@@ -11,7 +11,7 @@
11
11
  // 6. 内链,含文件和分类,参见Parser::handleInternalLinks2
12
12
  // 7. `'`,参见Parser::doQuotes
13
13
  // 8. 外链,参见Parser::handleExternalLinks
14
- // 9. ISBN、RFC(未来将废弃,不予支持)和自由外链,参见Parser::handleMagicLinks
14
+ // 9. ISBN、RFC和自由外链,参见Parser::handleMagicLinks
15
15
  // 10. 段落和列表,参见BlockLevelPass::execute
16
16
  // 11. 转换,参见LanguageConverter::recursiveConvertTopLevel
17
17
  // \0\d+.\x7F标记Token:
@@ -354,6 +354,14 @@ class Token extends element_1.AstElement {
354
354
  return index_1.default.normalizeTitle(title, defaultNs, this.#include, this.#config, opt);
355
355
  }
356
356
  /** @private */
357
+ inTableAttrs() {
358
+ return this.closest('table-attrs,ext')?.type === 'table-attrs' && (this.closest('table-attrs,arg,magic-word,template')?.type === 'table-attrs' ? 'error' : 'warning');
359
+ }
360
+ /** @private */
361
+ inHtmlAttrs() {
362
+ return this.closest('html-attrs,ext')?.type === 'html-attrs' ? 'error' : this.inTableAttrs();
363
+ }
364
+ /** @private */
357
365
  lint(start = this.getAbsoluteIndex(), re) {
358
366
  let errors = super.lint(start, re);
359
367
  if (this.type === 'root') {
@@ -9,6 +9,7 @@ declare type GalleryTypes = 'gallery' | 'imagemap';
9
9
  * 图库图片
10
10
  */
11
11
  export declare abstract class GalleryImageToken extends FileToken {
12
+ #private;
12
13
  get type(): `${GalleryTypes}-image`;
13
14
  /**
14
15
  * @param type 图片类型
@@ -89,10 +89,16 @@ let GalleryImageToken = (() => {
89
89
  const imagemap = this.type === 'imagemap-image';
90
90
  return this.normalizeTitle(this.firstChild.toString(), imagemap ? 0 : 6, { halfParsed: true, temporary, decode: !imagemap });
91
91
  }
92
+ /** 判定无效的图片 */
93
+ #lint() {
94
+ const { ns, } = this.getAttribute('title');
95
+ // eslint-disable-next-line @stylistic/semi
96
+ return ns !== 6;
97
+ }
92
98
  /** @private */
93
99
  lint(start = this.getAbsoluteIndex(), re) {
94
- const errors = super.lint(start, re), { ns, } = this.getAttribute('title');
95
- if (ns !== 6) {
100
+ const errors = super.lint(start, re);
101
+ if (this.#lint()) {
96
102
  const e = (0, lint_1.generateForSelf)(this, { start }, 'invalid-gallery', 'invalid gallery image');
97
103
  e.suggestions = [{ desc: 'prefix', range: [start, start], text: 'File:' }];
98
104
  errors.push(e);
@@ -53,19 +53,27 @@ class MagicLinkToken extends index_2.Token {
53
53
  super(url, config, accum, {});
54
54
  this.#type = type;
55
55
  }
56
- /** @private */
57
- lint(start = this.getAbsoluteIndex(), re) {
58
- const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start), { type, childNodes } = this;
59
- if (type === 'magic-link') {
56
+ /** 判定无效的ISBN */
57
+ #lint() {
58
+ if (this.type === 'magic-link') {
60
59
  const { link } = this;
61
60
  if (link.startsWith('ISBN')) {
62
61
  // eslint-disable-next-line unicorn/no-useless-spread, @typescript-eslint/no-misused-spread
63
62
  const digits = [...link.slice(5)].map(s => s === 'X' ? 10 : Number(s));
64
- if (digits.length === 10 && digits.reduce((sum, d, i) => sum + d * (10 - i), 0) % 11
65
- || digits.length === 13 && (digits[12] === 10
66
- || digits.reduce((sum, d, i) => sum + d * (i % 2 ? 3 : 1), 0) % 10)) {
67
- errors.push((0, lint_1.generateForSelf)(this, rect, 'invalid-isbn', 'invalid ISBN'));
68
- }
63
+ return digits.length === 10
64
+ ? digits.reduce((sum, d, i) => sum + d * (10 - i), 0) % 11 !== 0
65
+ : digits.length === 13 && (digits[12] === 10
66
+ || digits.reduce((sum, d, i) => sum + d * (i % 2 ? 3 : 1), 0) % 10 !== 0);
67
+ }
68
+ }
69
+ return false;
70
+ }
71
+ /** @private */
72
+ lint(start = this.getAbsoluteIndex(), re) {
73
+ const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start), { type, childNodes } = this;
74
+ if (type === 'magic-link') {
75
+ if (this.#lint()) {
76
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'invalid-isbn', 'invalid ISBN'));
69
77
  }
70
78
  return errors;
71
79
  }
@@ -99,7 +107,7 @@ class MagicLinkToken extends index_2.Token {
99
107
  .getUrl(articlePath);
100
108
  }
101
109
  link = link.startsWith('RFC')
102
- ? `https://tools.ietf.org/html/rfc${link.slice(4)}`
110
+ ? `https://datatracker.ietf.org/doc/html/rfc${link.slice(4)}`
103
111
  : `https://pubmed.ncbi.nlm.nih.gov/${link.slice(5)}`;
104
112
  }
105
113
  else if (link.startsWith('//')) {
@@ -7,6 +7,7 @@ import type { AttributesToken, ExtToken } from '../../internal';
7
7
  * 扩展标签内的纯文字Token
8
8
  */
9
9
  export declare abstract class NowikiToken extends NowikiBaseToken {
10
+ #private;
10
11
  readonly name: string;
11
12
  abstract get nextSibling(): undefined;
12
13
  abstract get previousSibling(): AttributesToken | undefined;
@@ -19,10 +19,15 @@ class NowikiToken extends base_1.NowikiBaseToken {
19
19
  get type() {
20
20
  return 'ext-inner';
21
21
  }
22
+ /** 扩展标签内的无效内容 */
23
+ #lint() {
24
+ const { name, firstChild: { data } } = this;
25
+ return voidExt.has(name) && Boolean(data);
26
+ }
22
27
  /** @private */
23
28
  lint(start = this.getAbsoluteIndex()) {
24
- const { name, firstChild: { data } } = this;
25
- if (voidExt.has(name) && data) {
29
+ const { name } = this;
30
+ if (this.#lint()) {
26
31
  const e = (0, lint_1.generateForSelf)(this, { start }, 'void-ext', index_1.default.msg('nothing should be in <$1>', name));
27
32
  e.fix = { range: [start, e.endIndex], text: '', desc: 'empty' };
28
33
  return [e];
@@ -4,34 +4,6 @@ exports.TrBaseToken = void 0;
4
4
  const lint_1 = require("../../util/lint");
5
5
  const base_1 = require("./base");
6
6
  const td_1 = require("./td");
7
- const tableTags = new Set(['tr', 'td', 'th', 'caption']), tableTemplates = new Set(['Template:!!', 'Template:!-']);
8
- /**
9
- * Check if the content is fostered
10
- * @param token
11
- */
12
- const isFostered = (token) => {
13
- const first = token.childNodes.find(child => child.text().trim());
14
- if (!first
15
- || first.type === 'text' && first.data.trim().startsWith('!')
16
- || first.type === 'magic-word' && first.name === '!'
17
- || first.type === 'template' && tableTemplates.has(first.name)
18
- || first.is('html') && tableTags.has(first.name)) {
19
- return false;
20
- }
21
- else if (first.is('arg')) {
22
- return first.length > 1 && isFostered(first.childNodes[1]);
23
- }
24
- else if (first.is('magic-word')) {
25
- try {
26
- const severity = first.getPossibleValues().map(isFostered);
27
- return severity.includes('error')
28
- ? 'error'
29
- : severity.includes('warning') && 'warning';
30
- }
31
- catch { }
32
- }
33
- return first.type === 'template' || first.type === 'magic-word' && first.name === 'invoke' ? 'warning' : 'error';
34
- };
35
7
  /**
36
8
  * table row or table
37
9
  *
@@ -44,7 +16,7 @@ class TrBaseToken extends base_1.TableBaseToken {
44
16
  if (!inter) {
45
17
  return errors;
46
18
  }
47
- const severity = isFostered(inter);
19
+ const severity = (0, lint_1.isFostered)(inter);
48
20
  if (!severity) {
49
21
  return errors;
50
22
  }
@@ -185,8 +185,11 @@ let ExtToken = (() => {
185
185
  /** @private */
186
186
  lint(start = this.getAbsoluteIndex(), re) {
187
187
  const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start);
188
- if (this.name !== 'nowiki' && this.closest('html-attrs,table-attrs')) {
189
- errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'extension tag in HTML tag attributes'));
188
+ if (this.name !== 'nowiki') {
189
+ const s = this.inHtmlAttrs();
190
+ if (s) {
191
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'extension tag in HTML tag attributes', s));
192
+ }
190
193
  }
191
194
  if (this.name === 'ref' && this.closest('heading-title')) {
192
195
  errors.push((0, lint_1.generateForSelf)(this, rect, 'var-anchor', 'variable anchor in a section header'));
package/dist/util/lint.js CHANGED
@@ -3,10 +3,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.provideValues = exports.cache = exports.generateForSelf = exports.generateForChild = exports.getEndPos = void 0;
6
+ exports.provideValues = exports.cache = exports.generateForSelf = exports.generateForChild = exports.getEndPos = exports.isFostered = void 0;
7
7
  const debug_1 = require("./debug");
8
8
  const rect_1 = require("../lib/rect");
9
9
  const index_1 = __importDefault(require("../index"));
10
+ const tableTags = new Set(['tr', 'td', 'th', 'caption']), tableTemplates = new Set(['Template:!!', 'Template:!-']);
11
+ /**
12
+ * Check if the content is fostered
13
+ * @param token
14
+ */
15
+ const isFostered = (token) => {
16
+ const first = token.childNodes.find(child => child.text().trim());
17
+ if (!first
18
+ || first.type === 'text' && first.data.trim().startsWith('!')
19
+ || first.type === 'magic-word' && first.name === '!'
20
+ || first.type === 'template' && tableTemplates.has(first.name)
21
+ || first.is('html') && tableTags.has(first.name)) {
22
+ return false;
23
+ }
24
+ else if (first.is('arg')) {
25
+ return first.length > 1 && (0, exports.isFostered)(first.childNodes[1]);
26
+ }
27
+ else if (first.is('magic-word')) {
28
+ try {
29
+ const severity = first.getPossibleValues().map(exports.isFostered);
30
+ return severity.includes('error')
31
+ ? 'error'
32
+ : severity.includes('warning') && 'warning';
33
+ }
34
+ catch { }
35
+ }
36
+ return first.type === 'template' || first.type === 'magic-word' && first.name === 'invoke' ? 'warning' : 'error';
37
+ };
38
+ exports.isFostered = isFostered;
10
39
  /**
11
40
  * 计算结束位置
12
41
  * @param top 起始行
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikilint",
3
- "version": "2.21.0",
3
+ "version": "2.21.1",
4
4
  "description": "A Node.js linter for MediaWiki markup",
5
5
  "keywords": [
6
6
  "mediawiki",
@@ -77,14 +77,13 @@
77
77
  "entities": "^6.0.0",
78
78
  "mathjax": "^3.2.2",
79
79
  "minimatch": "^10.0.1",
80
- "stylelint": "^16.19.1",
80
+ "stylelint": "^16.20.0",
81
81
  "vscode-css-languageservice": "^6.3.4",
82
82
  "vscode-html-languageservice": "^5.3.3",
83
83
  "vscode-json-languageservice": "^5.4.4"
84
84
  },
85
85
  "devDependencies": {
86
86
  "@stylistic/eslint-plugin": "^3.1.0",
87
- "@stylistic/stylelint-plugin": "^3.1.2",
88
87
  "@types/color-name": "^2.0.0",
89
88
  "@types/color-rgba": "^2.1.3",
90
89
  "@types/mocha": "^10.0.10",
@@ -102,11 +101,10 @@
102
101
  "eslint-plugin-promise": "^7.2.1",
103
102
  "eslint-plugin-regexp": "^2.7.0",
104
103
  "eslint-plugin-unicorn": "^56.0.1",
105
- "http-server": "^14.1.1",
106
104
  "mocha": "^11.1.0",
107
105
  "nyc": "^17.1.0",
108
106
  "typescript": "^5.8.2",
109
- "v8r": "^4.2.1",
107
+ "v8r": "^5.0.0",
110
108
  "vscode-languageserver-textdocument": "^1.0.12"
111
109
  },
112
110
  "engines": {