scss-variable-extractor 1.6.4 → 1.6.5

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 CHANGED
@@ -1,778 +1,1015 @@
1
- # SCSS Variable Extractor
2
-
3
- A standalone, reusable CLI tool that analyzes Angular project SCSS files, identifies repeated hardcoded values, extracts them into SCSS variables, and refactors the codebase to use those variables.
4
-
5
- ## Features
6
-
7
- ✨ **Automated Variable Extraction** - Identifies and extracts repeated hardcoded values
8
- 🎯 **Angular 15 & Material 15 Ready** - Follows best practices with `@use` imports
9
- 🔍 **Smart Pattern Recognition** - Detects colors, spacing, fonts, shadows, and more
10
- 📊 **Multiple Report Formats** - Table, JSON, or Markdown output
11
- 🛡️ **Safe Refactoring** - Preserves existing variables and avoids unsafe replacements
12
- ⚙️ **Highly Configurable** - Customize via `.scssextractrc.json`
13
- 🔧 **Modernization Tools** - Removes `::ng-deep` and `!important` anti-patterns
14
- 🚀 **Global Scope Scanning** - Analyze any folder in your project
15
- 📐 **Angular.json Integration** - Automatically detects project structure and settings
16
- 🔄 **Bootstrap to Material Migration** - Converts Bootstrap classes to Angular Material MDC components and utilities
17
-
18
- ## Installation
19
-
20
- ### From Git Repository
21
-
22
- ```bash
23
- npm install git+https://github.com/lpaszkiewicz/scss-variable-extractor.git
24
- ```
25
-
26
- ### As a Git Submodule
27
-
28
- ```bash
29
- git submodule add https://github.com/lpaszkiewicz/scss-variable-extractor.git tools/scss-extract
30
- cd tools/scss-extract
31
- npm install
32
- ```
33
-
34
- ### Local Development
35
-
36
- ```bash
37
- git clone https://github.com/lpaszkiewicz/scss-variable-extractor.git
38
- cd scss-variable-extractor
39
- npm install
40
- ```
41
-
42
- ## Quick Start
43
-
44
- > **💡 Tip:** If you have an `angular.json` file, you can omit the source path - the tool will auto-detect your project structure!
45
-
46
- ### 1. Analyze (Dry Run)
47
-
48
- See what values would be extracted without modifying any files:
49
-
50
- ```bash
51
- # With angular.json (auto-detects project)
52
- npx scss-extract analyze
53
-
54
- # Or specify path manually
55
- npx scss-extract analyze ./apps/subapp/src --threshold 2
56
- ```
57
-
58
- ### 2. Generate Variables File
59
-
60
- Create a `_variables.scss` file with extracted variables:
61
-
62
- ```bash
63
- # With angular.json
64
- npx scss-extract generate
65
-
66
- # Or specify paths manually
67
- npx scss-extract generate ./apps/subapp/src --output ./libs/styles/_variables.scss
68
- ```
69
-
70
- ### 3. Full Refactoring
71
-
72
- Generate variables file AND replace hardcoded values in all SCSS files:
73
-
74
- ```bash
75
- npx scss-extract refactor ./apps/subapp/src --output ./libs/styles/_variables.scss
76
- ```
77
-
78
- ### 4. Modernize Code (Remove Anti-Patterns)
79
-
80
- Remove `::ng-deep` and `!important` following Angular Material v15+ best practices:
81
-
82
- ```bash
83
- # Preview changes first
84
- npx scss-extract modernize ./src --dry-run
85
-
86
- # Apply modernization
87
- npx scss-extract modernize ./src
88
- ```
89
-
90
- ## CLI Commands
91
-
92
- ### `analyze` - Dry-run Analysis
93
-
94
- Scans SCSS files and reports repeated values without modifying anything.
95
-
96
- ```bash
97
- npx scss-extract analyze <src> [options]
98
- ```
99
-
100
- **Arguments:**
101
- - `<src>` - Source directory to scan (required)
102
-
103
- **Options:**
104
- - `--threshold <number>` - Minimum repeat count (default: `2`)
105
- - `--format <format>` - Report format: `table`, `json`, `markdown` (default: `table`)
106
- - `--config <path>` - Path to custom config file
107
-
108
- **Example:**
109
- ```bash
110
- npx scss-extract analyze ./src --threshold 3 --format markdown
111
- ```
112
-
113
- ### `generate` - Generate Variables File
114
-
115
- Creates a `_variables.scss` file with extracted variables.
116
-
117
- ```bash
118
- npx scss-extract generate <src> [options]
119
- ```
120
-
121
- **Arguments:**
122
- - `<src>` - Source directory to scan (required)
123
-
124
- **Options:**
125
- - `--output <path>` - Output path for variables file (default: `./libs/styles/_variables.scss`)
126
- - `--threshold <number>` - Minimum repeat count
127
- - `--config <path>` - Path to custom config file
128
-
129
- **Example:**
130
- ```bash
131
- npx scss-extract generate ./apps/myapp/src --output ./styles/_variables.scss
132
- ```
133
-
134
- ### `refactor` - Full Extraction + Replacement
135
-
136
- Generates variables file AND refactors SCSS files to use variables.
137
-
138
- ```bash
139
- npx scss-extract refactor <src> [options]
140
- ```
141
-
142
- **Arguments:**
143
- - `<src>` - Source directory to scan (required)
144
-
145
- **Options:**
146
- - `--output <path>` - Output path for variables file
147
- - `--threshold <number>` - Minimum repeat count
148
- - `--config <path>` - Path to custom config file
149
-
150
- **Example:**
151
- ```bash
152
- npx scss-extract refactor --src ./apps/subapp/src --output ./libs/styles/_variables.scss
153
- ```
154
-
155
- ### `analyze-patterns` - Analyze Angular Anti-Patterns
156
-
157
- Scans SCSS files for Angular Material v15+ anti-patterns like `::ng-deep` and `!important` usage.
158
-
159
- ```bash
160
- npx scss-extract analyze-patterns <src> [options]
161
- ```
162
-
163
- **Arguments:**
164
- - `<src>` - Source directory to scan (required)
165
-
166
- **Options:**
167
- - `--format <format>` - Report format: `table`, `json`, `markdown` (default: `table`)
168
- - `--config <path>` - Path to custom config file
169
-
170
- **Example:**
171
- ```bash
172
- npx scss-extract analyze-patterns ./src --format table
173
- ```
174
-
175
- ### `modernize` - Refactor to Angular Material v15+ Best Practices
176
-
177
- Automatically refactors SCSS files by removing `::ng-deep`, `/deep/`, `>>>`, and `!important` declarations, following Angular Material v15+ best practices.
178
-
179
- ```bash
180
- npx scss-extract modernize <src> [options]
181
- ```
182
-
183
- **Arguments:**
184
- - `<src>` - Source directory to scan (required)
185
-
186
- **Options:**
187
- - `--global-styles <path>` - Path to global styles file (default: `./src/styles.scss`)
188
- - `--no-ng-deep` - Skip ::ng-deep refactoring
189
- - `--no-important` - Skip !important refactoring
190
- - `--dry-run` - Preview changes without modifying files
191
- - `--config <path>` - Path to custom config file
192
-
193
- **Example:**
194
- ```bash
195
- # Preview changes
196
- npx scss-extract modernize ./src --dry-run
197
-
198
- # Apply changes
199
- npx scss-extract modernize ./src --global-styles ./src/styles.scss
200
- ```
201
-
202
- **What it does:**
203
- - ✅ Removes `::ng-deep`, `/deep/`, and `>>>` (deprecated shadow-piercing selectors)
204
- - Removes `!important` declarations (suggests increasing specificity instead)
205
- - ✅ Extracts styles that were using `::ng-deep` to global styles file
206
- - Provides warnings and suggestions for manual review
207
-
208
- **Angular Material v15+ Best Practices:**
209
- - Use CSS custom properties for theming
210
- - Use Angular Material theme mixins for component customization
211
- - Place global styles in `styles.scss` instead of using `::ng-deep`
212
- - Increase selector specificity instead of using `!important`
213
- - Consider `ViewEncapsulation.None` for components that need global styles
214
-
215
- ## Angular.json Integration
216
-
217
- The tool can automatically read your `angular.json` file to detect project structure and apply the correct schematics for style refactoring.
218
-
219
- ### Auto-detection
220
-
221
- By default, all commands will look for `angular.json` in the current directory and use it to configure:
222
- - Source directory (`sourceRoot`)
223
- - Output path for variables (based on global styles)
224
- - Style preprocessor (scss, sass, less, css)
225
- - Component prefix
226
- - Ignore patterns (`.angular`, `dist`, etc.)
227
-
228
- ### Usage
229
-
230
- **Without angular.json (manual configuration):**
231
- ```bash
232
- scss-extract analyze ./apps/myapp/src
233
- ```
234
-
235
- **With angular.json (auto-configured):**
236
- ```bash
237
- # Uses default project from angular.json
238
- scss-extract analyze
239
-
240
- # Use specific project
241
- scss-extract analyze --project myapp
242
-
243
- # Specify angular.json location
244
- scss-extract analyze --angular-json ./path/to/angular.json
245
- ```
246
-
247
- **Disable angular.json integration:**
248
- ```bash
249
- scss-extract analyze ./src --no-angular
250
- ```
251
-
252
- ### All Commands Support Angular.json
253
-
254
- Every command supports these options:
255
- - `--angular-json <path>` - Path to angular.json file
256
- - `--project <name>` - Specify which project to use
257
- - `--no-angular` - Disable angular.json integration
258
-
259
- **Examples:**
260
- ```bash
261
- # Analyze with angular.json
262
- scss-extract analyze --project frontend
263
-
264
- # Generate with specific project
265
- scss-extract generate --project admin-app
266
-
267
- # Modernize with angular.json auto-detection
268
- scss-extract modernize --dry-run
269
-
270
- # Refactor specific project
271
- scss-extract refactor --project mylib --output ./libs/mylib/styles/_variables.scss
272
- ```
273
-
274
- ### What Gets Auto-Configured
275
-
276
- When angular.json is detected, the tool automatically sets:
277
-
278
- | Config | Source |
279
- |--------|--------|
280
- | **src** | `project.sourceRoot` (e.g., `apps/myapp/src`) |
281
- | **output** | Derived from global styles location |
282
- | **styleExt** | From project schematics (scss, sass, etc.) |
283
- | **prefix** | Component prefix (e.g., `app`, `lib`) |
284
- | **ignore** | Adds `.angular/`, `dist/`, `out-tsc/` |
285
-
286
- The tool will display the detected Angular project info:
287
- ```
288
- Angular Project: myapp
289
- Prefix: app
290
- Style: scss
291
- ```
292
-
293
- ## Bootstrap to Angular Material Migration
294
-
295
- Automatically detect and migrate Bootstrap classes to Angular Material MDC-based components and utilities. For flex/grid/spacing classes, the tool generates custom utilities.
296
-
297
- ### Detect Bootstrap Usage
298
-
299
- Analyze your codebase for Bootstrap classes and get a comprehensive report:
300
-
301
- ```bash
302
- npx scss-extract detect-bootstrap [src]
303
-
304
- # With output format
305
- npx scss-extract detect-bootstrap ./src --format table
306
- npx scss-extract detect-bootstrap ./src --format json
307
- npx scss-extract detect-bootstrap ./src --format markdown
308
- ```
309
-
310
- **Arguments:**
311
- - `[src]` - Source directory to scan (optional, auto-detected from angular.json)
312
-
313
- **Options:**
314
- - `--format <type>` - Output format: table, json, markdown (default: table)
315
- - `--angular-json <path>` - Path to angular.json file
316
- - `--project <name>` - Specify which project to use
317
- - `--no-angular` - Disable angular.json integration
318
-
319
- **Example Output:**
320
- ```
321
- Bootstrap Usage Report
322
- ┌────────────┬───────┬─────────────────────────────────────────┐
323
- Category │ Count Classes │
324
- ├────────────┼───────┼─────────────────────────────────────────┤
325
- Components 5 │ btn, card, form-control, navbar, modal │
326
- Utilities │ 12 │ d-flex, m-3, p-2, text-center, etc. │
327
- └────────────┴───────┴─────────────────────────────────────────┘
328
- ```
329
-
330
- ### Migrate Bootstrap to Material
331
-
332
- Convert Bootstrap classes to Angular Material equivalents:
333
-
334
- ```bash
335
- npx scss-extract migrate-bootstrap [src]
336
-
337
- # With options
338
- npx scss-extract migrate-bootstrap ./src --custom-utilities ./src/utilities.scss --dry-run
339
- ```
340
-
341
- **Arguments:**
342
- - `[src]` - Source directory to scan (optional, auto-detected from angular.json)
343
-
344
- **Options:**
345
- - `--custom-utilities <path>` - Path for custom utilities file (default: `./src/styles/utilities.scss`)
346
- - `--no-custom-utilities` - Skip creating custom utility classes
347
- - `--dry-run` - Preview changes without modifying files
348
- - `--angular-json <path>` - Path to angular.json file
349
- - `--project <name>` - Specify which project to use
350
- - `--no-angular` - Disable angular.json integration
351
-
352
- **What it does:**
353
-
354
- **Component Migrations:**
355
- - `btn` `mat-button` / `mat-raised-button` / `mat-stroked-button`
356
- - `card` → `mat-card` with `mat-card-header`, `mat-card-content`, `mat-card-actions`
357
- - `form-control` `mat-form-field` with `matInput`
358
- - `navbar` → `mat-toolbar`
359
- - `modal` → `mat-dialog`
360
- - And 50+ more component mappings
361
-
362
- **Utility Migrations:**
363
- - `d-flex` → Custom flex utilities
364
- - `justify-content-*` → Custom flexbox utilities
365
- - `align-items-*` Custom flexbox utilities
366
- - `m-*`, `p-*` → Custom spacing utilities (0-5 scale)
367
- - `text-*` Custom text utilities
368
- - `w-*`, `h-*` → Custom sizing utilities
369
-
370
- ✅ **Generated Custom Utilities:**
371
- Creates a `utilities.scss` file with Material Design-aligned spacing:
372
- ```scss
373
- // Spacing utilities (0, 4px, 8px, 16px, 24px, 48px)
374
- .m-0 { margin: 0; }
375
- .m-1 { margin: 4px; }
376
- .m-2 { margin: 8px; }
377
- .m-3 { margin: 16px; }
378
- .p-t-2 { padding-top: 8px; }
379
-
380
- // Flexbox utilities
381
- .d-flex { display: flex; }
382
- .justify-content-center { justify-content: center; }
383
-
384
- // Display utilities
385
- .d-block { display: block; }
386
- .d-none { display: none; }
387
-
388
- // Text utilities
389
- .text-center { text-align: center; }
390
- .fw-bold { font-weight: 700; }
391
- ```
392
-
393
- **Migration Warnings:**
394
-
395
- The tool provides warnings for manual review items:
396
- - ⚠️ Bootstrap grid system → Material Layout or CSS Grid
397
- - ⚠️ Bootstrap forms → Material form fields (requires template changes)
398
- - ⚠️ Bootstrap modals → Material dialogs (requires component refactoring)
399
- - ⚠️ Complex component compositions → Manual Material implementation
400
-
401
- **Example Workflow:**
402
- ```bash
403
- # 1. Detect Bootstrap usage
404
- npx scss-extract detect-bootstrap --format table
405
-
406
- # 2. Preview migration
407
- npx scss-extract migrate-bootstrap --dry-run
408
-
409
- # 3. Apply migration
410
- npx scss-extract migrate-bootstrap
411
-
412
- # 4. Apply migration with custom utilities path
413
- npx scss-extract migrate-bootstrap --custom-utilities ./custom/utilities.scss
414
-
415
- # 5. Skip utilities generation
416
- npx scss-extract migrate-bootstrap --no-custom-utilities
417
-
418
- # 6. Review changes and test components
419
- # Manual review of generated utilities.scss and component templates
420
- ```
421
-
422
- ## Configuration
423
-
424
- Create a `.scssextractrc.json` file in your project root:
425
-
426
- ```json
427
- {
428
- "src": "./apps/subapp/src",
429
- "output": "./libs/styles/_variables.scss",
430
- "threshold": 2,
431
- "categories": {
432
- "colors": true,
433
- "spacing": true,
434
- "fontSizes": true,
435
- "fontWeights": true,
436
- "fontFamilies": true,
437
- "borderRadius": true,
438
- "shadows": true,
439
- "zIndex": true,
440
- "sizing": true,
441
- "lineHeight": true,
442
- "opacity": true,
443
- "transitions": true
444
- },
445
- "spacingScale": {
446
- "xxs": "2px",
447
- "xs": "4px",
448
- "sm": "8px",
449
- "md": "16px",
450
- "lg": "24px",
451
- "xl": "32px",
452
- "xxl": "48px"
453
- },
454
- "ignore": [
455
- "**/node_modules/**",
456
- "**/dist/**",
457
- "**/_variables.scss"
458
- ],
459
- "importStyle": "use",
460
- "reportFormat": "table"
461
- }
462
- ```
463
-
464
- See [`.scssextractrc.example.json`](./.scssextractrc.example.json) for a complete example.
465
-
466
- ## Value Detection Categories
467
-
468
- The tool detects and categorizes these types of repeated values:
469
-
470
- | Category | Prefix | Examples |
471
- |----------|--------|----------|
472
- | **Colors** | `$color-` | `#1976d2`, `rgb(25, 118, 210)`, `rgba(0,0,0,0.87)`, `white` |
473
- | **Spacing** | `$spacing-` | `4px`, `8px`, `16px`, `24px` (mapped to t-shirt sizes) |
474
- | **Font Sizes** | `$font-size-` | `12px`, `14px`, `16px`, `20px` |
475
- | **Font Weights** | `$font-weight-` | `400`, `500`, `700`, `bold` |
476
- | **Font Families** | `$font-family-` | `'Roboto', sans-serif` |
477
- | **Border Radius** | `$border-radius-` | `4px`, `8px`, `50%` |
478
- | **Box Shadows** | `$shadow-` | `0 2px 4px rgba(0,0,0,0.1)` |
479
- | **Z-Index** | `$z-index-` | `100`, `1000`, `9999` |
480
- | **Sizing** | `$size-` | Width/height pixel values |
481
- | **Line Height** | `$line-height-` | `1.5`, `1.25`, `24px` |
482
- | **Opacity** | `$opacity-` | `0.5`, `0.87` |
483
- | **Transitions** | `$transition-` | `all 0.3s ease` |
484
-
485
- ## How It Works
486
-
487
- 1. **Scanning** - Recursively finds all `.scss` files in the specified directory
488
- 2. **Parsing** - Extracts hardcoded values using regex patterns
489
- 3. **Analyzing** - Counts occurrences and groups by category
490
- 4. **Generating** - Creates `_variables.scss` with smart variable names
491
- 5. **Refactoring** - Replaces hardcoded values with `$variable` references
492
-
493
- ## Variable Naming Convention
494
-
495
- The tool uses intelligent naming based on value patterns and context:
496
-
497
- - **Kebab-case** for all variable names
498
- - **Category prefixes** (e.g., `$color-`, `$spacing-`)
499
- - **Semantic names** when possible:
500
- - `#1976d2``$color-brand-primary`
501
- - `rgba(0,0,0,0.87)``$color-text-primary`
502
- - `16px` (padding)`$spacing-md`
503
- - `14px` (font-size) → `$font-size-sm`
504
- - `500` (font-weight) → `$font-weight-medium`
505
-
506
- ### Spacing Scale (T-shirt Sizing)
507
-
508
- | Variable | Value |
509
- |----------|-------|
510
- | `$spacing-xxs` | `2px` |
511
- | `$spacing-xs` | `4px` |
512
- | `$spacing-sm` | `8px` |
513
- | `$spacing-md` | `16px` |
514
- | `$spacing-lg` | `24px` |
515
- | `$spacing-xl` | `32px` |
516
- | `$spacing-xxl` | `48px` |
517
-
518
- ## Safe Refactoring Rules
519
-
520
- The tool **WILL NOT** replace values in these contexts:
521
-
522
- Already-defined `$variable` declarations
523
- Values inside `url()` functions
524
- ✅ Values inside `content:` property
525
- ✅ Values inside string interpolation `#{}`
526
- ✅ Values inside `@use` or `@forward` statements
527
- ✅ Values inside comments
528
- Values in Angular Material mixin calls (e.g., `mat.define-palette()`)
529
- ✅ Single-use values (below the threshold)
530
-
531
- ## Angular 15 + Material 15 Integration
532
-
533
- The tool is designed for Angular 15 and Angular Material 15 projects:
534
-
535
- - Uses `@use` syntax (not deprecated `@import`)
536
- - 🎨 Recognizes Material theming patterns
537
- - 🛡️ Preserves Material palette functions:
538
- - `mat.define-palette()`
539
- - `mat.get-color-from-palette()`
540
- - `mat.define-light-theme()` / `mat.define-dark-theme()`
541
- - `mat.all-component-themes()`
542
-
543
- ### Generated Variables File
544
-
545
- ```scss
546
- //
547
- // Auto-generated SCSS Variables
548
- // Generated by scss-variable-extractor v1.0.0
549
- // Generated at: 2026-02-12T13:00:00.000Z
550
- //
551
- // DO NOT EDIT THIS FILE MANUALLY
552
- // This file is auto-generated. Your changes will be overwritten.
553
- //
554
-
555
- // Colors
556
- // ────────────────────────────────────────
557
- $color-brand-primary: #1976d2;
558
- $color-text-primary: rgba(0, 0, 0, 0.87);
559
- $color-white: white;
560
-
561
- // Spacing
562
- // ────────────────────────────────────────
563
- $spacing-sm: 8px;
564
- $spacing-md: 16px;
565
- $spacing-lg: 24px;
566
-
567
- // Font Sizes
568
- // ────────────────────────────────────────
569
- $font-size-xs: 12px;
570
- $font-size-sm: 14px;
571
- $font-size-xl: 20px;
572
- ```
573
-
574
- ### Refactored Component Example
575
-
576
- **Before:**
577
- ```scss
578
- .component-a {
579
- background-color: #1976d2;
580
- color: rgba(0, 0, 0, 0.87);
581
- padding: 16px;
582
- font-size: 14px;
583
- border-radius: 4px;
584
- }
585
- ```
586
-
587
- **After:**
588
- ```scss
589
- @use '../../../libs/styles/variables' as *;
590
-
591
- .component-a {
592
- background-color: $color-brand-primary;
593
- color: $color-text-primary;
594
- padding: $spacing-md;
595
- font-size: $font-size-sm;
596
- border-radius: $border-radius-sm;
597
- }
598
- ```
599
-
600
- ## Output Reports
601
-
602
- ### Console Table (default)
603
-
604
- ```
605
- Category | Value | Count | Files | Suggested Variable
606
- ─────────────|────────────────────|───────|───────|─────────────────────
607
- color | #1976d2 | 5 | 3 | $color-brand-primary
608
- color | rgba(0,0,0,0.87) | 8 | 6 | $color-text-primary
609
- spacing | 16px | 12 | 8 | $spacing-md
610
- font-size | 14px | 7 | 5 | $font-size-sm
611
- ```
612
-
613
- ### JSON (`--format json`)
614
-
615
- ```json
616
- {
617
- "colors": [
618
- {
619
- "value": "#1976d2",
620
- "count": 5,
621
- "fileCount": 3,
622
- "suggestedName": "$color-brand-primary"
623
- }
624
- ]
625
- }
626
- ```
627
-
628
- ### Markdown (`--format markdown`)
629
-
630
- ```markdown
631
- ## Colors
632
-
633
- | Value | Count | Files | Suggested Variable |
634
- |-------|-------|-------|-------------------|
635
- | #1976d2 | 5 | 3 | `$color-brand-primary` |
636
- ```
637
-
638
- ## Testing
639
-
640
- Run the test suite:
641
-
642
- ```bash
643
- npm test
644
- ```
645
-
646
- Run tests with coverage:
647
-
648
- ```bash
649
- npm test -- --coverage
650
- ```
651
-
652
- ## Project Structure
653
-
654
- ```
655
- scss-variable-extractor/
656
- ├── bin/
657
- │ └── cli.js # CLI entry point
658
- ├── src/
659
- │ ├── scanner.js # Finds .scss files
660
- │ ├── parser.js # Extracts hardcoded values
661
- │ ├── analyzer.js # Identifies repeated values
662
- │ ├── generator.js # Generates _variables.scss
663
- │ ├── refactorer.js # Replaces values with variables
664
- │ ├── config.js # Configuration management
665
- │ └── index.js # Main exports
666
- ├── templates/
667
- │ └── _variables.scss.template # Variables file template
668
- ├── test/
669
- │ ├── fixtures/ # Sample SCSS files
670
- │ ├── scanner.test.js
671
- │ ├── parser.test.js
672
- │ ├── analyzer.test.js
673
- │ ├── generator.test.js
674
- │ └── refactorer.test.js
675
- ├── .scssextractrc.example.json # Example config
676
- ├── package.json
677
- ├── README.md
678
- └── LICENSE
679
- ```
680
-
681
- ## Requirements
682
-
683
- - **Node.js** >= 14.0.0
684
- - **npm** >= 6.0.0
685
-
686
- ## Contributing
687
-
688
- Contributions are welcome! Please follow these guidelines:
689
-
690
- 1. Fork the repository
691
- 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
692
- 3. Make your changes
693
- 4. Add tests for new functionality
694
- 5. Ensure all tests pass (`npm test`)
695
- 6. Commit your changes (`git commit -m 'Add amazing feature'`)
696
- 7. Push to the branch (`git push origin feature/amazing-feature`)
697
- 8. Open a Pull Request
698
-
699
- ## License
700
-
701
- MIT License - see [LICENSE](./LICENSE) file for details
702
-
703
- ## Support
704
-
705
- - 🐛 [Report a bug](https://github.com/lpaszkiewicz/scss-variable-extractor/issues)
706
- - 💡 [Request a feature](https://github.com/lpaszkiewicz/scss-variable-extractor/issues)
707
- - 📖 [Documentation](https://github.com/lpaszkiewicz/scss-variable-extractor)
708
-
709
- ## Changelog
710
-
711
- ### 1.5.3 (2026-02-12)
712
-
713
- - **Fixed:** `migrate-bootstrap` now actually detects Bootstrap classes and generates utilities
714
- - **Fixed:** Invalid CSS ("Manual migration required") no longer added to utilities.scss
715
- - **Enhanced:** Utility classes are now properly added to customUtilitiesSet during migration
716
- - **Improved:** Component migrations are tracked and reported
717
-
718
- ### 1.5.2 (2026-02-12)
719
-
720
- - **Fixed:** `migrate-bootstrap` command option renamed from `--utilities` to `--custom-utilities` to work with `--no-custom-utilities`
721
- - **Fixed:** Default utilities path corrected to `./src/styles/utilities.scss`
722
-
723
- ### 1.5.1 (2026-02-12)
724
-
725
- - **Enhanced:** HTML class detection now handles spaces around `=` (e.g., `class = "py-3"`)
726
- - **Added:** Support for backtick quotes in class attributes (e.g., `class=\`py-3\``)
727
- - **Added:** Support for Angular property binding (e.g., `[class]="py-3"`)
728
- - **Improved:** More robust Bootstrap class detection across different HTML/template formats
729
-
730
- ### 1.5.0 (2026-02-12)
731
-
732
- - **Fixed:** Bootstrap detection now scans SCSS class selectors (`.py-3`, `.mt-4`, etc.)
733
- - **Enhanced:** Bootstrap commands now scan SCSS, HTML, and TypeScript files
734
- - **Added:** New `scanTemplateFiles` function for comprehensive file scanning
735
- - **Improved:** Bootstrap class detection with deduplication
736
-
737
- ### 1.4.0 (2026-02-12)
738
-
739
- - **Added:** Bootstrap to Angular Material migration capability
740
- - **Added:** `detect-bootstrap` command for analyzing Bootstrap usage
741
- - **Added:** `migrate-bootstrap` command for converting Bootstrap classes
742
- - **Added:** Custom utilities generation for flex/grid/spacing classes
743
- - **Added:** Material Design spacing scale (0, 4px, 8px, 16px, 24px, 48px)
744
- - 100+ Bootstrap class mappings
745
-
746
- ### 1.3.0 (2026-02-12)
747
-
748
- - **Added:** Angular.json integration for automatic project configuration
749
- - **Added:** Auto-detection of source directory and style preprocessor
750
- - **Added:** Support for multi-project Angular workspaces
751
- - All commands support `--angular-json`, `--project`, `--no-angular` options
752
-
753
- ### 1.2.0 (2026-02-12)
754
-
755
- - **Added:** Angular Material v15+ pattern refactoring
756
- - **Added:** `analyze-patterns` command to detect anti-patterns
757
- - **Added:** `modernize` command to remove `::ng-deep` and `!important`
758
- - Best practice enforcement with migration suggestions
759
-
760
- ### 1.1.0 (2026-02-12)
761
-
762
- - **Added:** Global installation support via npm link/publish
763
- - **Added:** Positional `[src]` argument for all commands
764
- - **Enhanced:** Scan any folder in your project
765
- - **Improved:** CLI help and documentation
766
-
767
- ### 1.0.0 (2026-02-12)
768
-
769
- - Initial release
770
- - Support for 12 value categories
771
- - Angular 15 & Material 15 compatibility
772
- - Three CLI commands: analyze, generate, refactor
773
- - Multiple report formats
774
- - Comprehensive test coverage
775
-
776
- ---
777
-
778
- Made with ❤️ for the Angular community
1
+ # SCSS Variable Extractor
2
+
3
+ A standalone, reusable CLI tool that analyzes Angular project SCSS files, identifies repeated hardcoded values, extracts them into SCSS variables, and refactors the codebase to use those variables.
4
+
5
+ ## Features
6
+
7
+ ✨ **Automated Variable Extraction** - Identifies and extracts repeated hardcoded values
8
+ 🎯 **Angular 15 & Material 15 Ready** - Follows best practices with `@use` imports
9
+ 🔍 **Smart Pattern Recognition** - Detects colors, spacing, fonts, shadows, and more
10
+ 📊 **Multiple Report Formats** - Table, JSON, or Markdown output
11
+ 🛡️ **Safe Refactoring** - Preserves existing variables and avoids unsafe replacements
12
+ ⚙️ **Highly Configurable** - Customize via `.scssextractrc.json`
13
+ 🔧 **Modernization Tools** - Removes `::ng-deep` and `!important` anti-patterns
14
+ 🚀 **Global Scope Scanning** - Analyze any folder in your project
15
+ 📐 **Angular.json Integration** - Automatically detects project structure and settings
16
+ 🔄 **Bootstrap to Material Migration** - Converts Bootstrap classes to Angular Material MDC components and utilities
17
+ 🎨 **Theme Generation** - Creates dark/light theme structure with Material Design support
18
+ **Auto Formatting** - Prettier integration for consistent code style
19
+ 🌍 **Global Styles Preservation** - Moves ::ng-deep and !important styles to global files
20
+
21
+ ## Installation
22
+
23
+ ### From Git Repository
24
+
25
+ ```bash
26
+ npm install git+https://github.com/lpaszkiewicz/scss-variable-extractor.git
27
+ ```
28
+
29
+ ### As a Git Submodule
30
+
31
+ ```bash
32
+ git submodule add https://github.com/lpaszkiewicz/scss-variable-extractor.git tools/scss-extract
33
+ cd tools/scss-extract
34
+ npm install
35
+ ```
36
+
37
+ ### Local Development
38
+
39
+ ```bash
40
+ git clone https://github.com/lpaszkiewicz/scss-variable-extractor.git
41
+ cd scss-variable-extractor
42
+ npm install
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ > **💡 Tip:** If you have an `angular.json` file, you can omit the source path - the tool will auto-detect your project structure!
48
+
49
+ ### 1. Analyze (Dry Run)
50
+
51
+ See what values would be extracted without modifying any files:
52
+
53
+ ```bash
54
+ # With angular.json (auto-detects project)
55
+ npx scss-extract analyze
56
+
57
+ # Or specify path manually
58
+ npx scss-extract analyze ./apps/subapp/src --threshold 2
59
+ ```
60
+
61
+ ### 2. Generate Variables File
62
+
63
+ Create a `_variables.scss` file with extracted variables:
64
+
65
+ ```bash
66
+ # With angular.json
67
+ npx scss-extract generate
68
+
69
+ # Or specify paths manually
70
+ npx scss-extract generate ./apps/subapp/src --output ./libs/styles/_variables.scss
71
+ ```
72
+
73
+ ### 3. Full Refactoring
74
+
75
+ Generate variables file AND replace hardcoded values in all SCSS files:
76
+
77
+ ```bash
78
+ npx scss-extract refactor ./apps/subapp/src --output ./libs/styles/_variables.scss
79
+ ```
80
+
81
+ ### 4. Modernize Code (Remove Anti-Patterns)
82
+
83
+ Remove `::ng-deep` and `!important` following Angular Material v15+ best practices:
84
+
85
+ ```bash
86
+ # Preview changes first
87
+ npx scss-extract modernize ./src --dry-run
88
+
89
+ # Apply modernization
90
+ npx scss-extract modernize ./src
91
+ ```
92
+
93
+ ## CLI Commands
94
+
95
+ ### `analyze` - Dry-run Analysis
96
+
97
+ Scans SCSS files and reports repeated values without modifying anything.
98
+
99
+ ```bash
100
+ npx scss-extract analyze <src> [options]
101
+ ```
102
+
103
+ **Arguments:**
104
+
105
+ - `<src>` - Source directory to scan (required)
106
+
107
+ **Options:**
108
+
109
+ - `--threshold <number>` - Minimum repeat count (default: `2`)
110
+ - `--format <format>` - Report format: `table`, `json`, `markdown` (default: `table`)
111
+ - `--config <path>` - Path to custom config file
112
+
113
+ **Example:**
114
+
115
+ ```bash
116
+ npx scss-extract analyze ./src --threshold 3 --format markdown
117
+ ```
118
+
119
+ ### `generate` - Generate Variables File
120
+
121
+ Creates a `_variables.scss` file with extracted variables.
122
+
123
+ ```bash
124
+ npx scss-extract generate <src> [options]
125
+ ```
126
+
127
+ **Arguments:**
128
+
129
+ - `<src>` - Source directory to scan (required)
130
+
131
+ **Options:**
132
+
133
+ - `--output <path>` - Output path for variables file (default: `./libs/styles/_variables.scss`)
134
+ - `--threshold <number>` - Minimum repeat count
135
+ - `--config <path>` - Path to custom config file
136
+
137
+ **Example:**
138
+
139
+ ```bash
140
+ npx scss-extract generate ./apps/myapp/src --output ./styles/_variables.scss
141
+ ```
142
+
143
+ ### `refactor` - Full Extraction + Replacement
144
+
145
+ Generates variables file AND refactors SCSS files to use variables.
146
+
147
+ ```bash
148
+ npx scss-extract refactor <src> [options]
149
+ ```
150
+
151
+ **Arguments:**
152
+
153
+ - `<src>` - Source directory to scan (required)
154
+
155
+ **Options:**
156
+
157
+ - `--output <path>` - Output path for variables file
158
+ - `--threshold <number>` - Minimum repeat count
159
+ - `--config <path>` - Path to custom config file
160
+
161
+ **Example:**
162
+
163
+ ```bash
164
+ npx scss-extract refactor --src ./apps/subapp/src --output ./libs/styles/_variables.scss
165
+ ```
166
+
167
+ ### `analyze-patterns` - Analyze Angular Anti-Patterns
168
+
169
+ Scans SCSS files for Angular Material v15+ anti-patterns like `::ng-deep` and `!important` usage.
170
+
171
+ ```bash
172
+ npx scss-extract analyze-patterns <src> [options]
173
+ ```
174
+
175
+ **Arguments:**
176
+
177
+ - `<src>` - Source directory to scan (required)
178
+
179
+ **Options:**
180
+
181
+ - `--format <format>` - Report format: `table`, `json`, `markdown` (default: `table`)
182
+ - `--config <path>` - Path to custom config file
183
+
184
+ **Example:**
185
+
186
+ ```bash
187
+ npx scss-extract analyze-patterns ./src --format table
188
+ ```
189
+
190
+ ### `modernize` - Refactor to Angular Material v15+ Best Practices
191
+
192
+ Automatically refactors SCSS files by removing `::ng-deep`, `/deep/`, `>>>`, and `!important` declarations, following Angular Material v15+ best practices.
193
+
194
+ ```bash
195
+ npx scss-extract modernize <src> [options]
196
+ ```
197
+
198
+ **Arguments:**
199
+
200
+ - `<src>` - Source directory to scan (required)
201
+
202
+ **Options:**
203
+
204
+ - `--global-styles <path>` - Path to global styles file (default: `./src/styles.scss`)
205
+ - `--no-ng-deep` - Skip ::ng-deep refactoring
206
+ - `--no-important` - Skip !important refactoring
207
+ - `--dry-run` - Preview changes without modifying files
208
+ - `--config <path>` - Path to custom config file
209
+
210
+ **Example:**
211
+
212
+ ```bash
213
+ # Preview changes
214
+ npx scss-extract modernize ./src --dry-run
215
+
216
+ # Apply changes
217
+ npx scss-extract modernize ./src --global-styles ./src/styles.scss
218
+ ```
219
+
220
+ **What it does:**
221
+
222
+ - Removes `::ng-deep`, `/deep/`, and `>>>` (deprecated shadow-piercing selectors)
223
+ - Removes `!important` declarations
224
+ - **Preserves styles in global file** - Extracts ng-deep and !important rules to global styles
225
+ - **Prevents parent overrides** - Global styles maintain proper specificity
226
+ - Provides warnings and suggestions for manual review
227
+ - ✅ Maintains code functionality while improving maintainability
228
+
229
+ **How Global Preservation Works:**
230
+
231
+ When `--global-styles` is enabled (default), the tool:
232
+
233
+ 1. **Identifies** rules using `::ng-deep` or `!important`
234
+ 2. **Extracts** complete CSS rules with their selectors
235
+ 3. **Moves** them to the global styles file with source comments
236
+ 4. **Preserves** `!important` where necessary for specificity
237
+ 5. **Removes** them from component files
238
+
239
+ This ensures styles aren't lost when parent components would otherwise override them.
240
+
241
+ **Example:**
242
+
243
+ Component file (before):
244
+
245
+ ```scss
246
+ .my-component {
247
+ ::ng-deep .nested {
248
+ color: red !important; // Needed to override parent
249
+ }
250
+ }
251
+ ```
252
+
253
+ After refactoring:
254
+
255
+ Component file:
256
+
257
+ ```scss
258
+ .my-component {
259
+ // ng-deep and !important removed - see global styles
260
+ }
261
+ ```
262
+
263
+ Global styles file:
264
+
265
+ ```scss
266
+ /* Moved from my-component.component.scss - requires !important for specificity */
267
+ .my-component .nested {
268
+ color: red !important;
269
+ }
270
+ ```
271
+
272
+ **Angular Material v15+ Best Practices:**
273
+
274
+ - Use CSS custom properties for theming
275
+ - Use Angular Material theme mixins for component customization
276
+ - Place global styles in `styles.scss` instead of using `::ng-deep`
277
+ - Increase selector specificity instead of using `!important`
278
+ - Consider `ViewEncapsulation.None` for components that need global styles
279
+
280
+ ## Angular.json Integration
281
+
282
+ The tool can automatically read your `angular.json` file to detect project structure and apply the correct schematics for style refactoring.
283
+
284
+ ### Auto-detection
285
+
286
+ By default, all commands will look for `angular.json` in the current directory and use it to configure:
287
+
288
+ - Source directory (`sourceRoot`)
289
+ - Output path for variables (based on global styles)
290
+ - Style preprocessor (scss, sass, less, css)
291
+ - Component prefix
292
+ - Ignore patterns (`.angular`, `dist`, etc.)
293
+
294
+ ### Usage
295
+
296
+ **Without angular.json (manual configuration):**
297
+
298
+ ```bash
299
+ scss-extract analyze ./apps/myapp/src
300
+ ```
301
+
302
+ **With angular.json (auto-configured):**
303
+
304
+ ```bash
305
+ # Uses default project from angular.json
306
+ scss-extract analyze
307
+
308
+ # Use specific project
309
+ scss-extract analyze --project myapp
310
+
311
+ # Specify angular.json location
312
+ scss-extract analyze --angular-json ./path/to/angular.json
313
+ ```
314
+
315
+ **Disable angular.json integration:**
316
+
317
+ ```bash
318
+ scss-extract analyze ./src --no-angular
319
+ ```
320
+
321
+ ### All Commands Support Angular.json
322
+
323
+ Every command supports these options:
324
+
325
+ - `--angular-json <path>` - Path to angular.json file
326
+ - `--project <name>` - Specify which project to use
327
+ - `--no-angular` - Disable angular.json integration
328
+
329
+ **Examples:**
330
+
331
+ ```bash
332
+ # Analyze with angular.json
333
+ scss-extract analyze --project frontend
334
+
335
+ # Generate with specific project
336
+ scss-extract generate --project admin-app
337
+
338
+ # Modernize with angular.json auto-detection
339
+ scss-extract modernize --dry-run
340
+
341
+ # Refactor specific project
342
+ scss-extract refactor --project mylib --output ./libs/mylib/styles/_variables.scss
343
+ ```
344
+
345
+ ### What Gets Auto-Configured
346
+
347
+ When angular.json is detected, the tool automatically sets:
348
+
349
+ | Config | Source |
350
+ | ------------ | --------------------------------------------- |
351
+ | **src** | `project.sourceRoot` (e.g., `apps/myapp/src`) |
352
+ | **output** | Derived from global styles location |
353
+ | **styleExt** | From project schematics (scss, sass, etc.) |
354
+ | **prefix** | Component prefix (e.g., `app`, `lib`) |
355
+ | **ignore** | Adds `.angular/`, `dist/`, `out-tsc/` |
356
+
357
+ The tool will display the detected Angular project info:
358
+
359
+ ```
360
+ Angular Project: myapp
361
+ Prefix: app
362
+ Style: scss
363
+ ```
364
+
365
+ ## Bootstrap to Angular Material Migration
366
+
367
+ Automatically detect and migrate Bootstrap classes to Angular Material MDC-based components and utilities. For flex/grid/spacing classes, the tool generates custom utilities.
368
+
369
+ ### Detect Bootstrap Usage
370
+
371
+ Analyze your codebase for Bootstrap classes and get a comprehensive report:
372
+
373
+ ```bash
374
+ npx scss-extract detect-bootstrap [src]
375
+
376
+ # With output format
377
+ npx scss-extract detect-bootstrap ./src --format table
378
+ npx scss-extract detect-bootstrap ./src --format json
379
+ npx scss-extract detect-bootstrap ./src --format markdown
380
+ ```
381
+
382
+ **Arguments:**
383
+
384
+ - `[src]` - Source directory to scan (optional, auto-detected from angular.json)
385
+
386
+ **Options:**
387
+
388
+ - `--format <type>` - Output format: table, json, markdown (default: table)
389
+ - `--angular-json <path>` - Path to angular.json file
390
+ - `--project <name>` - Specify which project to use
391
+ - `--no-angular` - Disable angular.json integration
392
+
393
+ **Example Output:**
394
+
395
+ ```
396
+ Bootstrap Usage Report
397
+ ┌────────────┬───────┬─────────────────────────────────────────┐
398
+ Category │ Count Classes │
399
+ ├────────────┼───────┼─────────────────────────────────────────┤
400
+ │ Components │ 5 │ btn, card, form-control, navbar, modal │
401
+ Utilities │ 12 │ d-flex, m-3, p-2, text-center, etc. │
402
+ └────────────┴───────┴─────────────────────────────────────────┘
403
+ ```
404
+
405
+ ### Migrate Bootstrap to Material
406
+
407
+ Convert Bootstrap classes to Angular Material equivalents:
408
+
409
+ ```bash
410
+ npx scss-extract migrate-bootstrap [src]
411
+
412
+ # With options
413
+ npx scss-extract migrate-bootstrap ./src --custom-utilities ./src/utilities.scss --dry-run
414
+ ```
415
+
416
+ **Arguments:**
417
+
418
+ - `[src]` - Source directory to scan (optional, auto-detected from angular.json)
419
+
420
+ **Options:**
421
+
422
+ - `--custom-utilities <path>` - Path for custom utilities file (default: `./src/styles/utilities.scss`)
423
+ - `--no-custom-utilities` - Skip creating custom utility classes
424
+ - `--dry-run` - Preview changes without modifying files
425
+ - `--angular-json <path>` - Path to angular.json file
426
+ - `--project <name>` - Specify which project to use
427
+ - `--no-angular` - Disable angular.json integration
428
+
429
+ **What it does:**
430
+
431
+ **Component Migrations:**
432
+
433
+ - `btn` → `mat-button` / `mat-raised-button` / `mat-stroked-button`
434
+ - `card` → `mat-card` with `mat-card-header`, `mat-card-content`, `mat-card-actions`
435
+ - `form-control` → `mat-form-field` with `matInput`
436
+ - `navbar` → `mat-toolbar`
437
+ - `modal` → `mat-dialog`
438
+ - And 50+ more component mappings
439
+
440
+ **Utility Migrations:**
441
+
442
+ - `d-flex` → Custom flex utilities
443
+ - `justify-content-*` → Custom flexbox utilities
444
+ - `align-items-*` → Custom flexbox utilities
445
+ - `m-*`, `p-*` → Custom spacing utilities (0-5 scale)
446
+ - `text-*` → Custom text utilities
447
+ - `w-*`, `h-*` → Custom sizing utilities
448
+
449
+ **Generated Custom Utilities:**
450
+ Creates a `utilities.scss` file with Material Design-aligned spacing:
451
+
452
+ ```scss
453
+ // Spacing utilities (0, 4px, 8px, 16px, 24px, 48px)
454
+ .m-0 {
455
+ margin: 0;
456
+ }
457
+ .m-1 {
458
+ margin: 4px;
459
+ }
460
+ .m-2 {
461
+ margin: 8px;
462
+ }
463
+ .m-3 {
464
+ margin: 16px;
465
+ }
466
+ .p-t-2 {
467
+ padding-top: 8px;
468
+ }
469
+
470
+ // Flexbox utilities
471
+ .d-flex {
472
+ display: flex;
473
+ }
474
+ .justify-content-center {
475
+ justify-content: center;
476
+ }
477
+
478
+ // Display utilities
479
+ .d-block {
480
+ display: block;
481
+ }
482
+ .d-none {
483
+ display: none;
484
+ }
485
+
486
+ // Text utilities
487
+ .text-center {
488
+ text-align: center;
489
+ }
490
+ .fw-bold {
491
+ font-weight: 700;
492
+ }
493
+ ```
494
+
495
+ **Migration Warnings:**
496
+
497
+ The tool provides warnings for manual review items:
498
+
499
+ - ⚠️ Bootstrap grid system → Material Layout or CSS Grid
500
+ - ⚠️ Bootstrap forms Material form fields (requires template changes)
501
+ - ⚠️ Bootstrap modals Material dialogs (requires component refactoring)
502
+ - ⚠️ Complex component compositions Manual Material implementation
503
+
504
+ **Example Workflow:**
505
+
506
+ ```bash
507
+ # 1. Detect Bootstrap usage
508
+ npx scss-extract detect-bootstrap --format table
509
+
510
+ # 2. Preview migration
511
+ npx scss-extract migrate-bootstrap --dry-run
512
+
513
+ # 3. Apply migration
514
+ npx scss-extract migrate-bootstrap
515
+
516
+ # 4. Apply migration with custom utilities path
517
+ npx scss-extract migrate-bootstrap --custom-utilities ./custom/utilities.scss
518
+
519
+ # 5. Skip utilities generation
520
+ npx scss-extract migrate-bootstrap --no-custom-utilities
521
+
522
+ # 6. Review changes and test components
523
+ # Manual review of generated utilities.scss and component templates
524
+ ```
525
+
526
+ ---
527
+
528
+ ### `generate-themes` - Theme Structure Generator
529
+
530
+ Generate a complete dark/light theme structure for Angular Material applications.
531
+
532
+ ```bash
533
+ npx scss-extract generate-themes [src]
534
+
535
+ # With options
536
+ npx scss-extract generate-themes ./src --output ./src/styles --analyze
537
+ ```
538
+
539
+ **Arguments:**
540
+
541
+ - `[src]` - Source directory to analyze for colors (optional)
542
+
543
+ **Options:**
544
+
545
+ - `--output <dir>` - Output directory for theme files (default: `./src/styles`)
546
+ - `--analyze` - Analyze existing styles for theme readiness
547
+ - `--format <format>` - Report format for analysis (table, json, markdown)
548
+
549
+ **What it generates:**
550
+
551
+ **Theme Files Created:**
552
+
553
+ - `_theme-base.scss` - Shared variables (spacing, typography, shadows, z-index)
554
+ - `_theme-light.scss` - Light theme color variables
555
+ - `_theme-dark.scss` - Dark theme color variables
556
+ - `themes.scss` - Angular Material theme configuration and loader
557
+ - `_css-variables.scss` - CSS custom properties for runtime switching
558
+ - `_component-theme-mixin.scss` - Template for component theme mixins
559
+
560
+ ✅ **Features:**
561
+
562
+ - Material Design color palettes
563
+ - Automatic dark/light mode switching
564
+ - CSS custom properties support
565
+ - Component theme mixin patterns
566
+ - Proper encapsulation (no ::ng-deep needed!)
567
+
568
+ **Example Usage:**
569
+
570
+ ```bash
571
+ # Generate theme structure
572
+ npx scss-extract generate-themes --output ./src/styles
573
+
574
+ # Analyze existing styles first
575
+ npx scss-extract generate-themes ./src --analyze --output ./src/styles
576
+ ```
577
+
578
+ **Using Generated Themes:**
579
+
580
+ 1. Import in your `styles.scss`:
581
+
582
+ ```scss
583
+ @use './styles/themes';
584
+ ```
585
+
586
+ 2. Add theme toggle to your app component:
587
+
588
+ ```typescript
589
+ export class AppComponent {
590
+ isDarkMode = false;
591
+
592
+ toggleTheme() {
593
+ this.isDarkMode = !this.isDarkMode;
594
+ }
595
+ }
596
+ ```
597
+
598
+ ```html
599
+ <div [class.dark-theme]="isDarkMode">
600
+ <router-outlet></router-outlet>
601
+ </div>
602
+ ```
603
+
604
+ 3. Use theme variables in components:
605
+
606
+ ```scss
607
+ @use '../../styles/theme-base' as base;
608
+
609
+ .my-component {
610
+ padding: base.$spacing-md;
611
+ border-radius: base.$border-radius-md;
612
+
613
+ &__header {
614
+ background-color: var(--color-primary);
615
+ color: var(--text-primary);
616
+ }
617
+ }
618
+ ```
619
+
620
+ **Theme Best Practices:**
621
+
622
+ - ✅ Use SCSS variables for build-time constants (spacing, shadows)
623
+ - ✅ Use CSS custom properties for runtime theme switching (colors)
624
+ - ✅ Create component theme mixins instead of using ::ng-deep
625
+ - ✅ Keep global styles in dedicated theme files
626
+ - ❌ Avoid ViewEncapsulation.None unless absolutely necessary
627
+ - ❌ Don't use ::ng-deep for theming - use theme mixins instead
628
+
629
+ ---
630
+
631
+ ## Auto Formatting
632
+
633
+ The tool now includes Prettier for consistent code formatting:
634
+
635
+ ```bash
636
+ # Format all files
637
+ npm run format
638
+
639
+ # Check formatting without changes
640
+ npm run format:check
641
+ ```
642
+
643
+ The formatting runs automatically before releases to ensure code quality.
644
+
645
+ ---
646
+
647
+ ## Configuration
648
+
649
+ Create a `.scssextractrc.json` file in your project root:
650
+
651
+ ```json
652
+ {
653
+ "src": "./apps/subapp/src",
654
+ "output": "./libs/styles/_variables.scss",
655
+ "threshold": 2,
656
+ "categories": {
657
+ "colors": true,
658
+ "spacing": true,
659
+ "fontSizes": true,
660
+ "fontWeights": true,
661
+ "fontFamilies": true,
662
+ "borderRadius": true,
663
+ "shadows": true,
664
+ "zIndex": true,
665
+ "sizing": true,
666
+ "lineHeight": true,
667
+ "opacity": true,
668
+ "transitions": true
669
+ },
670
+ "spacingScale": {
671
+ "xxs": "2px",
672
+ "xs": "4px",
673
+ "sm": "8px",
674
+ "md": "16px",
675
+ "lg": "24px",
676
+ "xl": "32px",
677
+ "xxl": "48px"
678
+ },
679
+ "ignore": ["**/node_modules/**", "**/dist/**", "**/_variables.scss"],
680
+ "importStyle": "use",
681
+ "reportFormat": "table"
682
+ }
683
+ ```
684
+
685
+ See [`.scssextractrc.example.json`](./.scssextractrc.example.json) for a complete example.
686
+
687
+ ## Value Detection Categories
688
+
689
+ The tool detects and categorizes these types of repeated values:
690
+
691
+ | Category | Prefix | Examples |
692
+ | ----------------- | ----------------- | ----------------------------------------------------------- |
693
+ | **Colors** | `$color-` | `#1976d2`, `rgb(25, 118, 210)`, `rgba(0,0,0,0.87)`, `white` |
694
+ | **Spacing** | `$spacing-` | `4px`, `8px`, `16px`, `24px` (mapped to t-shirt sizes) |
695
+ | **Font Sizes** | `$font-size-` | `12px`, `14px`, `16px`, `20px` |
696
+ | **Font Weights** | `$font-weight-` | `400`, `500`, `700`, `bold` |
697
+ | **Font Families** | `$font-family-` | `'Roboto', sans-serif` |
698
+ | **Border Radius** | `$border-radius-` | `4px`, `8px`, `50%` |
699
+ | **Box Shadows** | `$shadow-` | `0 2px 4px rgba(0,0,0,0.1)` |
700
+ | **Z-Index** | `$z-index-` | `100`, `1000`, `9999` |
701
+ | **Sizing** | `$size-` | Width/height pixel values |
702
+ | **Line Height** | `$line-height-` | `1.5`, `1.25`, `24px` |
703
+ | **Opacity** | `$opacity-` | `0.5`, `0.87` |
704
+ | **Transitions** | `$transition-` | `all 0.3s ease` |
705
+
706
+ ## How It Works
707
+
708
+ 1. **Scanning** - Recursively finds all `.scss` files in the specified directory
709
+ 2. **Parsing** - Extracts hardcoded values using regex patterns
710
+ 3. **Analyzing** - Counts occurrences and groups by category
711
+ 4. **Generating** - Creates `_variables.scss` with smart variable names
712
+ 5. **Refactoring** - Replaces hardcoded values with `$variable` references
713
+
714
+ ## Variable Naming Convention
715
+
716
+ The tool uses intelligent naming based on value patterns and context:
717
+
718
+ - **Kebab-case** for all variable names
719
+ - **Category prefixes** (e.g., `$color-`, `$spacing-`)
720
+ - **Semantic names** when possible:
721
+ - `#1976d2` `$color-brand-primary`
722
+ - `rgba(0,0,0,0.87)` → `$color-text-primary`
723
+ - `16px` (padding) → `$spacing-md`
724
+ - `14px` (font-size) → `$font-size-sm`
725
+ - `500` (font-weight) `$font-weight-medium`
726
+
727
+ ### Spacing Scale (T-shirt Sizing)
728
+
729
+ | Variable | Value |
730
+ | -------------- | ------ |
731
+ | `$spacing-xxs` | `2px` |
732
+ | `$spacing-xs` | `4px` |
733
+ | `$spacing-sm` | `8px` |
734
+ | `$spacing-md` | `16px` |
735
+ | `$spacing-lg` | `24px` |
736
+ | `$spacing-xl` | `32px` |
737
+ | `$spacing-xxl` | `48px` |
738
+
739
+ ## Safe Refactoring Rules
740
+
741
+ The tool **WILL NOT** replace values in these contexts:
742
+
743
+ ✅ Already-defined `$variable` declarations
744
+ Values inside `url()` functions
745
+ ✅ Values inside `content:` property
746
+ Values inside string interpolation `#{}`
747
+ ✅ Values inside `@use` or `@forward` statements
748
+ Values inside comments
749
+ Values in Angular Material mixin calls (e.g., `mat.define-palette()`)
750
+ ✅ Single-use values (below the threshold)
751
+
752
+ ## Angular 15 + Material 15 Integration
753
+
754
+ The tool is designed for Angular 15 and Angular Material 15 projects:
755
+
756
+ - Uses `@use` syntax (not deprecated `@import`)
757
+ - 🎨 Recognizes Material theming patterns
758
+ - 🛡️ Preserves Material palette functions:
759
+ - `mat.define-palette()`
760
+ - `mat.get-color-from-palette()`
761
+ - `mat.define-light-theme()` / `mat.define-dark-theme()`
762
+ - `mat.all-component-themes()`
763
+
764
+ ### Generated Variables File
765
+
766
+ ```scss
767
+ //
768
+ // Auto-generated SCSS Variables
769
+ // Generated by scss-variable-extractor v1.0.0
770
+ // Generated at: 2026-02-12T13:00:00.000Z
771
+ //
772
+ // DO NOT EDIT THIS FILE MANUALLY
773
+ // This file is auto-generated. Your changes will be overwritten.
774
+ //
775
+
776
+ // Colors
777
+ // ────────────────────────────────────────
778
+ $color-brand-primary: #1976d2;
779
+ $color-text-primary: rgba(0, 0, 0, 0.87);
780
+ $color-white: white;
781
+
782
+ // Spacing
783
+ // ────────────────────────────────────────
784
+ $spacing-sm: 8px;
785
+ $spacing-md: 16px;
786
+ $spacing-lg: 24px;
787
+
788
+ // Font Sizes
789
+ // ────────────────────────────────────────
790
+ $font-size-xs: 12px;
791
+ $font-size-sm: 14px;
792
+ $font-size-xl: 20px;
793
+ ```
794
+
795
+ ### Refactored Component Example
796
+
797
+ **Before:**
798
+
799
+ ```scss
800
+ .component-a {
801
+ background-color: #1976d2;
802
+ color: rgba(0, 0, 0, 0.87);
803
+ padding: 16px;
804
+ font-size: 14px;
805
+ border-radius: 4px;
806
+ }
807
+ ```
808
+
809
+ **After:**
810
+
811
+ ```scss
812
+ @use '../../../libs/styles/variables' as *;
813
+
814
+ .component-a {
815
+ background-color: $color-brand-primary;
816
+ color: $color-text-primary;
817
+ padding: $spacing-md;
818
+ font-size: $font-size-sm;
819
+ border-radius: $border-radius-sm;
820
+ }
821
+ ```
822
+
823
+ ## Output Reports
824
+
825
+ ### Console Table (default)
826
+
827
+ ```
828
+ Category | Value | Count | Files | Suggested Variable
829
+ ─────────────|────────────────────|───────|───────|─────────────────────
830
+ color | #1976d2 | 5 | 3 | $color-brand-primary
831
+ color | rgba(0,0,0,0.87) | 8 | 6 | $color-text-primary
832
+ spacing | 16px | 12 | 8 | $spacing-md
833
+ font-size | 14px | 7 | 5 | $font-size-sm
834
+ ```
835
+
836
+ ### JSON (`--format json`)
837
+
838
+ ```json
839
+ {
840
+ "colors": [
841
+ {
842
+ "value": "#1976d2",
843
+ "count": 5,
844
+ "fileCount": 3,
845
+ "suggestedName": "$color-brand-primary"
846
+ }
847
+ ]
848
+ }
849
+ ```
850
+
851
+ ### Markdown (`--format markdown`)
852
+
853
+ ```markdown
854
+ ## Colors
855
+
856
+ | Value | Count | Files | Suggested Variable |
857
+ | ------- | ----- | ----- | ---------------------- |
858
+ | #1976d2 | 5 | 3 | `$color-brand-primary` |
859
+ ```
860
+
861
+ ## Testing
862
+
863
+ Run the test suite:
864
+
865
+ ```bash
866
+ npm test
867
+ ```
868
+
869
+ Run tests with coverage:
870
+
871
+ ```bash
872
+ npm test -- --coverage
873
+ ```
874
+
875
+ ## Project Structure
876
+
877
+ ```
878
+ scss-variable-extractor/
879
+ ├── bin/
880
+ │ └── cli.js # CLI entry point
881
+ ├── src/
882
+ │ ├── scanner.js # Finds .scss files
883
+ │ ├── parser.js # Extracts hardcoded values
884
+ │ ├── analyzer.js # Identifies repeated values
885
+ │ ├── generator.js # Generates _variables.scss
886
+ │ ├── refactorer.js # Replaces values with variables
887
+ │ ├── config.js # Configuration management
888
+ │ └── index.js # Main exports
889
+ ├── templates/
890
+ │ └── _variables.scss.template # Variables file template
891
+ ├── test/
892
+ │ ├── fixtures/ # Sample SCSS files
893
+ │ ├── scanner.test.js
894
+ │ ├── parser.test.js
895
+ │ ├── analyzer.test.js
896
+ │ ├── generator.test.js
897
+ │ └── refactorer.test.js
898
+ ├── .scssextractrc.example.json # Example config
899
+ ├── package.json
900
+ ├── README.md
901
+ └── LICENSE
902
+ ```
903
+
904
+ ## Requirements
905
+
906
+ - **Node.js** >= 14.0.0
907
+ - **npm** >= 6.0.0
908
+
909
+ ## Contributing
910
+
911
+ Contributions are welcome! Please follow these guidelines:
912
+
913
+ 1. Fork the repository
914
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
915
+ 3. Make your changes
916
+ 4. Add tests for new functionality
917
+ 5. Ensure all tests pass (`npm test`)
918
+ 6. Commit your changes (`git commit -m 'Add amazing feature'`)
919
+ 7. Push to the branch (`git push origin feature/amazing-feature`)
920
+ 8. Open a Pull Request
921
+
922
+ ## License
923
+
924
+ MIT License - see [LICENSE](./LICENSE) file for details
925
+
926
+ ## Support
927
+
928
+ - 🐛 [Report a bug](https://github.com/lpaszkiewicz/scss-variable-extractor/issues)
929
+ - 💡 [Request a feature](https://github.com/lpaszkiewicz/scss-variable-extractor/issues)
930
+ - 📖 [Documentation](https://github.com/lpaszkiewicz/scss-variable-extractor)
931
+
932
+ ## Changelog
933
+
934
+ ### 1.7.0 (2026-02-12)
935
+
936
+ - **Added:** `generate-themes` command for automatic dark/light theme structure generation
937
+ - **Added:** Prettier integration for automatic code formatting
938
+ - **Added:** Theme utilities module with Material Design color palettes
939
+ - **Enhanced:** `modernize` command now preserves ::ng-deep and !important styles in global files
940
+ - **Enhanced:** !important rules are extracted to global styles instead of being removed
941
+ - **Fixed:** Global styles preserve proper specificity to prevent parent component overrides
942
+ - **Added:** Theme readiness analysis to identify hardcoded colors
943
+ - **Added:** Component theme mixin template for proper encapsulation
944
+ - **Added:** CSS custom properties support for runtime theme switching
945
+ - **Added:** `format` and `format:check` npm scripts
946
+ - **Improved:** Release process now includes automatic formatting
947
+
948
+ ### 1.5.3 (2026-02-12)
949
+
950
+ - **Fixed:** `migrate-bootstrap` now actually detects Bootstrap classes and generates utilities
951
+ - **Fixed:** Invalid CSS ("Manual migration required") no longer added to utilities.scss
952
+ - **Enhanced:** Utility classes are now properly added to customUtilitiesSet during migration
953
+ - **Improved:** Component migrations are tracked and reported
954
+
955
+ ### 1.5.2 (2026-02-12)
956
+
957
+ - **Fixed:** `migrate-bootstrap` command option renamed from `--utilities` to `--custom-utilities` to work with `--no-custom-utilities`
958
+ - **Fixed:** Default utilities path corrected to `./src/styles/utilities.scss`
959
+
960
+ ### 1.5.1 (2026-02-12)
961
+
962
+ - **Enhanced:** HTML class detection now handles spaces around `=` (e.g., `class = "py-3"`)
963
+ - **Added:** Support for backtick quotes in class attributes (e.g., `class=\`py-3\``)
964
+ - **Added:** Support for Angular property binding (e.g., `[class]="py-3"`)
965
+ - **Improved:** More robust Bootstrap class detection across different HTML/template formats
966
+
967
+ ### 1.5.0 (2026-02-12)
968
+
969
+ - **Fixed:** Bootstrap detection now scans SCSS class selectors (`.py-3`, `.mt-4`, etc.)
970
+ - **Enhanced:** Bootstrap commands now scan SCSS, HTML, and TypeScript files
971
+ - **Added:** New `scanTemplateFiles` function for comprehensive file scanning
972
+ - **Improved:** Bootstrap class detection with deduplication
973
+
974
+ ### 1.4.0 (2026-02-12)
975
+
976
+ - **Added:** Bootstrap to Angular Material migration capability
977
+ - **Added:** `detect-bootstrap` command for analyzing Bootstrap usage
978
+ - **Added:** `migrate-bootstrap` command for converting Bootstrap classes
979
+ - **Added:** Custom utilities generation for flex/grid/spacing classes
980
+ - **Added:** Material Design spacing scale (0, 4px, 8px, 16px, 24px, 48px)
981
+ - 100+ Bootstrap class mappings
982
+
983
+ ### 1.3.0 (2026-02-12)
984
+
985
+ - **Added:** Angular.json integration for automatic project configuration
986
+ - **Added:** Auto-detection of source directory and style preprocessor
987
+ - **Added:** Support for multi-project Angular workspaces
988
+ - All commands support `--angular-json`, `--project`, `--no-angular` options
989
+
990
+ ### 1.2.0 (2026-02-12)
991
+
992
+ - **Added:** Angular Material v15+ pattern refactoring
993
+ - **Added:** `analyze-patterns` command to detect anti-patterns
994
+ - **Added:** `modernize` command to remove `::ng-deep` and `!important`
995
+ - Best practice enforcement with migration suggestions
996
+
997
+ ### 1.1.0 (2026-02-12)
998
+
999
+ - **Added:** Global installation support via npm link/publish
1000
+ - **Added:** Positional `[src]` argument for all commands
1001
+ - **Enhanced:** Scan any folder in your project
1002
+ - **Improved:** CLI help and documentation
1003
+
1004
+ ### 1.0.0 (2026-02-12)
1005
+
1006
+ - Initial release
1007
+ - Support for 12 value categories
1008
+ - Angular 15 & Material 15 compatibility
1009
+ - Three CLI commands: analyze, generate, refactor
1010
+ - Multiple report formats
1011
+ - Comprehensive test coverage
1012
+
1013
+ ---
1014
+
1015
+ Made with ❤️ for the Angular community