diff --git a/README.md b/README.md index 898f80bd..7fcfafe9 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@

> **Release status** — -> 🟢 **Latest stable**: [v2.1.0](https://github.com/DemchaAV/GraphCompose/releases/tag/v2.1.0) — the **PowerPoint** release: `graph-compose-render-pptx` turns the same resolved layout into an editable deck — one page per slide, geometry-identical to the PDF, text and panels as native shapes. Ships as `@Beta`. **[What each backend supports ↓](docs/architecture/backend-capability-matrix.md)** +> 🟢 **Latest stable**: [v2.1.1](https://github.com/DemchaAV/GraphCompose/releases/tag/v2.1.1) — the **PowerPoint** release: `graph-compose-render-pptx` turns the same resolved layout into an editable deck — one page per slide, geometry-identical to the PDF, text and panels as native shapes. Ships as `@Beta`. **[What each backend supports ↓](docs/architecture/backend-capability-matrix.md)** >  ·  ⬆️ **Upgrading from 1.x?** `graph-compose` stays a drop-in for PDF with no code change; see the [2.0 modules migration guide](./docs/migration/v2.0.0-modules.md) >  ·  See [API stability policy](./docs/api-stability.md) for tier definitions. diff --git a/assets/readme/examples/engine-deck-v2.pdf b/assets/readme/examples/engine-deck-v2.pdf index f04be863..ede78caf 100644 Binary files a/assets/readme/examples/engine-deck-v2.pdf and b/assets/readme/examples/engine-deck-v2.pdf differ diff --git a/assets/readme/examples/engine-deck.pdf b/assets/readme/examples/engine-deck.pdf index 1738c367..6477ea93 100644 Binary files a/assets/readme/examples/engine-deck.pdf and b/assets/readme/examples/engine-deck.pdf differ diff --git a/examples/src/main/java/com/demcha/examples/flagships/EngineDeckExample.java b/examples/src/main/java/com/demcha/examples/flagships/EngineDeckExample.java index 112d9149..4448b26c 100644 --- a/examples/src/main/java/com/demcha/examples/flagships/EngineDeckExample.java +++ b/examples/src/main/java/com/demcha/examples/flagships/EngineDeckExample.java @@ -47,6 +47,7 @@ import com.demcha.compose.document.svg.SvgIcon; import com.demcha.compose.font.FontName; import com.demcha.examples.support.ExampleOutputPaths; +import com.demcha.examples.support.ExampleVersion; import java.awt.image.BufferedImage; import java.io.IOException; @@ -112,7 +113,7 @@ public final class EngineDeckExample { * filtering (e.g. straight from an IDE), so the banner never prints the raw * {@code @…@} token. */ - private static final String VERSION; + private static final String VERSION = ExampleVersion.withoutQualifier(); private static final String CODENAME; static { @@ -122,9 +123,8 @@ public final class EngineDeckExample { banner.load(in); } } catch (IOException ignored) { - // Missing/unreadable metadata falls through to the defaults below. + // Missing/unreadable metadata falls through to the default below. } - VERSION = resolved(banner.getProperty("version"), "dev"); CODENAME = resolved(banner.getProperty("codename"), ""); } @@ -411,10 +411,10 @@ private static DocumentNode brandLine() { /** Version pill ("v1.8.0") with the codename centred beside it as a tag. */ private static DocumentNode versionBlock() { - // Show the base version only: a dev/pre-release qualifier ("2.0.0-SNAPSHOT", - // "2.0.0-beta.1") is wider than the 96pt pill, and the engine wraps long - // tokens at their "." / "-" seams — the pill would break onto two lines. - String pillVersion = VERSION.replaceFirst("-.*$", ""); + // VERSION already carries no qualifier: one would be wider than the 96pt + // pill, and the engine wraps long tokens at their "." / "-" seams, so the + // pill would break onto two lines. + String pillVersion = VERSION; DocumentNode pill = new ShapeContainerBuilder().name("VerPill") .roundedRect(96, 30, 8).fillColor(VIOLET_DEEP) .center(new ParagraphBuilder().text("v" + pillVersion) diff --git a/examples/src/main/java/com/demcha/examples/flagships/EngineDeckV2Example.java b/examples/src/main/java/com/demcha/examples/flagships/EngineDeckV2Example.java index 26d454be..e28d4e91 100644 --- a/examples/src/main/java/com/demcha/examples/flagships/EngineDeckV2Example.java +++ b/examples/src/main/java/com/demcha/examples/flagships/EngineDeckV2Example.java @@ -113,7 +113,7 @@ public final class EngineDeckV2Example { private static final DocumentColor PALE_BLUE = DocumentColor.rgb(232, 243, 255); private static final DocumentColor PALE_MINT = DocumentColor.rgb(230, 249, 242); - private static final String VERSION = ExampleVersion.current(); + private static final String VERSION = ExampleVersion.withoutQualifier(); /** * The {@code major.minor} of {@link #VERSION}, for the banner's prose labels. diff --git a/examples/src/main/java/com/demcha/examples/support/ExampleVersion.java b/examples/src/main/java/com/demcha/examples/support/ExampleVersion.java index 76003677..1bf39522 100644 --- a/examples/src/main/java/com/demcha/examples/support/ExampleVersion.java +++ b/examples/src/main/java/com/demcha/examples/support/ExampleVersion.java @@ -44,6 +44,22 @@ public static String currentLine() { return majorMinor(CURRENT); } + /** + * {@link #current()} without any pre-release qualifier: {@code "2.1.1"} for + * {@code "2.1.1-SNAPSHOT"}. + * + *

Example documents are regenerated whenever their content changes, not + * only at a release, so between cuts the reactor version carries a + * {@code -SNAPSHOT} suffix. Rendering that suffix publishes a coordinate + * nobody can resolve, and the committed decks did exactly that after an + * off-cycle refresh. Anything a reader sees goes through here.

+ * + * @return the version up to the first {@code -} + */ + public static String withoutQualifier() { + return CURRENT.replaceFirst("-.*$", ""); + } + /** * Reduces a version to its {@code major.minor} prefix. * diff --git a/examples/src/test/java/com/demcha/examples/support/ExampleVersionTest.java b/examples/src/test/java/com/demcha/examples/support/ExampleVersionTest.java new file mode 100644 index 00000000..47c28b36 --- /dev/null +++ b/examples/src/test/java/com/demcha/examples/support/ExampleVersionTest.java @@ -0,0 +1,38 @@ +package com.demcha.examples.support; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Guards the version string the published example documents render. + * + *

Example PDFs are regenerated whenever their content changes, not only at a + * release, so between cuts the reactor version carries {@code -SNAPSHOT}. That + * suffix reached the committed decks once already, which meant the README-linked + * asset advertised a coordinate nobody could resolve. The strip lived privately + * in one deck and the other never inherited it; it is shared now, and this is + * what keeps a future caller from reaching for {@code current()} by habit.

+ */ +class ExampleVersionTest { + + @Test + void theRenderedVersionCarriesNoPreReleaseQualifier() { + assertThat(ExampleVersion.withoutQualifier()) + .describedAs("published examples must not render a -SNAPSHOT or -rc coordinate") + .doesNotContain("-"); + } + + @Test + void itKeepsTheReleaseDigitsIntact() { + assertThat(ExampleVersion.withoutQualifier()) + .describedAs("stripping the qualifier must not eat the version itself") + .isEqualTo(ExampleVersion.current().replaceFirst("-.*$", "")); + } + + @Test + void theLineIsTheLeadingMajorMinor() { + assertThat(ExampleVersion.majorMinor("2.1.1-SNAPSHOT")).isEqualTo("2.1"); + assertThat(ExampleVersion.majorMinor("dev")).isEqualTo("dev"); + } +} diff --git a/web/showcase/pdf/flagships/default/engine-deck-v2.pdf b/web/showcase/pdf/flagships/default/engine-deck-v2.pdf index f04be863..ede78caf 100644 Binary files a/web/showcase/pdf/flagships/default/engine-deck-v2.pdf and b/web/showcase/pdf/flagships/default/engine-deck-v2.pdf differ diff --git a/web/showcase/pdf/flagships/default/engine-deck.pdf b/web/showcase/pdf/flagships/default/engine-deck.pdf index 1738c367..6477ea93 100644 Binary files a/web/showcase/pdf/flagships/default/engine-deck.pdf and b/web/showcase/pdf/flagships/default/engine-deck.pdf differ