@markuplint/rules 4.12.0 → 5.0.0-alpha.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.
- package/CHANGELOG.md +58 -0
- package/lib/attr-check.d.ts +5 -2
- package/lib/attr-check.js +13 -3
- package/lib/character-reference/index.d.ts +2 -1
- package/lib/character-reference/index.js +5 -1
- package/lib/correct-aspect-ratio/index.d.ts +5 -0
- package/lib/correct-aspect-ratio/index.js +80 -0
- package/lib/correct-aspect-ratio/meta.d.ts +4 -0
- package/lib/correct-aspect-ratio/meta.js +3 -0
- package/lib/correct-aspect-ratio/resolve-image-size.d.ts +24 -0
- package/lib/correct-aspect-ratio/resolve-image-size.js +165 -0
- package/lib/create-message.d.ts +2 -2
- package/lib/create-message.js +4 -1
- package/lib/deprecated-element/index.d.ts +2 -4
- package/lib/deprecated-element/index.js +4 -6
- package/lib/end-tag/index.js +1 -1
- package/lib/heading-levels/index.js +0 -1
- package/lib/helpers.d.ts +1 -0
- package/lib/helpers.js +8 -15
- package/lib/index.d.ts +30 -41
- package/lib/index.js +12 -0
- package/lib/invalid-attr/index.d.ts +12 -28
- package/lib/invalid-attr/index.js +50 -116
- package/lib/link-types/index.d.ts +10 -0
- package/lib/link-types/index.js +180 -0
- package/lib/link-types/meta.d.ts +5 -0
- package/lib/link-types/meta.js +4 -0
- package/lib/neighbor-popovers/index.js +3 -5
- package/lib/no-orphaned-end-tag/index.d.ts +2 -2
- package/lib/no-orphaned-end-tag/index.js +3 -4
- package/lib/no-refer-to-non-existent-id/index.d.ts +1 -1
- package/lib/no-refer-to-non-existent-id/index.js +2 -2
- package/lib/no-unsupported-features/compat-data.d.ts +71 -0
- package/lib/no-unsupported-features/compat-data.js +204 -0
- package/lib/no-unsupported-features/index.d.ts +24 -0
- package/lib/no-unsupported-features/index.js +139 -0
- package/lib/no-unsupported-features/meta.d.ts +5 -0
- package/lib/no-unsupported-features/meta.js +4 -0
- package/lib/no-unsupported-features/resolve-browsers.d.ts +30 -0
- package/lib/no-unsupported-features/resolve-browsers.js +125 -0
- package/lib/permitted-contents/choice.js +1 -1
- package/lib/permitted-contents/count-pattern.js +1 -1
- package/lib/permitted-contents/order.js +1 -1
- package/lib/permitted-contents/represent-transparent-nodes.d.ts +26 -1
- package/lib/permitted-contents/represent-transparent-nodes.js +96 -13
- package/lib/permitted-contents/utils.d.ts +1 -1
- package/lib/permitted-contents/utils.js +22 -35
- package/lib/redundant-accessible-name/index.d.ts +10 -0
- package/lib/redundant-accessible-name/index.js +123 -0
- package/lib/redundant-accessible-name/meta.d.ts +5 -0
- package/lib/redundant-accessible-name/meta.js +4 -0
- package/lib/require-accessible-name/index.d.ts +3 -8
- package/lib/require-accessible-name/index.js +6 -5
- package/lib/require-dialog-autofocus/index.d.ts +22 -0
- package/lib/require-dialog-autofocus/index.js +62 -0
- package/lib/require-dialog-autofocus/meta.d.ts +5 -0
- package/lib/require-dialog-autofocus/meta.js +4 -0
- package/lib/required-attr/index.d.ts +8 -1
- package/lib/required-attr/index.js +27 -4
- package/lib/required-element/index.js +1 -1
- package/lib/srcset-sizes-constraint/index.d.ts +6 -0
- package/lib/srcset-sizes-constraint/index.js +108 -0
- package/lib/srcset-sizes-constraint/meta.d.ts +5 -0
- package/lib/srcset-sizes-constraint/meta.js +4 -0
- package/lib/srcset-sizes-constraint/parse-srcset.d.ts +40 -0
- package/lib/srcset-sizes-constraint/parse-srcset.js +56 -0
- package/lib/table-row-column-alignment/grid.js +22 -29
- package/lib/wai-aria/checkings/abstract-role.js +5 -2
- package/lib/wai-aria/checkings/disallowed-prop.js +5 -2
- package/lib/wai-aria/checkings/implicit-role.js +5 -2
- package/lib/wai-aria/checkings/non-existent-role.d.ts +1 -0
- package/lib/wai-aria/checkings/non-existent-role.js +9 -2
- package/lib/wai-aria/checkings/permitted-roles.js +5 -2
- package/lib/wai-aria/checkings/presentational-children.js +3 -2
- package/lib/wai-aria/checkings/required-accessibility-parent-role.d.ts +25 -0
- package/lib/wai-aria/checkings/required-accessibility-parent-role.js +56 -0
- package/lib/wai-aria/checkings/required-owned-elements.d.ts +5 -4
- package/lib/wai-aria/checkings/required-owned-elements.js +57 -28
- package/lib/wai-aria/checkings/required-prop.js +5 -2
- package/lib/wai-aria/index.js +12 -4
- package/lib/wai-aria/types.d.ts +9 -2
- package/package.json +15 -10
- package/schema.json +18 -0
package/lib/index.d.ts
CHANGED
|
@@ -17,6 +17,9 @@ declare const rules: {
|
|
|
17
17
|
readonly 'case-sensitive-tag-name': Readonly<import("@markuplint/ml-core").RuleSeed<import("./case-sensitive-tag-name/index.js").Value, undefined>>;
|
|
18
18
|
readonly 'character-reference': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
19
19
|
readonly 'class-naming': Readonly<import("@markuplint/ml-core").RuleSeed<import("./class-naming/index.js").Value, undefined>>;
|
|
20
|
+
readonly 'correct-aspect-ratio': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
|
|
21
|
+
readonly documentRoot?: string;
|
|
22
|
+
}>>;
|
|
20
23
|
readonly 'deprecated-attr': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
21
24
|
readonly 'deprecated-element': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
22
25
|
readonly 'disallowed-element': Readonly<import("@markuplint/ml-core").RuleSeed<string[], undefined>>;
|
|
@@ -30,53 +33,23 @@ declare const rules: {
|
|
|
30
33
|
readonly 'invalid-attr': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
|
|
31
34
|
allowAttrs?: (string | {
|
|
32
35
|
name: string;
|
|
33
|
-
value: import("packages/@markuplint/ml-spec/lib/index.js").AttributeType | (
|
|
34
|
-
|
|
35
|
-
} | {
|
|
36
|
-
pattern: string;
|
|
37
|
-
} | {
|
|
38
|
-
type: import("packages/@markuplint/ml-spec/lib/index.js").AttributeType;
|
|
39
|
-
});
|
|
40
|
-
})[] | Record<string, {
|
|
41
|
-
enum: [string, ...string[]];
|
|
42
|
-
} | {
|
|
43
|
-
pattern: string;
|
|
44
|
-
} | {
|
|
45
|
-
type: import("packages/@markuplint/ml-spec/lib/index.js").AttributeType;
|
|
46
|
-
}>;
|
|
36
|
+
value: import("packages/@markuplint/ml-spec/lib/index.js").AttributeType | import("packages/@markuplint/types/lib/types.schema.js").Pattern;
|
|
37
|
+
})[] | Record<string, import("packages/@markuplint/ml-spec/lib/index.js").AttributeType | import("packages/@markuplint/types/lib/types.schema.js").Pattern>;
|
|
47
38
|
disallowAttrs?: (string | {
|
|
48
39
|
name: string;
|
|
49
|
-
value: import("packages/@markuplint/ml-spec/lib/index.js").AttributeType | (
|
|
50
|
-
|
|
51
|
-
} | {
|
|
52
|
-
pattern: string;
|
|
53
|
-
} | {
|
|
54
|
-
type: import("packages/@markuplint/ml-spec/lib/index.js").AttributeType;
|
|
55
|
-
});
|
|
56
|
-
})[] | Record<string, {
|
|
57
|
-
enum: [string, ...string[]];
|
|
58
|
-
} | {
|
|
59
|
-
pattern: string;
|
|
60
|
-
} | {
|
|
61
|
-
type: import("packages/@markuplint/ml-spec/lib/index.js").AttributeType;
|
|
62
|
-
}>;
|
|
40
|
+
value: import("packages/@markuplint/ml-spec/lib/index.js").AttributeType | import("packages/@markuplint/types/lib/types.schema.js").Pattern;
|
|
41
|
+
})[] | Record<string, import("packages/@markuplint/ml-spec/lib/index.js").AttributeType | import("packages/@markuplint/types/lib/types.schema.js").Pattern>;
|
|
63
42
|
ignoreAttrNamePrefix?: string | string[];
|
|
64
43
|
allowToAddPropertiesForPretender?: boolean;
|
|
65
|
-
attrs?: Record<string, ({
|
|
66
|
-
enum: [string, ...string[]];
|
|
67
|
-
} | {
|
|
68
|
-
pattern: string;
|
|
69
|
-
} | {
|
|
70
|
-
type: import("packages/@markuplint/ml-spec/lib/index.js").AttributeType;
|
|
71
|
-
}) | {
|
|
72
|
-
disallowed: true;
|
|
73
|
-
}>;
|
|
74
44
|
}>>;
|
|
75
45
|
readonly 'label-has-control': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
76
46
|
readonly 'landmark-roles': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
|
|
77
47
|
ignoreRoles: (("banner" | "main" | "complementary" | "contentinfo") | "form" | "navigation" | "region")[];
|
|
78
48
|
labelEachArea: boolean;
|
|
79
49
|
}>>;
|
|
50
|
+
readonly 'link-types': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
|
|
51
|
+
readonly allowMicroformats?: boolean | readonly string[];
|
|
52
|
+
}>>;
|
|
80
53
|
readonly 'neighbor-popovers': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
81
54
|
readonly 'no-ambiguous-navigable-target-names': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
|
|
82
55
|
readonly 'no-boolean-attr-value': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
@@ -90,29 +63,45 @@ declare const rules: {
|
|
|
90
63
|
readonly 'no-hard-code-id': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
91
64
|
readonly 'no-orphaned-end-tag': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, null>>;
|
|
92
65
|
readonly 'no-refer-to-non-existent-id': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, {
|
|
93
|
-
ariaVersion: import("packages/@markuplint/ml-spec/lib/index.js").ARIAVersion;
|
|
66
|
+
ariaVersion: import("packages/@markuplint/ml-spec/lib/index.js").ARIAVersion | undefined;
|
|
94
67
|
fragmentRefersNameAttr: boolean;
|
|
95
68
|
}>>;
|
|
69
|
+
readonly 'no-unsupported-features': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
|
|
70
|
+
readonly browserslist?: string | readonly string[];
|
|
71
|
+
readonly browserslistConfig?: string;
|
|
72
|
+
readonly browserslistEnv?: string;
|
|
73
|
+
readonly ignoreFeatures?: readonly string[];
|
|
74
|
+
readonly checkExperimental?: boolean;
|
|
75
|
+
readonly checkNonStandard?: boolean;
|
|
76
|
+
}>>;
|
|
96
77
|
readonly 'no-use-event-handler-attr': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
|
|
97
78
|
ignore?: string | string[];
|
|
98
79
|
}>>;
|
|
99
80
|
readonly 'permitted-contents': Readonly<import("@markuplint/ml-core").RuleSeed<import("./permitted-contents/types.js").TagRule[], import("./permitted-contents/types.js").Options>>;
|
|
100
81
|
readonly 'placeholder-label-option': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
|
|
101
|
-
readonly '
|
|
102
|
-
|
|
82
|
+
readonly 'redundant-accessible-name': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, {
|
|
83
|
+
checkTitleFallback: boolean;
|
|
84
|
+
checkPlaceholderFallback: boolean;
|
|
85
|
+
}>>;
|
|
86
|
+
readonly 'require-accessible-name': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, {
|
|
87
|
+
ariaVersion: import("packages/@markuplint/ml-spec/lib/index.js").ARIAVersion | undefined;
|
|
103
88
|
}>>;
|
|
104
89
|
readonly 'require-datetime': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, {
|
|
105
90
|
langs?: import("./require-datetime/types.js").Lang[];
|
|
106
91
|
}>>;
|
|
92
|
+
readonly 'require-dialog-autofocus': Readonly<import("@markuplint/ml-core").RuleSeed<import("@markuplint/ml-core").RuleConfigValue, undefined>>;
|
|
107
93
|
readonly 'required-attr': Readonly<import("@markuplint/ml-core").RuleSeed<string | (string | {
|
|
108
94
|
name: string;
|
|
109
95
|
value?: string | string[];
|
|
110
|
-
})[],
|
|
96
|
+
})[], {
|
|
97
|
+
readonly ignoreAttrs?: readonly string[];
|
|
98
|
+
}>>;
|
|
111
99
|
readonly 'required-element': Readonly<import("@markuplint/ml-core").RuleSeed<string[], {
|
|
112
100
|
ignoreHasMutableContents: boolean;
|
|
113
101
|
ignoreOmittedElements: boolean;
|
|
114
102
|
}>>;
|
|
115
103
|
readonly 'required-h1': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, import("./required-h1/index.js").Options>>;
|
|
104
|
+
readonly 'srcset-sizes-constraint': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
|
|
116
105
|
readonly 'table-row-column-alignment': Readonly<import("@markuplint/ml-core").RuleSeed<boolean, undefined>>;
|
|
117
106
|
readonly 'use-list': Readonly<import("@markuplint/ml-core").RuleSeed<readonly string[], {
|
|
118
107
|
spaceNeededBullets?: string[];
|
package/lib/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import AttrValueQuotes from './attr-value-quotes/index.js';
|
|
|
11
11
|
import CaseSensitiveAttrName from './case-sensitive-attr-name/index.js';
|
|
12
12
|
import CaseSensitiveTagName from './case-sensitive-tag-name/index.js';
|
|
13
13
|
import CharacterReference from './character-reference/index.js';
|
|
14
|
+
import CorrectAspectRatio from './correct-aspect-ratio/index.js';
|
|
14
15
|
import ClassNaming from './class-naming/index.js';
|
|
15
16
|
import DeprecatedAttr from './deprecated-attr/index.js';
|
|
16
17
|
import DeprecatedElement from './deprecated-element/index.js';
|
|
@@ -23,6 +24,7 @@ import IneffectiveAttr from './ineffective-attr/index.js';
|
|
|
23
24
|
import InvalidAttr from './invalid-attr/index.js';
|
|
24
25
|
import LabelHasControl from './label-has-control/index.js';
|
|
25
26
|
import LandmarkRoles from './landmark-roles/index.js';
|
|
27
|
+
import LinkTypes from './link-types/index.js';
|
|
26
28
|
import NeighborPopovers from './neighbor-popovers/index.js';
|
|
27
29
|
import NoAmbiguousNavigableTargetNames from './no-ambiguous-navigable-target-names/index.js';
|
|
28
30
|
import NoBooleanAttrValue from './no-boolean-attr-value/index.js';
|
|
@@ -33,11 +35,15 @@ import NoEmptyPalpableContent from './no-empty-palpable-content/index.js';
|
|
|
33
35
|
import NoHardCodeId from './no-hard-code-id/index.js';
|
|
34
36
|
import NoOrphanedEndTag from './no-orphaned-end-tag/index.js';
|
|
35
37
|
import NoReferToNonExistentId from './no-refer-to-non-existent-id/index.js';
|
|
38
|
+
import NoUnsupportedFeatures from './no-unsupported-features/index.js';
|
|
36
39
|
import NoUseEventHandlerAttr from './no-use-event-handler-attr/index.js';
|
|
37
40
|
import PermittedContents from './permitted-contents/index.js';
|
|
38
41
|
import PlaceholderLabelOption from './placeholder-label-option/index.js';
|
|
42
|
+
import RedundantAccessibleName from './redundant-accessible-name/index.js';
|
|
39
43
|
import RequireAccessibleName from './require-accessible-name/index.js';
|
|
40
44
|
import RequireDatetime from './require-datetime/index.js';
|
|
45
|
+
import RequireDialogAutofocus from './require-dialog-autofocus/index.js';
|
|
46
|
+
import SrcsetSizesConstraint from './srcset-sizes-constraint/index.js';
|
|
41
47
|
import RequiredAttr from './required-attr/index.js';
|
|
42
48
|
import RequiredElement from './required-element/index.js';
|
|
43
49
|
import RequiredH1 from './required-h1/index.js';
|
|
@@ -55,6 +61,7 @@ const rules = {
|
|
|
55
61
|
'case-sensitive-tag-name': CaseSensitiveTagName,
|
|
56
62
|
'character-reference': CharacterReference,
|
|
57
63
|
'class-naming': ClassNaming,
|
|
64
|
+
'correct-aspect-ratio': CorrectAspectRatio,
|
|
58
65
|
'deprecated-attr': DeprecatedAttr,
|
|
59
66
|
'deprecated-element': DeprecatedElement,
|
|
60
67
|
'disallowed-element': DisallowedElement,
|
|
@@ -66,6 +73,7 @@ const rules = {
|
|
|
66
73
|
'invalid-attr': InvalidAttr,
|
|
67
74
|
'label-has-control': LabelHasControl,
|
|
68
75
|
'landmark-roles': LandmarkRoles,
|
|
76
|
+
'link-types': LinkTypes,
|
|
69
77
|
'neighbor-popovers': NeighborPopovers,
|
|
70
78
|
'no-ambiguous-navigable-target-names': NoAmbiguousNavigableTargetNames,
|
|
71
79
|
'no-boolean-attr-value': NoBooleanAttrValue,
|
|
@@ -76,14 +84,18 @@ const rules = {
|
|
|
76
84
|
'no-hard-code-id': NoHardCodeId,
|
|
77
85
|
'no-orphaned-end-tag': NoOrphanedEndTag,
|
|
78
86
|
'no-refer-to-non-existent-id': NoReferToNonExistentId,
|
|
87
|
+
'no-unsupported-features': NoUnsupportedFeatures,
|
|
79
88
|
'no-use-event-handler-attr': NoUseEventHandlerAttr,
|
|
80
89
|
'permitted-contents': PermittedContents,
|
|
81
90
|
'placeholder-label-option': PlaceholderLabelOption,
|
|
91
|
+
'redundant-accessible-name': RedundantAccessibleName,
|
|
82
92
|
'require-accessible-name': RequireAccessibleName,
|
|
83
93
|
'require-datetime': RequireDatetime,
|
|
94
|
+
'require-dialog-autofocus': RequireDialogAutofocus,
|
|
84
95
|
'required-attr': RequiredAttr,
|
|
85
96
|
'required-element': RequiredElement,
|
|
86
97
|
'required-h1': RequiredH1,
|
|
98
|
+
'srcset-sizes-constraint': SrcsetSizesConstraint,
|
|
87
99
|
'table-row-column-alignment': TableRowColumnAlignment,
|
|
88
100
|
'use-list': UseList,
|
|
89
101
|
'wai-aria': WaiAria,
|
|
@@ -1,31 +1,26 @@
|
|
|
1
1
|
import type { AttributeType } from '@markuplint/ml-spec';
|
|
2
|
+
import type { Pattern } from '@markuplint/types';
|
|
2
3
|
/**
|
|
3
4
|
* Configuration options for the `invalid-attr` rule.
|
|
4
5
|
*/
|
|
5
6
|
type Option = {
|
|
6
7
|
/**
|
|
8
|
+
* Attributes to allow beyond what the spec permits.
|
|
9
|
+
* Can override spec-level restrictions such as `noUse`.
|
|
10
|
+
*
|
|
7
11
|
* @since 3.7.0
|
|
8
12
|
*/
|
|
9
|
-
allowAttrs?: (string | Attr)[] | Record<string,
|
|
13
|
+
allowAttrs?: (string | Attr)[] | Record<string, AttributeType | Pattern>;
|
|
10
14
|
/**
|
|
15
|
+
* Attributes to disallow in addition to spec restrictions.
|
|
16
|
+
*
|
|
11
17
|
* @since 3.7.0
|
|
12
18
|
*/
|
|
13
|
-
disallowAttrs?: (string | Attr)[] | Record<string,
|
|
19
|
+
disallowAttrs?: (string | Attr)[] | Record<string, AttributeType | Pattern>;
|
|
14
20
|
/** Attribute name prefix(es) to ignore during validation. */
|
|
15
21
|
ignoreAttrNamePrefix?: string | string[];
|
|
16
22
|
/** Whether to allow additional properties for pretender elements (defaults to `true`). */
|
|
17
23
|
allowToAddPropertiesForPretender?: boolean;
|
|
18
|
-
/**
|
|
19
|
-
* @deprecated Since version 3.7.0. Use `allowAttrs` or `disallowAttrs` instead.
|
|
20
|
-
* This option (`attr`) is now considered ambiguous and may lead to confusion.
|
|
21
|
-
* Please use the more explicit `allowAttrs` or `disallowAttrs` option
|
|
22
|
-
* to specify allowed attributes for the `invalid-attr` rule.
|
|
23
|
-
* @see {@link Option.allowAttrs}
|
|
24
|
-
* @see {@link Option.disallowAttrs}
|
|
25
|
-
*/
|
|
26
|
-
attrs?: Record<string, ValueRule | {
|
|
27
|
-
disallowed: true;
|
|
28
|
-
}>;
|
|
29
24
|
};
|
|
30
25
|
/**
|
|
31
26
|
* Describes a single attribute with its name and expected value constraint.
|
|
@@ -34,18 +29,7 @@ type Attr = {
|
|
|
34
29
|
/** The attribute name. */
|
|
35
30
|
name: string;
|
|
36
31
|
/** The expected attribute value type or validation rule. */
|
|
37
|
-
value: AttributeType |
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* A validation constraint for an attribute value, defined as either an
|
|
41
|
-
* enumerated list, a regex pattern, or a spec-based type.
|
|
42
|
-
*/
|
|
43
|
-
type ValueRule = {
|
|
44
|
-
enum: [string, ...string[]];
|
|
45
|
-
} | {
|
|
46
|
-
pattern: string;
|
|
47
|
-
} | {
|
|
48
|
-
type: AttributeType;
|
|
32
|
+
value: AttributeType | Pattern;
|
|
49
33
|
};
|
|
50
34
|
/**
|
|
51
35
|
* Rule that validates attributes against the HTML spec, allowed lists,
|
|
@@ -53,9 +37,9 @@ type ValueRule = {
|
|
|
53
37
|
*
|
|
54
38
|
* Checks each attribute for: existence in the spec, correct value type,
|
|
55
39
|
* allowed/disallowed overrides from configuration, and typo suggestions
|
|
56
|
-
* via candidate matching. Supports `allowAttrs
|
|
57
|
-
*
|
|
58
|
-
*
|
|
40
|
+
* via candidate matching. Supports `allowAttrs` and `disallowAttrs`.
|
|
41
|
+
* Non-existent attributes on elements that allow additional properties
|
|
42
|
+
* (pretenders) can be optionally permitted.
|
|
59
43
|
*/
|
|
60
44
|
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Option>>;
|
|
61
45
|
export default _default;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createRule, getAttrSpecs, getSpec } from '@markuplint/ml-core';
|
|
2
|
+
import { check, isEnum, isPattern } from '@markuplint/types';
|
|
2
3
|
import { attrCheck } from '../attr-check.js';
|
|
3
4
|
import { log as ruleLog } from '../debug.js';
|
|
4
|
-
import { isValidAttr
|
|
5
|
+
import { isValidAttr } from '../helpers.js';
|
|
5
6
|
import meta from './meta.js';
|
|
6
7
|
const log = ruleLog.extend('invalid-attr');
|
|
7
8
|
/**
|
|
@@ -10,9 +11,9 @@ const log = ruleLog.extend('invalid-attr');
|
|
|
10
11
|
*
|
|
11
12
|
* Checks each attribute for: existence in the spec, correct value type,
|
|
12
13
|
* allowed/disallowed overrides from configuration, and typo suggestions
|
|
13
|
-
* via candidate matching. Supports `allowAttrs
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* via candidate matching. Supports `allowAttrs` and `disallowAttrs`.
|
|
15
|
+
* Non-existent attributes on elements that allow additional properties
|
|
16
|
+
* (pretenders) can be optionally permitted.
|
|
16
17
|
*/
|
|
17
18
|
export default createRule({
|
|
18
19
|
meta: meta,
|
|
@@ -57,19 +58,15 @@ export default createRule({
|
|
|
57
58
|
if (Array.isArray(attr.rule.options.allowAttrs)) {
|
|
58
59
|
for (const allowAttr of attr.rule.options.allowAttrs) {
|
|
59
60
|
if (typeof allowAttr === 'string') {
|
|
60
|
-
allowAttrs[allowAttr] =
|
|
61
|
+
allowAttrs[allowAttr] = 'Any';
|
|
61
62
|
continue;
|
|
62
63
|
}
|
|
63
|
-
|
|
64
|
-
allowAttrs[allowAttr.name] = allowAttr.value;
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
allowAttrs[allowAttr.name] = { type: allowAttr.value };
|
|
64
|
+
allowAttrs[allowAttr.name] = allowAttr.value;
|
|
68
65
|
}
|
|
69
66
|
}
|
|
70
67
|
else {
|
|
71
|
-
for (const [attrName,
|
|
72
|
-
allowAttrs[attrName] =
|
|
68
|
+
for (const [attrName, attrType] of Object.entries(attr.rule.options.allowAttrs)) {
|
|
69
|
+
allowAttrs[attrName] = attrType;
|
|
73
70
|
}
|
|
74
71
|
}
|
|
75
72
|
}
|
|
@@ -77,99 +74,50 @@ export default createRule({
|
|
|
77
74
|
if (Array.isArray(attr.rule.options.disallowAttrs)) {
|
|
78
75
|
for (const disallowAttr of attr.rule.options.disallowAttrs) {
|
|
79
76
|
if (typeof disallowAttr === 'string') {
|
|
80
|
-
disallowAttrs[disallowAttr] =
|
|
77
|
+
disallowAttrs[disallowAttr] = 'Any';
|
|
81
78
|
continue;
|
|
82
79
|
}
|
|
83
|
-
|
|
84
|
-
disallowAttrs[disallowAttr.name] = disallowAttr.value;
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
disallowAttrs[disallowAttr.name] = { type: disallowAttr.value };
|
|
80
|
+
disallowAttrs[disallowAttr.name] = disallowAttr.value;
|
|
88
81
|
}
|
|
89
82
|
}
|
|
90
83
|
else {
|
|
91
|
-
for (const [attrName,
|
|
92
|
-
disallowAttrs[attrName] =
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (attr.rule.options.attrs) {
|
|
97
|
-
for (const [attrName, valueRule] of Object.entries(attr.rule.options.attrs)) {
|
|
98
|
-
if ('disallowed' in valueRule) {
|
|
99
|
-
disallowAttrs[attrName] = { type: 'Any' };
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
allowAttrs[attrName] = valueRule;
|
|
84
|
+
for (const [attrName, attrType] of Object.entries(attr.rule.options.disallowAttrs)) {
|
|
85
|
+
disallowAttrs[attrName] = attrType;
|
|
103
86
|
}
|
|
104
87
|
}
|
|
105
88
|
}
|
|
106
89
|
const allowValue = allowAttrs[name] ?? null;
|
|
107
90
|
const disallowValue = disallowAttrs[name] ?? null;
|
|
108
|
-
if (allowValue) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
},
|
|
115
|
-
description: '',
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
else if ('pattern' in allowValue) {
|
|
119
|
-
if (!match(value, allowValue.pattern)) {
|
|
120
|
-
invalid = {
|
|
121
|
-
invalidType: 'invalid-value',
|
|
122
|
-
message: t('{0} is unmatched with the below patterns: {1}', t('the "{0*}" {1}', name, 'attribute'), allowValue.pattern),
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
else if ('type' in allowValue) {
|
|
127
|
-
invalid = attrCheck(t, name, value, true, { name, type: allowValue.type, description: '' });
|
|
128
|
-
}
|
|
91
|
+
if (allowValue !== null) {
|
|
92
|
+
invalid = attrCheck(t, name, value, true, {
|
|
93
|
+
name,
|
|
94
|
+
type: allowValue,
|
|
95
|
+
description: '',
|
|
96
|
+
});
|
|
129
97
|
}
|
|
130
|
-
else if (disallowValue) {
|
|
131
|
-
if ('
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
},
|
|
137
|
-
description: '',
|
|
138
|
-
});
|
|
139
|
-
if (checkResult === false) {
|
|
140
|
-
invalid = {
|
|
141
|
-
invalidType: 'invalid-value',
|
|
142
|
-
message: t('{0} is disallowed to accept the following values: {1}', t('the "{0*}" {1}', name, 'attribute'), t(disallowValue.enum)),
|
|
143
|
-
};
|
|
144
|
-
}
|
|
98
|
+
else if (disallowValue !== null) {
|
|
99
|
+
if (disallowValue === 'Any') {
|
|
100
|
+
invalid = {
|
|
101
|
+
invalidType: 'non-existent',
|
|
102
|
+
message: t('{0} is disallowed', t('the "{0*}" {1}', name, 'attribute')),
|
|
103
|
+
};
|
|
145
104
|
}
|
|
146
|
-
else
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
message: t('{0} is matched with the below disallowed patterns: {1}', t('the "{0*}" {1}', name, 'attribute'), disallowValue.pattern),
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
else if ('type' in disallowValue) {
|
|
155
|
-
if (disallowValue.type === 'Any') {
|
|
156
|
-
invalid = {
|
|
157
|
-
invalidType: 'non-existent',
|
|
158
|
-
message: t('{0} is disallowed', t('the "{0*}" {1}', name, 'attribute')),
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
const checkResult = attrCheck(t, name, value, true, {
|
|
105
|
+
else {
|
|
106
|
+
const checkResult = isPattern(disallowValue)
|
|
107
|
+
? check(value, disallowValue)
|
|
108
|
+
: attrCheck(t, name, value, true, {
|
|
163
109
|
name,
|
|
164
|
-
type: disallowValue
|
|
110
|
+
type: disallowValue,
|
|
165
111
|
description: '',
|
|
166
112
|
});
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
113
|
+
const isMatched = isPattern(disallowValue)
|
|
114
|
+
? checkResult.matched
|
|
115
|
+
: checkResult === false;
|
|
116
|
+
if (isMatched) {
|
|
117
|
+
invalid = {
|
|
118
|
+
invalidType: 'invalid-value',
|
|
119
|
+
message: createDisallowMessage(t, name, disallowValue),
|
|
120
|
+
};
|
|
173
121
|
}
|
|
174
122
|
}
|
|
175
123
|
}
|
|
@@ -227,35 +175,21 @@ export default createRule({
|
|
|
227
175
|
},
|
|
228
176
|
});
|
|
229
177
|
/**
|
|
230
|
-
*
|
|
231
|
-
* or simple type constraint) as opposed to a raw {@link AttributeType}.
|
|
178
|
+
* Creates an appropriate disallow message based on the type structure.
|
|
232
179
|
*
|
|
233
|
-
* @param
|
|
234
|
-
* @
|
|
180
|
+
* @param t - The i18n translator
|
|
181
|
+
* @param name - The attribute name
|
|
182
|
+
* @param type - The attribute type or pattern
|
|
183
|
+
* @returns A localized message string
|
|
235
184
|
*/
|
|
236
|
-
function
|
|
185
|
+
function createDisallowMessage(t, name,
|
|
237
186
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
238
|
-
|
|
239
|
-
if (
|
|
240
|
-
return
|
|
241
|
-
}
|
|
242
|
-
if ('enum' in value) {
|
|
243
|
-
if (Object.keys(value).length > 1) {
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
return true;
|
|
247
|
-
}
|
|
248
|
-
if ('token' in value) {
|
|
249
|
-
return false;
|
|
250
|
-
}
|
|
251
|
-
if ('pattern' in value) {
|
|
252
|
-
return true;
|
|
253
|
-
}
|
|
254
|
-
if (value.type === 'integer' || value.type === 'float') {
|
|
255
|
-
return false;
|
|
187
|
+
type) {
|
|
188
|
+
if (isPattern(type)) {
|
|
189
|
+
return t('{0} is matched with the below disallowed patterns: {1}', t('the "{0*}" {1}', name, 'attribute'), type.pattern);
|
|
256
190
|
}
|
|
257
|
-
if (
|
|
258
|
-
return
|
|
191
|
+
if (typeof type !== 'string' && isEnum(type)) {
|
|
192
|
+
return t('{0} is disallowed to accept the following values: {1}', t('the "{0*}" {1}', name, 'attribute'), t(type.enum));
|
|
259
193
|
}
|
|
260
|
-
return
|
|
194
|
+
return t('{0} is disallowed', t('{0} of {1}', t('the {0}', 'type'), t('the "{0*}" {1}', name, 'attribute')));
|
|
261
195
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Options = {
|
|
2
|
+
readonly allowMicroformats?: boolean | readonly string[];
|
|
3
|
+
};
|
|
4
|
+
/**
|
|
5
|
+
* Rule that validates link type keywords in the `rel` attribute on
|
|
6
|
+
* `<link>`, `<a>`, `<area>`, and `<form>` elements against the WHATWG
|
|
7
|
+
* standard and optionally the Microformats registry.
|
|
8
|
+
*/
|
|
9
|
+
declare const _default: Readonly<import("@markuplint/ml-core").RuleSeed<boolean, Options>>;
|
|
10
|
+
export default _default;
|