@quentinhsu/biome-config 0.2.0 → 0.3.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.
Files changed (33) hide show
  1. package/README.md +44 -0
  2. package/package.json +7 -4
  3. package/dist/build.mjs +0 -387
  4. package/dist/index.jsonc +0 -152
  5. package/dist/index.mjs +0 -357
  6. package/dist/next.jsonc +0 -169
  7. package/dist/nuxt.jsonc +0 -224
  8. package/dist/react.jsonc +0 -167
  9. package/dist/types/scripts/generate-biome-types.d.ts +0 -1
  10. package/dist/types/scripts/generate-changelog.d.ts +0 -6
  11. package/dist/types/src/build.d.ts +0 -1
  12. package/dist/types/src/constants/biome.d.ts +0 -1
  13. package/dist/types/src/generated/biome/index.d.ts +0 -11
  14. package/dist/types/src/generated/biome/no-compare-neg-zero-configuration.d.ts +0 -986
  15. package/dist/types/src/generated/biome/no-global-object-calls-options.d.ts +0 -306
  16. package/dist/types/src/generated/biome/no-nested-ternary-options.d.ts +0 -292
  17. package/dist/types/src/generated/biome/no-octal-escape-options.d.ts +0 -1138
  18. package/dist/types/src/generated/biome/no-shadow-configuration.d.ts +0 -241
  19. package/dist/types/src/generated/biome/nursery.d.ts +0 -1023
  20. package/dist/types/src/generated/biome/rule-with-no-duplicate-custom-properties-options.d.ts +0 -1095
  21. package/dist/types/src/generated/biome/rule-with-no-useless-catch-options.d.ts +0 -1430
  22. package/dist/types/src/generated/biome/rule-with-use-image-size-options.d.ts +0 -1339
  23. package/dist/types/src/generated/biome/schema.d.ts +0 -291
  24. package/dist/types/src/generated/biome/use-valid-lang-configuration.d.ts +0 -163
  25. package/dist/types/src/index.d.ts +0 -15
  26. package/dist/types/src/presets/next.d.ts +0 -1
  27. package/dist/types/src/presets/nuxt.d.ts +0 -1
  28. package/dist/types/src/presets/react.d.ts +0 -1
  29. package/dist/types/src/presets/vue.d.ts +0 -1
  30. package/dist/types/src/source/index.d.ts +0 -2
  31. package/dist/types/src/types.d.ts +0 -1
  32. package/dist/types/src/utils/merge.d.ts +0 -2
  33. package/dist/vue.jsonc +0 -176
package/README.md CHANGED
@@ -112,6 +112,50 @@ The base configuration includes:
112
112
  - **VCS**: Git integration with `.gitignore` support
113
113
  - **Files**: Ignores common output directories (`build`, `dist`, `.next`)
114
114
 
115
+ ### VS Code Integration
116
+
117
+ To integrate Biome with VS Code, install the [Biome extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome) and configure it in `.vscode/settings.json`:
118
+
119
+ <details>
120
+ <summary><b>.vscode/settings.json</b></summary>
121
+
122
+ ```json
123
+ {
124
+ "editor.formatOnSave": true,
125
+ "editor.defaultFormatter": "biomejs.biome",
126
+ "[javascript]": {
127
+ "editor.defaultFormatter": "biomejs.biome"
128
+ },
129
+ "[javascriptreact]": {
130
+ "editor.defaultFormatter": "biomejs.biome"
131
+ },
132
+ "[typescript]": {
133
+ "editor.defaultFormatter": "biomejs.biome"
134
+ },
135
+ "[typescriptreact]": {
136
+ "editor.defaultFormatter": "biomejs.biome"
137
+ },
138
+ "[json]": {
139
+ "editor.defaultFormatter": "biomejs.biome"
140
+ },
141
+ "[jsonc]": {
142
+ "editor.defaultFormatter": "biomejs.biome"
143
+ },
144
+ "editor.codeActionsOnSave": {
145
+ "source.fixAll.biome": "explicit",
146
+ "source.organizeImports.biome": "explicit",
147
+ "source.action.useSortedKeys.biome": "explicit"
148
+ }
149
+ }
150
+ ```
151
+
152
+ This configuration:
153
+ - Enables automatic formatting on save
154
+ - Sets Biome as the default formatter for JavaScript, TypeScript, and JSON files
155
+ - Automatically runs Biome's fix and import organization on save
156
+
157
+ </details>
158
+
115
159
  ### Running Biome
