wikilint 2.3.5 → 2.3.7
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/lib/element.js +7 -3
- package/dist/lib/node.js +5 -11
- package/dist/lib/text.js +28 -19
- package/dist/lib/title.js +1 -1
- package/dist/parser/braces.js +5 -5
- package/dist/parser/commentAndExt.js +6 -3
- package/dist/parser/converter.js +4 -4
- package/dist/parser/magicLinks.js +4 -4
- package/dist/parser/quotes.js +1 -1
- package/dist/parser/table.js +1 -1
- package/dist/src/attribute.js +9 -3
- package/dist/src/attributes.js +6 -7
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +4 -7
- package/dist/src/link/base.js +1 -1
- package/dist/src/magicLink.js +6 -5
- package/dist/src/nested.js +2 -2
- package/dist/src/nowiki/quote.js +1 -1
- package/dist/src/parameter.js +1 -1
- package/dist/src/table/td.js +8 -4
- package/dist/src/tagPair/ext.js +1 -3
- package/dist/src/transclude.js +3 -2
- package/dist/util/constants.js +6 -1
- package/dist/util/debug.js +2 -1
- package/dist/util/string.js +2 -2
- package/package.json +7 -5
package/dist/lib/element.js
CHANGED
|
@@ -19,7 +19,7 @@ class AstElement extends node_1.AstNode {
|
|
|
19
19
|
}
|
|
20
20
|
/** 合并相邻的文本子节点 */
|
|
21
21
|
normalize() {
|
|
22
|
-
const
|
|
22
|
+
const childNodes = [...this.childNodes];
|
|
23
23
|
for (let i = childNodes.length - 1; i >= 0; i--) {
|
|
24
24
|
const { type, data } = childNodes[i], prev = childNodes[i - 1];
|
|
25
25
|
if (type !== 'text' || this.getGaps(i - 1)) {
|
|
@@ -33,6 +33,7 @@ class AstElement extends node_1.AstNode {
|
|
|
33
33
|
childNodes.splice(i, 1);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
+
this.setAttribute('childNodes', childNodes);
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
38
39
|
* 移除子节点
|
|
@@ -81,7 +82,9 @@ class AstElement extends node_1.AstNode {
|
|
|
81
82
|
* @param elements 新的子节点
|
|
82
83
|
*/
|
|
83
84
|
replaceChildren(...elements) {
|
|
84
|
-
this.
|
|
85
|
+
for (let i = this.length - 1; i >= 0; i--) {
|
|
86
|
+
this.removeAt(i);
|
|
87
|
+
}
|
|
85
88
|
this.append(...elements);
|
|
86
89
|
}
|
|
87
90
|
/**
|
|
@@ -90,7 +93,8 @@ class AstElement extends node_1.AstNode {
|
|
|
90
93
|
* @param i 子节点位置
|
|
91
94
|
*/
|
|
92
95
|
setText(str, i = 0) {
|
|
93
|
-
|
|
96
|
+
i += i < 0 ? this.length : 0;
|
|
97
|
+
const oldText = this.childNodes[i];
|
|
94
98
|
const { data } = oldText;
|
|
95
99
|
oldText.replaceData(str);
|
|
96
100
|
return data;
|
package/dist/lib/node.js
CHANGED
|
@@ -11,7 +11,7 @@ class AstNode {
|
|
|
11
11
|
}
|
|
12
12
|
/** 末位子节点 */
|
|
13
13
|
get lastChild() {
|
|
14
|
-
return this.childNodes.
|
|
14
|
+
return this.childNodes[this.childNodes.length - 1];
|
|
15
15
|
}
|
|
16
16
|
/** 父节点 */
|
|
17
17
|
get parentNode() {
|
|
@@ -68,21 +68,15 @@ class AstNode {
|
|
|
68
68
|
posFromIndex(index) {
|
|
69
69
|
const str = String(this);
|
|
70
70
|
if (index >= -str.length && index <= str.length) {
|
|
71
|
-
const lines = str.slice(0, index).split('\n');
|
|
72
|
-
return {
|
|
73
|
-
top: lines.length - 1,
|
|
74
|
-
left: lines.at(-1).length,
|
|
75
|
-
};
|
|
71
|
+
const lines = str.slice(0, index).split('\n'), top = lines.length - 1;
|
|
72
|
+
return { top, left: lines[top].length };
|
|
76
73
|
}
|
|
77
74
|
return undefined;
|
|
78
75
|
}
|
|
79
76
|
/** 获取行数和最后一行的列数 */
|
|
80
77
|
#getDimension() {
|
|
81
|
-
const lines = String(this).split('\n');
|
|
82
|
-
return {
|
|
83
|
-
height: lines.length,
|
|
84
|
-
width: lines.at(-1).length,
|
|
85
|
-
};
|
|
78
|
+
const lines = String(this).split('\n'), height = lines.length;
|
|
79
|
+
return { height, width: lines[height - 1].length };
|
|
86
80
|
}
|
|
87
81
|
/** @private */
|
|
88
82
|
getGaps(i) {
|
package/dist/lib/text.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AstText = void 0;
|
|
4
4
|
const Parser = require("../index");
|
|
5
5
|
const node_1 = require("./node");
|
|
6
|
-
const errorSyntax = /<\s*\/?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*\])|(
|
|
6
|
+
const errorSyntax = /<\s*\/?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*\])|((?:^|\])[^[]*?)\]+|https?[:/]\/+/giu, errorSyntaxUrl = /<\s*\/?([a-z]\w*)|\{+|\}+|\[{2,}|\[(?![^[]*\])|((?:^|\])[^[]*?)\]+/giu, disallowedTags = [
|
|
7
7
|
'html',
|
|
8
8
|
'head',
|
|
9
9
|
'style',
|
|
@@ -37,7 +37,11 @@ class AstText extends node_1.AstNode {
|
|
|
37
37
|
/** @param text 包含文本 */
|
|
38
38
|
constructor(text) {
|
|
39
39
|
super();
|
|
40
|
-
this
|
|
40
|
+
Object.defineProperties(this, {
|
|
41
|
+
data: {
|
|
42
|
+
value: text,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
41
45
|
}
|
|
42
46
|
/** @private */
|
|
43
47
|
toString() {
|
|
@@ -68,17 +72,19 @@ class AstText extends node_1.AstNode {
|
|
|
68
72
|
else {
|
|
69
73
|
errorRegex = errorSyntax;
|
|
70
74
|
}
|
|
71
|
-
const errors = [
|
|
72
|
-
if (
|
|
75
|
+
const errors = [], { ext, html } = this.getRootNode().getAttribute('config');
|
|
76
|
+
if (data.search(errorRegex) !== -1) {
|
|
77
|
+
errorRegex.lastIndex = 0;
|
|
73
78
|
const root = this.getRootNode(), { top, left } = root.posFromIndex(start), tags = new Set(['onlyinclude', 'noinclude', 'includeonly', ext, html, disallowedTags].flat(2));
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
for (let mt = errorRegex.exec(data); mt; mt = errorRegex.exec(data)) {
|
|
80
|
+
const [, tag, prefix] = mt;
|
|
81
|
+
let { 0: error, index } = mt;
|
|
82
|
+
if (prefix && prefix !== ']') {
|
|
77
83
|
const { length } = prefix;
|
|
78
84
|
index += length;
|
|
79
85
|
error = error.slice(length);
|
|
80
86
|
}
|
|
81
|
-
const startIndex = start + index, lines = data.slice(0, index).split('\n'), startLine = lines.length + top - 1, line = lines.
|
|
87
|
+
const startIndex = start + index, 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, { 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 ?? ''))
|
|
82
88
|
|| char === '{' && (nextChar === char || previousChar === '-')
|
|
83
89
|
|| char === '}' && (previousChar === char || nextChar === '-')
|
|
84
90
|
|| char === '[' && (nextChar === char
|
|
@@ -88,17 +94,20 @@ class AstText extends node_1.AstNode {
|
|
|
88
94
|
|| !data.slice(0, index).trim() && previousType === 'free-ext-link')
|
|
89
95
|
? 'error'
|
|
90
96
|
: 'warning';
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
if (char !== '<' || tags.has(tag.toLowerCase())) {
|
|
98
|
+
errors.push({
|
|
99
|
+
message: Parser.msg('lonely "$1"', char === 'h' ? error : char),
|
|
100
|
+
severity,
|
|
101
|
+
startIndex,
|
|
102
|
+
endIndex,
|
|
103
|
+
startLine,
|
|
104
|
+
endLine: startLine,
|
|
105
|
+
startCol,
|
|
106
|
+
endCol: startCol + length,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return errors;
|
|
102
111
|
}
|
|
103
112
|
return [];
|
|
104
113
|
}
|
package/dist/lib/title.js
CHANGED
package/dist/parser/braces.js
CHANGED
|
@@ -17,7 +17,7 @@ const parseBraces = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
|
17
17
|
const source = `${config.excludes?.includes('heading') ? '' : '^(\0\\d+c\x7F)*={1,6}|'}\\[\\[|\\{{2,}|-\\{(?!\\{)`, { parserFunction: [, , , subst] } = config, stack = [], closes = { '=': '\n', '{': '\\}{2,}|\\|', '-': '\\}-', '[': '\\]\\]' }, marks = new Map([['!', '!'], ['!!', '+'], ['(!', '{'], ['!)', '}'], ['!-', '-'], ['=', '~']]);
|
|
18
18
|
let regex = new RegExp(source, 'gmu'), mt = regex.exec(wikitext), moreBraces = wikitext.includes('}}'), lastIndex;
|
|
19
19
|
while (mt
|
|
20
|
-
|| lastIndex !== undefined && lastIndex <= wikitext.length && stack.
|
|
20
|
+
|| lastIndex !== undefined && lastIndex <= wikitext.length && stack[stack.length - 1]?.[0]?.startsWith('=')) {
|
|
21
21
|
if (mt?.[1]) {
|
|
22
22
|
const [, { length }] = mt;
|
|
23
23
|
mt[0] = mt[0].slice(length);
|
|
@@ -29,14 +29,14 @@ const parseBraces = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
|
29
29
|
* @param text wikitext全文
|
|
30
30
|
*/
|
|
31
31
|
const push = (text) => {
|
|
32
|
-
parts.
|
|
32
|
+
parts[parts.length - 1].push(text.slice(topPos, curIndex));
|
|
33
33
|
};
|
|
34
34
|
if (syntax === ']]' || syntax === '}-') { // 情形1:闭合内链或转换
|
|
35
35
|
lastIndex = curIndex + 2;
|
|
36
36
|
}
|
|
37
37
|
else if (syntax === '\n') { // 情形2:闭合标题或文末
|
|
38
38
|
lastIndex = curIndex + 1;
|
|
39
|
-
const { pos, findEqual } = stack.
|
|
39
|
+
const { pos, findEqual } = stack[stack.length - 1] ?? {};
|
|
40
40
|
if (pos === undefined || findEqual || (0, string_1.removeComment)(wikitext.slice(pos, index)) !== '') {
|
|
41
41
|
const rmt = /^(={1,6})(.+)\1((?:\s|\0\d+c\x7F)*)$/u
|
|
42
42
|
.exec(wikitext.slice(index, curIndex));
|
|
@@ -112,10 +112,10 @@ const parseBraces = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
|
112
112
|
stack.push(...'0' in top ? [top] : [], mt);
|
|
113
113
|
}
|
|
114
114
|
moreBraces &&= wikitext.slice(lastIndex).includes('}}');
|
|
115
|
-
let curTop = stack.
|
|
115
|
+
let curTop = stack[stack.length - 1];
|
|
116
116
|
if (!moreBraces && curTop?.[0]?.startsWith('{')) {
|
|
117
117
|
stack.pop();
|
|
118
|
-
curTop = stack.
|
|
118
|
+
curTop = stack[stack.length - 1];
|
|
119
119
|
}
|
|
120
120
|
regex = new RegExp(source + (curTop ? `|${closes[curTop[0][0]]}${curTop.findEqual ? '|=' : ''}` : ''), 'gmu');
|
|
121
121
|
regex.lastIndex = lastIndex;
|
|
@@ -49,9 +49,12 @@ const parseCommentAndExt = (wikitext, config = Parser.getConfig(), accum = [], i
|
|
|
49
49
|
return str;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
const ext = config.ext.join('|'), noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly', regex = new RegExp('<!--.*?(?:-->|$)
|
|
53
|
-
+
|
|
54
|
-
+
|
|
52
|
+
const ext = config.ext.join('|'), noincludeRegex = includeOnly ? 'includeonly' : '(?:no|only)include', includeRegex = includeOnly ? 'noinclude' : 'includeonly', regex = new RegExp('<!--.*?(?:-->|$)' // comment
|
|
53
|
+
+ '|'
|
|
54
|
+
+ `<${noincludeRegex}(?:\\s[^>]*?)?>|</${noincludeRegex}\\s*>` // <noinclude>
|
|
55
|
+
+ '|'
|
|
56
|
+
+ `<(${ext})(\\s[^>]*?)?(?:/>|>(.*?)</(\\1\\s*)>)` // 扩展标签
|
|
57
|
+
+ '|'
|
|
55
58
|
+ `<(${includeRegex})(\\s[^>]*?)?(?:/>|>(.*?)(?:</(${includeRegex}\\s*)>|$))`, // <includeonly>
|
|
56
59
|
'gisu');
|
|
57
60
|
return wikitext.replace(regex, (substr, name, attr, inner, closing, include, includeAttr, includeInner, includeClosing) => {
|
package/dist/parser/converter.js
CHANGED
|
@@ -15,10 +15,10 @@ const parseConverter = (text, config = Parser.getConfig(), accum = []) => {
|
|
|
15
15
|
while (mt) {
|
|
16
16
|
const { 0: syntax, index } = mt;
|
|
17
17
|
if (syntax === '}-') {
|
|
18
|
-
const top = stack.pop(), { length } = accum, str = text.slice(top.index + 2, index), i = str.indexOf('|'), [flags, raw] = i === -1 ? [[], str] : [str.slice(0, i).split(';'), str.slice(i + 1)],
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const top = stack.pop(), { length } = accum, str = text.slice(top.index + 2, index), i = str.indexOf('|'), [flags, raw] = i === -1 ? [[], str] : [str.slice(0, i).split(';'), str.slice(i + 1)], temp = raw.replace(/(&[#a-z\d]+);/giu, '$1\x01'), variants = `(?:${config.variants.join('|')})`, rules = temp.split(new RegExp(`;(?=\\s*(?:${`(?:${variants}|[^;]*?=>\\s*${variants})\\s*:`
|
|
19
|
+
+ '|'
|
|
20
|
+
+ '(?:\0\\d+c\x7f(?:\\s|\0\\d+c\x7f)*)?$' // 末尾的空白
|
|
21
|
+
}))`, 'u')).map(rule => rule.replace(/\x01/gu, ';'));
|
|
22
22
|
new converter_1.ConverterToken(flags, rules, config, accum);
|
|
23
23
|
text = `${text.slice(0, top.index)}\0${length}v\x7F${text.slice(index + 2)}`;
|
|
24
24
|
if (stack.length === 0) {
|
|
@@ -11,9 +11,9 @@ const magicLink_1 = require("../src/magicLink");
|
|
|
11
11
|
* @param accum
|
|
12
12
|
*/
|
|
13
13
|
const parseMagicLinks = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
14
|
-
const regex = new RegExp(`(
|
|
15
|
-
return wikitext.replace(regex, (m, p1) => {
|
|
16
|
-
let trail = '', url = m;
|
|
14
|
+
const regex = new RegExp(`(^|[^\\p{L}\\d_])(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})`, 'giu');
|
|
15
|
+
return wikitext.replace(regex, (m, lead, p1) => {
|
|
16
|
+
let trail = '', url = lead ? m.slice(1) : m;
|
|
17
17
|
const m2 = /&(?:lt|gt|nbsp|#x0*(?:3[ce]|a0)|#0*(?:6[02]|160));/iu.exec(url);
|
|
18
18
|
if (m2) {
|
|
19
19
|
trail = url.slice(m2.index);
|
|
@@ -32,7 +32,7 @@ const parseMagicLinks = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
|
32
32
|
return m;
|
|
33
33
|
}
|
|
34
34
|
new magicLink_1.MagicLinkToken(url, false, config, accum);
|
|
35
|
-
return
|
|
35
|
+
return `${lead}\0${accum.length - 1}w\x7F${trail}`;
|
|
36
36
|
});
|
|
37
37
|
};
|
|
38
38
|
exports.parseMagicLinks = parseMagicLinks;
|
package/dist/parser/quotes.js
CHANGED
package/dist/parser/table.js
CHANGED
|
@@ -80,7 +80,7 @@ const parseTable = ({ firstChild: { data }, type, name }, config = Parser.getCon
|
|
|
80
80
|
top = stack.pop();
|
|
81
81
|
}
|
|
82
82
|
top.close(`\n${spaces}${closing}`, true);
|
|
83
|
-
push(attr, stack.
|
|
83
|
+
push(attr, stack[stack.length - 1]);
|
|
84
84
|
}
|
|
85
85
|
else if (row) {
|
|
86
86
|
top = pop();
|
package/dist/src/attribute.js
CHANGED
|
@@ -112,7 +112,13 @@ const commonHtmlAttrs = new Set([
|
|
|
112
112
|
]),
|
|
113
113
|
tabs: new Set(['plain', 'class', 'container', 'id', 'title', 'style']),
|
|
114
114
|
combobox: new Set(['placeholder', 'value', 'id', 'class', 'text', 'dropdown', 'style']),
|
|
115
|
-
}, insecureStyle = new RegExp(
|
|
115
|
+
}, insecureStyle = new RegExp('expression'
|
|
116
|
+
+ '|'
|
|
117
|
+
+ '(?:filter|accelerator|-o-link(?:-source)?|-o-replace)\\s*:'
|
|
118
|
+
+ '|'
|
|
119
|
+
+ '(?:url|image(?:-set)?)\\s*\\('
|
|
120
|
+
+ '|'
|
|
121
|
+
+ 'attr\\s*\\([^)]+[\\s,]url', 'u');
|
|
116
122
|
/**
|
|
117
123
|
* 扩展和HTML标签属性
|
|
118
124
|
* @classdesc `{childNodes: [AtomToken, Token|AtomToken]}`
|
|
@@ -172,7 +178,7 @@ class AttributeToken extends index_1.Token {
|
|
|
172
178
|
/** @private */
|
|
173
179
|
afterBuild() {
|
|
174
180
|
if (this.#equal.includes('\0')) {
|
|
175
|
-
this.#equal = this.buildFromStr(this.#equal,
|
|
181
|
+
this.#equal = this.buildFromStr(this.#equal, constants_1.BuildMethod.String);
|
|
176
182
|
}
|
|
177
183
|
if (this.parentNode) {
|
|
178
184
|
this.setAttribute('tag', this.parentNode.name);
|
|
@@ -233,7 +239,7 @@ class AttributeToken extends index_1.Token {
|
|
|
233
239
|
if (this.#quotes[1]) {
|
|
234
240
|
return value;
|
|
235
241
|
}
|
|
236
|
-
return this.#quotes[0] ?
|
|
242
|
+
return value[this.#quotes[0] ? 'trimEnd' : 'trim']();
|
|
237
243
|
}
|
|
238
244
|
return this.type === 'ext-attr' || '';
|
|
239
245
|
}
|
package/dist/src/attributes.js
CHANGED
|
@@ -33,12 +33,11 @@ class AttributesToken extends index_1.Token {
|
|
|
33
33
|
this.setAttribute('name', name);
|
|
34
34
|
if (attr) {
|
|
35
35
|
const regex = new RegExp('([^\\s/](?:(?!\0\\d+~\x7F)[^\\s/=])*)' // 属性名
|
|
36
|
-
+ '(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
+ ')?', 'gsu');
|
|
36
|
+
+ `(?:${'((?:\\s|\0\\d+c\x7F)*' // `=`前的空白字符
|
|
37
|
+
+ '(?:=|\0\\d+~\x7F)' // `=`
|
|
38
|
+
+ '(?:\\s|\0\\d+c\x7F)*)' // `=`后的空白字符
|
|
39
|
+
+ `(?:(["'])(.*?)(\\3|$)|(\\S*))` // 属性值
|
|
40
|
+
})?`, 'gsu');
|
|
42
41
|
let out = '', mt = regex.exec(attr), lastIndex = 0;
|
|
43
42
|
const insertDirty = /** 插入无效属性 */ () => {
|
|
44
43
|
if (out) {
|
|
@@ -84,7 +83,7 @@ class AttributesToken extends index_1.Token {
|
|
|
84
83
|
*/
|
|
85
84
|
getAttrToken(key) {
|
|
86
85
|
const tokens = this.getAttrTokens(key);
|
|
87
|
-
return tokens.
|
|
86
|
+
return tokens[tokens.length - 1];
|
|
88
87
|
}
|
|
89
88
|
/**
|
|
90
89
|
* 获取指定属性
|
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.js
CHANGED
|
@@ -127,15 +127,15 @@ class Token extends element_1.AstElement {
|
|
|
127
127
|
if (i % 2 === 0) {
|
|
128
128
|
return new text_1.AstText(s);
|
|
129
129
|
}
|
|
130
|
-
else if (Number.isNaN(Number(s.
|
|
130
|
+
else if (Number.isNaN(Number(s.slice(-1)))) {
|
|
131
131
|
return this.#accum[Number(s.slice(0, -1))];
|
|
132
132
|
}
|
|
133
133
|
throw new Error(`解析错误!未正确标记的 Token:${s}`);
|
|
134
134
|
});
|
|
135
|
-
if (type ===
|
|
135
|
+
if (type === constants_1.BuildMethod.String) {
|
|
136
136
|
return nodes.map(String).join('');
|
|
137
137
|
}
|
|
138
|
-
else if (type ===
|
|
138
|
+
else if (type === constants_1.BuildMethod.Text) {
|
|
139
139
|
return (0, string_1.text)(nodes);
|
|
140
140
|
}
|
|
141
141
|
return nodes;
|
|
@@ -279,10 +279,7 @@ class Token extends element_1.AstElement {
|
|
|
279
279
|
return this.#include;
|
|
280
280
|
}
|
|
281
281
|
const root = this.getRootNode();
|
|
282
|
-
|
|
283
|
-
return root.getAttribute('include');
|
|
284
|
-
}
|
|
285
|
-
return false;
|
|
282
|
+
return (root !== this && root.getAttribute('include'));
|
|
286
283
|
}
|
|
287
284
|
default:
|
|
288
285
|
return super.getAttribute(key);
|
package/dist/src/link/base.js
CHANGED
|
@@ -34,7 +34,7 @@ class LinkBaseToken extends index_1.Token {
|
|
|
34
34
|
afterBuild() {
|
|
35
35
|
this.#title = this.getTitle();
|
|
36
36
|
if (this.#delimiter.includes('\0')) {
|
|
37
|
-
this.#delimiter = this.buildFromStr(this.#delimiter,
|
|
37
|
+
this.#delimiter = this.buildFromStr(this.#delimiter, constants_1.BuildMethod.String);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
/** @private */
|
package/dist/src/magicLink.js
CHANGED
|
@@ -28,9 +28,10 @@ class MagicLinkToken extends index_1.Token {
|
|
|
28
28
|
}
|
|
29
29
|
rect ??= { start, ...this.getRootNode().posFromIndex(start) };
|
|
30
30
|
const refError = (0, lint_1.generateForChild)(child, rect, '', 'warning');
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
regexGlobal.lastIndex = 0;
|
|
32
|
+
for (let mt = regexGlobal.exec(data); mt; mt = regexGlobal.exec(data)) {
|
|
33
|
+
const { index, 0: s } = mt, lines = data.slice(0, index).split('\n'), { length: top } = lines, { length: left } = lines[lines.length - 1], startIndex = refError.startIndex + index, startLine = refError.startLine + top - 1, startCol = top === 1 ? refError.startCol + left : left;
|
|
34
|
+
errors.push({
|
|
34
35
|
...refError,
|
|
35
36
|
message: Parser.msg('$1 in URL', s.startsWith('|') ? '"|"' : Parser.msg('full-width punctuation')),
|
|
36
37
|
startIndex,
|
|
@@ -39,8 +40,8 @@ class MagicLinkToken extends index_1.Token {
|
|
|
39
40
|
endLine: startLine,
|
|
40
41
|
startCol,
|
|
41
42
|
endCol: startCol + s.length,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
44
45
|
}
|
|
45
46
|
return errors;
|
|
46
47
|
}
|
package/dist/src/nested.js
CHANGED
|
@@ -28,9 +28,9 @@ class NestedToken extends index_1.Token {
|
|
|
28
28
|
new comment_1.CommentToken(comment.slice(4, closed ? -3 : undefined), closed, config, accum);
|
|
29
29
|
}
|
|
30
30
|
return str;
|
|
31
|
-
})?.replace(/(
|
|
31
|
+
})?.replace(/(^|\0\d+[ce]\x7F)([^\0]+)(?=$|\0\d+[ce]\x7F)/gu, (_, lead, substr) => {
|
|
32
32
|
new noinclude_1.NoincludeToken(substr, config, accum);
|
|
33
|
-
return
|
|
33
|
+
return `${lead}\0${accum.length}c\x7F`;
|
|
34
34
|
});
|
|
35
35
|
super(wikitext, config, accum, {});
|
|
36
36
|
}
|
package/dist/src/nowiki/quote.js
CHANGED
|
@@ -14,7 +14,7 @@ class QuoteToken extends base_1.NowikiBaseToken {
|
|
|
14
14
|
let refError;
|
|
15
15
|
if (previousSibling?.type === 'text' && previousSibling.data.endsWith(`'`)) {
|
|
16
16
|
refError = (0, lint_1.generateForSelf)(this, { start }, message);
|
|
17
|
-
const { startIndex: endIndex, startLine: endLine, startCol: endCol } = refError, [{ length }] = /(
|
|
17
|
+
const { startIndex: endIndex, startLine: endLine, startCol: endCol } = refError, [, { length }] = /(?:^|[^'])('+)$/u.exec(previousSibling.data), startIndex = start - length;
|
|
18
18
|
errors.push({
|
|
19
19
|
...refError,
|
|
20
20
|
startIndex,
|
package/dist/src/parameter.js
CHANGED
|
@@ -10,7 +10,7 @@ const index_1 = require("./index");
|
|
|
10
10
|
* @param name 预定的参数名
|
|
11
11
|
*/
|
|
12
12
|
const getName = (name) => name.toString(new Set(['comment', 'noinclude', 'include']))
|
|
13
|
-
.replace(/^[ \t\n\0\v]+|(
|
|
13
|
+
.replace(/^[ \t\n\0\v]+|([^ \t\n\0\v])[ \t\n\0\v]+$/gu, '$1');
|
|
14
14
|
/**
|
|
15
15
|
* 模板或魔术字参数
|
|
16
16
|
* @classdesc `{childNodes: [Token, Token]}`
|
package/dist/src/table/td.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TdToken = void 0;
|
|
4
4
|
const lint_1 = require("../../util/lint");
|
|
5
|
+
const constants_1 = require("../../util/constants");
|
|
5
6
|
const Parser = require("../../index");
|
|
6
7
|
const index_1 = require("../index");
|
|
7
8
|
const base_1 = require("./base");
|
|
@@ -38,7 +39,7 @@ class TdToken extends base_1.TableBaseToken {
|
|
|
38
39
|
}
|
|
39
40
|
/** 表格语法信息 */
|
|
40
41
|
#getSyntax() {
|
|
41
|
-
const syntax = this.firstChild.text(), char = syntax.
|
|
42
|
+
const syntax = this.firstChild.text(), char = syntax.slice(-1);
|
|
42
43
|
let subtype = 'td';
|
|
43
44
|
if (char === '!') {
|
|
44
45
|
subtype = 'th';
|
|
@@ -51,7 +52,7 @@ class TdToken extends base_1.TableBaseToken {
|
|
|
51
52
|
/** @private */
|
|
52
53
|
afterBuild() {
|
|
53
54
|
if (this.#innerSyntax.includes('\0')) {
|
|
54
|
-
this.#innerSyntax = this.buildFromStr(this.#innerSyntax,
|
|
55
|
+
this.#innerSyntax = this.buildFromStr(this.#innerSyntax, constants_1.BuildMethod.String);
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
/** @private */
|
|
@@ -76,8 +77,11 @@ class TdToken extends base_1.TableBaseToken {
|
|
|
76
77
|
const errors = super.lint(start);
|
|
77
78
|
start += this.getRelativeIndex(this.length - 1);
|
|
78
79
|
for (const child of this.lastChild.childNodes) {
|
|
79
|
-
if (child.type === 'text'
|
|
80
|
-
|
|
80
|
+
if (child.type === 'text') {
|
|
81
|
+
const { data } = child;
|
|
82
|
+
if (data.includes('|')) {
|
|
83
|
+
errors.push((0, lint_1.generateForChild)(child, { start }, 'additional "|" in a table cell', data.includes('||') ? 'error' : 'warning'));
|
|
84
|
+
}
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
return errors;
|
package/dist/src/tagPair/ext.js
CHANGED
|
@@ -29,9 +29,7 @@ class ExtToken extends index_2.TagPairToken {
|
|
|
29
29
|
* @param closed 是否封闭
|
|
30
30
|
*/
|
|
31
31
|
constructor(name, attr, inner, closed, config = Parser.getConfig(), accum = []) {
|
|
32
|
-
const lcName = name.toLowerCase(), attrToken = new attributes_1.AttributesToken(!attr || attr.trimStart() !== attr
|
|
33
|
-
? attr
|
|
34
|
-
: ` ${attr}`, 'ext-attrs', lcName, config, accum), newConfig = { ...config, ext: del(config.ext, lcName), excludes: [...config.excludes ?? []] };
|
|
32
|
+
const lcName = name.toLowerCase(), attrToken = new attributes_1.AttributesToken(!attr || attr.trimStart() !== attr ? attr : ` ${attr}`, 'ext-attrs', lcName, config, accum), newConfig = { ...config, ext: del(config.ext, lcName), excludes: [...config.excludes ?? []] };
|
|
35
33
|
let innerToken;
|
|
36
34
|
switch (lcName) {
|
|
37
35
|
case 'tab':
|
package/dist/src/transclude.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.TranscludeToken = void 0;
|
|
|
4
4
|
const string_1 = require("../util/string");
|
|
5
5
|
const lint_1 = require("../util/lint");
|
|
6
6
|
const debug_1 = require("../util/debug");
|
|
7
|
+
const constants_1 = require("../util/constants");
|
|
7
8
|
const Parser = require("../index");
|
|
8
9
|
const index_1 = require("./index");
|
|
9
10
|
const parameter_1 = require("./parameter");
|
|
@@ -122,7 +123,7 @@ class TranscludeToken extends index_1.Token {
|
|
|
122
123
|
/** @private */
|
|
123
124
|
afterBuild() {
|
|
124
125
|
if (this.modifier.includes('\0')) {
|
|
125
|
-
this.setAttribute('modifier', this.buildFromStr(this.modifier,
|
|
126
|
+
this.setAttribute('modifier', this.buildFromStr(this.modifier, constants_1.BuildMethod.String));
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
129
|
/** @private */
|
|
@@ -230,7 +231,7 @@ class TranscludeToken extends index_1.Token {
|
|
|
230
231
|
* @param copy 是否返回一个备份
|
|
231
232
|
*/
|
|
232
233
|
getArgs(key, exact = false, copy = true) {
|
|
233
|
-
const keyStr = String(key).replace(/^[ \t\n\0\v]+|(
|
|
234
|
+
const keyStr = String(key).replace(/^[ \t\n\0\v]+|([^ \t\n\0\v])[ \t\n\0\v]+$/gu, '$1');
|
|
234
235
|
let args;
|
|
235
236
|
if (this.#args.has(keyStr)) {
|
|
236
237
|
args = this.#args.get(keyStr);
|
package/dist/util/constants.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MAX_STAGE = void 0;
|
|
3
|
+
exports.BuildMethod = exports.MAX_STAGE = void 0;
|
|
4
4
|
exports.MAX_STAGE = 11;
|
|
5
|
+
var BuildMethod;
|
|
6
|
+
(function (BuildMethod) {
|
|
7
|
+
BuildMethod[BuildMethod["String"] = 0] = "String";
|
|
8
|
+
BuildMethod[BuildMethod["Text"] = 1] = "Text";
|
|
9
|
+
})(BuildMethod || (exports.BuildMethod = BuildMethod = {}));
|
package/dist/util/debug.js
CHANGED
|
@@ -22,7 +22,8 @@ exports.isToken = isToken;
|
|
|
22
22
|
* @param inserted 插入的子节点
|
|
23
23
|
*/
|
|
24
24
|
const setChildNodes = (parent, position, deleteCount, inserted = []) => {
|
|
25
|
-
const
|
|
25
|
+
const childNodes = [...parent.childNodes], removed = childNodes.splice(position, deleteCount, ...inserted);
|
|
26
|
+
parent.setAttribute('childNodes', childNodes);
|
|
26
27
|
for (const node of inserted) {
|
|
27
28
|
node.setAttribute('parentNode', parent);
|
|
28
29
|
}
|
package/dist/util/string.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.noWrap = exports.decodeHtml = exports.text = exports.escapeRegExp = exports.removeComment = exports.extUrlChar = exports.extUrlCharFirst = void 0;
|
|
4
|
-
exports.extUrlCharFirst = '(?:\\[[\\da-f:.]+\\]|[^[\\]<>"
|
|
5
|
-
exports.extUrlChar = '(?:[^[\\]<>"
|
|
4
|
+
exports.extUrlCharFirst = '(?:\\[[\\da-f:.]+\\]|[^[\\]<>"\0-\x1F\x7F\\p{Zs}\uFFFD])';
|
|
5
|
+
exports.extUrlChar = '(?:[^[\\]<>"\0-\x1F\x7F\\p{Zs}\uFFFD]|\0\\d+[c!~]\x7F)*';
|
|
6
6
|
/**
|
|
7
7
|
* 生成正则替换函数
|
|
8
8
|
* @param regex 正则表达式
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wikilint",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.7",
|
|
4
4
|
"description": "A Node.js linter for MediaWiki markup",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mediawiki",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"/config/",
|
|
20
20
|
"/i18n/",
|
|
21
21
|
"/bin/cli",
|
|
22
|
-
"/dist/"
|
|
22
|
+
"/dist/",
|
|
23
|
+
"!/dist/test/"
|
|
23
24
|
],
|
|
24
25
|
"bin": {
|
|
25
26
|
"wikilint": "./bin/cli.js"
|
|
@@ -30,15 +31,15 @@
|
|
|
30
31
|
"url": "git+https://github.com/bhsd-harry/wikiparser-node.git"
|
|
31
32
|
},
|
|
32
33
|
"scripts": {
|
|
33
|
-
"prepublishOnly": "npm run build
|
|
34
|
-
"build": "rm -rf dist/; tsc
|
|
34
|
+
"prepublishOnly": "npm run build && rm dist/internal.js dist/base.js dist/[bmpu]*/*.d.ts",
|
|
35
|
+
"build": "rm -rf dist/; tsc && grep -rl --include='*.d.ts' '@private' dist/ | xargs gsed -i '/@private/,+1d'",
|
|
35
36
|
"diff": "git diff --ignore-all-space --color-moved",
|
|
36
37
|
"lint:ts": "tsc --noEmit && eslint --cache .",
|
|
37
38
|
"lint:json": "ajv -s config/.schema.json -d 'config/*.json' --strict=true --strict-required=false",
|
|
38
39
|
"lint": "npm run lint:ts && npm run lint:json",
|
|
39
40
|
"test": "npx wikilint test/single-page.wiki",
|
|
40
41
|
"test:real": "node dist/test/real.js",
|
|
41
|
-
"test:single": "node dist/test/single.js
|
|
42
|
+
"test:single": "node dist/test/single.js && node --prof dist/test/single.js && node --prof-process isolate-0x*-v8.log > test/processed.txt && rm isolate-0x*-v8.log"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
45
|
"@cypress/request": "^3.0.1",
|
|
@@ -49,6 +50,7 @@
|
|
|
49
50
|
"@typescript-eslint/parser": "^6.12.0",
|
|
50
51
|
"ajv-cli": "^5.0.0",
|
|
51
52
|
"eslint": "^8.56.0",
|
|
53
|
+
"eslint-plugin-es-x": "^7.3.0",
|
|
52
54
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
53
55
|
"eslint-plugin-jsdoc": "^47.0.2",
|
|
54
56
|
"eslint-plugin-json-es": "^1.5.7",
|