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
@@ -1,41 +1,39 @@
1
1
  'use strict';
2
2
 
3
3
  const {text, noWrap, extUrlChar} = require('../util/string'),
4
- Title = require('../lib/title'),
5
- /** @type {Parser} */ Parser = require('..'),
6
- Token = require('.');
4
+ Parser = require('..'),
5
+ Token = require('.'),
6
+ AstText = require('../lib/text');
7
7
 
8
8
  /**
9
9
  * 图片参数
10
- * @classdesc `{childNodes: ...(string|Token)}`
10
+ * @classdesc `{childNodes: ...(AstText|Token)}`
11
11
  */
12
12
  class ImageParameterToken extends Token {
13
- type = 'image-parameter';
14
- #syntax = '';
15
-
16
- static #noLink = Symbol('no-link');
13
+ static noLink = Symbol('no-link'); // 这个Symbol需要公开
17
14
 
18
15
  /**
16
+ * 检查图片参数是否合法
19
17
  * @template {string} T
20
- * @param {T} key
21
- * @param {string} value
18
+ * @param {T} key 参数名
19
+ * @param {string} value 参数值
22
20
  * @returns {T extends 'link' ? string|Symbol : boolean}
23
21
  */
24
- static #validate(key, value, config = Parser.getConfig()) {
25
- value = value.replace(/\x00\d+t\x7f/g, '').trim();
22
+ static #validate(key, value, config = Parser.getConfig(), halfParsed = false) {
23
+ value = value.replaceAll(/\0\d+t\x7F/gu, '').trim();
26
24
  if (key === 'width') {
27
- return /^\d*(?:x\d*)?$/.test(value);
25
+ return /^\d*(?:x\d*)?$/u.test(value);
28
26
  } else if (['alt', 'class', 'manualthumb', 'frameless', 'framed', 'thumbnail'].includes(key)) {
29
27
  return true;
30
28
  } else if (key === 'link') {
31
29
  if (!value) {
32
- return this.#noLink;
30
+ return this.noLink;
33
31
  }
34
- const regex = new RegExp(`(?:${config.protocol}|//)${extUrlChar}(?=\x00\\d+t\x7f|$)`, 'ui');
32
+ const regex = new RegExp(`(?:${config.protocol}|//)${extUrlChar}(?=\0\\d+t\x7F|$)`, 'iu');
35
33
  if (regex.test(value)) {
36
34
  return value;
37
35
  }
38
- if (/^\[\[.+]]$/.test(value)) {
36
+ if (value.startsWith('[[') && value.endsWith(']]')) {
39
37
  value = value.slice(2, -2);
40
38
  }
41
39
  if (value.includes('%')) {
@@ -43,24 +41,39 @@ class ImageParameterToken extends Token {
43
41
  value = decodeURIComponent(value);
44
42
  } catch {}
45
43
  }
46
- const {title, fragment, valid} = new Title(value, 0, config);
47
- return valid && `${title}${fragment && '#'}${fragment}`;
44
+ const title = Parser.normalizeTitle(value, 0, false, config, halfParsed);
45
+ return title.valid && String(title);
48
46
  }
49
47
  return !isNaN(value);
50
48
  }
51
49
 
50
+ type = 'image-parameter';
51
+ #syntax = '';
52
+
53
+ /** getValue()的getter */
54
+ get value() {
55
+ return this.getValue();
56
+ }
57
+
58
+ set value(value) {
59
+ this.setValue(value);
60
+ }
61
+
62
+ /** 图片链接 */
52
63
  get link() {
53
- if (this.name === 'link') {
54
- return ImageParameterToken.#validate('link', this.getValue(), this.getAttribute('config'));
55
- }
56
- return undefined;
64
+ return this.name === 'link'
65
+ ? ImageParameterToken.#validate('link', this.getValue(), this.getAttribute('config'))
66
+ : undefined;
57
67
  }
68
+
58
69
  set link(value) {
59
70
  if (this.name === 'link') {
60
- value = value === ImageParameterToken.#noLink ? '' : value;
71
+ value = value === ImageParameterToken.noLink ? '' : value;
61
72
  this.setValue(value);
62
73
  }
63
74
  }
75
+
76
+ /** 图片大小 */
64
77
  get size() {
65
78
  if (this.name === 'width') {
66
79
  const /** @type {string} */ size = this.getValue().trim();
@@ -68,30 +81,37 @@ class ImageParameterToken extends Token {
68
81
  const [width, height = ''] = size.split('x');
69
82
  return {width, height};
70
83
  }
71
- const token = Parser.parse(size, false, 2, this.getAttribute('config')),
72
- {childNodes} = token,
73
- i = childNodes.findIndex(child => typeof child === 'string' && child.includes('x'));
84
+ const /** @type {{childNodes: AstText[]}} */ token = Parser.parse(size, false, 2, this.getAttribute('config')),
85
+ i = token.childNodes.findIndex(({type, data}) => type === 'text' && data.includes('x')),
86
+ str = token.childNodes[i];
74
87
  if (i === -1) {
75
88
  return {width: size, height: ''};
76
89
  }
77
- token.splitText(i, childNodes[i].indexOf('x'));
78
- token.splitText(i + 1, 1);
90
+ str.splitText(str.data.indexOf('x'));
91
+ str.nextSibling.splitText(1);
92
+ // eslint-disable-next-line unicorn/consistent-destructuring
79
93
  return {width: text(token.childNodes.slice(0, i + 1)), height: text(token.childNodes.slice(i + 2))};
80
94
  }
81
95
  return undefined;
82
96
  }
97
+
98
+ /** 图片宽度 */
83
99
  get width() {
84
100
  return this.size?.width;
85
101
  }
102
+
86
103
  set width(width) {
87
104
  if (this.name === 'width') {
88
105
  const {height} = this;
89
106
  this.setValue(`${String(width || '')}${height && 'x'}${height}`);
90
107
  }
91
108
  }
109
+
110
+ /** 图片高度 */
92
111
  get height() {
93
112
  return this.size?.height;
94
113
  }
114
+
95
115
  set height(height) {
96
116
  height = String(height || '');
97
117
  if (this.name === 'width') {
@@ -100,20 +120,18 @@ class ImageParameterToken extends Token {
100
120
  }
101
121
 
102
122
  /**
103
- * @param {string} str
123
+ * @param {string} str 图片参数
104
124
  * @param {accum} accum
105
125
  */
106
126
  constructor(str, config = Parser.getConfig(), accum = []) {
107
127
  const regexes = Object.entries(config.img).map(
108
128
  /** @returns {[string, string, RegExp]} */
109
- ([syntax, param]) => [syntax, param, new RegExp(`^(\\s*)${syntax.replace('$1', '(.*)')}(\\s*)$`)],
129
+ ([syntax, param]) => [syntax, param, new RegExp(`^(\\s*)${syntax.replace('$1', '(.*)')}(\\s*)$`, 'u')],
110
130
  ),
111
131
  param = regexes.find(([,, regex]) => regex.test(str));
112
132
  if (param) {
113
- const mt = str.match(param[2]);
114
- if (mt.length === 4 && !ImageParameterToken.#validate(param[1], mt[2], config)) {
115
- // pass
116
- } else {
133
+ const mt = param[2].exec(str);
134
+ if (mt.length !== 4 || ImageParameterToken.#validate(param[1], mt[2], config, true)) {
117
135
  if (mt.length === 3) {
118
136
  super(undefined, config, true, accum);
119
137
  this.#syntax = str;
@@ -129,8 +147,9 @@ class ImageParameterToken extends Token {
129
147
  this.setAttribute('name', 'caption').setAttribute('stage', 7);
130
148
  }
131
149
 
150
+ /** @override */
132
151
  cloneNode() {
133
- const cloned = this.cloneChildren(),
152
+ const cloned = this.cloneChildNodes(),
134
153
  config = this.getAttribute('config'),
135
154
  token = Parser.run(() => new ImageParameterToken(this.#syntax.replace('$1', ''), config));
136
155
  token.replaceChildren(...cloned);
@@ -138,47 +157,52 @@ class ImageParameterToken extends Token {
138
157
  }
139
158
 
140
159
  /**
160
+ * @override
141
161
  * @template {string} T
142
- * @param {T} key
162
+ * @param {T} key 属性键
143
163
  * @returns {TokenAttribute<T>}
144
164
  */
145
165
  getAttribute(key) {
146
- if (key === 'syntax') {
147
- return this.#syntax;
148
- }
149
- return super.getAttribute(key);
166
+ return key === 'syntax' ? this.#syntax : super.getAttribute(key);
150
167
  }
151
168
 
169
+ /** @override */
152
170
  isPlain() {
153
171
  return true;
154
172
  }
155
173
 
174
+ /** 是否是不可变参数 */
156
175
  #isVoid() {
157
176
  return this.#syntax && !this.#syntax.includes('$1');
158
177
  }
159
178
 
160
- toString() {
161
- if (!this.#syntax) {
162
- return super.toString();
163
- }
164
- return this.#syntax.replace('$1', super.toString());
179
+ /**
180
+ * @override
181
+ * @param {string} selector
182
+ */
183
+ toString(selector) {
184
+ return this.#syntax && !(selector && this.matches(selector))
185
+ ? this.#syntax.replace('$1', super.toString(selector))
186
+ : super.toString(selector);
165
187
  }
166
188
 
189
+ /** @override */
167
190
  getPadding() {
168
191
  return Math.max(0, this.#syntax.indexOf('$1'));
169
192
  }
170
193
 
194
+ /** @override */
171
195
  text() {
172
- if (!this.#syntax) {
173
- return super.text().trim();
174
- }
175
- return this.#syntax.replace('$1', super.text()).trim();
196
+ return this.#syntax ? this.#syntax.replace('$1', super.text()).trim() : super.text().trim();
176
197
  }
177
198
 
178
199
  /**
179
- * @template {string|Token} T
180
- * @param {T} token
200
+ * @override
201
+ * @template {Token} T
202
+ * @param {T} token 待插入的子节点
203
+ * @param {number} i 插入位置
181
204
  * @complexity `n`
205
+ * @throws `Error` 不接受自定义输入的图片参数
182
206
  */
183
207
  insertAt(token, i = this.childNodes.length) {
184
208
  if (!Parser.running && this.#isVoid()) {
@@ -187,14 +211,19 @@ class ImageParameterToken extends Token {
187
211
  return super.insertAt(token, i);
188
212
  }
189
213
 
190
- /** @complexity `n` */
214
+ /**
215
+ * 获取参数值
216
+ * @complexity `n`
217
+ */
191
218
  getValue() {
192
219
  return this.#isVoid() || super.text();
193
220
  }
194
221
 
195
222
  /**
196
- * @param {string|boolean} value
223
+ * 设置参数值
224
+ * @param {string|boolean} value 参数值
197
225
  * @complexity `n`
226
+ * @throws SyntaxError` 非法的参数值
198
227
  */
199
228
  setValue(value) {
200
229
  if (this.#isVoid()) {
@@ -212,7 +241,7 @@ class ImageParameterToken extends Token {
212
241
  }]]`, this.getAttribute('include'), 6, this.getAttribute('config')),
213
242
  {childNodes: {length}, firstElementChild} = root,
214
243
  param = firstElementChild?.lastElementChild;
215
- if (length !== 1 || !firstElementChild?.matches('file#File:F')
244
+ if (length !== 1 || !firstElementChild?.matches('file#File\\:F')
216
245
  || firstElementChild.childNodes.length !== 2 || param.name !== this.name
217
246
  ) {
218
247
  throw new SyntaxError(`非法的 ${this.name} 参数:${noWrap(value)}`);