- Usage
- Features
- Standalone HTML Output
- Asciidoctor-Compatible Styling
- Full AsciiDoc Support
- Section Numbering
- Syntax Highlighting
- Stylesheets
- Docinfo files
- Customizing the CSS
- Content Security Policy
- Table Enhancements
- Substitution Control
- Icon support
- Mathematical Formulas (Stem)
- Semantic HTML5 Output (
html5s) - Document Attributes
- Performance Timing
- Output Structure
- Examples
- Technical Details
- Differences from Asciidoctor
HTML converter for AsciiDoc documents. This is the default backend for acdc.
acdc convert document.adocThis generates document.html in the same directory as the source file.
You can also convert multiple files at once:
acdc convert *.adocOr convert from stdin to stdout:
cat document.adoc | acdc convert --stdinGenerates complete, standalone HTML documents with embedded CSS. No external dependencies needed - the output file contains everything required for display.
Uses the same CSS as Asciidoctor for familiar, professional-looking output. The embedded stylesheet provides:
-
Clean, readable typography
-
Responsive layout
-
Syntax highlighting support
-
Print-optimized styles
Supports all major AsciiDoc constructs:
-
Document structure: Headers, sections, table of contents
-
Text formatting: Bold, italic, monospace, highlighting, subscript, superscript
-
Lists: Unordered, ordered, description lists, callout lists
-
Blocks: Listings, literals, examples, quotes, sidebars, open blocks
-
Admonitions: NOTE, TIP, IMPORTANT, WARNING, CAUTION (with Font Awesome icons when
:icons: font) -
Media: Images, videos (YouTube, Vimeo), audio
-
Tables: Full table support with headers, footers, cell formatting, cell spanning, and nested tables
-
Cross-references: Internal links and anchors
-
Attributes: Document-level attribute substitution
-
Index terms: Visible
termand concealed(term,secondary,tertiary)with catalog generation
Documents with :sectnums: render numbered section headings (e.g., "1. Introduction", "1.1. Overview"). Control numbering depth with :sectnumlevels: (default 3, max 5).
acdc convert -a sectnums -a sectnumlevels=2 document.adocTable of contents entries are also numbered when :sectnums: is set.
Source blocks with a language specified render with syntax highlighting (requires the highlighting feature flag). Uses syntect with inline CSS styles.
cargo build --features highlighting
acdc convert document.adocFalls back to plain text when the language isn’t recognized.
The HTML converter handles CSS output through document attributes, matching Asciidoctor’s stylesheet modes. By default, CSS is embedded directly in the HTML <style> tag, no external files needed.
|
Note
|
Stylesheet handling only applies to standalone HTML output. In embedded mode (acdc convert --embedded), the <head> element is not generated, so stylesheet attributes have no effect on the output. copycss is also skipped.
|
Out of the box, acdc embeds the full stylesheet and links Google Fonts:
acdc convert document.adocThe output is self-contained, one HTML file with everything included.
Set :linkcss: to reference CSS via a <link> tag instead of embedding it. The built-in stylesheet is automatically written to disk next to the HTML output (see link mode):
acdc convert -a linkcss document.adocOr in the document header:
= My Document
:linkcss:This produces a <link rel="stylesheet" href="./asciidoctor-light-mode.css"> in the HTML and copies the CSS file alongside the output.
Point to your own CSS file with :stylesheet:. When combined with :linkcss:, it links to the file. Without :linkcss:, the file is read from disk and embedded (see custom stylesheet):
# Embed custom CSS
acdc convert -a stylesheet=custom.css document.adoc
# Link to custom CSS
acdc convert -a linkcss -a stylesheet=custom.css document.adocThe converter looks for the file relative to :stylesdir: (default: .) and the source document directory. If the file can’t be read, it falls back to the built-in stylesheet.
Suppress all CSS and webfont output entirely (see disable mode):
acdc convert -a stylesheet! document.adocOr in the document:
= My Document
:!stylesheet:No <style> block, no <link> tags for CSS or fonts, just raw HTML.
Controls where stylesheet references point and where copies are written (see stylesdir):
acdc convert -a linkcss -a stylesdir=css document.adocProduces <link rel="stylesheet" href="css/asciidoctor-light-mode.css"> and writes the CSS to css/.
When :linkcss: is set, :copycss: controls whether the stylesheet is written to the output directory. It’s enabled by default. A non-empty value overrides the source path, useful when the CSS lives somewhere other than :stylesdir: (see copycss):
# Copy from a custom location
acdc convert -a linkcss -a copycss=/path/to/source.css document.adocBy default, the converter links Google Fonts (Open Sans, Noto Serif, Droid Sans Mono). You can customize or disable this (see webfonts):
# Disable webfonts
acdc convert -a webfonts! document.adoc
# Custom font families
acdc convert -a "webfonts=Roboto:400,700|Fira+Code:400" document.adocWebfonts are suppressed automatically when :!stylesheet: is set.
Set :dark-mode: to use the dark variant of the built-in stylesheet. This adds a <meta name="color-scheme" content="dark"> tag and uses asciidoctor-dark-mode.css (or html5s-dark-mode.css for the semantic backend):
acdc convert -a dark-mode document.adocTwo separate switches are involved:
-
The
terminalCargo feature is a build-time feature flag. It compiles the HTML terminal renderer. From the CLI this is thehtml-terminalfeature, which just enables this crate’sterminalfeature. -
The
:acdc-terminal:document attribute is only a source-block opt-in. It makes terminal-like source blocks render through that terminal renderer.
When the Cargo feature is enabled, acdc supports two terminal-looking HTML render paths:
-
Source blocks such as
[source,console]render as terminal previews only when the document sets:acdc-terminal:. -
[terminal]is an explicit block style for terminal session content. It renders as terminal output whenever theterminalCargo feature is enabled; the:acdc-terminal:document attribute is not required.
This is an acdc-only extension; Asciidoctor does not provide a
:acdc-terminal: attribute, the [terminal] or [terminal%replay] block
styles, or any equivalent built-in terminal preview or replay feature.
|
Note
|
Terminal rendering is built directly into the HTML converter, the
terminal Cargo feature of acdc-converters-html, backed by the
acdc-converters-terminal crate, rather than being loaded as a plug-in. If
acdc grows a first-class extension mechanism, this functionality may migrate to
an extension instead of being compiled into the converter.
|
Use :acdc-terminal: when existing source blocks should look like terminal
examples:
= Demo
:acdc-terminal:
:acdc-terminal-cols: 88
[source,console]
----
$ acdc --version
acdc 0.2.0
----Terminal previews are supported for terminal-like source languages such as
console, terminal, shell, sh, bash, zsh, fish, powershell,
ps1, and cmd.
Use [terminal] when the block content is a terminal session transcript or
captured terminal output:
[terminal,cols=80,rows=24]
----
$ cargo build --release
Compiling acdc v0.2.0
Finished release [optimized] in 2.34s
$ echo done
done
----The terminal session content is interpreted as terminal output, including ANSI escape sequences, and rendered as selectable styled HTML.
Use [terminal%replay] when the block contains pre-recorded ANSI output that
should be animated in HTML:
[terminal%replay,cols=80,rows=24]
----
\x1b[32mDownloading\x1b[0m
\x1b[32mComplete\x1b[0m
----Terminal replay is replay-only. acdc treats the block as recorded terminal
data and does not execute commands, shells, scripts, VHS tapes, or other
recording formats. Replay blocks require explicit terminal dimensions via
cols/rows block attributes or :acdc-terminal-cols:/:acdc-terminal-rows:
document attributes; invalid or missing dimensions fall back to a static
terminal preview with a structured warning.
Both formats render as an animated HTML replay driven by a small,
self-contained inline player. The final frame is rendered into the page
server-side, so readers without JavaScript (or who prefer reduced motion) still
see the finished screen; only the animation is lost. The raw-ANSI replay samples
dense recordings so the generated HTML stays small even for long output;
format=asciicast keeps every recorded frame and stays compact by emitting each
repeated line once and referencing it per frame. acdc draws no window chrome;
the recorded title (asciicast only) is exposed as a data-title attribute so
you can add your own.
For format=asciicast, the recording is replayed at its own recorded size so
its cursor movements render faithfully, then rows is the height of a window
that follows the output like a scrolling terminal: when the recording is taller
than rows, the replay shows the most recent rows lines and rests on the
last lines of output (it does not freeze on a region the recording cleared at
the end, such as a progress bar’s live area).
[terminal] and [terminal%replay] are acdc-only block styles. Asciidoctor
renders them as a plain listing or literal block with the raw text (ANSI escapes
included) left as-is, so documents that rely on them will not render the same
under asciidoctor.
|
Note
|
Terminal rendering runs the bundled terminal emulator only below the |
| Attribute | Effect |
|---|---|
|
Enables terminal preview rendering for terminal-like source blocks only. |
|
Sets the terminal grid width used to render source-block previews and |
|
Sets a fixed terminal grid height for source-block previews and |
|
Uses dark terminal shell colors for both source-block previews and |
|
Overrides the terminal grid width for one explicit terminal session block. |
|
Overrides the terminal grid height for one explicit terminal session block. When unset, acdc derives the height from the content. |
|
Renders pre-recorded ANSI terminal output as an animated replay. Replay blocks require fixed dimensions and never execute commands or recording files. |
|
Overrides the generated replay’s total playback duration in milliseconds. |
When using class-based syntax highlighting (:syntect-css: class), the highlighting CSS is handled the same way, embedded by default, or linked/written to disk when :linkcss: is set. See the Syntax Highlighting section above.
Docinfo files let you inject custom HTML into specific positions in the output, analytics snippets, custom <meta> tags, banners, footers, or anything else that doesn’t belong in the AsciiDoc source itself.
Enable docinfo with the :docinfo: document attribute:
= My Document
:docinfo: sharedThe :docinfo: attribute accepts:
-
shared: load shared docinfo files (used across all documents) -
private: load private docinfo files (specific to this document). This is the default when:docinfo:is set with no value -
Granular values:
shared-head,shared-header,shared-footer,private-head,private-header,private-footer -
Comma-separated combinations:
shared, private-footer
Docinfo files follow a naming convention based on scope and injection position:
| Position | Shared filename | Private filename |
|---|---|---|
Head (before |
|
|
Header (after |
|
|
Footer (before |
|
|
For a document named guide.adoc, the private head file would be guide-docinfo.html.
By default, docinfo files are loaded from the same directory as the source document. Set :docinfodir: to load them from a different location:
= My Document
:docinfo: shared
:docinfodir: _docinfoThe path is resolved relative to the source document directory, or can be absolute.
Docinfo content is processed with attribute substitution by default, {attribute-name} references in docinfo files are replaced with their values. Control this with :docinfosubs::
= My Document
:docinfo: shared
:docinfosubs: attributes|
Note
|
Currently only attributes substitution is supported for docinfo content.
|
-
Head: injected just before the closing
</head>tag -
Header: injected immediately after the opening
<body>tag -
Footer: injected just before the closing
</body>tag
When both private and shared files exist for the same position, private content is injected first.
|
Note
|
Docinfo is disabled when running in secure safe mode (--safe-mode secure). In embedded mode, head docinfo has no effect since the <head> element is not generated.
|
For full details, see the Asciidoctor docinfo documentation.
The output is class-based, so you can restyle it without forking the converter. Use whichever seam fits:
-
Override specific rules. Load your own stylesheet after acdc’s and target its classes. Body content uses the standard Asciidoctor classes (
.listingblock,.admonitionblock,.tableblock, and so on). The terminal preview and replay expose a stable class/attribute contract:Classes
Both share the base
.terminal-viewand a theme class (.terminal-view—light/.terminal-view—dark), and the block wrapper carries.terminal-block. Static preview adds.terminal-viewscreen(the<pre>). Replay adds the.terminal-view—replaymarker and.terminal-viewviewport>.terminal-viewstream>.terminal-viewrow.Attributes
data-title(the recorded title, asciicast only, present only when the recording carried one) for building your own title bar, e.g..terminal-view—replay::before{content:attr(data-title)} -
Replace the whole stylesheet. Use
:stylesheet: my.css(see Custom stylesheet (:stylesheet:)), embedded or linked with:linkcss:.:copycss:copies the built-in CSS out as a starting point. -
Augment the
<head>. Inject extra<style>/<link>with Docinfo files (:docinfo: shared-head). -
Embedded mode. There is no
<head>, so the embedding page owns the stylesheet. Override acdc’s classes from your page’s own CSS.
Most output is class-based and fully overridable by the seams above. A few elements carry an inline style= attribute, which beats any stylesheet rule (embedded, linked, replaced, or injected via docinfo) unless your rule uses !important:
| Inline-styled | How to override |
|---|---|
Syntax-highlighted code colours |
Inline is the default; set |
A recording’s own colours |
The cell palette, plus a replay container’s background/foreground when the cast recorded a theme; use |
Table column and table widths |
Per-table values (matches Asciidoctor); use |
Page break; image |
Match Asciidoctor’s output; use |
The static preview container’s colours are not inline: they come from .terminal-view—light / .terminal-view—dark, so override those classes directly. A replay with no recorded theme (raw ANSI, or a theme-less cast) uses those same classes; only a cast that carried its own theme paints the container colours inline.
For example, to recolour terminal cells:
.terminal-view__screen span { color: #eaeaea !important; }|
Note
|
With :!stylesheet: (all CSS suppressed) the static preview shows no colours, consistent with opting out of styling entirely.
|
By default acdc sets no CSP; the policy is up to whatever serves the file (your web server, CDN, or the page you embed into), exactly like Antora.
Set :csp: to have acdc emit a self-contained <meta http-equiv="Content-Security-Policy"> that hardens standalone output with no server configuration:
acdc convert -a csp document.adocThe emitted policy locks scripts to acdc’s own inline scripts by hash (no 'unsafe-inline' for script-src), plus the MathJax CDN when :stem: is set; keeps style-src 'unsafe-inline' (acdc emits inline styles, including recording-coloured terminal cells, that cannot be hashed); and stays permissive on images, media, and video embeds so document content keeps loading.
Keep in mind a CSP only restricts — it does not enable. A page with no CSP already runs anywhere, and a <meta> CSP cannot loosen a policy your host sends as a response header (the browser enforces the intersection). So :csp: is for shipping a hardened, self-contained page, not for "making it work" somewhere. Two consequences: frame-ancestors is omitted (it is ignored in a <meta> CSP — set it as a header), and an inline <script> you inject via Docinfo files will not run under :csp: unless you add its own hash. Embedded output has no <head>, so :csp: is standalone-only.
To set the CSP via a server header instead (or in embedded mode), a baseline that covers everything acdc emits:
default-src 'self';
script-src 'self' 'unsafe-inline';
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
font-src 'self';
connect-src 'self';
frame-ancestors 'none''unsafe-eval' is never needed. Add the entries below only when you use the matching feature:
| Feature | CSP additions |
|---|---|
Webfonts (on by default) |
add |
|
add |
|
add |
Remote or data-URI images |
adjust |
For a fully self-contained policy with no external origins, disable webfonts (:!webfonts:) and skip :stem: and icons=font. The baseline above then needs nothing extra.
To keep script-src off 'unsafe-inline', allowlist acdc’s two constant inline scripts by hash instead: the terminal-replay player (acdc_converters_html::REPLAY_PLAYER_SCRIPT_CSP_HASH) and, with :stem:, the MathJax config (MATHJAX_CONFIG_CSP_HASH). For assembling your own head (embedded mode), the converter also exposes the script strings and the MathJax loader URL (REPLAY_PLAYER_SCRIPT, MATHJAX_CONFIG_SCRIPT, MATHJAX_LOADER_URL), and a content_security_policy(&CspFeatures { .. }) builder that produces the same policy :csp: emits for the features a document uses. If the player script is blocked, the replay still shows its final frame and only the animation is lost.
Full table feature support:
-
Cell spanning: colspan (
2+|), rowspan (.2+|), combined (2.3+|) -
Visual attributes:
frame,grid,stripes,width,%autowidth -
Nested tables: Using
!===delimiter in AsciiDoc cells -
Cell-level formatting: Alignment, styles (strong, emphasis, monospace, etc.)
Verbatim blocks (listing, literal) support the subs attribute:
-
subs=none- disable all substitutions, output raw content -
subs=+quotes- enable inline formatting in code blocks -
subs=+attributes- enable attribute expansion -
subs=+replacements- enable typography (arrows, dashes, ellipsis)
When :icons: font is set, icon macros render as Font Awesome <i> elements. By default the icon uses fa-solid, but you can select a specific FA family with the set (or pack) attribute on the macro:
:icons: font
icon:github[set=fab]
icon:heart[set=far]
icon:bolt[]This produces fa-brands fa-github, fa-regular fa-heart, and fa-solid fa-bolt respectively.
You can also set a document-level default with :icon-set: (or :icon-pack:), which applies to all icons that don’t specify their own set:
:icons: font
:icon-set: brands
icon:github[]
icon:heart[set=far]Here github uses the document default (fa-brands), while heart overrides it with fa-regular.
Both shorthand and long-form values are supported:
| Value | CSS class |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For details on the icon macro syntax, see the AsciiDoc icon macro documentation. For available icons per family, see the Font Awesome icon gallery.
Render mathematical formulas using MathJax 4. Enable it by setting the :stem: document attribute.
= My Document
:stem: latexmathThe :stem: attribute accepts:
-
latexmath- use LaTeX notation -
asciimath- use AsciiMath notation -
(empty) - defaults to
latexmathfor blocks,asciimathfor inline
Inline formulas use the stem:[] macro:
The solution is stem:[x = (-b +- sqrt(b^2 - 4ac)) / (2a)].Block formulas use the [stem] attribute on a passthrough block:
[stem]
++++
x = (-b +- sqrt(b^2 - 4ac)) / (2a)
++++When enabled, MathJax is loaded from the jsdelivr CDN (cdn.jsdelivr.net/npm/mathjax@4) and renders formulas client-side. LaTeX uses \(…\) and \[…\] delimiters; AsciiMath uses \$…\$.
To suppress MathJax processing on specific elements, add the CSS class nostem, nolatexmath, or noasciimath.
An alternative backend that produces semantic HTML5 instead of the traditional div-based layout, inspired by Jakub Jirutka’s asciidoctor-html5s gem for Asciidoctor. Enable it with --backend html5s:
acdc convert --backend html5s document.adocKey differences from the standard backend:
-
Sections use
<section>elements instead of<div class="sectN"> -
Admonitions use
<aside>(note, tip) or<section>(warning, important, caution) with ARIA roles -
Images use
<figure>and<figcaption>instead of<div class="imageblock"> -
Example blocks use
<figure>instead of<div class="exampleblock"> -
Sidebars use
<aside>instead of<div class="sidebarblock"> -
Callout lists use
<ol>instead of a table layout -
Titled paragraphs are wrapped in
<section>with<h6 class="block-title"> -
Block titles use
<h6 class="block-title">instead of<div class="title">
The semantic variant ships with its own stylesheet (light and dark mode) and supports a few additional document attributes:
-
:html5s-force-stem-type:: override the stem notation (latexmathorasciimath) regardless of the:stem:value -
:html5s-image-default-link: self: make all images link to themselves by default -
:html5s-image-self-link-label:: custom aria label for self-linked images (default: "Open the image in full size")
Set document attributes via command line:
acdc convert -a toc=left -a toclevels=3 -a icons=font document.adocGenerated HTML includes:
-
Complete HTML5 document structure
-
Embedded CSS for styling
-
Metadata (generator, last updated timestamp)
-
Table of contents (if enabled via
:toc:attribute) -
Semantic HTML elements matching AsciiDoc structure
The HTML converter:
-
Generates valid HTML5
-
Preserves source line information for debugging
-
Handles Unicode correctly
-
Auto-numbers example blocks
-
Generates unique IDs for sections and anchors
-
Embeds the Asciidoctor CSS stylesheet for consistent styling
-
Includes file modification timestamps in metadata
While the HTML converter aims for compatibility with Asciidoctor, there are some known differences and limitations.
-
The
css-signatureattribute is not supported. Use a document ID instead (above the title). -
Syntax highlighting uses syntect with inline CSS styles rather than external highlight.js or Pygments. Language coverage may differ.
-
The
html5sbackend is inspired by Jakub Jirutka’s asciidoctor-html5s gem but is a separate implementation with its own output.