airier 0.0.9 → 0.1.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/AGENTS.md +315 -0
- package/LICENSE +1 -1
- package/README.md +42 -5
- package/eslint.config.example.js +3 -0
- package/eslint.config.js +4 -0
- package/index.js +6 -0
- package/modules/eslint_config.js +69 -0
- package/modules/{styleguide.cjs → styleguide.js} +3 -6
- package/package.json +31 -7
- package/.eslintrc.cjs +0 -7
- package/.eslintrc.onlystyles.example.js +0 -6
- package/.husky/pre-commit +0 -21
- package/.vscode/settings.json +0 -27
- package/index.cjs +0 -6
- package/modules/eslint_config.cjs +0 -50
package/AGENTS.md
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
# AI Coding Assistant Instructions
|
|
2
|
+
|
|
3
|
+
Write code that breathes. Think Ruby-like elegance meets modern js.
|
|
4
|
+
|
|
5
|
+
Important boundaries:
|
|
6
|
+
|
|
7
|
+
- You do not touch files specified in `.gitignore`
|
|
8
|
+
- You do not touch `.env` or `.env.*` files
|
|
9
|
+
- You do not touch dotfiles, pattern `.*`
|
|
10
|
+
|
|
11
|
+
==============================
|
|
12
|
+
|
|
13
|
+
## 1. Code Philosophy
|
|
14
|
+
|
|
15
|
+
**Code is written for human eyes**: Code is a description of the intent of a programmer, it must communicate the intent. For machines, the syntax and style is not relevant. Therefore, code style must be optimised for human eyes and mental models.
|
|
16
|
+
|
|
17
|
+
**More comments is better than less comments**: Reading code can clarify function but not intention. Comments are a reminder to self, or an explanation to coworkers.
|
|
18
|
+
|
|
19
|
+
**Readability Through Spacing**: Code needs room to breathe. Spacing makes structure visible at a glance.
|
|
20
|
+
|
|
21
|
+
**Remember**: Code is read far more than it's written. Make it beautiful, make it breathe, make it obvious.
|
|
22
|
+
|
|
23
|
+
==============================
|
|
24
|
+
|
|
25
|
+
## 2. Syntax preferences
|
|
26
|
+
|
|
27
|
+
Code should be elegant, not use superfluous characters, and have space to breathe. For example: do not use semicolons, add space in brackets. The linter will show you syntax preferences, to that end with every change learn the styling by:
|
|
28
|
+
|
|
29
|
+
1. save your changes and look at the syntax
|
|
30
|
+
2. run `npm run lint` and ignore the command output
|
|
31
|
+
3. look at how the linter changed the style, and mimic it in future responses.
|
|
32
|
+
|
|
33
|
+
==============================
|
|
34
|
+
|
|
35
|
+
## 3. Tooling preferences
|
|
36
|
+
|
|
37
|
+
### LLM agent context
|
|
38
|
+
|
|
39
|
+
Any LLM including you should always:
|
|
40
|
+
|
|
41
|
+
- Read the `AGENTS.md` file for instructions
|
|
42
|
+
- Check if `SPECIFICATION.md` exists, if so read it
|
|
43
|
+
- Check if `SPECIFICATION.*.md` patterned files exist, if so read them for context
|
|
44
|
+
- Check for all `*.md` files in the project root
|
|
45
|
+
|
|
46
|
+
### Node.js usage
|
|
47
|
+
|
|
48
|
+
- Use `nvm` for version management, with the latest LTS (24) in the `.nvmrc`
|
|
49
|
+
- Do not modify files in `node_modules/`
|
|
50
|
+
- Environment variables are stored in `.env` which is supported by node without dependencies
|
|
51
|
+
- Frontend code should use Vite for bundling
|
|
52
|
+
- Backend code should use Node.js
|
|
53
|
+
- Prefer javascript over typescript, including when setting up vite projects
|
|
54
|
+
|
|
55
|
+
### React usage
|
|
56
|
+
|
|
57
|
+
- Frontends should be built in react
|
|
58
|
+
- React should be used in frontend mode (no server components)
|
|
59
|
+
- Routing is done with `react-router` BrowserRouter
|
|
60
|
+
- State is put in the URL where possible using the `use-query-params` npm package
|
|
61
|
+
- State that is used in multiple places at once uses `zustand`
|
|
62
|
+
- Components follow a structure inspired by Atomic Design where they are split into:
|
|
63
|
+
- Atoms: stateless components
|
|
64
|
+
- Molecules: stateful components (may use Atoms)
|
|
65
|
+
- Pages: components rendered by the router
|
|
66
|
+
|
|
67
|
+
File structure in a react project:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
.
|
|
71
|
+
├── assets
|
|
72
|
+
├── package-lock.json
|
|
73
|
+
├── package.json
|
|
74
|
+
├── public
|
|
75
|
+
│ ├── assets
|
|
76
|
+
│ ├── favicon.ico
|
|
77
|
+
│ ├── logo192.png
|
|
78
|
+
│ ├── logo512.png
|
|
79
|
+
│ └── robots.txt
|
|
80
|
+
├── src
|
|
81
|
+
│ ├── App.jsx
|
|
82
|
+
│ ├── components
|
|
83
|
+
│ │ ├── atoms
|
|
84
|
+
│ │ ├── molecules
|
|
85
|
+
│ │ └── pages
|
|
86
|
+
│ ├── hooks
|
|
87
|
+
│ ├── index.css
|
|
88
|
+
│ ├── index.jsx
|
|
89
|
+
│ ├── modules
|
|
90
|
+
│ ├── routes
|
|
91
|
+
│ │ └── Routes.jsx
|
|
92
|
+
│ └── stores
|
|
93
|
+
└── vite.config.js
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Using Mentie Helpers
|
|
97
|
+
|
|
98
|
+
If `mentie` is installed, **always use its utilities**. Check `node_modules/mentie/index.js` for available exports.
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
import { log, multiline_trim, shuffle_array } from 'mentie'
|
|
102
|
+
|
|
103
|
+
log.info( `User logged in:`, user_id )
|
|
104
|
+
|
|
105
|
+
const query = multiline_trim( `
|
|
106
|
+
SELECT * FROM users
|
|
107
|
+
WHERE active = true
|
|
108
|
+
` )
|
|
109
|
+
|
|
110
|
+
const randomized = shuffle_array( items )
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
==============================
|
|
114
|
+
|
|
115
|
+
## 3. Code style preferences
|
|
116
|
+
|
|
117
|
+
### Always use template literals instead of strings
|
|
118
|
+
```js
|
|
119
|
+
// Use literals for regular strings
|
|
120
|
+
const name = `Ada Localace`
|
|
121
|
+
|
|
122
|
+
// Use templates for string manipulation too
|
|
123
|
+
const annotated_name = `${ name } ${ Math.random() }`
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
### snake_case for Everything
|
|
128
|
+
```js
|
|
129
|
+
const timeout_ms = 5_000
|
|
130
|
+
const user_name = 'John'
|
|
131
|
+
const fetch_user_data = async ( user_id ) => { }
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Use comments to describe intent
|
|
135
|
+
```js
|
|
136
|
+
import { abort_controller } from 'mentie'
|
|
137
|
+
|
|
138
|
+
// Load the users with a timeout to prevent hanging
|
|
139
|
+
const fetch_options = abort_controller( { timeout_ms: 10_000 } )
|
|
140
|
+
const { uids } = await fetch( 'https://...', fetch_options ).then( res => res.json() )
|
|
141
|
+
|
|
142
|
+
// Parallel fetch resulting data to optimise speed
|
|
143
|
+
const downstream_data = await Promise.all( uids.map( async uid => fetch( `https://...?uid=${ uid }` ) ) )
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
### Prioritise semantic clarity over optimisation
|
|
148
|
+
Don't reassign variables. Create new bindings for each transformation step.
|
|
149
|
+
```js
|
|
150
|
+
// Parse a dataset - each step is clear and traceable
|
|
151
|
+
const data = []
|
|
152
|
+
const filtered_data = data.filter( ( { relevant_number } ) => relevant_number > 1.5 )
|
|
153
|
+
const restructured_data = filtered_data.map( ( { base_value, second_value } ) => ( { composite_value: base_value * second_value } ) )
|
|
154
|
+
return restructured_data
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
### Lean towards onelining single statements
|
|
159
|
+
Single statements can be on one line. Multiple statements need blocks.
|
|
160
|
+
```js
|
|
161
|
+
// ✅ Single statement - oneline it
|
|
162
|
+
if( condition ) log.info( `Message` )
|
|
163
|
+
const filtered_data = data.filter( ( { relevant_property } ) => relevant_property )
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
### Functional Programming Over Loops
|
|
168
|
+
|
|
169
|
+
Prefer `.map()`, `.filter()`, `.reduce()`, `.find()`, `.some()`, `.every()` over `for`/`while` loops.
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
const active_users = users.filter( u => u.active )
|
|
173
|
+
const user_names = active_users.map( u => u.name )
|
|
174
|
+
const total_age = user_names.reduce( ( sum, age ) => sum + age, 0 )
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
### JSDoc for Exported Functions
|
|
179
|
+
|
|
180
|
+
**CRITICAL**: Every exported function MUST have JSDoc. Verify before finishing!
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
/**
|
|
184
|
+
* Fetches user data from the API
|
|
185
|
+
* @param {string} user_id - The ID of the user to fetch
|
|
186
|
+
* @returns {Promise<Object>} User data object
|
|
187
|
+
*/
|
|
188
|
+
export const fetch_user = async ( user_id ) => {
|
|
189
|
+
const response = await api.get( `/users/${ user_id }` )
|
|
190
|
+
return response.data
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Error Handling
|
|
195
|
+
|
|
196
|
+
Only at boundaries (user input, external APIs). Trust internal code. Remember `finally` for cleanup!
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
const fetch_user = async ( id ) => {
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
start_loading()
|
|
203
|
+
const response = await api.get( `/users/${ id }` )
|
|
204
|
+
return response.data
|
|
205
|
+
} catch( error ) {
|
|
206
|
+
throw new Error( `Failed to fetch user: ${ error.message }` )
|
|
207
|
+
} finally {
|
|
208
|
+
stop_loading()
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Complete example of well styled code
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
/**
|
|
217
|
+
* Fetches and processes active users from the API
|
|
218
|
+
* @param {Object} options
|
|
219
|
+
* @param {Array} options.user_ids - User ids to fetch
|
|
220
|
+
* @param {Number} options.limit - Limit the amount of users to fetch
|
|
221
|
+
* @returns {Promise<Array>} Processed user objects
|
|
222
|
+
*/
|
|
223
|
+
export async function fetch_and_process_users( { user_ids, limit=5 } = {} ) {
|
|
224
|
+
|
|
225
|
+
// Get users to ensure up to date data
|
|
226
|
+
const users = await api.get( `/users`, { user_ids, limit } )
|
|
227
|
+
|
|
228
|
+
// Keep only active users to prevent wasting time on inactive ones
|
|
229
|
+
const filtered_users = users.filter( ( { active } ) => active )
|
|
230
|
+
|
|
231
|
+
// Annotate users with value based on local conversion so we can show the user the computed values
|
|
232
|
+
const annotated_users = filtered_users.map( ( { score, user } ) => ( { score: score * local_conversion_value, ...user } ) )
|
|
233
|
+
|
|
234
|
+
// Return users with annotated data
|
|
235
|
+
return annotated_users
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
### React Specific styling
|
|
242
|
+
|
|
243
|
+
**Exception to snake_case**: React component names MUST be PascalCase (required by React/JSX).
|
|
244
|
+
|
|
245
|
+
```js
|
|
246
|
+
// ✅ Components are PascalCase
|
|
247
|
+
const UserProfile = ( { user_id } ) => { }
|
|
248
|
+
const DataTable = () => { }
|
|
249
|
+
|
|
250
|
+
// ✅ Everything else is snake_case
|
|
251
|
+
const user_name = `John`
|
|
252
|
+
const fetch_user_data = async ( user_id ) => { }
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**File naming**: Component files use PascalCase to match component name.
|
|
256
|
+
- `UserProfile.jsx` - Component files
|
|
257
|
+
- `fetch_user_data.js` - Utility files
|
|
258
|
+
|
|
259
|
+
**Event handlers**:
|
|
260
|
+
- Do not name things after the event (e.g. `on_click`) but name them actions (e.g. `save_user`)
|
|
261
|
+
|
|
262
|
+
**JSX spacing and structure**:
|
|
263
|
+
```js
|
|
264
|
+
// Styled and stateless sections use arrow functions or variables
|
|
265
|
+
const Header = styled.aside`
|
|
266
|
+
color: red;
|
|
267
|
+
`
|
|
268
|
+
|
|
269
|
+
// Use JSX comments to separate sections
|
|
270
|
+
export function UserProfile( { user_id, on_update } ) {
|
|
271
|
+
|
|
272
|
+
// Hooks at the top
|
|
273
|
+
const [ user_data, set_user_data ] = useState( null )
|
|
274
|
+
const [ is_loading, set_is_loading ] = useState( false )
|
|
275
|
+
|
|
276
|
+
// Effects after hooks
|
|
277
|
+
useEffect( () => {
|
|
278
|
+
fetch_user_data( user_id ).then( set_user_data )
|
|
279
|
+
}, [ user_id ] )
|
|
280
|
+
|
|
281
|
+
// Event handlers
|
|
282
|
+
const update_user = () => on_update( user_data )
|
|
283
|
+
|
|
284
|
+
// Conditional rendering
|
|
285
|
+
if( is_loading ) return <LoadingSpinner />
|
|
286
|
+
|
|
287
|
+
// Do not add () around returned jsx.
|
|
288
|
+
return <>
|
|
289
|
+
|
|
290
|
+
{ /* Profile header section */ }
|
|
291
|
+
<Header title={ user_data.name } />
|
|
292
|
+
|
|
293
|
+
{ /* Profile details */ }
|
|
294
|
+
<div className="profile">
|
|
295
|
+
{ user_data.details }
|
|
296
|
+
</div>
|
|
297
|
+
|
|
298
|
+
{ /* Actions */ }
|
|
299
|
+
<Button on_click={ update_user }>Save</Button>
|
|
300
|
+
|
|
301
|
+
</>
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Lists need keys
|
|
305
|
+
const user_list = users.map( ( user ) => <UserCard key={ user.id } user={ user } /> )
|
|
306
|
+
|
|
307
|
+
// Props always have spacing
|
|
308
|
+
<Component prop={ value } />
|
|
309
|
+
<div className="foo">{ children }</div>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
A shared set of standards and preferences, enforced through eslint and vscode. Priorities: minimalism, readability, documentation.
|
|
4
4
|
|
|
5
|
+
**Now updated for ESLint 9.x with flat config format and ESM support!**
|
|
6
|
+
|
|
5
7
|
## Quickstart
|
|
6
8
|
|
|
7
9
|
```shell
|
|
8
10
|
# Install dependencies
|
|
9
|
-
npm install -D airier
|
|
11
|
+
npm install -D airier husky
|
|
10
12
|
mkdir .vscode .husky || echo "Directories already exist"
|
|
11
13
|
|
|
12
14
|
# Create scripts
|
|
@@ -15,20 +17,55 @@ npm pkg set scripts.lint="eslint --fix src"
|
|
|
15
17
|
# Init husky
|
|
16
18
|
npx husky init
|
|
17
19
|
|
|
18
|
-
# Download files
|
|
19
|
-
curl https://raw.githubusercontent.com/actuallymentor/airier/main
|
|
20
|
+
# Download files (using new ESLint 9 flat config format)
|
|
21
|
+
curl https://raw.githubusercontent.com/actuallymentor/airier/main/eslint.config.example.js --output eslint.config.js
|
|
20
22
|
curl https://raw.githubusercontent.com/actuallymentor/airier/main/.vscode/settings.json --output .vscode/settings.json
|
|
21
23
|
curl https://raw.githubusercontent.com/actuallymentor/airier/main/.husky/pre-commit --output .husky/pre-commit
|
|
22
24
|
curl https://raw.githubusercontent.com/actuallymentor/airier/main/.babelrc --output .babelrc
|
|
25
|
+
curl https://raw.githubusercontent.com/actuallymentor/airier/main/AGENTS.md --output AGENTS.md
|
|
26
|
+
|
|
27
|
+
# Ensure .gitignore ignores all dotfiles by default
|
|
28
|
+
grep -q '^\.\*$' .gitignore || echo -e "\n# Dotfiles\n.*" >> .gitignore
|
|
23
29
|
|
|
24
30
|
# Add files to git
|
|
25
|
-
git add -f .
|
|
31
|
+
git add -f eslint.config.js .babelrc AGENTS.md .vscode/* .husky/*
|
|
26
32
|
|
|
27
33
|
# Make husky executable
|
|
28
34
|
chmod ug+x .husky/*
|
|
29
|
-
git add .husky/pre-commit
|
|
35
|
+
git add -f .husky/pre-commit
|
|
30
36
|
```
|
|
31
37
|
|
|
38
|
+
## ESLint 9 Migration
|
|
39
|
+
|
|
40
|
+
This package now uses ESLint 9.x with the new **flat config format** and **ESM-only**. If you're upgrading from an older version:
|
|
41
|
+
|
|
42
|
+
1. Remove your old `.eslintrc.*` files (they're no longer supported in ESLint 9)
|
|
43
|
+
2. Use `eslint.config.js` instead
|
|
44
|
+
3. Update your ESLint to version 9.39.2 or later
|
|
45
|
+
4. Ensure your project supports ESM (Node.js 20+)
|
|
46
|
+
|
|
47
|
+
### Usage
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
// eslint.config.js
|
|
51
|
+
import { eslint_config } from 'airier'
|
|
52
|
+
|
|
53
|
+
export default eslint_config
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## AI Assistant Instructions
|
|
57
|
+
|
|
58
|
+
This package includes an `AGENTS.md` file that instructs AI coding assistants (like Claude, GPT, Copilot) to follow the same minimalist, "airy" code style that the ESLint rules enforce.
|
|
59
|
+
|
|
60
|
+
When working with AI assistants, share this file with them to ensure they write code matching your style:
|
|
61
|
+
- No semicolons
|
|
62
|
+
- Spacing in brackets: `[ 1, 2, 3 ]`, `{ key: value }`, `func( args )`
|
|
63
|
+
- 4-space indentation
|
|
64
|
+
- Minimalist, Ruby-like aesthetics
|
|
65
|
+
- Modern ES modules only
|
|
66
|
+
|
|
67
|
+
The AI instructions complement the automated linting by teaching assistants *why* the code should look this way, not just enforcing it after the fact.
|
|
68
|
+
|
|
32
69
|
## Making changes
|
|
33
70
|
|
|
34
71
|
The relevant source files are in `modules/`. If you make a change, you can update the package by:
|
package/eslint.config.js
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Import required modules
|
|
2
|
+
import eslint from '@eslint/js'
|
|
3
|
+
import react from 'eslint-plugin-react'
|
|
4
|
+
import unusedImports from 'eslint-plugin-unused-imports'
|
|
5
|
+
import babelParser from '@babel/eslint-parser'
|
|
6
|
+
import globals from 'globals'
|
|
7
|
+
|
|
8
|
+
// Import the styleguide module
|
|
9
|
+
import styleguide from './styleguide.js'
|
|
10
|
+
|
|
11
|
+
// Export the flat config as an array
|
|
12
|
+
export default [
|
|
13
|
+
// Global ignores for build output and dependencies
|
|
14
|
+
{
|
|
15
|
+
ignores: [
|
|
16
|
+
'**/dist/**',
|
|
17
|
+
'**/build/**',
|
|
18
|
+
'**/node_modules/**',
|
|
19
|
+
'**/.next/**',
|
|
20
|
+
'**/coverage/**'
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
// Apply to all JavaScript and JSX files
|
|
24
|
+
{
|
|
25
|
+
files: [ '**/*.js', '**/*.jsx', '**/*.cjs', '**/*.mjs' ],
|
|
26
|
+
|
|
27
|
+
languageOptions: {
|
|
28
|
+
parser: babelParser,
|
|
29
|
+
parserOptions: {
|
|
30
|
+
ecmaVersion: 2020,
|
|
31
|
+
requireConfigFile: false,
|
|
32
|
+
babelOptions: {
|
|
33
|
+
presets: [ '@babel/preset-react' ]
|
|
34
|
+
},
|
|
35
|
+
ecmaFeatures: {
|
|
36
|
+
jsx: true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
globals: {
|
|
40
|
+
...globals.browser,
|
|
41
|
+
...globals.node,
|
|
42
|
+
...globals.mocha,
|
|
43
|
+
...globals.cypress
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
plugins: {
|
|
48
|
+
react,
|
|
49
|
+
'unused-imports': unusedImports
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
settings: {
|
|
53
|
+
react: {
|
|
54
|
+
version: '19'
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
rules: {
|
|
59
|
+
// ESLint recommended rules
|
|
60
|
+
...eslint.configs.recommended.rules,
|
|
61
|
+
|
|
62
|
+
// React recommended rules
|
|
63
|
+
...react.configs.recommended.rules,
|
|
64
|
+
|
|
65
|
+
// Custom styleguide rules
|
|
66
|
+
...styleguide
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// warn: we recomment this to change, but there are instances where you can choose to ignore it
|
|
4
4
|
// error: there is no reason for you to do this
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
export default {
|
|
7
7
|
|
|
8
8
|
/* ///////////////////////////////
|
|
9
9
|
// Built-in rules
|
|
@@ -15,9 +15,6 @@ module.exports = {
|
|
|
15
15
|
// Indentation setting
|
|
16
16
|
"indent": [ "warn", 4 ],
|
|
17
17
|
|
|
18
|
-
// Allow unnamed exports
|
|
19
|
-
"import/no-anonymous-default-export": 0,
|
|
20
|
-
|
|
21
18
|
// Prefer arrow callbacks
|
|
22
19
|
"prefer-arrow-callback": "warn",
|
|
23
20
|
|
|
@@ -56,7 +53,7 @@ module.exports = {
|
|
|
56
53
|
// Prefer the use of destructuring
|
|
57
54
|
"prefer-destructuring": "warn",
|
|
58
55
|
|
|
59
|
-
// Warn of unused variables, function
|
|
56
|
+
// Warn of unused variables, function arguments may have documentation value so are ignored
|
|
60
57
|
"no-unused-vars": [ "warn", { vars: 'all', args: 'none' } ],
|
|
61
58
|
|
|
62
59
|
// No use of "var"
|
|
@@ -93,4 +90,4 @@ module.exports = {
|
|
|
93
90
|
// /////////////////////////////*/
|
|
94
91
|
"unused-imports/no-unused-imports": "warn",
|
|
95
92
|
|
|
96
|
-
}
|
|
93
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "airier",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Opinionated Eslint and VSCode style guide",
|
|
5
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
6
7
|
"scripts": {
|
|
7
8
|
"lint": "eslint --fix ."
|
|
8
9
|
},
|
|
@@ -16,12 +17,35 @@
|
|
|
16
17
|
"url": "https://github.com/actuallymentor/airier/issues"
|
|
17
18
|
},
|
|
18
19
|
"homepage": "https://github.com/actuallymentor/airier#readme",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20.0.0"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"eslint",
|
|
25
|
+
"eslint-config",
|
|
26
|
+
"style-guide",
|
|
27
|
+
"code-style",
|
|
28
|
+
"javascript",
|
|
29
|
+
"react",
|
|
30
|
+
"minimalist",
|
|
31
|
+
"airy"
|
|
32
|
+
],
|
|
33
|
+
"files": [
|
|
34
|
+
"index.js",
|
|
35
|
+
"modules/",
|
|
36
|
+
".babelrc",
|
|
37
|
+
"eslint.config.js",
|
|
38
|
+
"eslint.config.example.js",
|
|
39
|
+
"AGENTS.md"
|
|
40
|
+
],
|
|
19
41
|
"peerDependencies": {
|
|
20
|
-
"eslint-
|
|
21
|
-
"@babel/eslint-parser": "^7.24.1",
|
|
42
|
+
"@babel/eslint-parser": "^7.28.5",
|
|
22
43
|
"@babel/preset-react": "^7.24.1",
|
|
23
|
-
"eslint": "^
|
|
24
|
-
"eslint
|
|
44
|
+
"@eslint/js": "^9.39.2",
|
|
45
|
+
"eslint": "^9.39.2",
|
|
46
|
+
"eslint-plugin-react": "^7.37.5",
|
|
47
|
+
"eslint-plugin-unused-imports": "^4.3.0",
|
|
48
|
+
"globals": "^15.0.0",
|
|
25
49
|
"husky": "^9.0.11"
|
|
26
50
|
}
|
|
27
|
-
}
|
|
51
|
+
}
|
package/.eslintrc.cjs
DELETED
package/.husky/pre-commit
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env sh
|
|
2
|
-
. "$(dirname -- "$0")/_/husky.sh"
|
|
3
|
-
|
|
4
|
-
echo "\n🤖 [ precommit hook ] linting before committing..."
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# If errors, make it clear they cannot commit
|
|
8
|
-
if ! lint_outcome=$( npm run lint ); then
|
|
9
|
-
echo "🚨 [ precommit hook ] lint encountered blocking issues, fix them before committing\n"
|
|
10
|
-
echo "$lint_outcome"
|
|
11
|
-
exit 1
|
|
12
|
-
fi
|
|
13
|
-
|
|
14
|
-
# If warnings, suggest they fix them
|
|
15
|
-
if echo $lint_outcome | grep -q "warning"; then
|
|
16
|
-
echo "⚠️ [ precommit hook ] lint encountered warnings, consider fixing them before pushing\n"
|
|
17
|
-
echo "$lint_outcome"
|
|
18
|
-
exit 0
|
|
19
|
-
fi
|
|
20
|
-
|
|
21
|
-
echo "✅ [ precommit hook ] lint encountered no blocking issues\n"
|
package/.vscode/settings.json
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"i18n-ally.localesPaths": [
|
|
3
|
-
"public/locales"
|
|
4
|
-
],
|
|
5
|
-
"i18n-ally.keystyle": "nested",
|
|
6
|
-
"eslint.validate": [
|
|
7
|
-
"javascript",
|
|
8
|
-
"javascriptreact",
|
|
9
|
-
"typescript",
|
|
10
|
-
"typescriptreact"
|
|
11
|
-
],
|
|
12
|
-
"editor.codeActionsOnSave": {
|
|
13
|
-
"source.fixAll.eslint": "explicit"
|
|
14
|
-
},
|
|
15
|
-
"editor.renderWhitespace": "all",
|
|
16
|
-
"editor.formatOnSave": true,
|
|
17
|
-
"eslint.format.enable": true,
|
|
18
|
-
"eslint.run": "onType",
|
|
19
|
-
"explorer.fileNesting.enabled": true,
|
|
20
|
-
"explorer.fileNesting.patterns": {
|
|
21
|
-
"vite.config.js": "*.js,.babelrc,.nvmrc,index.html,.gitignore",
|
|
22
|
-
".env": ".env*,.*.json",
|
|
23
|
-
"firebase.json": "fire*,.fire*",
|
|
24
|
-
"package.json": "package-lock.json, yarn.lock, pnpm-lock.yaml,.eslint*,config.*,.npm*,.nvm*,.ncu*",
|
|
25
|
-
"README.md": "*.md,LICENSE",
|
|
26
|
-
}
|
|
27
|
-
}
|
package/index.cjs
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
// Import the styleguide module using ES Module syntax
|
|
2
|
-
const styleguide = require( './styleguide.cjs' )
|
|
3
|
-
|
|
4
|
-
// Export the configuration object using `export default`
|
|
5
|
-
module.exports = {
|
|
6
|
-
|
|
7
|
-
// Recommended features
|
|
8
|
-
"extends": [ "eslint:recommended", "plugin:react/recommended" ],
|
|
9
|
-
|
|
10
|
-
// Plugins
|
|
11
|
-
plugins: [ 'unused-imports' ],
|
|
12
|
-
|
|
13
|
-
// React settings
|
|
14
|
-
"settings": {
|
|
15
|
-
"react": { "version": "detect" }
|
|
16
|
-
},
|
|
17
|
-
|
|
18
|
-
// Parser features
|
|
19
|
-
parser: "@babel/eslint-parser",
|
|
20
|
-
parserOptions: {
|
|
21
|
-
requireConfigFile: false,
|
|
22
|
-
ecmaFeatures: {
|
|
23
|
-
jsx: true
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
// Rules
|
|
28
|
-
rules: {
|
|
29
|
-
// Import styleguide
|
|
30
|
-
...styleguide
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
// What environment to run in
|
|
34
|
-
env: {
|
|
35
|
-
node: true,
|
|
36
|
-
browser: true,
|
|
37
|
-
mocha: true,
|
|
38
|
-
jest: false,
|
|
39
|
-
es6: true
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
// What global variables should be assumed to exist
|
|
43
|
-
globals: {
|
|
44
|
-
context: true,
|
|
45
|
-
cy: true,
|
|
46
|
-
it: true,
|
|
47
|
-
Cypress: true,
|
|
48
|
-
expect: true
|
|
49
|
-
}
|
|
50
|
-
}
|