@@ -2,23 +2,73 @@ import type { CSSRule, HeadwindConfig, ParsedClass } from './types'
2
2
import { builtInRules } from './rules'
3
3
import { parseClass } from './parser'
4
4
5
+ /**
6
+ * Deep merge objects
7
+ */
8
+ function deepMerge < T extends Record < string , any > > ( target : T , source : Partial < T > ) : T {
9
+ const result = { ...target }
10
+ for ( const key in source ) {
11
+ const sourceValue = source [ key ]
12
+ const targetValue = result [ key ]
13
+ if ( sourceValue && typeof sourceValue === 'object' && ! Array . isArray ( sourceValue ) && targetValue && typeof targetValue === 'object' && ! Array . isArray ( targetValue ) ) {
14
+ result [ key ] = deepMerge ( targetValue , sourceValue )
15
+ }
16
+ else if ( sourceValue !== undefined ) {
17
+ result [ key ] = sourceValue as any
18
+ }
19
+ }
20
+ return result
21
+ }
22
+
5
23
/**
6
24
* Generates CSS rules from parsed utility classes
7
25
*/
8
26
export class CSSGenerator {
9
27
private rules : Map < string , CSSRule [ ] > = new Map ( )
10
28
11
- constructor ( private config : HeadwindConfig ) { }
29
+ constructor ( private config : HeadwindConfig ) {
30
+ // Merge preset themes into the main config theme
31
+ if ( config . presets && config . presets . length > 0 ) {
32
+ for ( const preset of config . presets ) {
33
+ if ( preset . theme ) {
34
+ this . config . theme = deepMerge ( this . config . theme , preset . theme )
35
+ }
36
+ }
37
+ }
38
+ }
12
39
13
40
/**
14
41
* Generate CSS for a utility class
15
42
*/
16
43
generate ( className : string ) : void {
17
44
const parsed = parseClass ( className )
18
45
19
- // Check if class is blocklisted
20
- if ( this . config . blocklist . includes ( className ) ) {
21
- return
46
+ // Check if class is blocklisted (supports wildcards)
47
+ for ( const pattern of this . config . blocklist ) {
48
+ if ( pattern . includes ( '*' ) ) {
49
+ // Convert wildcard pattern to regex
50
+ const regexPattern = pattern . replace ( / \* / g, '.*' )
51
+ const regex = new RegExp ( `^${ regexPattern } $` )
52
+ if ( regex . test ( className ) ) {
53
+ return
54
+ }
55
+ }
56
+ else if ( pattern === className ) {
57
+ // Exact match
58
+ return
59
+ }
60
+ }
61
+
62
+ // Try custom rules from config first (allows overriding built-in rules)
63
+ for ( const [ pattern , handler ] of this . config . rules ) {
64
+ const match = className . match ( pattern )
65
+ if ( match ) {
66
+ const properties = handler ( match )
67
+ if ( properties ) {
68
+ this . addRule ( parsed , properties )
69
+ return
70
+ }
71
+ }
22
72
}
23
73
24
74
// Try built-in rules
@@ -36,18 +86,6 @@ export class CSSGenerator {
36
86
}
37
87
}
38
88
39
- // Try custom rules from config
40
- for ( const [ pattern , handler ] of this . config . rules ) {
41
- const match = className . match ( pattern )
42
- if ( match ) {
43
- const properties = handler ( match )
44
- if ( properties ) {
45
- this . addRule ( parsed , properties )
46
- return
47
- }
48
- }
49
- }
50
-
51
89
// Check shortcuts
52
90
const shortcut = this . config . shortcuts [ className ]
53
91
if ( shortcut ) {
0 commit comments