@enke.dev/lint 0.9.1 → 0.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/README.md CHANGED
@@ -33,25 +33,16 @@ Your config file can then be renamed to `eslint.config.ts` and look like this at
33
33
  ```ts
34
34
  import config from '@enke.dev/lint';
35
35
 
36
- export default config;
37
- ```
38
-
39
- You may want to modify the config to your needs, e.g. like this:
40
-
41
- ```ts
42
- import config from '@enke.dev/lint';
43
- import { defineConfig } from 'eslint/config';
44
-
45
36
  export default defineConfig([
46
37
  // extend the base config
47
38
  ...config,
48
- // ignore generated stuff
49
- { ignores: ['src/generated'] },
50
- // override rules for test files with mocha / chai
39
+ // configure typescript parser to your needs
51
40
  {
52
- files: ['**/*.spec.ts'],
53
- rules: {
54
- '@typescript-eslint/no-unused-expressions': ['off'],
41
+ languageOptions: {
42
+ parserOptions: {
43
+ project: true,
44
+ tsconfigRootDir: import.meta.dirname,
45
+ },
55
46
  },
56
47
  },
57
48
  ]);
@@ -89,3 +80,11 @@ export default defineConfig({ cssCustomPropertyPrefix: 'your-prefix' });
89
80
  ```
90
81
 
