Skip to content

Commit

Permalink
improve rule template
Browse files Browse the repository at this point in the history
  • Loading branch information
yannbf committed Jan 27, 2023
1 parent d8adb39 commit 1e6ab29
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 29 deletions.
3 changes: 2 additions & 1 deletion lib/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-fallthrough */
import { IncludeExcludeOptions, isExportStory } from '@storybook/csf'

import { ASTUtils, TSESTree, TSESLint } from '@typescript-eslint/utils'
Expand Down Expand Up @@ -63,7 +64,7 @@ export const getDescriptor = (
case 'Literal':
// @ts-expect-error TODO: Investigation needed. Type systems says, that "RegExpLiteral" does not exist
case 'RegExpLiteral':
// @ts-ignore
// @ts-expect-error TODO: investigation needed
return property.value.value
default:
throw new Error(`Unexpected descriptor: ${type}`)
Expand Down
74 changes: 46 additions & 28 deletions tools/generate-rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,18 @@ const questions = [
type: 'text',
name: 'authorName',
initial: '',
message: 'What is your name?',
message: 'What is your name? (to be given credit for the rule)',
validate: (name: string) => (name === '' ? "Name can't be empty" : true),
},
{
type: 'text',
name: 'ruleId',
message: dedent(`'What is the rule ID? Follow the ESLint rule naming conventions:
message: dedent(`Time to name your rule! Follow the ESLint rule naming conventions:
- If your rule is disallowing something, prefix it with no- such as no-eval for disallowing eval() and no-debugger for disallowing debugger.
- If your rule is enforcing the inclusion of something, use a short name without a special prefix.
- Use dashes between words.
What is the ID of this new rule?
`),
validate: (rule: string) => (rule === '' ? "Rule can't be empty" : true),
},
Expand All @@ -42,12 +43,16 @@ const questions = [
]

const generateRule = async () => {
const { authorName, ruleId, ruleDescription, isAutoFixable } = await prompts(questions)

if (!authorName) {
logger.log('Process canceled by the user.')
process.exit(0)
}
logger.log(
'👋 Welcome to the Storybook ESLint rule generator! Please answer a few questions so I can provide everything you need for your new rule.'
)
logger.log()
const { authorName, ruleId, ruleDescription, isAutoFixable } = await prompts(questions, {
onCancel: () => {
logger.log('Process canceled by the user.')
process.exit(0)
},
})

const ruleFile = path.resolve(__dirname, `../lib/rules/${ruleId}.ts`)
const testFile = path.resolve(__dirname, `../tests/lib/rules/${ruleId}.test.ts`)
Expand All @@ -61,8 +66,10 @@ const generateRule = async () => {
* @author ${authorName}
*/
import { TSESTree } from '@typescript-eslint/utils'
import { createStorybookRule } from '../utils/create-storybook-rule'
import { CategoryId } from '../utils/constants'
import { isIdentifier, isVariableDeclaration } from '../utils/ast'
//------------------------------------------------------------------------------
// Rule Definition
Expand All @@ -72,12 +79,12 @@ const generateRule = async () => {
name: '${ruleId}',
defaultOptions: [],
meta: {
type: null, // \`problem\`, \`suggestion\`, or \`layout\`
type: 'problem', // \`problem\`, \`suggestion\`, or \`layout\`
docs: {
description: 'Fill me in',
// Add the categories that suit this rule.
categories: [CategoryId.RECOMMENDED],
recommended: 'warn', // or 'error'
recommended: 'warn', // \`warn\` or \`error\`
},
messages: {
anyMessageIdHere: 'Fill me in',
Expand All @@ -102,20 +109,30 @@ const generateRule = async () => {
return {
/**
* This is an example rule that reports an error in case a named export is called 'wrong'
* Use https://eslint.org/docs/developer-guide/working-with-rules for Eslint API
* 👉 Please read this and then delete this entire comment block.
* This is an example rule that reports an error in case a named export is called 'wrong'.
* Hopefully this will guide you to write your own rules. Make sure to always use the AST utilities and account for all possible cases.
*
* Keep in mind that sometimes AST nodes change when in javascript or typescript format. For example, the type of "declaration" from "export default {}" is ObjectExpression but in "export default {} as SomeType" is TSAsExpression.
*
* Use https://eslint.org/docs/developer-guide/working-with-rules for Eslint API reference
* And check https://astexplorer.net/ to help write rules
* And delete this entire comment block
* Working with AST is fun. Good luck!
*/
ExportNamedDeclaration: function (node) {
const identifier = node.declaration.declarations[0].id
if (identifier) {
const { name } = identifier
if (name === 'wrong') {
context.report({
node,
messageId: 'anyMessageIdHere',
})
ExportNamedDeclaration: function (node: TSESTree.ExportNamedDeclaration) {
const declaration = node.declaration
if (!declaration) return
// use AST helpers to make sure the nodes are of the right type
if (isVariableDeclaration(declaration)) {
const identifier = declaration.declarations[0]?.id
if (isIdentifier(identifier)) {
const { name } = identifier
if (name === 'wrong') {
context.report({
node,
messageId: 'anyMessageIdHere',
})
}
}
}
},
Expand Down Expand Up @@ -145,22 +162,23 @@ const generateRule = async () => {
ruleTester.run('${ruleId}', rule, {
/**
* This is an example test for a rule that reports an error in case a named export is called 'wrong'
* Use https://eslint.org/docs/developer-guide/working-with-rules for Eslint API
* And delete this entire comment block
* 👉 Please read this and delete this entire comment block.
* This is an example test for a rule that reports an error in case a named export is called 'wrong'
* Use https://eslint.org/docs/developer-guide/working-with-rules for Eslint API reference
*/
valid: ['export const Correct'],
valid: ['export const correct = {}'],
invalid: [
{
code: 'export const wrong',
code: 'export const wrong = {}',
errors: [
{
messageId: 'anyMessageIdHere', // comes from the rule file
},
],
},
],
})\n`)
})
`)
)

logger.log(`creating docs/rules/${ruleId}.md`)
Expand Down

0 comments on commit 1e6ab29

Please sign in to comment.