@dimensional-innovations/tool-config 2.0.0 â 3.0.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 +94 -183
- package/bin/lib/formatting.js +103 -0
- package/bin/lib/handlers/stylelint.js +2 -2
- package/bin/lib/package-manager.js +87 -0
- package/bin/lib/ui.js +149 -21
- package/bin/lib/uninstall.js +199 -0
- package/bin/setup-tool-config.js +199 -21
- package/package.json +6 -4
- package/src/tools/stylelint/README.md +9 -9
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@dimensional-innovations/tool-config)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://nodejs.org/)
|
|
8
|
-
[](./tests/)
|
|
9
9
|
|
|
10
10
|
**One package. Five tools. Zero configuration.**
|
|
11
11
|
|
|
@@ -35,11 +35,13 @@ npm install --save-dev @dimensional-innovations/tool-config
|
|
|
35
35
|
|
|
36
36
|
- đ¯ **Zero Configuration** - Auto-detects your framework, environment, and TypeScript
|
|
37
37
|
- đ§° **Multi-Tool Support** - ESLint, Prettier, Stylelint, TypeScript, semantic-release in one package
|
|
38
|
-
- âī¸ **
|
|
38
|
+
- âī¸ **9 Frameworks** - React, Vue, Svelte, Solid, Astro, Angular, Vanilla JS, Node.js, Electron
|
|
39
39
|
- đĻ **All-In-One** - All plugins and parsers included as dependencies
|
|
40
40
|
- đ§ **Customizable** - Override any setting while keeping smart defaults
|
|
41
41
|
- đ **Modern** - ESLint 9+ flat config, TypeScript with tsgo support (10x faster)
|
|
42
|
-
-
|
|
42
|
+
- đ **Uninstall Support** - Clean removal with safety checks for modified files
|
|
43
|
+
- đŦ **Smart Scripts** - Auto-generated `check-all` script runs tools in optimal order
|
|
44
|
+
- â
**Battle-Tested** - 556 tests with 96% coverage
|
|
43
45
|
|
|
44
46
|
## Quick Start
|
|
45
47
|
|
|
@@ -118,14 +120,17 @@ That's it! The configs will automatically detect your framework and TypeScript s
|
|
|
118
120
|
"lint:fix": "eslint --fix .",
|
|
119
121
|
"prettier": "prettier --check .",
|
|
120
122
|
"prettier:fix": "prettier --write .",
|
|
121
|
-
"style": "stylelint '**/*.css'",
|
|
122
|
-
"style:fix": "stylelint '**/*.css' --fix",
|
|
123
|
+
"style": "stylelint '**/*.css' --allow-empty-input",
|
|
124
|
+
"style:fix": "stylelint '**/*.css' --fix --allow-empty-input",
|
|
123
125
|
"typecheck": "tsc --noEmit",
|
|
124
|
-
"typecheck:watch": "tsc --noEmit --watch"
|
|
126
|
+
"typecheck:watch": "tsc --noEmit --watch",
|
|
127
|
+
"check-all": "npm run prettier && npm run style && npm run lint && npm run typecheck"
|
|
125
128
|
}
|
|
126
129
|
}
|
|
127
130
|
```
|
|
128
131
|
|
|
132
|
+
**Tip:** The CLI automatically adds a `check-all` script when you setup multiple tools. This runs all validation tools in the optimal order: formatting â styles â linting â type checking.
|
|
133
|
+
|
|
129
134
|
## Supported Frameworks
|
|
130
135
|
|
|
131
136
|
| Framework | ESLint | Prettier | Stylelint | TypeScript | Auto-Detect |
|
|
@@ -138,6 +143,7 @@ That's it! The configs will automatically detect your framework and TypeScript s
|
|
|
138
143
|
| Angular | â
| â
| â
| â
decorators | â
|
|
|
139
144
|
| Vanilla | â
| â
| â
| â
browser | â
|
|
|
140
145
|
| Node.js | â
| â
| N/A | â
NodeNext | â
|
|
|
146
|
+
| Electron | â
| â
| N/A | â
multi-config | â
|
|
|
141
147
|
|
|
142
148
|
**Meta-frameworks**: Next.js (â React), Nuxt (â Vue), SvelteKit (â Svelte)
|
|
143
149
|
|
|
@@ -174,23 +180,11 @@ await createConfig('eslint', {
|
|
|
174
180
|
})
|
|
175
181
|
```
|
|
176
182
|
|
|
177
|
-
**
|
|
183
|
+
**Custom rules:**
|
|
178
184
|
|
|
179
185
|
```javascript
|
|
180
186
|
export default await createConfig('eslint', {
|
|
181
|
-
rules: {
|
|
182
|
-
'no-console': 'off',
|
|
183
|
-
'react/prop-types': 'warn'
|
|
184
|
-
}
|
|
185
|
-
})
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
**Example - Explicit Framework:**
|
|
189
|
-
|
|
190
|
-
```javascript
|
|
191
|
-
export default await createConfig('eslint', {
|
|
192
|
-
framework: 'vue',
|
|
193
|
-
typescript: true
|
|
187
|
+
rules: { 'no-console': 'off' }
|
|
194
188
|
})
|
|
195
189
|
```
|
|
196
190
|
|
|
@@ -199,20 +193,9 @@ export default await createConfig('eslint', {
|
|
|
199
193
|
```javascript
|
|
200
194
|
createConfig('prettier', {
|
|
201
195
|
framework: 'auto',
|
|
202
|
-
// Override any Prettier option
|
|
196
|
+
printWidth: 100, // Override any Prettier option
|
|
203
197
|
semi: false,
|
|
204
|
-
singleQuote: true
|
|
205
|
-
printWidth: 100
|
|
206
|
-
})
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
**Example - Custom Settings:**
|
|
210
|
-
|
|
211
|
-
```javascript
|
|
212
|
-
export default createConfig('prettier', {
|
|
213
|
-
printWidth: 120,
|
|
214
|
-
tabWidth: 4,
|
|
215
|
-
trailingComma: 'all'
|
|
198
|
+
singleQuote: true
|
|
216
199
|
})
|
|
217
200
|
```
|
|
218
201
|
|
|
@@ -221,57 +204,29 @@ export default createConfig('prettier', {
|
|
|
221
204
|
```javascript
|
|
222
205
|
createConfig('stylelint', {
|
|
223
206
|
framework: 'auto',
|
|
224
|
-
cssType: 'auto', // 'auto' | 'scss' | 'css'
|
|
207
|
+
cssType: 'auto', // 'auto' | 'scss' | 'css'
|
|
208
|
+
cssType: { preprocessor: 'scss', tailwind: true }, // Or object
|
|
225
209
|
rules: {} // Custom rule overrides
|
|
226
210
|
})
|
|
227
211
|
```
|
|
228
212
|
|
|
229
|
-
**Example - SCSS + Tailwind:**
|
|
230
|
-
|
|
231
|
-
```javascript
|
|
232
|
-
export default createConfig('stylelint', {
|
|
233
|
-
cssType: {
|
|
234
|
-
preprocessor: 'scss',
|
|
235
|
-
tailwind: true
|
|
236
|
-
}
|
|
237
|
-
})
|
|
238
|
-
```
|
|
239
|
-
|
|
240
213
|
### TypeScript Options
|
|
241
214
|
|
|
242
215
|
```javascript
|
|
243
216
|
await createConfig('typescript', {
|
|
244
217
|
framework: 'auto', // Auto-detect or specify framework
|
|
245
218
|
environment: 'auto', // 'auto' | 'browser' | 'node' | 'universal'
|
|
246
|
-
checker: 'auto', // 'auto' | 'modern' (tsgo) | 'legacy' (tsc
|
|
219
|
+
checker: 'auto', // 'auto' | 'modern' (tsgo) | 'legacy' (tsc)
|
|
247
220
|
strict: true, // Enable strict type checking
|
|
248
|
-
compilerOptions: {} // Custom TypeScript compiler options
|
|
249
|
-
})
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
**Example - React with Custom Options:**
|
|
253
|
-
|
|
254
|
-
```javascript
|
|
255
|
-
export default await createConfig('typescript', {
|
|
256
|
-
framework: 'react',
|
|
257
221
|
compilerOptions: {
|
|
222
|
+
// Custom compiler options
|
|
258
223
|
baseUrl: '.',
|
|
259
|
-
paths: {
|
|
260
|
-
'@/*': ['src/*']
|
|
261
|
-
}
|
|
224
|
+
paths: { '@/*': ['src/*'] }
|
|
262
225
|
}
|
|
263
226
|
})
|
|
264
227
|
```
|
|
265
228
|
|
|
266
|
-
**
|
|
267
|
-
|
|
268
|
-
```javascript
|
|
269
|
-
export default await createConfig('typescript', {
|
|
270
|
-
checker: 'modern' // Forces tsgo when installed
|
|
271
|
-
})
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
**tsgo Support:** Install `@typescript/native-preview` for 10x faster type checking. The package automatically detects and uses tsgo when available.
|
|
229
|
+
**tsgo Support:** Install `@typescript/native-preview` for 10x faster type checking. Auto-detected or set `checker: 'modern'` to force it.
|
|
275
230
|
|
|
276
231
|
### semantic-release Options
|
|
277
232
|
|
|
@@ -282,15 +237,6 @@ createConfig('semantic-release', {
|
|
|
282
237
|
})
|
|
283
238
|
```
|
|
284
239
|
|
|
285
|
-
**Example - Library Release:**
|
|
286
|
-
|
|
287
|
-
```javascript
|
|
288
|
-
export default createConfig('semantic-release', {
|
|
289
|
-
preset: 'library',
|
|
290
|
-
gitProvider: 'github'
|
|
291
|
-
})
|
|
292
|
-
```
|
|
293
|
-
|
|
294
240
|
## Framework-Specific Guides
|
|
295
241
|
|
|
296
242
|
### React
|
|
@@ -419,22 +365,68 @@ npx @dimensional-innovations/tool-config
|
|
|
419
365
|
- Choose which tools to configure
|
|
420
366
|
- Auto-detects framework and TypeScript
|
|
421
367
|
- Creates config files automatically
|
|
422
|
-
- Adds npm scripts to package.json
|
|
423
|
-
-
|
|
368
|
+
- Adds npm scripts to package.json (including `check-all` for multiple tools)
|
|
369
|
+
- Automated CI/CD pipeline setup
|
|
370
|
+
- **Uninstall support** - Clean removal of configs and scripts
|
|
424
371
|
- Supports dry-run mode
|
|
425
372
|
|
|
426
|
-
**Options:**
|
|
373
|
+
**Setup Options:**
|
|
427
374
|
|
|
428
375
|
```bash
|
|
376
|
+
# Interactive mode
|
|
377
|
+
npx @dimensional-innovations/tool-config # Choose tools interactively
|
|
378
|
+
|
|
379
|
+
# Single tool setup
|
|
429
380
|
npx @dimensional-innovations/tool-config eslint # Setup ESLint only
|
|
430
|
-
npx @dimensional-innovations/tool-config
|
|
431
|
-
npx @dimensional-innovations/tool-config
|
|
381
|
+
npx @dimensional-innovations/tool-config prettier # Setup Prettier only
|
|
382
|
+
npx @dimensional-innovations/tool-config stylelint # Setup Stylelint only
|
|
383
|
+
|
|
384
|
+
# Setup all tools
|
|
385
|
+
npx @dimensional-innovations/tool-config --all # Setup all tools at once
|
|
386
|
+
|
|
387
|
+
# CI/CD setup
|
|
432
388
|
npx @dimensional-innovations/tool-config --ci gitlab # Setup GitLab CI/CD
|
|
433
389
|
npx @dimensional-innovations/tool-config --ci github # Setup GitHub Actions
|
|
434
390
|
npx @dimensional-innovations/tool-config --setup-ci # Interactive CI setup
|
|
391
|
+
|
|
392
|
+
# Preview mode
|
|
393
|
+
npx @dimensional-innovations/tool-config --dry-run # Preview without creating files
|
|
394
|
+
|
|
395
|
+
# Help
|
|
435
396
|
npx @dimensional-innovations/tool-config --help # Show all options
|
|
436
397
|
```
|
|
437
398
|
|
|
399
|
+
**Uninstall Options:**
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
# Interactive uninstall
|
|
403
|
+
npx @dimensional-innovations/tool-config --uninstall # Choose which tools to remove
|
|
404
|
+
|
|
405
|
+
# Uninstall specific tool
|
|
406
|
+
npx @dimensional-innovations/tool-config --uninstall eslint
|
|
407
|
+
|
|
408
|
+
# Uninstall all detected tools
|
|
409
|
+
npx @dimensional-innovations/tool-config --uninstall --all
|
|
410
|
+
|
|
411
|
+
# Remove CI/CD configuration
|
|
412
|
+
npx @dimensional-innovations/tool-config --uninstall --ci
|
|
413
|
+
|
|
414
|
+
# Preview uninstall
|
|
415
|
+
npx @dimensional-innovations/tool-config --uninstall --dry-run
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**Safety Features:**
|
|
419
|
+
|
|
420
|
+
The uninstall command includes safety features to protect your customizations:
|
|
421
|
+
|
|
422
|
+
- Only removes files that match the original generated templates
|
|
423
|
+
- Skips modified configuration files (warns you instead)
|
|
424
|
+
- Only removes auto-generated package.json scripts
|
|
425
|
+
- Preserves custom scripts with the same names
|
|
426
|
+
- Supports dry-run to preview what will be removed
|
|
427
|
+
- Cleans up empty directories (e.g., `.github/workflows`)
|
|
428
|
+
- Idempotent - safe to run multiple times
|
|
429
|
+
|
|
438
430
|
**CI/CD Integration:**
|
|
439
431
|
|
|
440
432
|
When you select `semantic-release` in interactive mode, the CLI will automatically prompt you to setup CI/CD for automated releases. Or use the `--ci` flag to setup CI/CD directly:
|
|
@@ -535,64 +527,43 @@ See the [`examples/`](./examples/) directory for complete working examples:
|
|
|
535
527
|
- [Node Backend](./examples/node-backend/) - Express, TypeScript
|
|
536
528
|
- [Vanilla JS](./examples/vanilla-js/) - Pure JavaScript, no framework
|
|
537
529
|
|
|
538
|
-
Each example includes all
|
|
530
|
+
Each example includes all 5 tool configurations and npm scripts.
|
|
539
531
|
|
|
540
532
|
## Advanced Usage
|
|
541
533
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
Use different configs per workspace:
|
|
534
|
+
**Monorepo Support:**
|
|
545
535
|
|
|
546
536
|
```javascript
|
|
547
537
|
// apps/frontend/eslint.config.js
|
|
548
|
-
export default await createConfig('eslint', {
|
|
549
|
-
framework: 'react',
|
|
550
|
-
typescript: true
|
|
551
|
-
})
|
|
538
|
+
export default await createConfig('eslint', { framework: 'react' })
|
|
552
539
|
|
|
553
540
|
// apps/backend/eslint.config.js
|
|
554
|
-
export default await createConfig('eslint', {
|
|
555
|
-
framework: 'node',
|
|
556
|
-
environment: 'node'
|
|
557
|
-
})
|
|
541
|
+
export default await createConfig('eslint', { framework: 'node' })
|
|
558
542
|
```
|
|
559
543
|
|
|
560
|
-
|
|
544
|
+
**Custom Ignore Patterns:**
|
|
561
545
|
|
|
562
546
|
```javascript
|
|
563
547
|
export default await createConfig('eslint', {
|
|
564
|
-
ignore: ['dist/**', '
|
|
548
|
+
ignore: ['dist/**', '**/*.generated.ts']
|
|
565
549
|
})
|
|
566
550
|
```
|
|
567
551
|
|
|
568
|
-
|
|
552
|
+
**Environment-Specific Rules:**
|
|
569
553
|
|
|
570
554
|
```javascript
|
|
571
|
-
const isDev = process.env.NODE_ENV === 'development'
|
|
572
|
-
|
|
573
555
|
export default await createConfig('eslint', {
|
|
574
556
|
rules: {
|
|
575
|
-
'no-console':
|
|
576
|
-
'no-debugger': isDev ? 'warn' : 'error'
|
|
557
|
+
'no-console': process.env.NODE_ENV === 'development' ? 'off' : 'error'
|
|
577
558
|
}
|
|
578
559
|
})
|
|
579
560
|
```
|
|
580
561
|
|
|
581
|
-
|
|
562
|
+
**Combining with Other Configs:**
|
|
582
563
|
|
|
583
564
|
```javascript
|
|
584
|
-
import { createConfig } from '@dimensional-innovations/tool-config'
|
|
585
|
-
import customRules from './custom-rules.js'
|
|
586
|
-
|
|
587
565
|
const baseConfig = await createConfig('eslint')
|
|
588
|
-
|
|
589
|
-
export default [
|
|
590
|
-
...baseConfig,
|
|
591
|
-
{
|
|
592
|
-
files: ['**/*.js'],
|
|
593
|
-
rules: customRules
|
|
594
|
-
}
|
|
595
|
-
]
|
|
566
|
+
export default [...baseConfig, { files: ['**/*.js'], rules: customRules }]
|
|
596
567
|
```
|
|
597
568
|
|
|
598
569
|
## Ignoring Files
|
|
@@ -647,8 +618,7 @@ export default createConfig('stylelint', {
|
|
|
647
618
|
|
|
648
619
|
**Prettier** - Edit `.prettierignore` file:
|
|
649
620
|
|
|
650
|
-
```
|
|
651
|
-
# Custom ignores
|
|
621
|
+
```text
|
|
652
622
|
generated/
|
|
653
623
|
legacy/
|
|
654
624
|
```
|
|
@@ -670,77 +640,20 @@ npx prettier --check . --debug-check
|
|
|
670
640
|
|
|
671
641
|
## Troubleshooting
|
|
672
642
|
|
|
673
|
-
|
|
643
|
+
**ESLint not detecting framework:** Ensure framework is in `package.json` dependencies, or explicitly set `framework: 'react'`.
|
|
674
644
|
|
|
675
|
-
|
|
645
|
+
**TypeScript parsing errors:** Install TypeScript: `npm install --save-dev typescript`
|
|
676
646
|
|
|
677
|
-
|
|
678
|
-
2. **Stylelint**: Ignore patterns are applied automatically â
|
|
679
|
-
3. **Prettier**: Check that `.prettierignore` was created. If not, re-run config creation or manually create the file.
|
|
680
|
-
|
|
681
|
-
**Solution**: If `.prettierignore` is missing, it will be auto-created next time you use the config. Or create it manually:
|
|
647
|
+
**Prettier plugin not found:** Install required peer dependency:
|
|
682
648
|
|
|
683
649
|
```bash
|
|
684
|
-
|
|
685
|
-
|
|
650
|
+
npm install --save-dev prettier-plugin-svelte # Svelte
|
|
651
|
+
npm install --save-dev prettier-plugin-astro # Astro
|
|
686
652
|
```
|
|
687
653
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
Ensure your `package.json` includes the framework dependency:
|
|
654
|
+
**Stylelint not linting .vue files:** Update script: `"style": "stylelint '**/*.css' '**/*.vue' --allow-empty-input"`
|
|
691
655
|
|
|
692
|
-
|
|
693
|
-
{
|
|
694
|
-
"dependencies": {
|
|
695
|
-
"react": "^18.0.0"
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
```
|
|
699
|
-
|
|
700
|
-
Or explicitly specify:
|
|
701
|
-
|
|
702
|
-
```javascript
|
|
703
|
-
export default await createConfig('eslint', {
|
|
704
|
-
framework: 'react'
|
|
705
|
-
})
|
|
706
|
-
```
|
|
707
|
-
|
|
708
|
-
### TypeScript Parsing Errors
|
|
709
|
-
|
|
710
|
-
Make sure `typescript` is installed:
|
|
711
|
-
|
|
712
|
-
```bash
|
|
713
|
-
npm install --save-dev typescript
|
|
714
|
-
```
|
|
715
|
-
|
|
716
|
-
### Prettier Plugin Not Found
|
|
717
|
-
|
|
718
|
-
Install the required peer dependency:
|
|
719
|
-
|
|
720
|
-
```bash
|
|
721
|
-
npm install --save-dev prettier-plugin-svelte # For Svelte
|
|
722
|
-
npm install --save-dev prettier-plugin-astro # For Astro
|
|
723
|
-
```
|
|
724
|
-
|
|
725
|
-
### Stylelint Not Linting .vue Files
|
|
726
|
-
|
|
727
|
-
Update your npm script to include `.vue` files:
|
|
728
|
-
|
|
729
|
-
```json
|
|
730
|
-
{
|
|
731
|
-
"scripts": {
|
|
732
|
-
"style": "stylelint '**/*.css' '**/*.vue'"
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
```
|
|
736
|
-
|
|
737
|
-
### Config Not Updating After Framework Change
|
|
738
|
-
|
|
739
|
-
Delete `node_modules/.cache` and restart your editor:
|
|
740
|
-
|
|
741
|
-
```bash
|
|
742
|
-
rm -rf node_modules/.cache
|
|
743
|
-
```
|
|
656
|
+
**Config not updating:** Delete `node_modules/.cache` and restart editor.
|
|
744
657
|
|
|
745
658
|
## Requirements
|
|
746
659
|
|
|
@@ -757,20 +670,18 @@ This package follows these principles:
|
|
|
757
670
|
- **Fail Loudly** - Errors for critical issues, warnings for quality improvements
|
|
758
671
|
- **Framework Agnostic** - No opinions about which framework you use
|
|
759
672
|
- **Modern Standards** - Uses latest tooling and ESLint flat config
|
|
760
|
-
- **Comprehensive Coverage** -
|
|
673
|
+
- **Comprehensive Coverage** - 96% test coverage, battle-tested in production
|
|
761
674
|
|
|
762
675
|
## Contributing
|
|
763
676
|
|
|
764
|
-
Contributions welcome!
|
|
765
|
-
|
|
766
|
-
**To add a new framework:**
|
|
677
|
+
Contributions welcome! To add a new framework:
|
|
767
678
|
|
|
768
679
|
1. Add detection logic in `src/detectors.js`
|
|
769
680
|
2. Create presets in `src/tools/{tool}/presets/frameworks/`
|
|
770
681
|
3. Add tests with 100% coverage
|
|
771
682
|
4. Update documentation
|
|
772
683
|
|
|
773
|
-
See [
|
|
684
|
+
See [CLAUDE.md](./CLAUDE.md) for architecture details.
|
|
774
685
|
|
|
775
686
|
## License
|
|
776
687
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatting utilities for CLI output
|
|
3
|
+
* Standardized box drawing with consistent width
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import pc from 'picocolors'
|
|
7
|
+
|
|
8
|
+
const BOX_WIDTH = 70 // Standard width for all boxes
|
|
9
|
+
|
|
10
|
+
export const BOX = {
|
|
11
|
+
topLeft: 'â',
|
|
12
|
+
topRight: 'â',
|
|
13
|
+
bottomLeft: 'â',
|
|
14
|
+
bottomRight: 'â',
|
|
15
|
+
vertical: 'â',
|
|
16
|
+
horizontal: 'â',
|
|
17
|
+
separator: 'â',
|
|
18
|
+
width: BOX_WIDTH
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Create a box with standard width (70 chars)
|
|
23
|
+
* @param {string[]} lines - Array of content lines
|
|
24
|
+
* @param {string} title - Optional title for top border
|
|
25
|
+
* @returns {string} Formatted box
|
|
26
|
+
*/
|
|
27
|
+
export function createBox(lines, title = '') {
|
|
28
|
+
const width = BOX.width
|
|
29
|
+
const contentWidth = width - 4 // Remove: â + space + space + â
|
|
30
|
+
|
|
31
|
+
// Create top border
|
|
32
|
+
let top
|
|
33
|
+
if (title) {
|
|
34
|
+
const titlePart = `â ${title} `
|
|
35
|
+
const remaining = width - 2 - titlePart.length // -2 for corners
|
|
36
|
+
top = BOX.topLeft + titlePart + BOX.horizontal.repeat(remaining) + BOX.topRight
|
|
37
|
+
} else {
|
|
38
|
+
top = BOX.topLeft + BOX.horizontal.repeat(width - 2) + BOX.topRight
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Create content lines - pad each to exact width
|
|
42
|
+
const content = lines.map(line => {
|
|
43
|
+
const padded = line.slice(0, contentWidth).padEnd(contentWidth)
|
|
44
|
+
return `${BOX.vertical} ${padded} ${BOX.vertical}`
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
// Create bottom border
|
|
48
|
+
const bottom = BOX.bottomLeft + BOX.horizontal.repeat(width - 2) + BOX.bottomRight
|
|
49
|
+
|
|
50
|
+
return [top, ...content, bottom].join('\n')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Create a separator line
|
|
55
|
+
* @returns {string} Separator line
|
|
56
|
+
*/
|
|
57
|
+
export function createSeparator() {
|
|
58
|
+
return BOX.separator.repeat(BOX.width)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create a simple indented list
|
|
63
|
+
* @param {string[]} items - Array of items
|
|
64
|
+
* @param {string} bullet - Bullet character (default: 'âĸ')
|
|
65
|
+
* @returns {string} Formatted list
|
|
66
|
+
*/
|
|
67
|
+
export function createList(items, bullet = 'âĸ') {
|
|
68
|
+
return items.map(item => ` ${bullet} ${item}`).join('\n')
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Create a progress indicator
|
|
73
|
+
* @param {number} current - Current step
|
|
74
|
+
* @param {number} total - Total steps
|
|
75
|
+
* @param {string} label - Label for this step
|
|
76
|
+
* @returns {string} Progress line
|
|
77
|
+
*/
|
|
78
|
+
export function createProgress(current, total, label) {
|
|
79
|
+
return ` [${current}/${total}] ${label}`
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Color symbols for CLI output
|
|
84
|
+
*/
|
|
85
|
+
export const SYMBOLS = {
|
|
86
|
+
success: pc.green('â'),
|
|
87
|
+
warning: pc.yellow('â '),
|
|
88
|
+
error: pc.red('â'),
|
|
89
|
+
info: pc.blue('âš')
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Color helper functions
|
|
94
|
+
*/
|
|
95
|
+
export const colors = {
|
|
96
|
+
success: pc.green,
|
|
97
|
+
warning: pc.yellow,
|
|
98
|
+
error: pc.red,
|
|
99
|
+
info: pc.blue,
|
|
100
|
+
dim: pc.dim,
|
|
101
|
+
bold: pc.bold,
|
|
102
|
+
cyan: pc.cyan
|
|
103
|
+
}
|
|
@@ -51,8 +51,8 @@ export function getScripts(detected) {
|
|
|
51
51
|
extensions.length === 1 ? `**/*.${extensions[0]}` : `**/*.{${extensions.join(',')}}`
|
|
52
52
|
|
|
53
53
|
return {
|
|
54
|
-
style: `stylelint "${pattern}"`,
|
|
55
|
-
'style:fix': `stylelint "${pattern}" --fix`
|
|
54
|
+
style: `stylelint "${pattern}" --allow-empty-input`,
|
|
55
|
+
'style:fix': `stylelint "${pattern}" --fix --allow-empty-input`
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -112,3 +112,90 @@ export function updatePackageJsonScripts(tools, getScriptsFn, context) {
|
|
|
112
112
|
console.error(' â Failed to update package.json:', error.message)
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Remove scripts from package.json for tools
|
|
118
|
+
* @param {string[]} tools - Array of tool names to remove scripts for
|
|
119
|
+
* @param {Function} getScriptsFn - Function that returns scripts for a tool: (tool, detected) => object
|
|
120
|
+
* @param {Object} context - Context object with {detected, cwd, dryRun}
|
|
121
|
+
*/
|
|
122
|
+
export function removePackageJsonScripts(tools, getScriptsFn, context) {
|
|
123
|
+
const { detected, cwd, dryRun = false } = context
|
|
124
|
+
const packageJsonPath = join(cwd, 'package.json')
|
|
125
|
+
|
|
126
|
+
if (!existsSync(packageJsonPath)) {
|
|
127
|
+
console.log(' âšī¸ No package.json found - skipping script removal')
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'))
|
|
133
|
+
|
|
134
|
+
if (!packageJson.scripts) {
|
|
135
|
+
console.log(' âšī¸ No scripts section in package.json')
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const scriptsToRemove = []
|
|
140
|
+
|
|
141
|
+
// Collect script names to remove based on tools
|
|
142
|
+
for (const tool of tools) {
|
|
143
|
+
const toolScripts = getScriptsFn(tool, detected)
|
|
144
|
+
for (const scriptName of Object.keys(toolScripts)) {
|
|
145
|
+
const expectedCommand = toolScripts[scriptName]
|
|
146
|
+
const actualCommand = packageJson.scripts[scriptName]
|
|
147
|
+
|
|
148
|
+
// Only remove if the script exists and matches our expected command
|
|
149
|
+
if (actualCommand === expectedCommand) {
|
|
150
|
+
scriptsToRemove.push(scriptName)
|
|
151
|
+
} else if (actualCommand) {
|
|
152
|
+
console.log(` â ī¸ Script "${scriptName}" has been modified - skipping for safety`)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Handle check-all script separately
|
|
158
|
+
const checkAllScript = packageJson.scripts['check-all']
|
|
159
|
+
if (checkAllScript) {
|
|
160
|
+
// Only remove if it's auto-generated (follows npm run X && npm run Y pattern)
|
|
161
|
+
const isAutoGenerated =
|
|
162
|
+
checkAllScript.startsWith('npm run') && checkAllScript.includes(' && npm run')
|
|
163
|
+
|
|
164
|
+
if (isAutoGenerated) {
|
|
165
|
+
scriptsToRemove.push('check-all')
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (scriptsToRemove.length === 0) {
|
|
170
|
+
console.log(' âšī¸ No scripts to remove from package.json')
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (dryRun) {
|
|
175
|
+
console.log(' đ Would remove scripts from package.json:')
|
|
176
|
+
for (const name of scriptsToRemove) {
|
|
177
|
+
console.log(` - ${name}`)
|
|
178
|
+
}
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Remove scripts
|
|
183
|
+
for (const scriptName of scriptsToRemove) {
|
|
184
|
+
delete packageJson.scripts[scriptName]
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Remove scripts section if empty
|
|
188
|
+
if (Object.keys(packageJson.scripts).length === 0) {
|
|
189
|
+
delete packageJson.scripts
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8')
|
|
193
|
+
|
|
194
|
+
console.log(' â
Removed scripts from package.json:')
|
|
195
|
+
for (const name of scriptsToRemove) {
|
|
196
|
+
console.log(` - ${name}`)
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error(' â Failed to update package.json:', error.message)
|
|
200
|
+
}
|
|
201
|
+
}
|