Skip to content

Commit 1f50174

Browse files
committed
docs(recipes): nine pages complete the cookbook coverage
Closes every gap the recipe index tracked: rich-text (mixed runs, inline links/images/shapes, checkboxes), lists (markers, nesting), timelines (marker kinds, rail geometry, pagination opt-ins), barcodes (all symbologies, tinting, quiet zone), images (sources, sizing precedence, fit modes), pdf-chrome (metadata, watermarks, running header/footer placeholders, protection, links, outline bookmarks), translucency (alpha coverage and byte-identity), docx-export (node mapping, fallbacks, skipped kinds), and snapshot-testing (consumer-project regression flow). Every snippet is verified against the current sources rather than written from memory; pages whose feature has no runnable example link the relevant test instead (timelines, translucency, DOCX). Both indexes are updated and the folder README drops its 'not yet covered' list.
1 parent d828e30 commit 1f50174

12 files changed

Lines changed: 1091 additions & 15 deletions

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ Entries land here as they merge.
7878

7979
### Documentation
8080

81+
- **Recipe coverage is complete.** Nine new cookbook pages close every gap the
82+
recipe index tracked: rich text, lists, timelines, barcodes, images,
83+
PDF chrome (metadata / watermark / running header-footer / protection /
84+
links / bookmarks), translucency, semantic DOCX export, and layout-snapshot
85+
regression testing. Every snippet is verified against the current API;
86+
the folder index (`docs/recipes/README.md`) no longer carries a
87+
"not yet covered" list.
8188
- **`BusinessReportExample` chart is now a native vector chart.** The flagship
8289
report's five-quarter Revenue/Profit block previously rasterised a bar chart
8390
through Graphics2D into an embedded PNG; it now uses `ChartSpec.bar()` with a

docs/recipes.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ authoring API; public application code should not import
1919
| [Layered page design](recipes/layered-page-design.md) | Choosing between page backgrounds, rows, layer stacks, and canvases |
2020
| [Absolute placement](recipes/absolute-placement.md) | `addCanvas` + `position(x, y)` for pixel-precise certificates and badges |
2121
| [Tables](recipes/tables.md) | Row span, zebra rows, totals row, repeated header on page break |
22+
| [Rich text](recipes/rich-text.md) | `RichText` mixed-style runs, inline links/images/shapes, checkboxes |
23+
| [Lists](recipes/lists.md) | `addList`, marker customisation, nested lists with per-depth markers |
24+
| [Timelines](recipes/timelines.md) | `addTimeline`: markers on a connector rail, geometry and text-style controls |
25+
| [Barcodes](recipes/barcodes.md) | QR / Code 128 / EAN / UPC and friends, tinting, quiet zone |
26+
| [Images](recipes/images.md) | Sources, sizing precedence, fit modes, images in rows and cards |
27+
| [PDF chrome](recipes/pdf-chrome.md) | Metadata, watermarks, running header/footer placeholders, protection, links, bookmarks |
28+
| [Translucency](recipes/translucency.md) | `DocumentColor.rgba` / `withOpacity`, alpha coverage, layered tints |
29+
| [DOCX export](recipes/docx-export.md) | Semantic export, node mapping, fallbacks and skipped kinds |
30+
| [Snapshot testing](recipes/snapshot-testing.md) | Layout-snapshot regression testing in consumer projects |
2231
| [Streaming and output](recipes/streaming.md) | `buildPdf` / `writePdf` / `toPdfBytes`, DOCX export, layout snapshots, header / footer chrome, guide lines |
2332
| [Extending GraphCompose](recipes/extending.md) | New semantic node, fluent setter, render backend, snapshot-based regression tests |
2433

