52 lines
1.6 KiB
JavaScript
52 lines
1.6 KiB
JavaScript
#!/usr/bin/env node
|
|
// fix-svg.mjs
|
|
// Usage: node fix-svg.mjs input.svg output.svg 10 "#202020"
|
|
|
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
import { DOMParser, XMLSerializer } from "@xmldom/xmldom";
|
|
|
|
const input = process.argv[2];
|
|
const output = process.argv[3];
|
|
const margin = Number.parseFloat(process.argv[4] ?? "0");
|
|
const bg = process.argv[5] ?? null;
|
|
|
|
if (!input || !output) {
|
|
process.exit(1);
|
|
}
|
|
|
|
const xml = readFileSync(input, "utf8");
|
|
const doc = new DOMParser().parseFromString(xml, "image/svg+xml");
|
|
const svg = doc.documentElement;
|
|
|
|
if (!svg || svg.tagName.toLowerCase() !== "svg") {
|
|
process.exit(1);
|
|
}
|
|
|
|
// 1) Adjust viewBox (or derive it from root width/height if needed)
|
|
const vb = svg.getAttribute("viewBox");
|
|
if (vb) {
|
|
const parts = vb.trim().split(/\s+/).map((s) => Number.parseFloat(s));
|
|
if (parts.length === 4 && parts.every((n) => Number.isFinite(n))) {
|
|
let [x, y, w, h] = parts;
|
|
x -= margin;
|
|
y -= margin;
|
|
w += margin * 2;
|
|
h += margin * 2;
|
|
svg.setAttribute("viewBox", `${x} ${y} ${w} ${h}`);
|
|
}
|
|
}
|
|
|
|
// Remove ONLY root width/height so viewBox governs scaling (optional but common)
|
|
if (svg.hasAttribute("width")) { svg.removeAttribute("width"); }
|
|
if (svg.hasAttribute("height")) { svg.removeAttribute("height"); }
|
|
|
|
// 2) Set global background color (no inserted rect): root style background
|
|
if (bg) {
|
|
const style = svg.getAttribute("style") ?? "";
|
|
const next = style.trim().length > 0 ? `${style.trim().replace(/;+\s*$/, "")};background:${bg}` : `background:${bg}`;
|
|
svg.setAttribute("style", next);
|
|
}
|
|
|
|
const out = new XMLSerializer().serializeToString(doc);
|
|
writeFileSync(output, out);
|