@markuplint/rules 3.0.0-alpha.66 → 3.0.0-dev.176
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 +10 -44
- package/lib/attr-check.d.ts +22 -10
- package/lib/attr-check.js +32 -23
- package/lib/attr-duplication/index.d.ts +3 -1
- package/lib/attr-duplication/index.js +3 -2
- package/lib/attr-value-quotes/index.d.ts +5 -5
- package/lib/attr-value-quotes/index.js +1 -1
- package/lib/case-sensitive-attr-name/index.d.ts +2 -2
- package/lib/case-sensitive-attr-name/index.js +3 -3
- package/lib/case-sensitive-tag-name/index.d.ts +2 -2
- package/lib/case-sensitive-tag-name/index.js +3 -3
- package/lib/character-reference/index.d.ts +1 -1
- package/lib/character-reference/index.js +1 -1
- package/lib/class-naming/index.d.ts +2 -2
- package/lib/class-naming/index.js +3 -5
- package/lib/create-message.d.ts +13 -2
- package/lib/create-message.js +9 -8
- package/lib/debug.d.ts +1 -1
- package/lib/debug.js +1 -1
- package/lib/deprecated-attr/index.d.ts +3 -1
- package/lib/deprecated-element/index.d.ts +3 -1
- package/lib/deprecated-element/index.js +4 -4
- package/lib/disallowed-element/index.d.ts +1 -1
- package/lib/doctype/index.d.ts +3 -3
- package/lib/doctype/index.js +2 -2
- package/lib/end-tag/index.d.ts +1 -1
- package/lib/end-tag/index.js +3 -18
- package/lib/helpers.d.ts +38 -47
- package/lib/helpers.js +42 -93
- package/lib/id-duplication/index.d.ts +3 -1
- package/lib/index.d.ts +242 -62
- package/lib/index.js +10 -1
- package/lib/ineffective-attr/index.d.ts +3 -1
- package/lib/ineffective-attr/index.js +3 -6
- package/lib/invalid-attr/index.d.ts +40 -12
- package/lib/invalid-attr/index.js +159 -28
- package/lib/label-has-control/index.d.ts +4 -0
- package/lib/label-has-control/index.js +28 -0
- package/lib/landmark-roles/index.d.ts +6 -6
- package/lib/landmark-roles/index.js +10 -6
- package/lib/no-boolean-attr-value/index.d.ts +3 -1
- package/lib/no-boolean-attr-value/index.js +1 -1
- package/lib/no-default-value/index.d.ts +3 -1
- package/lib/no-default-value/index.js +1 -1
- package/lib/no-empty-palpable-content/index.d.ts +6 -0
- package/lib/no-empty-palpable-content/index.js +42 -0
- package/lib/no-hard-code-id/index.d.ts +3 -1
- package/lib/no-hard-code-id/index.js +1 -1
- package/lib/no-refer-to-non-existent-id/index.d.ts +9 -4
- package/lib/no-refer-to-non-existent-id/index.js +65 -5
- package/lib/no-use-event-handler-attr/index.d.ts +3 -3
- package/lib/no-use-event-handler-attr/index.js +6 -6
- package/lib/permitted-contents/choice.d.ts +10 -0
- package/lib/permitted-contents/choice.js +72 -0
- package/lib/permitted-contents/complex-branch.d.ts +20 -0
- package/lib/permitted-contents/complex-branch.js +29 -0
- package/lib/permitted-contents/content-model.d.ts +2 -0
- package/lib/permitted-contents/content-model.js +53 -0
- package/lib/permitted-contents/count-pattern.d.ts +29 -0
- package/lib/permitted-contents/count-pattern.js +162 -0
- package/lib/permitted-contents/debug.browser.d.ts +30 -0
- package/lib/permitted-contents/debug.browser.js +14 -0
- package/lib/permitted-contents/debug.d.ts +3 -0
- package/lib/permitted-contents/debug.js +13 -0
- package/lib/permitted-contents/index.d.ts +2 -8
- package/lib/permitted-contents/index.js +76 -249
- package/lib/permitted-contents/matches-selector.d.ts +8 -0
- package/lib/permitted-contents/matches-selector.js +187 -0
- package/lib/permitted-contents/order.d.ts +20 -0
- package/lib/permitted-contents/order.js +99 -0
- package/lib/permitted-contents/recursive-branch.d.ts +11 -0
- package/lib/permitted-contents/recursive-branch.js +45 -0
- package/lib/permitted-contents/represent-transparent-nodes.d.ts +10 -0
- package/lib/permitted-contents/represent-transparent-nodes.js +78 -0
- package/lib/permitted-contents/start.d.ts +18 -0
- package/lib/permitted-contents/start.js +73 -0
- package/lib/permitted-contents/transparent.d.ts +2 -0
- package/lib/permitted-contents/transparent.js +31 -0
- package/lib/permitted-contents/types.d.ts +52 -0
- package/lib/permitted-contents/types.js +2 -0
- package/lib/permitted-contents/utils.d.ts +100 -0
- package/lib/permitted-contents/utils.js +302 -0
- package/lib/placeholder-label-option/index.d.ts +2 -0
- package/lib/placeholder-label-option/index.js +88 -0
- package/lib/require-accessible-name/index.d.ts +3 -3
- package/lib/require-accessible-name/index.js +12 -4
- package/lib/require-datetime/index.d.ts +6 -0
- package/lib/require-datetime/index.js +34 -0
- package/lib/require-datetime/types.d.ts +10 -0
- package/lib/require-datetime/types.js +2 -0
- package/lib/require-datetime/utils.d.ts +11 -0
- package/lib/require-datetime/utils.js +137 -0
- package/lib/required-attr/index.d.ts +5 -5
- package/lib/required-attr/index.js +20 -17
- package/lib/required-element/index.d.ts +3 -3
- package/lib/required-element/index.js +3 -2
- package/lib/required-h1/index.d.ts +3 -3
- package/lib/required-h1/index.js +4 -3
- package/lib/use-list/index.d.ts +4 -4
- package/lib/use-list/index.js +9 -7
- package/lib/wai-aria/checkings/_.d.ts +15 -0
- package/lib/wai-aria/checkings/_.js +27 -0
- package/lib/wai-aria/checkings/abstract-role.js +1 -1
- package/lib/wai-aria/checkings/default-value.d.ts +7 -3
- package/lib/wai-aria/checkings/deprecated-props.d.ts +8 -4
- package/lib/wai-aria/checkings/disallowed-prop.d.ts +8 -4
- package/lib/wai-aria/checkings/disallowed-prop.js +27 -3
- package/lib/wai-aria/checkings/implicit-props.d.ts +8 -4
- package/lib/wai-aria/checkings/implicit-props.js +3 -2
- package/lib/wai-aria/checkings/implicit-role.js +2 -2
- package/lib/wai-aria/checkings/interaction-in-hidden.d.ts +11 -0
- package/lib/wai-aria/checkings/interaction-in-hidden.js +49 -0
- package/lib/wai-aria/checkings/no-global-prop.d.ts +7 -3
- package/lib/wai-aria/checkings/{non-existant-role.d.ts → non-existent-role.d.ts} +1 -1
- package/lib/wai-aria/checkings/{non-existant-role.js → non-existent-role.js} +4 -4
- package/lib/wai-aria/checkings/permitted-roles.js +1 -1
- package/lib/wai-aria/checkings/presentational-children.d.ts +29 -0
- package/lib/wai-aria/checkings/presentational-children.js +62 -0
- package/lib/wai-aria/checkings/{checking-required-owned-elements.d.ts → required-owned-elements.d.ts} +7 -3
- package/lib/wai-aria/checkings/required-owned-elements.js +103 -0
- package/lib/wai-aria/checkings/required-prop copy.d.ts +15 -0
- package/lib/wai-aria/checkings/required-prop copy.js +27 -0
- package/lib/wai-aria/checkings/required-prop.d.ts +12 -6
- package/lib/wai-aria/checkings/unadopted-explicit-roles.d.ts +15 -0
- package/lib/wai-aria/checkings/unadopted-explicit-roles.js +17 -0
- package/lib/wai-aria/checkings/value.d.ts +19 -4
- package/lib/wai-aria/checkings/value.js +77 -5
- package/lib/wai-aria/index.d.ts +1 -1
- package/lib/wai-aria/index.js +27 -16
- package/lib/wai-aria/types.d.ts +11 -9
- package/lib/xxx/index.d.ts +2 -0
- package/lib/xxx/index.js +32 -0
- package/package.json +18 -12
- package/schema.json +12 -0
- package/test/attr-check.spec.js +77 -0
- package/test/attr-duplication/index.spec.js +159 -0
- package/test/attr-value-quotes/index.spec.js +133 -0
- package/test/case-sensitive-attr-name/index.spec.js +65 -0
- package/test/case-sensitive-tag-name/index.spec.js +80 -0
- package/test/character-reference/index.spec.js +57 -0
- package/test/class-naming/index.spec.js +470 -0
- package/test/create-message.spec.js +497 -0
- package/test/deprecated-attr/index.spec.js +48 -0
- package/test/deprecated-element/index.spec.js +48 -0
- package/test/disallowed-element/index.spec.js +90 -0
- package/test/doctype/index.spec.js +50 -0
- package/test/end-tag/index.spec.js +162 -0
- package/test/id-duplication/index.spec.js +47 -0
- package/test/ineffective-attr/index.spec.js +31 -0
- package/test/invalid-attr/index.spec.js +1632 -0
- package/test/label-has-control/index.spec.js +29 -0
- package/test/landmark-roles/index.spec.js +187 -0
- package/test/no-boolean-attr-value/index.spec.js +41 -0
- package/test/no-default-value/index.spec.js +74 -0
- package/test/no-empty-palpable-content/index.spec.js +115 -0
- package/test/no-hard-code-id/index.spec.js +100 -0
- package/test/no-refer-to-non-existent-id/index.spec.js +254 -0
- package/test/no-use-event-handler-attr/index.spec.js +57 -0
- package/test/permitted-contents/choice.spec.js +174 -0
- package/test/permitted-contents/count-pattern.spec.js +308 -0
- package/test/permitted-contents/index.spec.js +1371 -0
- package/test/permitted-contents/matches-selector.spec.js +59 -0
- package/test/permitted-contents/order.spec.js +351 -0
- package/test/permitted-contents/recursive-branch.spec.js +41 -0
- package/test/permitted-contents/represent-transparent-nodes.spec.js +24 -0
- package/test/permitted-contents/start.spec.js +67 -0
- package/test/placeholder-label-option/index.spec.js +113 -0
- package/test/require-accessible-name/index.spec.js +446 -0
- package/test/require-datetime/index.spec.js +54 -0
- package/test/require-datetime/utils.spec.js +52 -0
- package/test/required-attr/index.spec.js +414 -0
- package/test/required-element/index.spec.js +188 -0
- package/test/required-h1/index.spec.js +69 -0
- package/test/use-list/index.spec.js +109 -0
- package/test/wai-aria/checkings/value.spec.js +33 -0
- package/test/wai-aria/index.spec.js +1173 -0
- package/lib/__foo/index.d.ts +0 -2
- package/lib/__foo/index.js +0 -46
- package/lib/attr-equal-space-after/index.d.ts +0 -3
- package/lib/attr-equal-space-after/index.js +0 -90
- package/lib/attr-equal-space-before/index.d.ts +0 -3
- package/lib/attr-equal-space-before/index.js +0 -90
- package/lib/attr-spacing/index.d.ts +0 -6
- package/lib/attr-spacing/index.js +0 -100
- package/lib/helper/aria/get-aria.d.ts +0 -7
- package/lib/helper/aria/get-aria.js +0 -53
- package/lib/helper/aria/get-computed-role.d.ts +0 -10
- package/lib/helper/aria/get-computed-role.js +0 -24
- package/lib/helper/aria/get-implicit-role.d.ts +0 -7
- package/lib/helper/aria/get-implicit-role.js +0 -12
- package/lib/helper/aria/get-permitted-roles.d.ts +0 -14
- package/lib/helper/aria/get-permitted-roles.js +0 -26
- package/lib/helper/aria/resolve-version.d.ts +0 -2
- package/lib/helper/aria/resolve-version.js +0 -21
- package/lib/helper/spec/aria-spec.d.ts +0 -5
- package/lib/helper/spec/aria-spec.js +0 -12
- package/lib/helper/spec/get-role-spec.d.ts +0 -11
- package/lib/helper/spec/get-role-spec.js +0 -39
- package/lib/helper/spec/html-spec.d.ts +0 -2
- package/lib/helper/spec/html-spec.js +0 -14
- package/lib/indentation/index.d.ts +0 -7
- package/lib/indentation/index.js +0 -208
- package/lib/permitted-contents/array.combination.d.ts +0 -1
- package/lib/permitted-contents/array.combination.js +0 -33
- package/lib/permitted-contents/permitted-content.spec-to-regexp.d.ts +0 -11
- package/lib/permitted-contents/permitted-content.spec-to-regexp.js +0 -230
- package/lib/permitted-contents/unfold-content-models-to-tags.d.ts +0 -2
- package/lib/permitted-contents/unfold-content-models-to-tags.js +0 -8
- package/lib/wai-aria/checkings/checking-required-owned-elements.js +0 -63
- package/tsconfig.test.json +0 -3
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkingRequiredOwnedElements = void 0;
|
|
4
|
+
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
5
|
+
/**
|
|
6
|
+
* Required Owned Elements
|
|
7
|
+
*
|
|
8
|
+
* @see https://w3c.github.io/aria/#mustContain
|
|
9
|
+
*/
|
|
10
|
+
const checkingRequiredOwnedElements = ({ el, role }) => t => {
|
|
11
|
+
if (!role) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (role.requiredOwnedElements.length === 0) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* > There may be times that required owned elements are missing,
|
|
19
|
+
* > for example, while editing or while loading a data set.
|
|
20
|
+
* > When a widget is missing required owned elements due to script execution or loading,
|
|
21
|
+
* > authors MUST mark a containing element with aria-busy equal to true.
|
|
22
|
+
* > For example, until a page is fully initialized and complete,
|
|
23
|
+
* > an author could mark the document element as busy.
|
|
24
|
+
*
|
|
25
|
+
* Stop to evaluate when it has `aria-busy=true` for it considers the contents are missing.
|
|
26
|
+
*/
|
|
27
|
+
if (el.matches('[aria-busy="true" i]')) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// TODO: Needs to resolve `aria-own`
|
|
31
|
+
const children = Array.from(el.childNodes).map(child => {
|
|
32
|
+
if (child.is(child.ELEMENT_NODE)) {
|
|
33
|
+
if (child.matches('[aria-busy="true" i]')) {
|
|
34
|
+
return [child, 'BUSY'];
|
|
35
|
+
}
|
|
36
|
+
const computedChild = (0, ml_spec_1.getComputedRole)(child.ownerMLDocument.specs, child, child.rule.options.version);
|
|
37
|
+
if (role.requiredOwnedElements.some(ownedRole => (0, ml_spec_1.isRequiredOwnedElement)(computedChild.el, computedChild.role, ownedRole, child.ownerMLDocument.specs, child.rule.options.version))) {
|
|
38
|
+
return [child, 'REQUIRED'];
|
|
39
|
+
}
|
|
40
|
+
return [child, 'OTHER'];
|
|
41
|
+
}
|
|
42
|
+
else if (child.is(child.MARKUPLINT_PREPROCESSOR_BLOCK)) {
|
|
43
|
+
return [child, 'PB'];
|
|
44
|
+
}
|
|
45
|
+
return [null, 'NO_ELEMENT'];
|
|
46
|
+
});
|
|
47
|
+
if (children.some(([, type]) => type === 'BUSY')) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* > Any element that will be owned by the element with this role.
|
|
52
|
+
* > For example, an element with the role list
|
|
53
|
+
* > **will own at least one element** with the role listitem.
|
|
54
|
+
*/
|
|
55
|
+
if (children.some(([, type]) => type === 'REQUIRED')) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (children.some(([, type]) => type === 'PB')) {
|
|
59
|
+
// TODO: https://github.com/markuplint/markuplint/issues/490
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Has mutable children
|
|
64
|
+
*
|
|
65
|
+
* Ex:
|
|
66
|
+
*
|
|
67
|
+
* ```jsx
|
|
68
|
+
* <table>
|
|
69
|
+
* <tbody>
|
|
70
|
+
* {list.map((item) => <tr><td>{item}</td></tr>)}
|
|
71
|
+
* </tbody>
|
|
72
|
+
* </table>
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
if (el.hasMutableChildren(true)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (mayBeBeforeCreated(el)) {
|
|
79
|
+
return {
|
|
80
|
+
scope: el,
|
|
81
|
+
message: t('{0}. Or, {1}', t('require {0}', role.requiredOwnedElements.length === 1 && role.requiredOwnedElements[0]
|
|
82
|
+
? t('the "{0*}" {1}', role.requiredOwnedElements[0], 'role')
|
|
83
|
+
: t('the {0}', 'roles') + `: ${t(role.requiredOwnedElements)}`), t('require {0}', 'aria-busy="true"')),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
scope: el,
|
|
88
|
+
message: t('{0} expects {1}', t('the "{0*}" {1}', role.name, 'role'), role.requiredOwnedElements.length === 1 && role.requiredOwnedElements[0]
|
|
89
|
+
? t('the "{0*}" {1}', role.requiredOwnedElements[0], 'role')
|
|
90
|
+
: t('the {0}', 'roles') + `: ${t(role.requiredOwnedElements)}`),
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
exports.checkingRequiredOwnedElements = checkingRequiredOwnedElements;
|
|
94
|
+
function mayBeBeforeCreated(
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
96
|
+
el) {
|
|
97
|
+
if (el.isEmpty()) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
return Array.from(el.children).every(child => {
|
|
101
|
+
return ['script', 'template'].includes(child.localName);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Options } from '../types';
|
|
2
|
+
import type { ElementChecker } from '@markuplint/ml-core';
|
|
3
|
+
import type { ARIAProperty, ARIARole } from '@markuplint/ml-spec';
|
|
4
|
+
export declare const checkingRequiredProp: ElementChecker<
|
|
5
|
+
boolean,
|
|
6
|
+
Options,
|
|
7
|
+
{
|
|
8
|
+
role?:
|
|
9
|
+
| (ARIARole & {
|
|
10
|
+
isImplicit?: boolean;
|
|
11
|
+
})
|
|
12
|
+
| null;
|
|
13
|
+
propSpecs: readonly ARIAProperty[];
|
|
14
|
+
}
|
|
15
|
+
>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkingRequiredProp = void 0;
|
|
4
|
+
const checkingRequiredProp = ({ el, role, propSpecs }) => t => {
|
|
5
|
+
var _a;
|
|
6
|
+
if (!role) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (role.isImplicit) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
const requiredProps = role.ownedProperties.filter(s => s.required).map(s => s.name);
|
|
13
|
+
for (const requiredProp of requiredProps) {
|
|
14
|
+
const has = el.attributes.some(attr => {
|
|
15
|
+
const attrName = attr.name.toLowerCase();
|
|
16
|
+
return attrName === requiredProp;
|
|
17
|
+
});
|
|
18
|
+
if (!has) {
|
|
19
|
+
const propSpec = propSpecs.find(p => p.name === requiredProp);
|
|
20
|
+
return {
|
|
21
|
+
scope: el,
|
|
22
|
+
message: t('{0:c} on {1}', t('Require {0}', t('the "{0*}" {1}', requiredProp, `ARIA ${(_a = propSpec === null || propSpec === void 0 ? void 0 : propSpec.type) !== null && _a !== void 0 ? _a : 'property'}`)), t('the "{0*}" {1}', role.name, 'role')),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
exports.checkingRequiredProp = checkingRequiredProp;
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import type { Options } from '../types';
|
|
2
2
|
import type { ElementChecker } from '@markuplint/ml-core';
|
|
3
3
|
import type { ARIAProperty, ARIARole } from '@markuplint/ml-spec';
|
|
4
|
-
export declare const checkingRequiredProp: ElementChecker<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
export declare const checkingRequiredProp: ElementChecker<
|
|
5
|
+
boolean,
|
|
6
|
+
Options,
|
|
7
|
+
{
|
|
8
|
+
role?:
|
|
9
|
+
| (ARIARole & {
|
|
10
|
+
isImplicit?: boolean;
|
|
11
|
+
})
|
|
12
|
+
| null;
|
|
13
|
+
propSpecs: readonly ARIAProperty[];
|
|
14
|
+
}
|
|
15
|
+
>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Options } from '../types';
|
|
2
|
+
import type { ElementChecker } from '@markuplint/ml-core';
|
|
3
|
+
import type { ARIAProperty, ARIARole } from '@markuplint/ml-spec';
|
|
4
|
+
export declare const checkingUnadoptedExplicitRoles: ElementChecker<
|
|
5
|
+
boolean,
|
|
6
|
+
Options,
|
|
7
|
+
{
|
|
8
|
+
role?:
|
|
9
|
+
| (ARIARole & {
|
|
10
|
+
isImplicit?: boolean;
|
|
11
|
+
})
|
|
12
|
+
| null;
|
|
13
|
+
propSpecs: readonly ARIAProperty[];
|
|
14
|
+
}
|
|
15
|
+
>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkingUnadoptedExplicitRoles = void 0;
|
|
4
|
+
const checkingUnadoptedExplicitRoles = ({ el, role, propSpecs }) => t => {
|
|
5
|
+
if (!role) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
if (role.name) {
|
|
9
|
+
console.log(el.localName, role.name);
|
|
10
|
+
return {
|
|
11
|
+
scope: el,
|
|
12
|
+
message: '',
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return;
|
|
16
|
+
};
|
|
17
|
+
exports.checkingUnadoptedExplicitRoles = checkingUnadoptedExplicitRoles;
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import type { Options } from '../types';
|
|
2
2
|
import type { AttrChecker } from '@markuplint/ml-core';
|
|
3
3
|
import type { ARIAProperty, ARIARole } from '@markuplint/ml-spec';
|
|
4
|
-
export declare const checkingValue: AttrChecker<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
export declare const checkingValue: AttrChecker<
|
|
5
|
+
boolean,
|
|
6
|
+
Options,
|
|
7
|
+
{
|
|
8
|
+
role?: ARIARole | null;
|
|
9
|
+
propSpecs: readonly ARIAProperty[];
|
|
10
|
+
booleanish?: boolean;
|
|
11
|
+
}
|
|
12
|
+
>;
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
|
|
16
|
+
*/
|
|
17
|
+
export declare function checkAriaValue(
|
|
18
|
+
type: string,
|
|
19
|
+
value: string,
|
|
20
|
+
tokenEnum: readonly string[],
|
|
21
|
+
booleanish?: boolean,
|
|
22
|
+
): boolean;
|
|
@@ -1,21 +1,93 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.checkingValue = void 0;
|
|
4
|
-
const
|
|
5
|
-
const checkingValue = ({ attr, role, propSpecs }) => t => {
|
|
3
|
+
exports.checkAriaValue = exports.checkingValue = void 0;
|
|
4
|
+
const checkingValue = ({ attr, role, propSpecs, booleanish }) => t => {
|
|
6
5
|
var _a;
|
|
7
6
|
if (attr.isDynamicValue) {
|
|
8
7
|
return;
|
|
9
8
|
}
|
|
10
9
|
const propSpec = propSpecs.find(p => p.name === attr.name);
|
|
11
|
-
const result =
|
|
10
|
+
const result = checkAria(propSpec, attr.value, role === null || role === void 0 ? void 0 : role.name, booleanish);
|
|
12
11
|
if (result.isValid) {
|
|
13
12
|
return;
|
|
14
13
|
}
|
|
15
14
|
return {
|
|
16
15
|
scope: attr,
|
|
17
16
|
message: t('{0:c} on {1}', t('{0} is {1:c}', t('the "{0}"', attr.value), 'disallowed'), t('the "{0*}" {1}', attr.name, `ARIA ${(_a = propSpec === null || propSpec === void 0 ? void 0 : propSpec.type) !== null && _a !== void 0 ? _a : 'property'}`)) +
|
|
18
|
-
('enum' in result && result.enum.length
|
|
17
|
+
('enum' in result && result.enum.length > 0
|
|
18
|
+
? t('. ') + t('Allowed values are: {0}', t(result.enum))
|
|
19
|
+
: ''),
|
|
19
20
|
};
|
|
20
21
|
};
|
|
21
22
|
exports.checkingValue = checkingValue;
|
|
23
|
+
function checkAria(propSpec, currentValue, role, booleanish) {
|
|
24
|
+
if (!propSpec) {
|
|
25
|
+
return {
|
|
26
|
+
currentValue,
|
|
27
|
+
// For skipping checking
|
|
28
|
+
isValid: true,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
let valueType = propSpec.value;
|
|
32
|
+
if (role && propSpec.conditionalValue) {
|
|
33
|
+
for (const cond of propSpec.conditionalValue) {
|
|
34
|
+
if (cond.role.includes(role)) {
|
|
35
|
+
valueType = cond.value;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const isValid = checkAriaValue(valueType, currentValue, propSpec.enum, booleanish);
|
|
41
|
+
return {
|
|
42
|
+
...propSpec,
|
|
43
|
+
currentValue,
|
|
44
|
+
isValid,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
* @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
|
|
50
|
+
*/
|
|
51
|
+
function checkAriaValue(type, value, tokenEnum, booleanish) {
|
|
52
|
+
switch (type) {
|
|
53
|
+
case 'token': {
|
|
54
|
+
return tokenEnum.includes(value);
|
|
55
|
+
}
|
|
56
|
+
case 'token list': {
|
|
57
|
+
const list = value.split(/\s+/g).map(s => s.trim());
|
|
58
|
+
return list.every(token => tokenEnum.includes(token));
|
|
59
|
+
}
|
|
60
|
+
case 'string':
|
|
61
|
+
case 'ID reference':
|
|
62
|
+
case 'ID reference list': {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
case 'true/false': {
|
|
66
|
+
if (booleanish && value === '') {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
return ['true', 'false'].includes(value);
|
|
70
|
+
}
|
|
71
|
+
case 'tristate': {
|
|
72
|
+
if (booleanish && value === '') {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return ['mixed', 'true', 'false', 'undefined'].includes(value);
|
|
76
|
+
}
|
|
77
|
+
case 'true/false/undefined': {
|
|
78
|
+
if (booleanish && value === '') {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return ['true', 'false', 'undefined'].includes(value);
|
|
82
|
+
}
|
|
83
|
+
case 'integer': {
|
|
84
|
+
return parseInt(value).toString() === value;
|
|
85
|
+
}
|
|
86
|
+
case 'number': {
|
|
87
|
+
return parseFloat(value).toString() === value;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// For skipping checking
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
exports.checkAriaValue = checkAriaValue;
|
package/lib/wai-aria/index.d.ts
CHANGED
package/lib/wai-aria/index.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
+
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
4
5
|
const helpers_1 = require("../helpers");
|
|
5
6
|
const abstract_role_1 = require("./checkings/abstract-role");
|
|
6
|
-
const checking_required_owned_elements_1 = require("./checkings/checking-required-owned-elements");
|
|
7
7
|
const default_value_1 = require("./checkings/default-value");
|
|
8
8
|
const deprecated_props_1 = require("./checkings/deprecated-props");
|
|
9
9
|
const disallowed_prop_1 = require("./checkings/disallowed-prop");
|
|
10
10
|
const implicit_props_1 = require("./checkings/implicit-props");
|
|
11
11
|
const implicit_role_1 = require("./checkings/implicit-role");
|
|
12
|
+
const interaction_in_hidden_1 = require("./checkings/interaction-in-hidden");
|
|
12
13
|
const no_global_prop_1 = require("./checkings/no-global-prop");
|
|
13
|
-
const
|
|
14
|
+
const non_existent_role_1 = require("./checkings/non-existent-role");
|
|
14
15
|
const permitted_roles_1 = require("./checkings/permitted-roles");
|
|
16
|
+
const presentational_children_1 = require("./checkings/presentational-children");
|
|
17
|
+
const required_owned_elements_1 = require("./checkings/required-owned-elements");
|
|
15
18
|
const required_prop_1 = require("./checkings/required-prop");
|
|
16
19
|
const value_1 = require("./checkings/value");
|
|
17
20
|
exports.default = (0, ml_core_1.createRule)({
|
|
@@ -20,17 +23,19 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
20
23
|
checkingDeprecatedProps: true,
|
|
21
24
|
permittedAriaRoles: true,
|
|
22
25
|
checkingRequiredOwnedElements: true,
|
|
26
|
+
checkingPresentationalChildren: false,
|
|
27
|
+
checkingInteractionInHidden: false,
|
|
23
28
|
disallowSetImplicitRole: true,
|
|
24
29
|
disallowSetImplicitProps: true,
|
|
25
30
|
disallowDefaultValue: false,
|
|
26
|
-
version:
|
|
31
|
+
version: ml_spec_1.ARIA_RECOMMENDED_VERSION,
|
|
27
32
|
},
|
|
28
33
|
async verify({ document, report, t }) {
|
|
29
34
|
await document.walkOn('Element', el => {
|
|
30
35
|
const roleAttr = el.getAttributeNode('role');
|
|
31
36
|
const propAttrs = el.attributes.filter(attr => /^aria-/i.test(attr.name));
|
|
32
37
|
const ariaAttrs = new helpers_1.Collection(roleAttr, ...propAttrs);
|
|
33
|
-
const elSpec = (0, ml_core_1.getSpec)(el, document.specs);
|
|
38
|
+
const elSpec = (0, ml_core_1.getSpec)(el, document.specs.specs);
|
|
34
39
|
if (!elSpec) {
|
|
35
40
|
return;
|
|
36
41
|
}
|
|
@@ -43,44 +48,50 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
43
48
|
}
|
|
44
49
|
return;
|
|
45
50
|
}
|
|
46
|
-
const computed = (0, ml_core_1.getComputedRole)(document.specs, el, el.rule.
|
|
47
|
-
const { props: propSpecs } = (0, ml_core_1.ariaSpecs)(document.specs, el.rule.
|
|
51
|
+
const computed = (0, ml_core_1.getComputedRole)(document.specs, el, el.rule.options.version);
|
|
52
|
+
const { props: propSpecs } = (0, ml_core_1.ariaSpecs)(document.specs, el.rule.options.version);
|
|
48
53
|
if (roleAttr) {
|
|
49
|
-
if (report((0,
|
|
54
|
+
if (report((0, non_existent_role_1.checkingNonExistentRole)({ attr: roleAttr }))) {
|
|
50
55
|
return;
|
|
51
56
|
}
|
|
52
57
|
if (report((0, abstract_role_1.checkingAbstractRole)({ attr: roleAttr }))) {
|
|
53
58
|
return;
|
|
54
59
|
}
|
|
55
60
|
report((0, required_prop_1.checkingRequiredProp)({ el, role: computed.role, propSpecs }));
|
|
56
|
-
if (el.rule.
|
|
61
|
+
if (el.rule.options.disallowSetImplicitRole) {
|
|
57
62
|
report((0, implicit_role_1.checkingImplicitRole)({ attr: roleAttr }));
|
|
58
63
|
}
|
|
59
|
-
if (el.rule.
|
|
64
|
+
if (el.rule.options.permittedAriaRoles) {
|
|
60
65
|
report((0, permitted_roles_1.checkingPermittedRoles)({ attr: roleAttr }));
|
|
61
66
|
}
|
|
62
67
|
}
|
|
63
68
|
for (const attr of propAttrs) {
|
|
64
69
|
report((0, disallowed_prop_1.checkingDisallowedProp)({ attr, role: computed.role, propSpecs }));
|
|
65
|
-
if (el.rule.
|
|
70
|
+
if (el.rule.options.checkingDeprecatedProps) {
|
|
66
71
|
report((0, deprecated_props_1.checkingDeprecatedProps)({ attr, role: computed.role, propSpecs }));
|
|
67
72
|
}
|
|
68
|
-
if (el.rule.
|
|
73
|
+
if (el.rule.options.disallowSetImplicitProps) {
|
|
69
74
|
const attrSpecs = (0, ml_core_1.getAttrSpecs)(el, document.specs);
|
|
70
75
|
report((0, implicit_props_1.checkingImplicitProps)({ attr, propSpecs, attrSpecs }));
|
|
71
76
|
}
|
|
72
|
-
if (el.rule.
|
|
73
|
-
report((0, value_1.checkingValue)({ attr, role: computed.role, propSpecs }));
|
|
77
|
+
if (el.rule.options.checkingValue) {
|
|
78
|
+
report((0, value_1.checkingValue)({ attr, role: computed.role, propSpecs, booleanish: document.booleanish }));
|
|
74
79
|
}
|
|
75
|
-
if (el.rule.
|
|
80
|
+
if (el.rule.options.disallowDefaultValue) {
|
|
76
81
|
report((0, default_value_1.checkingDefaultValue)({ attr, propSpecs }));
|
|
77
82
|
}
|
|
78
83
|
if (!computed.role) {
|
|
79
84
|
report((0, no_global_prop_1.checkingNoGlobalProp)({ attr, propSpecs }));
|
|
80
85
|
}
|
|
81
86
|
}
|
|
82
|
-
if (el.rule.
|
|
83
|
-
report((0,
|
|
87
|
+
if (el.rule.options.checkingRequiredOwnedElements) {
|
|
88
|
+
report((0, required_owned_elements_1.checkingRequiredOwnedElements)({ el, role: computed.role }));
|
|
89
|
+
}
|
|
90
|
+
if (el.rule.options.checkingPresentationalChildren) {
|
|
91
|
+
report((0, presentational_children_1.checkingPresentationalChildren)({ el }));
|
|
92
|
+
}
|
|
93
|
+
if (el.rule.options.checkingInteractionInHidden) {
|
|
94
|
+
report((0, interaction_in_hidden_1.checkingInteractionInHidden)({ el }));
|
|
84
95
|
}
|
|
85
96
|
});
|
|
86
97
|
},
|
package/lib/wai-aria/types.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { ARIAVersion } from '@markuplint/ml-spec';
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
export type Options = {
|
|
3
|
+
checkingValue: boolean;
|
|
4
|
+
checkingDeprecatedProps: boolean;
|
|
5
|
+
permittedAriaRoles: boolean;
|
|
6
|
+
checkingRequiredOwnedElements: boolean;
|
|
7
|
+
checkingPresentationalChildren: boolean;
|
|
8
|
+
checkingInteractionInHidden: boolean;
|
|
9
|
+
disallowSetImplicitRole: boolean;
|
|
10
|
+
disallowSetImplicitProps: boolean;
|
|
11
|
+
disallowDefaultValue: boolean;
|
|
12
|
+
version: ARIAVersion;
|
|
11
13
|
};
|
package/lib/xxx/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
+
exports.default = (0, ml_core_1.createRule)({
|
|
5
|
+
defaultValue: true,
|
|
6
|
+
defaultOptions: null,
|
|
7
|
+
async verify({ document, report, t }) {
|
|
8
|
+
// Element
|
|
9
|
+
await document.walkOn("Element", (el) => {
|
|
10
|
+
const raw = el.raw.trim();
|
|
11
|
+
if (/./i.test(raw)) {
|
|
12
|
+
report({
|
|
13
|
+
scope: el,
|
|
14
|
+
message: t("It is {0}", "issue"),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
// Attribute
|
|
19
|
+
await document.walkOn("Attr", (attr) => {
|
|
20
|
+
var _a, _b, _c;
|
|
21
|
+
if (/./i.test(attr.name)) {
|
|
22
|
+
report({
|
|
23
|
+
scope: attr,
|
|
24
|
+
line: (_a = attr.nameNode) === null || _a === void 0 ? void 0 : _a.startLine,
|
|
25
|
+
col: (_b = attr.nameNode) === null || _b === void 0 ? void 0 : _b.startCol,
|
|
26
|
+
raw: (_c = attr.nameNode) === null || _c === void 0 ? void 0 : _c.raw,
|
|
27
|
+
message: t("It is {0}", "issue"),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/rules",
|
|
3
|
-
"version": "3.0.0-
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.0.0-dev.176+f6ad62e9",
|
|
4
|
+
"description": "Built-in rules of markuplint",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -16,17 +16,23 @@
|
|
|
16
16
|
"dev": "tsc --build --watch",
|
|
17
17
|
"clean": "tsc --build --clean"
|
|
18
18
|
},
|
|
19
|
+
"browser": {
|
|
20
|
+
"./lib/permitted-contents/debug.js": "./lib/permitted-contents/debug.browser.js"
|
|
21
|
+
},
|
|
19
22
|
"dependencies": {
|
|
20
|
-
"@markuplint/html-spec": "3.0.0-
|
|
21
|
-
"@markuplint/ml-core": "3.0.0-
|
|
22
|
-
"@markuplint/ml-spec": "3.0.0-
|
|
23
|
-
"@markuplint/
|
|
23
|
+
"@markuplint/html-spec": "3.0.0-dev.176+f6ad62e9",
|
|
24
|
+
"@markuplint/ml-core": "3.0.0-dev.176+f6ad62e9",
|
|
25
|
+
"@markuplint/ml-spec": "3.0.0-dev.176+f6ad62e9",
|
|
26
|
+
"@markuplint/selector": "3.0.0-dev.176+f6ad62e9",
|
|
27
|
+
"@markuplint/shared": "3.5.1-dev.3129+f6ad62e9",
|
|
28
|
+
"@markuplint/types": "3.0.0-dev.176+f6ad62e9",
|
|
29
|
+
"@types/debug": "^4.1.7",
|
|
30
|
+
"@ungap/structured-clone": "^1.0.1",
|
|
31
|
+
"ansi-colors": "^4.1.3",
|
|
32
|
+
"chrono-node": "^2.5.0",
|
|
24
33
|
"debug": "^4.3.4",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
},
|
|
28
|
-
"devDependencies": {
|
|
29
|
-
"@types/debug": "^4.1.7"
|
|
34
|
+
"tslib": "^2.4.1",
|
|
35
|
+
"type-fest": "^3.8.0"
|
|
30
36
|
},
|
|
31
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "f6ad62e992e1569be4067f1e90d2d6017a658f57"
|
|
32
38
|
}
|
package/schema.json
CHANGED
|
@@ -48,6 +48,9 @@
|
|
|
48
48
|
"invalid-attr": {
|
|
49
49
|
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/invalid-attr/schema.json"
|
|
50
50
|
},
|
|
51
|
+
"label-has-control": {
|
|
52
|
+
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/label-has-control/schema.json"
|
|
53
|
+
},
|
|
51
54
|
"landmark-roles": {
|
|
52
55
|
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/landmark-roles/schema.json"
|
|
53
56
|
},
|
|
@@ -57,6 +60,9 @@
|
|
|
57
60
|
"no-default-value": {
|
|
58
61
|
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/no-default-value/schema.json"
|
|
59
62
|
},
|
|
63
|
+
"no-empty-palpable-content": {
|
|
64
|
+
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/no-empty-palpable-content/schema.json"
|
|
65
|
+
},
|
|
60
66
|
"no-hard-code-id": {
|
|
61
67
|
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/no-hard-code-id/schema.json"
|
|
62
68
|
},
|
|
@@ -69,9 +75,15 @@
|
|
|
69
75
|
"permitted-contents": {
|
|
70
76
|
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/permitted-contents/schema.json"
|
|
71
77
|
},
|
|
78
|
+
"placeholder-label-option": {
|
|
79
|
+
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/placeholder-label-option/schema.json"
|
|
80
|
+
},
|
|
72
81
|
"require-accessible-name": {
|
|
73
82
|
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/require-accessible-name/schema.json"
|
|
74
83
|
},
|
|
84
|
+
"require-datetime": {
|
|
85
|
+
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/require-datetime/schema.json"
|
|
86
|
+
},
|
|
75
87
|
"required-attr": {
|
|
76
88
|
"$ref": "https://raw.githubusercontent.com/markuplint/markuplint/main/packages/%40markuplint/rules/src/required-attr/schema.json"
|
|
77
89
|
},
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const { translator } = require('@markuplint/i18n');
|
|
2
|
+
const { i18n } = require('markuplint');
|
|
3
|
+
|
|
4
|
+
const { valueCheck } = require('../lib/attr-check');
|
|
5
|
+
|
|
6
|
+
let t;
|
|
7
|
+
|
|
8
|
+
beforeAll(async () => {
|
|
9
|
+
const locale = await i18n('en');
|
|
10
|
+
t = translator(locale);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test('OneCodePointChar List', () => {
|
|
14
|
+
expect(
|
|
15
|
+
valueCheck(t, 'accesskey', '@ 12', {
|
|
16
|
+
token: 'OneCodePointChar',
|
|
17
|
+
separator: 'space',
|
|
18
|
+
unique: true,
|
|
19
|
+
}),
|
|
20
|
+
).toStrictEqual([
|
|
21
|
+
'the "accesskey" attribute expects space-separated list. the the content of the list part includes unexpected characters. It expects one code point character (https://html.spec.whatwg.org/multipage/interaction.html#the-accesskey-attribute)',
|
|
22
|
+
{
|
|
23
|
+
col: 2,
|
|
24
|
+
line: 0,
|
|
25
|
+
raw: '12',
|
|
26
|
+
},
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('BrowsingContextNameOrKeyword', () => {
|
|
31
|
+
expect(valueCheck(t, 'target', '', 'BrowsingContextNameOrKeyword')).toStrictEqual([
|
|
32
|
+
'the "target" attribute must not be empty. It expects either "_blank", "_self", "_parent", "_top", "browsing context name" (https://html.spec.whatwg.org/multipage/browsers.html#valid-browsing-context-name-or-keyword)',
|
|
33
|
+
{
|
|
34
|
+
col: 0,
|
|
35
|
+
line: 0,
|
|
36
|
+
raw: '',
|
|
37
|
+
},
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('BCP47', () => {
|
|
42
|
+
expect(valueCheck(t, 'lang', '', 'BCP47')).toStrictEqual([
|
|
43
|
+
'the "lang" attribute must not be empty. It expects the BCP47 format (https://tools.ietf.org/rfc/bcp/bcp47.html)',
|
|
44
|
+
{
|
|
45
|
+
col: 0,
|
|
46
|
+
line: 0,
|
|
47
|
+
raw: '',
|
|
48
|
+
},
|
|
49
|
+
]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('DateTime', () => {
|
|
53
|
+
expect(valueCheck(t, 'datetime', '200-1-1', 'DateTime')).toStrictEqual([
|
|
54
|
+
'the year part of the "datetime" attribute expects four or more digits (https://html.spec.whatwg.org/multipage/text-level-semantics.html#datetime-value)',
|
|
55
|
+
{
|
|
56
|
+
col: 0,
|
|
57
|
+
line: 0,
|
|
58
|
+
raw: '200',
|
|
59
|
+
},
|
|
60
|
+
]);
|
|
61
|
+
expect(valueCheck(t, 'datetime', '2000-1-1', 'DateTime')).toStrictEqual([
|
|
62
|
+
'the month part of the "datetime" attribute expects two digits (https://html.spec.whatwg.org/multipage/text-level-semantics.html#datetime-value)',
|
|
63
|
+
{
|
|
64
|
+
col: 5,
|
|
65
|
+
line: 0,
|
|
66
|
+
raw: '1',
|
|
67
|
+
},
|
|
68
|
+
]);
|
|
69
|
+
expect(valueCheck(t, 'datetime', '00:00:00.0000', 'DateTime')).toStrictEqual([
|
|
70
|
+
'the fractional part part of the "datetime" attribute expects one to three digits (https://html.spec.whatwg.org/multipage/text-level-semantics.html#datetime-value)',
|
|
71
|
+
{
|
|
72
|
+
col: 9,
|
|
73
|
+
line: 0,
|
|
74
|
+
raw: '0000',
|
|
75
|
+
},
|
|
76
|
+
]);
|
|
77
|
+
});
|