docs/recipes/README.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ API, with copy-pasteable snippets verified against the current release.
88
| Recipe | Covers |
99
|---|---|
1010
| [charts.md](charts.md) | Native vector bar / line / area / pie-donut charts: data–spec–style layers, axis & grid toggles, point markers, value-label halos, legend placement, translucent area fills |
11+
| [rich-text.md](rich-text.md) | `RichText` mixed-style runs in one paragraph: bold/accent/styled segments, inline links, inline images, inline shapes and checkboxes |
12+
| [lists.md](lists.md) | `addList`: quick bulleted lists, marker customisation, nested lists with per-depth markers, spacing and styled items |
13+
| [timelines.md](timelines.md) | `addTimeline`: markers (dot / circle / numbered / square) on a connector rail, geometry and text-style controls, pagination opt-ins |
1114
| [keep-together.md](keep-together.md) | `keepTogether()` / `keepEntriesTogether()` — blocks that relocate whole instead of orphaning a heading at a page break |
1215
| [shapes.md](shapes.md) | Filled cards, dividers, accent bars, lines, spacers, ellipses, images |
1316
| [shape-as-container.md](shape-as-container.md) | Circles/ellipses/rounded cards holding clipped children, `ClipPolicy` |
@@ -17,21 +20,14 @@ API, with copy-pasteable snippets verified against the current release.
1720
| [transforms.md](transforms.md) | Rotation, scaling, skewing |
1821
| [tables.md](tables.md) | Tabular layouts: columns, headers, zebra rows, composed cells |
1922
| [themes.md](themes.md) | `BusinessTheme` presets and custom palettes |
23+
| [barcodes.md](barcodes.md) | QR / Code 128 / Code 39 / EAN / UPC / PDF417 / DataMatrix, tinting, quiet zone, card centring |
24+
| [images.md](images.md) | Sources (bytes/path), sizing precedence, STRETCH/CONTAIN/COVER fit modes, images in rows and cards |
25+
| [pdf-chrome.md](pdf-chrome.md) | Metadata, watermarks, running header/footer with `{page}/{pages}/{date}`, protection, links and outline bookmarks |
26+
| [translucency.md](translucency.md) | `DocumentColor.rgba` / `withOpacity`: which primitives honour alpha, byte-identity for opaque colours, layered tints |
27+
| [docx-export.md](docx-export.md) | Semantic DOCX export: 1:1 node mapping, chart/shape-container fallbacks, skipped kinds |
28+
| [snapshot-testing.md](snapshot-testing.md) | Layout-snapshot regression testing in consumer projects, baseline update flow |
2029
| [streaming.md](streaming.md) | Streaming PDFs to HTTP responses |
2130
| [extending.md](extending.md) | Extension patterns: custom nodes via the `NodeDefinition` SPI |
2231

23-
## Not yet covered (planned)
24-
25-
Functionality that ships in the library but does not have a dedicated recipe
26-
yet — until then, the runnable [examples](../../examples/README.md) are the
27-
reference for these:
28-
29-
- Rich text and inline runs (mixed styles, inline images/shapes, checkboxes)
30-
- Lists and nested lists
31-
- Timelines (`addTimeline`, markers, connector rail)
32-
- Barcodes and QR codes
33-
- Images: sources, sizing, fit modes
34-
- Links, bookmarks, and PDF chrome (metadata, watermark, header/footer, protection)
35-
- Translucent colours (`DocumentColor.rgba` / `withOpacity`) beyond their chart usage
36-
- Semantic DOCX export and its fallbacks
37-
- Layout-snapshot regression testing in consumer projects
32+
Every shipped feature now has a recipe; the runnable
33+
[examples](../../examples/README.md) remain the end-to-end references.

