wikilint 2.0.0 → 2.1.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.
- package/dist/index.js +9 -5
- package/dist/lib/node.js +2 -2
- package/dist/lib/text.js +3 -2
- package/dist/lib/title.d.ts +0 -1
- package/dist/lib/title.js +11 -11
- package/dist/parser/commentAndExt.js +5 -1
- package/dist/src/html.js +10 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,6 +10,11 @@ const constants_1 = require("./util/constants");
|
|
|
10
10
|
* @param dir 子路径
|
|
11
11
|
*/
|
|
12
12
|
const rootRequire = (file, dir) => require(file.startsWith('/') ? file : `../${file.includes('/') ? '' : dir}${file}`);
|
|
13
|
+
/**
|
|
14
|
+
* 清理解析专用的不可见字符
|
|
15
|
+
* @param text 源文本
|
|
16
|
+
*/
|
|
17
|
+
const tidy = (text) => text.replace(/[\0\x7F]/gu, '');
|
|
13
18
|
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
14
19
|
const Parser = {
|
|
15
20
|
config: 'default',
|
|
@@ -46,11 +51,10 @@ const Parser = {
|
|
|
46
51
|
/** @implements */
|
|
47
52
|
parse(wikitext, include, maxStage = constants_1.MAX_STAGE, config = Parser.getConfig()) {
|
|
48
53
|
const { Token } = require('./src/index');
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
token = new Token(wikitext.replace(/[\0\x7F]/gu, ''), config);
|
|
54
|
+
const root = debug_1.Shadow.run(() => {
|
|
55
|
+
const token = new Token(tidy(wikitext), config);
|
|
52
56
|
try {
|
|
53
|
-
token.parse(maxStage, include);
|
|
57
|
+
return token.parse(maxStage, include);
|
|
54
58
|
}
|
|
55
59
|
catch (e) {
|
|
56
60
|
if (e instanceof Error) {
|
|
@@ -64,7 +68,7 @@ const Parser = {
|
|
|
64
68
|
throw e;
|
|
65
69
|
}
|
|
66
70
|
});
|
|
67
|
-
return
|
|
71
|
+
return root;
|
|
68
72
|
},
|
|
69
73
|
};
|
|
70
74
|
const def = {}, enumerable = new Set([
|
package/dist/lib/node.js
CHANGED
|
@@ -19,12 +19,12 @@ class AstNode {
|
|
|
19
19
|
}
|
|
20
20
|
/** 后一个兄弟节点 */
|
|
21
21
|
get nextSibling() {
|
|
22
|
-
const childNodes = this
|
|
22
|
+
const childNodes = this.parentNode?.childNodes;
|
|
23
23
|
return childNodes && childNodes[childNodes.indexOf(this) + 1];
|
|
24
24
|
}
|
|
25
25
|
/** 前一个兄弟节点 */
|
|
26
26
|
get previousSibling() {
|
|
27
|
-
const childNodes = this
|
|
27
|
+
const childNodes = this.parentNode?.childNodes;
|
|
28
28
|
return childNodes && childNodes[childNodes.indexOf(this) - 1];
|
|
29
29
|
}
|
|
30
30
|
/** 行数 */
|
package/dist/lib/text.js
CHANGED
|
@@ -60,8 +60,9 @@ class AstText extends node_1.AstNode {
|
|
|
60
60
|
return errors
|
|
61
61
|
.map(({ 0: error, 1: prefix, 2: tag, index }) => {
|
|
62
62
|
if (prefix) {
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
const { length } = prefix;
|
|
64
|
+
index += length;
|
|
65
|
+
error = error.slice(length);
|
|
65
66
|
}
|
|
66
67
|
const startIndex = start + index, lines = data.slice(0, index).split('\n'), startLine = lines.length + top - 1, line = lines.at(-1), startCol = lines.length === 1 ? left + line.length : line.length, { 0: char, length } = error, endIndex = startIndex + length, rootStr = String(root), nextChar = rootStr[endIndex], previousChar = rootStr[startIndex - 1], severity = length > 1 && (char !== '<' || /[\s/>]/u.test(nextChar ?? ''))
|
|
67
68
|
|| char === '{' && (nextChar === char || previousChar === '-')
|
package/dist/lib/title.d.ts
CHANGED
package/dist/lib/title.js
CHANGED
|
@@ -8,6 +8,7 @@ class Title {
|
|
|
8
8
|
valid;
|
|
9
9
|
ns;
|
|
10
10
|
fragment;
|
|
11
|
+
/** @private */
|
|
11
12
|
encoded = false;
|
|
12
13
|
/**
|
|
13
14
|
* @param title 标题(含或不含命名空间前缀)
|
|
@@ -16,8 +17,7 @@ class Title {
|
|
|
16
17
|
* @param selfLink 是否允许selfLink
|
|
17
18
|
*/
|
|
18
19
|
constructor(title, defaultNs = 0, config = Parser.getConfig(), decode = false, selfLink = false) {
|
|
19
|
-
const {
|
|
20
|
-
let namespace = namespaces[defaultNs] ?? '';
|
|
20
|
+
const { nsid, } = config;
|
|
21
21
|
title = (0, string_1.decodeHtml)(title);
|
|
22
22
|
if (decode && title.includes('%')) {
|
|
23
23
|
try {
|
|
@@ -28,29 +28,29 @@ class Title {
|
|
|
28
28
|
catch { }
|
|
29
29
|
}
|
|
30
30
|
title = title.replaceAll('_', ' ').trim();
|
|
31
|
+
let ns = defaultNs;
|
|
31
32
|
if (title.startsWith(':')) {
|
|
32
|
-
|
|
33
|
+
ns = 0;
|
|
33
34
|
title = title.slice(1).trim();
|
|
34
35
|
}
|
|
35
36
|
const m = title.split(':');
|
|
36
37
|
if (m.length > 1) {
|
|
37
|
-
const
|
|
38
|
+
const id = nsid[m[0].trim().toLowerCase()];
|
|
38
39
|
if (id !== undefined) {
|
|
39
|
-
|
|
40
|
+
ns = id;
|
|
40
41
|
title = m.slice(1).join(':').trim();
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
|
-
this.ns =
|
|
44
|
+
this.ns = ns;
|
|
44
45
|
const i = title.indexOf('#');
|
|
45
|
-
let fragment;
|
|
46
46
|
if (i !== -1) {
|
|
47
|
-
|
|
47
|
+
// eslint-disable-next-line prefer-const
|
|
48
|
+
let fragment = title.slice(i + 1).trimEnd();
|
|
49
|
+
this.fragment = fragment;
|
|
48
50
|
title = title.slice(0, i).trim();
|
|
49
51
|
}
|
|
50
52
|
this.valid = Boolean(title
|
|
51
|
-
|| selfLink && fragment !== undefined)
|
|
52
|
-
&& !/\0\d+[eh!+-]\x7F|[<>[\]{}|]|%[\da-f]{2}/iu.test(title);
|
|
53
|
-
this.fragment = fragment;
|
|
53
|
+
|| selfLink && this.fragment !== undefined) && !/\0\d+[eh!+-]\x7F|[<>[\]{}|]|%[\da-f]{2}/iu.test(title);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
exports.Title = Title;
|
|
@@ -34,7 +34,11 @@ const parseCommentAndExt = (wikitext, config = Parser.getConfig(), accum = [], i
|
|
|
34
34
|
i = wikitext.indexOf(onlyincludeLeft);
|
|
35
35
|
j = wikitext.indexOf(onlyincludeRight, i + length);
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
if (wikitext) {
|
|
38
|
+
new noinclude_1.NoincludeToken(wikitext, config, accum);
|
|
39
|
+
str += `\0${accum.length - 1}c\x7F`;
|
|
40
|
+
}
|
|
41
|
+
return str;
|
|
38
42
|
}
|
|
39
43
|
}
|
|
40
44
|
const ext = config.ext.join('|'), includeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', noincludeRegex = includeOnly ? 'noinclude' : 'includeonly', regex = new RegExp('<!--.*?(?:-->|$)|' // comment
|
package/dist/src/html.js
CHANGED
|
@@ -35,23 +35,24 @@ class HtmlToken extends index_1.Token {
|
|
|
35
35
|
}
|
|
36
36
|
/** @private */
|
|
37
37
|
toString(omit) {
|
|
38
|
-
return `<${this
|
|
38
|
+
return `<${this.closing ? '/' : ''}${this.#tag}${super.toString()}${this.#selfClosing ? '/' : ''}>`;
|
|
39
39
|
}
|
|
40
40
|
/** @override */
|
|
41
41
|
text() {
|
|
42
|
-
|
|
42
|
+
const { closing } = this;
|
|
43
|
+
return `<${closing ? '/' : ''}${this.#tag}${closing ? '' : super.text()}${this.#selfClosing ? '/' : ''}>`;
|
|
43
44
|
}
|
|
44
45
|
/** @private */
|
|
45
46
|
getAttribute(key) {
|
|
46
47
|
return key === 'padding'
|
|
47
|
-
? this.#tag.length + (this
|
|
48
|
+
? this.#tag.length + (this.closing ? 2 : 1)
|
|
48
49
|
: super.getAttribute(key);
|
|
49
50
|
}
|
|
50
51
|
/** @override */
|
|
51
52
|
lint(start = this.getAbsoluteIndex()) {
|
|
52
53
|
const errors = super.lint(start);
|
|
53
54
|
let refError;
|
|
54
|
-
if (this.name === 'h1' && !this
|
|
55
|
+
if (this.name === 'h1' && !this.closing) {
|
|
55
56
|
refError = (0, lint_1.generateForSelf)(this, { start }, '<h1>');
|
|
56
57
|
errors.push(refError);
|
|
57
58
|
}
|
|
@@ -91,8 +92,8 @@ class HtmlToken extends index_1.Token {
|
|
|
91
92
|
* @throws `SyntaxError` 未闭合的标签
|
|
92
93
|
*/
|
|
93
94
|
findMatchingTag() {
|
|
94
|
-
const { html } = this.getAttribute('config'), { name: tagName, parentNode } = this, string = (0, string_1.noWrap)(String(this));
|
|
95
|
-
if (
|
|
95
|
+
const { html } = this.getAttribute('config'), { name: tagName, parentNode, closing } = this, string = (0, string_1.noWrap)(String(this));
|
|
96
|
+
if (closing && (this.#selfClosing || html[2].includes(tagName))) {
|
|
96
97
|
throw new SyntaxError(`tag that is both closing and self-closing: ${string}`);
|
|
97
98
|
}
|
|
98
99
|
else if (html[2].includes(tagName) || this.#selfClosing && html[1].includes(tagName)) { // 自封闭标签
|
|
@@ -104,10 +105,10 @@ class HtmlToken extends index_1.Token {
|
|
|
104
105
|
else if (!parentNode) {
|
|
105
106
|
return undefined;
|
|
106
107
|
}
|
|
107
|
-
const { childNodes } = parentNode, i = childNodes.indexOf(this), siblings =
|
|
108
|
+
const { childNodes } = parentNode, i = childNodes.indexOf(this), siblings = closing
|
|
108
109
|
? childNodes.slice(0, i).reverse().filter(({ type, name }) => type === 'html' && name === tagName)
|
|
109
110
|
: childNodes.slice(i + 1).filter(({ type, name }) => type === 'html' && name === tagName);
|
|
110
|
-
let imbalance =
|
|
111
|
+
let imbalance = closing ? -1 : 1;
|
|
111
112
|
for (const token of siblings) {
|
|
112
113
|
if (token.#closing) {
|
|
113
114
|
imbalance--;
|
|
@@ -119,7 +120,7 @@ class HtmlToken extends index_1.Token {
|
|
|
119
120
|
return token;
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
|
-
throw new SyntaxError(`${
|
|
123
|
+
throw new SyntaxError(`${closing ? 'unmatched closing' : 'unclosed'} tag: ${string}`);
|
|
123
124
|
}
|
|
124
125
|
}
|
|
125
126
|
exports.HtmlToken = HtmlToken;
|