wikiparser-node 1.42.0 → 1.44.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 (60) hide show
  1. package/README.md +45 -19
  2. package/bundle/bundle-es8.min.js +40 -31
  3. package/bundle/bundle-lsp.min.js +35 -26
  4. package/bundle/bundle.min.js +22 -22
  5. package/config/default.json +31 -0
  6. package/config/moegirl.json +39 -1
  7. package/dist/addon/attribute.js +4 -6
  8. package/dist/addon/link.js +3 -2
  9. package/dist/addon/transclude.js +16 -26
  10. package/dist/base.d.mts +4 -4
  11. package/dist/base.d.ts +4 -4
  12. package/dist/base.js +1 -0
  13. package/dist/base.mjs +1 -0
  14. package/dist/bin/config.js +6 -5
  15. package/dist/extensions/typings.d.ts +1 -1
  16. package/dist/index.js +8 -5
  17. package/dist/lib/document.d.ts +17 -14
  18. package/dist/lib/document.js +5 -5
  19. package/dist/lib/lintConfig.js +4 -1
  20. package/dist/lib/ranges.js +2 -2
  21. package/dist/lib/title.d.ts +4 -1
  22. package/dist/lib/title.js +5 -1
  23. package/dist/mixin/attributesParent.js +1 -1
  24. package/dist/parser/converter.js +1 -1
  25. package/dist/render/expand.js +4 -2
  26. package/dist/render/extension.js +30 -24
  27. package/dist/render/magicWords.js +25 -132
  28. package/dist/render/math.js +31 -0
  29. package/dist/render/syntaxhighlight.js +3 -0
  30. package/dist/src/arg.js +1 -2
  31. package/dist/src/atom.js +1 -1
  32. package/dist/src/attributes.d.ts +1 -0
  33. package/dist/src/attributes.js +27 -3
  34. package/dist/src/converterFlags.js +10 -5
  35. package/dist/src/converterRule.js +5 -7
  36. package/dist/src/heading.js +1 -2
  37. package/dist/src/imageParameter.d.ts +4 -3
  38. package/dist/src/imageParameter.js +16 -9
  39. package/dist/src/index.js +1 -1
  40. package/dist/src/link/base.js +1 -1
  41. package/dist/src/link/file.d.ts +5 -4
  42. package/dist/src/link/file.js +14 -12
  43. package/dist/src/magicLink.js +1 -2
  44. package/dist/src/nowiki/index.d.ts +1 -0
  45. package/dist/src/nowiki/index.js +40 -28
  46. package/dist/src/onlyinclude.js +1 -2
  47. package/dist/src/parameter.js +1 -2
  48. package/dist/src/table/index.js +1 -2
  49. package/dist/src/table/td.js +4 -6
  50. package/dist/src/tagPair/ext.d.ts +1 -0
  51. package/dist/src/tagPair/ext.js +36 -3
  52. package/dist/src/transclude.js +5 -3
  53. package/dist/util/search.js +24 -6
  54. package/dist/util/string.js +7 -1
  55. package/extensions/dist/base.js +1 -1
  56. package/extensions/dist/codejar.js +1 -1
  57. package/i18n/en.json +7 -0
  58. package/i18n/zh-hans.json +7 -0
  59. package/i18n/zh-hant.json +7 -0
  60. package/package.json +64 -21
