0.2.0 - Mid migration

This commit is contained in:
Daniel Mason 2022-04-25 14:47:15 +12:00
parent 139e6a915e
commit 7e38fdbd7d
42393 changed files with 5358157 additions and 62 deletions

View file

@ -0,0 +1,53 @@
export const parser = 'flow';
export default function transformer(file, api, options) {
const j = api.jscodeshift;
const s = j(file.source);
const { ruleName, rulePath } = options || {};
const nameSort = (a, b) => {
const aName = a.key.type === 'Literal' ? a.key.value : a.key.name;
const bName = b.key.type === 'Literal' ? b.key.value : b.key.name;
if (aName < bName) {
return -1;
}
if (bName < aName) {
return 1;
}
return 0;
};
let changesMade = 0;
const rulePathInSrc = `./${rulePath.match(/src\/(.*)\.js/)[1]}`;
changesMade += s
.find(j.Identifier, {
name: 'rules',
})
.forEach((path, index) => {
// Add rule path.
if (index === 0) {
path.parentPath.value.value.properties.unshift(j.property(
'init',
j.literal(ruleName),
j.callExpression(j.identifier('require'), [j.literal(rulePathInSrc)]),
));
path.parentPath.value.value.properties.sort(nameSort);
}
// Set default reporting to error.
if (index === 1) {
path.parentPath.value.value.properties.unshift(j.property('init', j.literal(`jsx-a11y/${ruleName}`), j.literal('error')));
path.parentPath.value.value.properties.sort(nameSort);
}
}).length;
if (changesMade === 0) {
return null;
}
return s.toSource({
quote: 'single',
trailingComma: true,
});
}

View file

@ -0,0 +1,24 @@
const docBoilerplateGenerator = (name) => `# ${name}
Write a useful explanation here!
### References
1.
## Rule details
This rule takes no arguments.
### Succeed
\`\`\`jsx
<div />
\`\`\`
### Fail
\`\`\`jsx
\`\`\`
`;
module.exports = docBoilerplateGenerator;

View file

@ -0,0 +1,35 @@
const ruleBoilerplate = (author, description) => `/**
* @fileoverview ${description}
* @author ${author}
* @flow
*/
// ----------------------------------------------------------------------------
// Rule Definition
// ----------------------------------------------------------------------------
import type { JSXOpeningElement } from 'ast-types-flow';
import { generateObjSchema } from '../util/schemas';
const errorMessage = '';
const schema = generateObjSchema();
module.exports = {
meta: {
docs: {},
schema: [schema],
},
create: (context: ESLintContext) => ({
JSXOpeningElement: (node: JSXOpeningElement) => {
context.report({
node,
message: errorMessage,
});
},
}),
};
`;
module.exports = ruleBoilerplate;

View file

@ -0,0 +1,34 @@
const testBoilerplate = (name, author, description) => `/* eslint-env jest */
/**
* @fileoverview ${description}
* @author ${author}
*/
// -----------------------------------------------------------------------------
// Requirements
// -----------------------------------------------------------------------------
import { RuleTester } from 'eslint';
import parserOptionsMapper from '../../__util__/parserOptionsMapper';
import rule from '../../../src/rules/${name}';
// -----------------------------------------------------------------------------
// Tests
// -----------------------------------------------------------------------------
const ruleTester = new RuleTester();
const expectedError = {
message: '',
type: 'JSXOpeningElement',
};
ruleTester.run('${name}', rule, {
valid: [
{ code: '<div />;' },
].map(parserOptionsMapper),
invalid: [].map(parserOptionsMapper),
});
`;
module.exports = testBoilerplate;

View file

@ -0,0 +1,57 @@
#!/usr/bin/env node --harmony
const path = require('path');
const fs = require('fs');
const { exec } = require('child_process');
const argv = require('minimist')(process.argv.slice(2)); // eslint-disable-line import/no-extraneous-dependencies
const jscodeshiftJSON = require('jscodeshift/package.json'); // eslint-disable-line import/no-extraneous-dependencies
const ruleBoilerplateGenerator = require('./boilerplate/rule');
const testBoilerplateGenerator = require('./boilerplate/test');
const docBoilerplateGenerator = require('./boilerplate/doc');
const ruleName = argv._[0];
const author = argv.author || '$AUTHOR';
const description = argv.description || '$DESCRIPTION';
const rulePath = path.resolve(`src/rules/${ruleName}.js`);
const testPath = path.resolve(`__tests__/src/rules/${ruleName}-test.js`);
const docsPath = path.resolve(`docs/rules/${ruleName}.md`);
const jscodeshiftMain = jscodeshiftJSON.main;
const jscodeshiftPath = require.resolve('jscodeshift');
const jscodeshiftRoot = jscodeshiftPath.slice(0, jscodeshiftPath.indexOf(jscodeshiftMain));
// Validate
if (!ruleName) {
throw new Error('Rule name is required');
} else if (fs.existsSync(rulePath)) {
throw new Error('Rule already exists!');
}
// Generate file boilerplate
const ruleBoilerplate = ruleBoilerplateGenerator(author, description);
const testBoilerplate = testBoilerplateGenerator(ruleName, author, description);
const docBoilerplate = docBoilerplateGenerator(ruleName);
// Create new files
fs.writeFileSync(rulePath, ruleBoilerplate);
fs.writeFileSync(testPath, testBoilerplate);
fs.writeFileSync(docsPath, docBoilerplate);
// Add the rule to the index
exec(
[
path.join(jscodeshiftRoot, jscodeshiftJSON.bin.jscodeshift),
'./src/index.js',
'-t ./scripts/addRuleToIndex.js',
'--extensions js',
'--parser flow',
`--ruleName=${ruleName}`,
`--rulePath=${rulePath}`,
].join(' '),
(error) => {
if (error) {
console.error(`exec error: ${error}`); // eslint-disable-line no-console
}
},
);

View file

@ -0,0 +1,21 @@
# Rule Generator
```bash
$ node scripts/create-rule.js rule-name --author="Your name" --description="Description of the rule"
# OR with npm script alias
$ npm run create -- rule-name --author="Your name" --description="Description of rule"
```
This script will generate three files with basic boilerplate for the given rule:
1. src/rules/${rule-name}.js
2. \__tests__/src/rules/${rule-name}-test.js
3. docs/rules/${rule-name}.md
If the rule already exists or is not specified in the correct format, an error will be thrown.
If we wanted to scaffold a rule for `no-marquee`, we could run:
```bash
$ node scripts/create-rule.js no-marquee --author="Ethan Cohen <@evcohen>" --description="Enforce <marquee> elements are not used."
# OR
$ npm run create -- no-marquee --author="Ethan Cohen <@evcohen>" --description="Enforce <marquee> elements are not used."
```