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
@@ -1,41 +1,39 @@
1
1
  'use strict';
2
2
 
3
- const {text, noWrap, extUrlChar} = require('../util/string'),
4
- Title = require('../lib/title'),
5
- /** @type {Parser} */ Parser = require('..'),
6
- Token = require('.');
3
+ const {text, noWrap, print, extUrlChar} = require('../util/string'),
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(/\0\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 = RegExp(`(?:${config.protocol}|//)${extUrlChar}(?=\0\\d+t\x7f|$)`, 'iu');
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,36 @@ 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);
79
92
  return {width: text(token.childNodes.slice(0, i + 1)), height: text(token.childNodes.slice(i + 2))};
80
93
  }
81
94
  return undefined;
82
95
  }
96
+
97
+ /** 图片宽度 */
83
98
  get width() {
84
99
  return this.size?.width;
85
100
  }
101
+
86
102
  set width(width) {
87
103
  if (this.name === 'width') {
88
104
  const {height} = this;
89
105
  this.setValue(`${String(width || '')}${height && 'x'}${height}`);
90
106
  }
91
107
  }
108
+
109
+ /** 图片高度 */
92
110
  get height() {
93
111
  return this.size?.height;
94
112
  }
113
+
95
114
  set height(height) {
96
115
  height = String(height || '');
97
116
  if (this.name === 'width') {
@@ -100,20 +119,18 @@ class ImageParameterToken extends Token {
100
119
  }
101
120
 
102
121
  /**
103
- * @param {string} str
122
+ * @param {string} str 图片参数
104
123
  * @param {accum} accum
105
124
  */
106
125
  constructor(str, config = Parser.getConfig(), accum = []) {
107
126
  const regexes = Object.entries(config.img).map(
108
127
  /** @returns {[string, string, RegExp]} */
109
- ([syntax, param]) => [syntax, param, RegExp(`^(\\s*)${syntax.replace('$1', '(.*)')}(\\s*)$`)],
128
+ ([syntax, param]) => [syntax, param, new RegExp(`^(\\s*)${syntax.replace('$1', '(.*)')}(\\s*)$`, 'u')],
110
129
  ),
111
130
  param = regexes.find(([,, regex]) => regex.test(str));
112
131
  if (param) {
113
132
  const mt = param[2].exec(str);
114
- if (mt.length === 4 && !ImageParameterToken.#validate(param[1], mt[2], config)) {
115
- // pass
116
- } else {
133
+ if (mt.length !== 4 || ImageParameterToken.#validate(param[1], mt[2], config, true)) {
117
134
  if (mt.length === 3) {
118
135
  super(undefined, config, true, accum);
119
136
  this.#syntax = str;
@@ -129,8 +146,9 @@ class ImageParameterToken extends Token {
129
146
  this.setAttribute('name', 'caption').setAttribute('stage', 7);
130
147
  }
131
148
 
149
+ /** @override */
132
150
  cloneNode() {
133
- const cloned = this.cloneChildren(),
151
+ const cloned = this.cloneChildNodes(),
134
152
  config = this.getAttribute('config'),
135
153
  token = Parser.run(() => new ImageParameterToken(this.#syntax.replace('$1', ''), config));
136
154
  token.replaceChildren(...cloned);
@@ -138,47 +156,59 @@ class ImageParameterToken extends Token {
138
156
  }
139
157
 
140
158
  /**
159
+ * @override
141
160
  * @template {string} T
142
- * @param {T} key
161
+ * @param {T} key 属性键
143
162
  * @returns {TokenAttribute<T>}
144
163
  */
145
164
  getAttribute(key) {
146
- if (key === 'syntax') {
147
- return this.#syntax;
148
- }
149
- return super.getAttribute(key);
165
+ return key === 'syntax' ? this.#syntax : super.getAttribute(key);
150
166
  }
151
167
 
168
+ /** @override */
152
169
  isPlain() {
153
170
  return true;
154
171
  }
155
172
 
173
+ /** 是否是不可变参数 */
156
174
  #isVoid() {
157
175
  return this.#syntax && !this.#syntax.includes('$1');
158
176
  }
159
177
 
160
- toString() {
161
- if (!this.#syntax) {
162
- return super.toString();
163
- }
164
- return this.#syntax.replace('$1', super.toString());
178
+ /**
179
+ * @override
180
+ * @param {string} selector
181
+ */
182
+ toString(selector) {
183
+ return this.#syntax && !(selector && this.matches(selector))
184
+ ? this.#syntax.replace('$1', super.toString(selector))
185
+ : super.toString(selector);
165
186
  }
166
187
 
188
+ /** @override */
167
189
  getPadding() {
168
190
  return Math.max(0, this.#syntax.indexOf('$1'));
169
191
  }
170
192
 
193
+ /** @override */
194
+ print() {
195
+ return this.#syntax
196
+ ? `<span class="wpb-image-parameter">${this.#syntax.replace('$1', print(this.childNodes))}</span>`
197
+ : super.print({class: 'image-caption'});
198
+ }
199
+
200
+ /** @override */
171
201
  text() {
172
- if (!this.#syntax) {
173
- return super.text().trim();
174
- }
175
- return this.#syntax.replace('$1', super.text()).trim();
202
+ return this.#syntax ? this.#syntax.replace('$1', super.text()).trim() : super.text().trim();
176
203
  }
177
204
 
178
205
  /**
179
- * @template {string|Token} T
180
- * @param {T} token
206
+ * @override
207
+ * @template {Token} T
208
+ * @param {T} token 待插入的子节点
209
+ * @param {number} i 插入位置
181
210
  * @complexity `n`
211
+ * @throws `Error` 不接受自定义输入的图片参数
182
212
  */
183
213
  insertAt(token, i = this.childNodes.length) {
184
214
  if (!Parser.running && this.#isVoid()) {
@@ -187,14 +217,19 @@ class ImageParameterToken extends Token {
187
217
  return super.insertAt(token, i);
188
218
  }
189
219
 
190
- /** @complexity `n` */
220
+ /**
221
+ * 获取参数值
222
+ * @complexity `n`
223
+ */
191
224
  getValue() {
192
225
  return this.#isVoid() || super.text();
193
226
  }
194
227
 
195
228
  /**
196
- * @param {string|boolean} value
229
+ * 设置参数值
230
+ * @param {string|boolean} value 参数值
197
231
  * @complexity `n`
232
+ * @throws SyntaxError` 非法的参数值
198
233
  */
199
234
  setValue(value) {
200
235
  if (this.#isVoid()) {
@@ -210,14 +245,14 @@ class ImageParameterToken extends Token {
210
245
  const root = Parser.parse(`[[File:F|${
211
246
  this.#syntax ? this.#syntax.replace('$1', value) : value
212
247
  }]]`, this.getAttribute('include'), 6, this.getAttribute('config')),
213
- {childNodes: {length}, firstElementChild} = root,
214
- param = firstElementChild?.lastElementChild;
215
- if (length !== 1 || !firstElementChild?.matches('file#File:F')
216
- || firstElementChild.childNodes.length !== 2 || param.name !== this.name
248
+ {childNodes: {length}, firstChild: file} = root,
249
+ {lastChild: imageParameter, type, name, childNodes: {length: fileLength}} = file;
250
+ if (length !== 1 || type !== 'file' || name !== 'File:F' || fileLength !== 2
251
+ || imageParameter.name !== this.name
217
252
  ) {
218
253
  throw new SyntaxError(`非法的 ${this.name} 参数:${noWrap(value)}`);
219
254
  }
220
- this.replaceChildren(...param.childNodes);
255
+ this.replaceChildren(...imageParameter.childNodes);
221
256
  }
222
257
  }
223
258