wikiparser-node 0.3.0 → 0.4.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/.eslintrc.json +472 -34
- package/README.md +1 -1
- package/config/default.json +58 -30
- package/config/llwiki.json +22 -90
- package/config/moegirl.json +51 -13
- package/config/zhwiki.json +1269 -0
- package/index.js +114 -104
- package/lib/element.js +448 -440
- package/lib/node.js +335 -115
- package/lib/ranges.js +27 -18
- package/lib/text.js +146 -0
- package/lib/title.js +13 -5
- package/mixin/attributeParent.js +70 -24
- package/mixin/fixedToken.js +14 -6
- package/mixin/hidden.js +6 -4
- package/mixin/sol.js +27 -10
- package/package.json +9 -3
- package/parser/brackets.js +22 -17
- package/parser/commentAndExt.js +18 -16
- package/parser/converter.js +14 -13
- package/parser/externalLinks.js +12 -11
- package/parser/hrAndDoubleUnderscore.js +23 -14
- package/parser/html.js +10 -9
- package/parser/links.js +15 -14
- package/parser/list.js +12 -11
- package/parser/magicLinks.js +12 -11
- package/parser/quotes.js +6 -5
- package/parser/selector.js +175 -0
- package/parser/table.js +25 -18
- package/printed/example.json +120 -0
- package/src/arg.js +56 -32
- package/src/atom/hidden.js +5 -2
- package/src/atom/index.js +17 -9
- package/src/attribute.js +182 -100
- package/src/converter.js +68 -41
- package/src/converterFlags.js +67 -45
- package/src/converterRule.js +117 -65
- package/src/extLink.js +66 -18
- package/src/gallery.js +42 -15
- package/src/heading.js +34 -15
- package/src/html.js +97 -35
- package/src/imageParameter.js +83 -54
- package/src/index.js +299 -178
- package/src/link/category.js +20 -52
- package/src/link/file.js +59 -28
- package/src/link/galleryImage.js +21 -7
- package/src/link/index.js +146 -60
- package/src/magicLink.js +34 -12
- package/src/nowiki/comment.js +22 -10
- package/src/nowiki/dd.js +37 -22
- package/src/nowiki/doubleUnderscore.js +16 -7
- package/src/nowiki/hr.js +11 -7
- package/src/nowiki/index.js +16 -9
- package/src/nowiki/list.js +2 -2
- package/src/nowiki/noinclude.js +8 -4
- package/src/nowiki/quote.js +11 -7
- package/src/onlyinclude.js +19 -7
- package/src/parameter.js +65 -38
- package/src/syntax.js +26 -20
- package/src/table/index.js +260 -165
- package/src/table/td.js +98 -52
- package/src/table/tr.js +102 -58
- package/src/tagPair/ext.js +27 -19
- package/src/tagPair/include.js +16 -11
- package/src/tagPair/index.js +64 -29
- package/src/transclude.js +170 -93
- package/test/api.js +83 -0
- package/test/real.js +133 -0
- package/test/test.js +28 -0
- package/test/util.js +80 -0
- package/tool/index.js +41 -31
- package/typings/api.d.ts +13 -0
- package/typings/array.d.ts +28 -0
- package/typings/event.d.ts +24 -0
- package/typings/index.d.ts +46 -4
- package/typings/node.d.ts +15 -9
- package/typings/parser.d.ts +7 -0
- package/typings/tool.d.ts +3 -2
- package/util/debug.js +21 -18
- package/util/string.js +40 -27
- package/typings/element.d.ts +0 -28
package/src/link/category.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const Title = require('../../lib/title'),
|
|
4
|
+
Parser = require('../..'),
|
|
4
5
|
LinkToken = require('.'),
|
|
5
6
|
Token = require('..');
|
|
6
7
|
|
|
@@ -10,72 +11,39 @@ const /** @type {Parser} */ Parser = require('../..'),
|
|
|
10
11
|
*/
|
|
11
12
|
class CategoryToken extends LinkToken {
|
|
12
13
|
type = 'category';
|
|
13
|
-
sortkey = '';
|
|
14
14
|
|
|
15
15
|
setLangLink = undefined;
|
|
16
16
|
setFragment = undefined;
|
|
17
17
|
asSelfLink = undefined;
|
|
18
18
|
pipeTrick = undefined;
|
|
19
19
|
|
|
20
|
+
/** 分类排序关键字 */
|
|
21
|
+
get sortkey() {
|
|
22
|
+
return this.children[1]?.text()
|
|
23
|
+
?.replaceAll(/&#(\d+);/gu, /** @param {string} p */ (_, p) => String.fromCodePoint(Number(p)))
|
|
24
|
+
?.replaceAll(/&#x([\da-f]+);/giu, /** @param {string} p */ (_, p) => String.fromCodePoint(parseInt(p, 16)))
|
|
25
|
+
?.replaceAll('\n', '') ?? '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
set sortkey(text) {
|
|
29
|
+
this.setSortkey(text);
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
/**
|
|
21
|
-
* @param {string} link
|
|
22
|
-
* @param {string|undefined} text
|
|
23
|
-
* @param {Title} title
|
|
33
|
+
* @param {string} link 分类名
|
|
34
|
+
* @param {string|undefined} text 排序关键字
|
|
35
|
+
* @param {Title} title 分类页面标题对象
|
|
24
36
|
* @param {accum} accum
|
|
25
37
|
*/
|
|
26
38
|
constructor(link, text, title, config = Parser.getConfig(), accum = []) {
|
|
27
39
|
super(link, text, title, config, accum);
|
|
28
|
-
this.seal(['
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
afterBuild() {
|
|
32
|
-
super.afterBuild();
|
|
33
|
-
this.#updateSortkey();
|
|
34
|
-
const that = this;
|
|
35
|
-
const /** @type {AstListener} */ categoryListener = ({prevTarget}) => {
|
|
36
|
-
if (prevTarget?.type === 'link-text') {
|
|
37
|
-
that.#updateSortkey();
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
this.addEventListener(['remove', 'insert', 'replace', 'text'], categoryListener);
|
|
41
|
-
return this;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
#updateSortkey() {
|
|
45
|
-
this.setAttribute('sortkey', this.children[1]?.text()
|
|
46
|
-
?.replace(/&#(\d+);/g, /** @param {string} p1 */ (_, p1) => String.fromCharCode(Number(p1)))
|
|
47
|
-
?.replace(/&#x([\da-f]+);/gi, /** @param {string} p1 */ (_, p1) => String.fromCharCode(parseInt(p1, 16)))
|
|
48
|
-
?.replaceAll('\n', '') ?? '',
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** @param {number} i */
|
|
53
|
-
removeAt(i) {
|
|
54
|
-
if (i === 1) {
|
|
55
|
-
this.setAttribute('sortkey', '');
|
|
56
|
-
}
|
|
57
|
-
return super.removeAt(i);
|
|
40
|
+
this.seal(['setFragment', 'asSelfLink', 'pipeTrick'], true);
|
|
58
41
|
}
|
|
59
42
|
|
|
60
43
|
/**
|
|
61
|
-
*
|
|
62
|
-
* @param {
|
|
63
|
-
* @param {number} i
|
|
44
|
+
* 设置排序关键字
|
|
45
|
+
* @param {string} text 排序关键字
|
|
64
46
|
*/
|
|
65
|
-
insertAt(token, i) {
|
|
66
|
-
super.insertAt(token, i);
|
|
67
|
-
if (i === 1 && !Parser.running) {
|
|
68
|
-
this.#updateSortkey();
|
|
69
|
-
}
|
|
70
|
-
return token;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** @returns {string} */
|
|
74
|
-
text() {
|
|
75
|
-
return `[[${this.firstElementChild.text()}]]`;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** @param {string} text */
|
|
79
47
|
setSortkey(text) {
|
|
80
48
|
this.setLinkText(text);
|
|
81
49
|
}
|
package/src/link/file.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const Title = require('../../lib/title'),
|
|
4
|
+
{explode, noWrap} = require('../../util/string'),
|
|
4
5
|
{externalUse} = require('../../util/debug'),
|
|
5
|
-
|
|
6
|
+
Parser = require('../..'),
|
|
6
7
|
LinkToken = require('.'),
|
|
7
8
|
ImageParameterToken = require('../imageParameter');
|
|
8
9
|
|
|
@@ -21,18 +22,25 @@ class FileToken extends LinkToken {
|
|
|
21
22
|
setLinkText = undefined;
|
|
22
23
|
pipeTrick = undefined;
|
|
23
24
|
|
|
25
|
+
/** 图片链接 */
|
|
24
26
|
get link() {
|
|
25
27
|
return this.getArg('link')?.link;
|
|
26
28
|
}
|
|
29
|
+
|
|
27
30
|
set link(value) {
|
|
28
31
|
this.setValue('link', value);
|
|
29
32
|
}
|
|
33
|
+
|
|
34
|
+
/** 图片大小 */
|
|
30
35
|
get size() {
|
|
31
36
|
return this.getArg('width')?.size;
|
|
32
37
|
}
|
|
38
|
+
|
|
39
|
+
/** 图片宽度 */
|
|
33
40
|
get width() {
|
|
34
41
|
return this.size?.width;
|
|
35
42
|
}
|
|
43
|
+
|
|
36
44
|
set width(width) {
|
|
37
45
|
const arg = this.getArg('width');
|
|
38
46
|
if (arg) {
|
|
@@ -41,9 +49,12 @@ class FileToken extends LinkToken {
|
|
|
41
49
|
this.setValue('width', width);
|
|
42
50
|
}
|
|
43
51
|
}
|
|
52
|
+
|
|
53
|
+
/** 图片高度 */
|
|
44
54
|
get height() {
|
|
45
55
|
return this.size?.height;
|
|
46
56
|
}
|
|
57
|
+
|
|
47
58
|
set height(height) {
|
|
48
59
|
const arg = this.getArg('width');
|
|
49
60
|
if (arg) {
|
|
@@ -54,9 +65,9 @@ class FileToken extends LinkToken {
|
|
|
54
65
|
}
|
|
55
66
|
|
|
56
67
|
/**
|
|
57
|
-
* @param {string} link
|
|
58
|
-
* @param {string|undefined} text
|
|
59
|
-
* @param {Title} title
|
|
68
|
+
* @param {string} link 文件名
|
|
69
|
+
* @param {string|undefined} text 图片参数
|
|
70
|
+
* @param {Title} title 文件标题对象
|
|
60
71
|
* @param {accum} accum
|
|
61
72
|
* @complexity `n`
|
|
62
73
|
*/
|
|
@@ -64,11 +75,12 @@ class FileToken extends LinkToken {
|
|
|
64
75
|
super(link, undefined, title, config, accum);
|
|
65
76
|
this.setAttribute('acceptable', {AtomToken: 0, ImageParameterToken: '1:'});
|
|
66
77
|
this.append(...explode('-{', '}-', '|', text).map(part => new ImageParameterToken(part, config, accum)));
|
|
67
|
-
this.seal(['setLangLink', 'setFragment', 'asSelfLink', 'setLinkText', 'pipeTrick']);
|
|
78
|
+
this.seal(['setLangLink', 'setFragment', 'asSelfLink', 'setLinkText', 'pipeTrick'], true);
|
|
68
79
|
}
|
|
69
80
|
|
|
70
81
|
/**
|
|
71
|
-
* @
|
|
82
|
+
* @override
|
|
83
|
+
* @param {number} i 移除位置
|
|
72
84
|
* @complexity `n`
|
|
73
85
|
*/
|
|
74
86
|
removeAt(i) {
|
|
@@ -82,7 +94,9 @@ class FileToken extends LinkToken {
|
|
|
82
94
|
}
|
|
83
95
|
|
|
84
96
|
/**
|
|
85
|
-
* @
|
|
97
|
+
* @override
|
|
98
|
+
* @param {ImageParameterToken} token 待插入的子节点
|
|
99
|
+
* @param {number} i 插入位置
|
|
86
100
|
* @complexity `n`
|
|
87
101
|
*/
|
|
88
102
|
insertAt(token, i = this.childNodes.length) {
|
|
@@ -93,12 +107,18 @@ class FileToken extends LinkToken {
|
|
|
93
107
|
return super.insertAt(token, i);
|
|
94
108
|
}
|
|
95
109
|
|
|
96
|
-
/**
|
|
110
|
+
/**
|
|
111
|
+
* 获取所有图片参数节点
|
|
112
|
+
* @returns {ImageParameterToken[]}
|
|
113
|
+
*/
|
|
97
114
|
getAllArgs() {
|
|
98
115
|
return this.childNodes.slice(1);
|
|
99
116
|
}
|
|
100
117
|
|
|
101
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* 获取图片框架属性参数节点
|
|
120
|
+
* @complexity `n`
|
|
121
|
+
*/
|
|
102
122
|
getFrameArgs() {
|
|
103
123
|
const args = this.getAllArgs()
|
|
104
124
|
.filter(({name}) => ['manualthumb', 'frameless', 'framed', 'thumbnail'].includes(name));
|
|
@@ -109,15 +129,16 @@ class FileToken extends LinkToken {
|
|
|
109
129
|
}
|
|
110
130
|
|
|
111
131
|
/**
|
|
112
|
-
*
|
|
132
|
+
* 获取指定图片参数
|
|
133
|
+
* @param {string} key 参数名
|
|
134
|
+
* @param {boolean} copy 是否返回备份
|
|
113
135
|
* @complexity `n`
|
|
114
136
|
*/
|
|
115
137
|
getArgs(key, copy = true) {
|
|
116
138
|
if (typeof key !== 'string') {
|
|
117
139
|
this.typeError('getArgs', 'String');
|
|
118
|
-
} else if (!copy && !Parser.debugging && externalUse('getArgs')) {
|
|
119
|
-
this.debugOnly('getArgs');
|
|
120
140
|
}
|
|
141
|
+
copy ||= !Parser.debugging && externalUse('getArgs');
|
|
121
142
|
let args = this.#args[key];
|
|
122
143
|
if (!args) {
|
|
123
144
|
args = new Set(this.getAllArgs().filter(({name}) => key === name));
|
|
@@ -127,7 +148,8 @@ class FileToken extends LinkToken {
|
|
|
127
148
|
}
|
|
128
149
|
|
|
129
150
|
/**
|
|
130
|
-
*
|
|
151
|
+
* 是否具有指定图片参数
|
|
152
|
+
* @param {string} key 参数名
|
|
131
153
|
* @complexity `n`
|
|
132
154
|
*/
|
|
133
155
|
hasArg(key) {
|
|
@@ -135,15 +157,17 @@ class FileToken extends LinkToken {
|
|
|
135
157
|
}
|
|
136
158
|
|
|
137
159
|
/**
|
|
138
|
-
*
|
|
160
|
+
* 获取生效的指定图片参数
|
|
161
|
+
* @param {string} key 参数名
|
|
139
162
|
* @complexity `n`
|
|
140
163
|
*/
|
|
141
164
|
getArg(key) {
|
|
142
|
-
return [...this.getArgs(key, false)].sort((a, b) => a.
|
|
165
|
+
return [...this.getArgs(key, false)].sort((a, b) => a.compareDocumentPosition(b)).at(-1);
|
|
143
166
|
}
|
|
144
167
|
|
|
145
168
|
/**
|
|
146
|
-
*
|
|
169
|
+
* 移除指定图片参数
|
|
170
|
+
* @param {string} key 参数名
|
|
147
171
|
* @complexity `n`
|
|
148
172
|
*/
|
|
149
173
|
removeArg(key) {
|
|
@@ -152,10 +176,13 @@ class FileToken extends LinkToken {
|
|
|
152
176
|
}
|
|
153
177
|
}
|
|
154
178
|
|
|
155
|
-
/**
|
|
179
|
+
/**
|
|
180
|
+
* 获取图片参数名
|
|
181
|
+
* @complexity `n`
|
|
182
|
+
*/
|
|
156
183
|
getKeys() {
|
|
157
184
|
const args = this.getAllArgs();
|
|
158
|
-
if (this.#keys.size === 0 && args.length) {
|
|
185
|
+
if (this.#keys.size === 0 && args.length > 0) {
|
|
159
186
|
for (const {name} of args) {
|
|
160
187
|
this.#keys.add(name);
|
|
161
188
|
}
|
|
@@ -164,7 +191,8 @@ class FileToken extends LinkToken {
|
|
|
164
191
|
}
|
|
165
192
|
|
|
166
193
|
/**
|
|
167
|
-
*
|
|
194
|
+
* 获取指定的图片参数值
|
|
195
|
+
* @param {string} key 参数名
|
|
168
196
|
* @complexity `n`
|
|
169
197
|
*/
|
|
170
198
|
getValues(key) {
|
|
@@ -172,22 +200,25 @@ class FileToken extends LinkToken {
|
|
|
172
200
|
}
|
|
173
201
|
|
|
174
202
|
/**
|
|
203
|
+
* 获取生效的指定图片参数值
|
|
175
204
|
* @template {string|undefined} T
|
|
176
|
-
* @param {T} key
|
|
205
|
+
* @param {T} key 参数名
|
|
177
206
|
* @returns {T extends undefined ? Object<string, string> : string|true}
|
|
178
207
|
* @complexity `n`
|
|
179
208
|
*/
|
|
180
209
|
getValue(key) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return Object.fromEntries(this.getKeys().map(k => [k, this.getValue(k)]));
|
|
210
|
+
return key === undefined
|
|
211
|
+
? Object.fromEntries(this.getKeys().map(k => [k, this.getValue(k)]))
|
|
212
|
+
: this.getArg(key)?.getValue();
|
|
185
213
|
}
|
|
186
214
|
|
|
187
215
|
/**
|
|
188
|
-
*
|
|
189
|
-
* @param {string
|
|
216
|
+
* 设置图片参数
|
|
217
|
+
* @param {string} key 参数名
|
|
218
|
+
* @param {string|boolean} value 参数值
|
|
190
219
|
* @complexity `n`
|
|
220
|
+
* @throws `RangeError` 未定义的图片参数
|
|
221
|
+
* @throws `SyntaxError` 非法的参数
|
|
191
222
|
*/
|
|
192
223
|
setValue(key, value) {
|
|
193
224
|
if (typeof key !== 'string') {
|
|
@@ -221,7 +252,7 @@ class FileToken extends LinkToken {
|
|
|
221
252
|
const wikitext = `[[File:F|${syntax ? syntax.replace('$1', value) : value}]]`,
|
|
222
253
|
root = Parser.parse(wikitext, this.getAttribute('include'), 6, config),
|
|
223
254
|
{childNodes: {length}, firstElementChild} = root;
|
|
224
|
-
if (length !== 1 || !firstElementChild?.matches('file#File
|
|
255
|
+
if (length !== 1 || !firstElementChild?.matches('file#File\\:F')
|
|
225
256
|
|| firstElementChild.childNodes.length !== 2 || firstElementChild.lastElementChild.name !== key
|
|
226
257
|
) {
|
|
227
258
|
throw new SyntaxError(`非法的 ${key} 参数:${noWrap(value)}`);
|
package/src/link/galleryImage.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const Title = require('../../lib/title'),
|
|
4
|
+
Parser = require('../..'),
|
|
4
5
|
Token = require('..'),
|
|
5
6
|
FileToken = require('./file');
|
|
6
7
|
|
|
@@ -16,9 +17,9 @@ class GalleryImageToken extends FileToken {
|
|
|
16
17
|
height = undefined;
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
|
-
* @param {string} link
|
|
20
|
-
* @param {string|undefined} text
|
|
21
|
-
* @param {Title} title
|
|
20
|
+
* @param {string} link 图片文件名
|
|
21
|
+
* @param {string|undefined} text 图片参数
|
|
22
|
+
* @param {Title} title 图片文件标题对象
|
|
22
23
|
* @param {accum} accum
|
|
23
24
|
*/
|
|
24
25
|
constructor(link, text, title, config = Parser.getConfig(), accum = []) {
|
|
@@ -26,21 +27,34 @@ class GalleryImageToken extends FileToken {
|
|
|
26
27
|
if (text !== undefined) {
|
|
27
28
|
token = new Token(text, config, true, accum);
|
|
28
29
|
token.type = 'temp';
|
|
29
|
-
token.setAttribute('stage', 1);
|
|
30
30
|
for (let n = 1; n < Parser.MAX_STAGE; n++) {
|
|
31
|
-
token.parseOnce();
|
|
31
|
+
token.getAttribute('parseOnce')();
|
|
32
32
|
}
|
|
33
33
|
accum.splice(accum.indexOf(token), 1);
|
|
34
34
|
}
|
|
35
35
|
const newConfig = structuredClone(config);
|
|
36
36
|
newConfig.img = Object.fromEntries(Object.entries(config.img).filter(([, param]) => param !== 'width'));
|
|
37
37
|
super(link, token?.toString(), title, newConfig, accum);
|
|
38
|
-
this.seal(['size', 'width', 'height']);
|
|
38
|
+
this.seal(['size', 'width', 'height'], true);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/** @override */
|
|
41
42
|
getPadding() {
|
|
42
43
|
return 0;
|
|
43
44
|
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @override
|
|
48
|
+
* @param {string} selector
|
|
49
|
+
*/
|
|
50
|
+
toString(selector) {
|
|
51
|
+
return super.toString(selector).replaceAll('\n', ' ');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** @override */
|
|
55
|
+
text() {
|
|
56
|
+
return super.text().replaceAll('\n', ' ');
|
|
57
|
+
}
|
|
44
58
|
}
|
|
45
59
|
|
|
46
60
|
Parser.classes.GalleryImageToken = __filename;
|