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
67 changes: 67 additions & 0 deletions .github/workflows/publish-emoji.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Publish emoji to Maven Central

# Publishes the graph-compose-emoji companion artifact to Maven Central,
# independently of the engine. The bundled Noto Emoji glyphs change rarely, so
# they release on their OWN tag line (emoji-v*) — pushing an engine v* tag
# never touches them, and re-publishing emoji does not require an engine
# release. This mirrors publish-fonts.yml but targets emoji/pom.xml.
#
# Tagging: emoji-vX.Y.Z (e.g. emoji-v1.0.0). The emoji artifact carries its
# own independent version (see emoji/pom.xml) — keep it in sync with the tag.
#
# Human prerequisites are identical to publish.yml (GPG key + Central token
# secrets). See docs/contributing/release-process.md for the runbook.

on:
push:
tags:
- 'emoji-v*'
workflow_dispatch:
inputs:
tag:
description: 'Existing emoji-v*-prefixed tag to (re-)publish'
required: true
type: string

permissions:
contents: read

jobs:
publish-emoji:
name: Publish ${{ github.ref_name }} to Maven Central
runs-on: ubuntu-latest
# Only ship plain semver tags (emoji-vX.Y.Z) to Central; pre-release
# suffixes ship nowhere from here.
if: |
github.event_name == 'workflow_dispatch' ||
(!contains(github.ref, '-rc') && !contains(github.ref, '-alpha') && !contains(github.ref, '-beta') && !contains(github.ref, '-snapshot'))
env:
JAVA_TOOL_OPTIONS: -Djava.awt.headless=true

steps:
- name: Check out repository at tag
uses: actions/checkout@v7
with:
ref: ${{ github.event.inputs.tag || github.ref }}

- name: Set up Temurin JDK 17 with Central credentials and GPG key
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '17'
cache: maven
server-id: central
server-username: CENTRAL_USERNAME
server-password: CENTRAL_TOKEN
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
gpg-passphrase: MAVEN_GPG_PASSPHRASE

