wikilint 2.9.3 → 2.11.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 (65) hide show
  1. package/config/.schema.json +5 -0
  2. package/config/enwiki.json +2 -1
  3. package/config/llwiki.json +2 -1
  4. package/config/moegirl.json +2 -1
  5. package/config/zhwiki.json +2 -1
  6. package/dist/base.d.ts +3 -2
  7. package/dist/index.js +21 -18
  8. package/dist/lib/element.js +2 -2
  9. package/dist/lib/node.d.ts +6 -1
  10. package/dist/lib/node.js +7 -0
  11. package/dist/lib/text.d.ts +0 -2
  12. package/dist/lib/text.js +8 -10
  13. package/dist/lib/title.js +4 -9
  14. package/dist/mixin/hidden.d.ts +1 -0
  15. package/dist/mixin/hidden.js +2 -2
  16. package/dist/parser/list.js +23 -6
  17. package/dist/parser/magicLinks.js +1 -2
  18. package/dist/parser/table.js +2 -2
  19. package/dist/src/arg.js +3 -6
  20. package/dist/src/attribute.js +9 -28
  21. package/dist/src/attributes.js +2 -3
  22. package/dist/src/converter.d.ts +1 -1
  23. package/dist/src/converter.js +4 -3
  24. package/dist/src/converterFlags.js +4 -7
  25. package/dist/src/converterRule.js +9 -13
  26. package/dist/src/extLink.js +3 -3
  27. package/dist/src/gallery.js +6 -5
  28. package/dist/src/heading.js +4 -3
  29. package/dist/src/hidden.js +1 -1
  30. package/dist/src/html.js +3 -6
  31. package/dist/src/imageParameter.js +8 -11
  32. package/dist/src/imagemap.js +2 -2
  33. package/dist/src/index.js +12 -11
  34. package/dist/src/link/base.js +15 -13
  35. package/dist/src/link/file.d.ts +0 -7
  36. package/dist/src/link/file.js +19 -25
  37. package/dist/src/link/redirectTarget.d.ts +1 -1
  38. package/dist/src/link/redirectTarget.js +3 -10
  39. package/dist/src/magicLink.d.ts +2 -0
  40. package/dist/src/magicLink.js +37 -53
  41. package/dist/src/nested.js +1 -1
  42. package/dist/src/nowiki/comment.js +4 -7
  43. package/dist/src/nowiki/doubleUnderscore.js +1 -1
  44. package/dist/src/nowiki/index.js +1 -4
  45. package/dist/src/nowiki/noinclude.js +5 -1
  46. package/dist/src/nowiki/quote.js +5 -0
  47. package/dist/src/onlyinclude.js +2 -2
  48. package/dist/src/paramTag/index.js +2 -2
  49. package/dist/src/parameter.js +11 -13
  50. package/dist/src/redirect.js +3 -3
  51. package/dist/src/syntax.d.ts +1 -1
  52. package/dist/src/syntax.js +2 -2
  53. package/dist/src/table/td.js +2 -2
  54. package/dist/src/table/trBase.js +3 -4
  55. package/dist/src/tagPair/ext.js +3 -3
  56. package/dist/src/tagPair/include.js +5 -1
  57. package/dist/src/tagPair/index.js +3 -3
  58. package/dist/src/transclude.js +16 -15
  59. package/dist/util/html.js +10 -0
  60. package/dist/util/lint.js +1 -1
  61. package/dist/util/string.js +11 -3
  62. package/errors/README +2 -0
  63. package/i18n/zh-hans.json +1 -1
  64. package/i18n/zh-hant.json +1 -1
  65. package/package.json +11 -11
@@ -36,11 +36,11 @@ class ExtLinkToken extends index_2.Token {
36
36
  }
37
37
  }
38
38
  /** @private */
