Format the Source Block Element

highlight.js tries to automatically determine the source language, which might fail or result in wrong matches. To help highlight.js in identifying the correct source language the <code/> element can be annotated with the language as a class.

That means instead of simply wrapping the code in <pre/> and <code/> elements we want to wrap it inside <pre> and <code class="java"/>. To allow Asciidoctor to apply the styles to properly embed a source block inside the document, the <pre/> element should also have the class highlight. Therefore we want to wrap the source text inside this construct:

<pre class="highlight">
  <code class="java">

To allow a syntax highlighter to create this construct it also has to implement the interface org.asciidoctor.syntaxhighlighter.Formatter:

import org.asciidoctor.syntaxhighlighter.Formatter;
import org.asciidoctor.syntaxhighlighter.SyntaxHighlighterAdapter;

import java.util.Map;

public class HighlightJsWithLanguageHighlighter implements SyntaxHighlighterAdapter, Formatter { (1)

    // Methods hasDocInfo() and getDocInfo()

    public String format(Block node, String lang, Map<String, Object> opts) {
        return "<pre class='highlight'><code class='" + lang + "'>" (2)
            + node.getContent()                                     (3)
            + "</code></pre>";
1 The SyntaxHighlighterAdapter also has to implement the interface Formatter. This interface only requires the implementation of the method format() that receives the org.asciidoctor.ast.Block that is highlighted, the source language, and additional options.
2 The implementation of format() wraps everything in a <pre/> and <code/> element with the required classes. The value for the class of the <code/> element is the source language which is passed as an argument to the method.
3 The source text to be nested into the <pre/> and <code/> elements has to be obtained using node.getContent(). This guarantees that further processing like substitutions work properly.