wikiparser-node 1.31.0 → 1.33.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 (111) hide show
  1. package/README.md +5 -0
  2. package/bundle/bundle-es8.min.js +28 -29
  3. package/bundle/bundle-lsp.min.js +31 -31
  4. package/bundle/bundle.min.js +24 -24
  5. package/coverage/badge.svg +1 -1
  6. package/dist/addon/attribute.js +186 -0
  7. package/dist/addon/link.js +91 -0
  8. package/dist/addon/table.js +150 -105
  9. package/dist/addon/token.js +8 -304
  10. package/dist/addon/transclude.js +9 -6
  11. package/dist/base.d.mts +9 -1
  12. package/dist/base.d.ts +9 -1
  13. package/dist/bin/config.js +1 -1
  14. package/dist/index.d.ts +24 -5
  15. package/dist/index.js +71 -92
  16. package/dist/internal.d.ts +4 -0
  17. package/dist/lib/document.d.ts +9 -7
  18. package/dist/lib/document.js +91 -66
  19. package/dist/lib/element.d.ts +7 -7
  20. package/dist/lib/element.js +48 -50
  21. package/dist/lib/lintConfig.js +3 -1
  22. package/dist/lib/lsp.js +127 -56
  23. package/dist/lib/node.js +20 -14
  24. package/dist/lib/text.js +6 -6
  25. package/dist/lib/title.d.ts +11 -0
  26. package/dist/lib/title.js +37 -13
  27. package/dist/mixin/elementLike.js +2 -3
  28. package/dist/mixin/syntax.js +13 -7
  29. package/dist/parser/commentAndExt.js +3 -3
  30. package/dist/parser/selector.js +16 -41
  31. package/dist/render/expand.js +216 -0
  32. package/dist/render/extension.js +141 -0
  33. package/dist/render/html.js +91 -0
  34. package/dist/{addon → render}/magicWords.js +48 -7
  35. package/dist/render/syntaxhighlight.js +415 -0
  36. package/dist/src/arg.js +1 -1
  37. package/dist/src/attribute.d.ts +9 -5
  38. package/dist/src/attribute.js +68 -108
  39. package/dist/src/attributes.d.ts +7 -1
  40. package/dist/src/attributes.js +22 -51
  41. package/dist/src/converter.js +4 -2
  42. package/dist/src/converterFlags.js +8 -6
  43. package/dist/src/converterRule.js +19 -15
  44. package/dist/src/extLink.js +1 -1
  45. package/dist/src/heading.d.ts +1 -1
  46. package/dist/src/heading.js +5 -3
  47. package/dist/src/imageParameter.d.ts +7 -4
  48. package/dist/src/imageParameter.js +47 -28
  49. package/dist/src/index.d.ts +13 -5
  50. package/dist/src/index.js +67 -42
  51. package/dist/src/link/base.d.ts +1 -1
  52. package/dist/src/link/base.js +26 -38
  53. package/dist/src/link/category.d.ts +7 -0
  54. package/dist/src/link/category.js +101 -37
  55. package/dist/src/link/categorytree.d.ts +27 -0
  56. package/dist/src/link/categorytree.js +115 -0
  57. package/dist/src/link/file.d.ts +3 -2
  58. package/dist/src/link/file.js +23 -9
  59. package/dist/src/link/galleryImage.js +7 -9
  60. package/dist/src/link/index.d.ts +1 -1
  61. package/dist/src/link/index.js +10 -31
  62. package/dist/src/multiLine/gallery.d.ts +1 -4
  63. package/dist/src/multiLine/gallery.js +1 -11
  64. package/dist/src/multiLine/imagemap.d.ts +0 -1
  65. package/dist/src/multiLine/imagemap.js +98 -152
  66. package/dist/src/multiLine/index.d.ts +1 -0
  67. package/dist/src/multiLine/index.js +77 -22
  68. package/dist/src/multiLine/inputbox.d.ts +3 -3
  69. package/dist/src/multiLine/inputbox.js +3 -7
  70. package/dist/src/multiLine/paramTag.d.ts +3 -4
  71. package/dist/src/multiLine/paramTag.js +6 -48
  72. package/dist/src/nowiki/comment.js +1 -1
  73. package/dist/src/nowiki/doubleUnderscore.js +4 -2
  74. package/dist/src/nowiki/index.js +34 -31
  75. package/dist/src/nowiki/listBase.d.ts +2 -1
  76. package/dist/src/nowiki/listBase.js +22 -8
  77. package/dist/src/nowiki/quote.d.ts +1 -1
  78. package/dist/src/nowiki/quote.js +1 -1
  79. package/dist/src/onlyinclude.js +1 -1
  80. package/dist/src/paramLine.d.ts +3 -0
  81. package/dist/src/paramLine.js +45 -7
  82. package/dist/src/parameter.js +1 -1
  83. package/dist/src/redirect.js +1 -1
  84. package/dist/src/table/base.d.ts +1 -1
  85. package/dist/src/table/base.js +4 -2
  86. package/dist/src/table/index.d.ts +2 -7
  87. package/dist/src/table/index.js +7 -54
  88. package/dist/src/table/td.js +9 -5
  89. package/dist/src/table/tr.d.ts +1 -1
  90. package/dist/src/tag/index.js +1 -1
  91. package/dist/src/tagPair/ext.js +33 -48
  92. package/dist/src/tagPair/index.js +6 -4
  93. package/dist/src/tagPair/translate.js +2 -2
  94. package/dist/src/transclude.d.ts +0 -6
  95. package/dist/src/transclude.js +16 -33
  96. package/dist/util/constants.js +5 -1
  97. package/dist/util/debug.js +81 -7
  98. package/dist/util/diff.js +17 -15
  99. package/dist/util/html.js +5 -3
  100. package/dist/util/selector.js +37 -0
  101. package/dist/util/sharable.d.mts +5 -1
  102. package/dist/util/sharable.js +69 -8
  103. package/dist/util/sharable.mjs +69 -7
  104. package/dist/util/string.js +31 -12
  105. package/extensions/dist/base.js +1 -1
  106. package/extensions/typings.d.ts +40 -0
  107. package/extensions/ui.css +1 -1
  108. package/i18n/en.json +2 -0
  109. package/i18n/zh-hans.json +31 -29
  110. package/i18n/zh-hant.json +32 -30
  111. package/package.json +19 -15
