Skip to content

Commit e7e2443

Browse files
authored
Merge pull request #142 from jessebeach/ethanc/create-rule-script
[new][dev] Add the new rule to the index, extends #139
2 parents a758c4a + c7931eb commit e7e2443

File tree

5 files changed

+796
-24
lines changed

5 files changed

+796
-24
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@ You can also enable all the recommended rules at once. Add `plugin:jsx-a11y/reco
111111
- [scope](docs/rules/scope.md): Enforce `scope` prop is only used on `<th>` elements.
112112
- [tabindex-no-positive](docs/rules/tabindex-no-positive.md): Enforce `tabIndex` value is not greater than zero.
113113

114+
## Creating a new rule
115+
116+
If you are developing new rules for this project, you can use the `create-rule`
117+
script to scaffold the new files.
118+
119+
```
120+
$ ./scripts/create-rule.js my-new-rule
121+
```
122+
114123
## License
115124

116125
eslint-plugin-jsx-a11y is licensed under the [MIT License](LICENSE.md).

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"eslint-config-airbnb-base": "^11.0.0",
3939
"eslint-plugin-import": "^2.2.0",
4040
"jest": "^18.1.0",
41+
"jscodeshift": "^0.3.30",
4142
"minimist": "^1.2.0",
4243
"rimraf": "^2.5.2",
4344
"to-ast": "^1.0.0"

scripts/addRuleToIndex.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
export const parser = 'flow';
2+
3+
export default function transformer(file, api, options) {
4+
const j = api.jscodeshift;
5+
const s = j(file.source);
6+
const {
7+
ruleName,
8+
rulePath,
9+
} = options || {};
10+
11+
const nameSort = (a, b) => {
12+
const aName = (a.key.type === 'Literal') ? a.key.value : a.key.name;
13+
const bName = (b.key.type === 'Literal') ? b.key.value : b.key.name;
14+
if (aName < bName) {
15+
return -1;
16+
}
17+
if (bName < aName) {
18+
return 1;
19+
}
20+
return 0;
21+
};
22+
23+
let changesMade = 0;
24+
25+
const rulePathInSrc = './' + rulePath.match(/src\/(.*)\.js/)[1];
26+
27+
changesMade += s.find(j.Identifier, {
28+
name: 'rules'
29+
}).forEach((path, index) => {
30+
// Add rule path.
31+
if (index === 0) {
32+
path.parentPath.value.value.properties.unshift(
33+
j.property(
34+
'init',
35+
j.literal(ruleName),
36+
j.callExpression(
37+
j.identifier('require'),
38+
[
39+
j.literal(rulePathInSrc),
40+
]
41+
),
42+
)
43+
);
44+
path.parentPath.value.value.properties.sort(nameSort);
45+
}
46+
// Set default reporting to error.
47+
if (index === 1) {
48+
path.parentPath.value.value.properties.unshift(
49+
j.property(
50+
'init',
51+
j.literal('jsx-a11y/' + ruleName),
52+
j.literal('error'),
53+
)
54+
);
55+
path.parentPath.value.value.properties.sort(nameSort);
56+
}
57+
}).length;
58+
59+
60+
if (changesMade === 0) {
61+
return null;
62+
}
63+
64+
return s.toSource({
65+
quote: 'single',
66+
trailingComma: true,
67+
});
68+
}

scripts/create-rule.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
#!/usr/bin/env node --harmony
12
const path = require('path');
23
const fs = require('fs');
34
const argv = require('minimist')(process.argv.slice(2)); // eslint-disable-line import/no-extraneous-dependencies
45
const ruleBoilerplateGenerator = require('./boilerplate/rule');
56
const testBoilerplateGenerator = require('./boilerplate/test');
67
const docBoilerplateGenerator = require('./boilerplate/doc');
8+
const exec = require('child_process').exec;
79

810
const ruleName = argv._[0];
911
const author = argv.author || '$AUTHOR';
@@ -13,6 +15,14 @@ const rulePath = path.resolve(`src/rules/${ruleName}.js`);
1315
const testPath = path.resolve(`__tests__/src/rules/${ruleName}-test.js`);
1416
const docsPath = path.resolve(`docs/rules/${ruleName}.md`);
1517

18+
const jscodeshiftJSON = require('jscodeshift/package.json');
19+
const jscodeshiftMain = jscodeshiftJSON.main;
20+
const jscodeshiftPath = require.resolve('jscodeshift');
21+
const jscodeshiftRoot = jscodeshiftPath.slice(
22+
0,
23+
jscodeshiftPath.indexOf(jscodeshiftMain)
24+
);
25+
1626
// Validate
1727
if (!ruleName) {
1828
throw new Error('Rule name is required');
@@ -29,3 +39,24 @@ const docBoilerplate = docBoilerplateGenerator(ruleName);
2939
fs.writeFileSync(rulePath, ruleBoilerplate);
3040
fs.writeFileSync(testPath, testBoilerplate);
3141
fs.writeFileSync(docsPath, docBoilerplate);
42+
43+
// Add the rule to the index
44+
exec([
45+
path.join(
46+
jscodeshiftRoot,
47+
jscodeshiftJSON.bin.jscodeshift
48+
),
49+
'./src/index.js',
50+
'-t ./scripts/addRuleToIndex.js',
51+
'--extensions js',
52+
'--parser flow',
53+
`--ruleName=${ruleName}`,
54+
`--rulePath=${rulePath}`,
55+
].join(' '),
56+
(error, stdout, stderr) => {
57+
if (error) {
58+
console.error(`exec error: ${error}`);
59+
return;
60+
}
61+
}
62+
);

0 commit comments

Comments
 (0)