diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..2cc1cefe --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,75 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +The [pdf-archiver.io](https://pdf-archiver.io) website: a Swift package that generates static HTML +with [Publish](https://github.com/JohnSundell/Publish) and Plot. `README.md` documents the project +for contributors — the paths, the language layout, and how to add a page or a language. This file +adds what is not written there. + +## Commands + +```bash +swift run # build the generator and write the site to Output/ +swift build # compile only +python3 -m http.server --directory Output # serve the generated site +``` + +There are no tests and no linter. Verification is `swift run` finishing green plus reading the files +it wrote to `Output/`. Every asset is linked absolutely (`/css/styles.css`), so opening +`Output/index.html` over `file://` renders unstyled — serve the folder instead. + +`Output/` and `.publish/` are generated and git-ignored; never edit anything below them. + +## Pipeline + +`SiteGenerator.swift` lists the publishing steps, and their **order is the architecture** — each +custom step in `PublishingSteps.swift` repairs something Publish does that this site cannot use: + +- `.buildPressKitArchive()` zips `presskit/` into `presskit.zip` at publish time, so the archive is + never versioned. +- `.moveGermanIndexPageToLanguageRoot()` turns `Content/de/index.md` into `/de` rather than + `/de/index`. +- `.removeFAQEntryPages()` deletes the per-question pages after HTML generation — the entries only + ever appear collected on `/faq` and `/de/faq`. +- `.generateCanonicalSiteMap(excluding:)` replaces Publish's site map, which omits the home pages + and spells URLs without their trailing slash. +- `.moveNotFoundPageToRoot()` writes `/404.html`, the only error page GitHub Pages serves. + +## Invariants worth knowing before changing anything + +- **The URL is the language.** `SiteLanguage(path:)` reads the leading path component, so a page's + language, strings and `lang` attribute all follow from where its file sits. Nothing carries the + language in front matter. +- **Every internal link ends in a slash.** GitHub Pages 301-redirects `/faq` to `/faq/`, so + `Path.directoryPath` and `canonicalURL(for:)` in `CanonicalPaths.swift` exist to keep the + canonical tag, the `hreflang` links and the site map pointing at the page instead of a redirect. + Use them for anything URL-shaped; `url(for:)` alone is one redirect off. +- **The home pages have no Markdown body.** `/` and `/de` are built from `SiteStrings`; their + Markdown files carry only `title` and `description`. Copy changes on the home page happen in + `Localization/SiteStrings+English.swift` and `+German.swift`, which must stay structurally + identical — `SiteStrings` has no optional members. +- **FAQ entries are ordered by file name.** `Content/faq/NN-slug.md`, sorted by path; the number is + the running order on the page. `/de/faq` renders the same English entries, because the FAQ itself + is not translated. +- **`Resources/` is copied verbatim into the site root; `root-resources/` holds files that must sit + unchanged at the root** (`CNAME`, `robots.txt`, `.well-known/`). Folder traversal skips dotted + folders, so `apple-app-site-association` is copied by name in a separate step, and the Pages + workflow needs `include-hidden-files: true` — universal links break silently otherwise. +- **The head is hand-assembled** in `Theme/DocumentHead.swift`: the full favicon set, `hreflang` + pairs, and JSON-LD that is emitted on the home pages only. `Website.favicon` and + `tagHTMLConfig` are deliberately `nil` so Publish adds nothing of its own. + +## Front end + +`Resources/css/styles.css` is the whole stylesheet, token-driven (`--font-heading`, `--font-body`, +`--font-mono`, the colour tokens) with a `prefers-color-scheme` block that only redefines tokens. +Headings are set in Charter, self-hosted from `Resources/assets/fonts/` under the Bitstream licence +that ships beside it as `charter-license.txt`. The other font files in that folder are leftovers of +the previous site and are referenced by nothing. + +## Conventions + +Base branch `develop`; branches are named `feature/…`. Pushing to `develop` builds on GitHub Actions +and publishes the Pages artifact — no branch holds the generated HTML. Pull requests build too, so a +broken generator surfaces before the merge. diff --git a/Resources/assets/fonts/charter-bold.woff2 b/Resources/assets/fonts/charter-bold.woff2 new file mode 100644 index 00000000..008c4f55 Binary files /dev/null and b/Resources/assets/fonts/charter-bold.woff2 differ diff --git a/Resources/assets/fonts/charter-license.txt b/Resources/assets/fonts/charter-license.txt new file mode 100644 index 00000000..148919d7 --- /dev/null +++ b/Resources/assets/fonts/charter-license.txt @@ -0,0 +1,3 @@ +This is a copy of the Charter fonts which Bitstream contributed to the X consortium. This is the original notice included with the fonts: + +(c) Copyright 1989-1992, Bitstream Inc., Cambridge, MA. You are hereby granted permission under all Bitstream propriety rights to use, copy, modify, sublicense, sell, and redistribute the 4 Bitstream Charter (r) Type 1 outline fonts and the 4 Courier Type 1 outline fonts for any purpose and without restriction; provided, that this notice is left intact on all copies of such fonts and that Bitstream's trademark is acknowledged as shown below on all unmodified copies of the 4 Charter Type 1 fonts. BITSTREAM CHARTER is a registered trademark of Bitstream Inc. \ No newline at end of file diff --git a/Resources/assets/fonts/charter-regular.woff2 b/Resources/assets/fonts/charter-regular.woff2 new file mode 100644 index 00000000..d4bc9e04 Binary files /dev/null and b/Resources/assets/fonts/charter-regular.woff2 differ diff --git a/Resources/css/styles.css b/Resources/css/styles.css index 08325bd9..71a4b117 100644 --- a/Resources/css/styles.css +++ b/Resources/css/styles.css @@ -2,6 +2,24 @@ Warm paper throughout, one dark card for "Keep it.", and the filename as the page's signature: typed out in the hero, at rest at the end, its separators reused as dividers. */ +/* Charter, Matthew Carter's 1987 text face. Bitstream gave it to the X Consortium for any use; + its licence has to travel with the files, so it sits next to them as charter-license.txt. */ +@font-face { + font-family: Charter; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url("/assets/fonts/charter-regular.woff2") format("woff2"); +} + +@font-face { + font-family: Charter; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url("/assets/fonts/charter-bold.woff2") format("woff2"); +} + :root { color-scheme: light dark; @@ -23,6 +41,7 @@ --wrap: 72rem; + --font-heading: Charter, Georgia, "Times New Roman", serif; --font-body: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; } @@ -63,6 +82,7 @@ h1, h2, h3 { margin: 0; + font-family: var(--font-heading); line-height: 1.08; letter-spacing: -0.02em; text-wrap: balance;