wikiparser-node 1.4.4 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -8,11 +8,11 @@
8
8
 
9
9
  # Introduction
10
10
 
11
- wikiparser-node is an offline [Wikitext](https://www.mediawiki.org/wiki/Wikitext) parser developed by Bhsd for the [Node.js](https://nodejs.org/) environment. It can parse almost all wiki syntax and generate an [Abstract Syntax Tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) ([Try it online](https://bhsd-harry.github.io/wikiparser-node/#editor)). It also allows for easy querying and modification of the AST, and returns the modified wikitext.
11
+ WikiParser-Node is an offline [Wikitext](https://www.mediawiki.org/wiki/Wikitext) parser developed by Bhsd for the [Node.js](https://nodejs.org/) environment. It can parse almost all wiki syntax and generate an [Abstract Syntax Tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) ([Try it online](https://bhsd-harry.github.io/wikiparser-node/#editor)). It also allows for easy querying and modification of the AST, and returns the modified wikitext.
12
12
 
13
13
  # Other Versions
14
14
 
15
- ## Mini (also known as [wikilint](https://www.npmjs.com/package/wikilint))
15
+ ## Mini (also known as [WikiLint](https://www.npmjs.com/package/wikilint))
16
16
 
17
17
  This version provides a [CLI](https://en.wikipedia.org/wiki/Command-line_interface), but only retains the parsing functionality and linting functionality. The parsed AST cannot be modified. It is used in the [eslint-plugin-wikitext](https://www.npmjs.com/package/eslint-plugin-wikitext) plugin.
18
18
 
@@ -24,7 +24,7 @@ A browser-compatible version, which can be used for code highlighting or as a li
24
24
 
25
25
  ## Node.js
26
26
 
27
- Please install the corresponding version as needed (`wikiparser-node` or `wikilint`), for example:
27
+ Please install the corresponding version as needed (`WikiParser-Node` or `WikiLint`), for example:
28
28
 
29
29
  ```sh
30
30
  npm i wikiparser-node
package/README.md CHANGED
@@ -8,11 +8,11 @@
8
8
 
9
9
  # 简介
10
10
 
11
- wikiparser-node 是一款由 Bhsd 开发的基于 [Node.js](https://nodejs.org/) 环境的离线[维基文本](https://www.mediawiki.org/wiki/Wikitext)语法解析器,可以解析几乎全部的维基语法并生成[语法树](https://en.wikipedia.org/wiki/Abstract_syntax_tree)([在线解析](https://bhsd-harry.github.io/wikiparser-node/#editor)),还可以很方便地对语法树进行查询和修改,最后返回修改后的维基文本。
11
+ WikiParser-Node 是一款由 Bhsd 开发的基于 [Node.js](https://nodejs.org/) 环境的离线[维基文本](https://www.mediawiki.org/wiki/Wikitext)语法解析器,可以解析几乎全部的维基语法并生成[语法树](https://en.wikipedia.org/wiki/Abstract_syntax_tree)([在线解析](https://bhsd-harry.github.io/wikiparser-node/#editor)),还可以很方便地对语法树进行查询和修改,最后返回修改后的维基文本。
12
12
 
13
13
  # 其他版本
14
14
 
15
- ## Mini (又名 [wikilint](https://www.npmjs.com/package/wikilint))
15
+ ## Mini (又名 [WikiLint](https://www.npmjs.com/package/wikilint))
16
16
 
17
17
  提供了 [CLI](https://en.wikipedia.org/wiki/Command-line_interface),但仅保留了解析功能和语法错误分析功能,解析生成的语法树不能修改。这个版本被应用于 [eslint-plugin-wikitext](https://www.npmjs.com/package/eslint-plugin-wikitext) 插件。
18
18
 
@@ -24,7 +24,7 @@ wikiparser-node 是一款由 Bhsd 开发的基于 [Node.js](https://nodejs.org/)
24
24
 
25
25
  ## Node.js
26
26
 
27
- 请根据需要需要安装对应的版本(`wikiparser-node` 或 `wikilint`),如:
27
+ 请根据需要需要安装对应的版本(`WikiParser-Node` 或 `WikiLint`),如:
28
28
 
29
29
  ```sh
30
30
  npm i wikiparser-node
@@ -41,13 +41,13 @@ npm i wikilint
41
41
  可以通过 CDN 下载代码,如:
42
42
 
43
43
  ```html
44
- <script src="//cdn.jsdelivr.net/npm/wikiparser-node@browser/bundle/bundle.min.js"></script>
44
+ <script src="//cdn.jsdelivr.net/npm/wikiparser-node@browser"></script>
45
45
  ```
46
46
 
47
47
 
48
48
 
49
49
  ```html
50
- <script src="//unpkg.com/wikiparser-node@browser/bundle/bundle.min.js"></script>
50
+ <script src="//unpkg.com/wikiparser-node@browser"></script>
51
51
  ```
52
52
 
53
53
  更多浏览器端可用的插件请查阅对应[文档](https://github.com/bhsd-harry/wikiparser-node/wiki/Browser)。
package/dist/base.d.ts CHANGED
@@ -14,7 +14,9 @@ export interface Config {
14
14
  readonly redirects?: [string, string][];
15
15
  }
16
16
  export type Severity = 'error' | 'warning';
17
+ export type Rule = 'bold-header' | 'format-leakage' | 'fostered-content' | 'h1' | 'illegal-attr' | 'insecure-style' | 'invalid-gallery' | 'invalid-imagemap' | 'invalid-invoke' | 'lonely-apos' | 'lonely-bracket' | 'lonely-http' | 'nested-link' | 'no-arg' | 'no-duplicate' | 'no-ignored' | 'obsolete-attr' | 'obsolete-tag' | 'parsing-order' | 'pipe-like' | 'table-layout' | 'tag-like' | 'unbalanced-header' | 'unclosed-comment' | 'unclosed-quote' | 'unclosed-table' | 'unescaped' | 'unknown-page' | 'unmatched-tag' | 'unterminated-url' | 'url-encoding' | 'var-anchor' | 'void-ext';
17
18
  export interface LintError {
19
+ readonly rule: Rule;
18
20
  readonly message: string;
19
21
  readonly severity: Severity;
20
22
  readonly startIndex: number;
package/dist/lib/text.js CHANGED
@@ -19,6 +19,13 @@ errorSyntax = new RegExp(`${source}|https?[:/]\\/+`, 'giu'), errorSyntaxUrl = ne
19
19
  '{': /[{}]/u,
20
20
  ']': /[[\]](?=[^[\]]*$)/u,
21
21
  '}': /[{}](?=[^{}]*$)/u,
22
+ }, ruleMap = {
23
+ '<': 'tag-like',
24
+ '[': 'lonely-bracket',
25
+ '{': 'lonely-bracket',
26
+ ']': 'lonely-bracket',
27
+ '}': 'lonely-bracket',
28
+ h: 'lonely-http',
22
29
  }, disallowedTags = [
23
30
  'html',
24
31
  'base',
@@ -186,6 +193,7 @@ class AstText extends node_1.AstNode {
186
193
  }
187
194
  const lines = data.slice(0, index).split('\n'), startLine = lines.length + top - 1, line = lines[lines.length - 1], startCol = lines.length === 1 ? left + line.length : line.length;
188
195
  errors.push({
196
+ rule: ruleMap[char],
189
197
  message: index_1.default.msg('lonely "$1"', char === 'h' ? error : char),
190
198
  severity,
191
199
  startIndex,
package/dist/src/arg.js CHANGED
@@ -72,7 +72,7 @@ class ArgToken extends index_2.Token {
72
72
  /** @override */
73
73
  lint(start = this.getAbsoluteIndex()) {
74
74
  if (!this.getAttribute('include')) {
75
- return [(0, lint_1.generateForSelf)(this, { start }, 'unexpected template argument')];
75
+ return [(0, lint_1.generateForSelf)(this, { start }, 'no-arg', 'unexpected template argument')];
76
76
  }
77
77
  const { childNodes: [argName, argDefault, ...rest] } = this, errors = argName.lint(start + 3);
78
78
  if (argDefault) {
@@ -81,7 +81,7 @@ class ArgToken extends index_2.Token {
81
81
  if (rest.length > 0) {
82
82
  const rect = { start, ...this.getRootNode().posFromIndex(start) };
83
83
  errors.push(...rest.map(child => {
84
- const error = (0, lint_1.generateForChild)(child, rect, 'invisible content inside triple braces');
84
+ const error = (0, lint_1.generateForChild)(child, rect, 'no-ignored', 'invisible content inside triple braces');
85
85
  return {
86
86
  ...error,
87
87
  startIndex: error.startIndex - 1,
@@ -346,7 +346,7 @@ let AttributeToken = (() => {
346
346
  if (!balanced) {
347
347
  const root = this.getRootNode();
348
348
  rect = { start, ...root.posFromIndex(start) };
349
- const e = (0, lint_1.generateForChild)(lastChild, rect, index_1.default.msg('unclosed $1', 'quotes'), 'warning');
349
+ const e = (0, lint_1.generateForChild)(lastChild, rect, 'unclosed-quote', index_1.default.msg('unclosed $1', 'quotes'), 'warning');
350
350
  errors.push({
351
351
  ...e,
352
352
  startIndex: e.startIndex - 1,
@@ -360,19 +360,19 @@ let AttributeToken = (() => {
360
360
  && !/^(?:xmlns:[\w:.-]+|data-[^:]*)$/u.test(name)
361
361
  && (tag === 'meta' || tag === 'link' || !commonHtmlAttrs.has(name))) {
362
362
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
363
- errors.push((0, lint_1.generateForChild)(firstChild, rect, 'illegal attribute name'));
363
+ errors.push((0, lint_1.generateForChild)(firstChild, rect, 'illegal-attr', 'illegal attribute name'));
364
364
  }
365
365
  else if (obsoleteAttrs[tag]?.has(name)) {
366
366
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
367
- errors.push((0, lint_1.generateForChild)(firstChild, rect, 'obsolete attribute', 'warning'));
367
+ errors.push((0, lint_1.generateForChild)(firstChild, rect, 'obsolete-attr', 'obsolete attribute', 'warning'));
368
368
  }
369
369
  else if (name === 'style' && typeof value === 'string' && insecureStyle.test(value)) {
370
370
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
371
- errors.push((0, lint_1.generateForChild)(lastChild, rect, 'insecure style'));
371
+ errors.push((0, lint_1.generateForChild)(lastChild, rect, 'insecure-style', 'insecure style'));
372
372
  }
373
373
  else if (name === 'tabindex' && typeof value === 'string' && value.trim() !== '0') {
374
374
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
375
- errors.push((0, lint_1.generateForChild)(lastChild, rect, 'nonzero tabindex'));
375
+ errors.push((0, lint_1.generateForChild)(lastChild, rect, 'illegal-attr', 'nonzero tabindex'));
376
376
  }
377
377
  return errors;
378
378
  }
@@ -149,13 +149,13 @@ class AttributesToken extends index_2.Token {
149
149
  let rect;
150
150
  if (parentNode?.type === 'html' && parentNode.closing && this.text().trim()) {
151
151
  rect = { start, ...this.getRootNode().posFromIndex(start) };
152
- errors.push((0, lint_1.generateForSelf)(this, rect, 'attributes of a closing tag'));
152
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'no-ignored', 'attributes of a closing tag'));
153
153
  }
154
154
  for (let i = 0; i < length; i++) {
155
155
  const attr = childNodes[i];
156
156
  if (attr instanceof atom_1.AtomToken && attr.text().trim()) {
157
157
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
158
- errors.push((0, lint_1.generateForChild)(attr, rect, 'containing invalid attribute'));
158
+ errors.push((0, lint_1.generateForChild)(attr, rect, 'no-ignored', 'containing invalid attribute'));
159
159
  }
160
160
  else if (attr instanceof attribute_1.AttributeToken) {
161
161
  const { name } = attr;
@@ -171,7 +171,7 @@ class AttributesToken extends index_2.Token {
171
171
  if (duplicated.size > 0) {
172
172
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
173
173
  for (const key of duplicated) {
174
- errors.push(...attrs.get(key).map(attr => (0, lint_1.generateForChild)(attr, rect, index_1.default.msg('duplicated $1 attribute', key))));
174
+ errors.push(...attrs.get(key).map(attr => (0, lint_1.generateForChild)(attr, rect, 'no-duplicate', index_1.default.msg('duplicated $1 attribute', key))));
175
175
  }
176
176
  }
177
177
  return errors;
@@ -78,7 +78,7 @@ class ConverterFlagsToken extends index_2.Token {
78
78
  && !variantFlags.has(flag)
79
79
  && !unknownFlags.has(flag)
80
80
  && (variantFlags.size > 0 || !validFlags.has(flag))) {
81
- errors.push((0, lint_1.generateForChild)(child, rect, 'invalid conversion flag'));
81
+ errors.push((0, lint_1.generateForChild)(child, rect, 'no-ignored', 'invalid conversion flag'));
82
82
  }
83
83
  }
84
84
  return errors;
@@ -130,7 +130,7 @@ let ExtLinkToken = (() => {
130
130
  lint(start = this.getAbsoluteIndex()) {
131
131
  const errors = super.lint(start);
132
132
  if (this.length === 1 && this.closest('heading-title')) {
133
- errors.push((0, lint_1.generateForSelf)(this, { start }, 'variable anchor in a section header'));
133
+ errors.push((0, lint_1.generateForSelf)(this, { start }, 'var-anchor', 'variable anchor in a section header'));
134
134
  }
135
135
  return errors;
136
136
  }
@@ -67,6 +67,7 @@ class GalleryToken extends index_2.Token {
67
67
  const child = this.childNodes[i], str = String(child), { length } = str, trimmed = str.trim(), startLine = top + i, startCol = i ? 0 : left;
68
68
  if (child.type === 'noinclude' && trimmed && !/^<!--.*-->$/u.test(trimmed)) {
69
69
  errors.push({
70
+ rule: 'no-ignored',
70
71
  message: index_1.default.msg('invalid content in <$1>', 'gallery'),
71
72
  severity: 'error',
72
73
  startIndex: start,
@@ -129,23 +129,23 @@ let HeadingToken = (() => {
129
129
  let rect;
130
130
  if (this.level === 1) {
131
131
  rect = { start, ...this.getRootNode().posFromIndex(start) };
132
- errors.push((0, lint_1.generateForChild)(firstChild, rect, '<h1>'));
132
+ errors.push((0, lint_1.generateForChild)(firstChild, rect, 'h1', '<h1>'));
133
133
  }
134
134
  if (innerStr.startsWith('=') || innerStr.endsWith('=')) {
135
135
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
136
- errors.push((0, lint_1.generateForChild)(firstChild, rect, index_1.default.msg('unbalanced $1 in a section header', '"="')));
136
+ errors.push((0, lint_1.generateForChild)(firstChild, rect, 'unbalanced-header', index_1.default.msg('unbalanced $1 in a section header', '"="')));
137
137
  }
138
138
  if (this.closest('html-attrs, table-attrs')) {
139
139
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
140
- errors.push((0, lint_1.generateForSelf)(this, rect, 'section header in a HTML tag'));
140
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'section header in a HTML tag'));
141
141
  }
142
142
  if (boldQuotes.length % 2) {
143
143
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
144
- errors.push((0, lint_1.generateForChild)(boldQuotes[boldQuotes.length - 1], { ...rect, start: start + level, left: rect.left + level }, index_1.default.msg('unbalanced $1 in a section header', 'bold apostrophes')));
144
+ errors.push((0, lint_1.generateForChild)(boldQuotes[boldQuotes.length - 1], { ...rect, start: start + level, left: rect.left + level }, 'format-leakage', index_1.default.msg('unbalanced $1 in a section header', 'bold apostrophes')));
145
145
  }
146
146
  if (italicQuotes.length % 2) {
147
147
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
148
- errors.push((0, lint_1.generateForChild)(italicQuotes[italicQuotes.length - 1], { start: start + level }, index_1.default.msg('unbalanced $1 in a section header', 'italic apostrophes')));
148
+ errors.push((0, lint_1.generateForChild)(italicQuotes[italicQuotes.length - 1], { start: start + level }, 'format-leakage', index_1.default.msg('unbalanced $1 in a section header', 'italic apostrophes')));
149
149
  }
150
150
  return errors;
151
151
  }
package/dist/src/html.js CHANGED
@@ -181,13 +181,14 @@ let HtmlToken = (() => {
181
181
  const errors = super.lint(start);
182
182
  let refError;
183
183
  if (this.name === 'h1' && !this.closing) {
184
- refError = (0, lint_1.generateForSelf)(this, { start }, '<h1>');
184
+ refError = (0, lint_1.generateForSelf)(this, { start }, 'h1', '<h1>');
185
185
  errors.push(refError);
186
186
  }
187
187
  if (this.closest('table-attrs')) {
188
- refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
188
+ refError ??= (0, lint_1.generateForSelf)(this, { start }, 'h1', '');
189
189
  errors.push({
190
190
  ...refError,
191
+ rule: 'parsing-order',
191
192
  message: index_1.default.msg('HTML tag in table attributes'),
192
193
  });
193
194
  }
@@ -197,8 +198,8 @@ let HtmlToken = (() => {
197
198
  catch (e) {
198
199
  if (e instanceof SyntaxError) {
199
200
  const { message } = e;
200
- refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
201
- const [msg] = message.split(':'), error = { ...refError, message: index_1.default.msg(msg) };
201
+ refError ??= (0, lint_1.generateForSelf)(this, { start }, 'h1', '');
202
+ const [msg] = message.split(':'), error = { ...refError, rule: 'unmatched-tag', message: index_1.default.msg(msg) };
202
203
  if (msg === 'unclosed tag' && !this.closest('heading-title')) {
203
204
  if (formattingTags.has(this.name)) {
204
205
  const childNodes = this.parentNode?.childNodes, i = childNodes?.indexOf(this);
@@ -220,17 +221,19 @@ let HtmlToken = (() => {
220
221
  }
221
222
  }
222
223
  if (obsoleteTags.has(this.name)) {
223
- refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
224
+ refError ??= (0, lint_1.generateForSelf)(this, { start }, 'h1', '');
224
225
  errors.push({
225
226
  ...refError,
227
+ rule: 'obsolete-tag',
226
228
  message: index_1.default.msg('obsolete HTML tag'),
227
229
  severity: 'warning',
228
230
  });
229
231
  }
230
232
  if ((this.name === 'b' || this.name === 'strong') && this.closest('heading-title')) {
231
- refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
233
+ refError ??= (0, lint_1.generateForSelf)(this, { start }, 'h1', '');
232
234
  errors.push({
233
235
  ...refError,
236
+ rule: 'format-leakage',
234
237
  message: index_1.default.msg('bold in section header'),
235
238
  severity: 'warning',
236
239
  });
@@ -168,10 +168,10 @@ class ImageParameterToken extends index_2.Token {
168
168
  lint(start = this.getAbsoluteIndex()) {
169
169
  const errors = super.lint(start), { link, name } = this;
170
170
  if (name === 'invalid') {
171
- errors.push((0, lint_1.generateForSelf)(this, { start }, 'invalid gallery image parameter'));
171
+ errors.push((0, lint_1.generateForSelf)(this, { start }, 'invalid-gallery', 'invalid gallery image parameter'));
172
172
  }
173
173
  else if (typeof link === 'object' && link.encoded) {
174
- errors.push((0, lint_1.generateForSelf)(this, { start }, 'unnecessary URL encoding in an internal link'));
174
+ errors.push((0, lint_1.generateForSelf)(this, { start }, 'url-encoding', 'unnecessary URL encoding in an internal link'));
175
175
  }
176
176
  return errors;
177
177
  }
@@ -103,10 +103,10 @@ class ImagemapToken extends index_2.Token {
103
103
  errors.push(...this.childNodes.filter(child => {
104
104
  const str = String(child).trim();
105
105
  return child.type === 'noinclude' && str && !str.startsWith('#');
106
- }).map(child => (0, lint_1.generateForChild)(child, rect, 'invalid link in <imagemap>')));
106
+ }).map(child => (0, lint_1.generateForChild)(child, rect, 'invalid-imagemap', 'invalid link in <imagemap>')));
107
107
  }
108
108
  else {
109
- errors.push((0, lint_1.generateForSelf)(this, rect, '<imagemap> without an image'));
109
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'invalid-imagemap', '<imagemap> without an image'));
110
110
  }
111
111
  return errors;
112
112
  }
package/dist/src/index.js CHANGED
@@ -414,7 +414,7 @@ class Token extends element_1.AstElement {
414
414
  }
415
415
  for (const value of Object.values(record)) {
416
416
  if (value.size > 1) {
417
- errors.push(...[...value].map(cat => (0, lint_1.generateForSelf)(cat, { start: cat.getAbsoluteIndex() }, 'duplicated category')));
417
+ errors.push(...[...value].map(cat => (0, lint_1.generateForSelf)(cat, { start: cat.getAbsoluteIndex() }, 'no-duplicate', 'duplicated category')));
418
418
  }
419
419
  }
420
420
  }
@@ -135,20 +135,20 @@ class LinkBaseToken extends index_2.Token {
135
135
  let rect;
136
136
  if (target.childNodes.some(({ type }) => type === 'template')) {
137
137
  rect = { start, ...this.getRootNode().posFromIndex(start) };
138
- errors.push((0, lint_1.generateForChild)(target, rect, 'template in an internal link target', 'warning'));
138
+ errors.push((0, lint_1.generateForChild)(target, rect, 'unknown-page', 'template in an internal link target', 'warning'));
139
139
  }
140
140
  if (encoded) {
141
141
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
142
- errors.push((0, lint_1.generateForChild)(target, rect, 'unnecessary URL encoding in an internal link'));
142
+ errors.push((0, lint_1.generateForChild)(target, rect, 'url-encoding', 'unnecessary URL encoding in an internal link'));
143
143
  }
144
144
  if ((linkType === 'link' || linkType === 'category')
145
145
  && linkText?.childNodes.some(({ type, data }) => type === 'text' && data.includes('|'))) {
146
146
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
147
- errors.push((0, lint_1.generateForChild)(linkText, rect, 'additional "|" in the link text', 'warning'));
147
+ errors.push((0, lint_1.generateForChild)(linkText, rect, 'pipe-like', 'additional "|" in the link text', 'warning'));
148
148
  }
149
149
  else if (linkType !== 'link' && fragment !== undefined) {
150
150
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
151
- errors.push((0, lint_1.generateForChild)(target, rect, 'useless fragment'));
151
+ errors.push((0, lint_1.generateForChild)(target, rect, 'no-ignored', 'useless fragment'));
152
152
  }
153
153
  return errors;
154
154
  }
@@ -104,7 +104,7 @@ class FileToken extends base_1.LinkBaseToken {
104
104
  return visibleNodes.length !== 1 || visibleNodes[0].type !== 'arg';
105
105
  }), keys = [...new Set(args.map(({ name }) => name))].filter(key => key !== 'invalid'), frameKeys = keys.filter(key => frame.has(key)), horizAlignKeys = keys.filter(key => horizAlign.has(key)), vertAlignKeys = keys.filter(key => vertAlign.has(key));
106
106
  if (this.closest('ext-link-text') && this.getValue('link')?.trim() !== '') {
107
- errors.push((0, lint_1.generateForSelf)(this, { start }, 'internal link in an external link'));
107
+ errors.push((0, lint_1.generateForSelf)(this, { start }, 'nested-link', 'internal link in an external link'));
108
108
  }
109
109
  if (args.length === keys.length
110
110
  && frameKeys.length < 2
@@ -118,7 +118,7 @@ class FileToken extends base_1.LinkBaseToken {
118
118
  * @param msg 消息键
119
119
  * @param p1 替换$1
120
120
  */
121
- const generate = (msg, p1) => (arg) => (0, lint_1.generateForChild)(arg, rect, index_1.default.msg(`${msg} image $1 parameter`, p1));
121
+ const generate = (msg, p1) => (arg) => (0, lint_1.generateForChild)(arg, rect, 'no-duplicate', index_1.default.msg(`${msg} image $1 parameter`, p1));
122
122
  for (const key of keys) {
123
123
  let relevantArgs = args.filter(({ name }) => name === key);
124
124
  if (key === 'caption') {
@@ -102,7 +102,7 @@ let GalleryImageToken = (() => {
102
102
  lint(start = this.getAbsoluteIndex()) {
103
103
  const errors = super.lint(start), { ns, interwiki } = this.getAttribute('title');
104
104
  if (interwiki || ns !== 6) {
105
- errors.push((0, lint_1.generateForSelf)(this, { start }, 'invalid gallery image'));
105
+ errors.push((0, lint_1.generateForSelf)(this, { start }, 'invalid-gallery', 'invalid gallery image'));
106
106
  }
107
107
  return errors;
108
108
  }
@@ -51,7 +51,7 @@ class LinkToken extends base_1.LinkBaseToken {
51
51
  lint(start = this.getAbsoluteIndex()) {
52
52
  const errors = super.lint(start);
53
53
  if (this.closest('ext-link-text')) {
54
- errors.push((0, lint_1.generateForSelf)(this, { start }, 'internal link in an external link'));
54
+ errors.push((0, lint_1.generateForSelf)(this, { start }, 'nested-link', 'internal link in an external link'));
55
55
  }
56
56
  return errors;
57
57
  }
@@ -111,7 +111,7 @@ let MagicLinkToken = (() => {
111
111
  continue;
112
112
  }
113
113
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
114
- const refError = (0, lint_1.generateForChild)(child, rect, '', 'warning');
114
+ const refError = (0, lint_1.generateForChild)(child, rect, 'unterminated-url', '', 'warning');
115
115
  regexGlobal.lastIndex = 0;
116
116
  for (let mt = regexGlobal.exec(data); mt; mt = regexGlobal.exec(data)) {
117
117
  const { index, 0: s } = mt, lines = data.slice(0, index).split('\n'), top = lines.length, left = lines[top - 1].length, startIndex = refError.startIndex + index, startLine = refError.startLine + top - 1, startCol = top === 1 ? refError.startCol + left : left;
@@ -61,7 +61,7 @@ class NestedToken extends index_2.Token {
61
61
  return str && !/^<!--.*-->$/su.test(str);
62
62
  }).map(child => {
63
63
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
64
- return (0, lint_1.generateForChild)(child, rect, index_1.default.msg('invalid content in <$1>', this.name));
64
+ return (0, lint_1.generateForChild)(child, rect, 'no-ignored', index_1.default.msg('invalid content in <$1>', this.name));
65
65
  }),
66
66
  ];
67
67
  }
@@ -31,7 +31,9 @@ class CommentToken extends (0, hidden_1.hiddenToken)(base_1.NowikiBaseToken) {
31
31
  }
32
32
  /** @override */
33
33
  lint(start = this.getAbsoluteIndex()) {
34
- return this.closed ? [] : [(0, lint_1.generateForSelf)(this, { start }, index_1.default.msg('unclosed $1', 'HTML comment'))];
34
+ return this.closed
35
+ ? []
36
+ : [(0, lint_1.generateForSelf)(this, { start }, 'unclosed-comment', index_1.default.msg('unclosed $1', 'HTML comment'))];
35
37
  }
36
38
  /** @private */
37
39
  toString() {
@@ -13,7 +13,7 @@ class NowikiToken extends base_1.NowikiBaseToken {
13
13
  lint(start = this.getAbsoluteIndex()) {
14
14
  const { name, firstChild: { data } } = this;
15
15
  return (name === 'templatestyles' || name === 'section') && data
16
- ? [(0, lint_1.generateForSelf)(this, { start }, index_1.default.msg('nothing should be in <$1>', name))]
16
+ ? [(0, lint_1.generateForSelf)(this, { start }, 'void-ext', index_1.default.msg('nothing should be in <$1>', name))]
17
17
  : super.lint(start);
18
18
  }
19
19
  }
@@ -70,7 +70,7 @@ let QuoteToken = (() => {
70
70
  const { previousSibling, nextSibling, bold } = this, message = index_1.default.msg('lonely "$1"', `'`), errors = [];
71
71
  let refError;
72
72
  if (previousSibling?.type === 'text' && previousSibling.data.endsWith(`'`)) {
73
- refError = (0, lint_1.generateForSelf)(this, { start }, message);
73
+ refError = (0, lint_1.generateForSelf)(this, { start }, 'lonely-apos', message);
74
74
  const { startIndex: endIndex, startLine: endLine, startCol: endCol } = refError, [, { length }] = /(?:^|[^'])('+)$/u.exec(previousSibling.data), startIndex = start - length;
75
75
  errors.push({
76
76
  ...refError,
@@ -82,7 +82,7 @@ let QuoteToken = (() => {
82
82
  });
83
83
  }
84
84
  if (nextSibling?.type === 'text' && nextSibling.data.startsWith(`'`)) {
85
- refError ??= (0, lint_1.generateForSelf)(this, { start }, message);
85
+ refError ??= (0, lint_1.generateForSelf)(this, { start }, 'lonely-apos', message);
86
86
  const { endIndex: startIndex, endLine: startLine, endCol: startCol } = refError, [{ length }] = /^'+/u.exec(nextSibling.data), endIndex = startIndex + length;
87
87
  errors.push({
88
88
  ...refError,
@@ -94,9 +94,10 @@ let QuoteToken = (() => {
94
94
  });
95
95
  }
96
96
  if (bold && this.closest('heading-title')) {
97
- refError ??= (0, lint_1.generateForSelf)(this, { start }, message);
97
+ refError ??= (0, lint_1.generateForSelf)(this, { start }, 'lonely-apos', message);
98
98
  errors.push({
99
99
  ...refError,
100
+ rule: 'bold-header',
100
101
  message: index_1.default.msg('bold in section header'),
101
102
  severity: 'warning',
102
103
  });
@@ -47,7 +47,7 @@ class ParamTagToken extends index_2.Token {
47
47
  return str && !(i >= 0 ? /^[a-z]+(?:\[\])?\s*(?:=|$)/iu : /^[a-z]+(?:\[\])?\s*=/iu).test(str);
48
48
  }).map(child => {
49
49
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
50
- return (0, lint_1.generateForChild)(child, rect, index_1.default.msg('invalid parameter of <$1>', this.name));
50
+ return (0, lint_1.generateForChild)(child, rect, 'no-ignored', index_1.default.msg('invalid parameter of <$1>', this.name));
51
51
  });
52
52
  }
53
53
  /** @override */
@@ -158,7 +158,7 @@ let ParameterToken = (() => {
158
158
  /https?:\/\/(?:\[[\da-f:.]+\]|[^[\]<>"\t\n\p{Zs}])(?:[^[\]<>"\0\t\n\p{Zs}]|\0\d+c\x7F)*$/iu;
159
159
  const errors = super.lint(start), { firstChild } = this, link = new RegExp(`https?://${string_1.extUrlCharFirst}${string_1.extUrlChar}$`, 'iu').exec(firstChild.text())?.[0];
160
160
  if (link && new URL(link).search) {
161
- const e = (0, lint_1.generateForChild)(firstChild, { start }, 'unescaped query string in an anonymous parameter');
161
+ const e = (0, lint_1.generateForChild)(firstChild, { start }, 'unescaped', 'unescaped query string in an anonymous parameter');
162
162
  errors.push({
163
163
  ...e,
164
164
  startIndex: e.endIndex,
@@ -41,7 +41,7 @@ class TableToken extends trBase_1.TrBaseToken {
41
41
  lint(start = this.getAbsoluteIndex()) {
42
42
  const errors = super.lint(start);
43
43
  if (!this.closed) {
44
- errors.push((0, lint_1.generateForChild)(this.firstChild, { start }, index_1.default.msg('unclosed $1', 'table')));
44
+ errors.push((0, lint_1.generateForChild)(this.firstChild, { start }, 'unclosed-table', index_1.default.msg('unclosed $1', 'table')));
45
45
  }
46
46
  /* NOT FOR BROWSER */
47
47
  const layout = this.getLayout(), { length } = layout;
@@ -49,7 +49,7 @@ class TableToken extends trBase_1.TrBaseToken {
49
49
  const j = new Array(length - 1).fill(undefined)
50
50
  .findIndex((_, i) => layout[i].length !== layout[i + 1].length) + 1;
51
51
  if (j) {
52
- errors.push((0, lint_1.generateForChild)(this.getNthRow(j), { start }, 'inconsistent table layout', 'warning'));
52
+ errors.push((0, lint_1.generateForChild)(this.getNthRow(j), { start }, 'table-layout', 'inconsistent table layout', 'warning'));
53
53
  }
54
54
  }
55
55
  /* NOT FOR BROWSER END */
@@ -193,7 +193,7 @@ let TdToken = (() => {
193
193
  if (child.type === 'text') {
194
194
  const { data } = child;
195
195
  if (data.includes('|')) {
196
- errors.push((0, lint_1.generateForChild)(child, { start }, 'additional "|" in a table cell', data.includes('||') ? 'error' : 'warning'));
196
+ errors.push((0, lint_1.generateForChild)(child, { start }, 'pipe-like', 'additional "|" in a table cell', data.includes('||') ? 'error' : 'warning'));
197
197
  }
198
198
  }
199
199
  }
@@ -29,7 +29,7 @@ class TrBaseToken extends base_1.TableBaseToken {
29
29
  }
30
30
  catch { }
31
31
  }
32
- const error = (0, lint_1.generateForChild)(inter, { start }, 'content to be moved out from the table');
32
+ const error = (0, lint_1.generateForChild)(inter, { start }, 'fostered-content', 'content to be moved out from the table');
33
33
  errors.push({
34
34
  ...error,
35
35
  severity: first.type === 'template' ? 'warning' : 'error',
@@ -177,11 +177,11 @@ let ExtToken = (() => {
177
177
  let rect;
178
178
  if (this.name !== 'nowiki' && this.closest('html-attrs, table-attrs')) {
179
179
  rect = { start, ...this.getRootNode().posFromIndex(start) };
180
- errors.push((0, lint_1.generateForSelf)(this, rect, 'extension tag in HTML tag attributes'));
180
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'extension tag in HTML tag attributes'));
181
181
  }
182
182
  if (this.name === 'ref' && this.closest('heading-title')) {
183
183
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
184
- errors.push((0, lint_1.generateForSelf)(this, rect, 'variable anchor in a section header'));
184
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'var-anchor', 'variable anchor in a section header'));
185
185
  }
186
186
  return errors;
187
187
  }
@@ -38,7 +38,9 @@ class IncludeToken extends (0, hidden_1.hiddenToken)(index_2.TagPairToken) {
38
38
  }
39
39
  /** @override */
40
40
  lint(start = this.getAbsoluteIndex()) {
41
- return this.closed ? [] : [(0, lint_1.generateForSelf)(this, { start }, index_1.default.msg('unclosed $1', `<${this.name}>`))];
41
+ return this.closed
42
+ ? []
43
+ : [(0, lint_1.generateForSelf)(this, { start }, 'unclosed-comment', index_1.default.msg('unclosed $1', `<${this.name}>`))];
42
44
  }
43
45
  /* NOT FOR BROWSER */
44
46
  /** @override */
@@ -232,21 +232,21 @@ class TranscludeToken extends index_2.Token {
232
232
  const title = this.#getTitle();
233
233
  if (title.fragment !== undefined) {
234
234
  rect = { start, ...this.getRootNode().posFromIndex(start) };
235
- errors.push((0, lint_1.generateForChild)(childNodes[type === 'template' ? 0 : 1], rect, 'useless fragment'));
235
+ errors.push((0, lint_1.generateForChild)(childNodes[type === 'template' ? 0 : 1], rect, 'no-ignored', 'useless fragment'));
236
236
  }
237
237
  if (!title.valid) {
238
238
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
239
- errors.push((0, lint_1.generateForChild)(childNodes[1], rect, 'illegal module name'));
239
+ errors.push((0, lint_1.generateForChild)(childNodes[1], rect, 'invalid-invoke', 'illegal module name'));
240
240
  }
241
241
  if (type === 'magic-word' && length === 2) {
242
242
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
243
- errors.push((0, lint_1.generateForSelf)(this, rect, 'missing module function'));
243
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'invalid-invoke', 'missing module function'));
244
244
  return errors;
245
245
  }
246
246
  const duplicatedArgs = this.getDuplicatedArgs();
247
247
  if (duplicatedArgs.length > 0) {
248
248
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
249
- errors.push(...duplicatedArgs.flatMap(([, args]) => args).map(arg => (0, lint_1.generateForChild)(arg, rect, 'duplicated parameter')));
249
+ errors.push(...duplicatedArgs.flatMap(([, args]) => args).map(arg => (0, lint_1.generateForChild)(arg, rect, 'no-duplicate', 'duplicated parameter')));
250
250
  }
251
251
  return errors;
252
252
  }
package/dist/util/lint.js CHANGED
@@ -6,9 +6,10 @@ const index_1 = require("../index");
6
6
  * 生成lint函数
7
7
  * @param func lint函数
8
8
  */
9
- const factory = (func) => (token, boundingRect, msg, severity = 'error') => {
9
+ const factory = (func) => (token, boundingRect, rule, msg, severity = 'error') => {
10
10
  const { start } = boundingRect, { top, left } = 'top' in boundingRect ? boundingRect : token.getRootNode().posFromIndex(start), { offsetHeight, offsetWidth } = token, { startIndex, startLine, startCol } = func(token, start, top, left);
11
11
  return {
12
+ rule,
12
13
  message: index_1.default.msg(msg),
13
14
  severity,
14
15
  startIndex,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikiparser-node",
3
- "version": "1.4.4",
3
+ "version": "1.4.5",
4
4
  "description": "A Node.js parser for MediaWiki markup with AST",
5
5
  "keywords": [
6
6
  "mediawiki",