wikiparser-node 0.0.3 → 0.2.1
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 +29 -1931
- package/config/default.json +12 -1
- package/config/llwiki.json +12 -1
- package/config/moegirl.json +9 -1
- package/errors/2022-07-04T22:30:41.785Z +1 -0
- package/errors/2022-07-04T22:30:41.785Z.err +11 -0
- package/errors/2022-07-04T22:30:41.785Z.json +5 -0
- package/index.js +43 -0
- package/lib/element.js +2 -1
- package/mixin/sol.js +42 -0
- package/package.json +2 -2
- package/parser/converter.js +44 -0
- package/parser/list.js +58 -0
- package/src/arg.js +6 -6
- package/src/attribute.js +27 -17
- package/src/converter.js +135 -0
- package/src/converterFlags.js +214 -0
- package/src/converterRule.js +209 -0
- package/src/extLink.js +21 -9
- package/src/heading.js +13 -17
- package/src/imageParameter.js +1 -1
- package/src/index.js +33 -18
- package/src/link/file.js +2 -2
- package/src/link/index.js +7 -7
- package/src/nowiki/dd.js +49 -0
- package/src/nowiki/hr.js +3 -2
- package/src/nowiki/list.js +16 -0
- package/src/parameter.js +2 -2
- package/src/syntax.js +3 -1
- package/src/table/index.js +9 -9
- package/src/table/td.js +1 -0
- package/src/table/tr.js +4 -6
- package/src/transclude.js +14 -14
- package/typings/index.d.ts +2 -0
- package/typings/node.d.ts +3 -3
- package/typings/token.d.ts +1 -0
- package/util/string.js +13 -1
- package/src/listToken.js +0 -47
package/config/default.json
CHANGED
|
@@ -763,5 +763,16 @@
|
|
|
763
763
|
"底部": "bottom",
|
|
764
764
|
"text-bottom": "text-bottom",
|
|
765
765
|
"文字底部": "text-bottom"
|
|
766
|
-
}
|
|
766
|
+
},
|
|
767
|
+
"variants": [
|
|
768
|
+
"zh",
|
|
769
|
+
"zh-hans",
|
|
770
|
+
"zh-hant",
|
|
771
|
+
"zh-cn",
|
|
772
|
+
"zh-tw",
|
|
773
|
+
"zh-hk",
|
|
774
|
+
"zh-sg",
|
|
775
|
+
"zh-my",
|
|
776
|
+
"zh-mo"
|
|
777
|
+
]
|
|
767
778
|
}
|
package/config/llwiki.json
CHANGED
|
@@ -683,5 +683,16 @@
|
|
|
683
683
|
"底部": "bottom",
|
|
684
684
|
"text-bottom": "text-bottom",
|
|
685
685
|
"文字底部": "text-bottom"
|
|
686
|
-
}
|
|
686
|
+
},
|
|
687
|
+
"variants": [
|
|
688
|
+
"zh",
|
|
689
|
+
"zh-hans",
|
|
690
|
+
"zh-hant",
|
|
691
|
+
"zh-cn",
|
|
692
|
+
"zh-tw",
|
|
693
|
+
"zh-hk",
|
|
694
|
+
"zh-sg",
|
|
695
|
+
"zh-my",
|
|
696
|
+
"zh-mo"
|
|
697
|
+
]
|
|
687
698
|
}
|
package/config/moegirl.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
TypeError: normalizeSpace is not a function
|
|
2
|
+
at AttributeToken.toString (/Users/mengxiwu/Documents/CCM-RP/node/wikiparser-node/src/attribute.js:249:44)
|
|
3
|
+
at #parseAttr (/Users/mengxiwu/Documents/CCM-RP/node/wikiparser-node/src/attribute.js:58:21)
|
|
4
|
+
at new AttributeToken (/Users/mengxiwu/Documents/CCM-RP/node/wikiparser-node/src/attribute.js:87:45)
|
|
5
|
+
at new TrToken (/Users/mengxiwu/Documents/CCM-RP/node/wikiparser-node/src/table/tr.js:28:4)
|
|
6
|
+
at new TableToken (/Users/mengxiwu/Documents/CCM-RP/node/wikiparser-node/src/table/index.js:66:3)
|
|
7
|
+
at parseTable (/Users/mengxiwu/Documents/CCM-RP/node/wikiparser-node/parser/table.js:40:18)
|
|
8
|
+
at #parseTable (/Users/mengxiwu/Documents/CCM-RP/node/wikiparser-node/src/index.js:553:16)
|
|
9
|
+
at Token.parseOnce (/Users/mengxiwu/Documents/CCM-RP/node/wikiparser-node/src/index.js:431:21)
|
|
10
|
+
at Token.parse (/Users/mengxiwu/Documents/CCM-RP/node/wikiparser-node/src/index.js:526:9)
|
|
11
|
+
at /Users/mengxiwu/Documents/CCM-RP/node/wikiparser-node/index.js:134:11
|
package/index.js
CHANGED
|
@@ -76,6 +76,8 @@ const /** @type {Parser} */ Parser = {
|
|
|
76
76
|
['QuoteToken'],
|
|
77
77
|
['ExtLinkToken'],
|
|
78
78
|
['MagicLinkToken'],
|
|
79
|
+
['ListToken', 'DdToken'],
|
|
80
|
+
['ConverterToken'],
|
|
79
81
|
],
|
|
80
82
|
|
|
81
83
|
config: './config/default',
|
|
@@ -177,6 +179,47 @@ const /** @type {Parser} */ Parser = {
|
|
|
177
179
|
delete require.cache[require.resolve('./tool')];
|
|
178
180
|
return require('./tool');
|
|
179
181
|
},
|
|
182
|
+
|
|
183
|
+
typeAliases: {
|
|
184
|
+
ext: ['extension'],
|
|
185
|
+
'ext-inner': ['extension-inner'],
|
|
186
|
+
arg: ['argument'],
|
|
187
|
+
'arg-name': ['argument-name'],
|
|
188
|
+
'arg-default': ['argument-default'],
|
|
189
|
+
'arg-redundant': ['argument-redundant'],
|
|
190
|
+
template: ['tpl'],
|
|
191
|
+
'template-name': ['tpl-name'],
|
|
192
|
+
'magic-word': ['parser-function', 'parser-func'],
|
|
193
|
+
'invoke-function': ['invoke-func'],
|
|
194
|
+
'invoke-module': ['invoke-mod'],
|
|
195
|
+
parameter: ['param'],
|
|
196
|
+
'parameter-key': ['param-key'],
|
|
197
|
+
'parameter-value': ['parameter-val', 'param-value', 'param-val'],
|
|
198
|
+
heading: ['header'],
|
|
199
|
+
'heading-title': ['header-title'],
|
|
200
|
+
table: ['tbl'],
|
|
201
|
+
'table-inter': ['tbl-inter'],
|
|
202
|
+
tr: ['table-row', 'tbl-row'],
|
|
203
|
+
td: ['table-cell', 'tbl-cell', 'table-data', 'tbl-data'],
|
|
204
|
+
'double-underscore': ['underscore', 'behavior-switch', 'behaviour-switch'],
|
|
205
|
+
hr: ['horizontal'],
|
|
206
|
+
category: ['category-link', 'cat', 'cat-link'],
|
|
207
|
+
file: ['file-link', 'image', 'image-link', 'img', 'img-link'],
|
|
208
|
+
'image-parameter': ['img-parameter', 'image-param', 'img-param'],
|
|
209
|
+
quote: ['quotes', 'quot', 'apostrophe', 'apostrophes', 'apos'],
|
|
210
|
+
'ext-link': ['external-link'],
|
|
211
|
+
'ext-link-text': ['external-link-text'],
|
|
212
|
+
'ext-link-url': ['external-link-url'],
|
|
213
|
+
'free-ext-link': ['free-external-link', 'magic-link'],
|
|
214
|
+
dd: ['indent', 'indentation'],
|
|
215
|
+
converter: ['convert', 'conversion'],
|
|
216
|
+
'converter-flags': ['convert-flags', 'conversion-flags', 'converter-flag', 'convert-flag', 'conversion-flag'],
|
|
217
|
+
'converter-rule': ['convert-rule', 'conversion-rule'],
|
|
218
|
+
'converter-rule-noconvert': ['convert-rule-noconvert', 'conversion-rule-noconvert'],
|
|
219
|
+
'converter-rule-variant': ['convert-rule-variant', 'conversion-rule-variant'],
|
|
220
|
+
'converter-rule-to': ['convert-rule-to', 'conversion-rule-to'],
|
|
221
|
+
'converter-rule-from': ['convert-rule-from', 'conversion-rule-from'],
|
|
222
|
+
},
|
|
180
223
|
};
|
|
181
224
|
|
|
182
225
|
const /** @type {PropertyDescriptorMap} */ def = {};
|
package/lib/element.js
CHANGED
|
@@ -402,7 +402,8 @@ class AstElement extends AstNode {
|
|
|
402
402
|
),
|
|
403
403
|
[type, ...parts] = plainSelector.trim().split('#'),
|
|
404
404
|
name = parts.join('#');
|
|
405
|
-
return (!type || this.type === type
|
|
405
|
+
return (!type || this.type === type || Boolean(Parser.typeAliases[this.type]?.includes(type)))
|
|
406
|
+
&& (!name || this.name === name)
|
|
406
407
|
&& attributes.every(args => this.matchesAttr(...args));
|
|
407
408
|
}
|
|
408
409
|
/*
|
package/mixin/sol.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const /** @type {Parser} */ Parser = require('..'),
|
|
4
|
+
Token = require('../src'); // eslint-disable-line no-unused-vars
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @template T
|
|
8
|
+
* @param {T} constructor
|
|
9
|
+
* @returns {T}
|
|
10
|
+
*/
|
|
11
|
+
const sol = constructor => class extends constructor {
|
|
12
|
+
/** @this {Token} */
|
|
13
|
+
prependNewLine() {
|
|
14
|
+
const {previousVisibleSibling = '', parentNode} = this;
|
|
15
|
+
return (previousVisibleSibling || parentNode?.type !== 'root') && !String(previousVisibleSibling).endsWith('\n')
|
|
16
|
+
? '\n'
|
|
17
|
+
: '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** @this {Token} */
|
|
21
|
+
appendNewLine() {
|
|
22
|
+
const {nextVisibleSibling = '', parentNode} = this;
|
|
23
|
+
return (nextVisibleSibling || parentNode?.type !== 'root') && !String(nextVisibleSibling ?? '').startsWith('\n')
|
|
24
|
+
? '\n'
|
|
25
|
+
: '';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
toString(ownLine = false) {
|
|
29
|
+
return `${this.prependNewLine()}${super.toString()}${ownLine ? this.appendNewLine() : ''}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getPadding() {
|
|
33
|
+
return this.prependNewLine().length;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
text(ownLine = false) {
|
|
37
|
+
return `${this.prependNewLine()}${super.text()}${ownLine ? this.appendNewLine() : ''}`;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
Parser.mixins.sol = __filename;
|
|
42
|
+
module.exports = sol;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wikiparser-node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "A Node.js parser for MediaWiki markup with AST",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mediawiki",
|
|
7
7
|
"wikitext",
|
|
8
8
|
"parser"
|
|
9
9
|
],
|
|
10
|
-
"homepage": "https://github.com/bhsd-harry/wikiparser-node
|
|
10
|
+
"homepage": "https://github.com/bhsd-harry/wikiparser-node/wiki",
|
|
11
11
|
"bugs": {
|
|
12
12
|
"url": "https://github.com/bhsd-harry/wikiparser-node/issues"
|
|
13
13
|
},
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const /** @type {Parser} */ Parser = require('..');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {string} firstChild
|
|
7
|
+
* @param {accum} accum
|
|
8
|
+
*/
|
|
9
|
+
const parseConverter = (firstChild, config = Parser.getConfig(), accum = []) => {
|
|
10
|
+
const ConverterToken = require('../src/converter'),
|
|
11
|
+
regex1 = /-{/g,
|
|
12
|
+
regex2 = /-{|}-/g,
|
|
13
|
+
/** @type {RegExpExecArray[]} */ stack = [];
|
|
14
|
+
let regex = regex1,
|
|
15
|
+
mt = regex.exec(firstChild);
|
|
16
|
+
while (mt) {
|
|
17
|
+
const {0: syntax, index} = mt;
|
|
18
|
+
if (syntax === '}-') {
|
|
19
|
+
const top = stack.pop(),
|
|
20
|
+
{length} = accum,
|
|
21
|
+
str = firstChild.slice(top.index + 2, index),
|
|
22
|
+
i = str.indexOf('|'),
|
|
23
|
+
[flags, text] = i === -1 ? [[], str] : [str.slice(0, i).split(';'), str.slice(i + 1)],
|
|
24
|
+
temp = text.replace(/(?<=&[#a-z0-9]+);/i, '\x01'),
|
|
25
|
+
variants = `(?:${config.variants.join('|')})`,
|
|
26
|
+
rules = temp.split(new RegExp(`;(?=\\s*(?:${variants}|[^;]*?=>\\s*${variants})\\s*:)`))
|
|
27
|
+
.map(rule => rule.replaceAll('\x01', ';'));
|
|
28
|
+
new ConverterToken(flags, rules, config, accum);
|
|
29
|
+
firstChild = `${firstChild.slice(0, top.index)}\x00${length}v\x7f${firstChild.slice(index + 2)}`;
|
|
30
|
+
if (stack.length === 0) {
|
|
31
|
+
regex = regex1;
|
|
32
|
+
}
|
|
33
|
+
regex.lastIndex = top.index + 3 + String(length).length;
|
|
34
|
+
} else {
|
|
35
|
+
stack.push(mt);
|
|
36
|
+
regex = regex2;
|
|
37
|
+
}
|
|
38
|
+
mt = regex.exec(firstChild);
|
|
39
|
+
}
|
|
40
|
+
return firstChild;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
Parser.parsers.parseConverter = __filename;
|
|
44
|
+
module.exports = parseConverter;
|
package/parser/list.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const /** @type {Parser} */ Parser = require('..');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {string} text
|
|
7
|
+
* @param {accum} accum
|
|
8
|
+
*/
|
|
9
|
+
const parseList = (text, config = Parser.getConfig(), accum = []) => {
|
|
10
|
+
const mt = text.match(/^(?:[;:*#]|\x00\d+c\x7f)*[;:*#]/);
|
|
11
|
+
if (!mt) {
|
|
12
|
+
return text;
|
|
13
|
+
}
|
|
14
|
+
const ListToken = require('../src/nowiki/list'),
|
|
15
|
+
[prefix] = mt;
|
|
16
|
+
text = `\x00${accum.length}d\x7f${text.slice(prefix.length)}`;
|
|
17
|
+
new ListToken(prefix, config, accum);
|
|
18
|
+
let dt = prefix.split(';').length - 1;
|
|
19
|
+
if (!dt) {
|
|
20
|
+
return text;
|
|
21
|
+
}
|
|
22
|
+
const DdToken = require('../src/nowiki/dd');
|
|
23
|
+
let regex = /:+|-{/g,
|
|
24
|
+
ex = regex.exec(text),
|
|
25
|
+
lc = 0;
|
|
26
|
+
while (ex && dt) {
|
|
27
|
+
const {0: syntax, index} = ex;
|
|
28
|
+
if (syntax[0] === ':') {
|
|
29
|
+
if (syntax.length >= dt) {
|
|
30
|
+
new DdToken(':'.repeat(dt), config, accum);
|
|
31
|
+
return `${text.slice(0, index)}\x00${accum.length - 1}d\x7f${text.slice(index + dt)}`;
|
|
32
|
+
}
|
|
33
|
+
text = `${text.slice(0, index)}\x00${accum.length}d\x7f${text.slice(regex.lastIndex)}`;
|
|
34
|
+
dt -= syntax.length;
|
|
35
|
+
regex.lastIndex = index + 4 + String(accum.length).length;
|
|
36
|
+
new DdToken(syntax, config, accum);
|
|
37
|
+
} else if (syntax === '-{') {
|
|
38
|
+
if (!lc) {
|
|
39
|
+
const {lastIndex} = regex;
|
|
40
|
+
regex = /-{|}-/g;
|
|
41
|
+
regex.lastIndex = lastIndex;
|
|
42
|
+
}
|
|
43
|
+
lc++;
|
|
44
|
+
} else {
|
|
45
|
+
lc--;
|
|
46
|
+
if (!lc) {
|
|
47
|
+
const {lastIndex} = regex;
|
|
48
|
+
regex = /:+|-{/g;
|
|
49
|
+
regex.lastIndex = lastIndex;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
ex = regex.exec(text);
|
|
53
|
+
}
|
|
54
|
+
return text;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
Parser.parsers.parseList = __filename;
|
|
58
|
+
module.exports = parseList;
|
package/src/arg.js
CHANGED
|
@@ -75,13 +75,13 @@ class ArgToken extends Token {
|
|
|
75
75
|
|
|
76
76
|
/** @returns {[number, string][]} */
|
|
77
77
|
plain() {
|
|
78
|
-
return this.
|
|
78
|
+
return this.childNodes.length > 1 ? this.children[1].plain() : [];
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/** @complexity `n` */
|
|
82
82
|
removeRedundant() {
|
|
83
83
|
Parser.run(() => {
|
|
84
|
-
for (let i = this.
|
|
84
|
+
for (let i = this.childNodes.length - 1; i > 1; i--) {
|
|
85
85
|
super.removeAt(i);
|
|
86
86
|
}
|
|
87
87
|
});
|
|
@@ -100,8 +100,8 @@ class ArgToken extends Token {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/** @param {Token} token */
|
|
103
|
-
insertAt(token, i = this.
|
|
104
|
-
const j = i < 0 ? i + this.
|
|
103
|
+
insertAt(token, i = this.childNodes.length) {
|
|
104
|
+
const j = i < 0 ? i + this.childNodes.length : i;
|
|
105
105
|
if (j > 1 && !Parser.running) {
|
|
106
106
|
throw new RangeError(`${this.constructor.name} 不可插入 arg-redundant 子节点!`);
|
|
107
107
|
}
|
|
@@ -117,7 +117,7 @@ class ArgToken extends Token {
|
|
|
117
117
|
name = String(name);
|
|
118
118
|
const root = Parser.parse(`{{{${name}}}}`, this.getAttribute('include'), 2, this.getAttribute('config')),
|
|
119
119
|
{childNodes: {length}, firstElementChild} = root;
|
|
120
|
-
if (length !== 1 || firstElementChild?.type !== 'arg' || firstElementChild.
|
|
120
|
+
if (length !== 1 || firstElementChild?.type !== 'arg' || firstElementChild.childNodes.length !== 1) {
|
|
121
121
|
throw new SyntaxError(`非法的参数名称:${noWrap(name)}`);
|
|
122
122
|
}
|
|
123
123
|
const newName = firstElementChild.firstElementChild;
|
|
@@ -131,7 +131,7 @@ class ArgToken extends Token {
|
|
|
131
131
|
value = String(value);
|
|
132
132
|
const root = Parser.parse(`{{{|${value}}}}`, this.getAttribute('include'), 2, this.getAttribute('config')),
|
|
133
133
|
{childNodes: {length}, firstElementChild} = root;
|
|
134
|
-
if (length !== 1 || firstElementChild?.type !== 'arg' || firstElementChild.
|
|
134
|
+
if (length !== 1 || firstElementChild?.type !== 'arg' || firstElementChild.childNodes.length !== 2) {
|
|
135
135
|
throw new SyntaxError(`非法的参数预设值:${noWrap(value)}`);
|
|
136
136
|
}
|
|
137
137
|
const [, oldDefault] = this.children,
|
package/src/attribute.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {externalUse} = require('../util/debug'),
|
|
4
|
-
{toCase, removeComment} = require('../util/string'),
|
|
4
|
+
{toCase, removeComment, normalizeSpace} = require('../util/string'),
|
|
5
5
|
/** @type {Parser} */ Parser = require('..'),
|
|
6
6
|
Token = require('.');
|
|
7
7
|
|
|
@@ -28,14 +28,13 @@ class AttributeToken extends Token {
|
|
|
28
28
|
) {
|
|
29
29
|
equal = '{{=}}';
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
return [...this.#attr].map(([k, v]) => {
|
|
32
32
|
if (v === true) {
|
|
33
33
|
return k;
|
|
34
34
|
}
|
|
35
35
|
const quote = v.includes('"') ? "'" : '"';
|
|
36
36
|
return `${k}${equal}${quote}${v}${quote}`;
|
|
37
37
|
}).join(' ');
|
|
38
|
-
return str && ` ${str}`;
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
/** @complexity `n` */
|
|
@@ -56,17 +55,17 @@ class AttributeToken extends Token {
|
|
|
56
55
|
*/
|
|
57
56
|
#parseAttr() {
|
|
58
57
|
this.#attr.clear();
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
let string = this.toString(),
|
|
59
|
+
/** @type {Token & {firstChild: string}} */ token;
|
|
60
|
+
if (this.type !== 'ext-attr' && !Parser.running) {
|
|
61
|
+
const config = this.getAttribute('config'),
|
|
62
|
+
include = this.getAttribute('include');
|
|
63
|
+
token = Parser.run(() => new Token(string, config).parseOnce(0, include).parseOnce());
|
|
64
|
+
string = token.firstChild;
|
|
65
|
+
}
|
|
66
|
+
string = removeComment(string).replace(/\x00\d+~\x7f/g, '=');
|
|
67
|
+
const build = /** @param {string|boolean} str */ str =>
|
|
68
|
+
typeof str === 'boolean' || !token ? str : token.buildFromStr(str).map(String).join('');
|
|
70
69
|
for (const [, key,, quoted, unquoted] of string
|
|
71
70
|
.matchAll(/([^\s/][^\s/=]*)(?:\s*=\s*(?:(["'])(.*?)(?:\2|$)|(\S*)))?/sg)
|
|
72
71
|
) {
|
|
@@ -241,13 +240,24 @@ class AttributeToken extends Token {
|
|
|
241
240
|
this.setAttr(key, force === true || force === undefined && value === false);
|
|
242
241
|
}
|
|
243
242
|
|
|
243
|
+
#leadingSpace(str = super.toString()) {
|
|
244
|
+
return this.type !== 'table-attr' && str && !/^\s/.test(str) ? ' ' : '';
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** @this {AttributeToken & Token} */
|
|
244
248
|
toString() {
|
|
245
|
-
const str = super.toString();
|
|
246
|
-
return this
|
|
249
|
+
const str = this.type === 'table-attr' ? normalizeSpace(this) : super.toString();
|
|
250
|
+
return `${this.#leadingSpace(str)}${str}`;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
getPadding() {
|
|
254
|
+
return this.#leadingSpace().length;
|
|
247
255
|
}
|
|
248
256
|
|
|
249
257
|
text() {
|
|
250
|
-
|
|
258
|
+
let str = this.#updateFromAttr();
|
|
259
|
+
str = `${this.#leadingSpace(str)}${str}`;
|
|
260
|
+
return this.type === 'table-attr' ? normalizeSpace(str) : str;
|
|
251
261
|
}
|
|
252
262
|
|
|
253
263
|
/** @returns {[number, string][]} */
|
package/src/converter.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {text} = require('../util/string'),
|
|
4
|
+
/** @type {Parser} */ Parser = require('..'),
|
|
5
|
+
Token = require('.'),
|
|
6
|
+
ConverterFlagsToken = require('./converterFlags'),
|
|
7
|
+
ConverterRuleToken = require('./converterRule');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 转换
|
|
11
|
+
* @classdesc `{childNodes: [ConverterFlagsToken, ...ConverterRuleToken]}`
|
|
12
|
+
*/
|
|
13
|
+
class ConverterToken extends Token {
|
|
14
|
+
type = 'converter';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {string[]} flags
|
|
18
|
+
* @param {string[]} rules
|
|
19
|
+
* @param {accum} accum
|
|
20
|
+
*/
|
|
21
|
+
constructor(flags, rules, config = Parser.getConfig(), accum = []) {
|
|
22
|
+
super(undefined, config, false, accum);
|
|
23
|
+
this.append(new ConverterFlagsToken(flags, config, accum));
|
|
24
|
+
if (rules.length) {
|
|
25
|
+
const [firstRule] = rules,
|
|
26
|
+
hasColon = firstRule.includes(':'),
|
|
27
|
+
firstRuleToken = new ConverterRuleToken(firstRule, hasColon, config, accum);
|
|
28
|
+
if (hasColon && firstRuleToken.childNodes.length === 1) {
|
|
29
|
+
this.appendChild(new ConverterRuleToken(rules.join(';'), false, config, accum));
|
|
30
|
+
} else {
|
|
31
|
+
this.append(
|
|
32
|
+
firstRuleToken,
|
|
33
|
+
...rules.slice(1).map(rule => new ConverterRuleToken(rule, true, config, accum)),
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
this.protectChildren(0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
cloneNode() {
|
|
41
|
+
const [flags, ...rules] = this.cloneChildren(),
|
|
42
|
+
token = Parser.run(() => new ConverterToken([], [], this.getAttribute('config')));
|
|
43
|
+
token.firstElementChild.safeReplaceWith(flags);
|
|
44
|
+
token.append(...rules);
|
|
45
|
+
return token;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
toString() {
|
|
49
|
+
const [flags, ...rules] = this.children;
|
|
50
|
+
return `-{${flags.toString()}${flags.childNodes.length ? '|' : ''}${rules.map(String).join(';')}}-`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
getPadding() {
|
|
54
|
+
return 2;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** @param {number} i */
|
|
58
|
+
getGaps(i = 0) {
|
|
59
|
+
i = i < 0 ? i + this.childNodes.length : i;
|
|
60
|
+
return i || this.firstElementChild.childNodes.length ? 1 : 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
text() {
|
|
64
|
+
const [flags, ...rules] = this.children;
|
|
65
|
+
return `-{${flags.text()}|${text(rules, ';')}}-`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** @returns {[number, string][]} */
|
|
69
|
+
plain() {
|
|
70
|
+
return this.children.slice(1).flatMap(child => child.plain());
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** @this {ConverterToken & {firstChild: ConverterFlagsToken}} */
|
|
74
|
+
getAllFlags() {
|
|
75
|
+
return this.firstChild.getAllFlags();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** @this {ConverterToken & {firstChild: ConverterFlagsToken}} */
|
|
79
|
+
getEffectiveFlags() {
|
|
80
|
+
return this.firstChild.getEffectiveFlags();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** @this {ConverterToken & {firstChild: ConverterFlagsToken}} */
|
|
84
|
+
getUnknownFlags() {
|
|
85
|
+
return this.firstChild.getUnknownFlags();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @this {ConverterToken & {firstChild: ConverterFlagsToken}}
|
|
90
|
+
* @param {string} flag
|
|
91
|
+
*/
|
|
92
|
+
hasFlag(flag) {
|
|
93
|
+
return this.firstChild.hasFlag(flag);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @this {ConverterToken & {firstChild: ConverterFlagsToken}}
|
|
98
|
+
* @param {string} flag
|
|
99
|
+
*/
|
|
100
|
+
hasEffectiveFlag(flag) {
|
|
101
|
+
return this.firstChild.hasEffectiveFlag(flag);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @this {ConverterToken & {firstChild: ConverterFlagsToken}}
|
|
106
|
+
* @param {string} flag
|
|
107
|
+
*/
|
|
108
|
+
removeFlag(flag) {
|
|
109
|
+
this.firstChild.removeFlag(flag);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @this {ConverterToken & {firstChild: ConverterFlagsToken}}
|
|
114
|
+
* @param {string} flag
|
|
115
|
+
*/
|
|
116
|
+
setFlag(flag) {
|
|
117
|
+
this.firstChild.setFlag(flag);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @this {ConverterToken & {firstChild: ConverterFlagsToken}}
|
|
122
|
+
* @param {string} flag
|
|
123
|
+
*/
|
|
124
|
+
toggleFlag(flag) {
|
|
125
|
+
this.firstChild.toggleFlag(flag);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** @this {ConverterToken & {children: [ConverterFlagsToken, ConverterRuleToken]}} */
|
|
129
|
+
get noConvert() {
|
|
130
|
+
return this.childNodes.length < 3 && !this.children[1]?.variant;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
Parser.classes.ConverterToken = __filename;
|
|
135
|
+
module.exports = ConverterToken;
|