diff --git a/.changeset/curvy-flies-develop.md b/.changeset/curvy-flies-develop.md new file mode 100644 index 000000000..d9a253397 --- /dev/null +++ b/.changeset/curvy-flies-develop.md @@ -0,0 +1,5 @@ +--- +'@compiled/eslint-plugin': minor +--- + +Adding flat config preset for `@compiled/eslint-plugin` and adding missing descriptions to ESLint rules diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 42f701761..530c97376 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -10,13 +10,42 @@ npm install @compiled/eslint-plugin --save-dev ## Usage +### Flat Config + +Import the `@compiled/eslint-plugin` and add it to your plugins like so, then configure the ruels you want to use under the rules section. + +```ts +import compiled from '@compiled/eslint-plugin'; + +export default [ + { + plugins: { + '@compiled': compiled, + }, + rules: { + '@compiled/no-js-xcss': 'error', + }, + }, +]; +``` + +You can also enable the recommended rules for compiled by extending the `flat/recommended` config like so: + +```ts +import compiled from '@compiled/eslint-plugin'; + +export default [compiled.configs['flat/recommended']]; +``` + +### Legacy Config (`.eslintrc`) + Add `@compiled` to the plugins section of your `.eslintrc` configuration file, then configure the rules you want to use under the rules section. ```json { "plugins": ["@compiled"], "rules": { - "@compiled/rule-name": "error" + "@compiled/no-js-xcss": "error" } } ``` @@ -32,15 +61,22 @@ You can also enable the recommended rules for compiled by adding `plugin:@compil ## Supported rules -:white_check_mark: = recommended, :wrench: = automatically fixable, :bulb: = manually fixable - -| Name | Description | :white_check_mark: | Fixable | -| -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | :----------------: | :------: | -| [@compiled/jsx-pragma](./src/rules/jsx-pragma) | Enforces a jsx pragma when using the `css` prop | | :wrench: | -| [@compiled/no-css-tagged-template-expression](./src/rules/no-css-tagged-template-expression) | Disallows the `css` tagged template expression | :white_check_mark: | :wrench: | -| [@compiled/no-emotion-css](./src/rules/no-emotion-css) | Disallows `@emotion` usages | | :wrench: | -| [@compiled/no-exported-css](./src/rules/no-exported-css) | Disallows `css` usages from being exported | :white_check_mark: | | -| [@compiled/no-exported-keyframes](./src/rules/no-exported-keyframes) | Disallows `keyframes` usages from being exported | :white_check_mark: | | -| [@compiled/no-keyframes-tagged-template-expression](./src/rules/no-keyframes-tagged-template-expression) | Disallows the `keyframes` tagged template expression | :white_check_mark: | :wrench: | -| [@compiled/no-styled-tagged-template-expression](./src/rules/no-styled-tagged-template-expression) | Disallows the `styled` tagged template expression | :white_check_mark: | :wrench: | -| [@compiled/no-css-prop-without-css-function](./src/rules/no-css-prop-without-css-function) | Disallows css prop without the css function | :white_check_mark: | :wrench: | +✅ Included in the recommended configuration.\ +🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\ + +| Name | Description | Recommended | Fixable | +| -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------: | :-----: | +| [@compiled/jsx-pragma](./src/rules/jsx-pragma) | Enforces a jsx pragma when using the `css` prop | | 🔧 | +| [@compiled/local-cx-xcss](./src/rules/local-cx-xcss) | Ensures the `cx()` function is only used within the `xcss` prop | ✅ | | +| [@compiled/no-css-prop-without-css-function](./src/rules/no-css-prop-without-css-function) | Disallows `css` prop usages where it is either not wrapped in the `css` import from `@compiled/react` or where `@compiled` cannot determine whether the `css` import is included at build time. | ✅ | 🔧 | +| [@compiled/no-css-tagged-template-expression](./src/rules/no-css-tagged-template-expression) | Disallows the `css` tagged template expression | ✅ | 🔧 | +| [@compiled/no-emotion-css](./src/rules/no-emotion-css) | Disallows `@emotion` usages | | 🔧 | +| [@compiled/no-empty-styled-expression](./src/rules/no-empty-styled-expression) | Disallows any `styled` expression to be used when passing empty arguments in `@compiled/react` | ✅ | | +| [@compiled/no-exported-css](./src/rules/no-exported-css) | Disallows `css` usages from being exported | ✅ | | +| [@compiled/no-exported-keyframes](./src/rules/no-exported-keyframes) | Disallows `keyframes` usages from being exported | ✅ | | +| [@compiled/no-invalid-css-map](./src/rules/no-invalid-css-map) | Checks the validity of a CSS map created through cssMap. This is intended to be used alongside TypeScript's type-checking. | ✅ | | +| [@compiled/no-js-xcss](./src/rules/no-js-xcss) | The xcss prop is predicated on adhering to the type contract. Using it without TypeScript breaks this contract and thus is not allowed. | ✅ | | +| [@compiled/no-keyframes-tagged-template-expression](./src/rules/no-keyframes-tagged-template-expression) | Disallows the `keyframes` tagged template expression | ✅ | 🔧 | +| [@compiled/no-styled-tagged-template-expression](./src/rules/no-styled-tagged-template-expression) | Disallows the `styled` tagged template expression | ✅ | 🔧 | +| [@compiled/no-suppress-xcss](./src/rules/no-suppress-xcss) | The xcss prop is predicated on adhering to the type contract. Supressing it breaks this contract and thus is not allowed. | ✅ | | +| [@compiled/shorthand-property-sorting](./src/rules/shorthand-property-sorting) | Prevent unwanted side-effect by ensuring shorthand properties are always defined before their related longhands. | ✅ | | diff --git a/packages/eslint-plugin/src/configs/flat-recommended.ts b/packages/eslint-plugin/src/configs/flat-recommended.ts new file mode 100644 index 000000000..2609f2151 --- /dev/null +++ b/packages/eslint-plugin/src/configs/flat-recommended.ts @@ -0,0 +1,16 @@ +export const flatRecommended = { + // plugin is not specified here because flat config needs a reference to the plugin + rules: { + '@compiled/local-cx-xcss': 'error', + '@compiled/no-css-prop-without-css-function': 'error', + '@compiled/no-css-tagged-template-expression': 'error', + '@compiled/no-empty-styled-expression': 'error', + '@compiled/no-exported-css': 'error', + '@compiled/no-exported-keyframes': 'error', + '@compiled/no-invalid-css-map': 'error', + '@compiled/no-js-xcss': 'error', + '@compiled/no-keyframes-tagged-template-expression': 'error', + '@compiled/no-styled-tagged-template-expression': 'error', + '@compiled/no-suppress-xcss': 'error', + }, +} as const; diff --git a/packages/eslint-plugin/src/configs/recommended.ts b/packages/eslint-plugin/src/configs/recommended.ts index ffa6b29ce..9a7e65d80 100644 --- a/packages/eslint-plugin/src/configs/recommended.ts +++ b/packages/eslint-plugin/src/configs/recommended.ts @@ -4,6 +4,7 @@ export const recommended = { '@compiled/local-cx-xcss': 'error', '@compiled/no-css-prop-without-css-function': 'error', '@compiled/no-css-tagged-template-expression': 'error', + '@compiled/no-empty-styled-expression': 'error', '@compiled/no-exported-css': 'error', '@compiled/no-exported-keyframes': 'error', '@compiled/no-invalid-css-map': 'error', @@ -11,6 +12,5 @@ export const recommended = { '@compiled/no-keyframes-tagged-template-expression': 'error', '@compiled/no-styled-tagged-template-expression': 'error', '@compiled/no-suppress-xcss': 'error', - '@compiled/no-empty-styled-expression': 'error', }, }; diff --git a/packages/eslint-plugin/src/index.ts b/packages/eslint-plugin/src/index.ts index 61c2a18a2..751992fce 100644 --- a/packages/eslint-plugin/src/index.ts +++ b/packages/eslint-plugin/src/index.ts @@ -1,3 +1,6 @@ +import pkgJson from '../package.json'; + +import { flatRecommended } from './configs/flat-recommended'; import { recommended } from './configs/recommended'; import { jsxPragmaRule } from './rules/jsx-pragma'; import { localCXXCSSRule } from './rules/local-cx-xcss'; @@ -14,6 +17,8 @@ import { noStyledTaggedTemplateExpressionRule } from './rules/no-styled-tagged-t import { noSuppressXCSS } from './rules/no-suppress-xcss'; import { shorthandFirst } from './rules/shorthand-property-sorting'; +const { name, version } = pkgJson; + export const rules = { 'jsx-pragma': jsxPragmaRule, 'local-cx-xcss': localCXXCSSRule, @@ -29,8 +34,25 @@ export const rules = { 'no-suppress-xcss': noSuppressXCSS, 'no-empty-styled-expression': noEmptyStyledExpressionRule, 'shorthand-property-sorting': shorthandFirst, -}; +} as const; + +export const plugin = { + name, + version, + rules, + configs: { + recommended, + 'flat/recommended': { + ...flatRecommended, + plugins: { + get '@compiled'() { + return plugin; + }, + }, + }, + }, +} as const; + +export const configs = plugin.configs; -export const configs = { - recommended, -}; +export default plugin; diff --git a/packages/eslint-plugin/src/rules/jsx-pragma/index.ts b/packages/eslint-plugin/src/rules/jsx-pragma/index.ts index 9df69b7d4..8049c0f11 100644 --- a/packages/eslint-plugin/src/rules/jsx-pragma/index.ts +++ b/packages/eslint-plugin/src/rules/jsx-pragma/index.ts @@ -114,6 +114,7 @@ function createFixer(context: Rule.RuleContext, source: SourceCode, options: Opt export const jsxPragmaRule: Rule.RuleModule = { meta: { docs: { + description: 'Enforces a jsx pragma when using the `css` prop', url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/jsx-pragma', }, fixable: 'code', diff --git a/packages/eslint-plugin/src/rules/local-cx-xcss/index.ts b/packages/eslint-plugin/src/rules/local-cx-xcss/index.ts index be4df07e0..bcd31336f 100644 --- a/packages/eslint-plugin/src/rules/local-cx-xcss/index.ts +++ b/packages/eslint-plugin/src/rules/local-cx-xcss/index.ts @@ -19,6 +19,7 @@ function getParentJSXAttribute(node: Rule.Node) { export const localCXXCSSRule: Rule.RuleModule = { meta: { docs: { + description: 'Ensures the `cx()` function is only used within the `xcss` prop', recommended: true, url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/local-cx-xcss', }, diff --git a/packages/eslint-plugin/src/rules/no-css-prop-without-css-function/index.ts b/packages/eslint-plugin/src/rules/no-css-prop-without-css-function/index.ts index d8ae4bc86..fc9ccd17d 100644 --- a/packages/eslint-plugin/src/rules/no-css-prop-without-css-function/index.ts +++ b/packages/eslint-plugin/src/rules/no-css-prop-without-css-function/index.ts @@ -222,7 +222,7 @@ export const noCssPropWithoutCssFunctionRule: TSESLint.RuleModule = { url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/no-css-prop-without-css-function', recommended: 'error', description: - 'Disallows `css` prop usages without wrapping in the `css` import from `@compiled/react`. Also forbids `css` prop usages where Compiled cannot determine whether the `css` import is included at build time.', + 'Disallows `css` prop usages where it is either not wrapped in the `css` import from `@compiled/react` or where `@compiled` cannot determine whether the `css` import is included at build time.', }, messages: { noCssFunction: 'css prop values are required to use the css import from @compiled/react', diff --git a/packages/eslint-plugin/src/rules/no-css-tagged-template-expression/index.ts b/packages/eslint-plugin/src/rules/no-css-tagged-template-expression/index.ts index 742f9570c..9688c2fce 100644 --- a/packages/eslint-plugin/src/rules/no-css-tagged-template-expression/index.ts +++ b/packages/eslint-plugin/src/rules/no-css-tagged-template-expression/index.ts @@ -5,6 +5,8 @@ import { createNoTaggedTemplateExpressionRule, isCss } from '../../utils'; export const noCssTaggedTemplateExpressionRule: Rule.RuleModule = { meta: { docs: { + recommended: true, + description: 'Disallows the `css` tagged template expression', url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/no-css-tagged-template-expression', }, fixable: 'code', diff --git a/packages/eslint-plugin/src/rules/no-emotion-css/index.ts b/packages/eslint-plugin/src/rules/no-emotion-css/index.ts index d4e68e5d8..b678b3bce 100644 --- a/packages/eslint-plugin/src/rules/no-emotion-css/index.ts +++ b/packages/eslint-plugin/src/rules/no-emotion-css/index.ts @@ -29,6 +29,7 @@ export const noEmotionCssRule: Rule.RuleModule = { fixable: 'code', type: 'problem', docs: { + description: 'Disallows `@emotion` usages', url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/no-emotion-css', }, messages: { diff --git a/packages/eslint-plugin/src/rules/no-empty-styled-expression/index.ts b/packages/eslint-plugin/src/rules/no-empty-styled-expression/index.ts index c2ef5f89c..ef624d4c4 100644 --- a/packages/eslint-plugin/src/rules/no-empty-styled-expression/index.ts +++ b/packages/eslint-plugin/src/rules/no-empty-styled-expression/index.ts @@ -50,6 +50,9 @@ const createNoEmptyStyledExpressionRule = export const noEmptyStyledExpressionRule: Rule.RuleModule = { meta: { docs: { + recommended: true, + description: + 'Disallows any `styled` expression to be used when passing empty arguments in `@compiled/react`', url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/no-empty-styled-expression', }, messages: { diff --git a/packages/eslint-plugin/src/rules/no-exported-css/index.ts b/packages/eslint-plugin/src/rules/no-exported-css/index.ts index 1eedebae2..1230eaa95 100644 --- a/packages/eslint-plugin/src/rules/no-exported-css/index.ts +++ b/packages/eslint-plugin/src/rules/no-exported-css/index.ts @@ -5,6 +5,8 @@ import { createNoExportedRule, isCss } from '../../utils'; export const noExportedCssRule: Rule.RuleModule = { meta: { docs: { + recommended: true, + description: 'Disallows `css` usages from being exported', url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/no-exported-css', }, messages: { diff --git a/packages/eslint-plugin/src/rules/no-exported-keyframes/index.ts b/packages/eslint-plugin/src/rules/no-exported-keyframes/index.ts index a31edfd47..93dde6eef 100644 --- a/packages/eslint-plugin/src/rules/no-exported-keyframes/index.ts +++ b/packages/eslint-plugin/src/rules/no-exported-keyframes/index.ts @@ -5,6 +5,8 @@ import { createNoExportedRule, isKeyframes } from '../../utils'; export const noExportedKeyframesRule: Rule.RuleModule = { meta: { docs: { + recommended: true, + description: 'Disallows `keyframes` usages from being exported', url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/no-exported-css', }, messages: { diff --git a/packages/eslint-plugin/src/rules/no-invalid-css-map/index.ts b/packages/eslint-plugin/src/rules/no-invalid-css-map/index.ts index ff76ad219..d7eb4d21c 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-css-map/index.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-css-map/index.ts @@ -69,6 +69,7 @@ const createCssMapRule = (context: Rule.RuleContext): Rule.RuleListener => { export const noInvalidCssMapRule: Rule.RuleModule = { meta: { docs: { + recommended: true, description: "Checks the validity of a CSS map created through cssMap. This is intended to be used alongside TypeScript's type-checking.", url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/no-invalid-css-map', diff --git a/packages/eslint-plugin/src/rules/no-keyframes-tagged-template-expression/index.ts b/packages/eslint-plugin/src/rules/no-keyframes-tagged-template-expression/index.ts index afb86177a..1f64020aa 100644 --- a/packages/eslint-plugin/src/rules/no-keyframes-tagged-template-expression/index.ts +++ b/packages/eslint-plugin/src/rules/no-keyframes-tagged-template-expression/index.ts @@ -5,6 +5,8 @@ import { createNoTaggedTemplateExpressionRule, isKeyframes } from '../../utils'; export const noKeyframesTaggedTemplateExpressionRule: Rule.RuleModule = { meta: { docs: { + recommended: true, + description: 'Disallows the `keyframes` tagged template expression', url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/no-keyframes-tagged-template-expression', }, fixable: 'code', diff --git a/packages/eslint-plugin/src/rules/no-styled-tagged-template-expression/index.ts b/packages/eslint-plugin/src/rules/no-styled-tagged-template-expression/index.ts index 6f0aa74e8..c6e314052 100644 --- a/packages/eslint-plugin/src/rules/no-styled-tagged-template-expression/index.ts +++ b/packages/eslint-plugin/src/rules/no-styled-tagged-template-expression/index.ts @@ -5,6 +5,8 @@ import { createNoTaggedTemplateExpressionRule, isStyled } from '../../utils'; export const noStyledTaggedTemplateExpressionRule: Rule.RuleModule = { meta: { docs: { + recommended: true, + description: 'Disallows the `styled` tagged template expression', url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/no-styled-tagged-template-expression', }, fixable: 'code', diff --git a/packages/eslint-plugin/src/rules/shorthand-property-sorting/index.ts b/packages/eslint-plugin/src/rules/shorthand-property-sorting/index.ts index c7f9c126f..2901f4822 100644 --- a/packages/eslint-plugin/src/rules/shorthand-property-sorting/index.ts +++ b/packages/eslint-plugin/src/rules/shorthand-property-sorting/index.ts @@ -57,7 +57,7 @@ export const shorthandFirst: Rule.RuleModule = { meta: { docs: { description: - 'Prevent unwanted side-effect by ensuring shorthand properties are always defined before their related longhands. See more in the README.', + 'Prevent unwanted side-effect by ensuring shorthand properties are always defined before their related longhands.', recommended: true, url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/shorthand-property-sorting', },