Authoring Rich Content
This how-to guide provides copy-ready recipes for authoring documentation pages in Supa Maven Skin using standard Markdown (.md), embedded HTML, and Velocity-preprocessed Markdown (.md.vm).
Choosing Markdown (.md) vs. Velocity Templates (.md.vm)
Doxia 2.0 supports two ways to author Markdown pages in src/site/markdown/:
| File Extension | Processing Pipeline | Best For |
|---|---|---|
page.md |
CommonMark → HTML + Furo DOM transforms | Fast, clean prose using :bi-...: icon shortcodes, > [!NOTE] admonitions, .supa-tabs, .supa-accordion, and embedded Bootstrap 6 HTML. |
page.md.vm |
Apache Velocity → CommonMark → HTML + Furo DOM transforms | Pages that need live Maven POM variables (${project.version}, ${project.groupId}, ${project.properties.getProperty("...")}) or Velocity helper macros (#bi, #bsAlert, #bsBadge, #bsCard, #bsCardGridStart, #bsGuideCard, #bsCardGridEnd). |
Rules for .md.vm Files and Embedded HTML
- Global Skin Macros in
.md.vm: Supa Maven Skin automatically registers its Velocity helper macros (#bi,#bsAlert,#bsBadge,#bsCard,#bsCardGridStart,#bsGuideCard,#bsCardGridEnd) globally viasite-macros.vmso they can be called directly in.md.vmpages. - Escaping
##Headings in.md.vm: Because##denotes a single-line comment in Apache Velocity, wrap level-2+ Markdown heading hashes in Velocity's unparsed block syntax (#[[##]]# Section Headingor#[[###]]# Subsection) inside.md.vmfiles so Velocity passes##/###through to the Markdown parser. - Keeping Multi-Line HTML Blocks Contiguous:
In CommonMark (Doxia 2.0), a blank line inside a raw HTML
<div>...</div>block ends the HTML block early. Keep multi-line HTML component wrappers free of internal empty lines (use if you need a blank line inside an HTML<pre><code>block).
Using Velocity Helper Macros (#bsBadge, #bsCard, & #bsGuideCard)
In .md.vm pages, #bsBadge( $theme $variant $text ), #bsCard( $title $subtitle $body $footer ), and #bsCardGridStart / #bsGuideCard / #bsCardGridEnd generate isolated .not-prose Bootstrap 6 components that can interpolate Maven properties:
#bsBadge( "primary" "" "v${project.version}" )
#bsBadge( "success" "subtle" "Stable API" )
#bsBadge( "info" "outline" "JDK 21+" )
#bsCard(
"${project.name}"
"${project.groupId}:${project.artifactId}"
"Zero-config Sphinx Furo aesthetics powered by Bootstrap 6."
"MIT License"
)
#bsCardGridStart( "" )
#bsGuideCard( "col-12 md:col-6" "rocket-takeoff" "primary" "getting-started.html" "Quickstart Tutorial" "Tutorial" "Step-by-step guide to configuring <code>pom.xml</code> and <code>site.xml</code>." )
#bsCardGridEnd()
Writing Admonitions and Alerts
Admonitions
Supa Maven Skin supports all 12 Sphinx Furo admonition types across 6 semantic categories, each rendered with a Bootstrap Icons glyph (<i class="bi bi-... supa-admonition-icon" aria-hidden="true"></i>), tinted header bar, and colored left accent border. Any text after the [!...] marker on the first line becomes a custom title, and nested blockquotes (> > [!WARNING]) are automatically transformed into nested admonitions. Inline Markdown such as code spans and emphasis works in custom titles too.
Select a category below to preview the rendered admonitions and copy their Markdown syntax:
[!NOTE] Renders with
bi-info-circleand the Info palette tokens. Adapts across all 6 WCAG 2.2 AA & AAA color schemes.
[!SEEALSO] Renders with
bi-arrow-up-right-circlefor cross-references ([!SEE-ALSO]is also supported). See the Kitchen Sink for all 12 types on one page.
> [!NOTE]
> Renders with `bi-info-circle` and the **Info** palette tokens.
> [!SEEALSO]
> Cross-reference related sections or external docs (`[!SEE-ALSO]` also works).
[!TIP] Custom Admonition Title Renders with
bi-lightbulb. Provide text immediately after[!TIP]on the first line to override the default heading.
[!HINT] Renders with
bi-question-circleand the Success / Tip palette tokens for gentle guidance or troubleshooting hints.
> [!TIP] Custom Admonition Title
> Provide text immediately after `[!TIP]` on the first line to override the default heading.
> [!HINT]
> Gentle guidance or troubleshooting hints (`bi-question-circle`).
[!IMPORTANT] Renders with
bi-fireand the Important / Accent palette tokens to highlight key requirements.
[!ADMONITION] Custom Admonition Heading Renders with
bi-card-text— equivalent to Sphinx's generic.. admonition:: Titledirective.
> [!IMPORTANT]
> Highlights essential requirements or prerequisites (`bi-fire`).
> [!ADMONITION] Custom Admonition Heading
> Equivalent to Sphinx's generic `.. admonition:: Title` directive (`bi-card-text`).
[!WARNING] Renders with
bi-exclamation-triangleand the Warning palette tokens for configuration pitfalls or breaking changes.
[!CAUTION] Renders with
bi-lightning-chargeand the Warning palette tokens when advising extra care.
> [!WARNING]
> Warns readers about potential configuration pitfalls (`bi-exclamation-triangle`).
> [!CAUTION]
> Advises caution before changing sensitive parameters (`bi-lightning-charge`).
[!ATTENTION] Renders with
bi-exclamation-diamondand the Danger / Error palette tokens.
[!DANGER] Renders with
bi-lightning-charge-fillfor destructive actions or data-loss risks.
[!ERROR] Renders with
bi-x-octagonto document failure modes or error states.
> [!ATTENTION]
> Demands immediate attention before proceeding (`bi-exclamation-diamond`).
> [!DANGER]
> Alerts readers to destructive actions or data-loss risks (`bi-lightning-charge-fill`).
> [!ERROR]
> Documents known error states or failure modes (`bi-x-octagon`).
[!TODO] Renders with
bi-check2-squareand neutral Todo tokens for tracking upcoming tasks.
> [!TODO]
> Renders with `bi-check2-square` for tracking upcoming tasks.
Bootstrap 6 Semantic Alerts
When you need a Bootstrap 6 .alert banner (supporting all 8 .theme-* colors and optional dismiss buttons), you can use the GFM blockquote shorthand, raw HTML, or the #bsAlert Velocity macro:
[!ALERT:primary dismissible] Release Ready Use
[!ALERT:theme dismissible]in Markdown or#bsAlertin Velocity.
> [!ALERT:primary dismissible] Release Ready
> Use `[!ALERT:theme dismissible]` in Markdown or `#bsAlert` in Velocity.
#bsAlert( "primary" "Release Ready" "Use #bsAlert in Velocity templates." true )
<div class="alert theme-primary not-prose" role="alert">
<div class="flex-grow-1">
<div class="alert-heading fw-semibold mb-1">Release Ready</div>
<div>Standard Bootstrap 6 alert markup.</div>
</div>
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
Adding Bootstrap Icons
Supa Maven Skin bundles 2,000+ Bootstrap Icons offline (bootstrap-icons.woff2). You can insert icons using Markdown shortcodes, the #bi Velocity macro, or HTML <i> tags.
1. Markdown Shortcode
Write :bi-<icon-name>: anywhere in prose, table cells, headings, or lists. You can optionally append space-separated utility classes (such as text-primary, text-success, fs-5, me-1) before the closing colon:
- :bi-rocket-takeoff: Basic decorative icon
- :bi-check-circle-fill text-success fs-5: Icon with color and font-size utilities
- :bi-github me-1: Icon with right margin inside a link
[!NOTE] Code Block Safety Shortcodes inside inline
`code`and<pre><code>blocks are automatically ignored and left untouched as literal text.
2. Velocity Macro
In .md.vm pages, use #bi( $name $extraClasses $ariaLabel ):
## Decorative icon (renders aria-hidden="true")
#bi( "rocket-takeoff" "" "" ) Launch
## Icon + extra CSS utility classes (renders aria-hidden="true")
#bi( "check-circle-fill" "text-success fs-5" "" ) Verified
## Semantic accessible icon (renders role="img" aria-label="Accessible")
#bi( "universal-access-circle" "text-info fs-5" "Accessible" ) WCAG 2.2 AAA
3. Raw HTML
<i class="bi bi-rocket-takeoff text-primary fs-5" aria-hidden="true"></i> Launch
Styling Code Blocks
Supa Maven Skin bundles Highlight.js offline for 18+ JVM, web, and configuration languages (java, kotlin, groovy, xml, html, velocity/vm, typescript/ts, javascript/js, json, yaml/yml, properties, sql, bash/sh/shell, python/py, css, scss, markdown/md, diff, and plaintext/text) and attaches a one-click Copy to clipboard button to every <pre> block.
File Header Bars & Line Numbers
To add a file-path header bar (.supa-code-header) or line numbers (.has-line-numbers) to a code block, use an HTML <pre> block with data-title="..." (or title="...") on <code> and class="line-numbers" on <pre>:
package io.example;
public final class Greeter {
public static String greet(String name) {
return "Hello, " + name + "!";
}
}
<pre class="line-numbers"><code class="language-java" data-title="src/main/java/io/example/Greeter.java">package io.example;
public final class Greeter {
public static String greet(String name) {
return "Hello, " + name + "!";
}
}</code></pre>
Unified Diffs
Use a standard ```diff fenced code block to highlight additions (+) and removals (-) with palette-aware semantic colors:
```diff
<skin>
- <groupId>org.apache.maven.skins</groupId>
- <artifactId>maven-fluido-skin</artifactId>
+ <groupId>io.github.mepcotterell</groupId>
+ <artifactId>supa-maven-skin</artifactId>
</skin>
```
Creating Synchronized Content Tabs
Wrap child <div title="Tab Label"> panels inside <div class="supa-tabs" title="group-key"> to create ARIA-compliant tablists.
- Synchronization: Every
.supa-tabscontainer sharing the sametitle(ordata-tab-group) attribute automatically synchronizes across the page and persists the user's preferred tab inlocalStorage(supa-tab-sync). - Keyboard Navigation: Supports
ArrowLeft,ArrowRight,Home, andEndkeys out of the box.
<dependency>
<groupId>io.github.mepcotterell</groupId>
<artifactId>supa-maven-skin</artifactId>
<version>0.2.0</version>
</dependency>
<skin>
<groupId>io.github.mepcotterell</groupId>
<artifactId>supa-maven-skin</artifactId>
<version>0.2.0</version>
</skin>
<div class="supa-tabs" title="build-tool-demo">
<div title="Maven (pom.xml)">
<pre><code class="language-xml"><dependency>
<groupId>io.github.mepcotterell</groupId>
<artifactId>supa-maven-skin</artifactId>
<version>0.2.0</version>
</dependency></code></pre>
</div>
<div title="Site Descriptor (site.xml)">
<pre><code class="language-xml"><skin>
<groupId>io.github.mepcotterell</groupId>
<artifactId>supa-maven-skin</artifactId>
<version>0.2.0</version>
</skin></code></pre>
</div>
</div>
Building Accordions and Steppers
Declarative Accordions (.supa-accordion)
Wrap <div title="Section Heading"> items inside <div class="supa-accordion">. Add class="open" to any item that should be expanded initially:
Set <colorScheme>modus</colorScheme> inside <custom><supaSkin> in your src/site/site.xml.
Yes. Bootstrap 6 CSS/JS, Bootstrap Icons fonts, and Highlight.js are all bundled directly inside the skin JAR.
<div class="supa-accordion">
<div title="How do I set a default color scheme?" class="open">
<p>Set <code><colorScheme>modus</colorScheme></code> inside <code><custom><supaSkin></code> in your <code>src/site/site.xml</code>.</p>
</div>
<div title="Does Supa Maven Skin work offline?">
<p>Yes. Bootstrap 6 CSS/JS, Bootstrap Icons fonts, and Highlight.js are all bundled directly inside the skin JAR.</p>
</div>
</div>
Declarative Steppers (ol.supa-stepper)
Use <ol class="supa-stepper" title="2"> where title specifies the 1-based active step index (all steps up to that number are styled as active/completed):
- Configure pom.xml
- Author Markdown
- Deploy Site
<ol class="supa-stepper" title="2">
<li>Configure pom.xml</li>
<li>Author Markdown</li>
<li>Deploy Site</li>
</ol>
Rendering Mermaid Diagrams and KaTeX Math
When <mermaid>auto</mermaid> and <katex>auto</katex> are enabled in site.xml (the default), Supa Maven Skin inspects each page at load time and only fetches Mermaid or KaTeX when diagrams or math expressions are present on that page. The default builds come from jsDelivr, pinned to exact versions and verified with Subresource Integrity; to serve them from your own site instead, follow Self-Hosting Mermaid & KaTeX.
Mermaid Diagrams
Use a standard fenced ```mermaid code block. The diagram automatically re-renders when the user toggles between Light and Dark themes:
```mermaid
flowchart LR
A["src/site/markdown/*.md"] --> B["Doxia 2.0"]
B --> C["Supa Maven Skin (site.vm)"]
C --> D["Responsive HTML5 Site"]
```
KaTeX Mathematical Notation
Write inline math between single $...$ delimiters (such as $O(n \log n)$) and display equations between $$...$$ delimiters:
Inline complexity $O(n \log n)$ or display block:
$$
\hat{y} = \sigma\left( \sum_{i=1}^{d} w_i x_i + b \right)
$$
Self-Hosting Mermaid & KaTeX
Serve both libraries from your own site when you cannot depend on jsDelivr, for example on an intranet or under a strict Content Security Policy.
-
Copy the classic builds into
src/site/resources/vendor/, keeping KaTeX'sdist/layout so the stylesheet findsfonts/and the loader finds../katex.min.js:mkdir -p src/site/resources/vendor/mermaid src/site/resources/vendor/katex curl -fsSL -o src/site/resources/vendor/mermaid/mermaid.min.js \ https://cdn.jsdelivr.net/npm/mermaid@11.17.2/dist/mermaid.min.js npm pack katex@0.16.47 --pack-destination /tmp && tar -xzf /tmp/katex-0.16.47.tgz -C /tmp cp -R /tmp/package/dist/katex.min.js /tmp/package/dist/katex.min.css \ /tmp/package/dist/fonts /tmp/package/dist/contrib src/site/resources/vendor/katex/ -
Point the overrides at root-relative paths (or absolute
https://URLs):<supaSkin> <mermaidCdnUrl>/my-project/vendor/mermaid/mermaid.min.js</mermaidCdnUrl> <katexCssCdnUrl>/my-project/vendor/katex/katex.min.css</katexCssCdnUrl> <katexJsCdnUrl>/my-project/vendor/katex/contrib/auto-render.min.js</katexJsCdnUrl> </supaSkin>Replace
/my-project/with the path your site is deployed under (/for a site at the domain root).
[!WARNING] Avoid document-relative values such as
vendor/mermaid/mermaid.min.js. Classic<script src>and<link href>URLs resolve against the current page, so they break on pages in subdirectories (for example, pages fromsrc/site/markdown/guides/*.md)..mjsURLs loaded withimport()resolve againstjs/supa-maven-skin.min.jsinstead and must start with./,../, or/. Root-relative and absolute URLs resolve the same way in all three cases.
Self-hosted URLs load without Subresource Integrity, because the skin only knows the hashes of its pinned defaults. The Configuration Reference lists every loading option, and Content Security Policy lists the origins to allow when you keep the jsDelivr defaults.
Documentation channels
Group project, version, and API links in a named navigation landmark. The native version disclosure works without JavaScript:
<nav class="supa-documentation-channels" aria-label="Documentation channels">
<a href="index.html" aria-current="page">Project home</a>
<a href="https://example.org/versions/">All versions</a>
<a href="api/index.html">API Reference</a>
<details class="documentation-version-picker">
<summary>Version: Current release</summary>
<ul>
<li><a href="dev/index.html">Development</a></li>
<li><a href="release/index.html">Current release</a></li>
</ul>
</details>
</nav>
Replace destinations and labels with your own. Set aria-current="page" only
on a link to the current page. The skin does not discover versions or rewrite
links. The component works inside or outside article prose, inherits all six
palettes and light, dark, or automatic polarity, and is hidden when printed.
On phones, the version list expands in the page flow; long labels wrap.
The existing .documentation-channels class is an equivalent alias. When
adopting this in a site such as the tracer, remove the old channel and
version-picker rules from consumer CSS (including dependencies.css). Keep
unrelated dependency-table styles. Later consumer CSS can otherwise override
the skin's layout and colors.