@@ -2,23 +2,73 @@ import type { CSSRule, HeadwindConfig, ParsedClass } from './types'
22import { builtInRules } from './rules'
33import { parseClass } from './parser'
44
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+
523/**
624 * Generates CSS rules from parsed utility classes
725 */
826export class CSSGenerator {
927 private rules : Map < string , CSSRule [ ] > = new Map ( )
1028
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+ }
1239
1340 /**
1441 * Generate CSS for a utility class
1542 */
1643 generate ( className : string ) : void {
1744 const parsed = parseClass ( className )
1845
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+ }
2272 }
2373
2474 // Try built-in rules
@@ -36,18 +86,6 @@ export class CSSGenerator {
3686 }
3787 }
3888
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-
5189 // Check shortcuts
5290 const shortcut = this . config . shortcuts [ className ]
5391 if ( shortcut ) {
0 commit comments