wikiparser-node 0.3.1 → 0.5.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.
Files changed (80) hide show
  1. package/README.md +1 -1
  2. package/config/default.json +13 -17
  3. package/config/llwiki.json +11 -79
  4. package/config/moegirl.json +7 -1
  5. package/config/zhwiki.json +1269 -0
  6. package/index.js +130 -97
  7. package/lib/element.js +410 -518
  8. package/lib/node.js +493 -115
  9. package/lib/ranges.js +27 -19
  10. package/lib/text.js +175 -0
  11. package/lib/title.js +14 -6
  12. package/mixin/attributeParent.js +70 -24
  13. package/mixin/fixedToken.js +18 -10
  14. package/mixin/hidden.js +6 -4
  15. package/mixin/sol.js +39 -12
  16. package/package.json +17 -4
  17. package/parser/brackets.js +18 -18
  18. package/parser/commentAndExt.js +16 -14
  19. package/parser/converter.js +14 -13
  20. package/parser/externalLinks.js +12 -11
  21. package/parser/hrAndDoubleUnderscore.js +24 -14
  22. package/parser/html.js +8 -7
  23. package/parser/links.js +13 -13
  24. package/parser/list.js +12 -11
  25. package/parser/magicLinks.js +11 -10
  26. package/parser/quotes.js +6 -5
  27. package/parser/selector.js +175 -0
  28. package/parser/table.js +31 -24
  29. package/src/arg.js +91 -43
  30. package/src/atom/hidden.js +5 -2
  31. package/src/atom/index.js +17 -9
  32. package/src/attribute.js +210 -101
  33. package/src/converter.js +78 -43
  34. package/src/converterFlags.js +104 -45
  35. package/src/converterRule.js +136 -78
  36. package/src/extLink.js +81 -27
  37. package/src/gallery.js +63 -20
  38. package/src/heading.js +58 -20
  39. package/src/html.js +138 -48
  40. package/src/imageParameter.js +93 -58
  41. package/src/index.js +314 -186
  42. package/src/link/category.js +22 -54
  43. package/src/link/file.js +83 -32
  44. package/src/link/galleryImage.js +21 -7
  45. package/src/link/index.js +170 -81
  46. package/src/magicLink.js +64 -14
  47. package/src/nowiki/comment.js +36 -10
  48. package/src/nowiki/dd.js +37 -22
  49. package/src/nowiki/doubleUnderscore.js +21 -7
  50. package/src/nowiki/hr.js +11 -7
  51. package/src/nowiki/index.js +16 -9
  52. package/src/nowiki/list.js +2 -2
  53. package/src/nowiki/noinclude.js +8 -4
  54. package/src/nowiki/quote.js +38 -7
  55. package/src/onlyinclude.js +24 -7
  56. package/src/parameter.js +102 -62
  57. package/src/syntax.js +23 -20
  58. package/src/table/index.js +282 -174
  59. package/src/table/td.js +112 -61
  60. package/src/table/tr.js +135 -74
  61. package/src/tagPair/ext.js +30 -23
  62. package/src/tagPair/include.js +26 -11
  63. package/src/tagPair/index.js +72 -29
  64. package/src/transclude.js +235 -127
  65. package/tool/index.js +42 -32
  66. package/util/debug.js +21 -18
  67. package/util/diff.js +76 -0
  68. package/util/lint.js +40 -0
  69. package/util/string.js +56 -26
  70. package/.eslintrc.json +0 -319
  71. package/errors/README +0 -1
  72. package/jsconfig.json +0 -7
  73. package/printed/README +0 -1
  74. package/typings/element.d.ts +0 -28
  75. package/typings/index.d.ts +0 -52
  76. package/typings/node.d.ts +0 -23
  77. package/typings/parser.d.ts +0 -9
  78. package/typings/table.d.ts +0 -14
  79. package/typings/token.d.ts +0 -22
  80. package/typings/tool.d.ts +0 -10
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
- /** @type {Parser} */ Parser = require('../..'),
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,54 +17,73 @@ class TdToken extends fixedToken(TrToken) {
14
17
  type = 'td';
15
18
  #innerSyntax = '';
16
19
 
17
- /** @complexity `n` */
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.lastChild.text();
53
+ }
54
+
55
+ /** 是否位于行首 */
38
56
  isIndependent() {
39
- return this.firstElementChild.text().startsWith('\n');
57
+ return this.firstChild.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
- const syntax = this.firstElementChild.text(),
48
- esc = syntax.includes('{{');
66
+ const syntax = this.firstChild.text(),
67
+ esc = syntax.includes('{{'),
68
+ char = syntax.at(-1);
49
69
  let subtype = 'td';
50
- if (syntax.endsWith('!')) {
70
+ if (char === '!') {
51
71
  subtype = 'th';
52
- } else if (syntax.endsWith('+')) {
72
+ } else if (char === '+') {
53
73
  subtype = 'caption';
54
74
  }
55
75
  if (this.isIndependent()) {
56
76
  return {subtype, escape: esc, correction: false};
57
77
  }
58
- const {previousElementSibling} = this;
59
- if (previousElementSibling?.type !== 'td') {
78
+ const {previousSibling} = this;
79
+ if (previousSibling?.type !== 'td') {
60
80
  return {subtype, escape: esc, correction: true};
61
81
  }
62
- const result = previousElementSibling.getSyntax();
82
+ const result = previousSibling.getSyntax();
63
83
  result.escape ||= esc;
64
- result.correction = previousElementSibling.lastElementChild.offsetHeight > 1;
84
+ result.correction = previousSibling.lastChild
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+!\x7f/.exec(inner),
104
+ let innerSyntax = inner?.match(/\||\0\d+!\x7F/u),
86
105
  attr = innerSyntax ? inner.slice(0, innerSyntax.index) : '';
87
- if (/\[\[|-\{/.test(attr)) {
106
+ if (/\[\[|-\{/u.test(attr)) {
88
107
  innerSyntax = null;
89
108
  attr = '';
90
109
  }
91
- super(syntax, attr, config, accum, TdToken.openingPattern);
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']).appendChild(innerToken.setAttribute('stage', 4));
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,21 +127,24 @@ class TdToken extends fixedToken(TrToken) {
106
127
  }
107
128
 
108
129
  /**
109
- * @param {string|Token} inner
110
- * @param {'td'|'th'|'caption'} subtype
111
- * @param {Record<string, string>} attr
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 (!['td', 'th', 'caption'].includes(subtype)) {
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);
120
144
  }
121
145
  const token = Parser.run(() => new TdToken('\n|', undefined, config));
122
146
  token.setSyntax(subtype);
123
- token.lastElementChild.safeReplaceWith(inner);
147
+ token.lastChild.safeReplaceWith(inner);
124
148
  for (const [k, v] of Object.entries(attr)) {
125
149
  token.setAttr(k, v);
126
150
  }
@@ -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
- if (key === 'innerSyntax') {
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
- * @return {this}
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,102 +179,129 @@ 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
- static #aliases = {td: '\n|', th: '\n!', caption: '\n|+'};
166
-
167
- /** @param {string} syntax */
168
- setSyntax(syntax, esc = false) {
169
- super.setSyntax(TdToken.#aliases[syntax] ?? syntax, esc);
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
- /** @complexity `n` */
199
+ /**
200
+ * 修复\<td\>语法
201
+ * @complexity `n`
202
+ */
173
203
  #correct() {
174
- if (this.children[1].toString()) {
204
+ if (String(this.childNodes[1])) {
175
205
  this.#innerSyntax ||= '|';
176
206
  }
177
- const {subtype, escape: esc, correction} = this.getSyntax();
207
+ const {subtype, escape, correction} = this.getSyntax();
178
208
  if (correction) {
179
- this.setSyntax(subtype, esc);
209
+ this.setSyntax(subtype, escape);
180
210
  }
181
211
  }
182
212
 
183
- /** @complexity `n` */
213
+ /**
214
+ * 改为独占一行
215
+ * @complexity `n`
216
+ */
184
217
  independence() {
185
218
  if (!this.isIndependent()) {
186
- const {subtype, escape: esc} = this.getSyntax();
187
- this.setSyntax(subtype, esc);
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.children;
198
- return `${syntax.toString()}${attr.toString()}${this.#innerSyntax}${inner.toString()}`;
232
+ const {childNodes: [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
- if (i !== 1) {
204
- return 0;
244
+ if (i === 1) {
245
+ this.#correct();
246
+ return this.#innerSyntax.length;
205
247
  }
206
- this.#correct();
207
- return this.#innerSyntax.length;
248
+ return 0;
249
+ }
250
+
251
+ /** @override */
252
+ print() {
253
+ const {childNodes: [syntax, attr, inner]} = this;
254
+ return `<span class="wpb-td">${syntax.print()}${attr.print()}${this.#innerSyntax}${inner.print()}</span>`;
208
255
  }
209
256
 
210
257
  /**
258
+ * @override
211
259
  * @returns {string}
212
260
  * @complexity `n`
213
261
  */
214
262
  text() {
215
263
  this.#correct();
216
- const [syntax, attr, inner] = this.children;
264
+ const {childNodes: [syntax, attr, inner]} = this;
217
265
  return `${syntax.text()}${attr.text()}${this.#innerSyntax}${inner.text()}`;
218
266
  }
219
267
 
220
268
  /**
269
+ * 获取单元格属性
221
270
  * @template {string} T
222
- * @param {T} key
271
+ * @param {T} key 属性键
223
272
  * @returns {T extends 'rowspan'|'colspan' ? number : Record<string, string|true>}
224
273
  */
225
274
  getAttr(key) {
226
275
  const /** @type {string|true} */ value = super.getAttr(key);
227
276
  key = key?.toLowerCase()?.trim();
228
- return ['rowspan', 'colspan'].includes(key) ? Number(value) || 1 : value;
277
+ return key === 'rowspan' || key === 'colspan' ? Number(value) || 1 : value;
229
278
  }
230
279
 
231
280
  /**
281
+ * 设置单元格属性
232
282
  * @template {string} T
233
- * @param {T} key
234
- * @param {T extends 'rowspan'|'colspan' ? number : string|boolean} value
283
+ * @param {T} key 属性键
284
+ * @param {T extends 'rowspan'|'colspan' ? number : string|boolean} value 属性值
235
285
  */
236
286
  setAttr(key, value) {
237
287
  if (typeof key !== 'string') {
238
288
  this.typeError('setAttr', 'String');
239
289
  }
240
290
  key = key.toLowerCase().trim();
241
- if (typeof value === 'number' && ['rowspan', 'colspan'].includes(key)) {
291
+ if (typeof value === 'number' && (key === 'rowspan' || key === 'colspan')) {
242
292
  value = value === 1 ? false : String(value);
243
293
  }
244
294
  const /** @type {boolean} */ result = super.setAttr(key, value);
245
- if (!this.children[1].toString()) {
295
+ if (!String(this.childNodes[1])) {
246
296
  this.#innerSyntax = '';
247
297
  }
248
298
  return result;
249
299
  }
250
300
 
301
+ /** @override */
251
302
  escape() {
252
303
  super.escape();
253
- if (this.children[1].toString()) {
304
+ if (String(this.childNodes[1])) {
254
305
  this.#innerSyntax ||= '{{!}}';
255
306
  }
256
307
  if (this.#innerSyntax === '|') {