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.
Files changed (81) hide show
  1. package/.eslintrc.json +472 -34
  2. package/README.md +1 -1
  3. package/config/default.json +58 -30
  4. package/config/llwiki.json +22 -90
  5. package/config/moegirl.json +51 -13
  6. package/config/zhwiki.json +1269 -0
  7. package/index.js +114 -104
  8. package/lib/element.js +448 -440
  9. package/lib/node.js +335 -115
  10. package/lib/ranges.js +27 -18
  11. package/lib/text.js +146 -0
  12. package/lib/title.js +13 -5
  13. package/mixin/attributeParent.js +70 -24
  14. package/mixin/fixedToken.js +14 -6
  15. package/mixin/hidden.js +6 -4
  16. package/mixin/sol.js +27 -10
  17. package/package.json +9 -3
  18. package/parser/brackets.js +22 -17
  19. package/parser/commentAndExt.js +18 -16
  20. package/parser/converter.js +14 -13
  21. package/parser/externalLinks.js +12 -11
  22. package/parser/hrAndDoubleUnderscore.js +23 -14
  23. package/parser/html.js +10 -9
  24. package/parser/links.js +15 -14
  25. package/parser/list.js +12 -11
  26. package/parser/magicLinks.js +12 -11
  27. package/parser/quotes.js +6 -5
  28. package/parser/selector.js +175 -0
  29. package/parser/table.js +25 -18
  30. package/printed/example.json +120 -0
  31. package/src/arg.js +56 -32
  32. package/src/atom/hidden.js +5 -2
  33. package/src/atom/index.js +17 -9
  34. package/src/attribute.js +182 -100
  35. package/src/converter.js +68 -41
  36. package/src/converterFlags.js +67 -45
  37. package/src/converterRule.js +117 -65
  38. package/src/extLink.js +66 -18
  39. package/src/gallery.js +42 -15
  40. package/src/heading.js +34 -15
  41. package/src/html.js +97 -35
  42. package/src/imageParameter.js +83 -54
  43. package/src/index.js +299 -178
  44. package/src/link/category.js +20 -52
  45. package/src/link/file.js +59 -28
  46. package/src/link/galleryImage.js +21 -7
  47. package/src/link/index.js +146 -60
  48. package/src/magicLink.js +34 -12
  49. package/src/nowiki/comment.js +22 -10
  50. package/src/nowiki/dd.js +37 -22
  51. package/src/nowiki/doubleUnderscore.js +16 -7
  52. package/src/nowiki/hr.js +11 -7
  53. package/src/nowiki/index.js +16 -9
  54. package/src/nowiki/list.js +2 -2
  55. package/src/nowiki/noinclude.js +8 -4
  56. package/src/nowiki/quote.js +11 -7
  57. package/src/onlyinclude.js +19 -7
  58. package/src/parameter.js +65 -38
  59. package/src/syntax.js +26 -20
  60. package/src/table/index.js +260 -165
  61. package/src/table/td.js +98 -52
  62. package/src/table/tr.js +102 -58
  63. package/src/tagPair/ext.js +27 -19
  64. package/src/tagPair/include.js +16 -11
  65. package/src/tagPair/index.js +64 -29
  66. package/src/transclude.js +170 -93
  67. package/test/api.js +83 -0
  68. package/test/real.js +133 -0
  69. package/test/test.js +28 -0
  70. package/test/util.js +80 -0
  71. package/tool/index.js +41 -31
  72. package/typings/api.d.ts +13 -0
  73. package/typings/array.d.ts +28 -0
  74. package/typings/event.d.ts +24 -0
  75. package/typings/index.d.ts +46 -4
  76. package/typings/node.d.ts +15 -9
  77. package/typings/parser.d.ts +7 -0
  78. package/typings/tool.d.ts +3 -2
  79. package/util/debug.js +21 -18
  80. package/util/string.js +40 -27
  81. package/typings/element.d.ts +0 -28
package/index.js CHANGED
@@ -1,30 +1,106 @@
1
1
  'use strict';
2
2
 
3
3
  const fs = require('fs'),
4
+ path = require('path'),
4
5
  {text} = require('./util/string');
5
6
 
