diff --git a/doc/en/_static/og-image.png b/doc/en/_static/og-image.png new file mode 100644 index 00000000000..4639aa31e9f Binary files /dev/null and b/doc/en/_static/og-image.png differ diff --git a/doc/en/_templates/page.html b/doc/en/_templates/page.html new file mode 100644 index 00000000000..5405f25320c --- /dev/null +++ b/doc/en/_templates/page.html @@ -0,0 +1,16 @@ +{% extends "!page.html" %} + +{% block extrahead %} +{{ super() }} + + + + + + + + + + + +{% endblock extrahead %} diff --git a/tools/make-og-image.py b/tools/make-og-image.py new file mode 100644 index 00000000000..d7ddc1c1e55 --- /dev/null +++ b/tools/make-og-image.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 +"""Generate the 1200x630 Open Graph image for docs.pytest.org. + +Pillow-only, reproducible. Run from the repo root: + python tools/make-og-image.py +Output: doc/en/_static/og-image.png + +Design: white ground, the project's own pytest1.png logo scaled on top, +official tagline, section pills, docs.pytest.org domain chip. +""" + +from __future__ import annotations + +from pathlib import Path + +from PIL import Image +from PIL import ImageDraw +from PIL import ImageFont + + +ROOT = Path(__file__).resolve().parents[1] +LOGO = ROOT / "doc" / "en" / "_static" / "pytest1.png" +OUT = ROOT / "doc" / "en" / "_static" / "og-image.png" + +W, H = 1200, 630 +GROUND = (255, 255, 255) +ACCENT = (250, 179, 14) # pytest yellow +INK = (34, 34, 34) +GREY = (110, 110, 110) +PILL_BG = (245, 245, 245) +PILL_FG = (51, 51, 51) +CHIP_BG = (250, 179, 14) +CHIP_FG = (34, 34, 34) + +FONT_DIR = Path("/usr/share/fonts/truetype/dejavu/") +FONT_BOLD = FONT_DIR / "DejaVuSans-Bold.ttf" +FONT_REG = FONT_DIR / "DejaVuSans.ttf" + + +def font(path, size): + return ImageFont.truetype(str(path), size) + + +def text_w(draw, s, f): + b = draw.textbbox((0, 0), s, font=f) + return b[2] - b[0] + + +def main(): + img = Image.new("RGB", (W, H), GROUND) + draw = ImageDraw.Draw(img) + + # Accent bar along the top. + draw.rectangle([0, 0, W, 10], fill=ACCENT) + + # Logo: the project's own pytest1.png (1500x1500, transparent bg, contains + # the bar-chart mark + "pytest" wordmark). Scale to fit fully on the card. + logo = Image.open(LOGO).convert("RGBA") + logo_w = 400 + logo_h = int(logo.height * logo_w / logo.width) + logo = logo.resize((logo_w, logo_h), Image.LANCZOS) + img.paste(logo, ((W - logo_w) // 2, 15), logo) + + # Tagline. + tagline = "helps you write better programs" + f_tag = font(FONT_REG, 40) + draw.text( + ((W - text_w(draw, tagline, f_tag)) / 2, 430), tagline, font=f_tag, fill=GREY + ) + + # Section pills. + pills = [ + "Getting started", + "How-to guides", + "Reference", + "Explanations", + "Examples", + ] + f_pill = font(FONT_BOLD, 26) + gap = 16 + pw = [text_w(draw, p, f_pill) + 40 for p in pills] + total = sum(pw) + gap * (len(pills) - 1) + x = (W - total) / 2 + for p, wdt in zip(pills, pw): + draw.rounded_rectangle([x, 485, x + wdt, 485 + 52], radius=26, fill=PILL_BG) + draw.text((x + 20, 485 + 11), p, font=f_pill, fill=PILL_FG) + x += wdt + gap + + # Domain chip. + chip = "docs.pytest.org" + f_chip = font(FONT_BOLD, 30) + cw = text_w(draw, chip, f_chip) + 56 + cx = (W - cw) / 2 + cy = 555 + draw.rounded_rectangle([cx, cy, cx + cw, cy + 56], radius=28, fill=CHIP_BG) + draw.text((cx + 28, cy + 11), chip, font=f_chip, fill=CHIP_FG) + + OUT.parent.mkdir(parents=True, exist_ok=True) + img.save(OUT, optimize=True) + print(f"wrote {OUT} {img.size}") + + +if __name__ == "__main__": + main()