91
82
  For now, [no TypeScript support](https://github.com/stylelint/stylelint/issues/4940) is possible.
83
+
84
+ ## Development
85
+
86
+ This repo self-tests the configuration by linting itself: `npm run lint`.\
87
+ Therefore, a `text.config.ts` is used.
88
+
89
+ And additionally, a naive test is in place to check that the linter actually finds issues: `npm run test`.\
90
+ It uses the native Node test runner against some obviously faulty code in the `test` directory.
@@ -1,2 +1,3 @@
1
- declare const _default: import("eslint").Linter.Config<import("eslint").Linter.RulesRecord>[];
1
+ import type { Linter } from 'eslint';
2
+ declare const _default: Linter.Config<Linter.RulesRecord>[];
2
3
  export default _default;
package/eslint.config.js CHANGED
@@ -1,48 +1,55 @@
1
1
  /// <reference types="./eslint-plugins.d.ts" />
2
+ import { readFile } from 'node:fs/promises';
2
3
  import { fixupPluginRules } from '@eslint/compat';
3
- import eslintJs from '@eslint/js';
4
- import eslintJson from '@eslint/json';
5
- import { defineConfig } from 'eslint/config';
6
- import eslintPluginHtml from 'eslint-plugin-html';
4
+ import eslintPluginJs from '@eslint/js';
5
+ import eslintPluginJson from '@eslint/json';
6
+ import eslintPluginHtml from '@html-eslint/eslint-plugin';
7
+ import eslintParserHtml from '@html-eslint/parser';
8
+ import { defineConfig, globalIgnores } from 'eslint/config';
9
+ import eslintPluginHtmlScripts from 'eslint-plugin-html';
7
10
  import eslintPluginImport from 'eslint-plugin-import';
8
11
  import eslintPluginImportExtension from 'eslint-plugin-import-extensions';
9
12
  import { configs as eslintPluginLitConfigs } from 'eslint-plugin-lit';
10
13
  import { configs as eslintPluginLitA11yConfigs } from 'eslint-plugin-lit-a11y';
11
- import { configs as eslintPluginPackageJsonConfigs } from 'eslint-plugin-package-json';
12
14
  import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
13
15
  import eslintPluginSimpleImportSort from 'eslint-plugin-simple-import-sort';
14
16
  import eslintPluginUnusedImports from 'eslint-plugin-unused-imports';
15
17
  import { configs as eslintPluginWebComponentsConfigs } from 'eslint-plugin-wc';
16
18
  import eslintTs from 'typescript-eslint';
19
+ // collect gitignore excludes
20
+ const gitIgnores = await readFile(new URL('./.gitignore', import.meta.url), 'utf-8');
21
+ const gitIgnoreLines = gitIgnores
22
+ .split('\n')
23
+ .map(line => line.trim().replace(/^\//, ''))
24
+ .filter(line => line && !line.startsWith('#'));
25
+ // shared parser options
26
+ const parserOptions = {
27
+ ecmaVersion: 'latest',
28
+ sourceType: 'module',
29
+ };
17
30
  export default defineConfig([
18
- eslintJs.configs.recommended,
19
- ...eslintTs.configs.strict,
20
- ...eslintTs.configs.stylistic,
31
+ globalIgnores([...gitIgnoreLines, 'dist/']),
21
32
  eslintPluginPrettierRecommended,
22
- eslintPluginImport.flatConfigs.recommended,
23
- {
24
- ignores: ['node_modules/', 'dist/'],
25
- },
26
33
  // Javascript and Typescript files
27
34
  {
28
- files: ['**/*.{js,ts}'],
29
- ...eslintPluginWebComponentsConfigs['flat/recommended'],
30
- ...eslintPluginLitConfigs['flat/recommended'],
31
- ...eslintPluginLitA11yConfigs.recommended,
35
+ files: ['**/*.js', '**/*.ts'],
36
+ extends: [
37
+ eslintPluginJs.configs.recommended,
38
+ ...eslintTs.configs.strict,
39
+ ...eslintTs.configs.stylistic,
40
+ eslintPluginWebComponentsConfigs['flat/recommended'],
41
+ eslintPluginLitConfigs['flat/recommended'],
42
+ eslintPluginLitA11yConfigs.recommended,
43
+ eslintPluginImport.flatConfigs.recommended,
44
+ ],
32
45
  plugins: {
33
46
  'simple-import-sort': eslintPluginSimpleImportSort,
34
47
  'unused-imports': eslintPluginUnusedImports,
35
48
  'import-extensions': fixupPluginRules(eslintPluginImportExtension),
49
+ html: eslintPluginHtml,
50
+ htmlScripts: eslintPluginHtmlScripts,
36
51
  },
37
- languageOptions: {
38
- parserOptions: {
39
- ecmaVersion: 'latest',
40
- project: true,
41
- requireConfigFile: false,
42
- sourceType: 'module',
43
- tsconfigRootDir: import.meta.dirname,
44
- },
45
- },
52
+ languageOptions: { parserOptions },
46
53
  settings: {
47
54
  'import/resolver': {
48
55
  typescript: true,
@@ -60,6 +67,16 @@ export default defineConfig([
60
67
  'linebreak-style': ['error', 'unix'],
61
68
  quotes: ['error', 'single', { avoidEscape: true }],
62
69
  semi: ['error', 'always'],
70
+ 'no-console': 'error',
71
+ // inline html
72
+ 'html/require-img-alt': 'error',
73
+ 'html/no-multiple-h1': 'error',
74
+ 'html/no-extra-spacing-attrs': 'error',
75
+ 'html/no-duplicate-id': 'error',
76
+ 'html/require-li-container': 'error',
77
+ 'html/no-obsolete-tags': 'error',
78
+ 'html/require-closing-tags': 'error',
79
+ 'html/no-duplicate-attrs': 'error',
63
80
  // import sorting
64
81
  'simple-import-sort/imports': [
65
82
  'error',
@@ -111,21 +128,49 @@ export default defineConfig([
111
128
  // HTML files
112
129
  {
113
130
  files: ['**/*.html'],
114
- plugins: { html: eslintPluginHtml },
131
+ plugins: {
132
+ html: eslintPluginHtml,
133
+ htmlScripts: eslintPluginHtmlScripts,
134
+ },
135
+ extends: [eslintPluginHtml.configs['flat/recommended']],
136
+ language: 'html/html',
137
+ languageOptions: {
138
+ parser: eslintParserHtml,
139
+ parserOptions,
140
+ },
141
+ settings: {
142
+ 'html/indent': '+2',
143
+ 'html/lowercase': 'error',
144
+ 'html/no-accesskey-attrs': 'error',
145
+ 'html/no-aria-hidden-body': 'error',
146
+ 'html/no-aria-hidden-on-focusable': 'error',
147
+ 'html/no-duplicate-class': 'error',
148
+ 'html/no-duplicate-in-head': 'error',
149
+ 'html/no-empty-headings': 'error',
150
+ 'html/no-invalid-entities': 'error',
151
+ 'html/no-heading-inside-button': 'error',
152
+ 'html/no-invalid-entity': 'error',
153
+ 'html/no-invalid-role': 'error',
154
+ 'html/no-nested-interactive': 'error',
155
+ 'html/no-multiple-empty-lines': 'error',
156
+ 'html/no-target-blank': 'error',
157
+ 'html/no-trailing-spaces': 'error',
158
+ 'html/report-bad-indent': 'error',
159
+ 'html/require-input-label': 'error',
160
+ },
161
+ rules: {
162
+ 'html/indent': ['error', 2],
163
+ },
115
164
  },
116
165
  // JSON files
117
166
  {
118
- ...eslintPluginPackageJsonConfigs.recommended,
119
- ...eslintJson.configs.recommended,
120
- ignores: ['package-lock.json'],
167
+ files: ['**/*.json'],
121
168
  language: 'json/json',
169
+ ignores: ['package-lock.json'],
170
+ plugins: { json: eslintPluginJson },
171
+ extends: [eslintPluginJson.configs.recommended],
122
172
  rules: {
123
- 'no-irregular-whitespace': 'off',
124
- 'import-extensions/require-extensions': 'off',
125
- 'import-extensions/require-index': 'off',
126
- },
127
- settings: {
128
- 'html/html-extensions': ['.html'],
173
+ 'json/top-level-interop': 'error',
129
174
  },
130
175
  },
131
176
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enke.dev/lint",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "Meta package to provide linting for web projects",
5
5
  "homepage": "https://github.com/enke-dev/lint",
6
6
  "repository": {
@@ -19,10 +19,11 @@
19
19
  "main": "eslint.config.js",
20
20
  "types": "eslint.config.d.ts",
21
21
  "scripts": {
22
- "lint": "eslint -c eslint.config.ts ./*.config.ts",
22
+ "lint": "eslint -c test.config.ts .",
23
+ "test": "node --experimental-strip-types --test test.run.ts",
23
24
  "inspect": "./node_modules/.bin/eslint-config-inspector --config eslint.config.ts",
24
- "dev": "tsc --watch",
25
- "build": "tsc"
25
+ "dev": "tsc -p tsconfig.build.json --watch",
26
+ "build": "tsc -p tsconfig.build.json"
26
27
  },
27
28
  "author": {
28
29
  "name": "David Enke",
@@ -64,6 +65,8 @@
64
65
  },
65
66
  "devDependencies": {
66
67
  "@eslint/config-inspector": "1.2.0",
68
+ "@html-eslint/eslint-plugin": "0.46.2",
69
+ "@html-eslint/parser": "0.46.2",
67
70
  "@types/node": "24.3.1",
68
71
  "eslint": "9.35.0",
69
72
  "jiti": "2.5.1",