@flint.fyi/jsx 0.0.0 → 0.3.1
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/LICENSE.md +20 -0
- package/lib/index.js +1 -2
- package/lib/plugin.d.ts +309 -1
- package/lib/plugin.js +12 -6
- package/lib/rules/accessKeys.d.ts +8 -1
- package/lib/rules/accessKeys.js +2 -3
- package/lib/rules/altTexts.d.ts +8 -1
- package/lib/rules/altTexts.js +6 -16
- package/lib/rules/anchorAmbiguousText.d.ts +8 -1
- package/lib/rules/anchorAmbiguousText.js +2 -5
- package/lib/rules/anchorContent.d.ts +8 -1
- package/lib/rules/anchorContent.js +2 -3
- package/lib/rules/anchorValidity.d.ts +8 -1
- package/lib/rules/anchorValidity.js +4 -5
- package/lib/rules/ariaActiveDescendantTabIndex.d.ts +8 -1
- package/lib/rules/ariaActiveDescendantTabIndex.js +4 -7
- package/lib/rules/ariaHiddenFocusables.d.ts +8 -1
- package/lib/rules/ariaHiddenFocusables.js +7 -9
- package/lib/rules/ariaPropTypes.d.ts +8 -1
- package/lib/rules/ariaPropTypes.js +6 -9
- package/lib/rules/ariaProps.d.ts +8 -1
- package/lib/rules/ariaProps.js +2 -3
- package/lib/rules/ariaRoleValidity.d.ts +8 -1
- package/lib/rules/ariaRoleValidity.js +3 -4
- package/lib/rules/ariaUnsupportedElements.d.ts +8 -1
- package/lib/rules/ariaUnsupportedElements.js +2 -3
- package/lib/rules/autoFocusProps.d.ts +8 -1
- package/lib/rules/autoFocusProps.js +4 -6
- package/lib/rules/autocomplete.d.ts +8 -1
- package/lib/rules/autocomplete.js +3 -4
- package/lib/rules/booleanValues.d.ts +8 -1
- package/lib/rules/booleanValues.js +2 -3
- package/lib/rules/bracedStatements.d.ts +8 -1
- package/lib/rules/bracedStatements.js +1 -2
- package/lib/rules/buttonTypes.d.ts +8 -1
- package/lib/rules/buttonTypes.js +3 -4
- package/lib/rules/childrenProps.d.ts +8 -1
- package/lib/rules/childrenProps.js +1 -2
- package/lib/rules/clickEventKeyEvents.d.ts +8 -1
- package/lib/rules/clickEventKeyEvents.js +2 -3
- package/lib/rules/commentTextNodes.d.ts +8 -1
- package/lib/rules/commentTextNodes.js +2 -3
- package/lib/rules/distractingElements.d.ts +8 -1
- package/lib/rules/distractingElements.js +2 -3
- package/lib/rules/elementChildrenValidity.d.ts +8 -1
- package/lib/rules/elementChildrenValidity.js +1 -2
- package/lib/rules/headingContents.d.ts +8 -1
- package/lib/rules/headingContents.js +5 -6
- package/lib/rules/htmlLangs.d.ts +8 -1
- package/lib/rules/htmlLangs.js +2 -3
- package/lib/rules/iframeTitles.d.ts +8 -1
- package/lib/rules/iframeTitles.js +3 -4
- package/lib/rules/interactiveElementRoles.d.ts +8 -1
- package/lib/rules/interactiveElementRoles.js +3 -4
- package/lib/rules/interactiveElementsFocusable.d.ts +8 -1
- package/lib/rules/interactiveElementsFocusable.js +7 -8
- package/lib/rules/labelAssociatedControls.d.ts +8 -1
- package/lib/rules/labelAssociatedControls.js +6 -7
- package/lib/rules/langValidity.d.ts +8 -1
- package/lib/rules/langValidity.js +1 -2
- package/lib/rules/mediaCaptions.d.ts +8 -1
- package/lib/rules/mediaCaptions.js +12 -13
- package/lib/rules/mouseEventKeyEvents.d.ts +8 -1
- package/lib/rules/mouseEventKeyEvents.js +2 -3
- package/lib/rules/nonInteractiveElementInteractions.d.ts +8 -1
- package/lib/rules/nonInteractiveElementInteractions.js +3 -4
- package/lib/rules/nonInteractiveElementRoles.d.ts +8 -1
- package/lib/rules/nonInteractiveElementRoles.js +3 -4
- package/lib/rules/nonInteractiveElementTabIndexes.d.ts +8 -1
- package/lib/rules/nonInteractiveElementTabIndexes.js +7 -8
- package/lib/rules/propDuplicates.d.ts +8 -1
- package/lib/rules/propDuplicates.js +2 -3
- package/lib/rules/roleRedundancies.d.ts +8 -1
- package/lib/rules/roleRedundancies.js +3 -4
- package/lib/rules/roleRequiredAriaProps.d.ts +8 -1
- package/lib/rules/roleRequiredAriaProps.js +3 -4
- package/lib/rules/roleSupportedAriaProps.d.ts +8 -1
- package/lib/rules/roleSupportedAriaProps.js +3 -4
- package/lib/rules/roleTags.d.ts +8 -1
- package/lib/rules/roleTags.js +2 -3
- package/lib/rules/ruleCreator.js +1 -2
- package/lib/rules/scopeProps.d.ts +8 -1
- package/lib/rules/scopeProps.js +2 -3
- package/lib/rules/staticElementInteractions.d.ts +8 -1
- package/lib/rules/staticElementInteractions.js +2 -3
- package/lib/rules/svgTitles.d.ts +8 -1
- package/lib/rules/svgTitles.js +5 -6
- package/lib/rules/tabIndexPositiveValues.d.ts +8 -1
- package/lib/rules/tabIndexPositiveValues.js +4 -5
- package/lib/rules/unescapedEntities.d.ts +8 -1
- package/lib/rules/unescapedEntities.js +1 -2
- package/lib/rules/unnecessaryFragments.d.ts +8 -1
- package/lib/rules/unnecessaryFragments.js +3 -4
- package/package.json +46 -51
- package/lib/jsx.d.ts +0 -8
- package/lib/jsx.js +0 -100
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/nonInteractiveElementRoles.ts
|
|
6
5
|
const nonInteractiveElements = new Set([
|
|
7
6
|
"article",
|
|
@@ -79,7 +78,7 @@ var nonInteractiveElementRoles_default = ruleCreator.createRule(typescriptLangua
|
|
|
79
78
|
about: {
|
|
80
79
|
description: "Reports non-interactive elements with interactive ARIA roles.",
|
|
81
80
|
id: "nonInteractiveElementRoles",
|
|
82
|
-
presets: ["logical"]
|
|
81
|
+
presets: ["logical", "logicalStrict"]
|
|
83
82
|
},
|
|
84
83
|
messages: { invalidRole: {
|
|
85
84
|
primary: "Non-interactive element <{{ element }}> should not have the interactive role `'{{ role }}'`.",
|
|
@@ -96,7 +95,7 @@ var nonInteractiveElementRoles_default = ruleCreator.createRule(typescriptLangua
|
|
|
96
95
|
const elementName = element.tagName.text.toLowerCase();
|
|
97
96
|
if (!nonInteractiveElements.has(elementName)) return;
|
|
98
97
|
const roleProperty = element.attributes.properties.find((property) => property.kind === SyntaxKind.JsxAttribute && property.name.kind === SyntaxKind.Identifier && property.name.text === "role");
|
|
99
|
-
if (
|
|
98
|
+
if (roleProperty?.kind !== SyntaxKind.JsxAttribute || roleProperty.initializer?.kind !== SyntaxKind.StringLiteral) return;
|
|
100
99
|
const role = roleProperty.initializer.text;
|
|
101
100
|
if (interactiveRoles.has(role) && !allowedExceptions[elementName]?.has(role)) context.report({
|
|
102
101
|
data: {
|
|
@@ -113,7 +112,7 @@ var nonInteractiveElementRoles_default = ruleCreator.createRule(typescriptLangua
|
|
|
113
112
|
} };
|
|
114
113
|
}
|
|
115
114
|
});
|
|
116
|
-
|
|
117
115
|
//#endregion
|
|
118
116
|
export { nonInteractiveElementRoles_default as default };
|
|
117
|
+
|
|
119
118
|
//# sourceMappingURL=nonInteractiveElementRoles.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports non-interactive elements with positive or zero tabIndex values.";
|
|
3
|
+
readonly id: "nonInteractiveElementTabIndexes";
|
|
4
|
+
readonly presets: ["logical", "logicalStrict"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "nonInteractiveTabIndex", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=nonInteractiveElementTabIndexes.d.ts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/nonInteractiveElementTabIndexes.ts
|
|
6
5
|
const nonInteractiveElements = new Set([
|
|
7
6
|
"article",
|
|
@@ -49,7 +48,7 @@ var nonInteractiveElementTabIndexes_default = ruleCreator.createRule(typescriptL
|
|
|
49
48
|
about: {
|
|
50
49
|
description: "Reports non-interactive elements with positive or zero tabIndex values.",
|
|
51
50
|
id: "nonInteractiveElementTabIndexes",
|
|
52
|
-
presets: ["logical"]
|
|
51
|
+
presets: ["logical", "logicalStrict"]
|
|
53
52
|
},
|
|
54
53
|
messages: { nonInteractiveTabIndex: {
|
|
55
54
|
primary: "Non-interactive element `<{{ element }}>` should not have an explicit, non-negative `tabIndex`.",
|
|
@@ -69,19 +68,19 @@ var nonInteractiveElementTabIndexes_default = ruleCreator.createRule(typescriptL
|
|
|
69
68
|
if (!attr.initializer) return;
|
|
70
69
|
if (attr.initializer.kind === SyntaxKind.StringLiteral) {
|
|
71
70
|
const value = parseInt(attr.initializer.text, 10);
|
|
72
|
-
return isNaN(value) ? void 0 : value;
|
|
71
|
+
return Number.isNaN(value) ? void 0 : value;
|
|
73
72
|
}
|
|
74
73
|
if (attr.initializer.kind === SyntaxKind.JsxExpression) {
|
|
75
74
|
const expr = attr.initializer.expression;
|
|
76
|
-
if (expr
|
|
75
|
+
if (expr?.kind === SyntaxKind.NumericLiteral) {
|
|
77
76
|
const value = parseInt(expr.text, 10);
|
|
78
|
-
return isNaN(value) ? void 0 : value;
|
|
77
|
+
return Number.isNaN(value) ? void 0 : value;
|
|
79
78
|
}
|
|
80
79
|
}
|
|
81
80
|
}
|
|
82
81
|
function getRoleValue(attributes) {
|
|
83
82
|
const roleProperty = attributes.properties.find((property) => property.kind === SyntaxKind.JsxAttribute && property.name.kind === SyntaxKind.Identifier && property.name.text === "role");
|
|
84
|
-
if (roleProperty
|
|
83
|
+
if (roleProperty?.kind === SyntaxKind.JsxAttribute && roleProperty.initializer?.kind === SyntaxKind.StringLiteral) return roleProperty.initializer.text;
|
|
85
84
|
}
|
|
86
85
|
function checkTabIndex(node, { sourceFile }) {
|
|
87
86
|
if (node.tagName.kind !== SyntaxKind.Identifier) return;
|
|
@@ -90,7 +89,7 @@ var nonInteractiveElementTabIndexes_default = ruleCreator.createRule(typescriptL
|
|
|
90
89
|
const role = getRoleValue(node.attributes);
|
|
91
90
|
if (role && interactiveRoles.has(role)) return;
|
|
92
91
|
const tabIndexProperty = node.attributes.properties.find((property) => property.kind === SyntaxKind.JsxAttribute && property.name.kind === SyntaxKind.Identifier && property.name.text === "tabIndex");
|
|
93
|
-
if (
|
|
92
|
+
if (tabIndexProperty?.kind !== SyntaxKind.JsxAttribute) return;
|
|
94
93
|
const tabIndexValue = getTabIndexValue(tabIndexProperty);
|
|
95
94
|
if (tabIndexValue !== void 0 && tabIndexValue >= 0) context.report({
|
|
96
95
|
data: { element: elementName },
|
|
@@ -104,7 +103,7 @@ var nonInteractiveElementTabIndexes_default = ruleCreator.createRule(typescriptL
|
|
|
104
103
|
} };
|
|
105
104
|
}
|
|
106
105
|
});
|
|
107
|
-
|
|
108
106
|
//#endregion
|
|
109
107
|
export { nonInteractiveElementTabIndexes_default as default };
|
|
108
|
+
|
|
110
109
|
//# sourceMappingURL=nonInteractiveElementTabIndexes.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Disallow duplicate props in JSX elements.";
|
|
3
|
+
readonly id: "propDuplicates";
|
|
4
|
+
readonly presets: ["logical", "logicalStrict"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "duplicateProp", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=propDuplicates.d.ts.map
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/propDuplicates.ts
|
|
6
5
|
var propDuplicates_default = ruleCreator.createRule(typescriptLanguage, {
|
|
7
6
|
about: {
|
|
8
7
|
description: "Disallow duplicate props in JSX elements.",
|
|
9
8
|
id: "propDuplicates",
|
|
10
|
-
presets: ["logical"]
|
|
9
|
+
presets: ["logical", "logicalStrict"]
|
|
11
10
|
},
|
|
12
11
|
messages: { duplicateProp: {
|
|
13
12
|
primary: "Duplicate prop `{{ propName }}` found in JSX element. The last occurrence will override earlier ones.",
|
|
@@ -34,7 +33,7 @@ var propDuplicates_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
34
33
|
} };
|
|
35
34
|
}
|
|
36
35
|
});
|
|
37
|
-
|
|
38
36
|
//#endregion
|
|
39
37
|
export { propDuplicates_default as default };
|
|
38
|
+
|
|
40
39
|
//# sourceMappingURL=propDuplicates.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports redundant ARIA roles on elements with implicit roles.";
|
|
3
|
+
readonly id: "roleRedundancies";
|
|
4
|
+
readonly presets: ["logical", "logicalStrict"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "redundantRole", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=roleRedundancies.d.ts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/roleRedundancies.ts
|
|
6
5
|
const implicitRoles = {
|
|
7
6
|
a: "link",
|
|
@@ -34,7 +33,7 @@ var roleRedundancies_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
34
33
|
about: {
|
|
35
34
|
description: "Reports redundant ARIA roles on elements with implicit roles.",
|
|
36
35
|
id: "roleRedundancies",
|
|
37
|
-
presets: ["logical"]
|
|
36
|
+
presets: ["logical", "logicalStrict"]
|
|
38
37
|
},
|
|
39
38
|
messages: { redundantRole: {
|
|
40
39
|
primary: "`<{{ element }}>` elements already implicitly have a role of `{{ role }}`. This explicit role is unnecessary.",
|
|
@@ -48,7 +47,7 @@ var roleRedundancies_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
48
47
|
const implicitRole = implicitRoles[element];
|
|
49
48
|
if (!implicitRole) return;
|
|
50
49
|
const roleProperty = node.attributes.properties.find((property) => property.kind === SyntaxKind.JsxAttribute && property.name.kind === SyntaxKind.Identifier && property.name.text === "role");
|
|
51
|
-
if (roleProperty
|
|
50
|
+
if (roleProperty?.kind === SyntaxKind.JsxAttribute && roleProperty.initializer?.kind === SyntaxKind.StringLiteral && roleProperty.initializer.text === implicitRole) {
|
|
52
51
|
const range = getTSNodeRange(roleProperty, sourceFile);
|
|
53
52
|
context.report({
|
|
54
53
|
data: {
|
|
@@ -71,7 +70,7 @@ var roleRedundancies_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
71
70
|
} };
|
|
72
71
|
}
|
|
73
72
|
});
|
|
74
|
-
|
|
75
73
|
//#endregion
|
|
76
74
|
export { roleRedundancies_default as default };
|
|
75
|
+
|
|
77
76
|
//# sourceMappingURL=roleRedundancies.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports ARIA roles missing their required ARIA properties.";
|
|
3
|
+
readonly id: "roleRequiredAriaProps";
|
|
4
|
+
readonly presets: ["logical", "logicalStrict"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "missingRequiredProps", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=roleRequiredAriaProps.d.ts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/roleRequiredAriaProps.ts
|
|
6
5
|
const requiredAriaPropsForRole = {
|
|
7
6
|
checkbox: ["aria-checked"],
|
|
@@ -33,7 +32,7 @@ var roleRequiredAriaProps_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
33
32
|
about: {
|
|
34
33
|
description: "Reports ARIA roles missing their required ARIA properties.",
|
|
35
34
|
id: "roleRequiredAriaProps",
|
|
36
|
-
presets: ["logical"]
|
|
35
|
+
presets: ["logical", "logicalStrict"]
|
|
37
36
|
},
|
|
38
37
|
messages: { missingRequiredProps: {
|
|
39
38
|
primary: "Elements with ARIA role `{{ role }}` must have the following ARIA property(s) defined: {{ props }}.",
|
|
@@ -47,7 +46,7 @@ var roleRequiredAriaProps_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
47
46
|
setup(context) {
|
|
48
47
|
function checkElement(node, { sourceFile }) {
|
|
49
48
|
const roleAttribute = node.attributes.properties.find((property) => property.kind === SyntaxKind.JsxAttribute && property.name.kind === SyntaxKind.Identifier && property.name.text === "role");
|
|
50
|
-
if (
|
|
49
|
+
if (roleAttribute?.kind !== SyntaxKind.JsxAttribute || roleAttribute.initializer?.kind !== SyntaxKind.StringLiteral) return;
|
|
51
50
|
const role = roleAttribute.initializer.text.toLowerCase();
|
|
52
51
|
const requiredProps = requiredAriaPropsForRole[role];
|
|
53
52
|
if (!requiredProps) return;
|
|
@@ -73,7 +72,7 @@ var roleRequiredAriaProps_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
73
72
|
} };
|
|
74
73
|
}
|
|
75
74
|
});
|
|
76
|
-
|
|
77
75
|
//#endregion
|
|
78
76
|
export { roleRequiredAriaProps_default as default };
|
|
77
|
+
|
|
79
78
|
//# sourceMappingURL=roleRequiredAriaProps.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports ARIA properties that are not supported by an element's role.";
|
|
3
|
+
readonly id: "roleSupportedAriaProps";
|
|
4
|
+
readonly presets: ["logical", "logicalStrict"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "unsupportedProp", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=roleSupportedAriaProps.d.ts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/roleSupportedAriaProps.ts
|
|
6
5
|
const globalAriaProperties = new Set([
|
|
7
6
|
"aria-atomic",
|
|
@@ -375,7 +374,7 @@ var roleSupportedAriaProps_default = ruleCreator.createRule(typescriptLanguage,
|
|
|
375
374
|
about: {
|
|
376
375
|
description: "Reports ARIA properties that are not supported by an element's role.",
|
|
377
376
|
id: "roleSupportedAriaProps",
|
|
378
|
-
presets: ["logical"]
|
|
377
|
+
presets: ["logical", "logicalStrict"]
|
|
379
378
|
},
|
|
380
379
|
messages: { unsupportedProp: {
|
|
381
380
|
primary: "The `{{ prop }}` ARIA property is not supported by the `{{ role }}` role.",
|
|
@@ -391,7 +390,7 @@ var roleSupportedAriaProps_default = ruleCreator.createRule(typescriptLanguage,
|
|
|
391
390
|
if (node.tagName.kind !== SyntaxKind.Identifier) return;
|
|
392
391
|
const elementName = node.tagName.text.toLowerCase();
|
|
393
392
|
const roleProperty = node.attributes.properties.find((property) => property.kind === SyntaxKind.JsxAttribute && property.name.kind === SyntaxKind.Identifier && property.name.text === "role");
|
|
394
|
-
const role = roleProperty
|
|
393
|
+
const role = roleProperty?.kind === SyntaxKind.JsxAttribute && roleProperty.initializer?.kind === SyntaxKind.StringLiteral ? roleProperty.initializer.text.toLowerCase() : implicitRoles[elementName];
|
|
395
394
|
if (!role) return;
|
|
396
395
|
const supportedProps = getSupportedPropsForRole(role);
|
|
397
396
|
for (const property of node.attributes.properties) {
|
|
@@ -414,7 +413,7 @@ var roleSupportedAriaProps_default = ruleCreator.createRule(typescriptLanguage,
|
|
|
414
413
|
} };
|
|
415
414
|
}
|
|
416
415
|
});
|
|
417
|
-
|
|
418
416
|
//#endregion
|
|
419
417
|
export { roleSupportedAriaProps_default as default };
|
|
418
|
+
|
|
420
419
|
//# sourceMappingURL=roleSupportedAriaProps.js.map
|
package/lib/rules/roleTags.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports ARIA roles that have semantic HTML element equivalents.";
|
|
3
|
+
readonly id: "roleTags";
|
|
4
|
+
readonly presets: ["logical", "logicalStrict"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "preferSemanticElement", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=roleTags.d.ts.map
|
package/lib/rules/roleTags.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/roleTags.ts
|
|
6
5
|
const roleToElement = {
|
|
7
6
|
article: "article",
|
|
@@ -48,7 +47,7 @@ var roleTags_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
48
47
|
function checkRole(node, { sourceFile }) {
|
|
49
48
|
if (node.tagName.kind !== SyntaxKind.Identifier || node.tagName.text.toLowerCase() !== node.tagName.text) return;
|
|
50
49
|
const roleProperty = node.attributes.properties.find((property) => property.kind === SyntaxKind.JsxAttribute && property.name.kind === SyntaxKind.Identifier && property.name.text === "role");
|
|
51
|
-
if (
|
|
50
|
+
if (roleProperty?.kind !== SyntaxKind.JsxAttribute || roleProperty.initializer?.kind !== SyntaxKind.StringLiteral) return;
|
|
52
51
|
const role = roleProperty.initializer.text;
|
|
53
52
|
const semanticElement = roleToElement[role];
|
|
54
53
|
if (semanticElement) context.report({
|
|
@@ -67,7 +66,7 @@ var roleTags_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
67
66
|
} };
|
|
68
67
|
}
|
|
69
68
|
});
|
|
70
|
-
|
|
71
69
|
//#endregion
|
|
72
70
|
export { roleTags_default as default };
|
|
71
|
+
|
|
73
72
|
//# sourceMappingURL=roleTags.js.map
|
package/lib/rules/ruleCreator.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { RuleCreator } from "@flint.fyi/core";
|
|
2
|
-
|
|
3
2
|
//#region src/rules/ruleCreator.ts
|
|
4
3
|
const ruleCreator = new RuleCreator({
|
|
5
4
|
docs: (ruleId) => `https://flint.fyi/rules/jsx/${ruleId.toLowerCase()}`,
|
|
@@ -10,7 +9,7 @@ const ruleCreator = new RuleCreator({
|
|
|
10
9
|
"stylistic"
|
|
11
10
|
]
|
|
12
11
|
});
|
|
13
|
-
|
|
14
12
|
//#endregion
|
|
15
13
|
export { ruleCreator };
|
|
14
|
+
|
|
16
15
|
//# sourceMappingURL=ruleCreator.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports scope props on non-th elements.";
|
|
3
|
+
readonly id: "scopeProps";
|
|
4
|
+
readonly presets: ["logical", "logicalStrict"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "invalidScope", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=scopeProps.d.ts.map
|
package/lib/rules/scopeProps.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/scopeProps.ts
|
|
6
5
|
var scopeProps_default = ruleCreator.createRule(typescriptLanguage, {
|
|
7
6
|
about: {
|
|
8
7
|
description: "Reports scope props on non-th elements.",
|
|
9
8
|
id: "scopeProps",
|
|
10
|
-
presets: ["logical"]
|
|
9
|
+
presets: ["logical", "logicalStrict"]
|
|
11
10
|
},
|
|
12
11
|
messages: { invalidScope: {
|
|
13
12
|
primary: "The `scope` prop only has an effect on <th> elements.",
|
|
@@ -36,7 +35,7 @@ var scopeProps_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
36
35
|
} };
|
|
37
36
|
}
|
|
38
37
|
});
|
|
39
|
-
|
|
40
38
|
//#endregion
|
|
41
39
|
export { scopeProps_default as default };
|
|
40
|
+
|
|
42
41
|
//# sourceMappingURL=scopeProps.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports static elements with event handlers that lack ARIA roles.";
|
|
3
|
+
readonly id: "staticElementInteractions";
|
|
4
|
+
readonly presets: ["logical", "logicalStrict"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "missingRole", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=staticElementInteractions.d.ts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/staticElementInteractions.ts
|
|
6
5
|
const interactiveHandlers = [
|
|
7
6
|
"onClick",
|
|
@@ -22,7 +21,7 @@ var staticElementInteractions_default = ruleCreator.createRule(typescriptLanguag
|
|
|
22
21
|
about: {
|
|
23
22
|
description: "Reports static elements with event handlers that lack ARIA roles.",
|
|
24
23
|
id: "staticElementInteractions",
|
|
25
|
-
presets: ["logical"]
|
|
24
|
+
presets: ["logical", "logicalStrict"]
|
|
26
25
|
},
|
|
27
26
|
messages: { missingRole: {
|
|
28
27
|
primary: "This static element that handles events is missing a role attribute.",
|
|
@@ -55,7 +54,7 @@ var staticElementInteractions_default = ruleCreator.createRule(typescriptLanguag
|
|
|
55
54
|
} };
|
|
56
55
|
}
|
|
57
56
|
});
|
|
58
|
-
|
|
59
57
|
//#endregion
|
|
60
58
|
export { staticElementInteractions_default as default };
|
|
59
|
+
|
|
61
60
|
//# sourceMappingURL=staticElementInteractions.js.map
|
package/lib/rules/svgTitles.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports <svg> elements without a <title> child element.";
|
|
3
|
+
readonly id: "svgTitles";
|
|
4
|
+
readonly presets: ["logical", "logicalStrict"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "missingTitle", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=svgTitles.d.ts.map
|
package/lib/rules/svgTitles.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/svgTitles.ts
|
|
6
5
|
var svgTitles_default = ruleCreator.createRule(typescriptLanguage, {
|
|
7
6
|
about: {
|
|
8
7
|
description: "Reports <svg> elements without a <title> child element.",
|
|
9
8
|
id: "svgTitles",
|
|
10
|
-
presets: ["logical"]
|
|
9
|
+
presets: ["logical", "logicalStrict"]
|
|
11
10
|
},
|
|
12
11
|
messages: { missingTitle: {
|
|
13
12
|
primary: "This <svg> element is missing a <title> child element.",
|
|
@@ -34,10 +33,10 @@ var svgTitles_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
34
33
|
});
|
|
35
34
|
}
|
|
36
35
|
function checkElement(node, { sourceFile }) {
|
|
37
|
-
const tagName = node.kind
|
|
36
|
+
const tagName = node.kind === SyntaxKind.JsxElement ? node.openingElement.tagName : node.tagName;
|
|
38
37
|
if (tagName.kind !== SyntaxKind.Identifier || tagName.text.toLowerCase() !== "svg") return;
|
|
39
|
-
if (hasValidAriaLabel(node.kind
|
|
40
|
-
if (node.kind
|
|
38
|
+
if (hasValidAriaLabel(node.kind === SyntaxKind.JsxElement ? node.openingElement.attributes : node.attributes)) return;
|
|
39
|
+
if (node.kind === SyntaxKind.JsxElement && node.children.some(isTitleElement)) return;
|
|
41
40
|
context.report({
|
|
42
41
|
message: "missingTitle",
|
|
43
42
|
range: getTSNodeRange(tagName, sourceFile)
|
|
@@ -54,7 +53,7 @@ function isTitleElement(node) {
|
|
|
54
53
|
const childTagName = node.kind === SyntaxKind.JsxElement ? node.openingElement.tagName : node.tagName;
|
|
55
54
|
return childTagName.kind === SyntaxKind.Identifier && childTagName.text === "title";
|
|
56
55
|
}
|
|
57
|
-
|
|
58
56
|
//#endregion
|
|
59
57
|
export { svgTitles_default as default };
|
|
58
|
+
|
|
60
59
|
//# sourceMappingURL=svgTitles.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Reports positive tabIndex values.";
|
|
3
|
+
readonly id: "tabIndexPositiveValues";
|
|
4
|
+
readonly presets: ["logical", "logicalStrict"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "noPositiveTabIndex", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=tabIndexPositiveValues.d.ts.map
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { getTSNodeRange, typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/tabIndexPositiveValues.ts
|
|
6
5
|
var tabIndexPositiveValues_default = ruleCreator.createRule(typescriptLanguage, {
|
|
7
6
|
about: {
|
|
8
7
|
description: "Reports positive tabIndex values.",
|
|
9
8
|
id: "tabIndexPositiveValues",
|
|
10
|
-
presets: ["logical"]
|
|
9
|
+
presets: ["logical", "logicalStrict"]
|
|
11
10
|
},
|
|
12
11
|
messages: { noPositiveTabIndex: {
|
|
13
12
|
primary: "Positive `tabIndex` values disrupt tab order and make keyboard navigation unpredictable.",
|
|
@@ -36,11 +35,11 @@ var tabIndexPositiveValues_default = ruleCreator.createRule(typescriptLanguage,
|
|
|
36
35
|
function getInitializerValue(initializer) {
|
|
37
36
|
if (initializer.kind === SyntaxKind.StringLiteral) {
|
|
38
37
|
const parsed = Number(initializer.text);
|
|
39
|
-
return isNaN(parsed) ? void 0 : parsed;
|
|
38
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
40
39
|
}
|
|
41
|
-
if (initializer.kind === SyntaxKind.JsxExpression) return initializer.expression
|
|
40
|
+
if (initializer.kind === SyntaxKind.JsxExpression) return initializer.expression?.kind === SyntaxKind.NumericLiteral ? Number(initializer.expression.text) : void 0;
|
|
42
41
|
}
|
|
43
|
-
|
|
44
42
|
//#endregion
|
|
45
43
|
export { tabIndexPositiveValues_default as default };
|
|
44
|
+
|
|
46
45
|
//# sourceMappingURL=tabIndexPositiveValues.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Disallow unescaped HTML entities in JSX text that may cause rendering issues.";
|
|
3
|
+
readonly id: "unescapedEntities";
|
|
4
|
+
readonly presets: ["stylistic"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "unescapedEntity", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=unescapedEntities.d.ts.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
|
-
|
|
4
3
|
//#region src/rules/unescapedEntities.ts
|
|
5
4
|
const problematicEntities = [
|
|
6
5
|
{
|
|
@@ -65,7 +64,7 @@ var unescapedEntities_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
65
64
|
} } };
|
|
66
65
|
}
|
|
67
66
|
});
|
|
68
|
-
|
|
69
67
|
//#endregion
|
|
70
68
|
export { unescapedEntities_default as default };
|
|
69
|
+
|
|
71
70
|
//# sourceMappingURL=unescapedEntities.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
declare const _default: import("@flint.fyi/core").Rule<
|
|
1
|
+
declare const _default: import("@flint.fyi/core").Rule<{
|
|
2
|
+
readonly description: "Disallow unnecessary JSX fragments that wrap a single child or have no children.";
|
|
3
|
+
readonly id: "unnecessaryFragments";
|
|
4
|
+
readonly presets: ["stylistic"];
|
|
5
|
+
} & {
|
|
6
|
+
presets?: ("logical" | "logicalStrict" | "stylistic")[];
|
|
7
|
+
url: string;
|
|
8
|
+
}, object, object, "unnecessaryFragment", import("@flint.fyi/core").AnyOptionalSchema>;
|
|
2
9
|
export default _default;
|
|
3
10
|
//# sourceMappingURL=unnecessaryFragments.d.ts.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ruleCreator } from "./ruleCreator.js";
|
|
2
2
|
import { typescriptLanguage } from "@flint.fyi/typescript-language";
|
|
3
3
|
import { SyntaxKind } from "typescript";
|
|
4
|
-
|
|
5
4
|
//#region src/rules/unnecessaryFragments.ts
|
|
6
5
|
var unnecessaryFragments_default = ruleCreator.createRule(typescriptLanguage, {
|
|
7
6
|
about: {
|
|
@@ -20,9 +19,9 @@ var unnecessaryFragments_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
20
19
|
} },
|
|
21
20
|
setup(context) {
|
|
22
21
|
function checkNodeChildren(node, range) {
|
|
23
|
-
const children = node.children.filter((child) => child.kind !== SyntaxKind.JsxText || child.text.trim().length
|
|
22
|
+
const children = node.children.filter((child) => child.kind !== SyntaxKind.JsxText || !!child.text.trim().length);
|
|
24
23
|
let childType;
|
|
25
|
-
if (children.length
|
|
24
|
+
if (!children.length) childType = "no children";
|
|
26
25
|
else if (children.length === 1) childType = "a single child";
|
|
27
26
|
if (childType) context.report({
|
|
28
27
|
data: { childType },
|
|
@@ -46,7 +45,7 @@ var unnecessaryFragments_default = ruleCreator.createRule(typescriptLanguage, {
|
|
|
46
45
|
} };
|
|
47
46
|
}
|
|
48
47
|
});
|
|
49
|
-
|
|
50
48
|
//#endregion
|
|
51
49
|
export { unnecessaryFragments_default as default };
|
|
50
|
+
|
|
52
51
|
//# sourceMappingURL=unnecessaryFragments.js.map
|