Skip to content

v2(Phase 2): port ModernProfessional preset#48

Merged
DemchaAV merged 3 commits into
developfrom
feature/cv-v2-preset-modern
May 24, 2026
Merged

v2(Phase 2): port ModernProfessional preset#48
DemchaAV merged 3 commits into
developfrom
feature/cv-v2-preset-modern

Conversation

@DemchaAV
Copy link
Copy Markdown
Owner

Summary

Second preset on the v2 architecture. Proves the
compose-don't-subclass pattern works for a visually different
style on the same data + same body renderers.

Single-column, no slots needed — slots will be exercised in Phase 3
when porting TwoColumnSidebar-style multi-column presets.

⚠️ Stacked on top of #47. Once #47 merges, this PR's diff shrinks
to just the Phase 2 commit.

What's new

  • presets/ModernProfessional.java — Helvetica-based preset:
    right-aligned big slate-blue display name, flat bright-blue bold
    section titles (no banner panels), pipe-separated contact + links
    on the right. Visual signature matches v1 ModernProfessional.
  • CvTheme.modernProfessional() factory — Helvetica typography,
    tighter spacing, classic palette + decoration. Body renderers
    (ParagraphRenderer, RowRenderer, EntryRenderer,
    SectionDispatcher) consumed unchanged — the win this PR was
    built to prove.
  • CvTypography.modernProfessional() — Helvetica scale (28pt
    name, 17.4pt section title, 10pt body).
  • CvSpacing.modernProfessional() — tighter spacing for
    single-page-friendly proportions.
  • CvModernV2Example — renders cv-modern-professional-v2.pdf.
  • ModernProfessionalSmokeTest — 4 tests (identity, default
    theme, custom theme, theme portability).

Architectural lessons learned

Documented in the preset's class-level JavaDoc:

  1. Preset-specific colours stay in the preset. Slate-blue name,
    bright-blue section title, royal-blue link are private static
    finals inside ModernProfessional, not on CvPalette. The
    palette has four fields today (ink/muted/rule/banner); adding
    three more for a single preset would bloat the shared theme
    record. When a second preset wants the same accents, extract them
    then.

  2. Section title rendering is inlined per-preset. Same pattern as
    MinimalUnderlined (Phase 0). Once 3+ presets need flat-title
    rendering, factor out a SectionTitleRenderer with style
    variants. Until then, per-preset inline keeps each preset
    readable end-to-end.

  3. Slot filter consistent. Preset reads
    doc.sectionsIn(Slot.MAIN) — sidebar content silently dropped,
    per the convention established in v2(Phase 1): slot mapping — CvDocument supports multi-column placement #47.

What's NOT changed

  • Engine — zero edits.
  • v1 CV surface — zero edits.
  • Existing v2 components / data layer — zero edits. This PR is
    purely additive in theme/ and presets/.
  • Public v2 API — all prior call sites continue to work.

Test plan

  • ModernProfessionalSmokeTest — 4 new tests pass
  • All prior v2 tests stay green: BoxedSectionsSmokeTest,
    MinimalUnderlinedSmokeTest, CvDecorationTest,
    CvDocumentSlotTest, CvNameTest, CvContactTest
  • Total v2 tests: 38/38 pass
  • cv-modern-professional-v2.pdf rendered, matches v1 visual
    signature (slate-blue name right, bright-blue section titles,
    Helvetica body). One row of content spills onto page 2 vs the
    v1 single-page render — minor spacing fidelity gap, not
    blocking.
  • CI green

Next phase

