wikiparser-node 0.0.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +226 -7
- 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/errors/README +1 -0
- package/index.js +85 -9
- package/lib/element.js +72 -13
- package/lib/node.js +17 -9
- package/mixin/sol.js +42 -0
- package/package.json +1 -1
- package/parser/converter.js +44 -0
- package/parser/externalLinks.js +1 -1
- package/parser/list.js +58 -0
- package/parser/table.js +2 -2
- package/printed/README +1 -0
- package/src/arg.js +9 -9
- package/src/attribute.js +33 -23
- package/src/converter.js +135 -0
- package/src/converterFlags.js +214 -0
- package/src/converterRule.js +209 -0
- package/src/extLink.js +23 -10
- package/src/heading.js +15 -20
- package/src/html.js +4 -3
- package/src/imageParameter.js +6 -7
- package/src/index.js +38 -23
- package/src/link/file.js +9 -9
- package/src/link/index.js +9 -11
- package/src/magicLink.js +2 -3
- package/src/nowiki/comment.js +1 -1
- 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 +5 -5
- package/src/syntax.js +3 -1
- package/src/table/index.js +35 -30
- package/src/table/td.js +3 -2
- package/src/table/tr.js +6 -12
- package/src/tagPair/index.js +1 -1
- package/src/transclude.js +28 -25
- package/tool/index.js +50 -40
- package/typings/index.d.ts +3 -0
- package/typings/node.d.ts +3 -3
- package/typings/token.d.ts +1 -0
- package/util/debug.js +3 -3
- package/util/string.js +16 -1
- package/src/listToken.js +0 -47
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
10. [findEnclosingHtml](#token.findenclosinghtml)
|
|
30
30
|
11. [getCategories](#token.getcategories)
|
|
31
31
|
12. [redoQuotes](#token.redoquotes)
|
|
32
|
+
13. [print](#token.print)
|
|
32
33
|
2. [实例属性](#token.instance.properties)
|
|
33
34
|
1. [type](#token.type)
|
|
34
35
|
3. [原型属性](#token.prototype.properties)
|
|
@@ -180,12 +181,35 @@
|
|
|
180
181
|
2. [setTarget](#magiclinktoken.settarget)
|
|
181
182
|
2. [原型属性](#magiclinktoken.prototype.properties)
|
|
182
183
|
1. [protocol](#magiclinktoken.protocol)
|
|
183
|
-
21. [
|
|
184
|
+
21. [ConverterToken](#convertertoken)
|
|
185
|
+
1. [原型方法](#convertertoken.prototype.methods)
|
|
186
|
+
1. [getAllFlags](#convertertoken.getallflags)
|
|
187
|
+
2. [getEffectiveFlags](#convertertoken.geteffectiveflags)
|
|
188
|
+
3. [hasFlag](#convertertoken.hasflag)
|
|
189
|
+
4. [hasEffectiveFlag](#convertertoken.haseffectiveflag)
|
|
190
|
+
5. [removeFlag](#convertertoken.removeflag)
|
|
191
|
+
6. [setFlag](#convertertoken.setflag)
|
|
192
|
+
7. [toggleFlag](#convertertoken.toggleflag)
|
|
193
|
+
2. [原型属性](#convertertoken.prototype.properties)
|
|
194
|
+
1. [noConvert](#convertertoken.noconvert)
|
|
195
|
+
22. [ConverterRuleToken](#converterruletoken)
|
|
196
|
+
1. [原型方法](#converterruletoken.prototype.methods)
|
|
197
|
+
1. [noConvert](#converterruletoken.noconvert)
|
|
198
|
+
2. [setTo](#converterruletoken.setto)
|
|
199
|
+
3. [setVariant](#converterruletoken.setvariant)
|
|
200
|
+
4. [setFrom](#converterruletoken.setfrom)
|
|
201
|
+
5. [makeUnidirectional](#converterruletoken.makeunidirectional)
|
|
202
|
+
6. [makeBidirectional](#converterruletoken.makebidirectional)
|
|
203
|
+
2. [实例属性](#converterruletoken.instance.properties)
|
|
204
|
+
1. [variant](#converterruletoken.variant)
|
|
205
|
+
2. [unidirectional](#converterruletoken.unidirectional)
|
|
206
|
+
3. [bidirectional](#converterruletoken.bidirectional)
|
|
207
|
+
23. [选择器](#选择器)
|
|
184
208
|
1. [type](#selector.type)
|
|
185
209
|
2. [name](#selector.name)
|
|
186
210
|
3. [属性](#selector.attribute)
|
|
187
211
|
4. [伪选择器](#selector.pseudo)
|
|
188
|
-
|
|
212
|
+
24. [$ (TokenCollection)](#-tokencollection)
|
|
189
213
|
</details>
|
|
190
214
|
|
|
191
215
|
# Parser
|
|
@@ -426,6 +450,15 @@ assert.deepStrictEqual(root.childNodes, ["'", root.firstElementChild, "a", root.
|
|
|
426
450
|
var root = Parser.parse(wikitext);
|
|
427
451
|
assert(root.type === 'root');
|
|
428
452
|
```
|
|
453
|
+
|
|
454
|
+
**print**(format?: 'markup'\|'json' = 'markup'): void\|object<a id="token.print"></a>
|
|
455
|
+
- 打印解析生成的 AST。
|
|
456
|
+
|
|
457
|
+
```js
|
|
458
|
+
var root = Parser.parse("<ref>{{T|<br>\n----\n[[File:F|thumb|''[//example.net]'']]}}</ref>");
|
|
459
|
+
root.print();
|
|
460
|
+
root.print('json', 'example'); // JSON格式的输出结果将保存至 /printed/example.json 文件
|
|
461
|
+
```
|
|
429
462
|
</details>
|
|
430
463
|
|
|
431
464
|
## 原型属性<a id="token.prototype.properties"></a>
|
|
@@ -930,7 +963,7 @@ param.setValue(' 2 ');
|
|
|
930
963
|
assert(root.toString() === '{{a|b= 2 }}'); // setValue方法总是保留空白字符,哪怕是无效的
|
|
931
964
|
```
|
|
932
965
|
|
|
933
|
-
**rename**(key: string, force
|
|
966
|
+
**rename**(key: string, force?: boolean = false): void<a id="parametertoken.rename"></a>
|
|
934
967
|
- 重命名参数,可选是否在导致重复参数时抛出错误。
|
|
935
968
|
|
|
936
969
|
```js
|
|
@@ -1164,7 +1197,7 @@ assert(root.toString() === '{|\n!colspan=2|\n|-\n| \n!\n|}');
|
|
|
1164
1197
|
|:-:|:-:|:-:|
|
|
1165
1198
|
|<table><tr><td colspan=2>td</td></tr><tr><td>td</td><td>td</td></tr></table>|<table><tr><td colspan=2>td</td></tr><tr><td>td</td><th>th</th></tr></table>|<table><tr><th colspan=2>th</th></tr><tr><td>td</td><th>th</th></tr></table>|
|
|
1166
1199
|
|
|
1167
|
-
**insertTableRow**(row: number, attr: Record\<string, string\|boolean>, inner?: string, subtype?: 'td'\|'th', innerAttr?: Record\<string, string\|boolean>): TrToken<a id="tabletoken.inserttablerow"></a>
|
|
1200
|
+
**insertTableRow**(row: number, attr: Record\<string, string\|boolean>, inner?: string, subtype?: 'td'\|'th' = 'td', innerAttr?: Record\<string, string\|boolean>): TrToken<a id="tabletoken.inserttablerow"></a>
|
|
1168
1201
|
- 插入空行或一行单元格。
|
|
1169
1202
|
|
|
1170
1203
|
```js
|
|
@@ -1179,7 +1212,7 @@ assert(root.toString() === '{|\n|a|| rowspan="3"|b||c\n|- class="tr"\n|-\n! clas
|
|
|
1179
1212
|
|:-:|:-:|
|
|
1180
1213
|
|<table><tr><td>a</td><td rowspan=2>b</td><td>c</td></tr><tr><td>d</td><td>e</td></tr></table>|<table><tr><td>a</td><td rowspan=3>b</td><td>c</td></tr><tr><th>f</th><th>f</th></tr><tr><td>d</td><td>e</td></tr></table>|
|
|
1181
1214
|
|
|
1182
|
-
**insertTableCol**(x: number, inner: string, subtype
|
|
1215
|
+
**insertTableCol**(x: number, inner: string, subtype?: 'td'\|'th' = 'td', attr?: Record\<string, string\|boolean>): void<a id="tabletoken.inserttablecol"></a>
|
|
1183
1216
|
- 插入一列单元格。
|
|
1184
1217
|
|
|
1185
1218
|
```js
|
|
@@ -1193,7 +1226,7 @@ assert(root.toString() === '{|\n| colspan="3"|a\n|-\n|b\n! class="th"|d\n|c\n|}'
|
|
|
1193
1226
|
|:-:|:-:|
|
|
1194
1227
|
|<table><tr><td colspan=2 align="center">a</td></tr><tr><td>b</td><td>c</td></tr></table>|<table><tr><td colspan=3 align="center">a</td></tr><tr><td>b</td><th>d</th><td>c</td></tr></table>|
|
|
1195
1228
|
|
|
1196
|
-
**insertTableCell**(inner: string, coords: {row: number, column: number}\|{x: number, y: number}, subtype
|
|
1229
|
+
**insertTableCell**(inner: string, coords: {row: number, column: number}\|{x: number, y: number}, subtype?: 'td'\|'th' = 'td', attr?: Record\<string, string\|boolean>): [TdToken](#tdtoken)<a id="tabletoken.inserttablecell"></a>
|
|
1197
1230
|
- 插入一个单元格。
|
|
1198
1231
|
|
|
1199
1232
|
```js
|
|
@@ -1471,7 +1504,7 @@ link.asSelfLink();
|
|
|
1471
1504
|
assert(root.toString() === '[[#b]]');
|
|
1472
1505
|
```
|
|
1473
1506
|
|
|
1474
|
-
**setLinkText**(linkText
|
|
1507
|
+
**setLinkText**(linkText: string)<a id="linktoken.setlinktext"></a>
|
|
1475
1508
|
- 修改链接文本。
|
|
1476
1509
|
|
|
1477
1510
|
```js
|
|
@@ -1797,6 +1830,192 @@ assert(root.toString() === 'https://example.org');
|
|
|
1797
1830
|
|
|
1798
1831
|
[返回目录](#目录)
|
|
1799
1832
|
|
|
1833
|
+
# ConverterToken
|
|
1834
|
+
转换。
|
|
1835
|
+
|
|
1836
|
+
## 原型方法<a id="convertertoken.prototype.methods"></a>
|
|
1837
|
+
<details>
|
|
1838
|
+
<summary>展开</summary>
|
|
1839
|
+
|
|
1840
|
+
**getAllFlags**(): Set\<string><a id="convertertoken.getallflags"></a>
|
|
1841
|
+
- 获取所有转换 flag,包括无效的。
|
|
1842
|
+
|
|
1843
|
+
```js
|
|
1844
|
+
var root = Parser.parse('-{zh-hans;zh-hant|}-'),
|
|
1845
|
+
converter = root.firstChild;
|
|
1846
|
+
assert.deepStrictEqual(converter.getAllFlags(), new Set(['zh-hans', 'zh-hant']));
|
|
1847
|
+
```
|
|
1848
|
+
|
|
1849
|
+
**getEffectiveFlags**(): Set\<string><a id="convertertoken.geteffectiveflags"></a>
|
|
1850
|
+
- 解析有效的转换 flag。
|
|
1851
|
+
|
|
1852
|
+
```js
|
|
1853
|
+
var root = Parser.parse('-{}-'),
|
|
1854
|
+
converter = root.firstChild;
|
|
1855
|
+
assert.deepStrictEqual(converter.getEffectiveFlags(), new Set(['S']));
|
|
1856
|
+
```
|
|
1857
|
+
|
|
1858
|
+
**hasFlag**(flag: string): boolean<a id="convertertoken.hasflag"></a>
|
|
1859
|
+
- 是否包含 flag,即使可能是无效 flag。
|
|
1860
|
+
|
|
1861
|
+
```js
|
|
1862
|
+
var root = Parser.parse('-{R|}-'),
|
|
1863
|
+
converter = root.firstChild;
|
|
1864
|
+
assert(converter.hasFlag('R') === true);
|
|
1865
|
+
```
|
|
1866
|
+
|
|
1867
|
+
**hasEffectiveFlag**(flag: string): boolean<a id="convertertoken.haseffectiveflag"></a>
|
|
1868
|
+
- 是否包含某有效 flag。
|
|
1869
|
+
|
|
1870
|
+
```js
|
|
1871
|
+
var root = Parser.parse('-{}-'),
|
|
1872
|
+
converter = root.firstChild;
|
|
1873
|
+
assert(converter.hasEffectiveFlag('S') === true);
|
|
1874
|
+
```
|
|
1875
|
+
|
|
1876
|
+
**removeFlag**(flag: string): void<a id="convertertoken.removeflag"></a>
|
|
1877
|
+
- 移除 flag,可能原本就是无效的 flag。
|
|
1878
|
+
|
|
1879
|
+
```js
|
|
1880
|
+
var root = Parser.parse('-{R|}-'),
|
|
1881
|
+
converter = root.firstChild;
|
|
1882
|
+
converter.removeFlag('R');
|
|
1883
|
+
assert(root.toString() === '-{}-');
|
|
1884
|
+
```
|
|
1885
|
+
|
|
1886
|
+
**setFlag**(flag: string): void<a id="convertertoken.setflag"></a>
|
|
1887
|
+
- 添加指定 flag,可能是无效 flag。
|
|
1888
|
+
|
|
1889
|
+
```js
|
|
1890
|
+
var root = Parser.parse('-{}-'),
|
|
1891
|
+
converter = root.firstChild;
|
|
1892
|
+
converter.setFlag('R');
|
|
1893
|
+
assert(root.toString() === '-{R|}-');
|
|
1894
|
+
```
|
|
1895
|
+
|
|
1896
|
+
**toggleFlag**(flag: string): void<a id="convertertoken.toggleflag"></a>
|
|
1897
|
+
- 改变某 flag 的有无,可能是无效 flag。
|
|
1898
|
+
|
|
1899
|
+
```js
|
|
1900
|
+
var root = Parser.parse('-{R|}-'),
|
|
1901
|
+
converter = root.firstChild;
|
|
1902
|
+
converter.toggleFlag('R');
|
|
1903
|
+
converter.toggleFlag('D');
|
|
1904
|
+
assert(root.toString() === '-{D|}-');
|
|
1905
|
+
```
|
|
1906
|
+
</details>
|
|
1907
|
+
|
|
1908
|
+
## 原型属性<a id="convertertoken.prototype.properties"></a>
|
|
1909
|
+
<details>
|
|
1910
|
+
<summary>展开</summary>
|
|
1911
|
+
|
|
1912
|
+
**noConvert**: boolean<a id="convertertoken.noconvert"></a>
|
|
1913
|
+
- 是否不会转换。
|
|
1914
|
+
|
|
1915
|
+
```js
|
|
1916
|
+
var root = Parser.parse('-{简体}-'),
|
|
1917
|
+
converter = root.firstChild;
|
|
1918
|
+
assert(converter.noConvert === true);
|
|
1919
|
+
```
|
|
1920
|
+
</details>
|
|
1921
|
+
|
|
1922
|
+
[返回目录](#目录)
|
|
1923
|
+
|
|
1924
|
+
# ConverterRuleToken
|
|
1925
|
+
单条转换规则。
|
|
1926
|
+
|
|
1927
|
+
## 原型方法<a id="converterruletoken.prototype.methods"></a>
|
|
1928
|
+
<details>
|
|
1929
|
+
<summary>展开</summary>
|
|
1930
|
+
|
|
1931
|
+
**noConvert**(): void<a id="converterruletoken.noconvert"></a>
|
|
1932
|
+
- 更改规则使得内容不会转换。
|
|
1933
|
+
|
|
1934
|
+
```js
|
|
1935
|
+
var root = Parser.parse('-{繁體=>zh-hans:繁體}-'),
|
|
1936
|
+
converterRule = root.querySelector('converter-rule');
|
|
1937
|
+
converterRule.noConvert();
|
|
1938
|
+
assert(root.toString() === '-{繁體}-');
|
|
1939
|
+
```
|
|
1940
|
+
|
|
1941
|
+
**setTo**(to: string): void<a id="converterruletoken.setto"></a>
|
|
1942
|
+
- 修改转换结果。
|
|
1943
|
+
|
|
1944
|
+
```js
|
|
1945
|
+
var root = Parser.parse('-{繁體=>zh-hans:繁體}-'),
|
|
1946
|
+
converterRule = root.querySelector('converter-rule');
|
|
1947
|
+
converterRule.setTo('繁体');
|
|
1948
|
+
assert(root.toString() === '-{繁體=>zh-hans:繁体}-');
|
|
1949
|
+
```
|
|
1950
|
+
|
|
1951
|
+
**setVariant**(variant: string): void<a id="converterruletoken.setvariant"></a>
|
|
1952
|
+
- 修改转换规则对应的语言变体。
|
|
1953
|
+
|
|
1954
|
+
```js
|
|
1955
|
+
var root = Parser.parse('-{繁體=>zh-hans:繁體}-'),
|
|
1956
|
+
converterRule = root.querySelector('converter-rule');
|
|
1957
|
+
converterRule.setVariant('zh-cn');
|
|
1958
|
+
assert(root.toString() === '-{繁體=>zh-cn:繁體}-');
|
|
1959
|
+
```
|
|
1960
|
+
|
|
1961
|
+
**setFrom**(from: string): void<a id="converterruletoken.setfrom"></a>
|
|
1962
|
+
- 对单项转换规则,修改待转换的内容。
|
|
1963
|
+
|
|
1964
|
+
```js
|
|
1965
|
+
var root = Parser.parse('-{繁體=>zh-hans:繁体}-'),
|
|
1966
|
+
converterRule = root.querySelector('converter-rule');
|
|
1967
|
+
converterRule.setFrom('正體');
|
|
1968
|
+
assert(root.toString() === '-{正體=>zh-hans:繁体}-');
|
|
1969
|
+
```
|
|
1970
|
+
|
|
1971
|
+
**makeUnidirectional**(from: string): void<a id="converterruletoken.makeunidirectional"></a>
|
|
1972
|
+
- [ConverterRuleToken.setFrom](#converterruletoken.setfrom) 方法的別名。
|
|
1973
|
+
|
|
1974
|
+
**makeBidirectional**(): void<a id="converterruletoken.makebidirectional"></a>
|
|
1975
|
+
- 将规则改为双向转换。
|
|
1976
|
+
|
|
1977
|
+
```js
|
|
1978
|
+
var root = Parser.parse('-{繁體=>zh-hans:繁体}-'),
|
|
1979
|
+
converterRule = root.querySelector('converter-rule');
|
|
1980
|
+
converterRule.makeBidirectional();
|
|
1981
|
+
assert(root.toString() === '-{zh-hans:繁体}-');
|
|
1982
|
+
```
|
|
1983
|
+
</details>
|
|
1984
|
+
|
|
1985
|
+
## 原型属性<a id="convertertoken.prototype.properties"></a>
|
|
1986
|
+
<details>
|
|
1987
|
+
<summary>展开</summary>
|
|
1988
|
+
|
|
1989
|
+
**variant**: string<a id="converterruletoken.variant"></a>
|
|
1990
|
+
- 规则对应的语言变体。
|
|
1991
|
+
|
|
1992
|
+
```js
|
|
1993
|
+
var root = Parser.parse('-{繁體=>zh-hans:繁体}-'),
|
|
1994
|
+
converterRule = root.querySelector('converter-rule');
|
|
1995
|
+
assert(converterRule.variant === 'zh-hans');
|
|
1996
|
+
```
|
|
1997
|
+
|
|
1998
|
+
**unidirectional**: boolean<a id="converterruletoken.unidirectional"></a>
|
|
1999
|
+
- 是否是单向转换。
|
|
2000
|
+
|
|
2001
|
+
```js
|
|
2002
|
+
var root = Parser.parse('-{繁體=>zh-hans:繁体}-'),
|
|
2003
|
+
converterRule = root.querySelector('converter-rule');
|
|
2004
|
+
assert(converterRule.unidirectional === true);
|
|
2005
|
+
```
|
|
2006
|
+
|
|
2007
|
+
**bidirectional**: boolean<a id="converterruletoken.bidirectional"></a>
|
|
2008
|
+
- 是否是双向转换。
|
|
2009
|
+
|
|
2010
|
+
```js
|
|
2011
|
+
var root = Parser.parse('-{zh-hans:繁体}-'),
|
|
2012
|
+
converterRule = root.querySelector('converter-rule');
|
|
2013
|
+
assert(converterRule.bidirectional === true);
|
|
2014
|
+
```
|
|
2015
|
+
</details>
|
|
2016
|
+
|
|
2017
|
+
[返回目录](#目录)
|
|
2018
|
+
|
|
1800
2019
|
# 选择器
|
|
1801
2020
|
Token 选择器的设计仿照了 CSS 和 jQuery 的选择器。
|
|
1802
2021
|
<details>
|
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/errors/README
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
这里记录解析失败时处于半解析状态的维基文本以及错误信息。
|
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',
|
|
@@ -108,7 +110,7 @@ const /** @type {Parser} */ Parser = {
|
|
|
108
110
|
}
|
|
109
111
|
}
|
|
110
112
|
};
|
|
111
|
-
|
|
113
|
+
this.run(() => {
|
|
112
114
|
build(['title', 'fragment']);
|
|
113
115
|
});
|
|
114
116
|
}
|
|
@@ -119,31 +121,105 @@ const /** @type {Parser} */ Parser = {
|
|
|
119
121
|
|
|
120
122
|
parse(wikitext, include = false, maxStage = Parser.MAX_STAGE, config = Parser.getConfig()) {
|
|
121
123
|
const Token = require('./src');
|
|
124
|
+
let token;
|
|
122
125
|
this.run(() => {
|
|
123
126
|
if (typeof wikitext === 'string') {
|
|
124
|
-
|
|
125
|
-
} else if (
|
|
127
|
+
token = new Token(wikitext, config);
|
|
128
|
+
} else if (wikitext instanceof Token) {
|
|
129
|
+
token = wikitext;
|
|
130
|
+
wikitext = token.toString();
|
|
131
|
+
} else {
|
|
126
132
|
throw new TypeError('待解析的内容应为 String 或 Token!');
|
|
127
133
|
}
|
|
128
134
|
try {
|
|
129
|
-
|
|
135
|
+
token.parse(maxStage, include);
|
|
130
136
|
} catch (e) {
|
|
131
137
|
if (e instanceof Error) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
);
|
|
138
|
+
const file = `${__dirname}/errors/${new Date().toISOString()}`,
|
|
139
|
+
stage = token.getAttribute('stage');
|
|
140
|
+
fs.writeFileSync(file, stage === this.MAX_STAGE ? wikitext : token.toString());
|
|
141
|
+
fs.writeFileSync(`${file}.err`, e.stack);
|
|
142
|
+
fs.writeFileSync(`${file}.json`, JSON.stringify({
|
|
143
|
+
stage, include: token.getAttribute('include'), config: this.config,
|
|
144
|
+
}, null, '\t'));
|
|
136
145
|
}
|
|
137
146
|
throw e;
|
|
138
147
|
}
|
|
139
148
|
});
|
|
140
|
-
return
|
|
149
|
+
return token;
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
reparse(date) {
|
|
153
|
+
const path = `${__dirname}/errors/`,
|
|
154
|
+
main = fs.readdirSync(path).find(name => name.startsWith(date) && name.endsWith('Z'));
|
|
155
|
+
if (!main) {
|
|
156
|
+
throw new RangeError(`找不到对应时间戳的错误记录:${date}`);
|
|
157
|
+
}
|
|
158
|
+
const Token = require('./src'),
|
|
159
|
+
file = `${path}${main}`,
|
|
160
|
+
wikitext = fs.readFileSync(file, 'utf8'),
|
|
161
|
+
{stage, include, config} = require(`${file}.json`);
|
|
162
|
+
this.config = config;
|
|
163
|
+
return this.run(() => {
|
|
164
|
+
const halfParsed = stage < this.MAX_STAGE,
|
|
165
|
+
token = new Token(wikitext, this.getConfig(), halfParsed);
|
|
166
|
+
if (halfParsed) {
|
|
167
|
+
token.setAttribute('stage', stage).parseOnce(stage, include);
|
|
168
|
+
} else {
|
|
169
|
+
token.parse(undefined, include);
|
|
170
|
+
}
|
|
171
|
+
fs.unlinkSync(file);
|
|
172
|
+
fs.unlinkSync(`${file}.err`);
|
|
173
|
+
fs.unlinkSync(`${file}.json`);
|
|
174
|
+
return token;
|
|
175
|
+
});
|
|
141
176
|
},
|
|
142
177
|
|
|
143
178
|
getTool() {
|
|
144
179
|
delete require.cache[require.resolve('./tool')];
|
|
145
180
|
return require('./tool');
|
|
146
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
|
+
},
|
|
147
223
|
};
|
|
148
224
|
|
|
149
225
|
const /** @type {PropertyDescriptorMap} */ def = {};
|
package/lib/element.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
{
|
|
3
|
+
const fs = require('fs'),
|
|
4
|
+
{externalUse} = require('../util/debug'),
|
|
5
|
+
{toCase, noWrap} = require('../util/string'),
|
|
5
6
|
{nth} = require('./ranges'),
|
|
6
7
|
EventEmitter = require('events'),
|
|
7
8
|
AstNode = require('./node'),
|
|
@@ -93,7 +94,7 @@ class AstElement extends AstNode {
|
|
|
93
94
|
this.addEventListener(type, listener, options);
|
|
94
95
|
}
|
|
95
96
|
} else if (typeof types !== 'string' || typeof listener !== 'function') {
|
|
96
|
-
typeError(
|
|
97
|
+
this.typeError('addEventListener', 'String', 'Function');
|
|
97
98
|
} else {
|
|
98
99
|
this.#events[options?.once ? 'once' : 'on'](types, listener);
|
|
99
100
|
}
|
|
@@ -109,7 +110,7 @@ class AstElement extends AstNode {
|
|
|
109
110
|
this.removeEventListener(type, listener);
|
|
110
111
|
}
|
|
111
112
|
} else if (typeof types !== 'string' || typeof listener !== 'function') {
|
|
112
|
-
typeError(
|
|
113
|
+
this.typeError('removeEventListener', 'String', 'Function');
|
|
113
114
|
} else {
|
|
114
115
|
this.#events.off(types, listener);
|
|
115
116
|
}
|
|
@@ -122,7 +123,7 @@ class AstElement extends AstNode {
|
|
|
122
123
|
this.removeAllEventListeners(type);
|
|
123
124
|
}
|
|
124
125
|
} else if (types !== undefined && typeof types !== 'string') {
|
|
125
|
-
typeError(
|
|
126
|
+
this.typeError('removeAllEventListeners', 'String');
|
|
126
127
|
} else {
|
|
127
128
|
this.#events.removeAllListeners(types);
|
|
128
129
|
}
|
|
@@ -134,7 +135,7 @@ class AstElement extends AstNode {
|
|
|
134
135
|
*/
|
|
135
136
|
listEventListeners(type) {
|
|
136
137
|
if (typeof type !== 'string') {
|
|
137
|
-
typeError(
|
|
138
|
+
this.typeError('listEventListeners', 'String');
|
|
138
139
|
}
|
|
139
140
|
return this.#events.listeners(type);
|
|
140
141
|
}
|
|
@@ -145,7 +146,7 @@ class AstElement extends AstNode {
|
|
|
145
146
|
*/
|
|
146
147
|
dispatchEvent(e, data) {
|
|
147
148
|
if (!(e instanceof Event)) {
|
|
148
|
-
typeError(
|
|
149
|
+
this.typeError('dispatchEvent', 'Event');
|
|
149
150
|
} else if (!e.target) { // 初始化
|
|
150
151
|
Object.defineProperty(e, 'target', {value: this, enumerable: true});
|
|
151
152
|
e.stopPropagation = function() {
|
|
@@ -357,7 +358,7 @@ class AstElement extends AstNode {
|
|
|
357
358
|
*/
|
|
358
359
|
matches(selector = '', simple = false) {
|
|
359
360
|
if (typeof selector !== 'string') {
|
|
360
|
-
typeError(
|
|
361
|
+
this.typeError('matches', 'String');
|
|
361
362
|
} else if (!selector.trim()) {
|
|
362
363
|
return true;
|
|
363
364
|
}
|
|
@@ -401,7 +402,8 @@ class AstElement extends AstNode {
|
|
|
401
402
|
),
|
|
402
403
|
[type, ...parts] = plainSelector.trim().split('#'),
|
|
403
404
|
name = parts.join('#');
|
|
404
|
-
return (!type || this.type === type
|
|
405
|
+
return (!type || this.type === type || Boolean(Parser.typeAliases[this.type]?.includes(type)))
|
|
406
|
+
&& (!name || this.name === name)
|
|
405
407
|
&& attributes.every(args => this.matchesAttr(...args));
|
|
406
408
|
}
|
|
407
409
|
/*
|
|
@@ -479,7 +481,7 @@ class AstElement extends AstNode {
|
|
|
479
481
|
*/
|
|
480
482
|
comparePosition(other) {
|
|
481
483
|
if (!(other instanceof AstElement)) {
|
|
482
|
-
typeError(
|
|
484
|
+
this.typeError('comparePosition', 'AstElement');
|
|
483
485
|
} else if (this === other) {
|
|
484
486
|
return 0;
|
|
485
487
|
} else if (this.contains(other)) {
|
|
@@ -541,7 +543,7 @@ class AstElement extends AstNode {
|
|
|
541
543
|
*/
|
|
542
544
|
posFromIndex(index) {
|
|
543
545
|
if (typeof index !== 'number') {
|
|
544
|
-
typeError(
|
|
546
|
+
this.typeError('posFromIndex', 'Number');
|
|
545
547
|
}
|
|
546
548
|
const text = this.toString();
|
|
547
549
|
if (index < -text.length || index >= text.length || !Number.isInteger(index)) {
|
|
@@ -558,7 +560,7 @@ class AstElement extends AstNode {
|
|
|
558
560
|
*/
|
|
559
561
|
indexFromPos(top, left) {
|
|
560
562
|
if (typeof top !== 'number' || typeof left !== 'number') {
|
|
561
|
-
typeError(
|
|
563
|
+
this.typeError('indexFromPos', 'Number');
|
|
562
564
|
} else if (top < 0 || left < 0 || !Number.isInteger(top) || !Number.isInteger(left)) {
|
|
563
565
|
return;
|
|
564
566
|
}
|
|
@@ -582,7 +584,7 @@ class AstElement extends AstNode {
|
|
|
582
584
|
*/
|
|
583
585
|
getRelativeIndex(j) {
|
|
584
586
|
if (j !== undefined && typeof j !== 'number') {
|
|
585
|
-
typeError(
|
|
587
|
+
this.typeError('getRelativeIndex', 'Number');
|
|
586
588
|
}
|
|
587
589
|
let /** @type {(string|this)[]} */ childNodes;
|
|
588
590
|
/**
|
|
@@ -684,6 +686,63 @@ class AstElement extends AstNode {
|
|
|
684
686
|
return node ? [[index + this.getRelativeIndex(i), node]] : [];
|
|
685
687
|
});
|
|
686
688
|
}
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* @template {'markup'|'json'} T
|
|
692
|
+
* @param {T} format
|
|
693
|
+
* @param {T extends 'markup' ? number : string} depth
|
|
694
|
+
* @returns {T extends 'markup' ? void : Record<string, any>}
|
|
695
|
+
*/
|
|
696
|
+
print(format = 'markup', depth = 0) {
|
|
697
|
+
if (format === 'json') {
|
|
698
|
+
const {childNodes, ...prop} = this,
|
|
699
|
+
json = {
|
|
700
|
+
...prop,
|
|
701
|
+
childNodes: childNodes.map(child => typeof child === 'string' ? child : child.print('json')),
|
|
702
|
+
};
|
|
703
|
+
if (typeof depth === 'string') {
|
|
704
|
+
fs.writeFileSync(
|
|
705
|
+
`${__dirname.slice(0, -3)}printed/${depth}${depth.endsWith('.json') ? '' : '.json'}`,
|
|
706
|
+
JSON.stringify(json, null, 2),
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
return json;
|
|
710
|
+
} else if (typeof depth !== 'number') {
|
|
711
|
+
this.typeError('print', 'Number');
|
|
712
|
+
}
|
|
713
|
+
const indent = ' '.repeat(depth),
|
|
714
|
+
str = this.toString(),
|
|
715
|
+
{childNodes, type, firstChild} = this,
|
|
716
|
+
{length} = childNodes;
|
|
717
|
+
if (!str || length === 0 || typeof firstChild === 'string' && firstChild === str) {
|
|
718
|
+
console.log(`${indent}\x1b[32m<%s>\x1b[0m${noWrap(str)}\x1b[32m</%s>\x1b[0m`, type, type);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
Parser.info(`${indent}<${type}>`);
|
|
722
|
+
let i = this.getPadding();
|
|
723
|
+
if (i) {
|
|
724
|
+
console.log(`${indent} ${noWrap(str.slice(0, i))}`);
|
|
725
|
+
}
|
|
726
|
+
for (const [j, child] of childNodes.entries()) {
|
|
727
|
+
const childStr = String(child),
|
|
728
|
+
gap = j === length - 1 ? 0 : this.getGaps(j);
|
|
729
|
+
if (!childStr) {
|
|
730
|
+
// pass
|
|
731
|
+
} else if (typeof child === 'string') {
|
|
732
|
+
console.log(`${indent} ${noWrap(child)}`);
|
|
733
|
+
} else {
|
|
734
|
+
child.print('markup', depth + 1);
|
|
735
|
+
}
|
|
736
|
+
i += childStr.length + gap;
|
|
737
|
+
if (gap) {
|
|
738
|
+
console.log(`${indent} ${noWrap(str.slice(i - gap, i))}`);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
if (i < str.length) {
|
|
742
|
+
console.log(`${indent} ${noWrap(str.slice(i))}`);
|
|
743
|
+
}
|
|
744
|
+
Parser.info(`${indent}</${type}>`);
|
|
745
|
+
}
|
|
687
746
|
}
|
|
688
747
|
|
|
689
748
|
Parser.classes.AstElement = __filename;
|