wikiparser-node 0.8.1-m → 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/README.md +39 -0
- package/config/moegirl.json +1 -0
- package/i18n/zh-hans.json +44 -0
- package/i18n/zh-hant.json +44 -0
- package/index.js +264 -10
- package/lib/element.js +507 -33
- package/lib/node.js +550 -6
- package/lib/ranges.js +130 -0
- package/lib/text.js +111 -41
- package/lib/title.js +28 -5
- package/mixin/attributeParent.js +117 -0
- package/mixin/fixedToken.js +40 -0
- package/mixin/hidden.js +3 -0
- package/mixin/singleLine.js +31 -0
- package/mixin/sol.js +54 -0
- package/package.json +9 -8
- package/parser/brackets.js +9 -2
- package/parser/commentAndExt.js +3 -5
- package/parser/converter.js +1 -0
- package/parser/externalLinks.js +1 -0
- package/parser/hrAndDoubleUnderscore.js +1 -0
- package/parser/html.js +1 -0
- package/parser/links.js +6 -5
- package/parser/list.js +1 -0
- package/parser/magicLinks.js +5 -4
- package/parser/quotes.js +1 -0
- package/parser/selector.js +177 -0
- package/parser/table.js +1 -0
- package/src/arg.js +123 -5
- package/src/atom/hidden.js +2 -0
- package/src/atom/index.js +17 -0
- package/src/attribute.js +191 -8
- package/src/attributes.js +311 -8
- package/src/charinsert.js +97 -0
- package/src/converter.js +108 -2
- package/src/converterFlags.js +190 -3
- package/src/converterRule.js +185 -4
- package/src/extLink.js +122 -2
- package/src/gallery.js +59 -11
- package/src/hasNowiki/index.js +12 -0
- package/src/hasNowiki/pre.js +12 -0
- package/src/heading.js +57 -6
- package/src/html.js +133 -12
- package/src/imageParameter.js +232 -38
- package/src/imagemap.js +65 -6
- package/src/imagemapLink.js +14 -2
- package/src/index.js +537 -8
- package/src/link/category.js +32 -1
- package/src/link/file.js +173 -11
- package/src/link/galleryImage.js +63 -5
- package/src/link/index.js +268 -9
- package/src/magicLink.js +92 -11
- package/src/nested/choose.js +1 -0
- package/src/nested/combobox.js +1 -0
- package/src/nested/index.js +31 -7
- package/src/nested/references.js +1 -0
- package/src/nowiki/comment.js +27 -3
- package/src/nowiki/dd.js +47 -1
- package/src/nowiki/doubleUnderscore.js +31 -1
- package/src/nowiki/hr.js +20 -1
- package/src/nowiki/index.js +25 -3
- package/src/nowiki/list.js +5 -2
- package/src/nowiki/noinclude.js +14 -0
- package/src/nowiki/quote.js +17 -3
- package/src/onlyinclude.js +26 -1
- package/src/paramTag/index.js +27 -4
- package/src/paramTag/inputbox.js +4 -1
- package/src/parameter.js +150 -8
- package/src/syntax.js +68 -0
- package/src/table/index.js +941 -4
- package/src/table/td.js +229 -10
- package/src/table/tr.js +249 -4
- package/src/tagPair/ext.js +36 -9
- package/src/tagPair/include.js +24 -0
- package/src/tagPair/index.js +51 -2
- package/src/transclude.js +547 -29
- package/tool/index.js +1202 -0
- package/util/debug.js +73 -0
- package/util/lint.js +8 -7
- package/util/string.js +67 -1
- package/config/minimum.json +0 -142
package/src/imageParameter.js
CHANGED
|
@@ -1,53 +1,124 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {extUrlChar, extUrlCharFirst} = require('../util/string'),
|
|
3
|
+
const {text, noWrap, print, extUrlChar, extUrlCharFirst} = require('../util/string'),
|
|
4
|
+
{generateForSelf} = require('../util/lint'),
|
|
5
|
+
Title = require('../lib/title'),
|
|
4
6
|
Parser = require('..'),
|
|
7
|
+
AstText = require('../lib/text'),
|
|
5
8
|
Token = require('.');
|
|
6
9
|
|
|
10
|
+
const params = new Set(['alt', 'link', 'lang', 'page', 'caption']);
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 检查图片参数是否合法
|
|
14
|
+
* @template {string} T
|
|
15
|
+
* @param {T} key 参数名
|
|
16
|
+
* @param {string} value 参数值
|
|
17
|
+
* @returns {T extends 'link' ? string|Title : boolean}
|
|
18
|
+
*/
|
|
19
|
+
const validate = (key, value, config = Parser.getConfig(), halfParsed = false) => {
|
|
20
|
+
value = value.replace(/\0\d+t\x7F/gu, '').trim();
|
|
21
|
+
switch (key) {
|
|
22
|
+
case 'width':
|
|
23
|
+
return /^(?:\d+x?|\d*x\d+)$/u.test(value);
|
|
24
|
+
case 'link': {
|
|
25
|
+
if (!value) {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
const regex = new RegExp(`(?:(?:${config.protocol}|//)${extUrlCharFirst}|\0\\d+m\x7F)${
|
|
29
|
+
extUrlChar
|
|
30
|
+
}(?=\0\\d+t\x7F|$)`, 'iu');
|
|
31
|
+
if (regex.test(value)) {
|
|
32
|
+
return value;
|
|
33
|
+
} else if (value.startsWith('[[') && value.endsWith(']]')) {
|
|
34
|
+
value = value.slice(2, -2);
|
|
35
|
+
}
|
|
36
|
+
const title = Parser.normalizeTitle(value, 0, false, config, halfParsed, true, true);
|
|
37
|
+
return title.valid && title;
|
|
38
|
+
}
|
|
39
|
+
case 'lang':
|
|
40
|
+
return config.variants.includes(value);
|
|
41
|
+
case 'alt':
|
|
42
|
+
case 'class':
|
|
43
|
+
case 'manualthumb':
|
|
44
|
+
return true;
|
|
45
|
+
default:
|
|
46
|
+
return !isNaN(value);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
7
50
|
/**
|
|
8
51
|
* 图片参数
|
|
9
52
|
* @classdesc `{childNodes: ...(AstText|Token)}`
|
|
10
53
|
*/
|
|
11
54
|
class ImageParameterToken extends Token {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
55
|
+
type = 'image-parameter';
|
|
56
|
+
#syntax = '';
|
|
57
|
+
|
|
58
|
+
/** 图片链接 */
|
|
59
|
+
get link() {
|
|
60
|
+
return this.name === 'link' ? validate('link', super.text(), this.getAttribute('config')) : undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
set link(value) {
|
|
64
|
+
if (this.name === 'link') {
|
|
65
|
+
this.setValue(value);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** getValue()的getter */
|
|
70
|
+
get value() {
|
|
71
|
+
return this.getValue();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
set value(value) {
|
|
75
|
+
this.setValue(value);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** 图片大小 */
|
|
79
|
+
get size() {
|
|
80
|
+
if (this.name === 'width') {
|
|
81
|
+
const /** @type {string} */ size = this.getValue().trim();
|
|
82
|
+
if (!size.includes('{{')) {
|
|
83
|
+
const [width, height = ''] = size.split('x');
|
|
84
|
+
return {width, height};
|
|
85
|
+
}
|
|
86
|
+
const /** @type {{childNodes: AstText[]}} */ token = Parser.parse(size, false, 2, this.getAttribute('config')),
|
|
87
|
+
i = token.childNodes.findIndex(({type, data}) => type === 'text' && data.includes('x')),
|
|
88
|
+
str = token.childNodes[i];
|
|
89
|
+
if (i === -1) {
|
|
90
|
+
return {width: size, height: ''};
|
|
37
91
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
case 'class':
|
|
42
|
-
case 'manualthumb':
|
|
43
|
-
return true;
|
|
44
|
-
default:
|
|
45
|
-
return !isNaN(value);
|
|
92
|
+
str.splitText(str.data.indexOf('x'));
|
|
93
|
+
str.nextSibling.splitText(1);
|
|
94
|
+
return {width: text(token.childNodes.slice(0, i + 1)), height: text(token.childNodes.slice(i + 2))};
|
|
46
95
|
}
|
|
96
|
+
return undefined;
|
|
47
97
|
}
|
|
48
98
|
|
|
49
|
-
|
|
50
|
-
|
|
99
|
+
/** 图片宽度 */
|
|
100
|
+
get width() {
|
|
101
|
+
return this.size?.width;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
set width(width) {
|
|
105
|
+
if (this.name === 'width') {
|
|
106
|
+
const {height} = this;
|
|
107
|
+
this.setValue(`${String(width || '')}${height && 'x'}${height}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** 图片高度 */
|
|
112
|
+
get height() {
|
|
113
|
+
return this.size?.height;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
set height(height) {
|
|
117
|
+
height = String(height || '');
|
|
118
|
+
if (this.name === 'width') {
|
|
119
|
+
this.setValue(`${this.width}${height && 'x'}${height}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
51
122
|
|
|
52
123
|
/**
|
|
53
124
|
* @param {string} str 图片参数
|
|
@@ -61,7 +132,7 @@ class ImageParameterToken extends Token {
|
|
|
61
132
|
),
|
|
62
133
|
param = regexes.find(([, key, regex]) => {
|
|
63
134
|
mt = regex.exec(str);
|
|
64
|
-
return mt && (mt.length !== 4 ||
|
|
135
|
+
return mt && (mt.length !== 4 || validate(key, mt[2], config, true) !== false);
|
|
65
136
|
});
|
|
66
137
|
if (param) {
|
|
67
138
|
if (mt.length === 3) {
|
|
@@ -69,6 +140,7 @@ class ImageParameterToken extends Token {
|
|
|
69
140
|
this.#syntax = str;
|
|
70
141
|
} else {
|
|
71
142
|
super(mt[2], config, true, accum, {
|
|
143
|
+
'Stage-2': ':', '!HeadingToken': ':',
|
|
72
144
|
});
|
|
73
145
|
this.#syntax = `${mt[1]}${param[0]}${mt[3]}`;
|
|
74
146
|
}
|
|
@@ -79,6 +151,13 @@ class ImageParameterToken extends Token {
|
|
|
79
151
|
this.setAttribute('name', 'caption').setAttribute('stage', 7);
|
|
80
152
|
}
|
|
81
153
|
|
|
154
|
+
/** @override */
|
|
155
|
+
afterBuild() {
|
|
156
|
+
if (this.parentNode.type === 'gallery-image' && !params.has(this.name)) {
|
|
157
|
+
this.setAttribute('name', 'invalid');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
82
161
|
/** @override */
|
|
83
162
|
isPlain() {
|
|
84
163
|
return this.name === 'caption';
|
|
@@ -86,9 +165,10 @@ class ImageParameterToken extends Token {
|
|
|
86
165
|
|
|
87
166
|
/**
|
|
88
167
|
* @override
|
|
168
|
+
* @param {string} selector
|
|
89
169
|
*/
|
|
90
170
|
toString(selector) {
|
|
91
|
-
return this.#syntax
|
|
171
|
+
return this.#syntax && !(selector && this.matches(selector))
|
|
92
172
|
? this.#syntax.replace('$1', super.toString(selector))
|
|
93
173
|
: super.toString(selector);
|
|
94
174
|
}
|
|
@@ -102,6 +182,120 @@ class ImageParameterToken extends Token {
|
|
|
102
182
|
getPadding() {
|
|
103
183
|
return Math.max(0, this.#syntax.indexOf('$1'));
|
|
104
184
|
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* @override
|
|
188
|
+
* @this {ImageParameterToken & {link: Title}}
|
|
189
|
+
* @param {number} start 起始位置
|
|
190
|
+
*/
|
|
191
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
192
|
+
const errors = super.lint(start);
|
|
193
|
+
if (this.name === 'invalid') {
|
|
194
|
+
errors.push(generateForSelf(this, {start}, 'invalid gallery image parameter'));
|
|
195
|
+
} else if (this.link?.encoded) {
|
|
196
|
+
errors.push(generateForSelf(this, {start}, 'unnecessary URL encoding in an internal link'));
|
|
197
|
+
}
|
|
198
|
+
return errors;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** @override */
|
|
202
|
+
print() {
|
|
203
|
+
return this.#syntax
|
|
204
|
+
? `<span class="wpb-image-parameter">${
|
|
205
|
+
this.#syntax.replace('$1', `<span class="wpb-image-caption">${print(this.childNodes)}</span>`)
|
|
206
|
+
}</span>`
|
|
207
|
+
: super.print({class: 'image-caption'});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** @override */
|
|
211
|
+
cloneNode() {
|
|
212
|
+
const cloned = this.cloneChildNodes(),
|
|
213
|
+
config = this.getAttribute('config');
|
|
214
|
+
return Parser.run(() => {
|
|
215
|
+
const token = new ImageParameterToken(this.#syntax.replace('$1', ''), config);
|
|
216
|
+
token.replaceChildren(...cloned);
|
|
217
|
+
return token;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @override
|
|
223
|
+
* @template {string} T
|
|
224
|
+
* @param {T} key 属性键
|
|
225
|
+
* @returns {TokenAttribute<T>}
|
|
226
|
+
*/
|
|
227
|
+
getAttribute(key) {
|
|
228
|
+
return key === 'syntax' ? this.#syntax : super.getAttribute(key);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* @override
|
|
233
|
+
* @param {PropertyKey} key 属性键
|
|
234
|
+
*/
|
|
235
|
+
hasAttribute(key) {
|
|
236
|
+
return key === 'syntax' || super.hasAttribute(key);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** 是否是不可变参数 */
|
|
240
|
+
#isVoid() {
|
|
241
|
+
return this.#syntax && !this.#syntax.includes('$1');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* @override
|
|
246
|
+
* @template {Token} T
|
|
247
|
+
* @param {T} token 待插入的子节点
|
|
248
|
+
* @param {number} i 插入位置
|
|
249
|
+
* @complexity `n`
|
|
250
|
+
* @throws `Error` 不接受自定义输入的图片参数
|
|
251
|
+
*/
|
|
252
|
+
insertAt(token, i = this.length) {
|
|
253
|
+
if (!Parser.running && this.#isVoid()) {
|
|
254
|
+
throw new Error(`图片参数 ${this.name} 不接受自定义输入!`);
|
|
255
|
+
}
|
|
256
|
+
return super.insertAt(token, i);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* 获取参数值
|
|
261
|
+
* @complexity `n`
|
|
262
|
+
*/
|
|
263
|
+
getValue() {
|
|
264
|
+
return this.name === 'invalid' ? this.text() : this.#isVoid() || super.text();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* 设置参数值
|
|
269
|
+
* @param {string|boolean} value 参数值
|
|
270
|
+
* @complexity `n`
|
|
271
|
+
* @throws SyntaxError` 非法的参数值
|
|
272
|
+
*/
|
|
273
|
+
setValue(value) {
|
|
274
|
+
if (this.name === 'invalid') {
|
|
275
|
+
throw new Error('无效的图片参数!');
|
|
276
|
+
} else if (this.#isVoid()) {
|
|
277
|
+
if (typeof value !== 'boolean') {
|
|
278
|
+
this.typeError('setValue', 'Boolean');
|
|
279
|
+
} else if (value === false) {
|
|
280
|
+
this.remove();
|
|
281
|
+
}
|
|
282
|
+
return;
|
|
283
|
+
} else if (typeof value !== 'string') {
|
|
284
|
+
this.typeError('setValue', 'String');
|
|
285
|
+
}
|
|
286
|
+
const root = Parser.parse(`[[File:F|${
|
|
287
|
+
this.#syntax ? this.#syntax.replace('$1', value) : value
|
|
288
|
+
}]]`, this.getAttribute('include'), 6, this.getAttribute('config')),
|
|
289
|
+
{length, firstChild: file} = root,
|
|
290
|
+
{lastChild: imageParameter, type, name, length: fileLength} = file;
|
|
291
|
+
if (length !== 1 || type !== 'file' || name !== 'File:F' || fileLength !== 2
|
|
292
|
+
|| imageParameter.name !== this.name
|
|
293
|
+
) {
|
|
294
|
+
throw new SyntaxError(`非法的 ${this.name} 参数:${noWrap(value)}`);
|
|
295
|
+
}
|
|
296
|
+
this.replaceChildren(...imageParameter.childNodes);
|
|
297
|
+
}
|
|
105
298
|
}
|
|
106
299
|
|
|
300
|
+
Parser.classes.ImageParameterToken = __filename;
|
|
107
301
|
module.exports = ImageParameterToken;
|
package/src/imagemap.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {generateForSelf, generateForChild} = require('../util/lint'),
|
|
4
|
+
singleLine = require('../mixin/singleLine'),
|
|
4
5
|
Parser = require('..'),
|
|
5
6
|
Token = require('.'),
|
|
6
7
|
NoincludeToken = require('./nowiki/noinclude'),
|
|
@@ -23,6 +24,14 @@ class ImagemapToken extends Token {
|
|
|
23
24
|
return this.childNodes.find(({type}) => type === 'imagemap-image');
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
/**
|
|
28
|
+
* 链接
|
|
29
|
+
* @returns {ImagemapLinkToken[]}
|
|
30
|
+
*/
|
|
31
|
+
get links() {
|
|
32
|
+
return this.childNodes.filter(({type}) => type === 'imagemap-link');
|
|
33
|
+
}
|
|
34
|
+
|
|
26
35
|
/**
|
|
27
36
|
* @param {string} inner 标签内部wikitext
|
|
28
37
|
* @param {accum} accum
|
|
@@ -30,13 +39,14 @@ class ImagemapToken extends Token {
|
|
|
30
39
|
*/
|
|
31
40
|
constructor(inner, config = Parser.getConfig(), accum = []) {
|
|
32
41
|
super(undefined, config, true, accum, {
|
|
42
|
+
GalleryImageToken: ':', ImagemapLinkToken: ':', SingleLineNoincludeToken: ':', AstText: ':',
|
|
33
43
|
});
|
|
34
44
|
if (!inner) {
|
|
35
45
|
return;
|
|
36
46
|
}
|
|
37
47
|
const lines = inner.split('\n'),
|
|
38
48
|
protocols = new Set(config.protocol.split('|')),
|
|
39
|
-
SingleLineNoincludeToken = NoincludeToken,
|
|
49
|
+
SingleLineNoincludeToken = singleLine(NoincludeToken),
|
|
40
50
|
fallback = /** @param {string} line 一行文本 */ line => {
|
|
41
51
|
super.insertAt(new SingleLineNoincludeToken(line, config, accum));
|
|
42
52
|
};
|
|
@@ -51,13 +61,14 @@ class ImagemapToken extends Token {
|
|
|
51
61
|
title = this.normalizeTitle(file, 0, true);
|
|
52
62
|
if (title.valid && !title.interwiki && title.ns === 6) {
|
|
53
63
|
const token = new GalleryImageToken(
|
|
54
|
-
file, options.length > 0 ? options.join('|') : undefined,
|
|
64
|
+
file, options.length > 0 ? options.join('|') : undefined, config, accum,
|
|
55
65
|
);
|
|
56
66
|
token.type = 'imagemap-image';
|
|
57
67
|
super.insertAt(token);
|
|
58
68
|
first = false;
|
|
59
69
|
continue;
|
|
60
70
|
} else {
|
|
71
|
+
Parser.error('<imagemap>标签内必须先包含一张合法图片!', line);
|
|
61
72
|
error = true;
|
|
62
73
|
}
|
|
63
74
|
} else if (line.trim().split(/[\t ]/u)[0] === 'desc') {
|
|
@@ -72,7 +83,7 @@ class ImagemapToken extends Token {
|
|
|
72
83
|
if (title.valid) {
|
|
73
84
|
super.insertAt(new ImagemapLinkToken(
|
|
74
85
|
line.slice(0, i),
|
|
75
|
-
|
|
86
|
+
mtIn.slice(1),
|
|
76
87
|
substr.slice(substr.indexOf(']]') + 2),
|
|
77
88
|
config,
|
|
78
89
|
accum,
|
|
@@ -101,6 +112,7 @@ class ImagemapToken extends Token {
|
|
|
101
112
|
|
|
102
113
|
/**
|
|
103
114
|
* @override
|
|
115
|
+
* @param {string} selector
|
|
104
116
|
*/
|
|
105
117
|
toString(selector) {
|
|
106
118
|
return super.toString(selector, '\n');
|
|
@@ -116,11 +128,16 @@ class ImagemapToken extends Token {
|
|
|
116
128
|
return 1;
|
|
117
129
|
}
|
|
118
130
|
|
|
131
|
+
/** @override */
|
|
132
|
+
print() {
|
|
133
|
+
return super.print({sep: '\n'});
|
|
134
|
+
}
|
|
135
|
+
|
|
119
136
|
/**
|
|
120
137
|
* @override
|
|
121
138
|
* @param {number} start 起始位置
|
|
122
139
|
*/
|
|
123
|
-
lint(start =
|
|
140
|
+
lint(start = this.getAbsoluteIndex()) {
|
|
124
141
|
const errors = super.lint(start),
|
|
125
142
|
rect = {start, ...this.getRootNode().posFromIndex(start)};
|
|
126
143
|
if (this.image) {
|
|
@@ -128,13 +145,55 @@ class ImagemapToken extends Token {
|
|
|
128
145
|
...this.childNodes.filter(child => {
|
|
129
146
|
const str = String(child).trim();
|
|
130
147
|
return child.type === 'noinclude' && str && str[0] !== '#';
|
|
131
|
-
}).map(child => generateForChild(child, rect, '
|
|
148
|
+
}).map(child => generateForChild(child, rect, 'invalid link in <imagemap>')),
|
|
132
149
|
);
|
|
133
150
|
} else {
|
|
134
|
-
errors.push(generateForSelf(this, rect, '
|
|
151
|
+
errors.push(generateForSelf(this, rect, '<imagemap> without an image'));
|
|
135
152
|
}
|
|
136
153
|
return errors;
|
|
137
154
|
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @override
|
|
158
|
+
* @template {string|Token} T
|
|
159
|
+
* @param {T} token 待插入的节点
|
|
160
|
+
* @param {number} i 插入位置
|
|
161
|
+
* @throws `Error` 当前缺少合法图片
|
|
162
|
+
* @throws `RangeError` 已有一张合法图片
|
|
163
|
+
*/
|
|
164
|
+
insertAt(token, i = 0) {
|
|
165
|
+
const {image} = this;
|
|
166
|
+
if (!image && (token.type === 'imagemap-link' || token.type === 'text')) {
|
|
167
|
+
throw new Error('当前缺少一张合法图片!');
|
|
168
|
+
} else if (image && token.type === 'imagemap-image') {
|
|
169
|
+
throw new RangeError('已有一张合法图片!');
|
|
170
|
+
}
|
|
171
|
+
return super.insertAt(token, i);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @override
|
|
176
|
+
* @param {number} i 移除位置
|
|
177
|
+
* @throws `Error` 禁止移除图片
|
|
178
|
+
*/
|
|
179
|
+
removeAt(i) {
|
|
180
|
+
const child = this.childNodes[i];
|
|
181
|
+
if (child.type === 'imagemap-image') {
|
|
182
|
+
throw new Error('禁止移除<imagemap>内的图片!');
|
|
183
|
+
}
|
|
184
|
+
return super.removeAt(i);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** @override */
|
|
188
|
+
cloneNode() {
|
|
189
|
+
const cloned = this.cloneChildNodes();
|
|
190
|
+
return Parser.run(() => {
|
|
191
|
+
const token = new ImagemapToken(undefined, this.getAttribute('config'));
|
|
192
|
+
token.append(...cloned);
|
|
193
|
+
return token;
|
|
194
|
+
});
|
|
195
|
+
}
|
|
138
196
|
}
|
|
139
197
|
|
|
198
|
+
Parser.classes.ImagemapToken = __filename;
|
|
140
199
|
module.exports = ImagemapToken;
|
package/src/imagemapLink.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const Title = require('../lib/title'),
|
|
4
|
+
fixedToken = require('../mixin/fixedToken'),
|
|
5
|
+
singleLine = require('../mixin/singleLine'),
|
|
6
|
+
Parser = require('..'),
|
|
4
7
|
Token = require('.'),
|
|
5
8
|
NoincludeToken = require('./nowiki/noinclude'),
|
|
6
9
|
LinkToken = require('./link'),
|
|
@@ -10,9 +13,17 @@ const Title = require('../lib/title'),
|
|
|
10
13
|
* `<imagemap>`内的链接
|
|
11
14
|
* @classdesc `{childNodes: [AstText, LinkToken|ExtLinkToken, NoincludeToken]}`
|
|
12
15
|
*/
|
|
13
|
-
class ImagemapLinkToken extends Token {
|
|
16
|
+
class ImagemapLinkToken extends fixedToken(singleLine(Token)) {
|
|
14
17
|
type = 'imagemap-link';
|
|
15
18
|
|
|
19
|
+
/**
|
|
20
|
+
* 内外链接
|
|
21
|
+
* @this {{childNodes: (LinkToken|ExtLinkToken)[]}}
|
|
22
|
+
*/
|
|
23
|
+
get link() {
|
|
24
|
+
return this.childNodes[1].link;
|
|
25
|
+
}
|
|
26
|
+
|
|
16
27
|
/**
|
|
17
28
|
* @param {string} pre 链接前的文本
|
|
18
29
|
* @param {[string, string, string|Title]} linkStuff 内外链接
|
|
@@ -20,10 +31,11 @@ class ImagemapLinkToken extends Token {
|
|
|
20
31
|
* @param {accum} accum
|
|
21
32
|
*/
|
|
22
33
|
constructor(pre, linkStuff, post, config, accum) {
|
|
23
|
-
const SomeLinkToken = linkStuff
|
|
34
|
+
const SomeLinkToken = linkStuff.length === 2 ? LinkToken : ExtLinkToken;
|
|
24
35
|
super(undefined, config, true, accum);
|
|
25
36
|
this.append(pre, new SomeLinkToken(...linkStuff, config, accum), new NoincludeToken(post, config, accum));
|
|
26
37
|
}
|
|
27
38
|
}
|
|
28
39
|
|
|
40
|
+
Parser.classes.ImagemapLinkToken = __filename;
|
|
29
41
|
module.exports = ImagemapLinkToken;
|