@markuplint/rules 1.10.2 → 2.0.0-alpha.0.23

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 (57) hide show
  1. package/README.md +21 -20
  2. package/lib/attr-check.d.ts +16 -0
  3. package/lib/attr-check.js +498 -0
  4. package/lib/attr-duplication/index.d.ts +1 -1
  5. package/lib/attr-duplication/index.js +5 -8
  6. package/lib/attr-equal-space-after/index.d.ts +1 -1
  7. package/lib/attr-equal-space-after/index.js +8 -11
  8. package/lib/attr-equal-space-before/index.d.ts +1 -1
  9. package/lib/attr-equal-space-before/index.js +8 -11
  10. package/lib/attr-spacing/index.d.ts +3 -3
  11. package/lib/attr-spacing/index.js +19 -21
  12. package/lib/attr-value-quotes/index.d.ts +1 -1
  13. package/lib/attr-value-quotes/index.js +9 -12
  14. package/lib/case-sensitive-attr-name/index.d.ts +1 -1
  15. package/lib/case-sensitive-attr-name/index.js +11 -14
  16. package/lib/case-sensitive-tag-name/index.d.ts +1 -1
  17. package/lib/case-sensitive-tag-name/index.js +8 -11
  18. package/lib/character-reference/index.d.ts +1 -1
  19. package/lib/character-reference/index.js +15 -11
  20. package/lib/class-naming/index.d.ts +1 -1
  21. package/lib/class-naming/index.js +7 -10
  22. package/lib/deprecated-attr/index.d.ts +1 -1
  23. package/lib/deprecated-attr/index.js +6 -9
  24. package/lib/deprecated-element/index.d.ts +1 -1
  25. package/lib/deprecated-element/index.js +10 -15
  26. package/lib/doctype/index.d.ts +1 -1
  27. package/lib/doctype/index.js +16 -25
  28. package/lib/helpers.d.ts +12 -11
  29. package/lib/helpers.js +38 -25
  30. package/lib/id-duplication/index.d.ts +1 -1
  31. package/lib/id-duplication/index.js +5 -8
  32. package/lib/indentation/index.d.ts +3 -3
  33. package/lib/indentation/index.js +81 -116
  34. package/lib/index.d.ts +45 -24
  35. package/lib/index.js +42 -42
  36. package/lib/invalid-attr/index.d.ts +2 -2
  37. package/lib/invalid-attr/index.js +23 -25
  38. package/lib/landmark-roles/index.d.ts +3 -3
  39. package/lib/landmark-roles/index.js +12 -20
  40. package/lib/permitted-contents/index.d.ts +2 -2
  41. package/lib/permitted-contents/index.js +63 -45
  42. package/lib/permitted-contents/permitted-content.spec-to-regexp.d.ts +2 -2
  43. package/lib/permitted-contents/permitted-content.spec-to-regexp.js +49 -30
  44. package/lib/permitted-contents/unfold-content-models-to-tags.d.ts +1 -1
  45. package/lib/permitted-contents/unfold-content-models-to-tags.js +2 -3
  46. package/lib/{type-check.d.ts → primitive-check.d.ts} +24 -7
  47. package/lib/primitive-check.js +109 -0
  48. package/lib/required-attr/index.d.ts +1 -1
  49. package/lib/required-attr/index.js +12 -16
  50. package/lib/required-h1/index.d.ts +3 -3
  51. package/lib/required-h1/index.js +8 -13
  52. package/lib/wai-aria/index.d.ts +1 -1
  53. package/lib/wai-aria/index.js +57 -64
  54. package/package.json +6 -6
  55. package/tsconfig.test.json +1 -24
  56. package/tsconfig.tsbuildinfo +1 -1
  57. package/lib/type-check.js +0 -321
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
+ var _TagList_list;
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  const tslib_1 = require("tslib");
4
- const array_combination_1 = tslib_1.__importDefault(require("./array.combination"));
5
5
  const helpers_1 = require("../helpers");
6
- const unfold_content_models_to_tags_1 = tslib_1.__importDefault(require("./unfold-content-models-to-tags"));
6
+ const array_combination_1 = (0, tslib_1.__importDefault)(require("./array.combination"));
7
+ const unfold_content_models_to_tags_1 = (0, tslib_1.__importDefault)(require("./unfold-content-models-to-tags"));
7
8
  const ALL = '(?:<[^>]+>)?';