116
160
 
117
161
  Once configured, you can use Biome commands:
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@quentinhsu/biome-config",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "author": "QuentinHsu",
5
+ "license": "MIT",
5
6
  "repository": {
6
7
  "type": "git",
7
8
  "url": "git+https://github.com/QuentinHsu/biome-config.git"
@@ -21,9 +22,9 @@
21
22
  },
22
23
  "scripts": {
23
24
  "generate:types": "tsx scripts/generate-biome-types.ts",
24
- "generate:changelog": "tsx scripts/generate-changelog.ts",
25
25
  "prebuild": "pnpm run generate:types",
26
26
  "build": "rslib build && node dist/build.mjs",
27
+ "dev": "nodemon --exec tsx scripts/build-presets.ts",
27
28
  "lint": "npx biome check ."
28
29
  },
29
30
  "keywords": [
@@ -37,10 +38,12 @@
37
38
  "access": "public"
38
39
  },
39
40
  "devDependencies": {
40
- "@biomejs/biome": "^2.3.0",
41
- "@rslib/core": "^0.16.1",
41
+ "@biomejs/biome": "2.3.2",
42
+ "@quentinhsu/biome-config": "workspace:*",
43
+ "@rslib/core": "^0.17.0",
42
44
  "@types/node": "^24.9.1",
43
45
  "json-schema-to-typescript": "^15.0.4",
46
+ "nodemon": "^3.1.10",
44
47
  "tsx": "^4.16.2",
45
48
  "typescript": "^5.6.3"
46
49
  }