39
- toString() {
39
+ toString(skip) {
40
40
  if (this.length === 1) {
41
- return `[${super.toString()}${this.#space}]`;
41
+ return `[${super.toString(skip)}${this.#space}]`;
42
42
  }
43
- return `[${super.toString(this.#space)}]`;
43
+ return `[${super.toString(skip, this.#space)}]`;
44
44
  }
45
45
  /** @private */
46
46
  text() {
@@ -42,8 +42,8 @@ class GalleryToken extends index_2.Token {
42
42
  return this.normalizeTitle(file, 6, true, true).valid;
43
43
  }
44
44
  /** @private */
45
- toString() {
46
- return super.toString('\n');
45
+ toString(skip) {
46
+ return super.toString(skip, '\n');
47
47
  }
48
48
  /** @private */
49
49
  text() {
@@ -59,12 +59,13 @@ class GalleryToken extends index_2.Token {
59
59
  for (let i = 0; i < this.length; i++) {
60
60
  const child = this.childNodes[i], str = child.toString(), { length } = str, trimmed = str.trim(), startLine = top + i, startCol = i ? 0 : left;
61
61
  if (child.type === 'noinclude' && trimmed && !/^<!--.*-->$/u.test(trimmed)) {
62
+ const endIndex = start + length;
62
63
  errors.push({
63
64
  rule: 'no-ignored',
64
65
  message: index_1.default.msg('invalid content in <$1>', 'gallery'),
65
66
  severity: trimmed.startsWith('|') ? 'warning' : 'error',
66
67
  startIndex: start,
67
- endIndex: start + length,
68
+ endIndex,
68
69
  startLine,
69
70
  endLine: startLine,
70
71
  startCol,
@@ -72,12 +73,12 @@ class GalleryToken extends index_2.Token {
72
73
  suggestions: [
73
74
  {
74
75
  desc: 'remove',
75
- range: [start, start + length],
76
+ range: [start, endIndex],
76
77
  text: '',
77
78
  },
78
79
  {
79
80
  desc: 'comment',
80
- range: [start, start + length],
81
+ range: [start, endIndex],
81
82
  text: `<!--${str}-->`,
82
83
  },
83
84
  ],
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HeadingToken = void 0;
4
4
  const lint_1 = require("../util/lint");
5
5
  const rect_1 = require("../lib/rect");
6
+ const debug_1 = require("../util/debug");
6
7
  const index_1 = require("../index");
7
8
  const index_2 = require("./index");
8
9
  const syntax_1 = require("./syntax");
@@ -37,9 +38,9 @@ class HeadingToken extends index_2.Token {
37
38
  this.append(token, trail);
38
39
  }
39
40
  /** @private */
40
- toString() {
41
+ toString(skip) {
41
42
  const equals = this.#equals;
42
- return equals + this.firstChild.toString() + equals + this.lastChild.toString();
43
+ return equals + this.firstChild.toString(skip) + equals + this.lastChild.toString(skip);
43
44
  }
44
45
  /** @private */
45
46
  text() {
@@ -56,7 +57,7 @@ class HeadingToken extends index_2.Token {
56
57
  }
57
58
  /** @private */
58
59
  lint(start = this.getAbsoluteIndex(), re) {
59
- const errors = super.lint(start, re), { firstChild, level } = this, innerStr = firstChild.toString(), quotes = firstChild.childNodes.filter((node) => node.type === 'quote'), boldQuotes = quotes.filter(({ bold }) => bold), italicQuotes = quotes.filter(({ italic }) => italic), rect = new rect_1.BoundingRect(this, start);
60
+ const errors = super.lint(start, re), { firstChild, level } = this, innerStr = firstChild.toString(), quotes = firstChild.childNodes.filter((0, debug_1.isToken)('quote')), boldQuotes = quotes.filter(({ bold }) => bold), italicQuotes = quotes.filter(({ italic }) => italic), rect = new rect_1.BoundingRect(this, start);
60
61
  if (this.level === 1) {
61
62
  errors.push((0, lint_1.generateForChild)(firstChild, rect, 'h1', '<h1>'));
62
63
  }
@@ -39,7 +39,7 @@ const hidden_1 = require("../mixin/hidden");
39
39
  const index_1 = require("./index");
40
40
  /** 不可见的节点 */
41
41
  let HiddenToken = (() => {
42
- let _classDecorators = [(0, hidden_1.hiddenToken)(true)];
42
+ let _classDecorators = [(0, hidden_1.hiddenToken)()];
43
43
  let _classDescriptor;
44
44
  let _classExtraInitializers = [];
45
45
  let _classThis;
package/dist/src/html.js CHANGED
@@ -66,8 +66,8 @@ class HtmlToken extends index_1.Token {
66
66
  this.#tag = name;
67
67
  }
68
68
  /** @private */
69
- toString() {
70
- return `<${this.closing ? '/' : ''}${this.#tag}${super.toString()}${this.#selfClosing ? '/' : ''}>`;
69
+ toString(skip) {
70
+ return `<${this.closing ? '/' : ''}${this.#tag}${super.toString(skip)}${this.#selfClosing ? '/' : ''}>`;
71
71
  }
72
72
  /** @private */
73
73
  text() {
@@ -125,10 +125,7 @@ class HtmlToken extends index_1.Token {
125
125
  else if (msg === 'tag that is both closing and self-closing') {
126
126
  const { html: [, , voidTags] } = this.getAttribute('config');
127
127
  if (voidTags.includes(this.name)) {
128
- error.fix = {
129
- range: [start + 1, start + 2],
130
- text: '',
131
- };
128
+ error.fix = { range: [start + 1, start + 2], text: '' };
132
129
  }
133
130
  }
134
131
  errors.push(error);
@@ -8,7 +8,7 @@ const index_2 = require("./index");
8
8
  exports.galleryParams = new Set(['alt', 'link', 'lang', 'page', 'caption']);
9
9
  function validate(key, val, config, halfParsed, ext) {
10
10
  val = val.trim();
11
- let value = val.replace(/\0\d+t\x7F/gu, '').trim();
11
+ let value = val.replace(key === 'link' ? /\0\d+[tq]\x7F/gu : /\0\d+t\x7F/gu, '').trim();
12
12
  switch (key) {
13
13
  case 'width':
14
14
  return !value || /^(?:\d+x?|\d*x\d+)(?:\s*px)?$/u.test(value);
@@ -16,9 +16,9 @@ function validate(key, val, config, halfParsed, ext) {
16
16
  if (!value) {
17
17
  return val;
18
18
  }
19
- const regex = new RegExp(String.raw `^(?:(?:${config.protocol}|//)${string_1.extUrlCharFirst}|\0\d+m\x7F)${string_1.extUrlChar}$`, 'iu');
20
- if (regex.test(value)) {
21
- return val;
19
+ const re1 = new RegExp(String.raw `^(?:${config.protocol}|//|\0\d+m\x7F)`, 'iu'), re2 = new RegExp(String.raw `^(?:(?:${config.protocol}|//)${string_1.extUrlCharFirst}|\0\d+m\x7F)${string_1.extUrlChar}$`, 'iu');
20
+ if (re1.test(value)) {
21
+ return re2.test(value) && val;
22
22
  }
23
23
  else if (value.startsWith('[[') && value.endsWith(']]')) {
24
24
  value = value.slice(2, -2);
@@ -86,8 +86,8 @@ class ImageParameterToken extends index_2.Token {
86
86
  super.afterBuild();
87
87
  }
88
88
  /** @private */
89
- toString() {
90
- return this.#syntax ? this.#syntax.replace('$1', super.toString()) : super.toString();
89
+ toString(skip) {
90
+ return this.#syntax ? this.#syntax.replace('$1', super.toString(skip)) : super.toString(skip);
91
91
  }
92
92
  /** @private */
93
93
  text() {
@@ -106,11 +106,8 @@ class ImageParameterToken extends index_2.Token {
106
106
  lint(start = this.getAbsoluteIndex(), re) {
107
107
  const errors = super.lint(start, re), { link, name } = this;
108
108
  if (name === 'invalid') {
109
- const e = (0, lint_1.generateForSelf)(this, { start }, 'invalid-gallery', 'invalid gallery image parameter');
110
- e.fix = {
111
- range: [start, start + e.endIndex],
112
- text: '',
113
- };
109
+ const e = (0, lint_1.generateForSelf)(this, { start }, 'invalid-gallery', 'invalid image parameter');
110
+ e.fix = { range: [start - 1, e.endIndex], text: '' };
114
111
  errors.push(e);
115
112
  }
116
113
  else if (typeof link === 'object' && link.encoded) {
@@ -77,8 +77,8 @@ class ImagemapToken extends index_2.Token {
77
77
  }
78
78
  }
79
79
  /** @private */
80
- toString() {
81
- return super.toString('\n');
80
+ toString(skip) {
81
+ return super.toString(skip, '\n');
82
82
  }
83
83
  /** @private */
84
84
  text() {
package/dist/src/index.js CHANGED
@@ -80,7 +80,7 @@ class Token extends element_1.AstElement {
80
80
  }
81
81
  /** @private */
82
82
  parseOnce(n = this.#stage, include = false) {
83
- if (n < this.#stage || !this.getAttribute('plain') || this.length === 0) {
83
+ if (n < this.#stage || this.length === 0 || !this.getAttribute('plain')) {
84
84
  return this;
85
85
  }
86
86
  else if (this.#stage >= constants_1.MAX_STAGE) {
@@ -89,7 +89,7 @@ class Token extends element_1.AstElement {
89
89
  switch (n) {
90
90
  case 0:
91
91
  if (this.type === 'root') {
92
- this.#accum.shift();
92
+ this.#accum.pop();
93
93
  const isRedirect = this.#parseRedirect();
94
94
  include &&= !isRedirect;
95
95
  }
@@ -129,7 +129,7 @@ class Token extends element_1.AstElement {
129
129
  }
130
130
  if (this.type === 'root') {
131
131
  for (const token of this.#accum) {
132
- token.parseOnce(n, include);
132
+ token?.parseOnce(n, include); // eslint-disable-line @typescript-eslint/no-unnecessary-condition
133
133
  }
134
134
  }
135
135
  this.#stage++;
@@ -163,7 +163,7 @@ class Token extends element_1.AstElement {
163
163
  this.normalize();
164
164
  if (this.type === 'root') {
165
165
  for (const token of this.#accum) {
166
- token.build();
166
+ token?.build(); // eslint-disable-line @typescript-eslint/no-unnecessary-condition
167
167
  }
168
168
  }
169
169
  }
@@ -172,7 +172,7 @@ class Token extends element_1.AstElement {
172
172
  afterBuild() {
173
173
  if (this.type === 'root') {
174
174
  for (const token of this.#accum) {
175
- token.afterBuild();
175
+ token?.afterBuild(); // eslint-disable-line @typescript-eslint/no-unnecessary-condition
176
176
  }
177
177
  }
178
178
  this.#built = true;
@@ -275,10 +275,10 @@ class Token extends element_1.AstElement {
275
275
  return;
276
276
  }
277
277
  const { parseList } = require('../parser/list');
278
- const lines = this.firstChild.toString().split('\n');
278
+ const lines = this.firstChild.toString().split('\n'), state = { lastPrefix: '' };
279
279
  let i = this.type === 'root' || this.type === 'ext-inner' && this.name === 'poem' ? 0 : 1;
280
280
  for (; i < lines.length; i++) {
281
- lines[i] = parseList(lines[i], this.#config, this.#accum);
281
+ lines[i] = parseList(lines[i], state, this.#config, this.#accum);
282
282
  }
283
283
  this.setText(lines.join('\n'));
284
284
  }
@@ -401,14 +401,15 @@ class Token extends element_1.AstElement {
401
401
  return errors;
402
402
  }
403
403
  /** @private */
404
- toString(separator) {
404
+ toString(skip, separator) {
405
405
  const { rev } = debug_1.Shadow, root = this.getRootNode();
406
- if (root.type === 'root'
406
+ if (!skip
407
+ && root.type === 'root'
407
408
  && root.#built) {
408
- this.#string ??= [rev, super.toString(separator)];
409
+ this.#string ??= [rev, super.toString(false, separator)];
409
410
  return this.#string[1];
410
411
  }
411
- return super.toString(separator);
412
+ return super.toString(skip, separator);
412
413
  }
413
414
  }
414
415
  exports.Token = Token;
@@ -2,11 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LinkBaseToken = void 0;
4
4
  const lint_1 = require("../../util/lint");
5
- const rect_1 = require("../../lib/rect");
6
5
  const constants_1 = require("../../util/constants");
6
+ const rect_1 = require("../../lib/rect");
7
7
  const index_1 = require("../../index");
8
8
  const index_2 = require("../index");
9
9
  const atom_1 = require("../atom");
10
+ /**
11
+ * 是否为普通内链
12
+ * @param type 节点类型
13
+ */
14
+ const isLink = (type) => type === 'redirect-target' || type === 'link';
10
15
  /**
11
16
  * 内链
12
17
  * @classdesc `{childNodes: [AtomToken, ...Token]}`
@@ -53,8 +58,8 @@ class LinkBaseToken extends index_2.Token {
53
58
  }
54
59
  }
55
60
  /** @private */
56
- toString() {
57
- const str = super.toString(this.#delimiter);
61
+ toString(skip) {
62
+ const str = super.toString(skip, this.#delimiter);
58
63
  return this.#bracket ? `[[${str}]]` : str;
59
64
  }
60
65
  /** @private */
@@ -75,31 +80,28 @@ class LinkBaseToken extends index_2.Token {
75
80
  }
76
81
  /** @private */
77
82
  lint(start = this.getAbsoluteIndex(), re) {
78
- const errors = super.lint(start, re), { childNodes: [target, linkText], type: linkType } = this, { encoded, fragment } = this.#title, rect = new rect_1.BoundingRect(this, start);
79
- if (target.childNodes.some(({ type }) => type === 'template')) {
83
+ const errors = super.lint(start, re), { childNodes: [target, linkText], type } = this, { encoded, fragment } = this.#title, rect = new rect_1.BoundingRect(this, start);
84
+ if (target.childNodes.some(({ type: t }) => t === 'template')) {
80
85
  errors.push((0, lint_1.generateForChild)(target, rect, 'unknown-page', 'template in an internal link target', 'warning'));
81
86
  }
82
87
  if (encoded) {
83
88
  errors.push((0, lint_1.generateForChild)(target, rect, 'url-encoding', 'unnecessary URL encoding in an internal link'));
84
89
  }
85
- if (linkType === 'link' || linkType === 'category') {
90
+ if (type === 'link' || type === 'category') {
86
91
  const textNode = linkText?.childNodes.find((c) => c.type === 'text' && c.data.includes('|'));
87
92
  if (textNode) {
88
- const e = (0, lint_1.generateForChild)(linkText, rect, 'pipe-like', 'additional "|" in the link text', 'warning');
93
+ const e = (0, lint_1.generateForChild)(linkText, rect, 'pipe-like', 'additional "|" in the link text', 'warning'), i = e.startIndex + textNode.getRelativeIndex();
89
94
  e.suggestions = [
90
95
  {
91
96
  desc: 'escape',
92
- range: [
93
- e.startIndex + textNode.getRelativeIndex(),
94
- e.startIndex + textNode.getRelativeIndex() + textNode.data.length,
95
- ],
97
+ range: [i, i + textNode.data.length],
96
98
  text: textNode.data.replace(/\|/gu, '&#124;'),
97
99
  },
98
100
  ];
99
101
  errors.push(e);
100
102
  }
101
103
  }
102
- if (linkType !== 'link' && linkType !== 'redirect-target' && fragment !== undefined) {
104
+ if (fragment !== undefined && !isLink(type)) {
103
105
  const e = (0, lint_1.generateForChild)(target, rect, 'no-ignored', 'useless fragment'), textNode = target.childNodes.find((c) => c.type === 'text' && c.data.includes('#'));
104
106
  if (textNode) {
105
107
  e.fix = {
@@ -113,7 +115,7 @@ class LinkBaseToken extends index_2.Token {
113
115
  }
114
116
  /** @private */
115
117
  getTitle(halfParsed) {
116
- return this.normalizeTitle(this.firstChild.text(), 0, halfParsed, true, true);
118
+ return this.normalizeTitle(this.firstChild.toString(true), 0, halfParsed, true, true);
117
119
  }
118
120
  }
119
121
  exports.LinkBaseToken = LinkBaseToken;
@@ -8,7 +8,6 @@ import type { Token, AtomToken } from '../../internal';
8
8
  * @classdesc `{childNodes: [AtomToken, ...ImageParameterToken]}`
9
9
  */
10
10
  export declare abstract class FileToken extends LinkBaseToken {
11
- #private;
12
11
  readonly childNodes: readonly [AtomToken, ...ImageParameterToken[]];
13
12
  abstract get lastChild(): AtomToken | ImageParameterToken;
14
13
  get type(): 'file' | 'gallery-image' | 'imagemap-image';
@@ -27,12 +26,6 @@ export declare abstract class FileToken extends LinkBaseToken {
27
26
  * @param key 参数名
28
27
  */
29
28
  getArgs(key: string): ImageParameterToken[];
30
- /** 获取图片框架属性参数节点 */
31
- getFrameArgs(): ImageParameterToken[];
32
- /** 获取图片水平对齐参数节点 */
33
- getHorizAlignArgs(): ImageParameterToken[];
34
- /** 获取图片垂直对齐参数节点 */
35
- getVertAlignArgs(): ImageParameterToken[];
36
29
  /**
37
30
  * 获取生效的指定图片参数
38
31
  * @param key 参数名
@@ -7,7 +7,12 @@ const rect_1 = require("../../lib/rect");
7
7
  const index_1 = require("../../index");
8
8
  const base_1 = require("./base");
9
9
  const imageParameter_1 = require("../imageParameter");
10
- const frame = new Set(['manualthumb', 'frameless', 'framed', 'thumbnail']), horizAlign = new Set(['left', 'right', 'center', 'none']), vertAlign = new Set(['baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom']);
10
+ const frame = new Map([
11
+ ['manualthumb', 'Thumb'],
12
+ ['frameless', 'Frameless'],
13
+ ['framed', 'Frame'],
14
+ ['thumbnail', 'Thumb'],
15
+ ]), horizAlign = new Set(['left', 'right', 'center', 'none']), vertAlign = new Set(['baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom']);
11
16
  /**
12
17
  * a more sophisticated string-explode function
13
18
  * @param start start syntax of a nested AST node
@@ -57,17 +62,24 @@ class FileToken extends base_1.LinkBaseToken {
57
62
  const { extension } = this.getTitle(true);
58
63
  this.append(...explode('-{', '}-', '|', text).map(
59
64
  // @ts-expect-error abstract class
60
- part => new imageParameter_1.ImageParameterToken(part, extension, config, accum)));
65
+ (part) => new imageParameter_1.ImageParameterToken(part, extension, config, accum)));
61
66
  }
62
67
  /** @private */
63
68
  lint(start = this.getAbsoluteIndex(), re) {
64
69
  const errors = super.lint(start, re), args = this.getAllArgs().filter(({ childNodes }) => {
65
70
  const visibleNodes = childNodes.filter(node => node.text().trim());
66
71
  return visibleNodes.length !== 1 || visibleNodes[0].type !== 'arg';
67
- }), keys = [...new Set(args.map(({ name }) => name))].filter(key => key !== 'invalid'), frameKeys = keys.filter(key => frame.has(key)), horizAlignKeys = keys.filter(key => horizAlign.has(key)), vertAlignKeys = keys.filter(key => vertAlign.has(key)), rect = new rect_1.BoundingRect(this, start);
72
+ }), keys = [...new Set(args.map(({ name }) => name))], frameKeys = keys.filter(key => frame.has(key)), horizAlignKeys = keys.filter(key => horizAlign.has(key)), vertAlignKeys = keys.filter(key => vertAlign.has(key)), [fr] = frameKeys, unscaled = fr === 'framed' || fr === 'manualthumb', rect = new rect_1.BoundingRect(this, start);
68
73
  if (this.closest('ext-link-text') && this.getValue('link')?.trim() !== '') {
69
74
  errors.push((0, lint_1.generateForSelf)(this, rect, 'nested-link', 'internal link in an external link'));
70
75
  }
76
+ if (unscaled) {
77
+ for (const arg of args.filter(({ name }) => name === 'width')) {
78
+ const e = (0, lint_1.generateForChild)(arg, rect, 'invalid-gallery', 'invalid image parameter');
79
+ e.fix = { range: [e.startIndex - 1, e.endIndex], text: '' };
80
+ errors.push(e);
81
+ }
82
+ }
71
83
  if (args.length === keys.length
72
84
  && frameKeys.length < 2
73
85
  && horizAlignKeys.length < 2
@@ -81,6 +93,9 @@ class FileToken extends base_1.LinkBaseToken {
81
93
  */
82
94
  const generate = (msg, p1) => (arg) => (0, lint_1.generateForChild)(arg, rect, 'no-duplicate', index_1.default.msg(`${msg} image $1 parameter`, p1));
83
95
  for (const key of keys) {
96
+ if (key === 'invalid' || key === 'width' && unscaled) {
97
+ continue;
98
+ }
84
99
  let relevantArgs = args.filter(({ name }) => name === key);
85
100
  if (key === 'caption') {
86
101
  relevantArgs = [...relevantArgs.slice(0, -1).filter(arg => arg.text()), ...relevantArgs.slice(-1)];
@@ -111,34 +126,13 @@ class FileToken extends base_1.LinkBaseToken {
111
126
  getArgs(key) {
112
127
  return this.getAllArgs().filter(({ name }) => key === name);
113
128
  }
114
- /**
115
- * 获取特定类型的图片属性参数节点
116
- * @param keys 接受的参数名
117
- * @param type 类型名
118
- */
119
- #getTypedArgs(keys, type) {
120
- const args = this.getAllArgs().filter(({ name }) => keys.has(name));
121
- return args;
122
- }
123
- /** 获取图片框架属性参数节点 */
124
- getFrameArgs() {
125
- return this.#getTypedArgs(frame, 'frame');
126
- }
127
- /** 获取图片水平对齐参数节点 */
128
- getHorizAlignArgs() {
129
- return this.#getTypedArgs(horizAlign, 'horizontal-align');
130
- }
131
- /** 获取图片垂直对齐参数节点 */
132
- getVertAlignArgs() {
133
- return this.#getTypedArgs(vertAlign, 'vertical-align');
134
- }
135
129
  /**
136
130
  * 获取生效的指定图片参数
137
131
  * @param key 参数名
138
132
  */
139
133
  getArg(key) {
140
134
  const args = this.getArgs(key);
141
- return args[args.length - 1];
135
+ return args[key === 'manualthumb' ? 0 : args.length - 1];
142
136
  }
143
137
  /**
144
138
  * 获取生效的指定图片参数值
@@ -6,7 +6,7 @@ import type { Title } from '../../lib/title';
6
6
  import type { Token, AtomToken } from '../../internal';
7
7
  /**
8
8
  * 重定向目标
9
- * @classdesc `{childNodes: [AtomToken, ?Token]}`
9
+ * @classdesc `{childNodes: [AtomToken, ?NoincludeToken]}`
10
10
  */
11
11
  export declare abstract class RedirectTargetToken extends LinkBaseToken {
12
12
  readonly childNodes: readonly [AtomToken] | readonly [AtomToken, NoincludeToken];
@@ -7,7 +7,7 @@ const base_1 = require("./base");
7
7
  const noinclude_1 = require("../nowiki/noinclude");
8
8
  /**
9
9
  * 重定向目标
10
- * @classdesc `{childNodes: [AtomToken, ?Token]}`
10
+ * @classdesc `{childNodes: [AtomToken, ?NoincludeToken]}`
11
11
  */
12
12
  class RedirectTargetToken extends base_1.LinkBaseToken {
13
13
  get type() {
@@ -30,20 +30,13 @@ class RedirectTargetToken extends base_1.LinkBaseToken {
30
30
  return this.normalizeTitle(this.firstChild.toString(), 0, true, true);
31
31
  }
32
32
  /** @private */
33
- text() {
34
- return `[[${this.firstChild.toString()}]]`;
35
- }
36
- /** @private */
37
33
  lint(start = this.getAbsoluteIndex()) {
38
- const errors = super.lint(start, /\]\]/u);
34
+ const errors = super.lint(start, false);
39
35
  if (this.length === 2) {
40
36
  const e = (0, lint_1.generateForChild)(this.lastChild, { start }, 'no-ignored', 'useless link text');
41
37
  e.startIndex--;
42
38
  e.startCol--;
43
- e.fix = {
44
- range: [e.startIndex, e.endIndex],
45
- text: '',
46
- };
39
+ e.fix = { range: [e.startIndex, e.endIndex], text: '' };
47
40
  errors.push(e);
48
41
  }
49
42
  return errors;
@@ -13,6 +13,8 @@ export declare abstract class MagicLinkToken extends Token {
13
13
  abstract get firstChild(): AstText | TranscludeToken;
14
14
  abstract get lastChild(): AstText | CommentToken | IncludeToken | NoincludeToken | TranscludeToken;
15
15
  get type(): ExtLinkTypes;
16
+ /** 链接显示文字 */
17
+ get innerText(): string;
16
18
  /** 和内链保持一致 */
17
19
  get link(): string;
18
20
  /**
@@ -16,21 +16,26 @@ class MagicLinkToken extends index_2.Token {
16
16
  get type() {
17
17
  return this.#type;
18
18
  }
19
- /** 和内链保持一致 */
20
- get link() {
21
- const map = { '!': '|', '=': '=' };
19
+ /** 链接显示文字 */
20
+ get innerText() {
21
+ const map = new Map([['!', '|'], ['=', '=']]);
22
22
  let link = (0, string_1.text)(this.childNodes.map(child => {
23
- const { type, name } = child;
24
- return type === 'magic-word' && String(name) in map ? map[name] : child;
23
+ const { type } = child, name = String(child.name);
24
+ return type === 'magic-word' && map.has(name) ? map.get(name) : child;
25
25
  }));
26
26
  if (this.type === 'magic-link') {
27
27
  link = link.replace(spaceRegex, ' ');
28
- if (link.startsWith('ISBN')) {
29
- link = `ISBN ${link.slice(5).replace(/[- ]/gu, '').replace(/x$/u, 'X')}`;
30
- }
31
28
  }
32
29
  return link;
33
30
  }
31
+ /** 和内链保持一致 */
32
+ get link() {
33
+ let { innerText } = this;
34
+ if (this.type === 'magic-link' && innerText.startsWith('ISBN')) {
35
+ innerText = `ISBN ${innerText.slice(5).replace(/[- ]/gu, '').replace(/x$/u, 'X')}`;
36
+ }
37
+ return innerText;
38
+ }
34
39
  /**
35
40
  * @param url 网址
36
41
  * @param type 类型
@@ -55,51 +60,30 @@ class MagicLinkToken extends index_2.Token {
55
60
  }
56
61
  return errors;
57
62
  }
58
- const pipe = this.type === 'ext-link-url', source = pipe ? String.raw `\|+` : '[,;。:!?()]+', regex = new RegExp(source, 'u'), regexGlobal = new RegExp(source, 'gu');
59
- for (const child of this.childNodes) {
60
- const { type, data } = child;
61
- if (type !== 'text' || !regex.test(data)) {
62
- continue;
63
- }
64
- const refError = (0, lint_1.generateForChild)(child, rect, 'unterminated-url', '', 'warning');
65
- regexGlobal.lastIndex = 0;
66
- for (let mt = regexGlobal.exec(data); mt; mt = regexGlobal.exec(data)) {
67
- const { index, 0: s } = mt, lines = data.slice(0, index).split('\n'), top = lines.length, left = lines[top - 1].length, startIndex = refError.startIndex + index, startLine = refError.startLine + top - 1, startCol = top === 1 ? refError.startCol + left : left;
68
- const e = {
69
- ...refError,
70
- message: index_1.default.msg('$1 in URL', pipe ? '"|"' : 'full-width punctuation'),
71
- startIndex,
72
- endIndex: startIndex + s.length,
73
- startLine,
74
- endLine: startLine,
75
- startCol,
76
- endCol: startCol + s.length,
77
- };
78
- if (!pipe) {
79
- e.suggestions = [
80
- {
81
- desc: 'whitespace',
82
- range: [startIndex, startIndex],
83
- text: ' ',
84
- },
85
- {
86
- desc: 'escape',
87
- range: [startIndex, e.endIndex],
88
- text: encodeURI(s),
89
- },
90
- ];
91
- }
92
- else if (s.length === 1) {
93
- e.suggestions = [
94
- {
95
- desc: 'whitespace',
96
- range: [startIndex, startIndex + 1],
97
- text: ' ',
98
- },
99
- ];
100
- }
101
- errors.push(e);
102
- }
63
+ const pipe = this.type === 'ext-link-url', regex = pipe ? /\|/u : /[,;。:!?()]+/u, child = this.childNodes.find((c) => c.type === 'text' && regex.test(c.data));
64
+ if (child) {
65
+ const { data } = child, e = (0, lint_1.generateForChild)(child, rect, 'unterminated-url', index_1.default.msg('$1 in URL', pipe ? '"|"' : 'full-width punctuation'), 'warning'), { index, 0: s } = regex.exec(data), i = e.startIndex + index;
66
+ e.suggestions = pipe
67
+ ? [
68
+ {
69
+ desc: 'whitespace',
70
+ range: [i, i + 1],
71
+ text: ' ',
72
+ },
73
+ ]
74
+ : [
75
+ {
76
+ desc: 'whitespace',
77
+ range: [i, i],
78
+ text: ' ',
79
+ },
80
+ {
81
+ desc: 'escape',
82
+ range: [i, i + s.length],
83
+ text: encodeURI(s),
84
+ },
85
+ ];
86
+ errors.push(e);
103
87
  }
104
88
  return errors;
105
89
  }
@@ -61,7 +61,7 @@ class NestedToken extends index_2.Token {
61
61
  },
62
62
  {
63
63
  desc: 'comment',
64
- range: [e.startIndex, e.startIndex],
64
+ range: [e.startIndex, e.endIndex],
65
65
  text: `<!--${child.toString()}-->`,
66
66
  },
67
67
  ];
@@ -41,7 +41,7 @@ const index_1 = require("../../index");
41
41
  const base_1 = require("./base");
42
42
  /** HTML注释,不可见 */
43
43
  let CommentToken = (() => {
44
- let _classDecorators = [(0, hidden_1.hiddenToken)()];
44
+ let _classDecorators = [(0, hidden_1.hiddenToken)(false)];
45
45
  let _classDescriptor;
46
46
  let _classExtraInitializers = [];
47
47
  let _classThis;
@@ -74,15 +74,12 @@ let CommentToken = (() => {
74
74
  return [];
75
75
  }
76
76
  const e = (0, lint_1.generateForSelf)(this, { start }, 'unclosed-comment', index_1.default.msg('unclosed $1', 'HTML comment'));
77
- e.fix = {
78
- range: [e.endIndex, e.endIndex],
79
- text: '-->',
80
- };
77
+ e.fix = { range: [e.endIndex, e.endIndex], text: '-->' };
81
78
  return [e];
82
79
  }
83
80
  /** @private */
84
- toString() {
85
- return `<!--${this.innerText}${this.closed ? '-->' : ''}`;
81
+ toString(skip) {
82
+ return skip ? '' : `<!--${this.innerText}${this.closed ? '-->' : ''}`;
86
83
  }
87
84
  };
88
85
  return CommentToken = _classThis;