AsciidoctorJ v3.0.x migration guide
AsciidoctorJ v3.0.0 introduces breaking changes. This guide will provide the steps required to update a project currently using 2.5.x version.
Update Preprocessors
In earlier versions of AsciidoctorJ (up to 2.5.x), Preprocessors were provided with a Reader
object that they had to modify directly.
Unlike the Ruby implementation, the Java implementation of Asciidoctor did not support Preprocessors to return a new Reader
.
To address this limitation, AsciidoctorJ 3.0.0 has introduced a fix, enabling Preprocessors to create and return a new Reader
.
This enhancement allows Preprocessors to have more flexibility and enables a cleaner implementation.
If you have existing Preprocessors, it is essential to update the signature of their process method to return a Reader object, even if the implementation does not create a new Reader object and returns null.
The following example shows how to update a Preprocessor to return a new Reader
:
public static class MyPreprocessor extends Preprocessor {
@Override
public void process(Document document, PreprocessorReader reader) {
// Do something with the reader
}
}
To ensure compatibility with AsciidoctorJ 3.0.0, the process method of the Preprocessor needs to be modified to return a Reader
.
However, if you wish to maintain the same behavior as before, the method can simply return null
.
public static class MyPreprocessor extends Preprocessor {
@Override
public Reader process(Document document, PreprocessorReader reader) {
// Do something with the reader
return null;
}
}
You may find it helpful to review the methods Processor::newReader
and PreprocessorReader::read
to simplify your code when creating a new Reader
and reading the content of the existing Reader
.
However, please note that following the steps mentioned above will be sufficient to migrate your existing processor.
Update Macro Processors
In the earlier version of AsciidoctorJ (2.5.x), the signature of Macro Processors required the implementation to return an unrestricted Object. However, the specific type that a Macro Processor had to return was unclear, making it difficult to understand the necessary implementation steps.
To address this issue, AsciidoctorJ 3.x.x has introduced the following changes:
InlineMacroProcessor::process
-
The implementation of this method now needs to return a
PhraseNode
. Please update your code accordingly to ensure that the returned value is of typePhraseNode
. BlockMacroProcessor::process
-
The implementation of this method now needs to return a
StructuralNode
. Make sure to modify your implementation to return aStructuralNode
as required.
Moreover, there was a problem with the first parameter of the process method in InlineMacroProcessors.
Previously, it incorrectly expected a PhraseNode
as the first parameter.
To resolve this issue, AsciidoctorJ 3.x.x has rectified the first parameter of InlineMacroProcessor::process
to be a StructuralNode
.
Please ensure that you update your code accordingly to reflect this change.
If you have any further questions or concerns, please refer to the updated documentation.
Update Inline Macro Processors
If your existing InlineMacroProcessor looks like this for AsciidoctorJ 2.5.x:
public class TestInlineMacro extends InlineMacroProcessor {
@Override
public Object process(ContentNode parent, String target, Map<String, Object> attributes) {
return createPhraseNode(parent, "quoted", "This is from an Inline Macro");
}
}
then you have to change it to this for AsciidoctorJ 3.x.x:
public class TestInlineMacro extends InlineMacroProcessor {
@Override
public PhraseNode process(StructuralNode parent, String target, Map<String, Object> attributes) {
return createPhraseNode(parent, "quoted", "This is from an Inline Macro");
}
}
In the above example you can see that the return type and the type of the first parameter of the process method have changed.
Update Block Macro Processors
If your existing BlockMacroProcessor looks like this for AsciidoctorJ 2.5.x:
public class TestBlockMacro extends BlockMacroProcessor {
@Override
public Object process(StructuralNode parent, String target, Map<String, Object> attributes) {
return createBlock(parent, "paragraph", "This is from a Block Macro");
}
}
then you have to change it to this for AsciidoctorJ 3.x.x:
public class TestBlockMacro extends BlockMacroProcessor {
@Override
public StructuralNode process(StructuralNode parent, String target, Map<String, Object> attributes) {
return createBlock(parent, "paragraph", "This is from a Block Macro");
}
}
Removal of deprecated methods in org.asciidoctor.Options
Several methods in org.asciidoctor.Options
class that were marked as @Deprecated
have been removed.
This has been done to remove duplicated features and simplify the API interaction.
Simplification of Options initialization
In v2.5.x the following alternatives to initialize Options
where possible:
Options options = new Options();
options.setBackend("html5");
options.setSafe(SafeMode.UNSAFE);
options.setMkDirs(true);
Map<String, Object> optionsMap = new HashMap<>();
optionsMap.put("backend", "html5");
optionsMap.put("sage", SafeMode.UNSAFE);
optionsMap.put("mkdirs", true);
Options options = new Options(optionsMap);
Options options = OptionsBuilder.options()
.backend("html5")
.mkDirs(true)
.safe(SafeMode.UNSAFE)
.get();
The new API streamlines the process with a more standard builder approach, in which
-
Only interaction with
org.asciidoctor.Options
is required. -
Nested methods offer IDE completion and creation of immutable instances.
-
Improved code readability through indentation.
From v3.0.x, use the new builder()
and build()
methods from org.asciidoctor.Options
.
Options options = Options.builder()
.backend("html5")
.mkDirs(true)
.safe(SafeMode.UNSAFE)
.build();
Note that Options
setter methods are still available, that means that Options
instances can still be modified as in this example.
Options options = Options.builder().build();
options.setBackend("html5");
options.setSafe(SafeMode.UNSAFE);
options.setMkDirs(true)
Free key-value insertion is still possible using:
|
Simplification of Attributes injection in Options
The previous API offered the following ways to inject attributes to an Options
instance.
Attributes attributes = new Attributes();
options.setAttributes(attributes);
Map<String, Object> attributesMap = new HashMap<>();
attributesMap.put("toclevels", 2);
attributesMap.put("icons", "font");
options.setAttributes(attributesMap);
Also, in v2.5.x it is possible to pass attributes to an OptionsBuilder
.
Attributes attributes = new Attributes();
Options options = OptionsBuilder.options()
.attributes(attributes)
.get();
Map<String, Object> attributesMap = new HashMap<>();
attributesMap.put("toclevels", 2);
attributesMap.put("icons", "font");
Options options = OptionsBuilder.options()
.attributes(attributesMap)
.get();
AttributesBuilder attributesBuilder = AttributesBuilder.attributes();
Options options = OptionsBuilder.options()
.attributes(attributesBuilder)
.get();
All these alternatives have been unified in two methods for Options
and one for OptionsBuilder
.
Attributes attributes = Attributes.builder()
.icons("font")
.build();
Options options = Options.builder().build();
options.setAttributes(attributes);
Map<String, Object> attributesMap = new HashMap<>();
attributesMap.put("toclevels", 2);
attributesMap.put("icons", "font");
Options options = Options.builder().build();
options.setAttributes(attributesMap);
Attributes attributes = Attributes.builder()
.icons("font")
.build();
Options options = Options.builder()
.attributes(attributes)
.build();
Free key-value or string insertion is still possible using:
|
Removal of deprecated methods in org.asciidoctor.Attributes
Several methods in org.asciidoctor.Attributes
class that were marked as @Deprecated
have been removed.
This has been done to remove duplicated features and simplify the API interaction.
Simplification of Attributes initialization
In v2.5.x the following alternatives to initialize Attributes
where possible:
Attributes attributes = new Attributes();
attributes.setIcons("font");
attributes.setNoFooter(true);
Map<String, Object> attributesMap = new HashMap<>();
attributesMap.put("toclevels", 2);
attributesMap.put("icons", "font");
Attributes attributes = new Attributes(attributesMap);
Attributes attributes = AttributesBuilder.attributes()
.icons("dont")
.noFooter(true)
.get();
The new API streamlines the process with a more standard builder approach, in which
-
Only interaction with
org.asciidoctor.Attributes
is required. -
Nested methods offer IDE completion and creation of immutable instances.
-
Improved code readability through indentation.
From v3.0.x, use the new builder()
and build()
methods from org.asciidoctor.Attributes
.
Attributes attributes = Attributes.builder()
.icons("dont")
.noFooter(true)
.build();
Note that Attributes
setter methods are still available, that means that Attributes
instances can still be modified as in this example.
Attributes attributes = Attributes.builder().build();
attributes.setIcons("font");
attributes.setNoFooter(true);
Free key-value insertion is still possible using:
|
Removal of asMap
from OptionsBuilder and AttributesBuilder
In v2.5.x it is possible to obtain the backing Map<String,Object>
for both options and attributes.
Map<String, Object> optionsMap = Options.builder()
.backend("html5")
.mkDirs(true)
.safe(SafeMode.UNSAFE)
.asMap();
Map<String, Object> attributesMap = Attributes.builder()
.icons("font")
.sectionNumbers(true)
.asMap();
To remove feature duplication and avoid confusion between values in the actual org.asciidoctor.Attributes
and org.asciidoctor.Options
and their respective builders, asMap
it’s no longer available in both builders.
To obtain the backing up, use the map()
method from the actual org.asciidoctor.Attributes
and org.asciidoctor.Options
instances.
Options::map() and Attributes::map() are marked as deprecated and subject to change at some point, but are still maintained and safe to use in v3.0.x.
|
Options options = Options.builder()
.backend("html5")
.mkDirs(true)
.safe(SafeMode.UNSAFE)
.build();
Map<String, Object> optionsMap = options.map();
Attributes attributes = Attributes.builder()
.icons("font")
.sectionNumbers(true)
.build();
Map<String, Object> attributesMap = attributes.map();
Removal of deprecated methods in org.asciidoctor.Asciidoctor
Several methods in org.asciidoctor.Asciidoctor
that were marked as @Deprecated
have been removed.
Removal of methods using Map<String,Object>
as options input
To streamline the API, only methods using Options
instances have been left in the org.asciidoctor.Asciidoctor
.
That means that the following methods are no longer available.
String convert(String content, Map<String, Object> options);
String convertFile(File file, Map<String, Object> options);
void convert(Reader contentReader, Writer rendererWriter, Map<String, Object> options) throws IOException;
<T> T convert(String content, Map<String, Object> options, Class<T> expectedResult);
<T> T convertFile(File file, Map<String, Object> options, Class<T> expectedResult);
String[] convertDirectory(Iterable<File> directoryWalker, Map<String, Object> options);
String[] convertFiles(Collection<File> files, Map<String, Object> options);
Document load(String content, Map<String, Object> options);
Document loadFile(File file, Map<String, Object> options);
For each of the methods above there’s an equivalent using org.asciidoctor.Options
.
Use those when migrating to v3.0.0.
Removal of methods using OptionsBuilder
as options input
Likewise to the methods seen in the previous section, the following methods are also no longer available.
String convert(String content, OptionsBuilder options);
String convertFile(File file, OptionsBuilder options);
void convert(Reader contentReader, Writer rendererWriter, OptionsBuilder options) throws IOException;
<T> T convert(String content, OptionsBuilder options, Class<T> expectedResult);
<T> T convertFile(File file, OptionsBuilder options, Class<T> expectedResult);
String[] convertDirectory(Iterable<File> directoryWalker, OptionsBuilder options);
String[] convertFiles(Collection<File> files, OptionsBuilder options);
For each of the methods above there’s an equivalent using org.asciidoctor.Options
.
Use those when migrating to v3.0.0.
Removal of methods readDocumentHeader
All implementations of Asciidoctor::readDocumentHeader
have been removed because the same feature can be obtained using load
with the parse_header_only
option.
Options options = Options.builder().option("parse_header_only", true).build();
Document document = asciidoctor.loadFile(documentHeaders, options);
List<Author> authors = document.getAuthors();
RevisionInfo revisionInfo = document.getRevisionInfo();
String doctitle = document.getDoctitle();
Title structuredDoctitle = document.getStructuredDoctitle();
As a consequence, class org.asciidoctor.ast.DocumentHeader
has been also removed.
Removal of deprecated methods in org.asciidoctor.ast.Document
Several methods in org.asciidoctor.ast.Document
that were marked as @Deprecated
have been removed.
For each of the removed methods, the equivalent can be found below.
String doctitle()
boolean basebackend(String backend)
String getDoctitle()
boolean isBasebackend(String backend)
Removal of deprecated constants from org.asciidoctor.extension.BlockProcessor
All constants in org.asciidoctor.extension.BlockProcessor
class that were marked as @Deprecated
have been removed.
You can find the new values in org.asciidoctor.extension.Contexts
interface.
See the table below for the equivalencies.
Deprecated value | Contexts value |
---|---|
CONTEXTS |
KEY |
CONTEXT_OPEN |
OPEN |
CONTEXT_EXAMPLE |
EXAMPLE |
CONTEXT_SIDEBAR |
SIDEBAR |
CONTEXT_LITERAL |
LITERAL |
CONTEXT_LISTING |
LISTING |
CONTEXT_QUOTE |
QUOTE |
CONTEXT_PASS |
PASS |
CONTEXT_PARAGRAPH |
PARAGRAPH |
Removal of deprecated methods in org.asciidoctor.extension
package
Several methods under org.asciidoctor.extension
that were marked as @Deprecated
have been removed.
The new methods align better with Java naming patterns and are easily identifiable.
PreprocessorReader::push_include
Reader::getLineno
Reader::lines
PreprocessorReader::pushInclude
Reader::getLineNumber
Reader::getLines
Removal of deprecated methods in org.asciidoctor.ast
package
Several methods under org.asciidoctor.ast
that were marked as @Deprecated
have been removed.
The new methods align better with Java naming patterns and are easily identifiable.
Here follows the list of affected interfaces, describing for each one the removed methods and the substitutions.
Block
List<String> lines()
String source()
List<String> getLines()
String getSource()
DescriptionList, PhraseNode and List
String render()
String convert()
ContentNode
String id()
ContentNode parent()
String context()
Document document()
String role()
Object getAttr(Object name, Object defaultValue, boolean inherit)
Object getAttr(Object name, Object defaultValue)
Object getAttr(Object name)
boolean hasAttr(Object name)
boolean hasAttr(Object name, boolean inherited)
boolean isAttr(Object name, Object expected)
boolean isAttr(Object name, Object expected, boolean inherit)
boolean setAttr(Object name, Object value, boolean overwrite)
String getId()
ContentNode getParent()
String getContext()
Document getDocument()
String getRole()
Object getAttribute(Object name, Object defaultValue, boolean inherit)
Object getAttribute(Object name, Object defaultValue)
Object getAttribute(Object name)
boolean hasAttribute(Object name)
boolean hasAttribute(Object name, boolean inherited)
boolean isAttribute(Object name, Object expected)
boolean isAttribute(Object name, Object expected, boolean inherit)
boolean setAttribute(Object name, Object value, boolean overwrite)
Section
On top of the methods replaced by Java getters, both number
and getNumber
are replaced by getNumeral
.
This is done to support non-number numerals.
int index()
int number()
int getNumber()
String sectname()
boolean special()
boolean numbered()
int getIndex()
String getNumeral()
String getSectionName()
boolean isSpecial()
boolean isNumbered()