Skip to content

Instantly share code, notes, and snippets.

@wpyoga
Created August 18, 2026 14:34
Show Gist options
  • Select an option

  • Save wpyoga/ceabddd187b8854a7e2bf0617b7dce0f to your computer and use it in GitHub Desktop.

Select an option

Save wpyoga/ceabddd187b8854a7e2bf0617b7dce0f to your computer and use it in GitHub Desktop.
Vibe-coded script to normalize an SVG file
import argparse
import math
import xml.etree.ElementTree as ET
from svgelements import SVG
def calculate_bbox(svg):
"""
Calculate the bounding box of drawable SVG content.
Returns:
(xmin, ymin, xmax, ymax)
"""
bbox = None
for element in svg.elements():
# Ignore elements that are explicitly hidden.
try:
if (
element.values.get("visibility") == "hidden"
or element.values.get("display") == "none"
):
continue
except AttributeError:
pass
element_bbox = element.bbox()
# try:
# element_bbox = element.bbox()
# except (AttributeError, TypeError, ValueError):
# continue
if element_bbox is None:
continue
if not all(math.isfinite(value) for value in element_bbox):
print(f"Not all the bounds are finite: {element_bbox}")
continue
xmin, ymin, xmax, ymax = element_bbox
if bbox is None:
bbox = [xmin, ymin, xmax, ymax]
else:
bbox[0] = min(bbox[0], xmin)
bbox[1] = min(bbox[1], ymin)
bbox[2] = max(bbox[2], xmax)
bbox[3] = max(bbox[3], ymax)
if bbox is None:
raise ValueError("SVG contains no drawable geometry")
return tuple(bbox)
def normalize_viewbox(input_filename, output_filename, padding=0):
"""
Replace the SVG's viewBox with the bounding box of its artwork.
The SVG is parsed with svgelements only for geometry calculation.
The actual SVG document is parsed and written using ElementTree.
"""
svg = SVG.parse(input_filename)
xmin, ymin, xmax, ymax = calculate_bbox(svg)
xmin -= padding
ymin -= padding
xmax += padding
ymax += padding
width = xmax - xmin
height = ymax - ymin
if width <= 0 or height <= 0:
raise ValueError(f"Invalid bounding box: " f"{xmin}, {ymin}, {xmax}, {ymax}")
ET.register_namespace("", "http://www.w3.org/2000/svg")
# Parse the ORIGINAL SVG document.
tree = ET.parse(input_filename)
root = tree.getroot()
# Change only the semantic SVG attribute.
root.set(
"viewBox",
f"{xmin:g} {ymin:g} {width:g} {height:g}",
)
root.set("width", f"{width:g}")
root.set("height", f"{height:g}")
# Write the original XML structure back out.
tree.write(
output_filename,
encoding="utf-8",
xml_declaration=True,
)
print(f"Input: {input_filename}")
print(f"BBox: {xmin:g} {ymin:g} {xmax:g} {ymax:g}")
print(f"New size: {width:g} × {height:g}")
print(f"New viewBox:{xmin:g} {ymin:g} {width:g} {height:g}")
print(f"Output: {output_filename}")
def main():
parser = argparse.ArgumentParser()
parser.add_argument("input")
parser.add_argument("output")
args = parser.parse_args()
normalize_viewbox(args.input, args.output)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment