wikiparser-node 1.23.0 → 1.24.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/README.md +3 -3
  2. package/bin/config.js +2 -2
  3. package/bundle/bundle-es8.min.js +24 -24
  4. package/config/default.json +6 -0
  5. package/config/enwiki.json +2 -2
  6. package/config/llwiki.json +382 -261
  7. package/config/moegirl.json +325 -325
  8. package/coverage/badge.svg +1 -1
  9. package/dist/base.d.mts +18 -2
  10. package/dist/base.d.ts +18 -2
  11. package/dist/bin/config.js +17 -5
  12. package/dist/index.d.ts +2 -1
  13. package/dist/index.js +3 -6
  14. package/dist/lib/element.d.ts +7 -7
  15. package/dist/lib/element.js +16 -13
  16. package/dist/lib/lsp.d.ts +19 -1
  17. package/dist/lib/lsp.js +130 -15
  18. package/dist/lib/node.d.ts +2 -1
  19. package/dist/lib/node.js +10 -2
  20. package/dist/lib/text.d.ts +17 -16
  21. package/dist/lib/text.js +77 -61
  22. package/dist/lib/title.js +4 -3
  23. package/dist/mixin/attributesParent.js +1 -1
  24. package/dist/mixin/elementLike.d.ts +7 -7
  25. package/dist/mixin/elementLike.js +9 -6
  26. package/dist/mixin/noEscape.js +2 -0
  27. package/dist/parser/commentAndExt.js +7 -8
  28. package/dist/parser/externalLinks.js +2 -2
  29. package/dist/parser/hrAndDoubleUnderscore.js +8 -5
  30. package/dist/src/arg.js +4 -4
  31. package/dist/src/attribute.d.ts +1 -1
  32. package/dist/src/attribute.js +11 -10
  33. package/dist/src/attributes.js +4 -4
  34. package/dist/src/converter.js +1 -1
  35. package/dist/src/converterFlags.js +2 -2
  36. package/dist/src/gallery.js +8 -7
  37. package/dist/src/heading.js +16 -7
  38. package/dist/src/html.js +16 -14
  39. package/dist/src/imageParameter.js +2 -2
  40. package/dist/src/imagemap.js +2 -2
  41. package/dist/src/index.d.ts +4 -0
  42. package/dist/src/index.js +1 -1
  43. package/dist/src/link/base.js +5 -18
  44. package/dist/src/link/file.js +14 -5
  45. package/dist/src/link/galleryImage.js +1 -1
  46. package/dist/src/link/index.js +6 -3
  47. package/dist/src/link/redirectTarget.js +1 -1
  48. package/dist/src/magicLink.js +4 -4
  49. package/dist/src/nested.js +2 -2
  50. package/dist/src/nowiki/base.js +1 -1
  51. package/dist/src/nowiki/comment.js +1 -1
  52. package/dist/src/nowiki/index.js +2 -2
  53. package/dist/src/nowiki/quote.js +10 -10
  54. package/dist/src/onlyinclude.js +1 -1
  55. package/dist/src/paramTag/index.js +1 -1
  56. package/dist/src/parameter.js +1 -1
  57. package/dist/src/redirect.js +2 -2
  58. package/dist/src/table/base.d.ts +2 -1
  59. package/dist/src/table/base.js +18 -15
  60. package/dist/src/table/index.js +6 -8
  61. package/dist/src/table/td.d.ts +1 -1
  62. package/dist/src/table/td.js +13 -21
  63. package/dist/src/tagPair/include.js +2 -2
  64. package/dist/src/tagPair/index.js +2 -2
  65. package/dist/src/transclude.js +8 -14
  66. package/dist/util/lint.js +89 -4
  67. package/dist/util/sharable.js +1 -1
  68. package/dist/util/sharable.mjs +1 -1
  69. package/dist/util/string.js +11 -10
  70. package/extensions/typings.d.ts +3 -1
  71. package/package.json +8 -8
  72. package/bundle/bundle-lsp.min.js +0 -32
  73. package/bundle/bundle.min.js +0 -29
  74. package/extensions/dist/base.js +0 -353
  75. package/extensions/dist/codejar.js +0 -57
  76. package/extensions/dist/editor.js +0 -159
  77. package/extensions/dist/highlight.js +0 -30
  78. package/extensions/dist/lint.js +0 -80
  79. package/extensions/dist/lsp.js +0 -83
  80. package/extensions/editor.css +0 -59
  81. package/extensions/ui.css +0 -1
@@ -41,6 +41,7 @@ exports.HeadingToken = void 0;
41
41
  const lint_1 = require("../util/lint");
42
42
  const debug_1 = require("../util/debug");
43
43
  const rect_1 = require("../lib/rect");
44
+ const noEscape_1 = require("../mixin/noEscape");
44
45
  const index_1 = __importDefault(require("../index"));
45
46
  const index_2 = require("./index");
46
47
  const syntax_1 = require("./syntax");
@@ -50,7 +51,6 @@ const string_1 = require("../util/string");
50
51
  const html_1 = require("../util/html");
