Skip to content

Commit 7f4ec8d

Browse files
authored
feat(examples): render the repository social preview card with the engine (#462)
* feat(examples): render the repository social preview card with the engine The card GitHub shows when the repo is linked was a hand-made image saying "Declarative document layout engine for Java" — true, and silent about the thing the 2.1 line is built on. A hand-made card also has no way to stay current: it drifts the moment the project does. SocialCardExample composes it through the canonical DSL at 1280x640, so it reads the same palette and wordmark as the rest of the brand and can be regenerated like the README hero. What it draws is the claim itself. One sheet on the left resolves into a portrait page and a 16:9 slide, and the content bars inside both are placed from one table of relative fractions — the picture asserts that a layout arrives in two shapes, and the code that draws it enforces that. Wired into GenerateAllExamples so a change that breaks it turns the examples smoke test red. * feat(examples): put a real rendered document inside the card's outputs The two output shapes held grey placeholder bars, which made the picture an illustration of the claim rather than the claim. They now hold an actual document the engine composed: a title, a line of body text and a bar chart with Q1-Q4 category labels, built once by documentBody and handed to both shapes. Only the chart's height follows the box it lands in. With a single aspect ratio the slide's chart overran its card while the page's left a third of the box empty — which is the reason a layout engine exists, so the card now demonstrates that instead of hiding it. The source sheet was a five-point outline whose folded corner read as a dent; it is a plain quadrilateral in gentle perspective now. * feat(examples): show the resolved graph between the source and the outputs The card jumped straight from a sheet to two shapes, which left out the part the name is about. It now reads in three stages: authored documents on the left, the resolved layout graph in the middle, and the two backends that consume it on the right. The middle panel carries a node tree — a document root, its sections and the leaf fragments each resolves to — over the flat ordered fragment stream the compiler emits. That stream is what both backends read, and drawing it is what makes "one layout pass" a statement about the architecture rather than about the picture. Two engine contracts learned in passing and noted in the code: a ShapeContainerNode must carry at least one layer, so an empty leaf box is a ShapeBuilder; and a paragraph helper that sizes its box against the page width collapses to nothing inside a narrower parent, which had the panel's footer rendering at zero width. * fix(examples): keep the card's chart inside its padding and align the rails The chart ran to the card's border. A node positioned into a card is measured against the card, not against the card minus its padding, so the width passed to the body was only ever used by the prose block while the chart laid out against the full container. An invisible content box of the padded size gives it something to lay out against. The graph rails were sized from literals that did not match the drops they joined: the tier rail overshot its last drop by two points, which at this size reads as a whisker past the junction. Both rails are now derived from the drop positions, and the leaf gap is a named constant rather than a repeated 29. Output labels moved off the cards' rounded corners. * fix(examples): hang the graph root over its own subtree, not the panel The root sat at w/2 while the section drops sit at w*t + 31, so their span is centred 2.3pt to the left. Centring the root on the panel put it visibly off the child it points at — the drop entered the middle section node off-axis. Both the root and its drop now derive from the tier row's centre, so the column stays plumb whatever the tier fractions become. Measured on the render: root and middle section centres agree to 0.0px, where they were 2.3pt apart. * fix(examples): tuck the beams behind the card borders, air under the wordmark Each wedge ran to the full height of the card it points at, so its point landed exactly on the rounded corner and stuck out past the curve as a sharp spike. Both now stop short of the corner radius and meet the straight part of the border. The tagline sat directly against the wordmark — measured on the render the two had no gap at all between them. It drops far enough to read as a second line rather than a descender. * feat(examples): emit the card as a deck too, and size it for a feed A social card is read at roughly 40% of its rendered width, so the type was chosen for 1:1 and vanished at the size anyone actually sees it. The labels, the document heading and the chart axis all move up, and the two faintest lines gain contrast instead of points — at that reduction brightness buys more legibility than size does. The card now also writes itself as a PowerPoint deck. It asserts that one composition reaches a PDF and an editable deck; emitting both from one session is the cheapest proof, and it keeps the assertion honest whenever this file changes. Making that deck editable meant dropping a clip: the content box carried CLIP_BOUNDS, and a clip that could cut ink sends its whole region through the PPTX raster fallback. The deck arrived with 6 text runs and three pictures. Without it: 29 runs, 163 native shapes, and the one remaining picture is the SVG wordmark, which the capability matrix already records as a raster fallback. The content is sized to that box anyway, so nothing needed cutting. Both artifacts are committed beside the other example output.
1 parent c9944c1 commit 7f4ec8d

5 files changed

Lines changed: 687 additions & 0 deletions

File tree

12.9 KB
Binary file not shown.
55.8 KB
Binary file not shown.

assets/readme/social-card.png

54.1 KB
Loading

examples/src/main/java/com/demcha/examples/GenerateAllExamples.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import com.demcha.examples.flagships.FinancialReportPptxExample;
5353
import com.demcha.examples.flagships.MasterShowcaseExample;
5454
import com.demcha.examples.flagships.MasterShowcasePptxExample;
55+
import com.demcha.examples.flagships.SocialCardExample;
5556
import com.demcha.examples.flagships.MavenBannerPptxExample;
5657
import com.demcha.examples.flagships.ModuleFirstFileExample;
5758
import com.demcha.examples.flagships.TwinOutputExample;
@@ -222,6 +223,8 @@ public static void main(String[] args) throws Exception {
222223
System.out.println("Generated: " + EngineDeckExample.generate());
223224
System.out.println("Generated: " + EngineDeckPptxExample.generate());
224225
System.out.println("Generated: " + MavenBannerPptxExample.generate());
226+
System.out.println("Generated: " + SocialCardExample.generate());
227+
System.out.println("Generated: " + SocialCardExample.generatePptx());
225228
System.out.println("Generated: " + TwinOutputExample.generate());
226229
System.out.println("Generated: " + FinancialReportExample.generate());
227230
System.out.println("Generated: " + FinancialReportPptxExample.generate());

0 commit comments

Comments
 (0)