feat(templates): let the column-flow presets take a runtime module - #591
Merged
Merged
Conversation
SidebarPortrait, MonogramSidebar and MintEditorial declare ModularCvTemplate, so CvTemplates.modular() offers a two-column design to a CV assembled at runtime rather than only single-column ones. They earn it through their own renderers: a module is lowered by SectionRouter to the shape its slot draws and drawn by that slot, or by the leftover tail under the author's heading, which is why it already comes out in the preset's style. Declaring it cost two of them a habit. Sidebar Portrait and Monogram Sidebar drew a grouped skills section as one flat run of every skill in the CV — the shipped fixture has thirty-two of them under six category names, and not one of those names reached a page — so a module whose only label was its group name arrived anonymous. Each group is headed by its own name now. That label is skipped when it would repeat the heading the block just drew. A module whose items carry no bodies is lowered into a single group named after the module itself, so the sidebar would otherwise print the section's title twice in a row. The comparison is on the titles as written rather than through SectionLookup.normalize: that strips every character outside [a-z0-9] because it matches English keyword lists, so two Cyrillic titles both reduce to the empty string and every non-Latin CV would lose the label instead. MintEditorial's own bars/index dedup went the same way — it was safe only because one side of it is always a Latin literal. kit() returns the canonical kit for all three, and says why: a kit styles the bodies a preset routes through SectionDispatcher, and these route none. The interface's promise repeated a sentence this change falsifies — "every shipped preset composes a single main column" — which is now what it always meant: every preset reads Slot.MAIN and no other, including the ones that compose a sidebar of their own. ModularCvTemplateFidelityTest grew three corrections. Its item assertions dropped case but not letter-spacing while its heading assertion dropped both, so a preset that letter-spaces an entry title failed for its typography rather than for losing anything; items are normalised the same way headings always were, per paragraph, so a match has to live inside one node instead of being assembled out of two that happen to adjoin. It required the canonical "Java 21, Kotlin" join for a skills group, which is a rendering style and not a promise; it asserts the group's name and its skills in order as a subsequence now, keeping the grouping and ordering the join carried while leaving bars, chips or a list to the preset. And its per-kind markers were prefixes of one another — "Item ENTRIES" lives inside "Item ENTRIES DATED" — so a template could drop two of the six kinds outright and stay green. groupTokens reads SkillGroup.skills() rather than splitting skillsInline() back apart on commas, which cut a skill carrying a comma of its own in half. docs/templates/v2-layered/using-templates.md still said these three were kept off the modular list because they rename headings, which stopped being true when every slot started printing the author's title.
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
CvTemplates.modular()is the list a CV builder offers when the CV is assembled atruntime, and every template on it was single-column. The three column-flow presets —
SidebarPortrait,MonogramSidebar,MintEditorial— had everything the promise needsafter the leftover-tail and slot-heading work, but nothing said so, so a caller building
a CV from data could not offer a two-column design at all.
What
The three declare
ModularCvTemplate; the list goes from seven templates to ten. Theyearn it through their own renderers rather than the shared dispatcher: a module is
lowered by
SectionRouterto the shape its slot draws and drawn by that slot, or by theleftover tail under the author's heading — which is why it already comes out in the
preset's style.
Rather than guess what the contract needed, I declared the interface and let
ModularCvTemplateFidelityTestanswer. It found six failures, and the split is theinteresting part: four were the harness, one was over-specification, and two
were real.
The real one. Sidebar Portrait and Monogram Sidebar drew a grouped skills section as
one flat run of every skill in the CV. The shipped fixture has thirty-two skills under six
category names and not one of those names reached a page, so a module whose only label was
its group name arrived anonymous. Each group is headed by its own name now — which is also
easier to read than twelve-plus unlabelled lines.
That label is skipped when it would repeat the heading the block just drew: a module whose
items carry no bodies is lowered into a single group named after the module itself, so the
sidebar would otherwise print the section's title twice in a row. The comparison is on the
titles as written, not through
SectionLookup.normalize— that strips every characteroutside
[a-z0-9]because it matches English keyword lists, so two Cyrillic titles bothreduce to
""and every non-Latin CV would lose the label instead. The gate caught thatone on the way in.
MintEditorial's own bars/index dedup went the same way; it was safeonly because one side of it is always a Latin literal.
kit()returns the canonical kit for all three, and says why: a kit styles the bodiesa preset routes through
SectionDispatcher, and these route none.SectionDispatcheralso resets the host's spacing and padding, which would fight a column layout, and
CvRenderKithas no way to say which of a two-column preset's body styles it is drawing.Tests
ModularCvTemplateFidelityTestgained three corrections, all of which weaken nothing:both, so a preset that letter-spaces an entry title failed for its typography rather
than for losing anything. Items are normalised the same way headings always were — and
per paragraph, so a match has to live inside one node rather than being assembled
out of two that happen to adjoin, which whole-page squashing would have allowed.
"Java 21, Kotlin"join for a skills group. That is arendering style, not a promise — a preset drawing bars or a list shows both skills and
failed anyway. It asserts the group's name and its skills in order, as a subsequence,
which keeps the grouping and ordering the join carried.
Item ENTRIESlives insideItem ENTRIES DATED, so a template could drop two of the six kinds outright and staygreen. Pre-existing, and this change re-derived every one of those assertions, so it is
fixed here.
SlotHeadingFidelityTestgains the case the fidelity fixtures never reach — a skillsmodule whose items carry no bodies, which is the natural runtime shape for a flat list.
Both presets were sabotaged to confirm it goes red without the dedup.
groupTokensreadsSkillGroup.skills()instead of splittingskillsInline()back aparton commas, which cut a skill carrying a comma of its own in half.
Full reactor gate green. Four baselines re-recorded (
sidebar_portrait×2,monogram_sidebar×2), the twelvevisual.approverewrote as collateral reverted, twocommitted previews refreshed. The pixel gate passed at every step without being told
anything — measured at budget 0, the grouping moves 3,515 + 11,923 px on Sidebar Portrait
and 1,019 + 9,687 on Monogram Sidebar, all well under the 50,000 the budget allows for
cross-platform font drift.
docs/templates/v2-layered/using-templates.mdstill told readers these three were keptoff the modular list because they rename headings — which stopped being true when every
slot started printing the author's title. That paragraph, the single-main-column claim it
repeated, and the
CvRenderKitparagraph are updated; the same falsified sentence inModularCvTemplate's own Javadoc is corrected too.