@markuplint/rules 3.0.0-alpha.66 → 3.0.0-dev.24
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 +2 -2
- package/lib/attr-check.js +1 -1
- package/lib/attr-duplication/index.js +1 -1
- package/lib/attr-value-quotes/index.d.ts +3 -3
- package/lib/attr-value-quotes/index.js +1 -1
- package/lib/case-sensitive-attr-name/index.d.ts +1 -1
- package/lib/case-sensitive-attr-name/index.js +3 -3
- package/lib/case-sensitive-tag-name/index.d.ts +1 -1
- package/lib/case-sensitive-tag-name/index.js +3 -3
- package/lib/character-reference/index.js +1 -1
- package/lib/class-naming/index.d.ts +1 -1
- package/lib/class-naming/index.js +2 -2
- package/lib/create-message.d.ts +1 -1
- package/lib/create-message.js +5 -5
- package/lib/debug.d.ts +1 -1
- package/lib/deprecated-element/index.js +2 -2
- package/lib/doctype/index.d.ts +2 -2
- package/lib/doctype/index.js +2 -2
- package/lib/end-tag/index.js +3 -18
- package/lib/helpers.d.ts +8 -32
- package/lib/helpers.js +17 -81
- package/lib/index.d.ts +2 -62
- package/lib/index.js +4 -0
- package/lib/ineffective-attr/index.js +1 -1
- package/lib/invalid-attr/index.d.ts +3 -2
- package/lib/invalid-attr/index.js +19 -14
- package/lib/label-has-control/index.d.ts +2 -0
- package/lib/label-has-control/index.js +28 -0
- package/lib/landmark-roles/index.d.ts +3 -3
- package/lib/landmark-roles/index.js +3 -3
- package/lib/no-boolean-attr-value/index.js +1 -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 +34 -0
- package/lib/no-hard-code-id/index.js +1 -1
- package/lib/no-refer-to-non-existent-id/index.js +1 -1
- package/lib/no-use-event-handler-attr/index.d.ts +1 -1
- package/lib/no-use-event-handler-attr/index.js +6 -6
- package/lib/permitted-contents/choice.d.ts +3 -0
- package/lib/permitted-contents/choice.js +37 -0
- package/lib/permitted-contents/complex-branch.d.ts +13 -0
- package/lib/permitted-contents/complex-branch.js +27 -0
- package/lib/permitted-contents/content-model.d.ts +2 -0
- package/lib/permitted-contents/content-model.js +49 -0
- package/lib/permitted-contents/count-pattern.d.ts +13 -0
- package/lib/permitted-contents/count-pattern.js +155 -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 +1 -7
- package/lib/permitted-contents/index.js +76 -246
- package/lib/permitted-contents/matches-selector.d.ts +3 -0
- package/lib/permitted-contents/matches-selector.js +185 -0
- package/lib/permitted-contents/order.d.ts +13 -0
- package/lib/permitted-contents/order.js +89 -0
- package/lib/permitted-contents/recursive-branch.d.ts +4 -0
- package/lib/permitted-contents/recursive-branch.js +43 -0
- package/lib/permitted-contents/represent-transparent-nodes.d.ts +6 -0
- package/lib/permitted-contents/represent-transparent-nodes.js +76 -0
- package/lib/permitted-contents/start.d.ts +12 -0
- package/lib/permitted-contents/start.js +71 -0
- package/lib/permitted-contents/transparent.d.ts +2 -0
- package/lib/permitted-contents/transparent.js +29 -0
- package/lib/permitted-contents/types.d.ts +45 -0
- package/lib/permitted-contents/types.js +2 -0
- package/lib/permitted-contents/utils.d.ts +32 -0
- package/lib/permitted-contents/utils.js +184 -0
- package/lib/require-accessible-name/index.d.ts +1 -1
- package/lib/require-accessible-name/index.js +11 -3
- package/lib/required-attr/index.d.ts +2 -2
- package/lib/required-attr/index.js +1 -1
- package/lib/required-element/index.d.ts +1 -1
- package/lib/required-element/index.js +1 -1
- package/lib/required-h1/index.js +2 -2
- package/lib/use-list/index.d.ts +2 -2
- package/lib/use-list/index.js +3 -3
- package/lib/wai-aria/checkings/abstract-role.js +1 -1
- 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 +47 -0
- 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 +60 -0
- package/lib/wai-aria/checkings/{checking-required-owned-elements.d.ts → required-owned-elements.d.ts} +0 -0
- package/lib/wai-aria/checkings/required-owned-elements.js +101 -0
- package/lib/wai-aria/checkings/value.d.ts +6 -0
- package/lib/wai-aria/checkings/value.js +74 -4
- package/lib/wai-aria/index.js +25 -15
- package/lib/wai-aria/types.d.ts +3 -1
- package/package.json +12 -8
- package/schema.json +6 -0
- package/tsconfig.tsbuildinfo +1 -1
- 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/README.md
CHANGED
|
@@ -1,58 +1,24 @@
|
|
|
1
1
|
# @markuplint/rules
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@markuplint/rules)
|
|
4
|
-
[](https://travis-ci.org/markuplint/markuplint)
|
|
5
|
-
[](https://coveralls.io/github/markuplint/markuplint?branch=main)
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
**Built-in rules**
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
## Documentation
|
|
10
8
|
|
|
11
|
-
- [
|
|
12
|
-
- [`character-reference`](./src/character-reference)
|
|
13
|
-
- [`deprecated-attr`](./src/deprecated-attr)
|
|
14
|
-
- [`deprecated-element`](./src/deprecated-element)
|
|
15
|
-
- [`disallowed-element`](./src/disallowed-element)
|
|
16
|
-
- [`doctype`](./src/doctype)
|
|
17
|
-
- [`id-duplication`](./src/id-duplication)
|
|
18
|
-
- [`ineffective-attr`](./src/ineffective-attr)
|
|
19
|
-
- [`invalid-attr`](./src/invalid-attr)
|
|
20
|
-
- [`permitted-contents`](./src/permitted-contents)
|
|
21
|
-
- [`required-attr`](./src/required-attr)
|
|
22
|
-
- [`required-element`](./src/required-element)
|
|
23
|
-
|
|
24
|
-
### Accessibility
|
|
25
|
-
|
|
26
|
-
- [`landmark-roles`](./src/landmark-roles)
|
|
27
|
-
- [`no-refer-to-non-existent-id`](./src/no-refer-to-non-existent-id)
|
|
28
|
-
- [`required-h1`](./src/required-h1)
|
|
29
|
-
- [`use-list`](./src/use-list)
|
|
30
|
-
- [`wai-aria`](./src/wai-aria)
|
|
31
|
-
|
|
32
|
-
### Naming Convention
|
|
33
|
-
|
|
34
|
-
- [`class-naming`](./src/class-naming)
|
|
35
|
-
|
|
36
|
-
### Maintainability
|
|
37
|
-
|
|
38
|
-
- [`no-hard-code-id`](./src/no-hard-code-id)
|
|
39
|
-
- [`no-use-event-handler-attr`](./src/no-use-event-handler-attr)
|
|
40
|
-
|
|
41
|
-
### Style
|
|
42
|
-
|
|
43
|
-
- [`attr-value-quotes`](./src/attr-value-quotes)
|
|
44
|
-
- [`case-sensitive-attr-name`](./src/case-sensitive-attr-name)
|
|
45
|
-
- [`case-sensitive-tag-name`](./src/case-sensitive-tag-name)
|
|
46
|
-
- [`end-tag`](./src/end-tag)
|
|
47
|
-
- [`no-boolean-attr-value`](./src/no-boolean-attr-value)
|
|
48
|
-
- [`no-default-value`](./src/no-default-value)
|
|
9
|
+
- [Rules](https://markuplint.dev/rules/)
|
|
49
10
|
|
|
50
11
|
## Install
|
|
51
12
|
|
|
52
|
-
|
|
13
|
+
[`markuplint`](https://www.npmjs.com/package/markuplint) package includes this package.
|
|
53
14
|
|
|
54
|
-
|
|
15
|
+
<details>
|
|
16
|
+
<summary>If you are installing purposely, how below:</summary>
|
|
17
|
+
|
|
18
|
+
```shell
|
|
55
19
|
$ npm install -D @markuplint/rules
|
|
56
20
|
|
|
57
21
|
$ yarn add -D @markuplint/rules
|
|
58
22
|
```
|
|
23
|
+
|
|
24
|
+
</details>
|
package/lib/attr-check.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Translator } from '@markuplint/i18n';
|
|
2
2
|
import type { Attribute as AttrSpec, AttributeType } from '@markuplint/ml-spec';
|
|
3
|
-
|
|
3
|
+
type Invalid = {
|
|
4
4
|
invalidType: 'non-existent' | 'invalid-value';
|
|
5
5
|
message: string;
|
|
6
6
|
loc?: Loc;
|
|
7
7
|
};
|
|
8
|
-
|
|
8
|
+
type Loc = {
|
|
9
9
|
raw: string;
|
|
10
10
|
line: number;
|
|
11
11
|
col: number;
|
package/lib/attr-check.js
CHANGED
|
@@ -11,7 +11,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
11
11
|
continue;
|
|
12
12
|
}
|
|
13
13
|
const attrName = attr.name;
|
|
14
|
-
const name = node.
|
|
14
|
+
const name = node.elementType === 'html' ? attrName.toLowerCase() : attrName;
|
|
15
15
|
if (attrNameStack.includes(name)) {
|
|
16
16
|
const scope = attr.nameNode || attr;
|
|
17
17
|
report({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
1
|
+
export type Type = 'double' | 'single';
|
|
2
|
+
export type Quote = '"' | "'";
|
|
3
|
+
export type QuoteMap = {
|
|
4
4
|
[P in Type]: Quote;
|
|
5
5
|
};
|
|
6
6
|
declare const _default: import("@markuplint/ml-core").RuleSeed<Type, null>;
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
4
|
exports.default = (0, ml_core_1.createRule)({
|
|
5
|
-
|
|
5
|
+
defaultSeverity: 'warning',
|
|
6
6
|
defaultValue: 'lower',
|
|
7
7
|
async verify({ document, report, t }) {
|
|
8
8
|
await document.walkOn('Attr', attr => {
|
|
9
9
|
var _a, _b, _c, _d;
|
|
10
10
|
const el = attr.ownerElement;
|
|
11
|
-
if (el.isForeignElement || el.
|
|
11
|
+
if (el.isForeignElement || el.elementType !== 'html') {
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
const value = attr.rule.value;
|
|
@@ -46,7 +46,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
46
46
|
await document.walkOn('Attr', attr => {
|
|
47
47
|
var _a;
|
|
48
48
|
const el = attr.ownerElement;
|
|
49
|
-
if (el.isForeignElement || el.
|
|
49
|
+
if (el.isForeignElement || el.elementType !== 'html') {
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
52
|
const attrSpecs = (0, ml_core_1.getAttrSpecs)(el, document.specs);
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
4
|
exports.default = (0, ml_core_1.createRule)({
|
|
5
|
-
|
|
5
|
+
defaultSeverity: 'warning',
|
|
6
6
|
defaultValue: 'lower',
|
|
7
7
|
async verify({ document, report, t }) {
|
|
8
8
|
await document.walkOn('Element', el => {
|
|
9
|
-
if (el.isForeignElement || el.
|
|
9
|
+
if (el.isForeignElement || el.elementType !== 'html') {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
const ms = el.rule.severity === 'error' ? 'must' : 'should';
|
|
@@ -38,7 +38,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
38
38
|
},
|
|
39
39
|
async fix({ document }) {
|
|
40
40
|
await document.walkOn('Element', el => {
|
|
41
|
-
if (el.isForeignElement || el.
|
|
41
|
+
if (el.isForeignElement || el.elementType !== 'html') {
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
const deny = el.rule.value === 'lower' ? /[A-Z]/ : /[a-z]/;
|
|
@@ -40,7 +40,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
for (const targetNode of targetNodes) {
|
|
43
|
-
if (!('scope' in targetNode && 'line' in targetNode)) {
|
|
43
|
+
if (!('scope' in targetNode && 'line' in targetNode && targetNode.line != null)) {
|
|
44
44
|
continue;
|
|
45
45
|
}
|
|
46
46
|
const escapedText = targetNode.raw.replace(/&(?:[a-z]+|#[0-9]+|x[0-9]);/gi, $0 => '*'.repeat($0.length));
|
|
@@ -3,14 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
4
|
const helpers_1 = require("../helpers");
|
|
5
5
|
exports.default = (0, ml_core_1.createRule)({
|
|
6
|
-
|
|
6
|
+
defaultSeverity: 'warning',
|
|
7
7
|
defaultValue: null,
|
|
8
8
|
async verify({ document, report, t }) {
|
|
9
9
|
await document.walkOn('Element', el => {
|
|
10
10
|
if (!el.rule.value) {
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
|
-
const classPatterns = Array.isArray(el.rule.value) ? el.rule.value : [el.rule.value];
|
|
13
|
+
const classPatterns = (Array.isArray(el.rule.value) ? el.rule.value : [el.rule.value]).filter(className => className && typeof className === 'string');
|
|
14
14
|
const attrs = el.getAttributeToken('class');
|
|
15
15
|
for (const attr of attrs) {
|
|
16
16
|
if (attr.isDynamicValue) {
|
package/lib/create-message.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ import type { Translator } from '@markuplint/i18n';
|
|
|
2
2
|
import type { AttributeType } from '@markuplint/ml-spec';
|
|
3
3
|
import type { UnmatchedResult } from '@markuplint/types';
|
|
4
4
|
export declare function createMessageValueExpected(t: Translator, baseTarget: string, type: AttributeType, matches: UnmatchedResult): string;
|
|
5
|
-
export declare function __createMessageValueExpected(t: Translator, baseTarget: string, expected: string | null, matches: Pick<UnmatchedResult, 'partName' | 'reason' | 'raw' | '
|
|
5
|
+
export declare function __createMessageValueExpected(t: Translator, baseTarget: string, expected: string | null, matches: Pick<UnmatchedResult, 'partName' | 'reason' | 'raw' | 'candidate' | 'ref' | 'extra'>): string;
|
package/lib/create-message.js
CHANGED
|
@@ -26,7 +26,7 @@ function __createMessageValueExpected(t, baseTarget, expected, matches) {
|
|
|
26
26
|
let reasonPart;
|
|
27
27
|
let expectPart;
|
|
28
28
|
let unnecessaryPart;
|
|
29
|
-
let
|
|
29
|
+
let candidatePart;
|
|
30
30
|
let expectOrNeed = 'expects';
|
|
31
31
|
if (matches.partName) {
|
|
32
32
|
if (matches.partName === 'the content of the list') {
|
|
@@ -188,10 +188,10 @@ function __createMessageValueExpected(t, baseTarget, expected, matches) {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
|
-
if (matches.
|
|
192
|
-
|
|
191
|
+
if (matches.candidate) {
|
|
192
|
+
candidatePart = t('Did you mean "{0*}"?', matches.candidate);
|
|
193
193
|
}
|
|
194
|
-
let message = [reasonPart, unnecessaryPart, expectPart,
|
|
194
|
+
let message = [reasonPart, unnecessaryPart, expectPart, candidatePart].filter(s => s).join(t('. '));
|
|
195
195
|
if (matches.ref) {
|
|
196
196
|
message += ` (${matches.ref})`;
|
|
197
197
|
}
|
|
@@ -232,7 +232,7 @@ function expectValueToWord(t, expect, type) {
|
|
|
232
232
|
return expect.value ? `%${expect.value}%` : '';
|
|
233
233
|
case 'format':
|
|
234
234
|
return t('the {0} format', expect.value);
|
|
235
|
-
case '
|
|
235
|
+
case 'regexp':
|
|
236
236
|
return t('{0} ({1})', 'regular expression', expect.value);
|
|
237
237
|
case 'syntax':
|
|
238
238
|
if ((0, types_1.isKeyword)(type) && type[0] === '<') {
|
package/lib/debug.d.ts
CHANGED
|
@@ -6,10 +6,10 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
6
6
|
await document.walkOn('Element', el => {
|
|
7
7
|
if (!(el.namespaceURI === 'http://www.w3.org/1999/xhtml' ||
|
|
8
8
|
el.namespaceURI === 'http://www.w3.org/2000/svg') ||
|
|
9
|
-
el.
|
|
9
|
+
el.elementType !== 'html') {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
-
const spec = (0, ml_core_1.getSpec)(el, document.specs);
|
|
12
|
+
const spec = (0, ml_core_1.getSpec)(el, document.specs.specs);
|
|
13
13
|
if (spec && (spec.obsolete || spec.deprecated || spec.nonStandard)) {
|
|
14
14
|
const message = t('{0} is {1:c}', t('the "{0*}" {1}', el.localName, 'element'), spec.deprecated ? 'deprecated' : spec.obsolete ? 'obsolete' : 'non-standard');
|
|
15
15
|
report({
|
package/lib/doctype/index.d.ts
CHANGED
package/lib/doctype/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const ml_core_1 = require("@markuplint/ml-core");
|
|
|
4
4
|
exports.default = (0, ml_core_1.createRule)({
|
|
5
5
|
defaultValue: 'always',
|
|
6
6
|
defaultOptions: {
|
|
7
|
-
|
|
7
|
+
denyObsoleteType: true,
|
|
8
8
|
},
|
|
9
9
|
verify({ document, report, t }) {
|
|
10
10
|
if (document.isFragment) {
|
|
@@ -23,7 +23,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
23
23
|
if ((doctype.name.toLowerCase() === 'html' && doctype.publicId) || doctype.systemId) {
|
|
24
24
|
report({
|
|
25
25
|
scope: doctype,
|
|
26
|
-
message: t('Never {0} {1}', '
|
|
26
|
+
message: t('Never {0} {1}', 'declare', 'obsolete doctype'),
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
},
|
package/lib/end-tag/index.js
CHANGED
|
@@ -1,24 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
|
-
const
|
|
5
|
-
'area',
|
|
6
|
-
'base',
|
|
7
|
-
'br',
|
|
8
|
-
'col',
|
|
9
|
-
'embed',
|
|
10
|
-
'hr',
|
|
11
|
-
'img',
|
|
12
|
-
'input',
|
|
13
|
-
'link',
|
|
14
|
-
'meta',
|
|
15
|
-
'param',
|
|
16
|
-
'source',
|
|
17
|
-
'track',
|
|
18
|
-
'wbr',
|
|
19
|
-
];
|
|
4
|
+
const ml_spec_1 = require("@markuplint/ml-spec");
|
|
20
5
|
exports.default = (0, ml_core_1.createRule)({
|
|
21
|
-
|
|
6
|
+
defaultSeverity: 'warning',
|
|
22
7
|
async verify({ document, report, t }) {
|
|
23
8
|
if (document.endTag === 'never') {
|
|
24
9
|
return;
|
|
@@ -28,7 +13,7 @@ exports.default = (0, ml_core_1.createRule)({
|
|
|
28
13
|
if (el.isOmitted) {
|
|
29
14
|
return;
|
|
30
15
|
}
|
|
31
|
-
if (
|
|
16
|
+
if ((0, ml_spec_1.isVoidElement)(el)) {
|
|
32
17
|
return;
|
|
33
18
|
}
|
|
34
19
|
if (el.closeTag != null) {
|
package/lib/helpers.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Log } from './debug';
|
|
2
2
|
import type { Translator } from '@markuplint/i18n';
|
|
3
3
|
import type { Element, RuleConfigValue, Document } from '@markuplint/ml-core';
|
|
4
|
-
import type {
|
|
4
|
+
import type { Attribute } from '@markuplint/ml-spec';
|
|
5
5
|
export declare function attrMatches<T extends RuleConfigValue, R>(node: Element<T, R>, condition: Attribute['condition']): boolean;
|
|
6
6
|
export declare function match(needle: string, pattern: string): boolean;
|
|
7
7
|
/**
|
|
@@ -30,42 +30,18 @@ export declare function isValidAttr(t: Translator, name: string, value: string,
|
|
|
30
30
|
} | undefined;
|
|
31
31
|
};
|
|
32
32
|
export declare function toNormalizedValue(value: string, spec: Attribute): string;
|
|
33
|
-
/**
|
|
34
|
-
*
|
|
35
|
-
* @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
|
|
36
|
-
*
|
|
37
|
-
* @param type
|
|
38
|
-
* @param value
|
|
39
|
-
* @param tokenEnum
|
|
40
|
-
*/
|
|
41
|
-
export declare function checkAriaValue(type: string, value: string, tokenEnum: string[]): boolean;
|
|
42
|
-
export declare function checkAria(specs: Readonly<MLMLSpec>, attrName: string, currentValue: string, version: ARIAVersion, role?: string): {
|
|
43
|
-
currentValue: string;
|
|
44
|
-
isValid: boolean;
|
|
45
|
-
} | {
|
|
46
|
-
currentValue: string;
|
|
47
|
-
isValid: boolean;
|
|
48
|
-
name: string;
|
|
49
|
-
type: "property" | "state";
|
|
50
|
-
deprecated?: true | undefined;
|
|
51
|
-
isGlobal?: true | undefined;
|
|
52
|
-
value: import("@markuplint/ml-spec").ARIAAttributeValue;
|
|
53
|
-
conditionalValue?: {
|
|
54
|
-
role: string[];
|
|
55
|
-
value: import("@markuplint/ml-spec").ARIAAttributeValue;
|
|
56
|
-
}[] | undefined;
|
|
57
|
-
enum: string[];
|
|
58
|
-
defaultValue?: string | undefined;
|
|
59
|
-
equivalentHtmlAttrs?: import("@markuplint/ml-spec").EquivalentHtmlAttr[] | undefined;
|
|
60
|
-
valueDescriptions?: Record<string, string> | undefined;
|
|
61
|
-
};
|
|
62
33
|
export declare function accnameMayBeMutable(el: Element<any, any>, document: Document<any, any>): boolean;
|
|
63
|
-
export declare function getOwnedLabel<V extends RuleConfigValue, O>(el: Element<V, O>,
|
|
34
|
+
export declare function getOwnedLabel<V extends RuleConfigValue, O>(el: Element<V, O>, document: Document<V, O>): Element<V, O> | null;
|
|
64
35
|
export declare function decodeCharRef(characterReference: string): string;
|
|
65
36
|
export declare class Collection<T> {
|
|
66
37
|
#private;
|
|
67
38
|
constructor(...items: (T | null | undefined)[]);
|
|
39
|
+
[Symbol.iterator](): Iterator<T>;
|
|
68
40
|
add(...items: (T | null | undefined)[]): void;
|
|
69
41
|
toArray(): readonly T[];
|
|
70
|
-
[Symbol.iterator](): Iterator<T>;
|
|
71
42
|
}
|
|
43
|
+
type Writeable<T> = {
|
|
44
|
+
-readonly [P in keyof T]: T[P];
|
|
45
|
+
};
|
|
46
|
+
export declare function deepCopy<T>(value: T): Writeable<T>;
|
|
47
|
+
export {};
|
package/lib/helpers.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var _Collection_items;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.
|
|
4
|
+
exports.deepCopy = exports.Collection = exports.decodeCharRef = exports.getOwnedLabel = exports.accnameMayBeMutable = exports.toNormalizedValue = exports.isValidAttr = exports.rePCENChar = exports.match = exports.attrMatches = void 0;
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
|
-
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
const structured_clone_1 = tslib_1.__importDefault(require("@ungap/structured-clone"));
|
|
7
8
|
const html_entities_1 = require("html-entities");
|
|
8
9
|
const attr_check_1 = require("./attr-check");
|
|
9
10
|
function attrMatches(node, condition) {
|
|
@@ -105,99 +106,30 @@ function toNormalizedValue(value, spec) {
|
|
|
105
106
|
return normalized;
|
|
106
107
|
}
|
|
107
108
|
exports.toNormalizedValue = toNormalizedValue;
|
|
108
|
-
/**
|
|
109
|
-
*
|
|
110
|
-
* @see https://www.w3.org/TR/wai-aria-1.2/#propcharacteristic_value
|
|
111
|
-
*
|
|
112
|
-
* @param type
|
|
113
|
-
* @param value
|
|
114
|
-
* @param tokenEnum
|
|
115
|
-
*/
|
|
116
|
-
function checkAriaValue(type, value, tokenEnum) {
|
|
117
|
-
switch (type) {
|
|
118
|
-
case 'token': {
|
|
119
|
-
return tokenEnum.includes(value);
|
|
120
|
-
}
|
|
121
|
-
case 'token list': {
|
|
122
|
-
const list = value.split(/\s+/g).map(s => s.trim());
|
|
123
|
-
return list.every(token => tokenEnum.includes(token));
|
|
124
|
-
}
|
|
125
|
-
case 'string':
|
|
126
|
-
case 'ID reference':
|
|
127
|
-
case 'ID reference list': {
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
case 'true/false': {
|
|
131
|
-
return ['true', 'false'].includes(value);
|
|
132
|
-
}
|
|
133
|
-
case 'tristate': {
|
|
134
|
-
return ['mixed', 'true', 'false', 'undefined'].includes(value);
|
|
135
|
-
}
|
|
136
|
-
case 'true/false/undefined': {
|
|
137
|
-
return ['true', 'false', 'undefined'].includes(value);
|
|
138
|
-
}
|
|
139
|
-
case 'integer': {
|
|
140
|
-
return parseInt(value).toString() === value;
|
|
141
|
-
}
|
|
142
|
-
case 'number': {
|
|
143
|
-
return parseFloat(value).toString() === value;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
// For skipping checking
|
|
147
|
-
return true;
|
|
148
|
-
}
|
|
149
|
-
exports.checkAriaValue = checkAriaValue;
|
|
150
|
-
function checkAria(specs, attrName, currentValue, version, role) {
|
|
151
|
-
const ariaAttrs = (0, ml_core_1.ariaSpecs)(specs, version).props;
|
|
152
|
-
const aria = ariaAttrs.find(a => a.name === attrName);
|
|
153
|
-
if (!aria) {
|
|
154
|
-
return {
|
|
155
|
-
currentValue,
|
|
156
|
-
// For skipping checking
|
|
157
|
-
isValid: true,
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
let valueType = aria.value;
|
|
161
|
-
if (role && aria.conditionalValue) {
|
|
162
|
-
for (const cond of aria.conditionalValue) {
|
|
163
|
-
if (cond.role.includes(role)) {
|
|
164
|
-
valueType = cond.value;
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
const isValid = checkAriaValue(valueType, currentValue, aria.enum);
|
|
170
|
-
return {
|
|
171
|
-
...aria,
|
|
172
|
-
currentValue,
|
|
173
|
-
isValid,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
exports.checkAria = checkAria;
|
|
177
109
|
function accnameMayBeMutable(el, document) {
|
|
178
110
|
if (el.hasMutableAttributes() || el.hasMutableChildren(true)) {
|
|
179
111
|
return true;
|
|
180
112
|
}
|
|
181
|
-
const
|
|
182
|
-
if (
|
|
113
|
+
const ownedLabel = getOwnedLabel(el, document);
|
|
114
|
+
if (ownedLabel && (ownedLabel.hasMutableAttributes() || ownedLabel.hasMutableChildren(true))) {
|
|
183
115
|
return true;
|
|
184
116
|
}
|
|
185
117
|
return false;
|
|
186
118
|
}
|
|
187
119
|
exports.accnameMayBeMutable = accnameMayBeMutable;
|
|
188
120
|
const labelable = ['button', 'input:not([type=hidden])', 'meter', 'output', 'progress', 'select', 'textarea'];
|
|
189
|
-
function getOwnedLabel(el,
|
|
121
|
+
function getOwnedLabel(el, document) {
|
|
190
122
|
if (!labelable.some(cond => el.matches(cond))) {
|
|
191
123
|
return null;
|
|
192
124
|
}
|
|
193
|
-
let
|
|
194
|
-
if (!
|
|
125
|
+
let ownedLabel = el.closest('label');
|
|
126
|
+
if (!ownedLabel) {
|
|
195
127
|
const id = el.getAttribute('id');
|
|
196
128
|
if (id) {
|
|
197
|
-
|
|
129
|
+
ownedLabel = document.querySelector(`label[for="${id}"]`);
|
|
198
130
|
}
|
|
199
131
|
}
|
|
200
|
-
return
|
|
132
|
+
return ownedLabel;
|
|
201
133
|
}
|
|
202
134
|
exports.getOwnedLabel = getOwnedLabel;
|
|
203
135
|
function decodeCharRef(characterReference) {
|
|
@@ -209,6 +141,9 @@ class Collection {
|
|
|
209
141
|
_Collection_items.set(this, new Set());
|
|
210
142
|
this.add(...items);
|
|
211
143
|
}
|
|
144
|
+
[(_Collection_items = new WeakMap(), Symbol.iterator)]() {
|
|
145
|
+
return tslib_1.__classPrivateFieldGet(this, _Collection_items, "f").values();
|
|
146
|
+
}
|
|
212
147
|
add(...items) {
|
|
213
148
|
for (const item of items) {
|
|
214
149
|
if (item == null) {
|
|
@@ -220,8 +155,9 @@ class Collection {
|
|
|
220
155
|
toArray() {
|
|
221
156
|
return Object.freeze(Array.from(tslib_1.__classPrivateFieldGet(this, _Collection_items, "f")));
|
|
222
157
|
}
|
|
223
|
-
[(_Collection_items = new WeakMap(), Symbol.iterator)]() {
|
|
224
|
-
return tslib_1.__classPrivateFieldGet(this, _Collection_items, "f").values();
|
|
225
|
-
}
|
|
226
158
|
}
|
|
227
159
|
exports.Collection = Collection;
|
|
160
|
+
function deepCopy(value) {
|
|
161
|
+
return (0, structured_clone_1.default)(value);
|
|
162
|
+
}
|
|
163
|
+
exports.deepCopy = deepCopy;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,63 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
'attr-value-quotes': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./attr-value-quotes").Type, null>;
|
|
4
|
-
'case-sensitive-attr-name': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./case-sensitive-attr-name").Value, null>;
|
|
5
|
-
'case-sensitive-tag-name': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./case-sensitive-tag-name").Value, null>;
|
|
6
|
-
'character-reference': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
|
|
7
|
-
'class-naming': import("packages/@markuplint/ml-core/lib").RuleSeed<import("./class-naming").Value, null>;
|
|
8
|
-
'deprecated-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
|
|
9
|
-
'deprecated-element': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
|
|
10
|
-
'disallowed-element': import("packages/@markuplint/ml-core/lib").RuleSeed<string[], null>;
|
|
11
|
-
doctype: import("packages/@markuplint/ml-core/lib").RuleSeed<"always", {
|
|
12
|
-
denyObsolateType: boolean;
|
|
13
|
-
}>;
|
|
14
|
-
'end-tag': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, null>;
|
|
15
|
-
'id-duplication': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
|
|
16
|
-
'ineffective-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
|
|
17
|
-
'invalid-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
|
|
18
|
-
attrs?: Record<string, {
|
|
19
|
-
enum: [string, ...string[]];
|
|
20
|
-
} | {
|
|
21
|
-
pattern: string;
|
|
22
|
-
} | {
|
|
23
|
-
type: import("packages/@markuplint/ml-spec/lib").AttributeType;
|
|
24
|
-
} | {
|
|
25
|
-
disallowed: true;
|
|
26
|
-
}> | undefined;
|
|
27
|
-
ignoreAttrNamePrefix?: string | string[] | undefined;
|
|
28
|
-
}>;
|
|
29
|
-
'landmark-roles': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
|
|
30
|
-
ignoreRoles: (("banner" | "main" | "complementary" | "contentinfo") | "form" | "navigation" | "region")[];
|
|
31
|
-
labelEachArea: boolean;
|
|
32
|
-
}>;
|
|
33
|
-
'no-boolean-attr-value': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
|
|
34
|
-
'no-default-value': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
|
|
35
|
-
'no-hard-code-id': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, null>;
|
|
36
|
-
'no-refer-to-non-existent-id': import("packages/@markuplint/ml-core/lib").RuleSeed<import("packages/@markuplint/ml-config/src").RuleConfigValue, {
|
|
37
|
-
ariaVersion: import("packages/@markuplint/ml-spec/lib").ARIAVersion;
|
|
38
|
-
}>;
|
|
39
|
-
'no-use-event-handler-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
|
|
40
|
-
ignore?: string | string[] | undefined;
|
|
41
|
-
}>;
|
|
42
|
-
'permitted-contents': import("packages/@markuplint/ml-core/lib").RuleSeed<(import("packages/@markuplint/ml-spec/lib").ContentModel & {
|
|
43
|
-
tag: string;
|
|
44
|
-
})[], {
|
|
45
|
-
ignoreHasMutableChildren: boolean;
|
|
46
|
-
}>;
|
|
47
|
-
'require-accessible-name': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, {
|
|
48
|
-
ariaVersion: import("packages/@markuplint/ml-spec/lib").ARIAVersion;
|
|
49
|
-
}>;
|
|
50
|
-
'required-attr': import("packages/@markuplint/ml-core/lib").RuleSeed<string | (string | {
|
|
51
|
-
name: string;
|
|
52
|
-
value: string | string[];
|
|
53
|
-
})[], null>;
|
|
54
|
-
'required-element': import("packages/@markuplint/ml-core/lib").RuleSeed<string[], {
|
|
55
|
-
ignoreHasMutableContents: boolean;
|
|
56
|
-
}>;
|
|
57
|
-
'required-h1': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, import("./required-h1").Options>;
|
|
58
|
-
'use-list': import("packages/@markuplint/ml-core/lib").RuleSeed<string[], {
|
|
59
|
-
spaceNeededBullets?: string[] | undefined;
|
|
60
|
-
}>;
|
|
61
|
-
'wai-aria': import("packages/@markuplint/ml-core/lib").RuleSeed<boolean, import("./wai-aria/types").Options>;
|
|
62
|
-
};
|
|
1
|
+
import type { AnyRuleSeed } from '@markuplint/ml-core';
|
|
2
|
+
declare const _default: Record<string, AnyRuleSeed>;
|
|
63
3
|
export default _default;
|
package/lib/index.js
CHANGED
|
@@ -15,9 +15,11 @@ const end_tag_1 = tslib_1.__importDefault(require("./end-tag"));
|
|
|
15
15
|
const id_duplication_1 = tslib_1.__importDefault(require("./id-duplication"));
|
|
16
16
|
const ineffective_attr_1 = tslib_1.__importDefault(require("./ineffective-attr"));
|
|
17
17
|
const invalid_attr_1 = tslib_1.__importDefault(require("./invalid-attr"));
|
|
18
|
+
const label_has_control_1 = tslib_1.__importDefault(require("./label-has-control"));
|
|
18
19
|
const landmark_roles_1 = tslib_1.__importDefault(require("./landmark-roles"));
|
|
19
20
|
const no_boolean_attr_value_1 = tslib_1.__importDefault(require("./no-boolean-attr-value"));
|
|
20
21
|
const no_default_value_1 = tslib_1.__importDefault(require("./no-default-value"));
|
|
22
|
+
const no_empty_palpable_content_1 = tslib_1.__importDefault(require("./no-empty-palpable-content"));
|
|
21
23
|
const no_hard_code_id_1 = tslib_1.__importDefault(require("./no-hard-code-id"));
|
|
22
24
|
const no_refer_to_non_existent_id_1 = tslib_1.__importDefault(require("./no-refer-to-non-existent-id"));
|
|
23
25
|
const no_use_event_handler_attr_1 = tslib_1.__importDefault(require("./no-use-event-handler-attr"));
|
|
@@ -43,9 +45,11 @@ exports.default = {
|
|
|
43
45
|
'id-duplication': id_duplication_1.default,
|
|
44
46
|
'ineffective-attr': ineffective_attr_1.default,
|
|
45
47
|
'invalid-attr': invalid_attr_1.default,
|
|
48
|
+
'label-has-control': label_has_control_1.default,
|
|
46
49
|
'landmark-roles': landmark_roles_1.default,
|
|
47
50
|
'no-boolean-attr-value': no_boolean_attr_value_1.default,
|
|
48
51
|
'no-default-value': no_default_value_1.default,
|
|
52
|
+
'no-empty-palpable-content': no_empty_palpable_content_1.default,
|
|
49
53
|
'no-hard-code-id': no_hard_code_id_1.default,
|
|
50
54
|
'no-refer-to-non-existent-id': no_refer_to_non_existent_id_1.default,
|
|
51
55
|
'no-use-event-handler-attr': no_use_event_handler_attr_1.default,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const ml_core_1 = require("@markuplint/ml-core");
|
|
4
4
|
exports.default = (0, ml_core_1.createRule)({
|
|
5
|
-
|
|
5
|
+
defaultSeverity: 'warning',
|
|
6
6
|
async verify({ document, report, t }) {
|
|
7
7
|
await document.walkOn('Attr', attr => {
|
|
8
8
|
const attrSpec = (0, ml_core_1.getAttrSpecs)(attr.ownerElement, document.specs);
|