Skip to content

Commit

Permalink
feat(deps): adopt eslint-plugin-tailwindcss
Browse files Browse the repository at this point in the history
- thanks to @navin-moorthy for initial PR
  • Loading branch information
ljosberinn committed Mar 25, 2023
1 parent 532a305 commit 1f8fcd4
Show file tree
Hide file tree
Showing 27 changed files with 182 additions and 18 deletions.
13 changes: 13 additions & 0 deletions __tests__/detection/detectTailwind.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { detectTailwind } from '../../src/getDependencies';

describe('detectTailwind', () => {
test('with tailwindcss', () => {
const map = new Map<string, string>([['tailwindcss', '1.0.0']]);

expect(detectTailwind(map)).toBe(true);
});

test('without any', () => {
expect(detectTailwind(new Map())).toBe(false);
});
});
1 change: 1 addition & 0 deletions __tests__/getDependencies.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ describe('getDependencies', () => {
"hasJestDom": false,
"hasNest": false,
"hasNodeTypes": false,
"hasTailwind": false,
"hasTestingLibrary": false,
"react": {
"hasReact": false,
Expand Down
13 changes: 13 additions & 0 deletions __tests__/plugins/__snapshots__/tailwindcss.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`with tailwind 1`] = `
{
"tailwindcss/classnames-order": "warn",
"tailwindcss/enforces-negative-arbitrary-values": "warn",
"tailwindcss/enforces-shorthand": "warn",
"tailwindcss/migration-from-tailwind-2": "warn",
"tailwindcss/no-arbitrary-value": "off",
"tailwindcss/no-contradicting-classname": "error",
"tailwindcss/no-custom-classname": "warn",
}
`;
2 changes: 1 addition & 1 deletion __tests__/plugins/eslint-core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ test('allows passing rules', () => {
},
});

expect(result[ruleName]).toBe(ruleValue);
expect(result?.[ruleName]).toBe(ruleValue);
});

[
Expand Down
2 changes: 1 addition & 1 deletion __tests__/plugins/import.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test('allows passing rules', () => {
},
});

expect(result[ruleName]).toBe(ruleValue);
expect(result?.[ruleName]).toBe(ruleValue);
});

test('with typescript', () => {
Expand Down
2 changes: 1 addition & 1 deletion __tests__/plugins/promise.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test('allows passing rules', () => {
},
});

expect(result[ruleName]).toBe(ruleValue);
expect(result?.[ruleName]).toBe(ruleValue);
});

test('with typescript', () => {
Expand Down
2 changes: 1 addition & 1 deletion __tests__/plugins/sonarjs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ test('allows passing rules', () => {
},
});

expect(result[ruleName]).toBe(ruleValue);
expect(result?.[ruleName]).toBe(ruleValue);
});

test('with typescript', () => {
Expand Down
25 changes: 25 additions & 0 deletions __tests__/plugins/tailwindcss.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createTailwindPlugin } from '../../src/plugins/tailwindcss';
import { defaultProject } from '../shared';

test('allows passing rules', () => {
const ruleName = 'foo';
const ruleValue = 'off';

const result = createTailwindPlugin({
...defaultProject,
rules: {
[ruleName]: ruleValue,
},
});

expect(result?.[ruleName]).toBe(ruleValue);
});

test('with tailwind', () => {
expect(
createTailwindPlugin({
...defaultProject,
hasTailwind: true,
})
).toMatchSnapshot();
});
2 changes: 1 addition & 1 deletion __tests__/plugins/unicorn.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test('allows passing rules', () => {
},
});

expect(result[ruleName]).toBe(ruleValue);
expect(result?.[ruleName]).toBe(ruleValue);
});