- name: Publish emoji to Maven Central
# Activates the emoji module's release profile (sources + javadoc +
# gpg sign + central-publishing) and flips gpg.skip=false. Blocks
# until Sonatype's validator confirms validation.
run: ./mvnw -B -ntp -f emoji/pom.xml -P release -Dgpg.skip=false deploy
env:
CENTRAL_USERNAME: ${{ secrets.CENTRAL_USERNAME }}
CENTRAL_TOKEN: ${{ secrets.CENTRAL_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
2 changes: 1 addition & 1 deletion bundle/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
<graphcompose.fonts.version>1.0.0</graphcompose.fonts.version>

<maven.gpg.plugin.version>3.2.8</maven.gpg.plugin.version>
<central.publishing.plugin.version>0.10.0</central.publishing.plugin.version>
<central.publishing.plugin.version>0.11.0</central.publishing.plugin.version>

<gpg.skip>true</gpg.skip>
</properties>
Expand Down
2 changes: 1 addition & 1 deletion docs/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ authoring API; public application code should not import
| [Layered page design](recipes/layered-page-design.md) | Choosing between page backgrounds, rows, layer stacks, and canvases |
| [Absolute placement](recipes/absolute-placement.md) | `addCanvas` + `position(x, y)` for pixel-precise certificates and badges |
| [Tables](recipes/tables.md) | Row span, zebra rows, totals row, repeated header on page break |
| [Rich text](recipes/rich-text.md) | `RichText` mixed-style runs, inline links/images/shapes, checkboxes |
| [Rich text](recipes/rich-text.md) | `RichText` mixed-style runs, inline links/images/shapes, SVG icons, emoji shortcodes, checkboxes |
| [Lists](recipes/lists.md) | `addList`, marker customisation, nested lists with per-depth markers |
| [Timelines](recipes/timelines.md) | `addTimeline`: markers on a connector rail, geometry and text-style controls |
| [Barcodes](recipes/barcodes.md) | QR / Code 128 / EAN / UPC and friends, tinting, quiet zone |
Expand Down
2 changes: 1 addition & 1 deletion docs/recipes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ API, with copy-pasteable snippets verified against the current release.
| Recipe | Covers |
|---|---|
| [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 |
| [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 |
| [rich-text.md](rich-text.md) | `RichText` mixed-style runs in one paragraph: bold/accent/styled segments, inline links, inline images, inline SVG icons, emoji shortcodes, inline shapes and checkboxes |
| [lists.md](lists.md) | `addList`: quick bulleted lists, marker customisation, nested lists with per-depth markers, spacing and styled items |
| [timelines.md](timelines.md) | `addTimeline`: markers (dot / circle / numbered / square) on a connector rail, geometry and text-style controls, pagination opt-ins |
| [keep-together.md](keep-together.md) | `keepTogether()` / `keepEntriesTogether()` — blocks that relocate whole instead of orphaning a heading at a page break |
Expand Down
46 changes: 46 additions & 0 deletions docs/recipes/rich-text.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,52 @@ relative to the surrounding line (`CENTER` by default); the full
overload adds a `baselineOffset` and `DocumentLinkOptions` for a
clickable inline image.

## Inline SVG icons

A parsed `SvgIcon` sits on the text baseline like a word, drawn as crisp
vector layers that carry their own colours — so it renders independently
of the active font's glyph coverage. `size` is the glyph height in points;
the width follows the icon's aspect ratio.

```java
import com.demcha.compose.document.svg.SvgIcon;

SvgIcon star = SvgIcon.parse(
"<svg viewBox='0 0 24 24'>"
+ " <path d='M12 2l3 7h7l-5.5 4 2 7L12 16l-6.5 4 2-7L2 9h7z' fill='#f5b301'/>"
+ "</svg>");

section.addRich(rich -> rich
.plain("Rated ")
.svgIcon(star, 11)
.plain(" by reviewers."));
```

On `ParagraphBuilder` the equivalent call is `inlineSvgIcon(icon, size)`;
both take `alignment` / `baselineOffset` / link overloads and a clickable
form via `DocumentLinkOptions`. `SvgIcon.parse(String)` reads inline SVG
markup; `SvgIcon.read(Path)` loads it from a file.

## Emoji / shortcodes

`emoji(":code:")` resolves a GitHub-style shortcode to an inline colour
glyph through `EmojiLibrary`. Resolution is lenient: an unknown shortcode —
or no emoji set on the classpath — falls back to the literal text, the way
GitHub renders an unrecognised `:code:`.

```java
section.addRich(rich -> rich
.plain("Deploy ")
.emoji(":white_check_mark:", 11)
.plain(" succeeded ")
.emoji(":rocket:", 11));
```

On `ParagraphBuilder` the call is `inlineEmoji(":code:", size)`. Glyphs ship
in the optional, independently-versioned `graph-compose-emoji` companion
artifact (Noto Emoji, SIL OFL 1.1) — add it to the classpath to resolve
shortcodes; the engine itself carries no emoji art.

## Inline shapes and checkboxes

Geometric figures drawn from geometry — not font glyphs — so they render
Expand Down
2 changes: 1 addition & 1 deletion emoji/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
<maven.source.plugin.version>3.4.0</maven.source.plugin.version>
<maven.javadoc.plugin.version>3.12.0</maven.javadoc.plugin.version>
<maven.gpg.plugin.version>3.2.8</maven.gpg.plugin.version>
<central.publishing.plugin.version>0.10.0</central.publishing.plugin.version>
<central.publishing.plugin.version>0.11.0</central.publishing.plugin.version>

<!-- See the engine pom: opted in via -Dgpg.skip=false on the publish workflow. -->
<gpg.skip>true</gpg.skip>
Expand Down
2 changes: 1 addition & 1 deletion fonts/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
<maven.source.plugin.version>3.4.0</maven.source.plugin.version>
<maven.javadoc.plugin.version>3.12.0</maven.javadoc.plugin.version>
<maven.gpg.plugin.version>3.2.8</maven.gpg.plugin.version>
<central.publishing.plugin.version>0.10.0</central.publishing.plugin.version>
<central.publishing.plugin.version>0.11.0</central.publishing.plugin.version>

<!-- See the engine pom: opted in via -Dgpg.skip=false on the publish workflow. -->
<gpg.skip>true</gpg.skip>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ public BarcodeBuilder linkTarget(DocumentLinkTarget linkTarget) {
*
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public BarcodeBuilder linkTo(String anchor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ public EllipseBuilder linkTarget(DocumentLinkTarget linkTarget) {
*
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public EllipseBuilder linkTo(String anchor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ public ImageBuilder linkTarget(DocumentLinkTarget linkTarget) {
*
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public ImageBuilder linkTo(String anchor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ public LineBuilder linkTarget(DocumentLinkTarget linkTarget) {
*
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public LineBuilder linkTo(String anchor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ public ParagraphBuilder linkTarget(DocumentLinkTarget linkTarget) {
*
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public ParagraphBuilder linkTo(String anchor) {
Expand Down Expand Up @@ -247,6 +248,7 @@ public ParagraphBuilder inlineLink(String text, DocumentLinkOptions linkOptions)
* @param text visible link text
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public ParagraphBuilder inlineLinkTo(String text, String anchor) {
Expand Down Expand Up @@ -340,6 +342,7 @@ public ParagraphBuilder inlineImage(DocumentImageData imageData,
* @param height target height in points
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public ParagraphBuilder inlineImageLinkTo(DocumentImageData imageData, double width, double height, String anchor) {
Expand All @@ -357,6 +360,7 @@ public ParagraphBuilder inlineImageLinkTo(DocumentImageData imageData, double wi
* @param baselineOffset extra vertical shift in points; positive moves up
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public ParagraphBuilder inlineImageLinkTo(DocumentImageData imageData,
Expand Down Expand Up @@ -653,6 +657,7 @@ public ParagraphBuilder inlineEmoji(String shortcode,
* @param fill fill color
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public ParagraphBuilder shapeLinkTo(ShapeOutline outline, DocumentColor fill, String anchor) {
Expand All @@ -671,6 +676,7 @@ public ParagraphBuilder shapeLinkTo(ShapeOutline outline, DocumentColor fill, St
* @param baselineOffset extra vertical shift in points; positive moves up
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public ParagraphBuilder shapeLinkTo(ShapeOutline outline,
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/demcha/compose/document/dsl/RichText.java
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ public RichText link(String text, String uri) {
* @param text visible link text
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public RichText linkTo(String text, String anchor) {
Expand All @@ -235,6 +236,7 @@ public RichText linkTo(String text, String anchor) {
* @param style explicit style for this run, or {@code null} for the link default
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public RichText linkTo(String text, DocumentTextStyle style, String anchor) {
Expand Down Expand Up @@ -343,6 +345,7 @@ public RichText image(DocumentImageData imageData,
* @param height target height in points
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public RichText imageLinkTo(DocumentImageData imageData, double width, double height, String anchor) {
Expand All @@ -360,6 +363,7 @@ public RichText imageLinkTo(DocumentImageData imageData, double width, double he
* @param baselineOffset extra vertical shift in points; positive moves up
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public RichText imageLinkTo(DocumentImageData imageData,
Expand Down Expand Up @@ -650,6 +654,7 @@ public RichText shape(ShapeOutline outline,
* @param fill fill color
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public RichText shapeLinkTo(ShapeOutline outline, DocumentColor fill, String anchor) {
Expand All @@ -668,6 +673,7 @@ public RichText shapeLinkTo(ShapeOutline outline, DocumentColor fill, String anc
* @param baselineOffset extra vertical shift in points; positive moves up
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public RichText shapeLinkTo(ShapeOutline outline,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ public ShapeBuilder linkTarget(DocumentLinkTarget linkTarget) {
*
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public ShapeBuilder linkTo(String anchor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ public TableBuilder linkTarget(DocumentLinkTarget linkTarget) {
*
* @param anchor target anchor name
* @return this builder
* @throws IllegalArgumentException if {@code anchor} is blank
* @since 1.9.0
*/
public TableBuilder linkTo(String anchor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
* <p>The engine carries no emoji art and has no Maven dependency on the emoji
* module — exactly like {@code DefaultFonts} and {@code graph-compose-fonts}.
* This resolver is fully data-driven: any classpath providing that layout works,
* so the small bundled starter set can be replaced wholesale by the full
* jdecked/twemoji set with no code change.</p>
* so the bundled Noto Emoji set (SIL OFL 1.1) can be swapped for another emoji
* set by changing the classpath alone, with no code change.</p>
*
* <p>Resolution is lenient by design — {@link #find(String)} returns an empty
* {@link Optional} for an unknown shortcode or when no emoji set is on the
Expand Down