@mrdemonwolf/iconwolf 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA8BrE,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAqH7B"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAgCrE,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAgI7B"}
package/dist/generator.js CHANGED
@@ -8,19 +8,21 @@ import { generateStandardIcon } from './variants/standard.js';
8
8
  import { generateFavicon } from './variants/favicon.js';
9
9
  import { generateSplashIcon } from './variants/splash.js';
10
10
  import { generateAndroidIcons } from './variants/android.js';
11
+ import { applyBanner, shouldApplyBanner } from './utils/banner.js';
11
12
  async function resolveInput(resolvedPath, bgColor, silent) {
12
13
  if (isIconComposerFolder(resolvedPath)) {
13
14
  if (!silent)
14
15
  logger.info(`Apple Icon Composer file: ${resolvedPath}`);
15
16
  const result = await renderIconComposerFolder(resolvedPath);
16
17
  const inputPath = result.composedImagePath;
18
+ const foregroundPath = result.foregroundImagePath;
17
19
  const cleanupPath = path.dirname(result.composedImagePath);
18
20
  if (bgColor === '#FFFFFF') {
19
21
  bgColor = result.extractedBgColor;
20
22
  if (!silent)
21
23
  logger.info(`Extracted background color: ${bgColor}`);
22
24
  }
23
- return { inputPath, cleanupPath, bgColor };
25
+ return { inputPath, foregroundPath, cleanupPath, bgColor };
24
26
  }
25
27
  return { inputPath: resolvedPath, bgColor };
26
28
  }
@@ -37,6 +39,7 @@ export async function generate(options) {
37
39
  throw new Error(`Source not found: ${resolvedInput}`);
38
40
  }
39
41
  let inputPath;
42
+ let foregroundPath;
40
43
  let cleanupPath;
41
44
  let splashPath;
42
45
  let splashCleanupPath;
@@ -44,6 +47,7 @@ export async function generate(options) {
44
47
  // Resolve main input (Apple Icon Composer .icon folder or PNG)
45
48
  const mainInput = await resolveInput(resolvedInput, bgColor, silent);
46
49
  inputPath = mainInput.inputPath;
50
+ foregroundPath = mainInput.foregroundPath;
47
51
  cleanupPath = mainInput.cleanupPath;
48
52
  bgColor = mainInput.bgColor;
49
53
  // Resolve splash input if provided
@@ -53,7 +57,7 @@ export async function generate(options) {
53
57
  throw new Error(`Splash source not found: ${resolvedSplashInput}`);
54
58
  }
55
59
  const splashInput = await resolveInput(resolvedSplashInput, bgColor, silent);
56
- splashPath = splashInput.inputPath;
60
+ splashPath = splashInput.foregroundPath ?? splashInput.inputPath;
57
61
  splashCleanupPath = splashInput.cleanupPath;
58
62
  }
59
63
  // Validate source image
@@ -100,11 +104,19 @@ export async function generate(options) {
100
104
  logger.generated(result);
101
105
  }
102
106
  if (generateAll || variants.splash) {
103
- const result = await generateSplashIcon(splashPath || inputPath, outputDir);
107
+ const result = await generateSplashIcon(splashPath || foregroundPath || inputPath, outputDir);
104
108
  results.push(result);
105
109
  if (!silent)
106
110
  logger.generated(result);
107
111
  }
112
+ // Apply banner overlay if requested
113
+ if (options.banner) {
114
+ for (const result of results) {
115
+ if (shouldApplyBanner(result.filePath)) {
116
+ await applyBanner(result, options.banner);
117
+ }
118
+ }
119
+ }
108
120
  if (!silent)
109
121
  logger.summary(results);
110
122
  return results;
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { generate } from './generator.js';
4
4
  import * as logger from './utils/logger.js';
5
5
  import { resolveDefaultOutputDir } from './utils/paths.js';
6
6
  import { readCachedUpdateInfo, refreshCacheInBackground, } from './utils/update-notifier.js';
7
- const VERSION = '0.1.0';
7
+ const VERSION = '0.2.0';
8
8
  const program = new Command();
9
9
  program
10
10
  .name('iconwolf')
@@ -18,6 +18,9 @@ program
18
18
  .option('--icon', 'Generate standard icon.png only')
19
19
  .option('--splash-input <path>', 'Use a separate image for the splash screen icon')
20
20
  .option('--bg-color <hex>', 'Background color for Android adaptive icon', '#FFFFFF')
21
+ .option('--banner <text>', 'Diagonal ribbon banner text (e.g. DEV, BETA, STAGING)')
22
+ .option('--banner-color <hex>', 'Ribbon color (default: auto from text)')
23
+ .option('--banner-position <pos>', 'Banner position: top-left, top-right, bottom-left, bottom-right', 'top-left')
21
24
  .action(async (input, opts) => {
22
25
  const updateInfo = readCachedUpdateInfo(VERSION);
23
26
  refreshCacheInBackground().catch(() => { });
@@ -32,6 +35,13 @@ program
32
35
  },
33
36
  bgColor: opts.bgColor,
34
37
  splashInputPath: opts.splashInput,
38
+ banner: opts.banner
39
+ ? {
40
+ text: opts.banner,
41
+ color: opts.bannerColor,
42
+ position: opts.bannerPosition,
43
+ }
44
+ : undefined,
35
45
  };