6
7
  const /** @type {Parser} */ Parser = {
7
8
  warning: true,
8
9
  debugging: false,
10
+ running: false,
11
+
12
+ config: './config/default',
13
+
14
+ MAX_STAGE: 11,
15
+
16
+ classes: {},
17
+ mixins: {},
18
+ parsers: {},
19
+
20
+ aliases: [
21
+ ['AstText'],
22
+ ['CommentToken', 'ExtToken', 'IncludeToken', 'NoincludeToken'],
23
+ ['ArgToken', 'TranscludeToken', 'HeadingToken'],
24
+ ['HtmlToken'],
25
+ ['TableToken'],
26
+ ['HrToken', 'DoubleUnderscoreToken'],
27
+ ['LinkToken', 'FileToken', 'CategoryToken'],
28
+ ['QuoteToken'],
29
+ ['ExtLinkToken'],
30
+ ['MagicLinkToken'],
31
+ ['ListToken', 'DdToken'],
32
+ ['ConverterToken'],
33
+ ],
34
+ typeAliases: {
35
+ include: ['includeonly'],
36
+ ext: ['extension'],
37
+ 'ext-attr': ['extension-attr'],
38
+ 'ext-inner': ['extension-inner'],
39
+ arg: ['argument'],
40
+ 'arg-name': ['argument-name'],
41
+ 'arg-default': ['argument-default'],
42
+ 'magic-word': ['parser-function', 'parser-func'],
43
+ 'invoke-function': ['invoke-func', 'lua-function', 'lua-func', 'module-function', 'module-func'],
44
+ 'invoke-module': ['lua-module'],
45
+ parameter: ['param'],
46
+ 'parameter-key': ['param-key'],
47
+ 'parameter-value': ['parameter-val', 'param-value', 'param-val'],
48
+ heading: ['header'],
49
+ 'heading-title': ['header-title'],
50
+ 'heading-trail': ['header-trail'],
51
+ 'table-attr': ['tr-attr', 'table-row-attr', 'td-attr', 'table-cell-attr', 'table-data-attr'],
52
+ tr: ['table-row'],
53
+ td: ['table-cell', 'table-data'],
54
+ 'td-inner': ['table-cell-inner', 'table-data-inner'],
55
+ 'double-underscore': ['underscore', 'behavior-switch', 'behaviour-switch'],
56
+ hr: ['horizontal'],
57
+ category: ['category-link', 'cat', 'cat-link'],
58
+ file: ['file-link', 'image', 'image-link', 'img', 'img-link'],
59
+ 'gallery-image': ['gallery-file', 'gallery-img'],
60
+ 'image-parameter': ['img-parameter', 'image-param', 'img-param'],
61
+ quote: ['quotes', 'quot', 'apostrophe', 'apostrophes', 'apos'],
62
+ 'ext-link': ['external-link'],
63
+ 'ext-link-text': ['external-link-text'],
64
+ 'ext-link-url': ['external-link-url'],
65
+ 'free-ext-link': ['free-external-link', 'magic-link'],
66
+ list: ['ol', 'ordered-list', 'ul', 'unordered-list', 'dl', 'description-list'],
67
+ dd: ['indent', 'indentation'],
68
+ converter: ['convert', 'conversion'],
69
+ 'converter-flags': ['convert-flags', 'conversion-flags'],
70
+ 'converter-flag': ['convert-flag', 'conversion-flag'],
71
+ 'converter-rule': ['convert-rule', 'conversion-rule'],
72
+ 'converter-rule-noconvert': ['convert-rule-noconvert', 'conversion-rule-noconvert'],
73
+ 'converter-rule-variant': ['convert-rule-variant', 'conversion-rule-variant'],
74
+ 'converter-rule-to': ['convert-rule-to', 'conversion-rule-to'],
75
+ 'converter-rule-from': ['convert-rule-from', 'conversion-rule-from'],
76
+ },
9
77
 
10
78
  warn(msg, ...args) {
11
79
  if (this.warning) {
12
- console.warn('\x1b[33m%s\x1b[0m', msg, ...args);
80
+ console.warn('\x1B[33m%s\x1B[0m', msg, ...args);
13
81
  }
14
82
  },
15
83
  debug(msg, ...args) {
16
84
  if (this.debugging) {
17
- console.debug('\x1b[34m%s\x1b[0m', msg, ...args);
85
+ console.debug('\x1B[34m%s\x1B[0m', msg, ...args);
18
86
  }
19
87
  },
20
88
  error(msg, ...args) {
21
- console.error('\x1b[31m%s\x1b[0m', msg, ...args);
89
+ console.error('\x1B[31m%s\x1B[0m', msg, ...args);
22
90
  },
23
91
  info(msg, ...args) {
24
- console.info('\x1b[32m%s\x1b[0m', msg, ...args);
92
+ console.info('\x1B[32m%s\x1B[0m', msg, ...args);
25
93
  },
26
94
 
27
- running: false,
95
+ log(f) {
96
+ if (typeof f === 'function') {
97
+ console.log(String(f));
98
+ }
99
+ },
100
+
101
+ getConfig() {
102
+ return require(this.config);
103
+ },
28
104
 
29
105
  run(callback) {
30
106
  const {running} = this;
@@ -39,74 +115,51 @@ const /** @type {Parser} */ Parser = {
39
115
  }
40
116
  },
41
117
 
42
- classes: {},
43
- mixins: {},
44
- parsers: {},
45
-
46
118
  clearCache() {
47
119
  const entries = [
48
120
  ...Object.entries(this.classes),
49
121
  ...Object.entries(this.mixins),
50
122
  ...Object.entries(this.parsers),
51
123
  ];
52
- for (const [, path] of entries) {
53
- delete require.cache[require.resolve(path)];
124
+ for (const [, filePath] of entries) {
125
+ delete require.cache[require.resolve(filePath)];
54
126
  }
55
- for (const [name, path] of entries) {
127
+ for (const [name, filePath] of entries) {
56
128
  if (name in global) {
57
- global[name] = require(path);
129
+ global[name] = require(filePath);
58
130
  }
59
131
  }
60
132
  },
61
133
 
62
- log(f) {
63
- if (typeof f === 'function') {
64
- console.log(f.toString());
65
- }
66
- },
67
-
68
- aliases: [
69
- ['String'],
70
- ['CommentToken', 'ExtToken', 'IncludeToken', 'NoincludeToken'],
71
- ['ArgToken', 'TranscludeToken', 'HeadingToken'],
72
- ['HtmlToken'],
73
- ['TableToken'],
74
- ['HrToken', 'DoubleUnderscoreToken'],
75
- ['LinkToken', 'FileToken', 'CategoryToken'],
76
- ['QuoteToken'],
77
- ['ExtLinkToken'],
78
- ['MagicLinkToken'],
79
- ['ListToken', 'DdToken'],
80
- ['ConverterToken'],
81
- ],
82
-
83
- config: './config/default',
84
-
85
- getConfig() {
86
- return require(this.config);
87
- },
88
-
89
134
  isInterwiki(title, {interwiki} = Parser.getConfig()) {
90
135
  title = String(title);
91
- return title.replaceAll('_', ' ').replace(/^\s*:?\s*/, '')
92
- .match(new RegExp(`^(${interwiki.join('|')})\\s*:`, 'i'));
136
+ return new RegExp(`^(${interwiki.join('|')})\\s*:`, 'iu')
137
+ .exec(title.replaceAll('_', ' ').replace(/^\s*:?\s*/u, ''));
93
138
  },
94
139
 
95
140
  normalizeTitle(title, defaultNs = 0, include = false, config = Parser.getConfig(), halfParsed = false) {
96
- title = String(title);
97
141
  let /** @type {Token} */ token;
98
142
  if (!halfParsed) {
99
143
  const Token = require('./src');
100
- token = this.run(() => new Token(title, config).parseOnce(0, include).parseOnce());
144
+ token = this.run(() => {
145
+ const newToken = new Token(String(title), config),
146
+ parseOnce = newToken.getAttribute('parseOnce');
147
+ parseOnce(0, include);
148
+ return parseOnce();
149
+ });
101
150
  title = token.firstChild;
102
151
  }
103
- const Title = require('./lib/title'),
104
- titleObj = new Title(title, defaultNs, config);
152
+ const Title = require('./lib/title');
153
+ const titleObj = new Title(String(title), defaultNs, config);
105
154
  if (token) {
106
- const build = /** @param {string[]} keys */ keys => {
155
+ /**
156
+ * 重建部分属性值
157
+ * @param {string[]} keys 属性键
158
+ */
159
+ const build = keys => {
107
160
  for (const key of keys) {
108
- if (titleObj[key].includes('\x00')) {
109
- titleObj[key] = text(token.buildFromStr(titleObj[key]));
161
+ if (titleObj[key].includes('\0')) {
162
+ titleObj[key] = text(token.getAttribute('buildFromStr')(titleObj[key]));
110
163
  }
111
164
  }
112
165
  };
@@ -117,9 +170,7 @@ const /** @type {Parser} */ Parser = {
117
170
  return titleObj;
118
171
  },
119
172
 
120
- MAX_STAGE: 11,
121
-
122
- parse(wikitext, include = false, maxStage = Parser.MAX_STAGE, config = Parser.getConfig()) {
173
+ parse(wikitext, include, maxStage = Parser.MAX_STAGE, config = Parser.getConfig()) {
123
174
  const Token = require('./src');
124
175
  let token;
125
176
  this.run(() => {
@@ -127,7 +178,7 @@ const /** @type {Parser} */ Parser = {
127
178
  token = new Token(wikitext, config);
128
179
  } else if (wikitext instanceof Token) {
129
180
  token = wikitext;
130
- wikitext = token.toString();
181
+ wikitext = String(token);
131
182
  } else {
132
183
  throw new TypeError('待解析的内容应为 String 或 Token!');
133
184
  }
@@ -135,9 +186,9 @@ const /** @type {Parser} */ Parser = {
135
186
  token.parse(maxStage, include);
136
187
  } catch (e) {
137
188
  if (e instanceof Error) {
138
- const file = `${__dirname}/errors/${new Date().toISOString()}`,
189
+ const file = path.join(__dirname, 'errors', new Date().toISOString()),
139
190
  stage = token.getAttribute('stage');
140
- fs.writeFileSync(file, stage === this.MAX_STAGE ? wikitext : token.toString());
191
+ fs.writeFileSync(file, stage === this.MAX_STAGE ? wikitext : String(token));
141
192
  fs.writeFileSync(`${file}.err`, e.stack);
142
193
  fs.writeFileSync(`${file}.json`, JSON.stringify({
143
194
  stage, include: token.getAttribute('include'), config: this.config,
@@ -150,21 +201,21 @@ const /** @type {Parser} */ Parser = {
150
201
  },
151
202
 
152
203
  reparse(date) {
153
- const path = `${__dirname}/errors/`,
154
- main = fs.readdirSync(path).find(name => name.startsWith(date) && name.endsWith('Z'));
204
+ const main = fs.readdirSync(path.join(__dirname, 'errors'))
205
+ .find(name => name.startsWith(date) && name.at(-1) === 'Z');
155
206
  if (!main) {
156
207
  throw new RangeError(`找不到对应时间戳的错误记录:${date}`);
157
208
  }
158
- const Token = require('./src'),
159
- file = `${path}${main}`,
160
- wikitext = fs.readFileSync(file, 'utf8'),
161
- {stage, include, config} = require(`${file}.json`);
209
+ const file = path.join(__dirname, 'errors', main),
210
+ wikitext = fs.readFileSync(file, 'utf8');
211
+ const {stage, include, config} = require(`${file}.json`),
212
+ Token = require('./src');
162
213
  this.config = config;
163
214
  return this.run(() => {
164
215
  const halfParsed = stage < this.MAX_STAGE,
165
216
  token = new Token(wikitext, this.getConfig(), halfParsed);
166
217
  if (halfParsed) {
167
- token.setAttribute('stage', stage).parseOnce(stage, include);
218
+ token.setAttribute('stage', stage).getAttribute('parseOnce')(stage, include);
168
219
  } else {
169
220
  token.parse(undefined, include);
170
221
  }
@@ -179,52 +230,11 @@ const /** @type {Parser} */ Parser = {
179
230
  delete require.cache[require.resolve('./tool')];
180
231
  return require('./tool');
181
232
  },
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
- },
223
233
  };
224
234
 
225
235
  const /** @type {PropertyDescriptorMap} */ def = {};
226
236
  for (const key in Parser) {
227
- if (['alises', 'MAX_STAGE'].includes(key)) {
237
+ if (['aliases', 'MAX_STAGE', 'typeAliases'].includes(key)) {
228
238
  def[key] = {enumerable: false, writable: false};
229
239
  } else if (!['config', 'isInterwiki', 'normalizeTitle', 'parse', 'getTool'].includes(key)) {
230
240
  def[key] = {enumerable: false};