@timobechtel/style 1.0.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 +64 -0
- package/eslint/core.cjs +49 -0
- package/eslint/rules/base.cjs +82 -0
- package/eslint/rules/css-in-js.cjs +16 -0
- package/eslint/rules/import.cjs +31 -0
- package/eslint/rules/typescript.cjs +83 -0
- package/eslint/rules/unicorn.cjs +129 -0
- package/package.json +35 -0
- package/prettier/index.mjs +18 -0
- package/semantic-release/index.cjs +21 -0
- package/tsconfig/core.json +23 -0
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Style 🛼
|
|
2
|
+
|
|
3
|
+
> Roll in style.
|
|
4
|
+
|
|
5
|
+
Highly opinionated configuration files for typescript projects. Inspired by [@vercel/style-guide](https://github.com/vercel/style-guide)
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i -D @timobechtel/style prettier eslint typescript
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Prettier
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
echo '"@timobechtel/style/prettier/index.mjs"' > .prettierrc
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Typescript
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
echo '{ "extends": "@timobechtel/style/tsconfig/core" }' > tsconfig.json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Eslint
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
echo 'const{resolve}=require("node:path");const project=resolve(process.cwd(),"tsconfig.json");module.exports={root:true,extends:[require.resolve("@timobechtel/style/eslint/core.cjs")],parserOptions:{project},settings:{"import/resolver":{typescript:{project}}}};' > .eslintrc.cjs
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Or copy the following to a `.eslintrc.cjs` manually:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
const { resolve } = require('node:path');
|
|
35
|
+
|
|
36
|
+
const project = resolve(process.cwd(), 'tsconfig.json');
|
|
37
|
+
|
|
38
|
+
module.exports = {
|
|
39
|
+
root: true,
|
|
40
|
+
extends: [require.resolve('@timobechtel/style/eslint/core.cjs')],
|
|
41
|
+
parserOptions: {
|
|
42
|
+
project,
|
|
43
|
+
},
|
|
44
|
+
settings: {
|
|
45
|
+
'import/resolver': {
|
|
46
|
+
typescript: {
|
|
47
|
+
project,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### semantic-release
|
|
55
|
+
|
|
56
|
+
This repo also contains a [semantic-release](https://github.com/semantic-release/semantic-release) configuration.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm i -D semantic-release
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
echo '{ "extends": "@timobechtel/style/semantic-release/index.cjs" }' > .releaserc.json
|
|
64
|
+
```
|
package/eslint/core.cjs
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { defineConfig } = require('eslint-define-config');
|
|
3
|
+
|
|
4
|
+
module.exports = defineConfig({
|
|
5
|
+
extends: [
|
|
6
|
+
'eslint:recommended',
|
|
7
|
+
'plugin:import/recommended',
|
|
8
|
+
'prettier',
|
|
9
|
+
require.resolve('./rules/base.cjs'),
|
|
10
|
+
require.resolve('./rules/import.cjs'),
|
|
11
|
+
require.resolve('./rules/unicorn.cjs'),
|
|
12
|
+
],
|
|
13
|
+
plugins: [],
|
|
14
|
+
env: {
|
|
15
|
+
es2021: true,
|
|
16
|
+
node: true,
|
|
17
|
+
browser: true,
|
|
18
|
+
},
|
|
19
|
+
// Report unused `eslint-disable` comments.
|
|
20
|
+
reportUnusedDisableDirectives: true,
|
|
21
|
+
// Tell ESLint not to ignore dot-files, which are ignored by default.
|
|
22
|
+
ignorePatterns: ['!.*.js'],
|
|
23
|
+
// Global settings used by all overrides.
|
|
24
|
+
settings: {
|
|
25
|
+
// Use the Node resolver by default.
|
|
26
|
+
'import/resolver': { node: {} },
|
|
27
|
+
},
|
|
28
|
+
// Global parser options.
|
|
29
|
+
parserOptions: {
|
|
30
|
+
ecmaVersion: 2021,
|
|
31
|
+
sourceType: 'module',
|
|
32
|
+
},
|
|
33
|
+
overrides: [
|
|
34
|
+
{
|
|
35
|
+
files: ['*.ts?(x)'],
|
|
36
|
+
extends: [
|
|
37
|
+
'plugin:@typescript-eslint/recommended',
|
|
38
|
+
'plugin:@typescript-eslint/recommended-type-checked',
|
|
39
|
+
'plugin:@typescript-eslint/strict',
|
|
40
|
+
'plugin:@typescript-eslint/strict-type-checked',
|
|
41
|
+
'plugin:@typescript-eslint/stylistic',
|
|
42
|
+
'plugin:@typescript-eslint/stylistic-type-checked',
|
|
43
|
+
'plugin:import/typescript',
|
|
44
|
+
'prettier',
|
|
45
|
+
require.resolve('./rules/typescript.cjs'),
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { defineConfig } = require('eslint-define-config');
|
|
3
|
+
|
|
4
|
+
module.exports = defineConfig({
|
|
5
|
+
rules: {
|
|
6
|
+
// prefer arrow functions for callbacks
|
|
7
|
+
'prefer-arrow-callback': [
|
|
8
|
+
'warn',
|
|
9
|
+
{
|
|
10
|
+
allowNamedFunctions: true,
|
|
11
|
+
allowUnboundThis: true,
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
// console logs other than error and warn are only needed for debugging, so they should be removed before merging
|
|
15
|
+
'no-console': [
|
|
16
|
+
'error',
|
|
17
|
+
{
|
|
18
|
+
allow: [
|
|
19
|
+
'warn',
|
|
20
|
+
'error',
|
|
21
|
+
'clear',
|
|
22
|
+
// sometimes we really need to log something, even in production, so info is allowed in edge cases
|
|
23
|
+
'info',
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
'max-depth': ['warn', 4],
|
|
28
|
+
// some globals, like "name" might be similar to the name of a variable, so we prevent them from being used
|
|
29
|
+
'no-restricted-globals': ['error', 'event', 'name'],
|
|
30
|
+
// Require curly braces for multiline blocks.
|
|
31
|
+
curly: ['warn', 'multi-line'],
|
|
32
|
+
// Require default clauses in switch statements to be last (if used).
|
|
33
|
+
'default-case-last': 'error',
|
|
34
|
+
// Require triple equals (`===` and `!==`).
|
|
35
|
+
eqeqeq: 'error',
|
|
36
|
+
// disallow the use of `alert()`
|
|
37
|
+
'no-alert': 'error',
|
|
38
|
+
// Disallow renaming import, export, and destructured assignments to the same name.
|
|
39
|
+
'no-useless-rename': 'warn',
|
|
40
|
+
// Require `let` or `const` instead of `var`.
|
|
41
|
+
'no-var': 'error',
|
|
42
|
+
// Require object literal shorthand syntax.
|
|
43
|
+
'object-shorthand': 'warn',
|
|
44
|
+
// Require default to `const` instead of `let`.
|
|
45
|
+
'prefer-const': 'warn',
|
|
46
|
+
// Require rest parameters instead of `arguments`.
|
|
47
|
+
'prefer-rest-params': 'error',
|
|
48
|
+
// Require spread syntax instead of `.apply()`.
|
|
49
|
+
'prefer-spread': 'error',
|
|
50
|
+
// Require template literals instead of string concatenation.
|
|
51
|
+
'prefer-template': 'warn',
|
|
52
|
+
// Disallow returning values from Promise executor functions.
|
|
53
|
+
'no-promise-executor-return': 'error',
|
|
54
|
+
// Disallow loops with a body that allows only one iteration.
|
|
55
|
+
'no-unreachable-loop': 'error',
|
|
56
|
+
// Require a capital letter for constructors.
|
|
57
|
+
'new-cap': ['error', { capIsNew: false }],
|
|
58
|
+
// Disallow the omission of parentheses when invoking a constructor with no arguments.
|
|
59
|
+
'new-parens': 'warn',
|
|
60
|
+
// Disallow if as the only statement in an else block.
|
|
61
|
+
'no-lonely-if': 'warn',
|
|
62
|
+
// Disallow ternary operators when simpler alternatives exist.
|
|
63
|
+
'no-unneeded-ternary': 'error',
|
|
64
|
+
// Require use of an object spread over Object.assign.
|
|
65
|
+
'prefer-object-spread': 'warn',
|
|
66
|
+
// Disallow labels that share a name with a variable.
|
|
67
|
+
'no-label-var': 'error',
|
|
68
|
+
// Disallow initializing variables to `undefined`.
|
|
69
|
+
'no-undef-init': 'warn',
|
|
70
|
+
// Disallow unused variables.
|
|
71
|
+
'no-unused-vars': [
|
|
72
|
+
'error',
|
|
73
|
+
{
|
|
74
|
+
args: 'after-used',
|
|
75
|
+
argsIgnorePattern: '^_',
|
|
76
|
+
ignoreRestSiblings: false,
|
|
77
|
+
vars: 'all',
|
|
78
|
+
varsIgnorePattern: '^_',
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { defineConfig } = require('eslint-define-config');
|
|
3
|
+
|
|
4
|
+
module.exports = defineConfig({
|
|
5
|
+
rules: {
|
|
6
|
+
'no-restricted-syntax': [
|
|
7
|
+
'error',
|
|
8
|
+
{
|
|
9
|
+
// catches common mistakes when writing comments in CSS
|
|
10
|
+
selector:
|
|
11
|
+
'TemplateElement[value.cooked=/\\s+\\u002F\\u002F\\s*/], Literal[value=/\\s+\\u002F\\u002F\\s*/]',
|
|
12
|
+
message: 'Invalid comment syntax. Use `/* */` instead of `//`.',
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { defineConfig } = require('eslint-define-config');
|
|
3
|
+
|
|
4
|
+
module.exports = defineConfig({
|
|
5
|
+
rules: {
|
|
6
|
+
// Disallow non-import statements appearing before import statements.
|
|
7
|
+
'import/first': 'error',
|
|
8
|
+
// Require a newline after the last import/require.
|
|
9
|
+
'import/newline-after-import': 'warn',
|
|
10
|
+
// Disallow a module from importing itself.
|
|
11
|
+
'import/no-self-import': 'error',
|
|
12
|
+
// Ensures that there are no useless path segments.
|
|
13
|
+
'import/no-useless-path-segments': ['error'],
|
|
14
|
+
// Enforce a module import order convention.
|
|
15
|
+
'import/order': [
|
|
16
|
+
'warn',
|
|
17
|
+
{
|
|
18
|
+
groups: [
|
|
19
|
+
'builtin', // Node.js built-in modules
|
|
20
|
+
'external', // Packages
|
|
21
|
+
'internal', // Aliased modules
|
|
22
|
+
'parent', // Relative parent
|
|
23
|
+
'sibling', // Relative sibling
|
|
24
|
+
'index', // Relative index
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
// allow default exports
|
|
29
|
+
'import/no-default-export': 'off',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const { defineConfig } = require('eslint-define-config');
|
|
2
|
+
const noUnusedVarsConfig = require('./base.cjs').rules['no-unused-vars'];
|
|
3
|
+
|
|
4
|
+
// @ts-check
|
|
5
|
+
module.exports = defineConfig({
|
|
6
|
+
rules: {
|
|
7
|
+
// Require consistent usage of type exports.
|
|
8
|
+
'@typescript-eslint/consistent-type-exports': [
|
|
9
|
+
'error',
|
|
10
|
+
{ fixMixedExportsWithInlineTypeSpecifier: true },
|
|
11
|
+
],
|
|
12
|
+
// Require consistent usage of type imports.
|
|
13
|
+
'@typescript-eslint/consistent-type-imports': [
|
|
14
|
+
'error',
|
|
15
|
+
{
|
|
16
|
+
prefer: 'type-imports',
|
|
17
|
+
fixStyle: 'inline-type-imports',
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
/**
|
|
21
|
+
* Require using function property types in method signatures.
|
|
22
|
+
* These have enhanced typechecking, whereas method signatures do not.
|
|
23
|
+
*/
|
|
24
|
+
'@typescript-eslint/method-signature-style': 'error',
|
|
25
|
+
/**
|
|
26
|
+
* Require consistent naming conventions.
|
|
27
|
+
* Improves IntelliSense suggestions and avoids name collisions.
|
|
28
|
+
*/
|
|
29
|
+
'@typescript-eslint/naming-convention': [
|
|
30
|
+
'error',
|
|
31
|
+
// Anything type-like should be written in PascalCase.
|
|
32
|
+
{
|
|
33
|
+
format: ['PascalCase'],
|
|
34
|
+
selector: ['typeLike', 'enumMember'],
|
|
35
|
+
},
|
|
36
|
+
// Interfaces cannot be prefixed with `I`, or have restricted names.
|
|
37
|
+
{
|
|
38
|
+
custom: {
|
|
39
|
+
match: false,
|
|
40
|
+
regex: '^I[A-Z]|^(Interface|Props|State)$',
|
|
41
|
+
},
|
|
42
|
+
format: ['PascalCase'],
|
|
43
|
+
selector: 'interface',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
// Disallow members of unions and intersections that do nothing or override type information.
|
|
47
|
+
'@typescript-eslint/no-redundant-type-constituents': 'error',
|
|
48
|
+
// Require using `RegExp.exec()` over `String.match()` for consistency.
|
|
49
|
+
'@typescript-eslint/prefer-regexp-exec': 'warn',
|
|
50
|
+
//
|
|
51
|
+
'@typescript-eslint/require-array-sort-compare': [
|
|
52
|
+
'error',
|
|
53
|
+
{ ignoreStringArrays: true },
|
|
54
|
+
],
|
|
55
|
+
/**
|
|
56
|
+
* Require exhaustive checks when using union types in switch statements.
|
|
57
|
+
* This ensures cases are considered when items are later added to a union.
|
|
58
|
+
*/
|
|
59
|
+
'@typescript-eslint/switch-exhaustiveness-check': 'error',
|
|
60
|
+
// Require default parameters to be last.
|
|
61
|
+
'default-param-last': 'off',
|
|
62
|
+
'@typescript-eslint/default-param-last': 'error',
|
|
63
|
+
// Disallow creation of functions within loops.
|
|
64
|
+
'no-loop-func': 'off',
|
|
65
|
+
'@typescript-eslint/no-loop-func': 'error',
|
|
66
|
+
// Disallow unused variables.
|
|
67
|
+
'no-unused-vars': 'off',
|
|
68
|
+
'@typescript-eslint/no-unused-vars': noUnusedVarsConfig,
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* These are enabled by `import/recommended`, but are better handled by
|
|
72
|
+
* TypeScript and @typescript-eslint.
|
|
73
|
+
*/
|
|
74
|
+
'import/default': 'off',
|
|
75
|
+
'import/export': 'off',
|
|
76
|
+
'import/namespace': 'off',
|
|
77
|
+
'import/no-unresolved': 'off',
|
|
78
|
+
|
|
79
|
+
// This is disabled as we feel that checking empty strings is a valid use
|
|
80
|
+
// of `||` over `??`.
|
|
81
|
+
'@typescript-eslint/prefer-nullish-coalescing': 'off',
|
|
82
|
+
},
|
|
83
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
const { defineConfig } = require('eslint-define-config');
|
|
3
|
+
|
|
4
|
+
module.exports = defineConfig({
|
|
5
|
+
plugins: ['unicorn'],
|
|
6
|
+
rules: {
|
|
7
|
+
// Use destructured variables over properties.
|
|
8
|
+
'unicorn/consistent-destructuring': 'warn',
|
|
9
|
+
// Move function definitions to the highest possible scope.
|
|
10
|
+
'unicorn/consistent-function-scoping': [
|
|
11
|
+
'warn',
|
|
12
|
+
{
|
|
13
|
+
checkArrowFunctions: false,
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
// Enforce passing a message value when creating a built-in error.
|
|
17
|
+
'unicorn/error-message': 'error',
|
|
18
|
+
// Require escape sequences to use uppercase values.
|
|
19
|
+
'unicorn/escape-case': 'warn',
|
|
20
|
+
// Disallow empty files.
|
|
21
|
+
'unicorn/no-empty-file': 'error',
|
|
22
|
+
// Do not use a for loop that can be replaced with a for-of loop.
|
|
23
|
+
'unicorn/no-for-loop': 'warn',
|
|
24
|
+
// Require Array.isArray() instead of instanceof Array.
|
|
25
|
+
'unicorn/no-instanceof-array': 'error',
|
|
26
|
+
// Prevent calling EventTarget#removeEventListener() with the result of an expression.
|
|
27
|
+
'unicorn/no-invalid-remove-event-listener': 'error',
|
|
28
|
+
// Disallow the use of objects as default parameters.
|
|
29
|
+
'unicorn/no-object-as-default-parameter': 'error',
|
|
30
|
+
// Disallow then property.
|
|
31
|
+
'unicorn/no-thenable': 'error',
|
|
32
|
+
// Disallow awaiting non-promise values.
|
|
33
|
+
'unicorn/no-unnecessary-await': 'error',
|
|
34
|
+
// Disallow unreadable IIFEs.
|
|
35
|
+
'unicorn/no-unreadable-iife': 'warn',
|
|
36
|
+
// Disallow useless fallback when spreading in object literals.
|
|
37
|
+
'unicorn/no-useless-fallback-in-spread': 'warn',
|
|
38
|
+
// Disallow useless array length check.
|
|
39
|
+
'unicorn/no-useless-length-check': 'warn',
|
|
40
|
+
// Disallow returning/yielding Promise.resolve/reject() in async functions or promise callbacks
|
|
41
|
+
'unicorn/no-useless-promise-resolve-reject': 'error',
|
|
42
|
+
// Disallow unnecessary spread.
|
|
43
|
+
'unicorn/no-useless-spread': 'error',
|
|
44
|
+
// Disallow number literals with zero fractions or dangling dots.
|
|
45
|
+
'unicorn/no-zero-fractions': 'warn',
|
|
46
|
+
// Enforce the style of numeric separators by correctly grouping digits.
|
|
47
|
+
'unicorn/numeric-separators-style': 'error',
|
|
48
|
+
// Prefer .addEventListener() and .removeEventListener() over on-functions.
|
|
49
|
+
'unicorn/prefer-add-event-listener': 'error',
|
|
50
|
+
// Prefer .find(…) and .findLast(…) over the first or last element from .filter(…).
|
|
51
|
+
'unicorn/prefer-array-find': 'error',
|
|
52
|
+
// Prefer Array#flat() over legacy techniques to flatten arrays.
|
|
53
|
+
'unicorn/prefer-array-flat': 'error',
|
|
54
|
+
// Prefer .flatMap(…) over .map(…).flat().
|
|
55
|
+
'unicorn/prefer-array-flat-map': 'error',
|
|
56
|
+
// Prefer Array#{indexOf,lastIndexOf}() over Array#{findIndex,findLastIndex}() when looking for the index of an item.
|
|
57
|
+
'unicorn/prefer-array-index-of': 'error',
|
|
58
|
+
// Prefer .some(…) over .filter(…).length check and .{find,findLast}(…).
|
|
59
|
+
'unicorn/prefer-array-some': 'error',
|
|
60
|
+
// Prefer .at() method for index access and String#charAt().
|
|
61
|
+
'unicorn/prefer-at': 'error',
|
|
62
|
+
// Prefer Blob#arrayBuffer() over FileReader#readAsArrayBuffer(…) and Blob#text() over FileReader#readAsText(…).
|
|
63
|
+
'unicorn/prefer-blob-reading-methods': 'error',
|
|
64
|
+
// Prefer Date.now() to get the number of milliseconds since the Unix Epoch.
|
|
65
|
+
'unicorn/prefer-date-now': 'error',
|
|
66
|
+
// Prefer default parameters over reassignment.
|
|
67
|
+
'unicorn/prefer-default-parameters': 'warn',
|
|
68
|
+
// Prefer Node#append() over Node#appendChild().
|
|
69
|
+
'unicorn/prefer-dom-node-append': 'error',
|
|
70
|
+
// Prefer using .dataset on DOM elements over calling attribute methods.
|
|
71
|
+
'unicorn/prefer-dom-node-dataset': 'error',
|
|
72
|
+
// Prefer childNode.remove() over parentNode.removeChild(childNode).
|
|
73
|
+
'unicorn/prefer-dom-node-remove': 'error',
|
|
74
|
+
// Prefer EventTarget over EventEmitter.
|
|
75
|
+
'unicorn/prefer-event-target': 'warn',
|
|
76
|
+
// Prefer export…from when re-exporting.
|
|
77
|
+
'unicorn/prefer-export-from': [
|
|
78
|
+
'warn',
|
|
79
|
+
{
|
|
80
|
+
ignoreUsedVariables: true,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
// Prefer .includes() over .indexOf() and Array#some() when checking for existence or non-existence.
|
|
84
|
+
'unicorn/prefer-includes': 'error',
|
|
85
|
+
// Prefer KeyboardEvent#key over KeyboardEvent#keyCode.
|
|
86
|
+
'unicorn/prefer-keyboard-event-key': 'error',
|
|
87
|
+
// Prefer using a logical operator over a ternary.
|
|
88
|
+
'unicorn/prefer-logical-operator-over-ternary': 'error',
|
|
89
|
+
// Enforce the use of Math.trunc instead of bitwise operators.
|
|
90
|
+
'unicorn/prefer-math-trunc': 'error',
|
|
91
|
+
// Prefer .before() over .insertBefore(), .replaceWith() over .replaceChild(), prefer one of .before(), .after(), .append() or .prepend() over insertAdjacentText() and insertAdjacentElement().
|
|
92
|
+
'unicorn/prefer-modern-dom-apis': 'error',
|
|
93
|
+
// Prefer modern Math APIs over legacy patterns.
|
|
94
|
+
'unicorn/prefer-modern-math-apis': 'error',
|
|
95
|
+
// Prefer negative index over .length - index when possible.
|
|
96
|
+
'unicorn/prefer-negative-index': 'error',
|
|
97
|
+
// Require using the `node:` protocol when importing Node.js built-in modules.
|
|
98
|
+
'unicorn/prefer-node-protocol': 'error',
|
|
99
|
+
// Prefer Number static properties over global ones.
|
|
100
|
+
'unicorn/prefer-number-properties': ['error', { checkInfinity: false }],
|
|
101
|
+
// Prefer using Object.fromEntries(…) to transform a list of key-value pairs into an object.
|
|
102
|
+
'unicorn/prefer-object-from-entries': 'error',
|
|
103
|
+
// Prefer Reflect.apply() over Function#apply().
|
|
104
|
+
'unicorn/prefer-reflect-apply': 'error',
|
|
105
|
+
// using RegExp.test() is faster than string.match()
|
|
106
|
+
// note: you should not use the global flag /g with RegExp.test() though!
|
|
107
|
+
'unicorn/prefer-regexp-test': 'error',
|
|
108
|
+
// Prefer Set#has() over Array#includes() when checking for existence or non-existence.
|
|
109
|
+
'unicorn/prefer-set-has': 'error',
|
|
110
|
+
// Prefer using Set#size instead of Array#length.
|
|
111
|
+
'unicorn/prefer-set-size': 'error',
|
|
112
|
+
// Prefer the spread operator over Array.from().
|
|
113
|
+
'unicorn/prefer-spread': 'error',
|
|
114
|
+
// Prefer String#replaceAll() over regex searches with the global flag.
|
|
115
|
+
'unicorn/prefer-string-replace-all': 'error',
|
|
116
|
+
// Prefer String#slice() over String#substr() and String#substring().
|
|
117
|
+
'unicorn/prefer-string-slice': 'error',
|
|
118
|
+
// Prefer String#startsWith() & String#endsWith() over RegExp#test().
|
|
119
|
+
'unicorn/prefer-string-starts-ends-with': 'error',
|
|
120
|
+
// Prefer ternary expressions over simple if-else statements.
|
|
121
|
+
'unicorn/prefer-ternary': ['warn', 'only-single-line'],
|
|
122
|
+
// Prefer top-level await over top-level promises and async function calls.
|
|
123
|
+
'unicorn/prefer-top-level-await': 'error',
|
|
124
|
+
// Enforce using the separator argument with Array#join().
|
|
125
|
+
'unicorn/require-array-join-separator': 'error',
|
|
126
|
+
// Enforce consistent brace style for case clauses.
|
|
127
|
+
'unicorn/switch-case-braces': 'error',
|
|
128
|
+
},
|
|
129
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@timobechtel/style",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"files": [
|
|
6
|
+
"bin",
|
|
7
|
+
"eslint",
|
|
8
|
+
"prettier",
|
|
9
|
+
"semantic-release",
|
|
10
|
+
"tsconfig"
|
|
11
|
+
],
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"eslint": "^8.53.0",
|
|
14
|
+
"prettier": "^3.0.3",
|
|
15
|
+
"semantic-release": "^22.0.7",
|
|
16
|
+
"typescript": "^5.2.2"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"eslint": "^8.53.0",
|
|
20
|
+
"prettier": "^3.0.3",
|
|
21
|
+
"semantic-release": "^22.0.7",
|
|
22
|
+
"typescript": "^5.2.2"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
26
|
+
"@semantic-release/git": "^10.0.1",
|
|
27
|
+
"@typescript-eslint/eslint-plugin": "^6.10.0",
|
|
28
|
+
"@typescript-eslint/parser": "^6.10.0",
|
|
29
|
+
"eslint-config-prettier": "^9.0.0",
|
|
30
|
+
"eslint-define-config": "^1.24.1",
|
|
31
|
+
"eslint-import-resolver-typescript": "^3.6.1",
|
|
32
|
+
"eslint-plugin-import": "^2.29.0",
|
|
33
|
+
"eslint-plugin-unicorn": "^49.0.0"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Some of Prettier's defaults can be overridden by an EditorConfig file. We
|
|
3
|
+
* define those here to ensure that doesn't happen.
|
|
4
|
+
*
|
|
5
|
+
* See: https://github.com/prettier/prettier/blob/main/docs/configuration.md#editorconfig
|
|
6
|
+
*/
|
|
7
|
+
const overridableDefaults = {
|
|
8
|
+
endOfLine: 'lf',
|
|
9
|
+
tabWidth: 2,
|
|
10
|
+
printWidth: 80,
|
|
11
|
+
useTabs: false,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/** @type {import("prettier").Config} */
|
|
15
|
+
export default {
|
|
16
|
+
...overridableDefaults,
|
|
17
|
+
singleQuote: true,
|
|
18
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @type {import('semantic-release').GlobalConfig}
|
|
3
|
+
*/
|
|
4
|
+
module.exports = {
|
|
5
|
+
branches: [
|
|
6
|
+
'main',
|
|
7
|
+
{
|
|
8
|
+
name: 'canary',
|
|
9
|
+
channel: 'canary',
|
|
10
|
+
prerelease: true,
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
plugins: [
|
|
14
|
+
'@semantic-release/commit-analyzer',
|
|
15
|
+
'@semantic-release/release-notes-generator',
|
|
16
|
+
'@semantic-release/changelog',
|
|
17
|
+
'@semantic-release/npm',
|
|
18
|
+
'@semantic-release/github',
|
|
19
|
+
'@semantic-release/git',
|
|
20
|
+
],
|
|
21
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"display": "Default",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"composite": false,
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"declarationMap": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"inlineSources": false,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"moduleResolution": "node",
|
|
13
|
+
"noUnusedLocals": false,
|
|
14
|
+
"noUnusedParameters": false,
|
|
15
|
+
"preserveWatchOutput": true,
|
|
16
|
+
"skipLibCheck": true,
|
|
17
|
+
"strict": true,
|
|
18
|
+
"strictNullChecks": true,
|
|
19
|
+
"incremental": true,
|
|
20
|
+
"resolveJsonModule": true
|
|
21
|
+
},
|
|
22
|
+
"exclude": ["node_modules"]
|
|
23
|
+
}
|