linter-bundle 4.0.3 → 5.0.1
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/.linter-bundle.js +10 -8
- package/CHANGELOG.md +28 -1
- package/README.md +24 -24
- package/eslint/{index.js → index.cjs} +7 -7
- package/eslint/{overrides-javascript-lazy.js → overrides-javascript-lazy.cjs} +1 -1
- package/eslint/{overrides-javascript.js → overrides-javascript.cjs} +1 -0
- package/eslint/{overrides-react.js → overrides-react.cjs} +4 -4
- package/eslint/rules/no-unnecessary-typeof.js +12 -1
- package/eslint/rules/package.json +8 -0
- package/eslint/rules/restricted-filenames.js +4 -4
- package/eslint/rules/restricted-filenames.md +1 -1
- package/eslint.cjs +5 -0
- package/files/index.js +54 -24
- package/helper/{ensure-type.js → ensure-type.cjs} +2 -0
- package/helper/get-git-files.js +3 -7
- package/helper/get-outdated-dependencies.js +48 -0
- package/helper/{validate-package-overrides.js → get-outdated-overrides.js} +9 -10
- package/helper/get-stylelint-path.js +15 -12
- package/helper/is-npm-or-yarn.js +12 -12
- package/helper/linter-bundle-config.cjs +70 -0
- package/helper/linter-bundle-config.d.ts +46 -0
- package/helper/linter-bundle-config.js +36 -0
- package/helper/run-process.js +14 -10
- package/lint.js +32 -26
- package/package.json +8 -7
- package/stylelint/index.cjs +1007 -0
- package/stylelint/plugins/stylelint-high-performance-animation.js +4 -5
- package/stylelint/plugins/stylelint-selector-no-empty.js +2 -2
- package/stylelint/plugins/stylelint-selector-tag-no-without-class.js +6 -7
- package/stylelint/plugins/stylelint-stylistic.js +7 -6
- package/stylelint.cjs +5 -0
- package/helper/config.js +0 -48
- package/helper/find-missing-overrides.js +0 -49
- package/stylelint/index.js +0 -1007
- package/types.d.ts +0 -43
- /package/eslint/{overrides-gatsby.js → overrides-gatsby.cjs} +0 -0
- /package/eslint/{overrides-jest.js → overrides-jest.cjs} +0 -0
- /package/eslint/{overrides-jsdoc.js → overrides-jsdoc.cjs} +0 -0
- /package/eslint/{overrides-storybook.js → overrides-storybook.cjs} +0 -0
- /package/eslint/{overrides-type-declarations.js → overrides-type-declarations.cjs} +0 -0
- /package/eslint/{overrides-worker.js → overrides-worker.cjs} +0 -0
package/.linter-bundle.js
CHANGED
|
@@ -8,7 +8,7 @@ const snippets = {
|
|
|
8
8
|
pascalCase: '[A-Z]*([a-zA-Z0-9])'
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
export default {
|
|
12
12
|
files: {
|
|
13
13
|
restrictions: [
|
|
14
14
|
{
|
|
@@ -17,30 +17,32 @@ module.exports = {
|
|
|
17
17
|
'.git/**',
|
|
18
18
|
'.github/FUNDING.yml',
|
|
19
19
|
'.vscode/settings.json',
|
|
20
|
+
`eslint/rules/package.json`,
|
|
20
21
|
`eslint/rules/${snippets.kebabCase}.{js,md}`,
|
|
21
|
-
`eslint/{index.
|
|
22
|
+
`eslint/{index.cjs,overrides-${snippets.kebabCase}.cjs}`,
|
|
22
23
|
'files/index.js',
|
|
23
|
-
`helper/${snippets.kebabCase}.js`,
|
|
24
|
+
`helper/${snippets.kebabCase}.{js,cjs,d.ts}`,
|
|
24
25
|
'markdownlint/base.json',
|
|
25
26
|
'node_modules/**',
|
|
26
|
-
'stylelint/index.
|
|
27
|
+
'stylelint/index.cjs',
|
|
27
28
|
`stylelint/plugins/stylelint-${snippets.kebabCase}.js`,
|
|
28
29
|
'.editorconfig',
|
|
29
|
-
'.eslintrc.
|
|
30
|
+
'.eslintrc.cjs',
|
|
30
31
|
'.gitattributes',
|
|
31
32
|
'.gitignore',
|
|
32
33
|
'.linter-bundle.js',
|
|
33
34
|
'.markdownlint.json',
|
|
34
35
|
'.npmignore',
|
|
35
36
|
'*.md',
|
|
37
|
+
'eslint.cjs',
|
|
36
38
|
'LICENSE',
|
|
37
39
|
'lint.js',
|
|
38
40
|
'package-lock.json',
|
|
39
41
|
'package.json',
|
|
40
|
-
'stylelint.
|
|
42
|
+
'stylelint.cjs',
|
|
43
|
+
'stylelint.config.cjs',
|
|
44
|
+
'test-stylelint.js',
|
|
41
45
|
'tsconfig.json',
|
|
42
|
-
'types.d.ts',
|
|
43
|
-
'validate-stylelint-options.mjs',
|
|
44
46
|
'vscode-eslint-1.png',
|
|
45
47
|
'vscode-eslint-2.png'
|
|
46
48
|
]
|
package/CHANGELOG.md
CHANGED
|
@@ -6,7 +6,34 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
-
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/
|
|
9
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v5.0.1...HEAD)
|
|
10
|
+
|
|
11
|
+
## [5.0.1] - 2023-09-03
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- [general] Updated [README.md](./README.md) to reflect breaking changes in v5.0.0.
|
|
16
|
+
|
|
17
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v5.0.0...v5.0.1)
|
|
18
|
+
|
|
19
|
+
## [5.0.0] - 2023-09-03
|
|
20
|
+
|
|
21
|
+
### Breaking change
|
|
22
|
+
|
|
23
|
+
- [general] Migrated the code base from CommonJS to ESModules (as far as possible, because ESLint currently does not support ESModules)
|
|
24
|
+
- [general] The linter-bundle configuration can now be a ESModule (`.linter-bundle.mjs` is supported)
|
|
25
|
+
- [general] `"extends"` in the .eslintrc.js needs to be suffixed with the ".cjs" file extension (e.g. `require.resolve('linter-bundle/eslint.cjs')`)
|
|
26
|
+
- [general] `"extends"` in the stylelint.config.js needs to be suffixed with the ".cjs" file extension (e.g. `require.resolve('linter-bundle/stylelint.cjs')`)
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- [files] Report unmatched `allowed` pattern
|
|
31
|
+
- [markdownlint] Updated `markdownlint-cli` from `0.35.0` to `0.36.0`
|
|
32
|
+
- [eslint] Disabled `considerComments` option of [`import/new-after-import`](https://github.com/import-js/eslint-plugin-import/blob/v2.28.1/docs/rules/newline-after-import.md) rule
|
|
33
|
+
as it conflicts with the [`import/order`](https://github.com/import-js/eslint-plugin-import/blob/v2.28.1/docs/rules/order.md) rule
|
|
34
|
+
- [eslint/overrides-javascript] Disable [`import/dynamic-import-chunkname`](https://github.com/import-js/eslint-plugin-import/blob/v2.28.1/docs/rules/dynamic-import-chunkname.md) for JavaScript files
|
|
35
|
+
|
|
36
|
+
[Show all code changes](https://github.com/jens-duttke/linter-bundle/compare/v4.0.3...v5.0.0)
|
|
10
37
|
|
|
11
38
|
## [4.0.3] - 2023-08-31
|
|
12
39
|
|
package/README.md
CHANGED
|
@@ -86,16 +86,16 @@ npm install linter-bundle --save-dev
|
|
|
86
86
|
```js
|
|
87
87
|
module.exports = {
|
|
88
88
|
extends: [
|
|
89
|
-
require.resolve('linter-bundle/eslint'),
|
|
90
|
-
// require.resolve('linter-bundle/eslint/overrides-gatsby'),
|
|
91
|
-
// require.resolve('linter-bundle/eslint/overrides-javascript'),
|
|
92
|
-
require.resolve('linter-bundle/eslint/overrides-javascript-lazy'),
|
|
93
|
-
// require.resolve('linter-bundle/eslint/overrides-jest'),
|
|
94
|
-
require.resolve('linter-bundle/eslint/overrides-jsdoc'),
|
|
95
|
-
// require.resolve('linter-bundle/eslint/overrides-react'),
|
|
96
|
-
// require.resolve('linter-bundle/eslint/overrides-storybook'),
|
|
97
|
-
// require.resolve('linter-bundle/eslint/overrides-type-declarations'),
|
|
98
|
-
// require.resolve('linter-bundle/eslint/overrides-worker')
|
|
89
|
+
require.resolve('linter-bundle/eslint.cjs'),
|
|
90
|
+
// require.resolve('linter-bundle/eslint/overrides-gatsby.cjs'),
|
|
91
|
+
// require.resolve('linter-bundle/eslint/overrides-javascript.cjs'),
|
|
92
|
+
require.resolve('linter-bundle/eslint/overrides-javascript-lazy.cjs'),
|
|
93
|
+
// require.resolve('linter-bundle/eslint/overrides-jest.cjs'),
|
|
94
|
+
require.resolve('linter-bundle/eslint/overrides-jsdoc.cjs'),
|
|
95
|
+
// require.resolve('linter-bundle/eslint/overrides-react.cjs'),
|
|
96
|
+
// require.resolve('linter-bundle/eslint/overrides-storybook.cjs'),
|
|
97
|
+
// require.resolve('linter-bundle/eslint/overrides-type-declarations.cjs'),
|
|
98
|
+
// require.resolve('linter-bundle/eslint/overrides-worker.cjs')
|
|
99
99
|
]
|
|
100
100
|
};
|
|
101
101
|
```
|
|
@@ -104,22 +104,22 @@ module.exports = {
|
|
|
104
104
|
|
|
105
105
|
Source | Description | Rules setup
|
|
106
106
|
-|-|-
|
|
107
|
-
`linter-bundle/eslint` | General rule setup. This is also the base for the following **overrides**. | [View](./eslint/index.
|
|
108
|
-
`linter-bundle/eslint/overrides-gatsby` | Settings for Gatsby-based projects. | [View](./eslint/overrides-gatsby.js)
|
|
109
|
-
`linter-bundle/eslint/overrides-javascript` | Strict settings for JavaScript files, which enforces correct types everywhere. | [View](./eslint/overrides-javascript.
|
|
110
|
-
`linter-bundle/eslint/overrides-javascript-lazy` | Can be used instead of `overrides-javascript`. It's less strict and allows the `any` type. | [View](./eslint/overrides-javascript-lazy.
|
|
111
|
-
`linter-bundle/eslint/overrides-jest` | Settings for projects using Jest. | [View](./eslint/overrides-jest.
|
|
112
|
-
`linter-bundle/eslint/overrides-jsdoc` | Settings for projects using JSDoc comments. | [View](./eslint/overrides-jsdoc.
|
|
113
|
-
`linter-bundle/eslint/overrides-react` | Settings for projects using React comments. | [View](./eslint/overrides-react.
|
|
114
|
-
`linter-bundle/eslint/overrides-storybook` | Settings for projects using Storybook comments. | [View](./eslint/overrides-storybook.
|
|
115
|
-
`linter-bundle/eslint/overrides-type-declarations` | Settings for type declaration files (.d.ts). | [View](./eslint/overrides-type-declarations.
|
|
116
|
-
`linter-bundle/eslint/overrides-worker` | Settings for projects using Web Workers. | [View](./eslint/overrides-worker.
|
|
107
|
+
`linter-bundle/eslint.cjs` | General rule setup. This is also the base for the following **overrides**. | [View](./eslint/index.cjs)
|
|
108
|
+
`linter-bundle/eslint/overrides-gatsby.cjs` | Settings for Gatsby-based projects. | [View](./eslint/overrides-gatsby.js)
|
|
109
|
+
`linter-bundle/eslint/overrides-javascript.cjs` | Strict settings for JavaScript files, which enforces correct types everywhere. | [View](./eslint/overrides-javascript.cjs)
|
|
110
|
+
`linter-bundle/eslint/overrides-javascript-lazy.cjs` | Can be used instead of `overrides-javascript`. It's less strict and allows the `any` type. | [View](./eslint/overrides-javascript-lazy.cjs)
|
|
111
|
+
`linter-bundle/eslint/overrides-jest.cjs` | Settings for projects using Jest. | [View](./eslint/overrides-jest.cjs)
|
|
112
|
+
`linter-bundle/eslint/overrides-jsdoc.cjs` | Settings for projects using JSDoc comments. | [View](./eslint/overrides-jsdoc.cjs)
|
|
113
|
+
`linter-bundle/eslint/overrides-react.cjs` | Settings for projects using React comments. | [View](./eslint/overrides-react.cjs)
|
|
114
|
+
`linter-bundle/eslint/overrides-storybook.cjs` | Settings for projects using Storybook comments. | [View](./eslint/overrides-storybook.cjs)
|
|
115
|
+
`linter-bundle/eslint/overrides-type-declarations.cjs` | Settings for type declaration files (.d.ts). | [View](./eslint/overrides-type-declarations.cjs)
|
|
116
|
+
`linter-bundle/eslint/overrides-worker.cjs` | Settings for projects using Web Workers. | [View](./eslint/overrides-worker.cjs)
|
|
117
117
|
|
|
118
118
|
#### stylelint.config.js
|
|
119
119
|
|
|
120
120
|
```js
|
|
121
121
|
module.exports = {
|
|
122
|
-
extends: 'linter-bundle/stylelint'
|
|
122
|
+
extends: 'linter-bundle/stylelint.cjs'
|
|
123
123
|
};
|
|
124
124
|
|
|
125
125
|
```
|
|
@@ -309,7 +309,7 @@ module.exports = {
|
|
|
309
309
|
*/
|
|
310
310
|
overrides: {
|
|
311
311
|
/**
|
|
312
|
-
* Rules that are applied to `linter-bundle/eslint`.
|
|
312
|
+
* Rules that are applied to `linter-bundle/eslint.cjs`.
|
|
313
313
|
*/
|
|
314
314
|
general: {
|
|
315
315
|
'no-restricted-globals': {
|
|
@@ -363,7 +363,7 @@ module.exports = {
|
|
|
363
363
|
},
|
|
364
364
|
|
|
365
365
|
/**
|
|
366
|
-
* Rules that are applied to `linter-bundle/eslint/overrides-react`.
|
|
366
|
+
* Rules that are applied to `linter-bundle/eslint/overrides-react.cjs`.
|
|
367
367
|
*/
|
|
368
368
|
react: {
|
|
369
369
|
'react/forbid-component-props': {
|
|
@@ -622,7 +622,7 @@ This can be done by adding these options to your `.vscode/settings.json`:
|
|
|
622
622
|
{
|
|
623
623
|
"eslint.nodePath": "./node_modules/linter-bundle/node_modules/eslint",
|
|
624
624
|
"eslint.options": {
|
|
625
|
-
"overrideConfigFile": "./.eslintrc.js",
|
|
625
|
+
"overrideConfigFile": "./.eslintrc.js", // or "./.eslintrc.cjs" or "./eslintrc.json"
|
|
626
626
|
"resolvePluginsRelativeTo": "./node_modules/linter-bundle",
|
|
627
627
|
"rulePaths": ["./node_modules/linter-bundle/eslint/rules"],
|
|
628
628
|
"reportUnusedDisableDirectives": "error",
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
const fs = require('node:fs');
|
|
9
9
|
const path = require('node:path');
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
const
|
|
11
|
+
const ensureType = require('../helper/ensure-type.cjs');
|
|
12
|
+
const { linterBundleConfig } = require('../helper/linter-bundle-config.cjs');
|
|
13
13
|
|
|
14
14
|
module.exports = {
|
|
15
15
|
ignorePatterns: [
|
|
@@ -283,16 +283,16 @@ module.exports = {
|
|
|
283
283
|
name: 'isNaN',
|
|
284
284
|
message: 'Use Number.isNaN() instead, and ensure that the input value is of type number. isNaN(undefined) !== Number.isNaN(undefined)'
|
|
285
285
|
},
|
|
286
|
-
...ensureType.array(
|
|
286
|
+
...ensureType.array(linterBundleConfig.ts?.overrides?.general?.['no-restricted-globals']?.additionalRestrictions)
|
|
287
287
|
],
|
|
288
288
|
'no-restricted-imports': 'off', // Covered by @typescript-eslint/no-restricted-imports
|
|
289
289
|
'no-restricted-properties': [
|
|
290
290
|
'error',
|
|
291
|
-
...ensureType.array(
|
|
291
|
+
...ensureType.array(linterBundleConfig.ts?.overrides?.general?.['no-restricted-properties']?.additionalRestrictions)
|
|
292
292
|
],
|
|
293
293
|
'no-restricted-syntax': [
|
|
294
294
|
'error',
|
|
295
|
-
...ensureType.array(
|
|
295
|
+
...ensureType.array(linterBundleConfig.ts?.overrides?.general?.['no-restricted-syntax']?.additionalRestrictions)
|
|
296
296
|
],
|
|
297
297
|
'no-return-assign': 'error',
|
|
298
298
|
'no-script-url': 'error',
|
|
@@ -821,7 +821,7 @@ module.exports = {
|
|
|
821
821
|
'import/max-dependencies': ['error', { max: 20, ignoreTypeImports: true }],
|
|
822
822
|
'import/named': 'error',
|
|
823
823
|
'import/namespace': ['error', { allowComputed: true }],
|
|
824
|
-
'import/newline-after-import': ['error', { considerComments:
|
|
824
|
+
'import/newline-after-import': ['error', { considerComments: false }],
|
|
825
825
|
'import/no-absolute-path': 'error',
|
|
826
826
|
'import/no-amd': 'error',
|
|
827
827
|
'import/no-anonymous-default-export': 'error',
|
|
@@ -866,7 +866,7 @@ module.exports = {
|
|
|
866
866
|
'newlines-between': 'always',
|
|
867
867
|
'pathGroupsExcludedImportTypes': [],
|
|
868
868
|
'pathGroups': [
|
|
869
|
-
...ensureType.array(
|
|
869
|
+
...ensureType.array(linterBundleConfig.ts?.overrides?.general?.['import/order']?.additionalExternalPatterns).map(
|
|
870
870
|
/**
|
|
871
871
|
* Creates an "external" group using the additional external pattern configuration.
|
|
872
872
|
* @param {string} pattern - A given pattern
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* @file Settings for React code in TypeScript (TSX) files.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const ensureType = require('../helper/ensure-type.cjs');
|
|
6
|
+
const { linterBundleConfig } = require('../helper/linter-bundle-config.cjs');
|
|
7
7
|
|
|
8
8
|
module.exports = {
|
|
9
9
|
overrides: [
|
|
@@ -91,11 +91,11 @@ module.exports = {
|
|
|
91
91
|
'react/forbid-component-props': ['error', { forbid: [
|
|
92
92
|
{
|
|
93
93
|
propName: 'className',
|
|
94
|
-
allowedFor: ensureType.array(
|
|
94
|
+
allowedFor: ensureType.array(linterBundleConfig.ts?.overrides?.react?.['react/forbid-component-props']?.allowClassNameFor)
|
|
95
95
|
},
|
|
96
96
|
{
|
|
97
97
|
propName: 'style',
|
|
98
|
-
allowedFor: ensureType.array(
|
|
98
|
+
allowedFor: ensureType.array(linterBundleConfig.ts?.overrides?.react?.['react/forbid-component-props']?.allowStyleFor)
|
|
99
99
|
}
|
|
100
100
|
] }],
|
|
101
101
|
'react/forbid-dom-props': 'error',
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
const ts = require('typescript');
|
|
8
8
|
|
|
9
|
-
// @ts-expect-error -- TypeScript is not able to resolve the folder since @typescript-eslint v6.0.0
|
|
10
9
|
const { ESLintUtils } = require('@typescript-eslint/utils');
|
|
11
10
|
|
|
12
11
|
/**
|
|
@@ -22,8 +21,20 @@ module.exports = {
|
|
|
22
21
|
text: 'Unnecessary `typeof`, because the only possible type of {{ variableName }} is `{{ typeName }}`.'
|
|
23
22
|
}
|
|
24
23
|
},
|
|
24
|
+
/**
|
|
25
|
+
* Create a new rule.
|
|
26
|
+
*
|
|
27
|
+
* @param {Readonly<import('@typescript-eslint/utils/ts-eslint').RuleContext<'text', []>>} context - RuleContext of @typescript-eslint instead of ESlint
|
|
28
|
+
* @returns {import('@typescript-eslint/utils/ts-eslint').RuleListener} RuleListener of @typescript-eslint, instead of ESlint
|
|
29
|
+
*/
|
|
25
30
|
create (context) {
|
|
26
31
|
return {
|
|
32
|
+
/**
|
|
33
|
+
* Rule function to handle unary expressions.
|
|
34
|
+
*
|
|
35
|
+
* @param {import('@typescript-eslint/typescript-estree').TSESTree.UnaryExpression} node - UnaryExpression of @typescript-eslint instead of ESlint
|
|
36
|
+
* @returns {import('@typescript-eslint/utils/ts-eslint').RuleFunction<import('@typescript-eslint/typescript-estree').TSESTree.UnaryExpression> | void} RuleFunction of @typescript-eslint instead of ESlint
|
|
37
|
+
*/
|
|
27
38
|
UnaryExpression (node) {
|
|
28
39
|
if (node.operator !== 'typeof') {
|
|
29
40
|
return;
|
|
@@ -6,7 +6,8 @@ const path = require('node:path');
|
|
|
6
6
|
|
|
7
7
|
const micromatch = require('micromatch');
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// eslint-disable-next-line n/no-process-env -- Only merge the linter-bundle config, if the linting is not started by the linter-bundle CLI tool (e.g. if ESlint is running separately in VSCode), to get warnings shown there too
|
|
10
|
+
const linterBundleConfig = (!process.env['LINTER_BUNDLE'] ? require('../../helper/linter-bundle-config.cjs').linterBundleConfig : undefined);
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* @type {import('eslint').Rule.RuleModule}
|
|
@@ -50,10 +51,9 @@ module.exports = {
|
|
|
50
51
|
}
|
|
51
52
|
},
|
|
52
53
|
create: (context) => {
|
|
53
|
-
const filePath = context.
|
|
54
|
+
const filePath = context.filename;
|
|
54
55
|
/** @type {{ basePath: string, allowed?: string[]; disallowed?: string[]; }[]} */
|
|
55
|
-
|
|
56
|
-
const options = (!process.env['LINTER_BUNDLE'] && config.files?.restrictions ? [...config.files.restrictions, ...context.options] : context.options);
|
|
56
|
+
const options = linterBundleConfig?.files?.restrictions ? [...linterBundleConfig.files.restrictions, ...context.options] : context.options;
|
|
57
57
|
|
|
58
58
|
for (const { basePath, allowed, disallowed } of options) {
|
|
59
59
|
const normalizedName = path.relative(path.join(process.cwd(), basePath), filePath);
|
|
@@ -64,7 +64,7 @@ If both are set, `disallowed` wins over `allowed` and all unspecified files are
|
|
|
64
64
|
|
|
65
65
|
Instead of defining the same complex patterns over and over again, e.g. for casing, you can write them into a variable and use them within the pattern, for example by using template strings.
|
|
66
66
|
|
|
67
|
-
Example of `.eslintrc.
|
|
67
|
+
Example of `.eslintrc.cjs`:
|
|
68
68
|
|
|
69
69
|
```js
|
|
70
70
|
const snippets = {
|
package/eslint.cjs
ADDED
package/files/index.js
CHANGED
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
* @file Ensures that only files which match given glob patterns are part of the project.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import * as fs from 'node:fs';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import micromatch from 'micromatch';
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
import { linterBundleConfig } from '../helper/linter-bundle-config.js';
|
|
11
11
|
|
|
12
|
-
const restrictions =
|
|
12
|
+
const restrictions = linterBundleConfig.files?.restrictions;
|
|
13
|
+
const matcherOptions = { dot: true };
|
|
13
14
|
|
|
14
15
|
if (Array.isArray(restrictions)) {
|
|
15
|
-
let
|
|
16
|
+
let noOfDisallowedFiles = 0;
|
|
16
17
|
|
|
17
18
|
const argFiles = process.argv.splice(2).map((filePath) => path.join(process.cwd(), filePath));
|
|
18
19
|
|
|
@@ -25,7 +26,24 @@ if (Array.isArray(restrictions)) {
|
|
|
25
26
|
const report = (filePath) => {
|
|
26
27
|
process.stderr.write(`Disallowed filename "${filePath}"\n`);
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
noOfDisallowedFiles++;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Reports the error to the `console` and increase the error counter.
|
|
34
|
+
*
|
|
35
|
+
* @param {[string, (str: string) => boolean][]} matchers - Array of micromatch matchers
|
|
36
|
+
* @param {string} filePath - Path to the file to check
|
|
37
|
+
* @returns {string | undefined} On match returns the matching pattern, otherwise `undefined`
|
|
38
|
+
*/
|
|
39
|
+
const isMatch = (matchers, filePath) => {
|
|
40
|
+
for (const [pattern, matcher] of matchers) {
|
|
41
|
+
if (matcher(filePath)) {
|
|
42
|
+
return pattern;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return;
|
|
29
47
|
};
|
|
30
48
|
|
|
31
49
|
for (const { basePath, allowed, disallowed } of restrictions) {
|
|
@@ -33,38 +51,50 @@ if (Array.isArray(restrictions)) {
|
|
|
33
51
|
|
|
34
52
|
const files = (argFiles.length > 0 ? argFiles.filter((filePath) => !path.relative(absoluteBasePath, filePath).startsWith('..')) : getFiles(absoluteBasePath));
|
|
35
53
|
|
|
54
|
+
const allowedMatchers = allowed?.map((pattern) => /** @type {[string, (str: string) => boolean]} */([pattern, micromatch.matcher(pattern, matcherOptions)]));
|
|
55
|
+
const disallowedMatchers = disallowed?.map((pattern) => /** @type {[string, (str: string) => boolean]} */([pattern, micromatch.matcher(pattern, matcherOptions)]));
|
|
56
|
+
|
|
57
|
+
const unmatchedAllowedPatterns = new Set(allowed);
|
|
58
|
+
|
|
36
59
|
for (const filePath of files) {
|
|
37
60
|
const normalizedFilePath = path.relative(absoluteBasePath, filePath);
|
|
38
61
|
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
report(normalizedFilePath);
|
|
62
|
+
if (allowedMatchers && !disallowedMatchers) {
|
|
63
|
+
const pattern = isMatch(allowedMatchers, normalizedFilePath);
|
|
42
64
|
|
|
43
|
-
|
|
65
|
+
if (pattern) {
|
|
66
|
+
unmatchedAllowedPatterns.delete(pattern);
|
|
44
67
|
}
|
|
45
|
-
|
|
46
|
-
else if (!allowed && disallowed) {
|
|
47
|
-
if (micromatch.isMatch(normalizedFilePath, disallowed, { dot: true })) {
|
|
68
|
+
else {
|
|
48
69
|
report(normalizedFilePath);
|
|
49
|
-
|
|
50
|
-
continue;
|
|
51
70
|
}
|
|
52
71
|
}
|
|
53
|
-
else if (
|
|
54
|
-
if (
|
|
55
|
-
micromatch.isMatch(normalizedFilePath, disallowed, { dot: true }) ||
|
|
56
|
-
!micromatch.isMatch(normalizedFilePath, allowed, { dot: true })
|
|
57
|
-
) {
|
|
72
|
+
else if (!allowedMatchers && disallowedMatchers) {
|
|
73
|
+
if (isMatch(disallowedMatchers, normalizedFilePath)) {
|
|
58
74
|
report(normalizedFilePath);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else if (allowedMatchers && disallowedMatchers) {
|
|
78
|
+
const pattern = isMatch(allowedMatchers, normalizedFilePath);
|
|
59
79
|
|
|
60
|
-
|
|
80
|
+
if (pattern) {
|
|
81
|
+
unmatchedAllowedPatterns.delete(pattern);
|
|
61
82
|
}
|
|
83
|
+
else if (isMatch(disallowedMatchers, normalizedFilePath)) {
|
|
84
|
+
report(normalizedFilePath);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (unmatchedAllowedPatterns.size > 0) {
|
|
90
|
+
for (const [pattern] of unmatchedAllowedPatterns.entries()) {
|
|
91
|
+
process.stderr.write(`Unmatched "allowed" pattern: "${pattern}"\n`);
|
|
62
92
|
}
|
|
63
93
|
}
|
|
64
94
|
}
|
|
65
95
|
|
|
66
|
-
if (
|
|
67
|
-
process.stderr.write(`\nFound ${
|
|
96
|
+
if (noOfDisallowedFiles > 0) {
|
|
97
|
+
process.stderr.write(`\nFound ${noOfDisallowedFiles} disallowed file${(noOfDisallowedFiles !== 0 ? 's' : '')}\n`);
|
|
68
98
|
|
|
69
99
|
process.exitCode = -1;
|
|
70
100
|
}
|
package/helper/get-git-files.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* @file Handling of changed files from Git.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import { runProcess } from './run-process.js';
|
|
6
6
|
|
|
7
|
-
/** @typedef {import('./run-process').ProcessResult} ProcessResult */
|
|
7
|
+
/** @typedef {import('./run-process.js').ProcessResult} ProcessResult */
|
|
8
8
|
|
|
9
9
|
/** @type {{ diff: Promise<ProcessResult>; modified: Promise<ProcessResult>; deleted: Promise<ProcessResult>; } | undefined} */
|
|
10
10
|
let gitFilesProcessPromise;
|
|
@@ -17,7 +17,7 @@ let gitFiles;
|
|
|
17
17
|
* @public
|
|
18
18
|
* @returns {Promise<string[]>} The list of changed files.
|
|
19
19
|
*/
|
|
20
|
-
async function getGitFiles () {
|
|
20
|
+
export async function getGitFiles () {
|
|
21
21
|
if (!gitFilesProcessPromise) {
|
|
22
22
|
gitFilesProcessPromise = {
|
|
23
23
|
// Returns changed files, also stashed and committed
|
|
@@ -46,7 +46,3 @@ async function getGitFiles () {
|
|
|
46
46
|
|
|
47
47
|
return gitFiles;
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
module.exports = {
|
|
51
|
-
getGitFiles
|
|
52
|
-
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Ensures that the installed dependencies of the project matches to the versions used by the linter-bundle.
|
|
3
|
+
*
|
|
4
|
+
* @see https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides
|
|
5
|
+
* @see https://classic.yarnpkg.com/en/docs/selective-version-resolutions/
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from 'node:fs/promises';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
|
|
12
|
+
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
|
|
14
|
+
/** @typedef {{ name: string; configuredVersion: string; expectedVersion: string; }} Dependency */
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Detects if installed versions of dependencies don't match to the required dependencies.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
* @returns {Promise<Dependency[]>} An array of missing overrides (=wrong versions).
|
|
21
|
+
*/
|
|
22
|
+
export async function getOutdatedDependencies () {
|
|
23
|
+
const linterBundleDependencies = JSON.parse(await fs.readFile(path.resolve(dirname, '../package.json'), 'utf8')).dependencies;
|
|
24
|
+
|
|
25
|
+
const outdatedDependencies = await Promise.all(Object.entries(linterBundleDependencies).map(async ([name, expectedVersion]) => {
|
|
26
|
+
let dependencyPackageJson;
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
dependencyPackageJson = JSON.parse(await fs.readFile(path.join(process.cwd(), 'node_modules', name, 'package.json'), 'utf8'));
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// If the file does not exist, we ignore it, because in this case it's most likely a linter-bundle-only dependency.
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (dependencyPackageJson.version !== expectedVersion) {
|
|
37
|
+
return {
|
|
38
|
+
name,
|
|
39
|
+
configuredVersion: dependencyPackageJson.version,
|
|
40
|
+
expectedVersion
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return;
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
return /** @type {Dependency[]} */(outdatedDependencies.filter((dependency) => dependency !== undefined));
|
|
48
|
+
}
|
|
@@ -5,8 +5,11 @@
|
|
|
5
5
|
* @see https://classic.yarnpkg.com/en/docs/selective-version-resolutions/
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
import * as fs from 'node:fs/promises';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
|
|
12
|
+
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
13
|
|
|
11
14
|
/** @typedef {{ name: string; configuredVersion: string; expectedVersion: string; }} Dependency */
|
|
12
15
|
|
|
@@ -14,11 +17,11 @@ const path = require('node:path');
|
|
|
14
17
|
* Detects outdated "overrides"/"resolutions" dependencies.
|
|
15
18
|
*
|
|
16
19
|
* @public
|
|
17
|
-
* @returns {{ overrides: Dependency[]; resolutions: Dependency[]; }} Either the input array, or an empty array, if the input array is not an array.
|
|
20
|
+
* @returns {Promise<{ overrides: Dependency[]; resolutions: Dependency[]; }>} Either the input array, or an empty array, if the input array is not an array.
|
|
18
21
|
*/
|
|
19
|
-
function
|
|
20
|
-
const linterBundleDependencies = JSON.parse(fs.
|
|
21
|
-
const projectPackageJson = JSON.parse(fs.
|
|
22
|
+
export async function getOutdatedOverrides () {
|
|
23
|
+
const linterBundleDependencies = JSON.parse(await fs.readFile(path.resolve(dirname, '../package.json'), 'utf8')).dependencies;
|
|
24
|
+
const projectPackageJson = JSON.parse(await fs.readFile(path.join(process.cwd(), 'package.json'), 'utf8'));
|
|
22
25
|
|
|
23
26
|
const overrides = [];
|
|
24
27
|
const resolutions = [];
|
|
@@ -57,7 +60,3 @@ function validatePackageOverrides () {
|
|
|
57
60
|
|
|
58
61
|
return { overrides, resolutions };
|
|
59
62
|
}
|
|
60
|
-
|
|
61
|
-
module.exports = {
|
|
62
|
-
validatePackageOverrides
|
|
63
|
-
};
|
|
@@ -2,31 +2,34 @@
|
|
|
2
2
|
* @file Returns the path to the Stylelint CLI script.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import * as fs from 'node:fs/promises';
|
|
6
|
+
import { createRequire } from 'node:module';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Returns if the project is using npm or yarn.
|
|
10
13
|
*
|
|
11
14
|
* @public
|
|
12
|
-
* @returns {string | null} Return the path to the Stylelint CLI script, or `null` if it can't be found.
|
|
15
|
+
* @returns {Promise<string | null>} Return the path to the Stylelint CLI script, or `null` if it can't be found.
|
|
13
16
|
*/
|
|
14
|
-
function getStylelintPath () {
|
|
17
|
+
export async function getStylelintPath () {
|
|
15
18
|
const stylelintLibPath = path.dirname(require.resolve('stylelint'));
|
|
16
19
|
|
|
17
|
-
for (const stylelintBinPath of [
|
|
20
|
+
for await (const stylelintBinPath of [
|
|
18
21
|
path.join(stylelintLibPath, '../bin/stylelint.mjs'),
|
|
19
22
|
path.join(stylelintLibPath, '../bin/stylelint.js')
|
|
20
23
|
]) {
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
try {
|
|
25
|
+
const stat = await fs.stat(stylelintBinPath);
|
|
26
|
+
|
|
27
|
+
if (stat.isFile()) {
|
|
28
|
+
return stylelintBinPath;
|
|
29
|
+
}
|
|
23
30
|
}
|
|
31
|
+
catch { /* Do nothing */ }
|
|
24
32
|
}
|
|
25
33
|
|
|
26
34
|
return null;
|
|
27
35
|
}
|
|
28
|
-
|
|
29
|
-
module.exports = {
|
|
30
|
-
getStylelintPath
|
|
31
|
-
};
|
|
32
|
-
|