wikiparser-node 1.12.3 → 1.12.4

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.
@@ -702,7 +702,10 @@
702
702
  "CONTENTLANGUAGE",
703
703
  "CONTENTLANG",
704
704
  "PAGELANGUAGE",
705
- "="
705
+ "=",
706
+ "#FORMAL",
707
+ "#timef",
708
+ "#timefl"
706
709
  ],
707
710
  [
708
711
  "msg",
@@ -331,7 +331,10 @@
331
331
  "CONTENTLANGUAGE",
332
332
  "CONTENTLANG",
333
333
  "PAGELANGUAGE",
334
- "="
334
+ "=",
335
+ "#FORMAL",
336
+ "#timef",
337
+ "#timefl"
335
338
  ],
336
339
  [
337
340
  "msg",
@@ -114,7 +114,10 @@
114
114
  },
115
115
  [
116
116
  "!",
117
- "="
117
+ "=",
118
+ "#FORMAL",
119
+ "#timef",
120
+ "#timefl"
118
121
  ],
119
122
  [
120
123
  "msg",
@@ -644,7 +644,10 @@
644
644
  "CONTENTLANGUAGE",
645
645
  "CONTENTLANG",
646
646
  "PAGELANGUAGE",
647
- "="
647
+ "=",
648
+ "#FORMAL",
649
+ "#timef",
650
+ "#timefl"
648
651
  ],
