Widen the prettier gate to cover CSS and all Markdown, not just top-level docs #12

Closed
opened 2026-08-09 03:43:02 +02:00 by clawbot · 2 comments
Collaborator

Problem

REPO_POLICIES.md scopes prettier to "JS/CSS/Markdown/HTML". script/fmt and
script/fmt-check in this repo cover only '*.md' — top-level markdown. The
canonical scripts use '**/*.md'.

Currently unformatted and ungated:

  • themes/loravega/static/css/style.css — CSS, squarely in scope.
  • content/_index.md and archetypes/default.md — Markdown, in scope, but
    see the caveat below.
  • themes/loravega/layouts/_default/baseof.html and
    themes/loravega/layouts/index.html — HTML, in scope by the letter of the
    policy, but see "no sensible equivalent" below.

The existing narrow scope was a deliberate choice, documented in the script
comment: "Scope is deliberately limited to top-level docs: site content under
content/ is left untouched so rendered output cannot change." That reasoning
is sound for one of the three file types and wrong for the other two.

What to change

CSS — add it. style.css is inlined verbatim into every page by
baseof.html via readFile. Prettier's CSS formatting is whitespace-only and
cannot change rendering. There is no reason it is not covered. Add '**/*.css'
to both scripts.

Markdown under content/ — add it, carefully. The stated fear is that
reformatting changes rendered output. For this content it is worth checking
rather than assuming: content/_index.md contains raw HTML blocks (<div class="settings">, <br>, <span>) and hugo.toml sets
markup.goldmark.renderer.unsafe = true, so the HTML passes through. Prettier
does reflow markdown and can alter whitespace inside and around inline HTML.

The correct procedure: run make fmt with the widened glob, build before and
after, and diff the generated public/index.html. If the rendered output is
byte-identical, include content/ and archetypes/. If it differs at all,
exclude content/ via .prettierignore and say so in the script comment

a formatter that can silently change a published page is not worth the
consistency. Report the result either way in the PR.

No sensible Hugo equivalent — do not force this