8
9
  const ___TRANSPARENT___ = '___TRANSPARENT___';
9
10
  const ___InTRANSPARENT = '___InTRANSPARENT';
@@ -13,20 +14,20 @@ class ExpGenerator {
13
14
  this._id = _id;
14
15
  this._idCounter = 0;
15
16
  }
16
- specToRegExp(contentRule, parentExp = null) {
17
+ specToRegExp(contentRule, parentExp = null, ownNS = null) {
17
18
  if (contentRule === true) {
18
- return new RegExp(`^(?:${ALL})$`);
19
+ return new RegExp(`^(?:${ALL})+$`);
19
20
  }
20
21
  if (contentRule === false) {
21
22
  return new RegExp('^$');
22
23
  }
23
24
  const parentPattern = parentExp ? parentExp.source.replace(/^\^|\$$/g, '') : ALL;
24
- const pattern = this._toPattern(contentRule, null, 1, 1).replace(___TRANSPARENT___, () => `(?<TRANSPARENT_${this._id}${this._idCounter++}>${parentPattern})`);
25
+ const pattern = this._toPattern(contentRule, null, ownNS, 1, 1).replace(___TRANSPARENT___, () => `(?<TRANSPARENT_${this._id}${this._idCounter++}>${parentPattern})`);
25
26
  return new RegExp(`^${pattern}$`, 'i');
26
27
  }
27
- _toPattern(contentRule, ignore, min, max) {
28
+ _toPattern(contentRule, ignore, ownNS, min, max) {
28
29
  if (isTarget(contentRule)) {
29
- return this._targetTags(contentRule, ignore, min, max);
30
+ return this._targetTags(contentRule, ignore, ownNS, min, max);
30
31
  }
31
32
  let notAllowedDescendantsNamedCapture = '';
32
33
  const exp = [];
@@ -41,7 +42,7 @@ class ExpGenerator {
41
42
  notAllowedDescendantsNamedCapture += `${___InTRANSPARENT}`;
42
43
  }
43
44
  }
44
- pattern = this._targetTags(nodeRule.require, nodeRule.ignore || null, nodeRule.min || 1, nodeRule.max || nodeRule.min || 1);
45
+ pattern = this._targetTags(nodeRule.require, nodeRule.ignore || null, ownNS, nodeRule.min || 1, nodeRule.max || nodeRule.min || 1);
45
46
  }
46
47
  else if (isOptionalContents(nodeRule)) {
47
48
  if (nodeRule.notAllowedDescendants) {
@@ -52,7 +53,7 @@ class ExpGenerator {
52
53
  notAllowedDescendantsNamedCapture += `${___InTRANSPARENT}`;
53
54
  }
54
55
  }
55
- pattern = this._targetTags(nodeRule.optional, nodeRule.ignore || null, 0, nodeRule.max || 1);
56
+ pattern = this._targetTags(nodeRule.optional, nodeRule.ignore || null, ownNS, 0, nodeRule.max || 1);
56
57
  }
57
58
  else if (isOneOrMoreContents(nodeRule)) {
58
59
  if (nodeRule.notAllowedDescendants) {
@@ -63,7 +64,7 @@ class ExpGenerator {
63
64
  notAllowedDescendantsNamedCapture += `${___InTRANSPARENT}`;
64
65
  }
65
66
  }
66
- pattern = this._toPattern(nodeRule.oneOrMore, nodeRule.ignore || null, 1, nodeRule.max || Infinity);
67
+ pattern = this._toPattern(nodeRule.oneOrMore, nodeRule.ignore || null, ownNS, 1, nodeRule.max || Infinity);
67
68
  }
68
69
  else if (isZeroOrMoreContents(nodeRule)) {
69
70
  if (nodeRule.notAllowedDescendants) {
@@ -74,13 +75,13 @@ class ExpGenerator {
74
75
  notAllowedDescendantsNamedCapture += `${___InTRANSPARENT}`;
75
76
  }
76
77
  }
77
- pattern = this._toPattern(nodeRule.zeroOrMore, nodeRule.ignore || null, 0, nodeRule.max || Infinity);
78
+ pattern = this._toPattern(nodeRule.zeroOrMore, nodeRule.ignore || null, ownNS, 0, nodeRule.max || Infinity);
78
79
  }
79
80
  else if (isChoiceContents(nodeRule)) {
80
- pattern = `(?:${nodeRule.choice.map(choice => this._toPattern(choice, null, 1, 1)).join('|')})`;
81
+ pattern = `(?:${nodeRule.choice.map(choice => this._toPattern(choice, null, ownNS, 1, 1)).join('|')})`;
81
82
  }
82
83
  else if (isInterleaveContents(nodeRule)) {
83
- pattern = this._interleavePattern(nodeRule.interleave);
84
+ pattern = this._interleavePattern(nodeRule.interleave, ownNS);
84
85
  }
85
86
  exp.push(pattern);
86
87
  }
