wikiparser-node 0.3.1 → 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 +446 -51
- package/README.md +1 -1
- package/config/default.json +13 -17
- package/config/llwiki.json +11 -79
- package/config/moegirl.json +7 -1
- package/config/zhwiki.json +1269 -0
- package/index.js +106 -96
- 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 +7 -4
- package/parser/brackets.js +18 -18
- package/parser/commentAndExt.js +15 -13
- package/parser/converter.js +14 -13
- package/parser/externalLinks.js +12 -11
- package/parser/hrAndDoubleUnderscore.js +23 -14
- package/parser/html.js +8 -7
- package/parser/links.js +13 -12
- package/parser/list.js +12 -11
- package/parser/magicLinks.js +11 -10
- package/parser/quotes.js +6 -5
- package/parser/selector.js +175 -0
- package/parser/table.js +24 -17
- 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 +180 -98
- package/src/converter.js +68 -41
- package/src/converterFlags.js +63 -41
- package/src/converterRule.js +117 -65
- package/src/extLink.js +66 -18
- package/src/gallery.js +28 -16
- package/src/heading.js +33 -14
- package/src/html.js +97 -35
- package/src/imageParameter.js +82 -53
- package/src/index.js +296 -175
- 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 +143 -57
- package/src/magicLink.js +33 -11
- 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 +23 -20
- package/src/table/index.js +260 -165
- package/src/table/td.js +97 -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 +167 -92
- 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 +38 -25
- package/typings/element.d.ts +0 -28
package/src/table/td.js
CHANGED
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
const fixedToken = require('../../mixin/fixedToken'),
|
|
4
4
|
{externalUse, typeError} = require('../../util/debug'),
|
|
5
|
-
|
|
5
|
+
Parser = require('../..'),
|
|
6
6
|
Token = require('..'),
|
|
7
7
|
TrToken = require('./tr');
|
|
8
8
|
|
|
9
|
+
const aliases = {td: '\n|', th: '\n!', caption: '\n|+'},
|
|
10
|
+
openingPattern = /^(?:\n[\S\n]*(?:[|!]|\|\+|\{\{\s*!\s*\}\}\+?)|(?:\||\{\{\s*!\s*\}\}){2}|!!|\{\{\s*!!\s*\}\})$/u;
|
|
11
|
+
|
|
9
12
|
/**
|
|
10
13
|
* `<td>`、`<th>`和`<caption>`
|
|
11
14
|
* @classdesc `{childNodes: [SyntaxToken, AttributeToken, Token]}`
|
|
@@ -14,42 +17,59 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
14
17
|
type = 'td';
|
|
15
18
|
#innerSyntax = '';
|
|
16
19
|
|
|
17
|
-
/**
|
|
20
|
+
/**
|
|
21
|
+
* 单元格类型
|
|
22
|
+
* @complexity `n`
|
|
23
|
+
*/
|
|
18
24
|
get subtype() {
|
|
19
25
|
return this.getSyntax().subtype;
|
|
20
26
|
}
|
|
27
|
+
|
|
21
28
|
set subtype(subtype) {
|
|
22
29
|
this.setSyntax(subtype);
|
|
23
30
|
}
|
|
24
31
|
|
|
32
|
+
/** rowspan */
|
|
25
33
|
get rowspan() {
|
|
26
34
|
return this.getAttr('rowspan');
|
|
27
35
|
}
|
|
36
|
+
|
|
28
37
|
set rowspan(rowspan) {
|
|
29
38
|
this.setAttr('rowspan', rowspan);
|
|
30
39
|
}
|
|
40
|
+
|
|
41
|
+
/** colspan */
|
|
31
42
|
get colspan() {
|
|
32
43
|
return this.getAttr('colspan');
|
|
33
44
|
}
|
|
45
|
+
|
|
34
46
|
set colspan(colspan) {
|
|
35
47
|
this.setAttr('colspan', colspan);
|
|
36
48
|
}
|
|
37
49
|
|
|
50
|
+
/** 内部wikitext */
|
|
51
|
+
get innerText() {
|
|
52
|
+
return this.lastElementChild.text();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** 是否位于行首 */
|
|
38
56
|
isIndependent() {
|
|
39
|
-
return this.firstElementChild.text()
|
|
57
|
+
return this.firstElementChild.text()[0] === '\n';
|
|
40
58
|
}
|
|
41
59
|
|
|
42
60
|
/**
|
|
61
|
+
* 获取单元格语法信息
|
|
43
62
|
* @returns {{subtype: 'td'|'th'|'caption', escape: boolean, correction: boolean}}
|
|
44
63
|
* @complexity `n`
|
|
45
64
|
*/
|
|
46
65
|
getSyntax() {
|
|
47
66
|
const syntax = this.firstElementChild.text(),
|
|
48
|
-
esc = syntax.includes('{{')
|
|
67
|
+
esc = syntax.includes('{{'),
|
|
68
|
+
char = syntax.at(-1);
|
|
49
69
|
let subtype = 'td';
|
|
50
|
-
if (
|
|
70
|
+
if (char === '!') {
|
|
51
71
|
subtype = 'th';
|
|
52
|
-
} else if (
|
|
72
|
+
} else if (char === '+') {
|
|
53
73
|
subtype = 'caption';
|
|
54
74
|
}
|
|
55
75
|
if (this.isIndependent()) {
|
|
@@ -61,7 +81,9 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
61
81
|
}
|
|
62
82
|
const result = previousElementSibling.getSyntax();
|
|
63
83
|
result.escape ||= esc;
|
|
64
|
-
result.correction = previousElementSibling.lastElementChild
|
|
84
|
+
result.correction = previousElementSibling.lastElementChild
|
|
85
|
+
.toString('comment, ext, include, noinclude, arg, template, magic-word, html')
|
|
86
|
+
.includes('\n');
|
|
65
87
|
if (subtype === 'th' && result.subtype !== 'th') {
|
|
66
88
|
result.subtype = 'th';
|
|
67
89
|
result.correction = true;
|
|
@@ -69,26 +91,23 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
69
91
|
return result;
|
|
70
92
|
}
|
|
71
93
|
|
|
72
|
-
static openingPattern
|
|
73
|
-
= /^(?:\n[\S\n]*(?:[|!]|\|\+|\{\{\s*!\s*\}\}\+?)|(?:\||\{\{\s*!\s*\}\}){2}|!!|\{\{\s*!!\s*\}\})$/;
|
|
74
|
-
|
|
75
94
|
getRowCount = undefined;
|
|
76
95
|
getNthCol = undefined;
|
|
77
96
|
insertTableCell = undefined;
|
|
78
97
|
|
|
79
98
|
/**
|
|
80
|
-
* @param {string} syntax
|
|
81
|
-
* @param {string} inner
|
|
99
|
+
* @param {string} syntax 单元格语法
|
|
100
|
+
* @param {string} inner 内部wikitext
|
|
82
101
|
* @param {accum} accum
|
|
83
102
|
*/
|
|
84
103
|
constructor(syntax, inner, config = Parser.getConfig(), accum = []) {
|
|
85
|
-
let innerSyntax = /\||\0\d+!\
|
|
104
|
+
let innerSyntax = inner?.match(/\||\0\d+!\x7F/u),
|
|
86
105
|
attr = innerSyntax ? inner.slice(0, innerSyntax.index) : '';
|
|
87
|
-
if (/\[\[|-\{
|
|
106
|
+
if (/\[\[|-\{/u.test(attr)) {
|
|
88
107
|
innerSyntax = null;
|
|
89
108
|
attr = '';
|
|
90
109
|
}
|
|
91
|
-
super(syntax, attr, config, accum,
|
|
110
|
+
super(syntax, attr, config, accum, openingPattern);
|
|
92
111
|
if (innerSyntax) {
|
|
93
112
|
[this.#innerSyntax] = innerSyntax;
|
|
94
113
|
}
|
|
@@ -96,9 +115,11 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
96
115
|
const innerToken = new Token(inner?.slice(innerSyntax?.index + this.#innerSyntax.length), config, true, accum);
|
|
97
116
|
innerToken.type = 'td-inner';
|
|
98
117
|
this.setAttribute('acceptable', {SyntaxToken: 0, AttributeToken: 1, Token: 2})
|
|
99
|
-
.seal(['getRowCount', 'getNthCol', 'insertTableCell']
|
|
118
|
+
.seal(['getRowCount', 'getNthCol', 'insertTableCell'], true)
|
|
119
|
+
.appendChild(innerToken.setAttribute('stage', 4));
|
|
100
120
|
}
|
|
101
121
|
|
|
122
|
+
/** @override */
|
|
102
123
|
cloneNode() {
|
|
103
124
|
const /** @type {TdToken} */ token = super.cloneNode();
|
|
104
125
|
token.setAttribute('innerSyntax', this.#innerSyntax);
|
|
@@ -106,14 +127,17 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
106
127
|
}
|
|
107
128
|
|
|
108
129
|
/**
|
|
109
|
-
*
|
|
110
|
-
* @param {
|
|
111
|
-
* @param {
|
|
130
|
+
* 创建新的单元格
|
|
131
|
+
* @param {string|Token} inner 内部wikitext
|
|
132
|
+
* @param {'td'|'th'|'caption'} subtype 单元格类型
|
|
133
|
+
* @param {Record<string, string>} attr 单元格属性
|
|
134
|
+
* @param {boolean} include 是否嵌入
|
|
135
|
+
* @throws `RangeError` 非法的单元格类型
|
|
112
136
|
*/
|
|
113
137
|
static create(inner, subtype = 'td', attr = {}, include = false, config = Parser.getConfig()) {
|
|
114
138
|
if (typeof inner !== 'string' && (!(inner instanceof Token) || !inner.isPlain()) || typeof attr !== 'object') {
|
|
115
139
|
typeError(this, 'create', 'String', 'Token', 'Object');
|
|
116
|
-
} else if (
|
|
140
|
+
} else if (subtype !== 'td' && subtype !== 'th' && subtype !== 'caption') {
|
|
117
141
|
throw new RangeError('单元格的子类型只能为 "td"、"th" 或 "caption"!');
|
|
118
142
|
} else if (typeof inner === 'string') {
|
|
119
143
|
inner = Parser.parse(inner, include, undefined, config);
|
|
@@ -128,22 +152,22 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
128
152
|
}
|
|
129
153
|
|
|
130
154
|
/**
|
|
155
|
+
* @override
|
|
131
156
|
* @template {string} T
|
|
132
|
-
* @param {T} key
|
|
157
|
+
* @param {T} key 属性键
|
|
133
158
|
* @returns {TokenAttribute<T>}
|
|
134
159
|
*/
|
|
135
160
|
getAttribute(key) {
|
|
136
|
-
|
|
137
|
-
return this.#innerSyntax;
|
|
138
|
-
}
|
|
139
|
-
return super.getAttribute(key);
|
|
161
|
+
return key === 'innerSyntax' ? this.#innerSyntax : super.getAttribute(key);
|
|
140
162
|
}
|
|
141
163
|
|
|
142
164
|
/**
|
|
165
|
+
* @override
|
|
143
166
|
* @template {string} T
|
|
144
|
-
* @param {T} key
|
|
145
|
-
* @param {TokenAttribute<T>} value
|
|
146
|
-
* @
|
|
167
|
+
* @param {T} key 属性键
|
|
168
|
+
* @param {TokenAttribute<T>} value 属性值
|
|
169
|
+
* @returns {this}
|
|
170
|
+
* @throws `RangeError` 仅用于代码调试
|
|
147
171
|
*/
|
|
148
172
|
setAttribute(key, value) {
|
|
149
173
|
if (key !== 'innerSyntax') {
|
|
@@ -155,49 +179,66 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
155
179
|
return this;
|
|
156
180
|
}
|
|
157
181
|
|
|
182
|
+
/** @override */
|
|
158
183
|
afterBuild() {
|
|
159
184
|
if (this.#innerSyntax.includes('\0')) {
|
|
160
|
-
this.#innerSyntax = this.buildFromStr(this.#innerSyntax).map(String).join('');
|
|
185
|
+
this.#innerSyntax = this.getAttribute('buildFromStr')(this.#innerSyntax).map(String).join('');
|
|
161
186
|
}
|
|
162
187
|
return this;
|
|
163
188
|
}
|
|
164
189
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
190
|
+
/**
|
|
191
|
+
* @override
|
|
192
|
+
* @param {string} syntax 表格语法
|
|
193
|
+
* @param {boolean} esc 是否需要转义
|
|
194
|
+
*/
|
|
195
|
+
setSyntax(syntax, esc) {
|
|
196
|
+
super.setSyntax(aliases[syntax] ?? syntax, esc);
|
|
170
197
|
}
|
|
171
198
|
|
|
172
|
-
/**
|
|
199
|
+
/**
|
|
200
|
+
* 修复\<td\>语法
|
|
201
|
+
* @complexity `n`
|
|
202
|
+
*/
|
|
173
203
|
#correct() {
|
|
174
|
-
if (this.children[1]
|
|
204
|
+
if (String(this.children[1])) {
|
|
175
205
|
this.#innerSyntax ||= '|';
|
|
176
206
|
}
|
|
177
|
-
const {subtype, escape
|
|
207
|
+
const {subtype, escape, correction} = this.getSyntax();
|
|
178
208
|
if (correction) {
|
|
179
|
-
this.setSyntax(subtype,
|
|
209
|
+
this.setSyntax(subtype, escape);
|
|
180
210
|
}
|
|
181
211
|
}
|
|
182
212
|
|
|
183
|
-
/**
|
|
213
|
+
/**
|
|
214
|
+
* 改为独占一行
|
|
215
|
+
* @complexity `n`
|
|
216
|
+
*/
|
|
184
217
|
independence() {
|
|
185
218
|
if (!this.isIndependent()) {
|
|
186
|
-
const {subtype, escape
|
|
187
|
-
this.setSyntax(subtype,
|
|
219
|
+
const {subtype, escape} = this.getSyntax();
|
|
220
|
+
this.setSyntax(subtype, escape);
|
|
188
221
|
}
|
|
189
222
|
}
|
|
190
223
|
|
|
191
224
|
/**
|
|
225
|
+
* @override
|
|
226
|
+
* @param {string} selector
|
|
192
227
|
* @returns {string}
|
|
193
228
|
* @complexity `n`
|
|
194
229
|
*/
|
|
195
|
-
toString() {
|
|
230
|
+
toString(selector) {
|
|
196
231
|
this.#correct();
|
|
197
|
-
const [syntax, attr, inner] = this
|
|
198
|
-
return
|
|
232
|
+
const {children: [syntax, attr, inner]} = this;
|
|
233
|
+
return selector && this.matches(selector)
|
|
234
|
+
? ''
|
|
235
|
+
: `${syntax.toString(selector)}${attr.toString(selector)}${this.#innerSyntax}${inner.toString(selector)}`;
|
|
199
236
|
}
|
|
200
237
|
|
|
238
|
+
/**
|
|
239
|
+
* @override
|
|
240
|
+
* @param {number} i 子节点位置
|
|
241
|
+
*/
|
|
201
242
|
getGaps(i = 0) {
|
|
202
243
|
i = i < 0 ? i + this.childNodes.length : i;
|
|
203
244
|
if (i !== 1) {
|
|
@@ -208,49 +249,53 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
208
249
|
}
|
|
209
250
|
|
|
210
251
|
/**
|
|
252
|
+
* @override
|
|
211
253
|
* @returns {string}
|
|
212
254
|
* @complexity `n`
|
|
213
255
|
*/
|
|
214
256
|
text() {
|
|
215
257
|
this.#correct();
|
|
216
|
-
const [syntax, attr, inner] = this
|
|
258
|
+
const {children: [syntax, attr, inner]} = this;
|
|
217
259
|
return `${syntax.text()}${attr.text()}${this.#innerSyntax}${inner.text()}`;
|
|
218
260
|
}
|
|
219
261
|
|
|
220
262
|
/**
|
|
263
|
+
* 获取单元格属性
|
|
221
264
|
* @template {string} T
|
|
222
|
-
* @param {T} key
|
|
265
|
+
* @param {T} key 属性键
|
|
223
266
|
* @returns {T extends 'rowspan'|'colspan' ? number : Record<string, string|true>}
|
|
224
267
|
*/
|
|
225
268
|
getAttr(key) {
|
|
226
269
|
const /** @type {string|true} */ value = super.getAttr(key);
|
|
227
270
|
key = key?.toLowerCase()?.trim();
|
|
228
|
-
return
|
|
271
|
+
return key === 'rowspan' || key === 'colspan' ? Number(value) || 1 : value;
|
|
229
272
|
}
|
|
230
273
|
|
|
231
274
|
/**
|
|
275
|
+
* 设置单元格属性
|
|
232
276
|
* @template {string} T
|
|
233
|
-
* @param {T} key
|
|
234
|
-
* @param {T extends 'rowspan'|'colspan' ? number : string|boolean} value
|
|
277
|
+
* @param {T} key 属性键
|
|
278
|
+
* @param {T extends 'rowspan'|'colspan' ? number : string|boolean} value 属性值
|
|
235
279
|
*/
|
|
236
280
|
setAttr(key, value) {
|
|
237
281
|
if (typeof key !== 'string') {
|
|
238
282
|
this.typeError('setAttr', 'String');
|
|
239
283
|
}
|
|
240
284
|
key = key.toLowerCase().trim();
|
|
241
|
-
if (typeof value === 'number' &&
|
|
285
|
+
if (typeof value === 'number' && (key === 'rowspan' || key === 'colspan')) {
|
|
242
286
|
value = value === 1 ? false : String(value);
|
|
243
287
|
}
|
|
244
288
|
const /** @type {boolean} */ result = super.setAttr(key, value);
|
|
245
|
-
if (!this.children[1]
|
|
289
|
+
if (!String(this.children[1])) {
|
|
246
290
|
this.#innerSyntax = '';
|
|
247
291
|
}
|
|
248
292
|
return result;
|
|
249
293
|
}
|
|
250
294
|
|
|
295
|
+
/** @override */
|
|
251
296
|
escape() {
|
|
252
297
|
super.escape();
|
|
253
|
-
if (this.children[1]
|
|
298
|
+
if (String(this.children[1])) {
|
|
254
299
|
this.#innerSyntax ||= '{{!}}';
|
|
255
300
|
}
|
|
256
301
|
if (this.#innerSyntax === '|') {
|
package/src/table/tr.js
CHANGED
|
@@ -1,11 +1,30 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const attributeParent = require('../../mixin/attributeParent'),
|
|
4
|
-
|
|
4
|
+
Parser = require('../..'),
|
|
5
|
+
AstText = require('../../lib/text'),
|
|
5
6
|
Token = require('..'),
|
|
6
7
|
SyntaxToken = require('../syntax'),
|
|
7
8
|
AttributeToken = require('../attribute');
|
|
8
9
|
|
|
10
|
+
const openingPattern = /^\n[^\S\n]*(?:\|-+|\{\{\s*!\s*\}\}-+|\{\{\s*!-\s*\}\}-*)$/u;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 转义表格语法
|
|
14
|
+
* @param {SyntaxToken} syntax 表格语法节点
|
|
15
|
+
*/
|
|
16
|
+
const escapeTable = syntax => {
|
|
17
|
+
const wikitext = syntax.childNodes.map(
|
|
18
|
+
child => child.type === 'text'
|
|
19
|
+
? String(child).replaceAll('{|', '{{(!}}').replaceAll('|}', '{{!)}}')
|
|
20
|
+
.replaceAll('||', '{{!!}}')
|
|
21
|
+
.replaceAll('|', '{{!}}')
|
|
22
|
+
: String(child),
|
|
23
|
+
).join(''),
|
|
24
|
+
token = Parser.parse(wikitext, syntax.getAttribute('include'), 2, syntax.getAttribute('config'));
|
|
25
|
+
syntax.replaceChildren(...token.childNodes);
|
|
26
|
+
};
|
|
27
|
+
|
|
9
28
|
/**
|
|
10
29
|
* 表格行,含开头的换行,不含结尾的换行
|
|
11
30
|
* @classdesc `{childNodes: [SyntaxToken, AttributeToken, ?Token, ...TdToken]}`
|
|
@@ -13,13 +32,13 @@ const attributeParent = require('../../mixin/attributeParent'),
|
|
|
13
32
|
class TrToken extends attributeParent(Token, 1) {
|
|
14
33
|
type = 'tr';
|
|
15
34
|
|
|
16
|
-
static openingPattern = /^\n[^\S\n]*(?:\|-+|\{\{\s*!\s*\}\}-+|\{\{\s*!-\s*\}\}-*)$/;
|
|
17
|
-
|
|
18
35
|
/**
|
|
19
|
-
* @param {string} syntax
|
|
36
|
+
* @param {string} syntax 表格语法
|
|
37
|
+
* @param {string} attr 表格属性
|
|
20
38
|
* @param {accum} accum
|
|
39
|
+
* @param {RegExp} pattern 表格语法正则
|
|
21
40
|
*/
|
|
22
|
-
constructor(syntax, attr = '', config = Parser.getConfig(), accum = [], pattern =
|
|
41
|
+
constructor(syntax, attr = '', config = Parser.getConfig(), accum = [], pattern = openingPattern) {
|
|
23
42
|
super(undefined, config, true, accum, {Token: 2, SyntaxToken: 0, AttributeToken: 1, TdToken: '2:'});
|
|
24
43
|
this.append(
|
|
25
44
|
new SyntaxToken(syntax, pattern, 'table-syntax', config, accum, {
|
|
@@ -27,14 +46,17 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
27
46
|
}),
|
|
28
47
|
new AttributeToken(attr, 'table-attr', 'tr', config, accum),
|
|
29
48
|
);
|
|
30
|
-
this.protectChildren(0, 1);
|
|
49
|
+
this.getAttribute('protectChildren')(0, 1);
|
|
31
50
|
}
|
|
32
51
|
|
|
52
|
+
/**
|
|
53
|
+
* @override
|
|
54
|
+
* @this {TrToken & {constructor: typeof TrToken}}
|
|
55
|
+
*/
|
|
33
56
|
cloneNode() {
|
|
34
|
-
const [syntax, attr, inner, ...cloned] = this.
|
|
35
|
-
/** @type {typeof TrToken} */ Constructor = this.constructor;
|
|
57
|
+
const [syntax, attr, inner, ...cloned] = this.cloneChildNodes();
|
|
36
58
|
return Parser.run(() => {
|
|
37
|
-
const token = new
|
|
59
|
+
const token = new this.constructor(undefined, undefined, this.getAttribute('config'));
|
|
38
60
|
token.firstElementChild.safeReplaceWith(syntax);
|
|
39
61
|
token.children[1].safeReplaceWith(attr);
|
|
40
62
|
if (token.type === 'td') { // TdToken
|
|
@@ -47,67 +69,70 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
47
69
|
});
|
|
48
70
|
}
|
|
49
71
|
|
|
72
|
+
/** 修复简单的表格语法错误 */
|
|
50
73
|
#correct() {
|
|
51
|
-
const [,, child] = this
|
|
74
|
+
const {children: [,, child]} = this;
|
|
52
75
|
if (child?.isPlain()) {
|
|
53
|
-
const {firstChild} = child;
|
|
54
|
-
if (
|
|
76
|
+
const /** @type {{firstChild: AstText}} */ {firstChild: {type, data}} = child;
|
|
77
|
+
if (type !== 'text') {
|
|
55
78
|
child.prepend('\n');
|
|
56
|
-
} else if (
|
|
57
|
-
child.setText(`\n${
|
|
79
|
+
} else if (data[0] !== '\n') {
|
|
80
|
+
child.setText(`\n${data}`);
|
|
58
81
|
}
|
|
59
82
|
}
|
|
60
83
|
}
|
|
61
84
|
|
|
62
|
-
|
|
85
|
+
/**
|
|
86
|
+
* @override
|
|
87
|
+
* @param {string} selector
|
|
88
|
+
*/
|
|
89
|
+
toString(selector) {
|
|
63
90
|
this.#correct();
|
|
64
|
-
return super.toString();
|
|
91
|
+
return super.toString(selector);
|
|
65
92
|
}
|
|
66
93
|
|
|
94
|
+
/** @override */
|
|
67
95
|
text() {
|
|
68
96
|
this.#correct();
|
|
69
97
|
const str = super.text();
|
|
70
98
|
return this.type === 'tr' && !str.trim().includes('\n') ? '' : str;
|
|
71
99
|
}
|
|
72
100
|
|
|
73
|
-
/**
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
.replaceAll('|', '{{!}}')
|
|
78
|
-
: child.toString(),
|
|
79
|
-
).join(''),
|
|
80
|
-
token = Parser.parse(wikitext, syntax.getAttribute('include'), 2, syntax.getAttribute('config'));
|
|
81
|
-
syntax.replaceChildren(...token.childNodes);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/** @complexity `n` */
|
|
101
|
+
/**
|
|
102
|
+
* 转义表格语法
|
|
103
|
+
* @complexity `n`
|
|
104
|
+
*/
|
|
85
105
|
escape() {
|
|
86
106
|
for (const child of this.children) {
|
|
87
107
|
if (child instanceof SyntaxToken) {
|
|
88
|
-
|
|
108
|
+
escapeTable(child);
|
|
89
109
|
} else if (child instanceof TrToken) {
|
|
90
110
|
child.escape();
|
|
91
111
|
}
|
|
92
112
|
}
|
|
93
113
|
}
|
|
94
114
|
|
|
95
|
-
/**
|
|
96
|
-
|
|
115
|
+
/**
|
|
116
|
+
* 设置表格语法
|
|
117
|
+
* @param {string} syntax 表格语法
|
|
118
|
+
* @param {boolean} esc 是否需要转义
|
|
119
|
+
*/
|
|
120
|
+
setSyntax(syntax, esc) {
|
|
97
121
|
const {firstElementChild} = this;
|
|
98
122
|
firstElementChild.replaceChildren(syntax);
|
|
99
123
|
if (esc) {
|
|
100
|
-
|
|
124
|
+
escapeTable(firstElementChild);
|
|
101
125
|
}
|
|
102
126
|
}
|
|
103
127
|
|
|
104
128
|
/**
|
|
105
|
-
* @
|
|
129
|
+
* @override
|
|
130
|
+
* @param {number} i 移除位置
|
|
106
131
|
* @complexity `n`
|
|
107
132
|
*/
|
|
108
133
|
removeAt(i) {
|
|
109
|
-
const TdToken = require('./td')
|
|
110
|
-
|
|
134
|
+
const TdToken = require('./td');
|
|
135
|
+
const child = this.childNodes.at(i);
|
|
111
136
|
if (child instanceof TdToken && child.isIndependent()) {
|
|
112
137
|
const {nextElementSibling} = child;
|
|
113
138
|
if (nextElementSibling?.type === 'td') {
|
|
@@ -118,8 +143,10 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
118
143
|
}
|
|
119
144
|
|
|
120
145
|
/**
|
|
121
|
-
* @
|
|
122
|
-
* @
|
|
146
|
+
* @override
|
|
147
|
+
* @template {AstText|Token} T
|
|
148
|
+
* @param {T} token 待插入的子节点
|
|
149
|
+
* @param {number} i 插入位置
|
|
123
150
|
* @returns {T}
|
|
124
151
|
* @complexity `n`
|
|
125
152
|
*/
|
|
@@ -127,8 +154,8 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
127
154
|
if (!Parser.running && !(token instanceof TrToken)) {
|
|
128
155
|
this.typeError('insertAt', 'TrToken');
|
|
129
156
|
}
|
|
130
|
-
const TdToken = require('./td')
|
|
131
|
-
|
|
157
|
+
const TdToken = require('./td');
|
|
158
|
+
const child = this.childNodes.at(i);
|
|
132
159
|
if (token instanceof TdToken && token.isIndependent() && child instanceof TdToken) {
|
|
133
160
|
child.independence();
|
|
134
161
|
}
|
|
@@ -136,45 +163,57 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
136
163
|
}
|
|
137
164
|
|
|
138
165
|
/**
|
|
166
|
+
* 获取行数
|
|
139
167
|
* @returns {0|1}
|
|
140
168
|
* @complexity `n`
|
|
141
169
|
*/
|
|
142
170
|
getRowCount() {
|
|
143
171
|
const TdToken = require('./td');
|
|
144
|
-
return Number(this.children.some(
|
|
145
|
-
child instanceof TdToken && child.isIndependent() &&
|
|
172
|
+
return Number(this.children.some(
|
|
173
|
+
child => child instanceof TdToken && child.isIndependent() && child.firstElementChild.text().at(-1) !== '+',
|
|
146
174
|
));
|
|
147
175
|
}
|
|
148
176
|
|
|
149
177
|
/**
|
|
150
|
-
*
|
|
178
|
+
* 获取相邻行
|
|
179
|
+
* @param {(children: Token[], index: number) => Token[]} subset 筛选兄弟节点的方法
|
|
151
180
|
* @complexity `n`
|
|
152
181
|
*/
|
|
153
182
|
#getSiblingRow(subset) {
|
|
154
|
-
const {
|
|
155
|
-
if (!
|
|
156
|
-
return;
|
|
183
|
+
const {parentNode} = this;
|
|
184
|
+
if (!parentNode) {
|
|
185
|
+
return undefined;
|
|
157
186
|
}
|
|
158
|
-
const {children} =
|
|
187
|
+
const {children} = parentNode,
|
|
159
188
|
index = children.indexOf(this);
|
|
160
189
|
for (const child of subset(children, index)) {
|
|
161
190
|
if (child instanceof TrToken && child.getRowCount()) {
|
|
162
191
|
return child;
|
|
163
192
|
}
|
|
164
193
|
}
|
|
194
|
+
return undefined;
|
|
165
195
|
}
|
|
166
196
|
|
|
167
|
-
/**
|
|
197
|
+
/**
|
|
198
|
+
* 获取下一行
|
|
199
|
+
* @complexity `n`
|
|
200
|
+
*/
|
|
168
201
|
getNextRow() {
|
|
169
202
|
return this.#getSiblingRow((children, index) => children.slice(index + 1));
|
|
170
203
|
}
|
|
171
204
|
|
|
172
|
-
/**
|
|
205
|
+
/**
|
|
206
|
+
* 获取前一行
|
|
207
|
+
* @complexity `n`
|
|
208
|
+
*/
|
|
173
209
|
getPreviousRow() {
|
|
174
210
|
return this.#getSiblingRow((children, index) => children.slice(0, index).reverse());
|
|
175
211
|
}
|
|
176
212
|
|
|
177
|
-
/**
|
|
213
|
+
/**
|
|
214
|
+
* 获取列数
|
|
215
|
+
* @complexity `n`
|
|
216
|
+
*/
|
|
178
217
|
getColCount() {
|
|
179
218
|
const TdToken = require('./td');
|
|
180
219
|
let count = 0,
|
|
@@ -189,11 +228,14 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
189
228
|
}
|
|
190
229
|
|
|
191
230
|
/**
|
|
192
|
-
*
|
|
231
|
+
* 获取第n列
|
|
232
|
+
* @param {number} n 列号
|
|
233
|
+
* @param {boolean} insert 是否用于判断插入新列的位置
|
|
193
234
|
* @returns {TdToken}
|
|
194
235
|
* @complexity `n`
|
|
236
|
+
* @throws `RangeError` 不存在对应单元格
|
|
195
237
|
*/
|
|
196
|
-
getNthCol(n, insert
|
|
238
|
+
getNthCol(n, insert) {
|
|
197
239
|
if (typeof n !== 'number') {
|
|
198
240
|
this.typeError('getNthCol', 'Number');
|
|
199
241
|
}
|
|
@@ -213,23 +255,25 @@ class TrToken extends attributeParent(Token, 1) {
|
|
|
213
255
|
if (n < 0) {
|
|
214
256
|
return child;
|
|
215
257
|
}
|
|
216
|
-
} else if (
|
|
258
|
+
} else if (child.type === 'tr' || child.type === 'table-syntax') {
|
|
217
259
|
return child;
|
|
218
260
|
}
|
|
219
261
|
}
|
|
262
|
+
return undefined;
|
|
220
263
|
}
|
|
221
264
|
|
|
222
265
|
/**
|
|
223
|
-
*
|
|
224
|
-
* @param {
|
|
225
|
-
* @param {
|
|
226
|
-
* @param {
|
|
266
|
+
* 插入新的单元格
|
|
267
|
+
* @param {string|Token} inner 单元格内部wikitext
|
|
268
|
+
* @param {TableCoords} coord 单元格坐标
|
|
269
|
+
* @param {'td'|'th'|'caption'} subtype 单元格类型
|
|
270
|
+
* @param {Record<string, string|boolean>} attr 单元格属性
|
|
227
271
|
* @returns {TdToken}
|
|
228
272
|
* @complexity `n`
|
|
229
273
|
*/
|
|
230
274
|
insertTableCell(inner, {column}, subtype = 'td', attr = {}) {
|
|
231
|
-
const TdToken = require('./td')
|
|
232
|
-
|
|
275
|
+
const TdToken = require('./td');
|
|
276
|
+
const token = TdToken.create(inner, subtype, attr, this.getAttribute('include'), this.getAttribute('config'));
|
|
233
277
|
return this.insertBefore(token, this.getNthCol(column, true));
|
|
234
278
|
}
|
|
235
279
|
}
|