wikilint 2.3.8 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/base.d.ts +8 -2
  2. package/dist/bin/declaration.js +27 -0
  3. package/dist/lib/element.d.ts +1 -1
  4. package/dist/lib/element.js +13 -4
  5. package/dist/lib/node.d.ts +1 -2
  6. package/dist/lib/text.d.ts +0 -1
  7. package/dist/lib/title.js +2 -2
  8. package/dist/mixin/hidden.js +3 -4
  9. package/dist/parser/braces.js +1 -1
  10. package/dist/parser/hrAndDoubleUnderscore.js +3 -3
  11. package/dist/src/arg.d.ts +1 -1
  12. package/dist/src/attribute.d.ts +1 -2
  13. package/dist/src/attribute.js +28 -5
  14. package/dist/src/attributes.d.ts +2 -2
  15. package/dist/src/converter.d.ts +2 -12
  16. package/dist/src/converterFlags.d.ts +1 -2
  17. package/dist/src/converterRule.d.ts +1 -1
  18. package/dist/src/extLink.d.ts +2 -13
  19. package/dist/src/gallery.d.ts +1 -2
  20. package/dist/src/heading.d.ts +1 -2
  21. package/dist/src/heading.js +16 -7
  22. package/dist/src/hidden.d.ts +1 -7
  23. package/dist/src/hidden.js +1 -1
  24. package/dist/src/html.d.ts +1 -2
  25. package/dist/src/html.js +53 -3
  26. package/dist/src/imageParameter.d.ts +2 -1
  27. package/dist/src/imageParameter.js +8 -0
  28. package/dist/src/imagemap.d.ts +1 -1
  29. package/dist/src/imagemapLink.d.ts +1 -1
  30. package/dist/src/index.d.ts +0 -1
  31. package/dist/src/link/base.d.ts +1 -2
  32. package/dist/src/link/base.js +2 -2
  33. package/dist/src/link/file.d.ts +16 -7
  34. package/dist/src/link/file.js +18 -0
  35. package/dist/src/link/galleryImage.d.ts +0 -3
  36. package/dist/src/link/galleryImage.js +1 -1
  37. package/dist/src/link/index.d.ts +4 -1
  38. package/dist/src/link/index.js +9 -0
  39. package/dist/src/magicLink.d.ts +1 -1
  40. package/dist/src/nested.d.ts +1 -1
  41. package/dist/src/nowiki/base.d.ts +1 -1
  42. package/dist/src/nowiki/comment.d.ts +1 -7
  43. package/dist/src/nowiki/comment.js +1 -1
  44. package/dist/src/nowiki/doubleUnderscore.d.ts +3 -9
  45. package/dist/src/nowiki/doubleUnderscore.js +3 -3
  46. package/dist/src/nowiki/noinclude.d.ts +1 -7
  47. package/dist/src/nowiki/noinclude.js +1 -1
  48. package/dist/src/nowiki/quote.d.ts +4 -0
  49. package/dist/src/nowiki/quote.js +17 -1
  50. package/dist/src/paramTag/index.d.ts +1 -1
  51. package/dist/src/parameter.d.ts +1 -1
  52. package/dist/src/pre.d.ts +1 -1
  53. package/dist/src/table/base.d.ts +1 -1
  54. package/dist/src/table/index.d.ts +1 -1
  55. package/dist/src/table/td.d.ts +1 -2
  56. package/dist/src/table/tr.d.ts +1 -1
  57. package/dist/src/tagPair/ext.d.ts +1 -1
  58. package/dist/src/tagPair/include.d.ts +2 -11
  59. package/dist/src/tagPair/include.js +1 -1
  60. package/dist/src/tagPair/index.d.ts +1 -2
  61. package/dist/src/transclude.d.ts +5 -6
  62. package/dist/src/transclude.js +2 -2
  63. package/i18n/zh-hans.json +7 -1
  64. package/i18n/zh-hant.json +7 -1
  65. package/package.json +4 -2