HTML templates under themes/loravega/layouts/ must stay excluded. The
policy says prettier covers HTML, but these are not HTML — they are Go
templates containing {{ define }}, {{ block }}, {{ .Content }}, and
{{ readFile ... | safeCSS }}. Prettier has no Go-template parser; it will
either fail or reflow the delimiters into something Hugo cannot parse. There is
no supported prettier plugin for Hugo templates in the org's dependency policy
(and adding an unvetted one would need hash-pinning and a package.json, which
#8 explicitly rules out). Add these paths to .prettierignore with a comment
explaining why, so the exclusion is a recorded decision and not an oversight.

Definition of done

  1. script/fmt and script/fmt-check cover '**/*.md' and '**/*.css'.
  2. themes/loravega/layouts/ is listed in .prettierignore with a comment
    stating that Go templates are not parseable by prettier.
  3. The before/after rendered-output comparison for content/ has been done and
    its result is stated in the PR. content/ is either covered (output
    identical) or in .prettierignore with a comment (output differed).
  4. The reformat itself is a separate commit from the script change.
    REPO_POLICIES.md: "If the repo has never been formatted to our standards,
    run make fmt and commit the result as a standalone branch/commit/PR before
    any other changes. Formatting diffs can be large and should not be mixed
    with functional changes."
  5. make fmt-check passes on a clean tree afterwards.
  6. make check passes and script/cibuild succeeds.
  7. The script comments in script/fmt and script/fmt-check are updated —
    they currently describe the old narrow scope.
  8. TODO.md updated.

Depends on

  • #8 (adds .prettierignore). Do not start this until #8 has landed, or this
    PR will have to create that file itself and conflict.

Ref: REPO_POLICIES.md — "Use platform-standard formatters… prettier for
JS/CSS/Markdown/HTML"; canonical script/fmt glob '**/*.md'.

## Problem `REPO_POLICIES.md` scopes prettier to "JS/CSS/Markdown/HTML". `script/fmt` and `script/fmt-check` in this repo cover only `'*.md'` — top-level markdown. The canonical scripts use `'**/*.md'`. Currently unformatted and ungated: - `themes/loravega/static/css/style.css` — CSS, squarely in scope. - `content/_index.md` and `archetypes/default.md` — Markdown, in scope, but see the caveat below. - `themes/loravega/layouts/_default/baseof.html` and `themes/loravega/layouts/index.html` — HTML, in scope by the letter of the policy, but see "no sensible equivalent" below. The existing narrow scope was a deliberate choice, documented in the script comment: "Scope is deliberately limited to top-level docs: site content under `content/` is left untouched so rendered output cannot change." That reasoning is sound for one of the three file types and wrong for the other two. ## What to change **CSS — add it.** `style.css` is inlined verbatim into every page by `baseof.html` via `readFile`. Prettier's CSS formatting is whitespace-only and cannot change rendering. There is no reason it is not covered. Add `'**/*.css'` to both scripts. **Markdown under `content/` — add it, carefully.** The stated fear is that reformatting changes rendered output. For this content it is worth checking rather than assuming: `content/_index.md` contains raw HTML blocks (`<div class="settings">`, `<br>`, `<span>`) and `hugo.toml` sets `markup.goldmark.renderer.unsafe = true`, so the HTML passes through. Prettier does reflow markdown and can alter whitespace inside and around inline HTML. The correct procedure: run `make fmt` with the widened glob, build before and after, and diff the generated `public/index.html`. If the rendered output is byte-identical, include `content/` and `archetypes/`. **If it differs at all, exclude `content/` via `.prettierignore` and say so in the script comment** — a formatter that can silently change a published page is not worth the consistency. Report the result either way in the PR. ## No sensible Hugo equivalent — do not force this **HTML templates under `themes/loravega/layouts/` must stay excluded.** The policy says prettier covers HTML, but these are not HTML — they are Go templates containing `{{ define }}`, `{{ block }}`, `{{ .Content }}`, and `{{ readFile ... | safeCSS }}`. Prettier has no Go-template parser; it will either fail or reflow the delimiters into something Hugo cannot parse. There is no supported prettier plugin for Hugo templates in the org's dependency policy (and adding an unvetted one would need hash-pinning and a `package.json`, which #8 explicitly rules out). Add these paths to `.prettierignore` with a comment explaining why, so the exclusion is a recorded decision and not an oversight. ## Definition of done 1. `script/fmt` and `script/fmt-check` cover `'**/*.md'` and `'**/*.css'`. 2. `themes/loravega/layouts/` is listed in `.prettierignore` with a comment stating that Go templates are not parseable by prettier. 3. The before/after rendered-output comparison for `content/` has been done and its result is stated in the PR. `content/` is either covered (output identical) or in `.prettierignore` with a comment (output differed). 4. The reformat itself is a **separate commit** from the script change. `REPO_POLICIES.md`: "If the repo has never been formatted to our standards, run `make fmt` and commit the result as a standalone branch/commit/PR before any other changes. Formatting diffs can be large and should not be mixed with functional changes." 5. `make fmt-check` passes on a clean tree afterwards. 6. `make check` passes and `script/cibuild` succeeds. 7. The script comments in `script/fmt` and `script/fmt-check` are updated — they currently describe the old narrow scope. 8. `TODO.md` updated. ## Depends on - #8 (adds `.prettierignore`). Do not start this until #8 has landed, or this PR will have to create that file itself and conflict. Ref: `REPO_POLICIES.md` — "Use platform-standard formatters… `prettier` for JS/CSS/Markdown/HTML"; canonical `script/fmt` glob `'**/*.md'`.
Author
Collaborator

Implementation plan (dependency on #8 is satisfied — .prettierrc and .prettierignore are on main as of 7dea837):

  1. Establish the content/ verdict first, empirically. Build public/ from the clean tree inside the pinned-Hugo image (docker build with CHECK_EPOCH, then extract /src/public from the image — no bind mounts, so nothing root-owned lands in the checkout). Then run prettier over content/ and archetypes/, rebuild, and diff the two rendered trees byte-for-byte. content/_index.md has raw <div class="settings"> / <br> / <span> blocks and hugo.toml has markup.goldmark.renderer.unsafe = true, so this is a real risk, not a formality. Identical output → content/ and archetypes/ are covered. Any difference at all → content/ goes into .prettierignore with a comment recording why. Result reported either way.
  2. .prettierignore: add themes/loravega/layouts/ with a comment stating these are Go templates ({{ define }}, {{ block }}, {{ readFile ... | safeCSS }}), which prettier has no parser for and would mangle. No prettier plugin, no package.json — out of scope. Plus the content/ entry if step 1 says so.
  3. Widen the glob in script/fmt and script/fmt-check to '**/*.md' and '**/*.css', and rewrite both header comments, which currently describe the old top-level-only scope.
  4. Commit ordering. Every commit must pass make check on its own — an intermediate red commit is what forced #31 to land as a merge commit. So: commit 1 is the pure reformat (prettier applied by hand-invoking the widened scope, but the scripts still at the old narrow glob, so make fmt-check passes both before and after it); commit 2 widens the glob and adds the ignore entries, and passes because the tree is already formatted. content/ reformat, if it happens, is in commit 1 with the rest of the churn, never mixed with the functional change.
  5. TODO.md updated in the functional commit.
  6. Verification: make check on a clean tree, then script/cibuild, confirming the check layer actually executed (#23's CHECK_EPOCH should guarantee that, but the output gets inspected rather than assumed).

script/bootstrap and .gitea/workflows/deploy.yml are untouched; the deploy path is unaffected.

Implementation plan (dependency on https://git.eeqj.de/sneak/lora.vegas/issues/8 is satisfied — `.prettierrc` and `.prettierignore` are on `main` as of `7dea837`): 1. **Establish the `content/` verdict first, empirically.** Build `public/` from the clean tree inside the pinned-Hugo image (`docker build` with `CHECK_EPOCH`, then extract `/src/public` from the image — no bind mounts, so nothing root-owned lands in the checkout). Then run prettier over `content/` and `archetypes/`, rebuild, and diff the two rendered trees byte-for-byte. `content/_index.md` has raw `<div class="settings">` / `<br>` / `<span>` blocks and `hugo.toml` has `markup.goldmark.renderer.unsafe = true`, so this is a real risk, not a formality. Identical output → `content/` and `archetypes/` are covered. Any difference at all → `content/` goes into `.prettierignore` with a comment recording why. Result reported either way. 2. **`.prettierignore`:** add `themes/loravega/layouts/` with a comment stating these are Go templates (`{{ define }}`, `{{ block }}`, `{{ readFile ... | safeCSS }}`), which prettier has no parser for and would mangle. No prettier plugin, no `package.json` — out of scope. Plus the `content/` entry if step 1 says so. 3. **Widen the glob** in `script/fmt` and `script/fmt-check` to `'**/*.md'` and `'**/*.css'`, and rewrite both header comments, which currently describe the old top-level-only scope. 4. **Commit ordering.** Every commit must pass `make check` on its own — an intermediate red commit is what forced https://git.eeqj.de/sneak/lora.vegas/pulls/31 to land as a merge commit. So: commit 1 is the pure reformat (prettier applied by hand-invoking the widened scope, but the scripts still at the old narrow glob, so `make fmt-check` passes both before and after it); commit 2 widens the glob and adds the ignore entries, and passes because the tree is already formatted. `content/` reformat, if it happens, is in commit 1 with the rest of the churn, never mixed with the functional change. 5. `TODO.md` updated in the functional commit. 6. Verification: `make check` on a clean tree, then `script/cibuild`, confirming the check layer actually executed (`#23`'s `CHECK_EPOCH` should guarantee that, but the output gets inspected rather than assumed). `script/bootstrap` and `.gitea/workflows/deploy.yml` are untouched; the deploy path is unaffected.
Author
Collaborator

Implemented in #32.

The content/ verdict: the rendered output DIFFERED, so content/ is excluded. With content/ in scope, prettier re-wrapped one list item in content/_index.md (the Lee's Sandwiches line), and the built public/index.html changed with it — the wrap arrived as a literal newline between 7 PM at and the following <a> tag inside the <li>. HTML collapses that newline to a space so the page looks identical, but the published bytes do not match, and per this issue's own rule that is enough to exclude. content/ is in .prettierignore with a comment recording the measurement, and both script/fmt and script/fmt-check name the exclusion in their header comments. The raw <div class="settings"> blocks were untouched in this particular run, but they pass through verbatim under markup.goldmark.renderer.unsafe = true, so the risk the issue anticipated is real. archetypes/ stays covered — it is a template for new content, not published output, and prettier leaves it unchanged.

themes/loravega/layouts/ is excluded with its own comment: Go templates, no prettier parser, and covering them would need a plugin and therefore a package.json. No plugin was added.

Both scripts now run '**/*.md' '**/*.css', so themes/loravega/static/css/style.css is formatted and gated for the first time.

Two commits, both green on their own, so no merge commit is needed. The reformat lands first, while the scripts still carry the old '*.md' glob that does not look at CSS; the widening commit then arrives on an already-clean tree. That is the inverse of the ordering that forced #31 to land as a merge commit.

Verification. public/ was extracted from the built image (pinned hugo v0.164.0) before the change and again at the final state: index.html, index.xml and sitemap.xml are byte-identical, and the only file that differs anywhere in the tree is the verbatim-copied public/css/style.css, which is identical once whitespace is stripped. The minified <style> block inlined into index.html is unchanged, which is the direct proof that CSS formatting cannot reach the rendered page. make check passes at both commits, and script/cibuild succeeded with the check layer genuinely executing — its output is present in the build log while the script/bootstrap layers above it are CACHED. script/bootstrap and .gitea/workflows/deploy.yml are untouched, so the deploy path is unaffected; nothing was run against the live Cloudflare Pages deploy.

Implemented in https://git.eeqj.de/sneak/lora.vegas/pulls/32. **The `content/` verdict: the rendered output DIFFERED, so `content/` is excluded.** With `content/` in scope, prettier re-wrapped one list item in `content/_index.md` (the Lee's Sandwiches line), and the built `public/index.html` changed with it — the wrap arrived as a literal newline between `7 PM at` and the following `<a>` tag inside the `<li>`. HTML collapses that newline to a space so the page looks identical, but the published bytes do not match, and per this issue's own rule that is enough to exclude. `content/` is in `.prettierignore` with a comment recording the measurement, and both `script/fmt` and `script/fmt-check` name the exclusion in their header comments. The raw `<div class="settings">` blocks were untouched in this particular run, but they pass through verbatim under `markup.goldmark.renderer.unsafe = true`, so the risk the issue anticipated is real. `archetypes/` stays covered — it is a template for new content, not published output, and prettier leaves it unchanged. `themes/loravega/layouts/` is excluded with its own comment: Go templates, no prettier parser, and covering them would need a plugin and therefore a `package.json`. No plugin was added. Both scripts now run `'**/*.md' '**/*.css'`, so `themes/loravega/static/css/style.css` is formatted and gated for the first time. **Two commits, both green on their own, so no merge commit is needed.** The reformat lands first, while the scripts still carry the old `'*.md'` glob that does not look at CSS; the widening commit then arrives on an already-clean tree. That is the inverse of the ordering that forced https://git.eeqj.de/sneak/lora.vegas/pulls/31 to land as a merge commit. **Verification.** `public/` was extracted from the built image (pinned hugo v0.164.0) before the change and again at the final state: `index.html`, `index.xml` and `sitemap.xml` are byte-identical, and the only file that differs anywhere in the tree is the verbatim-copied `public/css/style.css`, which is identical once whitespace is stripped. The minified `<style>` block inlined into `index.html` is unchanged, which is the direct proof that CSS formatting cannot reach the rendered page. `make check` passes at both commits, and `script/cibuild` succeeded with the check layer genuinely executing — its output is present in the build log while the `script/bootstrap` layers above it are `CACHED`. `script/bootstrap` and `.gitea/workflows/deploy.yml` are untouched, so the deploy path is unaffected; nothing was run against the live Cloudflare Pages deploy.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/lora.vegas#12