-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(refactor): Refactor rule structure to prevent merge conflicts (#…
…565) * chore(refactor): Refactor rule structure to prevent merge conflicts * chore(refactor): update generators to use ts & esm * chore(refactor): fix testing and rule curation * chore(refactor): fix readme generation * fix(generator): fix tsx generator to use same input and output content * chore(refactor): fix build bugs and address other misc issues
- Loading branch information
1 parent
88b58b0
commit 1bb4265
Showing
29 changed files
with
5,042 additions
and
3,694 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export interface Answers { | ||
componentName: string; | ||
propName: string; | ||
ruleName: string; | ||
referencePR: string; | ||
message?: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { join } from "path"; | ||
import { outputFile } from "fs-extra"; | ||
import { camelCase } from "case-anything"; | ||
import { Answers } from "./plop-interfaces"; | ||
|
||
async function baseReadme({ referencePR, ruleName, message }: Answers) { | ||
const camelCaseRuleName = camelCase(ruleName); | ||
const readMePath = join( | ||
require | ||
.resolve("@patternfly/eslint-plugin-pf-codemods") | ||
.replace( | ||
/dist\/(js|esm)\/index\.js/, | ||
`src/rules/v6/${camelCaseRuleName}` | ||
), | ||
`${ruleName}.md` | ||
); | ||
|
||
const readMeContent = `### ${ruleName} [(#${referencePR})](https://github.com/patternfly/patternfly-react/pull/${referencePR}) | ||
${message} | ||
#### Examples | ||
In: | ||
\`\`\`jsx | ||
%inputExample% | ||
\`\`\` | ||
Out: | ||
\`\`\`jsx | ||
%outputExample% | ||
\`\`\` | ||
`; | ||
|
||
await outputFile(readMePath, readMeContent); | ||
} | ||
|
||
export async function genericReadme(answers: Answers) { | ||
const message = "Default message"; | ||
await baseReadme({ message, ...answers }); | ||
} | ||
|
||
export async function addEventCBReadme(answers: Answers) { | ||
const { componentName, propName } = answers; | ||
|
||
const message = `We've updated the \`${propName}\` prop for ${componentName} so that the \`event\` parameter is the first parameter. Handlers may require an update.`; | ||
|
||
await baseReadme({ message, ...answers }); | ||
} | ||
|
||
export async function swapCBReadme(answers: Answers) { | ||
const { componentName, propName } = answers; | ||
|
||
const message = `We've updated the \`${propName}\` prop for ${componentName} so that the \`event\` parameter is the first parameter. Handlers may require an update.`; | ||
|
||
await baseReadme({ message, ...answers }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { join } from "path"; | ||
import { outputFile } from "fs-extra"; | ||
import { camelCase } from "case-anything"; | ||
import { Answers } from "./plop-interfaces"; | ||
|
||
async function baseRule(ruleName: string, fileContent: string) { | ||
const camelCaseRuleName = camelCase(ruleName); | ||
const destination = join( | ||
require | ||
.resolve("@patternfly/eslint-plugin-pf-codemods") | ||
.replace( | ||
/dist\/(js|esm)\/index\.js/, | ||
`src/rules/v6/${camelCaseRuleName}` | ||
), | ||
`${ruleName}.ts` | ||
); | ||
|
||
await outputFile(destination, fileContent); | ||
} | ||
|
||
export async function genericRule({ | ||
componentName, | ||
propName, | ||
ruleName, | ||
referencePR, | ||
message, | ||
}: Answers) { | ||
// the formatting for content here looks weird, but that's to preserve indentation in the written file | ||
const content = `import { getFromPackage } from '../../helpers'; | ||
// https://github.com/patternfly/patternfly-react/pull/${referencePR} | ||
module.exports = { | ||
meta: { fixable: 'code' }, | ||
create: function(context: { report: (arg0: { node: any; message: string; fix(fixer: any): any; }) => void; }) { | ||
const {imports, exports} = getFromPackage(context, '@patternfly/react-core') | ||
const componentImports = imports.filter((specifier: { imported: { name: string; }; }) => specifier.imported.name === '${componentName}'); | ||
const componentExports = exports.filter((specifier: { imported: { name: string; }; }) => specifier.imported.name === '${componentName}'); | ||
return !componentImports.length && !componentExports.length ? {} : { | ||
JSXOpeningElement(node: { name: { name: any; }; attributes: any[]; }) { | ||
if (componentImports.map((imp: { local: { name: any; }; }) => imp.local.name).includes(node.name.name)) { | ||
const attribute = node.attributes.find((attr: { name: { name: string; }; }) => attr.name?.name === '${propName}'); | ||
if (attribute) { | ||
context.report({ | ||
node, | ||
message: '${message}', | ||
fix(fixer: { replaceText: (arg0: any, arg1: string) => any; }) { | ||
return fixer.replaceText(attribute, ''); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
}; | ||
`; | ||
baseRule(ruleName, content); | ||
} | ||
|
||
export async function addEventCBRule({ | ||
componentName, | ||
propName, | ||
ruleName, | ||
referencePR, | ||
}: Answers) { | ||
const content = `const { addCallbackParam } = require("../../helpers"); | ||
// https://github.com/patternfly/patternfly-react/pull/${referencePR} | ||
module.exports = { | ||
meta: { fixable: "code" }, | ||
create: addCallbackParam(["${componentName}"], { ${propName}: "_event" }), | ||
}; | ||
`; | ||
baseRule(ruleName, content); | ||
} | ||
|
||
export async function swapCBRule({ | ||
componentName, | ||
propName, | ||
ruleName, | ||
referencePR, | ||
}: Answers) { | ||
const content = `const { addCallbackParam } = require("../../helpers"); | ||
// https://github.com/patternfly/patternfly-react/pull/${referencePR} | ||
module.exports = { | ||
meta: { fixable: "code" }, | ||
create: addCallbackParam(["${componentName}"], { ${propName}: { defaultParamName: "_event", previousParamIndex: 1, otherMatchers: /^_?(ev\\w*|e$)/ } }), | ||
}; | ||
`; | ||
baseRule(ruleName, content); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { join } from "path"; | ||
import { outputFile } from "fs-extra"; | ||
import { camelCase, pascalCase } from "case-anything"; | ||
import { Answers } from "./plop-interfaces"; | ||
|
||
async function baseTestSingle( | ||
{ componentName, ruleName }: Answers, | ||
componentUsage: string | ||
) { | ||
const camelCaseRuleName = camelCase(ruleName); | ||
const pascalCaseRuleName = pascalCase(ruleName); | ||
|
||
const ruleDir = require | ||
.resolve("@patternfly/eslint-plugin-pf-codemods") | ||
.replace(/dist\/(js|esm)\/index\.js/, `src/rules/v6/${camelCaseRuleName}`); | ||
|
||
const testInputPath = join(ruleDir, `${camelCaseRuleName}Input.tsx`); | ||
const testOutputPath = join(ruleDir, `${camelCaseRuleName}Output.tsx`); | ||
|
||
const testInputContent = `import { ${componentName} } from "@patternfly/react-core"; | ||
export const ${pascalCaseRuleName}Input = () => ${componentUsage}`; | ||
|
||
await outputFile(testInputPath, testInputContent); | ||
await outputFile(testOutputPath, testInputContent); | ||
} | ||
export async function genericTestSingle(answers: Answers) { | ||
const { componentName, propName } = answers; | ||
|
||
baseTestSingle(answers, `<${componentName} ${propName} />`); | ||
} | ||
|
||
export async function addEventCBTestSingle(answers: Answers) { | ||
const { componentName, propName } = answers; | ||
|
||
baseTestSingle( | ||
answers, | ||
`{ | ||
function handler1(foo) {} | ||
return ( | ||
<> | ||
<${componentName} ${propName}={handler1} /> | ||
<${componentName} ${propName}={(foo) => handler(foo)} /> | ||
</> | ||
); | ||
} | ||
` | ||
); | ||
} | ||
|
||
export async function swapCBTestSingle(answers: Answers) { | ||
const { componentName, propName } = answers; | ||
|
||
baseTestSingle( | ||
answers, | ||
`{ | ||
function handler1(foo, event) {} | ||
return ( | ||
<> | ||
<${componentName} ${propName}={handler1} /> | ||
<${componentName} ${propName}={(foo, event) => handler(foo)} /> | ||
</> | ||
); | ||
} | ||
` | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"extends": "../tsconfig.base.json", | ||
"compilerOptions": { | ||
"module": "commonjs", | ||
"outDir": "./dist/js" | ||
}, | ||
"include": ["./src/**/*"], | ||
"exclude": ["./dist"] | ||
} |
Oops, something went wrong.