@forthtilliath/eslint-config 0.4.1 → 0.5.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/README.md CHANGED
@@ -31,6 +31,17 @@ there's nothing else to install per variant.
31
31
 
32
32
  ## Usage
33
33
 
34
+ Quick reference — pick the row matching the package, in its `eslint.config.ts`:
35
+
36
+ | Variant | Subpath | Use for | Extends |
37
+ | ------------------- | --------------- | -------------------------- | ------------- |
38
+ | `baseConfig` | `.` (root) | A plain TypeScript library | — |
39
+ | `reactConfig` | `/react` | A React library | `baseConfig` |
40
+ | `nextJsConfig` | `/nextjs` | A Next.js app | `reactConfig` |
41
+ | `storybookConfig` | `/storybook` | A Storybook app | `reactConfig` |
42
+ | `reactNativeConfig` | `/react-native` | A React Native / Expo app | `reactConfig` |
43
+ | `angularConfig` | `/angular` | An Angular app/library | `baseConfig` |
44
+
34
45
  Pick the variant that matches the package, in its `eslint.config.ts`:
35
46
 
36
47
  ```ts
@@ -111,13 +122,16 @@ export default createBaseConfig({ strict: false, turbo: false });
111
122
  Options are forwarded down the chain, so `createNextJsConfig({ prettier: false })`
112
123
  also disables Prettier in the `reactConfig`/`baseConfig` layers it builds on.
113
124
 
114
- `createReactNativeConfig` also always adds `eslint-plugin-react-native`
115
- (`split-platform-components`, `no-raw-text`) and the RN/Metro-injected
116
- `__DEV__` global — these aren't behind an option, unlike the toggles above.
117
- `no-inline-styles` and `sort-styles` stay off (stylistic, not correctness);
118
- `no-unused-styles` and `no-single-element-style-arrays` also stay off —
119
- `eslint-plugin-react-native@5.0.0` crashes running them under ESLint 10
120
- (`context.getSourceCode is not a function`, an API ESLint 10 removed).
125
+ `createReactNativeConfig` also always adds `eslint-plugin-react-native`'s
126
+ `no-raw-text` rule and the RN/Metro-injected `__DEV__` global — these aren't
127
+ behind an option, unlike the toggles above. Every other rule of the plugin
128
+ stays off: `no-inline-styles`/`sort-styles` are stylistic rather than
129
+ correctness checks, and `no-unused-styles`, `no-single-element-style-arrays`,
130
+ `split-platform-components`, and `no-color-literals` all crash outright under
131
+ ESLint 10 — `eslint-plugin-react-native@5.0.0` still calls
132
+ `context.getSourceCode()`/`context.getFilename()`, APIs ESLint 10 removed.
133
+ `no-raw-text` is the only one that doesn't. Re-enable the others once the
134
+ plugin ships a fix.
121
135
 
122
136
  ```ts
123
137
  // Full i18n project (next-intl, react-intl...): forbid hardcoded JSX strings