51
52
  const fixed_1 = require("../mixin/fixed");
52
53
  const sol_1 = require("../mixin/sol");
53
- const noEscape_1 = require("../mixin/noEscape");
54
54
  const cached_1 = require("../mixin/cached");
55
55
  /* NOT FOR BROWSER END */
56
56
  /**
@@ -160,7 +160,7 @@ let HeadingToken = (() => {
160
160
  if (severities[0] && this.level === 1) {
161
161
  const e = (0, lint_1.generateForChild)(firstChild, rect, rules[0], '<h1>', severities[0]);
162
162
  if (!unbalanced) {
163
- e.suggestions = [{ desc: 'h2', range: [e.startIndex, e.endIndex], text: `=${innerStr}=` }];
163
+ e.suggestions = [(0, lint_1.fixBy)(e, 'h2', `=${innerStr}=`)];
164
164
  }
165
165
  errors.push(e);
166
166
  }
@@ -198,22 +198,31 @@ let HeadingToken = (() => {
198
198
  ...rect, // eslint-disable-line @typescript-eslint/no-misused-spread
199
199
  start: start + level,
200
200
  left: rect.left + level,
201
- }, rules[2], index_1.default.msg('unbalanced $1 in a section header', 'bold apostrophes'), severities[2]), end = start + level + innerStr.length;
201
+ }, rules[2], index_1.default.msg('unbalanced $1 in a section header', 'bold apostrophes'), severities[2]), end = start + level + innerStr.length, remove = (0, lint_1.fixByRemove)(e);
202
202
  if (rootStr.slice(e.endIndex, end).trim()) {
203
- e.suggestions = [{ desc: 'close', range: [end, end], text: `'''` }];
203
+ e.suggestions = [
204
+ remove,
205
+ (0, lint_1.fixByClose)(end, `'''`),
206
+ ];
207
+ }
208
+ else if (boldQuotes.length === 1 && italicQuotes.length === 0) {
209
+ e.fix = remove;
204
210
  }
205
211
  else {
206
- e.fix = { desc: 'remove', range: [e.startIndex, e.endIndex], text: '' };
212
+ e.suggestions = [remove];
207
213
  }
208
214
  errors.push(e);
209
215
  }
210
216
  if (italicQuotes.length % 2) {
211
217
  const e = (0, lint_1.generateForChild)(italicQuotes[italicQuotes.length - 1], { start: start + level }, rules[2], index_1.default.msg('unbalanced $1 in a section header', 'italic apostrophes'), severities[2]), end = start + level + innerStr.length;
212
218
  if (rootStr.slice(e.endIndex, end).trim()) {
213
- e.suggestions = [{ desc: 'close', range: [end, end], text: `''` }];
219
+ e.suggestions = [(0, lint_1.fixByClose)(end, `''`)];
220
+ }
221
+ else if (italicQuotes.length === 1 && boldQuotes.length === 0) {
222
+ e.fix = (0, lint_1.fixByRemove)(e);
214
223
  }
215
224
  else {
216
- e.fix = { desc: 'remove', range: [e.startIndex, e.endIndex], text: '' };
225
+ e.suggestions = [(0, lint_1.fixByRemove)(e)];
217
226
  }
218
227
  errors.push(e);
219
228
  }
package/dist/src/html.js CHANGED
@@ -204,7 +204,7 @@ let HtmlToken = (() => {
204
204
  if (s) {
205
205
  const e = (0, lint_1.generateForSelf)(this, rect, rule, 'HTML tag in table attributes', s);
206
206
  if (severity === 2) {
207
- e.fix = { desc: 'remove', range: [start, e.endIndex], text: '' };
207
+ e.suggestions = [(0, lint_1.fixByRemove)(e)];
208
208
  }
209
209
  errors.push(e);
210
210
  }
@@ -215,32 +215,35 @@ let HtmlToken = (() => {
215
215
  }
216
216
  rule = 'bold-header';
217
217
  s = index_1.default.lintConfig.getSeverity(rule, name);
218
- if (s && (name === 'b' || name === 'strong') && this.closest('heading-title')) {
219
- errors.push((0, lint_1.generateForSelf)(this, rect, rule, 'bold in section header', s));
218
+ if (s && (name === 'b' || name === 'strong')
219
+ && this.closest('heading-title,ext')?.type === 'heading-title') {
220
+ const e = (0, lint_1.generateForSelf)(this, rect, rule, 'bold in section header', s);
221
+ e.suggestions = [(0, lint_1.fixByRemove)(e)];
222
+ errors.push(e);
220
223
  }
221
224
  const { html: [, flexibleTags, voidTags] } = this.getAttribute('config'), isVoid = voidTags.includes(name), isFlexible = flexibleTags.includes(name), isNormal = !isVoid && !isFlexible;
222
225
  rule = 'unmatched-tag';
223
226
  if (closing && (selfClosing || isVoid) || selfClosing && isNormal) {
224
227
  s = index_1.default.lintConfig.getSeverity(rule, closing ? 'both' : 'selfClosing');
225
228
  if (s) {
226
- const error = (0, lint_1.generateForSelf)(this, rect, rule, closing ? 'tag that is both closing and self-closing' : 'invalid self-closing tag', s), open = { desc: 'open', range: [start + 1, start + 2], text: '' }, noSelfClosing = {
229
+ const e = (0, lint_1.generateForSelf)(this, rect, rule, closing ? 'tag that is both closing and self-closing' : 'invalid self-closing tag', s), open = (0, lint_1.fixByOpen)(start), noSelfClosing = {
227
230
  desc: 'no self-closing',
228
- range: [error.endIndex - 2, error.endIndex - 1],
231
+ range: [e.endIndex - 2, e.endIndex - 1],
229
232
  text: '',
230
233
  };
231
234
  if (isFlexible) {
232
- error.suggestions = [open, noSelfClosing];
235
+ e.suggestions = [open, noSelfClosing];
233
236
  }
234
237
  else if (closing) {
235
- error.fix = isVoid ? open : noSelfClosing;
238
+ e.fix = isVoid ? open : noSelfClosing;
236
239
  }
237
240
  else {
238
- error.suggestions = [
241
+ e.suggestions = [
239
242
  noSelfClosing,
240
- { desc: 'close', range: [error.endIndex - 2, error.endIndex], text: `></${name}>` },
243
+ (0, lint_1.fixByClose)(e.endIndex, `></${name}>`, -2),
241
244
  ];
242
245
  }
243
- errors.push(error);
246
+ errors.push(e);
244
247
  }
245
248
  }
246
249
  else if (!this.findMatchingTag()) {
@@ -250,15 +253,14 @@ let HtmlToken = (() => {
250
253
  }
251
254
  else if (closing) {
252
255
  s = index_1.default.lintConfig.getSeverity(rule, 'closing');
253
- error.suggestions = [{ desc: 'remove', range: [start, error.endIndex], text: '' }];
256
+ error.suggestions = [(0, lint_1.fixByRemove)(error)];
254
257
  }
255
258
  else {
256
259
  s = index_1.default.lintConfig.getSeverity(rule, 'opening');
257
260
  const childNodes = parentNode?.childNodes;
258
261
  if (formattingTags.has(name)) {
259
- if (childNodes?.slice(0, childNodes.indexOf(this))
260
- .some(({ type, name: n }) => type === 'html' && n === name)) {
261
- error.suggestions = [{ desc: 'close', range: [start + 1, start + 1], text: '/' }];
262
+ if (childNodes?.slice(0, childNodes.indexOf(this)).some(tag => tag.type === 'html' && tag.name === name && !tag.findMatchingTag())) {
263
+ error.suggestions = [(0, lint_1.fixByClose)(start + 1, '/')];
262
264
  }
263
265
  if (this.closest('heading-title')) {
264
266
  error.rule = 'format-leakage';
@@ -201,7 +201,7 @@ class ImageParameterToken extends index_2.Token {
201
201
  const rule = 'invalid-gallery', s = index_1.default.lintConfig.getSeverity(rule, 'parameter');
202
202
  if (s) {
203
203
  const e = (0, lint_1.generateForSelf)(this, { start }, rule, 'invalid image parameter', s);
204
- e.fix = { desc: 'remove', range: [start - 1, e.endIndex], text: '' };
204
+ e.fix = (0, lint_1.fixByRemove)(e, -1);
205
205
  errors.push(e);
206
206
  }
207
207
  }
@@ -209,7 +209,7 @@ class ImageParameterToken extends index_2.Token {
209
209
  const rule = 'url-encoding', s = index_1.default.lintConfig.getSeverity(rule, 'file');
210
210
  if (s) {
211
211
  const e = (0, lint_1.generateForSelf)(this, { start }, rule, 'unnecessary URL encoding in an internal link', s);
212
- e.suggestions = [{ desc: 'decode', range: [start, e.endIndex], text: (0, string_1.rawurldecode)(this.text()) }];
212
+ e.fix = (0, lint_1.fixByDecode)(e, this);
213
213
  errors.push(e);
214
214
  }
215
215
  }
@@ -157,8 +157,8 @@ let ImagemapToken = (() => {
157
157
  }).map(child => {
158
158
  const e = (0, lint_1.generateForChild)(child, rect, rule, 'invalid link in <imagemap>', s);
159
159
  e.suggestions = [
160
- { desc: 'remove', range: [e.startIndex - 1, e.endIndex], text: '' },
161
- { desc: 'comment', range: [e.startIndex, e.startIndex], text: '# ' },
160
+ (0, lint_1.fixByRemove)(e, -1),
161
+ (0, lint_1.fixBy)(e, 'comment', '# '),
162
162
  ];
163
163
  return e;
164
164
  }));
@@ -7,6 +7,9 @@ import type { AstNodes, IncludeToken, HtmlToken, ExtToken, CommentToken } from '
7
7
  import { Ranges } from '../lib/ranges';
8
8
  import { AstRange } from '../lib/range';
9
9
  import type { Range } from '../lib/ranges';
10
+ declare type ExtendedLintError = LintError[] & {
11
+ output?: string;
12
+ };
10
13
  /**
11
14
  * base class for all tokens
12
15
  *
@@ -147,3 +150,4 @@ export declare class Token extends AstElement {
147
150
  */