@@ -102,60 +103,78 @@ class ExpGenerator {
102
103
  }
103
104
  return `(${c}${exp.join('')})${range}`;
104
105
  }
105
- _interleavePattern(contents) {
106
- const interleave = contents.map(content => this._toPattern(content, null, 1, 1));
107
- const patterns = array_combination_1.default(interleave).map((pattern, i) => pattern.join('').replace(/(\(\?<[A-Z]+_)([0-9]+)_/g, ($0, $1, $2) => `${$1}${$2}${i}_`));
106
+ _interleavePattern(contents, ownNS) {
107
+ const interleave = contents.map(content => this._toPattern(content, null, ownNS, 1, 1));
108
+ const patterns = (0, array_combination_1.default)(interleave).map((pattern, i) => pattern.join('').replace(/(\(\?<[A-Z]+_)([0-9]+)_/g, ($0, $1, $2) => `${$1}${$2}${i}_`));
108
109
  return join(patterns);
109
110
  }
110
- _targetTags(target, ignore, min, max) {
111
- const tagList = this._resolveTags(target);
112
- const ignoreList = ignore ? this._resolveTags(ignore) : null;
111
+ _targetTags(target, ignore, ownNS, min, max) {
112
+ const tagList = this._resolveTags(target, ownNS);
113
+ const ignoreList = ignore ? this._resolveTags(ignore, ownNS) : null;
113
114
  if (ignoreList) {
114
115
  ignoreList.forEach(ignore => tagList.delete(ignore));
115
116
  }
116
117
  return join(Array.from(tagList), createRange(min, max));
117
118
  }
118
- _resolveTags(target) {
119
+ _resolveTags(target, ownNS) {
119
120
  const list = Array.isArray(target) ? target : [target];
120
- const tagList = new Set();
121
+ const tagList = new TagList();
121
122
  for (const name of list) {
122
123
  if (name !== '#text' && name[0] === '#') {
123
124
  switch (name) {
124
125
  case '#transparent': {
125
- tagList.add(___TRANSPARENT___);
126
+ tagList.addPattern(___TRANSPARENT___);
126
127
  break;
127
128
  }
128
129
  case '#custom': {
129
- tagList.add(CUSTOM_ELEMENT);
130
+ tagList.addPattern(CUSTOM_ELEMENT);
130
131
  break;
131
132
  }
132
133
  default: {
133
- const selectors = unfold_content_models_to_tags_1.default(name);
134
+ const selectors = (0, unfold_content_models_to_tags_1.default)(name);
134
135
  const counter = this._idCounter++;
135
136
  selectors.forEach(selector => {
136
137
  if (selector === '#custom') {
137
- tagList.add(CUSTOM_ELEMENT);
138
+ tagList.addPattern(CUSTOM_ELEMENT);
138
139
  return;
139
140
  }
140
141
  if (/]$/i.test(selector)) {
141
142
  const [, tagName] = /^([^[\]]+)\[[^\]]+\]$/.exec(selector) || [];
142
- // ACM = Attributes by comtent model
143
+ // ACM = Attributes by content model
143
144
  const exp = `(?<ACM_${this._id}${counter}_${name.slice(1)}_${tagName}><${tagName}>)`;
144
- tagList.add(exp);
145
+ tagList.addPattern(exp);
145
146
  return;
146
147
  }
147
- tagList.add(`<${selector}>`);
148
+ tagList.addTag(selector, ownNS);
148
149
  });
149
150
  }
150
151
  }
151
152
  continue;
152
153
  }
153
- tagList.add(`<${name}>`);
154
+ tagList.addTag(name, ownNS);
154
155
  }
155
- return tagList;
156
+ return tagList.result();
156
157
  }
157
158
  }
158
159
  exports.default = ExpGenerator;
160
+ class TagList {
161
+ constructor() {
162
+ _TagList_list.set(this, new Set());
163
+ }
164
+ addPattern(pattern) {
165
+ (0, tslib_1.__classPrivateFieldGet)(this, _TagList_list, "f").add(pattern);
166
+ }
167
+ addTag(tagNameOrSelector, ownNS) {
168
+ if (ownNS) {
169
+ tagNameOrSelector = tagNameOrSelector.replace(new RegExp(`^${ownNS}:`, 'i'), '');
170
+ }
171
+ (0, tslib_1.__classPrivateFieldGet)(this, _TagList_list, "f").add(`<${tagNameOrSelector}>`);
172
+ }
173
+ result() {
174
+ return (0, tslib_1.__classPrivateFieldGet)(this, _TagList_list, "f");
175
+ }
176
+ }
177
+ _TagList_list = new WeakMap();
159
178
  function isRequiredContents(contents) {
160
179
  return 'require' in contents;
161
180
  }
@@ -1,2 +1,2 @@
1
- import { ContentModel } from '@markuplint/ml-spec';
1
+ import type { ContentModel } from '@markuplint/ml-spec';
2
2
  export default function unfoldContentModelsToTags(contentModel: ContentModel): string[];
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- const html_spec_1 = tslib_1.__importDefault(require("@markuplint/html-spec"));
3
+ const html_spec_1 = require("@markuplint/html-spec");
5
4
  function unfoldContentModelsToTags(contentModel) {
6
- const tags = html_spec_1.default.def['#contentModels'][contentModel];
5
+ const tags = html_spec_1.def['#contentModels'][contentModel];
7
6
  return tags && Array.isArray(tags) ? tags.sort() : [];
8
7
  }
9
8
  exports.default = unfoldContentModelsToTags;
@@ -1,9 +1,3 @@
1
- import { Attribute as AttrSpec } from '@markuplint/ml-spec';
2
- declare type Invalid = {
3
- invalidType: 'non-existent' | 'invalid-value';
4
- message: string;
5
- };
6
- export declare function typeCheck(name: string, value: string, isCustomRule: boolean, spec?: AttrSpec): Invalid | false;
7
1
  /**
8
2
  * @see https://html.spec.whatwg.org/dev/common-microsyntaxes.html#signed-integers
9
3
  *
@@ -28,4 +22,27 @@ export declare function floatCheck(value: string): boolean;
28
22
  * @param value
29
23
  */
30
24
  export declare function nonZeroUintCheck(value: string): boolean;
31
- export {};
25
+ /**
26
+ * It is in the range between `from` and `to`.
27
+ *
28
+ * @param value
29
+ * @param from
30
+ * @param to
31
+ */
32
+ export declare function range(value: string, from: number, to: number): boolean;
33
+ /**
34
+ *
35
+ * @param value
36
+ * @returns
37
+ */
38
+ export declare function splitUnit(value: string): {
39
+ num: string;
40
+ unit: string;
41
+ };
42
+ /**
43
+ *
44
+ * @param value
45
+ * @param units
46
+ * @param numberType
47
+ */
48
+ export declare function numberCheckWithUnit(value: string, units: string[], numberType?: 'int' | 'uint' | 'float'): boolean;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.numberCheckWithUnit = exports.splitUnit = exports.range = exports.nonZeroUintCheck = exports.floatCheck = exports.uintCheck = exports.intCheck = void 0;
4
+ /**
5
+ * @see https://html.spec.whatwg.org/dev/common-microsyntaxes.html#signed-integers
6
+ *
7
+ * @param value
8
+ */
9
+ function intCheck(value) {
10
+ return /^-?[0-9]+$/.test(value);
11
+ }
12
+ exports.intCheck = intCheck;
13
+ /**
14
+ * @see https://html.spec.whatwg.org/dev/common-microsyntaxes.html#non-negative-integers
15
+ *
16
+ * @param value
17
+ */
18
+ function uintCheck(value) {
19
+ return /^[0-9]+$/.test(value);
20
+ }
21
+ exports.uintCheck = uintCheck;
22
+ /**
23
+ * @see https://html.spec.whatwg.org/dev/common-microsyntaxes.html#floating-point-numbers
24
+ *
25
+ * @param value
26
+ */
27
+ function floatCheck(value) {
28
+ return value === value.trim() && Number.isFinite(parseFloat(value));
29
+ }
30
+ exports.floatCheck = floatCheck;
31
+ /**
32
+ * Non-negative integer greater than zero
33
+ *
34
+ * @param value
35
+ */
36
+ function nonZeroUintCheck(value) {
37
+ return /^[0-9]+$/.test(value) && !/^0+$/.test(value);
38
+ }
39
+ exports.nonZeroUintCheck = nonZeroUintCheck;
40
+ /**
41
+ * It is in the range between `from` and `to`.
42
+ *
43
+ * @param value
44
+ * @param from
45
+ * @param to
46
+ */
47
+ function range(value, from, to) {
48
+ const num = parseFloat(value);
49
+ if (isNaN(num)) {
50
+ return false;
51
+ }
52
+ return from <= num && num <= to;
53
+ }
54
+ exports.range = range;
55
+ /**
56
+ *
57
+ * @param value
58
+ * @returns
59
+ */
60
+ function splitUnit(value) {
61
+ value = value.trim().toLowerCase();
62
+ const matched = value.match(/(^-?\.[0-9]+|^-?[0-9]+(?:\.[0-9]+(?:e[+-][0-9]+)?)?)([a-z]+$)/i);
63
+ if (!matched) {
64
+ return {
65
+ num: value,
66
+ unit: '',
67
+ };
68
+ }
69
+ const [, num, unit] = matched;
70
+ return {
71
+ num,
72
+ unit,
73
+ };
74
+ }
75
+ exports.splitUnit = splitUnit;
76
+ /**
77
+ *
78
+ * @param value
79
+ * @param units
80
+ * @param numberType
81
+ */
82
+ function numberCheckWithUnit(value, units, numberType = 'float') {
83
+ const { num, unit } = splitUnit(value);
84
+ if (!units.includes(unit.toLowerCase())) {
85
+ return false;
86
+ }
87
+ switch (numberType) {
88
+ case 'int': {
89
+ if (!intCheck(num)) {
90
+ return false;
91
+ }
92
+ break;
93
+ }
94
+ case 'uint': {
95
+ if (!uintCheck(num)) {
96
+ return false;
97
+ }
98
+ break;
99
+ }
100
+ case 'float': {
101
+ if (!floatCheck(num)) {
102
+ return false;
103
+ }
104
+ break;
105
+ }
106
+ }
107
+ return true;
108
+ }
109
+ exports.numberCheckWithUnit = numberCheckWithUnit;
@@ -1,3 +1,3 @@
1
1
  declare type RequiredAttributes = string | string[];
2
- declare const _default: import("@markuplint/ml-core").MLRule<RequiredAttributes, null>;
2
+ declare const _default: import("@markuplint/ml-core").RuleSeed<RequiredAttributes, null>;
3
3
  export default _default;
@@ -2,24 +2,24 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ml_core_1 = require("@markuplint/ml-core");
4
4
  const helpers_1 = require("../helpers");
5
- exports.default = ml_core_1.createRule({
6
- name: 'required-attr',
7
- defaultLevel: 'error',
5
+ exports.default = (0, ml_core_1.createRule)({
8
6
  defaultValue: [],
9
7
  defaultOptions: null,
10
- async verify(document, translate) {
11
- const reports = [];
8
+ async verify({ document, report, t }) {
12
9
  await document.walkOn('Element', async (node) => {
13
10
  if (node.hasSpreadAttr) {
14
11
  return;
15
12
  }
16
13
  const customRequiredAttrs = typeof node.rule.value === 'string' ? [node.rule.value] : node.rule.value;
17
- const attrSpec = helpers_1.getAttrSpecs(node.nodeName, document.specs);
14
+ const attrSpec = (0, helpers_1.getAttrSpecs)(node.nameWithNS, document.specs);
18
15
  const attributeSpecs = attrSpec
19
16
  ? attrSpec.map(attr => {
20
17
  const required = customRequiredAttrs.includes(attr.name);
21
18
  if (required) {
22
- return Object.assign(Object.assign({}, attr), { required: true });
19
+ return {
20
+ ...attr,
21
+ required: true,
22
+ };
23
23
  }
24
24
  return attr;
25
25
  })
@@ -37,26 +37,22 @@ exports.default = ml_core_1.createRule({
37
37
  invalid = !candidate.some(attrName => node.hasAttribute(attrName));
38
38
  }
39
39
  else if (spec.required === true) {
40
- invalid = helpers_1.attrMatches(node, spec.condition) && didntHave;
40
+ invalid = (0, helpers_1.attrMatches)(node, spec.condition) && didntHave;
41
41
  }
42
42
  else if (spec.required) {
43
- if (spec.required.ancestor) {
43
+ if ('ancestor' in spec.required && spec.required.ancestor) {
44
44
  const ancestors = spec.required.ancestor.split(',').map(a => a.trim());
45
45
  invalid = ancestors.some(a => node.closest(a)) && didntHave;
46
46
  }
47
47
  }
48
48
  if (invalid) {
49
- const message = translate('Required {0} on {1}', `'${spec.name}'`, `'<${node.nodeName}>'`);
50
- reports.push({
51
- severity: node.rule.severity,
49
+ const message = t('{0} expects {1}', t('the "{0}" {1}', spec.name, 'attribute'), t('the "{0}" {1}', node.nodeName, 'element'));
50
+ report({
51
+ scope: node,
52
52
  message,
53
- line: node.startLine,
54
- col: node.startCol,
55
- raw: node.raw,
56
53
  });
57
54
  }
58
55
  }
59
56
  });
60
- return reports;
61
57
  },
62
58
  });
@@ -1,7 +1,7 @@
1
1
  export declare type Value = boolean;
2
2
  export interface RequiredH1Options {
3
- 'expected-once': boolean;
4
- 'in-document-fragment': boolean;
3
+ 'expected-once'?: boolean;
4
+ 'in-document-fragment'?: boolean;
5
5
  }
6
- declare const _default: import("@markuplint/ml-core").MLRule<boolean, RequiredH1Options>;
6
+ declare const _default: import("@markuplint/ml-core").RuleSeed<boolean, RequiredH1Options>;
7
7
  export default _default;
@@ -1,21 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const ml_core_1 = require("@markuplint/ml-core");
4
- exports.default = ml_core_1.createRule({
5
- name: 'required-h1',
4
+ exports.default = (0, ml_core_1.createRule)({
6
5
  defaultValue: true,
7
6
  defaultOptions: {
8
7
  'expected-once': true,
9
8
  'in-document-fragment': false,
10
9
  },
11
- async verify(document, translate, globalRule) {
12
- const reports = [];
10
+ async verify({ document, report, globalRule, t }) {
13
11
  const h1Stack = [];
14
12
  if (document.nodeList.length === 0) {
15
- return reports;
13
+ return;
16
14
  }
17
15
  if (!globalRule.option['in-document-fragment'] && document.isFragment) {
18
- return reports;
16
+ return;
19
17
  }
20
18
  await document.walkOn('Element', async (node) => {
21
19
  if (node.nodeName.toLowerCase() === 'h1') {
@@ -23,9 +21,8 @@ exports.default = ml_core_1.createRule({
23
21
  }
24
22
  });
25
23
  if (h1Stack.length === 0) {
26
- const message = translate('Missing the {0} {1}', 'h1', 'element');
27
- reports.push({
28
- severity: globalRule.severity,
24
+ const message = t('Require {0}', t('the "{0}" {1}', 'h1', 'element'));
25
+ report({
29
26
  message,
30
27
  line: 1,
31
28
  col: 1,
@@ -33,15 +30,13 @@ exports.default = ml_core_1.createRule({
33
30
  });
34
31
  }
35
32
  else if (globalRule.option['expected-once'] && h1Stack.length > 1) {
36
- const message = translate('Duplicate the {0} {1}', 'h1', 'element');
37
- reports.push({
38
- severity: globalRule.severity,
33
+ const message = t('{0} is {1:c}', t('the "{0}" {1}', 'h1', 'element'), 'duplicated');
34
+ report({
39
35
  message,
40
36
  line: h1Stack[1].startLine,
41
37
  col: h1Stack[1].startCol,
42
38
  raw: h1Stack[1].raw,
43
39
  });
44
40
  }
45
- return reports;
46
41
  },
47
42
  });
@@ -6,5 +6,5 @@ declare type Options = {
6
6
  disallowSetImplicitProps?: boolean;
7
7
  disallowDefaultValue?: boolean;
8
8
  };
9
- declare const _default: import("@markuplint/ml-core").MLRule<true, Options>;
9
+ declare const _default: import("@markuplint/ml-core").RuleSeed<true, Options>;
10
10
  export default _default;