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/imageParameter.js
CHANGED
|
@@ -1,41 +1,39 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {text, noWrap, extUrlChar} = require('../util/string'),
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
Parser = require('..'),
|
|
5
|
+
Token = require('.'),
|
|
6
|
+
AstText = require('../lib/text');
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* 图片参数
|
|
10
|
-
* @classdesc `{childNodes: ...(
|
|
10
|
+
* @classdesc `{childNodes: ...(AstText|Token)}`
|
|
11
11
|
*/
|
|
12
12
|
class ImageParameterToken extends Token {
|
|
13
|
-
|
|
14
|
-
#syntax = '';
|
|
15
|
-
|
|
16
|
-
static #noLink = Symbol('no-link');
|
|
13
|
+
static noLink = Symbol('no-link'); // 这个Symbol需要公开
|
|
17
14
|
|
|
18
15
|
/**
|
|
16
|
+
* 检查图片参数是否合法
|
|
19
17
|
* @template {string} T
|
|
20
|
-
* @param {T} key
|
|
21
|
-
* @param {string} value
|
|
18
|
+
* @param {T} key 参数名
|
|
19
|
+
* @param {string} value 参数值
|
|
22
20
|
* @returns {T extends 'link' ? string|Symbol : boolean}
|
|
23
21
|
*/
|
|
24
|
-
static #validate(key, value, config = Parser.getConfig()) {
|
|
25
|
-
value = value.
|
|
22
|
+
static #validate(key, value, config = Parser.getConfig(), halfParsed = false) {
|
|
23
|
+
value = value.replaceAll(/\0\d+t\x7F/gu, '').trim();
|
|
26
24
|
if (key === 'width') {
|
|
27
|
-
return /^\d*(?:x\d*)
|
|
25
|
+
return /^\d*(?:x\d*)?$/u.test(value);
|
|
28
26
|
} else if (['alt', 'class', 'manualthumb', 'frameless', 'framed', 'thumbnail'].includes(key)) {
|
|
29
27
|
return true;
|
|
30
28
|
} else if (key === 'link') {
|
|
31
29
|
if (!value) {
|
|
32
|
-
return this
|
|
30
|
+
return this.noLink;
|
|
33
31
|
}
|
|
34
|
-
const regex = new RegExp(`(?:${config.protocol}|//)${extUrlChar}(?=\
|
|
32
|
+
const regex = new RegExp(`(?:${config.protocol}|//)${extUrlChar}(?=\0\\d+t\x7F|$)`, 'iu');
|
|
35
33
|
if (regex.test(value)) {
|
|
36
34
|
return value;
|
|
37
35
|
}
|
|
38
|
-
if (
|
|
36
|
+
if (value.startsWith('[[') && value.endsWith(']]')) {
|
|
39
37
|
value = value.slice(2, -2);
|
|
40
38
|
}
|
|
41
39
|
if (value.includes('%')) {
|
|
@@ -43,24 +41,39 @@ class ImageParameterToken extends Token {
|
|
|
43
41
|
value = decodeURIComponent(value);
|
|
44
42
|
} catch {}
|
|
45
43
|
}
|
|
46
|
-
const
|
|
47
|
-
return valid &&
|
|
44
|
+
const title = Parser.normalizeTitle(value, 0, false, config, halfParsed);
|
|
45
|
+
return title.valid && String(title);
|
|
48
46
|
}
|
|
49
47
|
return !isNaN(value);
|
|
50
48
|
}
|
|
51
49
|
|
|
50
|
+
type = 'image-parameter';
|
|
51
|
+
#syntax = '';
|
|
52
|
+
|
|
53
|
+
/** getValue()的getter */
|
|
54
|
+
get value() {
|
|
55
|
+
return this.getValue();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
set value(value) {
|
|
59
|
+
this.setValue(value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** 图片链接 */
|
|
52
63
|
get link() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return undefined;
|
|
64
|
+
return this.name === 'link'
|
|
65
|
+
? ImageParameterToken.#validate('link', this.getValue(), this.getAttribute('config'))
|
|
66
|
+
: undefined;
|
|
57
67
|
}
|
|
68
|
+
|
|
58
69
|
set link(value) {
|
|
59
70
|
if (this.name === 'link') {
|
|
60
|
-
value = value === ImageParameterToken
|
|
71
|
+
value = value === ImageParameterToken.noLink ? '' : value;
|
|
61
72
|
this.setValue(value);
|
|
62
73
|
}
|
|
63
74
|
}
|
|
75
|
+
|
|
76
|
+
/** 图片大小 */
|
|
64
77
|
get size() {
|
|
65
78
|
if (this.name === 'width') {
|
|
66
79
|
const /** @type {string} */ size = this.getValue().trim();
|
|
@@ -68,30 +81,37 @@ class ImageParameterToken extends Token {
|
|
|
68
81
|
const [width, height = ''] = size.split('x');
|
|
69
82
|
return {width, height};
|
|
70
83
|
}
|
|
71
|
-
const token = Parser.parse(size, false, 2, this.getAttribute('config')),
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
const /** @type {{childNodes: AstText[]}} */ token = Parser.parse(size, false, 2, this.getAttribute('config')),
|
|
85
|
+
i = token.childNodes.findIndex(({type, data}) => type === 'text' && data.includes('x')),
|
|
86
|
+
str = token.childNodes[i];
|
|
74
87
|
if (i === -1) {
|
|
75
88
|
return {width: size, height: ''};
|
|
76
89
|
}
|
|
77
|
-
|
|
78
|
-
|
|
90
|
+
str.splitText(str.data.indexOf('x'));
|
|
91
|
+
str.nextSibling.splitText(1);
|
|
92
|
+
// eslint-disable-next-line unicorn/consistent-destructuring
|
|
79
93
|
return {width: text(token.childNodes.slice(0, i + 1)), height: text(token.childNodes.slice(i + 2))};
|
|
80
94
|
}
|
|
81
95
|
return undefined;
|
|
82
96
|
}
|
|
97
|
+
|
|
98
|
+
/** 图片宽度 */
|
|
83
99
|
get width() {
|
|
84
100
|
return this.size?.width;
|
|
85
101
|
}
|
|
102
|
+
|
|
86
103
|
set width(width) {
|
|
87
104
|
if (this.name === 'width') {
|
|
88
105
|
const {height} = this;
|
|
89
106
|
this.setValue(`${String(width || '')}${height && 'x'}${height}`);
|
|
90
107
|
}
|
|
91
108
|
}
|
|
109
|
+
|
|
110
|
+
/** 图片高度 */
|
|
92
111
|
get height() {
|
|
93
112
|
return this.size?.height;
|
|
94
113
|
}
|
|
114
|
+
|
|
95
115
|
set height(height) {
|
|
96
116
|
height = String(height || '');
|
|
97
117
|
if (this.name === 'width') {
|
|
@@ -100,20 +120,18 @@ class ImageParameterToken extends Token {
|
|
|
100
120
|
}
|
|
101
121
|
|
|
102
122
|
/**
|
|
103
|
-
* @param {string} str
|
|
123
|
+
* @param {string} str 图片参数
|
|
104
124
|
* @param {accum} accum
|
|
105
125
|
*/
|
|
106
126
|
constructor(str, config = Parser.getConfig(), accum = []) {
|
|
107
127
|
const regexes = Object.entries(config.img).map(
|
|
108
128
|
/** @returns {[string, string, RegExp]} */
|
|
109
|
-
([syntax, param]) => [syntax, param, new RegExp(`^(\\s*)${syntax.replace('$1', '(.*)')}(\\s*)
|
|
129
|
+
([syntax, param]) => [syntax, param, new RegExp(`^(\\s*)${syntax.replace('$1', '(.*)')}(\\s*)$`, 'u')],
|
|
110
130
|
),
|
|
111
131
|
param = regexes.find(([,, regex]) => regex.test(str));
|
|
112
132
|
if (param) {
|
|
113
|
-
const mt =
|
|
114
|
-
if (mt.length
|
|
115
|
-
// pass
|
|
116
|
-
} else {
|
|
133
|
+
const mt = param[2].exec(str);
|
|
134
|
+
if (mt.length !== 4 || ImageParameterToken.#validate(param[1], mt[2], config, true)) {
|
|
117
135
|
if (mt.length === 3) {
|
|
118
136
|
super(undefined, config, true, accum);
|
|
119
137
|
this.#syntax = str;
|
|
@@ -129,8 +147,9 @@ class ImageParameterToken extends Token {
|
|
|
129
147
|
this.setAttribute('name', 'caption').setAttribute('stage', 7);
|
|
130
148
|
}
|
|
131
149
|
|
|
150
|
+
/** @override */
|
|
132
151
|
cloneNode() {
|
|
133
|
-
const cloned = this.
|
|
152
|
+
const cloned = this.cloneChildNodes(),
|
|
134
153
|
config = this.getAttribute('config'),
|
|
135
154
|
token = Parser.run(() => new ImageParameterToken(this.#syntax.replace('$1', ''), config));
|
|
136
155
|
token.replaceChildren(...cloned);
|
|
@@ -138,47 +157,52 @@ class ImageParameterToken extends Token {
|
|
|
138
157
|
}
|
|
139
158
|
|
|
140
159
|
/**
|
|
160
|
+
* @override
|
|
141
161
|
* @template {string} T
|
|
142
|
-
* @param {T} key
|
|
162
|
+
* @param {T} key 属性键
|
|
143
163
|
* @returns {TokenAttribute<T>}
|
|
144
164
|
*/
|
|
145
165
|
getAttribute(key) {
|
|
146
|
-
|
|
147
|
-
return this.#syntax;
|
|
148
|
-
}
|
|
149
|
-
return super.getAttribute(key);
|
|
166
|
+
return key === 'syntax' ? this.#syntax : super.getAttribute(key);
|
|
150
167
|
}
|
|
151
168
|
|
|
169
|
+
/** @override */
|
|
152
170
|
isPlain() {
|
|
153
171
|
return true;
|
|
154
172
|
}
|
|
155
173
|
|
|
174
|
+
/** 是否是不可变参数 */
|
|
156
175
|
#isVoid() {
|
|
157
176
|
return this.#syntax && !this.#syntax.includes('$1');
|
|
158
177
|
}
|
|
159
178
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
179
|
+
/**
|
|
180
|
+
* @override
|
|
181
|
+
* @param {string} selector
|
|
182
|
+
*/
|
|
183
|
+
toString(selector) {
|
|
184
|
+
return this.#syntax && !(selector && this.matches(selector))
|
|
185
|
+
? this.#syntax.replace('$1', super.toString(selector))
|
|
186
|
+
: super.toString(selector);
|
|
165
187
|
}
|
|
166
188
|
|
|
189
|
+
/** @override */
|
|
167
190
|
getPadding() {
|
|
168
191
|
return Math.max(0, this.#syntax.indexOf('$1'));
|
|
169
192
|
}
|
|
170
193
|
|
|
194
|
+
/** @override */
|
|
171
195
|
text() {
|
|
172
|
-
|
|
173
|
-
return super.text().trim();
|
|
174
|
-
}
|
|
175
|
-
return this.#syntax.replace('$1', super.text()).trim();
|
|
196
|
+
return this.#syntax ? this.#syntax.replace('$1', super.text()).trim() : super.text().trim();
|
|
176
197
|
}
|
|
177
198
|
|
|
178
199
|
/**
|
|
179
|
-
* @
|
|
180
|
-
* @
|
|
200
|
+
* @override
|
|
201
|
+
* @template {Token} T
|
|
202
|
+
* @param {T} token 待插入的子节点
|
|
203
|
+
* @param {number} i 插入位置
|
|
181
204
|
* @complexity `n`
|
|
205
|
+
* @throws `Error` 不接受自定义输入的图片参数
|
|
182
206
|
*/
|
|
183
207
|
insertAt(token, i = this.childNodes.length) {
|
|
184
208
|
if (!Parser.running && this.#isVoid()) {
|
|
@@ -187,14 +211,19 @@ class ImageParameterToken extends Token {
|
|
|
187
211
|
return super.insertAt(token, i);
|
|
188
212
|
}
|
|
189
213
|
|
|
190
|
-
/**
|
|
214
|
+
/**
|
|
215
|
+
* 获取参数值
|
|
216
|
+
* @complexity `n`
|
|
217
|
+
*/
|
|
191
218
|
getValue() {
|
|
192
219
|
return this.#isVoid() || super.text();
|
|
193
220
|
}
|
|
194
221
|
|
|
195
222
|
/**
|
|
196
|
-
*
|
|
223
|
+
* 设置参数值
|
|
224
|
+
* @param {string|boolean} value 参数值
|
|
197
225
|
* @complexity `n`
|
|
226
|
+
* @throws SyntaxError` 非法的参数值
|
|
198
227
|
*/
|
|
199
228
|
setValue(value) {
|
|
200
229
|
if (this.#isVoid()) {
|
|
@@ -212,7 +241,7 @@ class ImageParameterToken extends Token {
|
|
|
212
241
|
}]]`, this.getAttribute('include'), 6, this.getAttribute('config')),
|
|
213
242
|
{childNodes: {length}, firstElementChild} = root,
|
|
214
243
|
param = firstElementChild?.lastElementChild;
|
|
215
|
-
if (length !== 1 || !firstElementChild?.matches('file#File
|
|
244
|
+
if (length !== 1 || !firstElementChild?.matches('file#File\\:F')
|
|
216
245
|
|| firstElementChild.childNodes.length !== 2 || param.name !== this.name
|
|
217
246
|
) {
|
|
218
247
|
throw new SyntaxError(`非法的 ${this.name} 参数:${noWrap(value)}`);
|