wikiparser-node 0.4.0 → 0.6.2-b

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 (86) hide show
  1. package/bundle/bundle.min.js +34 -0
  2. package/package.json +12 -5
  3. package/.eslintrc.json +0 -714
  4. package/README.md +0 -39
  5. package/config/default.json +0 -769
  6. package/config/llwiki.json +0 -630
  7. package/config/moegirl.json +0 -727
  8. package/config/zhwiki.json +0 -1269
  9. package/errors/README +0 -1
  10. package/index.js +0 -245
  11. package/jsconfig.json +0 -7
  12. package/lib/element.js +0 -755
  13. package/lib/node.js +0 -585
  14. package/lib/ranges.js +0 -131
  15. package/lib/text.js +0 -146
  16. package/lib/title.js +0 -69
  17. package/mixin/attributeParent.js +0 -113
  18. package/mixin/fixedToken.js +0 -40
  19. package/mixin/hidden.js +0 -19
  20. package/mixin/sol.js +0 -59
  21. package/parser/brackets.js +0 -112
  22. package/parser/commentAndExt.js +0 -63
  23. package/parser/converter.js +0 -45
  24. package/parser/externalLinks.js +0 -31
  25. package/parser/hrAndDoubleUnderscore.js +0 -35
  26. package/parser/html.js +0 -42
  27. package/parser/links.js +0 -98
  28. package/parser/list.js +0 -59
  29. package/parser/magicLinks.js +0 -41
  30. package/parser/quotes.js +0 -64
  31. package/parser/selector.js +0 -175
  32. package/parser/table.js +0 -112
  33. package/printed/README +0 -1
  34. package/printed/example.json +0 -120
  35. package/src/arg.js +0 -169
  36. package/src/atom/hidden.js +0 -13
  37. package/src/atom/index.js +0 -41
  38. package/src/attribute.js +0 -422
  39. package/src/converter.js +0 -157
  40. package/src/converterFlags.js +0 -232
  41. package/src/converterRule.js +0 -253
  42. package/src/extLink.js +0 -167
  43. package/src/gallery.js +0 -91
  44. package/src/heading.js +0 -100
  45. package/src/html.js +0 -202
  46. package/src/imageParameter.js +0 -254
  47. package/src/index.js +0 -737
  48. package/src/link/category.js +0 -53
  49. package/src/link/file.js +0 -265
  50. package/src/link/galleryImage.js +0 -61
  51. package/src/link/index.js +0 -322
  52. package/src/magicLink.js +0 -108
  53. package/src/nowiki/comment.js +0 -57
  54. package/src/nowiki/dd.js +0 -59
  55. package/src/nowiki/doubleUnderscore.js +0 -51
  56. package/src/nowiki/hr.js +0 -41
  57. package/src/nowiki/index.js +0 -44
  58. package/src/nowiki/list.js +0 -16
  59. package/src/nowiki/noinclude.js +0 -28
  60. package/src/nowiki/quote.js +0 -36
  61. package/src/onlyinclude.js +0 -54
  62. package/src/parameter.js +0 -187
  63. package/src/syntax.js +0 -83
  64. package/src/table/index.js +0 -967
  65. package/src/table/td.js +0 -308
  66. package/src/table/tr.js +0 -282
  67. package/src/tagPair/ext.js +0 -105
  68. package/src/tagPair/include.js +0 -50
  69. package/src/tagPair/index.js +0 -117
  70. package/src/transclude.js +0 -703
  71. package/test/api.js +0 -83
  72. package/test/real.js +0 -133
  73. package/test/test.js +0 -28
  74. package/test/util.js +0 -80
  75. package/tool/index.js +0 -918
  76. package/typings/api.d.ts +0 -13
  77. package/typings/array.d.ts +0 -28
  78. package/typings/event.d.ts +0 -24
  79. package/typings/index.d.ts +0 -94
  80. package/typings/node.d.ts +0 -29
  81. package/typings/parser.d.ts +0 -16
  82. package/typings/table.d.ts +0 -14
  83. package/typings/token.d.ts +0 -22
  84. package/typings/tool.d.ts +0 -11
  85. package/util/debug.js +0 -73
  86. package/util/string.js +0 -88
