@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.
- package/README.md +21 -20
- package/lib/attr-check.d.ts +16 -0
- package/lib/attr-check.js +498 -0
- package/lib/attr-duplication/index.d.ts +1 -1
- package/lib/attr-duplication/index.js +5 -8
- package/lib/attr-equal-space-after/index.d.ts +1 -1
- package/lib/attr-equal-space-after/index.js +8 -11
- package/lib/attr-equal-space-before/index.d.ts +1 -1
- package/lib/attr-equal-space-before/index.js +8 -11
- package/lib/attr-spacing/index.d.ts +3 -3
- package/lib/attr-spacing/index.js +19 -21
- package/lib/attr-value-quotes/index.d.ts +1 -1
- package/lib/attr-value-quotes/index.js +9 -12
- package/lib/case-sensitive-attr-name/index.d.ts +1 -1
- package/lib/case-sensitive-attr-name/index.js +11 -14
- package/lib/case-sensitive-tag-name/index.d.ts +1 -1
- package/lib/case-sensitive-tag-name/index.js +8 -11
- package/lib/character-reference/index.d.ts +1 -1
- package/lib/character-reference/index.js +15 -11
- package/lib/class-naming/index.d.ts +1 -1
- package/lib/class-naming/index.js +7 -10
- package/lib/deprecated-attr/index.d.ts +1 -1
- package/lib/deprecated-attr/index.js +6 -9
- package/lib/deprecated-element/index.d.ts +1 -1
- package/lib/deprecated-element/index.js +10 -15
- package/lib/doctype/index.d.ts +1 -1
- package/lib/doctype/index.js +16 -25
- package/lib/helpers.d.ts +12 -11
- package/lib/helpers.js +38 -25
- package/lib/id-duplication/index.d.ts +1 -1
- package/lib/id-duplication/index.js +5 -8
- package/lib/indentation/index.d.ts +3 -3
- package/lib/indentation/index.js +81 -116
- package/lib/index.d.ts +45 -24
- package/lib/index.js +42 -42
- package/lib/invalid-attr/index.d.ts +2 -2
- package/lib/invalid-attr/index.js +23 -25
- package/lib/landmark-roles/index.d.ts +3 -3
- package/lib/landmark-roles/index.js +12 -20
- package/lib/permitted-contents/index.d.ts +2 -2
- package/lib/permitted-contents/index.js +63 -45
- package/lib/permitted-contents/permitted-content.spec-to-regexp.d.ts +2 -2
- package/lib/permitted-contents/permitted-content.spec-to-regexp.js +49 -30
- package/lib/permitted-contents/unfold-content-models-to-tags.d.ts +1 -1
- package/lib/permitted-contents/unfold-content-models-to-tags.js +2 -3
- package/lib/{type-check.d.ts → primitive-check.d.ts} +24 -7
- package/lib/primitive-check.js +109 -0
- package/lib/required-attr/index.d.ts +1 -1
- package/lib/required-attr/index.js +12 -16
- package/lib/required-h1/index.d.ts +3 -3
- package/lib/required-h1/index.js +8 -13
- package/lib/wai-aria/index.d.ts +1 -1
- package/lib/wai-aria/index.js +57 -64
- package/package.json +6 -6
- package/tsconfig.test.json +1 -24
- package/tsconfig.tsbuildinfo +1 -1
- 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
|
|
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
|
|
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.
|
|
126
|
+
tagList.addPattern(___TRANSPARENT___);
|
|
126
127
|
break;
|
|
127
128
|
}
|
|
128
129
|
case '#custom': {
|
|
129
|
-
tagList.
|
|
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.
|
|
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
|
|
143
|
+
// ACM = Attributes by content model
|
|
143
144
|
const exp = `(?<ACM_${this._id}${counter}_${name.slice(1)}_${tagName}><${tagName}>)`;
|
|
144
|
-
tagList.
|
|
145
|
+
tagList.addPattern(exp);
|
|
145
146
|
return;
|
|
146
147
|
}
|
|
147
|
-
tagList.
|
|
148
|
+
tagList.addTag(selector, ownNS);
|
|
148
149
|
});
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
continue;
|
|
152
153
|
}
|
|
153
|
-
tagList.
|
|
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
|
|
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.
|
|
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
|
-
|
|
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;
|
|
@@ -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,
|
|
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.
|
|
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
|
|
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 =
|
|
50
|
-
|
|
51
|
-
|
|
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'
|
|
4
|
-
'in-document-fragment'
|
|
3
|
+
'expected-once'?: boolean;
|
|
4
|
+
'in-document-fragment'?: boolean;
|
|
5
5
|
}
|
|
6
|
-
declare const _default: import("@markuplint/ml-core").
|
|
6
|
+
declare const _default: import("@markuplint/ml-core").RuleSeed<boolean, RequiredH1Options>;
|
|
7
7
|
export default _default;
|
package/lib/required-h1/index.js
CHANGED
|
@@ -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,
|
|
12
|
-
const reports = [];
|
|
10
|
+
async verify({ document, report, globalRule, t }) {
|
|
13
11
|
const h1Stack = [];
|
|
14
12
|
if (document.nodeList.length === 0) {
|
|
15
|
-
return
|
|
13
|
+
return;
|
|
16
14
|
}
|
|
17
15
|
if (!globalRule.option['in-document-fragment'] && document.isFragment) {
|
|
18
|
-
return
|
|
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 =
|
|
27
|
-
|
|
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 =
|
|
37
|
-
|
|
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
|
});
|
package/lib/wai-aria/index.d.ts
CHANGED
|
@@ -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").
|
|
9
|
+
declare const _default: import("@markuplint/ml-core").RuleSeed<true, Options>;
|
|
10
10
|
export default _default;
|