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
10 changes: 8 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ jobs:
# testing module + the engine test-jar on the classpath and so cannot
# live in the engine's own test scope). -am pulls the fonts / emoji
# upstreams; render-docx / bundle / examples / benchmarks are excluded.
run: ./mvnw -B -ntp -f aggregator/pom.xml clean verify -pl :graph-compose,:graph-compose-testing,:graph-compose-qa -am
run: ./mvnw -B -ntp -f aggregator/pom.xml clean verify -pl :graph-compose-core,:graph-compose-testing,:graph-compose-qa -am

- name: Generate Javadoc
# Run only on the baseline JDK — Javadoc output is identical
Expand Down Expand Up @@ -116,9 +116,15 @@ jobs:
# Central, so install it into the local repo before building examples.
run: ./mvnw -B -ntp -f emoji/pom.xml -DskipTests install

- name: Install root artifact
- name: Install root artifact (graph-compose-core)
run: ./mvnw -B -ntp -DskipTests install -pl .

- name: Install graph-compose (the compat wrapper, consumed by the examples module)
# examples depends on the graph-compose coordinate — the empty jar wrapper
# over graph-compose-core. Install it after the core so the examples build
# resolves it (and the engine classes transitively).
run: ./mvnw -B -ntp -f wrapper/pom.xml -DskipTests install