docs/recipes/barcodes.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Barcodes and QR codes
2+
3+
A barcode is a first-class canonical node: `addBarcode` lives on
4+
`AbstractFlowBuilder`, so codes drop into `pageFlow`, `module`, and
5+
`section` containers — and combine with rows, cards, layer stacks, and
6+
tables — like any other block. The builder is `BarcodeBuilder`; the
7+
result is a `BarcodeNode` carrying `DocumentBarcodeOptions`.
8+
9+
## Quick start: a QR code
10+
11+
```java
12+
document.pageFlow()
13+
.addBarcode(barcode -> barcode
14+
.name("RepoQr")
15+
.qrCode()
16+
.data("https://github.com/DemchaAV/GraphCompose")
17+
.size(150, 150))
18+
.build();
19+
```
20+
21+
`data(...)` sets the encoded content; `size(width, height)` (or the
22+
separate `width(...)` / `height(...)` setters) fixes the drawn box in
23+
points.
24+
25+
## Symbologies
26+
27+
Five formats have fluent shortcuts — each is a single call:
28+
29+
```java
30+
barcode.qrCode(); // QR code (2D)
31+
barcode.code128(); // Code 128 — invoice numbers, logistics ids
32+
barcode.code39(); // Code 39 — alphanumeric asset tags
33+
barcode.ean13(); // EAN-13 — 13-digit retail
34+
barcode.ean8(); // EAN-8 — 8-digit compact retail
35+
```
36+
37+
The full `DocumentBarcodeType` enum also covers `UPC_A`, `PDF_417`,
38+
and `DATA_MATRIX` — select those through the generic setter:
39+
40+
```java
41+
import com.demcha.compose.document.node.DocumentBarcodeType;
42+
43+
barcode.type(DocumentBarcodeType.DATA_MATRIX)
44+
.data("LOT-2026-04-001");
45+
```
46+
47+
## Brand tinting and quiet zone
48+
49+
Foreground and background take any `DocumentColor`, so a QR code can
50+
match the document palette instead of shipping in black-on-white.
51+
`quietZone(n)` adds the symbology's blank margin, measured in barcode
52+
modules:
53+
54+
```java
55+
import com.demcha.compose.document.style.DocumentColor;
56+
57+
section.addBarcode(barcode -> barcode
58+
.qrCode()
59+
.data("https://demcha.io/graphcompose")
60+
.foreground(DocumentColor.rgb(20, 80, 95)) // brand teal
61+
.background(DocumentColor.rgb(232, 244, 245)) // soft tint
62+
.quietZone(2)
63+
.size(150, 150));
64+
```
65+
66+
Keep the foreground much darker than the background — scanners need
67+
the contrast.
68+
69+
## Clickable codes
70+
71+
A barcode accepts the same link and bookmark metadata as paragraphs
72+
and images, so the printed QR can double as a clickable area in the
73+
PDF viewer:
74+
75+
```java
76+
import com.demcha.compose.document.node.DocumentLinkOptions;
77+
78+
barcode.qrCode()
79+
.data("https://github.com/DemchaAV/GraphCompose")
80+
.link(new DocumentLinkOptions("https://github.com/DemchaAV/GraphCompose"))
81+
.size(150, 150);
82+
```
83+
84+
## Centring a barcode in a card
85+
86+
Barcodes have fixed sizes, so inside a card they sit at the leading
87+
edge by default. Wrap the built node in a shape container sized to the
88+
card's content width with `CENTER` alignment — `OVERFLOW_VISIBLE`
89+
skips clipping (see the
90+
[shape-as-container recipe](shape-as-container.md)):
91+
92+
```java
93+
import com.demcha.compose.document.dsl.BarcodeBuilder;
94+
import com.demcha.compose.document.node.BarcodeNode;
95+
import com.demcha.compose.document.style.ClipPolicy;
96+
97+
BarcodeNode code = new BarcodeBuilder()
98+
.ean13()
99+
.data("5901234123457")
100+
.size(190, 90)
101+
.build();
102+
103+
section
104+
.softPanel(DocumentColor.WHITE, 8, 14)
105+
.addContainer(card -> card
106+
.name("Ean13_Center")
107+
.rectangle(228, code.height()) // card content width
108+
.clipPolicy(ClipPolicy.OVERFLOW_VISIBLE)
109+
.center(code));
110+
```
111+
112+
The container's rectangle spans the available slot; the barcode lands
113+
at the visual midline regardless of its natural aspect ratio.
114+
115+
## See also
116+
117+
- [Shape-as-container](shape-as-container.md) — the centring pattern
118+
above, plus clipped circles and rounded cards.
119+
- [PDF chrome](pdf-chrome.md) — links and bookmarks on any node,
120+
including barcodes.
121+
122+
Runnable showcase:
123+
[`BarcodeShowcaseExample`](../../examples/src/main/java/com/demcha/examples/features/barcodes/BarcodeShowcaseExample.java)
124+
([rendered PDF](../../assets/readme/examples/barcode-showcase.pdf)) —
125+
all five fluent symbologies plus a brand-tinted QR, each centred in a
126+
two-column card grid.

