Skip to content

Commit cb79370

Browse files
authored
Feat/rule do not use role on image (#32)
* chore: remove console.log * feat: add role do-not-use-role-on-image * docs: update docs for rule do-not-use-role-on-image * feat: replace 'img' value to 'image' in fixing method * docs: add example in example-app * chore: add no-console rule in eslint-plugin package
1 parent 238a4c6 commit cb79370

8 files changed

Lines changed: 155 additions & 3 deletions

File tree

example-app/.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
],
1010
"rules": {
1111
"@bam.tech/require-named-effect": "error",
12-
"@bam.tech/image-requires-accessible-prop": "error"
12+
"@bam.tech/image-requires-accessible-prop": "error",
13+
"@bam.tech/do-not-use-role-on-image": "error"
1314
}
1415
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Save without formatting: [⌘ + K] > [S]
2+
3+
// This should trigger an error breaking eslint-plugin-bam-custom-rules:
4+
// bam-custom-rules/do-not-use-role-on-image
5+
6+
import { Image } from "react-native";
7+
8+
export const MyComponent = () => {
9+
return (
10+
<>
11+
<Image
12+
source={{ uri: "" }}
13+
accessibilityIgnoresInvertColors
14+
accessible
15+
role="button"
16+
/>
17+
<Image
18+
source={{ uri: "" }}
19+
accessibilityIgnoresInvertColors
20+
accessible
21+
role="img"
22+
/>
23+
</>
24+
);
25+
};
26+

packages/eslint-plugin/.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ module.exports = {
1919
"https://github.com/bamlab/react-native-project-config/tree/main/packages/eslint-plugin/docs/rules/{{name}}.md",
2020
},
2121
],
22+
"no-console": ["error", { allow: ["warn", "error"] }],
2223
},
2324
env: {
2425
node: true,

packages/eslint-plugin/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ This plugin exports some custom rules that you can optionally use in your projec
5959

6060
| Name | Description | 🔧 | 💡 |
6161
| :----------------------------------------------------------------------------- | :----------------------------------------------------- | :-- | :-- |
62+
| [do-not-use-role-on-image](docs/rules/do-not-use-role-on-image.md) | Disallow role prop on Image component | 🔧 | |
6263
| [image-requires-accessible-prop](docs/rules/image-requires-accessible-prop.md) | Require accessible prop on image components | 🔧 | 💡 |
6364
| [require-named-effect](docs/rules/require-named-effect.md) | Enforces the use of named functions inside a useEffect | | |
6465

@@ -72,7 +73,8 @@ To use a rule, just declare it in your `.eslintrc`:
7273
"plugins": ["@bam.tech"],
7374
"rules": {
7475
"@bam.tech/require-named-effect": "error",
75-
"@bam.tech/image-requires-accessible-prop": "error"
76+
"@bam.tech/image-requires-accessible-prop": "error",
77+
"@bam.tech/do-not-use-role-on-image": "error"
7678
}
7779
}
7880
```
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Disallow role prop on Image component (`@bam.tech/do-not-use-role-on-image`)
2+
3+
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
4+
5+
<!-- end auto-generated rule header -->
6+
7+
Enforces the use of `accessibilityRole` instead of `role` on an image component.
8+
9+
## Rule Details
10+
11+
Examples of **incorrect** code for this rule:
12+
13+
```jsx
14+
<Image source={{ uri: "" }} role="button" />
15+
```
16+
17+
Examples of **correct** code for this rule:
18+
19+
```jsx
20+
<Image source={{ uri: "" }} accessibilityRole="button" />
21+
```
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* @fileoverview role prop does not work on react-native Image component
3+
* @author Paul Briand
4+
*/
5+
"use strict";
6+
7+
const isImage = require("../utils/isImage");
8+
9+
//------------------------------------------------------------------------------
10+
// Rule Definition
11+
//------------------------------------------------------------------------------
12+
13+
/** @type {import('eslint').Rule.RuleModule} */
14+
module.exports = {
15+
meta: {
16+
type: "problem", // `problem`, `suggestion`, or `layout`
17+
docs: {
18+
description: "Disallow role prop on Image component",
19+
recommended: false,
20+
url: "https://github.com/bamlab/react-native-project-config/tree/main/packages/eslint-plugin/docs/rules/do-not-use-role-on-image.md", // URL to the documentation page for this rule
21+
},
22+
fixable: "code", // Or `code` or `whitespace`
23+
schema: [], // Add a schema if the rule has options
24+
messages: {
25+
doNotUseRoleOnImage:
26+
"Use 'accessibilityRole' instead of 'role' on Image component",
27+
},
28+
},
29+
30+
create(context) {
31+
return {
32+
JSXAttribute: (node) => {
33+
if (node.name.name === "role" && isImage(node.parent))
34+
context.report({
35+
node,
36+
messageId: "doNotUseRoleOnImage",
37+
fix: (fixer) => {
38+
const roleFixer = fixer.replaceTextRange(
39+
[node.range[0], node.range[0] + 4],
40+
"accessibilityRole"
41+
);
42+
if (node.value.type === "Literal" && node.value.value === "img")
43+
return [
44+
roleFixer,
45+
fixer.replaceTextRange(
46+
[node.range[1] - 4, node.range[1] - 1],
47+
"image"
48+
),
49+
];
50+
return roleFixer;
51+
},
52+
});
53+
},
54+
};
55+
},
56+
};

packages/eslint-plugin/lib/rules/image-requires-accessible-prop.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ module.exports = {
2929
create(context) {
3030
return {
3131
JSXOpeningElement: (node) => {
32-
console.log(node);
3332
if (
3433
isImage(node) &&
3534
!node.attributes.some((attr) => attr.name.name === "accessible")
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* @fileoverview role prop does not work on react-native Image component
3+
* @author Paul Briand
4+
*/
5+
"use strict";
6+
7+
//------------------------------------------------------------------------------
8+
// Requirements
9+
//------------------------------------------------------------------------------
10+
11+
const rule = require("../../../lib/rules/do-not-use-role-on-image"),
12+
RuleTester = require("eslint").RuleTester;
13+
14+
//------------------------------------------------------------------------------
15+
// Tests
16+
//------------------------------------------------------------------------------
17+
18+
const ruleTester = new RuleTester({
19+
parser: require.resolve("@typescript-eslint/parser"),
20+
parserOptions: {
21+
ecmaVersion: 2021,
22+
sourceType: "module",
23+
ecmaFeatures: {
24+
jsx: true,
25+
},
26+
},
27+
});
28+
29+
const valid = [`<Image source={{uri:""}} accessibilityRole='button' />`];
30+
31+
const invalid = [
32+
{
33+
code: `<Image source={{uri:""}} role='button' />`,
34+
errors: ["Use 'accessibilityRole' instead of 'role' on Image component"],
35+
output: `<Image source={{uri:""}} accessibilityRole='button' />`,
36+
},
37+
{
38+
code: `<Image source={{uri:""}} role='img' />`,
39+
errors: ["Use 'accessibilityRole' instead of 'role' on Image component"],
40+
output: `<Image source={{uri:""}} accessibilityRole='image' />`,
41+
},
42+
];
43+
ruleTester.run("image-requires-accessible-prop", rule, {
44+
valid,
45+
invalid,
46+
});

0 commit comments

Comments
 (0)