feat(templates): add the Midnight Navy plate CV preset - #634
Merged
DemchaAV merged 2 commits intoAug 31, 2026
Merged
Conversation
A one-page CV on a full-height navy plate: an outlined monogram over a two-weight name and a tracked role line, then contact, education, metered skills and dotted languages down the plate, beside a paper column with the summary, roles on a rail, achievement discs and divided certification columns. Ships as cv.presets.MidnightNavy on the existing CvDocument model, so the port needed no model change. The plate is a page background rather than a section fill — it reaches three paper edges — sized by the same ratio the body row splits on. The monogram and the role line are built from the identity, so a document fills neither in twice. One page strictly: the body is a single row and a row is atomic, so a longer CV is refused with the node that could not fit rather than being cut. Splitting the row would leave the plate on one page and half the aside on the next. Guarded by a 15-case smoke test, an exact layout snapshot and a pixel-parity gate.
An accent is drawn centred on the edge it belongs to, so an entry section's left edge already is the rail's axis: a marker reaches it by walking back across the gutter and half its own width, and nothing else. Correcting by half the rail's thickness on top of that pushed every marker a rail width to the right of the line it sits on — 0.72 pt, measured on the render as a marker centre at x=449.5 against a rail centre at x=448.0 at 150 dpi. Centred, the residual is half a raster pixel at any resolution (0.24 pt at 150 dpi, 0.06 pt at 600), which is antialiasing rather than geometry. The change costs 200 of 2 173 720 pixels against the ported sheet, and both baselines are re-recorded with it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
midnight-navy-cvis the first of a second batch of finished AI Flow bundles. It is anavy-plate sidebar CV — an outlined monogram, metered skills, dotted language ratings,
an experience rail and achievement discs — and none of that combination is reachable
from a built-in preset today.
What
cv.presets.MidnightNavyon the existingCvDocumentmodel; the port needed no modelchange. Split as the family is:
MidnightNavyroutes,MidnightNavyStylesholds thetokens, and
Aside/Main/Widgets/Iconsdraw.The plate is page chrome, not a fill. The navy reaches the top, left and bottom
paper edges and a section's fill stops at its own box, so the plate is a page
background sized by the same ratio the body row splits on — the two cannot drift apart.
Every horizontal pair goes through one wrapper. A row nested directly in a row cell
is refused and both columns are cells, so a skill and its meter, a language and its
dots, a title and its dates, a disc and its line, and the certification columns are
each a row wrapped in a single layer of a stack.
Three marks are relationships rather than lengths. The experience rail is the entry
section's left accent, so its height derives from the entry and the gap between entries
is padding inside the border — which is what makes consecutive rails meet instead of
breaking between roles. A certification divider is its column's own accent. A skill
meter is three layers sharing the track's axis; seating one at the stack's top instead
draws a meter as three unaligned pieces.
The monogram and the role line come from the identity — two initials and the name's
own words — so a document fills neither in twice.
Seven berths reach their sections by title. The contact heading is the preset's own,
because a document has no section that carries it.
Two deliberate departures from the ported sheet, both measured. A link is drawn as
its own label with the address behind it, as on the presets before it. And every rail
marker is centred on its rail: an accent is drawn centred on the edge it belongs to, so
the section's left edge already is the rail's axis, and the ported sheet's extra
half-thickness correction put each marker a rail width to the right of the line it sits
on. Measured on the render, the marker centre was at x=449.5 against a rail centre at
x=448.0 at 150 dpi — 0.72 pt, visible at reading size. Centred, the residual is half
a raster pixel at any resolution (0.24 pt at 150 dpi, 0.06 pt at 600), which is
antialiasing rather than geometry. Together the two departures come to 2 498 of
2 173 720 pixels, of which the centring is 200.
One page, strictly
The body is a single row and a row is atomic, so this sheet does not paginate: a
longer CV is refused with an
AtomicNodeTooLargeExceptionnaming the node rather thanbeing cut. That is the honest failure for a design whose two columns have to reach the
same foot — splitting the row would leave the plate on one page and half the aside on
the next. The first draft of this PR claimed it flowed; the smoke test disproved it,
and both the Javadoc and the test now pin the real behaviour.
Tests
against the bundle's 240. The bundle also freezes to 0 against its own published
preview on both its pinned engine (2.2.2) and
2.2.3-SNAPSHOT, so there is no enginedrift to account for here.
MidnightNavySmokeTest— 15 cases: the packaged marks, the unknown-mark data error,the monogram taken from the name, the uppercased name and tracked role, a language
rating rounded to the nearest of five dots, a skill with no level, a trunk prefix left
undialled, the link targets on every kind of title, a dropped berth, a document with
nothing but an identity, and the refusal past one page.
MidnightNavyLayoutSnapshotTest— exact geometry, 240 nodes, one page.MidnightNavyVisualParityTest— pixel baseline; recorded without disturbing any otherbaseline in the suite.
./mvnw -B -ntp clean verify -pl :graph-compose-core,:graph-compose-render-pdf,:graph-compose-render-docx,:graph-compose-render-pptx,:graph-compose-templates,:graph-compose-testing,:graph-compose-qa,:graph-compose-coverage -amcv-midnight-navy-v2;assets/readme/examples/cv-midnight-navy-v2.pdfis regenerated from the committed code.