@archpublicwebsite/eslint-config 1.0.5 → 1.0.6
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 +30 -0
- package/package.json +3 -2
- package/tools/setup/install.mjs +33 -0
- package/tools/setup/vscode.mjs +100 -0
package/README.md
CHANGED
|
@@ -41,8 +41,38 @@ On install, this package automatically sets up in your project root:
|
|
|
41
41
|
- `.hooks/post-commit`
|
|
42
42
|
- `eslint.config.mjs` (if not present)
|
|
43
43
|
- `.prettierrc` plugin entry for `prettier-plugin-tailwindcss`
|
|
44
|
+
- `.vscode/settings.json` – ESLint flat-config settings so VS Code reads the config
|
|
45
|
+
- `.vscode/extensions.json` – recommended extensions (ESLint, Prettier, Volar)
|
|
44
46
|
- `git config core.hooksPath .hooks` (when in a git repo)
|
|
45
47
|
|
|
48
|
+
### VS Code integration
|
|
49
|
+
|
|
50
|
+
On install, `.vscode/settings.json` is created or merged with these settings:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"eslint.useFlatConfig": true,
|
|
55
|
+
"eslint.validate": [
|
|
56
|
+
"javascript", "javascriptreact",
|
|
57
|
+
"typescript", "typescriptreact",
|
|
58
|
+
"vue", "json", "jsonc", "markdown"
|
|
59
|
+
],
|
|
60
|
+
"editor.codeActionsOnSave": {
|
|
61
|
+
"source.fixAll.eslint": "explicit",
|
|
62
|
+
"source.organizeImports": "never"
|
|
63
|
+
},
|
|
64
|
+
"editor.formatOnSave": false
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
If `.vscode/settings.json` already exists, your existing settings are preserved — only the ESLint-related keys are added or updated.
|
|
69
|
+
|
|
70
|
+
You can also re-run it manually:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
node node_modules/@archpublicwebsite/eslint-config/tools/setup/install.mjs
|
|
74
|
+
```
|
|
75
|
+
|
|
46
76
|
## What this package provides
|
|
47
77
|
|
|
48
78
|
- `eslint.config.mjs` builder via `createArchipelagoConfig`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@archpublicwebsite/eslint-config",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"author": "Archipelago International",
|
|
5
5
|
"description": "Reusable ESLint flat config and git-hook toolkit for Archipelago projects",
|
|
6
6
|
"type": "module",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"eslint-config",
|
|
29
29
|
"flat-config",
|
|
30
30
|
"vue",
|
|
31
|
-
"git-hooks"
|
|
31
|
+
"git-hooks",
|
|
32
|
+
"vscode"
|
|
32
33
|
],
|
|
33
34
|
"private": false,
|
|
34
35
|
"engines": {
|
package/tools/setup/install.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process'
|
|
2
2
|
import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
3
3
|
import { join } from 'node:path'
|
|
4
|
+
import { ensureVscodeSettings } from './vscode.mjs'
|
|
4
5
|
|
|
5
6
|
function getProjectRoot() {
|
|
6
7
|
const root = process.env.INIT_CWD || process.cwd()
|
|
@@ -109,6 +110,36 @@ function ensureHooksPath(projectRoot) {
|
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
function ensureVscodeExtensions(projectRoot) {
|
|
114
|
+
const vscodeDir = join(projectRoot, '.vscode')
|
|
115
|
+
const extPath = join(vscodeDir, 'extensions.json')
|
|
116
|
+
|
|
117
|
+
if (!existsSync(vscodeDir))
|
|
118
|
+
mkdirSync(vscodeDir, { recursive: true })
|
|
119
|
+
|
|
120
|
+
const recommended = [
|
|
121
|
+
'dbaeumer.vscode-eslint',
|
|
122
|
+
'esbenp.prettier-vscode',
|
|
123
|
+
'vue.volar',
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
let current = { recommendations: [] }
|
|
127
|
+
if (existsSync(extPath)) {
|
|
128
|
+
try {
|
|
129
|
+
current = JSON.parse(readFileSync(extPath, 'utf8'))
|
|
130
|
+
if (!Array.isArray(current.recommendations))
|
|
131
|
+
current.recommendations = []
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
current = { recommendations: [] }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const merged = [...new Set([...current.recommendations, ...recommended])]
|
|
139
|
+
current.recommendations = merged
|
|
140
|
+
writeFileSync(extPath, `${JSON.stringify(current, null, 2)}\n`, 'utf8')
|
|
141
|
+
}
|
|
142
|
+
|
|
112
143
|
function main() {
|
|
113
144
|
const projectRoot = getProjectRoot()
|
|
114
145
|
if (!projectRoot)
|
|
@@ -118,6 +149,8 @@ function main() {
|
|
|
118
149
|
ensureHooksPath(projectRoot)
|
|
119
150
|
ensureEslintConfig(projectRoot)
|
|
120
151
|
ensurePrettierConfig(projectRoot)
|
|
152
|
+
ensureVscodeSettings(projectRoot)
|
|
153
|
+
ensureVscodeExtensions(projectRoot)
|
|
121
154
|
}
|
|
122
155
|
|
|
123
156
|
main()
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* VS Code settings required for ESLint flat config to work properly.
|
|
6
|
+
* These tell the ESLint extension to use flat config mode and validate
|
|
7
|
+
* the correct file types.
|
|
8
|
+
*/
|
|
9
|
+
const VSCODE_ESLINT_SETTINGS = {
|
|
10
|
+
// Use flat config mode (required for eslint.config.mjs)
|
|
11
|
+
'eslint.useFlatConfig': true,
|
|
12
|
+
|
|
13
|
+
// Enable ESLint for these languages
|
|
14
|
+
'eslint.validate': [
|
|
15
|
+
'javascript',
|
|
16
|
+
'javascriptreact',
|
|
17
|
+
'typescript',
|
|
18
|
+
'typescriptreact',
|
|
19
|
+
'vue',
|
|
20
|
+
'json',
|
|
21
|
+
'jsonc',
|
|
22
|
+
'markdown',
|
|
23
|
+
],
|
|
24
|
+
|
|
25
|
+
// Auto-fix on save via ESLint
|
|
26
|
+
'editor.codeActionsOnSave': {
|
|
27
|
+
'source.fixAll.eslint': 'explicit',
|
|
28
|
+
'source.organizeImports': 'never',
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
// Let ESLint handle formatting instead of the built-in formatter
|
|
32
|
+
'editor.formatOnSave': false,
|
|
33
|
+
|
|
34
|
+
// Disable the default VS Code JSON formatter for files ESLint handles
|
|
35
|
+
'[json]': {
|
|
36
|
+
'editor.defaultFormatter': 'dbaeumer.vscode-eslint',
|
|
37
|
+
},
|
|
38
|
+
'[jsonc]': {
|
|
39
|
+
'editor.defaultFormatter': 'dbaeumer.vscode-eslint',
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Deep-merge source into target. Arrays are replaced, not concatenated.
|
|
45
|
+
* Only plain objects are recursed into.
|
|
46
|
+
*/
|
|
47
|
+
function deepMerge(target, source) {
|
|
48
|
+
const result = { ...target }
|
|
49
|
+
for (const key of Object.keys(source)) {
|
|
50
|
+
const srcVal = source[key]
|
|
51
|
+
const tgtVal = result[key]
|
|
52
|
+
if (
|
|
53
|
+
srcVal !== null
|
|
54
|
+
&& typeof srcVal === 'object'
|
|
55
|
+
&& !Array.isArray(srcVal)
|
|
56
|
+
&& tgtVal !== null
|
|
57
|
+
&& typeof tgtVal === 'object'
|
|
58
|
+
&& !Array.isArray(tgtVal)
|
|
59
|
+
) {
|
|
60
|
+
result[key] = deepMerge(tgtVal, srcVal)
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
result[key] = srcVal
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return result
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Ensure `.vscode/settings.json` contains the ESLint flat-config settings.
|
|
71
|
+
* - If the file doesn't exist, create it with just the ESLint settings.
|
|
72
|
+
* - If it exists, deep-merge the ESLint settings without removing existing user settings.
|
|
73
|
+
*
|
|
74
|
+
* @param {string} projectRoot - Absolute path to the consuming project root.
|
|
75
|
+
*/
|
|
76
|
+
export function ensureVscodeSettings(projectRoot) {
|
|
77
|
+
const vscodeDir = join(projectRoot, '.vscode')
|
|
78
|
+
const settingsPath = join(vscodeDir, 'settings.json')
|
|
79
|
+
|
|
80
|
+
if (!existsSync(vscodeDir)) {
|
|
81
|
+
mkdirSync(vscodeDir, { recursive: true })
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let current = {}
|
|
85
|
+
if (existsSync(settingsPath)) {
|
|
86
|
+
try {
|
|
87
|
+
const raw = readFileSync(settingsPath, 'utf8')
|
|
88
|
+
current = JSON.parse(raw)
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// File exists but is not valid JSON – back it up and start fresh
|
|
92
|
+
const backupPath = `${settingsPath}.backup`
|
|
93
|
+
writeFileSync(backupPath, readFileSync(settingsPath, 'utf8'), 'utf8')
|
|
94
|
+
current = {}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const merged = deepMerge(current, VSCODE_ESLINT_SETTINGS)
|
|
99
|
+
writeFileSync(settingsPath, `${JSON.stringify(merged, null, 2)}\n`, 'utf8')
|
|
100
|
+
}
|