wikiparser-node 0.0.2 → 0.0.3
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 +15 -5
- package/errors/README +1 -0
- package/index.js +42 -9
- package/lib/element.js +70 -12
- package/lib/node.js +17 -9
- package/package.json +1 -1
- package/parser/externalLinks.js +1 -1
- package/parser/table.js +2 -2
- package/printed/README +1 -0
- package/src/arg.js +3 -3
- package/src/attribute.js +6 -6
- package/src/extLink.js +3 -2
- package/src/heading.js +2 -3
- package/src/html.js +4 -3
- package/src/imageParameter.js +5 -6
- package/src/index.js +5 -5
- package/src/link/file.js +7 -7
- package/src/link/index.js +2 -4
- package/src/magicLink.js +2 -3
- package/src/nowiki/comment.js +1 -1
- package/src/parameter.js +3 -3
- package/src/table/index.js +26 -21
- package/src/table/td.js +2 -2
- package/src/table/tr.js +2 -6
- package/src/tagPair/index.js +1 -1
- package/src/transclude.js +14 -11
- package/tool/index.js +50 -40
- package/typings/index.d.ts +1 -0
- package/util/debug.js +3 -3
- package/util/string.js +4 -1
package/src/index.js
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
* w: ExtLinkToken
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
|
-
const {
|
|
42
|
+
const {externalUse} = require('../util/debug'),
|
|
43
43
|
Ranges = require('../lib/ranges'),
|
|
44
44
|
AstElement = require('../lib/element'),
|
|
45
45
|
assert = require('assert/strict'),
|
|
@@ -255,7 +255,7 @@ class Token extends AstElement {
|
|
|
255
255
|
if (!parentNode) {
|
|
256
256
|
throw new Error('不存在父节点!');
|
|
257
257
|
} else if (token.constructor !== this.constructor) {
|
|
258
|
-
typeError(
|
|
258
|
+
this.typeError('safeReplaceWith', this.constructor.name);
|
|
259
259
|
}
|
|
260
260
|
try {
|
|
261
261
|
assert.deepEqual(token.getAttribute('acceptable'), this.#acceptable);
|
|
@@ -320,7 +320,7 @@ class Token extends AstElement {
|
|
|
320
320
|
*/
|
|
321
321
|
section(n) {
|
|
322
322
|
if (typeof n !== 'number') {
|
|
323
|
-
typeError(
|
|
323
|
+
this.typeError('section', 'Number');
|
|
324
324
|
}
|
|
325
325
|
return this.sections()[n];
|
|
326
326
|
}
|
|
@@ -332,7 +332,7 @@ class Token extends AstElement {
|
|
|
332
332
|
*/
|
|
333
333
|
findEnclosingHtml(tag) {
|
|
334
334
|
if (tag !== undefined && typeof tag !== 'string') {
|
|
335
|
-
typeError(
|
|
335
|
+
this.typeError('findEnclosingHtml', 'String');
|
|
336
336
|
}
|
|
337
337
|
tag = tag?.toLowerCase();
|
|
338
338
|
if (tag !== undefined && !this.#config.html.slice(0, 2).flat().includes(tag)) {
|
|
@@ -519,7 +519,7 @@ class Token extends AstElement {
|
|
|
519
519
|
/** 解析、重构、生成部分Token的`name`属性 */
|
|
520
520
|
parse(n = MAX_STAGE, include = false) {
|
|
521
521
|
if (typeof n !== 'number') {
|
|
522
|
-
typeError(
|
|
522
|
+
this.typeError('parse', 'Number');
|
|
523
523
|
} else if (n < MAX_STAGE && !Parser.debugging && externalUse('parse')) {
|
|
524
524
|
Parser.warn('指定解析层级的方法仅供熟练用户使用!');
|
|
525
525
|
}
|
package/src/link/file.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {explode} = require('../../util/string'),
|
|
4
|
-
{
|
|
3
|
+
const {explode, noWrap} = require('../../util/string'),
|
|
4
|
+
{externalUse} = require('../../util/debug'),
|
|
5
5
|
/** @type {Parser} */ Parser = require('../..'),
|
|
6
6
|
LinkToken = require('.'),
|
|
7
7
|
ImageParameterToken = require('../imageParameter');
|
|
@@ -102,7 +102,7 @@ class FileToken extends LinkToken {
|
|
|
102
102
|
const args = this.getAllArgs()
|
|
103
103
|
.filter(({name}) => ['manualthumb', 'frameless', 'framed', 'thumbnail'].includes(name));
|
|
104
104
|
if (args.length > 1) {
|
|
105
|
-
Parser.error(
|
|
105
|
+
Parser.error(`图片 ${this.name} 带有 ${args.length} 个框架参数,只有第 1 个 ${args[0].name} 会生效!`);
|
|
106
106
|
}
|
|
107
107
|
return args;
|
|
108
108
|
}
|
|
@@ -113,7 +113,7 @@ class FileToken extends LinkToken {
|
|
|
113
113
|
*/
|
|
114
114
|
getArgs(key, copy = true) {
|
|
115
115
|
if (typeof key !== 'string') {
|
|
116
|
-
typeError(
|
|
116
|
+
this.typeError('getArgs', 'String');
|
|
117
117
|
} else if (!copy && !Parser.debugging && externalUse('getArgs')) {
|
|
118
118
|
this.debugOnly('getArgs');
|
|
119
119
|
}
|
|
@@ -190,7 +190,7 @@ class FileToken extends LinkToken {
|
|
|
190
190
|
*/
|
|
191
191
|
setValue(key, value) {
|
|
192
192
|
if (typeof key !== 'string') {
|
|
193
|
-
typeError(
|
|
193
|
+
this.typeError('setValue', 'String');
|
|
194
194
|
} else if (value === false) {
|
|
195
195
|
this.removeArg(key);
|
|
196
196
|
return;
|
|
@@ -211,7 +211,7 @@ class FileToken extends LinkToken {
|
|
|
211
211
|
}
|
|
212
212
|
if (value === true) {
|
|
213
213
|
if (syntax.includes('$1')) {
|
|
214
|
-
typeError(
|
|
214
|
+
this.typeError('setValue', 'Boolean');
|
|
215
215
|
}
|
|
216
216
|
const newArg = Parser.run(() => new ImageParameterToken(syntax, config));
|
|
217
217
|
this.appendChild(newArg);
|
|
@@ -223,7 +223,7 @@ class FileToken extends LinkToken {
|
|
|
223
223
|
if (length !== 1 || !firstElementChild?.matches('file#File:F')
|
|
224
224
|
|| firstElementChild.childElementCount !== 2 || firstElementChild.lastElementChild.name !== key
|
|
225
225
|
) {
|
|
226
|
-
throw new SyntaxError(`非法的 ${key} 参数:${value
|
|
226
|
+
throw new SyntaxError(`非法的 ${key} 参数:${noWrap(value)}`);
|
|
227
227
|
}
|
|
228
228
|
this.appendChild(firstElementChild.lastChild);
|
|
229
229
|
}
|
package/src/link/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const Title = require('../../lib/title'), // eslint-disable-line no-unused-vars
|
|
4
|
-
{text} = require('../../util/string'),
|
|
4
|
+
{text, noWrap} = require('../../util/string'),
|
|
5
5
|
{undo} = require('../../util/debug'),
|
|
6
6
|
/** @type {Parser} */ Parser = require('../..'),
|
|
7
7
|
Token = require('..');
|
|
@@ -170,9 +170,7 @@ class LinkToken extends Token {
|
|
|
170
170
|
}L|${linkText}]]`, this.getAttribute('include'), 6, config),
|
|
171
171
|
{childNodes: {length}, firstElementChild} = root;
|
|
172
172
|
if (length !== 1 || firstElementChild?.type !== this.type || firstElementChild.childElementCount !== 2) {
|
|
173
|
-
throw new SyntaxError(`非法的${this.type === 'link' ? '内链文字' : '分类关键字'}:${
|
|
174
|
-
linkText.replaceAll('\n', '\\n')
|
|
175
|
-
}`);
|
|
173
|
+
throw new SyntaxError(`非法的${this.type === 'link' ? '内链文字' : '分类关键字'}:${noWrap(linkText)}`);
|
|
176
174
|
}
|
|
177
175
|
({lastElementChild} = firstElementChild);
|
|
178
176
|
} else {
|
package/src/magicLink.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
/** @type {Parser} */ Parser = require('..'),
|
|
3
|
+
const /** @type {Parser} */ Parser = require('..'),
|
|
5
4
|
Token = require('.');
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -17,7 +16,7 @@ class MagicLinkToken extends Token {
|
|
|
17
16
|
}
|
|
18
17
|
set protocol(value) {
|
|
19
18
|
if (typeof value !== 'string') {
|
|
20
|
-
typeError(
|
|
19
|
+
this.typeError('protocol', 'String');
|
|
21
20
|
}
|
|
22
21
|
if (!new RegExp(`${this.#protocolRegex.source}$`, 'i').test(value)) {
|
|
23
22
|
throw new RangeError(`非法的外链协议:${value}`);
|
package/src/nowiki/comment.js
CHANGED
|
@@ -30,7 +30,7 @@ class CommentToken extends hidden(NowikiToken) {
|
|
|
30
30
|
toString() {
|
|
31
31
|
const {firstChild, closed, nextSibling} = this;
|
|
32
32
|
if (!closed && nextSibling) {
|
|
33
|
-
Parser.error('自动闭合HTML注释',
|
|
33
|
+
Parser.error('自动闭合HTML注释', this);
|
|
34
34
|
this.closed = true;
|
|
35
35
|
}
|
|
36
36
|
return `<!--${firstChild}${this.closed ? '-->' : ''}`;
|
package/src/parameter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const {noWrap} = require('../util/string'),
|
|
4
4
|
fixedToken = require('../mixin/fixedToken'),
|
|
5
5
|
/** @type {Parser} */ Parser = require('..'),
|
|
6
6
|
Token = require('.');
|
|
@@ -116,7 +116,7 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
116
116
|
|| firstElementChild.childElementCount !== 2
|
|
117
117
|
|| lastElementChild.anon !== this.anon || lastElementChild.name !== '1'
|
|
118
118
|
) {
|
|
119
|
-
throw new SyntaxError(`非法的模板参数:${value
|
|
119
|
+
throw new SyntaxError(`非法的模板参数:${noWrap(value)}`);
|
|
120
120
|
}
|
|
121
121
|
const newValue = lastElementChild.lastChild;
|
|
122
122
|
root.destroy();
|
|
@@ -128,7 +128,7 @@ class ParameterToken extends fixedToken(Token) {
|
|
|
128
128
|
/** @param {string} key */
|
|
129
129
|
rename(key, force = false) {
|
|
130
130
|
if (typeof key !== 'string') {
|
|
131
|
-
typeError(
|
|
131
|
+
this.typeError('rename', 'String');
|
|
132
132
|
}
|
|
133
133
|
const {parentNode} = this;
|
|
134
134
|
// 必须检测是否是TranscludeToken
|
package/src/table/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
|
|
3
|
+
const assert = require('assert/strict'),
|
|
4
|
+
{noWrap} = require('../../util/string'),
|
|
5
5
|
/** @type {Parser} */ Parser = require('../..'),
|
|
6
6
|
Token = require('..'), // eslint-disable-line no-unused-vars
|
|
7
7
|
TrToken = require('./tr'),
|
|
@@ -84,26 +84,31 @@ class TableToken extends TrToken {
|
|
|
84
84
|
} else if (!Parser.running && i === this.childNodes.length && token instanceof SyntaxToken
|
|
85
85
|
&& (token.getAttribute('pattern') !== closingPattern || !closingPattern.test(token.text()))
|
|
86
86
|
) {
|
|
87
|
-
throw new SyntaxError(`表格的闭合部分不符合语法!${token.toString()
|
|
87
|
+
throw new SyntaxError(`表格的闭合部分不符合语法!${noWrap(token.toString())}`);
|
|
88
88
|
}
|
|
89
89
|
return super.insertAt(token, i);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/** @complexity `n` */
|
|
93
|
-
close(syntax = '\n|}') {
|
|
93
|
+
close(syntax = '\n|}', halfParsed = false) {
|
|
94
|
+
halfParsed &&= Parser.running;
|
|
94
95
|
const config = this.getAttribute('config'),
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
accum = this.getAttribute('accum'),
|
|
97
|
+
inner = !halfParsed && Parser.parse(syntax, this.getAttribute('include'), 2, config),
|
|
98
|
+
{lastElementChild} = this,
|
|
99
|
+
{closingPattern} = TableToken;
|
|
100
|
+
if (!halfParsed && !closingPattern.test(inner.text())) {
|
|
101
|
+
throw new SyntaxError(`表格的闭合部分不符合语法!${noWrap(syntax)}`);
|
|
99
102
|
} else if (lastElementChild instanceof SyntaxToken) {
|
|
100
103
|
lastElementChild.replaceChildren(...inner.childNodes);
|
|
101
104
|
} else {
|
|
102
105
|
this.appendChild(Parser.run(() => {
|
|
103
|
-
const token = new SyntaxToken(
|
|
106
|
+
const token = new SyntaxToken(syntax, closingPattern, 'table-syntax', config, accum, {
|
|
104
107
|
'Stage-1': ':', '!ExtToken': '', TranscludeToken: ':',
|
|
105
108
|
});
|
|
106
|
-
|
|
109
|
+
if (inner) {
|
|
110
|
+
token.replaceChildren(...inner.childNodes);
|
|
111
|
+
}
|
|
107
112
|
return token;
|
|
108
113
|
}));
|
|
109
114
|
}
|
|
@@ -132,7 +137,7 @@ class TableToken extends TrToken {
|
|
|
132
137
|
*/
|
|
133
138
|
getNthRow(n, force = false, insert = false) {
|
|
134
139
|
if (typeof n !== 'number') {
|
|
135
|
-
typeError(
|
|
140
|
+
this.typeError('getNthRow', 'Number');
|
|
136
141
|
}
|
|
137
142
|
const nRows = this.getRowCount(),
|
|
138
143
|
isRow = super.getRowCount();
|
|
@@ -240,7 +245,7 @@ class TableToken extends TrToken {
|
|
|
240
245
|
*/
|
|
241
246
|
toRenderedCoords({row, column}) {
|
|
242
247
|
if (typeof row !== 'number' || typeof column !== 'number') {
|
|
243
|
-
typeError(
|
|
248
|
+
this.typeError('toRenderedCoords', 'Number');
|
|
244
249
|
}
|
|
245
250
|
const rowLayout = this.getLayout({row, column})[row],
|
|
246
251
|
x = rowLayout?.findIndex(coords => cmpCoords(coords, {row, column}) === 0);
|
|
@@ -253,7 +258,7 @@ class TableToken extends TrToken {
|
|
|
253
258
|
*/
|
|
254
259
|
toRawCoords({x, y}) {
|
|
255
260
|
if (typeof x !== 'number' || typeof y !== 'number') {
|
|
256
|
-
typeError(
|
|
261
|
+
this.typeError('toRawCoords', 'Number');
|
|
257
262
|
}
|
|
258
263
|
const rowLayout = this.getLayout({x, y})[y],
|
|
259
264
|
coords = rowLayout?.[x];
|
|
@@ -272,7 +277,7 @@ class TableToken extends TrToken {
|
|
|
272
277
|
*/
|
|
273
278
|
getFullRow(y) {
|
|
274
279
|
if (typeof y !== 'number') {
|
|
275
|
-
typeError(
|
|
280
|
+
this.typeError('getFullRow', 'Number');
|
|
276
281
|
}
|
|
277
282
|
const rows = this.getAllRows();
|
|
278
283
|
return new Map(
|
|
@@ -286,7 +291,7 @@ class TableToken extends TrToken {
|
|
|
286
291
|
*/
|
|
287
292
|
getFullCol(x) {
|
|
288
293
|
if (typeof x !== 'number') {
|
|
289
|
-
typeError(
|
|
294
|
+
this.typeError('getFullCol', 'Number');
|
|
290
295
|
}
|
|
291
296
|
const layout = this.getLayout(),
|
|
292
297
|
colLayout = layout.map(row => row[x]).filter(coords => coords),
|
|
@@ -438,7 +443,7 @@ class TableToken extends TrToken {
|
|
|
438
443
|
*/
|
|
439
444
|
insertTableRow(y, attr = {}, inner = undefined, subtype = 'td', innerAttr = {}) {
|
|
440
445
|
if (typeof attr !== 'object') {
|
|
441
|
-
typeError(
|
|
446
|
+
this.typeError('insertTableRow', 'Object');
|
|
442
447
|
}
|
|
443
448
|
let reference = this.getNthRow(y, false, true);
|
|
444
449
|
/** @type {TrToken & AttributeToken}} */
|
|
@@ -482,7 +487,7 @@ class TableToken extends TrToken {
|
|
|
482
487
|
*/
|
|
483
488
|
insertTableCol(x, inner, subtype = 'td', attr = {}) {
|
|
484
489
|
if (typeof x !== 'number') {
|
|
485
|
-
typeError(
|
|
490
|
+
this.typeError('insertTableCol', 'Number');
|
|
486
491
|
}
|
|
487
492
|
const layout = this.getLayout(),
|
|
488
493
|
rowLength = layout.map(({length}) => length),
|
|
@@ -565,7 +570,7 @@ class TableToken extends TrToken {
|
|
|
565
570
|
*/
|
|
566
571
|
mergeCells(xlim, ylim) {
|
|
567
572
|
if ([...xlim, ...ylim].some(arg => typeof arg !== 'number')) {
|
|
568
|
-
typeError(
|
|
573
|
+
this.typeError('mergeCells', 'Number');
|
|
569
574
|
}
|
|
570
575
|
const layout = this.getLayout(),
|
|
571
576
|
maxCol = Math.max(...layout.map(({length}) => length));
|
|
@@ -711,7 +716,7 @@ class TableToken extends TrToken {
|
|
|
711
716
|
*/
|
|
712
717
|
moveTableRowBefore(y, before) {
|
|
713
718
|
if (typeof y !== 'number' || typeof before !== 'number') {
|
|
714
|
-
typeError(
|
|
719
|
+
this.typeError('moveTableRowBefore', 'Number');
|
|
715
720
|
}
|
|
716
721
|
const layout = this.getLayout(),
|
|
717
722
|
/**
|
|
@@ -748,7 +753,7 @@ class TableToken extends TrToken {
|
|
|
748
753
|
*/
|
|
749
754
|
moveTableRowAfter(y, after) {
|
|
750
755
|
if (typeof y !== 'number' || typeof after !== 'number') {
|
|
751
|
-
typeError(
|
|
756
|
+
this.typeError('moveTableRowAfter', 'Number');
|
|
752
757
|
}
|
|
753
758
|
const layout = this.getLayout(),
|
|
754
759
|
afterToken = this.getNthRow(after),
|
|
@@ -797,7 +802,7 @@ class TableToken extends TrToken {
|
|
|
797
802
|
*/
|
|
798
803
|
#moveCol(x, reference, after = false) {
|
|
799
804
|
if (typeof x !== 'number' || typeof reference !== 'number') {
|
|
800
|
-
typeError(
|
|
805
|
+
this.typeError(`moveTableCol${after ? 'After' : 'Before'}`, 'Number');
|
|
801
806
|
}
|
|
802
807
|
const layout = this.getLayout(),
|
|
803
808
|
/** @type {(rowLayout: TableCoords[], i: number, oneCol?: boolean) => boolean} */
|
package/src/table/td.js
CHANGED
|
@@ -110,7 +110,7 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
110
110
|
*/
|
|
111
111
|
static create(inner, subtype = 'td', attr = {}, include = false, config = Parser.getConfig()) {
|
|
112
112
|
if (typeof inner !== 'string' && (!(inner instanceof Token) || !inner.isPlain()) || typeof attr !== 'object') {
|
|
113
|
-
|
|
113
|
+
typeError(this, 'create', 'String', 'Token', 'Object');
|
|
114
114
|
} else if (!['td', 'th', 'caption'].includes(subtype)) {
|
|
115
115
|
throw new RangeError('单元格的子类型只能为 "td"、"th" 或 "caption"!');
|
|
116
116
|
} else if (typeof inner === 'string') {
|
|
@@ -231,7 +231,7 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
231
231
|
*/
|
|
232
232
|
setAttr(key, value) {
|
|
233
233
|
if (typeof key !== 'string') {
|
|
234
|
-
typeError(
|
|
234
|
+
this.typeError('setAttr', 'String');
|
|
235
235
|
}
|
|
236
236
|
key = key.toLowerCase().trim();
|
|
237
237
|
if (typeof value === 'number' && ['rowspan', 'colspan'].includes(key)) {
|
package/src/table/tr.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const attributeParent = require('../../mixin/attributeParent'),
|
|
4
|
-
{typeError} = require('../../util/debug'),
|
|
5
4
|
/** @type {Parser} */ Parser = require('../..'),
|
|
6
5
|
Token = require('..'),
|
|
7
6
|
SyntaxToken = require('../syntax'),
|
|
@@ -75,9 +74,6 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
75
74
|
|
|
76
75
|
/** @param {SyntaxToken} syntax */
|
|
77
76
|
static escape(syntax) {
|
|
78
|
-
if (!(syntax instanceof SyntaxToken)) {
|
|
79
|
-
typeError('SyntaxToken');
|
|
80
|
-
}
|
|
81
77
|
const wikitext = syntax.childNodes.map(child => typeof child === 'string'
|
|
82
78
|
? child.replaceAll('{|', '{{(!}}').replaceAll('|}', '{{!)}}').replaceAll('||', '{{!!}}')
|
|
83
79
|
.replaceAll('|', '{{!}}')
|
|
@@ -131,7 +127,7 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
131
127
|
*/
|
|
132
128
|
insertAt(token, i = this.childNodes.length) {
|
|
133
129
|
if (!Parser.running && !(token instanceof TrToken)) {
|
|
134
|
-
typeError(
|
|
130
|
+
this.typeError('insertAt', 'TrToken');
|
|
135
131
|
}
|
|
136
132
|
const TdToken = require('./td'),
|
|
137
133
|
child = this.childNodes.at(i);
|
|
@@ -201,7 +197,7 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
201
197
|
*/
|
|
202
198
|
getNthCol(n, insert = false) {
|
|
203
199
|
if (typeof n !== 'number') {
|
|
204
|
-
typeError(
|
|
200
|
+
this.typeError('getNthCol', 'Number');
|
|
205
201
|
}
|
|
206
202
|
const nCols = this.getColCount();
|
|
207
203
|
n = n < 0 ? n + nCols : n;
|
package/src/tagPair/index.js
CHANGED
|
@@ -52,7 +52,7 @@ class TagPairToken extends fixedToken(Token) {
|
|
|
52
52
|
const {closed, firstChild, lastChild, nextSibling, name, selfClosing} = this,
|
|
53
53
|
[opening, closing] = this.#tags;
|
|
54
54
|
if (!closed && nextSibling) {
|
|
55
|
-
Parser.error(`自动闭合 <${name}>`,
|
|
55
|
+
Parser.error(`自动闭合 <${name}>`, lastChild);
|
|
56
56
|
this.closed = true;
|
|
57
57
|
}
|
|
58
58
|
return selfClosing
|
package/src/transclude.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {removeComment, escapeRegExp, text} = require('../util/string'),
|
|
4
|
-
{
|
|
3
|
+
const {removeComment, escapeRegExp, text, noWrap} = require('../util/string'),
|
|
4
|
+
{externalUse} = require('../util/debug'),
|
|
5
5
|
/** @type {Parser} */ Parser = require('..'),
|
|
6
6
|
Token = require('.'),
|
|
7
7
|
ParameterToken = require('./parameter');
|
|
@@ -19,7 +19,7 @@ class TranscludeToken extends Token {
|
|
|
19
19
|
/** @complexity `n` */
|
|
20
20
|
setModifier(modifier = '') {
|
|
21
21
|
if (typeof modifier !== 'string') {
|
|
22
|
-
typeError(
|
|
22
|
+
this.typeError('setModifier', 'String');
|
|
23
23
|
}
|
|
24
24
|
const [,, raw, subst] = this.getAttribute('config').parserFunction,
|
|
25
25
|
lcModifier = modifier.trim().toLowerCase(),
|
|
@@ -291,7 +291,7 @@ class TranscludeToken extends Token {
|
|
|
291
291
|
*/
|
|
292
292
|
getArgs(key, exact = false, copy = true) {
|
|
293
293
|
if (!['string', 'number'].includes(typeof key)) {
|
|
294
|
-
typeError(
|
|
294
|
+
this.typeError('getArgs', 'String', 'Number');
|
|
295
295
|
} else if (!copy && !Parser.debugging && externalUse('getArgs')) {
|
|
296
296
|
this.debugOnly('getArgs');
|
|
297
297
|
}
|
|
@@ -383,7 +383,7 @@ class TranscludeToken extends Token {
|
|
|
383
383
|
if (length !== 1 || !firstElementChild?.matches(templateLike ? 'template#T' : 'magic-word#lc')
|
|
384
384
|
|| firstElementChild.childElementCount !== 2 || !firstElementChild.lastElementChild.anon
|
|
385
385
|
) {
|
|
386
|
-
throw new SyntaxError(`非法的匿名参数:${val
|
|
386
|
+
throw new SyntaxError(`非法的匿名参数:${noWrap(val)}`);
|
|
387
387
|
}
|
|
388
388
|
return this.appendChild(firstElementChild.lastChild);
|
|
389
389
|
}
|
|
@@ -395,7 +395,7 @@ class TranscludeToken extends Token {
|
|
|
395
395
|
*/
|
|
396
396
|
setValue(key, value) {
|
|
397
397
|
if (typeof key !== 'string') {
|
|
398
|
-
typeError(
|
|
398
|
+
this.typeError('setValue', 'String');
|
|
399
399
|
} else if (!this.matches('template, magic-word#invoke')) {
|
|
400
400
|
throw new Error(`${this.constructor.name}.setValue 方法仅供模板使用!`);
|
|
401
401
|
}
|
|
@@ -411,7 +411,7 @@ class TranscludeToken extends Token {
|
|
|
411
411
|
if (length !== 1 || !firstElementChild?.matches('template#T')
|
|
412
412
|
|| firstElementChild.childElementCount !== 2 || firstElementChild.lastElementChild.name !== key
|
|
413
413
|
) {
|
|
414
|
-
throw new SyntaxError(`非法的命名参数:${key}=${value
|
|
414
|
+
throw new SyntaxError(`非法的命名参数:${key}=${noWrap(value)}`);
|
|
415
415
|
}
|
|
416
416
|
this.appendChild(firstElementChild.lastChild);
|
|
417
417
|
}
|
|
@@ -432,7 +432,7 @@ class TranscludeToken extends Token {
|
|
|
432
432
|
if (this.type === 'magic-word') {
|
|
433
433
|
throw new Error(`${this.constructor.name}.replaceTemplate 方法仅用于更换模板!`);
|
|
434
434
|
} else if (typeof title !== 'string') {
|
|
435
|
-
typeError(
|
|
435
|
+
this.typeError('replaceTemplate', 'String');
|
|
436
436
|
}
|
|
437
437
|
const root = Parser.parse(`{{${title}}}`, this.getAttribute('include'), 2, this.getAttribute('config')),
|
|
438
438
|
{childNodes: {length}, firstElementChild} = root;
|
|
@@ -447,7 +447,7 @@ class TranscludeToken extends Token {
|
|
|
447
447
|
if (this.type !== 'magic-word' || this.name !== 'invoke') {
|
|
448
448
|
throw new Error(`${this.constructor.name}.replaceModule 方法仅用于更换模块!`);
|
|
449
449
|
} else if (typeof title !== 'string') {
|
|
450
|
-
typeError(
|
|
450
|
+
this.typeError('replaceModule', 'String');
|
|
451
451
|
}
|
|
452
452
|
const root = Parser.parse(`{{#invoke:${title}}}`, this.getAttribute('include'), 2, this.getAttribute('config')),
|
|
453
453
|
{childNodes: {length}, firstElementChild} = root;
|
|
@@ -470,7 +470,7 @@ class TranscludeToken extends Token {
|
|
|
470
470
|
if (this.type !== 'magic-word' || this.name !== 'invoke') {
|
|
471
471
|
throw new Error(`${this.constructor.name}.replaceModule 方法仅用于更换模块!`);
|
|
472
472
|
} else if (typeof func !== 'string') {
|
|
473
|
-
typeError(
|
|
473
|
+
this.typeError('replaceFunction', 'String');
|
|
474
474
|
} else if (this.childElementCount < 2) {
|
|
475
475
|
throw new Error('尚未指定模块名称!');
|
|
476
476
|
}
|
|
@@ -582,7 +582,10 @@ class TranscludeToken extends Token {
|
|
|
582
582
|
Parser.error(`${this.type === 'template'
|
|
583
583
|
? this.name
|
|
584
584
|
: this.normalizeTitle(this.children[1]?.text() ?? '', 828).title
|
|
585
|
-
} 还留有 ${remaining} 个重复的 ${key}
|
|
585
|
+
} 还留有 ${remaining} 个重复的 ${key} 参数:${[...this.getArgs(key)].map(arg => {
|
|
586
|
+
const {top, left} = arg.getBoundingClientRect();
|
|
587
|
+
return `第 ${top} 行第 ${left} 列`;
|
|
588
|
+
}).join('、')}`);
|
|
586
589
|
duplicatedKeys.push(key);
|
|
587
590
|
continue;
|
|
588
591
|
}
|