docs/recipes/docx-export.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# DOCX export: the semantic backend
2+
3+
PDF is GraphCompose's fixed-layout output — every fragment lands at exact
4+
coordinates. DOCX is different on purpose: it is a **semantic export** that
5+
walks the document graph and writes editable Word content, skipping the
6+
layout pass entirely (no per-page pagination, no PDF chrome). Use it when
7+
the recipient needs to *edit* the document; use PDF when pixels must match.
8+
9+
## Exporting a session
10+
11+
```java
12+
import com.demcha.compose.document.backend.semantic.DocxSemanticBackend;
13+
14+
try (DocumentSession document = GraphCompose.document()
15+
.pageSize(595, 842)
16+
.margin(DocumentInsets.of(36))
17+
.create()) {
18+
document.pageFlow().name("Flow")
19+
.addParagraph(p -> p.text("Hello Word"))
20+
.addTable(t -> t
21+
.columns(DocumentTableColumn.auto(), DocumentTableColumn.auto())
22+
.row("R1C1", "R1C2"))
23+
.build();
24+
25+
byte[] docx = document.export(new DocxSemanticBackend());
26+
// or write straight to disk:
27+
document.export(new DocxSemanticBackend(), Path.of("out/report.docx"));
28+
}
29+
```
30+
31+
`export(backend)` returns the DOCX bytes and also writes the session's
32+
default output file when one was given to `GraphCompose.document(path)`;
33+
the two-argument overload targets an explicit path.
34+
35+
**Dependency note:** the backend requires `org.apache.poi:poi-ooxml` on
36+
the classpath. GraphCompose declares it **optional** in its POM, so
37+
consumers who export DOCX must add it explicitly — consumers who only
38+
render PDF carry no POI footprint.
39+
40+
## What maps 1:1
41+
42+
| Document node | DOCX output |
43+
|---|---|
44+
| Paragraphs | Word paragraphs with alignment, font, size, colour, bold/italic/underline; inline runs preserved |
45+
| Tables | Word tables, one cell per cell |
46+
| Images | Embedded pictures at the node's declared size |
47+
| Rows | A one-row table, so editors keep the side-by-side layout (cell content limited to atomic children) |
48+
| Sections / containers | Children written in order |
49+
| Spacers | Empty paragraphs carrying the vertical gap as spacing-after |
50+
| Page breaks | Explicit Word page breaks |
51+
52+
Page geometry (size and margins) and session metadata (title, author,
53+
subject, keywords) carry into the Word document as well.
54+
55+
## What falls back
56+
57+
- **Charts → data table.** The semantic export has no layout pass, so a
58+
chart's compiled vector geometry does not exist here. Its *semantic*
59+
content is its data, so the backend writes a categories-by-series table
60+
(values formatted with the chart's own axis format) and logs **one
61+
capability warning per export**. See [charts.md](charts.md).
62+
- **Shape containers → inline layers.** DOCX has no portable equivalent
63+
of a graphics-state path clip, so the container's layers are written
64+
inline, in source order, without the outline frame and without clipping
65+
— again with one warning per export.
66+
67+
## What is skipped
68+
69+
Lines, ellipses, standalone shapes, and barcodes are **silently skipped**
70+
— they are pure fixed-layout geometry with no semantic equivalent.
71+
Headers/footers, watermarks, and protection options are also ignored by
72+
the current exporter.
73+
74+
The rule of thumb: if the document leans on geometry — shapes, layered
75+
designs, precise placement — export PDF for the reader and DOCX only as
76+
an editable companion.
77+
78+
Round-trip coverage (paragraphs, tables, metadata, chart fallback) lives in
79+
[`DocxSemanticBackendTest`](../../src/test/java/com/demcha/compose/document/backend/semantic/DocxSemanticBackendTest.java).

0 commit comments

Comments
 (0)