Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@

0. **Pre-requisites**
- Docker must be installed. This is used to run a martin tile server image, which is the one that converts source files to sprites.
- Python 3 must be installed. `generate_sprites.sh` uses it to strip the stretchable-icon marker fills (`content`/`stretchX`/`stretchY`) out of the SVGs before martin sees them (see `scripts/strip_stretchable_markers.py`). No extra packages needed - it only uses the standard library.
- Python 3 must be installed. It's used by `scripts/round_svg_numbers.py` (see step 2 below) and by `generate_sprites.sh`, which uses `scripts/strip_stretchable_markers.py` to strip the stretchable-icon marker fills (`content`/`stretchX`/`stretchY`) out of the SVGs before martin sees them. No extra packages needed - both only use the standard library.

1. **Make sure that the assets in `sprite_assets` are correct.**
It is essential that the file names are correct.
For each folder (= OMS partner), there should be two folders – `light` and `dark`. Then follow the same patterns as used in the app.
Remember - all svgs should have a theme suffix -> `light` or `dark`.

2. **Generate sprites**
2. **Round the SVGs before committing.**
Figma re-exports the same, unchanged design with slightly different floating point noise every time (e.g. `20.4598` one export, `20.4594` the next), which makes every touched SVG show up as modified even when nothing actually changed. Run this after exporting from Figma and before committing:
```sh
python3 scripts/round_svg_numbers.py sprite_assets
```
This rounds every numeric value (path data, coordinates, transforms, ...) to 2 decimal places directly in the SVG files - well below one pixel at these icon sizes, so it has no visible effect, but it means two exports of the same design produce an identical diff-free file. Files that need no changes are left untouched.

3. **Generate sprites**
```sh
bash generate_sprites.sh
```
Expand All @@ -27,7 +34,7 @@
python3 -m unittest discover scripts
```

3. **Upload sprites to GCS**
4. **Upload sprites to GCS**

Pre-requisites:
- `gcloud` CLI installed and authenticated: `gcloud auth application-default login`
Expand Down
Binary file modified generated_sprites/AtB/dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/AtB/dark@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/AtB/light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/AtB/light@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/FRAM/dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/FRAM/dark@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/FRAM/light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/FRAM/light@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/NFK/dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/NFK/dark@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/NFK/light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/NFK/light@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/Troms/dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/Troms/dark@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/Troms/light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified generated_sprites/Troms/light@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
112 changes: 112 additions & 0 deletions scripts/round_svg_numbers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/usr/bin/env python3
"""
Rounds numeric values in SVG files to a fixed precision, in place.

Every time an unchanged design is re-exported from Figma, the numbers in its
SVG (path data, coordinates, transforms, ...) come out with slightly
different floating point noise - e.g. 20.4598 one export, 20.4594 the next -
even though nothing actually changed. That makes every sprite_assets/*.svg
show up as modified on each re-export, with a diff nobody can meaningfully
review.

Rounding every numeric attribute to a fixed, small number of decimal places
absorbs that noise: two exports of the same design converge on the same
rounded numbers and produce no diff, while the rounding itself is far below
one pixel at these icon sizes and has no visible effect.

Usage:
round_svg_numbers.py <dir> [<dir> ...]

Every .svg file found recursively under the given directories is rounded and
overwritten in place. Files that need no changes are left untouched.
"""

import re
import sys
import xml.etree.ElementTree as ET
from pathlib import Path

SVG_NS = "http://www.w3.org/2000/svg"
ET.register_namespace("", SVG_NS)

PRECISION = 2

# Only attributes that are purely numeric (or a list of numbers/coordinates)
# are touched. Everything else (id, fill, filter="url(#...)", fill-rule, ...)
# is left completely alone.
NUMERIC_ATTRS = {
"x", "y", "width", "height", "cx", "cy", "r", "rx", "ry",
"x1", "y1", "x2", "y2", "fx", "fy", "fr",
"d", "points", "viewBox", "offset",
"transform", "gradientTransform", "patternTransform",
"stroke-width", "stroke-dasharray", "stroke-dashoffset", "stroke-miterlimit",
"opacity", "fill-opacity", "stroke-opacity", "stop-opacity", "flood-opacity",
"stdDeviation", "dx", "dy", "values",
}

NUMBER_RE = re.compile(r"-?\d*\.?\d+(?:[eE][+-]?\d+)?")


def round_number(match: re.Match) -> str:
value = round(float(match.group()), PRECISION)
if value == 0:
value = 0.0 # normalize -0.0
text = f"{value:.{PRECISION}f}".rstrip("0").rstrip(".")
return text if text else "0"


def process_svg(path: Path) -> tuple[bytes, bool]:
original = path.read_bytes()
tree = ET.parse(path)
root = tree.getroot()

changed = False
for elem in root.iter():
for attr in NUMERIC_ATTRS:
value = elem.get(attr)
if value is None:
continue
rounded = NUMBER_RE.sub(round_number, value)
if rounded != value:
elem.set(attr, rounded)
changed = True

if not changed:
return original, False

return ET.tostring(root, encoding="unicode").encode("utf-8"), True


def main() -> int:
if len(sys.argv) < 2:
print(__doc__, file=sys.stderr)
return 1

dirs = [Path(arg) for arg in sys.argv[1:]]
for d in dirs:
if not d.is_dir():
print(f"error: {d} is not a directory", file=sys.stderr)
return 1

touched = 0
total = 0
for d in dirs:
for path in sorted(d.rglob("*.svg")):
total += 1
try:
content, changed = process_svg(path)
except ET.ParseError as e:
print(f"error: failed to parse {path}: {e}", file=sys.stderr)
return 1

if changed:
path.write_bytes(content)
touched += 1
print(f"rounded: {path}")

print(f"done: {touched}/{total} file(s) rounded")
return 0


if __name__ == "__main__":
sys.exit(main())
22 changes: 11 additions & 11 deletions sprite_assets/AtB/dark/geofencingzone_allowed_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 12 additions & 12 deletions sprite_assets/AtB/dark/geofencingzone_noentry_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 12 additions & 12 deletions sprite_assets/AtB/dark/geofencingzone_noparking_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions sprite_assets/AtB/dark/geofencingzone_parking_dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading