diff --git a/README.md b/README.md index 0a32a16..3fbc920 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,26 @@ # @fullstory/eslint-plugin-annotate-react -An ESLint plugin for annotating React components. +An ESLint plugin for adding 'data-attribute' to React components. The purpose of this plugin is to automatically +make css selectors. Here is an example + +``` +const myDiv = () => ( +
+); `; +``` + +This plugin will autofix and add data-component to the div + +``` +const myDiv = () => ( + +); `; +``` + +This plugin is intended to not be too opinionated. In general the approach is to suggest to the developer to add 'data-attribute' when there is an obvious approach, but in questionable cases, the plugin will tend towards being quiet. + +- When there is a [fragment](https://reactjs.org/docs/fragments.html) this plugin won't add data-attribute +- Where there are multiple return elements this plugin won't add data-attribute ## Installation @@ -36,6 +56,14 @@ Then configure the rules you want to use under the rules section. } ``` +## Maintaining this plugin + +Tests can be ran using + +``` +npm run test +``` + ## Supported Rules ### @fullstory/annotate-react/data-component diff --git a/index.js b/index.js index b3377b8..ca17399 100644 --- a/index.js +++ b/index.js @@ -138,49 +138,51 @@ const rules = { return flag; }); - const [componentNode] = componentNodes; + componentNodes.forEach((componentNode) => { + const componentName = + componentNode?.id?.name ?? + componentNode?.declarations?.map( + (declaration) => declaration?.id?.name, + ); + + let fixNode = null; + + traverseTree( + getReturnStatement(componentNode), + visitorKeys, + (current) => { + if (isSubtreeDone(current)) { + throw DONE_WITH_SUBTREE; + } else if (isTreeDone(current, excludeComponentNames)) { + fixNode = current.openingElement; - const componentName = - componentNode?.id?.name ?? - componentNode?.declarations?.map( - (declaration) => declaration?.id?.name, + throw DONE_WITH_TREE; + } + }, ); - let fixNode = null; - - traverseTree( - getReturnStatement(componentNode), - visitorKeys, - (current) => { - if (isSubtreeDone(current)) { - throw DONE_WITH_SUBTREE; - } else if (isTreeDone(current, excludeComponentNames)) { - fixNode = current.openingElement; - - throw DONE_WITH_TREE; - } - }, - ); - - if (Boolean(componentName)) { - context.report({ - node: fixNode, - message: `${ - Array.isArray(componentName) ? componentName[0] : componentName - } is missing the data-component attribute for the top-level element.`, - fix: (fixer) => - fixer.insertTextAfterRange( - Boolean(fixNode.typeParameters) - ? fixNode.typeParameters.range - : fixNode.name.range, - `\ndata-component="${ - Array.isArray(componentName) - ? componentName[0] - : componentName - }"`, - ), - }); - } + if (Boolean(componentName)) { + context.report({ + node: fixNode, + message: `${ + Array.isArray(componentName) + ? componentName[0] + : componentName + } is missing the data-component attribute for the top-level element.`, + fix: (fixer) => + fixer.insertTextAfterRange( + Boolean(fixNode.typeParameters) + ? fixNode.typeParameters.range + : fixNode.name.range, + ` data-component="${ + Array.isArray(componentName) + ? componentName[0] + : componentName + }"`, + ), + }); + } + }); }, }; }, diff --git a/test.js b/test.js index 3b3d148..326119a 100644 --- a/test.js +++ b/test.js @@ -6,8 +6,90 @@ const { join } = require('path'); // Test File Definitions //------------------------------------------------------------------------------ +const singleComponent = `const temp = () => { +