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/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,25 +91,23 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
69
91
|
return result;
|
|
70
92
|
}
|
|
71
93
|
|
|
72
|
-
static openingPattern = /^(?:\n[\S\n]*(?:[|!]|\|\+|{{\s*!\s*}}\+?)|(?:\||{{\s*!\s*}}){2}|!!|{{\s*!!\s*}})$/;
|
|
73
|
-
|
|
74
94
|
getRowCount = undefined;
|
|
75
95
|
getNthCol = undefined;
|
|
76
96
|
insertTableCell = undefined;
|
|
77
97
|
|
|
78
98
|
/**
|
|
79
|
-
* @param {string} syntax
|
|
80
|
-
* @param {string} inner
|
|
99
|
+
* @param {string} syntax 单元格语法
|
|
100
|
+
* @param {string} inner 内部wikitext
|
|
81
101
|
* @param {accum} accum
|
|
82
102
|
*/
|
|
83
103
|
constructor(syntax, inner, config = Parser.getConfig(), accum = []) {
|
|
84
|
-
let innerSyntax = inner?.match(/\||\
|
|
104
|
+
let innerSyntax = inner?.match(/\||\0\d+!\x7F/u),
|
|
85
105
|
attr = innerSyntax ? inner.slice(0, innerSyntax.index) : '';
|
|
86
|
-
if (/\[\[
|
|
106
|
+
if (/\[\[|-\{/u.test(attr)) {
|
|
87
107
|
innerSyntax = null;
|
|
88
108
|
attr = '';
|
|
89
109
|
}
|
|
90
|
-
super(syntax, attr, config, accum,
|
|
110
|
+
super(syntax, attr, config, accum, openingPattern);
|
|
91
111
|
if (innerSyntax) {
|
|
92
112
|
[this.#innerSyntax] = innerSyntax;
|
|
93
113
|
}
|
|
@@ -95,9 +115,11 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
95
115
|
const innerToken = new Token(inner?.slice(innerSyntax?.index + this.#innerSyntax.length), config, true, accum);
|
|
96
116
|
innerToken.type = 'td-inner';
|
|
97
117
|
this.setAttribute('acceptable', {SyntaxToken: 0, AttributeToken: 1, Token: 2})
|
|
98
|
-
.seal(['getRowCount', 'getNthCol', 'insertTableCell']
|
|
118
|
+
.seal(['getRowCount', 'getNthCol', 'insertTableCell'], true)
|
|
119
|
+
.appendChild(innerToken.setAttribute('stage', 4));
|
|
99
120
|
}
|
|
100
121
|
|
|
122
|
+
/** @override */
|
|
101
123
|
cloneNode() {
|
|
102
124
|
const /** @type {TdToken} */ token = super.cloneNode();
|
|
103
125
|
token.setAttribute('innerSyntax', this.#innerSyntax);
|
|
@@ -105,14 +127,17 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
105
127
|
}
|
|
106
128
|
|
|
107
129
|
/**
|
|
108
|
-
*
|
|
109
|
-
* @param {
|
|
110
|
-
* @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` 非法的单元格类型
|
|
111
136
|
*/
|
|
112
137
|
static create(inner, subtype = 'td', attr = {}, include = false, config = Parser.getConfig()) {
|
|
113
138
|
if (typeof inner !== 'string' && (!(inner instanceof Token) || !inner.isPlain()) || typeof attr !== 'object') {
|
|
114
139
|
typeError(this, 'create', 'String', 'Token', 'Object');
|
|
115
|
-
} else if (
|
|
140
|
+
} else if (subtype !== 'td' && subtype !== 'th' && subtype !== 'caption') {
|
|
116
141
|
throw new RangeError('单元格的子类型只能为 "td"、"th" 或 "caption"!');
|
|
117
142
|
} else if (typeof inner === 'string') {
|
|
118
143
|
inner = Parser.parse(inner, include, undefined, config);
|
|
@@ -127,22 +152,22 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
127
152
|
}
|
|
128
153
|
|
|
129
154
|
/**
|
|
155
|
+
* @override
|
|
130
156
|
* @template {string} T
|
|
131
|
-
* @param {T} key
|
|
157
|
+
* @param {T} key 属性键
|
|
132
158
|
* @returns {TokenAttribute<T>}
|
|
133
159
|
*/
|
|
134
160
|
getAttribute(key) {
|
|
135
|
-
|
|
136
|
-
return this.#innerSyntax;
|
|
137
|
-
}
|
|
138
|
-
return super.getAttribute(key);
|
|
161
|
+
return key === 'innerSyntax' ? this.#innerSyntax : super.getAttribute(key);
|
|
139
162
|
}
|
|
140
163
|
|
|
141
164
|
/**
|
|
165
|
+
* @override
|
|
142
166
|
* @template {string} T
|
|
143
|
-
* @param {T} key
|
|
144
|
-
* @param {TokenAttribute<T>} value
|
|
145
|
-
* @
|
|
167
|
+
* @param {T} key 属性键
|
|
168
|
+
* @param {TokenAttribute<T>} value 属性值
|
|
169
|
+
* @returns {this}
|
|
170
|
+
* @throws `RangeError` 仅用于代码调试
|
|
146
171
|
*/
|
|
147
172
|
setAttribute(key, value) {
|
|
148
173
|
if (key !== 'innerSyntax') {
|
|
@@ -154,49 +179,66 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
154
179
|
return this;
|
|
155
180
|
}
|
|
156
181
|
|
|
182
|
+
/** @override */
|
|
157
183
|
afterBuild() {
|
|
158
|
-
if (this.#innerSyntax.includes('\
|
|
159
|
-
this.#innerSyntax = this.buildFromStr(this.#innerSyntax).map(String).join('');
|
|
184
|
+
if (this.#innerSyntax.includes('\0')) {
|
|
185
|
+
this.#innerSyntax = this.getAttribute('buildFromStr')(this.#innerSyntax).map(String).join('');
|
|
160
186
|
}
|
|
161
187
|
return this;
|
|
162
188
|
}
|
|
163
189
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
190
|
+
/**
|
|
191
|
+
* @override
|
|
192
|
+
* @param {string} syntax 表格语法
|
|
193
|
+
* @param {boolean} esc 是否需要转义
|
|
194
|
+
*/
|
|
195
|
+
setSyntax(syntax, esc) {
|
|
196
|
+
super.setSyntax(aliases[syntax] ?? syntax, esc);
|
|
169
197
|
}
|
|
170
198
|
|
|
171
|
-
/**
|
|
199
|
+
/**
|
|
200
|
+
* 修复\<td\>语法
|
|
201
|
+
* @complexity `n`
|
|
202
|
+
*/
|
|
172
203
|
#correct() {
|
|
173
|
-
if (this.children[1]
|
|
204
|
+
if (String(this.children[1])) {
|
|
174
205
|
this.#innerSyntax ||= '|';
|
|
175
206
|
}
|
|
176
|
-
const {subtype, escape
|
|
207
|
+
const {subtype, escape, correction} = this.getSyntax();
|
|
177
208
|
if (correction) {
|
|
178
|
-
this.setSyntax(subtype,
|
|
209
|
+
this.setSyntax(subtype, escape);
|
|
179
210
|
}
|
|
180
211
|
}
|
|
181
212
|
|
|
182
|
-
/**
|
|
213
|
+
/**
|
|
214
|
+
* 改为独占一行
|
|
215
|
+
* @complexity `n`
|
|
216
|
+
*/
|
|
183
217
|
independence() {
|
|
184
218
|
if (!this.isIndependent()) {
|
|
185
|
-
const {subtype, escape
|
|
186
|
-
this.setSyntax(subtype,
|
|
219
|
+
const {subtype, escape} = this.getSyntax();
|
|
220
|
+
this.setSyntax(subtype, escape);
|
|
187
221
|
}
|
|
188
222
|
}
|
|
189
223
|
|
|
190
224
|
/**
|
|
225
|
+
* @override
|
|
226
|
+
* @param {string} selector
|
|
191
227
|
* @returns {string}
|
|
192
228
|
* @complexity `n`
|
|
193
229
|
*/
|
|
194
|
-
toString() {
|
|
230
|
+
toString(selector) {
|
|
195
231
|
this.#correct();
|
|
196
|
-
const [syntax, attr, inner] = this
|
|
197
|
-
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)}`;
|
|
198
236
|
}
|
|
199
237
|
|
|
238
|
+
/**
|
|
239
|
+
* @override
|
|
240
|
+
* @param {number} i 子节点位置
|
|
241
|
+
*/
|
|
200
242
|
getGaps(i = 0) {
|
|
201
243
|
i = i < 0 ? i + this.childNodes.length : i;
|
|
202
244
|
if (i !== 1) {
|
|
@@ -207,49 +249,53 @@ class TdToken extends fixedToken(TrToken) {
|
|
|
207
249
|
}
|
|
208
250
|
|
|
209
251
|
/**
|
|
252
|
+
* @override
|
|
210
253
|
* @returns {string}
|
|
211
254
|
* @complexity `n`
|
|
212
255
|
*/
|
|
213
256
|
text() {
|
|
214
257
|
this.#correct();
|
|
215
|
-
const [syntax, attr, inner] = this
|
|
258
|
+
const {children: [syntax, attr, inner]} = this;
|
|
216
259
|
return `${syntax.text()}${attr.text()}${this.#innerSyntax}${inner.text()}`;
|
|
217
260
|
}
|
|
218
261
|
|
|
219
262
|
/**
|
|
263
|
+
* 获取单元格属性
|
|
220
264
|
* @template {string} T
|
|
221
|
-
* @param {T} key
|
|
265
|
+
* @param {T} key 属性键
|
|
222
266
|
* @returns {T extends 'rowspan'|'colspan' ? number : Record<string, string|true>}
|
|
223
267
|
*/
|
|
224
268
|
getAttr(key) {
|
|
225
269
|
const /** @type {string|true} */ value = super.getAttr(key);
|
|
226
270
|
key = key?.toLowerCase()?.trim();
|
|
227
|
-
return
|
|
271
|
+
return key === 'rowspan' || key === 'colspan' ? Number(value) || 1 : value;
|
|
228
272
|
}
|
|
229
273
|
|
|
230
274
|
/**
|
|
275
|
+
* 设置单元格属性
|
|
231
276
|
* @template {string} T
|
|
232
|
-
* @param {T} key
|
|
233
|
-
* @param {T extends 'rowspan'|'colspan' ? number : string|boolean} value
|
|
277
|
+
* @param {T} key 属性键
|
|
278
|
+
* @param {T extends 'rowspan'|'colspan' ? number : string|boolean} value 属性值
|
|
234
279
|
*/
|
|
235
280
|
setAttr(key, value) {
|
|
236
281
|
if (typeof key !== 'string') {
|
|
237
282
|
this.typeError('setAttr', 'String');
|
|
238
283
|
}
|
|
239
284
|
key = key.toLowerCase().trim();
|
|
240
|
-
if (typeof value === 'number' &&
|
|
285
|
+
if (typeof value === 'number' && (key === 'rowspan' || key === 'colspan')) {
|
|
241
286
|
value = value === 1 ? false : String(value);
|
|
242
287
|
}
|
|
243
288
|
const /** @type {boolean} */ result = super.setAttr(key, value);
|
|
244
|
-
if (!this.children[1]
|
|
289
|
+
if (!String(this.children[1])) {
|
|
245
290
|
this.#innerSyntax = '';
|
|
246
291
|
}
|
|
247
292
|
return result;
|
|
248
293
|
}
|
|
249
294
|
|
|
295
|
+
/** @override */
|
|
250
296
|
escape() {
|
|
251
297
|
super.escape();
|
|
252
|
-
if (this.children[1]
|
|
298
|
+
if (String(this.children[1])) {
|
|
253
299
|
this.#innerSyntax ||= '{{!}}';
|
|
254
300
|
}
|
|
255
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
|
}
|