@purpurds/eslint-plugin-purpur 6.9.0 → 6.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purpurds/eslint-plugin-purpur",
3
- "version": "6.9.0",
3
+ "version": "6.10.0",
4
4
  "main": "src/index.js",
5
5
  "files": [
6
6
  "index.js",
@@ -10,16 +10,17 @@
10
10
  ],
11
11
  "dependencies": {
12
12
  "requireindex": "~1.2.0",
13
- "@purpurds/purpur": "6.9.0"
13
+ "@purpurds/purpur": "6.10.0"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/node": "20.12.12",
17
17
  "eslint-config-prettier": "~8.10.0",
18
18
  "eslint-plugin-prettier": "~3.4.1",
19
- "eslint": "^8.57.0",
20
- "lint-staged": "~10.5.3",
19
+ "eslint": "9.24.0",
20
+ "lint-staged": "15.5.0",
21
21
  "mocha": "~10.2.0",
22
- "prettier": "~2.8.8"
22
+ "prettier": "~2.8.8",
23
+ "@purpurds/component-rig": "1.0.0"
23
24
  },
24
25
  "peerDependencies": {
25
26
  "eslint": ">=8"
package/readme.md CHANGED
@@ -8,8 +8,20 @@ rush: `rush add -p @purpurds/eslint-plugin-purpur --dev`
8
8
 
9
9
  npm: `npm i @purpurds/eslint-plugin-purpur`
10
10
 
11
- ## Basic usage
12
11
 
12
+ ## Flat config
13
+ ```ts
14
+ import purpurPlugin from "@purpurds/eslint-plugin-purpur"
15
+
16
+ export default [
17
+ {
18
+ files: ["**/*.ts?(x)"],
19
+ ...purpurPlugin.configs["recommended-flat"],
20
+ }
21
+ ]
22
+ ```
23
+
24
+ ## Legacy config
13
25
  ```js
14
26
  // eslint <= 8
15
27
  module.exports = {
@@ -19,33 +31,30 @@ module.exports = {
19
31
 
20
32
  ## Custom usage
21
33
 
22
- Available rules:
23
-
24
- - `no-barrel-imports`
25
-
26
- ```js
27
- // eslint <= 8
28
- module.exports = {
29
- plugins: ["@purpurds/purpur"],
30
- rules: {
31
- "@purpurds/purpur/[RULE_NAME]": "error" | "warn",
32
- },
33
- };
34
- ```
35
-
36
- ```js
37
- // eslint >= 9
38
- import purpur from "@purpur/eslint-plugin-purpur";
34
+ ### Flat config
35
+ ```ts
36
+ import purpurPlugin from "@purpur/eslint-plugin-purpur";
39
37
 
40
38
  export default [
41
39
  {
42
- files: ["**/*.js"],
40
+ files: ["**/*.ts?(x)"],
43
41
  plugins: {
44
- purpur: purpur,
42
+ purpur: purpurPlugin,
45
43
  },
46
44
  rules: {
47
- "purpur/no-barrel-imports": "error",
45
+ "purpur/no-barrel-imports-flat": "error",
48
46
  },
49
47
  },
50
48
  ];
51
49
  ```
50
+
51
+ ### Legacy config
52
+ ```js
53
+ // eslint <= 8
54
+ module.exports = {
55
+ plugins: ["@purpurds/purpur"],
56
+ rules: {
57
+ "@purpurds/purpur/no-barrel-imports": "error" | "warn",
58
+ },
59
+ };
60
+ ```
@@ -0,0 +1,7 @@
1
+ // @ts-check
2
+ module.exports = {
3
+ plugins: ["@purpurds/purpur"],
4
+ rules: {
5
+ "@purpurds/purpur/no-barrel-imports-flat": "error",
6
+ },
7
+ };
@@ -0,0 +1,96 @@
1
+ // eslint-plugin-no-barrel-import.js
2
+ const { toKebabCase } = require("../internal/utils");
3
+ const componentsMetadata = require("@purpurds/purpur/components-metadata");
4
+
5
+ const exportToModuleMap = new Map(
6
+ componentsMetadata.flatMap((metadata) =>
7
+ metadata.exports.map((exportName) => [exportName, metadata.moduleName])
8
+ )
9
+ );
10
+
11
+ const isValidImport = (moduleName, node) => {
12
+ if (node.source.value === `@purpurds/purpur/${moduleName}`) {
13
+ const metadata = componentsMetadata.find(
14
+ (componentMetadata) => componentMetadata.moduleName === moduleName
15
+ );
16
+ return node.specifiers.every((specifier) => metadata.exports.includes(specifier.imported.name));
17
+ }
18
+
19
+ return false;
20
+ };
21
+
22
+ const invalidBarrelImports = [
23
+ "@purpurds/purpur",
24
+ "@purpurds/purpur/icon",
25
+ "@purpurds/purpur/illustrative-icon",
26
+ ];
27
+
28
+ module.exports = {
29
+ rules: {
30
+ "no-barrel-import": {
31
+ meta: {
32
+ type: "problem",
33
+ docs: {
34
+ description: "Disallows imports from barrel files in '@purpurds/purpur'",
35
+ category: "Best Practices",
36
+ recommended: true,
37
+ },
38
+ messages: {
39
+ noBarrelImport: `Bad purpur import, do not import directly from {{wrongImport}}. Do this instead:\n\n{{correctImport}}\n\n`,
40
+ },
41
+ fixable: "code",
42
+ schema: [],
43
+ },
44
+ create: (context) => ({
45
+ ImportDeclaration(node) {
46
+ if (
47
+ invalidBarrelImports.includes(node.source.value) &&
48
+ !isValidImport("icon", node) &&
49
+ !isValidImport("illustrative-icon", node)
50
+ ) {
51
+ const importsByModule = new Map();
52
+
53
+ node.specifiers.forEach((specifier) => {
54
+ const importName = specifier.imported.name;
55
+ const localName = specifier.local.name;
56
+ const moduleName = exportToModuleMap.get(importName) || toKebabCase(importName);
57
+
58
+ if (!importsByModule.has(moduleName)) {
59
+ importsByModule.set(moduleName, []);
60
+ }
61
+ importsByModule.get(moduleName).push({ importName, localName });
62
+ });
63
+
64
+ const importsSortedByModuleName = Array.from(importsByModule.entries())
65
+ .sort(([a], [b]) => a.localeCompare(b))
66
+ .map(([moduleName, importNames]) => [
67
+ moduleName,
68
+ importNames.sort((a, b) => a.importName.localeCompare(b.importName)),
69
+ ]);
70
+
71
+ const correctImport = importsSortedByModuleName
72
+ .map(
73
+ ([moduleName, importNames]) =>
74
+ `import { ${importNames
75
+ .map(({ importName, localName }) =>
76
+ importName === localName ? importName : `${importName} as ${localName}`
77
+ )
78
+ .join(", ")} } from "@purpurds/purpur/${moduleName}";`
79
+ )
80
+ .join("\n");
81
+
82
+ context.report({
83
+ node,
84
+ messageId: "noBarrelImport",
85
+ data: {
86
+ correctImport,
87
+ wrongImport: node.source.value,
88
+ },
89
+ fix: (fixer) => fixer.replaceText(node, correctImport),
90
+ });
91
+ }
92
+ },
93
+ }),
94
+ },
95
+ },
96
+ };