diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 65f74cc..8d64582 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,6 +29,9 @@ jobs:
- name: Verify accessible SVG contract
run: python3 scripts/test-lint-a11y.py
+ - name: Verify URL SVG normalization
+ run: python3 scripts/test-build-icons-quoted-attributes.py
+
- name: Run skin linter
run: python3 scripts/lint-skin.py --all --baseline
diff --git a/scripts/build-icons.py b/scripts/build-icons.py
index b191b2a..88c9325 100644
--- a/scripts/build-icons.py
+++ b/scripts/build-icons.py
@@ -249,8 +249,10 @@ def normalize_url(raw: str) -> str:
- inline style="fill:#..." is rewritten to a fill= attribute.
- Inkscape layer translate() transforms are stripped (canvas offset artefact).
"""
- vb_match = re.search(r'viewBox="([^"]+)"', raw, re.IGNORECASE)
- viewbox = vb_match.group(1) if vb_match else "0 0 128 128"
+ vb_match = re.search(
+ r'\bviewBox\s*=\s*(["\'])(.*?)\1', raw, flags=re.IGNORECASE
+ )
+ viewbox = vb_match.group(2).strip() if vb_match else "0 0 128 128"
inner = re.search(r"", raw, flags=re.DOTALL | re.IGNORECASE)
if not inner:
raise ValueError("no