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/transclude.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {removeComment, escapeRegExp, text, noWrap, print} = require('../util/string'),
|
|
3
|
+
const {removeComment, escapeRegExp, text, noWrap, print, decodeHtml} = require('../util/string'),
|
|
4
4
|
{externalUse} = require('../util/debug'),
|
|
5
5
|
{generateForChild} = require('../util/lint'),
|
|
6
6
|
Parser = require('..'),
|
|
@@ -18,8 +18,9 @@ class TranscludeToken extends Token {
|
|
|
18
18
|
modifier = '';
|
|
19
19
|
/** @type {Record<string, Set<ParameterToken>>} */ #args = {};
|
|
20
20
|
/** @type {Set<string>} */ #keys = new Set();
|
|
21
|
-
#fragment
|
|
21
|
+
#fragment;
|
|
22
22
|
#valid = true;
|
|
23
|
+
#raw = false;
|
|
23
24
|
|
|
24
25
|
/** 是否存在重复参数 */
|
|
25
26
|
get duplication() {
|
|
@@ -36,14 +37,18 @@ class TranscludeToken extends Token {
|
|
|
36
37
|
this.typeError('setModifier', 'String');
|
|
37
38
|
}
|
|
38
39
|
const {parserFunction: [,, raw, subst]} = this.getAttribute('config'),
|
|
39
|
-
lcModifier = modifier
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
lcModifier = removeComment(modifier).trim();
|
|
41
|
+
if (modifier && !lcModifier.endsWith(':')) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const magicWord = lcModifier.slice(0, -1).toLowerCase(),
|
|
45
|
+
isRaw = raw.includes(magicWord),
|
|
46
|
+
isSubst = subst.includes(magicWord);
|
|
47
|
+
if (this.#raw && isRaw || !this.#raw && (isSubst || modifier === '')
|
|
44
48
|
|| (Parser.running || this.length > 1) && (isRaw || isSubst || modifier === '')
|
|
45
49
|
) {
|
|
46
50
|
this.setAttribute('modifier', modifier);
|
|
51
|
+
this.#raw = isRaw;
|
|
47
52
|
return Boolean(modifier);
|
|
48
53
|
}
|
|
49
54
|
return false;
|
|
@@ -60,15 +65,20 @@ class TranscludeToken extends Token {
|
|
|
60
65
|
super(undefined, config, true, accum, {
|
|
61
66
|
AtomToken: 0, SyntaxToken: 0, ParameterToken: '1:',
|
|
62
67
|
});
|
|
63
|
-
const {parserFunction: [insensitive, sensitive, raw]} = config;
|
|
64
68
|
this.seal('modifier');
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
const {parserFunction: [insensitive, sensitive]} = config,
|
|
70
|
+
argSubst = /^(?:\s|\0\d+c\x7F)*\0\d+s\x7F/u.exec(title)?.[0];
|
|
71
|
+
if (argSubst) {
|
|
72
|
+
this.setAttribute('modifier', argSubst);
|
|
73
|
+
title = title.slice(argSubst.length);
|
|
74
|
+
} else if (title.includes(':')) {
|
|
75
|
+
const [modifier, ...arg] = title.split(':'),
|
|
76
|
+
[mt] = /^(?:\s|\0\d+c\x7F)*/u.exec(arg[0] ?? '');
|
|
77
|
+
if (this.setModifier(`${modifier}:${mt}`)) {
|
|
78
|
+
title = arg.join(':').slice(mt.length);
|
|
69
79
|
}
|
|
70
80
|
}
|
|
71
|
-
if (title.includes(':') || parts.length === 0 && !raw
|
|
81
|
+
if (title.includes(':') || parts.length === 0 && !this.#raw) {
|
|
72
82
|
const [magicWord, ...arg] = title.split(':'),
|
|
73
83
|
cleaned = removeComment(magicWord),
|
|
74
84
|
name = cleaned[arg.length > 0 ? 'trimStart' : 'trim'](),
|
|
@@ -103,7 +113,7 @@ class TranscludeToken extends Token {
|
|
|
103
113
|
}
|
|
104
114
|
}
|
|
105
115
|
if (this.type === 'template') {
|
|
106
|
-
const name = removeComment(title).split('#')[0].trim();
|
|
116
|
+
const name = removeComment(decodeHtml(title)).split('#')[0].trim();
|
|
107
117
|
if (!name || /\0\d+[eh!+-]\x7F|[<>[\]{}\n]|%[\da-f]{2}/u.test(name)) {
|
|
108
118
|
accum.pop();
|
|
109
119
|
throw new SyntaxError(`非法的模板名称:${noWrap(name)}`);
|
|
@@ -132,6 +142,9 @@ class TranscludeToken extends Token {
|
|
|
132
142
|
|
|
133
143
|
/** @override */
|
|
134
144
|
afterBuild() {
|
|
145
|
+
if (this.modifier.includes('\0')) {
|
|
146
|
+
this.setAttribute('modifier', this.getAttribute('buildFromStr')(this.modifier, 'string'));
|
|
147
|
+
}
|
|
135
148
|
if (this.isTemplate()) {
|
|
136
149
|
const isTemplate = this.type === 'template',
|
|
137
150
|
titleObj = this.normalizeTitle(this.childNodes[isTemplate ? 0 : 1].text(), isTemplate ? 10 : 828);
|
|
@@ -182,7 +195,7 @@ class TranscludeToken extends Token {
|
|
|
182
195
|
return '';
|
|
183
196
|
}
|
|
184
197
|
const {childNodes, firstChild, modifier} = this;
|
|
185
|
-
return `{{${modifier}${
|
|
198
|
+
return `{{${modifier}${
|
|
186
199
|
this.type === 'magic-word'
|
|
187
200
|
? `${String(firstChild)}${childNodes.length > 1 ? ':' : ''}${childNodes.slice(1).map(String).join('|')}`
|
|
188
201
|
: super.toString(selector, '|')
|
|
@@ -198,7 +211,7 @@ class TranscludeToken extends Token {
|
|
|
198
211
|
const {childNodes, firstChild, modifier, type, name} = this;
|
|
199
212
|
return type === 'magic-word' && name === 'vardefine'
|
|
200
213
|
? ''
|
|
201
|
-
: `{{${modifier}${
|
|
214
|
+
: `{{${modifier}${
|
|
202
215
|
this.type === 'magic-word'
|
|
203
216
|
? `${firstChild.text()}${childNodes.length > 1 ? ':' : ''}${text(childNodes.slice(1), '|')}`
|
|
204
217
|
: super.text('|')
|
|
@@ -207,7 +220,7 @@ class TranscludeToken extends Token {
|
|
|
207
220
|
|
|
208
221
|
/** @override */
|
|
209
222
|
getPadding() {
|
|
210
|
-
return this.modifier
|
|
223
|
+
return this.modifier.length + 2;
|
|
211
224
|
}
|
|
212
225
|
|
|
213
226
|
/** @override */
|
|
@@ -218,7 +231,7 @@ class TranscludeToken extends Token {
|
|
|
218
231
|
/** @override */
|
|
219
232
|
print() {
|
|
220
233
|
const {childNodes, firstChild, modifier} = this;
|
|
221
|
-
return `<span class="wpb-${this.type}">{{${modifier}${
|
|
234
|
+
return `<span class="wpb-${this.type}">{{${modifier}${
|
|
222
235
|
this.type === 'magic-word'
|
|
223
236
|
? `${firstChild.print()}${childNodes.length > 1 ? ':' : ''}${print(childNodes.slice(1), {sep: '|'})}`
|
|
224
237
|
: print(childNodes, {sep: '|'})
|
|
@@ -229,25 +242,25 @@ class TranscludeToken extends Token {
|
|
|
229
242
|
* @override
|
|
230
243
|
* @param {number} start 起始位置
|
|
231
244
|
*/
|
|
232
|
-
lint(start =
|
|
245
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
233
246
|
const errors = super.lint(start),
|
|
234
247
|
{type, childNodes} = this;
|
|
235
248
|
let rect;
|
|
236
249
|
if (!this.isTemplate()) {
|
|
237
250
|
return errors;
|
|
238
|
-
} else if (this.#fragment) {
|
|
251
|
+
} else if (this.#fragment !== undefined) {
|
|
239
252
|
rect = {start, ...this.getRootNode().posFromIndex(start)};
|
|
240
|
-
errors.push(generateForChild(childNodes[type === 'template' ? 0 : 1], rect, '
|
|
253
|
+
errors.push(generateForChild(childNodes[type === 'template' ? 0 : 1], rect, 'useless fragment'));
|
|
241
254
|
}
|
|
242
255
|
if (!this.#valid) {
|
|
243
256
|
rect = {start, ...this.getRootNode().posFromIndex(start)};
|
|
244
|
-
errors.push(generateForChild(childNodes[1], rect, '
|
|
257
|
+
errors.push(generateForChild(childNodes[1], rect, 'illegal module name'));
|
|
245
258
|
}
|
|
246
259
|
const duplicatedArgs = this.getDuplicatedArgs();
|
|
247
260
|
if (duplicatedArgs.length > 0) {
|
|
248
261
|
rect ||= {start, ...this.getRootNode().posFromIndex(start)};
|
|
249
262
|
errors.push(...duplicatedArgs.flatMap(([, args]) => args).map(
|
|
250
|
-
arg => generateForChild(arg, rect, '
|
|
263
|
+
arg => generateForChild(arg, rect, 'duplicated parameter'),
|
|
251
264
|
));
|
|
252
265
|
}
|
|
253
266
|
return errors;
|
|
@@ -413,7 +426,11 @@ class TranscludeToken extends Token {
|
|
|
413
426
|
config = this.getAttribute('config');
|
|
414
427
|
return Parser.run(() => {
|
|
415
428
|
const token = new TranscludeToken(this.type === 'template' ? '' : first.text(), [], config);
|
|
416
|
-
|
|
429
|
+
if (this.#raw) {
|
|
430
|
+
token.setModifier(this.modifier);
|
|
431
|
+
} else {
|
|
432
|
+
token.setAttribute('modifier', this.modifier);
|
|
433
|
+
}
|
|
417
434
|
token.firstChild.safeReplaceWith(first);
|
|
418
435
|
token.afterBuild();
|
|
419
436
|
token.append(...cloned);
|
|
@@ -423,12 +440,12 @@ class TranscludeToken extends Token {
|
|
|
423
440
|
|
|
424
441
|
/** 替换引用 */
|
|
425
442
|
subst() {
|
|
426
|
-
this.setModifier('subst');
|
|
443
|
+
this.setModifier('subst:');
|
|
427
444
|
}
|
|
428
445
|
|
|
429
446
|
/** 安全的替换引用 */
|
|
430
447
|
safesubst() {
|
|
431
|
-
this.setModifier('safesubst');
|
|
448
|
+
this.setModifier('safesubst:');
|
|
432
449
|
}
|
|
433
450
|
|
|
434
451
|
/**
|
package/util/lint.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const Parser = require('..'),
|
|
4
|
+
Token = require('../src');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* 生成对于子节点的LintError对象
|
|
7
8
|
* @param {Token} child 子节点
|
|
8
9
|
* @param {{top: number, left: number, start: number}} boundingRect 父节点的绝对定位
|
|
9
|
-
* @param {string}
|
|
10
|
+
* @param {string} msg 错误信息
|
|
10
11
|
* @param {'error'|'warning'} severity 严重程度
|
|
11
12
|
* @returns {LintError}
|
|
12
13
|
*/
|
|
13
|
-
const generateForChild = (child, boundingRect,
|
|
14
|
+
const generateForChild = (child, boundingRect, msg, severity = 'error') => {
|
|
14
15
|
const index = child.getRelativeIndex(),
|
|
15
16
|
{offsetHeight, offsetWidth, parentNode, length} = child,
|
|
16
17
|
{top: offsetTop, left: offsetLeft} = parentNode.posFromIndex(index),
|
|
@@ -23,23 +24,23 @@ const generateForChild = (child, boundingRect, message, severity = 'error') => {
|
|
|
23
24
|
endLine = startLine + offsetHeight - 1,
|
|
24
25
|
startCol = offsetTop ? offsetLeft : left + offsetLeft,
|
|
25
26
|
endCol = offsetHeight > 1 ? offsetWidth : startCol + offsetWidth;
|
|
26
|
-
return {message, severity, startIndex, endIndex, startLine, endLine, startCol, endCol, excerpt};
|
|
27
|
+
return {message: Parser.msg(msg), severity, startIndex, endIndex, startLine, endLine, startCol, endCol, excerpt};
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* 生成对于自己的LintError对象
|
|
31
32
|
* @param {Token} token 节点
|
|
32
33
|
* @param {{top: number, left: number, start: number}} boundingRect 绝对定位
|
|
33
|
-
* @param {string}
|
|
34
|
+
* @param {string} msg 错误信息
|
|
34
35
|
* @param {'error'|'warning'} severity 严重程度
|
|
35
36
|
* @returns {LintError}
|
|
36
37
|
*/
|
|
37
|
-
const generateForSelf = (token, boundingRect,
|
|
38
|
+
const generateForSelf = (token, boundingRect, msg, severity = 'error') => {
|
|
38
39
|
const {start} = boundingRect,
|
|
39
40
|
{offsetHeight, offsetWidth, length} = token,
|
|
40
41
|
{top, left} = 'top' in boundingRect ? boundingRect : token.getRootNode().posFromIndex(start);
|
|
41
42
|
return {
|
|
42
|
-
message,
|
|
43
|
+
message: Parser.msg(msg),
|
|
43
44
|
severity,
|
|
44
45
|
startIndex: start,
|
|
45
46
|
endIndex: start + length,
|
package/util/string.js
CHANGED
|
@@ -72,6 +72,15 @@ const text = (childNodes, separator = '') => {
|
|
|
72
72
|
return childNodes.map(child => typeof child === 'string' ? child : child.text()).join(separator);
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* decode HTML entities
|
|
77
|
+
* @param {string} str 原字符串
|
|
78
|
+
*/
|
|
79
|
+
const decodeHtml = str => str?.replace(
|
|
80
|
+
/&#(\d+|x[\da-f]+);/giu,
|
|
81
|
+
(_, code) => String.fromCodePoint(`${code[0].toLowerCase() === 'x' ? '0' : ''}${code}`),
|
|
82
|
+
);
|
|
83
|
+
|
|
75
84
|
/**
|
|
76
85
|
* optionally convert to lower cases
|
|
77
86
|
* @param {string} val 属性值
|
|
@@ -103,5 +112,15 @@ const normalizeSpace = token => {
|
|
|
103
112
|
};
|
|
104
113
|
|
|
105
114
|
module.exports = {
|
|
106
|
-
extUrlCharFirst,
|
|
115
|
+
extUrlCharFirst,
|
|
116
|
+
extUrlChar,
|
|
117
|
+
removeComment,
|
|
118
|
+
print,
|
|
119
|
+
escapeRegExp,
|
|
120
|
+
explode,
|
|
121
|
+
text,
|
|
122
|
+
decodeHtml,
|
|
123
|
+
toCase,
|
|
124
|
+
noWrap,
|
|
125
|
+
normalizeSpace,
|
|
107
126
|
};
|