Phase 3 — port TimelineMinimal: two-column with slots (uses #47),
vertical timeline rail with circle dots between sections (new
decorative component). First real test of the slot model on a
multi-column layout.

DemchaAV added 2 commits May 24, 2026 13:09
Closes the single-column-only regression that v2 had vs. the legacy
CvBuilder.place(slot, name) API. Single PR, no engine changes, no v1
edits, no behavioural change for existing single-column callers.

What's new
----------

- data/Slot.java — enum {MAIN, SIDEBAR, FOOTER}. MAIN is the default
  when a section is built without an explicit slot.
- data/CvDocument refactor: canonical record is now
  (CvIdentity, List<Placement>) where Placement(Slot, CvSection).
  Custom sections() method still returns the flat list (source-order)
  so debug/inspect call sites keep working. New sectionsIn(Slot) and
  slotOf(CvSection) accessors.
- CvDocument.Builder gains:
    .section(Slot slot, CvSection section)
    .sections(Slot slot, CvSection... values)
  The pre-existing zero-slot calls (.section(s), .sections(s1, s2))
  default to MAIN — every existing call site keeps compiling and
  rendering identically.
- @deprecated CvDocument.ofMainSections(identity, list) — migration
  helper for any caller that used a direct two-arg constructor. The
  Builder is the recommended path forward.

What's updated
--------------

- presets/BoxedSections + presets/MinimalUnderlined now iterate
  doc.sectionsIn(Slot.MAIN) instead of doc.sections(). Sidebar /
  footer placements are silently dropped by single-column presets —
  documented in AUTHORS.md.
- AUTHORS.md gains Recipe 6 ("place sections in slots") with both the
  builder-side and the preset-side patterns. Old Recipe 6 (conditional
  sections) renumbered to 7.
- package-info.java gains a "Slots — placing sections in columns"
  section in the root v2 package.
- data/package-info.java mentions Placement and Slot.

Tests
-----

- New CvDocumentSlotTest with 10 cases (default MAIN, explicit slot,
  source-order across slots, sectionsIn filter, slotOf, deprecated
  ofMainSections, null guards).
- All existing v2 tests stay green (BoxedSectionsSmokeTest,
  MinimalUnderlinedSmokeTest, CvDecorationTest, CvNameTest,
  CvContactTest).
- Full mvn test: 881/881 pass.
- cv-boxed-sections-v2.pdf and cv-minimal-underlined.pdf render
  pixel-identical to baseline (sample data is all MAIN today).
Second preset on the v2 architecture — proves the
compose-don't-subclass pattern works for a visually-different style
on the same data + same body renderers. Single-column, no slots
needed (those are exercised in Phase 3).

What's new
----------

- presets/ModernProfessional.java — Helvetica-based preset with
  right-aligned big slate-blue display name, flat bright-blue bold
  section titles (no banner panels), pipe-separated contact + links
  on the right. Visual signature ported from the v1 preset of the
  same name.
- theme/CvTheme.modernProfessional() factory — Helvetica typography,
  tighter spacing, classic palette + decoration. Body renderers
  (ParagraphRenderer, RowRenderer, EntryRenderer, SectionDispatcher)
  consumed unchanged.
- theme/CvTypography.modernProfessional() — Helvetica scale: 28pt
  name, 17.4pt section title, 10pt body.
- theme/CvSpacing.modernProfessional() — tighter spacing for
  single-page-friendly proportions.
- examples/CvModernV2Example — renders cv-modern-professional-v2.pdf
  against the shared sample data.
- ModernProfessionalSmokeTest — 4 tests (identity, default theme,
  custom theme, theme portability).

Architectural notes
-------------------

- The preset's three preset-specific colours (slate-blue name,
  bright-blue section title, royal-blue link) live as private static
  finals inside the preset class, NOT in CvPalette. The palette has
  four fields today (ink/muted/rule/banner); adding three more for
  a single preset would pollute the shared theme record. When a
  second preset reaches for the same accent colours, extract them
  to CvPalette and update both call sites.
- Section title rendering is an inline private method
  (renderSectionTitle), same pattern as MinimalUnderlined. Once 3+
  presets need a flat-title rendering, factor out a
  SectionTitleRenderer component with style variants. Until then,
  per-preset inline keeps each preset readable end-to-end.
- Preset reads doc.sectionsIn(Slot.MAIN) — sidebar content is
  silently dropped, consistent with the single-column convention
  established in Phase 1.

Test results
------------

- 38/38 v2 tests pass (4 new ModernProfessional + 34 prior).
- cv-modern-professional-v2.pdf renders cleanly with the v1 visual
  signature (slate-blue name right, bright-blue section titles,
  Helvetica body). One row of content spills onto page 2 vs the v1
  single-page render — minor spacing fidelity gap, not blocking.

Engine and v1 surface untouched.
@DemchaAV DemchaAV merged commit 65d1bec into develop May 24, 2026
9 checks passed
@DemchaAV DemchaAV deleted the feature/cv-v2-preset-modern branch May 24, 2026 13:52
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.

2 participants