diff options
Diffstat (limited to 'AGENTS.md')
| -rw-r--r-- | AGENTS.md | 26 |
1 files changed, 20 insertions, 6 deletions
@@ -185,13 +185,23 @@ internal/web/ server.go (host router, middleware, render helpers) header text colour; hidden on phones so a long title can wrap. `NavStyle` `plain` is regular weight + underline for the menu links (blog.css makes them bold). + **Custom fonts** (`CustomFont`, `CustomHeadingFont`: font file ids or ""): + a chosen file is declared as `@font-face` (`"BlogFont"` / `"BlogHeadingFont"`, + `src:url(/media/<id>)`, same-origin so no CORS) and put first in the stack, + the built-in `Font`/`HeadingFont` choice behind it as the fallback — so + there is no "custom" enum value and no invalid state. `HeadingFontFamily` + builds on the text's stack when `HeadingFont` is `same`, and the `h1…h6` + rule is emitted whenever `HeadingFontSet` (a heading choice or a heading + file). Picked with the `fontpick` partial: a plain `<select>` of the newest + `recentImages` library fonts (`kind = font`) plus the chosen older one, and + an upload input — no library panel, no script. Optional colours (`LinkHover`, `NavHover`) are `""` = inherit and come from a colour input paired with a `<name>_custom` checkbox, shown/hidden with CSS only (`.hoverpick > input:not(:checked) ~ …`). Image fields use the `imagepick` partial: a `<select>` of the `recentImages` newest library images (`kind = image`) plus the chosen one (`imageNames` looks up an older - one's filename), so the page never grows with the library; `none` clears, a - uuid selects, no value keeps (`pickImage`); an upload in `<name>_file` wins. + one's filename, fonts included), so the page never grows with the library; `none` clears, a + uuid selects, no value keeps (`pickFile`); an upload in `<name>_file` wins. The `imagelib` partial (one per form; the design page and the post form both include it) is the panel behind "Choose from library…", with its own script: it marks every `.imagepick` with `.js` (hiding the select, showing @@ -245,15 +255,18 @@ internal/web/ server.go (host router, middleware, render helpers) - **Files** (`files` table, `store/files.go`, `handlers_files.go`, `filetype.go`, `/b/{sub}/files…`): the upload library, any type. A row is `id, filename, content_type, kind, size, data`; `kind` (image, document, - audio, video, archive, other) is decided at upload by `fileType`, which + audio, video, font, archive, other) is decided at upload by `fileType`, which trusts `http.DetectContentType` first and lets the extension refine only a generic sniff (text/plain, octet-stream) to a type on the allowlists in `filetype.go`; anything unknown is stored as `application/octet-stream`. + Fonts (`fontTypes`: WOFF2, WOFF, TTF, OTF) are known by their bytes alone, + like images; TTC and EOT stay `other`. `/media/{uuid}` is served on every host with immutable cache headers, from the host's blog database only (the root domain serves the root blog's files); dashboard previews for another blog on the root host use `GET /b/{sub}/media/{id}` (`withBlog`). **The root domain carries the - session cookie, so `servedAs` renders inline only images, PDF, plain text, + session cookie, so `servedAs` renders inline only images, fonts (a browser + parses one only inside `@font-face`), PDF, plain text, audio and video; everything else (HTML, SVG, XML, JS, archives, binaries) goes out as `application/octet-stream` + `Content-Disposition: attachment`.** `?download` forces attachment. SVG is therefore never an image (download @@ -293,7 +306,8 @@ internal/web/ server.go (host router, middleware, render helpers) `outro_file`) + `appendFile(body, f, format)` (the no-JS path: `fileMarkdown` or `fileHTML`, i.e. `<img>`/`<a>`), and store `renderBody(format, src)` (`markdown.Render`, or the source untouched - for HTML) in the `*_html` column — the public templates only ever print + for HTML) in the `*_html` column (`readUpload`'s last argument is the kind + the field must be — `"image"`, `"font"` — or `""` for anything) — the public templates only ever print that column. **HTML mode** (`.editor.html`, toggled by the radios): the Markdown toolbar groups (`.ed-md`), link box, shortcuts, list continuation and cheat-sheet @@ -444,7 +458,7 @@ superadmin password to `admin`. Production refuses both. `-- +goose Up/Down` sections; they run automatically at startup. Never edit an applied migration. Blog chain so far: `00001_init`, `00002_language`, `00003_files`, `00004_tags`, `00005_search`, `00006_format`, `00007_post_image`, - `00008_page_outro`, `00009_gizmo_style`; control: `00001_init`, `00002_upload_limit`. Both chains were re-baselined at 00001 after + `00008_page_outro`, `00009_gizmo_style`, `00010_font_kind`; control: `00001_init`, `00002_upload_limit`. Both chains were re-baselined at 00001 after the move to per-blog databases; deployments from before it have `goose_db_version` rows 2–7 in the control DB that must be deleted once (README "Upgrading from a single database") or the next control migration |
