scss-variable-extractor 1.6.3 → 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/.prettierignore +7 -0
- package/.prettierrc.json +18 -0
- package/.scssextractrc.example.json +31 -35
- package/README.md +1015 -778
- package/THEME-GUIDE.md +289 -0
- package/bin/cli.js +807 -652
- package/jest.config.js +7 -12
- package/package.json +49 -45
- package/src/analyzer.js +285 -285
- package/src/angular-parser.js +383 -381
- package/src/bootstrap-migrator.js +694 -661
- package/src/config.js +87 -91
- package/src/generator.js +220 -219
- package/src/index.js +37 -29
- package/src/ng-refactorer.js +654 -578
- package/src/parser.js +424 -421
- package/src/refactorer.js +329 -249
- package/src/scanner.js +63 -55
- package/src/style-organizer.js +500 -499
- package/src/theme-utils.js +432 -0
- package/test/analyzer.test.js +107 -107
- package/test/angular-parser.test.js +230 -230
- package/test/bootstrap-migrator.test.js +230 -213
- package/test/generator.test.js +139 -149
- package/test/ng-refactorer-global.test.js +140 -0
- package/test/ng-refactorer.test.js +191 -184
- package/test/parser.test.js +131 -131
- package/test/refactorer-edge-cases.test.js +385 -0
- package/test/refactorer.test.js +277 -211
- package/test/scanner.test.js +34 -32
- package/test/style-organizer.test.js +106 -106
- package/test/theme-utils.test.js +140 -0
package/THEME-GUIDE.md
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# Theme Generation and Global Styles Example
|
|
2
|
+
|
|
3
|
+
This guide demonstrates the new features for theme generation and global styles preservation.
|
|
4
|
+
|
|
5
|
+
## 1. Generate Theme Structure
|
|
6
|
+
|
|
7
|
+
First, generate a complete theme structure for your Angular Material app:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Analyze existing styles and generate themes
|
|
11
|
+
npx scss-extract generate-themes ./src --analyze --output ./src/styles
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
This creates:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
src/styles/
|
|
18
|
+
├── _theme-base.scss # Shared variables (spacing, typography)
|
|
19
|
+
├── _theme-light.scss # Light mode colors
|
|
20
|
+
├── _theme-dark.scss # Dark mode colors
|
|
21
|
+
├── themes.scss # Material theme loader
|
|
22
|
+
├── _css-variables.scss # CSS custom properties
|
|
23
|
+
└── _component-theme-mixin.scss # Theme mixin template
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 2. Modernize Components (Preserve Global Styles)
|
|
27
|
+
|
|
28
|
+
Next, refactor your components to remove ::ng-deep and !important while preserving the styles globally:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Preview changes
|
|
32
|
+
npx scss-extract modernize ./src --dry-run
|
|
33
|
+
|
|
34
|
+
# Apply modernization with global preservation
|
|
35
|
+
npx scss-extract modernize ./src --global-styles ./src/styles/global-overrides.scss
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Before (component-a.component.scss):**
|
|
39
|
+
|
|
40
|
+
```scss
|
|
41
|
+
.container {
|
|
42
|
+
padding: 16px;
|
|
43
|
+
|
|
44
|
+
::ng-deep .mat-dialog-container {
|
|
45
|
+
border-radius: 8px !important; // Override Material's default
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.header {
|
|
49
|
+
color: #1976d2 !important; // Prevent parent override
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**After modernization:**
|
|
55
|
+
|
|
56
|
+
**component-a.component.scss:**
|
|
57
|
+
|
|
58
|
+
```scss
|
|
59
|
+
.container {
|
|
60
|
+
padding: 16px;
|
|
61
|
+
|
|
62
|
+
// ng-deep and !important removed - see global-overrides.scss
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**src/styles/global-overrides.scss:**
|
|
67
|
+
|
|
68
|
+
```scss
|
|
69
|
+
/* Moved from component-a.component.scss - requires !important for specificity */
|
|
70
|
+
.container .mat-dialog-container {
|
|
71
|
+
border-radius: 8px !important;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Moved from component-a.component.scss - requires !important for specificity */
|
|
75
|
+
.container .header {
|
|
76
|
+
color: #1976d2 !important;
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
✅ **Benefits:**
|
|
81
|
+
|
|
82
|
+
- Styles are preserved with proper specificity
|
|
83
|
+
- No parent component overrides
|
|
84
|
+
- Follows Angular Material v15+ best practices
|
|
85
|
+
- Centralized global styles for easier maintenance
|
|
86
|
+
|
|
87
|
+
## 3. Set Up Theme Switching
|
|
88
|
+
|
|
89
|
+
Import the generated themes in your `styles.scss`:
|
|
90
|
+
|
|
91
|
+
```scss
|
|
92
|
+
@use './styles/themes';
|
|
93
|
+
@use './styles/global-overrides';
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Add theme toggle to your app component:
|
|
97
|
+
|
|
98
|
+
**app.component.ts:**
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { Component } from '@angular/core';
|
|
102
|
+
|
|
103
|
+
@Component({
|
|
104
|
+
selector: 'app-root',
|
|
105
|
+
templateUrl: './app.component.html',
|
|
106
|
+
styleUrls: ['./app.component.scss'],
|
|
107
|
+
})
|
|
108
|
+
export class AppComponent {
|
|
109
|
+
isDarkMode = false;
|
|
110
|
+
|
|
111
|
+
constructor() {
|
|
112
|
+
// Check user preference or localStorage
|
|
113
|
+
const savedTheme = localStorage.getItem('theme');
|
|
114
|
+
this.isDarkMode = savedTheme === 'dark';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
toggleTheme() {
|
|
118
|
+
this.isDarkMode = !this.isDarkMode;
|
|
119
|
+
localStorage.setItem('theme', this.isDarkMode ? 'dark' : 'light');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**app.component.html:**
|
|
125
|
+
|
|
126
|
+
```html
|
|
127
|
+
<div [class.dark-theme]="isDarkMode">
|
|
128
|
+
<mat-toolbar color="primary">
|
|
129
|
+
<span>My App</span>
|
|
130
|
+
<span class="spacer"></span>
|
|
131
|
+
<button mat-icon-button (click)="toggleTheme()">
|
|
132
|
+
<mat-icon>{{ isDarkMode ? 'light_mode' : 'dark_mode' }}</mat-icon>
|
|
133
|
+
</button>
|
|
134
|
+
</mat-toolbar>
|
|
135
|
+
|
|
136
|
+
<router-outlet></router-outlet>
|
|
137
|
+
</div>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## 4. Use Theme Variables in Components
|
|
141
|
+
|
|
142
|
+
Instead of hardcoded values, use the generated theme variables:
|
|
143
|
+
|
|
144
|
+
**Before:**
|
|
145
|
+
|
|
146
|
+
```scss
|
|
147
|
+
.my-card {
|
|
148
|
+
padding: 16px;
|
|
149
|
+
margin: 24px;
|
|
150
|
+
border-radius: 8px;
|
|
151
|
+
background: #ffffff;
|
|
152
|
+
color: rgba(0, 0, 0, 0.87);
|
|
153
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**After:**
|
|
158
|
+
|
|
159
|
+
```scss
|
|
160
|
+
@use '../../styles/theme-base' as base;
|
|
161
|
+
|
|
162
|
+
.my-card {
|
|
163
|
+
padding: base.$spacing-md;
|
|
164
|
+
margin: base.$spacing-lg;
|
|
165
|
+
border-radius: base.$border-radius-md;
|
|
166
|
+
background: var(--surface-color);
|
|
167
|
+
color: var(--text-primary);
|
|
168
|
+
box-shadow: base.$shadow-sm;
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
✅ **Benefits:**
|
|
173
|
+
|
|
174
|
+
- Automatic dark/light mode switching
|
|
175
|
+
- Consistent spacing and design tokens
|
|
176
|
+
- No hardcoded values
|
|
177
|
+
- Easy theme updates
|
|
178
|
+
|
|
179
|
+
## 5. Create Component Theme Mixins (Advanced)
|
|
180
|
+
|
|
181
|
+
For components that need different colors in light/dark themes:
|
|
182
|
+
|
|
183
|
+
**my-component.theme.scss:**
|
|
184
|
+
|
|
185
|
+
```scss
|
|
186
|
+
@use '@angular/material' as mat;
|
|
187
|
+
|
|
188
|
+
@mixin component-theme($theme) {
|
|
189
|
+
$color-config: mat.get-color-config($theme);
|
|
190
|
+
|
|
191
|
+
@if $color-config != null {
|
|
192
|
+
$primary: map.get($color-config, 'primary');
|
|
193
|
+
$background: map.get($color-config, 'background');
|
|
194
|
+
|
|
195
|
+
.my-special-component {
|
|
196
|
+
background-color: mat.get-color-from-palette($background, 'card');
|
|
197
|
+
border-left: 4px solid mat.get-color-from-palette($primary);
|
|
198
|
+
|
|
199
|
+
&__header {
|
|
200
|
+
background-color: mat.get-color-from-palette($primary);
|
|
201
|
+
color: mat.get-color-from-palette($primary, 'default-contrast');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Then include in `themes.scss`:
|
|
209
|
+
|
|
210
|
+
```scss
|
|
211
|
+
@use './my-component.theme' as my-component;
|
|
212
|
+
|
|
213
|
+
// Light theme
|
|
214
|
+
@include my-component.component-theme($light-theme);
|
|
215
|
+
|
|
216
|
+
// Dark theme
|
|
217
|
+
.dark-theme {
|
|
218
|
+
@include my-component.component-theme($dark-theme);
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## 6. Auto-Format Code
|
|
223
|
+
|
|
224
|
+
Keep your code consistently formatted:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# Format all files
|
|
228
|
+
npm run format
|
|
229
|
+
|
|
230
|
+
# Check formatting (CI/CD)
|
|
231
|
+
npm run format:check
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
The formatter runs automatically before releases.
|
|
235
|
+
|
|
236
|
+
## Complete Workflow Example
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
# 1. Generate theme structure
|
|
240
|
+
npx scss-extract generate-themes ./src --analyze
|
|
241
|
+
|
|
242
|
+
# 2. Extract hardcoded values to variables
|
|
243
|
+
npx scss-extract refactor ./src --output ./src/styles/_variables.scss
|
|
244
|
+
|
|
245
|
+
# 3. Modernize components (preserve global styles)
|
|
246
|
+
npx scss-extract modernize ./src --global-styles ./src/styles/global-overrides.scss
|
|
247
|
+
|
|
248
|
+
# 4. Detect and migrate Bootstrap (if applicable)
|
|
249
|
+
npx scss-extract detect-bootstrap ./src
|
|
250
|
+
npx scss-extract migrate-bootstrap ./src
|
|
251
|
+
|
|
252
|
+
# 5. Format code
|
|
253
|
+
npm run format
|
|
254
|
+
|
|
255
|
+
# 6. Run tests and commit
|
|
256
|
+
npm test
|
|
257
|
+
git add .
|
|
258
|
+
git commit -m "feat: Implement theme system and modernize styles"
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Best Practices Summary
|
|
262
|
+
|
|
263
|
+
✅ **DO:**
|
|
264
|
+
|
|
265
|
+
- Use theme variables for all colors
|
|
266
|
+
- Use base variables for spacing, typography, shadows
|
|
267
|
+
- Move global styles to dedicated files
|
|
268
|
+
- Use CSS custom properties for runtime theme switching
|
|
269
|
+
- Create component theme mixins for complex theming
|
|
270
|
+
- Format code regularly
|
|
271
|
+
|
|
272
|
+
❌ **DON'T:**
|
|
273
|
+
|
|
274
|
+
- Use ::ng-deep (use theme mixins instead)
|
|
275
|
+
- Hardcode colors (use theme variables)
|
|
276
|
+
- Hardcode spacing (use base spacing scale)
|
|
277
|
+
- Use ViewEncapsulation.None unnecessarily
|
|
278
|
+
- Mix !important in component files (move to global)
|
|
279
|
+
|
|
280
|
+
## Result
|
|
281
|
+
|
|
282
|
+
🎨 **Professional Theme System:**
|
|
283
|
+
|
|
284
|
+
- Dark and light modes
|
|
285
|
+
- Consistent design tokens
|
|
286
|
+
- Maintainable global styles
|
|
287
|
+
- No ViewEncapsulation issues
|
|
288
|
+
- Material Design aligned
|
|
289
|
+
- Easy to extend and customize
|