- name: Install graph-compose-render-docx (consumed by the examples module)
# The DOCX export example depends on the render-docx backend module, which
# is not on Central. Install it after the engine (its graph-compose
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ jobs:
CENTRAL_TOKEN: ${{ secrets.CENTRAL_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

- name: Publish graph-compose (compat wrapper) to Maven Central
# The empty jar that keeps the `graph-compose` coordinate a drop-in: it
# depends on graph-compose-core, resolved from the local repo installed by
# the engine (core) deploy above. Ships on the same v* tag, lockstep.
run: ./mvnw -B -ntp -f wrapper/pom.xml -P release -DskipTests -Dgpg.skip=false deploy
env:
CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
CENTRAL_TOKEN: ${{ secrets.CENTRAL_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

- name: Publish render-docx to Maven Central
# The semantic DOCX/PPTX backend, lockstep-versioned with the engine
# (ships on the same v* tag). graph-compose resolves from the local repo
Expand Down
21 changes: 11 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,17 @@ for this cycle.

### Packaging

- 2.0 splits the single `graph-compose` jar into modules: a lean core
(`graph-compose`), pluggable render backends (`graph-compose-render-pdf`,
`graph-compose-render-docx`), `graph-compose-templates`, and
`graph-compose-testing`, with render backends discovered via a `ServiceLoader`
SPI. The `graph-compose` artifact keeps its coordinate but no longer contains
the PDF backend or the templates — add `graph-compose-render-pdf` for PDF
output, or depend on `graph-compose-bundle` for a batteries-included coordinate
(core + render-pdf + templates + fonts + emoji). The optional
`graph-compose-fonts` and `graph-compose-emoji` artifacts are unchanged. Full
install guidance ships with 2.0.0.
- 2.0 splits the monolithic engine into modules. The engine now builds under a new
**`graph-compose-core`** coordinate, and the original **`graph-compose` coordinate
becomes a thin drop-in aggregator** that depends on `graph-compose-core` — so an
existing `graph-compose` dependency keeps compiling and rendering PDF unchanged.
Consumer-testing support (`graph-compose-testing`) and the semantic DOCX/PPTX
backend (`graph-compose-render-docx`) are already separate artifacts; the PDF
render backend and the built-in templates move into their own modules over the
rest of the 2.0 cycle, at which point `graph-compose` aggregates the PDF backend
and `graph-compose-core` becomes the lean, bring-your-own-backend coordinate. The
optional `graph-compose-fonts` / `graph-compose-emoji` artifacts are unchanged.
Full install guidance ships with 2.0.0.
- `graph-compose-render-docx` is now a separate artifact: the semantic DOCX/PPTX
backend and Apache POI leave the `graph-compose` jar. `DocxSemanticBackend` moves
to `com.demcha.compose.document.backend.semantic.docx` and `PptxSemanticBackend`
Expand Down
1 change: 1 addition & 0 deletions aggregator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
-->
<modules>
<module>..</module>
<module>../wrapper</module>
<module>../fonts</module>
<module>../emoji</module>
<module>../render-docx</module>
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<!-- The library under benchmark. -->
<dependency>
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose</artifactId>
<artifactId>graph-compose-core</artifactId>
<version>${graphcompose.version}</version>
</dependency>

Expand All @@ -74,7 +74,7 @@
-->
<dependency>
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose</artifactId>
<artifactId>graph-compose-core</artifactId>
<version>${graphcompose.version}</version>
<type>test-jar</type>
<classifier>tests</classifier>
Expand Down
11 changes: 6 additions & 5 deletions jitpack.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# JitPack builds the published library artifact
# (com.github.DemchaAV:GraphCompose) from the standalone root pom.xml.
# JitPack builds the published library coordinates
# (com.github.DemchaAV:GraphCompose) from the standalone poms.
#
# JDK is pinned to 17 — the project's compile baseline
# (maven.compiler.release=17) and the JDK the release verify/javadoc gate
# runs on — so the jar consumers download is built on the same JDK CI
# validates, not a drifting newer one.
#
# install is scoped to the root module (-pl .) so JitPack builds only the
# library, never the examples/benchmarks reactor siblings.
# install is scoped to the two published coordinates — graph-compose-core (the
# engine, at the root pom) and graph-compose (the drop-in wrapper in wrapper/) — so
# JitPack serves both, never the examples/benchmarks reactor siblings.
jdk:
- openjdk17
install:
- ./mvnw -DskipTests install -pl .
- ./mvnw -DskipTests -f aggregator/pom.xml install -pl :graph-compose-core,:graph-compose
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
<modelVersion>4.0.0</modelVersion>

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

<name>GraphCompose</name>
<description>A declarative layout engine for programmatic document generation, implemented primarily in Java.</description>
<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>
<url>https://github.com/DemchaAV/GraphCompose</url>

<licenses>
Expand Down Expand Up @@ -400,7 +400,7 @@
Build a tests-classifier jar so the sibling `benchmarks/`
module can reuse the test-only fixtures (com.demcha.mock.*,
etc.) without duplicating them. The artifact is
graph-compose-${version}-tests.jar in the local repository
graph-compose-core-${version}-tests.jar in the local repository
after `mvn install`. It is a LOCAL build aid only: the
`release` profile disables this execution (phase=none) so the
tests jar is never attached and therefore never deployed to
Expand Down Expand Up @@ -463,7 +463,7 @@
<!--
Keep the tests-classifier jar OUT of the published
artifact set. The default build attaches a
graph-compose-${version}-tests.jar (for the local
graph-compose-core-${version}-tests.jar (for the local
benchmarks module); on a release `deploy` that jar
would otherwise be uploaded to Maven Central, where it
is pure dead weight (test classes + heavy golden
Expand Down
4 changes: 2 additions & 2 deletions qa/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<dependencies>
<dependency>
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose</artifactId>
<artifactId>graph-compose-core</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
Expand All @@ -64,7 +64,7 @@
-->
<dependency>
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose</artifactId>
<artifactId>graph-compose-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<classifier>tests</classifier>
Expand Down
2 changes: 1 addition & 1 deletion render-docx/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
<dependencies>
<dependency>
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose</artifactId>
<artifactId>graph-compose-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
Expand Down
6 changes: 5 additions & 1 deletion scripts/cut-release.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ function Run-ShowcaseSync {
$execProp = '"-Dexec.mainClass=com.demcha.examples.support.ShowcaseSync"'
# The examples module depends on these bumped SNAPSHOT siblings (not on
# Central); each must be installed before exec:java can resolve them.
$exampleSnapshotSiblings = @('render-docx/pom.xml', 'testing/pom.xml')
$exampleSnapshotSiblings = @('wrapper/pom.xml', 'render-docx/pom.xml', 'testing/pom.xml')
if ($DryRun) {
Write-Host " [DRY RUN] $mvnw -B -ntp -DskipTests install -pl ." -ForegroundColor Yellow
foreach ($modulePom in $exampleSnapshotSiblings) {
Expand Down Expand Up @@ -504,6 +504,9 @@ try {
# automatically). graph-compose-qa is an aggregator child (its version is
# inherited) and is never published, so it needs no explicit bump.
Update-PomVersion (Join-Path $repoRoot 'testing/pom.xml') $Version
# graph-compose (the graph-compose compat wrapper (wrapper/)) tracks the engine line lockstep;
# its graph-compose-core dep is ${project.version} (follows automatically).
Update-PomVersion (Join-Path $repoRoot 'wrapper/pom.xml') $Version
# Bundle tracks the engine line: its project <version> bumps here; its
# graph-compose dep is ${project.version} (follows automatically) and its
# graph-compose-fonts dep is ${graphcompose.fonts.version} (stays pinned —
Expand Down Expand Up @@ -574,6 +577,7 @@ try {
'bundle/pom.xml',
'render-docx/pom.xml',
'testing/pom.xml',
'wrapper/pom.xml',
'examples/pom.xml',
'benchmarks/pom.xml',
'README.md',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ void everyModuleResolvesToTheRootProjectVersion() throws Exception {
assertThat(effectiveVersion(PROJECT_ROOT.resolve("testing/pom.xml")))
.describedAs("testing (graph-compose-testing) tracks the engine line and must equal the root version (%s)", root)
.isEqualTo(root);
assertThat(effectiveVersion(PROJECT_ROOT.resolve("wrapper/pom.xml")))
.describedAs("wrapper (the graph-compose compat wrapper) tracks the engine line and must equal the root version (%s)", root)
.isEqualTo(root);

// NOTE: fonts/pom.xml (graph-compose-fonts) is intentionally NOT checked
// here. It carries an independent version line (it ships on its own
Expand Down Expand Up @@ -103,6 +106,25 @@ void childModulesInheritVersionInsteadOfDeclaringTheirOwn() throws Exception {
.isFalse();
}

@Test
void graphComposeWrapperStaysAJarOverCore() throws Exception {
Element project = parse(PROJECT_ROOT.resolve("wrapper/pom.xml")).getDocumentElement();

// Packaging MUST stay jar (the default when <packaging> is absent). A pom
// would force every existing graph-compose consumer to add <type>pom</type>
// and break their build — the entire point of the wrapper is a drop-in jar.
Element packaging = directChild(project, "packaging");
assertThat(packaging == null ? "jar" : packaging.getTextContent().trim())
.describedAs("wrapper/pom.xml (the graph-compose coordinate) must stay a jar, never pom — a pom would force consumers to add <type>pom</type>")
.isEqualTo("jar");

// And it must aggregate the engine: the dependency on graph-compose-core is
// what makes a bare `graph-compose` bring the engine transitively.
assertThat(declaresDependencyOn(project, "graph-compose-core"))
.describedAs("wrapper/pom.xml must depend on graph-compose-core so `graph-compose` still brings the engine")
.isTrue();
}

@Test
void benchmarksDependencyDerivesVersionAndIsNotHardcoded() throws IOException {
String pom = Files.readString(PROJECT_ROOT.resolve("benchmarks/pom.xml"));
Expand Down Expand Up @@ -283,6 +305,24 @@ private static String effectiveVersion(Path pom) throws Exception {
throw new IllegalStateException("No <project>/<version> or inherited <parent>/<version> in " + pom);
}

private static boolean declaresDependencyOn(Element project, String artifactId) {
Element deps = directChild(project, "dependencies");
if (deps == null) {
return false;
}
NodeList children = deps.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals("dependency")) {
Element aid = directChild((Element) node, "artifactId");
if (aid != null && artifactId.equals(aid.getTextContent().trim())) {
return true;
}
}
}
return false;
}

private static Element directChild(Element parent, String name) {
NodeList children = parent.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Expand Down
2 changes: 1 addition & 1 deletion testing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
<dependencies>
<dependency>
<groupId>io.github.demchaav</groupId>
<artifactId>graph-compose</artifactId>
<artifactId>graph-compose-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
Expand Down
Loading