diff --git a/CHANGELOG.md b/CHANGELOG.md index fe920b2..aa4560e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,40 @@ Keep a Changelog change-type headings, so a consumer reads only the sections that affect its template. Version numbers follow the `MAJOR.MINOR.PATCH` policy described in [the README](README.md#versioning). +## Unreleased + +### shared + +- The brand assets are the **ClumL company mark**, replacing a + `brand.svg` that was the Clumit Security product logo — one consumer's + product, shipped to every consumer. A project documenting a different + product would have published another product's branding. +- `brand.svg` now carries **white** lettering, for the site header, which + sits on the primary-coloured bar. Anything rendering it on a light + background needs `brand-print.svg` instead. +- Added `brand-print.svg`, the black-lettering variant the PDF cover + uses, and `brand-symbol.svg`, the cube alone. A wordmark scaled to a + 16-pixel tab icon is unreadable; the cube is not. + +### manual + +- `theme.favicon` points at `theme/brand-symbol.svg` rather than the + wordmark. + +### api-reference + +- `theme.favicon` points at `theme/brand-symbol.svg` rather than the + wordmark. + +### scripts + +- `fetch-theme.sh` installs all three brand assets. +- `build-docs-pdf.sh` takes the cover logo from `brand-print.svg`, and + accepts `extra.pdf.cover_logo` — a path relative to `docs_dir` — so a + project documenting a product with its own mark can put it on the + cover. A path that does not resolve is an error rather than a silent + fall back to the company mark. + ## [0.2.0] - 2026-08-08 ### manual diff --git a/README.md b/README.md index c991994..6cf2013 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,9 @@ templates/ Template assets grouped by document type release-notes/ (planned) shared/ Assets shared across all templates fonts/ Roboto and Pretendard web fonts - brand.svg Brand logo + brand.svg ClumL wordmark, white lettering (site header) + brand-print.svg ClumL wordmark, black lettering (PDF cover) + brand-symbol.svg ClumL cube alone (favicon) styles/ Base CSS samples/ Per-template sample sites for previewing index.html Landing page linking to all samples @@ -190,6 +192,8 @@ It downloads the release named in `docs/theme.toml` and installs: | `shared/styles/base.css` | `docs/theme/styles/base.css` | | `shared/fonts/` | `docs/theme/fonts/` | | `shared/brand.svg` | `docs/theme/brand.svg` | +| `shared/brand-print.svg` | `docs/theme/brand-print.svg` | +| `shared/brand-symbol.svg` | `docs/theme/brand-symbol.svg` | | `scripts/build-docs-pdf.sh` | `docs/theme/build-docs-pdf.sh` | The install directory must not be dot-prefixed: MkDocs drops every @@ -253,6 +257,37 @@ default, and a consumer that needs its own `i18n` languages redefines the whole `plugins` list (which replaces the default wholesale), as the sample sites do. +### Branding + +The theme ships the **ClumL company mark** in three variants, because one +file cannot serve all three places. `brand.svg` has white lettering for +the site header, which sits on the primary-coloured bar. `brand-print.svg` +has black lettering for the PDF cover, which sits on white paper. +`brand-symbol.svg` is the cube alone: a wordmark scaled to a 16-pixel tab +icon is unreadable, and the cube is not. The base wires all three, so a +project documenting something ClumL publishes needs no branding config at +all. + +A project documenting a product with its own mark overrides them. Commit +the product's assets under `docs/` — **not** under `docs/theme/`, which +is covered by the `.meta` digest and reverted on the next installer run: + +```yaml +theme: + logo: assets/product-logo.svg + favicon: assets/product-symbol.svg + +extra: + pdf: + cover_logo: assets/product-logo-print.svg +``` + +`theme` is a mapping, so those two keys merge into the base rather than +replacing it — the palette, fonts, and features it defines all survive. +`extra.pdf.cover_logo` is a path relative to `docs_dir`; a path that does +not resolve is an error rather than a silent fall back to the company +mark, which would otherwise ship a cover branded with the wrong name. + The base already wires `extra_css` to the installed stylesheets (base, lists, and PDF guardrails, plus `api.css` for the api-reference template), so you do not list them yourself. To review the full set of diff --git a/scripts/build-docs-pdf.sh b/scripts/build-docs-pdf.sh index c036751..03b66a0 100755 --- a/scripts/build-docs-pdf.sh +++ b/scripts/build-docs-pdf.sh @@ -303,9 +303,24 @@ if cover_subtitle is not None: if toc_title is not None: options["toc_title"] = toc_title -brand_svg = os.path.join(theme_dir, "brand.svg") -if os.path.isfile(brand_svg): - options["cover_logo"] = brand_svg +# The cover sits on white paper, so it needs the black-lettering variant. +# theme/brand.svg is the white-lettering one the site header uses; putting +# that on the cover renders an invisible logo and nothing downstream would +# report it. A consumer documenting a product with its own mark points +# extra.pdf.cover_logo at it, relative to docs_dir. +cover_logo = text("cover_logo") +if cover_logo is not None: + docs_dir = str(data.get("docs_dir") or "docs") + cover_logo = os.path.join(root, docs_dir, cover_logo) + if not os.path.isfile(cover_logo): + fail(f"{config_path}: 'extra.pdf.cover_logo' does not exist at " + f"{cover_logo}") +else: + cover_logo = os.path.join(theme_dir, "brand-print.svg") + if not os.path.isfile(cover_logo): + fail(f"{cover_logo} is missing; the installed theme is incomplete. " + "Re-run ./scripts/fetch-theme.sh.") +options["cover_logo"] = cover_logo # cover_tagline is not a mkdocs-with-pdf option. The plugin seeds the # cover template context from `extra` and never overwrites this name, so diff --git a/scripts/fetch-theme.sh b/scripts/fetch-theme.sh index 2d12872..f597694 100755 --- a/scripts/fetch-theme.sh +++ b/scripts/fetch-theme.sh @@ -285,10 +285,16 @@ def stage(src, staging, template, template_dir, label): fail(f"shared/fonts/ not found in {label}") copy_tree(shared_fonts, os.path.join(staging, "fonts")) - brand = os.path.join(src, "shared", "brand.svg") - if not os.path.isfile(brand): - fail(f"shared/brand.svg not found in {label}") - copy_file(brand, os.path.join(staging, "brand.svg")) + # brand.svg carries white lettering for the site header, which sits on + # the primary-coloured bar; brand-print.svg is the black-lettering + # variant the PDF cover needs on white paper; brand-symbol.svg is the + # cube alone, which is the only one of the three that stays legible at + # favicon size. + for name in ("brand.svg", "brand-print.svg", "brand-symbol.svg"): + asset = os.path.join(src, "shared", name) + if not os.path.isfile(asset): + fail(f"shared/{name} not found in {label}") + copy_file(asset, os.path.join(staging, name)) pdf_script = os.path.join(src, "scripts", "build-docs-pdf.sh") if not os.path.isfile(pdf_script): diff --git a/shared/brand-print.svg b/shared/brand-print.svg new file mode 100644 index 0000000..eb8de33 --- /dev/null +++ b/shared/brand-print.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/shared/brand-symbol.svg b/shared/brand-symbol.svg new file mode 100644 index 0000000..cdb533c --- /dev/null +++ b/shared/brand-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/shared/brand.svg b/shared/brand.svg index 3e05650..aced5e5 100644 --- a/shared/brand.svg +++ b/shared/brand.svg @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/templates/api-reference/mkdocs-base.yml b/templates/api-reference/mkdocs-base.yml index 4009e5b..274cba6 100644 --- a/templates/api-reference/mkdocs-base.yml +++ b/templates/api-reference/mkdocs-base.yml @@ -27,7 +27,7 @@ theme: language: en font: false logo: theme/brand.svg - favicon: theme/brand.svg + favicon: theme/brand-symbol.svg features: - navigation.tabs - navigation.sections diff --git a/templates/manual/mkdocs-base.yml b/templates/manual/mkdocs-base.yml index 0ab55c5..357e5cf 100644 --- a/templates/manual/mkdocs-base.yml +++ b/templates/manual/mkdocs-base.yml @@ -27,7 +27,7 @@ theme: language: en font: false logo: theme/brand.svg - favicon: theme/brand.svg + favicon: theme/brand-symbol.svg features: - navigation.tabs - navigation.sections diff --git a/tests/installer-test.sh b/tests/installer-test.sh index aa3db0c..8bbdca7 100755 --- a/tests/installer-test.sh +++ b/tests/installer-test.sh @@ -87,6 +87,8 @@ for entry in \ fonts/Roboto-Regular.woff2 \ fonts/Pretendard-Regular.woff2 \ brand.svg \ + brand-print.svg \ + brand-symbol.svg \ build-docs-pdf.sh \ .meta do diff --git a/tests/pdf-test.sh b/tests/pdf-test.sh index e662e02..e20c349 100755 --- a/tests/pdf-test.sh +++ b/tests/pdf-test.sh @@ -711,4 +711,70 @@ contains "$WORK/tables.txt" "overlong-end" "a row taller than a page" contains "$WORK/tables.txt" "after-overlong" "the row after an overlong one" ok "a row taller than a page splits rather than losing its content" +# --- the cover logo ----------------------------------------------------- + +# The cover sits on white paper, so it must carry the black-lettering +# brand-print.svg. theme/brand.svg is the white-lettering variant the +# site header uses; rendering that on the cover produces an invisible +# logo, which is exactly the kind of silent asset loss nothing else here +# would catch. +generated="$(debug_build_pdf "$full" en)" +grep -q 'cover_logo:.*brand-print\.svg' "$generated" \ + || die "the cover did not default to brand-print.svg" +grep -q 'cover_logo:.*brand\.svg' "$generated" \ + && die "the cover used the white-lettering header logo" +ok "the cover logo defaults to the print variant, not the header one" + +# A consumer documenting a product with its own mark overrides it. The +# fixture carries a element so the substitution is observable in +# the rendered page rather than only in the generated config. +override="$WORK/override" +new_project "$override" +cat > "$override/docs/product-logo.svg" <<'SVG' +PRODUCTLOGOMARK +SVG +cat > "$override/mkdocs.yml" <<'EOF' +site_name: Override Fixture +extra: + pdf: + cover_logo: product-logo.svg +EOF +build_pdf "$override" en +pdf_text "$override/site/pdf/override-fixture.en.pdf" > "$WORK/override.txt" +contains "$WORK/override.txt" "PRODUCTLOGOMARK" "the overridden cover logo" +ok "extra.pdf.cover_logo puts a consumer's own mark on the cover" + +# A path that does not resolve is an error. Falling back to the theme +# logo would hand a consumer a cover branded with the wrong company. +cat > "$override/mkdocs.missing.yml" <<'EOF' +site_name: Missing Logo Fixture +extra: + pdf: + cover_logo: does-not-exist.svg +EOF +if (cd "$override" && ./docs/theme/build-docs-pdf.sh en mkdocs.missing.yml) \ + > "$WORK/missing-logo.log" 2>&1 +then + die "a cover_logo that does not exist should be an error" +fi +grep -q "extra.pdf.cover_logo" "$WORK/missing-logo.log" \ + || die "the error does not name extra.pdf.cover_logo" +ok "a cover_logo that does not resolve fails instead of falling back" + +# An incomplete install is an error for the same reason. This needs a +# config without an override, or the override would satisfy the cover and +# the missing asset would go unnoticed. +cat > "$override/mkdocs.default.yml" <<'EOF' +site_name: Default Logo Fixture +EOF +rm -f "$override/docs/theme/brand-print.svg" +if (cd "$override" && ./docs/theme/build-docs-pdf.sh en mkdocs.default.yml) \ + > "$WORK/no-print-logo.log" 2>&1 +then + die "a missing brand-print.svg should be an error" +fi +grep -q "brand-print.svg" "$WORK/no-print-logo.log" \ + || die "the error does not name the missing asset" +ok "a missing brand-print.svg fails instead of rendering a logo-less cover" + echo "All PDF script checks passed."