From 29a735c091bc063c5f535ba311fe04299e75df99 Mon Sep 17 00:00:00 2001 From: Matthew Venn Date: Sun, 2 Aug 2026 17:42:03 +0200 Subject: [PATCH] continue tweaking --- docs/product/assets/README.md | 14 +++-- docs/product/build.py | 32 ++++++++++- docs/product/datasheet.html.mustache | 33 ++++++++++- docs/product/datasheet.yaml | 82 +++++++++++++++++----------- docs/product/partials/logo.mustache | 6 +- 5 files changed, 126 insertions(+), 41 deletions(-) diff --git a/docs/product/assets/README.md b/docs/product/assets/README.md index cf38efc..e80eccb 100644 --- a/docs/product/assets/README.md +++ b/docs/product/assets/README.md @@ -1,13 +1,19 @@ # Datasheet assets -Both files are embedded as data URIs by `build.py`, so the generated HTML is -self-contained. Swap either one by dropping in a replacement and updating the +Files here are embedded as data URIs by `build.py`, so the generated HTML is +self-contained. Swap any of them by dropping in a replacement and updating the `assets:` block in `datasheet.yaml`. | File | Source | Licence | | ---- | ------ | ------- | | `archivo.woff2` | [Archivo](https://github.com/Omnibus-Type/Archivo) via Google Fonts, latin subset, variable weight 100–900 | SIL Open Font License 1.1 — see `OFL.txt` | | `demoboard.jpg` | Tiny Tapeout ETR demoboard quickstart guide, downscaled to 1000px | © 2024 Pat Deegan, psychogenic.com — **not** covered by this repo's Apache-2.0 licence | +| `supporters/*` | Logos from [tinytapeout.com/credits](https://tinytapeout.com/credits/) | Trademarks of their respective owners | -The demoboard photo is credited in the datasheet caption. Confirm redistribution -is agreed with the copyright holder before publishing the datasheet externally. +The demoboard photo carries an embedded copyright of © 2024 Pat Deegan. **Matt +has permission from Pat to use it**, so it needs no on-sheet credit — the +datasheet caption that previously carried one has been removed. It remains +outside this repo's Apache-2.0 licence: don't reuse it elsewhere without asking. + +The supporter logos are only rendered when the `supporters:` block in +`datasheet.yaml` is uncommented, which it currently is not. diff --git a/docs/product/build.py b/docs/product/build.py index b49b3e9..0945681 100644 --- a/docs/product/build.py +++ b/docs/product/build.py @@ -164,12 +164,30 @@ def validate_markup(content: dict) -> None: raise SystemExit("\n".join(f"{p}" for p in problems)) +MIME_TYPES = {".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg"} + + def as_data_uri_payload(path: Path) -> str: if not path.is_file(): raise SystemExit(f"missing asset: {path}") return base64.b64encode(path.read_bytes()).decode() +def prepare_supporters(supporters: dict, assets: Path) -> None: + """Inline each supporter logo and work out its per-item sizing.""" + height = supporters.get("logo_height", "8.5mm") + for item in supporters.get("items") or []: + path = assets / "supporters" / item["file"] + suffix = path.suffix.lower() + if suffix not in MIME_TYPES: + raise SystemExit(f"{path}: expected one of {', '.join(MIME_TYPES)}") + item["data_uri"] = ( + f"data:{MIME_TYPES[suffix]};base64,{as_data_uri_payload(path)}" + ) + scale = item.get("scale", 1) + item["style"] = f"height: calc({height} * {scale})" + + def find_chrome() -> str: for candidate in CHROME_CANDIDATES: if candidate and (Path(candidate).is_file() or shutil.which(candidate)): @@ -195,6 +213,8 @@ window.addEventListener("load", () => setTimeout(() => { def run_chrome(*flags: str, page: Path) -> bytes: + # Deliberately no --user-data-dir: combined with --print-to-pdf, Chrome + # writes the PDF correctly and then never exits. result = subprocess.run( [ find_chrome(), @@ -206,6 +226,7 @@ def run_chrome(*flags: str, page: Path) -> bytes: ], check=True, capture_output=True, + timeout=120, ) return result.stdout @@ -234,8 +255,13 @@ def check_fit(html_path: Path) -> bool: found = re.search(rb'
([^<]*)
', dom) if not found or found.group(1) == b"pending": - logging.warning("could not measure sheet fit — skipping check") - return True + # Fail closed: reporting success without having measured anything is how + # clipped content ships unnoticed. + logging.error( + "could not measure sheet fit — Chrome returned no report. " + "Re-run, or pass --no-check to build without verifying the fit" + ) + return False overflowed = False for entry in found.group(1).decode().split(","): @@ -297,6 +323,8 @@ def main() -> None: assets = HERE / "assets" content["font_b64"] = as_data_uri_payload(assets / content["assets"]["font"]) content["photo_b64"] = as_data_uri_payload(assets / content["assets"]["photo"]) + if "supporters" in content: + prepare_supporters(content["supporters"], assets) with open(HERE / "datasheet.html.mustache", encoding="utf-8") as fh: rendered = chevron.render( diff --git a/docs/product/datasheet.html.mustache b/docs/product/datasheet.html.mustache index 7fb0552..fa91063 100644 --- a/docs/product/datasheet.html.mustache +++ b/docs/product/datasheet.html.mustache @@ -265,6 +265,10 @@ tbody tr:last-child td { border-bottom: 0; } .faq > div { border-top: 1px solid var(--rule); padding-top: 1.8mm; } +/* The first row sits just under the heading's own 2px rule; a second hairline + that close reads as a printing error. Keep the padding so rows stay aligned. */ +.faq > div:nth-child(-n + 2) { border-top: 0; } + .faq h3 { margin: 0 0 1.2mm; font-size: var(--t-body); @@ -292,6 +296,18 @@ tbody tr:last-child td { border-bottom: 0; } .linkline b { color: var(--red); font-weight: 700; } +/* ---------- supporter logos ---------- */ + +.supporters { + display: flex; + align-items: center; + justify-content: space-between; + gap: 5mm; + padding-top: 0.4mm; +} + +.supporters img { width: auto; max-width: 32mm; object-fit: contain; display: block; } + a { color: inherit; text-decoration: none; } a:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; } @media screen { .tnote a, .note a { text-decoration: underline; text-underline-offset: 1.5px; } } @@ -365,7 +381,7 @@ a:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; } {{> logo}}
{{&doc.wordmark}}{{#doc.wordmark_sub}}{{&doc.wordmark_sub}}{{/doc.wordmark_sub}}
{{&doc.tag}}
-
{{&doc.ref}}
+ {{#doc.ref}}
{{&doc.ref}}
{{/doc.ref}}
@@ -378,7 +394,7 @@ a:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; }
{{hero.photo_alt}} -
{{&hero.photo_caption}}
+ {{#hero.photo_caption}}
{{&hero.photo_caption}}
{{/hero.photo_caption}}
@@ -430,7 +446,7 @@ a:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; }
{{> logo}} -
{{&doc.wordmark}}{{&doc.ref}}
+
{{&doc.wordmark}}{{#doc.ref}}{{&doc.ref}}{{/doc.ref}}
{{&doc.page2_title}}
@@ -467,6 +483,17 @@ a:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; } {{#ordering}}{{> secthead}}{{> table}}{{> footnote}}{{/ordering}} + {{#supporters}} +
+ {{> secthead}} +
+ {{#items}} + {{name}} + {{/items}} +
+
+ {{/supporters}} +