Widen the prettier gate to markdown and CSS everywhere (closes #12) #32

Merged
clawbot merged 2 commits from issue-12-widen-prettier-scope into main 2026-08-09 18:30:36 +02:00
5 changed files with 112 additions and 62 deletions

View File

@@ -1,2 +1,25 @@
node_modules/ node_modules/
yarn.lock yarn.lock
# Site content. Measured, not assumed: formatting content/_index.md
# re-wrapped one list item, and the rendered public/index.html changed
# with it - the wrap landed as a literal newline between "7 PM at" and
# the following <a> tag. HTML collapses that newline to a space, so the
# page looks the same, but the published bytes are not the same, and
# this content carries raw HTML blocks (div/span/br) that goldmark
# passes through verbatim because hugo.toml sets
# markup.goldmark.renderer.unsafe = true. A formatter that can silently
# change a published page is not worth the consistency, so content/ is
# formatted by hand.
content/
# Hugo layout templates. REPO_POLICIES.md puts HTML in prettier's
# scope, but these files are not HTML: they are Go templates carrying
# {{ define }}, {{ block }}, {{ .Content }} and
# {{ readFile ... | safeCSS }}. Prettier has no Go-template parser, so
# it would either fail outright or reflow the delimiters into markup
# Hugo can no longer parse. Formatting them would require an
# out-of-tree prettier plugin, which in turn requires a package.json -
# deliberately out of scope for this repo. Excluded on purpose, not by
# oversight.
themes/loravega/layouts/

19
TODO.md
View File

@@ -28,6 +28,25 @@ remaining policy scaffold is otherwise complete.
# Completed Steps # Completed Steps
- 2026-08-09: widened the prettier gate from top-level markdown to `'**/*.md'`
and `'**/*.css'` (closes #12). `themes/loravega/static/css/style.css` was
never formatted or gated even though it is inlined into every page; it is now
both, and the reformat landed as its own commit ahead of the script change so
no commit in the branch is red. `content/` is excluded in `.prettierignore`,
and that exclusion is measured rather than assumed: with `content/` in scope,
prettier re-wrapped one list item in `content/_index.md` and the rendered
`public/index.html` changed with it (the wrap became a literal newline between
`7 PM at` and the following `<a>`). HTML collapses that newline to a space so
the page looks identical, but the published bytes are not, and this content
carries raw HTML that goldmark passes through verbatim under `unsafe = true`.
`themes/loravega/layouts/` is excluded too, with the reason recorded: those
files are Go templates, not HTML, and prettier has no parser for `{{ ... }}`
covering them would need a plugin and therefore a `package.json`. Verified by
extracting `public/` from the built image before and after: with the final
scope, `index.html`, `index.xml` and `sitemap.xml` are byte-identical and only
the verbatim-copied `public/css/style.css` changes, in whitespace only — the
minified `<style>` block inlined into `index.html` is unchanged, which is the
direct evidence that CSS formatting cannot reach the rendered page
- 2026-08-09: added the canonical policy dotfiles and hardened both ignore files - 2026-08-09: added the canonical policy dotfiles and hardened both ignore files
(closes #8). `REPO_POLICIES.md` is a byte-identical copy of the canonical (closes #8). `REPO_POLICIES.md` is a byte-identical copy of the canonical
`prompts` file, front matter intact; `.editorconfig`, `.prettierrc` and `prompts` file, front matter intact; `.editorconfig`, `.prettierrc` and

View File

@@ -1,8 +1,11 @@
#!/bin/sh #!/bin/sh
# script/fmt: format the repo's own top-level markdown docs (README.md, # script/fmt: format this repo's markdown and CSS with prettier, using
# TODO.md, ...) with prettier, using our standard settings. Scope is # our standard settings. Scope is every markdown and CSS file in the
# deliberately limited to top-level docs: site content under content/ # tree, per REPO_POLICIES.md ("prettier for JS/CSS/Markdown/HTML").
# is left untouched so rendered output cannot change. # What is deliberately NOT covered is recorded in .prettierignore, with
# the reason next to each entry: the Hugo layout templates, which are
# Go templates and not HTML, and content/, whose reformatting was
# measured to change the rendered page.
set -eu set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
@@ -12,7 +15,7 @@ PRETTIER_VERSION="3.4.2"
main() { main() {
cd "$ROOT" cd "$ROOT"
npx --yes "prettier@${PRETTIER_VERSION}" --write \ npx --yes "prettier@${PRETTIER_VERSION}" --write \
'*.md' --tab-width 4 --prose-wrap always '**/*.md' '**/*.css' --tab-width 4 --prose-wrap always
} }
main "$@" main "$@"

View File

@@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# script/fmt-check: check the formatting of the repo's own top-level # script/fmt-check: check the formatting of this repo's markdown and
# markdown docs (read-only). Same scope as script/fmt, but fails # CSS (read-only). Same scope and same settings as script/fmt - keep
# instead of writing. # the two in sync - but fails instead of writing.
set -eu set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
@@ -11,7 +11,7 @@ PRETTIER_VERSION="3.4.2"
main() { main() {
cd "$ROOT" cd "$ROOT"
npx --yes "prettier@${PRETTIER_VERSION}" --check \ npx --yes "prettier@${PRETTIER_VERSION}" --check \
'*.md' --tab-width 4 --prose-wrap always '**/*.md' '**/*.css' --tab-width 4 --prose-wrap always
} }
main "$@" main "$@"

View File

@@ -1,101 +1,106 @@
:root { :root {
--bg: #ffffff; --bg: #ffffff;
--fg: #1a1a1a; --fg: #1a1a1a;
--accent: #0066cc; --accent: #0066cc;
--muted: #666; --muted: #666;
--max-w: 600px; --max-w: 600px;
} }
* { margin: 0; padding: 0; box-sizing: border-box; } * {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body { body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
background: var(--bg); "Helvetica Neue", Arial, sans-serif;
color: var(--fg); background: var(--bg);
line-height: 1.6; color: var(--fg);
padding: 2rem 1rem; line-height: 1.6;
max-width: 90%; padding: 2rem 1rem;
margin: 0 auto; max-width: 90%;
margin: 0 auto;
} }
h1 { h1 {
font-size: 1.8rem; font-size: 1.8rem;
margin-bottom: 0.25rem; margin-bottom: 0.25rem;
} }
.tagline { .tagline {
color: var(--muted); color: var(--muted);
margin-bottom: 2rem; margin-bottom: 2rem;
} }
h2 { h2 {
font-size: 1.2rem; font-size: 1.2rem;
margin-top: 2rem; margin-top: 2rem;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
border-bottom: 1px solid #e0e0e0; border-bottom: 1px solid #e0e0e0;
padding-bottom: 0.25rem; padding-bottom: 0.25rem;
} }
h3 { h3 {
font-size: 1rem; font-size: 1rem;
margin-top: 1.5rem; margin-top: 1.5rem;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
font-weight: 600; font-weight: 600;
color: var(--muted); color: var(--muted);
} }
ul { ul {
list-style: none; list-style: none;
padding: 0; padding: 0;
} }
li { li {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
a { a {
color: var(--accent); color: var(--accent);
text-decoration: none; text-decoration: none;
} }
a:hover { a:hover {
text-decoration: underline; text-decoration: underline;
} }
.settings { .settings {
background: #f8f8f8; background: #f8f8f8;
border: 1px solid #e0e0e0; border: 1px solid #e0e0e0;
border-radius: 4px; border-radius: 4px;
padding: 1rem; padding: 1rem;
margin-top: 0.5rem; margin-top: 0.5rem;
font-family: "SF Mono", "Fira Code", "Consolas", monospace; font-family: "SF Mono", "Fira Code", "Consolas", monospace;
font-size: 0.9rem; font-size: 0.9rem;
line-height: 1.8; line-height: 1.8;
overflow-wrap: break-word; overflow-wrap: break-word;
word-break: break-all; word-break: break-all;
} }
.settings .label { .settings .label {
color: var(--muted); color: var(--muted);
} }
.settings .value { .settings .value {
color: var(--accent); color: var(--accent);
} }
.mono-link { .mono-link {
font-family: "SF Mono", "Fira Code", "Consolas", monospace; font-family: "SF Mono", "Fira Code", "Consolas", monospace;
font-size: 0.85rem; font-size: 0.85rem;
} }
footer { footer {
margin-top: 3rem; margin-top: 3rem;
color: var(--muted); color: var(--muted);
font-size: 0.8rem; font-size: 0.8rem;
border-top: 1px solid #e0e0e0; border-top: 1px solid #e0e0e0;
padding-top: 1rem; padding-top: 1rem;
} }
.contribute-link { .contribute-link {
font-size: 0.7rem; font-size: 0.7rem;
} }