AsciidoctorJ Documentation
repository·main·Indexed 20 days ago
https://github.com/asciidoctor/asciidoctorjOfficial Java bindings for Asciidoctor that allow developers to convert AsciiDoc content to formats like HTML and PDF or analyze document structures from the JVM. Includes references for the AsciidoctorJ CLI, the Abstract Syntax Tree (AST) class hierarchy, the Table API, and the AsciidoctorModule for registering extensions.
What's inside AsciidoctorJ
- AsciidoctorJ provides Java bindings for Asciidoctor, an implementation of the AsciiDoc format. It uses JRuby to run the Ruby-based Asciidoctor engine on the JVM. AsciidoctorJ bundles all necessary Ruby gems and wraps the functionality into a native Java API, allowing you to use Asciidoctor in Java applications without manually managing Ruby runtimes or gems. It is also available as a standalone distribution that can be downloaded and executed directly.
Supported syntax highlighters in AsciidoctorJ
mainAsciidoctorJ supports several built-in syntax highlighters for rendering source blocks. Since version 2.1.0, AsciidoctorJ also allows you to adapt and plug in custom syntax highlighters when rendering to HTML.What is the Abstract Syntax Tree (AST) in AsciidoctorJ?
mainThe Abstract Syntax Tree (AST) is the intermediate representation of a document created by AsciidoctorJ before it is rendered into a target format (like HTML or PDF). Understanding the AST classes is essential for developers writing extensions or converters, as it defines how the document structure is modeled internally.What is a Preprocessor and how does it work
mainPreprocessors allow you to manipulate raw Asciidoctor source text before the parser and converter process it. This is useful for tasks like making hidden comments visible in draft versions or transforming specific syntax patterns into standard AsciiDoc blocks.
Key Concepts
- Timing: Preprocessors run on the raw input before Asciidoctor parses the document into an Abstract Syntax Tree (AST).
- Independence: Multiple preprocessors can be registered. Because the execution order is undefined, each preprocessor should be designed to be independent of others.
- Mechanism: A preprocessor typically accesses the raw input via a
PreprocessorReader, modifies the content, and returns a new reader containing the processed content to replace the original input.
What is a Postprocessor and when is it used
mainPostprocessors are extension points called after Asciidoctor has completed the conversion of a document to its target format. They allow you to modify the final output (e.g., inserting a custom copyright notice into an HTML footer) before the result is returned to the user.
Important Limitations:
- String-based formats only: Postprocessors currently only support target formats that are string-based (like HTML). You cannot write Postprocessors for binary formats such as PDF or EPUB.
Use positional and named attributes in block macros
mainBlock macros can support attributes that are either passed by their position within the brackets or by explicitly naming them.
For example, if a macro defines
providerandrepoas positional attributes:- Positional:
gist::target[github, myrepo[](wheregithubis the first attribute andmyrepois the second). - Named:
gist::target[provider="gitlab", repo="project/repo"].
When implementing this in a
BlockMacroProcessor, you can extract these values from the macro's attributes to compute the final output content.// Positional attributes gist::mygithubaccount/8810011364687d7bec2c[github, myrepo] // Named attributes gist::mygithubaccount/8810011364687d7bec2c[provider="gitlab", repo="gitlab-org/gitlab-foss"]- Positional:
Access document metadata via the Catalog
mainDuring conversion, you can access document-wide metadata through the
Catalogobject, which is available viaDocument.getCatalog(). This is useful for rendering elements like footnotes or anchors.Available catalog methods:
getFootnotes(): Returns a list of footnotes. Note that these are only available afterDocument.getContent()has been called.getRefs(): Returns a map of IDs to document elements. This is used to resolve inline anchors and link to specific document targets (like sections or explicitly assigned IDs).
Shutdown and destroy an Asciidoctor instance
mainAsciidoctor instances manage a Ruby runtime that consumes resources. You must explicitly release these resources using the
shutdown()method. Onceshutdown()is called, all subsequent method calls on that instance will fail.Because
Asciidoctorimplementsjava.io.AutoCloseable, the recommended way to ensure resources are freed is to use a try-with-resources block, which automatically callsshutdown().// Explicit shutdown String html = asciidoctor.convert("content", options); asciidoctor.shutdown(); // Recommended: Automatic shutdown using try-with-resources try (Asciidoctor asciidoctor = Asciidoctor.Factory.create()) { String html = asciidoctor.convert("content", options); }How to adapt a custom syntax highlighter
mainTo implement a custom syntax highlighter adapter for AsciidoctorJ (HTML rendering), you must implement a subset of the following core tasks:
- Resource Management: Include the necessary stylesheets and scripts into the resulting HTML document.
- File-based Assets: Create stylesheet and script resources on the filesystem if the document is rendered to a file and uses the
:linkcssand:copycssattributes. - Block Formatting: Wrap source block elements in
<pre/>and<code>elements with specific attributes. For example, convertingputs "Hello World"to<pre class="highlightme"><code class="language">puts "Hello World"</code></pre>. - Text Tokenization: Format the source text itself by mapping it to
<span>elements (e.g., convertingputs "Hello World"to<span class="id">puts</span> <span class="stringliteral">"Hello World"</span>).
When external stylesheets are written to the filesystem
mainExternal stylesheets are not written for every conversion. They are only written to the target directory when the following conditions are met:
- The conversion target is a file (not a stream or a string).
- The AsciiDoc attributes
:linkcssand:copycssare both set. - The highlighter implements
org.asciidoctor.syntaxhighlighter.StylesheetWriterandisWriteStylesheet()returnstrue.
Implement a Block extension in Ruby
mainWhen writing a Ruby extension for AsciidoctorJ, your class should inherit from
Asciidoctor::Extensions::BlockProcessor.You can use the
optionmethod to define the:contexts(e.g.,[:paragraph]) and the:content_model(e.g.,:simple). Theprocessmethod is then responsible for transforming the input using theparent,reader, andattributesarguments, typically returning a newAsciidoctor::Blockobject.require 'asciidoctor' require 'asciidoctor/extensions' class YellRubyBlock < Asciidoctor::Extensions::BlockProcessor option :contexts, [:paragraph] option :content_model, :simple def process(parent, reader, attributes) lines = reader.lines.map { |line| line.upcase.gsub(/\.( |$)/, '!\1') } Asciidoctor::Block.new(parent, :paragraph, :source => lines, :attributes => attributes) end endHow block macros work
mainA block macro is a specific type of block in AsciiDoc used to trigger custom processing. The syntax structure is:
macro-name::target[attributes]- Macro name: The identifier (e.g.,
gist). - Two colons:
::separates the name from the target. - Target: The specific resource identifier (e.g.,
mygithubaccount/8810011364687d7bec2c). - Attributes: Optional parameters enclosed in square brackets
[].
- Macro name: The identifier (e.g.,