@@ -14,11 +14,24 @@ export default defineWxtModule<AutoIconsOptions>({
1414 {
1515 enabled : true ,
1616 baseIconPath : resolve ( wxt . config . srcDir , 'assets/icon.png' ) ,
17- grayscaleOnDevelopment : true ,
17+ developmentIndicator : 'grayscale' ,
1818 sizes : [ 128 , 48 , 32 , 16 ] ,
1919 } ,
2020 ) ;
2121
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+
2235 const resolvedPath = resolve ( wxt . config . srcDir , parsedOptions . baseIconPath ) ;
2336
2437 if ( ! parsedOptions . enabled )
@@ -42,21 +55,44 @@ export default defineWxtModule<AutoIconsOptions>({
4255 } ) ;
4356
4457 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-
5458 const outputFolder = wxt . config . outDir ;
5559
5660 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+
5894 ensureDir ( resolve ( outputFolder , 'icons' ) ) ;
59- await resized . toFile ( resolve ( outputFolder , `icons/${ size } .png` ) ) ;
95+ await resizedImage . toFile ( resolve ( outputFolder , `icons/${ size } .png` ) ) ;
6096
6197 output . publicAssets . push ( {
6298 type : 'asset' ,
@@ -89,9 +125,20 @@ export interface AutoIconsOptions {
89125 * @default "<srcDir>/assets/icon.png"
90126 */
91127 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 ;
92138 /**
93139 * Grayscale the image when in development mode to indicate development
94140 * @default true
141+ * @deprecated Use `developmentIndicator` instead
95142 */
96143 grayscaleOnDevelopment ?: boolean ;
97144 /**
0 commit comments