build(icons): migrate icon rasterization to rsvg-convert\n\n- Replace ImageMagick (magick/convert) with rsvg-convert in build script\n- Update icons/README to document rsvg-convert requirement
This commit is contained in:
		
					parent
					
						
							
								815fc66219
							
						
					
				
			
			
				commit
				
					
						f293092657
					
				
			
		
					 2 changed files with 18 additions and 21 deletions
				
			
		| 
						 | 
					@ -15,8 +15,8 @@ Run `npm run build` (or `npm run build:icons`) to regenerate. The manifest is wi
 | 
				
			||||||
Notes
 | 
					Notes
 | 
				
			||||||
-----
 | 
					-----
 | 
				
			||||||
- Source: `icons/file-search.svg` defines the exact stroke color (an emphasis color) directly in the SVG.
 | 
					- Source: `icons/file-search.svg` defines the exact stroke color (an emphasis color) directly in the SVG.
 | 
				
			||||||
- The build script does not inject or replace colors; it rasterizes the SVG as-is to transparent PNGs using ImageMagick.
 | 
					- The build script does not inject or replace colors; it rasterizes the SVG as-is to transparent PNGs using `rsvg-convert`.
 | 
				
			||||||
- To change the icon color, edit the `stroke="#..."` attribute in `icons/file-search.svg`.
 | 
					- To change the icon color, edit the `stroke="#..."` attribute in `icons/file-search.svg`.
 | 
				
			||||||
- Firefox does not require .ico; PNG is recommended.
 | 
					- Firefox does not require .ico; PNG is recommended.
 | 
				
			||||||
- Theme variants can be added later via `browser_action.theme_icons` if desired.
 | 
					- Theme variants can be added later via `browser_action.theme_icons` if desired.
 | 
				
			||||||
- Rasterizer: uses ImageMagick only (`magick` or `convert`). Ensure your ImageMagick build supports reading SVG (via `librsvg` or a compatible delegate).
 | 
					- Rasterizer: uses `rsvg-convert` (from librsvg). Ensure it is installed and available on your PATH.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
#!/usr/bin/env node
 | 
					#!/usr/bin/env node
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 Generates extension and toolbar PNG icons from the base SVG with transparent
 | 
					 Generates extension and toolbar PNG icons from the base SVG with transparent
 | 
				
			||||||
 background. Requires ImageMagick (`magick` or `convert`).
 | 
					 background. Requires `rsvg-convert` (from librsvg).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 The SVG defines its own stroke color (set directly in icons/file-search.svg).
 | 
					 The SVG defines its own stroke color (set directly in icons/file-search.svg).
 | 
				
			||||||
 To change colors, edit the SVG; the script does not inject or replace colors.
 | 
					 To change colors, edit the SVG; the script does not inject or replace colors.
 | 
				
			||||||
| 
						 | 
					@ -20,54 +20,51 @@ const SRC_SVG = path.join(ICONS_DIR, 'file-search.svg');
 | 
				
			||||||
const ADDON_SIZES = [48, 96, 128];
 | 
					const ADDON_SIZES = [48, 96, 128];
 | 
				
			||||||