package/dist/base.d.ts CHANGED
@@ -24,17 +24,23 @@ export interface LintError {
24
24
  /** 类似Node */
25
25
  export interface AstNode {
26
26
  type: string;
27
- readonly childNodes: AstNode[];
27
+ readonly childNodes: readonly AstNode[];
28
28
  /** Linter */
29
29
  lint(): LintError[];
30
30
  }
31
+ /** 类似HTMLElement */
32
+ interface AstElement extends AstNode {
33
+ }
31
34
  export interface Parser {
32
35
  config: string | Config;
33
36
  i18n: string | Record<string, string> | undefined;
37
+ /** 获取解析设置 */
38
+ getConfig(): Config;
34
39
  /**
35
40
  * 解析wikitext
36
41
  * @param include 是否嵌入
37
42
  * @param maxStage 最大解析层级
38
43
  */
39
- parse(wikitext: string, include?: boolean, maxStage?: number, config?: Config): AstNode;
44
+ parse(wikitext: string, include?: boolean, maxStage?: number, config?: Config): AstElement;
40
45
  }
46
+ export {};
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ // eslint-disable-next-line @stylistic/max-len
6
+ const regex = /declare [^\n]+?: \(+abstract new [^\n]+\n(.+)\}\) & typeof (\w+\.)?(\w+)\b.+(export [^\n]+ extends )\w+\b(.+?\n)/isu;
7
+ for (const file of fs.readdirSync('dist/src/', { recursive: true })) {
8
+ if (!file.endsWith('.d.ts')) {
9
+ continue;
10
+ }
11
+ const fullPath = path.join('dist/src', file), content = fs.readFileSync(fullPath, 'utf8');
12
+ if (content.includes('(abstract new ')) {
13
+ // console.log(file);
14
+ fs.writeFileSync(fullPath, content.replace(regex, (_, mixins, parser, base, exp, impl) => {
15
+ const str = `${exp}${base}${impl}${mixins.split(/\n\}\) & \(+abstract new .+/u)
16
+ .map(mixin => mixin.slice(0, mixin.indexOf('toString'))
17
+ .replace(/^[ \t]+(?:$|readonly .+\n)/gmu, ''))
18
+ .join('\n')}`, regex2 = new RegExp(`import \\{\\s*${base}\\b.+?;\n`, 'su');
19
+ let imports = '';
20
+ if (parser && !regex2.test(content)) {
21
+ const original = fs.readFileSync(path.join('src', file.replace(/d\.ts$/u, 'ts')), 'utf8');
22
+ [imports] = regex2.exec(original);
23
+ }
24
+ return imports + str;
25
+ }));
26
+ }
27
+ }
@@ -29,7 +29,7 @@ export declare abstract class AstElement extends AstNode {
29
29
  * 最近的祖先节点
30
30
  * @param selector 选择器
31
31
  */
32
- closest<T extends Token>(selector: string): T | undefined;
32
+ closest<T = Token>(selector: string): T | undefined;
33
33
  /**
34
34
  * 在末尾批量插入子节点
35
35
  * @param elements 插入节点
@@ -52,14 +52,23 @@ class AstElement extends node_1.AstNode {
52
52
  return node;
53
53
  }
54
54
  /**
55
- * 最近的祖先节点
55
+ * 将选择器转化为类型谓词
56
56
  * @param selector 选择器
57
57
  */
58
- closest(selector) {
59
- let { parentNode } = this, condition;
58
+ #getCondition(selector) {
59
+ let condition;
60
60
  const types = new Set(selector.split(',').map(str => str.trim()));
61
61
  // eslint-disable-next-line prefer-const
62
- condition = /** @implements */ (token) => types.has(token.type);
62
+ condition = (token => types.has(token.type));
63
+ return condition;
64
+ }
65
+ /**
66
+ * 最近的祖先节点
67
+ * @param selector 选择器
68
+ */
69
+ closest(selector) {
70
+ const condition = this.#getCondition(selector);
71
+ let { parentNode } = this;
63
72
  while (parentNode) {
64
73
  if (condition(parentNode)) {
65
74
  return parentNode;
@@ -16,10 +16,9 @@ export interface CaretPosition {
16
16
  }
17
17
  /** 类似Node */
18
18
  export declare abstract class AstNode implements AstNodeBase {
19
- #private;
20
19
  type: TokenTypes | 'text';
21
20
  data?: string | undefined;
22
- readonly childNodes: AstNodes[];
21
+ readonly childNodes: readonly AstNodes[];
23
22
  abstract lint(): LintError[];
24
23
  /** 首位子节点 */
25
24
  get firstChild(): AstNodes | undefined;
@@ -2,7 +2,6 @@ import { AstNode } from './node';
2
2
  import type { LintError } from '../base';
3
3
  /** 文本节点 */
4
4
  export declare class AstText extends AstNode {
5
- #private;
6
5
  readonly type = "text";
7
6
  readonly name: undefined;
8
7
  readonly data: string;
package/dist/lib/title.js CHANGED
@@ -36,7 +36,7 @@ class Title {
36
36
  const m = title.split(':');
37
37
  if (m.length > 1) {
38
38
  const id = nsid[m[0].trim().toLowerCase()];
39
- if (id !== undefined) {
39
+ if (id) {
40
40
  ns = id;
41
41
  title = m.slice(1).join(':').trim();
42
42
  }
@@ -50,7 +50,7 @@ class Title {
50
50
  title = title.slice(0, i).trim();
51
51
  }
52
52
  this.valid = Boolean(title
53
- || selfLink && this.fragment !== undefined) && !/\0\d+[eh!+-]\x7F|[<>[\]{}|]|%[\da-f]{2}/iu.test(title);
53
+ || selfLink && this.fragment !== undefined) && !/^:|\0\d+[eh!+-]\x7F|[<>[\]{}|]|%[\da-f]{2}/iu.test(title);
54
54
  }
55
55
  }
56
56
  exports.Title = Title;
@@ -1,14 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hidden = void 0;
3
+ exports.hiddenToken = void 0;
4
4
  /**
5
5
  * 解析后不可见的类
6
6
  * @param constructor 基类
7
7
  */
8
- const hidden = (constructor) => {
8
+ const hiddenToken = (constructor) => {
9
9
  /** 解析后不可见的类 */
10
10
  class AnyHiddenToken extends constructor {
11
- static hidden = true;
12
11
  /** 没有可见部分 */
13
12
  text() {
14
13
  return '';
@@ -20,4 +19,4 @@ const hidden = (constructor) => {
20
19
  }
21
20
  return AnyHiddenToken;
22
21
  };
23
- exports.hidden = hidden;
22
+ exports.hiddenToken = hiddenToken;
@@ -84,7 +84,7 @@ const parseBraces = (wikitext, config = Parser.getConfig(), accum = []) => {
84
84
  }
85
85
  }
86
86
  catch (e) {
87
- if (e instanceof SyntaxError && e.message.startsWith('非法的模板名称:')) {
87
+ if (e instanceof SyntaxError && e.message === '非法的模板名称') {
88
88
  skip = true;
89
89
  }
90
90
  else {
@@ -20,9 +20,9 @@ const parseHrAndDoubleUnderscore = ({ firstChild: { data }, type, name }, config
20
20
  new hr_1.HrToken(m, config, accum);
21
21
  return `${lead}\0${accum.length - 1}r\x7F`;
22
22
  }).replace(new RegExp(`__(${doubleUnderscore.flat().join('|')})__`, 'giu'), (m, p1) => {
23
- const fixed = sensitive.has(p1);
24
- if (fixed || insensitive.has(p1.toLowerCase())) {
25
- new doubleUnderscore_1.DoubleUnderscoreToken(p1, fixed, config, accum);
23
+ const caseSensitive = sensitive.has(p1);
24
+ if (caseSensitive || insensitive.has(p1.toLowerCase())) {
25
+ new doubleUnderscore_1.DoubleUnderscoreToken(p1, caseSensitive, config, accum);
26
26
  return `\0${accum.length - 1}u\x7F`;
27
27
  }
28
28
  return m;
package/dist/src/arg.d.ts CHANGED
@@ -9,7 +9,7 @@ import type { LintError } from '../base';
9
9
  */
10
10
  export declare class ArgToken extends Token {
11
11
  readonly type = "arg";
12
- readonly childNodes: [AtomToken] | [AtomToken, Token, ...HiddenToken[]];
12
+ readonly childNodes: readonly [AtomToken] | readonly [AtomToken, Token, ...HiddenToken[]];
13
13
  abstract get firstChild(): AtomToken;
14
14
  abstract get lastChild(): Token;
15
15
  /** 预设值 */
@@ -9,11 +9,10 @@ export type AttributeTypes = 'ext-attr' | 'html-attr' | 'table-attr';
9
9
  * @classdesc `{childNodes: [AtomToken, Token|AtomToken]}`
10
10
  */
11
11
  export declare class AttributeToken extends Token {
12
- #private;
13
12
  type: AttributeTypes;
14
13
  readonly name: string;
15
14
  readonly tag: string;
16
- readonly childNodes: [AtomToken, Token];
15
+ readonly childNodes: readonly [AtomToken, Token];
17
16
  abstract get firstChild(): AtomToken;
18
17
  abstract get lastChild(): Token;
19
18
  abstract get parentNode(): AttributesToken | undefined;
@@ -32,7 +32,7 @@ const commonHtmlAttrs = new Set([
32
32
  'itemref',
33
33
  'itemscope',
34
34
  'itemtype',
35
- ]), blockAttrs = new Set(['align']), citeAttrs = new Set(['cite']), citeAndAttrs = new Set(['cite', 'datetime']), widthAttrs = new Set(['width']), tdAttrs = new Set(['align', 'valign', 'abbr', 'axis', 'headers', 'scope', 'rowspan', 'colspan', 'width', 'height', 'bgcolor']), typeAttrs = new Set(['type']), htmlAttrs = {
35
+ ]), blockAttrs = new Set(['align']), citeAttrs = new Set(['cite']), citeAndAttrs = new Set(['cite', 'datetime']), widthAttrs = new Set(['width']), obsoleteTdAttrs = new Set(['axis', 'align', 'bgcolor', 'height', 'width', 'valign']), tdAttrs = new Set([...obsoleteTdAttrs, 'abbr', 'headers', 'scope', 'rowspan', 'colspan']), typeAttrs = new Set(['type']), obsoleteTableAttrs = new Set(['summary', 'align', 'bgcolor', 'cellpadding', 'cellspacing', 'frame', 'rules', 'width']), brAttrs = new Set(['clear']), trAttrs = new Set(['bgcolor', 'align', 'valign']), htmlAttrs = {
36
36
  div: blockAttrs,
37
37
  h1: blockAttrs,
38
38
  h2: blockAttrs,
@@ -43,16 +43,16 @@ const commonHtmlAttrs = new Set([
43
43
  blockquote: citeAttrs,
44
44
  q: citeAttrs,
45
45
  p: blockAttrs,
46
- br: new Set(['clear']),
46
+ br: brAttrs,
47
47
  pre: widthAttrs,
48
48
  ins: citeAndAttrs,
49
49
  del: citeAndAttrs,
50
50
  ul: typeAttrs,
51
51
  ol: new Set(['type', 'start', 'reversed']),
52
52
  li: new Set(['type', 'value']),
53
- table: new Set(['summary', 'width', 'border', 'frame', 'rules', 'cellspacing', 'cellpadding', 'align', 'bgcolor']),
53
+ table: new Set([...obsoleteTableAttrs, 'border']),
54
54
  caption: blockAttrs,
55
- tr: new Set(['bgcolor', 'align', 'valign']),
55
+ tr: trAttrs,
56
56
  td: tdAttrs,
57
57
  th: tdAttrs,
58
58
  img: new Set(['alt', 'src', 'width', 'height', 'srcset']),
@@ -118,7 +118,26 @@ const commonHtmlAttrs = new Set([
118
118
  + '|'
119
119
  + '(?:url|image(?:-set)?)\\s*\\('
120
120
  + '|'
121
- + 'attr\\s*\\([^)]+[\\s,]url', 'u');
121
+ + 'attr\\s*\\([^)]+[\\s,]url', 'u'), obsoleteAttrs = {
122
+ table: obsoleteTableAttrs,
123
+ td: new Set([...obsoleteTdAttrs, 'scope']),
124
+ th: obsoleteTdAttrs,
125
+ br: brAttrs,
126
+ caption: blockAttrs,
127
+ div: blockAttrs,
128
+ hr: widthAttrs,
129
+ h1: blockAttrs,
130
+ h2: blockAttrs,
131
+ h3: blockAttrs,
132
+ h4: blockAttrs,
133
+ h5: blockAttrs,
134
+ h6: blockAttrs,
135
+ li: typeAttrs,
136
+ p: blockAttrs,
137
+ pre: widthAttrs,
138
+ tr: trAttrs,
139
+ ul: typeAttrs,
140
+ };
122
141
  /**
123
142
  * 扩展和HTML标签属性
124
143
  * @classdesc `{childNodes: [AtomToken, Token|AtomToken]}`
@@ -223,6 +242,10 @@ class AttributeToken extends index_1.Token {
223
242
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
224
243
  errors.push((0, lint_1.generateForChild)(firstChild, rect, 'illegal attribute name'));
225
244
  }
245
+ else if (obsoleteAttrs[tag]?.has(name)) {
246
+ rect ??= { start, ...this.getRootNode().posFromIndex(start) };
247
+ errors.push((0, lint_1.generateForChild)(firstChild, rect, 'obsolete attribute', 'warning'));
248
+ }
226
249
  else if (name === 'style' && typeof value === 'string' && insecureStyle.test(value)) {
227
250
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
228
251
  errors.push((0, lint_1.generateForChild)(lastChild, rect, 'insecure style'));
@@ -13,7 +13,7 @@ declare type AttributesTypes = `${AttributeTypes}s`;
13
13
  export declare class AttributesToken extends Token {
14
14
  type: AttributesTypes;
15
15
  readonly name: string;
16
- readonly childNodes: (AtomToken | AttributeToken)[];
16
+ readonly childNodes: readonly (AtomToken | AttributeToken)[];
17
17
  abstract get firstChild(): AtomToken | AttributeToken | undefined;
18
18
  abstract get lastChild(): AtomToken | AttributeToken | undefined;
19
19
  abstract get parentNode(): ExtToken | HtmlToken | TableToken | TrToken | TdToken | undefined;
@@ -27,7 +27,7 @@ export declare class AttributesToken extends Token {
27
27
  * 所有指定属性名的AttributeToken
28
28
  * @param key 属性名
29
29
  */
30
- getAttrTokens(key?: string): readonly AttributeToken[];
30
+ getAttrTokens(key?: string): AttributeToken[];
31
31
  /**
32
32
  * 指定属性名的最后一个AttributeToken
33
33
  * @param key 属性名
@@ -2,19 +2,9 @@ import * as Parser from '../index';
2
2
  import { Token } from './index';
3
3
  import { ConverterFlagsToken } from './converterFlags';
4
4
  import { ConverterRuleToken } from './converterRule';
5
- declare const ConverterToken_base: (abstract new (...args: any[]) => {
6
- readonly firstChild: Parser.ConverterFlagsToken;
7
- toString(omit?: Set<string> | undefined, separator?: string | undefined): string;
8
- text(separator?: string | undefined): string;
9
- lint(start?: number | undefined): Parser.LintError[];
10
- }) & typeof Parser.Token;
11
- /**
12
- * 转换
13
- * @classdesc `{childNodes: [ConverterFlagsToken, ...ConverterRuleToken]}`
14
- */
15
- export declare class ConverterToken extends ConverterToken_base {
5
+ export declare class ConverterToken extends Token {
16
6
  readonly type = "converter";
17
- readonly childNodes: [ConverterFlagsToken, ...ConverterRuleToken[]];
7
+ readonly childNodes: readonly [ConverterFlagsToken, ...ConverterRuleToken[]];
18
8
  abstract get lastChild(): ConverterFlagsToken | ConverterRuleToken;
19
9
  /**
20
10
  * @param flags 转换类型标记
@@ -8,9 +8,8 @@ import type { ConverterToken, ConverterRuleToken } from '../internal';
8
8
  * @classdesc `{childNodes: ...AtomToken}`
9
9
  */
10
10
  export declare class ConverterFlagsToken extends Token {
11
- #private;
12
11
  readonly type = "converter-flags";
13
- readonly childNodes: AtomToken[];
12
+ readonly childNodes: readonly AtomToken[];
14
13
  abstract get firstChild(): AtomToken | undefined;
15
14
  abstract get lastChild(): AtomToken | undefined;
16
15
  abstract get parentNode(): ConverterToken | undefined;
@@ -8,7 +8,7 @@ import type { ConverterToken, ConverterFlagsToken } from '../internal';
8
8
  */
9
9
  export declare class ConverterRuleToken extends Token {
10
10
  readonly type = "converter-rule";
11
- readonly childNodes: [AtomToken] | [AtomToken, AtomToken] | [AtomToken, AtomToken, AtomToken];
11
+ readonly childNodes: readonly [AtomToken] | readonly [AtomToken, AtomToken] | readonly [AtomToken, AtomToken, AtomToken];
12
12
  abstract get firstChild(): AtomToken;
13
13
  abstract get lastChild(): AtomToken;
14
14
  abstract get parentNode(): ConverterToken | undefined;
@@ -1,20 +1,9 @@
1
1
  import * as Parser from '../index';
2
2
  import { Token } from './index';
3
3
  import { MagicLinkToken } from './magicLink';
4
- declare const ExtLinkToken_base: (abstract new (...args: any[]) => {
5
- readonly firstChild: Parser.MagicLinkToken;
6
- toString(omit?: Set<string> | undefined, separator?: string | undefined): string;
7
- text(separator?: string | undefined): string;
8
- lint(start?: number | undefined): Parser.LintError[];
9
- }) & typeof Parser.Token;
10
- /**
11
- * 外链
12
- * @classdesc `{childNodes: [MagicLinkToken, ?Token]}`
13
- */
14
- export declare class ExtLinkToken extends ExtLinkToken_base {
15
- #private;
4
+ export declare class ExtLinkToken extends Token {
16
5
  readonly type = "ext-link";
17
- readonly childNodes: [MagicLinkToken] | [MagicLinkToken, Token];
6
+ readonly childNodes: readonly [MagicLinkToken] | readonly [MagicLinkToken, Token];
18
7
  abstract get lastChild(): Token;
19
8
  /**
20
9
  * @param url 网址
@@ -9,10 +9,9 @@ import type { AstText, AttributesToken, ExtToken } from '../internal';
9
9
  * @classdesc `{childNodes: ...(GalleryImageToken|NoincludeToken|AstText)}`
10
10
  */
11
11
  export declare class GalleryToken extends Token {
12
- #private;
13
12
  readonly type = "ext-inner";
14
13
  readonly name: 'gallery';
15
- readonly childNodes: (GalleryImageToken | NoincludeToken | AstText)[];
14
+ readonly childNodes: readonly (GalleryImageToken | NoincludeToken | AstText)[];
16
15
  abstract get firstChild(): GalleryImageToken | NoincludeToken | AstText | undefined;
17
16
  abstract get lastChild(): GalleryImageToken | NoincludeToken | AstText | undefined;
18
17
  abstract get nextSibling(): undefined;
@@ -7,9 +7,8 @@ import type { LintError } from '../base';
7
7
  * @classdesc `{childNodes: [Token, SyntaxToken]}`
8
8
  */
9
9
  export declare class HeadingToken extends Token {
10
- #private;
11
10
  readonly type = "heading";
12
- readonly childNodes: [Token, SyntaxToken];
11
+ readonly childNodes: readonly [Token, SyntaxToken];
13
12
  abstract get firstChild(): Token;
14
13
  abstract get lastChild(): SyntaxToken;
15
14
  /** 标题层级 */
@@ -55,18 +55,27 @@ class HeadingToken extends index_1.Token {
55
55
  }
56
56
  /** @override */
57
57
  lint(start = this.getAbsoluteIndex()) {
58
- const errors = super.lint(start), { firstChild } = this, innerStr = String(firstChild);
59
- let refError;
58
+ const errors = super.lint(start), { firstChild, level } = this, innerStr = String(firstChild), quotes = firstChild.childNodes.filter((node) => node.type === 'quote'), boldQuotes = quotes.filter(({ bold }) => bold), italicQuotes = quotes.filter(({ italic }) => italic);
59
+ let rect;
60
60
  if (this.level === 1) {
61
- refError = (0, lint_1.generateForChild)(firstChild, { start }, '<h1>');
62
- errors.push(refError);
61
+ rect = { start, ...this.getRootNode().posFromIndex(start) };
62
+ errors.push((0, lint_1.generateForChild)(firstChild, rect, '<h1>'));
63
63
  }
64
64
  if (innerStr.startsWith('=') || innerStr.endsWith('=')) {
65
- refError ??= (0, lint_1.generateForChild)(firstChild, { start }, '');
66
- errors.push({ ...refError, message: Parser.msg('unbalanced "=" in a section header') });
65
+ rect ??= { start, ...this.getRootNode().posFromIndex(start) };
66
+ errors.push((0, lint_1.generateForChild)(firstChild, rect, Parser.msg('unbalanced $1 in a section header', '"="')));
67
67
  }
68
68
  if (this.closest('html-attrs, table-attrs')) {
69
- errors.push({ ...(0, lint_1.generateForSelf)(this, { start }, ''), message: Parser.msg('section header in a HTML tag') });
69
+ rect ??= { start, ...this.getRootNode().posFromIndex(start) };
70
+ errors.push((0, lint_1.generateForSelf)(this, rect, 'section header in a HTML tag'));
71
+ }
72
+ if (boldQuotes.length % 2) {
73
+ rect ??= { start, ...this.getRootNode().posFromIndex(start) };
74
+ errors.push((0, lint_1.generateForChild)(boldQuotes[boldQuotes.length - 1], { ...rect, start: start + level, left: rect.left + level }, Parser.msg('unbalanced $1 in a section header', 'bold apostrophes')));
75
+ }
76
+ if (italicQuotes.length % 2) {
77
+ rect ??= { start, ...this.getRootNode().posFromIndex(start) };
78
+ errors.push((0, lint_1.generateForChild)(italicQuotes[italicQuotes.length - 1], { start: start + level }, Parser.msg('unbalanced $1 in a section header', 'italic apostrophes')));
70
79
  }
71
80
  return errors;
72
81
  }
@@ -1,13 +1,7 @@
1
1
  import { Token } from './index';
2
- declare const HiddenToken_base: ((abstract new (...args: any[]) => {
2
+ export declare class HiddenToken extends Token {
3
3
  text(): string;
4
4
  lint(): import("..").LintError[];
5
- toString(omit?: Set<string> | undefined, separator?: string | undefined): string;
6
- }) & {
7
- readonly hidden: true;
8
- }) & typeof Token;
9
- /** 不可见的节点 */
10
- export declare class HiddenToken extends HiddenToken_base {
11
5
  readonly type = "hidden";
12
6
  }
13
7
  export {};
@@ -4,7 +4,7 @@ exports.HiddenToken = void 0;
4
4
  const hidden_1 = require("../mixin/hidden");
5
5
  const index_1 = require("./index");
6
6
  /** 不可见的节点 */
7
- class HiddenToken extends (0, hidden_1.hidden)(index_1.Token) {
7
+ class HiddenToken extends (0, hidden_1.hiddenToken)(index_1.Token) {
8
8
  type = 'hidden';
9
9
  }
10
10
  exports.HiddenToken = HiddenToken;
@@ -7,10 +7,9 @@ import type { AttributesToken } from '../internal';
7
7
  * @classdesc `{childNodes: [AttributesToken]}`
8
8
  */
9
9
  export declare class HtmlToken extends Token {
10
- #private;
11
10
  readonly type = "html";
12
11
  readonly name: string;
13
- readonly childNodes: [AttributesToken];
12
+ readonly childNodes: readonly [AttributesToken];
14
13
  abstract get firstChild(): AttributesToken;
15
14
  abstract get lastChild(): AttributesToken;
16
15
  /** 是否是闭合标签 */
package/dist/src/html.js CHANGED
@@ -5,7 +5,33 @@ const lint_1 = require("../util/lint");
5
5
  const string_1 = require("../util/string");
6
6
  const Parser = require("../index");
7
7
  const index_1 = require("./index");
8
- const magicWords = new Set(['if', 'ifeq', 'ifexpr', 'ifexist', 'iferror', 'switch']);
8
+ const magicWords = new Set(['if', 'ifeq', 'ifexpr', 'ifexist', 'iferror', 'switch']), formattingTags = new Set([
9
+ 'b',
10
+ 'big',
11
+ 'center',
12
+ 'cite',
13
+ 'code',
14
+ 'del',
15
+ 'dfn',
16
+ 'em',
17
+ 'font',
18
+ 'i',
19
+ 'ins',
20
+ 'kbd',
21
+ 'mark',
22
+ 'pre',
23
+ 'q',
24
+ 's',
25
+ 'samp',
26
+ 'small',
27
+ 'strike',
28
+ 'strong',
29
+ 'sub',
30
+ 'sup',
31
+ 'tt',
32
+ 'u',
33
+ 'var',
34
+ ]), obsoleteTags = new Set(['strike', 'big', 'center', 'font', 'tt']);
9
35
  /**
10
36
  * HTML标签
11
37
  * @classdesc `{childNodes: [AttributesToken]}`
@@ -74,8 +100,16 @@ class HtmlToken extends index_1.Token {
74
100
  const { message: errorMsg } = e;
75
101
  refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
76
102
  const [msg] = errorMsg.split(':'), error = { ...refError, message: Parser.msg(msg) };
77
- if (msg === 'unclosed tag') {
78
- error.severity = 'warning';
103
+ if (msg === 'unclosed tag' && !this.closest('heading-title')) {
104
+ if (formattingTags.has(this.name)) {
105
+ const childNodes = this.parentNode?.childNodes, i = childNodes?.indexOf(this);
106
+ if (!childNodes?.slice(0, i).some(({ type, name }) => type === 'html' && name === this.name)) {
107
+ error.severity = 'warning';
108
+ }
109
+ }
110
+ else {
111
+ error.severity = 'warning';
112
+ }
79
113
  }
80
114
  else if (msg === 'unmatched closing tag') {
81
115
  const ancestor = this.closest('magic-word');
@@ -86,6 +120,22 @@ class HtmlToken extends index_1.Token {
86
120
  errors.push(error);
87
121
  }
88
122
  }
123
+ if (obsoleteTags.has(this.name)) {
124
+ refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
125
+ errors.push({
126
+ ...refError,
127
+ message: Parser.msg('obsolete HTML tag'),
128
+ severity: 'warning',
129
+ });
130
+ }
131
+ if ((this.name === 'b' || this.name === 'strong') && this.closest('heading-title')) {
132
+ refError ??= (0, lint_1.generateForSelf)(this, { start }, '');
133
+ errors.push({
134
+ ...refError,
135
+ message: Parser.msg('bold in section header'),
136
+ severity: 'warning',
137
+ });
138
+ }
89
139
  return errors;
90
140
  }
91
141
  /**
@@ -6,7 +6,6 @@ import type { AtomToken, FileToken } from '../internal';
6
6
  export declare const galleryParams: Set<string>;
7
7
  /** 图片参数 */
8
8
  export declare class ImageParameterToken extends Token {
9
- #private;
10
9
  readonly type = "image-parameter";
11
10
  readonly name: string;
12
11
  abstract get parentNode(): FileToken | undefined;
@@ -20,4 +19,6 @@ export declare class ImageParameterToken extends Token {
20
19
  text(): string;
21
20
  /** @override */
22
21
  lint(start?: number): LintError[];
22
+ /** 获取参数值 */
23
+ getValue(): string | true;
23
24
  }
@@ -111,5 +111,13 @@ class ImageParameterToken extends index_1.Token {
111
111
  }
112
112
  return errors;
113
113
  }
114
+ /** 是否是不可变参数 */
115
+ #isVoid() {
116
+ return this.#syntax && !this.#syntax.includes('$1');
117
+ }
118
+ /** 获取参数值 */
119
+ getValue() {
120
+ return this.name === 'invalid' ? this.text() : this.#isVoid() || super.text();
121
+ }
114
122
  }
115
123
  exports.ImageParameterToken = ImageParameterToken;
@@ -12,7 +12,7 @@ import type { AstText, AttributesToken, ExtToken } from '../internal';
12
12
  export declare class ImagemapToken extends Token {
13
13
  readonly type = "ext-inner";
14
14
  readonly name: 'imagemap';
15
- readonly childNodes: (GalleryImageToken | NoincludeToken | ImagemapLinkToken | AstText)[];
15
+ readonly childNodes: readonly (GalleryImageToken | NoincludeToken | ImagemapLinkToken | AstText)[];
16
16
  abstract get firstChild(): NoincludeToken | GalleryImageToken | undefined;
17
17
  abstract get lastChild(): GalleryImageToken | NoincludeToken | ImagemapLinkToken | AstText | undefined;
18
18
  abstract get nextSibling(): undefined;
@@ -10,7 +10,7 @@ import type { AstText, ImagemapToken } from '../internal';
10
10
  */
11
11
  export declare class ImagemapLinkToken extends Token {
12
12
  readonly type = "imagemap-link";
13
- readonly childNodes: [AstText, LinkToken | ExtLinkToken, NoincludeToken];
13
+ readonly childNodes: readonly [AstText, LinkToken | ExtLinkToken, NoincludeToken];
14
14
  abstract get firstChild(): AstText;
15
15
  abstract get lastChild(): NoincludeToken;
16
16
  abstract get parentNode(): ImagemapToken | undefined;
@@ -10,7 +10,6 @@ import type { TokenTypes } from '../util/constants';
10
10
  * @classdesc `{childNodes: ...(AstText|Token)}`
11
11
  */
12
12
  export declare class Token extends AstElement {
13
- #private;
14
13
  type: TokenTypes;
15
14
  /** @class */
16
15
  constructor(wikitext?: string, config?: Parser.Config, accum?: Token[], acceptable?: Acceptable);
@@ -8,9 +8,8 @@ import type { Title } from '../../lib/title';
8
8
  * @classdesc `{childNodes: [AtomToken, ...Token]}`
9
9
  */
10
10
  export declare abstract class LinkBaseToken extends Token {
11
- #private;
12
11
  type: 'link' | 'category' | 'file' | 'gallery-image' | 'imagemap-image';
13
- readonly childNodes: [AtomToken, ...Token[]];
12
+ readonly childNodes: readonly [AtomToken, ...Token[]];
14
13
  abstract get firstChild(): AtomToken;
15
14
  abstract get lastChild(): Token;
16
15
  /**
@@ -76,7 +76,7 @@ class LinkBaseToken extends index_1.Token {
76
76
  lint(start = this.getAbsoluteIndex()) {
77
77
  const errors = super.lint(start), { childNodes: [target, linkText], type: linkType } = this, { encoded, fragment } = this.#title;
78
78
  let rect;
79
- if (linkType === 'link' && target.childNodes.some(({ type }) => type === 'template')) {
79
+ if (target.childNodes.some(({ type }) => type === 'template')) {
80
80
  rect = { start, ...this.getRootNode().posFromIndex(start) };
81
81
  errors.push((0, lint_1.generateForChild)(target, rect, 'template in an internal link target', 'warning'));
82
82
  }
@@ -84,7 +84,7 @@ class LinkBaseToken extends index_1.Token {
84
84
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
85
85
  errors.push((0, lint_1.generateForChild)(target, rect, 'unnecessary URL encoding in an internal link'));
86
86
  }
87
- if (linkType === 'link' && linkText?.childNodes.some(({ type, data }) => type === 'text' && data.includes('|'))) {
87
+ if ((linkType === 'link' || linkType === 'category') && linkText?.childNodes.some(({ type, data }) => type === 'text' && data.includes('|'))) {
88
88
  rect ??= { start, ...this.getRootNode().posFromIndex(start) };
89
89
  errors.push((0, lint_1.generateForChild)(linkText, rect, 'additional "|" in the link text', 'warning'));
90
90
  }