36
46
  try {
37
47
  await generate(options);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AAGpC,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CACV,+GAA+G,CAChH;KACA,OAAO,CAAC,OAAO,CAAC;KAChB,QAAQ,CACP,SAAS,EACT,6DAA6D,CAC9D;KACA,MAAM,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,CAAC;KAC3E,MAAM,CAAC,WAAW,EAAE,8CAA8C,CAAC;KACnE,MAAM,CAAC,WAAW,EAAE,2BAA2B,CAAC;KAChD,MAAM,CAAC,UAAU,EAAE,kCAAkC,CAAC;KACtD,MAAM,CAAC,QAAQ,EAAE,iCAAiC,CAAC;KACnD,MAAM,CACL,uBAAuB,EACvB,iDAAiD,CAClD;KACA,MAAM,CACL,kBAAkB,EAClB,4CAA4C,EAC5C,SAAS,CACV;KACA,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,IAAI,EAAE,EAAE;IACpC,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACjD,wBAAwB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAE3C,MAAM,OAAO,GAAqB;QAChC,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,IAAI,CAAC,MAAM;QACtB,QAAQ,EAAE;YACR,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK;YAC9B,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK;YAC9B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;YAC5B,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK;SACzB;QACD,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,eAAe,EAAE,IAAI,CAAC,WAAW;KAClC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;QAExB,IAAI,UAAU,EAAE,eAAe,EAAE,CAAC;YAChC,MAAM,CAAC,YAAY,CACjB,UAAU,CAAC,cAAc,EACzB,UAAU,CAAC,aAAa,CACzB,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AAGpC,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CACV,+GAA+G,CAChH;KACA,OAAO,CAAC,OAAO,CAAC;KAChB,QAAQ,CACP,SAAS,EACT,6DAA6D,CAC9D;KACA,MAAM,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,CAAC;KAC3E,MAAM,CAAC,WAAW,EAAE,8CAA8C,CAAC;KACnE,MAAM,CAAC,WAAW,EAAE,2BAA2B,CAAC;KAChD,MAAM,CAAC,UAAU,EAAE,kCAAkC,CAAC;KACtD,MAAM,CAAC,QAAQ,EAAE,iCAAiC,CAAC;KACnD,MAAM,CACL,uBAAuB,EACvB,iDAAiD,CAClD;KACA,MAAM,CACL,kBAAkB,EAClB,4CAA4C,EAC5C,SAAS,CACV;KACA,MAAM,CACL,iBAAiB,EACjB,uDAAuD,CACxD;KACA,MAAM,CAAC,sBAAsB,EAAE,wCAAwC,CAAC;KACxE,MAAM,CACL,yBAAyB,EACzB,iEAAiE,EACjE,UAAU,CACX;KACA,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,IAAI,EAAE,EAAE;IACpC,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACjD,wBAAwB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAE3C,MAAM,OAAO,GAAqB;QAChC,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,IAAI,CAAC,MAAM;QACtB,QAAQ,EAAE;YACR,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK;YAC9B,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK;YAC9B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;YAC5B,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK;SACzB;QACD,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,eAAe,EAAE,IAAI,CAAC,WAAW;QACjC,MAAM,EAAE,IAAI,CAAC,MAAM;YACjB,CAAC,CAAC;gBACE,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,KAAK,EAAE,IAAI,CAAC,WAAW;gBACvB,QAAQ,EAAE,IAAI,CAAC,cAAgC;aAChD;YACH,CAAC,CAAC,SAAS;KACd,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;QAExB,IAAI,UAAU,EAAE,eAAe,EAAE,CAAC;YAChC,MAAM,CAAC,YAAY,CACjB,UAAU,CAAC,cAAc,EACzB,UAAU,CAAC,aAAa,CACzB,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
package/dist/lib.d.ts CHANGED
@@ -4,7 +4,8 @@ export { generateFavicon } from './variants/favicon.js';
4
4
  export { generateSplashIcon } from './variants/splash.js';
5
5
  export { generateAndroidIcons } from './variants/android.js';
6
6
  export { validateSourceImage } from './utils/image.js';
7
+ export { applyBanner, createBannerSvg, shouldApplyBanner } from './utils/banner.js';
7
8
  export { isIconComposerFolder, renderIconComposerFolder, } from './utils/icon-composer.js';
8
9
  export { OUTPUT_FILES, resolveOutputPath } from './utils/paths.js';
9
- export type { VariantFlags, GeneratorOptions, GenerationResult, } from './types.js';
10
+ export type { BannerOptions, BannerPosition, VariantFlags, GeneratorOptions, GenerationResult, } from './types.js';
10
11
  //# sourceMappingURL=lib.d.ts.map
package/dist/lib.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EACL,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACnE,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"lib.d.ts","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EACL,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACnE,YAAY,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
package/dist/lib.js CHANGED
@@ -4,6 +4,7 @@ export { generateFavicon } from './variants/favicon.js';
4
4
  export { generateSplashIcon } from './variants/splash.js';
5
5
  export { generateAndroidIcons } from './variants/android.js';
6
6
  export { validateSourceImage } from './utils/image.js';
7
+ export { applyBanner, createBannerSvg, shouldApplyBanner } from './utils/banner.js';
7
8
  export { isIconComposerFolder, renderIconComposerFolder, } from './utils/icon-composer.js';
8
9
  export { OUTPUT_FILES, resolveOutputPath } from './utils/paths.js';
9
10
  //# sourceMappingURL=lib.js.map
package/dist/lib.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EACL,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"lib.js","sourceRoot":"","sources":["../src/lib.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EACL,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
package/dist/types.d.ts CHANGED
@@ -1,3 +1,9 @@
1
+ export type BannerPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
2
+ export interface BannerOptions {
3
+ text: string;
4
+ color?: string;
5
+ position?: BannerPosition;
6
+ }
1
7
  export interface VariantFlags {
2
8
  android: boolean;
3
9
  favicon: boolean;
@@ -10,6 +16,7 @@ export interface GeneratorOptions {
10
16
  variants: VariantFlags;
11
17
  bgColor: string;
12
18
  splashInputPath?: string;
19
+ banner?: BannerOptions;
13
20
  silent?: boolean;
14
21
  }
15
22
  export interface GenerationResult {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GACtB,UAAU,GACV,WAAW,GACX,aAAa,GACb,cAAc,CAAC;AAEnB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd"}
@@ -0,0 +1,5 @@
1
+ import type { BannerOptions, BannerPosition, GenerationResult } from '../types.js';
2
+ export declare function createBannerSvg(size: number, text: string, color: string, position: BannerPosition): string;
3
+ export declare function applyBanner(result: GenerationResult, bannerOptions: BannerOptions): Promise<void>;
4
+ export declare function shouldApplyBanner(filePath: string): boolean;
5
+ //# sourceMappingURL=banner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.d.ts","sourceRoot":"","sources":["../../src/utils/banner.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAgBnF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,cAAc,GACvB,MAAM,CA0CR;AAUD,wBAAsB,WAAW,CAC/B,MAAM,EAAE,gBAAgB,EACxB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,IAAI,CAAC,CAqBf;AASD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE3D"}
@@ -0,0 +1,88 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import sharp from 'sharp';
4
+ const DEFAULT_COLORS = {
5
+ DEV: '#4CAF50',
6
+ BETA: '#FF9800',
7
+ STAGING: '#2196F3',
8
+ ALPHA: '#9C27B0',
9
+ };
10
+ const FALLBACK_COLOR = '#F44336';
11
+ function resolveColor(text, color) {
12
+ if (color)
13
+ return color;
14
+ return DEFAULT_COLORS[text.toUpperCase()] ?? FALLBACK_COLOR;
15
+ }
16
+ export function createBannerSvg(size, text, color, position) {
17
+ const ribbonWidth = Math.round(size * 0.42);
18
+ const ribbonHeight = Math.round(size * 0.08);
19
+ const fontSize = Math.round(ribbonHeight * 0.6);
20
+ const halfDiag = ribbonWidth / 2;
21
+ // Center of the ribbon in each corner
22
+ let cx;
23
+ let cy;
24
+ let angle;
25
+ switch (position) {
26
+ case 'top-left':
27
+ cx = size * 0.2;
28
+ cy = size * 0.2;
29
+ angle = -45;
30
+ break;
31
+ case 'top-right':
32
+ cx = size * 0.8;
33
+ cy = size * 0.2;
34
+ angle = 45;
35
+ break;
36
+ case 'bottom-left':
37
+ cx = size * 0.2;
38
+ cy = size * 0.8;
39
+ angle = 45;
40
+ break;
41
+ case 'bottom-right':
42
+ cx = size * 0.8;
43
+ cy = size * 0.8;
44
+ angle = -45;
45
+ break;
46
+ }
47
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
48
+ <g transform="translate(${cx}, ${cy}) rotate(${angle})">
49
+ <rect x="${-halfDiag}" y="${-ribbonHeight / 2}" width="${ribbonWidth}" height="${ribbonHeight}" fill="${color}"/>
50
+ <text x="0" y="0" text-anchor="middle" dominant-baseline="central"
51
+ font-family="Arial, Helvetica, sans-serif" font-weight="bold"
52
+ font-size="${fontSize}" fill="white">${escapeXml(text)}</text>
53
+ </g>
54
+ </svg>`;
55
+ }
56
+ function escapeXml(s) {
57
+ return s
58
+ .replace(/&/g, '&amp;')
59
+ .replace(/</g, '&lt;')
60
+ .replace(/>/g, '&gt;')
61
+ .replace(/"/g, '&quot;');
62
+ }
63
+ export async function applyBanner(result, bannerOptions) {
64
+ const color = resolveColor(bannerOptions.text, bannerOptions.color);
65
+ const position = bannerOptions.position ?? 'top-left';
66
+ const meta = await sharp(result.filePath).metadata();
67
+ const size = meta.width ?? 1024;
68
+ const svg = createBannerSvg(size, bannerOptions.text, color, position);
69
+ const svgBuffer = Buffer.from(svg);
70
+ const tmpPath = result.filePath + '.tmp';
71
+ await sharp(result.filePath)
72
+ .composite([{ input: svgBuffer, top: 0, left: 0 }])
73
+ .png()
74
+ .toFile(tmpPath);
75
+ fs.renameSync(tmpPath, result.filePath);
76
+ const stat = fs.statSync(result.filePath);
77
+ result.size = stat.size;
78
+ }
79
+ /** Files that should not receive a banner overlay. */
80
+ const SKIP_FILES = new Set([
81
+ 'favicon.png',
82
+ 'android-icon-background.png',
83
+ 'monochrome-icon.png',
84
+ ]);
85
+ export function shouldApplyBanner(filePath) {
86
+ return !SKIP_FILES.has(path.basename(filePath));
87
+ }
88
+ //# sourceMappingURL=banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.js","sourceRoot":"","sources":["../../src/utils/banner.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  export interface IconComposerResult {
2
2
  composedImagePath: string;
3
+ foregroundImagePath: string;
3
4
  extractedBgColor: string;
4
5
  }
5
6
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"icon-composer.d.ts","sourceRoot":"","sources":["../../src/utils/icon-composer.ts"],"names":[],"mappings":"AAsCA,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAS/D;AA6HD;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAgG7B"}
1
+ {"version":3,"file":"icon-composer.d.ts","sourceRoot":"","sources":["../../src/utils/icon-composer.ts"],"names":[],"mappings":"AAsCA,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAS/D;AA6HD;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAoH7B"}
@@ -185,15 +185,32 @@ export async function renderIconComposerFolder(iconFolderPath) {
185
185
  compositeOps.push({ input: layerBuffer, left, top });
186
186
  }
187
187
  }
188
- // Compose final image
188
+ // Compose final image (with background)
189
189
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'iconwolf-compose-'));
190
190
  const composedPath = path.join(tmpDir, 'composed-icon.png');
191
191
  await sharp(backgroundBuffer)
192
192
  .composite(compositeOps)
193
193
  .png()
194
194
  .toFile(composedPath);
195
+ // Compose foreground-only image (transparent background) for splash
196
+ const foregroundPath = path.join(tmpDir, 'foreground-icon.png');
197
+ const transparentBg = await sharp({
198
+ create: {
199
+ width: ICON_SIZE,
200
+ height: ICON_SIZE,
201
+ channels: 4,
202
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
203
+ },
204
+ })
205
+ .png()
206
+ .toBuffer();
207
+ await sharp(transparentBg)
208
+ .composite(compositeOps)
209
+ .png()
210
+ .toFile(foregroundPath);
195
211
  return {
196
212
  composedImagePath: composedPath,
213
+ foregroundImagePath: foregroundPath,
197
214
  extractedBgColor,
198
215
  };
199
216
  }
@@ -1 +1 @@
1
- {"version":3,"file":"icon-composer.js","sourceRoot":"","sources":["../../src/utils/icon-composer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"icon-composer.js","sourceRoot":"","sources":["../../src/utils/icon-composer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,SAAS,GAAG,IAAI,CAAC;AAuCvB;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB;IACpD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;YAAE,OAAO,KAAK,CAAC;QACtC,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,KAAa;IAMnC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAC1E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,OAAO;QACL,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QACzC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QACzC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QACzC,CAAC,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KACxB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;IAC/C,OAAO,CACL,GAAG;QACH,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;aACN,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;aAC3C,IAAI,CAAC,EAAE,CAAC;aACR,WAAW,EAAE,CACjB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CACxB,MAAgB,EAChB,WAGC,EACD,IAAY;IAEZ,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChD,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAEjD,MAAM,KAAK,GAAG,YAAY;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACZ,MAAM,MAAM,GACV,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;QACxE,OAAO,iBAAiB,MAAM,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,MAAM,CAAC;IACrG,CAAC,CAAC;SACD,IAAI,CAAC,UAAU,CAAC,CAAC;IAEpB,OAAO,eAAe,IAAI,aAAa,IAAI;;kCAEX,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE;QAChE,KAAK;;;iBAGI,IAAI,aAAa,IAAI;OAC/B,CAAC;AACR,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,gBAAgB,CAC7B,IAAsB;IAEtB,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QACnE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;QAC9D,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO;YACL,MAAM;YACN,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;SAC5D,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;IAC5C,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC;YACzB,MAAM,EAAE;gBACN,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,SAAS;gBACjB,QAAQ,EAAE,CAAC;gBACX,UAAU,EAAE;oBACV,CAAC,EAAE,KAAK,CAAC,CAAC;oBACV,CAAC,EAAE,KAAK,CAAC,CAAC;oBACV,CAAC,EAAE,KAAK,CAAC,CAAC;oBACV,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC;iBACjC;aACF;SACF,CAAC;aACC,GAAG,EAAE;aACL,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,CAAC;IAED,6BAA6B;IAC7B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC;QACzB,MAAM,EAAE;YACN,KAAK,EAAE,SAAS;YAChB,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;SACnD;KACF,CAAC;SACC,GAAG,EAAE;SACL,QAAQ,EAAE,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,cAAsB;IAEtB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IAEvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,0BAA0B,cAAc,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAyB,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAE/D,oBAAoB;IACpB,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAC3D,MAAM,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAExC,4CAA4C;IAC5C,MAAM,YAAY,GAA2B,EAAE,CAAC;IAEhD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;YAC7D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAI,KAAK,CAAC,0BAA0B,SAAS,EAAE,CAAC,CAAC;YACzD,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC/C,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChC,MAAM,IAAI,KAAK,CACb,oCAAoC,KAAK,CAAC,YAAY,CAAC,EAAE,CAC1D,CAAC;YACJ,CAAC;YAED,wCAAwC;YACxC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClE,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAEpE,8DAA8D;YAC9D,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC;YACtD,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;YAC1D,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;YAE1D,IAAI,WAAW,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC;iBACrC,MAAM,CAAC,WAAW,EAAE,YAAY,EAAE;gBACjC,GAAG,EAAE,SAAS;gBACd,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;aAC3C,CAAC;iBACD,GAAG,EAAE;iBACL,QAAQ,EAAE,CAAC;YAEd,iEAAiE;YACjE,IACE,IAAI,GAAG,CAAC;gBACR,GAAG,GAAG,CAAC;gBACP,IAAI,GAAG,WAAW,GAAG,SAAS;gBAC9B,GAAG,GAAG,YAAY,GAAG,SAAS,EAC9B,CAAC;gBACD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBACpC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;gBAClC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,GAAG,IAAI,CAAC,CAAC;gBAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,SAAS,GAAG,GAAG,CAAC,CAAC;gBAC3D,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;gBACvC,MAAM,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;gBAExC,IAAI,SAAS,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC;oBAAE,SAAS;gBAEhD,WAAW,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC;qBACnC,OAAO,CAAC;oBACP,IAAI,EAAE,QAAQ;oBACd,GAAG,EAAE,OAAO;oBACZ,KAAK,EAAE,SAAS;oBAChB,MAAM,EAAE,UAAU;iBACnB,CAAC;qBACD,GAAG,EAAE;qBACL,QAAQ,EAAE,CAAC;gBACd,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;gBACzB,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YACzB,CAAC;YAED,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,MAAM,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAE5D,MAAM,KAAK,CAAC,gBAAgB,CAAC;SAC1B,SAAS,CAAC,YAAY,CAAC;SACvB,GAAG,EAAE;SACL,MAAM,CAAC,YAAY,CAAC,CAAC;IAExB,oEAAoE;IACpE,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAEhE,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC;QAChC,MAAM,EAAE;YACN,KAAK,EAAE,SAAS;YAChB,MAAM,EAAE,SAAS;YACjB,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;SAC3C;KACF,CAAC;SACC,GAAG,EAAE;SACL,QAAQ,EAAE,CAAC;IAEd,MAAM,KAAK,CAAC,aAAa,CAAC;SACvB,SAAS,CAAC,YAAY,CAAC;SACvB,GAAG,EAAE;SACL,MAAM,CAAC,cAAc,CAAC,CAAC;IAE1B,OAAO;QACL,iBAAiB,EAAE,YAAY;QAC/B,mBAAmB,EAAE,cAAc;QACnC,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrdemonwolf/iconwolf",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "A CLI tool that takes an iOS app compositor icon and generates all necessary icon variants for cross-platform use.",
5
5
  "type": "module",
6
6
  "main": "./dist/lib.js",
package/src/generator.ts CHANGED
@@ -11,10 +11,12 @@ import { generateStandardIcon } from './variants/standard.js';
11
11
  import { generateFavicon } from './variants/favicon.js';
12
12
  import { generateSplashIcon } from './variants/splash.js';
13
13
  import { generateAndroidIcons } from './variants/android.js';
14
+ import { applyBanner, shouldApplyBanner } from './utils/banner.js';
14
15
  import type { GeneratorOptions, GenerationResult } from './types.js';
15
16
 
16
17
  interface ResolvedInput {
17
18
  inputPath: string;
19
+ foregroundPath?: string;
18
20
  cleanupPath?: string;
19
21
  bgColor: string;
20
22
  }
@@ -28,6 +30,7 @@ async function resolveInput(
28
30
  if (!silent) logger.info(`Apple Icon Composer file: ${resolvedPath}`);
29
31
  const result = await renderIconComposerFolder(resolvedPath);
30
32
  const inputPath = result.composedImagePath;
33
+ const foregroundPath = result.foregroundImagePath;
31
34
  const cleanupPath = path.dirname(result.composedImagePath);
32
35
 
33
36
  if (bgColor === '#FFFFFF') {
@@ -35,7 +38,7 @@ async function resolveInput(
35
38
  if (!silent) logger.info(`Extracted background color: ${bgColor}`);
36
39
  }
37
40
 
38
- return { inputPath, cleanupPath, bgColor };
41
+ return { inputPath, foregroundPath, cleanupPath, bgColor };
39
42
  }
40
43
 
41
44
  return { inputPath: resolvedPath, bgColor };
@@ -58,6 +61,7 @@ export async function generate(
58
61
  }
59
62
 
60
63
  let inputPath: string;
64
+ let foregroundPath: string | undefined;
61
65
  let cleanupPath: string | undefined;
62
66
  let splashPath: string | undefined;
63
67
  let splashCleanupPath: string | undefined;
@@ -66,6 +70,7 @@ export async function generate(
66
70
  // Resolve main input (Apple Icon Composer .icon folder or PNG)
67
71
  const mainInput = await resolveInput(resolvedInput, bgColor, silent);
68
72
  inputPath = mainInput.inputPath;
73
+ foregroundPath = mainInput.foregroundPath;
69
74
  cleanupPath = mainInput.cleanupPath;
70
75
  bgColor = mainInput.bgColor;
71
76
 
@@ -80,7 +85,7 @@ export async function generate(
80
85
  bgColor,
81
86
  silent,
82
87
  );
83
- splashPath = splashInput.inputPath;
88
+ splashPath = splashInput.foregroundPath ?? splashInput.inputPath;
84
89
  splashCleanupPath = splashInput.cleanupPath;
85
90
  }
86
91
 
@@ -141,13 +146,22 @@ export async function generate(
141
146
 
142
147
  if (generateAll || variants.splash) {
143
148
  const result = await generateSplashIcon(
144
- splashPath || inputPath,
149
+ splashPath || foregroundPath || inputPath,
145
150
  outputDir,
146
151
  );
147
152
  results.push(result);
148
153
  if (!silent) logger.generated(result);
149
154
  }
150
155
 
156
+ // Apply banner overlay if requested
157
+ if (options.banner) {
158
+ for (const result of results) {
159
+ if (shouldApplyBanner(result.filePath)) {
160
+ await applyBanner(result, options.banner);
161
+ }
162
+ }
163
+ }
164
+
151
165
  if (!silent) logger.summary(results);
152
166
 
153
167
  return results;
package/src/index.ts CHANGED
@@ -8,9 +8,9 @@ import {
8
8
  readCachedUpdateInfo,
9
9
  refreshCacheInBackground,
10
10
  } from './utils/update-notifier.js';
11
- import type { GeneratorOptions } from './types.js';
11
+ import type { BannerPosition, GeneratorOptions } from './types.js';
12
12
 
13
- const VERSION = '0.1.0';
13
+ const VERSION = '0.2.0';
14
14
 
15
15
  const program = new Command();
16
16
 
@@ -38,6 +38,16 @@ program
38
38
  'Background color for Android adaptive icon',
39
39
  '#FFFFFF',
40
40
  )
41
+ .option(
42
+ '--banner <text>',
43
+ 'Diagonal ribbon banner text (e.g. DEV, BETA, STAGING)',
44
+ )
45
+ .option('--banner-color <hex>', 'Ribbon color (default: auto from text)')
46
+ .option(
47
+ '--banner-position <pos>',
48
+ 'Banner position: top-left, top-right, bottom-left, bottom-right',
49
+ 'top-left',
50
+ )
41
51
  .action(async (input: string, opts) => {
42
52
  const updateInfo = readCachedUpdateInfo(VERSION);
43
53
  refreshCacheInBackground().catch(() => {});
@@ -53,6 +63,13 @@ program
53
63
  },
54
64
  bgColor: opts.bgColor,
55
65
  splashInputPath: opts.splashInput,
66
+ banner: opts.banner
67
+ ? {
68
+ text: opts.banner,
69
+ color: opts.bannerColor,
70
+ position: opts.bannerPosition as BannerPosition,
71
+ }
72
+ : undefined,
56
73
  };
57
74
 
58
75
  try {
package/src/lib.ts CHANGED
@@ -4,12 +4,15 @@ export { generateFavicon } from './variants/favicon.js';
4
4
  export { generateSplashIcon } from './variants/splash.js';
5
5
  export { generateAndroidIcons } from './variants/android.js';
6
6
  export { validateSourceImage } from './utils/image.js';
7
+ export { applyBanner, createBannerSvg, shouldApplyBanner } from './utils/banner.js';
7
8
  export {
8
9
  isIconComposerFolder,
9
10
  renderIconComposerFolder,
10
11
  } from './utils/icon-composer.js';
11
12
  export { OUTPUT_FILES, resolveOutputPath } from './utils/paths.js';
12
13
  export type {
14
+ BannerOptions,
15
+ BannerPosition,
13
16
  VariantFlags,
14
17
  GeneratorOptions,
15
18
  GenerationResult,
package/src/types.ts CHANGED
@@ -1,3 +1,15 @@
1
+ export type BannerPosition =
2
+ | 'top-left'
3
+ | 'top-right'
4
+ | 'bottom-left'
5
+ | 'bottom-right';
6
+
7
+ export interface BannerOptions {
8
+ text: string;
9
+ color?: string;
10
+ position?: BannerPosition;
11
+ }
12
+
1
13
  export interface VariantFlags {
2
14
  android: boolean;
3
15
  favicon: boolean;
@@ -11,6 +23,7 @@ export interface GeneratorOptions {
11
23
  variants: VariantFlags;
12
24
  bgColor: string;
13
25
  splashInputPath?: string;
26
+ banner?: BannerOptions;
14
27
  silent?: boolean;
15
28
  }
16
29
 
@@ -0,0 +1,112 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import sharp from 'sharp';
4
+ import type { BannerOptions, BannerPosition, GenerationResult } from '../types.js';
5
+
6
+ const DEFAULT_COLORS: Record<string, string> = {
7
+ DEV: '#4CAF50',
8
+ BETA: '#FF9800',
9
+ STAGING: '#2196F3',
10
+ ALPHA: '#9C27B0',
11
+ };
12
+
13
+ const FALLBACK_COLOR = '#F44336';
14
+
15
+ function resolveColor(text: string, color?: string): string {
16
+ if (color) return color;
17
+ return DEFAULT_COLORS[text.toUpperCase()] ?? FALLBACK_COLOR;
18
+ }
19
+
20
+ export function createBannerSvg(
21
+ size: number,
22
+ text: string,
23
+ color: string,
24
+ position: BannerPosition,
25
+ ): string {
26
+ const ribbonWidth = Math.round(size * 0.42);
27
+ const ribbonHeight = Math.round(size * 0.08);
28
+ const fontSize = Math.round(ribbonHeight * 0.6);
29
+ const halfDiag = ribbonWidth / 2;
30
+
31
+ // Center of the ribbon in each corner
32
+ let cx: number;
33
+ let cy: number;
34
+ let angle: number;
35
+
36
+ switch (position) {
37
+ case 'top-left':
38
+ cx = size * 0.2;
39
+ cy = size * 0.2;
40
+ angle = -45;
41
+ break;
42
+ case 'top-right':
43
+ cx = size * 0.8;
44
+ cy = size * 0.2;
45
+ angle = 45;
46
+ break;
47
+ case 'bottom-left':
48
+ cx = size * 0.2;
49
+ cy = size * 0.8;
50
+ angle = 45;
51
+ break;
52
+ case 'bottom-right':
53
+ cx = size * 0.8;
54
+ cy = size * 0.8;
55
+ angle = -45;
56
+ break;
57
+ }
58
+
59
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
60
+ <g transform="translate(${cx}, ${cy}) rotate(${angle})">
61
+ <rect x="${-halfDiag}" y="${-ribbonHeight / 2}" width="${ribbonWidth}" height="${ribbonHeight}" fill="${color}"/>
62
+ <text x="0" y="0" text-anchor="middle" dominant-baseline="central"
63
+ font-family="Arial, Helvetica, sans-serif" font-weight="bold"
64
+ font-size="${fontSize}" fill="white">${escapeXml(text)}</text>
65
+ </g>
66
+ </svg>`;
67
+ }
68
+
69
+ function escapeXml(s: string): string {
70
+ return s
71
+ .replace(/&/g, '&amp;')
72
+ .replace(/</g, '&lt;')
73
+ .replace(/>/g, '&gt;')
74
+ .replace(/"/g, '&quot;');
75
+ }
76
+
77
+ export async function applyBanner(
78
+ result: GenerationResult,
79
+ bannerOptions: BannerOptions,
80
+ ): Promise<void> {
81
+ const color = resolveColor(bannerOptions.text, bannerOptions.color);
82
+ const position = bannerOptions.position ?? 'top-left';
83
+
84
+ const meta = await sharp(result.filePath).metadata();
85
+ const size = meta.width ?? 1024;
86
+
87
+ const svg = createBannerSvg(size, bannerOptions.text, color, position);
88
+ const svgBuffer = Buffer.from(svg);
89
+
90
+ const tmpPath = result.filePath + '.tmp';
91
+
92
+ await sharp(result.filePath)
93
+ .composite([{ input: svgBuffer, top: 0, left: 0 }])
94
+ .png()
95
+ .toFile(tmpPath);
96
+
97
+ fs.renameSync(tmpPath, result.filePath);
98
+
99
+ const stat = fs.statSync(result.filePath);
100
+ result.size = stat.size;
101
+ }
102
+
103
+ /** Files that should not receive a banner overlay. */
104
+ const SKIP_FILES = new Set([
105
+ 'favicon.png',
106
+ 'android-icon-background.png',
107
+ 'monochrome-icon.png',
108
+ ]);
109
+
110
+ export function shouldApplyBanner(filePath: string): boolean {
111
+ return !SKIP_FILES.has(path.basename(filePath));
112
+ }
@@ -38,6 +38,7 @@ interface IconComposerManifest {
38
38
 
39
39
  export interface IconComposerResult {
40
40
  composedImagePath: string;
41
+ foregroundImagePath: string;
41
42
  extractedBgColor: string;
42
43
  }
43
44
 
@@ -267,7 +268,7 @@ export async function renderIconComposerFolder(
267
268
  }
268
269
  }
269
270
 
270
- // Compose final image
271
+ // Compose final image (with background)
271
272
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'iconwolf-compose-'));
272
273
  const composedPath = path.join(tmpDir, 'composed-icon.png');
273
274
 
@@ -276,8 +277,28 @@ export async function renderIconComposerFolder(
276
277
  .png()
277
278
  .toFile(composedPath);
278
279
 
280
+ // Compose foreground-only image (transparent background) for splash
281
+ const foregroundPath = path.join(tmpDir, 'foreground-icon.png');
282
+
283
+ const transparentBg = await sharp({
284
+ create: {
285
+ width: ICON_SIZE,
286
+ height: ICON_SIZE,
287
+ channels: 4,
288
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
289
+ },
290
+ })
291
+ .png()
292
+ .toBuffer();
293
+
294
+ await sharp(transparentBg)
295
+ .composite(compositeOps)
296
+ .png()
297
+ .toFile(foregroundPath);
298
+
279
299
  return {
280
300
  composedImagePath: composedPath,
301
+ foregroundImagePath: foregroundPath,
281
302
  extractedBgColor,
282
303
  };
283
304
  }
package/tests/cli.test.ts CHANGED
@@ -40,6 +40,9 @@ describe('CLI end-to-end', () => {
40
40
  expect(output).toContain('--icon');
41
41
  expect(output).toContain('--splash-input');
42
42
  expect(output).toContain('--bg-color');
43
+ expect(output).toContain('--banner');
44
+ expect(output).toContain('--banner-color');
45
+ expect(output).toContain('--banner-position');
43
46
  });
44
47
 
45
48
  it('generates icon.png via CLI with --icon flag', () => {
@@ -73,6 +76,14 @@ describe('CLI end-to-end', () => {
73
76
  }).toThrow();
74
77
  });
75
78
 
79
+ it('generates icon with --banner DEV flag', () => {
80
+ const outDir = path.join(tmpDir, 'cli-banner');
81
+
82
+ runCli(`${testPng} --icon --banner DEV -o ${outDir}`);
83
+
84
+ expect(fs.existsSync(path.join(outDir, 'icon.png'))).toBe(true);
85
+ });
86
+
76
87
  it('generates favicon when --favicon flag is used', () => {
77
88
  const outDir = path.join(tmpDir, 'cli-favicon');
78
89
 
@@ -347,6 +347,52 @@ describe('generate', () => {
347
347
  expect(fs.existsSync(path.join(outDir, 'splash-icon.png'))).toBe(true);
348
348
  });
349
349
 
350
+ it('applies banner to icon, adaptive-icon, and splash but not favicon', async () => {
351
+ const outDir = path.join(tmpDir, 'banner-test');
352
+
353
+ const results = await generate({
354
+ inputPath: testPng,
355
+ outputDir: outDir,
356
+ variants: { android: false, favicon: false, splash: false, icon: false },
357
+ bgColor: '#FFFFFF',
358
+ banner: { text: 'DEV' },
359
+ });
360
+
361
+ // All 4 default files should exist
362
+ expect(fs.existsSync(path.join(outDir, OUTPUT_FILES.icon))).toBe(true);
363
+ expect(fs.existsSync(path.join(outDir, OUTPUT_FILES.favicon))).toBe(true);
364
+ expect(fs.existsSync(path.join(outDir, OUTPUT_FILES.splashIcon))).toBe(true);
365
+ expect(
366
+ fs.existsSync(path.join(outDir, OUTPUT_FILES.androidForeground)),
367
+ ).toBe(true);
368
+ expect(results.length).toBe(4);
369
+ });
370
+
371
+ it('skips banner on background and monochrome android variants', async () => {
372
+ const outDir = path.join(tmpDir, 'banner-android');
373
+
374
+ const results = await generate({
375
+ inputPath: testPng,
376
+ outputDir: outDir,
377
+ variants: { android: true, favicon: false, splash: false, icon: false },
378
+ bgColor: '#FFFFFF',
379
+ banner: { text: 'STAGING', color: '#2196F3' },
380
+ });
381
+
382
+ // adaptive-icon.png should exist (banner applied)
383
+ expect(
384
+ fs.existsSync(path.join(outDir, OUTPUT_FILES.androidForeground)),
385
+ ).toBe(true);
386
+ // background and monochrome should exist (no banner)
387
+ expect(
388
+ fs.existsSync(path.join(outDir, OUTPUT_FILES.androidBackground)),
389
+ ).toBe(true);
390
+ expect(
391
+ fs.existsSync(path.join(outDir, OUTPUT_FILES.androidMonochrome)),
392
+ ).toBe(true);
393
+ expect(results.length).toBe(3);
394
+ });
395
+
350
396
  it('throws on missing splash input file', async () => {
351
397
  const outDir = path.join(tmpDir, 'splash-missing');
352
398
 
@@ -0,0 +1,123 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import sharp from 'sharp';
4
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
5
+ import {
6
+ createBannerSvg,
7
+ applyBanner,
8
+ shouldApplyBanner,
9
+ } from '../../src/utils/banner.js';
10
+ import { createTestPng, createTmpDir, cleanDir } from '../helpers.js';
11
+
12
+ let tmpDir: string;
13
+
14
+ beforeAll(() => {
15
+ tmpDir = createTmpDir();
16
+ });
17
+
18
+ afterAll(() => {
19
+ cleanDir(tmpDir);
20
+ });
21
+
22
+ describe('createBannerSvg', () => {
23
+ it('generates valid SVG with correct dimensions', () => {
24
+ const svg = createBannerSvg(1024, 'DEV', '#4CAF50', 'top-left');
25
+ expect(svg).toContain('width="1024"');
26
+ expect(svg).toContain('height="1024"');
27
+ expect(svg).toContain('DEV');
28
+ expect(svg).toContain('#4CAF50');
29
+ });
30
+
31
+ it('renders different positions', () => {
32
+ const positions = [
33
+ 'top-left',
34
+ 'top-right',
35
+ 'bottom-left',
36
+ 'bottom-right',
37
+ ] as const;
38
+
39
+ for (const pos of positions) {
40
+ const svg = createBannerSvg(1024, 'BETA', '#FF9800', pos);
41
+ expect(svg).toContain('BETA');
42
+ expect(svg).toContain('<svg');
43
+ }
44
+ });
45
+
46
+ it('escapes XML characters in text', () => {
47
+ const svg = createBannerSvg(1024, 'A&B<C>', '#FF0000', 'top-left');
48
+ expect(svg).toContain('A&amp;B&lt;C&gt;');
49
+ });
50
+
51
+ it('scales ribbon proportionally to icon size', () => {
52
+ const svg512 = createBannerSvg(512, 'DEV', '#4CAF50', 'top-left');
53
+ const svg1024 = createBannerSvg(1024, 'DEV', '#4CAF50', 'top-left');
54
+ expect(svg512).toContain('width="512"');
55
+ expect(svg1024).toContain('width="1024"');
56
+ });
57
+ });
58
+
59
+ describe('applyBanner', () => {
60
+ it('composites banner onto a PNG file', async () => {
61
+ const pngPath = await createTestPng(1024, 1024, tmpDir, 'banner-test.png');
62
+ const originalSize = fs.statSync(pngPath).size;
63
+
64
+ const result = { filePath: pngPath, width: 1024, height: 1024, size: originalSize };
65
+
66
+ await applyBanner(result, { text: 'DEV' });
67
+
68
+ expect(fs.existsSync(pngPath)).toBe(true);
69
+ // The file should still be a valid PNG
70
+ const meta = await sharp(pngPath).metadata();
71
+ expect(meta.width).toBe(1024);
72
+ expect(meta.height).toBe(1024);
73
+ expect(meta.format).toBe('png');
74
+ // Size in result should be updated
75
+ expect(result.size).toBe(fs.statSync(pngPath).size);
76
+ });
77
+
78
+ it('uses custom color when provided', async () => {
79
+ const pngPath = await createTestPng(1024, 1024, tmpDir, 'banner-custom-color.png');
80
+ const result = { filePath: pngPath, width: 1024, height: 1024, size: fs.statSync(pngPath).size };
81
+
82
+ await applyBanner(result, { text: 'TEST', color: '#FF00FF' });
83
+
84
+ const meta = await sharp(pngPath).metadata();
85
+ expect(meta.width).toBe(1024);
86
+ });
87
+
88
+ it('uses custom position', async () => {
89
+ const pngPath = await createTestPng(1024, 1024, tmpDir, 'banner-pos.png');
90
+ const result = { filePath: pngPath, width: 1024, height: 1024, size: fs.statSync(pngPath).size };
91
+
92
+ await applyBanner(result, { text: 'DEV', position: 'bottom-right' });
93
+
94
+ const meta = await sharp(pngPath).metadata();
95
+ expect(meta.width).toBe(1024);
96
+ });
97
+ });
98
+
99
+ describe('shouldApplyBanner', () => {
100
+ it('returns true for icon.png', () => {
101
+ expect(shouldApplyBanner('/out/icon.png')).toBe(true);
102
+ });
103
+
104
+ it('returns true for adaptive-icon.png', () => {
105
+ expect(shouldApplyBanner('/out/adaptive-icon.png')).toBe(true);
106
+ });
107
+
108
+ it('returns true for splash-icon.png', () => {
109
+ expect(shouldApplyBanner('/out/splash-icon.png')).toBe(true);
110
+ });
111
+
112
+ it('returns false for favicon.png', () => {
113
+ expect(shouldApplyBanner('/out/favicon.png')).toBe(false);
114
+ });
115
+
116
+ it('returns false for android-icon-background.png', () => {
117
+ expect(shouldApplyBanner('/out/android-icon-background.png')).toBe(false);
118
+ });
119
+
120
+ it('returns false for monochrome-icon.png', () => {
121
+ expect(shouldApplyBanner('/out/monochrome-icon.png')).toBe(false);
122
+ });
123
+ });