Vibecoded CI/CD
Some checks failed
Build and Deploy Lean / build (push) Failing after 16m44s
Build and Deploy Nuxt / build (push) Failing after 48s

This commit is contained in:
2026-10-06 00:23:17 +02:00
parent a57770619e
commit e2c2c66d7f
79 changed files with 6044 additions and 47 deletions

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env python3
"""Draw desktop/icon-source.png — the 1024² master the icon set is cut from.
The wiki's own mark is the ∑ in the sidebar (AppHeader.vue's .logo-mark) over
the dark reading surface, so the app icon is that: the sigma, in the accent the
wiki wears by default, on the dark navy of its dark theme.
python3 desktop/make-icon.py # writes desktop/icon-source.png
npm run desktop:icons # cuts src-tauri/icons/ from it
Requires Pillow (pip install pillow). Nothing else in the project uses it —
this is build tooling, not app code.
"""
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
SIZE = 1024
PAD = 64 # the margin macOS wants round an app icon; harmless elsewhere
RADIUS = 200
TOP = (16, 21, 44) # the navy a touch above --bg, so the square reads as an object
BOTTOM = (6, 8, 14) # ... down to just under it
ACCENT = (124, 140, 255) # --accent, dark theme (#7c8cff)
MARK = "\u2211" # ∑ — the wiki's mark
FONTS = [
"/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSerif-Bold.ttf",
]
OUT = Path(__file__).resolve().parent / "icon-source.png"
def load_font(size: int) -> ImageFont.FreeTypeFont:
"""The first system font that actually carries a sigma."""
for path in FONTS:
try:
font = ImageFont.truetype(path, size)
except OSError:
continue
if font.getbbox(MARK)[2] > 0:
return font
raise SystemExit(f"no font with a {MARK} found — look for one of: {', '.join(FONTS)}")
def main() -> None:
# vertical gradient, then clipped to a rounded square
gradient = Image.new("RGB", (1, SIZE))
for y in range(SIZE):
t = y / (SIZE - 1)
gradient.putpixel((0, y), tuple(round(a + (b - a) * t) for a, b in zip(TOP, BOTTOM)))
gradient = gradient.resize((SIZE, SIZE))
mask = Image.new("L", (SIZE, SIZE), 0)
ImageDraw.Draw(mask).rounded_rectangle(
[PAD, PAD, SIZE - PAD, SIZE - PAD], radius=RADIUS, fill=255
)
icon = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0))
icon.paste(gradient, (0, 0), mask)
draw = ImageDraw.Draw(icon)
# a hairline of accent light along the edge, so the dark square does not
# vanish into a dark taskbar
draw.rounded_rectangle(
[PAD, PAD, SIZE - PAD, SIZE - PAD], radius=RADIUS, outline=(124, 140, 255, 56), width=3
)
font = load_font(600)
left, top, right, bottom = draw.textbbox((0, 0), MARK, font=font)
w, h = right - left, bottom - top
# centred on the box the glyph is drawn in, not on its typographic cell:
# an ascent-based centre would sit the sigma high
draw.text(
((SIZE - w) / 2 - left, (SIZE - h) / 2 - top),
MARK,
font=font,
fill=ACCENT + (255,),
)
icon.save(OUT)
print(f"wrote {OUT}")
if __name__ == "__main__":
main()