Skip to content

Commit 9b694c7

Browse files
authored
docs(examples): syntax-highlight the twin-output code card with styled inline runs (#430)
1 parent 1d8ed1d commit 9b694c7

5 files changed

Lines changed: 61 additions & 22 deletions

File tree

76 Bytes
Binary file not shown.
154 Bytes
Binary file not shown.

assets/readme/twin-output-pdf.png

1.32 KB
Loading

assets/readme/twin-output-pptx.png

2.49 KB
Loading

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

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public final class TwinOutputExample {
6060
private static final DocumentColor ON_DARK = DocumentColor.rgb(245, 247, 252);
6161
private static final DocumentColor ON_DARK_MUTED = DocumentColor.rgb(177, 185, 207);
6262
private static final DocumentColor CODE_TXT = DocumentColor.rgb(190, 195, 214);
63+
private static final DocumentColor CODE_TYPE = DocumentColor.rgb(150, 190, 255);
64+
private static final DocumentColor CODE_STR = DocumentColor.rgb(120, 204, 170);
6365

6466
// Accent family.
6567
private static final DocumentColor VIOLET = DocumentColor.rgb(124, 92, 252);
@@ -181,38 +183,75 @@ private static DocumentNode logoLockup() {
181183
.build();
182184
}
183185

184-
private static DocumentNode codeCard() {
185-
// {indent level, code, trailing comment} — indentation is positional
186-
// because paragraph text trims leading whitespace.
187-
String[][] lines = {
188-
{"0", "Path deck = Path.of(\"twin-output.pptx\");", ""},
189-
{"0", "try (DocumentSession doc = GraphCompose", ""},
190-
{"2", ".document(Path.of(\"twin-output.pdf\"))", ""},
191-
{"2", ".pageSize(DocumentPageSize.SLIDE_16_9)", ""},
192-
{"2", ".create()) {", ""},
193-
{"1", "compose(doc);", "// one description"},
194-
{"1", "doc.buildPdf();", "// print-ready PDF"},
195-
{"1", "doc.buildPptx(deck);", "// editable PowerPoint"},
196-
{"0", "}", ""},
186+
/** One syntax-coloured slice of a code line: {@code kind} selects the style. */
187+
private record CodeRun(char kind, String text) {
188+
}
189+
190+
private static CodeRun t(String text) {
191+
return new CodeRun('t', text); // plain code
192+
}
193+
194+
private static CodeRun c(String text) {
195+
return new CodeRun('c', text); // class / type
196+
}
197+
198+
private static CodeRun s(String text) {
199+
return new CodeRun('s', text); // string literal
200+
}
201+
202+
private static CodeRun k(String text) {
203+
return new CodeRun('k', text); // keyword / hero call
204+
}
205+
206+
private static DocumentColor codeColor(char kind) {
207+
return switch (kind) {
208+
case 'c' -> CODE_TYPE;
209+
case 's' -> CODE_STR;
210+
case 'k' -> VIOLET_LIGHT;
211+
default -> CODE_TXT;
197212
};
213+
}
214+
215+
private static DocumentNode codeCard() {
216+
// {indent, runs, trailing comment} — indentation is positional because
217+
// paragraph text trims leading whitespace; each line is ONE paragraph
218+
// of styled inline runs, so both backends carry it as rich text (the
219+
// PPTX side lands one editable text frame with coloured runs per line).
220+
record CodeLine(int indent, List<CodeRun> runs, String note) {
221+
}
222+
List<CodeLine> lines = List.of(
223+
new CodeLine(0, List.of(c("Path"), t(" deck = "), c("Path"), t(".of("),
224+
s("\"twin-output.pptx\""), t(");")), ""),
225+
new CodeLine(0, List.of(k("try"), t(" ("), c("DocumentSession"), t(" doc = "),
226+
c("GraphCompose")), ""),
227+
new CodeLine(2, List.of(t(".document("), c("Path"), t(".of("),
228+
s("\"twin-output.pdf\""), t("))")), ""),
229+
new CodeLine(2, List.of(t(".pageSize("), c("DocumentPageSize"),
230+
t(".SLIDE_16_9)")), ""),
231+
new CodeLine(2, List.of(t(".create()) {")), ""),
232+
new CodeLine(1, List.of(t("compose(doc);")), "// one description"),
233+
new CodeLine(1, List.of(t("doc."), k("buildPdf"), t("();")), "// print-ready PDF"),
234+
new CodeLine(1, List.of(t("doc."), k("buildPptx"), t("(deck);")), "// editable PowerPoint"),
235+
new CodeLine(0, List.of(t("}")), ""));
198236
ShapeContainerBuilder card = new ShapeContainerBuilder()
199237
.name("TwinCode")
200238
.roundedRect(470, 152, 14)
201239
.fillColor(DocumentColor.rgba(7, 10, 24, 220))
202240
.stroke(DocumentStroke.of(DARK_LINE, 0.8));
203-
for (int i = 0; i < lines.length; i++) {
241+
for (int i = 0; i < lines.size(); i++) {
242+
CodeLine line = lines.get(i);
204243
double y = 12 + i * 14.6;
205-
double indent = 20 + Integer.parseInt(lines[i][0]) * 18;
206-
card.position(new ParagraphBuilder()
244+
ParagraphBuilder code = new ParagraphBuilder()
207245
.name("TwinCodeLine" + i)
208-
.text(lines[i][1])
209-
.textStyle(mono(9.5, CODE_TXT, false))
210-
.margin(DocumentInsets.zero())
211-
.build(), indent, y, LayerAlign.TOP_LEFT);
212-
if (!lines[i][2].isEmpty()) {
246+
.margin(DocumentInsets.zero());
247+
for (CodeRun run : line.runs()) {
248+
code.inlineText(run.text(), mono(9.5, codeColor(run.kind()), false));
249+
}
250+
card.position(code.build(), 20 + line.indent() * 18, y, LayerAlign.TOP_LEFT);
251+
if (!line.note().isEmpty()) {
213252
card.position(new ParagraphBuilder()
214253
.name("TwinCodeNote" + i)
215-
.text(lines[i][2])
254+
.text(line.note())
216255
.textStyle(mono(9.5, MINT, false))
217256
.margin(DocumentInsets.zero())
218257
.build(), 250, y, LayerAlign.TOP_LEFT);

0 commit comments

Comments
 (0)