diff --git a/CHANGELOG.md b/CHANGELOG.md index f5aaaca2..782755d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -265,6 +265,16 @@ PDF `GoTo` actions. External links are unchanged. in the PDF backend. `PdfVisualRegression` also gains direct `renderPages(session)` / `assertMatchesBaseline(name, session)` overloads on the same path. +### Deprecations + +- **`templates.api.CoverLetterTemplate`** marked `@Deprecated(forRemoval = true)`. + Nothing implements it — the layered cover-letter presets implement the generic + `DocumentTemplate` seam instead. Removed in 2.0. +- **`cv.v2.components.HeadlineRenderer` / `ContactRenderer` / `BannerRenderer`** + (already-deprecated pre-widgets shims) are now `forRemoval` — use the + `cv.v2.widgets` `Headline` / `ContactLine` / `SectionHeader` widgets instead. + Removed in 2.0. + ### Documentation - New runnable flagship example diff --git a/docs/adr/0011-templates-v2-architecture.md b/docs/adr/0011-templates-v2-architecture.md index 90ba8a34..c2171d5f 100644 --- a/docs/adr/0011-templates-v2-architecture.md +++ b/docs/adr/0011-templates-v2-architecture.md @@ -206,10 +206,10 @@ references. The reopen made an explicit trade-off: switch to the new factory (see migration table in `CHANGELOG.md` and `docs/roadmaps/migration-v1-5-to-v1-6.md`). - **Cinematic V2 templates remain.** `InvoiceTemplateV2` / - `ProposalTemplateV2` / `WeeklyScheduleTemplateV1` / - `BuiltInCvTemplateSupport` stay in `templates/builtins/`. The - builtins folder is not yet empty; final cleanup happens once - `ModernInvoice` / `ModernProposal` close cinematic feature parity. + `ProposalTemplateV2` / `WeeklyScheduleTemplateV1` stay in + `templates/builtins/`. The builtins folder is not yet empty; final + cleanup happens once `ModernInvoice` / `ModernProposal` close + cinematic feature parity. - **`templates/data/` is partially deferred.** `data/cv/CvDocumentSpec.java` and `data/coverletter/CoverLetterDocumentSpec.java` are dead code referenced only by tests; `data/invoice/*` / diff --git a/docs/api-stability.md b/docs/api-stability.md index cf9198e1..619406a8 100644 --- a/docs/api-stability.md +++ b/docs/api-stability.md @@ -177,6 +177,8 @@ window starts, and its `Status` flips to `deprecated 1.x`. | Element | Tier now | Status | Why the 1.x shape is a compromise | 2.0 action | ADR | Issue | |---|---|---|---|---|---|---| | `DocumentSession.pageMargins(List)` / `PageMarginRule` | Stable | planned | Per-page margins resolve a block's content width by the page it *begins* on (the engine measures each block once, before pagination). A margin that changes the content width therefore does not re-wrap a block mid-flow across a page boundary. | Revisit a page-aware per-line/per-fragment width model so a block can re-wrap when it crosses a margin boundary, if demand warrants. | — | — | +| `templates.api.CoverLetterTemplate` | Stable | deprecated 1.9 | Orphan interface — nothing implements it; cover-letter presets implement the generic `DocumentTemplate` seam. | Remove; callers implement `DocumentTemplate`. | — | — | +| `templates.cv.v2.components.HeadlineRenderer` / `ContactRenderer` / `BannerRenderer` | Stable | deprecated 1.9 | Pre-widgets delegating shims superseded by the `cv.v2.widgets` `Headline` / `ContactLine` / `SectionHeader` widgets; no callers. | Remove; use the widgets. | — | — | --- diff --git a/docs/architecture/package-map.md b/docs/architecture/package-map.md index fcf77042..cdebd0d7 100644 --- a/docs/architecture/package-map.md +++ b/docs/architecture/package-map.md @@ -72,7 +72,6 @@ intended. | `com.demcha.compose.document.templates.blocks` | Templates-v2 module-body block kinds — `ParagraphBlock`, `BulletListBlock`, `NumberedListBlock`, `IndentedBlock`, `KeyValueBlock`, `MultiParagraphBlock`, `EducationBlock`, `WorkHistoryBlock`. | A block declares *what* content appears; the renderer expands it per active theme / tokens. | | `com.demcha.compose.document.templates.decorations` | Templates-v2 decoration library — `Divider`, `AccentStrip`, `Spacer` (Panel / Banner / Ornament reserved). | First-class artefacts any preset can attach; not baked into composer logic. | | `com.demcha.compose.document.templates.widgets` | Shared visual widgets usable by every family — `CardWidget`, `TableWidget`, `TimelineAxisWidget`. | Keep generic (no CV-only assumptions) so invoice / proposal / cover-letter can reuse them. | -| `com.demcha.compose.document.templates.tables` | **Reserved** for Templates-v2 reusable table styles (zebra / minimal-grid / borderless / accent-header / financial). Currently `package-info.java` only — no classes yet (Phase F). | Land table *styles* here, independent of the data they render. | > **Preset families.** Concrete document families live under `…templates.` — `cv`, `coverletter`, `invoice`, `proposal`, `schedule`. CV and cover letter additionally ship a layered v2 surface (`…cv.v2.*` / `…coverletter.v2.*`: `data` / `theme` / `components` / `widgets` / `presets`). These per-family packages are documented by the template guides rather than enumerated here — see [which-template-system.md](../templates/which-template-system.md) for the status matrix and [templates/v2-layered/](../templates/v2-layered/README.md) for the layered architecture. diff --git a/examples/src/main/java/com/demcha/examples/support/ExampleDataFactory.java b/examples/src/main/java/com/demcha/examples/support/ExampleDataFactory.java index 7037eb39..8d1581dc 100644 --- a/examples/src/main/java/com/demcha/examples/support/ExampleDataFactory.java +++ b/examples/src/main/java/com/demcha/examples/support/ExampleDataFactory.java @@ -1,18 +1,6 @@ package com.demcha.examples.support; -import com.demcha.compose.document.templates.blocks.BulletListBlock; -import com.demcha.compose.document.templates.blocks.EducationBlock; -import com.demcha.compose.document.templates.blocks.IndentedBlock; -import com.demcha.compose.document.templates.blocks.KeyValueBlock; -import com.demcha.compose.document.templates.blocks.MultiParagraphBlock; -import com.demcha.compose.document.templates.blocks.ParagraphBlock; -import com.demcha.compose.document.templates.blocks.WorkHistoryBlock; -import com.demcha.compose.document.templates.coverletter.spec.CoverLetterHeader; -import com.demcha.compose.document.templates.coverletter.spec.CoverLetterSpec; import com.demcha.compose.document.templates.coverletter.v2.data.CoverLetterDocument; -import com.demcha.compose.document.templates.cv.spec.CvHeader; -import com.demcha.compose.document.templates.cv.spec.CvModule; -import com.demcha.compose.document.templates.cv.spec.CvSpec; import com.demcha.compose.document.templates.cv.v2.data.CvDocument; import com.demcha.compose.document.templates.cv.v2.data.CvIdentity; import com.demcha.compose.document.templates.cv.v2.data.CvSkill; @@ -262,195 +250,6 @@ private static ScheduleSlot slot(String start, String end) { return ScheduleSlot.of(start, end); } - // -- Templates v2 sample data --------------------------------------- - - /** - * Returns a sample {@code CvSpec} for the Templates v2 CV pipeline. - * Mirrors the content of {@link #sampleCv()} in the v2 spec shape - * (immutable records, semantic Block kinds, markdown-aware - * paragraph text). - * - * @return sample v2 CV spec - */ - public static CvSpec sampleCvSpecV2() { - return CvSpec.builder() - .header(sampleCvHeaderV2()) - .module(CvModule.of("Professional Summary", - new ParagraphBlock( - "Platform engineer with **10+ years** building resilient " - + "document-generation pipelines, layout engines, and " - + "developer-facing template systems. Specialised in " - + "high-throughput PDF rendering, semantic authoring " - + "DSLs, and turning brittle production-ops scripts " - + "into typed, snapshot-tested libraries that scale."))) - .module(CvModule.of("Technical Skills", - new BulletListBlock(List.of( - "**Languages:** Java 21, Kotlin, Groovy, Python, SQL", - "**Document & Print:** PDFBox, Apache POI (DOCX/XLSX), iText, " - + "PostScript, ICC colour profiles, font metrics", - "**Layout engines:** Custom DSL design, semantic layout trees, " - + "pagination, snapshot testing, visual regression", - "**Build & infrastructure:** Maven, Gradle, GitHub Actions, " - + "JitPack, Docker, JMH benchmarking", - "**Testing:** JUnit 5, AssertJ, PDFBox-based PNG diff, " - + "layout-graph snapshots, mutation testing (Pitest)", - "**Distribution:** Maven Central, Sonatype OSSRH, GPG signing, " - + "JitPack, semantic versioning discipline")))) - .module(CvModule.of("Education & Certifications", - // Preferred: structured EducationBlock with - // explicit (degree, institution, year, details) - // fields. BoxedSections renders each item with - // the same structured layout as Professional - // Experience — degree bold left, year right, - // institution italic on the next line, and - // details as a full-width paragraph below. - new EducationBlock(List.of( - new EducationBlock.Item( - "MSc Computer Science", - "University of Manchester", - "2021", - "Distinction. Thesis: *Composable layout primitives " - + "for deterministic document rendering*."), - new EducationBlock.Item( - "BSc Software Engineering", - "Imperial College London", - "2019", - "First-class honours. Specialisation in compilers and " - + "static analysis."), - new EducationBlock.Item( - "Oracle Java Certification", - "Professional track", - "2023", - "Java 17 platform deep-dive: records, sealed types, " - + "pattern matching, virtual threads."))))) - .module(CvModule.of("Projects", - new BulletListBlock(List.of( - "**GraphCompose (Java 21, PDFBox, Maven, JMH)** - " - + "Declarative Java PDF layout engine. Semantic DSL, " - + "slot-based templates, snapshot testing. Powers " - + "production CV / invoice / proposal pipelines for " - + "hiring tools and billing systems. *(Open source)*", - "**Template Studio (Kotlin, Compose Desktop, PDFBox PNG diff)** - " - + "Internal tool for evaluating CV, proposal, and " - + "invoice output across 14 design presets. PNG " - + "diffing, side-by-side layout, baseline freezing.", - "**LayoutLint (Java 21, JavaParser, Spoon)** - Static analyser " - + "that flags fragile authoring patterns (deeply " - + "nested rows, untyped offsets, implicit page " - + "breaks) before they ship to production.", - "**ChromeForge (Java, GraphCompose, Pandoc bridge)** - " - + "Editorial-magazine document toolkit built on " - + "GraphCompose: cinematic covers, pull quotes, " - + "multi-column flow, sidebar callouts.")))) - .module(CvModule.of("Professional Experience", - // Preferred: structured WorkHistoryBlock with - // explicit (title, organisation, date, - // description) fields. BoxedSections renders - // each item as a structured row (title bold - // left, date right, organisation italic on the - // next line, description full-width below) - // without falling back to the legacy - // pipe-separated string parser. - new WorkHistoryBlock(List.of( - new WorkHistoryBlock.Item( - "Senior Platform Engineer", - "Northwind Systems", - "2024-Present", - "Led the reusable document-generation platform serving " - + "billing, hiring, and reporting flows across " - + "**8 product teams**. Reduced template maintenance " - + "time by **70%** by retiring per-team PDF scripts " - + "in favour of one canonical engine."), - new WorkHistoryBlock.Item( - "Software Engineer", - "BrightLeaf Labs", - "2021-2024", - "Built backend services and production document rendering " - + "pipelines processing **2M+ documents per month**. " - + "Drove the migration from iText to a custom layout " - + "engine, eliminating licensing risk and cutting " - + "p99 render latency from 1.4s to 380ms."), - new WorkHistoryBlock.Item( - "Backend Engineer", - "Helix Print Co", - "2019-2021", - "Maintained a high-volume invoice-printing service " - + "(15M PDFs/year) and authored the compliance test " - + "harness that gated every template change."))))) - .module(CvModule.of("Additional Information", - new KeyValueBlock(List.of( - new KeyValueBlock.Entry("Languages", - "English (Fluent), German (Intermediate), Spanish (Basic)"), - new KeyValueBlock.Entry("Work Eligibility", - "Eligible to work in the UK and the EU"), - new KeyValueBlock.Entry("Open Source", - "Maintainer of GraphCompose. Regular contributor to PDFBox issue triage."), - new KeyValueBlock.Entry("Speaking", - "JVM Summit 2024, Devoxx UK 2025 — both on declarative document layout."))))) - .build(); - } - - /** - * Returns a sample {@code CvHeader} for the Templates v2 CV - * pipeline. - * - * @return sample v2 CV header - */ - public static CvHeader sampleCvHeaderV2() { - return CvHeader.builder() - .name("Jordan Rivera") - .jobTitle("Backend Java Developer") - .address("London, UK") - .phone("+44 20 5555 1000") - .email("jordan.rivera@example.com") - .link("LinkedIn", "https://linkedin.com/in/jordan-rivera-demo") - .link("GitHub", "https://github.com/jrivera-demo") - .build(); - } - - /** - * Returns a sample {@code CoverLetterSpec} for the Templates v2 - * cover-letter pipeline. - * - * @return sample v2 cover letter spec - */ - public static CoverLetterSpec sampleCoverLetterSpecV2() { - return CoverLetterSpec.builder() - .header(sampleCoverLetterHeaderV2()) - .greeting("Dear Hiring Team at **Northwind Systems**,") - .paragraph("I am excited to share my interest in the Senior " - + "Platform Engineer role. My recent work has focused " - + "on building **reusable document-generation systems** " - + "that balance public API design, render quality, and " - + "maintainability.") - .paragraph("I enjoy translating fuzzy workflow requirements into " - + "clear template abstractions, reliable test coverage, " - + "and examples that make adoption easier for the rest " - + "of the team.") - .paragraph("I would welcome the opportunity to bring that same " - + "mix of engineering rigor and product thinking to your " - + "platform group.") - .closing("Sincerely, *Artem Demchyshyn*") - .build(); - } - - /** - * Returns a sample {@code CoverLetterHeader} mirroring the v2 CV - * header so a writer's CV and cover letter ship as a matched set. - * - * @return sample v2 cover letter header - */ - public static CoverLetterHeader sampleCoverLetterHeaderV2() { - return CoverLetterHeader.builder() - .name("Jordan Rivera") - .address("London, UK") - .phone("+44 20 5555 1000") - .email("jordan.rivera@example.com") - .link("LinkedIn", "https://linkedin.com/in/jordan-rivera-demo") - .link("GitHub", "https://github.com/jrivera-demo") - .build(); - } - // -- Templates v2 (cv/v2) sample data ------------------------------ /** diff --git a/src/main/java/com/demcha/compose/document/templates/api/CoverLetterTemplate.java b/src/main/java/com/demcha/compose/document/templates/api/CoverLetterTemplate.java index 29cb0c22..1e6abe51 100644 --- a/src/main/java/com/demcha/compose/document/templates/api/CoverLetterTemplate.java +++ b/src/main/java/com/demcha/compose/document/templates/api/CoverLetterTemplate.java @@ -10,25 +10,13 @@ * semantic blocks into a caller-owned {@link DocumentSession}. Implementations * are usually immutable value objects configured by a theme.