@@ -37,7 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
38
38
  };
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
- exports.AttributeToken = void 0;
40
+ exports.AttributeToken = exports.stages = void 0;
41
41
  const lint_1 = require("../util/lint");
42
42
  const string_1 = require("../util/string");
43
43
  const constants_1 = require("../util/constants");
@@ -53,7 +53,8 @@ const document_1 = require("../lib/document");
53
53
  const debug_1 = require("../util/debug");
54
54
  const fixed_1 = require("../mixin/fixed");
55
55
  const cached_1 = require("../mixin/cached");
56
- const stages = { 'ext-attr': 0, 'html-attr': 2, 'table-attr': 3 }, ariaAttrs = new Set(['aria-describedby', 'aria-flowto', 'aria-labelledby', 'aria-owns']);
56
+ exports.stages = { 'ext-attr': 0, 'html-attr': 2, 'table-attr': 3 };
57
+ const ariaAttrs = new Set(['aria-describedby', 'aria-flowto', 'aria-labelledby', 'aria-owns']);
57
58
  const insecureStyle = /expression|(?:accelerator|-o-link(?:-source)?|-o-replace)\s*:|(?:url|src|image(?:-set)?)\s*\(|attr\s*\([^)]+[\s,]url/u, evil = /(?:^|\s|\*\/)(?:javascript|vbscript)(?:\W|$)/iu, complexTypes = new Set(['ext', 'arg', 'magic-word', 'template']), urlAttrs = new Set([
58
59
  'about',
59
60
  'property',
@@ -125,16 +126,16 @@ let AttributeToken = (() => {
125
126
  * @param type 标签类型
126
127
  * @param tag 标签名
127
128
  * @param key 属性名
129
+ * @param quotes 引号
128
130
  * @param equal 等号
129
131
  * @param value 属性值
130
- * @param quotes 引号
131
132
  */
132
- constructor(type, tag, key, equal = '', value, quotes = [], config = index_1.default.getConfig(), accum = []) {
133
+ constructor(type, tag, key, quotes, config, equal = '', value, accum = []) {
133
134
  const keyToken = new atom_1.AtomToken(key, 'attr-key', config, accum, type === 'ext-attr' ? { AstText: ':' } : { 'Stage-2': ':', '!ExtToken': '', '!HeadingToken': '' });
134
135
  let valueToken;
135
136
  if (key === 'title' || tag === 'img' && key === 'alt') {
136
137
  valueToken = new index_2.Token(value, config, accum, {
137
- [`Stage-${stages[type]}`]: ':', ConverterToken: ':',
138
+ [`Stage-${exports.stages[type]}`]: ':', ConverterToken: ':',
138
139
  });
139
140
  valueToken.type = 'attr-value';
140
141
  valueToken.setAttribute('stage', constants_1.MAX_STAGE - 1);
@@ -162,7 +163,7 @@ let AttributeToken = (() => {
162
163
  }
163
164
  else {
164
165
  valueToken = new atom_1.AtomToken(value, 'attr-value', config, accum, {
165
- [`Stage-${stages[type]}`]: ':',
166
+ [`Stage-${exports.stages[type]}`]: ':',
166
167
  });
167
168
  }
168
169
  super(undefined, config, accum);
@@ -217,9 +218,12 @@ let AttributeToken = (() => {
217
218
  }
218
219
  if (!attrs?.has(name)
219
220
  && !attrs2?.has(name)
220
- // 不是未定义的扩展标签或包含嵌入的HTML标签
221
+ // 已知定义的扩展标签或不包含嵌入的HTML标签
221
222
  && (type === 'ext-attr' ? attrs || attrs2 : !/\{\{[^{]+\}\}/u.test(name))
222
- && (type === 'ext-attr' && !attrs2
223
+ && (
224
+ // 不支持通用HTML属性的扩展标签
225
+ type === 'ext-attr' && !attrs2
226
+ // 或非通用HTML属性
223
227
  || !/^(?:xmlns:[\w:.-]+|data-(?!ooui|mw|parsoid)[^:]*)$/u.test(name)
224
228
  && (tag === 'meta' || tag === 'link' || !sharable_1.commonHtmlAttrs.has(name)))
225
229
  || (name === 'itemtype' || name === 'itemid' || name === 'itemref')
@@ -325,26 +329,28 @@ let AttributeToken = (() => {
325
329
  }
326
330
  /* NOT FOR BROWSER ONLY */
327
331
  const rule = 'invalid-css', sError = lintConfig.getSeverity(rule), sWarn = lintConfig.getSeverity(rule, 'warn');
328
- if (document_1.cssLSP
329
- && (sError || sWarn)
332
+ if ((sError || sWarn)
330
333
  && name === 'style'
331
334
  && lastChild.length === 1 && lastChild.firstChild.type === 'text') {
332
- const root = this.getRootNode(), textDoc = new document_1.EmbeddedCSSDocument(root, lastChild);
333
- Array.prototype.push.apply(errors, document_1.cssLSP.doValidation(textDoc, textDoc.styleSheet)
334
- .filter(({ code, severity }) => code !== 'css-ruleorselectorexpected' && code !== 'emptyRules'
335
- && (severity === 1 ? sError : sWarn))
336
- .map(({ range: { start: { line, character }, end }, message, severity, code }) => ({
337
- code: code,
338
- rule,
339
- message,
340
- severity: (severity === 1 ? sError : sWarn),
341
- startLine: line,
342
- startCol: character,
343
- startIndex: root.indexFromPos(line, character),
344
- endLine: end.line,
345
- endCol: end.character,
346
- endIndex: root.indexFromPos(end.line, end.character),
347
- })));
335
+ const cssLSP = (0, document_1.loadCssLSP)();
336
+ if (cssLSP) {
337
+ const root = this.getRootNode(), textDoc = new document_1.EmbeddedCSSDocument(root, lastChild);
338
+ Array.prototype.push.apply(errors, cssLSP.doValidation(textDoc, textDoc.styleSheet)
339
+ .filter(({ code, severity }) => code !== 'css-ruleorselectorexpected' && code !== 'emptyRules'
340
+ && (severity === 1 ? sError : sWarn))
341
+ .map(({ range: { start: { line, character }, end }, message, severity, code }) => ({
342
+ code: code,
343
+ rule,
344
+ message,
345
+ severity: (severity === 1 ? sError : sWarn),
346
+ startLine: line,
347
+ startCol: character,
348
+ startIndex: root.indexFromPos(line, character),
349
+ endLine: end.line,
350
+ endCol: end.character,
351
+ endIndex: root.indexFromPos(end.line, end.character),
352
+ })));
353
+ }
348
354
  }
349
355
  /* NOT FOR BROWSER ONLY END */
350
356
  return errors;
@@ -369,12 +375,19 @@ let AttributeToken = (() => {
369
375
  /* PRINT ONLY */
370
376
  /** @private */
371
377
  getAttribute(key) {
378
+ /* NOT FOR BROWSER */
379
+ if (key === 'quotes') {
380
+ return this.#quotes;
381
+ }
382
+ /* NOT FOR BROWSER END */
372
383
  return key === 'invalid' ? this.#lint() : super.getAttribute(key);
373
384
  }
374
385
  /** @private */
375
386
  print() {
376
- const [quoteStart = '', quoteEnd = ''] = this.#quotes;
377
- return this.#equal ? super.print({ sep: (0, string_1.escape)(this.#equal) + quoteStart, post: quoteEnd }) : super.print();
387
+ PRINT: {
388
+ const [quoteStart = '', quoteEnd = ''] = this.#quotes;
389
+ return this.#equal ? super.print({ sep: (0, string_1.escape)(this.#equal) + quoteStart, post: quoteEnd }) : super.print();
390
+ }
378
391
  }
379
392
  /** @private */
380
393
  json(_, start = this.getAbsoluteIndex()) {
@@ -386,11 +399,23 @@ let AttributeToken = (() => {
386
399
  }
387
400
  /* PRINT ONLY END */
388
401
  /* NOT FOR BROWSER */
402
+ /** @private */
403
+ setAttribute(key, value) {
404
+ if (key === 'equal') {
405
+ this.#equal = value && (this.#equal || value);
406
+ }
407
+ else if (key === 'quotes') {
408
+ this.#quotes = value;
409
+ }
410
+ else {
411
+ super.setAttribute(key, value);
412
+ }
413
+ }
389
414
  cloneNode() {
390
415
  const [key, value] = this.cloneChildNodes(), k = key.toString();
391
416
  return debug_1.Shadow.run(() => {
392
417
  // @ts-expect-error abstract class
393
- const token = new AttributeToken(this.type, this.tag, k, this.#equal, undefined, this.#quotes, this.getAttribute('config'));
418
+ const token = new AttributeToken(this.type, this.tag, k, this.#quotes, this.getAttribute('config'), this.#equal, undefined);
394
419
  token.firstChild.safeReplaceWith(key);
395
420
  token.lastChild.safeReplaceWith(value);
396
421
  return token;
@@ -416,33 +441,10 @@ let AttributeToken = (() => {
416
441
  * @throws `RangeError` 同时包含单引号和双引号
417
442
  */
418
443
  setValue(value) {
419
- if (value === false) {
420
- this.remove();
421
- return;
422
- }
423
- else if (value === true) {
424
- this.#equal = '';
425
- return;
426
- }
427
- const { type, lastChild } = this;
428
- if (type === 'ext-attr' && value.includes('>')) {
429
- throw new RangeError('Attributes of an extension tag cannot contain ">"!');
430
- }
431
- else if (value.includes('"') && value.includes(`'`)) {
432
- throw new RangeError('Attribute values cannot contain single and double quotes simultaneously!');
433
- }
434
- const { childNodes } = index_1.default.parseWithRef(value, this, stages[type] + 1);
435
- lastChild.safeReplaceChildren(childNodes);
436
- if (value.includes('"')) {
437
- this.#quotes = [`'`, `'`];
438
- }
439
- else if (value.includes(`'`) || !this.#quotes[0]) {
440
- this.#quotes = ['"', '"'];
441
- }
442
- else {
443
- this.close();
444
- }
444
+ require('../addon/attribute');
445
+ this.setValue(value);
445
446
  }
447
+ /* istanbul ignore next */
446
448
  /**
447
449
  * Rename the attribute
448
450
  *
@@ -451,12 +453,12 @@ let AttributeToken = (() => {
451
453
  * @throws `Error` title和alt属性不能更名
452
454
  */
453
455
  rename(key) {
454
- const { type, name, tag, firstChild } = this;
455
- if (name === 'title' || name === 'alt' && tag === 'img') {
456
- throw new Error(`${name} attribute cannot be renamed!`);
457
- }
458
- const { childNodes } = index_1.default.parseWithRef(key, this, stages[type] + 1);
459
- firstChild.safeReplaceChildren(childNodes);
456
+ require('../addon/attribute');
457
+ this.rename(key);
458
+ }
459
+ /** @private */
460
+ asHtmlAttr() {
461
+ this.#type = 'html-attr';
460
462
  }
461
463
  /** @private */
462
464
  toHtmlInternal() {
@@ -469,10 +471,12 @@ let AttributeToken = (() => {
469
471
  return '';
470
472
  }
471
473
  const sanitized = ariaAttrs.has(name)
472
- ? value.split(/\s+/u).filter(Boolean).map(v => (0, string_1.sanitizeAttr)(v, true)).join(' ')
474
+ ? value.split(/\s+/u).filter(v => v !== '').map(v => (0, string_1.sanitizeAttr)(v, true))
475
+ .join(' ')
473
476
  : (0, string_1.sanitizeAttr)(value, name === 'id');
474
477
  return `${name}="${sanitized}"`;
475
478
  }
479
+ /* istanbul ignore next */
476
480
  /**
477
481
  * Get or set the value of a style property
478
482
  *
@@ -485,52 +489,8 @@ let AttributeToken = (() => {
485
489
  * @throws `Error` 无CSS语言服务
486
490
  */
487
491
  css(key, value) {
488
- const { name, lastChild } = this;
489
- if (name !== 'style') {
490
- throw new Error('Not a style attribute!');
491
- }
492
- else if (lastChild.length !== 1 || lastChild.firstChild.type !== 'text') {
493
- throw new Error('Complex style attribute!');
494
- }
495
- else if (!document_1.cssLSP) {
496
- throw new Error('CSS language service is not available!');
497
- }
498
- const doc = new document_1.EmbeddedCSSDocument(this.getRootNode(), lastChild), styleSheet = doc.styleSheet, { children: [{ declarations }] } = styleSheet, declaration = declarations.children?.filter(({ property }) => property.getText() === key) ?? [];
499
- if (value === undefined) {
500
- return declaration.at(-1)?.value.getText();
501
- }
502
- else if (typeof value === 'number') {
503
- value = String(value);
504
- }
505
- const style = styleSheet.getText().slice(0, -1);
506
- if (!value) {
507
- if (declaration.length === declarations.children?.length) {
508
- this.setValue('');
509
- }
510
- else if (declaration.length > 0) {
511
- let output = '', start = doc.pre.length;
512
- for (const { offset, length } of declaration) {
513
- output += style.slice(start, offset);
514
- start = offset + length;
515
- }
516
- output += style.slice(start);
517
- this.setValue(output.replace(/^\s*;\s*|;\s*(?=;)/gu, ''));
518
- }
519
- return undefined;
520
- }
521
- const hasQuote = value.includes('"');
522
- if (this.#quotes[0] && value.includes(this.#quotes[0]) || hasQuote && value.includes(`'`)) {
523
- const quote = this.#quotes[0] || '"';
524
- throw new RangeError(`Please consider replacing \`${quote}\` with \`${quote === '"' ? `'` : '"'}\`!`);
525
- }
526
- else if (declaration.length > 0) {
527
- const { offset, length } = declaration.at(-1).value;
528
- this.setValue(style.slice(doc.pre.length, offset) + value + style.slice(offset + length));
529
- }
530
- else {
531
- this.setValue(`${style.slice(doc.pre.length)}${/;\s*$/u.test(style) ? '' : '; '}${key}: ${value}`);
532
- }
533
- return undefined;
492
+ require('../addon/attribute');
493
+ return this.css(key, value);
534
494
  }
535
495
  };
536
496
  return AttributeToken = _classThis;
@@ -6,6 +6,11 @@ import type { ExtToken, HtmlToken, SyntaxToken } from '../internal';
6
6
  import type { AttributeTypes } from './attribute';
7
7
  import type { TableTokens } from './table/index';
8
8
  declare type AttributesTypes = `${AttributeTypes}s`;
9
+ /**
10
+ * 将属性类型转换为单属性类型
11
+ * @param type 属性类型
12
+ */
13
+ export declare const toAttributeType: (type: AttributesTypes) => AttributeTypes;
9
14
  /**
10
15
  * attributes of extension and HTML tags
11
16
  *
@@ -134,7 +139,8 @@ export declare abstract class AttributesToken extends Token {
134
139
  * 获取某一样式属性的值
135
140
  * @param key style property / 样式属性
136
141
  * @param value style property value / 样式属性值
142
+ * @since v1.17.1
137
143
  */
138
- css(key: string, value?: string): string | undefined;
144
+ css(key: string, value?: string | number): string | undefined;
139
145
  }
140
146
  export {};
@@ -37,7 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
38
38
  };
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
- exports.AttributesToken = void 0;
40
+ exports.AttributesToken = exports.toAttributeType = void 0;
41
41
  const lint_1 = require("../util/lint");
42
42
  const string_1 = require("../util/string");
43
43
  const rect_1 = require("../lib/rect");
@@ -57,11 +57,12 @@ const stages = { 'ext-attrs': 0, 'html-attrs': 2, 'table-attrs': 3 };
57
57
  * @param type 属性类型
58
58
  */
59
59
  const toAttributeType = (type) => type.slice(0, -1);
60
+ exports.toAttributeType = toAttributeType;
60
61
  /**
61
62
  * 将属性类型转换为无效属性类型
62
63
  * @param type 属性类型
63
64
  */
64
- const toDirty = (type) => `${toAttributeType(type)}-dirty`;
65
+ const toDirty = (type) => `${(0, exports.toAttributeType)(type)}-dirty`;
65
66
  const wordRegex = /* #__PURE__ */ (() => {
66
67
  try {
67
68
  // eslint-disable-next-line prefer-regex-literals
@@ -118,7 +119,7 @@ let AttributesToken = (() => {
118
119
  /** class attribute in Set / 以Set表示的class属性 */
119
120
  get classList() {
120
121
  if (!this.#classList) {
121
- this.#classList = new Set(this.className.split(/\s/u));
122
+ this.#classList = new Set(this.className.split(/\s+/u));
122
123
  /**
123
124
  * 更新classList
124
125
  * @param prop 方法名
@@ -184,7 +185,7 @@ let AttributesToken = (() => {
184
185
  if (/^(?:[\w:]|\0\d+t\x7F)(?:[\w:.-]|\0\d+t\x7F)*$/u.test((0, string_1.removeComment)(key).trim())) {
185
186
  const value = quoted ?? unquoted, quotes = [quoteStart, quoteEnd],
186
187
  // @ts-expect-error abstract class
187
- token = new attribute_1.AttributeToken(toAttributeType(type), name, key, equal, value, quotes, config, accum);
188
+ token = new attribute_1.AttributeToken((0, exports.toAttributeType)(type), name, key, quotes, config, equal, value, accum);
188
189
  insertDirty();
189
190
  super.insertAt(token);
190
191
  }
@@ -332,29 +333,21 @@ let AttributesToken = (() => {
332
333
  }
333
334
  /** @private */
334
335
  print() {
335
- return this.toString()
336
+ PRINT: return this.toString()
336
337
  ? `<span class="wpb-${this.type}${this.#lint() ? ' wpb-invalid' : ''}">${this.childNodes.map(child => child.print(child instanceof atom_1.AtomToken ? { class: child.toString().trim() && 'attr-dirty' } : undefined)).join('')}</span>`
337
338
  : '';
338
339
  }
339
340
  /* PRINT ONLY END */
340
341
  /* NOT FOR BROWSER */
342
+ /* istanbul ignore next */
341
343
  /**
342
344
  * Sanitize invalid attributes
343
345
  *
344
346
  * 清理无效属性
345
347
  */
346
348
  sanitize() {
347
- let dirty = false;
348
- for (let i = this.length - 1; i >= 0; i--) {
349
- const child = this.childNodes[i];
350
- if (child instanceof atom_1.AtomToken && child.text().trim()) {
351
- dirty = true;
352
- this.removeAt(i);
353
- }
354
- }
355
- if (!debug_1.Shadow.running && dirty) {
356
- index_1.default.warn('AttributesToken.sanitize will remove invalid attributes!');
357
- }
349
+ require('../addon/attribute');
350
+ this.sanitize();
358
351
  }
359
352
  cloneNode() {
360
353
  // @ts-expect-error abstract class
@@ -368,12 +361,14 @@ let AttributesToken = (() => {
368
361
  */
369
362
  insertAt(token, i = this.length) {
370
363
  if (!(token instanceof attribute_1.AttributeToken)) {
364
+ /* istanbul ignore if */
371
365
  if (!debug_1.Shadow.running && token.toString().trim()) {
372
366
  this.constructorError('can only insert AttributeToken');
373
367
  }
374
368
  return super.insertAt(token, i);
375
369
  }
376
370
  const { type, name, length } = this;
371
+ /* istanbul ignore if */
377
372
  if (token.type !== type.slice(0, -1) || token.tag !== name) {
378
373
  throw new RangeError(`The AttributeToken to be inserted can only be used for <${token.tag}> tag!`);
379
374
  }
@@ -400,27 +395,8 @@ let AttributesToken = (() => {
400
395
  return token;
401
396
  }
402
397
  setAttr(keyOrProp, value) {
403
- if (typeof keyOrProp === 'object') {
404
- for (const [key, val] of Object.entries(keyOrProp)) {
405
- this.setAttr(key, val);
406
- }
407
- return;
408
- }
409
- const { type, name } = this;
410
- if (type === 'ext-attrs' && typeof value === 'string' && value.includes('>')) {
411
- throw new RangeError('Attributes of an extension tag cannot contain ">"!');
412
- }
413
- const key = (0, string_1.trimLc)(keyOrProp), attr = this.getAttrToken(key);
414
- if (attr) {
415
- attr.setValue(value);
416
- return;
417
- }
418
- else if (value === false) {
419
- return;
420
- }
421
- // @ts-expect-error abstract class
422
- const token = debug_1.Shadow.run(() => new attribute_1.AttributeToken(toAttributeType(type), name, key, value === true ? '' : '=', value === true ? '' : value, ['"', '"'], this.getAttribute('config')));
423
- this.insertAt(token);
398
+ require('../addon/attribute');
399
+ this.setAttr(keyOrProp, value);
424
400
  }
425
401
  /**
426
402
  * Get all attribute names
@@ -449,6 +425,7 @@ let AttributesToken = (() => {
449
425
  attr.remove();
450
426
  }
451
427
  }
428
+ /* istanbul ignore next */
452
429
  /**
453
430
  * Toggle the specified attribute
454
431
  *
@@ -458,17 +435,8 @@ let AttributesToken = (() => {
458
435
  * @throws `RangeError` 不为Boolean类型的属性值
459
436
  */
460
437
  toggleAttr(key, force) {
461
- key = (0, string_1.trimLc)(key);
462
- const attr = this.getAttrToken(key);
463
- if (attr && attr.getValue() !== true) {
464
- throw new RangeError(`${key} attribute is not Boolean!`);
465
- }
466
- else if (attr) {
467
- attr.setValue(force === true);
468
- }
469
- else if (force !== false) {
470
- this.setAttr(key, true);
471
- }
438
+ require('../addon/attribute');
439
+ this.toggleAttr(key, force);
472
440
  }
473
441
  /**
474
442
  * 生成引导空格
@@ -496,18 +464,21 @@ let AttributesToken = (() => {
496
464
  }
497
465
  /** @private */
498
466
  toHtmlInternal() {
499
- const map = new Map(this.childNodes.filter(child => child instanceof attribute_1.AttributeToken).map(child => [child.name, child]));
500
- return map.size === 0 ? '' : ` ${(0, html_1.html)([...map.values()], ' ')}`;
467
+ const map = new Map(this.childNodes.filter(child => child instanceof attribute_1.AttributeToken).map(child => [child.name, child])), output = map.size === 0 ? '' : (0, html_1.html)([...map.values()], ' ', { removeBlank: true });
468
+ return output && ` ${output}`;
501
469
  }
470
+ /* istanbul ignore next */
502
471
  /**
503
472
  * Get the value of a style property
504
473
  *
505
474
  * 获取某一样式属性的值
506
475
  * @param key style property / 样式属性
507
476
  * @param value style property value / 样式属性值
477
+ * @since v1.17.1
508
478
  */
509
479
  css(key, value) {
510
- return this.getAttrToken('style')?.css(key, value);
480
+ require('../addon/attribute');
481
+ return this.css(key, value);
511
482
  }
512
483
  };
513
484
  })();
@@ -133,8 +133,10 @@ let ConverterToken = (() => {
133
133
  }
134
134
  /** @private */
135
135
  print() {
136
- const { childNodes: [flags, ...rules] } = this;
137
- return `<span class="wpb-converter">-{${flags.print()}${flags.length > 0 ? '|' : ''}${(0, string_1.print)(rules, { sep: ';' })}}-</span>`;
136
+ PRINT: {
137
+ const { childNodes: [flags, ...rules] } = this;
138
+ return `<span class="wpb-converter">-{${flags.print()}${flags.length > 0 ? '|' : ''}${(0, string_1.print)(rules, { sep: ';' })}}-</span>`;
139
+ }
138
140
  }
139
141
  /* NOT FOR BROWSER */
140
142
  cloneNode() {
@@ -140,11 +140,13 @@ let ConverterFlagsToken = (() => {
140
140
  /** @private */
141
141
  isInvalidFlag(flag, variant, unknown, valid) {
142
142
  /* PRINT ONLY */
143
- if (typeof flag === 'object') {
144
- flag = flag.text().trim();
145
- variant = this.getVariantFlags();
146
- unknown = this.getUnknownFlags();
147
- valid = new Set(this.#flags.filter(f => definedFlags.has(f)));
143
+ PRINT: {
144
+ if (typeof flag === 'object') {
145
+ flag = flag.text().trim();
146
+ variant = this.getVariantFlags();
147
+ unknown = this.getUnknownFlags();
148
+ valid = new Set(this.#flags.filter(f => definedFlags.has(f)));
149
+ }
148
150
  }
149
151
  /* PRINT ONLY END */
150
152
  return Boolean(flag) && !variant.has(flag) && !unknown.has(flag) && (variant.size > 0 || !valid.has(flag));
@@ -180,7 +182,7 @@ let ConverterFlagsToken = (() => {
180
182
  }
181
183
  /** @private */
182
184
  print() {
183
- return super.print({ sep: ';' });
185
+ PRINT: return super.print({ sep: ';' });
184
186
  }
185
187
  /* NOT FOR BROWSER */
186
188
  cloneNode() {
@@ -182,12 +182,14 @@ let ConverterRuleToken = (() => {
182
182
  }
183
183
  /** @private */
184
184
  print() {
185
- const { childNodes } = this;
186
- if (childNodes.length === 3) {
187
- const [from, variant, to] = childNodes;
188
- return `<span class="wpb-converter-rule">${from.print()}=>${variant.print()}:${to.print()}</span>`;
185
+ PRINT: {
186
+ const { childNodes } = this;
187
+ if (childNodes.length === 3) {
188
+ const [from, variant, to] = childNodes;
189
+ return `<span class="wpb-converter-rule">${from.print()}=>${variant.print()}:${to.print()}</span>`;
190
+ }
191
+ return super.print({ sep: ':' });
189
192
  }
190
- return super.print({ sep: ':' });
191
193
  }
192
194
  /** @private */
193
195
  json(_, start = this.getAbsoluteIndex()) {
@@ -212,17 +214,19 @@ let ConverterRuleToken = (() => {
212
214
  /** @private */
213
215
  afterBuild() {
214
216
  super.afterBuild();
215
- const /** @implements */ converterRuleListener = (e, data) => {
216
- const { prevTarget } = e;
217
- if (this.length > 1 && this.childNodes[this.length - 2] === prevTarget) {
218
- const { variant } = this;
219
- if (!this.getAttribute('config').variants.includes(variant)) {
220
- (0, debug_1.undo)(e, data);
221
- throw new Error(`Invalid language variant: ${variant}`);
217
+ if (!index_1.default.internal) {
218
+ const /** @implements */ converterRuleListener = (e, data) => {
219
+ const { prevTarget } = e;
220
+ if (this.length > 1 && this.childNodes[this.length - 2] === prevTarget) {
221
+ const { variant } = this;
222
+ if (!this.getAttribute('config').variants.includes(variant)) {
223
+ (0, debug_1.undo)(e, data);
224
+ throw new Error(`Invalid language variant: ${variant}`);
225
+ }
222
226
  }
223
- }
224
- };
225
- this.addEventListener(['remove', 'insert', 'text', 'replace'], converterRuleListener);
227
+ };
228
+ this.addEventListener(['remove', 'insert', 'text', 'replace'], converterRuleListener);
229
+ }
226
230
  }
227
231
  /**
228
232
  * @override
@@ -167,7 +167,7 @@ let ExtLinkToken = (() => {
167
167
  }
168
168
  /** @private */
169
169
  print() {
170
- return super.print(this.length === 1 ? { pre: '[', post: `${this.#space}]` } : { pre: '[', sep: this.#space, post: ']' });
170
+ PRINT: return super.print(this.length === 1 ? { pre: '[', post: `${this.#space}]` } : { pre: '[', sep: this.#space, post: ']' });
171
171
  }
172
172
  /* NOT FOR BROWSER */
173
173
  cloneNode() {
@@ -56,7 +56,7 @@ export declare abstract class HeadingToken extends Token {
56
56
  * Get the section led by this heading
57
57
  *
58
58
  * 获取由此标题引导的章节
59
- * @since v1.29.3
59
+ * @since v1.30.0
60
60
  */
61
61
  section(): AstRange | undefined;
62
62
  }
@@ -242,8 +242,10 @@ let HeadingToken = (() => {
242
242
  }
243
243
  /** @private */
244
244
  print() {
245
- const equals = this.#getEquals();
246
- return super.print({ pre: equals, sep: equals });
245
+ PRINT: {
246
+ const equals = this.#getEquals();
247
+ return super.print({ pre: equals, sep: equals });
248
+ }
247
249
  }
248
250
  /** @private */
249
251
  json(_, start = this.getAbsoluteIndex()) {
@@ -309,7 +311,7 @@ let HeadingToken = (() => {
309
311
  * Get the section led by this heading
310
312
  *
311
313
  * 获取由此标题引导的章节
312
- * @since v1.29.3
314
+ * @since v1.30.0
313
315
  */
314
316
  section() {
315
317
  const { parentNode, level } = this;
@@ -1,8 +1,7 @@
1
1
  import { Token } from './index';
2
- import type { LintError, Config } from '../base';
2
+ import type { LintError, Config, TokenTypes } from '../base';
3
3
  import type { Title } from '../lib/title';
4
4
  import type { AtomToken, FileToken, AstNodes, AstText } from '../internal';
5
- export declare const galleryParams: Set<string>, extensions: Set<string>;
6
5
  /**
7
6
  * image parameter
8
7
  *
@@ -47,8 +46,12 @@ export declare abstract class ImageParameterToken extends Token {
47
46
  /** image height / 图片高度 */
48
47
  get height(): string | undefined;
49
48
  set height(height: string | undefined);
50
- /** @param str 图片参数 */
51
- constructor(str: string, extension: string | undefined, config: Config, accum?: Token[]);
49
+ /**
50
+ * @param str 图片参数
51
+ * @param extension 文件扩展名
52
+ * @param type 父节点类型
53
+ */
54
+ constructor(str: string, extension: string | undefined, type: TokenTypes | undefined, config: Config, accum?: Token[]);
52
55
  /**
53
56
  * Get the parameter value
54
57
  *