wikiparser-node 1.21.0 → 1.21.2

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 (78) hide show
  1. package/README.md +42 -7
  2. package/bundle/bundle-es8.min.js +24 -24
  3. package/bundle/bundle-lsp.min.js +25 -25
  4. package/bundle/bundle.min.js +24 -24
  5. package/config/default.json +1 -0
  6. package/config/minimum.json +1 -0
  7. package/config/moegirl.json +1 -0
  8. package/coverage/badge.svg +1 -1
  9. package/dist/addon/table.js +5 -5
  10. package/dist/addon/token.js +129 -12
  11. package/dist/bin/config.js +3 -3
  12. package/dist/index.d.ts +7 -0
  13. package/dist/lib/attributes.js +1 -2
  14. package/dist/lib/element.d.ts +1 -0
  15. package/dist/lib/element.js +8 -4
  16. package/dist/lib/lsp.d.ts +2 -0
  17. package/dist/lib/lsp.js +5 -4
  18. package/dist/lib/node.d.ts +20 -3
  19. package/dist/lib/node.js +39 -17
  20. package/dist/lib/text.d.ts +2 -0
  21. package/dist/lib/text.js +17 -12
  22. package/dist/lib/title.d.ts +3 -1
  23. package/dist/lib/title.js +3 -1
  24. package/dist/mixin/sol.js +1 -1
  25. package/dist/parser/list.js +8 -5
  26. package/dist/parser/table.js +2 -2
  27. package/dist/src/arg.js +1 -1
  28. package/dist/src/atom.js +10 -0
  29. package/dist/src/attribute.d.ts +1 -0
  30. package/dist/src/attribute.js +53 -17
  31. package/dist/src/attributes.js +19 -9
  32. package/dist/src/converter.js +1 -1
  33. package/dist/src/converterFlags.js +14 -5
  34. package/dist/src/extLink.js +2 -2
  35. package/dist/src/gallery.d.ts +12 -2
  36. package/dist/src/gallery.js +12 -2
  37. package/dist/src/heading.d.ts +6 -1
  38. package/dist/src/heading.js +14 -4
  39. package/dist/src/hidden.js +7 -1
  40. package/dist/src/html.js +12 -5
  41. package/dist/src/imageParameter.d.ts +1 -0
  42. package/dist/src/imageParameter.js +9 -3
  43. package/dist/src/imagemap.js +9 -4
  44. package/dist/src/index.d.ts +3 -0
  45. package/dist/src/index.js +25 -5
  46. package/dist/src/link/base.js +4 -4
  47. package/dist/src/link/file.d.ts +9 -1
  48. package/dist/src/link/file.js +13 -5
  49. package/dist/src/link/galleryImage.d.ts +1 -0
  50. package/dist/src/link/galleryImage.js +19 -6
  51. package/dist/src/link/redirectTarget.d.ts +6 -1
  52. package/dist/src/link/redirectTarget.js +7 -2
  53. package/dist/src/magicLink.d.ts +6 -1
  54. package/dist/src/magicLink.js +31 -12
  55. package/dist/src/nested.js +1 -1
  56. package/dist/src/nowiki/comment.js +1 -1
  57. package/dist/src/nowiki/index.d.ts +1 -0
  58. package/dist/src/nowiki/index.js +13 -3
  59. package/dist/src/nowiki/listBase.d.ts +6 -1
  60. package/dist/src/nowiki/listBase.js +7 -2
  61. package/dist/src/nowiki/quote.d.ts +6 -1
  62. package/dist/src/nowiki/quote.js +9 -2
  63. package/dist/src/parameter.js +1 -1
  64. package/dist/src/redirect.js +1 -1
  65. package/dist/src/table/index.js +8 -7
  66. package/dist/src/table/td.js +1 -1
  67. package/dist/src/table/trBase.d.ts +1 -1
  68. package/dist/src/table/trBase.js +3 -31
  69. package/dist/src/tagPair/ext.js +5 -2
  70. package/dist/src/transclude.d.ts +21 -8
  71. package/dist/src/transclude.js +48 -26
  72. package/dist/util/html.js +3 -6
  73. package/dist/util/lint.js +33 -1
  74. package/extensions/dist/base.js +1 -1
  75. package/extensions/ui.css +1 -1
  76. package/i18n/zh-hans.json +1 -1
  77. package/i18n/zh-hant.json +1 -1
  78. package/package.json +7 -13