package/src/attribute.js DELETED
@@ -1,422 +0,0 @@
1
- 'use strict';
2
-
3
- const {externalUse} = require('../util/debug'),
4
- {toCase, removeComment, normalizeSpace} = require('../util/string'),
5
- Parser = require('..'),
6
- Token = require('.');
7
-
8
- const stages = {'ext-attr': 0, 'html-attr': 2, 'table-attr': 3};
9
-
10
- /**
11
- * 扩展和HTML标签属性
12
- * @classdesc `{childNodes: [AstText]|(AstText|ArgToken|TranscludeToken)[]}`
13
- */
14
- class AttributeToken extends Token {
15
- /** @type {Map<string, string|true>} */ #attr = new Map();
16
- #sanitized = true;
17
-
18
- /**
19
- * @override
20
- * @param {string} key 属性键
21
- * @param {string|undefined} equal 属性规则运算符,`equal`存在时`val`和`i`也一定存在
22
- * @param {string|undefined} val 属性值
23
- * @param {string|undefined} i 是否对大小写不敏感
24
- */
25
- #matchesAttr = (key, equal, val, i) => {
26
- if (!equal) {
27
- return this.hasAttr(key);
28
- } else if (!this.hasAttr(key)) {
29
- return equal === '!=';
30
- }
31
- val = toCase(val, i);
32
- const attr = this.getAttr(key),
33
- thisVal = toCase(attr === true ? '' : attr, i);
34
- switch (equal) {
35
- case '~=':
36
- return attr !== true && thisVal.split(/\s/u).includes(val);
37
- case '|=': // 允许`val === ''`
38
- return thisVal === val || thisVal.startsWith(`${val}-`);
39
- case '^=':
40
- return attr !== true && thisVal.startsWith(val);
41
- case '$=':
42
- return attr !== true && thisVal.endsWith(val);
43
- case '*=':
44
- return attr !== true && thisVal.includes(val);
45
- case '!=':
46
- return thisVal !== val;
47
- default: // `=`
48
- return thisVal === val;
49
- }
50
- };
51
-
52
- /**
53
- * getAttr()方法的getter写法
54
- * @returns {Record<string, string|true>}
55
- */
56
- get attributes() {
57
- return this.getAttr();
58
- }
59
-
60
- /** 以字符串表示的class属性 */
61
- get className() {
62
- const attr = this.getAttr('class');
63
- return typeof attr === 'string' ? attr : '';
64
- }
65
-
66
- set className(className) {
67
- this.setAttr('class', className);
68
- }
69
-
70
- /** 以Set表示的class属性 */
71
- get classList() {
72
- return new Set(this.className.split(/\s/u));
73
- }
74
-
75
- /** id属性 */
76
- get id() {
77
- const attr = this.getAttr('id');
78
- return typeof attr === 'string' ? attr : '';
79
- }
80
-
81
- set id(id) {
82
- this.setAttr('id', id);
83
- }
84
-
85
- /**
86
- * 从`this.#attr`更新`childNodes`
87
- * @complexity `n`
88
- */
89
- #updateFromAttr() {
90
- let equal = '=';
91
- const ParameterToken = require('./parameter');
92
- const parent = this.closest('ext, parameter');
93
- if (parent instanceof ParameterToken && parent.anon
94
- && parent.parentNode?.matches('template, magic-word#invoke')
95
- ) {
96
- equal = '{{=}}';
97
- }
98
- return [...this.#attr].map(([k, v]) => {
99
- if (v === true) {
100
- return k;
101
- }
102
- const quote = v.includes('"') ? "'" : '"';
103
- return `${k}${equal}${quote}${v}${quote}`;
104
- }).join(' ');
105
- }
106
-
107
- /**
108
- * 清理标签属性
109
- * @complexity `n`
110
- */
111
- sanitize() {
112
- if (!Parser.running && !this.#sanitized) {
113
- Parser.warn(`${this.constructor.name}.sanitize 方法将清理无效属性!`);
114
- }
115
- const token = Parser.parse(this.#updateFromAttr(), false, stages[this.type], this.getAttribute('config'));
116
- Parser.run(() => {
117
- this.replaceChildren(...token.childNodes, true);
118
- });
119
- this.#sanitized = true;
120
- }
121
-
122
- /**
123
- * 从`childNodes`更新`this.#attr`
124
- * @complexity `n`
125
- */
126
- #parseAttr() {
127
- this.#attr.clear();
128
- let string = this.toString('comment, include, noinclude, heading, html'),
129
- token;
130
- if (this.type !== 'ext-attr' && !Parser.running) {
131
- const config = this.getAttribute('config'),
132
- include = this.getAttribute('include');
133
- token = Parser.run(() => {
134
- const newToken = new Token(string, config),
135
- parseOnce = newToken.getAttribute('parseOnce');
136
- parseOnce(0, include);
137
- return parseOnce();
138
- });
139
- string = String(token);
140
- }
141
- string = removeComment(string).replaceAll(/\0\d+~\x7F/gu, '=');
142
-
143
- /**
144
- * 解析并重建标签属性
145
- * @param {string|boolean} str 半解析的标签属性文本
146
- */
147
- const build = str =>
148
- typeof str === 'boolean' || !token ? str : token.getAttribute('buildFromStr')(str).map(String).join('');
149
- for (const [, key,, quoted, unquoted] of string
150
- .matchAll(/([^\s/][^\s/=]*)(?:\s*=\s*(?:(["'])(.*?)(?:\2|$)|(\S*)))?/gsu)
151
- ) {
152
- if (!this.setAttr(build(key), build(quoted ?? unquoted ?? true), true)) {
153
- this.#sanitized = false;
154
- }
155
- }
156
- }
157
-
158
- /**
159
- * @param {string} attr 标签属性
160
- * @param {'ext-attr'|'html-attr'|'table-attr'} type 标签类型
161
- * @param {string} name 标签名
162
- * @param {accum} accum
163
- */
164
- constructor(attr, type, name, config = Parser.getConfig(), accum = []) {
165
- super(attr, config, true, accum, {[`Stage-${stages[type]}`]: ':'});
166
- this.type = type;
167
- this.setAttribute('name', name).#parseAttr();
168
- }
169
-
170
- /** @override */
171
- cloneNode() {
172
- const cloned = this.cloneChildNodes();
173
- return Parser.run(() => {
174
- const token = new AttributeToken(undefined, this.type, this.name, this.getAttribute('config'));
175
- token.append(...cloned);
176
- return token.afterBuild();
177
- });
178
- }
179
-
180
- /**
181
- * @override
182
- * @template {string} T
183
- * @param {T} key 属性键
184
- * @returns {TokenAttribute<T>}
185
- */
186
- getAttribute(key) {
187
- if (key === 'matchesAttr') {
188
- return this.#matchesAttr;
189
- }
190
- return key === 'attr' ? new Map(this.#attr) : super.getAttribute(key);
191
- }
192
-
193
- /** @override */
194
- afterBuild() {
195
- if (this.type !== 'ext-attr') {
196
- const buildFromStr = this.getAttribute('buildFromStr');
197
- for (let [key, text] of this.#attr) {
198
- let built = false;
199
- if (key.includes('\0')) {
200
- this.#attr.delete(key);
201
- key = buildFromStr(key).map(String).join('');
202
- built = true;
203
- }
204
- if (typeof text === 'string' && text.includes('\0')) {
205
- text = buildFromStr(text).map(String).join('');
206
- built = true;
207
- }
208
- if (built) {
209
- this.#attr.set(key, text);
210
- }
211
- }
212
- }
213
- const /** @type {AstListener} */ attributeListener = ({type, target}) => {
214
- if (type === 'text' || target !== this) {
215
- this.#parseAttr();
216
- }
217
- };
218
- this.addEventListener(['remove', 'insert', 'replace', 'text'], attributeListener);
219
- return this;
220
- }
221
-
222
- /**
223
- * 标签是否具有某属性
224
- * @param {string} key 属性键
225
- */
226
- hasAttr(key) {
227
- return typeof key === 'string' ? this.#attr.has(key.toLowerCase().trim()) : this.typeError('hasAttr', 'String');
228
- }
229
-
230
- /**
231
- * 获取标签属性
232
- * @template {string|undefined} T
233
- * @param {T} key 属性键
234
- * @returns {T extends string ? string|true : Record<string, string|true>}
235
- */
236
- getAttr(key) {
237
- if (key === undefined) {
238
- return Object.fromEntries(this.#attr);
239
- }
240
- return typeof key === 'string' ? this.#attr.get(key.toLowerCase().trim()) : this.typeError('getAttr', 'String');
241
- }
242
-
243
- /** 获取全部的标签属性名 */
244
- getAttrNames() {
245
- return [...this.#attr.keys()];
246
- }
247
-
248
- /** 标签是否具有任意属性 */
249
- hasAttrs() {
250
- return this.getAttrNames().length > 0;
251
- }
252
-
253
- /**
254
- * 设置标签属性
255
- * @param {string} key 属性键
256
- * @param {string|boolean} value 属性值
257
- * @param {boolean} init 是否是初次解析
258
- * @complexity `n`
259
- * @throws `RangeError` 扩展标签属性不能包含">"
260
- * @throws `RangeError` 无效的属性名
261
- */
262
- setAttr(key, value, init) {
263
- init &&= !externalUse('setAttr');
264
- if (typeof key !== 'string' || typeof value !== 'string' && typeof value !== 'boolean') {
265
- this.typeError('setAttr', 'String', 'Boolean');
266
- } else if (!init && this.type === 'ext-attr' && typeof value === 'string' && value.includes('>')) {
267
- throw new RangeError('扩展标签属性不能包含 ">"!');
268
- }
269
- key = key.toLowerCase().trim();
270
- const config = this.getAttribute('config'),
271
- include = this.getAttribute('include'),
272
- parsedKey = this.type === 'ext-attr' || init
273
- ? key
274
- : Parser.run(() => {
275
- const token = new Token(key, config),
276
- parseOnce = token.getAttribute('parseOnce');
277
- parseOnce(0, include);
278
- return String(parseOnce());
279
- });
280
- if (!/^(?:[\w:]|\0\d+[t!~{}+-]\x7F)(?:[\w:.-]|\0\d+[t!~{}+-]\x7F)*$/u.test(parsedKey)) {
281
- if (init) {
282
- return false;
283
- }
284
- throw new RangeError(`无效的属性名:${key}!`);
285
- } else if (value === false) {
286
- this.#attr.delete(key);
287
- } else {
288
- this.#attr.set(key, value === true ? true : value.replaceAll(/\s/gu, ' ').trim());
289
- }
290
- if (!init) {
291
- this.sanitize();
292
- }
293
- return true;
294
- }
295
-
296
- /**
297
- * 移除标签属性
298
- * @param {string} key 属性键
299
- * @complexity `n`
300
- */
301
- removeAttr(key) {
302
- if (typeof key !== 'string') {
303
- this.typeError('removeAttr', 'String');
304
- }
305
- key = key.toLowerCase().trim();
306
- if (this.#attr.delete(key)) {
307
- this.sanitize();
308
- }
309
- }
310
-
311
- /**
312
- * 开关标签属性
313
- * @param {string} key 属性键
314
- * @param {boolean|undefined} force 强制开启或关闭
315
- * @complexity `n`
316
- * @throws `RangeError` 不为Boolean类型的属性值
317
- */
318
- toggleAttr(key, force) {
319
- if (typeof key !== 'string') {
320
- this.typeError('toggleAttr', 'String');
321
- } else if (force !== undefined) {
322
- force = Boolean(force);
323
- }
324
- key = key.toLowerCase().trim();
325
- const value = this.#attr.has(key) ? this.#attr.get(key) : false;
326
- if (typeof value !== 'boolean') {
327
- throw new RangeError(`${key} 属性的值不为 Boolean!`);
328
- }
329
- this.setAttr(key, force === true || force === undefined && value === false);
330
- }
331
-
332
- /**
333
- * 生成引导空格
334
- * @param {string} str 属性字符串
335
- */
336
- #leadingSpace(str = super.toString()) {
337
- return this.type !== 'table-attr' && str && str.trimStart() === str ? ' ' : '';
338
- }
339
-
340
- /**
341
- * @override
342
- * @this {AttributeToken & Token}
343
- * @param {string} selector
344
- */
345
- toString(selector) {
346
- if (this.type === 'table-attr') {
347
- normalizeSpace(this);
348
- }
349
- const str = super.toString(selector);
350
- return `${this.#leadingSpace(str)}${str}`;
351
- }
352
-
353
- /** @override */
354
- getPadding() {
355
- return this.#leadingSpace().length;
356
- }
357
-
358
- /** @override */
359
- text() {
360
- if (this.type === 'table-attr') {
361
- normalizeSpace(this);
362
- }
363
- const str = this.#updateFromAttr();
364
- return `${this.#leadingSpace(str)}${str}`;
365
- }
366
-
367
- /**
368
- * @override
369
- * @param {number} i 移除位置
370
- * @param {boolean} done 是否已解析过改变后的标签属性
371
- * @complexity `n`
372
- */
373
- removeAt(i, done) {
374
- done &&= !externalUse('removeAt');
375
- done ||= Parser.running;
376
- const token = super.removeAt(i);
377
- if (!done) {
378
- this.#parseAttr();
379
- }
380
- return token;
381
- }
382
-
383
- /**
384
- * @override
385
- * @template {Token} T
386
- * @param {T} token 待插入的节点
387
- * @param {number} i 插入位置
388
- * @param {boolean} done 是否已解析过改变后的标签属性
389
- * @complexity `n`
390
- */
391
- insertAt(token, i = this.childNodes.length, done = false) {
392
- done &&= !externalUse('insertAt');
393
- done ||= Parser.running;
394
- super.insertAt(token, i);
395
- if (!done) {
396
- this.#parseAttr();
397
- }
398
- return token;
399
- }
400
-
401
- /**
402
- * @override
403
- * @param {...Token} elements 待替换的子节点
404
- * @complexity `n²`
405
- */
406
- replaceChildren(...elements) {
407
- let done = false;
408
- if (typeof elements.at(-1) === 'boolean') {
409
- done = elements.pop();
410
- }
411
- done &&= !externalUse('replaceChildren');
412
- for (let i = this.childNodes.length - 1; i >= 0; i--) {
413
- this.removeAt(i, done);
414
- }
415
- for (const element of elements) {
416
- this.insertAt(element, undefined, done);
417
- }
418
- }
419
- }
420
-
421
- Parser.classes.AttributeToken = __filename;
422
- module.exports = AttributeToken;
package/src/converter.js DELETED
@@ -1,157 +0,0 @@
1
- 'use strict';
2
-
3
- const {text} = require('../util/string'),
4
- 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
- * 是否无转换
18
- * @this {ConverterToken & {lastChild: ConverterRuleToken}}
19
- */
20
- get noConvert() {
21
- return this.hasFlag('R') || this.childNodes.length === 2 && !this.lastChild.variant;
22
- }
23
-
24
- /**
25
- * @param {string[]} flags 转换类型标记
26
- * @param {string[]} rules 转换规则
27
- * @param {accum} accum
28
- */
29
- constructor(flags, rules, config = Parser.getConfig(), accum = []) {
30
- super(undefined, config, true, accum);
31
- this.append(new ConverterFlagsToken(flags, config, accum));
32
- const [firstRule] = rules,
33
- hasColon = firstRule.includes(':'),
34
- firstRuleToken = new ConverterRuleToken(firstRule, hasColon, config, accum);
35
- if (hasColon && firstRuleToken.childNodes.length === 1) {
36
- this.appendChild(new ConverterRuleToken(rules.join(';'), false, config, accum));
37
- } else {
38
- this.append(
39
- firstRuleToken,
40
- ...rules.slice(1).map(rule => new ConverterRuleToken(rule, true, config, accum)),
41
- );
42
- }
43
- this.getAttribute('protectChildren')(0);
44
- }
45
-
46
- /** @override */
47
- cloneNode() {
48
- const [flags, ...rules] = this.cloneChildNodes(),
49
- token = Parser.run(() => new ConverterToken([], [], this.getAttribute('config')));
50
- token.firstElementChild.safeReplaceWith(flags);
51
- token.append(...rules);
52
- return token;
53
- }
54
-
55
- /**
56
- * @override
57
- * @param {string} selector
58
- */
59
- toString(selector) {
60
- const {children: [flags, ...rules]} = this;
61
- return selector && this.matches(selector)
62
- ? ''
63
- : `-{${flags.toString(selector)}${flags.childNodes.length > 0 ? '|' : ''}${rules.map(String).join(';')}}-`;
64
- }
65
-
66
- /** @override */
67
- getPadding() {
68
- return 2;
69
- }
70
-
71
- /**
72
- * /** @override
73
- * @param {number} i 子节点位置
74
- */
75
- getGaps(i = 0) {
76
- i = i < 0 ? i + this.childNodes.length : i;
77
- return i || this.firstElementChild.childNodes.length > 0 ? 1 : 0;
78
- }
79
-
80
- /** @override */
81
- text() {
82
- const {children: [flags, ...rules]} = this;
83
- return `-{${flags.text()}|${text(rules, ';')}}-`;
84
- }
85
-
86
- /**
87
- * 获取所有转换类型标记
88
- * @this {{firstChild: ConverterFlagsToken}}
89
- */
90
- getAllFlags() {
91
- return this.firstChild.getAllFlags();
92
- }
93
-
94
- /**
95
- * 获取有效的转换类型标记
96
- * @this {{firstChild: ConverterFlagsToken}}
97
- */
98
- getEffectiveFlags() {
99
- return this.firstChild.getEffectiveFlags();
100
- }
101
-
102
- /**
103
- * 获取未知的转换类型标记
104
- * @this {{firstChild: ConverterFlagsToken}}
105
- */
106
- getUnknownFlags() {
107
- return this.firstChild.getUnknownFlags();
108
- }
109
-
110
- /**
111
- * 是否具有某转换类型标记
112
- * @this {{firstChild: ConverterFlagsToken}}
113
- * @param {string} flag 转换类型标记
114
- */
115
- hasFlag(flag) {
116
- return this.firstChild.hasFlag(flag);
117
- }
118
-
119
- /**
120
- * 是否具有某有效的转换类型标记
121
- * @this {{firstChild: ConverterFlagsToken}}
122
- * @param {string} flag 转换类型标记
123
- */
124
- hasEffectiveFlag(flag) {
125
- return this.firstChild.hasEffectiveFlag(flag);
126
- }
127
-
128
- /**
129
- * 移除转换类型标记
130
- * @this {{firstChild: ConverterFlagsToken}}
131
- * @param {string} flag 转换类型标记
132
- */
133
- removeFlag(flag) {
134
- this.firstChild.removeFlag(flag);
135
- }
136
-
137
- /**
138
- * 设置转换类型标记
139
- * @this {{firstChild: ConverterFlagsToken}}
140
- * @param {string} flag 转换类型标记
141
- */
142
- setFlag(flag) {
143
- this.firstChild.setFlag(flag);
144
- }
145
-
146
- /**
147
- * 开关某转换类型标记
148
- * @this {{firstChild: ConverterFlagsToken}}
149
- * @param {string} flag 转换类型标记
150
- */
151
- toggleFlag(flag) {
152
- this.firstChild.toggleFlag(flag);
153
- }
154
- }
155
-
156
- Parser.classes.ConverterToken = __filename;
157
- module.exports = ConverterToken;