@mouse_484/eslint-config 5.3.9 → 5.4.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/README.md +1 -4
- package/bin/cli.js +82 -150
- package/package.json +1 -1
- package/src/configs/tailwind.js +20 -10
- package/src/configs/typescript.js +20 -0
- package/src/index.d.ts +20 -7
- package/src/index.js +2 -0
- package/src/lib/factory.d.ts +5 -5
- package/src/lib/factory.js +4 -1
package/README.md
CHANGED
|
@@ -4,8 +4,5 @@ ESLint Config based on [@antfu/eslint-config](https://github.com/antfu/eslint-co
|
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
```
|
|
7
|
-
@mouse_484/eslint-config@latest
|
|
7
|
+
npx @mouse_484/eslint-config@latest
|
|
8
8
|
```
|
|
9
|
-
|
|
10
|
-
> [!WARNING]
|
|
11
|
-
> `npx` does not work. Use `pnpx` or run bin/cli.js directly after installation.
|
package/bin/cli.js
CHANGED
|
@@ -1,182 +1,114 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import { spawn } from 'node:child_process'
|
|
3
|
+
import { readFile, writeFile } from 'node:fs/promises'
|
|
4
4
|
import path from 'node:path'
|
|
5
5
|
import process from 'node:process'
|
|
6
6
|
import { resolveCommand } from 'package-manager-detector/commands'
|
|
7
7
|
import { detect } from 'package-manager-detector/detect'
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* @property {string} import - Import name in config
|
|
13
|
-
* @property {string} [version] - Package version
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/** @type {PackageInfo} */
|
|
17
|
-
const SOURCE = {
|
|
18
|
-
name: '@antfu/eslint-config',
|
|
19
|
-
import: 'antfu',
|
|
9
|
+
const PACKAGE_NAME = {
|
|
10
|
+
BASE: '@antfu/eslint-config',
|
|
11
|
+
CUSTOM: '@mouse_484/eslint-config',
|
|
20
12
|
}
|
|
21
13
|
|
|
22
|
-
/** @type {PackageInfo} */
|
|
23
|
-
const TARGET = {
|
|
24
|
-
name: '@mouse_484/eslint-config',
|
|
25
|
-
import: 'mouse',
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const PACKAGE_JSON_FILE = 'package.json'
|
|
29
|
-
const ESLINT_CONFIG_JS_FILE = 'eslint.config.js'
|
|
30
|
-
const ESLINT_CONFIG_MJS_FILE = 'eslint.config.mjs'
|
|
31
|
-
|
|
32
|
-
// infinite loop prevention
|
|
33
|
-
const isRunningFromSourcePackage = process.argv[1].includes(SOURCE.name)
|
|
34
|
-
|
|
35
14
|
/**
|
|
36
|
-
*
|
|
37
|
-
* @param {
|
|
38
|
-
* @param {string[]} args - Command arguments
|
|
39
|
-
* @returns {Promise<void>}
|
|
15
|
+
* Simple logger function
|
|
16
|
+
* @param {*} message
|
|
40
17
|
*/
|
|
41
|
-
function
|
|
42
|
-
console.info(
|
|
43
|
-
const spawnedProcess = spawn(command, args, { stdio: 'inherit', shell: true })
|
|
44
|
-
|
|
45
|
-
return new Promise((resolve, reject) => {
|
|
46
|
-
spawnedProcess.on('close', (code) => {
|
|
47
|
-
if (code === 0) {
|
|
48
|
-
setTimeout(() => {
|
|
49
|
-
resolve()
|
|
50
|
-
}, 300)
|
|
51
|
-
} else {
|
|
52
|
-
reject(new Error(`Command failed with exit code ${code}`))
|
|
53
|
-
}
|
|
54
|
-
})
|
|
55
|
-
spawnedProcess.on('error', reject)
|
|
56
|
-
})
|
|
18
|
+
function logger(message) {
|
|
19
|
+
console.info('@mouse_484/eslint-config:', message)
|
|
57
20
|
}
|
|
58
21
|
|
|
59
22
|
/**
|
|
60
|
-
*
|
|
61
|
-
* @returns {Promise<void>}
|
|
23
|
+
* @type {(...args: Parameters<typeof import("package-manager-detector/commands").resolveCommand>) => Promise<void>}
|
|
62
24
|
*/
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const cwd = process.cwd()
|
|
67
|
-
const cliPath = path.join(cwd, 'node_modules', SOURCE.name, 'bin', 'index.js')
|
|
68
|
-
|
|
25
|
+
function runAgentCommand(agent, command_, args_) {
|
|
26
|
+
const { command, args } = resolveCommand(agent, command_, args_)
|
|
69
27
|
return new Promise((resolve, reject) => {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
28
|
+
const child = spawn(
|
|
29
|
+
command,
|
|
30
|
+
args,
|
|
31
|
+
{
|
|
32
|
+
stdio: 'inherit',
|
|
33
|
+
},
|
|
34
|
+
)
|
|
75
35
|
|
|
76
|
-
|
|
36
|
+
child.on('close', (code) => {
|
|
77
37
|
if (code === 0) {
|
|
78
|
-
|
|
79
|
-
resolve()
|
|
80
|
-
}, 300)
|
|
38
|
+
resolve()
|
|
81
39
|
} else {
|
|
82
|
-
reject(new Error(`
|
|
40
|
+
reject(new Error(`Command failed: ${code} (${command} ${args.join(' ')})`))
|
|
83
41
|
}
|
|
84
42
|
})
|
|
85
|
-
|
|
43
|
+
child.on('error', (error) => {
|
|
44
|
+
reject(error)
|
|
45
|
+
})
|
|
86
46
|
})
|
|
87
47
|
}
|
|
88
48
|
|
|
89
|
-
/**
|
|
90
|
-
* Update JSON file with transform function
|
|
91
|
-
* @param {string} filePath - JSON file path
|
|
92
|
-
* @param {(data: any) => any} updateFunction - Transform function
|
|
93
|
-
*/
|
|
94
|
-
async function updateJSONFile(filePath, updateFunction) {
|
|
95
|
-
const content = await fs.readFile(filePath, 'utf8')
|
|
96
|
-
const data = JSON.parse(content)
|
|
97
|
-
const updated = updateFunction(data)
|
|
98
|
-
await fs.writeFile(filePath, JSON.stringify(updated, undefined, 2))
|
|
99
|
-
return updated
|
|
100
|
-
}
|
|
101
|
-
|
|
102
49
|
async function main() {
|
|
103
|
-
|
|
50
|
+
const cwd = process.cwd()
|
|
51
|
+
logger('Starting setup')
|
|
104
52
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
process.exitCode = 1
|
|
110
|
-
return
|
|
53
|
+
const packageManager = await detect() ?? {
|
|
54
|
+
name: 'npm',
|
|
55
|
+
agent: 'npm',
|
|
56
|
+
version: 'unknown',
|
|
111
57
|
}
|
|
112
58
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
59
|
+
logger(`Detected package manager: ${packageManager.name}`)
|
|
60
|
+
|
|
61
|
+
logger(`Setting up base package ${PACKAGE_NAME.BASE}`)
|
|
62
|
+
await runAgentCommand(
|
|
63
|
+
packageManager.agent,
|
|
64
|
+
'execute',
|
|
65
|
+
[PACKAGE_NAME.BASE],
|
|
66
|
+
)
|
|
67
|
+
logger('Modifying base config to custom config')
|
|
68
|
+
|
|
69
|
+
logger(`Uninstalling base package ${PACKAGE_NAME.BASE}`)
|
|
70
|
+
await runAgentCommand(
|
|
71
|
+
packageManager.agent,
|
|
72
|
+
'uninstall',
|
|
73
|
+
[PACKAGE_NAME.BASE],
|
|
74
|
+
)
|
|
75
|
+
logger(`Installing custom package ${PACKAGE_NAME.CUSTOM}`)
|
|
76
|
+
await runAgentCommand(
|
|
77
|
+
packageManager.agent,
|
|
78
|
+
'install',
|
|
79
|
+
['-D', PACKAGE_NAME.CUSTOM],
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
logger('Updating package.json scripts')
|
|
83
|
+
const packageJsonPath = path.join(cwd, 'package.json')
|
|
84
|
+
/**
|
|
85
|
+
* @type {{ scripts: Record<string, string>, type?: "module" }}
|
|
86
|
+
*/
|
|
87
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'))
|
|
88
|
+
packageJson.scripts = {
|
|
89
|
+
...packageJson.scripts,
|
|
90
|
+
'lint': 'eslint .',
|
|
91
|
+
'lint:fix': 'eslint --fix .',
|
|
121
92
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
let targetVersion
|
|
140
|
-
try {
|
|
141
|
-
targetVersion = execSync(`npm view ${TARGET.name} dist-tags.latest`).toString().trim()
|
|
142
|
-
} catch (error) {
|
|
143
|
-
console.warn(
|
|
144
|
-
`Warning: Could not fetch latest version for ${TARGET.name}, using 'latest'. `
|
|
145
|
-
+ `Error: ${error.message}`,
|
|
146
|
-
)
|
|
147
|
-
targetVersion = 'latest'
|
|
148
|
-
}
|
|
149
|
-
TARGET.version = targetVersion
|
|
150
|
-
packageData.devDependencies[TARGET.name] = targetVersion
|
|
151
|
-
|
|
152
|
-
packageData.scripts = {
|
|
153
|
-
...packageData.scripts,
|
|
154
|
-
'lint': 'eslint .',
|
|
155
|
-
'lint:fix': 'eslint --fix .',
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return packageData
|
|
93
|
+
await writeFile(packageJsonPath, JSON.stringify(packageJson, undefined, 2), 'utf8')
|
|
94
|
+
|
|
95
|
+
logger('Updating config file')
|
|
96
|
+
const configPath = path.join(cwd, `eslint.config.${packageJson.type === 'module' ? 'js' : 'mjs'}`)
|
|
97
|
+
await writeFile(configPath, `
|
|
98
|
+
import mouse from '${PACKAGE_NAME.CUSTOM}'
|
|
99
|
+
|
|
100
|
+
export default mouse()
|
|
101
|
+
`.trim(), 'utf8')
|
|
102
|
+
|
|
103
|
+
logger('Linting the project to verify setup')
|
|
104
|
+
await runAgentCommand(
|
|
105
|
+
packageManager.agent,
|
|
106
|
+
'run',
|
|
107
|
+
['lint:fix'],
|
|
108
|
+
).catch((error) => {
|
|
109
|
+
logger(`Linting failed: ${error.message}`)
|
|
159
110
|
})
|
|
160
|
-
|
|
161
|
-
const configExtension = package_.type === 'module' ? 'js' : 'mjs'
|
|
162
|
-
const eslintConfigFile = configExtension === 'js'
|
|
163
|
-
? ESLINT_CONFIG_JS_FILE
|
|
164
|
-
: ESLINT_CONFIG_MJS_FILE
|
|
165
|
-
const configPath = path.join(cwd, eslintConfigFile)
|
|
166
|
-
|
|
167
|
-
let configContent = await fs.readFile(configPath, 'utf8')
|
|
168
|
-
configContent = configContent
|
|
169
|
-
.replace(
|
|
170
|
-
`import ${SOURCE.import} from '${SOURCE.name}'`,
|
|
171
|
-
`import ${TARGET.import} from '${TARGET.name}'`,
|
|
172
|
-
)
|
|
173
|
-
.replaceAll(new RegExp(`(?<!['"])${SOURCE.import}(?!['"])`, 'g'), TARGET.import)
|
|
174
|
-
await fs.writeFile(configPath, configContent)
|
|
175
|
-
|
|
176
|
-
const finalInstallCmd = resolveCommand(pm.agent, 'install', [])
|
|
177
|
-
await runCommand(finalInstallCmd.command, finalInstallCmd.args)
|
|
178
|
-
|
|
179
|
-
console.info(`Successfully replaced the config from ${SOURCE.name} to ${TARGET.name}`)
|
|
180
111
|
}
|
|
181
112
|
|
|
182
113
|
await main()
|
|
114
|
+
console.info('---------------- Setup Complete ----------------')
|
package/package.json
CHANGED
package/src/configs/tailwind.js
CHANGED
|
@@ -6,28 +6,38 @@ export default createConfigs({
|
|
|
6
6
|
baseWithOption: 'tailwind',
|
|
7
7
|
configs: [
|
|
8
8
|
(meta) => {
|
|
9
|
+
if (!meta?.entryPoint) return
|
|
10
|
+
|
|
9
11
|
return {
|
|
10
12
|
name: 'tailwind',
|
|
11
13
|
plugins: {
|
|
12
14
|
tailwind: eslintPluginBetterTailwindcss,
|
|
13
15
|
},
|
|
14
16
|
rules: {
|
|
15
|
-
//
|
|
16
|
-
'tailwind/
|
|
17
|
+
// Stylistic rules
|
|
18
|
+
'tailwind/enforce-consistent-line-wrapping': ['warn', {
|
|
17
19
|
group: 'newLine',
|
|
18
20
|
}],
|
|
19
|
-
'tailwind/
|
|
20
|
-
|
|
21
|
+
'tailwind/enforce-consistent-class-order': ['warn', {
|
|
22
|
+
order: 'improved',
|
|
23
|
+
}],
|
|
24
|
+
'tailwind/enforce-consistent-variable-syntax': 'warn',
|
|
25
|
+
'tailwind/enforce-consistent-important-position': 'error',
|
|
26
|
+
'tailwind/enforce-shorthand-classes': 'warn',
|
|
21
27
|
'tailwind/no-duplicate-classes': 'error',
|
|
22
|
-
'tailwind/
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
'tailwind/no-deprecated-classes': 'error',
|
|
29
|
+
'tailwind/no-unnecessary-whitespace': 'warn',
|
|
30
|
+
// Correctness rules
|
|
31
|
+
'tailwind/no-unregistered-classes': ['error', {
|
|
32
|
+
ignore: [],
|
|
33
|
+
detectComponentClasses: true,
|
|
34
|
+
}],
|
|
25
35
|
'tailwind/no-conflicting-classes': 'error',
|
|
26
|
-
'tailwind/no-restricted-classes': 'off',
|
|
36
|
+
'tailwind/no-restricted-classes': 'off', // arbitrary valuesの制限を今後検討
|
|
27
37
|
},
|
|
28
38
|
settings: {
|
|
29
|
-
|
|
30
|
-
entryPoint: meta
|
|
39
|
+
'better-tailwindcss': {
|
|
40
|
+
entryPoint: meta.entryPoint,
|
|
31
41
|
},
|
|
32
42
|
},
|
|
33
43
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { GLOB_TS } from '@antfu/eslint-config'
|
|
2
|
+
import { createConfigs } from '../lib/factory.js'
|
|
3
|
+
|
|
4
|
+
export default createConfigs({
|
|
5
|
+
name: 'typescript',
|
|
6
|
+
baseWithOption: 'typescript',
|
|
7
|
+
configs: [
|
|
8
|
+
(meta) => {
|
|
9
|
+
if (meta && 'tsconfigPath' in meta && meta.tsconfigPath) {
|
|
10
|
+
return {
|
|
11
|
+
name: 'type-aware',
|
|
12
|
+
files: [GLOB_TS],
|
|
13
|
+
rules: {
|
|
14
|
+
'ts/no-deprecated': 'error',
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
})
|
package/src/index.d.ts
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type {
|
|
2
|
+
TypedFlatConfigItem as AntfuTypedFlatConfigItem,
|
|
3
|
+
OptionsConfig,
|
|
4
|
+
Rules,
|
|
5
|
+
} from '@antfu/eslint-config'
|
|
6
|
+
import type { Linter } from 'eslint'
|
|
7
|
+
import type { FlatConfigComposer } from 'eslint-flat-config-utils'
|
|
8
|
+
import type { RuleOptions } from './lib/rules.gen'
|
|
2
9
|
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
type Awaitable<T> = T | Promise<T>
|
|
11
|
+
export interface TypedFlatConfigItem extends Omit<AntfuTypedFlatConfigItem, 'rules'> {
|
|
12
|
+
rules?: Rules & RuleOptions
|
|
13
|
+
}
|
|
14
|
+
type Config = Awaitable<
|
|
15
|
+
TypedFlatConfigItem
|
|
16
|
+
| TypedFlatConfigItem[]
|
|
17
|
+
| FlatConfigComposer<any, any>
|
|
18
|
+
| Linter.Config[]
|
|
19
|
+
>
|
|
20
|
+
export interface Options extends OptionsConfig, Omit<TypedFlatConfigItem, 'files'> {
|
|
8
21
|
tailwind?: false | { entryPoint: string }
|
|
9
22
|
}
|
|
10
23
|
|
|
11
24
|
export declare function mouse(
|
|
12
25
|
options?: Options,
|
|
13
|
-
...configs:
|
|
26
|
+
...configs: Config[]
|
|
14
27
|
): ReturnType<typeof antfu>
|
|
15
28
|
export default mouse
|
package/src/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import perfectionist from './configs/perfectionist.js'
|
|
|
5
5
|
import stylistic from './configs/stylistic.js'
|
|
6
6
|
import svelte from './configs/svelte.js'
|
|
7
7
|
import tailwind from './configs/tailwind.js'
|
|
8
|
+
import typescript from './configs/typescript.js'
|
|
8
9
|
import unicorn from './configs/unicorn.js'
|
|
9
10
|
|
|
10
11
|
/** @type {import('.').mouse} */
|
|
@@ -25,6 +26,7 @@ async function mouse(options, ...userConfigs) {
|
|
|
25
26
|
...unicorn(options),
|
|
26
27
|
...perfectionist(options),
|
|
27
28
|
// Language specific
|
|
29
|
+
...typescript(options),
|
|
28
30
|
...astro(options),
|
|
29
31
|
...svelte(options),
|
|
30
32
|
// Tools
|
package/src/lib/factory.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Options } from '..'
|
|
3
|
-
import type { RuleOptions } from './rules.gen'
|
|
1
|
+
import type { Options, TypedFlatConfigItem } from '..'
|
|
4
2
|
|
|
5
3
|
interface ConfigItem extends TypedFlatConfigItem {
|
|
6
4
|
withOptions?: (keyof Options)[]
|
|
7
5
|
name: string
|
|
8
|
-
rules?: Rules & RuleOptions
|
|
9
6
|
}
|
|
10
7
|
|
|
11
8
|
type OnlyObject<T> = T extends object ? T : never
|
|
12
9
|
export declare function createConfigs<T extends keyof Options = undefined>(parameters: {
|
|
13
10
|
name: string
|
|
14
11
|
baseWithOption?: T
|
|
15
|
-
configs: (
|
|
12
|
+
configs: (
|
|
13
|
+
ConfigItem
|
|
14
|
+
| ((meta?: OnlyObject<Options[T]>) => ConfigItem)
|
|
15
|
+
)[]
|
|
16
16
|
}): (options: Options) => TypedFlatConfigItem[]
|
package/src/lib/factory.js
CHANGED
|
@@ -30,7 +30,10 @@ export function createConfigs({ name, baseWithOption, configs }) {
|
|
|
30
30
|
}
|
|
31
31
|
const meta = options[baseWithOption]
|
|
32
32
|
// @ts-ignore
|
|
33
|
-
configItem = configItem(typeof meta === 'object' ? meta : undefined)
|
|
33
|
+
configItem = configItem(typeof meta === 'object' ? meta : undefined) ?? {}
|
|
34
|
+
}
|
|
35
|
+
if (!configItem) {
|
|
36
|
+
return []
|
|
34
37
|
}
|
|
35
38
|
const { name: configName, withOptions = [], ...restConfig } = configItem
|
|
36
39
|
return createConfig(
|