package/dist/build.mjs DELETED
@@ -1,387 +0,0 @@
1
- import { mkdir, writeFile } from "node:fs/promises";
2
- import { dirname, join } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- const isPlainObject = (value)=>null !== value && 'object' == typeof value && !Array.isArray(value);
5
- const mergeArrays = (a, b)=>{
6
- const result = [
7
- ...a
8
- ];
9
- for (const item of b)if (!result.some((existing)=>deepEqual(existing, item))) result.push(item);
10
- return result;
11
- };
12
- const deepEqual = (a, b)=>{
13
- if (a === b) return true;
14
- if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((item, index)=>deepEqual(item, b[index]));
15
- if (isPlainObject(a) && isPlainObject(b)) {
16
- const keysA = Object.keys(a);
17
- const keysB = Object.keys(b);
18
- return keysA.length === keysB.length && keysA.every((key)=>deepEqual(a[key], b[key]));
19
- }
20
- return false;
21
- };
22
- const deepMerge = (target, source)=>{
23
- for (const [key, value] of Object.entries(source)){
24
- const current = target[key];
25
- if (Array.isArray(value)) {
26
- if (Array.isArray(current)) target[key] = mergeArrays(current, value);
27
- else target[key] = [
28
- ...value
29
- ];
30
- continue;
31
- }
32
- if (isPlainObject(value)) {
33
- const nextTarget = isPlainObject(current) ? {
34
- ...current
35
- } : {};
36
- target[key] = deepMerge(nextTarget, value);
37
- continue;
38
- }
39
- target[key] = value;
40
- }
41
- return target;
42
- };
43
- const mergeConfigs = (...configs)=>{
44
- const merged = configs.reduce((accumulator, config)=>deepMerge(accumulator, config), {});
45
- return merged;
46
- };
47
- const BIOME_SCHEMA_URL = 'https://biomejs.dev/schemas/2.2.6/schema.json';
48
- const indexConfig = {
49
- $schema: BIOME_SCHEMA_URL,
50
- root: true,
51
- vcs: {
52
- enabled: true,
53
- clientKind: 'git',
54
- useIgnoreFile: true,
55
- defaultBranch: 'main'
56
- },
57
- files: {
58
- ignoreUnknown: true,
59
- includes: [
60
- '**',
61
- '!**/build',
62
- '!**/dist',
63
- '!**/.next'
64
- ]
65
- },
66
- formatter: {
67
- enabled: true,
68
- indentStyle: 'space',
69
- lineWidth: 140,
70
- formatWithErrors: true
71
- },
72
- assist: {
73
- actions: {
74
- source: {
75
- organizeImports: {
76
- level: 'on',
77
- options: {
78
- groups: [
79
- [
80
- ':NODE:',
81
- ':BUN:',
82
- ':PACKAGE_WITH_PROTOCOL:',
83
- ':PACKAGE:'
84
- ],
85
- ':BLANK_LINE:',
86
- ':ALIAS:',
87
- ':BLANK_LINE:',
88
- ':PATH:'
89
- ]
90
- }
91
- },
92
- useSortedAttributes: {
93
- level: 'on',
94
- options: {
95
- sortOrder: 'natural'
96
- }
97
- }
98
- }
99
- }
100
- },
101
- linter: {
102
- enabled: true,
103
- rules: {
104
- recommended: true,
105
- complexity: {
106
- noUselessStringConcat: 'error',
107
- noUselessUndefinedInitialization: 'error',
108
- noVoid: 'error',
109
- useDateNow: 'error'
110
- },
111
- correctness: {
112
- noConstantMathMinMaxClamp: 'error',
113
- noUndeclaredVariables: 'error',
114
- noUnusedImports: 'error',
115
- noUnusedFunctionParameters: 'error',
116
- noUnusedPrivateClassMembers: 'error',
117
- useExhaustiveDependencies: {
118
- level: 'error',
119
- options: {
120
- reportUnnecessaryDependencies: false
121
- }
122
- },
123
- noUnusedVariables: 'error'
124
- },
125
- style: {
126
- noParameterProperties: 'error',
127
- noYodaExpression: 'error',
128
- useConsistentBuiltinInstantiation: 'error',
129
- useFragmentSyntax: 'error',
130
- useImportType: {
131
- level: 'error',
132
- fix: 'safe',
133
- options: {
134
- style: 'separatedType'
135
- }
136
- },
137
- useSelfClosingElements: {
138
- level: 'error',
139
- fix: 'safe',
140
- options: {}
141
- },
142
- useShorthandAssign: 'error',
143
- useArrayLiterals: 'error'
144
- },
145
- nursery: {
146
- useSortedClasses: {
147
- level: 'error',
148
- fix: 'safe',
149
- options: {
150
- functions: [
151
- 'clsx',
152
- 'cn'
153
- ]
154
- }
155
- }
156
- },
157
- suspicious: {
158
- useAwait: 'error',
159
- noEvolvingTypes: 'error'
160
- }
161
- }
162
- },
163
- javascript: {
164
- formatter: {
165
- quoteStyle: 'single',
166
- jsxQuoteStyle: 'single',
167
- arrowParentheses: 'asNeeded',
168
- trailingCommas: 'all'
169
- }
170
- },
171
- overrides: [
172
- {
173
- includes: [
174
- '**/*.jsx',
175
- '**/*.tsx'
176
- ],
177
- linter: {
178
- rules: {
179
- style: {
180
- noParameterAssign: 'error'
181
- }
182
- }
183
- }
184
- },
185
- {
186
- includes: [
187
- '**/*.ts',
188
- '**/*.tsx'
189
- ],
190
- linter: {
191
- rules: {
192
- correctness: {
193
- noUnusedVariables: 'off'
194
- }
195
- }
196
- }
197
- }
198
- ]
199
- };
200
- const reactOverlay = {
201
- files: {
202
- includes: [
203
- '!**/.storybook'
204
- ]
205
- },
206
- javascript: {
207
- jsxRuntime: 'reactClassic'
208
- },
209
- linter: {
210
- rules: {
211
- style: {
212
- useFragmentSyntax: 'error'
213
- }
214
- }
215
- },
216
- overrides: [
217
- {
218
- includes: [
219
- '**/__tests__/**',
220
- '**/*.{test,spec}.{ts,tsx,js,jsx}'
221
- ],
222
- linter: {
223
- rules: {
224
- correctness: {
225
- noUnusedVariables: 'off'
226
- }
227
- }
228
- }
229
- }
230
- ]
231
- };
232
- const reactConfig = mergeConfigs(indexConfig, reactOverlay);
233
- const nextOverlay = {
234
- files: {
235
- includes: [
236
- '!**/.next',
237
- '!**/.vercel',
238
- '!**/out'
239
- ]
240
- },
241
- javascript: {
242
- jsxRuntime: 'transparent'
243
- },
244
- linter: {
245
- rules: {
246
- correctness: {
247
- useExhaustiveDependencies: {
248
- level: 'error',
249
- options: {
250
- reportUnnecessaryDependencies: true
251
- }
252
- }
253
- }
254
- }
255
- }
256
- };
257
- const nextConfig = mergeConfigs(reactConfig, nextOverlay);
258
- const vueOverlay = {
259
- files: {
260
- includes: [
261
- '!**/.vitepress',
262
- '!**/.output'
263
- ]
264
- },
265
- javascript: {
266
- parser: {
267
- jsxEverywhere: false
268
- }
269
- },
270
- html: {
271
- formatter: {
272
- indentScriptAndStyle: true,
273
- selfCloseVoidElements: 'always'
274
- }
275
- },
276
- overrides: [
277
- {
278
- includes: [
279
- '**/*.vue'
280
- ],
281
- formatter: {
282
- lineWidth: 120
283
- },
284
- javascript: {
285
- formatter: {
286
- quoteStyle: 'single'
287
- }
288
- }
289
- }
290
- ]
291
- };
292
- const vueConfig = mergeConfigs(indexConfig, vueOverlay);
293
- const nuxtOverlay = {
294
- files: {
295
- includes: [
296
- '!**/.nuxt',
297
- '!**/.nitro',
298
- '!**/.output'
299
- ]
300
- },
301
- javascript: {
302
- globals: [
303
- 'defineNuxtConfig',
304
- 'defineAppConfig',
305
- 'defineNuxtPlugin',
306
- 'defineNuxtRouteMiddleware',
307
- 'defineNuxtServerPlugin',
308
- 'defineNitroPlugin',
309
- 'defineEventHandler',
310
- 'defineLazyEventHandler',
311
- 'definePayloadPlugin',
312
- 'defineRouteRules',
313
- 'definePageMeta',
314
- 'useRuntimeConfig',
315
- 'useNuxtApp',
316
- 'useAsyncData',
317
- 'useLazyAsyncData',
318
- 'useFetch',
319
- 'useLazyFetch',
320
- 'useState',
321
- 'useCookie',
322
- 'useHead',
323
- 'useSeoMeta',
324
- 'useError',
325
- 'clearError',
326
- 'showError',
327
- 'navigateTo',
328
- 'abortNavigation',
329
- 'refreshNuxtData',
330
- 'onNuxtReady',
331
- 'useRouter',
332
- 'useRoute',
333
- 'useRequestEvent',
334
- 'useRequestHeaders'
335
- ]
336
- },
337
- overrides: [
338
- {
339
- includes: [
340
- '**/*.ts'
341
- ],
342
- linter: {
343
- rules: {
344
- correctness: {
345
- noUndeclaredVariables: 'error'
346
- }
347
- }
348
- }
349
- }
350
- ]
351
- };
352
- const nuxtConfig = mergeConfigs(vueConfig, nuxtOverlay);
353
- const allPresets = Object.freeze({
354
- index: indexConfig,
355
- react: reactConfig,
356
- next: nextConfig,
357
- vue: vueConfig,
358
- nuxt: nuxtConfig
359
- });
360
- const currentDir = dirname(fileURLToPath(import.meta.url));
361
- const outputDir = currentDir;
362
- const serialize = (config)=>`${JSON.stringify(config, null, 2)}\n`;
363
- async function ensureDir(path) {
364
- await mkdir(path, {
365
- recursive: true
366
- });
367
- }
368
- async function buildJsonPresets() {
369
- await ensureDir(outputDir);
370
- const tasks = Object.entries(allPresets).map(async ([name, config])=>{
371
- const filePath = join(outputDir, `${name}.jsonc`);
372
- const data = serialize(config);
373
- await writeFile(filePath, data, 'utf8');
374
- return filePath;
375
- });
376
- const writtenFiles = await Promise.all(tasks);
377
- return writtenFiles;
378
- }
379
- (async ()=>{
380
- try {
381
- const files = await buildJsonPresets();
382
- console.log(`Generated presets: ${files.join(', ')}`);
383
- } catch (error) {
384
- console.error('Failed to generate Biome presets', error);
385
- process.exitCode = 1;
386
- }
387
- })();
package/dist/index.jsonc DELETED
@@ -1,152 +0,0 @@
1
- {
2
- "$schema": "https://biomejs.dev/schemas/2.2.6/schema.json",
3
- "root": true,
4
- "vcs": {
5
- "enabled": true,
6
- "clientKind": "git",
7
- "useIgnoreFile": true,
8
- "defaultBranch": "main"
9
- },
10
- "files": {
11
- "ignoreUnknown": true,
12
- "includes": [
13
- "**",
14
- "!**/build",
15
- "!**/dist",
16
- "!**/.next"
17
- ]
18
- },
19
- "formatter": {
20
- "enabled": true,
21
- "indentStyle": "space",
22
- "lineWidth": 140,
23
- "formatWithErrors": true
24
- },
25
- "assist": {
26
- "actions": {
27
- "source": {
28
- "organizeImports": {
29
- "level": "on",
30
- "options": {
31
- "groups": [
32
- [
33
- ":NODE:",
34
- ":BUN:",
35
- ":PACKAGE_WITH_PROTOCOL:",
36
- ":PACKAGE:"
37
- ],
38
- ":BLANK_LINE:",
39
- ":ALIAS:",
40
- ":BLANK_LINE:",
41
- ":PATH:"
42
- ]
43
- }
44
- },
45
- "useSortedAttributes": {
46
- "level": "on",
47
- "options": {
48
- "sortOrder": "natural"
49
- }
50
- }
51
- }
52
- }
53
- },
54
- "linter": {
55
- "enabled": true,
56
- "rules": {
57
- "recommended": true,
58
- "complexity": {
59
- "noUselessStringConcat": "error",
60
- "noUselessUndefinedInitialization": "error",
61
- "noVoid": "error",
62
- "useDateNow": "error"
63
- },
64
- "correctness": {
65
- "noConstantMathMinMaxClamp": "error",
66
- "noUndeclaredVariables": "error",
67
- "noUnusedImports": "error",
68
- "noUnusedFunctionParameters": "error",
69
- "noUnusedPrivateClassMembers": "error",
70
- "useExhaustiveDependencies": {
71
- "level": "error",
72
- "options": {
73
- "reportUnnecessaryDependencies": false
74
- }
75
- },
76
- "noUnusedVariables": "error"
77
- },
78
- "style": {
79
- "noParameterProperties": "error",
80
- "noYodaExpression": "error",
81
- "useConsistentBuiltinInstantiation": "error",
82
- "useFragmentSyntax": "error",
83
- "useImportType": {
84
- "level": "error",
85
- "fix": "safe",
86
- "options": {
87
- "style": "separatedType"
88
- }
89
- },
90
- "useSelfClosingElements": {
91
- "level": "error",
92
- "fix": "safe",
93
- "options": {}
94
- },
95
- "useShorthandAssign": "error",
96
- "useArrayLiterals": "error"
97
- },
98
- "nursery": {
99
- "useSortedClasses": {
100
- "level": "error",
101
- "fix": "safe",
102
- "options": {
103
- "functions": [
104
- "clsx",
105
- "cn"
106
- ]
107
- }
108
- }
109
- },
110
- "suspicious": {
111
- "useAwait": "error",
112
- "noEvolvingTypes": "error"
113
- }
114
- }
115
- },
116
- "javascript": {
117
- "formatter": {
118
- "quoteStyle": "single",
119
- "jsxQuoteStyle": "single",
120
- "arrowParentheses": "asNeeded",
121
- "trailingCommas": "all"
122
- }
123
- },
124
- "overrides": [
125
- {
126
- "includes": [
127
- "**/*.jsx",
128
- "**/*.tsx"
129
- ],
130
- "linter": {
131
- "rules": {
132
- "style": {
133
- "noParameterAssign": "error"
134
- }
135
- }
136
- }
137
- },
138
- {
139
- "includes": [
140
- "**/*.ts",
141
- "**/*.tsx"
142
- ],
143
- "linter": {
144
- "rules": {
145
- "correctness": {
146
- "noUnusedVariables": "off"
147
- }
148
- }
149
- }
150
- }
151
- ]
152
- }