@fabdeh/eslint-config 0.2.0 → 0.2.2

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/dist/index.d.mts CHANGED
@@ -187,7 +187,7 @@ interface StylisticOptions {
187
187
  */
188
188
  interface TypeScriptParserOptions {
189
189
  /**
190
- * Optional parser options to be used by the TypeScript parser.
190
+ * Additional parser options for TypeScript.
191
191
  */
192
192
  parserOptions?: TSESLint.FlatConfig.ParserOptions;
193
193
  }
@@ -307,7 +307,7 @@ interface CreateConfigOptions {
307
307
  *
308
308
  * @default auto-detected
309
309
  */
310
- typescript?: OverridesOptions & TypeScriptParserOptions;
310
+ typescript?: boolean | (OverridesOptions & TypeScriptParserOptions);
311
311
  /**
312
312
  * Enable stylistic rules.
313
313
  *
@@ -729,5 +729,14 @@ declare function ensurePackages(packages: (string | undefined)[]): Promise<void>
729
729
  * @returns The name of the nearest package.json
730
730
  */
731
731
  declare function findNearestPackageJsonName(directoryPath?: string): Promise<string>;
732
+ type ResolvedOptions<T> = T extends boolean ? never : NonNullable<T>;
733
+ /**
734
+ * Returns the object representation of the configuration or an empty object if it is a boolean.
735
+ *
736
+ * @param options - The {@link CreateConfigOptions} object to extract the sub-options from.
737
+ * @param key - The property name.
738
+ * @returns An object representing the required options.
739
+ */
740
+ declare function resolveSubOptions<K extends keyof CreateConfigOptions>(options: CreateConfigOptions, key: K): ResolvedOptions<CreateConfigOptions[K]>;
732
741
 
733
- export { type AngularOptions, type Awaitable, type CreateConfigOptions, type FilesOptions, type FormattersOptions, GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, type NgrxOperators, type NgrxOptions, type OverridesOptions, STYLISTIC_CONFIG_DEFAULT, type StylisticConfig, type StylisticOptions, type TestingOptions, type TypeScriptParserOptions, type UnicornOptions, angular, comments, createConfig, ensurePackages, findNearestPackageJsonName, getWorkspaceRoot, ignores, imports, interopDefault, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, perfectionist, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };
742
+ export { type AngularOptions, type Awaitable, type CreateConfigOptions, type FilesOptions, type FormattersOptions, GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, type NgrxOperators, type NgrxOptions, type OverridesOptions, type ResolvedOptions, STYLISTIC_CONFIG_DEFAULT, type StylisticConfig, type StylisticOptions, type TestingOptions, type TypeScriptParserOptions, type UnicornOptions, angular, comments, createConfig, ensurePackages, findNearestPackageJsonName, getWorkspaceRoot, ignores, imports, interopDefault, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, perfectionist, resolveSubOptions, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };
package/dist/index.mjs CHANGED
@@ -10,8 +10,8 @@ import preferArrowFunctions from 'eslint-plugin-prefer-arrow-functions';
10
10
  import unusedImports from 'eslint-plugin-unused-imports';
11
11
  import globals from 'globals';
12
12
  import eslintComments from '@eslint-community/eslint-plugin-eslint-comments';
13
- import * as importX from 'eslint-plugin-import-x';
14
13
  import jsdocPlugin from 'eslint-plugin-jsdoc';
14
+ import * as importX from 'eslint-plugin-import-x';
15
15
  import perfectionistPlugin from 'eslint-plugin-perfectionist';
16
16
  import unicornPlugin from 'eslint-plugin-unicorn';
17
17
  import { mergeProcessors, processorPassThrough } from 'eslint-merge-processors';
@@ -135,6 +135,12 @@ async function findNearestPackageJsonName(directoryPath = resolve()) {
135
135
  return findNearestPackageJsonName(parentDir);
136
136
  }
137
137
  }
138
+ function resolveSubOptions(options, key) {
139
+ if (typeof options[key] === "boolean") {
140
+ return {};
141
+ }
142
+ return options[key] ?? {};
143
+ }
138
144
 
139
145
  async function angular(options = {}) {
140
146
  const angularEslint = await interopDefault(import('angular-eslint'));
@@ -272,7 +278,7 @@ function imports(options = {}) {
272
278
  const { stylistic = true } = options;
273
279
  return tseslint.config(
274
280
  {
275
- name: "fabdeh/imports/common/rules",
281
+ name: "fabdeh/imports/rules",
276
282
  files: [GLOB_SRC],
277
283
  plugins: {
278
284
  "import-x": importX
@@ -282,7 +288,9 @@ function imports(options = {}) {
282
288
  "import-x/default": "error",
283
289
  "import-x/export": "error",
284
290
  "import-x/first": "error",
291
+ "import-x/named": "error",
285
292
  "import-x/no-absolute-path": "error",
293
+ "import-x/no-deprecated": "error",
286
294
  "import-x/no-duplicates": "error",
287
295
  "import-x/no-empty-named-blocks": "error",
288
296
  "import-x/no-extraneous-dependencies": "error",
@@ -299,15 +307,7 @@ function imports(options = {}) {
299
307
  }
300
308
  },
301
309
  {
302
- name: "fabdeh/imports/js-only/rules",
303
- files: [GLOB_JS],
304
- rules: {
305
- "import-x/named": "error",
306
- "import-x/no-deprecated": "error"
307
- }
308
- },
309
- {
310
- name: "fabdeh/imports/ts-only/rules",
310
+ name: "fabdeh/imports/ts-disables",
311
311
  files: [GLOB_TS],
312
312
  rules: {
313
313
  "import-x/named": "off",
@@ -332,7 +332,6 @@ function javascript(options = {}) {
332
332
  navigator: "readonly",
333
333
  window: "readonly"
334
334
  },
335
- parser: tseslint.parser,
336
335
  parserOptions: {
337
336
  ecmaFeatures: {
338
337
  jsx: true
@@ -602,6 +601,28 @@ async function markdown(options = {}) {
602
601
  overrides = {}
603
602
  } = options;
604
603
  const markdownPlugin = await interopDefault(import('@eslint/markdown'));
604
+ const parserPlain = {
605
+ meta: {
606
+ name: "parser-plain"
607
+ },
608
+ parseForESLint: (code) => ({
609
+ ast: {
610
+ body: [],
611
+ comments: [],
612
+ loc: { end: code.length, start: 0 },
613
+ range: [0, code.length],
614
+ tokens: [],
615
+ type: "Program"
616
+ },
617
+ // eslint-disable-next-line unicorn/no-null
618
+ scopeManager: null,
619
+ services: { isPlain: true },
620
+ visitorKeys: {
621
+ // eslint-disable-next-line @typescript-eslint/naming-convention
622
+ Program: []
623
+ }
624
+ })
625
+ };
605
626
  return tseslint.config(
606
627
  {
607
628
  name: "fabdeh/markdown/setup",
@@ -616,16 +637,18 @@ async function markdown(options = {}) {
616
637
  processor: mergeProcessors([
617
638
  markdownPlugin.processors.markdown,
618
639
  processorPassThrough
619
- ]),
620
- rules: {
621
- ...markdownPlugin.configs.recommended.at(0)?.rules,
622
- "markdown/no-duplicate-headings": "error"
640
+ ])
641
+ },
642
+ {
643
+ name: "fabdeh/markdown/parser",
644
+ files,
645
+ languageOptions: {
646
+ parser: parserPlain
623
647
  }
624
648
  },
625
649
  {
626
650
  name: "fabdeh/markdown/disables",
627
651
  languageOptions: {
628
- parser: tseslint.parser,
629
652
  parserOptions: {
630
653
  ecmaFeatures: {
631
654
  impliedStrict: true
@@ -659,9 +682,16 @@ async function markdown(options = {}) {
659
682
  "unicode-bom": "off",
660
683
  "unused-imports/no-unused-imports": "off",
661
684
  "unused-imports/no-unused-vars": "off",
662
- "unicorn/filename-case": "off",
663
685
  ...overrides
664
686
  }
687
+ },
688
+ {
689
+ name: "fabdeh/markdown/rules",
690
+ files,
691
+ rules: {
692
+ ...markdownPlugin.configs.recommended.at(0)?.rules,
693
+ "markdown/no-duplicate-headings": "error"
694
+ }
665
695
  }
666
696
  );
667
697
  }
@@ -1249,27 +1279,36 @@ const memberOrdering = {
1249
1279
  };
1250
1280
 
1251
1281
  function typescript(options = {}) {
1252
- const { stylistic = true, parserOptions, overrides } = options;
1282
+ const { stylistic = true, parserOptions = {}, overrides = {} } = options;
1253
1283
  return tseslint.config(
1254
1284
  {
1255
1285
  name: "fabdeh/typescript/setup",
1286
+ files: [GLOB_TS],
1287
+ ignores: [`${GLOB_MARKDOWN}/**`],
1256
1288
  languageOptions: {
1257
- parserOptions: parserOptions ?? {
1258
- projectService: true,
1259
- tsconfigRootDir: getWorkspaceRoot(process.cwd(), process.cwd())
1289
+ parser: tseslint.parser,
1290
+ parserOptions: {
1291
+ sourceType: "module",
1292
+ projectService: {
1293
+ allowDefaultProject: ["*.js"],
1294
+ defaultProject: "tsconfig.json"
1295
+ },
1296
+ tsconfigRootDir: getWorkspaceRoot(process.cwd(), process.cwd()),
1297
+ ...parserOptions
1260
1298
  }
1261
1299
  }
1262
1300
  },
1263
1301
  {
1264
1302
  name: "fabdeh/typescript/rules",
1265
1303
  files: [GLOB_TS],
1304
+ ignores: [`${GLOB_MARKDOWN}/**`],
1266
1305
  plugins: {
1267
1306
  "@typescript-eslint": tseslint.plugin,
1268
1307
  "unused-imports": unusedImports
1269
1308
  },
1270
1309
  rules: {
1271
- ...tseslint.configs.stylisticTypeChecked.find((c) => c.name === "typescript-eslint/eslint-recommended")?.rules,
1272
- ...tseslint.configs.stylisticTypeChecked.find((c) => c.name === "typescript-eslint/strict-type-checked")?.rules,
1310
+ ...tseslint.configs.strictTypeChecked.find((c) => c.name === "typescript-eslint/eslint-recommended")?.rules,
1311
+ ...tseslint.configs.strictTypeChecked.find((c) => c.name === "typescript-eslint/strict-type-checked")?.rules,
1273
1312
  ...stylistic ? tseslint.configs.stylisticTypeChecked.find((c) => c.name === "typescript-eslint/stylistic-type-checked")?.rules : {},
1274
1313
  "@typescript-eslint/array-type": ["error", { default: "array" }],
1275
1314
  "@typescript-eslint/consistent-indexed-object-style": "error",
@@ -1341,8 +1380,8 @@ function typescript(options = {}) {
1341
1380
  function unicorn(options = {}) {
1342
1381
  return tseslint.config({
1343
1382
  name: "fabdeh/unicorn/rules",
1344
- plugins: { unicorn: unicornPlugin },
1345
1383
  files: [GLOB_SRC],
1384
+ plugins: { unicorn: unicornPlugin },
1346
1385
  rules: {
1347
1386
  ...options.allRecommended ? unicornPlugin.configs.recommended.rules : {
1348
1387
  "unicorn/catch-error-name": "error",
@@ -1354,7 +1393,7 @@ function unicorn(options = {}) {
1354
1393
  "unicorn/error-message": "error",
1355
1394
  "unicorn/escape-case": "error",
1356
1395
  "unicorn/explicit-length-check": "error",
1357
- "unicorn/filename-case": ["error", { case: "kebabCase" }],
1396
+ "unicorn/filename-case": ["error", { case: "kebabCase", ignore: [/^[A-Z0-9_-]+\.md$/] }],
1358
1397
  "unicorn/new-for-builtins": "error",
1359
1398
  "unicorn/no-abusive-eslint-disable": "error",
1360
1399
  "unicorn/no-anonymous-default-export": "error",
@@ -1563,10 +1602,12 @@ function mergePrettierOptions(options, overrides = {}) {
1563
1602
  return {
1564
1603
  ...options,
1565
1604
  ...overrides,
1605
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
1566
1606
  plugins: [
1567
1607
  ...overrides.plugins ?? [],
1568
1608
  ...options.plugins ?? []
1569
1609
  ]
1610
+ /* eslint-enable @typescript-eslint/no-unsafe-assignment */
1570
1611
  };
1571
1612
  }
1572
1613
  async function formatters(options = {}, stylistic = {}) {
@@ -1788,6 +1829,7 @@ async function createConfig(options = {}, ...userConfigs) {
1788
1829
  gitignore: enableGitignore = true,
1789
1830
  ngrx: enableNgrx = NGRX_PACKAGES.some((p) => isPackageExists(p)),
1790
1831
  tailwindcss: enableTailwind = isPackageExists("tailwindcss"),
1832
+ typescript: enableTypescript = isPackageExists("typescript"),
1791
1833
  unicorn: enableUnicorn = true,
1792
1834
  vitest: enableVitest = isPackageExists("vitest")
1793
1835
  } = options;
@@ -1811,38 +1853,47 @@ async function createConfig(options = {}, ...userConfigs) {
1811
1853
  configs.push(
1812
1854
  ignores(options.ignores),
1813
1855
  javascript({ overrides: options.javascript?.overrides }),
1814
- typescript({
1815
- stylistic: stylisticOptions,
1816
- parserOptions: options.typescript?.parserOptions,
1817
- overrides: options.typescript?.overrides
1818
- }),
1819
1856
  comments(),
1820
- imports({ stylistic: stylisticOptions }),
1857
+ // TODO: add node rules ???
1821
1858
  jsdoc({ stylistic: stylisticOptions }),
1859
+ imports({ stylistic: stylisticOptions }),
1822
1860
  perfectionist()
1823
1861
  );
1824
1862
  if (enableUnicorn) {
1825
- configs.push(unicorn(typeof enableUnicorn === "object" ? enableUnicorn : {}));
1863
+ const unicornOptions = resolveSubOptions(options, "unicorn");
1864
+ configs.push(unicorn(unicornOptions));
1865
+ }
1866
+ if (enableTypescript) {
1867
+ const typescriptOptions = resolveSubOptions(options, "typescript");
1868
+ configs.push(typescript({
1869
+ ...typescriptOptions,
1870
+ stylistic: stylisticOptions
1871
+ }));
1826
1872
  }
1827
1873
  if (stylisticOptions) {
1828
1874
  configs.push(stylistic({ stylistic: stylisticOptions }));
1829
1875
  }
1830
1876
  if (enableAngular) {
1831
- configs.push(angular(typeof enableAngular === "object" ? enableAngular : {}));
1877
+ const angularOptions = resolveSubOptions(options, "angular");
1878
+ configs.push(angular(angularOptions));
1832
1879
  }
1833
1880
  if (enableNgrx) {
1834
- configs.push(ngrx(typeof enableNgrx === "object" ? enableNgrx : {}));
1881
+ const ngrxOptions = resolveSubOptions(options, "ngrx");
1882
+ configs.push(ngrx(ngrxOptions));
1835
1883
  }
1836
1884
  if (enableVitest) {
1837
- configs.push(vitest(typeof enableVitest === "object" ? enableVitest : {}));
1885
+ const vitestOptions = resolveSubOptions(options, "vitest");
1886
+ configs.push(vitest(vitestOptions));
1838
1887
  }
1839
1888
  if (enableTailwind) {
1840
- configs.push(tailwindcss(typeof enableTailwind === "object" ? enableTailwind : {}));
1889
+ const tailwindcssOptions = resolveSubOptions(options, "tailwindcss");
1890
+ configs.push(tailwindcss(tailwindcssOptions));
1841
1891
  }
1842
1892
  if (options.jsonc ?? true) {
1893
+ const jsoncOptions = resolveSubOptions(options, "jsonc");
1843
1894
  configs.push(
1844
1895
  jsonc({
1845
- overrides: typeof options.jsonc === "object" ? options.jsonc.overrides : {},
1896
+ ...jsoncOptions,
1846
1897
  stylistic: stylisticOptions
1847
1898
  }),
1848
1899
  sortPackageJson(),
@@ -1850,21 +1901,22 @@ async function createConfig(options = {}, ...userConfigs) {
1850
1901
  );
1851
1902
  }
1852
1903
  if (options.yaml ?? true) {
1904
+ const yamlOptions = resolveSubOptions(options, "yaml");
1853
1905
  configs.push(yaml({
1854
- overrides: typeof options.yaml === "object" ? options.yaml.overrides : {},
1906
+ ...yamlOptions,
1855
1907
  stylistic: stylisticOptions
1856
1908
  }));
1857
1909
  }
1858
1910
  if (options.toml ?? true) {
1911
+ const tomlOptions = resolveSubOptions(options, "toml");
1859
1912
  configs.push(toml({
1860
- overrides: typeof options.toml === "object" ? options.toml.overrides : {},
1913
+ ...tomlOptions,
1861
1914
  stylistic: stylisticOptions
1862
1915
  }));
1863
1916
  }
1864
1917
  if (options.markdown ?? true) {
1865
- configs.push(markdown({
1866
- overrides: typeof options.markdown === "object" ? options.markdown.overrides : {}
1867
- }));
1918
+ const markdownOptions = resolveSubOptions(options, "markdown");
1919
+ configs.push(markdown(markdownOptions));
1868
1920
  }
1869
1921
  if (options.formatters) {
1870
1922
  configs.push(formatters(options.formatters, typeof stylisticOptions === "boolean" ? {} : stylisticOptions));
@@ -1881,4 +1933,4 @@ async function createConfig(options = {}, ...userConfigs) {
1881
1933
  return tseslint.config(...await Promise.all(configs), ...await Promise.all(userConfigs));
1882
1934
  }
1883
1935
 
1884
- export { GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, STYLISTIC_CONFIG_DEFAULT, angular, comments, createConfig, ensurePackages, findNearestPackageJsonName, getWorkspaceRoot, ignores, imports, interopDefault, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, perfectionist, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };
1936
+ export { GLOB_HTML, GLOB_JS, GLOB_SRC, GLOB_TESTS, GLOB_TS, STYLISTIC_CONFIG_DEFAULT, angular, comments, createConfig, ensurePackages, findNearestPackageJsonName, getWorkspaceRoot, ignores, imports, interopDefault, isPackageInScope, javascript, jsdoc, jsonc, markdown, ngrx, perfectionist, resolveSubOptions, sortPackageJson, sortTsConfig, stylistic, tailwindcss, toml, typescript, unicorn, vitest, yaml };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fabdeh/eslint-config",
3
3
  "type": "module",
4
- "version": "0.2.0",
4
+ "version": "0.2.2",
5
5
  "packageManager": "pnpm@10.4.1",
6
6
  "description": "My personal eslint config preset",
7
7
  "author": {