wikiparser-node 0.8.1 → 0.9.0-m
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/default.json +0 -1
- package/config/llwiki.json +0 -35
- package/config/moegirl.json +1 -44
- package/config/zhwiki.json +0 -466
- package/i18n/zh-hans.json +44 -0
- package/i18n/zh-hant.json +44 -0
- package/index.js +16 -256
- package/lib/element.js +29 -504
- package/lib/node.js +6 -542
- package/lib/text.js +10 -127
- package/lib/title.js +7 -32
- package/mixin/hidden.js +0 -3
- package/package.json +8 -8
- package/parser/brackets.js +8 -3
- package/parser/commentAndExt.js +1 -5
- package/parser/converter.js +0 -1
- package/parser/externalLinks.js +0 -1
- package/parser/hrAndDoubleUnderscore.js +0 -1
- package/parser/html.js +0 -1
- package/parser/links.js +5 -6
- package/parser/list.js +0 -1
- package/parser/magicLinks.js +0 -1
- package/parser/quotes.js +1 -2
- package/parser/table.js +0 -1
- package/src/arg.js +9 -119
- package/src/atom/hidden.js +0 -2
- package/src/atom/index.js +0 -17
- package/src/attribute.js +7 -181
- package/src/attributes.js +8 -312
- package/src/converter.js +2 -108
- package/src/converterFlags.js +3 -190
- package/src/converterRule.js +3 -187
- package/src/extLink.js +2 -121
- package/src/gallery.js +5 -62
- package/src/hasNowiki/index.js +0 -12
- package/src/hasNowiki/pre.js +0 -12
- package/src/heading.js +7 -58
- package/src/html.js +18 -127
- package/src/imageParameter.js +61 -200
- package/src/imagemap.js +7 -66
- package/src/imagemapLink.js +2 -14
- package/src/index.js +11 -534
- package/src/link/category.js +1 -37
- package/src/link/file.js +18 -168
- package/src/link/galleryImage.js +6 -64
- package/src/link/index.js +9 -277
- package/src/magicLink.js +2 -85
- package/src/nested/choose.js +0 -1
- package/src/nested/combobox.js +0 -1
- package/src/nested/index.js +3 -33
- package/src/nested/references.js +0 -1
- package/src/nowiki/comment.js +3 -27
- package/src/nowiki/dd.js +1 -47
- package/src/nowiki/doubleUnderscore.js +1 -31
- package/src/nowiki/hr.js +1 -20
- package/src/nowiki/index.js +3 -25
- package/src/nowiki/list.js +2 -5
- package/src/nowiki/noinclude.js +0 -14
- package/src/nowiki/quote.js +3 -17
- package/src/onlyinclude.js +1 -26
- package/src/paramTag/index.js +4 -27
- package/src/paramTag/inputbox.js +1 -4
- package/src/parameter.js +7 -149
- package/src/syntax.js +0 -68
- package/src/table/index.js +4 -942
- package/src/table/td.js +9 -230
- package/src/table/tr.js +4 -249
- package/src/tagPair/ext.js +13 -27
- package/src/tagPair/include.js +0 -24
- package/src/tagPair/index.js +2 -51
- package/src/transclude.js +38 -528
- package/util/lint.js +8 -7
- package/util/string.js +12 -44
- package/README.md +0 -39
- package/lib/ranges.js +0 -130
- package/mixin/attributeParent.js +0 -117
- package/mixin/fixedToken.js +0 -40
- package/mixin/singleLine.js +0 -31
- package/mixin/sol.js +0 -65
- package/parser/selector.js +0 -177
- package/src/charinsert.js +0 -97
- package/tool/index.js +0 -1202
- package/util/debug.js +0 -73
package/lib/text.js
CHANGED
|
@@ -4,7 +4,7 @@ const Parser = require('..'),
|
|
|
4
4
|
AstNode = require('./node'),
|
|
5
5
|
AstElement = require('./element');
|
|
6
6
|
|
|
7
|
-
const errorSyntax = /https
|
|
7
|
+
const errorSyntax = /https?:\/\/|\{+|\}+|\[{2,}|\[(?![^[]*\])|(?<=^|\])([^[]*?)\]+|<\s*\/?([a-z]\w*)(?=[\s/>])/giu,
|
|
8
8
|
errorSyntaxUrl = /\{+|\}+|\[{2,}|\[(?![^[]*\])|(?<=^|\])([^[]*?)\]+|<\s*\/?([a-z]\w*)(?=[\s/>])/giu,
|
|
9
9
|
disallowedTags = [
|
|
10
10
|
'html',
|
|
@@ -61,24 +61,13 @@ const errorSyntax = /https?:|\{+|\}+|\[{2,}|\[(?![^[]*\])|(?<=^|\])([^[]*?)\]+|<
|
|
|
61
61
|
|
|
62
62
|
/** 文本节点 */
|
|
63
63
|
class AstText extends AstNode {
|
|
64
|
-
#config;
|
|
65
64
|
type = 'text';
|
|
66
65
|
/** @type {string} */ data;
|
|
67
66
|
|
|
68
|
-
/** 文本长度 */
|
|
69
|
-
get length() {
|
|
70
|
-
return this.data.length;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
67
|
/** @param {string} text 包含文本 */
|
|
74
|
-
constructor(text = ''
|
|
68
|
+
constructor(text = '') {
|
|
75
69
|
super();
|
|
76
|
-
this
|
|
77
|
-
Object.defineProperties(this, {
|
|
78
|
-
data: {value: text, writable: false},
|
|
79
|
-
childNodes: {enumerable: false, configurable: false},
|
|
80
|
-
type: {enumerable: false, writable: false, configurable: false},
|
|
81
|
-
});
|
|
70
|
+
this.data = text;
|
|
82
71
|
}
|
|
83
72
|
|
|
84
73
|
/** 输出字符串 */
|
|
@@ -97,20 +86,20 @@ class AstText extends AstNode {
|
|
|
97
86
|
* @param {number} start 起始位置
|
|
98
87
|
* @returns {LintError[]}
|
|
99
88
|
*/
|
|
100
|
-
lint(start =
|
|
89
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
101
90
|
const {data, parentNode} = this,
|
|
102
91
|
type = parentNode?.type,
|
|
103
92
|
name = parentNode?.name,
|
|
104
|
-
urlAttr = ['itemtype', 'src', 'srcset'].includes(parentNode?.parentNode?.name),
|
|
105
93
|
errorRegex
|
|
106
94
|
= type === 'free-ext-link' || type === 'ext-link-url' || type === 'image-parameter' && name === 'link'
|
|
107
95
|
? errorSyntaxUrl
|
|
108
96
|
: errorSyntax,
|
|
109
|
-
errors = [...data.matchAll(errorRegex)]
|
|
97
|
+
errors = [...data.matchAll(errorRegex)],
|
|
98
|
+
{ext, html} = this.getRootNode().getAttribute('config');
|
|
110
99
|
if (errors.length > 0) {
|
|
111
100
|
const root = this.getRootNode(),
|
|
112
101
|
{top, left} = root.posFromIndex(start),
|
|
113
|
-
tags = new Set([
|
|
102
|
+
tags = new Set([ext, html, disallowedTags].flat(2));
|
|
114
103
|
return errors.map(/** @returns {LintError} */ ({0: error, 1: prefix, 2: tag, index}) => {
|
|
115
104
|
if (prefix) {
|
|
116
105
|
index += prefix.length;
|
|
@@ -124,29 +113,9 @@ class AstText extends AstNode {
|
|
|
124
113
|
{0: char, length} = error,
|
|
125
114
|
endIndex = startIndex + length,
|
|
126
115
|
end = char === '}' || char === ']' ? endIndex : startIndex + (char === 'h' ? 49 : 50);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
case 'ext-link-text':
|
|
131
|
-
severity = 'warning';
|
|
132
|
-
break;
|
|
133
|
-
case 'attr-value':
|
|
134
|
-
if (urlAttr) {
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
break;
|
|
138
|
-
case 'ext-inner':
|
|
139
|
-
if (name === 'sm2' || name === 'flashmp3') {
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
// no default
|
|
143
|
-
}
|
|
144
|
-
} else if (char === '<' && !tags.has(tag.toLowerCase())) {
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
return {
|
|
148
|
-
message: `孤立的"${char === 'h' ? error : char}"`,
|
|
149
|
-
severity,
|
|
116
|
+
return (char !== 'h' || index > 0) && (char !== '<' || tags.has(tag.toLowerCase())) && {
|
|
117
|
+
message: Parser.msg('lonely "$1"', char === 'h' ? error : char),
|
|
118
|
+
severity: length > 1 ? 'error' : 'warning',
|
|
150
119
|
startIndex,
|
|
151
120
|
endIndex,
|
|
152
121
|
startLine,
|
|
@@ -166,12 +135,7 @@ class AstText extends AstNode {
|
|
|
166
135
|
*/
|
|
167
136
|
#setData(text) {
|
|
168
137
|
text = String(text);
|
|
169
|
-
const {data} = this,
|
|
170
|
-
e = new Event('text', {bubbles: true});
|
|
171
138
|
this.setAttribute('data', text);
|
|
172
|
-
if (data !== text) {
|
|
173
|
-
this.dispatchEvent(e, {oldText: data, newText: text});
|
|
174
|
-
}
|
|
175
139
|
}
|
|
176
140
|
|
|
177
141
|
/**
|
|
@@ -181,87 +145,6 @@ class AstText extends AstNode {
|
|
|
181
145
|
replaceData(text = '') {
|
|
182
146
|
this.#setData(text);
|
|
183
147
|
}
|
|
184
|
-
|
|
185
|
-
/** 复制 */
|
|
186
|
-
cloneNode() {
|
|
187
|
-
return new AstText(this.data, this.#config);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* @override
|
|
192
|
-
* @template {string} T
|
|
193
|
-
* @param {T} key 属性键
|
|
194
|
-
* @returns {TokenAttribute<T>}
|
|
195
|
-
* @throws `Error` 文本节点没有子节点
|
|
196
|
-
*/
|
|
197
|
-
getAttribute(key) {
|
|
198
|
-
return key === 'verifyChild'
|
|
199
|
-
? () => {
|
|
200
|
-
throw new Error('文本节点没有子节点!');
|
|
201
|
-
}
|
|
202
|
-
: super.getAttribute(key);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* 在后方添加字符串
|
|
207
|
-
* @param {string} text 添加的字符串
|
|
208
|
-
*/
|
|
209
|
-
appendData(text) {
|
|
210
|
-
this.#setData(this.data + text);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* 删减字符串
|
|
215
|
-
* @param {number} offset 起始位置
|
|
216
|
-
* @param {number} count 删减字符数
|
|
217
|
-
*/
|
|
218
|
-
deleteData(offset, count) {
|
|
219
|
-
this.#setData(this.data.slice(0, offset) + this.data.slice(offset + count));
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* 插入字符串
|
|
224
|
-
* @param {number} offset 插入位置
|
|
225
|
-
* @param {string} text 待插入的字符串
|
|
226
|
-
*/
|
|
227
|
-
insertData(offset, text) {
|
|
228
|
-
this.#setData(this.data.slice(0, offset) + text + this.data.slice(offset));
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* 提取子串
|
|
233
|
-
* @param {number} offset 起始位置
|
|
234
|
-
* @param {number} count 字符数
|
|
235
|
-
*/
|
|
236
|
-
substringData(offset, count) {
|
|
237
|
-
return this.data.slice(offset, offset + count);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* 将文本子节点分裂为两部分
|
|
242
|
-
* @param {number} offset 分裂位置
|
|
243
|
-
* @throws `RangeError` 错误的断开位置
|
|
244
|
-
* @throws `Error` 没有父节点
|
|
245
|
-
*/
|
|
246
|
-
splitText(offset) {
|
|
247
|
-
if (!Number.isInteger(offset)) {
|
|
248
|
-
this.typeError('splitText', 'Number');
|
|
249
|
-
} else if (offset > this.length || offset < -this.length) {
|
|
250
|
-
throw new RangeError(`错误的断开位置!${offset}`);
|
|
251
|
-
}
|
|
252
|
-
const {parentNode, data} = this;
|
|
253
|
-
if (!parentNode) {
|
|
254
|
-
throw new Error('待分裂的文本节点没有父节点!');
|
|
255
|
-
}
|
|
256
|
-
const newText = new AstText(data.slice(offset), this.#config),
|
|
257
|
-
childNodes = [...parentNode.childNodes];
|
|
258
|
-
this.setAttribute('data', data.slice(0, offset));
|
|
259
|
-
childNodes.splice(childNodes.indexOf(this) + 1, 0, newText);
|
|
260
|
-
newText.setAttribute('parentNode', parentNode);
|
|
261
|
-
parentNode.setAttribute('childNodes', childNodes);
|
|
262
|
-
return newText;
|
|
263
|
-
}
|
|
264
148
|
}
|
|
265
149
|
|
|
266
|
-
Parser.classes.AstText = __filename;
|
|
267
150
|
module.exports = AstText;
|
package/lib/title.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const {decodeHtml} = require('../util/string'),
|
|
4
|
+
Parser = require('..');
|
|
4
5
|
|
|
5
6
|
/** MediaWiki页面标题对象 */
|
|
6
7
|
class Title {
|
|
7
8
|
valid = true;
|
|
8
9
|
ns = 0;
|
|
9
|
-
fragment
|
|
10
|
+
fragment;
|
|
10
11
|
encoded = false;
|
|
11
|
-
title = '';
|
|
12
|
-
main = '';
|
|
13
|
-
prefix = '';
|
|
14
|
-
interwiki = '';
|
|
15
12
|
|
|
16
13
|
/**
|
|
17
14
|
* @param {string} title 标题(含或不含命名空间前缀)
|
|
@@ -22,9 +19,10 @@ class Title {
|
|
|
22
19
|
constructor(title, defaultNs = 0, config = Parser.getConfig(), decode = false, selfLink = false) {
|
|
23
20
|
const {namespaces, nsid} = config;
|
|
24
21
|
let namespace = namespaces[defaultNs];
|
|
22
|
+
title = decodeHtml(title);
|
|
25
23
|
if (decode && title.includes('%')) {
|
|
26
24
|
try {
|
|
27
|
-
const encoded = /%(?!5[bd]|7[b-d])[\da-f]{2}/iu.test(title);
|
|
25
|
+
const encoded = /%(?!21|3[ce]|5[bd]|7[b-d])[\da-f]{2}/iu.test(title);
|
|
28
26
|
title = decodeURIComponent(title);
|
|
29
27
|
this.encoded = encoded;
|
|
30
28
|
} catch {}
|
|
@@ -34,11 +32,6 @@ class Title {
|
|
|
34
32
|
namespace = '';
|
|
35
33
|
title = title.slice(1).trim();
|
|
36
34
|
}
|
|
37
|
-
const iw = defaultNs ? undefined : Parser.isInterwiki(title, config);
|
|
38
|
-
if (iw) {
|
|
39
|
-
this.interwiki = iw[1].toLowerCase();
|
|
40
|
-
title = title.slice(iw[0].length);
|
|
41
|
-
}
|
|
42
35
|
const m = title.split(':');
|
|
43
36
|
if (m.length > 1) {
|
|
44
37
|
const id = namespaces[nsid[m[0].trim().toLowerCase()]];
|
|
@@ -49,33 +42,15 @@ class Title {
|
|
|
49
42
|
}
|
|
50
43
|
this.ns = nsid[namespace.toLowerCase()];
|
|
51
44
|
const i = title.indexOf('#');
|
|
52
|
-
let fragment
|
|
45
|
+
let fragment;
|
|
53
46
|
if (i !== -1) {
|
|
54
47
|
fragment = title.slice(i + 1).trimEnd();
|
|
55
|
-
if (fragment.includes('%')) {
|
|
56
|
-
try {
|
|
57
|
-
fragment = decodeURIComponent(fragment);
|
|
58
|
-
} catch {}
|
|
59
|
-
} else if (fragment.includes('.')) {
|
|
60
|
-
try {
|
|
61
|
-
fragment = decodeURIComponent(fragment.replaceAll('.', '%'));
|
|
62
|
-
} catch {}
|
|
63
|
-
}
|
|
64
48
|
title = title.slice(0, i).trim();
|
|
65
49
|
}
|
|
66
|
-
this.valid = Boolean(title || selfLink && fragment
|
|
50
|
+
this.valid = Boolean(title || selfLink && fragment !== undefined)
|
|
67
51
|
&& !/\0\d+[eh!+-]\x7F|[<>[\]{}|]|%[\da-f]{2}/iu.test(title);
|
|
68
52
|
this.fragment = fragment;
|
|
69
|
-
this.main = title && `${title[0].toUpperCase()}${title.slice(1)}`;
|
|
70
|
-
this.prefix = `${namespace}${namespace && ':'}`;
|
|
71
|
-
this.title = `${iw ? `${this.interwiki}:` : ''}${this.prefix}${this.main.replaceAll(' ', '_')}`;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** @override */
|
|
75
|
-
toString() {
|
|
76
|
-
return `${this.title}${this.fragment && '#'}${this.fragment}`;
|
|
77
53
|
}
|
|
78
54
|
}
|
|
79
55
|
|
|
80
|
-
Parser.classes.Title = __filename;
|
|
81
56
|
module.exports = Title;
|
package/mixin/hidden.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wikiparser-node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0-m",
|
|
4
4
|
"description": "A Node.js parser for MediaWiki markup with AST",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mediawiki",
|
|
@@ -15,22 +15,22 @@
|
|
|
15
15
|
"author": "Bhsd",
|
|
16
16
|
"files": [
|
|
17
17
|
"/index.js",
|
|
18
|
-
"/parser/",
|
|
19
|
-
"/util/",
|
|
20
|
-
"/lib/",
|
|
21
|
-
"/src/",
|
|
22
18
|
"/config/",
|
|
19
|
+
"/i18n/",
|
|
20
|
+
"/lib/",
|
|
23
21
|
"/mixin/",
|
|
24
|
-
"/
|
|
22
|
+
"/parser/",
|
|
23
|
+
"/src/",
|
|
24
|
+
"/util/"
|
|
25
25
|
],
|
|
26
26
|
"repository": {
|
|
27
27
|
"type": "git",
|
|
28
28
|
"url": "git+https://github.com/bhsd-harry/wikiparser-node.git"
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
|
-
"test": "eslint .
|
|
31
|
+
"test": "eslint .",
|
|
32
32
|
"real": "node test/real.js",
|
|
33
|
-
"single": "node
|
|
33
|
+
"single": "node test/single.js"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^17.0.23",
|
package/parser/brackets.js
CHANGED
|
@@ -14,6 +14,7 @@ const {removeComment} = require('../util/string'),
|
|
|
14
14
|
*/
|
|
15
15
|
const parseBrackets = (text, config = Parser.getConfig(), accum = []) => {
|
|
16
16
|
const source = `${config.excludes.includes('heading') ? '' : '^(\0\\d+c\x7F)*={1,6}|'}\\[\\[|\\{{2,}|-\\{(?!\\{)`,
|
|
17
|
+
{parserFunction: [,,, subst]} = config,
|
|
17
18
|
/** @type {BracketExecArray[]} */ stack = [],
|
|
18
19
|
closes = {'=': '\n', '{': '\\}{2,}|\\|', '-': '\\}-', '[': '\\]\\]'},
|
|
19
20
|
/** @type {Record<string, string>} */ marks = {'!': '!', '!!': '+', '(!': '{', '!)': '}', '!-': '-', '=': '~'};
|
|
@@ -62,12 +63,17 @@ const parseBrackets = (text, config = Parser.getConfig(), accum = []) => {
|
|
|
62
63
|
let skip = false,
|
|
63
64
|
ch = 't';
|
|
64
65
|
if (close.length === 3) {
|
|
65
|
-
|
|
66
|
+
const argParts = parts.map(part => part.join('=')),
|
|
67
|
+
str = argParts.length > 1 && removeComment(argParts[1]).trim();
|
|
68
|
+
new ArgToken(argParts, config, accum);
|
|
69
|
+
if (str && str.endsWith(':') && subst.includes(str.slice(0, -1).toLowerCase())) {
|
|
70
|
+
ch = 's';
|
|
71
|
+
}
|
|
66
72
|
} else {
|
|
67
73
|
const name = removeComment(parts[0][0]).trim();
|
|
68
74
|
if (name in marks) {
|
|
69
75
|
ch = marks[name]; // 标记{{!}}等
|
|
70
|
-
} else if (/^(?:
|
|
76
|
+
} else if (/^(?:filepath|(?:full|canonical)urle?):.|^server$/iu.test(name)) {
|
|
71
77
|
ch = 'm';
|
|
72
78
|
} else if (/^#vardefine:./iu.test(name)) {
|
|
73
79
|
ch = 'c';
|
|
@@ -116,5 +122,4 @@ const parseBrackets = (text, config = Parser.getConfig(), accum = []) => {
|
|
|
116
122
|
return text;
|
|
117
123
|
};
|
|
118
124
|
|
|
119
|
-
Parser.parsers.parseBrackets = __filename;
|
|
120
125
|
module.exports = parseBrackets;
|
package/parser/commentAndExt.js
CHANGED
|
@@ -20,10 +20,7 @@ const parseCommentAndExt = (text, config = Parser.getConfig(), accum = [], inclu
|
|
|
20
20
|
const str = `\0${accum.length}e\x7F`;
|
|
21
21
|
new OnlyincludeToken(inner, config, accum);
|
|
22
22
|
return str;
|
|
23
|
-
}).replace(/(?<=^|\0\d+e\x7F)
|
|
24
|
-
if (substr === '') {
|
|
25
|
-
return '';
|
|
26
|
-
}
|
|
23
|
+
}).replace(/(?<=^|\0\d+e\x7F)[^\0]+(?=$|\0\d+e\x7F)/gu, substr => {
|
|
27
24
|
new NoincludeToken(substr, config, accum);
|
|
28
25
|
return `\0${accum.length - 1}c\x7F`;
|
|
29
26
|
});
|
|
@@ -58,5 +55,4 @@ const parseCommentAndExt = (text, config = Parser.getConfig(), accum = [], inclu
|
|
|
58
55
|
);
|
|
59
56
|
};
|
|
60
57
|
|
|
61
|
-
Parser.parsers.parseCommentAndExt = __filename;
|
|
62
58
|
module.exports = parseCommentAndExt;
|
package/parser/converter.js
CHANGED
package/parser/externalLinks.js
CHANGED
|
@@ -34,5 +34,4 @@ const parseHrAndDoubleUnderscore = ({firstChild: {data}, type, name}, config = P
|
|
|
34
34
|
return type === 'root' || type === 'ext-inner' && name === 'poem' ? data : data.slice(1);
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
Parser.parsers.parseHrAndDoubleUnderscore = __filename;
|
|
38
37
|
module.exports = parseHrAndDoubleUnderscore;
|
package/parser/html.js
CHANGED
package/parser/links.js
CHANGED
|
@@ -44,12 +44,12 @@ const parseLinks = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
|
44
44
|
continue;
|
|
45
45
|
}
|
|
46
46
|
const title = Parser.normalizeTitle(link, 0, false, config, true, true, true),
|
|
47
|
-
{ns,
|
|
47
|
+
{ns, valid} = title;
|
|
48
48
|
if (!valid) {
|
|
49
49
|
s += `[[${x}`;
|
|
50
50
|
continue;
|
|
51
51
|
} else if (mightBeImg) {
|
|
52
|
-
if (
|
|
52
|
+
if (ns !== 6) {
|
|
53
53
|
s += `[[${x}`;
|
|
54
54
|
continue;
|
|
55
55
|
}
|
|
@@ -79,16 +79,15 @@ const parseLinks = (wikitext, config = Parser.getConfig(), accum = []) => {
|
|
|
79
79
|
s += `\0${accum.length}l\x7F${after}`;
|
|
80
80
|
let SomeLinkToken = LinkToken;
|
|
81
81
|
if (!force) {
|
|
82
|
-
if (
|
|
82
|
+
if (ns === 6) {
|
|
83
83
|
SomeLinkToken = FileToken;
|
|
84
|
-
} else if (
|
|
84
|
+
} else if (ns === 14) {
|
|
85
85
|
SomeLinkToken = CategoryToken;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
new SomeLinkToken(link, text,
|
|
88
|
+
new SomeLinkToken(link, text, config, accum, delimiter);
|
|
89
89
|
}
|
|
90
90
|
return s;
|
|
91
91
|
};
|
|
92
92
|
|
|
93
|
-
Parser.parsers.parseLinks = __filename;
|
|
94
93
|
module.exports = parseLinks;
|
package/parser/list.js
CHANGED
package/parser/magicLinks.js
CHANGED
package/parser/quotes.js
CHANGED
|
@@ -31,7 +31,7 @@ const parseQuotes = (text, config = Parser.getConfig(), accum = []) => {
|
|
|
31
31
|
nBold++;
|
|
32
32
|
if (firstSingle) {
|
|
33
33
|
break;
|
|
34
|
-
} else if (arr[i - 1].
|
|
34
|
+
} else if (arr[i - 1].endsWith(' ')) {
|
|
35
35
|
if (!firstMulti && !firstSpace) {
|
|
36
36
|
firstSpace = i;
|
|
37
37
|
}
|
|
@@ -60,5 +60,4 @@ const parseQuotes = (text, config = Parser.getConfig(), accum = []) => {
|
|
|
60
60
|
return arr.join('');
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
Parser.parsers.parseQuotes = __filename;
|
|
64
63
|
module.exports = parseQuotes;
|
package/parser/table.js
CHANGED
package/src/arg.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {text
|
|
3
|
+
const {text} = require('../util/string'),
|
|
4
4
|
{generateForSelf, generateForChild} = require('../util/lint'),
|
|
5
5
|
Parser = require('..'),
|
|
6
6
|
Token = require('.');
|
|
@@ -24,13 +24,11 @@ class ArgToken extends Token {
|
|
|
24
24
|
*/
|
|
25
25
|
constructor(parts, config = Parser.getConfig(), accum = []) {
|
|
26
26
|
super(undefined, config, true, accum, {
|
|
27
|
-
AtomToken: 0, Token: 1, HiddenToken: '2:',
|
|
28
27
|
});
|
|
29
28
|
for (let i = 0; i < parts.length; i++) {
|
|
30
29
|
if (i === 0 || i > 1) {
|
|
31
30
|
const AtomToken = i === 0 ? require('./atom') : require('./atom/hidden');
|
|
32
31
|
const token = new AtomToken(parts[i], i === 0 ? 'arg-name' : undefined, config, accum, {
|
|
33
|
-
'Stage-2': ':', '!HeadingToken': '',
|
|
34
32
|
});
|
|
35
33
|
super.insertAt(token);
|
|
36
34
|
} else {
|
|
@@ -39,15 +37,13 @@ class ArgToken extends Token {
|
|
|
39
37
|
super.insertAt(token.setAttribute('stage', 2));
|
|
40
38
|
}
|
|
41
39
|
}
|
|
42
|
-
this.getAttribute('protectChildren')(0);
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
/**
|
|
46
43
|
* @override
|
|
47
|
-
* @param {string} selector
|
|
48
44
|
*/
|
|
49
45
|
toString(selector) {
|
|
50
|
-
return
|
|
46
|
+
return `{{{${super.toString(selector, '|')}}}}`;
|
|
51
47
|
}
|
|
52
48
|
|
|
53
49
|
/**
|
|
@@ -68,19 +64,14 @@ class ArgToken extends Token {
|
|
|
68
64
|
return 1;
|
|
69
65
|
}
|
|
70
66
|
|
|
71
|
-
/** @override */
|
|
72
|
-
print() {
|
|
73
|
-
return super.print({pre: '{{{', post: '}}}', sep: '|'});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
67
|
/**
|
|
77
68
|
* @override
|
|
78
69
|
* @param {number} start 起始位置
|
|
79
70
|
* @returns {LintError[]}
|
|
80
71
|
*/
|
|
81
|
-
lint(start =
|
|
72
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
82
73
|
if (!this.getAttribute('include')) {
|
|
83
|
-
return [generateForSelf(this, {start}, '
|
|
74
|
+
return [generateForSelf(this, {start}, 'unexpected template argument')];
|
|
84
75
|
}
|
|
85
76
|
const {childNodes: [argName, argDefault, ...rest]} = this,
|
|
86
77
|
errors = argName.lint(start + 3);
|
|
@@ -89,115 +80,14 @@ class ArgToken extends Token {
|
|
|
89
80
|
}
|
|
90
81
|
if (rest.length > 0) {
|
|
91
82
|
const rect = {start, ...this.getRootNode().posFromIndex(start)};
|
|
92
|
-
errors.push(...rest.map(child =>
|
|
83
|
+
errors.push(...rest.map(child => {
|
|
84
|
+
const error = generateForChild(child, rect, 'invisible content inside triple brackets'),
|
|
85
|
+
{startIndex, startCol, excerpt} = error;
|
|
86
|
+
return {...error, startIndex: startIndex - 1, startCol: startCol - 1, excerpt: `|${excerpt}`};
|
|
87
|
+
}));
|
|
93
88
|
}
|
|
94
89
|
return errors;
|
|
95
90
|
}
|
|
96
|
-
|
|
97
|
-
/** @override */
|
|
98
|
-
cloneNode() {
|
|
99
|
-
const [name, ...cloned] = this.cloneChildNodes();
|
|
100
|
-
return Parser.run(() => {
|
|
101
|
-
const token = new ArgToken([''], this.getAttribute('config'));
|
|
102
|
-
token.firstChild.safeReplaceWith(name);
|
|
103
|
-
token.append(...cloned);
|
|
104
|
-
token.afterBuild();
|
|
105
|
-
return token;
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/** @override */
|
|
110
|
-
afterBuild() {
|
|
111
|
-
this.setAttribute('name', this.firstChild.text().trim());
|
|
112
|
-
const /** @type {AstListener} */ argListener = ({prevTarget}) => {
|
|
113
|
-
if (prevTarget === this.firstChild) {
|
|
114
|
-
this.setAttribute('name', prevTarget.text().trim());
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
this.addEventListener(['remove', 'insert', 'replace', 'text'], argListener);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* 移除无效部分
|
|
122
|
-
* @complexity `n`
|
|
123
|
-
*/
|
|
124
|
-
removeRedundant() {
|
|
125
|
-
Parser.run(() => {
|
|
126
|
-
for (let i = this.length - 1; i > 1; i--) {
|
|
127
|
-
super.removeAt(i);
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* 移除子节点,且在移除`arg-default`子节点时自动移除全部多余子节点
|
|
134
|
-
* @param {number} i 移除位置
|
|
135
|
-
* @returns {Token}
|
|
136
|
-
*/
|
|
137
|
-
removeAt(i) {
|
|
138
|
-
if (i === 1) {
|
|
139
|
-
this.removeRedundant();
|
|
140
|
-
}
|
|
141
|
-
return super.removeAt(i);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* @override
|
|
146
|
-
* @param {Token} token 待插入的子节点
|
|
147
|
-
* @param {number} i 插入位置
|
|
148
|
-
* @throws `RangeError` 不可插入多余子节点
|
|
149
|
-
*/
|
|
150
|
-
insertAt(token, i = this.length) {
|
|
151
|
-
const j = i < 0 ? i + this.length : i;
|
|
152
|
-
if (j > 1) {
|
|
153
|
-
throw new RangeError(`${this.constructor.name} 不可插入多余的子节点!`);
|
|
154
|
-
}
|
|
155
|
-
super.insertAt(token, i);
|
|
156
|
-
if (j === 1) {
|
|
157
|
-
token.type = 'arg-default';
|
|
158
|
-
}
|
|
159
|
-
return token;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* 设置参数名
|
|
164
|
-
* @param {string} name 新参数名
|
|
165
|
-
* @throws `SyntaxError` 非法的参数名
|
|
166
|
-
*/
|
|
167
|
-
setName(name) {
|
|
168
|
-
name = String(name);
|
|
169
|
-
const root = Parser.parse(`{{{${name}}}}`, this.getAttribute('include'), 2, this.getAttribute('config')),
|
|
170
|
-
{length, firstChild: arg} = root;
|
|
171
|
-
if (length !== 1 || arg.type !== 'arg' || arg.length !== 1) {
|
|
172
|
-
throw new SyntaxError(`非法的参数名称:${noWrap(name)}`);
|
|
173
|
-
}
|
|
174
|
-
const {firstChild} = arg;
|
|
175
|
-
arg.destroy(true);
|
|
176
|
-
this.firstChild.safeReplaceWith(firstChild);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* 设置预设值
|
|
181
|
-
* @param {string} value 预设值
|
|
182
|
-
* @throws `SyntaxError` 非法的参数预设值
|
|
183
|
-
*/
|
|
184
|
-
setDefault(value) {
|
|
185
|
-
value = String(value);
|
|
186
|
-
const root = Parser.parse(`{{{|${value}}}}`, this.getAttribute('include'), 2, this.getAttribute('config')),
|
|
187
|
-
{length, firstChild: arg} = root;
|
|
188
|
-
if (length !== 1 || arg.type !== 'arg' || arg.length !== 2) {
|
|
189
|
-
throw new SyntaxError(`非法的参数预设值:${noWrap(value)}`);
|
|
190
|
-
}
|
|
191
|
-
const {childNodes: [, oldDefault]} = this,
|
|
192
|
-
{lastChild} = arg;
|
|
193
|
-
arg.destroy(true);
|
|
194
|
-
if (oldDefault) {
|
|
195
|
-
oldDefault.safeReplaceWith(lastChild);
|
|
196
|
-
} else {
|
|
197
|
-
this.insertAt(lastChild);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
91
|
}
|
|
201
92
|
|
|
202
|
-
Parser.classes.ArgToken = __filename;
|
|
203
93
|
module.exports = ArgToken;
|
package/src/atom/hidden.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const hidden = require('../../mixin/hidden'),
|
|
4
|
-
Parser = require('../..'),
|
|
5
4
|
AtomToken = require('.');
|
|
6
5
|
|
|
7
6
|
/** 不可见的节点 */
|
|
@@ -9,5 +8,4 @@ class HiddenToken extends hidden(AtomToken) {
|
|
|
9
8
|
type = 'hidden';
|
|
10
9
|
}
|
|
11
10
|
|
|
12
|
-
Parser.classes.HiddenToken = __filename;
|
|
13
11
|
module.exports = HiddenToken;
|