v2(Phase 3): widgets/ layer — LEGO bricks for preset authors#49
Merged
Conversation
1d936dd to
486202e
Compare
This was referenced May 24, 2026
DemchaAV
added a commit
that referenced
this pull request
May 24, 2026
…h audit Phase 3 of the documentation work after audit (#50 added the templates-layered/ guide; #51 here restructures the entire docs/ tree and fixes terminology + link hygiene). Reorg — docs/ structure ----------------------- Was: 21 flat .md files in docs/ with no obvious category. Now grouped by purpose, mirroring the personas: docs/ ├── README.md ← NEW real docs index ├── SHOWCASE.md ← renamed from docs/README.md │ (GitHub Pages showcase doc) ├── getting-started.md ← kept flat (high traffic) ├── recipes.md ← kept flat (recipes index) ├── adr/ ← unchanged (8 ADRs) ├── archive/ ← unchanged (3 archived docs) ├── recipes/ ← unchanged (7 recipes) ├── architecture/ ← NEW (5 files moved) │ ├── overview.md ← was architecture.md │ ├── lifecycle.md │ ├── pagination-ordering.md │ ├── canonical-legacy-parity.md │ └── package-map.md ├── operations/ ← NEW (5 files moved) │ ├── benchmarks.md │ ├── logging.md │ ├── performance.md │ ├── production-rendering.md │ └── layout-snapshot-testing.md ├── contributing/ ← NEW (3 files moved) │ ├── extension-guide.md │ ├── implementation-guide.md │ └── release-process.md ├── roadmaps/ ← NEW (3 files moved) │ ├── v1.6-roadmap.md │ ├── migration-v1-4-to-v1-5.md │ └── migration-v1-5-to-v1-6.md └── templates/ ← NEW (groups both surfaces) ├── v1-classic/ ← was docs/templates-v2.md + template-authoring.md │ ├── README.md ← v1.6 "Templates v2" landing │ └── authoring.md ← was template-authoring.md └── v2-layered/ ← was docs/templates-layered/ ├── README.md ├── quickstart.md ├── using-templates.md ├── authoring-presets.md └── contributor-guide.md 20 files moved via `git mv` so the history is preserved. Documentation index — docs/README.md ------------------------------------ The old docs/README.md was about the GitHub Pages showcase site, not a docs index — opening docs/ on GitHub showed the wrong thing. - Renamed old docs/README.md → docs/SHOWCASE.md - Wrote new docs/README.md as the canonical docs landing: persona map + category map + ADR list + recipe list + quick links. v1/v2 terminology — explicit callouts ------------------------------------- The codebase has TWO surfaces both casually called "v2": - The v1.6 rebuilt templates (CvSpec / CvBuilder / *Presets) which the project calls "Templates v2" internally (ADR-0011). - The newer layered cv/v2/ architecture introduced in PRs #45-#49. Added clarifying callouts at the top of: - docs/templates/v1-classic/README.md — "this is the v1.6 surface; for the newer layered pattern see v2-layered/" - docs/templates/v1-classic/authoring.md — same callout - docs/templates/v2-layered/README.md — "this is the layered architecture; NOT the older v1.6 'Templates v2'" Both surfaces are still shipped and supported; neither is deprecated. The callouts just kill the confusion. CONTRIBUTING.md update ---------------------- The "New built-in template" section now opens with a fork: - For a NEW template family from scratch → layered architecture (with link to contributor-guide.md) - For a new preset inside an existing v1-classic family → keep using BusinessTheme + CvBuilder + the existing presets pattern Plus a "📚 Map of template docs" pointer to docs/README.md so contributors don't have to guess. Orphan resolution ----------------- - docs/performance.md was nowhere-linked. Moved to operations/ and indexed from docs/README.md. - docs/recipes/shapes.md was nowhere-linked-from-root-README but IS linked from recipes.md (the recipe index). Root README now links recipes.md so it's discoverable. - ADR numbering gap (0005-0010 missing) explained inline in docs/README.md as a note next to the ADR list. Link integrity -------------- - sed sweep across 58 .md files updated every absolute `docs/X.md` reference to its new categorised path. - Internal relative links inside moved files (e.g. `./benchmarks.md` from within docs/architecture/) updated by hand for every affected file. - Final automated sweep verifies **zero broken markdown links** repo-wide. Tech accuracy spot-check ------------------------ Sampled 4 high-traffic docs against the current code: - getting-started.md — every referenced class (DocumentSession, BusinessTheme, etc.) exists in src/. - templates/v1-classic/authoring.md — every layout class (SingleColumn, TwoColumnSidebar, ThreeColumnMagazine, etc.) exists. - templates/v1-classic/README.md — accurate. - contributing/extension-guide.md — accurate. No stale class references found. Root README update ------------------ Documentation section reorganised: - New "📚 Full docs index" link to docs/README.md. - Templates split into v2-layered (new) and v1-classic (legacy but shipped) with cross-link to authoring guides. - Sub-grouped: Templates / Architecture & operations / Recipes & examples / Contributing & releases. No engine, source, or test changes. Pure documentation.
Closes the "concept" gap surfaced in conversation: until now, an
author who wanted a preset with section titles different from
BoxedSections' banner had to read another preset's private rendering
methods and copy-paste. With widgets, the author picks a named
visual building block and inserts it.
What's new
----------
- cv/v2/widgets/Headline.java
.spacedCentered — BoxedSections/MinimalUnderlined style
.rightAligned — ModernProfessional style
.render(...) — low-level: any (alignment, spacedCaps) combo
- cv/v2/widgets/ContactLine.java
.centered — BoxedSections/MinimalUnderlined style
.rightAligned — ModernProfessional style
.render(...) — low-level: alignment + field Order
- cv/v2/widgets/SectionHeader.java
.banner — pale-grey panel, centred spaced-caps
.underlined — left spaced-caps + accent rule below
.flat(color) — large bold colour, no panel
- cv/v2/widgets/package-info.java — philosophy doc
Each widget has 2–3 named factory methods plus an escape-hatch
.render() with parameters. No spec record / builder for now — keep
the API tight; expand when patterns repeat.
Refactor
--------
- BoxedSections.compose() — Headline.spacedCentered +
ContactLine.centered +
SectionHeader.banner
- MinimalUnderlined.compose() — Headline.spacedCentered +
ContactLine.centered +
SectionHeader.underlined
(private renderUnderlinedTitle deleted)
- ModernProfessional.compose() — SectionHeader.flat(SECTION_TITLE_COLOR)
(private renderHeader / renderContact
kept inline — preset-specific colours
don't fit widget defaults; documented
as the "widget doesn't fit → inline"
pattern in AUTHORS.md)
Each preset's compose() shrank from ~30 lines of DSL plumbing to
~12 lines of widget calls. Reading a preset now reads as a sequence
of visual decisions, not as rendering code.
Backward compatibility
----------------------
- components/HeadlineRenderer → @deprecated, delegates to Headline.spacedCentered
- components/ContactRenderer → @deprecated, delegates to ContactLine.centered
- components/BannerRenderer → @deprecated, delegates to SectionHeader.banner
Old v2 callers keep compiling unchanged. @deprecated marks the
forward path so new code reaches for widgets directly.
Docs
----
- AUTHORS.md gains a full "Widget cookbook" section: catalog table
per widget, composing-a-preset example (12-line full compose()),
when-to-add-a-widget guidance, "doesn't fit → inline" recipe,
forward-looking examples (Badge, IconLabel, Divider — not yet
implemented, included as illustration of where the catalog can
grow).
- package-info.java ASCII diagram updated to show widgets/ layer
between presets/ and components/.
Tests
-----
- New WidgetSmokeTest (4 cases) covers every public widget variant
against the default theme + the modernProfessional theme.
- All 3 v2 preset PDFs render pixel-identical to baseline — proof
that the widget extraction is purely a refactor.
- Full mvn test: 889/889 pass.
Engine and v1 surface untouched.
486202e to
d5c09d4
Compare
DemchaAV
added a commit
that referenced
this pull request
May 24, 2026
…h audit Phase 3 of the documentation work after audit (#50 added the templates-layered/ guide; #51 here restructures the entire docs/ tree and fixes terminology + link hygiene). Reorg — docs/ structure ----------------------- Was: 21 flat .md files in docs/ with no obvious category. Now grouped by purpose, mirroring the personas: docs/ ├── README.md ← NEW real docs index ├── SHOWCASE.md ← renamed from docs/README.md │ (GitHub Pages showcase doc) ├── getting-started.md ← kept flat (high traffic) ├── recipes.md ← kept flat (recipes index) ├── adr/ ← unchanged (8 ADRs) ├── archive/ ← unchanged (3 archived docs) ├── recipes/ ← unchanged (7 recipes) ├── architecture/ ← NEW (5 files moved) │ ├── overview.md ← was architecture.md │ ├── lifecycle.md │ ├── pagination-ordering.md │ ├── canonical-legacy-parity.md │ └── package-map.md ├── operations/ ← NEW (5 files moved) │ ├── benchmarks.md │ ├── logging.md │ ├── performance.md │ ├── production-rendering.md │ └── layout-snapshot-testing.md ├── contributing/ ← NEW (3 files moved) │ ├── extension-guide.md │ ├── implementation-guide.md │ └── release-process.md ├── roadmaps/ ← NEW (3 files moved) │ ├── v1.6-roadmap.md │ ├── migration-v1-4-to-v1-5.md │ └── migration-v1-5-to-v1-6.md └── templates/ ← NEW (groups both surfaces) ├── v1-classic/ ← was docs/templates-v2.md + template-authoring.md │ ├── README.md ← v1.6 "Templates v2" landing │ └── authoring.md ← was template-authoring.md └── v2-layered/ ← was docs/templates-layered/ ├── README.md ├── quickstart.md ├── using-templates.md ├── authoring-presets.md └── contributor-guide.md 20 files moved via `git mv` so the history is preserved. Documentation index — docs/README.md ------------------------------------ The old docs/README.md was about the GitHub Pages showcase site, not a docs index — opening docs/ on GitHub showed the wrong thing. - Renamed old docs/README.md → docs/SHOWCASE.md - Wrote new docs/README.md as the canonical docs landing: persona map + category map + ADR list + recipe list + quick links. v1/v2 terminology — explicit callouts ------------------------------------- The codebase has TWO surfaces both casually called "v2": - The v1.6 rebuilt templates (CvSpec / CvBuilder / *Presets) which the project calls "Templates v2" internally (ADR-0011). - The newer layered cv/v2/ architecture introduced in PRs #45-#49. Added clarifying callouts at the top of: - docs/templates/v1-classic/README.md — "this is the v1.6 surface; for the newer layered pattern see v2-layered/" - docs/templates/v1-classic/authoring.md — same callout - docs/templates/v2-layered/README.md — "this is the layered architecture; NOT the older v1.6 'Templates v2'" Both surfaces are still shipped and supported; neither is deprecated. The callouts just kill the confusion. CONTRIBUTING.md update ---------------------- The "New built-in template" section now opens with a fork: - For a NEW template family from scratch → layered architecture (with link to contributor-guide.md) - For a new preset inside an existing v1-classic family → keep using BusinessTheme + CvBuilder + the existing presets pattern Plus a "📚 Map of template docs" pointer to docs/README.md so contributors don't have to guess. Orphan resolution ----------------- - docs/performance.md was nowhere-linked. Moved to operations/ and indexed from docs/README.md. - docs/recipes/shapes.md was nowhere-linked-from-root-README but IS linked from recipes.md (the recipe index). Root README now links recipes.md so it's discoverable. - ADR numbering gap (0005-0010 missing) explained inline in docs/README.md as a note next to the ADR list. Link integrity -------------- - sed sweep across 58 .md files updated every absolute `docs/X.md` reference to its new categorised path. - Internal relative links inside moved files (e.g. `./benchmarks.md` from within docs/architecture/) updated by hand for every affected file. - Final automated sweep verifies **zero broken markdown links** repo-wide. Tech accuracy spot-check ------------------------ Sampled 4 high-traffic docs against the current code: - getting-started.md — every referenced class (DocumentSession, BusinessTheme, etc.) exists in src/. - templates/v1-classic/authoring.md — every layout class (SingleColumn, TwoColumnSidebar, ThreeColumnMagazine, etc.) exists. - templates/v1-classic/README.md — accurate. - contributing/extension-guide.md — accurate. No stale class references found. Root README update ------------------ Documentation section reorganised: - New "📚 Full docs index" link to docs/README.md. - Templates split into v2-layered (new) and v1-classic (legacy but shipped) with cross-link to authoring guides. - Sub-grouped: Templates / Architecture & operations / Recipes & examples / Contributing & releases. No engine, source, or test changes. Pure documentation.
DemchaAV
added a commit
that referenced
this pull request
May 24, 2026
…h audit (#51) Phase 3 of the documentation work after audit (#50 added the templates-layered/ guide; #51 here restructures the entire docs/ tree and fixes terminology + link hygiene). Reorg — docs/ structure ----------------------- Was: 21 flat .md files in docs/ with no obvious category. Now grouped by purpose, mirroring the personas: docs/ ├── README.md ← NEW real docs index ├── SHOWCASE.md ← renamed from docs/README.md │ (GitHub Pages showcase doc) ├── getting-started.md ← kept flat (high traffic) ├── recipes.md ← kept flat (recipes index) ├── adr/ ← unchanged (8 ADRs) ├── archive/ ← unchanged (3 archived docs) ├── recipes/ ← unchanged (7 recipes) ├── architecture/ ← NEW (5 files moved) │ ├── overview.md ← was architecture.md │ ├── lifecycle.md │ ├── pagination-ordering.md │ ├── canonical-legacy-parity.md │ └── package-map.md ├── operations/ ← NEW (5 files moved) │ ├── benchmarks.md │ ├── logging.md │ ├── performance.md │ ├── production-rendering.md │ └── layout-snapshot-testing.md ├── contributing/ ← NEW (3 files moved) │ ├── extension-guide.md │ ├── implementation-guide.md │ └── release-process.md ├── roadmaps/ ← NEW (3 files moved) │ ├── v1.6-roadmap.md │ ├── migration-v1-4-to-v1-5.md │ └── migration-v1-5-to-v1-6.md └── templates/ ← NEW (groups both surfaces) ├── v1-classic/ ← was docs/templates-v2.md + template-authoring.md │ ├── README.md ← v1.6 "Templates v2" landing │ └── authoring.md ← was template-authoring.md └── v2-layered/ ← was docs/templates-layered/ ├── README.md ├── quickstart.md ├── using-templates.md ├── authoring-presets.md └── contributor-guide.md 20 files moved via `git mv` so the history is preserved. Documentation index — docs/README.md ------------------------------------ The old docs/README.md was about the GitHub Pages showcase site, not a docs index — opening docs/ on GitHub showed the wrong thing. - Renamed old docs/README.md → docs/SHOWCASE.md - Wrote new docs/README.md as the canonical docs landing: persona map + category map + ADR list + recipe list + quick links. v1/v2 terminology — explicit callouts ------------------------------------- The codebase has TWO surfaces both casually called "v2": - The v1.6 rebuilt templates (CvSpec / CvBuilder / *Presets) which the project calls "Templates v2" internally (ADR-0011). - The newer layered cv/v2/ architecture introduced in PRs #45-#49. Added clarifying callouts at the top of: - docs/templates/v1-classic/README.md — "this is the v1.6 surface; for the newer layered pattern see v2-layered/" - docs/templates/v1-classic/authoring.md — same callout - docs/templates/v2-layered/README.md — "this is the layered architecture; NOT the older v1.6 'Templates v2'" Both surfaces are still shipped and supported; neither is deprecated. The callouts just kill the confusion. CONTRIBUTING.md update ---------------------- The "New built-in template" section now opens with a fork: - For a NEW template family from scratch → layered architecture (with link to contributor-guide.md) - For a new preset inside an existing v1-classic family → keep using BusinessTheme + CvBuilder + the existing presets pattern Plus a "📚 Map of template docs" pointer to docs/README.md so contributors don't have to guess. Orphan resolution ----------------- - docs/performance.md was nowhere-linked. Moved to operations/ and indexed from docs/README.md. - docs/recipes/shapes.md was nowhere-linked-from-root-README but IS linked from recipes.md (the recipe index). Root README now links recipes.md so it's discoverable. - ADR numbering gap (0005-0010 missing) explained inline in docs/README.md as a note next to the ADR list. Link integrity -------------- - sed sweep across 58 .md files updated every absolute `docs/X.md` reference to its new categorised path. - Internal relative links inside moved files (e.g. `./benchmarks.md` from within docs/architecture/) updated by hand for every affected file. - Final automated sweep verifies **zero broken markdown links** repo-wide. Tech accuracy spot-check ------------------------ Sampled 4 high-traffic docs against the current code: - getting-started.md — every referenced class (DocumentSession, BusinessTheme, etc.) exists in src/. - templates/v1-classic/authoring.md — every layout class (SingleColumn, TwoColumnSidebar, ThreeColumnMagazine, etc.) exists. - templates/v1-classic/README.md — accurate. - contributing/extension-guide.md — accurate. No stale class references found. Root README update ------------------ Documentation section reorganised: - New "📚 Full docs index" link to docs/README.md. - Templates split into v2-layered (new) and v1-classic (legacy but shipped) with cross-link to authoring guides. - Sub-grouped: Templates / Architecture & operations / Recipes & examples / Contributing & releases. No engine, source, or test changes. Pure documentation.
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.
Summary
Closes the «пишу свой preset — выбираю кубики и вставляю» gap.
Until now, an author who wanted a section title style different
from BoxedSections' banner had to read another preset's private
rendering methods and copy-paste. With widgets, they pick a named
visual building block.
This is what gives v2 its «понятный, читаемый, переиспользуемый»
authoring story.
What changes for preset authors
Before — preset's
compose()had ~30 lines of DSL plumbing orcalled CV-specific renderers:
After — preset reads as a sequence of visual decisions:
A full preset's
compose()is now ~12 lines (was ~30). Reading itno longer requires mentally executing DSL.
New:
cv/v2/widgets/Headline.java.spacedCentered,.rightAligned,.render(align, spacedCaps)ContactLine.java.centered,.rightAligned,.render(align, order)SectionHeader.java.banner,.underlined,.flat(color)Three layers of customisation per widget:
render(...)— same widget, more knobsoptional helpers, not required wrappers
Refactor — 3 presets use widgets
BoxedSections: 3 widget calls incompose()MinimalUnderlined: 3 widget calls, privaterenderUnderlinedTitledeletedModernProfessional: 1 widget call (SectionHeader.flat) plusrenderHeader/renderContactkept inline because thepreset-specific colours (slate-blue name, royal-blue links) don't
fit widget defaults. This is the documented "widget doesn't fit
→ inline" pattern.
Backward compatibility
components/HeadlineRenderer→@Deprecated, delegates to widgetcomponents/ContactRenderer→@Deprecated, delegates to widgetcomponents/BannerRenderer→@Deprecated, delegates to widgetOld v2 callers keep compiling unchanged.
Docs
AUTHORS.mdgains full "Widget cookbook" section: catalogtable per widget, 12-line composing-a-preset example,
when-to-add-a-widget guidance, "doesn't fit → inline" recipe,
forward-looking examples (Badge, IconLabel, Divider — not yet
implemented, included as illustration where the catalog can
grow).
package-info.javaASCII diagram updated withwidgets/layerbetween
presets/andcomponents/.What's NOT changed
baseline. Refactor proven.
*Rendererclasses still work(deprecated, delegating); widgets are additive.
Test plan
WidgetSmokeTest— 4 new tests cover every widget variantmvn test— 889/889 passcv-boxed-sections-v2.pdf— pixel-identical to baselinecv-minimal-underlined.pdf— pixel-identical to baselinecv-modern-professional-v2.pdf— pixel-identical to baselineWhat this PR completes (and what it doesn't)
This PR finishes the concept: 4 layers (
data/theme/components/presets) + widgets layer in between gives authorsboth structural understanding ("what goes where") AND
compositional ergonomics ("pick a brick, place it").
This PR does NOT migrate v1 templates. That's a separate decision —
"when do we deprecate v1 and port the remaining 13 presets". With
this PR, the concept is sufficiently proven that we can make that
call from data, not theory.