@@ -184,6 +184,7 @@ describe('wordpressPlugin', () => {
184184 const result = ( plugin . options as any ) ( {
185185 input : 'src/index.ts' ,
186186 } ) as InputOptions ;
187+
187188 const external = result . external as ( id : string ) => boolean ;
188189
189190 expect ( external ( '@wordpress/element' ) ) . toBe ( true ) ;
@@ -195,6 +196,7 @@ describe('wordpressPlugin', () => {
195196 const result = ( plugin . options as any ) ( {
196197 input : 'src/index.ts' ,
197198 } ) as InputOptions ;
199+
198200 const external = result . external as ( id : string ) => boolean ;
199201
200202 expect ( external ( 'react' ) ) . toBe ( false ) ;
@@ -266,6 +268,7 @@ describe('wordpressThemeJson', () => {
266268 vi . mocked ( fs . readFileSync ) . mockReturnValue (
267269 JSON . stringify ( mockBaseThemeJson )
268270 ) ;
271+
269272 vi . mocked ( path . resolve ) . mockImplementation ( ( ...paths : string [ ] ) =>
270273 paths . join ( '/' )
271274 ) ;
@@ -289,36 +292,16 @@ describe('wordpressThemeJson', () => {
289292 }
290293 ` ;
291294
292- // Transform to capture CSS content
293295 ( plugin . transform as any ) ( cssContent , 'app.css' ) ;
294-
295- // Mock emitFile to capture theme.json
296296 const emitFile = vi . fn ( ) ;
297297 ( plugin . generateBundle as any ) . call ( { emitFile } ) ;
298298
299299 expect ( emitFile ) . toHaveBeenCalledWith (
300300 expect . objectContaining ( {
301301 fileName : 'assets/theme.json' ,
302- source : expect . stringContaining ( '"name": "primary "' ) ,
302+ source : expect . stringContaining ( '"name": "Primary "' ) ,
303303 } )
304304 ) ;
305-
306- const themeJson = JSON . parse ( emitFile . mock . calls [ 0 ] [ 0 ] . source ) ;
307- expect ( themeJson . settings . color . palette ) . toContainEqual ( {
308- name : 'primary' ,
309- slug : 'primary' ,
310- color : '#000000' ,
311- } ) ;
312- expect ( themeJson . settings . typography . fontFamilies ) . toContainEqual ( {
313- name : 'inter' ,
314- slug : 'inter' ,
315- fontFamily : 'Inter' ,
316- } ) ;
317- expect ( themeJson . settings . typography . fontSizes ) . toContainEqual ( {
318- name : 'lg' ,
319- slug : 'lg' ,
320- size : '1.125rem' ,
321- } ) ;
322305 } ) ;
323306
324307 it ( 'should handle numeric color shades' , ( ) => {
@@ -329,6 +312,10 @@ describe('wordpressThemeJson', () => {
329312 const cssContent = `
330313 @theme {
331314 --color-red-500: #ef4444;
315+ --color-blue-100: #e0f2fe;
316+ --color-primary: #000000;
317+ --color-white: #ffffff;
318+ --color-black: #000000;
332319 }
333320 ` ;
334321
@@ -337,11 +324,36 @@ describe('wordpressThemeJson', () => {
337324 ( plugin . generateBundle as any ) . call ( { emitFile } ) ;
338325
339326 const themeJson = JSON . parse ( emitFile . mock . calls [ 0 ] [ 0 ] . source ) ;
327+
340328 expect ( themeJson . settings . color . palette ) . toContainEqual ( {
341- name : 'red- 500' ,
329+ name : 'Red ( 500) ' ,
342330 slug : 'red-500' ,
343331 color : '#ef4444' ,
344332 } ) ;
333+
334+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
335+ name : 'Blue (100)' ,
336+ slug : 'blue-100' ,
337+ color : '#e0f2fe' ,
338+ } ) ;
339+
340+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
341+ name : 'Primary' ,
342+ slug : 'primary' ,
343+ color : '#000000' ,
344+ } ) ;
345+
346+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
347+ name : 'White' ,
348+ slug : 'white' ,
349+ color : '#ffffff' ,
350+ } ) ;
351+
352+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
353+ name : 'Black' ,
354+ slug : 'black' ,
355+ color : '#000000' ,
356+ } ) ;
345357 } ) ;
346358
347359 it ( 'should respect disable flags' , ( ) => {
@@ -365,6 +377,7 @@ describe('wordpressThemeJson', () => {
365377 ( plugin . generateBundle as any ) . call ( { emitFile } ) ;
366378
367379 const themeJson = JSON . parse ( emitFile . mock . calls [ 0 ] [ 0 ] . source ) ;
380+
368381 expect ( themeJson . settings . color ?. palette ) . toBeUndefined ( ) ;
369382 expect ( themeJson . settings . typography . fontFamilies ) . toBeUndefined ( ) ;
370383 expect ( themeJson . settings . typography . fontSizes ) . toBeUndefined ( ) ;
@@ -435,6 +448,117 @@ describe('wordpressThemeJson', () => {
435448 ) . rejects . toThrow ( 'Unclosed @theme { block - missing closing brace' ) ;
436449 } ) ;
437450
451+ it ( 'should handle shade labels' , ( ) => {
452+ const plugin = wordpressThemeJson ( {
453+ tailwindConfig : mockTailwindConfig ,
454+ shadeLabels : {
455+ '50' : 'Lightest' ,
456+ '100' : 'Lighter' ,
457+ '500' : 'Default' ,
458+ '900' : 'Darkest' ,
459+ } ,
460+ } ) ;
461+
462+ const cssContent = `
463+ @theme {
464+ --color-blue-50: #f0f9ff;
465+ --color-blue-100: #e0f2fe;
466+ --color-blue-500: #3b82f6;
467+ --color-blue-900: #1e3a8a;
468+ --color-primary: #000000;
469+ }
470+ ` ;
471+
472+ ( plugin . transform as any ) ( cssContent , 'app.css' ) ;
473+ const emitFile = vi . fn ( ) ;
474+ ( plugin . generateBundle as any ) . call ( { emitFile } ) ;
475+
476+ const themeJson = JSON . parse ( emitFile . mock . calls [ 0 ] [ 0 ] . source ) ;
477+
478+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
479+ name : 'Lightest Blue' ,
480+ slug : 'blue-50' ,
481+ color : '#f0f9ff' ,
482+ } ) ;
483+
484+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
485+ name : 'Lighter Blue' ,
486+ slug : 'blue-100' ,
487+ color : '#e0f2fe' ,
488+ } ) ;
489+
490+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
491+ name : 'Default Blue' ,
492+ slug : 'blue-500' ,
493+ color : '#3b82f6' ,
494+ } ) ;
495+
496+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
497+ name : 'Darkest Blue' ,
498+ slug : 'blue-900' ,
499+ color : '#1e3a8a' ,
500+ } ) ;
501+
502+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
503+ name : 'Primary' ,
504+ slug : 'primary' ,
505+ color : '#000000' ,
506+ } ) ;
507+ } ) ;
508+
509+ it ( 'should format shades without labels as Color (shade)' , ( ) => {
510+ const plugin = wordpressThemeJson ( {
511+ tailwindConfig : mockTailwindConfig ,
512+ // No shade labels configured
513+ } ) ;
514+
515+ const cssContent = `
516+ @theme {
517+ --color-blue-50: #f0f9ff;
518+ --color-blue-100: #e0f2fe;
519+ --color-red-500: #ef4444;
520+ --color-gray-900: #111827;
521+ --color-primary: #000000;
522+ }
523+ ` ;
524+
525+ ( plugin . transform as any ) ( cssContent , 'app.css' ) ;
526+ const emitFile = vi . fn ( ) ;
527+ ( plugin . generateBundle as any ) . call ( { emitFile } ) ;
528+
529+ const themeJson = JSON . parse ( emitFile . mock . calls [ 0 ] [ 0 ] . source ) ;
530+
531+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
532+ name : 'Blue (50)' ,
533+ slug : 'blue-50' ,
534+ color : '#f0f9ff' ,
535+ } ) ;
536+
537+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
538+ name : 'Blue (100)' ,
539+ slug : 'blue-100' ,
540+ color : '#e0f2fe' ,
541+ } ) ;
542+
543+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
544+ name : 'Red (500)' ,
545+ slug : 'red-500' ,
546+ color : '#ef4444' ,
547+ } ) ;
548+
549+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
550+ name : 'Gray (900)' ,
551+ slug : 'gray-900' ,
552+ color : '#111827' ,
553+ } ) ;
554+
555+ expect ( themeJson . settings . color . palette ) . toContainEqual ( {
556+ name : 'Primary' ,
557+ slug : 'primary' ,
558+ color : '#000000' ,
559+ } ) ;
560+ } ) ;
561+
438562 it ( 'should preserve existing theme.json settings' , ( ) => {
439563 const existingThemeJson = {
440564 settings : {
0 commit comments