feat(templates): declare which presets can be handed a runtime module - #581
Open
DemchaAV wants to merge 1 commit into
Open
feat(templates): declare which presets can be handed a runtime module#581DemchaAV wants to merge 1 commit into
DemchaAV wants to merge 1 commit into
Conversation
A module is only worth building if the template renders it, and not every preset can promise that. Several compose a fixed set of modules and find each by matching headings, so a section they do not recognise never reaches a renderer: the CV comes out, minus a section, looking finished. Nothing about that failure is visible at the point it happens. ModularCvTemplate is the promise and CvTemplates.modular() is the list a CV builder should offer; CvTemplates also answers byId, all, ids, and recommendedMargin, so picking a preset at runtime stops being a map kept by hand in every consumer. Declaring the interface costs something: ModularCvTemplateFidelityTest renders every kind, a section this catalogue has no name for, a heading in a script no keyword list contains, and a heading that does match one, through each template that declares it. Seven presets qualify. ClassicSerif does not — it draws any shape it is given but only gives itself the sections it recognises, and finding that out is what the gate is for. The promise covers Slot.MAIN and says so, rather than leaving "renders whatever it is handed" to be read generously: every shipped preset composes one main column, so a sidebar section is dropped by these templates as by every other. The gate pins that too, so the contract and the code have to change together. CvRenderKit is the three shapes a section body reduces to — a paragraph, a label/value row, a timeline entry — and a template hands back the kit it draws them with. The lowering from CvItem stays shared: what a linked title looks like, which fields a kind reads, what an empty description does to a trailing colon are the model's decisions and must not be re-made sixteen times. BlueBanner, ClassicSerif and EditorialBlue now draw modules with their own entry and project shapes. EditorialBlue also stops renaming a module's heading. Its keyword vocabulary turned "Certifications & Awards" into EDUCATION, which is the one thing the promise says cannot happen; the canonical sections keep the rename that gives the preset its voice. CvTemplatesCoverageTest derives the catalogue from the presets package rather than trusting it, so a preset that ships unregistered fails the build instead of being invisible to every caller that looks one up by id.
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
The previous PR made a CV section's shape a runtime value. That is only worth anything if the template you hand it to renders it — and not every preset can promise that. Several compose a fixed set of modules and find each by matching headings against private keyword lists, so a section they do not recognise never reaches a renderer at all. The CV still comes out, minus a section, looking finished. Nothing about that failure is visible at the point it happens; it surfaces weeks later as a job that was never listed.
So the question "can I give this template a module I invented?" needs an answer that is checked rather than assumed. And a second question follows it: if a preset can render the module, can it render it in its own style rather than the canonical one — the limitation #580 documented and left open.
What changed
ModularCvTemplateis the promise;CvTemplates.modular()is the list to offer. The registry also answersbyId,all,ids, andrecommendedMargin(the margin a preset was designed at, which a caller needs while building the session, before it has a template). Picking a template at runtime stops being a map kept by hand in each consumer — the one this model exists for keeps exactly that map in another repository, where nothing tells it a preset shipped.ModularCvTemplateFidelityTestenumeratesCvTemplates.modular()and everyCvKind— not lists of its own — and renders: every kind, a section this catalogue has no name for, a heading in a script no keyword list contains, and a heading that does match one. Seven presets qualify.ClassicSerifdoes not — it draws any shape it is given, but only gives itself the sections it recognises. Finding that out is what the gate is for; it kept its kit and lost the claim.Slot.MAIN. Every shipped preset composes one main column, so a section placed inSlot.SIDEBARis dropped — by these templates as by every other, which is whatCvDocumenthas always documented. Saying so in the contract, and pinning it in the gate, is the difference between a contract and a slogan; when slots go live that test goes red and the promise moves with the code.CvRenderKitis the three shapes a section body reduces to — a paragraph, a label/value row, a timeline entry — and a template hands back the kit it draws them with. The lowering fromCvItemstays shared: what a linked title looks like, which fields a kind reads, what an empty description does to a trailing colon are the model's decisions and must not be re-made sixteen times. It is also the shape the presets already had — their private renderers take aCvEntryor aCvRowtoday.BlueBanner,ClassicSerifandEditorialBluenow draw modules with their own entry and project shapes; the rest returnCvRenderKit.defaults(), and every one of them passes its kit to the dispatcher so overriding it later actually does something.EditorialBluestops renaming a module's heading. Its keyword vocabulary turned "Certifications & Awards" intoEDUCATION— the one thing the promise says cannot happen. The canonical sections keep the rename that gives the preset its voice.CvTemplatesCoverageTestderives the catalogue from the presets package rather than trusting it, so a preset that ships unregistered fails the build instead of being invisible to every caller that looks one up by id. No preset list in this repo had such a guard.Verification
./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 -am→ BUILD SUCCESS, qa 821 tests (+14). The 16 CV visual baselines are untouched: the three-argumentSectionDispatcher.renderBodydelegates withdefaults(), whose methods are the same static renderers, and the kit-passing presets reach the four-argument form only from their module branch.EditorialBlue's heading rename turnsaHeadingThePresetHasAWordForIsStillTheAuthorsHeadingred foreditorial-blueand nothing else.Panelfrom the catalogue failseveryPresetInThePackageIsInTheCataloguewith the directory named in the message.SectionDispatchergained an overload rather than changing one.javadoc:javadoc→ 0 warnings.ModuleSectionKindCoverageTestrather than copied, so the 16×6 documents are rendered once.Lane: templates (api + components + registry + nine presets).
Limits:
SectionRole-driven routing, and live slots are the next PR.EditorialBlue's kit draws entries in its experience styling: it picks between experience and education by sniffing a heading, which is what a module carries a role to avoid, and the kit is not handed that role yet.