wikiparser-node 0.8.1 → 0.9.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/config/moegirl.json +1 -0
- package/i18n/zh-hans.json +44 -0
- package/i18n/zh-hant.json +44 -0
- package/index.js +15 -3
- package/lib/element.js +27 -27
- package/lib/node.js +3 -5
- package/lib/text.js +11 -33
- package/lib/title.js +8 -6
- package/mixin/sol.js +3 -14
- package/package.json +7 -6
- package/parser/brackets.js +8 -2
- package/parser/commentAndExt.js +1 -4
- package/parser/links.js +1 -1
- package/parser/quotes.js +1 -1
- package/parser/selector.js +5 -5
- package/src/arg.js +7 -3
- package/src/attribute.js +14 -8
- package/src/attributes.js +6 -7
- package/src/converterFlags.js +3 -3
- package/src/converterRule.js +4 -6
- package/src/extLink.js +4 -3
- package/src/gallery.js +6 -9
- package/src/heading.js +8 -8
- package/src/html.js +15 -9
- package/src/imageParameter.js +78 -55
- package/src/imagemap.js +5 -5
- package/src/imagemapLink.js +1 -1
- package/src/index.js +9 -6
- package/src/link/category.js +4 -9
- package/src/link/file.js +16 -11
- package/src/link/galleryImage.js +7 -7
- package/src/link/index.js +19 -18
- package/src/magicLink.js +2 -2
- package/src/nested/index.js +3 -6
- package/src/nowiki/comment.js +2 -2
- package/src/nowiki/index.js +2 -2
- package/src/nowiki/quote.js +3 -3
- package/src/paramTag/index.js +3 -3
- package/src/parameter.js +2 -2
- package/src/table/index.js +5 -6
- package/src/table/td.js +5 -6
- package/src/table/tr.js +3 -3
- package/src/tagPair/ext.js +14 -8
- package/src/transclude.js +43 -26
- package/util/lint.js +8 -7
- package/util/string.js +20 -1
package/src/link/category.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const {decodeHtml} = require('../../util/string'),
|
|
4
4
|
Parser = require('../..'),
|
|
5
5
|
LinkToken = require('.');
|
|
6
6
|
|
|
@@ -13,11 +13,7 @@ class CategoryToken extends LinkToken {
|
|
|
13
13
|
|
|
14
14
|
/** 分类排序关键字 */
|
|
15
15
|
get sortkey() {
|
|
16
|
-
return this.childNodes[1]?.text()
|
|
17
|
-
/&#(\d+|x[\da-f]+);|\n/gu,
|
|
18
|
-
/** @param {string} p */
|
|
19
|
-
(_, p) => p ? String.fromCodePoint(p[0] === 'x' ? parseInt(p.slice(1), 16) : Number(p)) : '',
|
|
20
|
-
);
|
|
16
|
+
return decodeHtml(this.childNodes[1]?.text());
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
set sortkey(text) {
|
|
@@ -27,12 +23,11 @@ class CategoryToken extends LinkToken {
|
|
|
27
23
|
/**
|
|
28
24
|
* @param {string} link 分类名
|
|
29
25
|
* @param {string|undefined} text 排序关键字
|
|
30
|
-
* @param {Title} title 分类页面标题对象
|
|
31
26
|
* @param {accum} accum
|
|
32
27
|
* @param {string} delimiter `|`
|
|
33
28
|
*/
|
|
34
|
-
constructor(link, text,
|
|
35
|
-
super(link, text,
|
|
29
|
+
constructor(link, text, config = Parser.getConfig(), accum = [], delimiter = '|') {
|
|
30
|
+
super(link, text, config, accum, delimiter);
|
|
36
31
|
this.seal(['selfLink', 'interwiki', 'setLangLink', 'setFragment', 'asSelfLink', 'pipeTrick'], true);
|
|
37
32
|
}
|
|
38
33
|
|
package/src/link/file.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const {explode, noWrap} = require('../../util/string'),
|
|
4
4
|
{generateForChild} = require('../../util/lint'),
|
|
5
5
|
Parser = require('../..'),
|
|
6
|
-
Title = require('../../lib/title'),
|
|
7
6
|
LinkToken = require('.'),
|
|
8
7
|
ImageParameterToken = require('../imageParameter');
|
|
9
8
|
|
|
@@ -63,13 +62,12 @@ class FileToken extends LinkToken {
|
|
|
63
62
|
/**
|
|
64
63
|
* @param {string} link 文件名
|
|
65
64
|
* @param {string|undefined} text 图片参数
|
|
66
|
-
* @param {Title} title 文件标题对象
|
|
67
65
|
* @param {accum} accum
|
|
68
66
|
* @param {string} delimiter `|`
|
|
69
67
|
* @complexity `n`
|
|
70
68
|
*/
|
|
71
|
-
constructor(link, text,
|
|
72
|
-
super(link, undefined,
|
|
69
|
+
constructor(link, text, config = Parser.getConfig(), accum = [], delimiter = '|') {
|
|
70
|
+
super(link, undefined, config, accum, delimiter);
|
|
73
71
|
this.setAttribute('acceptable', {AtomToken: 0, ImageParameterToken: '1:'});
|
|
74
72
|
this.append(...explode('-{', '}-', '|', text).map(part => new ImageParameterToken(part, config, accum)));
|
|
75
73
|
this.seal(
|
|
@@ -82,10 +80,13 @@ class FileToken extends LinkToken {
|
|
|
82
80
|
* @override
|
|
83
81
|
* @param {number} start 起始位置
|
|
84
82
|
*/
|
|
85
|
-
lint(start =
|
|
83
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
86
84
|
const errors = super.lint(start),
|
|
87
|
-
args = this.getAllArgs()
|
|
88
|
-
|
|
85
|
+
args = this.getAllArgs().filter(({childNodes}) => {
|
|
86
|
+
const visibleNodes = childNodes.filter(node => node.text().trim());
|
|
87
|
+
return visibleNodes.length !== 1 || visibleNodes[0].type !== 'arg';
|
|
88
|
+
}),
|
|
89
|
+
keys = [...new Set(args.map(({name}) => name))].filter(key => key !== 'invalid'),
|
|
89
90
|
frameKeys = keys.filter(key => frame.has(key)),
|
|
90
91
|
horizAlignKeys = keys.filter(key => horizAlign.has(key)),
|
|
91
92
|
vertAlignKeys = keys.filter(key => vertAlign.has(key));
|
|
@@ -104,24 +105,28 @@ class FileToken extends LinkToken {
|
|
|
104
105
|
];
|
|
105
106
|
}
|
|
106
107
|
if (relevantArgs.length > 1) {
|
|
107
|
-
errors.push(...relevantArgs.map(
|
|
108
|
+
errors.push(...relevantArgs.map(
|
|
109
|
+
arg => generateForChild(arg, rect, Parser.msg('duplicated image $1 parameter', key)),
|
|
110
|
+
));
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
113
|
if (frameKeys.size > 1) {
|
|
111
114
|
errors.push(
|
|
112
|
-
...args.filter(({name}) => frame.has(name)).map(
|
|
115
|
+
...args.filter(({name}) => frame.has(name)).map(
|
|
116
|
+
arg => generateForChild(arg, rect, 'conflicting image $1 parameter', 'frame'),
|
|
117
|
+
),
|
|
113
118
|
);
|
|
114
119
|
}
|
|
115
120
|
if (horizAlignKeys.size > 1) {
|
|
116
121
|
errors.push(
|
|
117
122
|
...args.filter(({name}) => horizAlign.has(name))
|
|
118
|
-
.map(arg => generateForChild(arg, rect, '
|
|
123
|
+
.map(arg => generateForChild(arg, rect, 'conflicting image $1 parameter', 'horizontal-alignment')),
|
|
119
124
|
);
|
|
120
125
|
}
|
|
121
126
|
if (vertAlignKeys.size > 1) {
|
|
122
127
|
errors.push(
|
|
123
128
|
...args.filter(({name}) => vertAlign.has(name))
|
|
124
|
-
.map(arg => generateForChild(arg, rect, '
|
|
129
|
+
.map(arg => generateForChild(arg, rect, 'conflicting image $1 parameter', 'vertical-alignment')),
|
|
125
130
|
);
|
|
126
131
|
}
|
|
127
132
|
return errors;
|
package/src/link/galleryImage.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const {generateForSelf} = require('../../util/lint'),
|
|
4
4
|
{undo} = require('../../util/debug'),
|
|
5
5
|
singleLine = require('../../mixin/singleLine'),
|
|
6
|
-
Title = require('../../lib/title'),
|
|
7
6
|
Parser = require('../..'),
|
|
8
7
|
Token = require('..'),
|
|
9
8
|
FileToken = require('./file');
|
|
@@ -22,16 +21,17 @@ class GalleryImageToken extends singleLine(FileToken) {
|
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
set link(value) {
|
|
25
|
-
|
|
24
|
+
if (this.type !== 'imagemap-image') {
|
|
25
|
+
super.link = value;
|
|
26
|
+
}
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* @param {string} link 图片文件名
|
|
30
31
|
* @param {string|undefined} text 图片参数
|
|
31
|
-
* @param {Title} title 图片文件标题对象
|
|
32
32
|
* @param {accum} accum
|
|
33
33
|
*/
|
|
34
|
-
constructor(link, text,
|
|
34
|
+
constructor(link, text, config = Parser.getConfig(), accum = []) {
|
|
35
35
|
let token;
|
|
36
36
|
if (text !== undefined) {
|
|
37
37
|
token = new Token(text, config, true, accum);
|
|
@@ -41,7 +41,7 @@ class GalleryImageToken extends singleLine(FileToken) {
|
|
|
41
41
|
}
|
|
42
42
|
accum.splice(accum.indexOf(token), 1);
|
|
43
43
|
}
|
|
44
|
-
super(link, token?.toString(),
|
|
44
|
+
super(link, token?.toString(), config, accum);
|
|
45
45
|
this.setAttribute('bracket', false);
|
|
46
46
|
if (!Object.values(config.img).includes('width')) {
|
|
47
47
|
this.seal(['size', 'width', 'height'], true);
|
|
@@ -87,10 +87,10 @@ class GalleryImageToken extends singleLine(FileToken) {
|
|
|
87
87
|
* @override
|
|
88
88
|
* @param {number} start 起始位置
|
|
89
89
|
*/
|
|
90
|
-
lint(start =
|
|
90
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
91
91
|
const errors = super.lint(start);
|
|
92
92
|
if (this.#invalid) {
|
|
93
|
-
errors.push(generateForSelf(this, {start}, '
|
|
93
|
+
errors.push(generateForSelf(this, {start}, 'invalid gallery image'));
|
|
94
94
|
}
|
|
95
95
|
return errors;
|
|
96
96
|
}
|
package/src/link/index.js
CHANGED
|
@@ -4,7 +4,6 @@ const {generateForChild} = require('../../util/lint'),
|
|
|
4
4
|
{noWrap} = require('../../util/string'),
|
|
5
5
|
{undo} = require('../../util/debug'),
|
|
6
6
|
Parser = require('../..'),
|
|
7
|
-
Title = require('../../lib/title'),
|
|
8
7
|
AstText = require('../../lib/text'),
|
|
9
8
|
Token = require('..'),
|
|
10
9
|
AtomToken = require('../atom');
|
|
@@ -17,12 +16,12 @@ class LinkToken extends Token {
|
|
|
17
16
|
type = 'link';
|
|
18
17
|
#bracket = true;
|
|
19
18
|
#delimiter;
|
|
20
|
-
#fragment
|
|
19
|
+
#fragment;
|
|
21
20
|
#encoded = false;
|
|
22
21
|
|
|
23
22
|
/** 完整链接,和FileToken保持一致 */
|
|
24
23
|
get link() {
|
|
25
|
-
return
|
|
24
|
+
return this.#getTitle();
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
set link(link) {
|
|
@@ -31,7 +30,8 @@ class LinkToken extends Token {
|
|
|
31
30
|
|
|
32
31
|
/** 是否链接到自身 */
|
|
33
32
|
get selfLink() {
|
|
34
|
-
|
|
33
|
+
const {title, fragment} = this.#getTitle();
|
|
34
|
+
return !title && Boolean(fragment);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
set selfLink(selfLink) {
|
|
@@ -46,7 +46,7 @@ class LinkToken extends Token {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
set fragment(fragment) {
|
|
49
|
-
this
|
|
49
|
+
this.#setFragment(fragment);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/** interwiki */
|
|
@@ -59,7 +59,7 @@ class LinkToken extends Token {
|
|
|
59
59
|
this.typeError('set interwiki', 'String');
|
|
60
60
|
}
|
|
61
61
|
const {prefix, main, fragment} = this.#getTitle(),
|
|
62
|
-
link = `${interwiki}:${prefix}${main}${fragment
|
|
62
|
+
link = `${interwiki}:${prefix}${main}${fragment === undefined ? '' : `#${fragment}`}`;
|
|
63
63
|
if (interwiki && !this.isInterwiki(link)) {
|
|
64
64
|
throw new RangeError(`${interwiki} 不是合法的跨维基前缀!`);
|
|
65
65
|
}
|
|
@@ -79,11 +79,10 @@ class LinkToken extends Token {
|
|
|
79
79
|
/**
|
|
80
80
|
* @param {string} link 链接标题
|
|
81
81
|
* @param {string|undefined} linkText 链接显示文字
|
|
82
|
-
* @param {Title} title 链接标题对象
|
|
83
82
|
* @param {accum} accum
|
|
84
83
|
* @param {string} delimiter `|`
|
|
85
84
|
*/
|
|
86
|
-
constructor(link, linkText,
|
|
85
|
+
constructor(link, linkText, config = Parser.getConfig(), accum = [], delimiter = '|') {
|
|
87
86
|
super(undefined, config, true, accum, {
|
|
88
87
|
AtomToken: 0, Token: 1,
|
|
89
88
|
});
|
|
@@ -191,22 +190,22 @@ class LinkToken extends Token {
|
|
|
191
190
|
* @override
|
|
192
191
|
* @param {number} start 起始位置
|
|
193
192
|
*/
|
|
194
|
-
lint(start =
|
|
193
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
195
194
|
const errors = super.lint(start),
|
|
196
195
|
{childNodes: [target, linkText], type: linkType} = this;
|
|
197
196
|
let rect;
|
|
198
|
-
if (this.#encoded
|
|
197
|
+
if (this.#encoded) {
|
|
199
198
|
rect = {start, ...this.getRootNode().posFromIndex(start)};
|
|
200
|
-
errors.push(generateForChild(target, rect, '
|
|
199
|
+
errors.push(generateForChild(target, rect, 'unnecessary URL encoding in an internal link'));
|
|
201
200
|
}
|
|
202
201
|
if (linkType === 'link' && linkText?.childNodes?.some(
|
|
203
202
|
/** @param {AstText} */ ({type, data}) => type === 'text' && data.includes('|'),
|
|
204
203
|
)) {
|
|
205
204
|
rect ||= {start, ...this.getRootNode().posFromIndex(start)};
|
|
206
|
-
errors.push(generateForChild(linkText, rect, '
|
|
207
|
-
} else if (linkType !== 'link' && this.#fragment) {
|
|
205
|
+
errors.push(generateForChild(linkText, rect, 'additional "|" in the link text', 'warning'));
|
|
206
|
+
} else if (linkType !== 'link' && this.#fragment !== undefined) {
|
|
208
207
|
rect ||= {start, ...this.getRootNode().posFromIndex(start)};
|
|
209
|
-
errors.push(generateForChild(target, rect, '
|
|
208
|
+
errors.push(generateForChild(target, rect, 'useless fragment'));
|
|
210
209
|
}
|
|
211
210
|
return errors;
|
|
212
211
|
}
|
|
@@ -286,10 +285,12 @@ class LinkToken extends Token {
|
|
|
286
285
|
* @throws `SyntaxError` 非法的fragment
|
|
287
286
|
*/
|
|
288
287
|
#setFragment(fragment, page = true) {
|
|
289
|
-
fragment
|
|
288
|
+
fragment &&= String(fragment).replace(/[<>[\]#|=]/gu, p => encodeURIComponent(p));
|
|
290
289
|
const include = this.getAttribute('include'),
|
|
291
290
|
config = this.getAttribute('config'),
|
|
292
|
-
root = Parser.parse(`[[${page ? `:${this.name}` : ''}
|
|
291
|
+
root = Parser.parse(`[[${page ? `:${this.name}` : ''}${
|
|
292
|
+
fragment === undefined ? '' : `#${fragment}`
|
|
293
|
+
}]]`, include, 6, config),
|
|
293
294
|
{length, firstChild: wikiLink} = root,
|
|
294
295
|
{type, length: linkLength, firstChild} = wikiLink;
|
|
295
296
|
if (length !== 1 || type !== 'link' || linkLength !== 1) {
|
|
@@ -315,8 +316,8 @@ class LinkToken extends Token {
|
|
|
315
316
|
* @throws `RangeError` 空fragment
|
|
316
317
|
*/
|
|
317
318
|
asSelfLink(fragment = this.fragment) {
|
|
318
|
-
fragment
|
|
319
|
-
if (!fragment
|
|
319
|
+
fragment &&= String(fragment);
|
|
320
|
+
if (!fragment?.trim()) {
|
|
320
321
|
throw new RangeError(`${this.constructor.name}.asSelfLink 方法必须指定非空的 fragment!`);
|
|
321
322
|
}
|
|
322
323
|
this.#setFragment(fragment, false);
|
package/src/magicLink.js
CHANGED
|
@@ -43,7 +43,7 @@ class MagicLinkToken extends Token {
|
|
|
43
43
|
* @override
|
|
44
44
|
* @param {number} start 起始位置
|
|
45
45
|
*/
|
|
46
|
-
lint(start =
|
|
46
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
47
47
|
const errors = super.lint(start),
|
|
48
48
|
source = `[,;。:!?()]+${this.type === 'ext-link-url' ? '|\\|+' : ''}`;
|
|
49
49
|
let /** @type {{top: number, left: number}} */ rect;
|
|
@@ -63,7 +63,7 @@ class MagicLinkToken extends Token {
|
|
|
63
63
|
startCol = (top > 1 ? 0 : refError.startCol) + left;
|
|
64
64
|
return {
|
|
65
65
|
...refError,
|
|
66
|
-
message:
|
|
66
|
+
message: Parser.msg('$1 in URL', char === '|' ? '"|"' : Parser.msg('full-width punctuation')),
|
|
67
67
|
startIndex,
|
|
68
68
|
endIndex: startIndex + length,
|
|
69
69
|
startLine,
|
package/src/nested/index.js
CHANGED
|
@@ -34,10 +34,7 @@ class NestedToken extends Token {
|
|
|
34
34
|
}
|
|
35
35
|
return str;
|
|
36
36
|
},
|
|
37
|
-
)?.replace(/(?<=^|\0\d+[ce]\x7F)
|
|
38
|
-
if (substr === '') {
|
|
39
|
-
return '';
|
|
40
|
-
}
|
|
37
|
+
)?.replace(/(?<=^|\0\d+[ce]\x7F)[^\0]+(?=$|\0\d+[ce]\x7F)/gu, substr => {
|
|
41
38
|
new NoincludeToken(substr, config, accum);
|
|
42
39
|
return `\0${accum.length}c\x7F`;
|
|
43
40
|
});
|
|
@@ -51,7 +48,7 @@ class NestedToken extends Token {
|
|
|
51
48
|
* @override
|
|
52
49
|
* @param {number} start 起始位置
|
|
53
50
|
*/
|
|
54
|
-
lint(start =
|
|
51
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
55
52
|
let rect;
|
|
56
53
|
return [
|
|
57
54
|
...super.lint(start),
|
|
@@ -63,7 +60,7 @@ class NestedToken extends Token {
|
|
|
63
60
|
return str && !/^<!--.*-->$/u.test(str);
|
|
64
61
|
}).map(child => {
|
|
65
62
|
rect ||= {start, ...this.getRootNode().posFromIndex(start)};
|
|
66
|
-
return generateForChild(child, rect,
|
|
63
|
+
return generateForChild(child, rect, Parser.msg('invalid content in <$1>', this.name));
|
|
67
64
|
}),
|
|
68
65
|
];
|
|
69
66
|
}
|
package/src/nowiki/comment.js
CHANGED
|
@@ -43,8 +43,8 @@ class CommentToken extends hidden(NowikiToken) {
|
|
|
43
43
|
* @override
|
|
44
44
|
* @param {number} start 起始位置
|
|
45
45
|
*/
|
|
46
|
-
lint(start =
|
|
47
|
-
return this.closed ? [] : [generateForSelf(this, {start}, '
|
|
46
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
47
|
+
return this.closed ? [] : [generateForSelf(this, {start}, 'unclosed HTML comment')];
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
package/src/nowiki/index.js
CHANGED
|
@@ -25,10 +25,10 @@ class NowikiToken extends fixedToken(Token) {
|
|
|
25
25
|
* @override
|
|
26
26
|
* @param {number} start 起始位置
|
|
27
27
|
*/
|
|
28
|
-
lint(start =
|
|
28
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
29
29
|
const {type, name} = this;
|
|
30
30
|
return type === 'ext-inner' && (name === 'templatestyles' || name === 'section') && String(this)
|
|
31
|
-
? [generateForSelf(this, {start},
|
|
31
|
+
? [generateForSelf(this, {start}, Parser.msg('nothing should be in <$1>', name))]
|
|
32
32
|
: super.lint(start);
|
|
33
33
|
}
|
|
34
34
|
|
package/src/nowiki/quote.js
CHANGED
|
@@ -26,12 +26,12 @@ class QuoteToken extends NowikiToken {
|
|
|
26
26
|
* @this {AstText}
|
|
27
27
|
* @param {number} start 起始位置
|
|
28
28
|
*/
|
|
29
|
-
lint(start =
|
|
29
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
30
30
|
const {previousSibling, nextSibling} = this,
|
|
31
|
-
message =
|
|
31
|
+
message = Parser.msg('lonely "$1"', `'`),
|
|
32
32
|
/** @type {LintError[]} */ errors = [];
|
|
33
33
|
let refError, wikitext;
|
|
34
|
-
if (previousSibling?.type === 'text' && previousSibling.data.
|
|
34
|
+
if (previousSibling?.type === 'text' && previousSibling.data.endsWith(`'`)) {
|
|
35
35
|
refError = generateForSelf(this, {start}, message);
|
|
36
36
|
wikitext = String(this.getRootNode());
|
|
37
37
|
const {startIndex: endIndex, startLine: endLine, startCol: endCol} = refError,
|
package/src/paramTag/index.js
CHANGED
|
@@ -58,16 +58,16 @@ class ParamTagToken extends Token {
|
|
|
58
58
|
* @override
|
|
59
59
|
* @param {number} start 起始位置
|
|
60
60
|
*/
|
|
61
|
-
lint(start =
|
|
61
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
62
62
|
let /** @type {{top: number, left: number}} */ rect;
|
|
63
63
|
return this.childNodes.filter(child => {
|
|
64
64
|
const {childNodes} = child,
|
|
65
65
|
i = childNodes.findIndex(({type}) => type !== 'text'),
|
|
66
66
|
str = (i >= 0 ? childNodes.slice(0, i).map(String).join('') : String(child)).trim();
|
|
67
|
-
return str && !(i >= 0 ? /^[a-z]
|
|
67
|
+
return str && !(i >= 0 ? /^[a-z]+(?:\[\])?\s*(?:=|$)/iu : /^[a-z]+(?:\[\])?\s*=/iu).test(str);
|
|
68
68
|
}).map(child => {
|
|
69
69
|
rect ||= {start, ...this.getRootNode().posFromIndex(start)};
|
|
70
|
-
return generateForChild(child, rect,
|
|
70
|
+
return generateForChild(child, rect, Parser.msg('invalid parameter of $1', this.name));
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
73
|
|
package/src/parameter.js
CHANGED
|
@@ -117,13 +117,13 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
117
117
|
* @override
|
|
118
118
|
* @param {number} start 起始位置
|
|
119
119
|
*/
|
|
120
|
-
lint(start =
|
|
120
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
121
121
|
const errors = super.lint(start),
|
|
122
122
|
{firstChild, lastChild} = this,
|
|
123
123
|
link = new RegExp(`https?://${extUrlCharFirst}${extUrlChar}$`, 'iu')
|
|
124
124
|
.exec(firstChild.toString('comment, noinclude, include'))?.[0];
|
|
125
125
|
if (link && new URL(link).search) {
|
|
126
|
-
const e = generateForChild(firstChild, {start}, '
|
|
126
|
+
const e = generateForChild(firstChild, {start}, 'unescaped query string in an anonymous parameter');
|
|
127
127
|
errors.push({
|
|
128
128
|
...e,
|
|
129
129
|
startIndex: e.endIndex,
|
package/src/table/index.js
CHANGED
|
@@ -72,13 +72,12 @@ const format = (cells, attr = {}, multi = false) => {
|
|
|
72
72
|
*/
|
|
73
73
|
const fill = (y, rowToken, layout, maxCol, token) => {
|
|
74
74
|
const rowLayout = layout[y],
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|| undefined;
|
|
75
|
+
lastIndex = rowToken.childNodes.findLastIndex(child => child instanceof TdToken && child.subtype !== 'caption'),
|
|
76
|
+
pos = lastIndex + 1 || undefined;
|
|
78
77
|
Parser.run(() => {
|
|
79
78
|
for (let i = 0; i < maxCol; i++) {
|
|
80
79
|
if (!rowLayout[i]) {
|
|
81
|
-
rowToken.insertAt(token.cloneNode(),
|
|
80
|
+
rowToken.insertAt(token.cloneNode(), pos);
|
|
82
81
|
}
|
|
83
82
|
}
|
|
84
83
|
});
|
|
@@ -171,12 +170,12 @@ class TableToken extends TrToken {
|
|
|
171
170
|
* @override
|
|
172
171
|
* @param {number} start 起始位置
|
|
173
172
|
*/
|
|
174
|
-
lint(start =
|
|
173
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
175
174
|
const errors = super.lint(start);
|
|
176
175
|
if (!this.closed) {
|
|
177
176
|
const {firstChild, lastChild: tr} = this,
|
|
178
177
|
{lastChild: td} = tr,
|
|
179
|
-
error = generateForChild(firstChild, {start}, '
|
|
178
|
+
error = generateForChild(firstChild, {start}, 'unclosed table');
|
|
180
179
|
errors.push({...error, excerpt: String(td?.type === 'td' ? td : tr).slice(0, 50)});
|
|
181
180
|
}
|
|
182
181
|
return errors;
|
package/src/table/td.js
CHANGED
|
@@ -9,7 +9,7 @@ const {generateForChild} = require('../../util/lint'),
|
|
|
9
9
|
TrToken = require('./tr');
|
|
10
10
|
|
|
11
11
|
const aliases = {td: '\n|', th: '\n!', caption: '\n|+'},
|
|
12
|
-
openingPattern = /^(?:\n[
|
|
12
|
+
openingPattern = /^(?:\n[^\S\n]*(?:[|!]|\|\+|\{\{\s*!\s*\}\}\+?)|(?:\||\{\{\s*!\s*\}\}){2}|!!|\{\{\s*!!\s*\}\})$/u;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* `<td>`、`<th>`和`<caption>`
|
|
@@ -166,13 +166,12 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
166
166
|
* @override
|
|
167
167
|
* @param {number} start 起始位置
|
|
168
168
|
*/
|
|
169
|
-
lint(start =
|
|
170
|
-
const errors = super.lint(start)
|
|
171
|
-
{lastChild} = this;
|
|
169
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
170
|
+
const errors = super.lint(start);
|
|
172
171
|
start += this.getRelativeIndex(-1);
|
|
173
|
-
for (const child of lastChild.childNodes) {
|
|
172
|
+
for (const child of this.lastChild.childNodes) {
|
|
174
173
|
if (child.type === 'text' && child.data.includes('|')) {
|
|
175
|
-
errors.push(generateForChild(child, {start}, '
|
|
174
|
+
errors.push(generateForChild(child, {start}, 'additional "|" in a table cell', 'warning'));
|
|
176
175
|
}
|
|
177
176
|
}
|
|
178
177
|
return errors;
|
package/src/table/tr.js
CHANGED
|
@@ -55,7 +55,7 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
55
55
|
* @override
|
|
56
56
|
* @param {number} start 起始位置
|
|
57
57
|
*/
|
|
58
|
-
lint(start =
|
|
58
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
59
59
|
const TranscludeToken = require('../transclude'),
|
|
60
60
|
ArgToken = require('../arg');
|
|
61
61
|
const errors = super.lint(start),
|
|
@@ -75,7 +75,7 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
75
75
|
}
|
|
76
76
|
} catch {}
|
|
77
77
|
}
|
|
78
|
-
const error = generateForChild(inter, {start}, '
|
|
78
|
+
const error = generateForChild(inter, {start}, 'content to be moved out from the table');
|
|
79
79
|
errors.push({
|
|
80
80
|
...error,
|
|
81
81
|
startIndex: error.startIndex + 1,
|
|
@@ -207,7 +207,7 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
207
207
|
getRowCount() {
|
|
208
208
|
const TdToken = require('./td');
|
|
209
209
|
return Number(this.childNodes.some(
|
|
210
|
-
child => child instanceof TdToken && child.isIndependent() && child.firstChild.text().
|
|
210
|
+
child => child instanceof TdToken && child.isIndependent() && !child.firstChild.text().endsWith('+'),
|
|
211
211
|
));
|
|
212
212
|
}
|
|
213
213
|
|
package/src/tagPair/ext.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const {generateForSelf} = require('../../util/lint'),
|
|
4
4
|
attributeParent = require('../../mixin/attributeParent'),
|
|
5
|
-
path = require('path'),
|
|
6
5
|
Parser = require('../..'),
|
|
7
6
|
Token = require('..'),
|
|
8
7
|
TagPairToken = require('.'),
|
|
@@ -65,12 +64,19 @@ class ExtToken extends attributeParent(TagPairToken) {
|
|
|
65
64
|
innerToken = new CharinsertToken(inner, newConfig, accum);
|
|
66
65
|
break;
|
|
67
66
|
}
|
|
68
|
-
case 'references':
|
|
69
|
-
|
|
67
|
+
case 'references': {
|
|
68
|
+
const ReferencesToken = require('../nested/references');
|
|
69
|
+
innerToken = new ReferencesToken(inner, newConfig, accum);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
case 'choose': {
|
|
73
|
+
const ChooseToken = require('../nested/choose');
|
|
74
|
+
innerToken = new ChooseToken(inner, newConfig, accum);
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
70
77
|
case 'combobox': {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
innerToken = new NestedExtToken(inner, newConfig, accum);
|
|
78
|
+
const ComboboxToken = require('../nested/combobox');
|
|
79
|
+
innerToken = new ComboboxToken(inner, newConfig, accum);
|
|
74
80
|
break;
|
|
75
81
|
}
|
|
76
82
|
case 'imagemap': {
|
|
@@ -113,13 +119,13 @@ class ExtToken extends attributeParent(TagPairToken) {
|
|
|
113
119
|
* @override
|
|
114
120
|
* @param {number} start 起始位置
|
|
115
121
|
*/
|
|
116
|
-
lint(start =
|
|
122
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
117
123
|
const errors = super.lint(start);
|
|
118
124
|
if (this.name !== 'nowiki' && this.closest('html-attrs, table-attrs')) {
|
|
119
125
|
const root = this.getRootNode(),
|
|
120
126
|
excerpt = String(root).slice(Math.max(0, start - 25), start + 25),
|
|
121
127
|
rect = {start, ...root.posFromIndex(start)};
|
|
122
|
-
errors.push({...generateForSelf(this, rect, 'HTML
|
|
128
|
+
errors.push({...generateForSelf(this, rect, 'extension tag in HTML tag attributes'), excerpt});
|
|
123
129
|
}
|
|
124
130
|
return errors;
|
|
125
131
|
}
|