* - *
{@code
- * CoverLetterTemplate template = new CoverLetterTemplateV1();
- * CoverLetterDocumentSpec coverLetter = CoverLetterDocumentSpec.builder()
- *         .header(header -> header
- *                 .name("Artem Demchyshyn")
- *                 .email("artem@demo.dev", "artem@demo.dev")
- *                 .linkedIn("https://linkedin.com/in/graphcompose", "LinkedIn"))
- *         .letter(letterBody)
- *         .job(job -> job
- *                 .company("Northwind Systems")
- *                 .title("Platform Engineer"))
- *         .build();
- *
- * try (DocumentSession document = GraphCompose.document(Path.of("cover-letter.pdf")).create()) {
- *     template.compose(document, coverLetter);
- *     document.buildPdf();
- * }
- * }
+ * @deprecated since 1.9.0; removed in 2.0. No type implements this interface — + * the layered cover-letter presets implement the generic + * {@link DocumentTemplate} seam + * ({@code DocumentTemplate}) instead. + * Implement {@code DocumentTemplate}. */ +@Deprecated(since = "1.9.0", forRemoval = true) public interface CoverLetterTemplate { /** diff --git a/src/main/java/com/demcha/compose/document/templates/builtins/BuiltInCvTemplateSupport.java b/src/main/java/com/demcha/compose/document/templates/builtins/BuiltInCvTemplateSupport.java deleted file mode 100644 index 8764458b..00000000 --- a/src/main/java/com/demcha/compose/document/templates/builtins/BuiltInCvTemplateSupport.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.demcha.compose.document.templates.builtins; - -import com.demcha.compose.document.api.DocumentSession; -import com.demcha.compose.document.templates.data.cv.CvDocumentSpec; -import com.demcha.compose.document.templates.support.common.SessionTemplateComposeTarget; -import com.demcha.compose.document.templates.support.common.TemplateComposeTarget; -import com.demcha.compose.document.templates.support.common.TemplateLifecycleLog; - -final class BuiltInCvTemplateSupport { - private BuiltInCvTemplateSupport() { - } - - static void compose(String templateId, DocumentSession document, CvDocumentSpec documentSpec, Renderer renderer) { - long startNanos = TemplateLifecycleLog.start(templateId, documentSpec); - try { - renderer.compose(new SessionTemplateComposeTarget(document), documentSpec); - TemplateLifecycleLog.success(templateId, documentSpec, startNanos); - } catch (RuntimeException | Error ex) { - TemplateLifecycleLog.failure(templateId, documentSpec, startNanos, ex); - throw ex; - } - } - - static void composeDirect(String templateId, DocumentSession document, CvDocumentSpec documentSpec, DocumentRenderer renderer) { - long startNanos = TemplateLifecycleLog.start(templateId, documentSpec); - try { - renderer.compose(document, documentSpec); - TemplateLifecycleLog.success(templateId, documentSpec, startNanos); - } catch (RuntimeException | Error ex) { - TemplateLifecycleLog.failure(templateId, documentSpec, startNanos, ex); - throw ex; - } - } - - @FunctionalInterface - interface Renderer { - void compose(TemplateComposeTarget target, CvDocumentSpec documentSpec); - } - - @FunctionalInterface - interface DocumentRenderer { - void compose(DocumentSession document, CvDocumentSpec documentSpec); - } -} diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/AUTHORS.md b/src/main/java/com/demcha/compose/document/templates/cv/v2/AUTHORS.md index f4d591de..4ce07dbc 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/AUTHORS.md +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/AUTHORS.md @@ -88,9 +88,8 @@ CvTheme theme = new CvTheme( DocumentTemplate template = BoxedSections.create(theme); ``` -That's it. No renderer code changes. `RowRenderer` and -`ContactRenderer` read these strings from `theme.decoration()` on every -call. +That's it. No renderer code changes. `RowRenderer` and the `ContactLine` +widget read these strings from `theme.decoration()` on every call. **Why the second-line indent is its own token:** when a stacked row (Projects style) wraps to a second line, the body text must align under @@ -149,7 +148,7 @@ CvTheme compactTheme = new CvTheme( --- -## Recipe 4 — write a new preset (reuse existing renderers) +## Recipe 4 — write a new preset (reuse existing widgets) You want a different page layout — no banner panels, section titles underlined instead. Same data, same components, different composition. @@ -181,15 +180,15 @@ public final class MyPreset { .name("MyRoot") .spacing(theme.spacing().pageFlowSpacing()) .addSection("Headline", s -> - HeadlineRenderer.render(s, doc.identity().name(), theme)) + Headline.spacedCentered(s, doc.identity().name(), theme)) .addSection("Contact", s -> - ContactRenderer.render(s, doc.identity(), theme)); + ContactLine.centered(s, doc.identity(), theme)); for (int i = 0; i < doc.sections().size(); i++) { final CvSection sec = doc.sections().get(i); final int idx = i; - // Replace BannerRenderer with whatever title style you want. + // Replace SectionHeader.banner(...) with whatever title style you want. pageFlow.addSection("Title_" + idx, host -> { /* custom title rendering */ }); @@ -203,8 +202,9 @@ public final class MyPreset { } ``` -The renderers in `components/` are all `static` — your preset just -calls them. No inheritance, no instance state to manage. +The widgets in `widgets/` and the section renderers in `components/` are +all `static` — your preset just calls them. No inheritance, no instance +state to manage. --- diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/components/BannerRenderer.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/components/BannerRenderer.java index 7f85c757..79782a47 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/components/BannerRenderer.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/components/BannerRenderer.java @@ -13,7 +13,7 @@ * delegating shim so v2 code written before the widgets layer keeps * compiling unchanged. */ -@Deprecated +@Deprecated(forRemoval = true) public final class BannerRenderer { private BannerRenderer() { 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 0af091a6..2c091171 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 @@ -13,7 +13,7 @@ * delegating shim so v2 code written before the widgets layer keeps * compiling unchanged. */ -@Deprecated +@Deprecated(forRemoval = true) public final class ContactRenderer { private ContactRenderer() { 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 915691cc..7da0ccf9 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 @@ -13,7 +13,7 @@ * centred-spaced-caps form. Kept as a thin delegating shim so v2 * code written before the widgets layer keeps compiling unchanged. */ -@Deprecated +@Deprecated(forRemoval = true) public final class HeadlineRenderer { private HeadlineRenderer() { 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 db347515..2173828c 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 @@ -27,7 +27,8 @@ * compositional exercise. The pieces that change:

* *
    - *
  • {@link com.demcha.compose.document.templates.cv.v2.components.BannerRenderer} + *
  • The centred banner section header + * ({@link com.demcha.compose.document.templates.cv.v2.widgets.SectionHeader}) * is not used.
  • *
  • A small inline paragraph + an {@code accentBottom} draws the * section title.
  • diff --git a/src/main/java/com/demcha/compose/document/templates/cv/v2/theme/CvDecoration.java b/src/main/java/com/demcha/compose/document/templates/cv/v2/theme/CvDecoration.java index 29888cd0..39ab54ca 100644 --- a/src/main/java/com/demcha/compose/document/templates/cv/v2/theme/CvDecoration.java +++ b/src/main/java/com/demcha/compose/document/templates/cv/v2/theme/CvDecoration.java @@ -15,7 +15,7 @@ * *

    Decorations live in the {@code theme} layer because they are * cosmetic. They are not renderer constants: - * components like {@code RowRenderer} and {@code ContactRenderer} + * components like {@code RowRenderer} and the {@code ContactLine} widget * read these strings from the active theme on every call.

    * * @param bulletGlyph glyph + trailing space used by row styles diff --git a/src/main/java/com/demcha/compose/document/templates/tables/package-info.java b/src/main/java/com/demcha/compose/document/templates/tables/package-info.java deleted file mode 100644 index ab73b08b..00000000 --- a/src/main/java/com/demcha/compose/document/templates/tables/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Templates v2 reusable table styles — zebra, minimal grid, borderless, accent header, financial. - * - *

    Table styles capture the visual presentation of a table independently - * of the data it carries. An invoice template can pick a financial style - * with totals; a CV technical-skills table can pick a zebra style; a - * proposal can pick borderless. The same data can render with any style.

    - * - *

    This package will be populated during Phase F of the Templates v2 - * migration with at least:

    - * - *
      - *
    • {@code presets/ZebraTable} — alternating row backgrounds.
    • - *
    • {@code presets/MinimalGridTable} — thin grid lines, no fill.
    • - *
    • {@code presets/BorderlessTable} — no grid, columns separated by spacing only.
    • - *
    • {@code presets/AccentHeaderTable} — coloured header row, plain body.
    • - *
    • {@code presets/FinancialTable} — column alignment for currency, - * totals row, optional tax row (used by invoice templates).
    • - *
    • {@code TableStyleBuilder} — fully custom table styles.
    • - *
    - * - * @since 1.6.0 - */ -package com.demcha.compose.document.templates.tables;