148
151
  buildLists(): void;
149
152
  }
153
+ export {};
package/dist/src/index.js CHANGED
@@ -555,7 +555,7 @@ let Token = (() => {
555
555
  errors.push(...[...value].map(cat => {
556
556
  const e = (0, lint_1.generateForSelf)(cat, { start: cat.getAbsoluteIndex() }, r, msg, severity);
557
557
  if (isCat) {
558
- e.suggestions = [{ desc: 'remove', range: [e.startIndex, e.endIndex], text: '' }];
558
+ e.suggestions = [(0, lint_1.fixByRemove)(e)];
559
559
  }
560
560
  return e;
561
561
  }));
@@ -40,15 +40,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.LinkBaseToken = void 0;
41
41
  const lint_1 = require("../../util/lint");
42
42
  const constants_1 = require("../../util/constants");
43
- const string_1 = require("../../util/string");
44
43
  const rect_1 = require("../../lib/rect");
45
44
  const padded_1 = require("../../mixin/padded");
45
+ const noEscape_1 = require("../../mixin/noEscape");
46
46
  const index_1 = __importDefault(require("../../index"));
47
47
  const index_2 = require("../index");
48
48
  const atom_1 = require("../atom");
49
49
  /* NOT FOR BROWSER */
50
50
  const debug_1 = require("../../util/debug");
51
- const noEscape_1 = require("../../mixin/noEscape");
51
+ const string_1 = require("../../util/string");
52
52
  const cached_1 = require("../../mixin/cached");
53
53
  /* NOT FOR BROWSER END */
54
54
  /**
@@ -223,7 +223,7 @@ let LinkBaseToken = (() => {
223
223
  s = index_1.default.lintConfig.getSeverity(rule);
224
224
  if (s && encoded) {
225
225
  const e = (0, lint_1.generateForChild)(target, rect, rule, 'unnecessary URL encoding in an internal link', s);
226
- e.fix = { desc: 'decode', range: [e.startIndex, e.endIndex], text: (0, string_1.rawurldecode)(target.text()) };
226
+ e.fix = (0, lint_1.fixByDecode)(e, target);
227
227
  errors.push(e);
228
228
  }
229
229
  rule = 'pipe-like';
@@ -232,13 +232,7 @@ let LinkBaseToken = (() => {
232
232
  const j = linkText?.childNodes.findIndex(c => c.type === 'text' && c.data.includes('|')), textNode = linkText?.childNodes[j];
233
233
  if (textNode) {
234
234
  const e = (0, lint_1.generateForChild)(linkText, rect, rule, 'additional "|" in the link text', s), i = e.startIndex + linkText.getRelativeIndex(j);
235
- e.suggestions = [
236
- {
237
- desc: 'escape',
238
- range: [i, i + textNode.data.length],
239
- text: textNode.data.replace(/\|/gu, '&#124;'),
240
- },
241
- ];
235
+ e.suggestions = [(0, lint_1.fixByPipe)(i, textNode.data)];
242
236
  errors.push(e);
243
237
  }
244
238
  }
@@ -247,14 +241,7 @@ let LinkBaseToken = (() => {
247
241
  if (s && fragment !== undefined && !isLink(type)) {
248
242
  const e = (0, lint_1.generateForChild)(target, rect, rule, 'useless fragment', s), j = target.childNodes.findIndex(c => c.type === 'text' && c.data.includes('#')), textNode = target.childNodes[j];
249
243
  if (textNode) {
250
- e.fix = {
251
- desc: 'remove',
252
- range: [
253
- e.startIndex + target.getRelativeIndex(j) + textNode.data.indexOf('#'),
254
- e.endIndex,
255
- ],
256
- text: '',
257
- };
244
+ e.fix = (0, lint_1.fixByRemove)(e, target.getRelativeIndex(j) + textNode.data.indexOf('#'));
258
245
  }
259
246
  errors.push(e);
260
247
  }
@@ -184,19 +184,28 @@ let FileToken = (() => {
184
184
  }
185
185
  /** @private */
186
186
  lint(start = this.getAbsoluteIndex(), re) {
187
- const errors = super.lint(start, re), args = filterArgs(this.getAllArgs(), argTypes), 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);
187
+ const errors = super.lint(start, re), args = filterArgs(this.getAllArgs(), argTypes), 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), { extension } = this;
188
188
  let rule = 'nested-link', s = index_1.default.lintConfig.getSeverity(rule, 'file');
189
189
  if (s
190
+ && extensions.has(extension)
190
191
  && this.closest('ext-link-text')
191
192
  && this.getValue('link')?.trim() !== '') {
192
- errors.push((0, lint_1.generateForSelf)(this, rect, rule, 'internal link in an external link', s));
193
+ const e = (0, lint_1.generateForSelf)(this, rect, rule, 'internal link in an external link', s), link = this.getArg('link');
194
+ if (link) {
195
+ const from = start + link.getRelativeIndex();
196
+ e.fix = { desc: 'delink', range: [from, from + link.toString().length], text: 'link=' };
197
+ }
198
+ else {
199
+ e.fix = (0, lint_1.fixByInsert)(e.endIndex - 2, 'delink', '|link=');
200
+ }
201
+ errors.push(e);
193
202
  }
194
203
  rule = 'invalid-gallery';
195
204
  s = index_1.default.lintConfig.getSeverity(rule, 'parameter');
196
205
  if (s && unscaled) {
197
206
  for (const arg of args.filter(({ name }) => name === 'width')) {
198
207
  const e = (0, lint_1.generateForChild)(arg, rect, rule, 'invalid image parameter', s);
199
- e.fix = { desc: 'remove', range: [e.startIndex - 1, e.endIndex], text: '' };
208
+ e.fix = (0, lint_1.fixByRemove)(e, -1);
200
209
  errors.push(e);
201
210
  }
202
211
  }
@@ -207,7 +216,7 @@ let FileToken = (() => {
207
216
  return errors;
208
217
  }
209
218
  rule = 'no-duplicate';
210
- const { extension } = this, severities = ['unknownImageParameter', 'imageParameter'].map(k => index_1.default.lintConfig.getSeverity(rule, k));
219
+ const severities = ['unknownImageParameter', 'imageParameter'].map(k => index_1.default.lintConfig.getSeverity(rule, k));
211
220
  /**
212
221
  * 图片参数到语法错误的映射
213
222
  * @param tokens 图片参数节点
@@ -221,7 +230,7 @@ let FileToken = (() => {
221
230
  return false;
222
231
  }
223
232
  const e = (0, lint_1.generateForChild)(arg, rect, rule, index_1.default.msg(`${msg} image $1 parameter`, p1), s);
224
- e.suggestions = [{ desc: 'remove', range: [e.startIndex - 1, e.endIndex], text: '' }];
233
+ e.suggestions = [(0, lint_1.fixByRemove)(e, -1)];
225
234
  return e;
226
235
  }).filter((e) => e !== false);
227
236
  for (const key of keys) {
@@ -123,7 +123,7 @@ let GalleryImageToken = (() => {
123
123
  const errors = super.lint(start, re), rule = 'invalid-gallery', s = index_1.default.lintConfig.getSeverity(rule, 'image');
124
124
  if (s && this.#lint()) {
125
125
  const e = (0, lint_1.generateForSelf)(this, { start }, rule, 'invalid gallery image', s);
126
- e.suggestions = [{ desc: 'prefix', range: [start, start], text: 'File:' }];
126
+ e.suggestions = [(0, lint_1.fixByInsert)(start, 'prefix', 'File:')];
127
127
  errors.push(e);
128
128
  }
129
129
  return errors;
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.LinkToken = void 0;
7
+ const common_1 = require("@bhsd/common");
7
8
  const lint_1 = require("../../util/lint");
8
9
  const index_1 = __importDefault(require("../../index"));
9
10
  const base_1 = require("./base");
@@ -22,13 +23,13 @@ class LinkToken extends base_1.LinkBaseToken {
22
23
  get type() {
23
24
  return 'link';
24
25
  }
25
- /* NOT FOR BROWSER */
26
26
  /** link text / 链接显示文字 */
27
27
  get innerText() {
28
28
  return this.length > 1
29
29
  ? this.lastChild.text()
30
- : (0, string_1.rawurldecode)(this.firstChild.text().replace(/^\s*:?/u, ''));
30
+ : (0, common_1.rawurldecode)(this.firstChild.text().replace(/^\s*:?/u, ''));
31
31
  }
32
+ /* NOT FOR BROWSER */
32
33
  set innerText(text) {
33
34
  this.setLinkText(text);
34
35
  }
@@ -47,7 +48,9 @@ class LinkToken extends base_1.LinkBaseToken {
47
48
  lint(start = this.getAbsoluteIndex(), re) {
48
49
  const errors = super.lint(start, re), rule = 'nested-link', s = index_1.default.lintConfig.getSeverity(rule);
49
50
  if (s && this.closest('ext-link-text')) {
50
- errors.push((0, lint_1.generateForSelf)(this, { start }, rule, 'internal link in an external link', s));
51
+ const e = (0, lint_1.generateForSelf)(this, { start }, rule, 'internal link in an external link', s);
52
+ e.fix = (0, lint_1.fixBy)(e, 'delink', this.innerText);
53
+ errors.push(e);
51
54
  }
52
55
  return errors;
53
56
  }
@@ -59,7 +59,7 @@ class RedirectTargetToken extends base_1.LinkBaseToken {
59
59
  const e = (0, lint_1.generateForChild)(this.lastChild, { start }, rule, 'useless link text', s);
60
60
  e.startIndex--;
61
61
  e.startCol--;
62
- e.fix = { desc: 'remove', range: [e.startIndex, e.endIndex], text: '' };
62
+ e.fix = (0, lint_1.fixByRemove)(e);
63
63
  errors.push(e);
64
64
  }
65
65
  return errors;
@@ -38,13 +38,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  };
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.MagicLinkToken = void 0;
41
- const common_1 = require("@bhsd/common");
42
41
  const lint_1 = require("../util/lint");
43
42
  const string_1 = require("../util/string");
44
43
  const rect_1 = require("../lib/rect");
45
44
  const index_1 = __importDefault(require("../index"));
46
45
  const index_2 = require("./index");
47
46
  /* NOT FOR BROWSER */
47
+ const common_1 = require("@bhsd/common");
48
48
  const debug_1 = require("../util/debug");
49
49
  const constants_1 = require("../util/constants");
50
50
  const clone_1 = require("../mixin/clone");
@@ -193,10 +193,10 @@ let MagicLinkToken = (() => {
193
193
  if (child) {
194
194
  const { data } = child, e = (0, lint_1.generateForChild)(child, rect, rule, index_1.default.msg('$1 in URL', pipe ? '"|"' : 'full-width punctuation'), severity), { index, 0: s } = regex.exec(data), i = e.startIndex + index;
195
195
  e.suggestions = pipe
196
- ? [{ desc: 'whitespace', range: [i, i + 1], text: ' ' }]
196
+ ? [(0, lint_1.fixBySpace)(i, 1)]
197
197
  : [
198
- { desc: 'whitespace', range: [i, i], text: ' ' },
199
- { desc: 'escape', range: [i, i + s.length], text: encodeURI(s) },
198
+ (0, lint_1.fixBySpace)(i),
199
+ { desc: 'encode', range: [i, i + s.length], text: encodeURI(s) },
200
200
  ];
201
201
  errors.push(e);
202
202
  }
@@ -130,8 +130,8 @@ let NestedToken = (() => {
130
130
  }).map(child => {
131
131
  const e = (0, lint_1.generateForChild)(child, rect, rule, index_1.default.msg('invalid content in <$1>', this.name), s);
132
132
  e.suggestions = [
133
- { desc: 'remove', range: [e.startIndex, e.endIndex], text: '' },
134
- { desc: 'comment', range: [e.startIndex, e.endIndex], text: `<!--${child.toString()}-->` },
133
+ (0, lint_1.fixByRemove)(e),
134
+ (0, lint_1.fixByComment)(e, child.toString()),
135
135
  ];
136
136
  return e;
137
137
  }),
@@ -35,12 +35,12 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
35
35
  };
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  exports.NowikiBaseToken = void 0;
38
+ const noEscape_1 = require("../../mixin/noEscape");
38
39
  const index_1 = require("../index");
39
40
  /* NOT FOR BROWSER */
40
41
  const debug_1 = require("../../util/debug");
41
42
  const constants_1 = require("../../util/constants");
42
43
  const fixed_1 = require("../../mixin/fixed");
43
- const noEscape_1 = require("../../mixin/noEscape");
44
44
  /**
45
45
  * text-only token that will not be parsed
46
46
  *
@@ -95,7 +95,7 @@ let CommentToken = (() => {
95
95
  return [];
96
96
  }
97
97
  const e = (0, lint_1.generateForSelf)(this, { start }, rule, index_1.default.msg('unclosed $1', 'HTML comment'), s);
98
- e.suggestions = [{ desc: 'close', range: [e.endIndex, e.endIndex], text: '-->' }];
98
+ e.suggestions = [(0, lint_1.fixByClose)(e.endIndex, '-->')];
99
99
  return [e];
100
100
  }
101
101
  /** @private */
@@ -13,7 +13,7 @@ const constants_1 = require("../../util/constants");
13
13
  /* NOT FOR BROWSER END */
14
14
  /<\s*(?:\/\s*)?(nowiki)\b/giu; // eslint-disable-line @typescript-eslint/no-unused-expressions
15
15
  const getLintRegex = (0, common_1.getRegex)(name => new RegExp(String.raw `<\s*(?:/\s*)${name === 'nowiki' ? '' : '?'}(${name})\b`, 'giu'));
16
- const voidExt = new Set(['img', 'languages', 'section', 'templatestyles']);
16
+ const voidExt = new Set(['languages', 'section', 'templatestyles']);
17
17
  /**
18
18
  * text-only token inside an extension tag
19
19
  *
@@ -34,7 +34,7 @@ class NowikiToken extends base_1.NowikiBaseToken {
34
34
  const { name } = this, rule = 'void-ext', s = index_1.default.lintConfig.getSeverity(rule, name);
35
35
  if (s && this.#lint()) {
36
36
  const e = (0, lint_1.generateForSelf)(this, { start }, rule, index_1.default.msg('nothing should be in <$1>', name), s);
37
- e.fix = { desc: 'empty', range: [start, e.endIndex], text: '' };
37
+ e.suggestions = [(0, lint_1.fixByRemove)(e)];
38
38
  return [e];
39
39
  }
40
40
  return super.lint(start, getLintRegex(name));
@@ -117,24 +117,24 @@ let QuoteToken = (() => {
117
117
  if (previousData?.endsWith(`'`)) {
118
118
  const severity = severities[(closing.bold || closing.italic) && /[a-z\d]'$/iu.test(previousData) ? 1 : 0];
119
119
  if (severity) {
120
- const e = (0, lint_1.generateForSelf)(this, rect, rules[0], index_1.default.msg('lonely "$1"', `'`), severity), { startIndex: endIndex, startLine: endLine, startCol: endCol } = e, [, { length }] = /(?:^|[^'])('+)$/u.exec(previousData), startIndex = start - length;
121
- errors.push({
120
+ const e = (0, lint_1.generateForSelf)(this, rect, rules[0], index_1.default.msg('lonely "$1"', `'`), severity), { startLine: endLine, startCol: endCol } = e, [, { length }] = /(?:^|[^'])('+)$/u.exec(previousData), startIndex = start - length, eNew = {
122
121
  ...e,
123
122
  startIndex,
124
- endIndex,
123
+ endIndex: start,
125
124
  endLine,
126
125
  startCol: endCol - length,
127
126
  endCol,
128
- suggestions: [
129
- { desc: 'escape', range: [startIndex, endIndex], text: '&apos;'.repeat(length) },
130
- { desc: 'remove', range: [startIndex, endIndex], text: '' },
131
- ],
132
- });
127
+ };
128
+ eNew.suggestions = [
129
+ (0, lint_1.fixByEscape)(startIndex, '&apos;', length),
130
+ (0, lint_1.fixByRemove)(eNew),
131
+ ];
132
+ errors.push(eNew);
133
133
  }
134
134
  }
135
- if (s && bold && this.closest('heading-title')) {
135
+ if (s && bold && this.closest('heading-title,ext')?.type === 'heading-title') {
136
136
  const e = (0, lint_1.generateForSelf)(this, rect, rules[1], 'bold in section header', s);
137
- e.suggestions = [{ desc: 'remove', range: [start, start + 3], text: '' }];
137
+ e.suggestions = [(0, lint_1.fixByRemove)(e)];
138
138
  errors.push(e);
139
139
  }
140
140
  return errors;
@@ -39,11 +39,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
40
  exports.OnlyincludeToken = void 0;
41
41
  const padded_1 = require("../mixin/padded");
42
+ const noEscape_1 = require("../mixin/noEscape");
42
43
  const index_1 = require("./index");
43
44
  /* NOT FOR BROWSER */
44
45
  const constants_1 = require("../util/constants");
45
46
  const clone_1 = require("../mixin/clone");
46
- const noEscape_1 = require("../mixin/noEscape");
47
47
  const index_2 = __importDefault(require("../index"));
48
48
  /* NOT FOR BROWSER END */
49
49
  /**
@@ -112,7 +112,7 @@ let ParamTagToken = (() => {
112
112
  const i = grandChildren.findIndex(({ type }) => type !== 'text'), str = grandChildren.slice(0, i === -1 ? undefined : i).map(String).join('');
113
113
  if (str && !(i === -1 ? /^[a-z]+(?:\[\])?\s*=/iu : /^[a-z]+(?:\[\])?\s*(?:=|$)/iu).test(str)) {
114
114
  const e = (0, lint_1.generateForChild)(child, rect, rule, msg, s);
115
- e.suggestions = [{ desc: 'remove', range: [e.startIndex, e.endIndex], text: '' }];
115
+ e.suggestions = [(0, lint_1.fixByRemove)(e)];
116
116
  errors.push(e);
117
117
  }
118
118
  else {
@@ -186,7 +186,7 @@ let ParameterToken = (() => {
186
186
  e.startCol = e.endCol;
187
187
  e.endIndex++;
188
188
  e.endCol++;
189
- e.fix = { desc: 'escape', range: [e.startIndex, e.endIndex], text: '{{=}}' };
189
+ e.fix = (0, lint_1.fixByEscape)(e.startIndex, '{{=}}');
190
190
  errors.push(e);
191
191
  }
192
192
  }
@@ -36,6 +36,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  exports.RedirectToken = void 0;
38
38
  const hidden_1 = require("../mixin/hidden");
39
+ const noEscape_1 = require("../mixin/noEscape");
39
40
  const index_1 = require("./index");
40
41
  const syntax_1 = require("./syntax");
41
42
  const redirectTarget_1 = require("./link/redirectTarget");
@@ -44,7 +45,6 @@ const common_1 = require("@bhsd/common");
44
45
  const constants_1 = require("../util/constants");
45
46
  const debug_1 = require("../util/debug");
46
47
  const fixed_1 = require("../mixin/fixed");
47
- const noEscape_1 = require("../mixin/noEscape");
48
48
  /^(?:#redirect|#重定向)\s*(?::\s*)?$/iu; // eslint-disable-line @typescript-eslint/no-unused-expressions
49
49
  const getPattern = (0, common_1.getRegex)(redirection => new RegExp(String.raw `^(?:${redirection.join('|')})\s*(?::\s*)?$`, 'iu'));
50
50
  /* NOT FOR BROWSER END */
@@ -55,7 +55,7 @@ const getPattern = (0, common_1.getRegex)(redirection => new RegExp(String.raw `
55
55
  * @classdesc `{childNodes: [SyntaxToken, LinkToken]}`
56
56
  */
57
57
  let RedirectToken = (() => {
58
- let _classDecorators = [fixed_1.fixedToken, noEscape_1.noEscape, (0, hidden_1.hiddenToken)(false, false)];
58
+ let _classDecorators = [fixed_1.fixedToken, (0, hidden_1.hiddenToken)(false, false), noEscape_1.noEscape];
59
59
  let _classDescriptor;
60
60
  let _classExtraInitializers = [];
61
61
  let _classThis;
@@ -1,3 +1,4 @@
1
+ import Parser from '../../index';
1
2
  import { Token } from '../index';
2
3
  import { SyntaxToken } from '../syntax';
3
4
  import { AttributesToken } from '../attributes';
@@ -21,7 +22,7 @@ export declare abstract class TableBaseToken extends Token {
21
22
  * @param attr 表格属性
22
23
  */
23
24
  constructor(pattern: RegExp, syntax: string, type: TableTypes, attr?: string, config?: Config, accum?: Token[], acceptable?: WikiParserAcceptable);
24
- cloneNode(): this;
25
25
  escape(): void;
26
+ cloneNode(): this;
26
27
  }
27
28
  export {};
@@ -5,21 +5,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.TableBaseToken = void 0;
7
7
  const attributesParent_1 = require("../../mixin/attributesParent");
8
- const index_1 = require("../index");
8
+ const index_1 = __importDefault(require("../../index"));
9
+ const index_2 = require("../index");
9
10
  const syntax_1 = require("../syntax");
10
11
  const attributes_1 = require("../attributes");
11
12
  /* NOT FOR BROWSER */
12
13
  const debug_1 = require("../../util/debug");
13
14
  const constants_1 = require("../../util/constants");
14
- const index_2 = __importDefault(require("../../index"));
15
15
  /**
16
16
  * 转义表格语法
17
17
  * @param syntax 表格语法节点
18
18
  */
19
19
  const escapeTable = (syntax) => {
20
20
  const wikitext = syntax.childNodes.map(child => child.type === 'text'
21
- ? child.data.replaceAll('|', '{{!}}')
22
- : child.toString()).join(''), { childNodes } = index_2.default
21
+ ? child.data.replace(/\|\|/gu, '{{!!}}')
22
+ .replace(/\|/gu, '{{!}}')
23
+ : child.toString()).join(''), { childNodes } = index_1.default
23
24
  .parse(wikitext, syntax.getAttribute('include'), 2, syntax.getAttribute('config'));
24
25
  syntax.safeReplaceChildren(childNodes);
25
26
  };
@@ -29,7 +30,7 @@ const escapeTable = (syntax) => {
29
30
  * 表格行,含开头的换行,不含结尾的换行
30
31
  * @classdesc `{childNodes: [SyntaxToken, AttributesToken, ...Token[]]}`
31
32
  */
32
- class TableBaseToken extends (0, attributesParent_1.attributesParent)(1)(index_1.Token) {
33
+ class TableBaseToken extends (0, attributesParent_1.attributesParent)(1)(index_2.Token) {
33
34
  /* NOT FOR BROWSER END */
34
35
  /**
35
36
  * @param pattern 表格语法正则
@@ -45,6 +46,18 @@ class TableBaseToken extends (0, attributesParent_1.attributesParent)(1)(index_1
45
46
  /* NOT FOR BROWSER */
46
47
  this.protectChildren([0, 1]);
47
48
  }
49
+ escape() {
50
+ LSP: { // eslint-disable-line no-unused-labels
51
+ for (const child of this.childNodes) {
52
+ if (child instanceof syntax_1.SyntaxToken) {
53
+ escapeTable(child);
54
+ }
55
+ else {
56
+ child.escape();
57
+ }
58
+ }
59
+ }
60
+ }
48
61
  /* NOT FOR BROWSER */
49
62
  cloneNode() {
50
63
  const [syntax, attr, ...cloned] = this.cloneChildNodes();
@@ -61,16 +74,6 @@ class TableBaseToken extends (0, attributesParent_1.attributesParent)(1)(index_1
61
74
  return token;
62
75
  });
63
76
  }
64
- escape() {
65
- for (const child of this.childNodes) {
66
- if (child instanceof syntax_1.SyntaxToken) {
67
- escapeTable(child);
68
- }
69
- else {
70
- child.escape();
71
- }
72
- }
73
- }
74
77
  /** @private */
75
78
  setSyntax(syntax, esc) {
76
79
  const { firstChild } = this;