Skip to content

text-1c: declare fonts with --font, and render text - #72

Merged
softmarshmallow merged 1 commit into
mainfrom
text-1c-cli-fonts
Aug 5, 2026
Merged

text-1c: declare fonts with --font, and render text#72
softmarshmallow merged 1 commit into
mainfrom
text-1c-cli-fonts

Conversation

@softmarshmallow

Copy link
Copy Markdown
Member

Text was compilable but unreachable from the product surface. #71 admitted <text>, but the CLI had no way to declare a font, so every run refused — the feature shipped behind a door with no handle. This adds the handle, under the hermetic rule the method ratified in #68.

n0 fixtures/web-first/text/svg-text-em-box.svg out.png 100x100 \
  --font Ahem=fixtures/web-first/fonts/ahem.ttf@sha256:b719ecb3…94b8448

The digest is executable

A family name is not a font identity — the same name resolves to different bytes on different machines — so a declaration carries the digest of the bytes it means, and the host verifies before a frame exists. Three behaviors, all exercised against the real binary:

Invocation Result
declared + verified renders; byte-identical to the committed Chromium oracle
no declaration degraded: skipped svg/text[1]: … font family "Ahem" is not in the declared environment
wrong digest error: … is not the declared identity: expected sha256 0000…, read b719ecb3… — refuses before any pixel

No system fallback, no ambient face, no machine-local pixel anywhere on this path.

The end-to-end law

declared_fonts_render_text_and_an_undeclared_one_refuses renders the text cell through the host and asserts it equals fixtures/web-first/text/chromium/svg-text-em-box.png byte for byte — the same cell the compiler gate uses, now proven through the surface it actually ships behind. The parse and verification laws cover the grammar's edges: a path containing = and @ still parses (only the first = ends the family, only the last @sha256: ends the path), a missing or malformed digest refuses with the reason, and the pinned gate font verifies while a wrong digest does not.

Statement of record

crates/n0_cli/README.md gains the text slice — the environment rule, the v0 profile, what places a run, the numeric domain and why it is where the gate holds, and every named refusal (the CSS spelling of text-anchor, a generic family, <tspan>, stroke on text, colour faces, the inline-HTML entry which declares no fonts). That file is the one statement of record for the admitted slice, so this closes the gap #71 left in it.

Full workspace green, fmt and clippy clean, lock unchanged (sha2 was already in the graph).

With this, text is complete end to end and the arc's remaining item is text-2 — the D-M deciding spike.

Text was compilable but unreachable from the product surface: the CLI
had no way to declare a font, so every <text> run refused. It now does,
under the hermetic rule the text-oracle method ratified.

    --font FAMILY=PATH@sha256:HEX        (repeatable)

A family name is not a font identity — the same name resolves to
different bytes on different machines — so a declaration carries the
digest of the bytes it means, and the host verifies them before a frame
exists. A mismatch refuses the render; it never becomes a silently
different pixel. An undeclared family refuses by name: no system
fallback, no ambient face, no machine-local pixel anywhere on this path.

The end-to-end law renders fixtures/web-first/text/svg-text-em-box.svg
through the host and asserts it is the committed Chromium oracle byte
for byte — the same cell the compiler gate uses, now proven through the
product surface it ships behind.

The statement of record gains the text slice: the environment rule, the
v0 profile, what places a run, the numeric domain and why it is where
the gate holds, and every named refusal (including the CSS spelling of
text-anchor, a generic family, and the inline-HTML entry, which declares
no fonts).
@vercel

vercel Bot commented Aug 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nothing Ready Ready Preview Aug 4, 2026 7:03pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 853f2e11-febb-44e5-b70c-5f587b77b68c

📥 Commits

Reviewing files that changed from the base of the PR and between 3a06dd9 and b235d9f.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • crates/n0_cli/Cargo.toml
  • crates/n0_cli/README.md
  • crates/n0_cli/src/fonts.rs
  • crates/n0_cli/src/main.rs

Walkthrough

The CLI now accepts repeatable SHA-256-pinned font declarations. It verifies font bytes, builds a textlayout::Environment, and passes it to SVG rendering. Documentation and tests cover declared fonts, undeclared families, strict rendering, best-effort behavior, and existing render paths.

Changes

Hermetic font rendering

Layer / File(s) Summary
Font declaration and verification
crates/n0_cli/Cargo.toml, crates/n0_cli/src/fonts.rs
Adds FontDeclaration, parses FAMILY=PATH@sha256:HEX, verifies font bytes, and creates a textlayout::Environment.
CLI parsing and render wiring
crates/n0_cli/src/main.rs
Adds repeatable --font handling and passes the verified font environment to standalone SVG rendering.
Text admission and regression coverage
crates/n0_cli/README.md, crates/n0_cli/src/main.rs
Documents declared-font text admission and validates declared, undeclared, strict, best-effort, and existing render paths.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant parse_render_options
  participant load_environment
  participant textlayout_Environment
  participant render_source_to_png
  CLI->>parse_render_options: Parse --font declarations
  parse_render_options-->>CLI: Return FontDeclaration values
  CLI->>load_environment: Verify declared font bytes
  load_environment->>textlayout_Environment: Create verified environment
  textlayout_Environment-->>CLI: Return font environment
  CLI->>render_source_to_png: Render with font environment
Loading

Possibly related PRs

  • gridaco/nothing#68: Introduces the textlayout::Environment and resolver architecture used here.
  • gridaco/nothing#70: Provides the text layout environment that this CLI supplies with verified fonts.
  • gridaco/nothing#71: Adds SVG text rendering extended here with CLI font declarations and verification.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds font and text-rendering support but does not implement issue #39's painter consolidation, debug separation, or architecture lock. Link the PR to the relevant text-rendering issue, or add the required painter refactor, architecture test, and related validation for issue #39.
Out of Scope Changes check ⚠️ Warning The font declaration and text-rendering changes are unrelated to issue #39's required painter module refactor. Remove the font and text-rendering changes from this PR, or update the linked issue to the text-rendering objective they implement.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the addition of CLI font declarations and SVG text rendering.
Description check ✅ Passed The description directly explains hermetic font declarations, digest verification, text rendering, tests, and documentation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch text-1c-cli-fonts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@softmarshmallow
softmarshmallow merged commit 7634fa3 into main Aug 5, 2026
14 checks passed
@softmarshmallow
softmarshmallow deleted the text-1c-cli-fonts branch August 5, 2026 05:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant