Skip to content

Commit df9886b

Browse files
committed
feat(examples): open the carousel with the social card, and correct its licence
The carousel now leads with SocialCardExample's artwork rather than restating it, so the post opens on the picture that already explains the premise. That drove the page size. The card is a 1280pt canvas with absolute coordinates, and the DSL has no node-level scale outside images, so scaling it would have meant rebuilding it against a width. Widening the carousel to 1280x1600 keeps the frame at 4:5 and carries the card at native size instead. Everything else was drawn against a 1080-wide page, so the three type helpers multiply by the ratio and the slides keep their proportions. Its own page takes a zero margin so the artwork reaches the edges, and a spacer centres it in the taller frame; both share the night background, so the space above and below reads as letterboxing rather than a gap. The closing slide said APACHE-2.0. The repository is MIT - LICENSE, the README badge and the card's own footer all agree - so the carousel was contradicting the slide it now opens with. The Maven coordinate also broke mid-artifact at that width and is set as groupId over artifactId.
1 parent ed9d9eb commit df9886b

2 files changed

Lines changed: 66 additions & 23 deletions

File tree

examples/src/main/java/com/demcha/examples/flagships/LinkedInCarouselExample.java

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.demcha.compose.GraphCompose;
44
import com.demcha.compose.document.api.DocumentSession;
5+
import com.demcha.compose.document.api.PageMarginRule;
56
import com.demcha.compose.document.chart.AxisSpec;
67
import com.demcha.compose.document.chart.ChartData;
78
import com.demcha.compose.document.chart.ChartSize;
@@ -25,6 +26,7 @@
2526
import com.demcha.examples.support.ExampleVersion;
2627

2728
import java.nio.file.Path;
29+
import java.util.List;
2830
import java.util.Locale;
2931

3032
/**
@@ -46,12 +48,23 @@
4648
*/
4749
public final class LinkedInCarouselExample {
4850

49-
/** LinkedIn renders document posts in a 4:5 frame; this is that frame. */
50-
public static final double PAGE_WIDTH = 1080;
51-
/** LinkedIn renders document posts in a 4:5 frame; this is that frame. */
52-
public static final double PAGE_HEIGHT = 1350;
51+
/**
52+
* LinkedIn renders document posts in a 4:5 frame; this is that frame, sized
53+
* so the opening slide can carry {@link SocialCardExample}'s card at its
54+
* native {@value SocialCardExample#CARD_WIDTH}pt width without scaling.
55+
*/
56+
public static final double PAGE_WIDTH = SocialCardExample.CARD_WIDTH;
57+
/** Four-by-five against {@link #PAGE_WIDTH}. */
58+
public static final double PAGE_HEIGHT = PAGE_WIDTH * 5 / 4;
59+
60+
/**
61+
* Everything below was drawn against a 1080-wide page. Rather than restate
62+
* every size, the type helpers scale by this ratio, so the slides keep their
63+
* proportions on the wider frame.
64+
*/
65+
private static final double SCALE = PAGE_WIDTH / 1080.0;
5366

54-
private static final double MARGIN = 80;
67+
private static final double MARGIN = 80 * SCALE;
5568
private static final double CONTENT_WIDTH = PAGE_WIDTH - 2 * MARGIN;
5669

5770
private static final DocumentColor NIGHT = DocumentColor.rgb(9, 12, 27);
@@ -66,7 +79,7 @@ public final class LinkedInCarouselExample {
6679
private static final DocumentColor AMBER = DocumentColor.rgb(230, 160, 68);
6780

6881
/** Uniform padding inside every card, as passed to {@code softPanel}. */
69-
private static final double CARD_PAD = 30;
82+
private static final double CARD_PAD = 30 * SCALE;
7083

7184
/**
7285
* Width available inside a card.
@@ -173,9 +186,17 @@ static void compose(DocumentSession document) {
173186
.producer("GraphCompose")
174187
.build());
175188

189+
// The opening slide is the social card at native size. Its own page gets
190+
// no margin so the artwork reaches the edges, and a spacer centres it in
191+
// the taller frame - both share the same night background, so the space above
192+
// and below reads as deliberate letterboxing rather than a gap.
193+
document.pageMargins(List.of(PageMarginRule.page(1, DocumentInsets.zero())));
194+
176195
document.pageFlow()
177196
.name("Carousel")
178197
.spacing(0)
198+
.addSection("Card", LinkedInCarouselExample::cardSlide)
199+
.addPageBreak(b -> b.name("ToCover"))
179200
.addSection("Cover", LinkedInCarouselExample::cover)
180201
.addPageBreak(b -> b.name("ToBackend"))
181202
.addSection("Backend", LinkedInCarouselExample::backendSlide)
@@ -190,15 +211,22 @@ static void compose(DocumentSession document) {
190211

191212
// ───────────────────────── slides ─────────────────────────
192213

214+
private static void cardSlide(SectionBuilder slide) {
215+
slide.spacing(0);
216+
slide.addSpacer(sp -> sp.width(PAGE_WIDTH)
217+
.height((PAGE_HEIGHT - SocialCardExample.CARD_HEIGHT) / 2));
218+
slide.add(SocialCardExample.scene());
219+
}
220+
193221
private static void cover(SectionBuilder slide) {
194-
slide.spacing(56);
222+
slide.spacing(56 * SCALE);
195223
eyebrow(slide, "GRAPHCOMPOSE " + ExampleVersion.currentLine(), VIOLET_LIGHT);
196224
slide.addParagraph(p -> p
197225
.text("One composition.\nTwo formats.")
198226
.textStyle(headline(132))
199227
.lineSpacing(1.03)
200228
.margin(DocumentInsets.zero()));
201-
slide.addShape(shape -> shape.size(160, 7).fillColor(VIOLET)
229+
slide.addShape(shape -> shape.size(160 * SCALE, 7 * SCALE).fillColor(VIOLET)
202230
.margin(DocumentInsets.symmetric(14, 0)));
203231
slide.addParagraph(p -> p
204232
.text("A Java DSL describes the document. The engine resolves layout "
@@ -219,7 +247,7 @@ private static void cover(SectionBuilder slide) {
219247
}
220248

221249
private static void backendSlide(SectionBuilder slide) {
222-
slide.spacing(30);
250+
slide.spacing(30 * SCALE);
223251
eyebrow(slide, "WHAT " + ExampleVersion.currentLine() + " ADDS", MINT);
224252
slide.addParagraph(p -> p
225253
.text("PowerPoint is a\nfirst-class backend.")
@@ -245,7 +273,7 @@ private static void backendSlide(SectionBuilder slide) {
245273
}
246274

247275
private static void numbersSlide(SectionBuilder slide, EngineDeckData.BenchRun bench) {
248-
slide.spacing(40);
276+
slide.spacing(40 * SCALE);
249277
eyebrow(slide, "MEASURED, NOT CLAIMED", AMBER);
250278
slide.addParagraph(p -> p
251279
.text("A " + TIER + "-row report")
@@ -279,7 +307,7 @@ private static void numbersSlide(SectionBuilder slide, EngineDeckData.BenchRun b
279307
}
280308

281309
private static void guaranteesSlide(SectionBuilder slide) {
282-
slide.spacing(30);
310+
slide.spacing(30 * SCALE);
283311
eyebrow(slide, "HOW IT STAYS HONEST", VIOLET_LIGHT);
284312
slide.addParagraph(p -> p
285313
.text("Guarantees you\ncan run.")
@@ -304,8 +332,8 @@ private static void guaranteesSlide(SectionBuilder slide) {
304332
}
305333

306334
private static void closeSlide(SectionBuilder slide) {
307-
slide.spacing(30);
308-
eyebrow(slide, "OPEN SOURCE · APACHE-2.0", MINT);
335+
slide.spacing(30 * SCALE);
336+
eyebrow(slide, "OPEN SOURCE · MIT", MINT);
309337
slide.addParagraph(p -> p
310338
.text("Try it.")
311339
.textStyle(headline(132))
@@ -315,9 +343,15 @@ private static void closeSlide(SectionBuilder slide) {
315343
.stroke(DocumentStroke.of(LINE, 1))
316344
.spacing(4);
317345
card.addSpacer(sp -> sp.width(CARD_INNER).height(0));
346+
// Split on the colon rather than set in one line: the coordinate is
347+
// wider than the card at this size and broke mid-artifact.
348+
card.addParagraph(p -> p
349+
.text("io.github.demchaav")
350+
.textStyle(mono(31, ON_DARK_MUTED))
351+
.margin(DocumentInsets.zero()));
318352
card.addParagraph(p -> p
319-
.text("io.github.demchaav:graph-compose-bundle")
320-
.textStyle(mono(37, ON_DARK))
353+
.text("graph-compose-bundle")
354+
.textStyle(mono(40, ON_DARK))
321355
.margin(DocumentInsets.zero()));
322356
// Deliberately not the reactor version: this file renders from a
323357
// -SNAPSHOT tree, and printing that would advertise a coordinate that
@@ -372,7 +406,7 @@ private static void point(SectionBuilder slide, String title, DocumentColor acce
372406
.text(title)
373407
.textStyle(DocumentTextStyle.builder()
374408
.fontName(FontName.HELVETICA_BOLD)
375-
.size(40)
409+
.size(40 * SCALE)
376410
.color(ON_DARK)
377411
.build())
378412
.margin(DocumentInsets.zero()));
@@ -394,7 +428,7 @@ private static void formatChip(RowBuilder row, String name, String lane,
394428
.text(name)
395429
.textStyle(DocumentTextStyle.builder()
396430
.fontName(FontName.HELVETICA_BOLD)
397-
.size(56)
431+
.size(56 * SCALE)
398432
.color(accent)
399433
.build())
400434
.align(TextAlign.CENTER)
@@ -421,7 +455,7 @@ private static void ratio(RowBuilder row, String value, String label, DocumentCo
421455
.text(value)
422456
.textStyle(DocumentTextStyle.builder()
423457
.fontName(FontName.HELVETICA_BOLD)
424-
.size(64)
458+
.size(64 * SCALE)
425459
.color(accent)
426460
.build())
427461
.margin(DocumentInsets.zero()));
@@ -446,7 +480,7 @@ private static ChartSpec latencyChart(EngineDeckData.BenchRun bench) {
446480
.showCategoryLabels(true)
447481
.legend(LegendPosition.NONE)
448482
.valueLabels(ValueLabelMode.OUTSIDE)
449-
.size(ChartSize.fixedHeight(470))
483+
.size(ChartSize.fixedHeight(470 * SCALE))
450484
.build();
451485
}
452486

@@ -479,19 +513,19 @@ private static String snapshotDate(EngineDeckData.BenchRun bench) {
479513
private static DocumentTextStyle headline(double size) {
480514
return DocumentTextStyle.builder()
481515
.fontName(FontName.HELVETICA_BOLD)
482-
.size(size)
516+
.size(size * SCALE)
483517
.color(ON_DARK)
484518
.build();
485519
}
486520

487521
private static DocumentTextStyle body(double size, DocumentColor color) {
488-
return DocumentTextStyle.builder().size(size).color(color).build();
522+
return DocumentTextStyle.builder().size(size * SCALE).color(color).build();
489523
}
490524

491525
private static DocumentTextStyle mono(double size, DocumentColor color) {
492526
return DocumentTextStyle.builder()
493527
.fontName(FontName.COURIER)
494-
.size(size)
528+
.size(size * SCALE)
495529
.color(color)
496530
.build();
497531
}

examples/src/main/java/com/demcha/examples/flagships/SocialCardExample.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,16 @@ private static void compose(DocumentSession document) {
212212
.build();
213213
}
214214

215-
private static DocumentNode scene() {
215+
/**
216+
* The card artwork as a single node.
217+
*
218+
* <p>Package-private so {@link LinkedInCarouselExample} can open with the
219+
* same picture instead of redrawing it. It is a canvas of {@link #CARD_WIDTH}
220+
* by {@link #CARD_HEIGHT}, so a host page has to be at least that wide.</p>
221+
*
222+
* @return the composed card
223+
*/
224+
static DocumentNode scene() {
216225
List<CanvasChild> layers = new ArrayList<>();
217226
layers.addAll(grid());
218227

0 commit comments

Comments
 (0)