@@ -147,7 +147,7 @@ let ImagemapToken = (() => {
147
147
  if (this.image) {
148
148
  errors.push(...this.childNodes.filter(child => {
149
149
  const str = child.toString().trim();
150
- return child.type === 'noinclude' && str && !str.startsWith('#');
150
+ return child.is('noinclude') && str && !str.startsWith('#');
151
151
  }).map(child => {
152
152
  const e = (0, lint_1.generateForChild)(child, rect, 'invalid-imagemap', 'invalid link in <imagemap>');
153
153
  e.suggestions = [
@@ -162,12 +162,17 @@ let ImagemapToken = (() => {
162
162
  }
163
163
  return errors;
164
164
  }
165
+ /* PRINT ONLY */
166
+ /** @private */
167
+ getAttribute(key) {
168
+ return key === 'invalid' ? !this.image : super.getAttribute(key);
169
+ }
165
170
  insertAt(token, i) {
166
171
  const { image } = this;
167
- if (!image && (typeof token === 'string' || token.type === 'imagemap-link' || token.type === 'text')) {
172
+ if (!image && (typeof token === 'string' || token.is('imagemap-link') || token.type === 'text')) {
168
173
  throw new Error('Missing a valid image!');
169
174
  }
170
- else if (image && typeof token !== 'string' && token.type === 'imagemap-image') {
175
+ else if (image && typeof token !== 'string' && token.is('imagemap-image')) {
171
176
  throw new RangeError('Already have a valid image!');
172
177
  }
173
178
  return super.insertAt(token, i);
@@ -178,7 +183,7 @@ let ImagemapToken = (() => {
178
183
  * @throws `Error` 禁止移除图片
179
184
  */
180
185
  removeAt(i) {
181
- if (this.childNodes[i]?.type === 'imagemap-image') {
186
+ if (this.childNodes[i]?.is('imagemap-image')) {
182
187
  throw new Error('Do not remove the image in <imagemap>!');
183
188
  }
184
189
  return super.removeAt(i);
@@ -117,6 +117,7 @@ export declare class Token extends AstElement {
117
117
  * Expand templates
118
118
  *
119
119
  * 展开模板
120
+ * @since v1.10.0
120
121
  */
121
122
  expand(): Token;
122
123
  /**
@@ -135,12 +136,14 @@ export declare class Token extends AstElement {
135
136
  * Generate HTML
136
137
  *
137
138
  * 生成HTML
139
+ * @since v1.10.0
138
140
  */
139
141
  toHtml(): string;
140
142
  /**
141
143
  * Build lists
142
144
  *
143
145
  * 构建列表
146
+ * @since v1.17.1
144
147
  */
145
148
  buildLists(): void;
146
149
  }
package/dist/src/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  // PHP解析器的步骤:
3
- // -1. 替换签名和`{{subst:}}`,参见Parser::preSaveTransform;这在revision中不可能保留,可以跳过
4
- // 0. 移除特定字符`\0`和`\x7F`,参见Parser::parse
3
+ // -2. 替换签名和`{{subst:}}`,参见Parser::preSaveTransform;这在revision中不可能保留,可以跳过
4
+ // -1. 移除特定字符`\0`和`\x7F`,参见Parser::parse
5
+ // 0. 重定向,参见WikitextContentHandler::extractRedirectTargetAndText
5
6
  // 1. 注释/扩展标签('<'相关),参见Preprocessor_Hash::buildDomTreeArrayFromText和Sanitizer::decodeTagAttributes
6
7
  // 2. 模板/模板变量/标题,注意rightmost法则,以及`-{`和`[[`可以破坏`{{`或`{{{`语法,
7
8
  // 参见Preprocessor_Hash::buildDomTreeArrayFromText
@@ -11,7 +12,7 @@
11
12
  // 6. 内链,含文件和分类,参见Parser::handleInternalLinks2
12
13
  // 7. `'`,参见Parser::doQuotes
13
14
  // 8. 外链,参见Parser::handleExternalLinks
14
- // 9. ISBN、RFC(未来将废弃,不予支持)和自由外链,参见Parser::handleMagicLinks
15
+ // 9. ISBN、RFC和自由外链,参见Parser::handleMagicLinks
15
16
  // 10. 段落和列表,参见BlockLevelPass::execute
16
17
  // 11. 转换,参见LanguageConverter::recursiveConvertTopLevel
17
18
  // \0\d+.\x7F标记Token:
@@ -434,6 +435,10 @@ let Token = (() => {
434
435
  return this.#built;
435
436
  case 'stage':
436
437
  return this.#stage;
438
+ /* PRINT ONLY */
439
+ case 'invalid':
440
+ return (this.type === 'table-inter' && (0, lint_1.isFostered)(this) === 'error');
441
+ /* PRINT ONLY END */
437
442
  /* NOT FOR BROWSER */
438
443
  case 'protectedChildren':
439
444
  return this.#protectedChildren;
@@ -500,13 +505,25 @@ let Token = (() => {
500
505
  return index_1.default.normalizeTitle(title, defaultNs, this.#include, this.#config, opt);
501
506
  }
502
507
  /** @private */
508
+ inTableAttrs() {
509
+ return this.closest('table-attrs,ext')?.type === 'table-attrs' && (this.closest('table-attrs,arg,magic-word,template')?.is('table-attrs')
510
+ ? 'error'
511
+ : 'warning');
512
+ }
513
+ /** @private */
514
+ inHtmlAttrs() {
515
+ return this.closest('html-attrs,ext')?.is('html-attrs')
516
+ ? 'error'
517
+ : this.inTableAttrs();
518
+ }
519
+ /** @private */
503
520
  lint(start = this.getAbsoluteIndex(), re) {
504
521
  let errors = super.lint(start, re);
505
522
  if (this.type === 'root') {
506
523
  const record = new Map(), selector = 'category,html-attr#id,ext-attr#id,table-attr#id';
507
524
  for (const cat of this.querySelectorAll(selector)) {
508
525
  let key;
509
- if (cat.type === 'category') {
526
+ if (cat.is('category')) {
510
527
  key = cat.name;
511
528
  }
512
529
  else {
@@ -621,7 +638,7 @@ let Token = (() => {
621
638
  /* NOT FOR BROWSER */
622
639
  /** @private */
623
640
  print(opt) {
624
- return this.type === 'list-range' ? (0, string_1.print)(this.childNodes) : super.print(opt);
641
+ return this.is('list-range') ? (0, string_1.print)(this.childNodes) : super.print(opt);
625
642
  }
626
643
  /** @private */
627
644
  getAcceptable() {
@@ -831,6 +848,7 @@ let Token = (() => {
831
848
  * Expand templates
832
849
  *
833
850
  * 展开模板
851
+ * @since v1.10.0
834
852
  */
835
853
  expand() {
836
854
  require('../addon/token');
@@ -864,6 +882,7 @@ let Token = (() => {
864
882
  * Generate HTML
865
883
  *
866
884
  * 生成HTML
885
+ * @since v1.10.0
867
886
  */
868
887
  toHtml() {
869
888
  require('../addon/token');
@@ -888,6 +907,7 @@ let Token = (() => {
888
907
  * Build lists
889
908
  *
890
909
  * 构建列表
910
+ * @since v1.17.1
891
911
  */
892
912
  buildLists() {
893
913
  this.#buildLists(true);
@@ -182,7 +182,7 @@ let LinkBaseToken = (() => {
182
182
  if (key === 'bracket') {
183
183
  this.#bracket = value;
184
184
  }
185
- else if (key === 'title') {
185
+ else /* istanbul ignore if */ if (key === 'title') {
186
186
  this.#title = value;
187
187
  }
188
188
  else {
@@ -214,8 +214,8 @@ let LinkBaseToken = (() => {
214
214
  errors.push((0, lint_1.generateForChild)(target, rect, 'unknown-page', 'template in an internal link target', 'warning'));
215
215
  }
216
216
  if (encoded) {
217
- const e = (0, lint_1.generateForChild)(target, rect, 'url-encoding', 'unnecessary URL encoding in an internal link');
218
- e.suggestions = [{ desc: 'decode', range: [e.startIndex, e.endIndex], text: (0, string_1.rawurldecode)(target.text()) }];
217
+ const e = (0, lint_1.generateForChild)(target, rect, 'url-encoding', 'unnecessary URL encoding in an internal link', 'warning');
218
+ e.fix = { desc: 'decode', range: [e.startIndex, e.endIndex], text: (0, string_1.rawurldecode)(target.text()) };
219
219
  errors.push(e);
220
220
  }
221
221
  if (type === 'link' || type === 'category') {
@@ -236,12 +236,12 @@ let LinkBaseToken = (() => {
236
236
  const e = (0, lint_1.generateForChild)(target, rect, 'no-ignored', 'useless fragment', 'warning'), j = target.childNodes.findIndex(c => c.type === 'text' && c.data.includes('#')), textNode = target.childNodes[j];
237
237
  if (textNode) {
238
238
  e.fix = {
239
+ desc: 'remove',
239
240
  range: [
240
241
  e.startIndex + target.getRelativeIndex(j) + textNode.data.indexOf('#'),
241
242
  e.endIndex,
242
243
  ],
243
244
  text: '',
244
- desc: 'remove',
245
245
  };
246
246
  }
247
247
  errors.push(e);
@@ -16,7 +16,12 @@ export declare abstract class FileToken extends LinkBaseToken {
16
16
  abstract get children(): [AtomToken, ...ImageParameterToken[]];
17
17
  abstract get lastElementChild(): AtomToken | ImageParameterToken;
18
18
  get type(): 'file' | 'gallery-image' | 'imagemap-image';
19
- /** file extension / 扩展名 */
19
+ /**
20
+ * file extension
21
+ *
22
+ * 扩展名
23
+ * @since v1.5.3
24
+ */
20
25
  get extension(): string | undefined;
21
26
  /** image link / 图片链接 */
22
27
  get link(): string | Title;
@@ -91,18 +96,21 @@ export declare abstract class FileToken extends LinkBaseToken {
91
96
  * Get the effective image frame paremter value
92
97
  *
93
98
  * 获取生效的图片框架属性参数
99
+ * @since v1.11.0
94
100
  */
95
101
  getFrame(): string | Title | undefined;
96
102
  /**
97
103
  * Get the effective image horizontal alignment parameter value
98
104
  *
99
105
  * 获取生效的图片水平对齐参数
106
+ * @since v1.11.0
100
107
  */
101
108
  getHorizAlign(): string | undefined;
102
109
  /**
103
110
  * Get the effective image vertical alignment parameter value
104
111
  *
105
112
  * 获取生效的图片垂直对齐参数
113
+ * @since v1.11.0
106
114
  */
107
115
  getVertAlign(): string | undefined;
108
116
  /**
@@ -64,7 +64,12 @@ class FileToken extends base_1.LinkBaseToken {
64
64
  get type() {
65
65
  return 'file';
66
66
  }
67
- /** file extension / 扩展名 */
67
+ /**
68
+ * file extension
69
+ *
70
+ * 扩展名
71
+ * @since v1.5.3
72
+ */
68
73
  get extension() {
69
74
  return this.getAttribute('title').extension;
70
75
  }
@@ -86,7 +91,7 @@ class FileToken extends base_1.LinkBaseToken {
86
91
  }
87
92
  /** image width / 图片宽度 */
88
93
  get width() {
89
- return this.type === 'gallery-image'
94
+ return this.is('gallery-image')
90
95
  ? this.parentNode?.widths.toString()
91
96
  : this.size?.width;
92
97
  }
@@ -101,7 +106,7 @@ class FileToken extends base_1.LinkBaseToken {
101
106
  }
102
107
  /** image height / 图片高度 */
103
108
  get height() {
104
- return this.type === 'gallery-image'
109
+ return this.is('gallery-image')
105
110
  ? this.parentNode?.heights.toString()
106
111
  : this.size?.height;
107
112
  }
@@ -141,7 +146,7 @@ class FileToken extends base_1.LinkBaseToken {
141
146
  if (unscaled) {
142
147
  for (const arg of args.filter(({ name }) => name === 'width')) {
143
148
  const e = (0, lint_1.generateForChild)(arg, rect, 'invalid-gallery', 'invalid image parameter');
144
- e.fix = { range: [e.startIndex - 1, e.endIndex], text: '', desc: 'remove' };
149
+ e.fix = { desc: 'remove', range: [e.startIndex - 1, e.endIndex], text: '' };
145
150
  errors.push(e);
146
151
  }
147
152
  }
@@ -282,6 +287,7 @@ class FileToken extends base_1.LinkBaseToken {
282
287
  * Get the effective image frame paremter value
283
288
  *
284
289
  * 获取生效的图片框架属性参数
290
+ * @since v1.11.0
285
291
  */
286
292
  getFrame() {
287
293
  const [arg] = this.getFrameArgs(), val = arg?.name;
@@ -291,6 +297,7 @@ class FileToken extends base_1.LinkBaseToken {
291
297
  * Get the effective image horizontal alignment parameter value
292
298
  *
293
299
  * 获取生效的图片水平对齐参数
300
+ * @since v1.11.0
294
301
  */
295
302
  getHorizAlign() {
296
303
  return this.getHorizAlignArgs()[0]?.name;
@@ -299,6 +306,7 @@ class FileToken extends base_1.LinkBaseToken {
299
306
  * Get the effective image vertical alignment parameter value
300
307
  *
301
308
  * 获取生效的图片垂直对齐参数
309
+ * @since v1.11.0
302
310
  */
303
311
  getVertAlign() {
304
312
  return this.getVertAlignArgs()[0]?.name;
@@ -396,7 +404,7 @@ class FileToken extends base_1.LinkBaseToken {
396
404
  }) ?? '', titleFromCaption = visibleCaption && type !== 'gallery-image' ? '' : (0, string_1.sanitizeAlt)(caption), hasLink = manual || link !== file, title = titleFromCaption || (hasLink && typeof link !== 'string' ? link.getTitleAttr() : ''), titleAttr = title && ` title="${title}"`, alt = (0, string_1.sanitizeAlt)(this.getArg('alt')?.toHtmlInternal({
397
405
  ...opt,
398
406
  nowrap: true,
399
- })) ?? titleFromCaption, horiz = this.getHorizAlign() ?? '', vert = this.getVertAlign() ?? '', className = `${horiz ? `mw-halign-${horiz}` : vert && `mw-valign-${vert}`}${this.getValue('border') ? ' mw-image-border' : ''} ${(0, string_1.sanitizeAlt)(this.getValue('class')) ?? ''}`.trim(), classAttr = className && ` class="${className}"`, img = `<img${alt && ` alt="${alt}"`} src="${(manual ? fr : file).getUrl()}" class="mw-file-element"${isInteger(width) ? ` width="${width}"` : ''}${isInteger(height) ? ` height="${height}"` : ''}>`;
407
+ })) ?? titleFromCaption, horiz = this.getHorizAlign() ?? '', vert = this.getVertAlign() ?? '', className = `${horiz ? `mw-halign-${horiz}` : vert && `mw-valign-${vert}`}${this.getValue('border') ? ' mw-image-border' : ''} ${(0, string_1.sanitizeAlt)(this.getValue('class')) ?? ''}`.trim(), classAttr = className && ` class="${className}"`, img = `<img${alt && ` alt="${alt}"`} src="${(manual ? fr : file).getUrl()}" decoding="async" class="mw-file-element"${isInteger(width) ? ` width="${width}"` : ''}${isInteger(height) ? ` height="${height}"` : ''}>`;
400
408
  let href = '';
401
409
  if (link) {
402
410
  try {
@@ -10,6 +10,7 @@ declare type GalleryTypes = 'gallery' | 'imagemap';
10
10
  * 图库图片
11
11
  */
12
12
  export declare abstract class GalleryImageToken extends FileToken {
13
+ #private;
13
14
  get type(): `${GalleryTypes}-image`;
14
15
  /** image link / 图片链接 */
15
16
  get link(): string | Title;
@@ -106,19 +106,30 @@ let GalleryImageToken = (() => {
106
106
  const imagemap = this.type === 'imagemap-image';
107
107
  return this.normalizeTitle(this.firstChild.toString(), imagemap ? 0 : 6, { halfParsed: true, temporary, decode: !imagemap });
108
108
  }
109
- /** @private */
110
- lint(start = this.getAbsoluteIndex(), re) {
111
- const errors = super.lint(start, re), { ns,
109
+ /** 判定无效的图片 */
110
+ #lint() {
111
+ const { ns,
112
112
  /* NOT FOR BROWSER */
113
113
  interwiki, } = this.getAttribute('title');
114
- if (ns !== 6
115
- || interwiki) {
114
+ return ns !== 6
115
+ || Boolean(interwiki);
116
+ }
117
+ /** @private */
118
+ lint(start = this.getAbsoluteIndex(), re) {
119
+ const errors = super.lint(start, re);
120
+ if (this.#lint()) {
116
121
  const e = (0, lint_1.generateForSelf)(this, { start }, 'invalid-gallery', 'invalid gallery image');
117
122
  e.suggestions = [{ desc: 'prefix', range: [start, start], text: 'File:' }];
118
123
  errors.push(e);
119
124
  }
120
125
  return errors;
121
126
  }
127
+ /* PRINT ONLY */
128
+ /** @private */
129
+ getAttribute(key) {
130
+ return key === 'invalid' ? this.#lint() : super.getAttribute(key);
131
+ }
132
+ /* PRINT ONLY END */
122
133
  /* NOT FOR BROWSER */
123
134
  /**
124
135
  * @override
@@ -128,7 +139,9 @@ let GalleryImageToken = (() => {
128
139
  * @throws `TypeError` 不可插入文本节点
129
140
  */
130
141
  insertAt(child, i) {
131
- if (this.type === 'gallery-image' && child.type === 'image-parameter' && !imageParameter_1.galleryParams.has(child.name)) {
142
+ if (this.type === 'gallery-image'
143
+ && child.is('image-parameter')
144
+ && !imageParameter_1.galleryParams.has(child.name)) {
132
145
  child.setAttribute('name', 'invalid');
133
146
  }
134
147
  return super.insertAt(child, i);
@@ -17,7 +17,12 @@ export declare abstract class RedirectTargetToken extends LinkBaseToken {
17
17
  abstract get lastElementChild(): AtomToken | NoincludeToken;
18
18
  abstract set link(link: string);
19
19
  get type(): 'redirect-target';
20
- /** link text / 链接显示文字 */
20
+ /**
21
+ * link text
22
+ *
23
+ * 链接显示文字
24
+ * @since v1.10.0
25
+ */
21
26
  get innerText(): string;
22
27
  /**
23
28
  * @param link 链接标题
@@ -19,7 +19,12 @@ class RedirectTargetToken extends base_1.LinkBaseToken {
19
19
  return 'redirect-target';
20
20
  }
21
21
  /* NOT FOR BROWSER */
22
- /** link text / 链接显示文字 */
22
+ /**
23
+ * link text
24
+ *
25
+ * 链接显示文字
26
+ * @since v1.10.0
27
+ */
23
28
  get innerText() {
24
29
  return this.link.toString(true);
25
30
  }
@@ -50,7 +55,7 @@ class RedirectTargetToken extends base_1.LinkBaseToken {
50
55
  const e = (0, lint_1.generateForChild)(this.lastChild, { start }, 'no-ignored', 'useless link text', 'warning');
51
56
  e.startIndex--;
52
57
  e.startCol--;
53
- e.fix = { range: [e.startIndex, e.endIndex], text: '', desc: 'remove' };
58
+ e.fix = { desc: 'remove', range: [e.startIndex, e.endIndex], text: '' };
54
59
  errors.push(e);
55
60
  }
56
61
  return errors;
@@ -21,7 +21,12 @@ export declare abstract class MagicLinkToken extends Token {
21
21
  abstract get firstElementChild(): CommentToken | IncludeToken | NoincludeToken | TranscludeToken | undefined;
22
22
  abstract get lastElementChild(): CommentToken | IncludeToken | NoincludeToken | TranscludeToken | undefined;
23
23
  get type(): ExtLinkTypes;
24
- /** text of the link / 链接显示文字 */
24
+ /**
25
+ * text of the link
26
+ *
27
+ * 链接显示文字
28
+ * @since v1.10.0
29
+ */
25
30
  get innerText(): string;
26
31
  /** link / 链接 */
27
32
  get link(): string;
@@ -90,7 +90,12 @@ let MagicLinkToken = (() => {
90
90
  get type() {
91
91
  return this.#type;
92
92
  }
93
- /** text of the link / 链接显示文字 */
93
+ /**
94
+ * text of the link
95
+ *
96
+ * 链接显示文字
97
+ * @since v1.10.0
98
+ */
94
99
  get innerText() {
95
100
  const map = new Map([['!', '|'], ['=', '=']]);
96
101
  let link = (0, string_1.text)(this.childNodes.map(child => {
@@ -111,7 +116,7 @@ let MagicLinkToken = (() => {
111
116
  .replace(/x$/u, 'X')}`
112
117
  : innerText;
113
118
  }
114
- return (0, string_1.decodeNumber)(innerText);
119
+ return (0, string_1.decodeNumber)(innerText).replace(/\n/gu, '%0A');
115
120
  }
116
121
  /* NOT FOR BROWSER */
117
122
  set link(url) {
@@ -149,19 +154,27 @@ let MagicLinkToken = (() => {
149
154
  }
150
155
  this.setAttribute('pattern', pattern);
151
156
  }
152
- /** @private */
153
- lint(start = this.getAbsoluteIndex(), re) {
154
- const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start), { type, childNodes } = this;
155
- if (type === 'magic-link') {
157
+ /** 判定无效的ISBN */
158
+ #lint() {
159
+ if (this.type === 'magic-link') {
156
160
  const { link } = this;
157
161
  if (link.startsWith('ISBN')) {
158
162
  // eslint-disable-next-line unicorn/no-useless-spread, @typescript-eslint/no-misused-spread
159
163
  const digits = [...link.slice(5)].map(s => s === 'X' ? 10 : Number(s));
160
- if (digits.length === 10 && digits.reduce((sum, d, i) => sum + d * (10 - i), 0) % 11
161
- || digits.length === 13 && (digits[12] === 10
162
- || digits.reduce((sum, d, i) => sum + d * (i % 2 ? 3 : 1), 0) % 10)) {
163
- errors.push((0, lint_1.generateForSelf)(this, rect, 'invalid-isbn', 'invalid ISBN'));
164
- }
164
+ return digits.length === 10
165
+ ? digits.reduce((sum, d, i) => sum + d * (10 - i), 0) % 11 !== 0
166
+ : digits.length === 13 && (digits[12] === 10
167
+ || digits.reduce((sum, d, i) => sum + d * (i % 2 ? 3 : 1), 0) % 10 !== 0);
168
+ }
169
+ }
170
+ return false;
171
+ }
172
+ /** @private */
173
+ lint(start = this.getAbsoluteIndex(), re) {
174
+ const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start), { type, childNodes } = this;
175
+ if (type === 'magic-link') {
176
+ if (this.#lint()) {
177
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'invalid-isbn', 'invalid ISBN'));
165
178
  }
166
179
  return errors;
167
180
  }
@@ -195,7 +208,7 @@ let MagicLinkToken = (() => {
195
208
  .getUrl(articlePath);
196
209
  }
197
210
  link = link.startsWith('RFC')
198
- ? `https://tools.ietf.org/html/rfc${link.slice(4)}`
211
+ ? `https://datatracker.ietf.org/doc/html/rfc${link.slice(4)}`
199
212
  : `https://pubmed.ncbi.nlm.nih.gov/${link.slice(5)}`;
200
213
  }
201
214
  else if (link.startsWith('//')) {
@@ -204,6 +217,12 @@ let MagicLinkToken = (() => {
204
217
  return new URL(link);
205
218
  }
206
219
  }
220
+ /* PRINT ONLY */
221
+ /** @private */
222
+ getAttribute(key) {
223
+ return key === 'invalid' ? this.#lint() : super.getAttribute(key);
224
+ }
225
+ /* PRINT ONLY END */
207
226
  /* NOT FOR BROWSER */
208
227
  cloneNode() {
209
228
  const token = (0, html_1.cloneNode)(this,
@@ -96,7 +96,7 @@ class NestedToken extends index_2.Token {
96
96
  * @param i position to be inseted at / 插入位置
97
97
  */
98
98
  insertAt(token, i) {
99
- if (!debug_1.Shadow.running && token.type === 'ext' && !this.#tags.includes(token.name)) {
99
+ if (!debug_1.Shadow.running && token.is('ext') && !this.#tags.includes(token.name)) {
100
100
  this.constructorError(`can only have ${this.#tags.join(' or ')} tags as child nodes`);
101
101
  }
102
102
  return super.insertAt(token, i);
@@ -91,7 +91,7 @@ let CommentToken = (() => {
91
91
  return [];
92
92
  }
93
93
  const e = (0, lint_1.generateForSelf)(this, { start }, 'unclosed-comment', index_1.default.msg('unclosed $1', 'HTML comment'));
94
- e.suggestions = [{ range: [e.endIndex, e.endIndex], text: '-->', desc: 'close' }];
94
+ e.suggestions = [{ desc: 'close', range: [e.endIndex, e.endIndex], text: '-->' }];
95
95
  return [e];
96
96
  }
97
97
  /** @private */
@@ -7,6 +7,7 @@ import type { AttributesToken, ExtToken } from '../../internal';
7
7
  * 扩展标签内的纯文字Token
8
8
  */
9
9
  export declare abstract class NowikiToken extends NowikiBaseToken {
10
+ #private;
10
11
  readonly name: string;
11
12
  abstract get nextSibling(): undefined;
12
13
  abstract get previousSibling(): AttributesToken | undefined;
@@ -24,16 +24,26 @@ class NowikiToken extends base_1.NowikiBaseToken {
24
24
  get type() {
25
25
  return 'ext-inner';
26
26
  }
27
+ /** 扩展标签内的无效内容 */
28
+ #lint() {
29
+ const { name, firstChild: { data } } = this;
30
+ return voidExt.has(name) && Boolean(data);
31
+ }
27
32
  /** @private */
28
33
  lint(start = this.getAbsoluteIndex()) {
29
- const { name, firstChild: { data } } = this;
30
- if (voidExt.has(name) && data) {
34
+ const { name } = this;
35
+ if (this.#lint()) {
31
36
  const e = (0, lint_1.generateForSelf)(this, { start }, 'void-ext', index_1.default.msg('nothing should be in <$1>', name));
32
- e.fix = { range: [start, e.endIndex], text: '', desc: 'empty' };
37
+ e.fix = { desc: 'empty', range: [start, e.endIndex], text: '' };
33
38
  return [e];
34
39
  }
35
40
  return super.lint(start, getLintRegex(name));
36
41
  }
42
+ /* PRINT ONLY */
43
+ /** @private */
44
+ getAttribute(key) {
45
+ return key === 'invalid' ? this.#lint() : super.getAttribute(key);
46
+ }
37
47
  }
38
48
  exports.NowikiToken = NowikiToken;
39
49
  constants_1.classes['NowikiToken'] = __filename;
@@ -11,7 +11,12 @@ export interface ListRangeToken extends Token {
11
11
  /** `;:*#` */
12
12
  export declare abstract class ListBaseToken extends NowikiBaseToken {
13
13
  abstract get type(): 'dd' | 'list';
14
- /** number of indentation / 缩进数 */
14
+ /**
15
+ * number of indentation
16
+ *
17
+ * 缩进数
18
+ * @since v1.16.5
19
+ */
15
20
  get indent(): number;
16
21
  /** @throws `Error` not `<dd>` only */
17
22
  set indent(indent: number);
@@ -10,7 +10,12 @@ const index_1 = require("../index");
10
10
  /** `;:*#` */
11
11
  class ListBaseToken extends base_1.NowikiBaseToken {
12
12
  /* PRINT ONLY */
13
- /** number of indentation / 缩进数 */
13
+ /**
14
+ * number of indentation
15
+ *
16
+ * 缩进数
17
+ * @since v1.16.5
18
+ */
14
19
  get indent() {
15
20
  return this.innerText.split(':').length - 1;
16
21
  }
@@ -78,7 +83,7 @@ class ListBaseToken extends base_1.NowikiBaseToken {
78
83
  nDt++;
79
84
  }
80
85
  }
81
- else if (nextSibling.type === 'dd') {
86
+ else if (nextSibling.is('dd')) {
82
87
  break;
83
88
  }
84
89
  ({ nextSibling } = nextSibling);
@@ -12,7 +12,12 @@ export declare abstract class QuoteToken extends NowikiBaseToken {
12
12
  get type(): 'quote';
13
13
  get bold(): boolean;
14
14
  get italic(): boolean;
15
- /** whether to be closing quotes / 是否闭合 */
15
+ /**
16
+ * whether to be closing quotes
17
+ *
18
+ * 是否闭合
19
+ * @since v1.16.5
20
+ */
16
21
  get closing(): Partial<Font>;
17
22
  get font(): Font;
18
23
  /** @param closing 是否闭合 */
@@ -77,7 +77,12 @@ let QuoteToken = (() => {
77
77
  get italic() {
78
78
  return this.innerText.length !== 3;
79
79
  }
80
- /** whether to be closing quotes / 是否闭合 */
80
+ /**
81
+ * whether to be closing quotes
82
+ *
83
+ * 是否闭合
84
+ * @since v1.16.5
85
+ */
81
86
  get closing() {
82
87
  return {
83
88
  ...this.bold ? { bold: this.#closing.bold } : undefined,
@@ -97,7 +102,9 @@ let QuoteToken = (() => {
97
102
  /** @private */
98
103
  text() {
99
104
  const { parentNode, innerText } = this;
100
- return parentNode?.type === 'image-parameter' && parentNode.name !== 'caption' ? '' : innerText;
105
+ return parentNode?.is('image-parameter') && parentNode.name !== 'caption'
106
+ ? ''
107
+ : innerText;
101
108
  }
102
109
  /** @private */
103
110
  lint(start = this.getAbsoluteIndex()) {
@@ -183,7 +183,7 @@ let ParameterToken = (() => {
183
183
  e.startCol = e.endCol;
184
184
  e.endIndex++;
185
185
  e.endCol++;
186
- e.fix = { range: [e.startIndex, e.endIndex], text: '{{=}}', desc: 'escape' };
186
+ e.fix = { desc: 'escape', range: [e.startIndex, e.endIndex], text: '{{=}}' };
187
187
  errors.push(e);
188
188
  }
189
189
  return errors;
@@ -113,7 +113,7 @@ let RedirectToken = (() => {
113
113
  const cloned = this.cloneChildNodes(), config = this.getAttribute('config');
114
114
  return debug_1.Shadow.run(() => {
115
115
  // @ts-expect-error abstract class
116
- const token = new RedirectToken(this.#pre, undefined, '', undefined, this.#post, config, []);
116
+ const token = new RedirectToken(this.#pre, undefined, '', undefined, this.#post, config);
117
117
  token.firstChild.safeReplaceWith(cloned[0]);
118
118
  token.lastChild.safeReplaceWith(cloned[1]);
119
119
  return token;