diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvContact.java b/src/main/java/com/demcha/compose/document/templates/core/identity/Contact.java similarity index 87% rename from src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvContact.java rename to src/main/java/com/demcha/compose/document/templates/core/identity/Contact.java index ef8543d9f..88f96ca7c 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvContact.java +++ b/src/main/java/com/demcha/compose/document/templates/core/identity/Contact.java @@ -1,4 +1,4 @@ -package com.demcha.compose.document.templates.cv.v2.data; +package com.demcha.compose.document.templates.core.identity; import java.util.Objects; @@ -13,12 +13,12 @@ * @param email non-blank email (rendered as a clickable mailto link) * @param address non-blank location / postal address line */ -public record CvContact(String phone, String email, String address) { +public record Contact(String phone, String email, String address) { /** * Validates that every field is non-null and non-blank. */ - public CvContact { + public Contact { Objects.requireNonNull(phone, "phone"); Objects.requireNonNull(email, "email"); Objects.requireNonNull(address, "address"); diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/ContactLine.java b/src/main/java/com/demcha/compose/document/templates/core/identity/ContactLine.java similarity index 91% rename from src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/ContactLine.java rename to src/main/java/com/demcha/compose/document/templates/core/identity/ContactLine.java index ed2cec482..a0b900ca6 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/ContactLine.java +++ b/src/main/java/com/demcha/compose/document/templates/core/identity/ContactLine.java @@ -1,13 +1,10 @@ -package com.demcha.compose.document.templates.cv.v2.widgets; +package com.demcha.compose.document.templates.core.identity; import com.demcha.compose.document.dsl.SectionBuilder; import com.demcha.compose.document.node.DocumentLinkOptions; import com.demcha.compose.document.node.TextAlign; import com.demcha.compose.document.style.DocumentInsets; import com.demcha.compose.document.style.DocumentTextStyle; -import com.demcha.compose.document.templates.cv.v2.data.CvContact; -import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; -import com.demcha.compose.document.templates.cv.v2.data.CvLink; import com.demcha.compose.document.templates.core.theme.BrandTheme; import java.util.ArrayList; @@ -34,7 +31,7 @@ * * *

Email is always rendered as a clickable {@code mailto:} link; - * each optional {@link CvLink} becomes a clickable hyperlink with + * each optional {@link Link} becomes a clickable hyperlink with * the {@code label} as the visible text. The separator glyph comes * from {@code theme.decoration().contactSeparator()}.

*/ @@ -52,14 +49,14 @@ private ContactLine() { * @param identity the CV identity supplying contact fields and links * @param theme the active theme supplying palette, typography, and spacing */ - public static void centered(SectionBuilder host, CvIdentity identity, BrandTheme theme) { + public static void centered(SectionBuilder host, PartyIdentity identity, BrandTheme theme) { render(host, identity, theme, TextAlign.CENTER, Order.PHONE_FIRST); } /** * Centred contact row with explicit text-style overrides for * non-link text, clickable links, and separators. Same ordering as - * {@link #centered(SectionBuilder, CvIdentity, BrandTheme)}, but lets + * {@link #centered(SectionBuilder, PartyIdentity, BrandTheme)}, but lets * editorial presets tint / underline the links without forking the * contact assembly logic. * @@ -76,7 +73,7 @@ public static void centered(SectionBuilder host, CvIdentity identity, BrandTheme * {@code null} → * {@code theme.contactSeparatorStyle()} */ - public static void centered(SectionBuilder host, CvIdentity identity, + public static void centered(SectionBuilder host, PartyIdentity identity, BrandTheme theme, DocumentTextStyle bodyStyleOverride, DocumentTextStyle linkStyleOverride, @@ -94,7 +91,7 @@ public static void centered(SectionBuilder host, CvIdentity identity, * @param identity the CV identity supplying contact fields and links * @param theme the active theme supplying palette, typography, and spacing */ - public static void rightAligned(SectionBuilder host, CvIdentity identity, BrandTheme theme) { + public static void rightAligned(SectionBuilder host, PartyIdentity identity, BrandTheme theme) { render(host, identity, theme, TextAlign.RIGHT, Order.ADDRESS_FIRST); } @@ -107,7 +104,7 @@ public static void rightAligned(SectionBuilder host, CvIdentity identity, BrandT * @param identity the CV identity supplying contact fields and links * @param theme the active theme supplying palette, typography, and spacing */ - public static void leftAligned(SectionBuilder host, CvIdentity identity, + public static void leftAligned(SectionBuilder host, PartyIdentity identity, BrandTheme theme) { render(host, identity, theme, TextAlign.LEFT, Order.ADDRESS_FIRST); } @@ -129,7 +126,7 @@ public static void leftAligned(SectionBuilder host, CvIdentity identity, * {@code null} -> * {@code theme.contactSeparatorStyle()} */ - public static void leftAligned(SectionBuilder host, CvIdentity identity, + public static void leftAligned(SectionBuilder host, PartyIdentity identity, BrandTheme theme, DocumentTextStyle bodyStyleOverride, DocumentTextStyle linkStyleOverride, @@ -151,7 +148,7 @@ public static void leftAligned(SectionBuilder host, CvIdentity identity, *
  • Row 2 — email {@code |} link₁ {@code |} link₂ … (all clickable)
  • * * - *

    Email and every {@link CvLink} are rendered as proper PDF + *

    Email and every {@link Link} are rendered as proper PDF * hyperlinks (mailto: for the email, the link's URL for each * label) — not just styled text.

    * @@ -168,7 +165,7 @@ public static void leftAligned(SectionBuilder host, CvIdentity identity, * separator; {@code null} → * {@code theme.contactSeparatorStyle()} */ - public static void twoRowRightAligned(SectionBuilder host, CvIdentity identity, + public static void twoRowRightAligned(SectionBuilder host, PartyIdentity identity, BrandTheme theme, DocumentTextStyle bodyStyleOverride, DocumentTextStyle linkStyleOverride, @@ -180,7 +177,7 @@ public static void twoRowRightAligned(SectionBuilder host, CvIdentity identity, DocumentTextStyle separatorStyle = separatorStyleOverride != null ? separatorStyleOverride : theme.contactSeparatorStyle(); - CvContact c = identity.contact(); + Contact c = identity.contact(); host.spacing(0).padding(theme.spacing().contactPadding()) // Row 1 — address + phone. .addParagraph(p -> p @@ -200,7 +197,7 @@ public static void twoRowRightAligned(SectionBuilder host, CvIdentity identity, .rich(rich -> { rich.with(c.email(), linkStyle, new DocumentLinkOptions("mailto:" + c.email())); - for (CvLink l : identity.links()) { + for (Link l : identity.links()) { rich.style(" | ", separatorStyle); rich.with(l.label(), linkStyle, new DocumentLinkOptions(l.url())); @@ -218,7 +215,7 @@ public static void twoRowRightAligned(SectionBuilder host, CvIdentity identity, * @param theme the active theme supplying palette, typography, and spacing */ public static void rightAlignedStacked(SectionBuilder host, - CvIdentity identity, + PartyIdentity identity, BrandTheme theme) { rightAlignedStacked(host, identity, theme, null, null); } @@ -236,7 +233,7 @@ public static void rightAlignedStacked(SectionBuilder host, * → resolved body style */ public static void rightAlignedStacked(SectionBuilder host, - CvIdentity identity, + PartyIdentity identity, BrandTheme theme, DocumentTextStyle bodyStyleOverride, DocumentTextStyle linkStyleOverride) { @@ -274,7 +271,7 @@ public static void rightAlignedStacked(SectionBuilder host, * @param alignment horizontal text alignment for the row * @param order the field order in the rendered line */ - public static void render(SectionBuilder host, CvIdentity identity, BrandTheme theme, + public static void render(SectionBuilder host, PartyIdentity identity, BrandTheme theme, TextAlign alignment, Order order) { List parts = parts(identity, order); DocumentTextStyle textStyle = theme.contactStyle(); @@ -302,7 +299,7 @@ public static void render(SectionBuilder host, CvIdentity identity, BrandTheme t })); } - private static void renderStyled(SectionBuilder host, CvIdentity identity, + private static void renderStyled(SectionBuilder host, PartyIdentity identity, BrandTheme theme, TextAlign alignment, Order order, DocumentTextStyle bodyStyleOverride, @@ -352,8 +349,8 @@ public enum Order { ADDRESS_FIRST } - private static List parts(CvIdentity identity, Order order) { - CvContact c = identity.contact(); + private static List parts(PartyIdentity identity, Order order) { + Contact c = identity.contact(); List parts = new ArrayList<>(4 + identity.links().size()); DocumentLinkOptions email = new DocumentLinkOptions("mailto:" + c.email()); switch (order) { @@ -368,7 +365,7 @@ private static List parts(CvIdentity identity, Order order) { parts.add(new Part(c.email(), email)); } } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { parts.add(new Part(link.label(), new DocumentLinkOptions(link.url()))); } return parts; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/Headline.java b/src/main/java/com/demcha/compose/document/templates/core/identity/Headline.java similarity index 89% rename from src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/Headline.java rename to src/main/java/com/demcha/compose/document/templates/core/identity/Headline.java index e3e6cf78c..2ed21edd1 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/Headline.java +++ b/src/main/java/com/demcha/compose/document/templates/core/identity/Headline.java @@ -1,11 +1,10 @@ -package com.demcha.compose.document.templates.cv.v2.widgets; +package com.demcha.compose.document.templates.core.identity; import com.demcha.compose.document.dsl.SectionBuilder; import com.demcha.compose.document.node.TextAlign; import com.demcha.compose.document.style.DocumentInsets; import com.demcha.compose.document.style.DocumentTextStyle; import com.demcha.compose.document.templates.core.text.TextOrnaments; -import com.demcha.compose.document.templates.cv.v2.data.CvName; import com.demcha.compose.document.templates.core.theme.BrandTheme; /** @@ -55,7 +54,7 @@ private Headline() { * @param name name to render * @param theme the active theme supplying palette, typography, and spacing */ - public static void spacedCentered(SectionBuilder host, CvName name, BrandTheme theme) { + public static void spacedCentered(SectionBuilder host, String name, BrandTheme theme) { render(host, name, theme, TextAlign.CENTER, true); } @@ -68,7 +67,7 @@ public static void spacedCentered(SectionBuilder host, CvName name, BrandTheme t * @param name name to render * @param theme the active theme supplying palette, typography, and spacing */ - public static void uppercaseCentered(SectionBuilder host, CvName name, + public static void uppercaseCentered(SectionBuilder host, String name, BrandTheme theme) { uppercaseCentered(host, name, theme, null); } @@ -83,10 +82,10 @@ public static void uppercaseCentered(SectionBuilder host, CvName name, * @param styleOverride explicit style; pass {@code null} to fall * back to {@code theme.headlineStyle()} */ - public static void uppercaseCentered(SectionBuilder host, CvName name, + public static void uppercaseCentered(SectionBuilder host, String name, BrandTheme theme, DocumentTextStyle styleOverride) { - renderText(host, name.full().toUpperCase(java.util.Locale.ROOT), + renderText(host, name.toUpperCase(java.util.Locale.ROOT), theme, TextAlign.CENTER, styleOverride); } @@ -99,7 +98,7 @@ public static void uppercaseCentered(SectionBuilder host, CvName name, * @param name name to render * @param theme the active theme supplying palette, typography, and spacing */ - public static void uppercaseLeftAligned(SectionBuilder host, CvName name, + public static void uppercaseLeftAligned(SectionBuilder host, String name, BrandTheme theme) { uppercaseLeftAligned(host, name, theme, null); } @@ -114,10 +113,10 @@ public static void uppercaseLeftAligned(SectionBuilder host, CvName name, * @param styleOverride explicit style; pass {@code null} to fall * back to {@code theme.headlineStyle()} */ - public static void uppercaseLeftAligned(SectionBuilder host, CvName name, + public static void uppercaseLeftAligned(SectionBuilder host, String name, BrandTheme theme, DocumentTextStyle styleOverride) { - renderText(host, name.full().toUpperCase(java.util.Locale.ROOT), + renderText(host, name.toUpperCase(java.util.Locale.ROOT), theme, TextAlign.LEFT, styleOverride); } @@ -131,7 +130,7 @@ public static void uppercaseLeftAligned(SectionBuilder host, CvName name, * @param name name to render * @param theme the active theme supplying palette, typography, and spacing */ - public static void rightAligned(SectionBuilder host, CvName name, BrandTheme theme) { + public static void rightAligned(SectionBuilder host, String name, BrandTheme theme) { rightAligned(host, name, theme, null); } @@ -147,7 +146,7 @@ public static void rightAligned(SectionBuilder host, CvName name, BrandTheme the * @param styleOverride text style for the headline; pass {@code null} * to fall back to {@code theme.headlineStyle()} */ - public static void rightAligned(SectionBuilder host, CvName name, BrandTheme theme, + public static void rightAligned(SectionBuilder host, String name, BrandTheme theme, DocumentTextStyle styleOverride) { render(host, name, theme, TextAlign.RIGHT, false, styleOverride); } @@ -165,14 +164,14 @@ public static void rightAligned(SectionBuilder host, CvName name, BrandTheme the * @param spacedCaps if true, transforms to letter-spaced * uppercase; if false, renders verbatim */ - public static void render(SectionBuilder host, CvName name, BrandTheme theme, + public static void render(SectionBuilder host, String name, BrandTheme theme, TextAlign alignment, boolean spacedCaps) { render(host, name, theme, alignment, spacedCaps, null); } /** * Lower-level entry with explicit style override. Same shape as - * the 5-arg {@link #render(SectionBuilder, CvName, BrandTheme, TextAlign, boolean)} + * the 5-arg {@link #render(SectionBuilder, String, BrandTheme, TextAlign, boolean)} * but lets the caller supply a custom {@link DocumentTextStyle}. * * @param host host section @@ -184,15 +183,15 @@ public static void render(SectionBuilder host, CvName name, BrandTheme theme, * @param styleOverride explicit style; pass {@code null} to fall * back to {@code theme.headlineStyle()} */ - public static void render(SectionBuilder host, CvName name, BrandTheme theme, + public static void render(SectionBuilder host, String name, BrandTheme theme, TextAlign alignment, boolean spacedCaps, DocumentTextStyle styleOverride) { DocumentTextStyle style = styleOverride != null ? styleOverride : theme.headlineStyle(); String text = spacedCaps - ? TextOrnaments.spacedUpper(name.full()) - : name.full(); + ? TextOrnaments.spacedUpper(name) + : name; renderText(host, text, theme, alignment, style); } diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvLink.java b/src/main/java/com/demcha/compose/document/templates/core/identity/Link.java similarity index 70% rename from src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvLink.java rename to src/main/java/com/demcha/compose/document/templates/core/identity/Link.java index 6d5928efb..85dbe7348 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvLink.java +++ b/src/main/java/com/demcha/compose/document/templates/core/identity/Link.java @@ -1,4 +1,4 @@ -package com.demcha.compose.document.templates.cv.v2.data; +package com.demcha.compose.document.templates.core.identity; import java.util.Objects; @@ -9,12 +9,12 @@ * @param label visible link text (required, non-blank) * @param url click target (required, non-blank) */ -public record CvLink(String label, String url) { +public record Link(String label, String url) { /** * Validates that both fields are non-null and non-blank. */ - public CvLink { + public Link { Objects.requireNonNull(label, "label"); Objects.requireNonNull(url, "url"); if (label.isBlank()) { @@ -26,14 +26,14 @@ public record CvLink(String label, String url) { } /** - * Convenience factory mirroring {@code CvLink.of("LinkedIn", + * Convenience factory mirroring {@code Link.of("LinkedIn", * "https://...")} call sites. * * @param label visible link text (required, non-blank) * @param url click target (required, non-blank) - * @return a {@code CvLink} with the given label and target + * @return a {@code Link} with the given label and target */ - public static CvLink of(String label, String url) { - return new CvLink(label, url); + public static Link of(String label, String url) { + return new Link(label, url); } } diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/Masthead.java b/src/main/java/com/demcha/compose/document/templates/core/identity/Masthead.java similarity index 94% rename from src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/Masthead.java rename to src/main/java/com/demcha/compose/document/templates/core/identity/Masthead.java index e4f7b0331..38395f7d8 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/Masthead.java +++ b/src/main/java/com/demcha/compose/document/templates/core/identity/Masthead.java @@ -1,12 +1,10 @@ -package com.demcha.compose.document.templates.cv.v2.widgets; +package com.demcha.compose.document.templates.core.identity; import com.demcha.compose.document.dsl.SectionBuilder; import com.demcha.compose.document.node.DocumentLinkOptions; import com.demcha.compose.document.node.TextAlign; import com.demcha.compose.document.style.DocumentInsets; import com.demcha.compose.document.style.DocumentTextStyle; -import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; -import com.demcha.compose.document.templates.cv.v2.data.CvLink; import com.demcha.compose.document.templates.core.theme.BrandTheme; import java.util.ArrayList; @@ -32,16 +30,16 @@ private Masthead() { * {@link Style#defaults(BrandTheme)} */ public static void centered(SectionBuilder host, - CvIdentity identity, + PartyIdentity identity, BrandTheme theme, Style style) { Style safeStyle = style == null ? Style.defaults(theme) : style; DocumentTextStyle nameStyle = safeStyle.nameStyle() == null ? theme.headlineStyle() : safeStyle.nameStyle(); - Headline.uppercaseCentered(host, identity.name(), theme, + Headline.uppercaseCentered(host, identity.displayName(), theme, nameStyle); - addOptionalLine(host, identity.jobTitle(), safeStyle.titleStyle(), + addOptionalLine(host, identity.tagline(), safeStyle.titleStyle(), safeStyle.lineMargin()); addOptionalLine(host, join(safeStyle.metaJoiner(), @@ -66,7 +64,7 @@ private static void addOptionalLine(SectionBuilder host, } private static void addLinkRow(SectionBuilder host, - CvIdentity identity, + PartyIdentity identity, BrandTheme theme, Style style) { List parts = linkParts(identity); @@ -103,14 +101,14 @@ private static void addLinkRow(SectionBuilder host, })); } - private static List linkParts(CvIdentity identity) { + private static List linkParts(PartyIdentity identity) { List parts = new ArrayList<>(); String email = identity.contact().email(); if (!email.isBlank()) { parts.add(new LinkPart(email, new DocumentLinkOptions("mailto:" + email))); } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { if (!link.label().isBlank()) { parts.add(new LinkPart(link.label(), link.url().isBlank() ? null diff --git a/src/main/java/com/demcha/compose/document/templates/core/identity/PartyIdentity.java b/src/main/java/com/demcha/compose/document/templates/core/identity/PartyIdentity.java new file mode 100644 index 000000000..e20491fcf --- /dev/null +++ b/src/main/java/com/demcha/compose/document/templates/core/identity/PartyIdentity.java @@ -0,0 +1,45 @@ +package com.demcha.compose.document.templates.core.identity; + +import java.util.List; + +/** + * Family-neutral identity contract rendered by the shared header widgets + * ({@link Headline}, {@link ContactLine}, {@link Masthead}). A CV supplies a + * person; an invoice or proposal supplies an organisation — both implement + * this interface, so the same widgets draw either masthead without knowing the + * family's concrete data model. + * + * @since 2.0.0 + */ +public interface PartyIdentity { + + /** + * Full display name — a person's full name for a CV, a company name for an + * invoice or proposal. + * + * @return the display name, never {@code null} + */ + String displayName(); + + /** + * Secondary line shown under the name — a job title for a CV, a strapline + * for an organisation. May be empty when the family has no tagline. + * + * @return the tagline, never {@code null} (empty when absent) + */ + String tagline(); + + /** + * Contact block (phone / email / address). + * + * @return the contact details, never {@code null} + */ + Contact contact(); + + /** + * Labelled links (portfolio, social, web). + * + * @return the links in display order, never {@code null} + */ + List links(); +} diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/Subheadline.java b/src/main/java/com/demcha/compose/document/templates/core/identity/Subheadline.java similarity index 97% rename from src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/Subheadline.java rename to src/main/java/com/demcha/compose/document/templates/core/identity/Subheadline.java index bcc56eb8e..6fde920b4 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/Subheadline.java +++ b/src/main/java/com/demcha/compose/document/templates/core/identity/Subheadline.java @@ -1,4 +1,4 @@ -package com.demcha.compose.document.templates.cv.v2.widgets; +package com.demcha.compose.document.templates.core.identity; import com.demcha.compose.document.dsl.SectionBuilder; import com.demcha.compose.document.node.TextAlign; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/SvgGlyph.java b/src/main/java/com/demcha/compose/document/templates/core/identity/SvgGlyph.java similarity index 96% rename from src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/SvgGlyph.java rename to src/main/java/com/demcha/compose/document/templates/core/identity/SvgGlyph.java index 8ee51189c..d33001a98 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/SvgGlyph.java +++ b/src/main/java/com/demcha/compose/document/templates/core/identity/SvgGlyph.java @@ -1,4 +1,4 @@ -package com.demcha.compose.document.templates.cv.v2.widgets; +package com.demcha.compose.document.templates.core.identity; import com.demcha.compose.document.style.DocumentColor; import com.demcha.compose.document.style.DocumentPathSegment; @@ -43,8 +43,8 @@ * *

    Reuse

    * - *

    Lives in {@code cv/v2/widgets} as the shared glyph primitive behind - * {@link IconTextRow} and the per-preset contact rows. Reuse it instead of + *

    Lives in the core identity layer as the shared glyph primitive behind + * the header widgets and per-preset contact rows. Reuse it instead of * loading icon bytes by hand.

    */ public final class SvgGlyph { diff --git a/src/main/java/com/demcha/compose/document/templates/core/identity/package-info.java b/src/main/java/com/demcha/compose/document/templates/core/identity/package-info.java new file mode 100644 index 000000000..b46b1fc05 --- /dev/null +++ b/src/main/java/com/demcha/compose/document/templates/core/identity/package-info.java @@ -0,0 +1,25 @@ +/** + *

    Core — neutral identity (identity)

    + * + *

    The family-neutral identity layer shared by every template family. A + * masthead is the same shape everywhere — a name, an optional tagline, a + * contact block, and a set of links — so the contract and the widgets that + * draw it live here rather than in any one family.

    + * + *
      + *
    • {@link com.demcha.compose.document.templates.core.identity.PartyIdentity} + * — the contract a family's identity record implements + * ({@code CvIdentity} for a CV, an org record for invoice / proposal).
    • + *
    • {@link com.demcha.compose.document.templates.core.identity.Contact} / + * {@link com.demcha.compose.document.templates.core.identity.Link} + * — the contact-block and labelled-link value records.
    • + *
    • {@link com.demcha.compose.document.templates.core.identity.Headline} / + * {@link com.demcha.compose.document.templates.core.identity.Subheadline} / + * {@link com.demcha.compose.document.templates.core.identity.ContactLine} / + * {@link com.demcha.compose.document.templates.core.identity.Masthead} + * — the header widgets that render a {@code PartyIdentity}.
    • + *
    • {@link com.demcha.compose.document.templates.core.identity.SvgGlyph} + * — a small inline-SVG glyph helper used by the header widgets.
    • + *
    + */ +package com.demcha.compose.document.templates.core.identity; diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/BlueBannerLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/BlueBannerLetter.java index 2c3acb177..4226e31ba 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/BlueBannerLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/BlueBannerLetter.java @@ -6,8 +6,8 @@ import com.demcha.compose.document.templates.coverletter.v2.components.LetterBody; import com.demcha.compose.document.templates.coverletter.v2.data.CoverLetterDocument; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import java.util.Objects; @@ -90,7 +90,7 @@ public void compose(DocumentSession document, CoverLetterDocument doc) { .name("CoverLetterV2BlueBannerRoot") .spacing(theme.spacing().pageFlowSpacing()) .addSection("CoverLetterV2BlueBannerHeader", section -> - Headline.spacedCentered(section, doc.identity().name(), theme)) + Headline.spacedCentered(section, doc.identity().name().full(), theme)) .addSection("CoverLetterV2BlueBannerContact", section -> ContactLine.centered(section, doc.identity(), theme)); diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/BoxedSectionsLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/BoxedSectionsLetter.java index c4793702e..d037f79dc 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/BoxedSectionsLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/BoxedSectionsLetter.java @@ -6,8 +6,8 @@ import com.demcha.compose.document.templates.coverletter.v2.components.LetterBody; import com.demcha.compose.document.templates.coverletter.v2.data.CoverLetterDocument; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import java.util.Objects; @@ -91,7 +91,7 @@ public void compose(DocumentSession document, CoverLetterDocument doc) { .addSection("CoverLetterV2BoxedHeadline", section -> { section.accentBottom(theme.palette().rule(), theme.spacing().accentRuleWidth()); - Headline.spacedCentered(section, doc.identity().name(), theme); + Headline.spacedCentered(section, doc.identity().name().full(), theme); }) .addSection("CoverLetterV2BoxedContact", section -> { section.accentBottom(theme.palette().rule(), diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/CenteredHeadlineLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/CenteredHeadlineLetter.java index 9c79ab580..bda81c9ee 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/CenteredHeadlineLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/CenteredHeadlineLetter.java @@ -12,9 +12,9 @@ import com.demcha.compose.document.templates.core.text.TextStyles; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; -import com.demcha.compose.document.templates.cv.v2.widgets.Subheadline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; +import com.demcha.compose.document.templates.core.identity.Subheadline; import java.util.Objects; @@ -102,7 +102,7 @@ public void compose(DocumentSession document, CoverLetterDocument doc) { .name("CoverLetterV2CenteredHeadlineRoot") .spacing(theme.spacing().pageFlowSpacing()) .addSection("CoverLetterV2CenteredHeadlineHeadline", section -> { - Headline.spacedCentered(section, identity.name(), theme); + Headline.spacedCentered(section, identity.name().full(), theme); if (!identity.jobTitle().isBlank()) { Subheadline.centeredSpacedCaps(section, identity.jobTitle(), subheadlineStyle()); diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ClassicSerifLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ClassicSerifLetter.java index 1422cc7df..b51a0fc7c 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ClassicSerifLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ClassicSerifLetter.java @@ -12,8 +12,8 @@ import com.demcha.compose.document.templates.core.text.TextStyles; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import java.util.Objects; @@ -114,7 +114,7 @@ private void addHeader(PageFlowBuilder flow, CvIdentity identity, double width) { flow.addSection("CoverLetterV2ClassicSerifHeader", section -> { section.spacing(5); - Headline.spacedCentered(section, identity.name(), theme); + Headline.spacedCentered(section, identity.name().full(), theme); section.addLine(line -> line .name("CoverLetterV2ClassicSerifHeaderRule") .horizontal(width) diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/CompactMonoLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/CompactMonoLetter.java index 43b3f046b..defab276b 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/CompactMonoLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/CompactMonoLetter.java @@ -12,8 +12,8 @@ import com.demcha.compose.document.templates.core.text.TextStyles; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import java.util.Objects; @@ -134,7 +134,7 @@ private void addHeader(PageFlowBuilder flow, CvIdentity identity, .fillColor(HEADER) .cornerRadius(3); section.addSection("Name", name -> - Headline.uppercaseLeftAligned(name, identity.name(), + Headline.uppercaseLeftAligned(name, identity.name().full(), theme, headerNameStyle())); section.addSection("Contact", contact -> ContactLine.leftAligned(contact, identity, theme, diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/EditorialBlueLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/EditorialBlueLetter.java index e970ae1c1..7f786ed62 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/EditorialBlueLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/EditorialBlueLetter.java @@ -11,7 +11,7 @@ import com.demcha.compose.document.templates.coverletter.v2.data.CoverLetterDocument; import com.demcha.compose.document.templates.core.text.TextStyles; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.Masthead; +import com.demcha.compose.document.templates.core.identity.Masthead; import com.demcha.compose.font.FontName; import java.util.Objects; diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/EngineeringResumeLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/EngineeringResumeLetter.java index c5678f14c..1c4706298 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/EngineeringResumeLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/EngineeringResumeLetter.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.coverletter.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.dsl.PageFlowBuilder; import com.demcha.compose.document.dsl.SectionBuilder; @@ -12,7 +14,6 @@ import com.demcha.compose.document.templates.core.text.TextStyles; import com.demcha.compose.document.templates.core.text.MarkdownInline; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; -import com.demcha.compose.document.templates.cv.v2.data.CvLink; import com.demcha.compose.document.templates.core.theme.BrandTheme; import java.util.ArrayList; @@ -220,7 +221,7 @@ private static List contactParts(CvIdentity identity) { if (!email.isBlank()) { addPart(parts, email, new DocumentLinkOptions("mailto:" + email)); } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { addPart(parts, link.label(), link.url().isBlank() ? null : new DocumentLinkOptions(link.url().trim())); diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ExecutiveLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ExecutiveLetter.java index 47d027dc7..a5dfb0830 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ExecutiveLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ExecutiveLetter.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.coverletter.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.dsl.PageFlowBuilder; import com.demcha.compose.document.dsl.SectionBuilder; @@ -15,9 +17,8 @@ import com.demcha.compose.document.templates.core.text.TextStyles; import com.demcha.compose.document.templates.core.text.TextOrnaments; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; -import com.demcha.compose.document.templates.cv.v2.data.CvLink; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.font.FontName; import java.util.Objects; @@ -135,7 +136,7 @@ private void addHeader(PageFlowBuilder flow, CvIdentity identity, flow.addSection("CoverLetterV2ExecutiveHeader", section -> { section.spacing(2) .padding(DocumentInsets.zero()); - Headline.uppercaseLeftAligned(section, identity.name(), theme, + Headline.uppercaseLeftAligned(section, identity.name().full(), theme, nameStyle()); String meta = TextOrnaments.joinPipe(identity.contact().address(), identity.contact().phone()); @@ -176,7 +177,7 @@ private void addLinkRow(SectionBuilder section, CvIdentity identity) { new DocumentLinkOptions("mailto:" + email)); first = false; } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { if (link.label().isBlank()) { continue; } diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/MintEditorialLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/MintEditorialLetter.java index 21a08cb18..8c94063bd 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/MintEditorialLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/MintEditorialLetter.java @@ -16,8 +16,8 @@ import com.demcha.compose.document.templates.core.text.TextOrnaments; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; -import com.demcha.compose.document.templates.cv.v2.widgets.Subheadline; +import com.demcha.compose.document.templates.core.identity.Headline; +import com.demcha.compose.document.templates.core.identity.Subheadline; import java.util.Objects; @@ -321,7 +321,7 @@ private void addMasthead(SectionBuilder section, CvIdentity identity, private void addPlainMasthead(SectionBuilder section, CvIdentity identity) { // Style-override variant so only the name colour can change. - Headline.render(section, identity.name(), theme, + Headline.render(section, identity.name().full(), theme, TextAlign.CENTER, true, mastheadNameStyle()); String jobTitle = identity.jobTitle(); if (jobTitle != null && !jobTitle.isBlank()) { diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ModernProfessionalLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ModernProfessionalLetter.java index 5dc58d788..7eec19c8f 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ModernProfessionalLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/ModernProfessionalLetter.java @@ -10,8 +10,8 @@ import com.demcha.compose.document.templates.coverletter.v2.data.CoverLetterDocument; import com.demcha.compose.document.templates.core.text.TextStyles; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.font.FontName; import java.util.Objects; @@ -120,7 +120,7 @@ public void compose(DocumentSession document, CoverLetterDocument doc) { .name("CoverLetterV2ModernRoot") .spacing(theme.spacing().pageFlowSpacing()) .addSection("Header", section -> - Headline.rightAligned(section, doc.identity().name(), + Headline.rightAligned(section, doc.identity().name().full(), theme, nameStyle)) .addSection("Contact", section -> { section.accentBottom(theme.palette().rule(), diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/MonogramSidebarLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/MonogramSidebarLetter.java index 21de2f00e..26d2330ec 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/MonogramSidebarLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/MonogramSidebarLetter.java @@ -15,7 +15,7 @@ import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; import com.demcha.compose.document.templates.cv.v2.data.CvName; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; +import com.demcha.compose.document.templates.core.identity.ContactLine; import com.demcha.compose.font.FontName; import java.util.ArrayList; diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/NordicCleanLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/NordicCleanLetter.java index 78208d202..54539c166 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/NordicCleanLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/NordicCleanLetter.java @@ -13,8 +13,8 @@ import com.demcha.compose.document.templates.core.text.MarkdownInline; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import java.util.Locale; import java.util.Objects; @@ -117,7 +117,7 @@ private void addHeader(PageFlowBuilder flow, CvIdentity identity) { .weights(1.2, 0.8) .addSection("Identity", id -> { id.spacing(3).padding(new DocumentInsets(1, 0, 2, 0)); - Headline.uppercaseLeftAligned(id, identity.name(), theme, + Headline.uppercaseLeftAligned(id, identity.name().full(), theme, headlineStyle()); id.addShape(shape -> shape .name("CoverLetterV2NordicCleanNameAccent") diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/PanelLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/PanelLetter.java index 0d6f19490..19e9a5fd7 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/PanelLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/PanelLetter.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.coverletter.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.dsl.PageFlowBuilder; import com.demcha.compose.document.dsl.SectionBuilder; @@ -12,7 +14,6 @@ import com.demcha.compose.document.templates.core.text.TextStyles; import com.demcha.compose.document.templates.core.text.TextOrnaments; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; -import com.demcha.compose.document.templates.cv.v2.data.CvLink; import com.demcha.compose.document.templates.core.theme.BrandTheme; import com.demcha.compose.document.templates.widgets.CardWidget; import com.demcha.compose.font.FontName; @@ -178,7 +179,7 @@ private void addLinkRow(SectionBuilder section, CvIdentity identity) { new DocumentLinkOptions("mailto:" + email)); first = false; } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { if (link.label().isBlank()) { continue; } diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/SidebarPortraitLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/SidebarPortraitLetter.java index 5a7c5b4be..d31121529 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/SidebarPortraitLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/SidebarPortraitLetter.java @@ -13,7 +13,7 @@ import com.demcha.compose.document.templates.core.text.TextOrnaments; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; +import com.demcha.compose.document.templates.core.identity.ContactLine; import java.util.Objects; diff --git a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/TimelineMinimalLetter.java b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/TimelineMinimalLetter.java index e9245e21a..dcaef1bdc 100644 --- a/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/TimelineMinimalLetter.java +++ b/src/main/java/com/demcha/compose/document/templates/coverletter/v2/presets/TimelineMinimalLetter.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.coverletter.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.dsl.PageFlowBuilder; import com.demcha.compose.document.dsl.SectionBuilder; @@ -17,9 +19,8 @@ import com.demcha.compose.document.templates.cv.v2.components.SectionLookup; import com.demcha.compose.document.templates.core.text.TextOrnaments; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; -import com.demcha.compose.document.templates.cv.v2.data.CvLink; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.SvgGlyph; +import com.demcha.compose.document.templates.core.identity.SvgGlyph; import java.util.*; @@ -192,7 +193,7 @@ private List contactItems(CvIdentity identity) { addContactItem(items, "@", "email.svg", email, new DocumentLinkOptions("mailto:" + email)); } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { String label = link.label(); if (label.isBlank()) { continue; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/presets/MonogramSidebar.java b/src/main/java/com/demcha/compose/document/templates/cv/presets/MonogramSidebar.java index 101a532dc..048f8bd52 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/presets/MonogramSidebar.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/presets/MonogramSidebar.java @@ -20,7 +20,7 @@ import com.demcha.compose.document.style.DocumentTextDecoration; import com.demcha.compose.document.style.DocumentTextStyle; import com.demcha.compose.document.templates.api.DocumentTemplate; -import com.demcha.compose.document.templates.cv.v2.widgets.SvgGlyph; +import com.demcha.compose.document.templates.core.identity.SvgGlyph; import com.demcha.compose.document.templates.blocks.Block; import com.demcha.compose.document.templates.blocks.BulletListBlock; import com.demcha.compose.document.templates.blocks.IndentedBlock; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/presets/SidebarPortrait.java b/src/main/java/com/demcha/compose/document/templates/cv/presets/SidebarPortrait.java index d6d6f8cc4..30ef68033 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/presets/SidebarPortrait.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/presets/SidebarPortrait.java @@ -14,7 +14,7 @@ import com.demcha.compose.document.style.DocumentTextStyle; import com.demcha.compose.document.svg.SvgIcon; import com.demcha.compose.document.templates.api.DocumentTemplate; -import com.demcha.compose.document.templates.cv.v2.widgets.SvgGlyph; +import com.demcha.compose.document.templates.core.identity.SvgGlyph; import com.demcha.compose.document.templates.blocks.Block; import com.demcha.compose.document.templates.blocks.BulletListBlock; import com.demcha.compose.document.templates.blocks.IndentedBlock; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/presets/TimelineMinimal.java b/src/main/java/com/demcha/compose/document/templates/cv/presets/TimelineMinimal.java index 955cad367..250cab15f 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/presets/TimelineMinimal.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/presets/TimelineMinimal.java @@ -13,7 +13,7 @@ import com.demcha.compose.document.style.DocumentTextDecoration; import com.demcha.compose.document.style.DocumentTextStyle; import com.demcha.compose.document.templates.api.DocumentTemplate; -import com.demcha.compose.document.templates.cv.v2.widgets.SvgGlyph; +import com.demcha.compose.document.templates.core.identity.SvgGlyph; import com.demcha.compose.document.templates.blocks.Block; import com.demcha.compose.document.templates.blocks.BulletListBlock; import com.demcha.compose.document.templates.blocks.IndentedBlock; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/components/ContactRenderer.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/components/ContactRenderer.java index 132be50f6..88ec45955 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/components/ContactRenderer.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/components/ContactRenderer.java @@ -3,11 +3,11 @@ import com.demcha.compose.document.dsl.SectionBuilder; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; +import com.demcha.compose.document.templates.core.identity.ContactLine; /** * @deprecated Use - * {@link com.demcha.compose.document.templates.cv.v2.widgets.ContactLine#centered} + * {@link com.demcha.compose.document.templates.core.identity.ContactLine#centered} * instead — the widget gives you named centred/right-aligned * variants plus a configurable field order. Kept as a thin * delegating shim so v2 code written before the widgets layer keeps diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/components/HeadlineRenderer.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/components/HeadlineRenderer.java index 730603a87..c724c8b56 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/components/HeadlineRenderer.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/components/HeadlineRenderer.java @@ -3,11 +3,11 @@ import com.demcha.compose.document.dsl.SectionBuilder; import com.demcha.compose.document.templates.cv.v2.data.CvName; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.Headline; /** * @deprecated Use - * {@link com.demcha.compose.document.templates.cv.v2.widgets.Headline#spacedCentered} + * {@link com.demcha.compose.document.templates.core.identity.Headline#spacedCentered} * instead — the widget gives you a named API plus alignment + * spaced-caps variants, while this class only ever did the * centred-spaced-caps form. Kept as a thin delegating shim so v2 @@ -27,6 +27,6 @@ private HeadlineRenderer() { */ @Deprecated public static void render(SectionBuilder section, CvName name, BrandTheme theme) { - Headline.spacedCentered(section, name, theme); + Headline.spacedCentered(section, name.full(), theme); } } diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvIdentity.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvIdentity.java index f99eadcaf..cd866ecc3 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvIdentity.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/data/CvIdentity.java @@ -1,5 +1,9 @@ package com.demcha.compose.document.templates.cv.v2.data; +import com.demcha.compose.document.templates.core.identity.Contact; +import com.demcha.compose.document.templates.core.identity.Link; +import com.demcha.compose.document.templates.core.identity.PartyIdentity; + import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -10,7 +14,7 @@ * outbound links. * *

    Required pieces have their own types ({@link CvName}, - * {@link CvContact}); optional links are accumulated through the + * {@link Contact}); optional links are accumulated through the * builder's {@code link(...)} method — added when the author wants * them, simply omitted otherwise.

    * @@ -22,7 +26,8 @@ * @param links ordered list of optional outbound links; never null */ public record CvIdentity(CvName name, String jobTitle, - CvContact contact, List links) { + Contact contact, List links) + implements PartyIdentity { /** * Validates that {@code name} and {@code contact} are non-null, @@ -45,10 +50,30 @@ public record CvIdentity(CvName name, String jobTitle, * @param contact phone / email / address — all three required * @param links ordered list of optional outbound links; never null */ - public CvIdentity(CvName name, CvContact contact, List links) { + public CvIdentity(CvName name, Contact contact, List links) { this(name, "", contact, links); } + /** + * {@inheritDoc} For a CV this is the candidate's full name. + * + * @return {@link CvName#full()} + */ + @Override + public String displayName() { + return name.full(); + } + + /** + * {@inheritDoc} For a CV this is the professional title. + * + * @return the job title, blank when absent + */ + @Override + public String tagline() { + return jobTitle; + } + /** * Creates a fluent builder for {@code CvIdentity}. * @@ -64,8 +89,8 @@ public static Builder builder() { public static final class Builder { private CvName name; private String jobTitle = ""; - private CvContact contact; - private final List links = new ArrayList<>(); + private Contact contact; + private final List links = new ArrayList<>(); private Builder() { } @@ -124,7 +149,7 @@ public Builder jobTitle(String value) { * @param value the contact block to use * @return this builder for chaining */ - public Builder contact(CvContact value) { + public Builder contact(Contact value) { this.contact = value; return this; } @@ -138,7 +163,7 @@ public Builder contact(CvContact value) { * @return this builder for chaining */ public Builder contact(String phone, String email, String address) { - this.contact = new CvContact(phone, email, address); + this.contact = new Contact(phone, email, address); return this; } @@ -148,7 +173,7 @@ public Builder contact(String phone, String email, String address) { * @param link the link to append (non-null) * @return this builder for chaining */ - public Builder link(CvLink link) { + public Builder link(Link link) { this.links.add(Objects.requireNonNull(link, "link")); return this; } @@ -161,7 +186,7 @@ public Builder link(CvLink link) { * @return this builder for chaining */ public Builder link(String label, String url) { - this.links.add(new CvLink(label, url)); + this.links.add(new Link(label, url)); return this; } diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/BlueBanner.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/BlueBanner.java index 769b956ca..faa5c417b 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/BlueBanner.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/BlueBanner.java @@ -13,9 +13,9 @@ import com.demcha.compose.document.templates.cv.v2.components.*; import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; +import com.demcha.compose.document.templates.core.identity.ContactLine; import com.demcha.compose.document.templates.cv.v2.widgets.FlowSectionHeader; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.Headline; import java.util.ArrayList; import java.util.List; @@ -122,7 +122,7 @@ public void compose(DocumentSession document, CvDocument doc) { .spacing(theme.spacing().pageFlowSpacing()) .addSection("Header", section -> Headline.spacedCentered(section, - doc.identity().name(), theme)) + doc.identity().name().full(), theme)) .addSection("Contact", section -> ContactLine.centered(section, doc.identity(), theme)); diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/BoxedSections.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/BoxedSections.java index ece8b5dad..1b6703914 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/BoxedSections.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/BoxedSections.java @@ -8,8 +8,8 @@ import com.demcha.compose.document.templates.cv.v2.data.CvSection; import com.demcha.compose.document.templates.cv.v2.data.Slot; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.document.templates.cv.v2.widgets.SectionHeader; import java.util.List; @@ -107,7 +107,7 @@ public void compose(DocumentSession document, CvDocument doc) { .addSection("CvV2Headline", section -> { section.accentBottom(theme.palette().rule(), theme.spacing().accentRuleWidth()); - Headline.spacedCentered(section, doc.identity().name(), theme); + Headline.spacedCentered(section, doc.identity().name().full(), theme); }) .addSection("CvV2Contact", section -> { section.accentBottom(theme.palette().rule(), diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/CenteredHeadline.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/CenteredHeadline.java index 2818a1e44..38929fd6e 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/CenteredHeadline.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/CenteredHeadline.java @@ -12,10 +12,10 @@ import com.demcha.compose.document.templates.cv.v2.components.SectionDispatcher; import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.document.templates.cv.v2.widgets.SectionHeader; -import com.demcha.compose.document.templates.cv.v2.widgets.Subheadline; +import com.demcha.compose.document.templates.core.identity.Subheadline; import java.util.List; import java.util.Objects; @@ -134,7 +134,7 @@ public void compose(DocumentSession document, CvDocument doc) { .name("CenteredHeadlineRoot") .spacing(theme.spacing().pageFlowSpacing()) .addSection("Headline", section -> { - Headline.spacedCentered(section, doc.identity().name(), theme); + Headline.spacedCentered(section, doc.identity().name().full(), theme); Subheadline.centeredSpacedCaps(section, SUBHEADLINE_CAPTION, subheadlineStyle()); }) diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/ClassicSerif.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/ClassicSerif.java index a281d8cf1..abbe55318 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/ClassicSerif.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/ClassicSerif.java @@ -16,8 +16,8 @@ import com.demcha.compose.document.templates.cv.v2.components.*; import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.document.templates.cv.v2.widgets.SectionHeader; import java.util.List; @@ -135,7 +135,7 @@ private void addHeader(PageFlowBuilder flow, CvDocument doc, double width) { flow.addSection("CvV2ClassicSerifHeader", section -> { section.spacing(5); - Headline.spacedCentered(section, doc.identity().name(), theme); + Headline.spacedCentered(section, doc.identity().name().full(), theme); section.addLine(line -> line .name("CvV2ClassicSerifHeaderRule") .horizontal(width) diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/CompactMono.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/CompactMono.java index b00d9bb62..121fe3b3a 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/CompactMono.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/CompactMono.java @@ -11,8 +11,8 @@ import com.demcha.compose.document.templates.cv.v2.components.*; import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.document.templates.cv.v2.widgets.SectionHeader; import com.demcha.compose.document.templates.cv.v2.widgets.SectionModule; import com.demcha.compose.document.templates.widgets.CardWidget; @@ -148,7 +148,7 @@ private void addHeader(PageFlowBuilder flow, CvDocument doc, .cornerRadius(3); section.addSection("Name", name -> Headline.uppercaseLeftAligned(name, - doc.identity().name(), theme, + doc.identity().name().full(), theme, headerNameStyle())); section.addSection("Contact", contact -> ContactLine.leftAligned(contact, doc.identity(), theme, diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/EditorialBlue.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/EditorialBlue.java index ff52ebd27..a85d0cf6a 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/EditorialBlue.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/EditorialBlue.java @@ -16,7 +16,7 @@ import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; import com.demcha.compose.document.templates.cv.v2.widgets.FlowSectionHeader; -import com.demcha.compose.document.templates.cv.v2.widgets.Masthead; +import com.demcha.compose.document.templates.core.identity.Masthead; import com.demcha.compose.document.templates.widgets.TableWidget; import com.demcha.compose.font.FontName; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/EngineeringResume.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/EngineeringResume.java index a8372b465..fc409afea 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/EngineeringResume.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/EngineeringResume.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.cv.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.dsl.PageFlowBuilder; import com.demcha.compose.document.dsl.SectionBuilder; @@ -239,7 +241,7 @@ private static List contactParts(CvIdentity identity) { addPart(parts, email, new DocumentLinkOptions("mailto:" + email)); } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { addPart(parts, link.label(), link.url().isBlank() ? null : new DocumentLinkOptions(link.url().trim())); diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/Executive.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/Executive.java index 0d0705c21..80a99723e 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/Executive.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/Executive.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.cv.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.dsl.PageFlowBuilder; import com.demcha.compose.document.dsl.SectionBuilder; @@ -14,7 +16,7 @@ import com.demcha.compose.document.templates.cv.v2.components.SectionDispatcher; import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.document.templates.cv.v2.widgets.SectionHeader; import com.demcha.compose.font.FontName; @@ -139,7 +141,7 @@ private void addHeader(PageFlowBuilder flow, CvIdentity identity, flow.addSection("CvV2ExecutiveHeader", section -> { section.spacing(2) .padding(DocumentInsets.zero()); - Headline.uppercaseLeftAligned(section, identity.name(), theme, + Headline.uppercaseLeftAligned(section, identity.name().full(), theme, nameStyle()); String meta = joinPipe(identity.contact().address(), identity.contact().phone()); @@ -180,7 +182,7 @@ private void addLinkRow(SectionBuilder section, CvIdentity identity) { new DocumentLinkOptions("mailto:" + email)); first = false; } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { if (link.label().isBlank()) { continue; } diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MinimalUnderlined.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MinimalUnderlined.java index c554ac419..42f28f4cd 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MinimalUnderlined.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MinimalUnderlined.java @@ -8,8 +8,8 @@ import com.demcha.compose.document.templates.cv.v2.data.CvSection; import com.demcha.compose.document.templates.cv.v2.data.Slot; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.document.templates.cv.v2.widgets.SectionHeader; import java.util.List; @@ -105,7 +105,7 @@ public void compose(DocumentSession document, CvDocument doc) { .name("CvV2MinimalRoot") .spacing(theme.spacing().pageFlowSpacing()) .addSection("Headline", section -> - Headline.spacedCentered(section, doc.identity().name(), theme)) + Headline.spacedCentered(section, doc.identity().name().full(), theme)) .addSection("Contact", section -> { section.accentBottom(theme.palette().rule(), theme.spacing().accentRuleWidth()); diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MintEditorial.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MintEditorial.java index c76daf780..ce0780bb1 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MintEditorial.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MintEditorial.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.cv.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.dsl.PageFlowBuilder; import com.demcha.compose.document.dsl.ParagraphBuilder; @@ -20,11 +22,11 @@ import com.demcha.compose.document.templates.core.text.TextOrnaments; import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.document.templates.cv.v2.widgets.IconTextRow; import com.demcha.compose.document.templates.cv.v2.widgets.SkillBar; -import com.demcha.compose.document.templates.cv.v2.widgets.Subheadline; -import com.demcha.compose.document.templates.cv.v2.widgets.SvgGlyph; +import com.demcha.compose.document.templates.core.identity.Subheadline; +import com.demcha.compose.document.templates.core.identity.SvgGlyph; import com.demcha.compose.document.svg.SvgIcon; import java.io.IOException; @@ -572,7 +574,7 @@ private void addPlainHeader(SectionBuilder section, CvIdentity identity) { // Render the name through Headline's style-override variant so only // the colour can change — alignment, spaced-caps transform, font and // size all stay exactly as Headline.spacedCentered produced them. - Headline.render(section, identity.name(), theme, + Headline.render(section, identity.name().full(), theme, TextAlign.CENTER, true, mastheadNameStyle()); String jobTitle = identity.jobTitle(); if (jobTitle != null && !jobTitle.isBlank()) { @@ -693,7 +695,7 @@ private void addContact(SectionBuilder section, CvIdentity identity) { CONTACT_ICON_SIZE, address, style, null, DocumentInsets.bottom(13)); } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { if (link.label().isBlank()) { continue; } @@ -825,7 +827,7 @@ private void addSocial(SectionBuilder section, CvIdentity identity) { block.spacing(0).padding(DocumentInsets.zero()); addBlockHeading(block, "Social"); DocumentTextStyle style = labelStyle(); - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { if (link.label().isBlank()) { continue; } diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/ModernProfessional.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/ModernProfessional.java index f6188a48a..a33f75ec8 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/ModernProfessional.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/ModernProfessional.java @@ -11,8 +11,8 @@ import com.demcha.compose.document.templates.cv.v2.data.CvSection; import com.demcha.compose.document.templates.cv.v2.data.Slot; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.document.templates.cv.v2.widgets.SectionHeader; import com.demcha.compose.font.FontName; @@ -158,7 +158,7 @@ public void compose(DocumentSession document, CvDocument doc) { .name("CvV2ModernRoot") .spacing(theme.spacing().pageFlowSpacing()) .addSection("Header", section -> - Headline.rightAligned(section, doc.identity().name(), + Headline.rightAligned(section, doc.identity().name().full(), theme, nameStyle)) .addSection("Contact", section -> { section.accentBottom(theme.palette().rule(), diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MonogramSidebar.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MonogramSidebar.java index 1d5939dbe..f132389ee 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MonogramSidebar.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/MonogramSidebar.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.cv.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.templates.core.text.MarkdownInline; import com.demcha.compose.document.templates.core.text.TextOrnaments; import com.demcha.compose.document.templates.core.text.TextStyles; @@ -16,7 +18,7 @@ import com.demcha.compose.document.templates.cv.v2.components.*; import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.SvgGlyph; +import com.demcha.compose.document.templates.core.identity.SvgGlyph; import com.demcha.compose.font.FontName; import java.util.*; @@ -852,7 +854,7 @@ private static List contactItems(CvIdentity identity) { } addContactItem(items, "location.svg", identity.contact().address(), null); - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { String label = link.label(); if (label.isBlank()) { continue; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/NordicClean.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/NordicClean.java index f65274e5b..e826ef6bf 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/NordicClean.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/NordicClean.java @@ -11,8 +11,8 @@ import com.demcha.compose.document.templates.cv.v2.components.*; import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.ContactLine; -import com.demcha.compose.document.templates.cv.v2.widgets.Headline; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; import com.demcha.compose.document.templates.cv.v2.widgets.ProfileBand; import com.demcha.compose.document.templates.cv.v2.widgets.SectionModule; @@ -297,7 +297,7 @@ private void addHeader(PageFlowBuilder flow, CvDocument doc) { identity.spacing(3) .padding(new DocumentInsets(1, 0, 2, 0)); Headline.uppercaseLeftAligned(identity, - doc.identity().name(), theme, + doc.identity().name().full(), theme, headlineStyle()); identity.addShape(shape -> shape .name("CvV2NordicCleanNameAccent") diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/Panel.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/Panel.java index 7c118c4c7..671850da2 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/Panel.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/Panel.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.cv.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.templates.core.text.TextStyles; import com.demcha.compose.document.api.DocumentSession; @@ -275,7 +277,7 @@ private void addLinkRow(SectionBuilder section, CvIdentity identity) { new DocumentLinkOptions("mailto:" + email)); first = false; } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { if (link.label().isBlank()) { continue; } diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/SidebarPortrait.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/SidebarPortrait.java index f8563ee58..b22ee7859 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/SidebarPortrait.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/SidebarPortrait.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.cv.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.api.PageBackgroundFill; import com.demcha.compose.document.dsl.SectionBuilder; @@ -18,7 +20,7 @@ import com.demcha.compose.document.templates.cv.v2.components.SectionLookup; import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.SvgGlyph; +import com.demcha.compose.document.templates.core.identity.SvgGlyph; import java.io.IOException; import java.io.InputStream; @@ -896,7 +898,7 @@ private static List contactItems(CvIdentity identity) { } addContactItem(items, "location.svg", identity.contact().address(), null); - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { String label = link.label(); if (label.isBlank()) { continue; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/TimelineMinimal.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/TimelineMinimal.java index e9c905c06..504f3f894 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/TimelineMinimal.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/presets/TimelineMinimal.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.cv.v2.presets; +import com.demcha.compose.document.templates.core.identity.Link; + import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.dsl.RowBuilder; import com.demcha.compose.document.dsl.SectionBuilder; @@ -17,7 +19,7 @@ import com.demcha.compose.document.templates.cv.v2.components.SectionLookup; import com.demcha.compose.document.templates.cv.v2.data.*; import com.demcha.compose.document.templates.core.theme.BrandTheme; -import com.demcha.compose.document.templates.cv.v2.widgets.SvgGlyph; +import com.demcha.compose.document.templates.core.identity.SvgGlyph; import com.demcha.compose.document.templates.widgets.TimelineAxisWidget; import java.util.*; @@ -286,7 +288,7 @@ private List contactItems(CvIdentity identity) { addContactItem(items, "@", "email.svg", email, new DocumentLinkOptions("mailto:" + email)); } - for (CvLink link : identity.links()) { + for (Link link : identity.links()) { String label = link.label(); if (label.isBlank()) { continue; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/IconTextRow.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/IconTextRow.java index b5f115e04..ac9ec3e76 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/IconTextRow.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/IconTextRow.java @@ -1,5 +1,7 @@ package com.demcha.compose.document.templates.cv.v2.widgets; +import com.demcha.compose.document.templates.core.identity.SvgGlyph; + import com.demcha.compose.document.dsl.SectionBuilder; import com.demcha.compose.document.image.DocumentImageData; import com.demcha.compose.document.node.DocumentLinkOptions; diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/SectionHeader.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/SectionHeader.java index f765f31a0..749bca0ab 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/SectionHeader.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/SectionHeader.java @@ -45,7 +45,8 @@ * {@code ClassicSerif}. * * - *

    Unlike {@link Headline} (one rendering shape, two text + *

    Unlike {@link com.demcha.compose.document.templates.core.identity.Headline} + * (one rendering shape, two text * transforms), section headers are structurally * different per variant — soft-panel vs accentBottom vs plain * paragraph. That's why each variant gets its own factory method diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/package-info.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/package-info.java index f170e9aec..4230eb462 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/package-info.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/widgets/package-info.java @@ -41,19 +41,19 @@ *

    Current widget catalog

    * *
      - *
    • {@link com.demcha.compose.document.templates.cv.v2.widgets.Headline} + *
    • {@link com.demcha.compose.document.templates.core.identity.Headline} * — top-of-document name in 4 variants * ({@code spacedCentered}, {@code uppercaseCentered}, * {@code uppercaseLeftAligned}, {@code rightAligned}).
    • - *
    • {@link com.demcha.compose.document.templates.cv.v2.widgets.Subheadline} + *
    • {@link com.demcha.compose.document.templates.core.identity.Subheadline} * — secondary tagline under the name in 1 variant * ({@code centeredSpacedCaps}).
    • - *
    • {@link com.demcha.compose.document.templates.cv.v2.widgets.ContactLine} + *
    • {@link com.demcha.compose.document.templates.core.identity.ContactLine} * — contact + links row/stack in 5 variants * ({@code centered}, {@code rightAligned}, * {@code leftAligned}, {@code rightAlignedStacked}, * {@code twoRowRightAligned}).
    • - *
    • {@link com.demcha.compose.document.templates.cv.v2.widgets.Masthead} + *
    • {@link com.demcha.compose.document.templates.core.identity.Masthead} * — centred editorial identity block: name, optional title, * compact metadata, and link row.
    • *
    • {@link com.demcha.compose.document.templates.cv.v2.widgets.SectionHeader} diff --git a/src/test/java/com/demcha/compose/document/templates/cv/v2/data/CvContactTest.java b/src/test/java/com/demcha/compose/document/templates/core/identity/ContactTest.java similarity index 69% rename from src/test/java/com/demcha/compose/document/templates/cv/v2/data/CvContactTest.java rename to src/test/java/com/demcha/compose/document/templates/core/identity/ContactTest.java index 7dded26be..a1f7a9c65 100644 --- a/src/test/java/com/demcha/compose/document/templates/cv/v2/data/CvContactTest.java +++ b/src/test/java/com/demcha/compose/document/templates/core/identity/ContactTest.java @@ -1,42 +1,42 @@ -package com.demcha.compose.document.templates.cv.v2.data; +package com.demcha.compose.document.templates.core.identity; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -class CvContactTest { +class ContactTest { @Test void rejects_blank_phone() { - assertThatThrownBy(() -> new CvContact("", "j@d.com", "London")) + assertThatThrownBy(() -> new Contact("", "j@d.com", "London")) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("phone"); } @Test void rejects_blank_email() { - assertThatThrownBy(() -> new CvContact("+44 0", " ", "London")) + assertThatThrownBy(() -> new Contact("+44 0", " ", "London")) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("email"); } @Test void rejects_blank_address() { - assertThatThrownBy(() -> new CvContact("+44 0", "j@d.com", "")) + assertThatThrownBy(() -> new Contact("+44 0", "j@d.com", "")) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("address"); } @Test void rejects_null_field() { - assertThatThrownBy(() -> new CvContact(null, "j@d.com", "London")) + assertThatThrownBy(() -> new Contact(null, "j@d.com", "London")) .isInstanceOf(NullPointerException.class); } @Test void happy_path_keeps_fields() { - CvContact c = new CvContact("+44 1234", "j@d.com", "London, UK"); + Contact c = new Contact("+44 1234", "j@d.com", "London, UK"); assertThat(c.phone()).isEqualTo("+44 1234"); assertThat(c.email()).isEqualTo("j@d.com"); assertThat(c.address()).isEqualTo("London, UK"); diff --git a/src/test/java/com/demcha/compose/document/templates/cv/v2/data/CvIdentityTest.java b/src/test/java/com/demcha/compose/document/templates/cv/v2/data/CvIdentityTest.java new file mode 100644 index 000000000..e003457d8 --- /dev/null +++ b/src/test/java/com/demcha/compose/document/templates/cv/v2/data/CvIdentityTest.java @@ -0,0 +1,57 @@ +package com.demcha.compose.document.templates.cv.v2.data; + +import com.demcha.compose.document.templates.core.identity.Contact; +import com.demcha.compose.document.templates.core.identity.Link; +import com.demcha.compose.document.templates.core.identity.PartyIdentity; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Covers the {@link PartyIdentity} mapping that {@link CvIdentity} adds — the + * neutral header widgets read a CV through this contract. + */ +class CvIdentityTest { + + private static CvIdentity sample(String jobTitle) { + return new CvIdentity( + CvName.of("Jane", "Doe"), + jobTitle, + new Contact("+44 1234", "jane@demo.dev", "London"), + List.of(new Link("GitHub", "https://example.dev"))); + } + + @Test + void isAPartyIdentity() { + assertThat(sample("Engineer")).isInstanceOf(PartyIdentity.class); + } + + @Test + void displayNameIsTheFullName() { + CvIdentity id = sample("Engineer"); + assertThat(id.displayName()).isEqualTo(id.name().full()); + } + + @Test + void taglineMirrorsJobTitle() { + CvIdentity id = sample("Platform Engineer"); + assertThat(id.tagline()).isEqualTo(id.jobTitle()).isEqualTo("Platform Engineer"); + } + + @Test + void taglineIsBlankWhenJobTitleAbsent() { + // the back-compat three-arg constructor leaves the title blank + PartyIdentity id = new CvIdentity(CvName.of("Jane", "Doe"), + new Contact("+44 1234", "jane@demo.dev", "London"), List.of()); + assertThat(id.tagline()).isEmpty(); + } + + @Test + void contactAndLinksAreExposedThroughTheContract() { + PartyIdentity id = sample("Engineer"); + assertThat(id.contact().email()).isEqualTo("jane@demo.dev"); + assertThat(id.links()).hasSize(1); + } +} diff --git a/src/test/java/com/demcha/compose/document/templates/cv/v2/widgets/WidgetSmokeTest.java b/src/test/java/com/demcha/compose/document/templates/cv/v2/widgets/WidgetSmokeTest.java index 6ca9cc9f7..62dbe8ea3 100644 --- a/src/test/java/com/demcha/compose/document/templates/cv/v2/widgets/WidgetSmokeTest.java +++ b/src/test/java/com/demcha/compose/document/templates/cv/v2/widgets/WidgetSmokeTest.java @@ -1,5 +1,11 @@ package com.demcha.compose.document.templates.cv.v2.widgets; +import com.demcha.compose.document.templates.core.identity.ContactLine; +import com.demcha.compose.document.templates.core.identity.Headline; +import com.demcha.compose.document.templates.core.identity.Masthead; +import com.demcha.compose.document.templates.core.identity.Subheadline; +import com.demcha.compose.document.templates.core.identity.SvgGlyph; + import com.demcha.compose.GraphCompose; import com.demcha.compose.document.api.DocumentSession; import com.demcha.compose.document.node.TextAlign; @@ -27,19 +33,19 @@ class WidgetSmokeTest { @Test void headline_variants_render_without_throwing() throws Exception { renderWithSection(section -> { - Headline.spacedCentered(section, name(), BrandTheme.boxedClassic()); + Headline.spacedCentered(section, name().full(), BrandTheme.boxedClassic()); }); renderWithSection(section -> { - Headline.uppercaseCentered(section, name(), BrandTheme.editorialBlue()); + Headline.uppercaseCentered(section, name().full(), BrandTheme.editorialBlue()); }); renderWithSection(section -> { - Headline.uppercaseLeftAligned(section, name(), BrandTheme.nordicClean()); + Headline.uppercaseLeftAligned(section, name().full(), BrandTheme.nordicClean()); }); renderWithSection(section -> { - Headline.rightAligned(section, name(), BrandTheme.boxedClassic()); + Headline.rightAligned(section, name().full(), BrandTheme.boxedClassic()); }); renderWithSection(section -> { - Headline.render(section, name(), BrandTheme.boxedClassic(), + Headline.render(section, name().full(), BrandTheme.boxedClassic(), TextAlign.LEFT, false); }); } @@ -183,7 +189,7 @@ void masthead_renders_without_throwing() throws Exception { @Test void widgets_work_against_modernProfessional_theme() throws Exception { BrandTheme theme = BrandTheme.modernProfessional(); - renderWithSection(section -> Headline.rightAligned(section, name(), theme)); + renderWithSection(section -> Headline.rightAligned(section, name().full(), theme)); renderWithSection(section -> ContactLine.rightAligned(section, identity(), theme)); renderWithSection(section -> SectionHeader.flat(section, "Summary", DocumentColor.rgb(0, 0, 0), theme));