test('with typescript', () => {
Expand Down
1 change: 1 addition & 0 deletions __tests__/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const defaultProject: Parameters<OverrideCreator>[0] = {
hasNest: false,
hasNodeTypes: false,
hasTestingLibrary: false,
hasTailwind: true,
react: {
hasReact: false,
isCreateReactApp: false,
Expand Down
3 changes: 2 additions & 1 deletion integration/cra-js/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
"config": null,
"hasTypeScript": false,
"version": null
}
},
"hasTailwind": false
}
3 changes: 2 additions & 1 deletion integration/cra-ts/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@
},
"hasTypeScript": true,
"version": "^4.4.2"
}
},
"hasTailwind": false
}
3 changes: 2 additions & 1 deletion integration/jest/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,6 @@
},
"hasTypeScript": true,
"version": "4.6.4"
}
},
"hasTailwind": false
}
3 changes: 2 additions & 1 deletion integration/js-ts-migration-mix-checkJs-off/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,6 @@
},
"hasTypeScript": true,
"version": "4.6.4"
}
},
"hasTailwind": false
}
3 changes: 2 additions & 1 deletion integration/js-ts-migration-mix-checkJs-on/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,6 @@
},
"hasTypeScript": true,
"version": "4.6.4"
}
},
"hasTailwind": false
}
3 changes: 2 additions & 1 deletion integration/js-ts-migration-mix-force-js-linting/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@
},
"hasTypeScript": true,
"version": "4.6.4"
}
},
"hasTailwind": false
}
3 changes: 2 additions & 1 deletion integration/nest-ts/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@
},
"hasTypeScript": true,
"version": "^4.4.4"
}
},
"hasTailwind": false
}
3 changes: 2 additions & 1 deletion integration/next-js/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
"config": null,
"hasTypeScript": false,
"version": null
}
},
"hasTailwind": false
}
3 changes: 2 additions & 1 deletion integration/next-ts/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,6 @@
},
"hasTypeScript": true,
"version": "4.9.4"
}
},
"hasTailwind": false
}
3 changes: 2 additions & 1 deletion integration/remix-js/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
"config": null,
"hasTypeScript": false,
"version": null
}
},
"hasTailwind": false
}
3 changes: 2 additions & 1 deletion integration/remix-ts/deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,6 @@
},
"hasTypeScript": true,
"version": "^4.1.2"
}
},
"hasTailwind": false
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
"eslint-plugin-simple-import-sort": "10.0.0",
"eslint-plugin-sonarjs": "0.19.0",
"eslint-plugin-storybook": "0.6.11",
"eslint-plugin-tailwindcss": "3.10.1",
"eslint-plugin-testing-library": "5.10.2",
"eslint-plugin-unicorn": "46.0.0",
"lodash.merge": "4.6.2",
Expand Down
2 changes: 2 additions & 0 deletions src/createConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { createImportRules } from './plugins/import';
import { createSimpleImportSortRules } from './plugins/import-sort';
import { createPromiseRules } from './plugins/promise';
import { createSonarjsRules } from './plugins/sonarjs';
import { createTailwindRules } from './plugins/tailwindcss';
import { createUnicornRules } from './plugins/unicorn';
import {
type ESLintConfig,
Expand Down Expand Up @@ -98,6 +99,7 @@ export const createConfig = ({
...createImportRules(dependencies),
...createSonarjsRules(dependencies),
...createSimpleImportSortRules(dependencies),
...createTailwindRules(dependencies),
...rules,
},
flags
Expand Down
9 changes: 9 additions & 0 deletions src/getDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ export const detectStorybook = (
};
};

export const detectTailwind = (
dependencies: Map<string, string>
): Dependencies['hasTailwind'] => {
return dependencies.has('tailwindcss');
};

export const detectNest = (
dependencies: Map<string, string>
): Dependencies['hasNest'] => {
Expand Down Expand Up @@ -142,6 +148,7 @@ export const getDependencies = ({
const hasTestingLibrary = detectTestingLibrary(deps);
const storybook = detectStorybook(deps);
const hasNest = detectNest(deps);
const hasTailwind = detectTailwind(deps);

return {
hasJest,
Expand All @@ -152,6 +159,7 @@ export const getDependencies = ({
storybook,
react,
typescript,
hasTailwind,
};
} catch (error) {
// eslint-disable-next-line no-console
Expand Down Expand Up @@ -180,6 +188,7 @@ export const getDependencies = ({
hasTypeScript: false,
version: null,
},
hasTailwind: false,
};
}
};
70 changes: 70 additions & 0 deletions src/plugins/tailwindcss.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import type { RulesetCreator } from '../types';

export const createTailwindPlugin: RulesetCreator = ({
rules: customRules,
...dependencies
}) => ({
...createTailwindRules(dependencies),
...customRules,
});

/**
* @see https://github.com/francoismassart/eslint-plugin-tailwindcss
*
*/
export const createTailwindRules: RulesetCreator = ({ hasTailwind }) => {
if (!hasTailwind) {
return null;
}

return {
/**
* order classnames for consistency and it makes merge conflict a bit easier to resolve
*
* @see https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/classnames-order.md
*/
'tailwindcss/classnames-order': 'warn',

/**
* make sure to use negative arbitrary values classname without the negative classname e.g. -top-[5px] should become top-[-5px]
*
* @see https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/enforces-negative-arbitrary-values.md
*/
'tailwindcss/enforces-negative-arbitrary-values': 'warn',

/**
* merge multiple classnames into shorthand if possible e.g. mx-5 my-5 should become m-5
*
* @see https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/enforces-shorthand.md
*/
'tailwindcss/enforces-shorthand': 'warn',

/**
* for easy upgrade from Tailwind CSS v2 to v3. Warning: at the moment you should temporary turn off the no-custom-classname rule if you want to see the warning from migration-from-tailwind-2
*
* @see https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/migration-from-tailwind-2.md
*/
'tailwindcss/migration-from-tailwind-2': 'warn',

/**
* forbid using arbitrary values in classnames (turned off by default)
*
* @see https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/no-arbitrary-value.md
*/
'tailwindcss/no-arbitrary-value': 'off',

/**
* only allow classnames from Tailwind CSS and the values from the whitelist option
*
* @see https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/no-custom-classname.md
*/
'tailwindcss/no-custom-classname': 'warn',

/**
* e.g. avoid p-2 p-3, different Tailwind CSS classnames (pt-2 & pt-3) but targeting the same property several times for the same variant.
*
* @see https://github.com/francoismassart/eslint-plugin-tailwindcss/blob/master/docs/rules/no-contradicting-classname.md
*/
'tailwindcss/no-contradicting-classname': 'error',
};
};
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export type Dependencies = {
hasTypeScript: boolean;
version: null | string;
};
hasTailwind: boolean;
};

export type ESLintConfig = Omit<
Expand Down Expand Up @@ -67,7 +68,7 @@ export type RulesetCreator = (
args: Dependencies & {
rules?: Linter.RulesRecord;
}
) => Linter.RulesRecord;
) => Linter.RulesRecord | null;

/**
* internal type including the custom `overrideType` property
Expand Down
19 changes: 18 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2835,6 +2835,14 @@ [email protected]:
requireindex "^1.1.0"
ts-dedent "^2.2.0"

[email protected]:
version "3.10.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-tailwindcss/-/eslint-plugin-tailwindcss-3.10.1.tgz#727193f78cc22b9b358ef5f99de2177d173a5209"
integrity sha512-NLPZ6b6nd/8CgGNMQ6NDiPUfBLQpSGu/u9RyX3MCZOwzNs2dFt1OamNAiRuo3Ixh7Gv4t5UcAcdNt8z74UDJkA==
dependencies:
fast-glob "^3.2.5"
postcss "^8.4.4"

[email protected]:
version "5.10.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.2.tgz#12f231ad9b52b6aef45c801fd00aa129a932e0c2"
Expand Down Expand Up @@ -3055,7 +3063,7 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==

fast-glob@^3.2.11, fast-glob@^3.2.9:
fast-glob@^3.2.11, fast-glob@^3.2.5, fast-glob@^3.2.9:
version "3.2.12"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
Expand Down Expand Up @@ -5809,6 +5817,15 @@ [email protected]:
picocolors "^1.0.0"
source-map-js "^1.0.2"

postcss@^8.4.4:
version "8.4.21"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4"
integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==
dependencies:
nanoid "^3.3.4"
picocolors "^1.0.0"
source-map-js "^1.0.2"

prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
Expand Down

0 comments on commit 1f8fcd4

Please sign in to comment.