@@ -141,6 +155,23 @@ Rules that need type information (`consistent-type-exports`,
141
155
  from linting entirely — none of them belong to a package's own `tsconfig`
142
156
  project, so type-aware rules crash on them otherwise.
143
157
 
158
+ ### Angular import order
159
+
160
+ `angularConfig` overrides `simple-import-sort/imports` on `**/*.ts` so
161
+ `@angular/core`/`rxjs` sort before every other package, ahead of the generic
162
+ "third-party packages, alphabetically" group `baseConfig` uses everywhere
163
+ else — the conventional Angular reading order (framework, then everything
164
+ else, then app code).
165
+
166
+ ## Testing this package
167
+
168
+ Unlike the other five variants — each already exercised by whatever
169
+ package/app in this monorepo lints under them — `angularConfig` has no real
170
+ consumer here yet, so `src/angular.test.js` lints small fixture files under
171
+ `src/__fixtures__/angular/` through ESLint's Node API directly, standing in
172
+ for that. Extend it (or add a sibling `<variant>.test.js`) whenever a variant
173
+ changes without a real consumer to catch a regression.
174
+
144
175
  ## Scripts
145
176
 
146
177
  ```bash
@@ -148,6 +179,8 @@ pnpm run build # tsc -> dist/ (consumers import the built output)
148
179
  pnpm run dev # tsc --watch
149
180
  pnpm run check-types # tsc --noEmit
150
181
  pnpm run lint # eslint (lints its own src/)
182
+ pnpm run test # vitest run
183
+ pnpm run test:watch # vitest
151
184
  ```
152
185
 
153
186
  Run `pnpm run build` after editing `src/*.js` — consuming packages resolve
@@ -1 +1 @@
1
- {"version":3,"file":"angular.d.ts","sourceRoot":"","sources":["../src/angular.js"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,8CAHW,OAAO,WAAW,EAAE,iBAAiB,GACnC,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CA2C5C;AAED;;;;8CAI8C;AAC9C,4BADU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CACS"}
1
+ {"version":3,"file":"angular.d.ts","sourceRoot":"","sources":["../src/angular.js"],"names":[],"mappings":"AAMA;;;;;;;;;;GAUG;AACH,8CAHW,OAAO,WAAW,EAAE,iBAAiB,GACnC,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CA+D5C;AAED;;;;8CAI8C;AAC9C,4BADU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CACS"}
package/dist/angular.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import angular from "angular-eslint";
2
2
  import { defineConfig } from "eslint/config";
3
3
  import tseslint from "typescript-eslint";
4
- import { createBaseConfig } from "./base.js";
4
+ import { createBaseConfig, NODE_BUILTIN_IMPORT_GROUP } from "./base.js";
5
5
  /**
6
6
  * A custom ESLint configuration for Angular applications/libraries.
7
7
  *
@@ -38,6 +38,26 @@ export function createAngularConfig(options) {
38
38
  // Un composant/page Angular sans logique propre (juste un template +
39
39
  // decorateur) est un corps de classe legitimement vide, pas du code mort.
40
40
  "@typescript-eslint/no-extraneous-class": "off",
41
+ // Convention Angular : le framework (et RxJS, quasi-systematiquement
42
+ // utilise a ses cotes) se lit avant le reste — packages tiers, puis
43
+ // imports internes de l'app. baseConfig's generic "^@?\\w" group
44
+ // sorts every third-party package alphabetically together, which
45
+ // would interleave "@angular/core" with unrelated libs instead.
46
+ "simple-import-sort/imports": [
47
+ "error",
48
+ {
49
+ groups: [
50
+ NODE_BUILTIN_IMPORT_GROUP,
51
+ ["^@angular", "^rxjs"],
52
+ ["^@?\\w"],
53
+ ["^(@forthtilliath)(/.*|$)"],
54
+ ["^(@|@ui|components|utils|config)(/.*|$)"],
55
+ ["^\\u0000"],
56
+ ["^\\.\\.(?!/?$)", "^\\.\\./?$"],
57
+ ["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"],
58
+ ],
59
+ },
60
+ ],
41
61
  },
42
62
  },
43
63
  {
package/dist/base.d.ts CHANGED
@@ -19,6 +19,14 @@
19
19
  * @returns {import("eslint").Linter.Config[]}
20
20
  */
21
21
  export function createBaseConfig({ prettier, strict, turbo, }?: BaseConfigOptions): import("eslint").Linter.Config[];
22
+ /**
23
+ * Node.js builtins without the `node:` prefix, as the first
24
+ * `simple-import-sort/imports` group. Exported so other variants (e.g.
25
+ * angular.js, which overrides this rule with Angular-specific groups) don't
26
+ * have to duplicate the list to keep builtins sorted first too.
27
+ * @type {string[]}
28
+ */
29
+ export const NODE_BUILTIN_IMPORT_GROUP: string[];
22
30
  /**
23
31
  * A shared ESLint configuration for the repository, with the default options.
24
32
  * Use `createBaseConfig(options)` instead to customize it.
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;GAaG;AAEH;;;;;GAKG;AACH,gEAHW,iBAAiB,GACf,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAyI5C;AAED;;;;;KAKK;AACL,yBAFU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAEG"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.js"],"names":[],"mappings":"AAuBA;;;;;;;;;;;;;GAaG;AAEH;;;;;GAKG;AACH,gEAHW,iBAAiB,GACf,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAoI5C;AAtKD;;;;;;GAMG;AACH,wCAFU,MAAM,EAAE,CAQhB;AA2JF;;;;;KAKK;AACL,yBAFU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAEG"}
package/dist/base.js CHANGED
@@ -5,6 +5,20 @@ import simpleImportSortPlugin from "eslint-plugin-simple-import-sort";
5
5
  import turboPlugin from "eslint-plugin-turbo";
6
6
  import globals from "globals";
7
7
  import tseslint from "typescript-eslint";
8
+ /**
9
+ * Node.js builtins without the `node:` prefix, as the first
10
+ * `simple-import-sort/imports` group. Exported so other variants (e.g.
11
+ * angular.js, which overrides this rule with Angular-specific groups) don't
12
+ * have to duplicate the list to keep builtins sorted first too.
13
+ * @type {string[]}
14
+ */
15
+ export const NODE_BUILTIN_IMPORT_GROUP = [
16
+ // Node.js builtins. You could also generate this regex if you use a `.js` config.
17
+ // For example: `^(${require("module").builtinModules.join("|")})(/|$)`
18
+ // Note that if you use the `node:` prefix for Node.js builtins,
19
+ // you can avoid this complexity: You can simply use "^node:".
20
+ "^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib|freelist|v8|process|async_hooks|http2|perf_hooks)(/.*|$)",
21
+ ];
8
22
  /**
9
23
  * @typedef {object} BaseConfigOptions
10
24
  * @property {boolean} [prettier=true] - Append eslint-config-prettier at the
@@ -33,6 +47,7 @@ export function createBaseConfig({ prettier = true, strict = true, turbo = true,
33
47
  {
34
48
  ignores: [
35
49
  "dist/**",
50
+ "coverage/**",
36
51
  "storybook-static/**",
37
52
  "postcss.config.cjs",
38
53
  "postcss.config.mjs",
@@ -72,13 +87,7 @@ export function createBaseConfig({ prettier = true, strict = true, turbo = true,
72
87
  "error",
73
88
  {
74
89
  groups: [
75
- // Node.js builtins. You could also generate this regex if you use a `.js` config.
76
- // For example: `^(${require("module").builtinModules.join("|")})(/|$)`
77
- // Note that if you use the `node:` prefix for Node.js builtins,
78
- // you can avoid this complexity: You can simply use "^node:".
79
- [
80
- "^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib|freelist|v8|process|async_hooks|http2|perf_hooks)(/.*|$)",
81
- ],
90
+ NODE_BUILTIN_IMPORT_GROUP,
82
91
  // Packages. `react` related packages come first.
83
92
  ["^react", "^@?\\w"],
84
93
  // Internal packages.
@@ -1 +1 @@
1
- {"version":3,"file":"react-native.d.ts","sourceRoot":"","sources":["../src/react-native.js"],"names":[],"mappings":"AAKA;;;;;GAKG;AAEH;;;;iDAIiD;AACjD,+DAFW,OAAO,WAAW,EAAE,iBAAiB,GAAG,OAAO,YAAY,EAAE,kBAAkB,GAC7E,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAoC5C;AAED;;;;;8CAK8C;AAC9C,gCADU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CACiB"}
1
+ {"version":3,"file":"react-native.d.ts","sourceRoot":"","sources":["../src/react-native.js"],"names":[],"mappings":"AAKA;;;;;GAKG;AAEH;;;;iDAIiD;AACjD,+DAFW,OAAO,WAAW,EAAE,iBAAiB,GAAG,OAAO,YAAY,EAAE,kBAAkB,GAC7E,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAwC5C;AAED;;;;;8CAK8C;AAC9C,gCADU,OAAO,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CACiB"}
@@ -29,21 +29,25 @@ export function createReactNativeConfig({ a11y = false, ...options } = {}) {
29
29
  "react-native": pluginReactNative,
30
30
  },
31
31
  rules: {
32
- "react-native/split-platform-components": "error",
32
+ // The only rule of the plugin that doesn't crash under ESLint 10 (see
33
+ // below) — real, useful signal (raw text outside a <Text>).
33
34
  "react-native/no-raw-text": "error",
34
- // Off by default: both are stylistic preferences rather than
35
- // correctness checks, and inline styles in particular are a common,
36
- // legitimate RN pattern (one-off layout tweaks) that Prettier already
37
- // keeps readable.
35
+ // Off by default: stylistic preference rather than a correctness
36
+ // check, and a common, legitimate RN pattern (one-off layout tweaks)
37
+ // that Prettier already keeps readable.
38
38
  "react-native/no-inline-styles": "off",
39
- // Off: crashes outright under ESLint 10 ("context.getSourceCode is
40
- // not a function") — eslint-plugin-react-native@5.0.0 still calls the
41
- // API ESLint 10 removed, in the util shared by no-unused-styles/
42
- // no-color-literals and in sort-styles/no-single-element-style-arrays
43
- // directly. Re-enable once the plugin ships a fix.
39
+ // Off: every other rule crashes outright under ESLint 10
40
+ // ("context.getSourceCode/getFilename is not a function") —
41
+ // eslint-plugin-react-native@5.0.0 still calls APIs ESLint 10
42
+ // removed, either directly (sort-styles,
43
+ // no-single-element-style-arrays, split-platform-components) or via
44
+ // the util shared with no-unused-styles/no-color-literals. Re-enable
45
+ // each once the plugin ships a fix.
44
46
  "react-native/no-unused-styles": "off",
45
47
  "react-native/no-single-element-style-arrays": "off",
46
48
  "react-native/sort-styles": "off",
49
+ "react-native/split-platform-components": "off",
50
+ "react-native/no-color-literals": "off",
47
51
  },
48
52
  },
49
53
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forthtilliath/eslint-config",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -45,15 +45,20 @@
45
45
  "typescript": ">=5.0.0"
46
46
  },
47
47
  "devDependencies": {
48
+ "@angular/core": "^21.0.0",
48
49
  "eslint": "10.7.0",
50
+ "rxjs": "^7.8.0",
49
51
  "typescript": "^5.9.3",
52
+ "vitest": "^4.1.10",
50
53
  "@forthtilliath/typescript-config": "0.0.0"
51
54
  },
52
55
  "scripts": {
53
- "dev": "tsc --watch",
54
- "build": "tsc",
56
+ "dev": "tsc --watch -p tsconfig.build.json",
57
+ "build": "tsc -p tsconfig.build.json",
55
58
  "clean": "rm -rf dist",
56
59
  "check-types": "tsc --noEmit",
57
- "lint": "eslint . --max-warnings 0"
60
+ "lint": "eslint . --max-warnings 0",
61
+ "test": "vitest run",
62
+ "test:watch": "vitest"
58
63
  }
59
64
  }