@@ -108,7 +108,7 @@ let LinkBaseToken = (() => {
108
108
  const { prefix, main, fragment } = this.#title, link = `${interwiki}:${prefix}${main}${fragment === undefined ? '' : `#${fragment}`}`;
109
109
  /* c8 ignore next 3 */
110
110
  if (interwiki && !this.isInterwiki(link)) {
111
- throw new RangeError(`${interwiki} is not a valid interwiki prefix!`);
111
+ throw new RangeError(`${JSON.stringify(interwiki)} is not a valid interwiki prefix!`);
112
112
  }
113
113
  this.setTarget(link);
114
114
  }
@@ -1,6 +1,7 @@
1
1
  import { LinkBaseToken } from './base';
2
2
  import { ImageParameterToken } from '../imageParameter';
3
- import type { TokenTypes, Config, LintError, AST } from '../../base';
3
+ import type { Config, LintError, AST } from '../../base';
4
+ import type { GalleryImageTypes } from '../imageParameter';
4
5
  import type { Token, AtomToken } from '../../internal';
5
6
  import { Title } from '../../lib/title';
6
7
  /**
@@ -15,7 +16,7 @@ export declare abstract class FileToken extends LinkBaseToken {
15
16
  abstract get lastChild(): AtomToken | ImageParameterToken;
16
17
  abstract get children(): [AtomToken, ...ImageParameterToken[]];
17
18
  abstract get lastElementChild(): AtomToken | ImageParameterToken;
18
- get type(): 'file' | 'gallery-image' | 'imagemap-image';
19
+ get type(): 'file' | GalleryImageTypes;
19
20
  /**
20
21
  * file extension
21
22
  *
@@ -45,9 +46,9 @@ export declare abstract class FileToken extends LinkBaseToken {
45
46
  * @param link 文件名
46
47
  * @param text 图片参数
47
48
  * @param delimiter `|`
48
- * @param type 节点类型
49
+ * @param type 图库节点类型
49
50
  */
50
- constructor(link: string, text?: string, config?: Config, accum?: Token[], delimiter?: string, type?: TokenTypes);
51
+ constructor(link: string, text?: string, config?: Config, accum?: Token[], delimiter?: string, type?: GalleryImageTypes);
51
52
  /**
52
53
  * Get all image parameter tokens
53
54
  *
@@ -49,6 +49,7 @@ const string_1 = require("../../util/string");
49
49
  const debug_1 = require("../../util/debug");
50
50
  const title_1 = require("../../lib/title");
51
51
  const cached_1 = require("../../mixin/cached");
52
+ const extension_1 = require("../../render/extension");
52
53
  const frame = new Map([
53
54
  ['manualthumb', 'Thumb'],
54
55
  ['frameless', 'Frameless'],
@@ -173,7 +174,7 @@ let FileToken = (() => {
173
174
  * @param link 文件名
174
175
  * @param text 图片参数
175
176
  * @param delimiter `|`
176
- * @param type 节点类型
177
+ * @param type 图库节点类型
177
178
  */
178
179
  constructor(link, text, config, accum = [], delimiter = '|', type) {
179
180
  super(link, undefined, config, accum, delimiter);
@@ -360,7 +361,7 @@ let FileToken = (() => {
360
361
  #getTypedArgs(keys, type) {
361
362
  const args = this.getAllArgs().filter(({ name }) => keys.has(name));
362
363
  if (args.length > 1) {
363
- index_1.default.warn(`The image ${this.name} has ${args.length} ${type} parameters. Only the last ${args[0].name} will take effect!`);
364
+ index_1.default.warn(`The image ${JSON.stringify(this.name)} has ${args.length} ${type} parameters. Only the last ${args[0].name} will take effect!`);
364
365
  }
365
366
  return args;
366
367
  }
@@ -485,8 +486,7 @@ let FileToken = (() => {
485
486
  // @ts-expect-error abstract class
486
487
  new imageParameter_1.ImageParameterToken(syntax.replace('$1', key === 'width' ? '1' : ''), this.extension, this.type, config));
487
488
  if (free) {
488
- const { childNodes } = index_1.default.parseWithRef(value, this);
489
- parameter.safeReplaceChildren(childNodes);
489
+ parameter.safeReplaceChildren(index_1.default.parseWithRef(value, this).childNodes);
490
490
  }
491
491
  this.insertAt(parameter);
492
492
  }
@@ -501,13 +501,13 @@ let FileToken = (() => {
501
501
  /* c8 ignore stop */
502
502
  /** @private */
503
503
  toHtmlInternal(opt) {
504
- const { link, width, height, type } = this, file = this.getAttribute('title'), fr = this.getFrame(), manual = fr instanceof title_1.Title, framed = fr === 'framed', visibleCaption = manual || framed || fr === 'thumbnail' || type === 'gallery-image', caption = this.getArg('caption')?.toHtmlInternal({
504
+ const { link, width, height, type, parentNode } = this, file = this.getAttribute('title'), fr = this.getFrame(), manual = fr instanceof title_1.Title, isThumb = manual || fr === 'thumbnail', framed = fr === 'framed', visibleCaption = isThumb || framed || type === 'gallery-image', caption = this.getArg('caption')?.toHtmlInternal({
505
505
  ...opt,
506
506
  nowrap: true,
507
507
  }) ?? '', 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({
508
508
  ...opt,
509
509
  nowrap: true,
510
- })) ?? titleFromCaption, horiz = this.getHorizAlign() ?? '', vert = this.getVertAlign() ?? '', hasWidth = isInteger(width), hasHeight = isInteger(height), className = `${manual || framed || hasWidth || hasHeight ? '' : 'mw-default-size '}${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}"`;
510
+ })) ?? titleFromCaption, horiz = this.getHorizAlign() ?? '', vert = this.getVertAlign() ?? '', gallery = type === 'gallery-image' && parentNode?.parentNode, mode = gallery && gallery.getAttr('mode')?.toLowerCase(), nolines = mode === 'nolines', slideshow = mode === 'slideshow', packed = extension_1.packedModes.has(mode), hasWidth = isInteger(width) && !packed, hasHeight = !nolines && !slideshow && isInteger(height), className = `${manual || framed || hasWidth || hasHeight ? '' : 'mw-default-size '}${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}"`;
511
511
  let src;
512
512
  try {
513
513
  src = manual ? fr.getFileUrl() : file.getFileUrl(hasWidth && Number(width), hasHeight && Number(height));
@@ -515,7 +515,7 @@ let FileToken = (() => {
515
515
  catch {
516
516
  return '';
517
517
  }
518
- const img = `<img${alt && ` alt="${alt}"`} src="${src}" decoding="async" class="mw-file-element"${hasWidth ? ` width="${width}"` : ''}${hasHeight ? ` height="${height}"` : ''}>`;
518
+ const img = `<img${alt || this.hasArg('alt') ? ` alt="${alt}"` : ''}${isThumb && hasLink ? ` resource="${file.getUrl()}"` : ''} src="${src}" decoding="async"${hasWidth ? ` width="${width}"` : ''}${hasHeight ? ` height="${height}"` : ''} class="mw-file-element"${nolines || slideshow ? ` style="max-height: ${height}px"` : ''}>`;
519
519
  let href = '';
520
520
  if (link) {
521
521
  try {
@@ -535,15 +535,17 @@ let FileToken = (() => {
535
535
  const a = link
536
536
  ? `<a${href && ` href="${href}"`}${hasLink ? '' : ' class="mw-file-description"'}${titleAttr}${typeof link === 'string' ? ' rel="nofollow"' : ''}>${img}</a>`
537
537
  : `<span${titleAttr}>${img}</span>`;
538
- if (type !== 'gallery-image') {
538
+ if (gallery === false) {
539
539
  return horiz || visibleCaption
540
540
  ? `<figure${classAttr} typeof="mw:File${fr ? `/${manual ? 'Thumb' : frame.get(fr)}` : ''}">${a}<figcaption>${caption}</figcaption></figure>`
541
541
  : `<span${classAttr}>${a}</span>`;
542
542
  }
543
- const parent = this.parentNode, nolines = parent?.parentNode?.getAttr('mode')?.toLowerCase() === 'nolines', padding = nolines ? 0 : 30;
544
- return `\t<li class="gallerybox" style="width: ${Number(width) + padding + 5}px">\n\t\t<div class="thumb" style="width: ${Number(width) + padding}px${nolines ? '' : `; height: ${Number(height) + padding}px`}"><span>${a}</span></div>\n\t\t<div class="gallerytext">${parent?.parentNode?.hasAttr('showfilename')
545
- ? `<a href="${file.getUrl()}" class="galleryfilename galleryfilename-truncate" title="${file.title}">${file.main}</a>\n`
546
- : ''}${caption}</div>\n\t</li>`;
543
+ const padding = nolines ? 0 : 30, overlay = packed && mode !== 'packed';
544
+ return `\t\t<li class="gallerybox"${packed ? '' : ` style="width: ${Number(width) + padding + 5}px"`}>\n\t\t\t<div class="thumb"${packed
545
+ ? ''
546
+ : ` style="width: ${Number(width) + padding}px;${nolines || slideshow ? '' : ` height: ${Number(height) + padding}px;`}"`}><span>${a}</span></div>\n\t\t\t${overlay ? '<div class="gallerytextwrapper">' : ''}<div class="gallerytext">${gallery?.hasAttr('showfilename')
547
+ ? `<a href="${file.getUrl()}" class="galleryfilename galleryfilename-truncate" title="${(0, string_1.sanitizeId)(file.title)}">${file.main}</a>\n`
548
+ : ''}${caption}</div>${overlay ? '\n\t\t\t</div>' : ''}\n\t\t</li>`;
547
549
  }
548
550
  };
549
551
  })();
@@ -281,8 +281,7 @@ let MagicLinkToken = (() => {
281
281
  * @param url URL containing the protocol / 含协议的网址
282
282
  */
283
283
  setTarget(url) {
284
- const { childNodes } = index_1.default.parseWithRef(url, this, 2);
285
- this.safeReplaceChildren(childNodes);
284
+ this.safeReplaceChildren(index_1.default.parseWithRef(url, this, 2).childNodes);
286
285
  }
287
286
  /**
288
287
  * Check if it is a parameter of a template or magic word
@@ -1,6 +1,7 @@
1
1
  import { NowikiBaseToken } from './base';
2
2
  import type { LintError } from '../../base';
3
3
  import type { AttributesToken, ExtToken, AstNodes } from '../../internal';
4
+ import type { TexvcReport } from '../../lib/document';
4
5
  /**
5
6
  * text-only token inside an extension tag
6
7
  *
@@ -46,9 +46,7 @@ class NowikiToken extends base_1.NowikiBaseToken {
46
46
  /** @private */
47
47
  lint(start = this.getAbsoluteIndex()) {
48
48
  LINT: {
49
- const { name, innerText,
50
- /* NOT FOR BROWSER ONLY */
51
- previousSibling, } = this, { lintConfig } = index_1.default;
49
+ const { name, innerText } = this, { lintConfig } = index_1.default;
52
50
  let rule = 'void-ext', s = lintConfig.getSeverity(rule, name);
53
51
  if (s && this.#lint()) {
54
52
  const e = (0, lint_1.generateForSelf)(this, { start }, rule, index_1.default.msg('nothing-in', name), s);
@@ -84,31 +82,9 @@ class NowikiToken extends base_1.NowikiBaseToken {
84
82
  rule = 'invalid-math';
85
83
  s = lintConfig.getSeverity(rule);
86
84
  if (s && constants_2.mathTags.has(name)) {
87
- const texvcjs = (0, document_1.loadTexvcjs)();
88
- if (texvcjs) {
89
- const isChem = name !== 'math', display = previousSibling?.getAttr('display') ?? 'block';
90
- let tex = innerText, n = 0;
91
- if (isChem) {
92
- tex = String.raw `\ce{${tex}}`;
93
- n = 4;
94
- }
95
- switch (display) {
96
- case 'block':
97
- tex = String.raw `{\displaystyle ${tex}}`;
98
- n += 15;
99
- break;
100
- case 'inline':
101
- tex = String.raw `{\textstyle ${tex}}`;
102
- n += 12;
103
- break;
104
- case 'linebreak':
105
- tex = String.raw `\[ ${tex} \]`;
106
- n += 3;
107
- // no default
108
- }
109
- const result = texvcjs.check(tex, {
110
- usemhchem: isChem || Boolean(previousSibling?.hasAttr('chem')),
111
- });
85
+ const report = this.texvcCheck();
86
+ if (report) {
87
+ const [result, n] = report;
112
88
  if (result.status === '+') {
113
89
  return [];
114
90
  }
@@ -133,6 +109,42 @@ class NowikiToken extends base_1.NowikiBaseToken {
133
109
  return key === 'invalid' ? this.#lint() : super.getAttribute(key);
134
110
  }
135
111
  /* PRINT ONLY END */
112
+ /* NOT FOR BROWSER ONLY */
113
+ /** @private */
114
+ texvcCheck() {
115
+ const texvcjs = (0, document_1.loadTexvcjs)();
116
+ if (!texvcjs) {
117
+ return undefined;
118
+ }
119
+ let tex = this.innerText, n = 0;
120
+ if (this.name !== 'math') {
121
+ tex = String.raw `\ce{${tex}}`;
122
+ n = 4;
123
+ }
124
+ switch (this.previousSibling?.getAttr('display') ?? 'block') {
125
+ case 'block':
126
+ tex = String.raw `{\displaystyle ${tex}}`;
127
+ n += 15;
128
+ break;
129
+ case 'inline':
130
+ tex = String.raw `{\textstyle ${tex}}`;
131
+ n += 12;
132
+ break;
133
+ case 'linebreak':
134
+ tex = String.raw `\[ ${tex} \]`;
135
+ n += 3;
136
+ // no default
137
+ }
138
+ return [
139
+ texvcjs.check(tex, {
140
+ usemathrm: true,
141
+ usemhchem: this.name !== 'math' || Boolean(this.previousSibling?.hasAttr('chem')),
142
+ }),
143
+ n,
144
+ tex,
145
+ ];
146
+ }
147
+ /* NOT FOR BROWSER ONLY END */
136
148
  /* NOT FOR BROWSER */
137
149
  /** @private */
138
150
  safeReplaceChildren(elements) {
@@ -85,8 +85,7 @@ let OnlyincludeToken = (() => {
85
85
  if (text.includes('</onlyinclude>')) {
86
86
  throw new RangeError('"</onlyinclude>" is not allowed in the text!');
87
87
  }
88
- const { childNodes } = index_2.default.parseWithRef(text, this, undefined, true);
89
- this.safeReplaceChildren(childNodes);
88
+ this.safeReplaceChildren(index_2.default.parseWithRef(text, this, undefined, true).childNodes);
90
89
  }
91
90
  /* NOT FOR BROWSER END */
92
91
  /** @private */
@@ -249,9 +249,8 @@ let ParameterToken = (() => {
249
249
  * @param value parameter value / 参数值
250
250
  */
251
251
  setValue(value) {
252
- const { childNodes } = index_1.default.parseWithRef(value, this);
253
252
  this.lastChild
254
- .safeReplaceChildren(childNodes);
253
+ .safeReplaceChildren(index_1.default.parseWithRef(value, this).childNodes);
255
254
  }
256
255
  /**
257
256
  * Rename the parameter
@@ -168,8 +168,7 @@ let TableToken = (() => {
168
168
  }
169
169
  /* NOT FOR BROWSER */
170
170
  if (!halfParsed) {
171
- const { childNodes } = index_1.default.parseWithRef(syntax, this, 2);
172
- this.lastChild.safeReplaceChildren(childNodes);
171
+ this.lastChild.safeReplaceChildren(index_1.default.parseWithRef(syntax, this, 2).childNodes);
173
172
  }
174
173
  }
175
174
  /**
@@ -158,8 +158,7 @@ let TdToken = (() => {
158
158
  return this.lastChild.text().trim();
159
159
  }
160
160
  set innerText(text) {
161
- const { childNodes } = index_1.default.parseWithRef(text, this, undefined, true);
162
- this.lastChild.safeReplaceChildren(childNodes);
161
+ this.lastChild.safeReplaceChildren(index_1.default.parseWithRef(text, this, undefined, true).childNodes);
163
162
  }
164
163
  /* NOT FOR BROWSER END */
165
164
  /**
@@ -369,7 +368,7 @@ let TdToken = (() => {
369
368
  if (notEOL) {
370
369
  html = html.replace(/(?<=[\S\n])[^\S\n]*$/u, '');
371
370
  }
372
- return `${lf}<${subtype}${attr.toHtmlInternal()}>${subtype === 'caption' ? (0, string_1.newline)(html) : html + (notEOL ? '' : lf)}</${subtype}>`;
371
+ return `${lf}<${subtype}${attr.toHtmlInternal()}>${subtype === 'caption' ? (0, string_1.newline)(html) : html}${notEOL ? '' : lf}</${subtype}>`;
373
372
  }
374
373
  };
375
374
  return TdToken = _classThis;
@@ -384,11 +383,10 @@ exports.TdToken = TdToken;
384
383
  * @param attr 单元格属性
385
384
  */
386
385
  const createTd = (inner, ref, subtype = 'td', attr = {}) => {
387
- const innerToken = typeof inner === 'string' ? index_1.default.parseWithRef(inner, ref) : inner,
388
386
  // @ts-expect-error abstract class
389
- token = debug_1.Shadow.run(() => new TdToken('\n|', undefined, ref.getAttribute('config')));
387
+ const token = debug_1.Shadow.run(() => new TdToken('\n|', undefined, ref.getAttribute('config')));
390
388
  token.setSyntax(subtype);
391
- token.lastChild.safeReplaceWith(innerToken);
389
+ token.lastChild.safeReplaceWith(typeof inner === 'string' ? index_1.default.parseWithRef(inner, ref) : inner);
392
390
  token.setAttr(attr);
393
391
  return token;
394
392
  };
@@ -1,3 +1,4 @@
1
+ import { BoundingRect } from '../../lib/rect';
1
2
  import Parser from '../../index';
2
3
  import { Token } from '../index';
3
4
  import { TagPairToken } from './index';
@@ -49,6 +49,7 @@ const attributes_1 = require("../attributes");
49
49
  const debug_1 = require("../../util/debug");
50
50
  const constants_1 = require("../../util/constants");
51
51
  const cached_1 = require("../../mixin/cached");
52
+ const nonVoidExt = new Set(['dynamicpagelist', 'templatedata', 'rss']);
52
53
  /**
53
54
  * extension tag
54
55
  *
@@ -214,16 +215,35 @@ let ExtToken = (() => {
214
215
  this.seal('closed', true);
215
216
  }
216
217
  /** @private */
218
+ lintRef(rect, severity) {
219
+ LINT: {
220
+ const refName = this.getAttr('name'), text = this.innerText?.trim();
221
+ let msg = '';
222
+ if (this.closest('ext#references')) {
223
+ if (!refName) {
224
+ msg = 'no-named-in-references';
225
+ }
226
+ else if (!text) {
227
+ msg = 'no-empty-in-references';
228
+ }
229
+ }
230
+ else if (!refName && !text) {
231
+ msg = this.hasAttr('details') ? 'ref-details' : 'ref-no-name';
232
+ }
233
+ return msg && (rect ? (0, lint_1.generateForSelf)(this, rect, 'invalid-ref', msg, severity) : msg);
234
+ }
235
+ }
236
+ /** @private */
217
237
  lint(start = this.getAbsoluteIndex(), re) {
218
238
  LINT: {
219
- const errors = super.lint(start, re), { lintConfig } = index_1.default, rect = new rect_1.BoundingRect(this, start);
220
- if (this.name !== 'nowiki') {
239
+ const errors = super.lint(start, re), { name } = this, { lintConfig } = index_1.default, rect = new rect_1.BoundingRect(this, start);
240
+ if (name !== 'nowiki') {
221
241
  const s = this.inHtmlAttrs(), rule = 'parsing-order', severity = s && lintConfig.getSeverity(rule, s === 2 ? 'ext' : 'templateInTable');
222
242
  if (severity) {
223
243
  errors.push((0, lint_1.generateForSelf)(this, rect, rule, 'ext-in-html', severity));
224
244
  }
225
245
  }
226
- if (this.name === 'ref') {
246
+ if (name === 'ref') {
227
247
  let rule = 'var-anchor', s = lintConfig.getSeverity(rule, 'ref');
228
248
  if (s && this.closest('heading-title')) {
229
249
  errors.push((0, lint_1.generateForSelf)(this, rect, rule, 'variable-anchor', s));
@@ -233,6 +253,19 @@ let ExtToken = (() => {
233
253
  if (s && this.closest('link-text,ext-link-text')) {
234
254
  errors.push((0, lint_1.generateForSelf)(this, rect, rule, 'ref-in-link', s));
235
255
  }
256
+ s = lintConfig.getSeverity('invalid-ref');
257
+ if (s) {
258
+ const e = this.lintRef(rect, s);
259
+ if (e) {
260
+ errors.push(e);
261
+ }
262
+ }
263
+ }
264
+ else {
265
+ const rule = 'void-ext', s = lintConfig.getSeverity(rule, name);
266
+ if (s && nonVoidExt.has(name) && !this.innerText) {
267
+ errors.push((0, lint_1.generateForSelf)(this, { start }, rule, index_1.default.msg('no-empty', name), s));
268
+ }
236
269
  }
237
270
  return errors;
238
271
  }
@@ -525,7 +525,7 @@ let TranscludeToken = (() => {
525
525
  * @throws `Error` 不是可接受的魔术字
526
526
  */
527
527
  getPossibleValues() {
528
- const { type, name, childNodes } = this;
528
+ const { type, name, childNodes, length: l } = this;
529
529
  if (type === 'template') {
530
530
  throw new Error('TranscludeToken.getPossibleValues method is only for specific magic words!');
531
531
  }
@@ -534,12 +534,14 @@ let TranscludeToken = (() => {
534
534
  case 'if':
535
535
  case 'ifexist':
536
536
  case 'ifexpr':
537
- case 'iferror':
538
537
  start = 2;
539
538
  break;
540
539
  case 'ifeq':
541
540
  start = 3;
542
541
  break;
542
+ case 'iferror':
543
+ start = l > 3 ? 2 : 1;
544
+ break;
543
545
  case 'switch': {
544
546
  const parameters = childNodes.slice(2), last = parameters[parameters.length - 1];
545
547
  queue = [
@@ -869,7 +871,7 @@ let TranscludeToken = (() => {
869
871
  if (type === 'template' && !name.startsWith('Special:')) {
870
872
  if (this.normalizeTitle(name, 0, { halfParsed: true, temporary: true }).valid) {
871
873
  const title = name.replaceAll('_', ' ');
872
- return `<a href="${this.#title.getUrl()}?action=edit&redlink=1" class="new" title="${title} (page does not exist)">${title}</a>`;
874
+ return `<a href="${this.#title.getUrl()}?action=edit&redlink=1" class="new" title="${(0, string_1.sanitizeId)(title)} (page does not exist)">${title}</a>`;
873
875
  }
874
876
  const str = this.text();
875
877
  return opt?.nowrap ? str.replaceAll('\n', ' ') : str;
@@ -1,16 +1,34 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const binary_search_1 = __importDefault(require("binary-search"));
7
3
  /**
8
4
  * 二分法查找索引
9
5
  * @param haystack 数组
10
6
  * @param needle 目标值
11
7
  * @param comparator 比较函数
8
+ * @author The Dark Sky Company, LLC <support@darkskyapp.com>
9
+ * @license CC0-1.0
10
+ * @see https://github.com/darkskyapp/binary-search/blob/master/index.js
12
11
  */
13
12
  exports.default = (haystack, needle, comparator) => {
14
- const found = (0, binary_search_1.default)(haystack, needle, comparator);
15
- return found < 0 ? ~found : found; // eslint-disable-line no-bitwise
13
+ let low = 0, high = haystack.length - 1;
14
+ while (low <= high) {
15
+ // The naive `low + high >>> 1` could fail for array lengths > 2**31
16
+ // because `>>>` converts its operands to int32. `low + (high - low >>> 1)`
17
+ // works for array lengths <= 2**32-1 which is also Javascript's max array
18
+ // length.
19
+ const mid = low + (high - low >>> 1), // eslint-disable-line no-bitwise
20
+ cmp = comparator(haystack[mid], needle);
21
+ if (cmp < 0) {
22
+ low = mid + 1;
23
+ }
24
+ else if (cmp > 0) {
25
+ high = mid - 1;
26
+ }
27
+ else {
28
+ // Key found.
29
+ return mid;
30
+ }
31
+ }
32
+ // Key not found.
33
+ return low;
16
34
  };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isInterwiki = exports.removeCommentLine = exports.newline = exports.sanitizeAlt = exports.sanitizeId = exports.sanitizeAttr = exports.sanitize = exports.normalizeSpace = exports.encode = exports.noWrap = exports.escapeRegExp = exports.print = exports.escape = exports.replaceEntities = exports.decodeNumber = exports.decodeHtml = exports.decodeHtmlBasic = exports.text = exports.removeComment = exports.tidy = exports.trimLc = exports.extUrlChar = exports.extUrlCharFirst = exports.zs = void 0;
3
+ exports.isInterwiki = exports.removeCommentLine = exports.newline = exports.sanitizeAlt = exports.sanitizeId = exports.sanitizeAttr = exports.sanitize = exports.normalizeSpace = exports.encode = exports.noWrap = exports.escapeRegExp = exports.print = exports.escape = exports.replaceEntities = exports.toLowerCase = exports.decodeNumber = exports.decodeHtml = exports.decodeHtmlBasic = exports.text = exports.removeComment = exports.tidy = exports.trimLc = exports.extUrlChar = exports.extUrlCharFirst = exports.zs = void 0;
4
4
  exports.restore = restore;
5
5
  /* NOT FOR BROWSER */
6
6
  const common_1 = require("@bhsd/common");
@@ -71,6 +71,12 @@ const decodeHtml = (str) => {
71
71
  exports.decodeHtml = decodeHtml;
72
72
  /** decode numbered HTML entities */
73
73
  exports.decodeNumber = factory(/&#(\d+|x[\da-f]+);/giu, (_, code) => String.fromCodePoint(Number((/^x/iu.test(code) ? '0' : '') + code)));
74
+ /**
75
+ * Convert an array of strings to lowercase
76
+ * @param str array of strings
77
+ */
78
+ const toLowerCase = (str) => str.map(s => s.toLowerCase());
79
+ exports.toLowerCase = toLowerCase;
74
80
  /* PRINT ONLY */
75
81
  const entities = {
76
82
  '&': 'amp',
@@ -1,6 +1,6 @@
1
1
  (() => {
2
2
  var _a;
3
- const version = '1.42.0', src = (_a = document.currentScript) === null || _a === void 0 ? void 0 : _a.src, file = /\/extensions\/dist\/base\.(?:min\.)?js$/u, CDN = src && file.test(src)
3
+ const version = '1.44.0', src = (_a = document.currentScript) === null || _a === void 0 ? void 0 : _a.src, file = /\/extensions\/dist\/base\.(?:min\.)?js$/u, CDN = src && file.test(src)
4
4
  ? src.replace(file, '')
5
5
  : `https://fastly.jsdelivr.net/npm/wikiparser-node@${version}`;
6
6
  const workerJS = () => {
@@ -1,6 +1,6 @@
1
1
  (() => {
2
2
  const codejar = (async () => {
3
- const { CodeJar } = 'CodeJar' in globalThis
3
+ const { CodeJar } = Object.hasOwn(globalThis, 'CodeJar')
4
4
  ? globalThis
5
5
  : await import('https://fastly.jsdelivr.net/npm/codejar-async');
6
6
  return (textbox, include, linenums) => {
package/i18n/en.json CHANGED
@@ -34,6 +34,7 @@
34
34
  "in-url": "$1 in URL",
35
35
  "inconsistent-table": "inconsistent table layout",
36
36
  "insecure-style": "insecure style",
37
+ "int-name": "name cannot be a simple integer",
37
38
  "invalid-attribute": "element containing an invalid attribute name",
38
39
  "invalid-category": "invalid category name",
39
40
  "invalid-content": "invalid content in <$1>",
@@ -55,6 +56,9 @@
55
56
  "missing-extension": "missing file extension",
56
57
  "missing-function": "missing Scribunto module function name",
57
58
  "newline": null,
59
+ "no-empty": "<$1> should not be empty",
60
+ "no-empty-in-references": "<ref> tag defined in <references> has no content",
61
+ "no-named-in-references": "<ref> tag defined in <references> has no name attribute",
58
62
  "no-self-closing": "no self-closing",
59
63
  "nonzero-tabindex": "nonzero tabindex",
60
64
  "nothing-in": "nothing should be in <$1>",
@@ -65,7 +69,10 @@
65
69
  "pipe-in-link": "additional \"|\" in the link text",
66
70
  "pipe-in-table": "additional \"|\" in a table cell",
67
71
  "redirect-like": "redirect-like syntax in a list item",
72
+ "ref-details": "a <ref> tag with details must contain content or point to a parent reference by name",
73
+ "ref-follow": "a <ref follow> tag that is the continuation of a previous one cannot be named individually or have details",
68
74
  "ref-in-link": "<ref> in an internal or external link",
75
+ "ref-no-name": "<ref> with no name must have content",
69
76
  "remove": null,
70
77
  "required-attribute": "required $1 attribute is missing",
71
78
  "template-in-link": "template in an internal link target",
package/i18n/zh-hans.json CHANGED
@@ -33,6 +33,7 @@
33
33
  "imagemap-without-image": "没有图像的<imagemap>",
34
34
  "in-url": "URL中的$1",
35
35
  "inconsistent-table": "不一致的表格布局",
36
+ "int-name": "name不能是单纯整数",
36
37
  "insecure-style": "不安全的样式",
37
38
  "invalid-attribute": "包含无效属性名称的元素",
38
39
  "invalid-category": "无效的分类名",
@@ -55,6 +56,9 @@
55
56
  "missing-extension": "缺少文件扩展名",
56
57
  "missing-function": "缺少Scribunto模块函数名",
57
58
  "newline": "换行",
59
+ "no-empty": "<$1>不应为空",
60
+ "no-empty-in-references": "<references>内定义的<ref>标签没有内容",
61
+ "no-named-in-references": "<references>内定义的<ref>标签没有设置name属性",
58
62
  "no-self-closing": "移除自封闭",
59
63
  "nonzero-tabindex": "非零的tabindex",
60
64
  "nothing-in": "<$1>不应有任何内容",
@@ -65,7 +69,10 @@
65
69
  "pipe-in-link": "链接文本中的额外\"|\"",
66
70
  "pipe-in-table": "表格单元格中的额外\"|\"",
67
71
  "redirect-like": "列表项中的疑似重定向语法",
72
+ "ref-details": "带有详细信息的<ref>标签必须包含内容或通过名称指向父级参考",
73
+ "ref-follow": "作为前一个标签的延续的<ref follow>标签不能被单独命名或包含详细信息",
68
74
  "ref-in-link": "内部或外部链接中的<ref>",
75
+ "ref-no-name": "没有name的<ref>必须有内容",
69
76
  "remove": "移除",
70
77
  "required-attribute": "缺少必需的$1属性",
71
78
  "template-in-link": "内部链接目标中的模板",
package/i18n/zh-hant.json CHANGED
@@ -33,6 +33,7 @@
33
33
  "imagemap-without-image": "<imagemap>沒有圖片",
34
34
  "in-url": "URL中有$1",
35
35
  "inconsistent-table": "表格版面不一致",
36
+ "int-name": "name屬性不能使用數字",
36
37
  "insecure-style": "不安全的樣式",
37
38
  "invalid-attribute": "包含無效屬性名稱的元素",
38
39
  "invalid-category": "無效的分類名",
@@ -55,6 +56,9 @@
55
56
  "missing-extension": "缺少副檔名",
56
57
  "missing-function": "缺少Scribunto模組函式名稱",
57
58
  "newline": "換行",
59
+ "no-empty": "<$1>不應為空",
60
+ "no-empty-in-references": "<references>內定義的<ref>標籤沒有內容",
61
+ "no-named-in-references": "<references> 中定義的 <ref> 沒有設定 name 屬性",
58
62
  "no-self-closing": "移除自封閉",
59
63
  "nonzero-tabindex": "非零的tabindex",
60
64
  "nothing-in": "<$1>不應有任何內容",
@@ -65,7 +69,10 @@
65
69
  "pipe-in-link": "連結文字有額外的\"|\"字元",
66
70
  "pipe-in-table": "表格儲存格有額外的\"|\"字元",
67
71
  "redirect-like": "列表項中的疑似重新導向語法",
72
+ "ref-details": "一個帶有詳細資訊的 <ref> 標籤必須包含內容、或透過名稱指向父級參考",
73
+ "ref-follow": "作為前一個延續的 <ref follow> 標籤,不能單獨命名或包含詳細資訊",
68
74
  "ref-in-link": "內部或外部連結裡的<ref>",
75
+ "ref-no-name": "沒有名稱的<ref>必須要有內容",
69
76
  "remove": "移除",
70
77
  "required-attribute": "缺少必需的$1屬性",
71
78
  "template-in-link": "內部連結目標中的模板",