649
652
  [
650
653
  "msg",
@@ -194,7 +194,7 @@ const expand = (wikitext, config, include, context, accum = [], stack = []) => {
194
194
  else if (!context || !context.hasArg(arg)) {
195
195
  const effective = target.childNodes[1] ?? target;
196
196
  // @ts-expect-error sparse array
197
- accum[accum.indexOf(effective)] = undefined;
197
+ accum[accum.indexOf(length === 1 ? f : effective)] = undefined;
198
198
  return prev + effective.toString();
199
199
  }
200
200
  // @ts-expect-error sparse array
@@ -205,8 +205,15 @@ const expand = (wikitext, config, include, context, accum = [], stack = []) => {
205
205
  if (context === false) {
206
206
  return m;
207
207
  }
208
- const c = target.getAttribute('config'), t = index_1.default.normalizeTitle((0, string_1.removeComment)(f.toString()), 10, include, c, true), { title } = t;
209
- if (!index_1.default.templates.has(title)) {
208
+ const c = target.getAttribute('config'), t = index_1.default.normalizeTitle((0, string_1.removeComment)(f.toString()), 10, include, c, true), { title, valid } = t;
209
+ if (!valid) {
210
+ // @ts-expect-error sparse array
211
+ accum[accum.indexOf(target)] = undefined;
212
+ // @ts-expect-error sparse array
213
+ accum[accum.indexOf(f)] = undefined;
214
+ return prev + target.toString();
215
+ }
216
+ else if (!index_1.default.templates.has(title)) {
210
217
  if (index_1.default.templateDir === undefined) {
211
218
  return m;
212
219
  }
@@ -222,7 +229,7 @@ const expand = (wikitext, config, include, context, accum = [], stack = []) => {
222
229
  index_1.default.templates.set(title, fs.readFileSync(file, 'utf8'));
223
230
  }
224
231
  else if (stack.includes(title)) {
225
- return `<span class="error">Template loop detected: [[${title}]]</span>`;
232
+ return `${prev}<span class="error">Template loop detected: [[${title}]]</span>`;
226
233
  }
227
234
  return implicitNewLine(expand(index_1.default.templates.get(title), config, true, target, accum, [...stack, title]).toString(), prev);
228
235
  }
@@ -305,15 +312,9 @@ const expand = (wikitext, config, include, context, accum = [], stack = []) => {
305
312
  return token;
306
313
  };
307
314
  index_2.Token.prototype.expand = /** @implements */ function () {
308
- if (this.type !== 'root') {
309
- throw new Error('Only root token can be expanded!');
310
- }
311
315
  return debug_1.Shadow.run(() => expand(this.toString(), this.getAttribute('config'), this.getAttribute('include')).parse());
312
316
  };
313
317
  index_2.Token.prototype.solveConst = /** @implements */ function () {
314
- if (this.type !== 'root') {
315
- throw new Error('Only root token can be expanded!');
316
- }
317
318
  return debug_1.Shadow.run(() => expand(this.toString(), this.getAttribute('config'), this.getAttribute('include'), false).parse());
318
319
  };
319
320
  index_2.Token.prototype.toHtml = /** @implements */ function () {
@@ -13,15 +13,16 @@ const selector_1 = require("../parser/selector");
13
13
  * 将选择器转化为类型谓词
14
14
  * @param selector 选择器
15
15
  */
16
- const getCondition = (selector) => {
17
- /* NOT FOR BROWSER */
18
- if (/[^a-z\-,\s]/u.test(selector)) {
19
- return (0, selector_1.checkToken)(selector);
20
- }
21
- /* NOT FOR BROWSER END */
22
- const types = new Set(selector.split(',').map(str => str.trim()));
23
- return (({ type }) => types.has(type));
24
- };
16
+ const getCondition = (selector) => (
17
+ /* eslint-disable @stylistic/operator-linebreak */
18
+ /[^a-z\-,#]/u.test(selector) ?
19
+ (0, selector_1.checkToken)(selector) :
20
+ ({ type, name }) => selector.split(',').some(str => {
21
+ const [t, ...ns] = str.trim().split('#');
22
+ return (!t || t === type) && ns.every(n => n === name);
23
+ })
24
+ /* eslint-enable @stylistic/operator-linebreak */
25
+ );
25
26
  /** 类似HTMLElement */
26
27
  class AstElement extends node_1.AstNode {
27
28
  /** 子节点总数 */
@@ -28,8 +28,8 @@ const hiddenToken = (linter = true, html = true) => (constructor, _) => {
28
28
  dispatchEvent() {
29
29
  //
30
30
  }
31
- toHtmlInternal(nowrap) {
32
- return html ? '' : super.toHtmlInternal(nowrap);
31
+ toHtmlInternal() {
32
+ return html ? '' : super.toHtmlInternal();
33
33
  }
34
34
  }
35
35
  (0, debug_1.mixin)(AnyHiddenToken, constructor);
@@ -6,6 +6,7 @@ const magicLink_1 = require("../src/magicLink");
6
6
  /* NOT FOR BROWSER */
7
7
  const constants_1 = require("../util/constants");
8
8
  /* NOT FOR BROWSER END */
9
+ const space = String.raw `[\p{Zs}\t]|&nbsp;|&#0*160;|&#x0*a0;`, sp = `(?:${space})+`, spdash = `(?:${space}|-)`, magicLinkPattern = String.raw `(?:RFC|PMID)${sp}\d+\b|ISBN${sp}(?:97[89]${spdash}?)?(?:\d${spdash}?){9}[\dx]\b`;
9
10
  /**
10
11
  * 解析自由外链
11
12
  * @param wikitext
@@ -15,7 +16,7 @@ const constants_1 = require("../util/constants");
15
16
  const parseMagicLinks = (wikitext, config, accum) => {
16
17
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions
17
18
  /(^|[^\p{L}\d_])(?:(?:ftp:\/\/|http:\/\/)((?:\[[\da-f:.]+\]|[^[\]<>"\t\n\p{Zs}])[^[\]<>"\0\t\n\p{Zs}]*)|(?:rfc|pmid)[\p{Zs}\t]+\d+\b|isbn[\p{Zs}\t]+(?:97[89][\p{Zs}\t-]?)?(?:\d[\p{Zs}\t-]?){9}[\dx]\b)/giu;
18
- const space = String.raw `[\p{Zs}\t]|&nbsp;|&#0*160;|&#x0*a0;`, spdash = `(?:${space}|-)`, regex = new RegExp(String.raw `(^|[^\p{L}\d_])(?:(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})|(?:RFC|PMID)(?:${space})+\d+\b|ISBN(?:${space})+(?:97[89]${spdash}?)?(?:\d${spdash}?){9}[\dx]\b)`, 'giu');
19
+ const regex = new RegExp(String.raw `(^|[^\p{L}\d_])(?:(?:${config.protocol})(${string_1.extUrlCharFirst}${string_1.extUrlChar})|${magicLinkPattern})`, 'giu');
19
20
  return wikitext.replace(regex, (m, lead, p1) => {
20
21
  let url = lead ? m.slice(lead.length) : m;
21
22
  if (p1) {
package/dist/src/arg.d.ts CHANGED
@@ -2,7 +2,7 @@ import Parser from '../index';
2
2
  import { Token } from './index';
3
3
  import { AtomToken } from './atom';
4
4
  import { HiddenToken } from './hidden';
5
- import type { LintError, AST } from '../base';
5
+ import type { LintError } from '../base';
6
6
  /**
7
7
  * `{{{}}}`包裹的参数
8
8
  * @classdesc `{childNodes: [AtomToken, ?Token, ...HiddenToken]}`
@@ -22,8 +22,6 @@ export declare abstract class ArgToken extends Token {
22
22
  set default(value: string | false);
23
23
  /** @param parts 以'|'分隔的各部分 */
24
24
  constructor(parts: readonly string[], config?: Parser.Config, accum?: Token[]);
25
- /** @override */
26
- json(): AST;
27
25
  cloneNode(): this;
28
26
  /** 移除无效部分 */
29
27
  removeRedundant(): void;
package/dist/src/arg.js CHANGED
@@ -114,12 +114,6 @@ class ArgToken extends index_2.Token {
114
114
  print() {
115
115
  return super.print({ pre: '{{{', post: '}}}', sep: '|' });
116
116
  }
117
- /** @override */
118
- json() {
119
- const json = super.json();
120
- json['default'] = this.default;
121
- return json;
122
- }
123
117
  /* NOT FOR BROWSER */
124
118
  cloneNode() {
125
119
  const [name, ...cloned] = this.cloneChildNodes();
@@ -213,12 +207,12 @@ class ArgToken extends index_2.Token {
213
207
  }
214
208
  }
215
209
  /** @private */
216
- toHtmlInternal(nowrap) {
210
+ toHtmlInternal(nowrap, nocc) {
217
211
  if (this.length === 1) {
218
212
  const html = (0, html_1.font)(this, this.toString());
219
213
  return nowrap ? html.replaceAll('\n', ' ') : html;
220
214
  }
221
- return (0, html_1.font)(this, this.childNodes[1].toHtmlInternal(nowrap));
215
+ return (0, html_1.font)(this, this.childNodes[1].toHtmlInternal(nowrap, nocc));
222
216
  }
223
217
  }
224
218
  exports.ArgToken = ArgToken;
@@ -135,13 +135,16 @@ let ConverterToken = (() => {
135
135
  });
136
136
  }
137
137
  /** @private */
138
- toHtmlInternal(nowrap) {
138
+ toHtmlInternal(nowrap, nocc) {
139
139
  const flags = this.getEffectiveFlags(), { childNodes: [, ...rules] } = this;
140
- if (flags.has('S')) {
140
+ if (nocc || flags.has('R') || this.getVariantFlags().size > 0) {
141
+ return (0, html_1.font)(this, (nocc ? '-{' : '') + (0, html_1.html)(rules, ';', nowrap, nocc) + (nocc ? '}-' : ''));
142
+ }
143
+ else if (flags.has('S')) {
141
144
  return (0, html_1.font)(this, rules.find(({ variant }) => variant)?.lastChild.toHtmlInternal(nowrap).trim()
142
145
  ?? rules[0].lastChild.toHtmlInternal(nowrap));
143
146
  }
144
- return flags.has('R') || this.getVariantFlags().size > 0 ? (0, html_1.font)(this, (0, html_1.html)(rules, ';', nowrap)) : '';
147
+ return '';
145
148
  }
146
149
  };
147
150
  return ConverterToken = _classThis;
@@ -207,11 +207,11 @@ class ConverterRuleToken extends index_2.Token {
207
207
  }
208
208
  }
209
209
  /** @private */
210
- toHtmlInternal(nowrap) {
210
+ toHtmlInternal(nowrap, nocc) {
211
211
  const { childNodes, firstChild, lastChild } = this;
212
212
  return childNodes.length === 3
213
- ? `${firstChild.toHtmlInternal(nowrap)}=>${childNodes[1].text()}:${lastChild.toHtmlInternal(nowrap)}`
214
- : (0, html_1.html)(childNodes, ':', nowrap);
213
+ ? `${firstChild.toHtmlInternal(nowrap, nocc)}=>${childNodes[1].text()}:${lastChild.toHtmlInternal(nowrap, nocc)}`
214
+ : (0, html_1.html)(childNodes, ':', nowrap, nocc);
215
215
  }
216
216
  }
217
217
  exports.ConverterRuleToken = ConverterRuleToken;
@@ -191,7 +191,7 @@ let ExtLinkToken = (() => {
191
191
  this.#space ||= ' ';
192
192
  }
193
193
  /** @private */
194
- toHtmlInternal(nowrap) {
194
+ toHtmlInternal(nowrap, nocc) {
195
195
  const { length, lastChild } = this;
196
196
  let trail = '', innerText, autonumber = false, href;
197
197
  if (length > 1) {
@@ -201,9 +201,9 @@ let ExtLinkToken = (() => {
201
201
  if (i !== -1) {
202
202
  const after = childNodes.slice(i);
203
203
  this.after(...after);
204
- trail = (0, html_1.html)(after, '', nowrap);
204
+ trail = (0, html_1.html)(after, '', nowrap, nocc);
205
205
  }
206
- innerText = lastChild.toHtmlInternal();
206
+ innerText = lastChild.toHtmlInternal(false, nocc);
207
207
  }
208
208
  else {
209
209
  ({ innerText } = this);
@@ -24,6 +24,8 @@ export declare abstract class HeadingToken extends Token {
24
24
  get innerText(): string;
25
25
  /** @throws `Error` 首尾包含`=` */
26
26
  set innerText(text: string);
27
+ /** id属性 */
28
+ get id(): string;
27
29
  /**
28
30
  * @param level 标题层级
29
31
  * @param input 标题文字
@@ -95,6 +95,10 @@ let HeadingToken = (() => {
95
95
  const { childNodes } = index_1.default.parse(text, this.getAttribute('include'), undefined, this.getAttribute('config'));
96
96
  this.firstChild.replaceChildren(...childNodes);
97
97
  }
98
+ /** id属性 */
99
+ get id() {
100
+ return this.#getId(true);
101
+ }
98
102
  /* NOT FOR BROWSER END */
99
103
  /**
100
104
  * @param level 标题层级
@@ -138,7 +142,7 @@ let HeadingToken = (() => {
138
142
  if (innerStr.startsWith('=') || innerStr.endsWith('=')) {
139
143
  errors.push((0, lint_1.generateForChild)(firstChild, rect, 'unbalanced-header', index_1.default.msg('unbalanced $1 in a section header', '"="')));
140
144
  }
141
- if (this.closest('html-attrs, table-attrs')) {
145
+ if (this.closest('html-attrs,table-attrs')) {
142
146
  errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'section header in a HTML tag'));
143
147
  }
144
148
  if (boldQuotes.length % 2) {
@@ -182,25 +186,34 @@ let HeadingToken = (() => {
182
186
  removeTrail() {
183
187
  this.lastChild.replaceChildren();
184
188
  }
185
- /** @private */
186
- toHtmlInternal() {
187
- const { level, firstChild } = this, html = firstChild.toHtmlInternal(), headings = constants_1.states.get(this.getRootNode())?.headings;
188
- let id = (0, string_1.decodeHtml)((0, string_1.sanitizeAlt)(html)).replace(/[\s_]+/gu, '_');
189
+ /**
190
+ * id属性
191
+ * @param expand 是否展开模板
192
+ */
193
+ #getId(expand) {
194
+ const token = expand ? this.firstChild.expand() : this.firstChild;
195
+ let id = (0, string_1.decodeHtml)((0, string_1.sanitizeAlt)(token.toHtmlInternal(false, true))).replace(/[\s_]+/gu, '_');
189
196
  if (id.endsWith('_')) {
190
197
  id = id.slice(0, -1);
191
198
  }
192
- const lcId = id.toLowerCase();
199
+ return id;
200
+ }
201
+ /** @private */
202
+ toHtmlInternal() {
203
+ let id = this.#getId();
204
+ const { level, firstChild } = this, lcId = id.toLowerCase(), headings = constants_1.states.get(this.getRootNode())?.headings;
193
205
  if (headings?.has(lcId)) {
194
206
  let i = 2;
195
207
  for (; headings.has(`${lcId}_${i}`); i++) {
196
208
  // pass
197
209
  }
198
210
  id = `${id}_${i}`;
211
+ headings.add(`${lcId}_${i}`);
199
212
  }
200
213
  else {
201
214
  headings?.add(lcId);
202
215
  }
203
- return `<div class="mw-heading mw-heading${level}"><h${level} id="${(0, string_1.sanitizeId)(id)}">${html.trim()}</h${level}></div>`;
216
+ return `<div class="mw-heading mw-heading${level}"><h${level} id="${(0, string_1.sanitizeId)(id)}">${firstChild.toHtmlInternal().trim()}</h${level}></div>`;
204
217
  }
205
218
  };
206
219
  return HeadingToken = _classThis;
package/dist/src/index.js CHANGED
@@ -126,15 +126,15 @@ class Token extends element_1.AstElement {
126
126
  /* NOT FOR BROWSER */
127
127
  /** 所有图片,包括图库 */
128
128
  get images() {
129
- return this.querySelectorAll('file, gallery-image, imagemap-image');
129
+ return this.querySelectorAll('file,gallery-image,imagemap-image');
130
130
  }
131
131
  /** 所有内链、外链和自由外链 */
132
132
  get links() {
133
- return this.querySelectorAll('link, redirect-target, ext-link, free-ext-link, magic-link, image-parameter#link');
133
+ return this.querySelectorAll('link,redirect-target,ext-link,free-ext-link,magic-link,image-parameter#link');
134
134
  }
135
135
  /** 所有模板和模块 */
136
136
  get embeds() {
137
- return this.querySelectorAll('template, magic-word#invoke');
137
+ return this.querySelectorAll('template,magic-word#invoke');
138
138
  }
139
139
  /* NOT FOR BROWSER END */
140
140
  /** @class */
@@ -445,27 +445,38 @@ class Token extends element_1.AstElement {
445
445
  index_1.default.viewOnly = true;
446
446
  let errors = super.lint(start, re);
447
447
  if (this.type === 'root') {
448
- const record = {};
449
- for (const cat of this.querySelectorAll('category')) {
450
- const thisCat = record[cat.name];
448
+ const record = {}, selector = 'category,html-attr#id,ext-attr#id,table-attr#id';
449
+ for (const cat of this.querySelectorAll(selector)) {
450
+ let key;
451
+ if (cat.type === 'category') {
452
+ key = cat.name;
453
+ }
454
+ else {
455
+ const value = cat.getValue();
456
+ key = `#${value === true ? '' : value}`;
457
+ }
458
+ const thisCat = record[key];
451
459
  if (thisCat) {
452
460
  thisCat.add(cat);
453
461
  }
454
462
  else {
455
- record[cat.name] = new Set([cat]);
463
+ record[key] = new Set([cat]);
456
464
  }
457
465
  }
458
- for (const value of Object.values(record)) {
459
- if (value.size > 1) {
466
+ for (const [key, value] of Object.entries(record)) {
467
+ if (value.size > 1 && !key.startsWith('#mw-customcollapsible-')) {
468
+ const isCat = !key.startsWith('#'), msg = `duplicated ${isCat ? 'category' : 'id'}`, severity = isCat ? 'error' : 'warning';
460
469
  errors.push(...[...value].map(cat => {
461
- const e = (0, lint_1.generateForSelf)(cat, { start: cat.getAbsoluteIndex() }, 'no-duplicate', 'duplicated category');
462
- e.suggestions = [
463
- {
464
- desc: 'remove',
465
- range: [e.startIndex, e.endIndex],
466
- text: '',
467
- },
468
- ];
470
+ const e = (0, lint_1.generateForSelf)(cat, { start: cat.getAbsoluteIndex() }, 'no-duplicate', msg, severity);
471
+ if (isCat) {
472
+ e.suggestions = [
473
+ {
474
+ desc: 'remove',
475
+ range: [e.startIndex, e.endIndex],
476
+ text: '',
477
+ },
478
+ ];
479
+ }
469
480
  return e;
470
481
  }));
471
482
  }
@@ -759,7 +770,7 @@ class Token extends element_1.AstElement {
759
770
  return this.toHtml();
760
771
  }
761
772
  /** @private */
762
- toHtmlInternal(nowrap) {
773
+ toHtmlInternal(nowrap, nocc) {
763
774
  for (const child of this.childNodes) {
764
775
  if (child.type === 'text') {
765
776
  child.removeBlankLines();
@@ -772,7 +783,7 @@ class Token extends element_1.AstElement {
772
783
  }
773
784
  }
774
785
  this.normalize();
775
- return (0, html_1.font)(this, (0, html_1.html)(this.childNodes, '', nowrap));
786
+ return (0, html_1.font)(this, (0, html_1.html)(this.childNodes, '', nowrap, nocc));
776
787
  }
777
788
  }
778
789
  exports.Token = Token;
@@ -246,10 +246,10 @@ class LinkBaseToken extends index_2.Token {
246
246
  }
247
247
  }
248
248
  /** @private */
249
- toHtmlInternal() {
249
+ toHtmlInternal(_, nocc) {
250
250
  if (this.is('link') || this.is('redirect-target')) {
251
251
  const { link, length, lastChild, type } = this, title = link.getTitleAttr();
252
- return (0, html_1.font)(this, `<a${link.interwiki && ' class="extiw"'} href="${link.getUrl()}"${title && ` title="${title}"`}>${type === 'link' && length > 1 ? lastChild.toHtmlInternal(true) : (0, string_1.sanitize)(this.innerText)}</a>`);
252
+ return (0, html_1.font)(this, `<a${link.interwiki && ' class="extiw"'} href="${link.getUrl()}"${title && ` title="${title}"`}>${type === 'link' && length > 1 ? lastChild.toHtmlInternal(true, nocc) : (0, string_1.sanitize)(this.innerText)}</a>`);
253
253
  }
254
254
  return '';
255
255
  }
@@ -303,10 +303,10 @@ class FileToken extends base_1.LinkBaseToken {
303
303
  throw new Error('LinkBaseToken.setLinkText method is not applicable to images!');
304
304
  }
305
305
  /** @private */
306
- toHtmlInternal() {
306
+ toHtmlInternal(_, nocc) {
307
307
  /** @ignore */
308
308
  const isInteger = (n) => Boolean(n && /^\d+$/u.test(n));
309
- const { link, width, height } = this, file = this.getAttribute('title'), fr = this.getFrame(), manual = fr instanceof title_1.Title, visibleCaption = manual || fr === 'thumbnail' || fr === 'framed', caption = this.getArg('caption')?.toHtmlInternal(true) ?? '', titleFromCaption = visibleCaption ? '' : (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(true)) ?? titleFromCaption, horiz = this.getHorizAlign() ?? '', vert = this.getVertAlign() ?? '', className = `${horiz ? `mw-halign-${horiz}` : vert && `mw-valign-${vert}`}${this.getValue('border') ? ' mw-image-border' : ''} ${(0, string_1.sanitizeAlt)(this.getValue('class')) ?? ''}`.trim(), classAttr = className && ` class="${className}"`, img = `<img${alt && ` alt="${alt}"`} src="${(manual ? fr : file).getUrl()}" class="mw-file-element"${isInteger(width) ? ` width="${width}"` : ''}${isInteger(height) ? ` height="${height}"` : ''}>`;
309
+ const { link, width, height } = this, file = this.getAttribute('title'), fr = this.getFrame(), manual = fr instanceof title_1.Title, visibleCaption = manual || fr === 'thumbnail' || fr === 'framed', caption = this.getArg('caption')?.toHtmlInternal(true, nocc) ?? '', titleFromCaption = visibleCaption ? '' : (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(true)) ?? titleFromCaption, horiz = this.getHorizAlign() ?? '', vert = this.getVertAlign() ?? '', className = `${horiz ? `mw-halign-${horiz}` : vert && `mw-valign-${vert}`}${this.getValue('border') ? ' mw-image-border' : ''} ${(0, string_1.sanitizeAlt)(this.getValue('class')) ?? ''}`.trim(), classAttr = className && ` class="${className}"`, img = `<img${alt && ` alt="${alt}"`} src="${(manual ? fr : file).getUrl()}" class="mw-file-element"${isInteger(width) ? ` width="${width}"` : ''}${isInteger(height) ? ` height="${height}"` : ''}>`;
310
310
  let href = '';
311
311
  if (link) {
312
312
  try {
@@ -176,7 +176,7 @@ let ExtToken = (() => {
176
176
  /** @private */
177
177
  lint(start = this.getAbsoluteIndex(), re) {
178
178
  const errors = super.lint(start, re), rect = new rect_1.BoundingRect(this, start);
179
- if (this.name !== 'nowiki' && this.closest('html-attrs, table-attrs')) {
179
+ if (this.name !== 'nowiki' && this.closest('html-attrs,table-attrs')) {
180
180
  errors.push((0, lint_1.generateForSelf)(this, rect, 'parsing-order', 'extension tag in HTML tag attributes'));
181
181
  }
182
182
  if (this.name === 'ref' && this.closest('heading-title')) {
@@ -195,16 +195,16 @@ let ExtToken = (() => {
195
195
  });
196
196
  }
197
197
  /** @private */
198
- toHtmlInternal() {
198
+ toHtmlInternal(_, nocc) {
199
199
  const { name, firstChild, lastChild } = this;
200
200
  switch (name) {
201
201
  case 'nowiki':
202
202
  return (0, html_1.font)(this, (0, string_1.newline)(lastChild.toHtmlInternal()));
203
203
  case 'pre':
204
- return (0, html_1.font)(this, `<pre${firstChild.toHtmlInternal()}>${(0, string_1.newline)(lastChild.toHtmlInternal())}</pre>`);
204
+ return (0, html_1.font)(this, `<pre${firstChild.toHtmlInternal()}>${(0, string_1.newline)(lastChild.toHtmlInternal(false, nocc))}</pre>`);
205
205
  case 'poem':
206
206
  firstChild.classList.add('poem');
207
- return (0, html_1.font)(this, `<div${firstChild.toHtmlInternal()}>${lastChild.toHtmlInternal().replace(/(?<!^|<hr>)\n(?!$)/gu, '<br>\n')
207
+ return (0, html_1.font)(this, `<div${firstChild.toHtmlInternal()}>${lastChild.toHtmlInternal(false, nocc).replace(/(?<!^|<hr>)\n(?!$)/gu, '<br>\n')
208
208
  .replace(/^ +/gmu, p => '&nbsp;'.repeat(p.length))}</div>`);
209
209
  default:
210
210
  return '';
package/dist/util/html.js CHANGED
@@ -80,13 +80,14 @@ const openList = (chars, state) => {
80
80
  * @param childNodes a Token's contents
81
81
  * @param separator delimiter between nodes
82
82
  * @param nowrap whether to normalize newlines
83
+ * @param nocc whether to perform language conversion
83
84
  */
84
- const html = (childNodes, separator = '', nowrap) => {
85
+ const html = (childNodes, separator = '', nowrap, nocc) => {
85
86
  let lastPrefix = '';
86
87
  const results = [], state = { dt: [] };
87
88
  for (let j = 0; j < childNodes.length; j++) {
88
89
  const child = childNodes[j];
89
- let result = child.toHtmlInternal(nowrap);
90
+ let result = child.toHtmlInternal(nowrap, nocc);
90
91
  if (child.is('list-range')) {
91
92
  result = result.trim();
92
93
  const { previousSibling: { firstChild: { data } } } = child, prefix = data.trim(), prefix2 = prefix.replaceAll(';', ':'), commonPrefixLength = (0, exports.getCommon)(prefix2, lastPrefix);
package/i18n/zh-hans.json CHANGED
@@ -11,6 +11,7 @@
11
11
  "content to be moved out from the table": "将被移出表格的内容",
12
12
  "duplicated $1 attribute": "重复的$1属性",
13
13
  "duplicated category": "重复的分类",
14
+ "duplicated id": "重复的id",
14
15
  "duplicated image $1 parameter": "重复的图片$1参数",
15
16
  "duplicated parameter": "重复参数",
16
17
  "extension tag in HTML tag attributes": "HTML标签属性中的扩展标签",
package/i18n/zh-hant.json CHANGED
@@ -11,6 +11,7 @@
11
11
  "content to be moved out from the table": "將被移出表格的內容",
12
12
  "duplicated $1 attribute": "重複的$1屬性",
13
13
  "duplicated category": "重複的分類",
14
+ "duplicated id": "重複的id",
14
15
  "duplicated image $1 parameter": "重複的圖片$1參數",
15
16
  "duplicated parameter": "重複參數",
16
17
  "extension tag in HTML tag attributes": "HTML標籤屬性中的擴展標籤",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wikiparser-node",
3
- "version": "1.12.3",
3
+ "version": "1.12.4",
4
4
  "description": "A Node.js parser for MediaWiki markup with AST",
5
5
  "keywords": [
6
6
  "mediawiki",