@@ -14,11 +14,24 @@ export default defineWxtModule<AutoIconsOptions>({
14
14
{
15
15
enabled : true ,
16
16
baseIconPath : resolve ( wxt . config . srcDir , 'assets/icon.png' ) ,
17
- grayscaleOnDevelopment : true ,
17
+ developmentIndicator : 'grayscale' ,
18
18
sizes : [ 128 , 48 , 32 , 16 ] ,
19
19
} ,
20
20
) ;
21
21
22
+ // Backward compatibility for the deprecated option
23
+ if ( options ?. grayscaleOnDevelopment !== undefined ) {
24
+ wxt . logger . warn (
25
+ '`[auto-icons]` "grayscaleOnDevelopment" is deprecated. Use "developmentIndicator" instead.' ,
26
+ ) ;
27
+
28
+ if ( options ?. developmentIndicator === undefined ) {
29
+ parsedOptions . developmentIndicator = options ! . grayscaleOnDevelopment
30
+ ? 'grayscale'
31
+ : false ;
32
+ }
33
+ }
34
+
22
35
const resolvedPath = resolve ( wxt . config . srcDir , parsedOptions . baseIconPath ) ;
23
36
24
37
if ( ! parsedOptions . enabled )
@@ -42,21 +55,44 @@ export default defineWxtModule<AutoIconsOptions>({
42
55
} ) ;
43
56
44
57
wxt . hooks . hook ( 'build:done' , async ( wxt , output ) => {
45
- const image = sharp ( resolvedPath ) . png ( ) ;
46
-
47
- if (
48
- wxt . config . mode === 'development' &&
49
- parsedOptions . grayscaleOnDevelopment
50
- ) {
51
- image . grayscale ( ) ;
52
- }
53
-
54
58
const outputFolder = wxt . config . outDir ;
55
59
56
60
for ( const size of parsedOptions . sizes ) {
57
- const resized = image . resize ( size ) ;
61
+ const resizedImage = sharp ( resolvedPath ) . resize ( size ) . png ( ) ;
62
+
63
+ if ( wxt . config . mode === 'development' ) {
64
+ if ( parsedOptions . developmentIndicator === 'grayscale' ) {
65
+ resizedImage . grayscale ( ) ;
66
+ } else if ( parsedOptions . developmentIndicator === 'overlay' ) {
67
+ // Helper to build an overlay that places a yellow rectangle at the bottom
68
+ // of the icon with the text "DEV" in black. The overlay has the same
69
+ // dimensions as the icon so we can composite it with default gravity.
70
+ const buildDevOverlay = ( size : number ) => {
71
+ const rectHeight = Math . round ( size * 0.5 ) ;
72
+ const fontSize = Math . round ( size * 0.35 ) ;
73
+
74
+ return Buffer . from ( `<?xml version="1.0" encoding="UTF-8"?>
75
+ <svg width="${ size } " height="${ size } " viewBox="0 0 ${ size } ${ size } " xmlns="http://www.w3.org/2000/svg">
76
+ <rect x="0" y="${ size - rectHeight } " width="${ size } " height="${ rectHeight } " fill="#ffff00" />
77
+ <text x="${ size / 2 } " y="${ size - rectHeight / 2 } " font-family="Arial, Helvetica, sans-serif" font-size="${ fontSize } " font-weight="bold" fill="black" text-anchor="middle" dominant-baseline="middle">DEV</text>
78
+ </svg>` ) ;
79
+ } ;
80
+ const overlayBuffer = await sharp ( buildDevOverlay ( size ) )
81
+ . png ( )
82
+ . toBuffer ( ) ;
83
+
84
+ resizedImage . composite ( [
85
+ {
86
+ input : overlayBuffer ,
87
+ left : 0 ,
88
+ top : 0 ,
89
+ } ,
90
+ ] ) ;
91
+ }
92
+ }
93
+
58
94
ensureDir ( resolve ( outputFolder , 'icons' ) ) ;
59
- await resized . toFile ( resolve ( outputFolder , `icons/${ size } .png` ) ) ;
95
+ await resizedImage . toFile ( resolve ( outputFolder , `icons/${ size } .png` ) ) ;
60
96
61
97
output . publicAssets . push ( {
62
98
type : 'asset' ,
@@ -89,9 +125,20 @@ export interface AutoIconsOptions {
89
125
* @default "<srcDir>/assets/icon.png"
90
126
*/
91
127
baseIconPath ?: string ;
128
+ /**
129
+ * Apply a visual indicator to the icon when running in development mode.
130
+ *
131
+ * "grayscale" converts the icon to grayscale.
132
+ * "overlay" covers the bottom half with a yellow rectangle and writes "DEV" in black text.
133
+ * Set to `false` to disable any indicator.
134
+ *
135
+ * @default "grayscale"
136
+ */
137
+ developmentIndicator ?: 'grayscale' | 'overlay' | false ;
92
138
/**
93
139
* Grayscale the image when in development mode to indicate development
94
140
* @default true
141
+ * @deprecated Use `developmentIndicator` instead
95
142
*/
96
143
grayscaleOnDevelopment ?: boolean ;
97
144
/**
0 commit comments