const TOOLBAR_SIZES = [16, 32];
 | 
					const TOOLBAR_SIZES = [16, 32];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function ensureMagick() {
 | 
					function ensureRsvgConvert() {
 | 
				
			||||||
  try {
 | 
					  try {
 | 
				
			||||||
    let res = spawnSync('magick', ['-version'], { stdio: 'ignore' });
 | 
					    const res = spawnSync('rsvg-convert', ['--version'], { stdio: 'ignore' });
 | 
				
			||||||
    if (res && res.status === 0) return 'magick';
 | 
					    if (res && res.status === 0) return 'rsvg-convert';
 | 
				
			||||||
    res = spawnSync('convert', ['-version'], { stdio: 'ignore' });
 | 
					 | 
				
			||||||
    if (res && res.status === 0) return 'convert';
 | 
					 | 
				
			||||||
  } catch (_) {}
 | 
					  } catch (_) {}
 | 
				
			||||||
  return null;
 | 
					  return null;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function readSvg() {
 | 
					function assertSvgExists() {
 | 
				
			||||||
  if (!fs.existsSync(SRC_SVG)) {
 | 
					  if (!fs.existsSync(SRC_SVG)) {
 | 
				
			||||||
    console.error(`Base SVG not found: ${path.relative(REPO_ROOT, SRC_SVG)}`);
 | 
					    console.error(`Base SVG not found: ${path.relative(REPO_ROOT, SRC_SVG)}`);
 | 
				
			||||||
    process.exit(1);
 | 
					    process.exit(1);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return fs.readFileSync(SRC_SVG, 'utf8');
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function rasterize(magickBin, svgString, size, outPath) {
 | 
					function rasterize(rsvgBin, size, outPath) {
 | 
				
			||||||
  const args = ['-background', 'none', '-density', '384', 'svg:-', '-resize', `${size}x${size}`, outPath];
 | 
					  // rsvg-convert preserves transparency by default; specify width/height and PNG output
 | 
				
			||||||
  const proc = spawnSync(magickBin, args, { input: svgString, stdio: ['pipe', 'inherit', 'inherit'] });
 | 
					  const args = ['-w', String(size), '-h', String(size), '-f', 'png', '-o', outPath, SRC_SVG];
 | 
				
			||||||
 | 
					  const proc = spawnSync(rsvgBin, args, { stdio: ['ignore', 'inherit', 'inherit'] });
 | 
				
			||||||
  if (proc.status !== 0) {
 | 
					  if (proc.status !== 0) {
 | 
				
			||||||
    console.error(`Failed to generate ${outPath} using ${magickBin}.`);
 | 
					    console.error(`Failed to generate ${outPath} using ${rsvgBin}.`);
 | 
				
			||||||
    process.exit(proc.status || 1);
 | 
					    process.exit(proc.status || 1);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function main() {
 | 
					function main() {
 | 
				
			||||||
  const magick = ensureMagick();
 | 
					  const rsvg = ensureRsvgConvert();
 | 
				
			||||||
  if (!magick) {
 | 
					  if (!rsvg) {
 | 
				
			||||||
    console.error('ImageMagick not found. Please install ImageMagick (magick or convert) and ensure SVG support is available.');
 | 
					    console.error('rsvg-convert not found. Please install librsvg (rsvg-convert) and ensure it is on your PATH.');
 | 
				
			||||||
    process.exit(1);
 | 
					    process.exit(1);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (!fs.existsSync(ICONS_DIR)) fs.mkdirSync(ICONS_DIR, { recursive: true });
 | 
					  if (!fs.existsSync(ICONS_DIR)) fs.mkdirSync(ICONS_DIR, { recursive: true });
 | 
				
			||||||
 | 
					  assertSvgExists();
 | 
				
			||||||
  const base = readSvg();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Add-on icons (use SVG colors as-is)
 | 
					  // Add-on icons (use SVG colors as-is)
 | 
				
			||||||
  for (const s of ADDON_SIZES) {
 | 
					  for (const s of ADDON_SIZES) {
 | 
				
			||||||
    const out = path.join(ICONS_DIR, `icon-${s}.png`);
 | 
					    const out = path.join(ICONS_DIR, `icon-${s}.png`);
 | 
				
			||||||
    rasterize(magick, base, s, out);
 | 
					    rasterize(rsvg, s, out);
 | 
				
			||||||
    console.log(`Generated ${path.relative(REPO_ROOT, out)}`);
 | 
					    console.log(`Generated ${path.relative(REPO_ROOT, out)}`);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Toolbar icons (use SVG colors as-is)
 | 
					  // Toolbar icons (use SVG colors as-is)
 | 
				
			||||||
  for (const s of TOOLBAR_SIZES) {
 | 
					  for (const s of TOOLBAR_SIZES) {
 | 
				
			||||||
    const out = path.join(ICONS_DIR, `icon-${s}.png`);
 | 
					    const out = path.join(ICONS_DIR, `icon-${s}.png`);
 | 
				
			||||||
    rasterize(magick, base, s, out);
 | 
					    rasterize(rsvg, s, out);
 | 
				
			||||||
    console.log(`Generated ${path.relative(REPO_ROOT, out)}`);
 | 
					    console.log(`Generated ${path.relative(REPO_ROOT, out)}`);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue