Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 40 additions & 32 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,49 @@
All notable changes to GraphCompose are documented here. Versions
follow semantic versioning; release dates are ISO 8601.

## v2.1.0 — in progress
## v2.1.0 — Planned

### Public API

- **Keep a heading with its content** — `SectionBuilder.keepWithNext()`. A section
marked keep-with-next is never left stranded as the last block on a page apart from
the content it introduces: when the section plus the first slice of the following
block would overflow the remaining page space (but fit on a fresh page), the section
relocates to the next page so the heading stays glued to its body. The first slice is
a paragraph's first line, a table's repeated header rows plus first body row, or a
list's first item, so the rule holds whether the following block is atomic or a
page-spanning table or list. Distinct from `keepTogether()`, which relocates a
*whole* block — keep-with-next binds only the start of the following block, the right
tool for a boxed section title above a long, page-spanning body. Inert when nothing
follows (a trailing heading is never moved) and best-effort when the heading plus the
first slice cannot share a page. Default off, so layouts that do not opt in are
unchanged.
- `LineBuilder.keepWithNext()` — the line counterpart of
`SectionBuilder.keepWithNext()`, so a full-width header rule joins its banner's
keep-with-next run and the whole title block (rule + banner + rule) relocates
together instead of the banner stranding apart from its rules or its body.
- Keep-with-next surfaces on the node model as well: `DocumentNode.keepWithNext()`
is a new default method (existing implementations keep the `false` default and
need no change), and `SectionNode` and `LineNode` each gain a trailing
`keepWithNext` record component. Constructor calls are unaffected — both records
keep an overload at the previous argument count that defaults the flag to
`false` — but the canonical component count changed (`SectionNode` 13 → 14,
`LineNode` 17 → 18), so a **record deconstruction pattern** written against the
2.0.0 component list must add the new binding to compile.
- **Single-column CV presets no longer orphan a section title.** Every preset whose
sections flow down the page — BoxedSections, MinimalUnderlined, ModernProfessional,
Executive, CenteredHeadline, BlueBanner, EditorialBlue, and ClassicSerif — keeps a
section heading with the first line of its body across a page break: a standalone
header section binds to the following body section (a multi-node rule + banner + rule
group binds as one run), and a combined header+body module keeps the heading in a
nested keep-with-next group — including Panel's full-width Profile card, whose header
now stays with the summary if a long profile splits the card. Multi-column presets
place their sections in fixed columns that do not paginate, so no heading can strand
there.
- **The Modern Proposal template no longer orphans a section heading.** Its flowing
section bodies, the Timeline and Investment tables, and the Acceptance terms each keep
their title with the first line of the block it introduces across a page break — each
title now renders in its own keep-with-next section rather than a bare paragraph.
- **CV entry titles and subtitles accept inline `[text](url)` links.** In the layered
CV presets, a `[label](url)` in an experience/education entry title or subtitle now
renders as a clickable hyperlink — the same inline-Markdown convention already used
Expand Down Expand Up @@ -303,37 +342,6 @@ for this cycle.

### Public API

- **Keep a heading with its content** — `SectionBuilder.keepWithNext()`. A section
marked keep-with-next is never left stranded as the last block on a page apart from
the content it introduces: when the section plus the first slice of the following
block would overflow the remaining page space (but fit on a fresh page), the section
relocates to the next page so the heading stays glued to its body. The first slice is
a paragraph's first line, a table's repeated header rows plus first body row, or a
list's first item, so the rule holds whether the following block is atomic or a
page-spanning table or list. Distinct from `keepTogether()`, which relocates a
*whole* block — keep-with-next binds only the start of the following block, the right
tool for a boxed section title above a long, page-spanning body. Inert when nothing
follows (a trailing heading is never moved) and best-effort when the heading plus the
first slice cannot share a page. Default off, so layouts that do not opt in are
unchanged.
- `LineBuilder.keepWithNext()` — the line counterpart of
`SectionBuilder.keepWithNext()`, so a full-width header rule joins its banner's
keep-with-next run and the whole title block (rule + banner + rule) relocates
together instead of the banner stranding apart from its rules or its body.
- **Single-column CV presets no longer orphan a section title.** Every preset whose
sections flow down the page — BoxedSections, MinimalUnderlined, ModernProfessional,
Executive, CenteredHeadline, BlueBanner, EditorialBlue, and ClassicSerif — keeps a
section heading with the first line of its body across a page break: a standalone
header section binds to the following body section (a multi-node rule + banner + rule
group binds as one run), and a combined header+body module keeps the heading in a
nested keep-with-next group — including Panel's full-width Profile card, whose header
now stays with the summary if a long profile splits the card. Multi-column presets
place their sections in fixed columns that do not paginate, so no heading can strand
there.
- **The Modern Proposal template no longer orphans a section heading.** Its flowing
section bodies, the Timeline and Investment tables, and the Acceptance terms each keep
their title with the first line of the block it introduces across a page break — each
title now renders in its own keep-with-next section rather than a bare paragraph.
- **Reproducible PDF output** (`@Beta`). `PdfFixedLayoutBackend.builder().deterministic(true)`
(or `.deterministic(Instant)` for an explicit timestamp) pins the document
CreationDate / ModDate and derives the PDF `/ID` from the document metadata instead
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-build</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion bundle/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
graph-compose and graph-compose-templates dependencies below use
${project.version}, so they follow automatically.
-->
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>GraphCompose Bundle</name>
Expand Down
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-core</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>

<name>GraphCompose Core</name>
<description>A declarative layout engine for programmatic document generation, implemented primarily in Java. This is the lean engine coordinate; depend on the `graph-compose` artifact for the drop-in, PDF-capable install.</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ public LineBuilder fill() {
* {@link SectionBuilder#keepWithNext()}.
*
* @return this builder
* @since 2.0.0
* @since 2.1.0
*/
public LineBuilder keepWithNext() {
this.keepWithNext = true;
Expand All @@ -301,7 +301,7 @@ public LineBuilder keepWithNext() {
*
* @param value true to keep the line with the next block
* @return this builder
* @since 2.0.0
* @since 2.1.0
*/
public LineBuilder keepWithNext(boolean value) {
this.keepWithNext = value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public SectionBuilder keepTogether(boolean value) {
* nothing follows the section on the page.
*
* @return this builder
* @since 2.0.0
* @since 2.1.0
*/
public SectionBuilder keepWithNext() {
this.keepWithNext = true;
Expand All @@ -72,7 +72,7 @@ public SectionBuilder keepWithNext() {
*
* @param value true to keep the section with the first line of the next block
* @return this builder
* @since 2.0.0
* @since 2.1.0
*/
public SectionBuilder keepWithNext(boolean value) {
this.keepWithNext = value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ default List<LayoutFragment> emitOverlayFragments(PreparedNode<E> prepared,
*
* @param prepared prepared node whose first slice is being measured
* @return the first slice's height in points
* @since 2.0.0
* @since 2.1.0
*/
default double firstSliceHeight(PreparedNode<E> prepared) {
return prepared.measureResult().height();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ default boolean keepTogether() {
* siblings relocate together, with the break hoisted before the run.</p>
*
* @return true to keep this node with the first line of the following block
* @since 2.0.0
* @since 2.1.0
*/
default boolean keepWithNext() {
return false;
Expand Down
2 changes: 1 addition & 1 deletion coverage/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<parent>
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-build</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-build</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-build</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>
<packaging>pom</packaging>

<name>GraphCompose Build Aggregator</name>
Expand Down
2 changes: 1 addition & 1 deletion qa/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<parent>
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-build</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion render-docx/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
-->
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-render-docx</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>

<name>GraphCompose Render — DOCX</name>
<description>Semantic DOCX export backend for GraphCompose, backed by Apache POI.</description>
Expand Down
2 changes: 1 addition & 1 deletion render-pdf/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
-->
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-render-pdf</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>

<name>GraphCompose Render — PDF</name>
<description>The PDFBox-backed PDF render backend for GraphCompose.</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ public org.apache.pdfbox.pdmodel.PDPage documentPage(int localPageIndex) {
*
* @param alpha non-stroking alpha constant in {@code [0, 1]}
* @return shared graphics state owned by the current render pass
* @since 2.1.0
*/
public PDExtendedGraphicsState fillAlphaState(float alpha) {
return fillAlphaStates.computeIfAbsent(alpha, value -> {
Expand All @@ -139,6 +140,7 @@ public PDExtendedGraphicsState fillAlphaState(float alpha) {
*
* @param alpha stroking alpha constant in {@code [0, 1]}
* @return shared graphics state owned by the current render pass
* @since 2.1.0
*/
public PDExtendedGraphicsState strokeAlphaState(float alpha) {
return strokeAlphaStates.computeIfAbsent(alpha, value -> {
Expand Down
2 changes: 1 addition & 1 deletion render-pptx/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
-->
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-render-pptx</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>

<name>GraphCompose Render — PPTX</name>
<description>PPTX render backends for GraphCompose: the coordinate-exact fixed-layout backend (POI XSLF) and the slide-safe semantic export skeleton.</description>
Expand Down
2 changes: 1 addition & 1 deletion templates/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
-->
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-templates</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>

<name>GraphCompose Templates</name>
<description>Built-in CV, cover-letter, invoice, and proposal document templates for GraphCompose.</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public static void appendTrimmed(RichText rich, String text,
* @param text source string; null treated as empty
* @param baseStyle style applied to the transformed runs
* @param displayTransform transform applied to visible text (never the url)
* @since 2.1.0
*/
public static void appendTransformed(RichText rich, String text,
DocumentTextStyle baseStyle,
Expand All @@ -133,6 +134,7 @@ public static void appendTransformed(RichText rich, String text,
* @param rich target rich-text builder
* @param text source string; null treated as empty
* @param baseStyle style applied to the upper-cased runs
* @since 2.1.0
*/
public static void appendUpperCased(RichText rich, String text,
DocumentTextStyle baseStyle) {
Expand Down Expand Up @@ -180,6 +182,7 @@ public static void appendPlainIfPresent(RichText rich, String prefix,
* @param prefix separator prepended before the value (never a link)
* @param value source string; null treated as empty
* @param style style applied to the prefix and the value's plain runs
* @since 2.1.0
*/
public static void appendIfPresent(RichText rich, String prefix,
String value,
Expand Down
2 changes: 1 addition & 1 deletion testing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
-->
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose-testing</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>

<name>GraphCompose Testing</name>
<description>Consumer testing support for GraphCompose: layout-snapshot assertions and PDF visual regression.</description>
Expand Down
2 changes: 1 addition & 1 deletion wrapper/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
-->
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose</artifactId>
<version>2.0.1-SNAPSHOT</version>
<version>2.1.0-SNAPSHOT</version>

<name>GraphCompose</name>
<description>The graph-compose coordinate: a drop-in aggregator over graph-compose-core for a PDF-capable install.</description>
Expand Down
Loading