From afd6d59d7795a3a01ef0eb978273af37e53c951b Mon Sep 17 00:00:00 2001
From: Abel Salgado Romero <abelromero@gmail.com>
Date: Sun, 21 May 2023 20:31:36 +0200
Subject: [PATCH] Remove deprecated methods from Asciidoctor interface

* Also remove class org.asciidoctor.ast.DocumentHeader
* Update changelog

Fixes #1201
---
 CHANGELOG.adoc                                |   1 +
 .../java/org/asciidoctor/Asciidoctor.java     | 310 +-----------------
 .../main/java/org/asciidoctor/Attributes.java |   2 +-
 .../main/java/org/asciidoctor/Options.java    |   2 +-
 .../org/asciidoctor/ast/DocumentHeader.java   |  48 ---
 .../jruby/ast/impl/DocumentHeaderImpl.java    |  67 ----
 .../jruby/internal/JRubyAsciidoctor.java      | 138 +-------
 ...enADocumentContainsNumberedSections.groovy |   9 +-
 .../WhenSubstitutionsAreUsed.groovy           |  17 +-
 .../WhenTheSourceShouldBeAccessed.groovy      |  10 +-
 ...xtensionIsRegisteredWithAnnotations.groovy |  30 +-
 .../WhenAPreprocessorIsRegistered.groovy      |  13 +-
 .../WhenATreeProcessorWorksOnTables.groovy    |   2 +-
 .../extension/WhenAstIsIterated.groovy        |   8 +-
 ...AttributesMapDecoratorSpecification.groovy |  10 +-
 .../WhenAnAsciidoctorClassIsInstantiated.java |  28 +-
 .../WhenAnAsciidoctorJInstanceIsRequired.java |   2 +-
 .../WhenAsciiDocIsLoadedToDocument.java       | 130 +++-----
 .../WhenAsciidoctorLogsToConsole.java         |  29 +-
 .../WhenAttributesAreUsedInAsciidoctor.java   |  17 +-
 .../WhenDocumentHeaderIsRequired.java         |  37 ++-
 .../WhenSourceHighlightingIsUsed.java         |  27 +-
 .../converter/WhenConverterIsRegistered.java  |  29 +-
 .../extension/BlockMacroRegistrationTest.java |  28 +-
 .../BlockProcessorRegistrationTest.java       |  22 +-
 .../InlineMacroRegistrationTest.java          |  22 +-
 .../WhenJavaExtensionIsRegistered.java        |   3 +-
 .../WhenReaderIsManipulatedInExtension.java   |  22 +-
 .../WhenTheInlineMacroProcessorRunsTwice.java |   6 +-
 .../asciidoctor/util/OptionsTestHelper.java   |  10 +
 .../AsciidoctorInterface.java                 |   3 +-
 .../SimpleAsciidoctorRendering.java           |   8 +-
 .../extension/YellBlockProcessorTest.java     |   2 +-
 .../HighlightJsHighlighterTest.java           |   6 +-
 .../org/asciidoctor/AsciidoctorServlet.java   |   2 +-
 35 files changed, 286 insertions(+), 814 deletions(-)
 delete mode 100644 asciidoctorj-api/src/main/java/org/asciidoctor/ast/DocumentHeader.java
 delete mode 100644 asciidoctorj-core/src/main/java/org/asciidoctor/jruby/ast/impl/DocumentHeaderImpl.java
 create mode 100644 asciidoctorj-core/src/test/java/org/asciidoctor/util/OptionsTestHelper.java

diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 1dc7f942d..9b7761b3e 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -37,6 +37,7 @@ Improvement::
 * Return Document AST when using convert or convertFile with appropriate options (#1171) (@abelsromero)
 * Expose Links in the catalog (#1183) (@abelsromero)
 * BREAKING: Remove deprecated methods in Options, OptionsBuilder, Attributes & AttributesBuilder (#1199) (@abelsromero)
+* BREAKING: Remove deprecated Asciidoctor interface (#1201) (@abelsromero)
 
 Bug Fixes::
 
diff --git a/asciidoctorj-api/src/main/java/org/asciidoctor/Asciidoctor.java b/asciidoctorj-api/src/main/java/org/asciidoctor/Asciidoctor.java
index 6a8cbe671..ce0051c5d 100644
--- a/asciidoctorj-api/src/main/java/org/asciidoctor/Asciidoctor.java
+++ b/asciidoctorj-api/src/main/java/org/asciidoctor/Asciidoctor.java
@@ -1,7 +1,6 @@
 package org.asciidoctor;
 
 import org.asciidoctor.ast.Document;
-import org.asciidoctor.ast.DocumentHeader;
 import org.asciidoctor.converter.AbstractConverter;
 import org.asciidoctor.converter.JavaConverterRegistry;
 import org.asciidoctor.extension.ExtensionGroup;
@@ -30,36 +29,6 @@
  */
 public interface Asciidoctor extends AutoCloseable {
 
-    /**
-     * Parse the AsciiDoc source input into a Document {@link Document} and
-     * convert it to the specified backend format.
-     * <p>
-     * Accepts input as String object.
-     * @deprecated User {@link #convert(String, Options)} instead.
-     * 
-     * @param content the AsciiDoc source as String.
-     * @param options a Map of options to control processing (default: {}).
-     * @return the rendered output String is returned
-     */
-    @Deprecated
-    String convert(String content, Map<String, Object> options);
-
-    /**
-     * Parse the AsciiDoc source input into a Document {@link Document} and
-     * convert it to the specified backend format.
-     * <p>
-     * Accepts input as String object.
-     * @deprecated Use {@link #convert(String, Options, Class)} instead.
-     * 
-     * @param content        the AsciiDoc source as String.
-     * @param options        a Map of options to control processing (default: {}).
-     * @param expectedResult the expected return type. Usually {@link String} for HTML based formats.
-     *                       In this case {@link #convert(String, Map)} is the same.
-     * @return the rendered output String is returned
-     */
-    @Deprecated
-    <T> T convert(String content, Map<String, Object> options, Class<T> expectedResult);
-
     /**
      * Parse the AsciiDoc source input into a Document {@link Document} and
      * convert it to the specified backend format.
@@ -90,52 +59,6 @@ public interface Asciidoctor extends AutoCloseable {
      */
     <T> T convert(String content, Options options, Class<T> expectedResult);
 
-    /**
-     * Parse the AsciiDoc source input into a Document {@link Document} and
-     * convert it to the specified backend format.
-     * <p>
-     * Accepts input as String object.
-     * @deprecated Use {@link #convert(String, Options)} instead.
-     * 
-     * @param content the AsciiDoc source as String.
-     * @param options a Map of options to control processing (default: {}).
-     * @return the rendered output String is returned
-     */
-    @Deprecated
-    String convert(String content, OptionsBuilder options);
-
-    /**
-     * Parse the AsciiDoc source input into a Document {@link Document} and
-     * convert it to the specified backend format.
-     * <p>
-     * Accepts input as String object.
-     * @deprecated Use {@link #convert(String, Options, Class)} instead.
-     * 
-     * @param content        the AsciiDoc source as String.
-     * @param options        a Map of options to control processing (default: {}).
-     * @param expectedResult the expected return type. Usually {@link String} for HTML based formats.
-     *                       In this case {@link #convert(String, OptionsBuilder)} is the same.
-     * @return the rendered output String is returned
-     */
-    @Deprecated
-    <T> T convert(String content, OptionsBuilder options, Class<T> expectedResult);
-
-    /**
-     * Parse the document read from reader sending the converted result to
-     * writer.
-     * @deprecated Use {@link #convert(Reader, Writer, Options)} instead.
-     * 
-     * @param contentReader  where asciidoc content is read.
-     * @param rendererWriter where rendered content is written. Writer is flushed, but not
-     *                       closed.
-     * @param options        a Map of options to control processing (default: {}).
-     * @throws IOException if an error occurs while writing rendered content, this
-     *                     exception is thrown.
-     */
-    @Deprecated
-    void convert(Reader contentReader, Writer rendererWriter,
-                 Map<String, Object> options) throws IOException;
-
     /**
      * Parse the document read from reader sending the converted result to
      * writer.
@@ -150,77 +73,6 @@ void convert(Reader contentReader, Writer rendererWriter,
     void convert(Reader contentReader, Writer rendererWriter, Options options)
             throws IOException;
 
-    /**
-     * Parse the document read from reader sending the converted result to
-     * writer.
-     * @deprecated Use {@link #convert(Reader, Writer, Options)} instead.
-     * 
-     * @param contentReader  where asciidoc content is read.
-     * @param rendererWriter where rendered content is written. Writer is flushed, but not
-     *                       closed.
-     * @param options        a Map of options to control processing (default: {}).
-     * @throws IOException if an error occurs while writing rendered content, this
-     *                     exception is thrown.
-     */
-    @Deprecated
-    void convert(Reader contentReader, Writer rendererWriter,
-                 OptionsBuilder options) throws IOException;
-
-    /**
-     * Parse the AsciiDoc source input into a Document {@link Document} and
-     * convert it to the specified backend format.
-     * <p>
-     * Accepts input as File.
-     * <p>
-     * If the :in_place option is true, and the input is a File, the output is
-     * written to a file adjacent to the input file, having an extension that
-     * corresponds to the backend format. Otherwise, if the :to_file option is
-     * specified, the file is written to that file. If :to_file is not an
-     * absolute path, it is resolved relative to :to_dir, if given, otherwise
-     * the Document#base_dir. If the target directory does not exist, it will
-     * not be created unless the :mkdirs option is set to true. If the file
-     * cannot be written because the target directory does not exist, or because
-     * it falls outside of the Document#base_dir in safe mode, an IOError is
-     * raised.
-     * @deprecated Use {@link #convertFile(File, Options)} instead.
-     * 
-     * @param file    an input Asciidoctor file.
-     * @param options a Map of options to control processing (default: {}).
-     * @return returns nothing if the rendered output String is written to a
-     * file.
-     */
-    @Deprecated
-    String convertFile(File file, Map<String, Object> options);
-
-    /**
-     * Parse the AsciiDoc source input into a Document {@link Document} and
-     * convert it to the specified backend format.
-     * <p>
-     * Accepts input as File.
-     * <p>
-     * If the :in_place option is true, and the input is a File, the output is
-     * written to a file adjacent to the input file, having an extension that
-     * corresponds to the backend format. Otherwise, if the :to_file option is
-     * specified, the file is written to that file. If :to_file is not an
-     * absolute path, it is resolved relative to :to_dir, if given, otherwise
-     * the Document#base_dir. If the target directory does not exist, it will
-     * not be created unless the :mkdirs option is set to true. If the file
-     * cannot be written because the target directory does not exist, or because
-     * it falls outside of the Document#base_dir in safe mode, an IOError is
-     * raised.
-     * @deprecated User {@link #convertFile(File, Options, Class)} instead.
-     * 
-     * @param file           an input Asciidoctor file.
-     * @param options        a Map of options to control processing (default: {}).
-     * @param expectedResult the expected return type. Usually {@link String} for HTML based formats.
-     *                       In this case {@link #convertFile(File, Map)} is the same.
-     * @return returns nothing if the rendered output is written to a
-     * file.
-     */
-    @Deprecated
-    <T> T convertFile(File file, Map<String, Object> options, Class<T> expectedResult);
-
-
     /**
      * Parse the AsciiDoc source input into a Document {@link Document} and
      * convert it to the specified backend format.
@@ -265,79 +117,12 @@ void convert(Reader contentReader, Writer rendererWriter,
      * @param file           an input Asciidoctor file.
      * @param options        options to control processing (default: empty).
      * @param expectedResult the expected return type. Usually {@link String} for HTML based formats.
-     *                       In this case {@link #convertFile(File, Map)} is the same.
+     *                       In this case {@link #convertFile(File, Options)} is the same.
      * @return returns nothing if the rendered output is written to a
      * file.
      */
     <T> T convertFile(File file, Options options, Class<T> expectedResult);
 
-    /**
-     * Parse the AsciiDoc source input into a Document {@link Document} and
-     * convert it to the specified backend format.
-     * <p>
-     * Accepts input as File.
-     * <p>
-     * If the :in_place option is true, and the input is a File, the output is
-     * written to a file adjacent to the input file, having an extension that
-     * corresponds to the backend format. Otherwise, if the :to_file option is
-     * specified, the file is written to that file. If :to_file is not an
-     * absolute path, it is resolved relative to :to_dir, if given, otherwise
-     * the Document#base_dir. If the target directory does not exist, it will
-     * not be created unless the :mkdirs option is set to true. If the file
-     * cannot be written because the target directory does not exist, or because
-     * it falls outside of the Document#base_dir in safe mode, an IOError is
-     * raised.
-     * @deprecated Use {@link #convertFile(File, Options)} instead.
-     * 
-     * @param file    an input Asciidoctor file.
-     * @param options a Map of options to control processing (default: {}).
-     * @return returns nothing if the rendered output String is written to a
-     * file.
-     */
-    @Deprecated
-    String convertFile(File file, OptionsBuilder options);
-
-    /**
-     * Parse the AsciiDoc source input into a Document {@link Document} and
-     * convert it to the specified backend format.
-     * <p>
-     * Accepts input as File.
-     * <p>
-     * If the :in_place option is true, and the input is a File, the output is
-     * written to a file adjacent to the input file, having an extension that
-     * corresponds to the backend format. Otherwise, if the :to_file option is
-     * specified, the file is written to that file. If :to_file is not an
-     * absolute path, it is resolved relative to :to_dir, if given, otherwise
-     * the Document#base_dir. If the target directory does not exist, it will
-     * not be created unless the :mkdirs option is set to true. If the file
-     * cannot be written because the target directory does not exist, or because
-     * it falls outside of the Document#base_dir in safe mode, an IOError is
-     * raised.
-     * @deprecated User {@link #convertFile(File, Options, Class)} instead.
-     * 
-     * @param file           an input Asciidoctor file.
-     * @param options        a Map of options to control processing (default: {}).
-     * @param expectedResult the expected return type. Usually {@link String} for HTML based formats.
-     *                       In this case {@link #convertFile(File, Map)} is the same.
-     * @return returns nothing if the rendered output is written to a
-     * file.
-     */
-    @Deprecated
-    <T> T convertFile(File file, OptionsBuilder options, Class<T> expectedResult);
-
-    /**
-     * Convert all AsciiDoc files found in directoryWalker.
-     * See {@code AsciiDocDirectoryWalker} for reference strategy.
-     * @deprecated Use {@link #convertDirectory(Iterable, Options)} instead.
-     * 
-     * @param directoryWalker strategy used to retrieve all files to be rendered.
-     * @param options         a Map of options to control processing (default: {}).
-     * @return returns an array of 0 positions if the rendered output is written
-     * to a file.
-     */
-    @Deprecated
-    String[] convertDirectory(Iterable<File> directoryWalker, Map<String, Object> options);
-
     /**
      * Convert all AsciiDoc files found in directoryWalker.
      * See {@code AsciiDocDirectoryWalker} for reference strategy.
@@ -349,31 +134,6 @@ void convert(Reader contentReader, Writer rendererWriter,
      */
     String[] convertDirectory(Iterable<File> directoryWalker, Options options);
 
-    /**
-     * Convert all AsciiDoc files found in directoryWalker.
-     * See {@code AsciiDocDirectoryWalker} for reference strategy.
-     * @deprecated Use {@link #convertDirectory(Iterable, Options)} instead.
-     *     
-     * @param directoryWalker strategy used to retrieve all files to be rendered.
-     * @param options         a Map of options to control processing (default: {}).
-     * @return returns an array of 0 positions if the rendered output is written
-     * to a file.
-     */
-    @Deprecated
-    String[] convertDirectory(Iterable<File> directoryWalker, OptionsBuilder options);
-
-    /**
-     * Convert all files from a collection.
-     * @deprecated Use {@link #convertFiles(Collection, Options)} instead.
-     * 
-     * @param files   to be converted.
-     * @param options a Map of options to control processing (default: {}).
-     * @return returns an array of 0 positions if the rendered output is written
-     * to a file.
-     */
-    @Deprecated
-    String[] convertFiles(Collection<File> files, Map<String, Object> options);
-
     /**
      * Convert all files from a collection.
      *
@@ -384,18 +144,6 @@ void convert(Reader contentReader, Writer rendererWriter,
      */
     String[] convertFiles(Collection<File> asciidoctorFiles, Options options);
 
-    /**
-     * Convert all files from a collection.
-     * @deprecated Use {@link #convertFiles(Collection, Options)} instead. 
-     * 
-     * @param files   to be converted.
-     * @param options a Map of options to control processing (default: {}).
-     * @return returns an array of 0 positions if the rendered output is written
-     * to a file.
-     */
-    @Deprecated
-    String[] convertFiles(Collection<File> files, OptionsBuilder options);
-
     /**
      * Loads the given Ruby gem(s) by name.
      *
@@ -410,40 +158,6 @@ void convert(Reader contentReader, Writer rendererWriter,
      */
     void requireLibraries(Collection<String> requiredLibraries);
 
-    /**
-     * Reads only header parameters instead of all document.
-     *
-     * @deprecated Use {@link #loadFile(File, Map)} instead.
-     *
-     * @param file to read the attributes.
-     * @return header.
-     */
-    @Deprecated
-    DocumentHeader readDocumentHeader(File file);
-
-    /**
-     * Reads only header parameters instead of all document.
-     *
-     * @deprecated Use {@link #load(String, Map)} instead.
-     *
-     * @param content where converted content is written. Writer is flushed, but not
-     *                closed.
-     * @return header.
-     */
-    @Deprecated
-    DocumentHeader readDocumentHeader(String content);
-
-    /**
-     * Reads only header parameters instead of all document.
-     *
-     * @deprecated Use {@link #loadFile(File, Map)} instead.
-     *
-     * @param contentReader where asciidoc content is read.
-     * @return header.
-     */
-    @Deprecated
-    DocumentHeader readDocumentHeader(Reader contentReader);
-
     /**
      * Creates an extension registry ready to be used for registering Java extensions.
      *
@@ -550,17 +264,6 @@ public static Asciidoctor create() {
         }
     }
 
-    /**
-     * Loads AsciiDoc content and returns the Document object.
-     * @deprecated Use {@link #load(String, Options)} instead.
-     * 
-     * @param content to be parsed.
-     * @param options a Map of options to control processing (default: {}).
-     * @return Document of given content.
-     */
-    @Deprecated
-    Document load(String content, Map<String, Object> options);
-
     /**
      * Loads AsciiDoc content and returns the Document object.
      *
@@ -569,17 +272,6 @@ public static Asciidoctor create() {
      * @return Document of given content.
      */
     Document load(String content, Options options);
-    
-    /**
-     * Loads AsciiDoc content from file and returns the Document object.
-     * @deprecated Use {@link #loadFile(File, Options)} instead.
-     * 
-     * @param file    to be parsed.
-     * @param options a Map of options to control processing (default: {}).
-     * @return Document of given content.
-     */
-    @Deprecated
-    Document loadFile(File file, Map<String, Object> options);
 
     /**
      * Loads AsciiDoc content from file and returns the Document object.
diff --git a/asciidoctorj-api/src/main/java/org/asciidoctor/Attributes.java b/asciidoctorj-api/src/main/java/org/asciidoctor/Attributes.java
index f0424e4a9..125a28473 100644
--- a/asciidoctorj-api/src/main/java/org/asciidoctor/Attributes.java
+++ b/asciidoctorj-api/src/main/java/org/asciidoctor/Attributes.java
@@ -61,7 +61,7 @@ public class Attributes {
     public static final String HIDE_URI_SCHEME = "hide-uri-scheme";
     public static final String COMPAT_MODE = "compat-mode";
 
-    private Map<String, Object> attributes = new LinkedHashMap<>();
+    private final Map<String, Object> attributes = new LinkedHashMap<>();
 
     Attributes() {
     }
diff --git a/asciidoctorj-api/src/main/java/org/asciidoctor/Options.java b/asciidoctorj-api/src/main/java/org/asciidoctor/Options.java
index 5797a7f15..70e045cc9 100644
--- a/asciidoctorj-api/src/main/java/org/asciidoctor/Options.java
+++ b/asciidoctorj-api/src/main/java/org/asciidoctor/Options.java
@@ -33,7 +33,7 @@ public class Options {
     public static final String PARSE = "parse";
     public static final String PARSE_HEADER_ONLY = "parse_header_only";
 
-    private Map<String, Object> options = new HashMap<>();
+    private final Map<String, Object> options = new HashMap<>();
 
     Options() {
     }
diff --git a/asciidoctorj-api/src/main/java/org/asciidoctor/ast/DocumentHeader.java b/asciidoctorj-api/src/main/java/org/asciidoctor/ast/DocumentHeader.java
deleted file mode 100644
index 0538111c8..000000000
--- a/asciidoctorj-api/src/main/java/org/asciidoctor/ast/DocumentHeader.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package org.asciidoctor.ast;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Document header information holder.
- *
- */
-@Deprecated
-public interface DocumentHeader {
-
-    /**
-     * @deprecated Use {@link Document#getAuthors()} instead.
-     */
-    @Deprecated
-    List<Author> getAuthors();
-
-    /**
-     * @deprecated Use {@link Document#getStructuredDoctitle()} instead.
-     */
-    @Deprecated
-    Title getDocumentTitle();
-
-    /**
-     * @deprecated Use {@link Document#getDoctitle()} instead.
-     */
-    @Deprecated
-    String getPageTitle();
-
-    /**
-     * @deprecated Use {@link Document#getAuthors()} instead.
-     */
-    @Deprecated
-    Author getAuthor();
-
-    /**
-     * @deprecated Use {@link Document#getRevisionInfo()} instead.
-     */
-    @Deprecated
-    RevisionInfo getRevisionInfo();
-
-    /**
-     * @deprecated Use {@link Document#getAttributes()} instead.
-     */
-    @Deprecated
-    Map<String, Object> getAttributes();
-}
diff --git a/asciidoctorj-core/src/main/java/org/asciidoctor/jruby/ast/impl/DocumentHeaderImpl.java b/asciidoctorj-core/src/main/java/org/asciidoctor/jruby/ast/impl/DocumentHeaderImpl.java
deleted file mode 100644
index 2934058aa..000000000
--- a/asciidoctorj-core/src/main/java/org/asciidoctor/jruby/ast/impl/DocumentHeaderImpl.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.asciidoctor.jruby.ast.impl;
-
-import org.asciidoctor.ast.Author;
-import org.asciidoctor.ast.DocumentHeader;
-import org.asciidoctor.ast.RevisionInfo;
-import org.asciidoctor.ast.Title;
-import org.asciidoctor.jruby.internal.CaseInsensitiveMap;
-
-import java.util.List;
-import java.util.Map;
-
-public class DocumentHeaderImpl implements DocumentHeader {
-
-    private Title documentTitle;
-    private String pageTitle;
-    private List<Author> authors;
-    private RevisionInfo revisionInfo;
-
-    private Map<String, Object> attributes;
-
-    private DocumentHeaderImpl() {
-        super();
-    }
-
-    public List<Author> getAuthors() {
-        return this.authors;
-    }
-
-    public Title getDocumentTitle() {
-        return documentTitle;
-    }
-
-    public String getPageTitle() {
-        return pageTitle;
-    }
-
-    public Author getAuthor() {
-        return authors == null || authors.size() == 0 ? null : authors.get(0);
-    }
-
-    public RevisionInfo getRevisionInfo() {
-        return revisionInfo;
-    }
-
-    public Map<String, Object> getAttributes() {
-        return attributes;
-    }
-
-    public static DocumentHeaderImpl createDocumentHeader(Title documentTitle, String pageTitle,
-                                                          List<Author> authors, Map<String, Object> attributes) {
-
-        DocumentHeaderImpl documentHeader = new DocumentHeaderImpl();
-
-        documentHeader.documentTitle = documentTitle;
-        documentHeader.pageTitle = pageTitle;
-        documentHeader.attributes = new CaseInsensitiveMap<>(attributes);
-        documentHeader.authors = authors;
-        documentHeader.revisionInfo = getRevisionInfo(attributes);
-
-        return documentHeader;
-    }
-
-    private static RevisionInfo getRevisionInfo(Map<String, Object> attributes) {
-        return RevisionInfoImpl.getInstance(attributes);
-    }
-
-}
diff --git a/asciidoctorj-core/src/main/java/org/asciidoctor/jruby/internal/JRubyAsciidoctor.java b/asciidoctorj-core/src/main/java/org/asciidoctor/jruby/internal/JRubyAsciidoctor.java
index d3a384b2a..d672c1e62 100644
--- a/asciidoctorj-core/src/main/java/org/asciidoctor/jruby/internal/JRubyAsciidoctor.java
+++ b/asciidoctorj-core/src/main/java/org/asciidoctor/jruby/internal/JRubyAsciidoctor.java
@@ -2,15 +2,12 @@
 
 import org.asciidoctor.Attributes;
 import org.asciidoctor.Options;
-import org.asciidoctor.OptionsBuilder;
 import org.asciidoctor.ast.Document;
-import org.asciidoctor.ast.DocumentHeader;
 import org.asciidoctor.converter.JavaConverterRegistry;
 import org.asciidoctor.extension.ExtensionGroup;
 import org.asciidoctor.extension.JavaExtensionRegistry;
 import org.asciidoctor.extension.RubyExtensionRegistry;
 import org.asciidoctor.jruby.AsciidoctorJRuby;
-import org.asciidoctor.jruby.ast.impl.DocumentHeaderImpl;
 import org.asciidoctor.jruby.ast.impl.NodeConverter;
 import org.asciidoctor.jruby.converter.internal.ConverterRegistryExecutor;
 import org.asciidoctor.jruby.extension.internal.ExtensionRegistryExecutor;
@@ -161,50 +158,7 @@ public Ruby getRubyRuntime() {
         return rubyRuntime;
     }
 
-    private DocumentHeader toDocumentHeader(Document document) {
-
-        Document documentImpl = (Document) NodeConverter.createASTNode(document);
-
-        return DocumentHeaderImpl.createDocumentHeader(
-                documentImpl.getStructuredDoctitle(),
-                documentImpl.getDoctitle(),
-                documentImpl.getAuthors(),
-                document.getAttributes());
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public DocumentHeader readDocumentHeader(File file) {
-
-        RubyHash rubyHash = getParseHeaderOnlyOption();
-
-        Document document = (Document) NodeConverter.createASTNode(getAsciidoctorModule().callMethod("load_file", rubyRuntime.newString(file.getAbsolutePath()), rubyHash));
-
-        return toDocumentHeader(document);
-    }
-
-    @Override
-    public DocumentHeader readDocumentHeader(String content) {
-
-        RubyHash rubyHash = getParseHeaderOnlyOption();
-
-        Document document = (Document) NodeConverter.createASTNode(getAsciidoctorModule().callMethod("load", rubyRuntime.newString(content), rubyHash));
-        return toDocumentHeader(document);
-    }
-
-    @Override
-    public DocumentHeader readDocumentHeader(Reader contentReader) {
-        String content = IOUtils.readFull(contentReader);
-        return this.readDocumentHeader(content);
-    }
-
-    private RubyHash getParseHeaderOnlyOption() {
-        Map<String, Object> options = new HashMap<>();
-        options.put("parse_header_only", true);
-        return RubyHashUtil.convertMapToRubyHashWithSymbols(rubyRuntime, options);
-    }
-
-    private List<String> convertAllFiles(Map<String, Object> options, final Iterable<File> asciidoctorFiles) {
+    private List<String> convertAllFiles(Options options, final Iterable<File> asciidoctorFiles) {
         List<String> asciidoctorContent = new ArrayList<>();
         for (File asciidoctorFile : asciidoctorFiles) {
             String renderedFile = convertFile(asciidoctorFile, options);
@@ -272,11 +226,6 @@ private RubyModule getAsciidoctorModule() {
         return rubyRuntime.getModule("Asciidoctor");
     }
 
-    @Override
-    public String convert(String content, Map<String, Object> options) {
-        return convert(content, options, String.class);
-    }
-
     public <T> T convert(String content, Map<String, Object> options, Class<T> expectedResult) {
 
         this.rubyGemsPreloader.preloadRequiredLibraries(options);
@@ -330,39 +279,14 @@ public <T> T convert(String content, Options options, Class<T> expectedResult) {
         return convert(content, options.map(), expectedResult);
     }
 
-    @Override
-    public String convert(String content, OptionsBuilder options) {
-        return convert(content, options, String.class);
-    }
-
-    @Override
-    public <T> T convert(String content, OptionsBuilder options, Class<T> expectedResult) {
-        return convert(content, options.build(), expectedResult);
-    }
-
-    @Override
-    public void convert(Reader contentReader, Writer rendererWriter, Map<String, Object> options) throws IOException {
-        String content = IOUtils.readFull(contentReader);
-        String renderedContent = convert(content, options);
-        IOUtils.writeFull(rendererWriter, renderedContent);
-    }
-
     @Override
     public void convert(Reader contentReader, Writer rendererWriter, Options options) throws IOException {
-        this.convert(contentReader, rendererWriter, options.map());
-    }
-
-    @Override
-    public void convert(Reader contentReader, Writer rendererWriter, OptionsBuilder options) throws IOException {
-        this.convert(contentReader, rendererWriter, options.build());
-    }
-
-    @Override
-    public String convertFile(File file, Map<String, Object> options) {
-        return convertFile(file, options, String.class);
+        final String content = IOUtils.readFull(contentReader);
+        final String renderedContent = convert(content, options);
+        IOUtils.writeFull(rendererWriter, renderedContent);
     }
 
-    @Override
+    // @Override
     public <T> T convertFile(File file, Map<String, Object> options, Class<T> expectedResult) {
 
         this.rubyGemsPreloader.preloadRequiredLibraries(options);
@@ -419,53 +343,16 @@ public <T> T convertFile(File file, Options options, Class<T> expectedResult) {
         return convertFile(file, options.map(), expectedResult);
     }
 
-    @Override
-    public String convertFile(File file, OptionsBuilder options) {
-        return convertFile(file, options.build(), String.class);
-    }
-
-    @Override
-    public <T> T convertFile(File file, OptionsBuilder options, Class<T> expectedResult) {
-        return convertFile(file, options.build(), expectedResult);
-    }
-
-    @Override
-    public String[] convertDirectory(Iterable<File> directoryWalker, Map<String, Object> options) {
-        List<String> asciidoctorContent = convertAllFiles(options, directoryWalker);
-        return asciidoctorContent.toArray(new String[0]);
-    }
-
     @Override
     public String[] convertDirectory(Iterable<File> directoryWalker, Options options) {
-        return convertDirectory(directoryWalker, options.map());
-    }
-
-    @Override
-    public String[] convertDirectory(Iterable<File> directoryWalker, OptionsBuilder options) {
-        return convertDirectory(directoryWalker, options.build());
-    }
-
-    @Override
-    public String[] convertFiles(Collection<File> files, Map<String, Object> options) {
-        List<String> asciidoctorContent = convertAllFiles(options, files);
+        List<String> asciidoctorContent = convertAllFiles(options, directoryWalker);
         return asciidoctorContent.toArray(new String[0]);
     }
 
     @Override
     public String[] convertFiles(Collection<File> asciidoctorFiles, Options options) {
-        return convertFiles(asciidoctorFiles, options.map());
-    }
-
-    @Override
-    public String[] convertFiles(Collection<File> files, OptionsBuilder options) {
-        return convertFiles(files, options.build());
-    }
-
-    @Override
-    public Document load(String content, Map<String, Object> options) {
-        RubyHash rubyHash = RubyHashUtil.convertMapToRubyHashWithSymbols(rubyRuntime, options);
-        return (Document) NodeConverter.createASTNode(getAsciidoctorModule().callMethod("load",
-                rubyRuntime.newString(content), rubyHash));
+        List<String> asciidoctorContent = convertAllFiles(options, asciidoctorFiles);
+        return asciidoctorContent.toArray(new String[0]);
     }
 
     @Override
@@ -475,18 +362,9 @@ public Document load(String content, Options options) {
                 Optional.ofNullable(content).map(rubyRuntime::newString).orElse(null), rubyHash));
     }
 
-    @Override
-    public Document loadFile(File file, Map<String, Object> options) {
-        RubyHash rubyHash = RubyHashUtil.convertMapToRubyHashWithSymbols(rubyRuntime, options);
-
-        return (Document) NodeConverter.createASTNode(getAsciidoctorModule().callMethod("load_file",
-                rubyRuntime.newString(file.getAbsolutePath()), rubyHash));
-    }
-
     @Override
     public Document loadFile(File file, Options options) {
         RubyHash rubyHash = RubyHashUtil.convertMapToRubyHashWithSymbols(rubyRuntime, options.map());
-
         return (Document) NodeConverter.createASTNode(getAsciidoctorModule().callMethod("load_file",
                 rubyRuntime.newString(file.getAbsolutePath()), rubyHash));
     }
diff --git a/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenADocumentContainsNumberedSections.groovy b/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenADocumentContainsNumberedSections.groovy
index 93ac9d681..6a8c80d07 100644
--- a/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenADocumentContainsNumberedSections.groovy
+++ b/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenADocumentContainsNumberedSections.groovy
@@ -1,8 +1,11 @@
 package org.asciidoctor
 
+
 import org.asciidoctor.ast.Section
 import spock.lang.Specification
 
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions
+
 class WhenADocumentContainsNumberedSections extends Specification {
 
     private Asciidoctor asciidoctor = Asciidoctor.Factory.create()
@@ -18,7 +21,7 @@ class WhenADocumentContainsNumberedSections extends Specification {
             '''.stripIndent()
 
         when:
-        def document = asciidoctor.load source, [:]
+        def document = asciidoctor.load(source, emptyOptions())
 
         then:
         final appendix = (Section) document.blocks[0]
@@ -36,7 +39,7 @@ class WhenADocumentContainsNumberedSections extends Specification {
             '''.stripIndent()
 
         when:
-        def document = asciidoctor.load source, [:]
+        def document = asciidoctor.load(source, emptyOptions())
 
         then:
         final section = (Section) document.blocks[0]
@@ -58,7 +61,7 @@ class WhenADocumentContainsNumberedSections extends Specification {
             '''.stripIndent()
 
         when:
-        def document = asciidoctor.load source, [:]
+        def document = asciidoctor.load(source, emptyOptions())
 
         then:
         final part = (Section) document.blocks[0]
diff --git a/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenSubstitutionsAreUsed.groovy b/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenSubstitutionsAreUsed.groovy
index 999c59666..7c0db8f47 100644
--- a/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenSubstitutionsAreUsed.groovy
+++ b/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenSubstitutionsAreUsed.groovy
@@ -11,6 +11,7 @@ import static org.asciidoctor.ast.StructuralNode.SUBSTITUTION_ATTRIBUTES
 import static org.asciidoctor.ast.StructuralNode.SUBSTITUTION_REPLACEMENTS
 import static org.asciidoctor.ast.StructuralNode.SUBSTITUTION_MACROS
 import static org.asciidoctor.ast.StructuralNode.SUBSTITUTION_POST_REPLACEMENTS
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions
 
 class WhenSubstitutionsAreUsed extends Specification {
 
@@ -33,7 +34,7 @@ System.out.println("Hello World");
 '''
 
         when:
-        Document doc = asciidoctor.load(document, Map.of())
+        Document doc = asciidoctor.load(document, emptyOptions())
         Block paragraph = doc.blocks[0].blocks[0]
         Block source = doc.blocks[0].blocks[1]
 
@@ -58,11 +59,11 @@ Second test paragraph {foo}
 
         when:
         asciidoctor.javaExtensionRegistry().treeprocessor(TestTreeprocessor)
-        Document doc = asciidoctor.load(document, Map.of())
+        Document doc = asciidoctor.load(document, emptyOptions())
         Block firstparagraph = doc.blocks[0].blocks[0]
         Block secondparagraph = doc.blocks[0].blocks[1]
 
-        String html = asciidoctor.convert(document, Map.of())
+        String html = asciidoctor.convert(document, emptyOptions())
 
         then:
         firstparagraph.substitutions == [SUBSTITUTION_SPECIAL_CHARACTERS, SUBSTITUTION_QUOTES, SUBSTITUTION_ATTRIBUTES, SUBSTITUTION_REPLACEMENTS, SUBSTITUTION_MACROS, SUBSTITUTION_POST_REPLACEMENTS]
@@ -93,11 +94,11 @@ System.out.println("{foo}");
 
         when:
         asciidoctor.javaExtensionRegistry().treeprocessor(TestTreeprocessor)
-        Document doc = asciidoctor.load(document, Map.of())
+        Document doc = asciidoctor.load(document, emptyOptions())
         Block firstparagraph = doc.blocks[0].blocks[0]
         Block secondparagraph = doc.blocks[0].blocks[1]
 
-        String html = asciidoctor.convert(document, Options.builder())
+        String html = asciidoctor.convert(document, emptyOptions())
 
         then:
         firstparagraph.substitutions == [SUBSTITUTION_SPECIAL_CHARACTERS, SUBSTITUTION_QUOTES, SUBSTITUTION_ATTRIBUTES, SUBSTITUTION_REPLACEMENTS, SUBSTITUTION_MACROS, SUBSTITUTION_POST_REPLACEMENTS]
@@ -139,10 +140,10 @@ First test paragraph *{foo}
 
         when:
         asciidoctor.javaExtensionRegistry().treeprocessor(PrependSubstitutionTestTreeprocessor)
-        Document doc = asciidoctor.load(document, Map.of())
+        Document doc = asciidoctor.load(document, emptyOptions())
         Block firstparagraph = doc.blocks[0].blocks[0]
 
-        String html = asciidoctor.convert(document, Map.of())
+        String html = asciidoctor.convert(document, emptyOptions())
 
         then:
         firstparagraph.substitutions == [SUBSTITUTION_ATTRIBUTES, SUBSTITUTION_SPECIAL_CHARACTERS, SUBSTITUTION_QUOTES, SUBSTITUTION_ATTRIBUTES, SUBSTITUTION_REPLACEMENTS, SUBSTITUTION_MACROS, SUBSTITUTION_POST_REPLACEMENTS]
@@ -177,7 +178,7 @@ First test paragraph *{foo}
 
         when:
         asciidoctor.javaExtensionRegistry().treeprocessor(SetSubstitutionTestTreeprocessor)
-        Document doc = asciidoctor.load(document, Options.builder().build())
+        Document doc = asciidoctor.load(document, emptyOptions())
         Block firstparagraph = doc.blocks[0].blocks[0]
 
         String html = asciidoctor.convert(document, Options.builder().build())
diff --git a/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenTheSourceShouldBeAccessed.groovy b/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenTheSourceShouldBeAccessed.groovy
index 94cf07f1a..af3642df7 100644
--- a/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenTheSourceShouldBeAccessed.groovy
+++ b/asciidoctorj-core/src/test/groovy/org/asciidoctor/WhenTheSourceShouldBeAccessed.groovy
@@ -12,6 +12,8 @@ import org.asciidoctor.extension.Treeprocessor
 import org.jsoup.Jsoup
 import spock.lang.Specification
 
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions
+
 /**
  * Tests that the unsubstituted text can be retrieved from nodes
  */
@@ -37,7 +39,7 @@ This paragraph should show {foo}
 
 '''
         when:
-        Document doc = asciidoctor.load(document, Map.of())
+        Document doc = asciidoctor.load(document, emptyOptions())
         Block block = doc.blocks[0].blocks[0]
 
         then:
@@ -60,7 +62,7 @@ This paragraph should show {foo}
 
 '''
         when:
-        Document doc = asciidoctor.load(document, Map.of())
+        Document doc = asciidoctor.load(document, emptyOptions())
         List list = doc.blocks[0].blocks[0]
         ListItem listItem = list.items[0]
 
@@ -90,7 +92,7 @@ That::
 
 '''
         when:
-        Document doc = asciidoctor.load(document, Map.of())
+        Document doc = asciidoctor.load(document, emptyOptions())
         DescriptionList list = doc.blocks[0].blocks[0]
         DescriptionListEntry listItem = list.items[0]
 
@@ -117,7 +119,7 @@ and should continue here'''
 
 '''
         when:
-        Document doc = asciidoctor.load(document, Map.of())
+        Document doc = asciidoctor.load(document, emptyOptions())
         Table table = doc.blocks[0].blocks[0]
         Cell cell = table.body[0].cells[0]
 
diff --git a/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAJavaExtensionIsRegisteredWithAnnotations.groovy b/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAJavaExtensionIsRegisteredWithAnnotations.groovy
index 45445b323..474bd0ed2 100644
--- a/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAJavaExtensionIsRegisteredWithAnnotations.groovy
+++ b/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAJavaExtensionIsRegisteredWithAnnotations.groovy
@@ -2,6 +2,7 @@ package org.asciidoctor.extension
 
 import org.asciidoctor.Asciidoctor
 import org.asciidoctor.Options
+import org.asciidoctor.OptionsBuilder
 import org.asciidoctor.SafeMode
 import org.jsoup.Jsoup
 import org.jsoup.nodes.Document
@@ -86,7 +87,7 @@ And even more infos on manpage:git[7].
     def "a docinfoprocessor should be configurable via the Location annotation"() {
         when:
         asciidoctor.javaExtensionRegistry().docinfoProcessor(AnnotatedDocinfoProcessor)
-        String result = asciidoctor.convert(DOCUMENT, Options.builder().standalone(true).safe(SafeMode.SERVER))
+        String result = asciidoctor.convert(DOCUMENT, options())
 
         then:
         Document doc = Jsoup.parse(result, UTF8)
@@ -97,7 +98,7 @@ And even more infos on manpage:git[7].
     def "a docinfoprocessor instance should be configurable via the Location annotation"() {
         when:
         asciidoctor.javaExtensionRegistry().docinfoProcessor(new AnnotatedDocinfoProcessor())
-        String result = asciidoctor.convert(DOCUMENT, Options.builder().standalone(true).safe(SafeMode.SERVER).build())
+        String result = asciidoctor.convert(DOCUMENT, options())
 
         then:
         Document doc = Jsoup.parse(result, UTF8)
@@ -109,7 +110,7 @@ And even more infos on manpage:git[7].
     def "a docinfoprocessor instance can override the annotation from footer to header"() {
         when:
         asciidoctor.javaExtensionRegistry().docinfoProcessor(new AnnotatedDocinfoProcessor(LocationType.HEADER))
-        String result = asciidoctor.convert(DOCUMENT, Options.builder().standalone(true).safe(SafeMode.SERVER).build())
+        String result = asciidoctor.convert(DOCUMENT, options())
 
         then:
         Document doc = Jsoup.parse(result, UTF8)
@@ -119,7 +120,7 @@ And even more infos on manpage:git[7].
     def "a docinfoprocessor instance can override the annotation from footer to footer"() {
         when:
         asciidoctor.javaExtensionRegistry().docinfoProcessor(new AnnotatedDocinfoProcessor(LocationType.FOOTER))
-        String result = asciidoctor.convert(DOCUMENT, Options.builder().standalone(true).safe(SafeMode.SERVER).build())
+        String result = asciidoctor.convert(DOCUMENT, options())
 
         then:
         Document doc = Jsoup.parse(result, UTF8)
@@ -131,7 +132,7 @@ And even more infos on manpage:git[7].
 
         when:
         asciidoctor.javaExtensionRegistry().blockMacro(AnnotatedBlockMacroProcessor)
-        String result = asciidoctor.convert(BLOCK_MACRO_DOCUMENT, Options.builder().standalone(false).build())
+        String result = asciidoctor.convert(BLOCK_MACRO_DOCUMENT, disableStandaloneOption())
 
         then:
         result.contains(AnnotatedBlockMacroProcessor.RESULT)
@@ -143,7 +144,7 @@ And even more infos on manpage:git[7].
 
         when:
         asciidoctor.javaExtensionRegistry().block(AnnotatedBlockProcessor)
-        String result = asciidoctor.convert(BLOCK_DOCUMENT, Options.builder().standalone(false).build())
+        String result = asciidoctor.convert(BLOCK_DOCUMENT, disableStandaloneOption())
 
         then:
         result.contains(DO_NOT_TOUCH_THIS)
@@ -157,7 +158,7 @@ And even more infos on manpage:git[7].
 
         when:
         asciidoctor.javaExtensionRegistry().block(new AnnotatedBlockProcessor('dummy', 'yell2'))
-        String result = asciidoctor.convert(BLOCK_DOCUMENT_2, Options.builder().standalone(false).build())
+        String result = asciidoctor.convert(BLOCK_DOCUMENT_2, disableStandaloneOption())
 
         then:
         result.contains(DO_NOT_TOUCH_THIS)
@@ -168,7 +169,7 @@ And even more infos on manpage:git[7].
     def "when registering an InlineMacroProcessor class with long format it should be configurable via annotations"() {
         when:
         asciidoctor.javaExtensionRegistry().inlineMacro(AnnotatedLongInlineMacroProcessor)
-        String result = asciidoctor.convert(INLINE_MACRO_DOCUMENT, Options.builder().standalone(false).build())
+        String result = asciidoctor.convert(INLINE_MACRO_DOCUMENT, disableStandaloneOption())
 
         then:
         Document doc = Jsoup.parse(result, UTF8)
@@ -179,7 +180,7 @@ And even more infos on manpage:git[7].
     def "when registering an InlineMacroProcessor class with regexp it should be configurable via annotations"() {
         when:
         asciidoctor.javaExtensionRegistry().inlineMacro(AnnotatedRegexpInlineMacroProcessor)
-        String result = asciidoctor.convert(INLINE_MACRO_REGEXP_DOCUMENT, Options.builder().standalone(false).build())
+        String result = asciidoctor.convert(INLINE_MACRO_REGEXP_DOCUMENT, disableStandaloneOption())
 
         then:
         Document doc = Jsoup.parse(result, UTF8)
@@ -187,4 +188,15 @@ And even more infos on manpage:git[7].
         link.attr(HREF) == 'git.html'
     }
 
+    private OptionsBuilder standaloneBuilder(boolean enable) {
+        Options.builder().standalone(enable)
+    }
+
+    private Options disableStandaloneOption() {
+        standaloneBuilder(false).build()
+    }
+
+    private Options options() {
+        standaloneBuilder(true).safe(SafeMode.SERVER).build()
+    }
 }
diff --git a/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAPreprocessorIsRegistered.groovy b/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAPreprocessorIsRegistered.groovy
index c816048c0..f97d72d82 100644
--- a/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAPreprocessorIsRegistered.groovy
+++ b/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAPreprocessorIsRegistered.groovy
@@ -1,12 +1,13 @@
 package org.asciidoctor.extension
 
 import org.asciidoctor.Asciidoctor
-import org.asciidoctor.Options
 import org.asciidoctor.ast.Document
 import spock.lang.Specification
 
 import java.util.concurrent.atomic.AtomicBoolean
 
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions
+
 class WhenAPreprocessorIsRegistered extends Specification {
 
     private Asciidoctor asciidoctor = Asciidoctor.Factory.create()
@@ -46,7 +47,7 @@ $secondLine"""
         })
 
         when:
-        asciidoctor.convert(document, Map.of())
+        asciidoctor.convert(document, emptyOptions())
 
         then:
         preprocessorCalled.get()
@@ -79,7 +80,7 @@ $secondLine"""
         })
 
         when:
-        asciidoctor.convert(document, Map.of())
+        asciidoctor.convert(document, emptyOptions())
 
         then:
         preprocessorCalled.get()
@@ -103,7 +104,7 @@ $secondLine"""
         })
 
         when:
-        asciidoctor.convert(document, Options.builder())
+        asciidoctor.convert(document, emptyOptions())
 
         then:
         preprocessorCalled.get()
@@ -134,7 +135,7 @@ $secondLine"""
         })
 
         when:
-        asciidoctor.convert(document, Options.builder())
+        asciidoctor.convert(document, emptyOptions())
 
         then:
         preprocessorCalled.get()
@@ -168,7 +169,7 @@ $secondLine"""
         })
 
         when:
-        asciidoctor.convert(document, Map.of())
+        asciidoctor.convert(document, emptyOptions())
 
         then:
         preprocessorCalled.get()
diff --git a/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenATreeProcessorWorksOnTables.groovy b/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenATreeProcessorWorksOnTables.groovy
index 8123584c6..442f8f1f1 100644
--- a/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenATreeProcessorWorksOnTables.groovy
+++ b/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenATreeProcessorWorksOnTables.groovy
@@ -67,7 +67,7 @@ class WhenATreeProcessorWorksOnTables extends Specification {
 | World | Hello 
 |===
 
-''', Options.builder().standalone(false))
+''', Options.builder().standalone(false).build())
 
         def htmlDocument = Jsoup.parse(content)
 
diff --git a/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAstIsIterated.groovy b/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAstIsIterated.groovy
index 95a7314a8..b2d21daaa 100644
--- a/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAstIsIterated.groovy
+++ b/asciidoctorj-core/src/test/groovy/org/asciidoctor/extension/WhenAstIsIterated.groovy
@@ -1,10 +1,12 @@
 package org.asciidoctor.extension
 
 import org.asciidoctor.Asciidoctor
-import org.asciidoctor.ast.StructuralNode
 import org.asciidoctor.ast.Document
+import org.asciidoctor.ast.StructuralNode
 import spock.lang.Specification
 
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions
+
 class WhenAstIsIterated extends Specification {
 
     Asciidoctor asciidoctor = Asciidoctor.Factory.create()
@@ -30,7 +32,7 @@ A list with items
 
     def "getDocument should always return the same instance"() {
         when:
-        Document document = asciidoctor.load(DOCUMENT, [:])
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions())
         List<StructuralNode>  allBlocks = document.findBy([:])
 
         then:
@@ -40,7 +42,7 @@ A list with items
 
     def "getParent should always return the same instance"() {
         when:
-        Document document = asciidoctor.load(DOCUMENT, [:])
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions())
         def allBlocks = document.findBy([:])
 
         then: 'Every block of the document should return the same node as the parent from getParent()'
diff --git a/asciidoctorj-core/src/test/groovy/org/asciidoctor/jruby/internal/RubyAttributesMapDecoratorSpecification.groovy b/asciidoctorj-core/src/test/groovy/org/asciidoctor/jruby/internal/RubyAttributesMapDecoratorSpecification.groovy
index 6497ba7d9..2c14a31c0 100644
--- a/asciidoctorj-core/src/test/groovy/org/asciidoctor/jruby/internal/RubyAttributesMapDecoratorSpecification.groovy
+++ b/asciidoctorj-core/src/test/groovy/org/asciidoctor/jruby/internal/RubyAttributesMapDecoratorSpecification.groovy
@@ -5,6 +5,8 @@ import org.asciidoctor.ast.Block
 import org.asciidoctor.ast.Document
 import spock.lang.Specification
 
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions
+
 class RubyAttributesMapDecoratorSpecification extends Specification {
 
     public static final String ATTR_ONE = '1'
@@ -25,7 +27,7 @@ Lorem ipsum dolor
     def "should consistently show positional attributes as string keys"() {
 
         when:
-        Document document = asciidoctor.load(documentWithPositionalAttribute, new HashMap<String, Object>())
+        Document document = asciidoctor.load(documentWithPositionalAttribute, emptyOptions())
 
         Block block = (Block) document.getBlocks().get(0)
         Map<String, Object> attributes = block.getAttributes()
@@ -42,7 +44,7 @@ Lorem ipsum dolor
     def "should remove positional attributes by string keys"() {
 
         given: 'a block with a positional attribute'
-        Document document = asciidoctor.load(documentWithPositionalAttribute, new HashMap<String, Object>())
+        Document document = asciidoctor.load(documentWithPositionalAttribute, emptyOptions())
 
         Block block = (Block) document.getBlocks().get(0)
 
@@ -63,14 +65,14 @@ Lorem ipsum dolor
 
     def "should return previous value on put"() {
         given: 'a block with a positional attribute'
-        Document document = asciidoctor.load(documentWithPositionalAttribute, new HashMap<String, Object>())
+        Document document = asciidoctor.load(documentWithPositionalAttribute, emptyOptions())
 
         Block block = (Block) document.getBlocks().get(0)
 
         when: 'I put another value for the positional attribute 1'
         def attributes = block.getAttributes()
         def newValue = 42
-        def previousValue = attributes.put(ATTR_ONE, newValue)
+        String previousValue = attributes.put(ATTR_ONE, newValue)
 
         then: 'put returned the previous value'
         previousValue.startsWith(blockStyle)
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAnAsciidoctorClassIsInstantiated.java b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAnAsciidoctorClassIsInstantiated.java
index 1451dd4ef..679661440 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAnAsciidoctorClassIsInstantiated.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAnAsciidoctorClassIsInstantiated.java
@@ -21,8 +21,11 @@
 import java.nio.file.Path;
 import java.text.Format;
 import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
 
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.Matchers.isEmptyString;
@@ -49,16 +52,14 @@ public class WhenAnAsciidoctorClassIsInstantiated {
 
     @Test
     public void should_accept_empty_string_as_empty_content_when_output_is_String() {
-        Options basicOptions = Options.builder().build();
-        String result = asciidoctor.convert("", basicOptions);
+        String result = asciidoctor.convert("", emptyOptions());
 
         assertThat(result, isEmptyString());
     }
 
     @Test
     public void should_accept_null_string_as_empty_content_when_output_is_String() {
-        Options basicOptions = Options.builder().build();
-        String result = asciidoctor.convert(null, basicOptions);
+        String result = asciidoctor.convert(null, emptyOptions());
 
         assertThat(result, isEmptyString());
     }
@@ -78,10 +79,9 @@ public void should_accept_null_string_as_empty_content_when_output_is_File() {
 
     @Test
     public void should_fail_when_reader_is_null() {
-        Options basicOptions = Options.builder().build();
         StringWriter writer = new StringWriter();
 
-        Throwable throwable = Assertions.catchThrowable(() -> asciidoctor.convert(null, writer, basicOptions));
+        Throwable throwable = Assertions.catchThrowable(() -> asciidoctor.convert(null, writer, emptyOptions()));
 
         Assertions.assertThat(throwable)
                 .isInstanceOf(NullPointerException.class)
@@ -94,7 +94,7 @@ public void content_should_be_read_from_reader_and_written_to_writer()
 
         FileReader inputAsciidoctorFile = new FileReader(renderSampleDocument);
         StringWriter rendererWriter = new StringWriter();
-        asciidoctor.convert(inputAsciidoctorFile, rendererWriter, options().build().map());
+        asciidoctor.convert(inputAsciidoctorFile, rendererWriter, emptyOptions());
 
         StringBuffer renderedContent = rendererWriter.getBuffer();
         assertRenderedFile(renderedContent.toString());
@@ -127,8 +127,8 @@ public void file_document_should_be_rendered_into_current_directory_using_option
     @Test
     public void file_document_should_be_rendered_into_current_directory() {
 
-        String renderContent = asciidoctor.convertFile(renderSampleDocument, options()
-                .inPlace(true).build().map());
+        Options inPlaceOptions = options().inPlace(true).build();
+        String renderContent = asciidoctor.convertFile(renderSampleDocument, inPlaceOptions);
 
         File expectedFile = new File(renderSampleDocument.getParent(), "rendersample.html");
 
@@ -191,7 +191,7 @@ public void file_document_should_be_rendered_into_foreign_directory_using_option
     public void docbook_document_should_be_rendered_into_current_directory() {
 
         Attributes attributes = Attributes.builder().backend("docbook").build();
-        Map<String, Object> options = options().inPlace(true).attributes(attributes).build().map();
+        Options options = options().inPlace(true).attributes(attributes).build();
 
         String renderContent = asciidoctor.convertFile(renderSampleDocument, options);
 
@@ -245,7 +245,7 @@ public void string_content_with_custom_date_should_be_rendered(
         customDate.set(Calendar.DATE, 5);
 
         Attributes attributes = Attributes.builder().localDate(customDate.getTime()).build();
-        Map<String, Object> options = options().attributes(attributes).build().map();
+        Options options = options().attributes(attributes).build();
 
         String render_file = asciidoctor.convert(Files.readString(documentWithDate), options);
         assertRenderedLocalDateContent(render_file, "2012-12-05.");
@@ -263,7 +263,7 @@ public void string_content_with_custom_time_should_be_rendered(
         customTime.set(Calendar.SECOND, 0);
 
         Attributes attributes = Attributes.builder().localTime(customTime.getTime()).build();
-        Map<String, Object> options = options().attributes(attributes).build().map();
+        Options options = options().attributes(attributes).build();
 
         String render_file = asciidoctor.convert(Files.readString(documentWithDate), options);
 
@@ -277,7 +277,7 @@ public void string_content_with_custom_time_should_be_rendered(
     public void string_content_document_should_be_rendered_into_default_backend() throws IOException, SAXException,
             ParserConfigurationException {
 
-        String render_file = asciidoctor.convert(Files.readString(renderSampleDocument.toPath()), new HashMap<>());
+        String render_file = asciidoctor.convert(Files.readString(renderSampleDocument.toPath()), emptyOptions());
 
         assertRenderedFile(render_file);
     }
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAnAsciidoctorJInstanceIsRequired.java b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAnAsciidoctorJInstanceIsRequired.java
index b5954fd14..a446bc9ce 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAnAsciidoctorJInstanceIsRequired.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAnAsciidoctorJInstanceIsRequired.java
@@ -15,7 +15,7 @@ public void shouldUnwrapAsciidoctorInstanceAndRegisterRubyExtension() {
         AsciidoctorJRuby asciidoctorj = Asciidoctor.Factory.create().unwrap(AsciidoctorJRuby.class);
         asciidoctorj.rubyExtensionRegistry().loadClass(getClass().getResourceAsStream("/ruby-extensions/YellRubyBlock.rb")).block("yell", "YellRubyBlock");
 
-        String html = asciidoctorj.convert(DOC, Options.builder().standalone(false));
+        String html = asciidoctorj.convert(DOC, Options.builder().standalone(false).build());
 
         assertThat(html, containsString("HELLO WORLD"));
     }
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciiDocIsLoadedToDocument.java b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciiDocIsLoadedToDocument.java
index 560f4255f..62602bf7e 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciiDocIsLoadedToDocument.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciiDocIsLoadedToDocument.java
@@ -16,9 +16,9 @@
 import java.util.List;
 import java.util.Map;
 
-import static java.util.Collections.emptyMap;
 import static java.util.stream.Collectors.toList;
 import static org.asciidoctor.test.AsciidoctorInstance.InstanceScope.PER_METHOD;
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.*;
@@ -72,12 +72,12 @@ public class WhenAsciiDocIsLoadedToDocument {
 
     @Test
     public void should_return_empty_sources_when_document_is_null() {
-        assertEmptySources(asciidoctor.load(null, Options.builder().build()));
+        assertEmptySources(asciidoctor.load(null, emptyOptions()));
     }
 
     @Test
     public void should_return_empty_sources_when_document_is_empty() {
-        assertEmptySources(asciidoctor.load(null, Options.builder().build()));
+        assertEmptySources(asciidoctor.load(null, emptyOptions()));
     }
 
     private static void assertEmptySources(Document document) {
@@ -89,7 +89,7 @@ private static void assertEmptySources(Document document) {
 
     @Test
     public void should_return_section_blocks() {
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
         Section section = (Section) document.getBlocks().get(1);
         assertThat(section.getIndex(), is(0));
         assertThat(section.getSectionName(), either(is("sect1")).or(is("section")));
@@ -98,16 +98,14 @@ public void should_return_section_blocks() {
 
     @Test
     public void should_return_blocks_from_a_document() {
-
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
         assertThat(document.getDoctitle(), is("Document Title"));
         assertThat(document.getBlocks(), hasSize(3));
     }
 
     @Test
     public void should_return_a_document_object_from_string() {
-
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
         assertThat(document.getDoctitle(), is("Document Title"));
     }
 
@@ -127,30 +125,16 @@ public void should_find_all_nodes() {
 
     @Test
     public void should_find_elements_from_document() {
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
+        List<StructuralNode> findBy = document.findBy(Map.of("context", ":image"));
 
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
-        Map<Object, Object> selector = new HashMap<>();
-        selector.put("context", ":image");
-        List<StructuralNode> findBy = document.findBy(selector);
         assertThat(findBy, hasSize(2));
-
         assertThat((String) findBy.get(0).getAttributes().get("target"), is("tiger.png"));
         assertThat(findBy.get(0).getLevel(), greaterThan(0));
-
     }
 
     @Test
-    public void should_return_options_from_parsed_string_when_passed_as_map() {
-        Map<String, Object> options = Options.builder().compact(true).build().map();
-        Document document = asciidoctor.load(DOCUMENT, options);
-
-        Map<Object, Object> documentOptions = document.getOptions();
-
-        assertThat((Boolean) documentOptions.get("compact"), is(true));
-    }
-
-    @Test
-    public void should_return_options_from_parsed_string_when_passed_as_options_object() {
+    public void should_return_options_from_parsed_string() {
         Options options = Options.builder()
                 .compact(true)
                 .build();
@@ -162,7 +146,7 @@ public void should_return_options_from_parsed_string_when_passed_as_options_obje
     }
 
     @Test
-    public void should_return_options_from_parsed_file_when_passed_as_options_object(
+    public void should_return_options_from_parsed_file(
             @ClasspathResource("sourcelocation.adoc") File resource) {
 
         Options options = Options.builder()
@@ -177,29 +161,28 @@ public void should_return_options_from_parsed_file_when_passed_as_options_object
 
     @Test
     public void should_return_node_name() {
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
         assertThat(document.getNodeName(), is("document"));
     }
 
     @Test
     public void should_return_if_it_is_inline() {
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
         assertThat(document.isInline(), is(false));
     }
 
     @Test
     public void should_return_if_it_is_block() {
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
         assertThat(document.isBlock(), is(true));
     }
 
     @Test
     public void should_be_able_to_manipulate_attributes() {
-        Map<String, Object> options = Options.builder()
+        Options options = Options.builder()
                 .attributes(Attributes.builder().dataUri(true).build())
                 .compact(true)
-                .build()
-                .map();
+                .build();
         Document document = asciidoctor.load(DOCUMENT, options);
         assertThat(document.getAttributes(), hasKey("toc-placement"));
         assertThat(document.hasAttribute("toc-placement"), is(true));
@@ -209,7 +192,7 @@ public void should_be_able_to_manipulate_attributes() {
 
     @Test
     public void should_be_able_to_get_roles() {
-        Document document = asciidoctor.load(ROLE, new HashMap<>());
+        Document document = asciidoctor.load(ROLE, emptyOptions());
         StructuralNode abstractBlock = document.getBlocks().get(0);
         assertThat(abstractBlock.getRole(), is("famous"));
         assertThat(abstractBlock.hasRole("famous"), is(true));
@@ -220,7 +203,7 @@ public void should_be_able_to_get_roles() {
     @Test
     public void should_be_able_to_add_role() {
         final String tmpRole = "tmpRole";
-        Document document = asciidoctor.load(ROLE, new HashMap<>());
+        Document document = asciidoctor.load(ROLE, emptyOptions());
         StructuralNode abstractBlock = document.getBlocks().get(0);
         assertThat(abstractBlock.hasRole(tmpRole), is(false));
         abstractBlock.addRole(tmpRole);
@@ -230,7 +213,7 @@ public void should_be_able_to_add_role() {
     @Test
     public void should_be_able_to_remove_role() {
         final String famousRole = "famous";
-        Document document = asciidoctor.load(ROLE, new HashMap<>());
+        Document document = asciidoctor.load(ROLE, emptyOptions());
         StructuralNode abstractBlock = document.getBlocks().get(0);
         assertThat(abstractBlock.hasRole(famousRole), is(true));
         abstractBlock.removeRole(famousRole);
@@ -239,7 +222,7 @@ public void should_be_able_to_remove_role() {
 
     @Test
     public void should_be_able_to_get_reftext() {
-        Document document = asciidoctor.load(REFTEXT, new HashMap<>());
+        Document document = asciidoctor.load(REFTEXT, emptyOptions());
         StructuralNode abstractBlock = document.getBlocks().get(0);
         assertThat(abstractBlock.getReftext(), is("the first section"));
         assertThat(abstractBlock.isReftext(), is(true));
@@ -247,22 +230,20 @@ public void should_be_able_to_get_reftext() {
 
     @Test
     public void should_be_able_to_get_icon_uri_string_reference() {
-        Map<String, Object> options = Options.builder()
+        Options options = Options.builder()
                 .attributes(Attributes.builder().dataUri(false).build())
                 .compact(true)
-                .build()
-                .map();
+                .build();
         Document document = asciidoctor.load(DOCUMENT, options);
         assertThat(document.iconUri("note"), is("./images/icons/note.png"));
     }
 
     @Test
     public void should_be_able_to_get_icon_uri() {
-        Map<String, Object> options = Options.builder().safe(SafeMode.SAFE)
+        Options options = Options.builder().safe(SafeMode.SAFE)
                 .attributes(Attributes.builder().dataUri(true).icons("font").build())
                 .compact(true)
-                .build()
-                .map();
+                .build();
         Document document = asciidoctor.load(DOCUMENT, options);
         assertThat(document.iconUri("note"),
                 either(
@@ -273,17 +254,16 @@ public void should_be_able_to_get_icon_uri() {
 
     @Test
     public void should_be_able_to_get_media_uri() {
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
         assertThat(document.mediaUri("target"), is("target"));
     }
 
     @Test
     public void should_be_able_to_get_image_uri() {
-        Map<String, Object> options = Options.builder().safe(SafeMode.SAFE)
+        Options options = Options.builder().safe(SafeMode.SAFE)
                 .attributes(Attributes.builder().dataUri(false).build())
                 .compact(true)
-                .build()
-                .map();
+                .build();
         Document document = asciidoctor.load(DOCUMENT, options);
         assertThat(document.imageUri("target.jpg"), is("target.jpg"));
         assertThat(document.imageUri("target.jpg", "imagesdir"), is("target.jpg"));
@@ -291,7 +271,7 @@ public void should_be_able_to_get_image_uri() {
 
     @Test
     public void should_be_able_to_normalize_web_path() {
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
         assertThat(document.normalizeWebPath("target", null, true), is("target"));
     }
 
@@ -299,11 +279,10 @@ public void should_be_able_to_normalize_web_path() {
     public void should_be_able_to_read_asset(
             @ClasspathResource("rendersample.asciidoc") File inputFile) throws IOException {
 
-        Map<String, Object> options = Options.builder().safe(SafeMode.SAFE)
+        Options options = Options.builder().safe(SafeMode.SAFE)
                 .attributes(Attributes.builder().dataUri(false).build())
                 .compact(true)
-                .build()
-                .map();
+                .build();
         Document document = asciidoctor.load(DOCUMENT, options);
 
         String content = document.readAsset(inputFile.getAbsolutePath(), new HashMap<>());
@@ -314,7 +293,7 @@ public void should_be_able_to_read_asset(
     public void should_be_able_to_set_attribute() {
         final Object attributeName = "testattribute";
         final Object attributeValue = "testvalue";
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
         assertThat(document.setAttribute(attributeName, attributeValue, true), is(true));
         assertThat(document.getAttribute(attributeName), is(attributeValue));
         assertThat(document.getAttributes().get(attributeName), is(attributeValue));
@@ -324,7 +303,7 @@ public void should_be_able_to_set_attribute() {
     public void should_be_able_to_set_attribute_on_attributes_map() {
         final String attributeName = "testattribute";
         final Object attributeValue = "testvalue";
-        Document document = asciidoctor.load(DOCUMENT, new HashMap<>());
+        Document document = asciidoctor.load(DOCUMENT, emptyOptions());
         document.getAttributes().put(attributeName, attributeValue);
         assertThat(document.getAttribute(attributeName), is(attributeValue));
         assertThat(document.getAttributes().get(attributeName), is(attributeValue));
@@ -335,23 +314,23 @@ public void should_be_able_to_get_source_location(
             @ClasspathResource("sourcelocation.adoc") File file) {
 
         // When
-        Document document = asciidoctor.loadFile(file, Options.builder().sourcemap(true).docType("book").build().map());
+        Document document = asciidoctor.loadFile(file, Options.builder().sourcemap(true).docType("book").build());
         Map<Object, Object> selector = new HashMap<>();
         selector.put("context", ":paragraph");
         List<StructuralNode> findBy = document.findBy(selector);
 
         // Then
-        StructuralNode block1 = findBy.get(0);
-        assertThat(block1.getSourceLocation().getLineNumber(), is(3));
-        assertThat(block1.getSourceLocation().getPath(), is(file.getName()));
-        assertThat(block1.getSourceLocation().getFile(), is(file.getName()));
-        assertThat(block1.getSourceLocation().getDir(), is(file.getParent().replaceAll("\\\\", "/")));
+        Cursor sourceLocation1 = findBy.get(0).getSourceLocation();
+        assertThat(sourceLocation1.getLineNumber(), is(3));
+        assertThat(sourceLocation1.getPath(), is(file.getName()));
+        assertThat(sourceLocation1.getFile(), is(file.getName()));
+        assertThat(sourceLocation1.getDir(), is(file.getParent().replaceAll("\\\\", "/")));
 
-        StructuralNode block2 = findBy.get(1);
-        assertThat(block2.getSourceLocation().getLineNumber(), is(8));
-        assertThat(block2.getSourceLocation().getPath(), is(file.getName()));
-        assertThat(block2.getSourceLocation().getFile(), is(file.getName()));
-        assertThat(block2.getSourceLocation().getDir(), is(file.getParent().replaceAll("\\\\", "/")));
+        Cursor sourceLocation2 = findBy.get(1).getSourceLocation();
+        assertThat(sourceLocation2.getLineNumber(), is(8));
+        assertThat(sourceLocation2.getPath(), is(file.getName()));
+        assertThat(sourceLocation2.getFile(), is(file.getName()));
+        assertThat(sourceLocation2.getDir(), is(file.getParent().replaceAll("\\\\", "/")));
     }
 
     @Test
@@ -367,7 +346,7 @@ public void should_get_attributes() {
                 "paragraph\n" +
                 "\n";
 
-        Document document = asciidoctor.load(documentWithAttributes, new HashMap<>());
+        Document document = asciidoctor.load(documentWithAttributes, emptyOptions());
         List<StructuralNode> blocks = document.getBlocks();
 
         Section section = (Section) blocks.get(1);
@@ -398,7 +377,7 @@ public void should_get_content_model() {
                 + "And herein lies the problem.\n"
                 + "\n";
 
-        Document document = asciidoctor.load(documentWithPreambleAndSection, new HashMap<>());
+        Document document = asciidoctor.load(documentWithPreambleAndSection, emptyOptions());
         List<StructuralNode> blocks = document.getBlocks();
 
         StructuralNode preambleContainer = blocks.get(0);
@@ -414,24 +393,24 @@ public void should_get_content_model() {
 
     @Test
     public void should_be_able_to_get_parent_from_document() {
-        String s = "== A small Example\n" +
+        String content = "== A small Example\n" +
                 "\n" +
                 "Lorem ipsum dolor sit amet:\n";
 
-        Document document = asciidoctor.load(s, new HashMap<>());
+        Document document = asciidoctor.load(content, emptyOptions());
         assertThat(document.getParent(), nullValue());
     }
 
     @Test
     public void should_read_caption() {
-        String s = "[caption=\"Table A. \"]\n" +
+        String content = "[caption=\"Table A. \"]\n" +
                 ".A formal table\n" +
                 "|===\n" +
                 "|Cell in column 1, row 1\n" +
                 "|Cell in column 2, row 1\n" +
                 "|===";
 
-        Document document = asciidoctor.load(s, new HashMap<>());
+        Document document = asciidoctor.load(content, emptyOptions());
         assertThat(document.getBlocks(), notNullValue());
         assertThat(document.getBlocks().size(), is(1));
         assertThat(document.getBlocks().get(0).getCaption(), is("Table A. "));
@@ -443,7 +422,7 @@ public void should_get_empty_collection_when_no_author_is_set() {
                 "\n" +
                 "Preamble...";
 
-        Document document = asciidoctor.load(content, emptyMap());
+        Document document = asciidoctor.load(content, emptyOptions());
 
         List<Author> authors = document.getAuthors();
         assertThat(authors, hasSize(0));
@@ -456,7 +435,7 @@ public void should_get_single_author_when_only_one_is_set_in_author_line() {
                 "\n" +
                 "Preamble...";
 
-        Document document = asciidoctor.load(content, emptyMap());
+        Document document = asciidoctor.load(content, emptyOptions());
 
         List<Author> authors = document.getAuthors();
         assertThat(authors, hasSize(1));
@@ -478,7 +457,7 @@ public void should_get_single_author_when_only_one_is_set_in_attribute() {
                 "\n" +
                 "Preamble...";
 
-        Document document = asciidoctor.load(content, emptyMap());
+        Document document = asciidoctor.load(content, emptyOptions());
 
         List<Author> authors = document.getAuthors();
         assertThat(authors, hasSize(1));
@@ -499,7 +478,7 @@ public void should_get_multiple_authors_when_they_arez_set_in_author_line() {
                 "\n" +
                 "Preamble...";
 
-        Document document = asciidoctor.load(content, emptyMap());
+        Document document = asciidoctor.load(content, emptyOptions());
 
         List<Author> authors = document.getAuthors();
         assertThat(authors, hasSize(2));
@@ -529,7 +508,7 @@ public void should_get_revision_info() {
                 "\n" +
                 "Preamble...";
 
-        Document document = asciidoctor.load(content, emptyMap());
+        Document document = asciidoctor.load(content, emptyOptions());
 
         RevisionInfo revisionInfo = document.getRevisionInfo();
 
@@ -619,8 +598,7 @@ public void should_return_source_and_source_lines_without_resolving_includes() {
     }
 
     private Document loadDocument(String source) {
-        Options options = Options.builder().build();
-        return asciidoctor.load(source, options);
+        return asciidoctor.load(source, emptyOptions());
     }
 
     static String asciidocWithSections() {
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciidoctorLogsToConsole.java b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciidoctorLogsToConsole.java
index d3d569815..d9efa46f2 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciidoctorLogsToConsole.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAsciidoctorLogsToConsole.java
@@ -71,7 +71,8 @@ public void shouldRedirectToJUL() {
                 Options.builder()
                         .inPlace(true)
                         .safe(SafeMode.SERVER)
-                        .attributes(Attributes.builder().allowUriRead(true).build()));
+                        .attributes(Attributes.builder().allowUriRead(true).build())
+                        .build());
 
         File expectedFile = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
         expectedFile.delete();
@@ -101,7 +102,8 @@ public void shouldNotifyLogHandler() {
                 Options.builder()
                         .inPlace(true)
                         .safe(SafeMode.SERVER)
-                        .attributes(Attributes.builder().allowUriRead(true).build()));
+                        .attributes(Attributes.builder().allowUriRead(true).build())
+                        .build());
 
         File expectedFile = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
         expectedFile.delete();
@@ -134,7 +136,8 @@ public void shouldLogInvalidRefs() {
                         .inPlace(true)
                         .safe(SafeMode.SERVER)
                         .toFile(false)
-                        .attributes(Attributes.builder().allowUriRead(true).build()));
+                        .attributes(Attributes.builder().allowUriRead(true).build())
+                        .build());
 
         assertThat(logRecords, hasSize(1));
         assertThat(logRecords.get(0).getMessage(), containsString("invalid reference: invalidref"));
@@ -157,7 +160,8 @@ public void shouldOnlyNotifyFromRegisteredAsciidoctor() {
                 Options.builder()
                         .inPlace(true)
                         .safe(SafeMode.SERVER)
-                        .attributes(Attributes.builder().allowUriRead(true).build()));
+                        .attributes(Attributes.builder().allowUriRead(true).build())
+                        .build());
 
         File expectedFile1 = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
         expectedFile1.delete();
@@ -169,7 +173,8 @@ public void shouldOnlyNotifyFromRegisteredAsciidoctor() {
                 Options.builder()
                         .inPlace(true)
                         .safe(SafeMode.SERVER)
-                        .attributes(Attributes.builder().allowUriRead(true).build()));
+                        .attributes(Attributes.builder().allowUriRead(true).build())
+                        .build());
 
         File expectedFile2 = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
         expectedFile2.delete();
@@ -195,7 +200,8 @@ public void shouldNoLongerNotifyAfterUnregisterOnlyNotifyFromRegisteredAsciidoct
                 Options.builder()
                         .inPlace(true)
                         .safe(SafeMode.SERVER)
-                        .attributes(Attributes.builder().allowUriRead(true).build()));
+                        .attributes(Attributes.builder().allowUriRead(true).build())
+                        .build());
 
         File expectedFile = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
         expectedFile.delete();
@@ -209,12 +215,12 @@ public void shouldNoLongerNotifyAfterUnregisterOnlyNotifyFromRegisteredAsciidoct
                 Options.builder()
                         .inPlace(true)
                         .safe(SafeMode.SERVER)
-                        .attributes(Attributes.builder().allowUriRead(true).build()));
+                        .attributes(Attributes.builder().allowUriRead(true).build())
+                        .build());
 
         File expectedFile2 = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
         expectedFile2.delete();
         assertEquals(0, logRecords.size());
-
     }
 
     @Test
@@ -225,7 +231,8 @@ public void shouldNotifyLogHandlerService() {
                 Options.builder()
                         .inPlace(true)
                         .safe(SafeMode.SERVER)
-                        .attributes(Attributes.builder().allowUriRead(true).build()));
+                        .attributes(Attributes.builder().allowUriRead(true).build())
+                        .build());
 
         File expectedFile = new File(inputFile.getParent(), "documentwithnotexistingfile.html");
         expectedFile.delete();
@@ -271,7 +278,7 @@ public void a_extension_should_be_able_to_log() {
         asciidoctor.javaExtensionRegistry().block(LoggingProcessor.class);
 
         String renderContent = asciidoctor.convert("= Test\n\n== Something different\n\n[big]\nHello World",
-                Options.builder().option("sourcemap", "true").build().map());
+                Options.builder().option("sourcemap", "true").build());
 
         assertEquals(1, logRecords.size());
         assertThat(logRecords.get(0).getMessage(), is("Hello Log"));
@@ -292,7 +299,7 @@ public void should_fail_convert_when_logHandler_throws_an_exception() {
         try {
             asciidoctor.convert(
                     "= Test\n\n== Something different\n\n[big]\nHello World",
-                    Options.builder().option("sourcemap", "true").build().map());
+                    Options.builder().option("sourcemap", "true").build());
         } catch (Throwable t) {
             // then
             assertThat(t.getMessage(), containsString("Failed to load AsciiDoc document"));
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAttributesAreUsedInAsciidoctor.java b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAttributesAreUsedInAsciidoctor.java
index cb3762b88..e653331e2 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAttributesAreUsedInAsciidoctor.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenAttributesAreUsedInAsciidoctor.java
@@ -59,7 +59,7 @@ public void qualified_http_url_inline_with_hide_uri_scheme_set() {
                 .hiddenUriScheme(true)
                 .build();
 
-        String content = asciidoctor.convert("The AsciiDoc project is located at https://asciidoc.org.", Options.builder().attributes(attributes));
+        String content = asciidoctor.convert("The AsciiDoc project is located at https://asciidoc.org.", Options.builder().attributes(attributes).build());
 
         Document doc = Jsoup.parse(content, "UTF-8");
         Element link = doc.getElementsByTag("a").first();
@@ -75,7 +75,7 @@ public void compat_mode_should_change_how_document_is_rendered_to_legacy_system(
                 .compatMode(CompatMode.LEGACY)
                 .build();
 
-        String content = asciidoctor.convert("The `AsciiDoc {version}` project.", Options.builder().attributes(attributes));
+        String content = asciidoctor.convert("The `AsciiDoc {version}` project.", Options.builder().attributes(attributes).build());
 
         Document doc = Jsoup.parse(content, "UTF-8");
         Element code = doc.getElementsByTag("code").first();
@@ -90,7 +90,7 @@ public void no_compat_mode_should_change_how_document_is_rendered_to_new_system(
                 .attribute("version", "1.0.0")
                 .build();
 
-        String content = asciidoctor.convert("The `AsciiDoc {version}` project.", Options.builder().attributes(attributes));
+        String content = asciidoctor.convert("The `AsciiDoc {version}` project.", Options.builder().attributes(attributes).build());
 
         Document doc = Jsoup.parse(content, "UTF-8");
         Element code = doc.getElementsByTag("code").first();
@@ -105,7 +105,7 @@ public void should_preload_open_cache_uri_gem() {
                 .cacheUri(true)
                 .build();
 
-        String content = asciidoctor.convert("read my lips", Options.builder().attributes(attributes));
+        String content = asciidoctor.convert("read my lips", Options.builder().attributes(attributes).build());
 
         assertThat(content, is(notNullValue()));
 
@@ -158,7 +158,7 @@ public void should_add_a_hardbreak_at_end_of_each_line_when_hardbreaks_option_is
 
         Attributes attributes = Attributes.builder().hardbreaks(true).build();
 
-        String content = asciidoctor.convert("read\nmy\nlips", Options.builder().attributes(attributes));
+        String content = asciidoctor.convert("read\nmy\nlips", Options.builder().attributes(attributes).build());
 
         Document doc = Jsoup.parse(content, "UTF-8");
         Element paragraph = doc.getElementsByAttributeValue("class", "paragraph").first();
@@ -854,7 +854,7 @@ public void string_content_with_icons_enabled_should_be_rendered()
         Attributes attributes = Attributes.builder()
                 .icons(Attributes.IMAGE_ICONS)
                 .build();
-        Map<String, Object> options = Options.builder().attributes(attributes).build().map();
+        Options options = Options.builder().attributes(attributes).build();
 
         String result = asciidoctor.convert(Files.readString(documentWithNote.toPath()), options);
         result = result.replaceAll("<img(.*?)>", "<img$1/>");
@@ -871,7 +871,7 @@ public void string_content_with_fontawesome_icons_enabled_should_be_rendered()
         Attributes attributes = Attributes.builder()
                 .icons(Attributes.FONT_ICONS)
                 .build();
-        Map<String, Object> options = Options.builder().attributes(attributes).build().map();
+        Options options = Options.builder().attributes(attributes).build();
 
         String result = asciidoctor.convert(toString(content), options);
         assertRenderedFontAwesomeAdmonitionIcon(result);
@@ -888,7 +888,7 @@ public void string_content_with_icons_enabled_and_iconsdir_set_should_be_rendere
                 .icons(Attributes.IMAGE_ICONS)
                 .iconsDir("icons")
                 .build();
-        Map<String, Object> options = Options.builder().attributes(attributes).build().map();
+        Options options = Options.builder().attributes(attributes).build();
 
         String renderContent = asciidoctor.convert(toString(content), options);
 
@@ -983,5 +983,4 @@ private static org.w3c.dom.Document inputStream2Document(
                 inputStream);
         return parse;
     }
-
 }
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenDocumentHeaderIsRequired.java b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenDocumentHeaderIsRequired.java
index c4c5374f4..a61e55c5d 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenDocumentHeaderIsRequired.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenDocumentHeaderIsRequired.java
@@ -1,7 +1,7 @@
 package org.asciidoctor;
 
 import org.asciidoctor.ast.Author;
-import org.asciidoctor.ast.DocumentHeader;
+import org.asciidoctor.ast.Document;
 import org.asciidoctor.ast.RevisionInfo;
 import org.asciidoctor.test.AsciidoctorInstance;
 import org.asciidoctor.test.ClasspathResource;
@@ -35,30 +35,31 @@ public class WhenDocumentHeaderIsRequired {
 
     @Test
     public void doctitle_blocks_and_attributes_should_be_returned() {
+        final Options options = parseHeaderOnlyOptions();
+        final Document document = asciidoctor.loadFile(documentHeaders, options);
 
-        DocumentHeader header = asciidoctor.readDocumentHeader(documentHeaders);
+        assertThat(document.getDoctitle(), is("Sample Document"));
+        assertThat(document.getStructuredDoctitle().getMain(), is("Sample Document"));
 
-
-        assertThat(header.getDocumentTitle().getMain(), is("Sample Document"));
-        assertThat(header.getPageTitle(), is("Sample Document"));
-
-        Map<String, Object> attributes = header.getAttributes();
+        Map<String, Object> attributes = document.getAttributes();
         assertThat((String) attributes.get("revdate"), is("2013-05-20"));
         assertThat((String) attributes.get("revnumber"), is("1.0"));
         assertThat((String) attributes.get("revremark"), is("First draft"));
         //attributes should be incasesensitive
         assertThat((String) attributes.get("tags"), is("[document, example]"));
-        assertThat((String) attributes.get("Tags"), is("[document, example]"));
         assertThat((String) attributes.get("author"), is("Doc Writer"));
         assertThat((String) attributes.get("email"), is("doc.writer@asciidoc.org"));
     }
 
     @Test
     public void author_info_should_be_bound_into_author_class() {
+        final Options options = parseHeaderOnlyOptions();
+        final Document document = asciidoctor.loadFile(documentHeaders, options);
 
-        DocumentHeader header = asciidoctor.readDocumentHeader(documentHeaders);
+        List<Author> authors = document.getAuthors();
+        assertThat(authors, hasSize(2));
 
-        Author author = header.getAuthor();
+        Author author = authors.get(0);
         assertThat(author.getEmail(), is("doc.writer@asciidoc.org"));
         assertThat(author.getFullName(), is("Doc Writer"));
         assertThat(author.getFirstName(), is("Doc"));
@@ -68,10 +69,10 @@ public void author_info_should_be_bound_into_author_class() {
 
     @Test
     public void revision_info_should_be_bound_into_revision_info_class() {
+        final Options options = parseHeaderOnlyOptions();
+        final Document document = asciidoctor.loadFile(documentHeaders, options);
 
-        DocumentHeader header = asciidoctor.readDocumentHeader(documentHeaders);
-
-        RevisionInfo revisionInfo = header.getRevisionInfo();
+        RevisionInfo revisionInfo = document.getRevisionInfo();
 
         assertThat(revisionInfo.getDate(), is("2013-05-20"));
         assertThat(revisionInfo.getNumber(), is("1.0"));
@@ -81,9 +82,10 @@ public void revision_info_should_be_bound_into_revision_info_class() {
     @Test
     public void multiple_authors_should_be_bound_into_list_of_authors() {
 
-        DocumentHeader header = asciidoctor.readDocumentHeader(documentHeaders);
+        final Options options = parseHeaderOnlyOptions();
+        final Document document = asciidoctor.loadFile(documentHeaders, options);
 
-        List<? extends Author> authors = header.getAuthors();
+        List<Author> authors = document.getAuthors();
         assertThat(authors, hasSize(2));
 
         Author author1 = authors.get(0);
@@ -103,4 +105,9 @@ public void multiple_authors_should_be_bound_into_list_of_authors() {
         assertThat(author2.getInitials(), is("JS"));
     }
 
+    private static Options parseHeaderOnlyOptions() {
+        return Options.builder()
+                .option("parse_header_only", true)
+                .build();
+    }
 }
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenSourceHighlightingIsUsed.java b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenSourceHighlightingIsUsed.java
index 60b662344..99d483a84 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/WhenSourceHighlightingIsUsed.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/WhenSourceHighlightingIsUsed.java
@@ -30,13 +30,7 @@ public class WhenSourceHighlightingIsUsed {
     @Test
     public void should_render_with_rouge() {
         String html = asciidoctor.convert(DOCUMENT,
-                Options.builder()
-                        .standalone(true)
-                        .safe(SafeMode.UNSAFE)
-                        .attributes(
-                                Attributes.builder()
-                                        .sourceHighlighter("rouge")
-                                        .build()));
+                sourceHighlighter("rouge"));
 
         Document doc = Jsoup.parse(html);
 
@@ -47,18 +41,21 @@ public void should_render_with_rouge() {
     @Test
     public void should_render_with_coderay() {
         String html = asciidoctor.convert(DOCUMENT,
-                Options.builder()
-                        .standalone(true)
-                        .safe(SafeMode.UNSAFE)
-                        .attributes(
-                                Attributes.builder()
-                                        .sourceHighlighter("coderay")
-                                        .build()));
-
+                sourceHighlighter("coderay"));
 
         Document doc = Jsoup.parse(html);
 
         assertThat("No elements were highlighted", doc.select("pre.CodeRay span.class").size(), greaterThan(0));
         assertThat("CSS was not added", html, containsString(".CodeRay .class"));
     }
+
+    private static Options sourceHighlighter(String sourceHighlighter) {
+        return Options.builder()
+                .standalone(true)
+                .safe(SafeMode.UNSAFE)
+                .attributes(Attributes.builder()
+                        .sourceHighlighter(sourceHighlighter)
+                        .build())
+                .build();
+    }
 }
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/converter/WhenConverterIsRegistered.java b/asciidoctorj-core/src/test/java/org/asciidoctor/converter/WhenConverterIsRegistered.java
index 252979551..d58400860 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/converter/WhenConverterIsRegistered.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/converter/WhenConverterIsRegistered.java
@@ -56,7 +56,7 @@ public void shouldCleanUpRegistry() {
     public void shouldRegisterAndExecuteGivenConverter() {
         asciidoctor.javaConverterRegistry().register(TextConverter.class, "test");
 
-        String result = asciidoctor.convert("== Hello\n\nWorld!\n\n- a\n- b", Options.builder().backend("test"));
+        String result = asciidoctor.convert("== Hello\n\nWorld!\n\n- a\n- b", Options.builder().backend("test").build());
 
         assertThat(result, is("== Hello ==\n\nWorld!\n\n-> a\n-> b\n"));
     }
@@ -67,7 +67,7 @@ public void shouldRegisterWithBackendNameFromAnnotation() {
         asciidoctor.javaConverterRegistry().register(TextConverter.class);
         asciidoctor.javaConverterRegistry().register(DummyConverter.class);
 
-        String result = asciidoctor.convert("== Hello\n\nWorld!\n\n- a\n- b", Options.builder().backend(TextConverter.DEFAULT_FORMAT));
+        String result = asciidoctor.convert("== Hello\n\nWorld!\n\n- a\n- b", Options.builder().backend(TextConverter.DEFAULT_FORMAT).build());
 
         assertThat(result, is("== Hello ==\n\nWorld!\n\n-> a\n-> b\n"));
     }
@@ -77,7 +77,7 @@ public void shouldUseDefaultBackend() {
         // Register as default converter
         asciidoctor.javaConverterRegistry().register(DummyConverter.class);
 
-        String result = asciidoctor.convert("== Hello\n\nWorld!\n\n- a\n- b", Options.builder().backend("Undefined"));
+        String result = asciidoctor.convert("== Hello\n\nWorld!\n\n- a\n- b", Options.builder().backend("Undefined").build());
 
         assertThat(result, is("Dummy"));
     }
@@ -95,7 +95,7 @@ public void shouldBeAbleToLog() {
         try {
             asciidoctor.javaConverterRegistry().register(TextConverter.class);
 
-            String result = asciidoctor.convert("== Hello\n\nWorld!\n\n- a\n- b", Options.builder().backend(TextConverter.DEFAULT_FORMAT));
+            asciidoctor.convert("== Hello\n\nWorld!\n\n- a\n- b", Options.builder().backend(TextConverter.DEFAULT_FORMAT).build());
 
             assertThat(handler.getLogRecords(), hasSize(1));
             assertThat(handler.getLogRecords().get(0).getMessage(), is("Now we're logging"));
@@ -142,7 +142,7 @@ void processNode(StructuralNode block) {
                 "\n" +
                 "== Test" +
                 "\n" +
-                "== Test2\n", Options.builder().backend("test3").standalone(false));
+                "== Test2\n", Options.builder().backend("test3").standalone(false).build());
 
         assertEquals("== 1 Test ==\n" +
                 "== 42 Test2 ==", result);
@@ -157,7 +157,7 @@ public void shouldRegisterConverterViaConverterRegistryExecutor(
         try {
             Thread.currentThread().setContextClassLoader(new URLClassLoader(new URL[]{serviceLoader.toURI().toURL()}));
             asciidoctor = JRubyAsciidoctor.create();
-            String result = asciidoctor.convert("== Hello\n\nWorld!\n\n- a\n- b", Options.builder().backend("extensiontext"));
+            String result = asciidoctor.convert("== Hello\n\nWorld!\n\n- a\n- b", Options.builder().backend("extensiontext").build());
 
             assertThat(result, is("== Hello ==\n\nWorld!\n\n-> a\n-> b\n"));
         } finally {
@@ -168,26 +168,21 @@ public void shouldRegisterConverterViaConverterRegistryExecutor(
 
     @Test
     public void shouldWriteFileWithSuffixFromConverterWithAnnotation(@TempDir File tempDir) {
-
         asciidoctor.javaConverterRegistry().register(TextConverter.class);
 
-        File todir = tempDir;
-        asciidoctor.convertFile(simpleDocument, Options.builder().backend(TextConverter.DEFAULT_FORMAT).toDir(todir).safe(SafeMode.UNSAFE));
+        asciidoctor.convertFile(simpleDocument, Options.builder().backend(TextConverter.DEFAULT_FORMAT).toDir(tempDir).safe(SafeMode.UNSAFE).build());
 
-        assertThat(new File(todir, "simple.html").exists(), is(false));
-        assertThat(new File(todir, "simple.txt").exists(), is(true));
+        assertThat(new File(tempDir, "simple.html").exists(), is(false));
+        assertThat(new File(tempDir, "simple.txt").exists(), is(true));
     }
 
     @Test
     public void shouldWriteFileWithSuffixFromConverterThatInvokesSetOutfileSuffix(@TempDir File tempDir) {
-
         asciidoctor.javaConverterRegistry().register(TextConverterWithSuffix.class);
 
-        File todir = tempDir;
-        asciidoctor.convertFile(simpleDocument, Options.builder().backend(TextConverterWithSuffix.DEFAULT_FORMAT).toDir(todir).safe(SafeMode.UNSAFE));
+        asciidoctor.convertFile(simpleDocument, Options.builder().backend(TextConverterWithSuffix.DEFAULT_FORMAT).toDir(tempDir).safe(SafeMode.UNSAFE).build());
 
-        assertThat(new File(todir, "simple.html").exists(), is(false));
-        assertThat(new File(todir, "simple.text").exists(), is(true));
+        assertThat(new File(tempDir, "simple.html").exists(), is(false));
+        assertThat(new File(tempDir, "simple.text").exists(), is(true));
     }
-
 }
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/BlockMacroRegistrationTest.java b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/BlockMacroRegistrationTest.java
index 0602e85b5..200a2be72 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/BlockMacroRegistrationTest.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/BlockMacroRegistrationTest.java
@@ -2,6 +2,7 @@
 
 import org.asciidoctor.Asciidoctor;
 import org.asciidoctor.Options;
+import org.asciidoctor.OptionsBuilder;
 import org.asciidoctor.ast.StructuralNode;
 import org.asciidoctor.jruby.internal.AsciidoctorCoreException;
 import org.asciidoctor.test.AsciidoctorInstance;
@@ -19,6 +20,7 @@
 import static java.lang.annotation.ElementType.TYPE;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 import static org.asciidoctor.test.AsciidoctorInstance.InstanceScope.PER_METHOD;
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions;
 import static org.junit.Assert.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
@@ -83,23 +85,23 @@ public static class AnnotatedTestProcessorWithMultipleNameAnnotations extends Ab
     @Test
     public void testRegisterNamedClassAsClass() {
         asciidoctor.javaExtensionRegistry().blockMacro(AnnotatedTestProcessor.class);
-        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "Hello World"), Options.builder());
+        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "Hello World"), emptyOptions());
         check("HELLO WORLD", result);
     }
 
     @Test
     public void testRegisterClassWithMetaNameAnnotation() {
         asciidoctor.javaExtensionRegistry().blockMacro(AnnotatedTestProcessorWithMetaNameAnnotation.class);
-        final String result = asciidoctor.convert(document(MetaNameAnnotation.NAME, "Hello World"), Options.builder());
+        final String result = asciidoctor.convert(document(MetaNameAnnotation.NAME, "Hello World"), emptyOptions());
         check("HELLO WORLD", result);
     }
 
     @Test
     public void testRegisterClassWithMultipleNameAnnotations() {
         asciidoctor.javaExtensionRegistry().blockMacro(AnnotatedTestProcessorWithMultipleNameAnnotations.class);
-        String result = asciidoctor.convert(document(MetaNameAnnotation.NAME, "Hello World"), Options.builder());
+        String result = asciidoctor.convert(document(MetaNameAnnotation.NAME, "Hello World"), emptyOptions());
         check("HELLO WORLD", result);
-        result = asciidoctor.convert(document(AnnotatedTestProcessorWithMultipleNameAnnotations.NAME, "Hello World"), Options.builder());
+        result = asciidoctor.convert(document(AnnotatedTestProcessorWithMultipleNameAnnotations.NAME, "Hello World"), emptyOptions());
         check("HELLO WORLD", result);
     }
 
@@ -107,14 +109,14 @@ public void testRegisterClassWithMultipleNameAnnotations() {
     public void testRegisterNamedClassAsClassWithExplicitName() {
         final String explicitblockname = "explicitblockname";
         asciidoctor.javaExtensionRegistry().blockMacro(explicitblockname, AnnotatedTestProcessor.class);
-        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit"), emptyOptions());
         check("HELLO EXPLICIT", result);
     }
 
     @Test
     public void testRegisterNamedClassAsInstance() {
         asciidoctor.javaExtensionRegistry().blockMacro(new AnnotatedTestProcessor());
-        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "Another Test"), Options.builder());
+        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "Another Test"), emptyOptions());
         check("ANOTHER TEST", result);
     }
 
@@ -122,7 +124,7 @@ public void testRegisterNamedClassAsInstance() {
     public void testRegisterNamedClassAsInstanceWithExplicitName() {
         final String blockName = "somename";
         asciidoctor.javaExtensionRegistry().blockMacro(blockName, new AnnotatedTestProcessor());
-        final String result = asciidoctor.convert(document(blockName, "Yet Another Test"), Options.builder());
+        final String result = asciidoctor.convert(document(blockName, "Yet Another Test"), emptyOptions());
         check("YET ANOTHER TEST", result);
     }
 
@@ -135,7 +137,7 @@ public void testRegisterClassWithoutExplicitName() {
     public void testRegisterClassAsClassWithExplicitName() {
         final String explicitblockname = "anotherexplicitname";
         asciidoctor.javaExtensionRegistry().blockMacro(explicitblockname, AbstractTestProcessor.class);
-        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit Class"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit Class"), emptyOptions());
         check("HELLO EXPLICIT CLASS", result);
     }
 
@@ -143,7 +145,7 @@ public void testRegisterClassAsClassWithExplicitName() {
     public void testRegisterClassAsInstance() {
         assertThrows(AsciidoctorCoreException.class, () -> {
             asciidoctor.javaExtensionRegistry().blockMacro(new AbstractTestProcessor());
-            asciidoctor.convert(document("foo", "Hello Explicit Instance"), Options.builder());
+            asciidoctor.convert(document("foo", "Hello Explicit Instance"), emptyOptions());
         });
     }
 
@@ -151,7 +153,7 @@ public void testRegisterClassAsInstance() {
     public void testRegisterClassAsInstanceWithExplicitName() {
         final String explicitblockname = "aname";
         asciidoctor.javaExtensionRegistry().blockMacro(explicitblockname, new AbstractTestProcessor());
-        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit Instance"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit Instance"), emptyOptions());
         check("HELLO EXPLICIT INSTANCE", result);
     }
 
@@ -165,14 +167,14 @@ public void testRegisterClassWithNameAsClass() {
     public void testRegisterClassWithNameAsClassWithExplicitName() {
         final String explicitblockname = "explicitblockname";
         asciidoctor.javaExtensionRegistry().blockMacro(explicitblockname, TestProcessorWithName.class);
-        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit"), emptyOptions());
         check("HELLO EXPLICIT", result);
     }
 
     @Test
     public void testRegisterClassWithNameAsInstance() {
         asciidoctor.javaExtensionRegistry().blockMacro(new TestProcessorWithName());
-        final String result = asciidoctor.convert(document(TestProcessorWithName.NAME, "Another Test"), Options.builder());
+        final String result = asciidoctor.convert(document(TestProcessorWithName.NAME, "Another Test"), emptyOptions());
         check("ANOTHER TEST", result);
     }
 
@@ -180,7 +182,7 @@ public void testRegisterClassWithNameAsInstance() {
     public void testRegisterClassWithNameAsInstanceWithExplicitName() {
         final String blockName = "somename";
         asciidoctor.javaExtensionRegistry().blockMacro(blockName, new TestProcessorWithName());
-        final String result = asciidoctor.convert(document(blockName, "Yet Another Test"), Options.builder());
+        final String result = asciidoctor.convert(document(blockName, "Yet Another Test"), emptyOptions());
         check("YET ANOTHER TEST", result);
     }
 
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/BlockProcessorRegistrationTest.java b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/BlockProcessorRegistrationTest.java
index 5863b0188..ac5298b9e 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/BlockProcessorRegistrationTest.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/BlockProcessorRegistrationTest.java
@@ -1,7 +1,6 @@
 package org.asciidoctor.extension;
 
 import org.asciidoctor.Asciidoctor;
-import org.asciidoctor.Options;
 import org.asciidoctor.ast.StructuralNode;
 import org.asciidoctor.jruby.internal.AsciidoctorCoreException;
 import org.asciidoctor.test.AsciidoctorInstance;
@@ -16,6 +15,7 @@
 import static java.util.stream.Collectors.joining;
 import static java.util.stream.Collectors.toList;
 import static org.asciidoctor.test.AsciidoctorInstance.InstanceScope.PER_METHOD;
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions;
 import static org.junit.Assert.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
@@ -75,7 +75,7 @@ public static class AnnotatedTestProcessor extends AbstractTestProcessor {
     @Test
     public void testRegisterNamedClassAsClass() {
         asciidoctor.javaExtensionRegistry().block(AnnotatedTestProcessor.class);
-        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "Hello World"), Options.builder());
+        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "Hello World"), emptyOptions());
         check("H e l l o W o r l d", result);
     }
 
@@ -83,14 +83,14 @@ public void testRegisterNamedClassAsClass() {
     public void testRegisterNamedClassAsClassWithExplicitName() {
         final String explicitblockname = "explicitblockname";
         asciidoctor.javaExtensionRegistry().block(explicitblockname, AnnotatedTestProcessor.class);
-        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit"), emptyOptions());
         check("H e l l o E x p l i c i t", result);
     }
 
     @Test
     public void testRegisterNamedClassAsInstance() {
         asciidoctor.javaExtensionRegistry().block(new AnnotatedTestProcessor());
-        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "Another Test"), Options.builder());
+        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "Another Test"), emptyOptions());
         check("A n o t h e r T e s t", result);
     }
 
@@ -98,7 +98,7 @@ public void testRegisterNamedClassAsInstance() {
     public void testRegisterNamedClassAsInstanceWithExplicitName() {
         final String blockName = "somename";
         asciidoctor.javaExtensionRegistry().block(blockName, new AnnotatedTestProcessor());
-        final String result = asciidoctor.convert(document(blockName, "Yet Another Test"), Options.builder());
+        final String result = asciidoctor.convert(document(blockName, "Yet Another Test"), emptyOptions());
         check("Y e t A n o t h e r T e s t", result);
     }
 
@@ -117,7 +117,7 @@ public void testRegisterClassAsClass() {
     public void testRegisterClassAsClassWithExplicitName() {
         final String explicitblockname = "anotherexplicitname";
         asciidoctor.javaExtensionRegistry().block(explicitblockname, AbstractTestProcessor.class);
-        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit Class"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit Class"), emptyOptions());
         check("H e l l o E x p l i c i t C l a s s", result);
     }
 
@@ -125,7 +125,7 @@ public void testRegisterClassAsClassWithExplicitName() {
     public void testRegisterClassAsInstance() {
         assertThrows(AsciidoctorCoreException.class, () -> {
             asciidoctor.javaExtensionRegistry().block(new AbstractTestProcessor());
-            asciidoctor.convert(document("foo", "Hello Explicit Instance"), Options.builder());
+            asciidoctor.convert(document("foo", "Hello Explicit Instance"), emptyOptions());
         });
     }
 
@@ -133,7 +133,7 @@ public void testRegisterClassAsInstance() {
     public void testRegisterClassAsInstanceWithExplicitName() {
         final String explicitblockname = "aname";
         asciidoctor.javaExtensionRegistry().block(explicitblockname, new AbstractTestProcessor());
-        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit Instance"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit Instance"), emptyOptions());
         check("H e l l o E x p l i c i t I n s t a n c e", result);
     }
 
@@ -147,14 +147,14 @@ public void testRegisterClassWithNameAsClass() {
     public void testRegisterClassWithNameAsClassWithExplicitName() {
         final String explicitblockname = "explicitblockname";
         asciidoctor.javaExtensionRegistry().block(explicitblockname, TestProcessorWithName.class);
-        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "Hello Explicit"), emptyOptions());
         check("H e l l o E x p l i c i t", result);
     }
 
     @Test
     public void testRegisterClassWithNameAsInstance() {
         asciidoctor.javaExtensionRegistry().block(new TestProcessorWithName());
-        final String result = asciidoctor.convert(document(TestProcessorWithName.NAME, "Another Test"), Options.builder());
+        final String result = asciidoctor.convert(document(TestProcessorWithName.NAME, "Another Test"), emptyOptions());
         check("A n o t h e r T e s t", result);
     }
 
@@ -162,7 +162,7 @@ public void testRegisterClassWithNameAsInstance() {
     public void testRegisterClassWithNameAsInstanceWithExplicitName() {
         final String blockName = "somename";
         asciidoctor.javaExtensionRegistry().block(blockName, new TestProcessorWithName());
-        final String result = asciidoctor.convert(document(blockName, "Yet Another Test"), Options.builder());
+        final String result = asciidoctor.convert(document(blockName, "Yet Another Test"), emptyOptions());
         check("Y e t A n o t h e r T e s t", result);
     }
 
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/InlineMacroRegistrationTest.java b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/InlineMacroRegistrationTest.java
index 40b2fbf92..300d5c6a3 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/InlineMacroRegistrationTest.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/InlineMacroRegistrationTest.java
@@ -1,7 +1,6 @@
 package org.asciidoctor.extension;
 
 import org.asciidoctor.Asciidoctor;
-import org.asciidoctor.Options;
 import org.asciidoctor.ast.PhraseNode;
 import org.asciidoctor.ast.StructuralNode;
 import org.asciidoctor.jruby.internal.AsciidoctorCoreException;
@@ -16,6 +15,7 @@
 
 import static java.util.stream.Collectors.joining;
 import static org.asciidoctor.test.AsciidoctorInstance.InstanceScope.PER_METHOD;
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions;
 import static org.junit.Assert.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
@@ -70,7 +70,7 @@ public static class AnnotatedTestProcessor extends AbstractTestProcessor {
     @Test
     public void testRegisterNamedClassAsClass() {
         asciidoctor.javaExtensionRegistry().inlineMacro(AnnotatedTestProcessor.class);
-        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "World"), Options.builder());
+        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "World"), emptyOptions());
         check("Hello WORLD", result);
     }
 
@@ -78,14 +78,14 @@ public void testRegisterNamedClassAsClass() {
     public void testRegisterNamedClassAsClassWithExplicitName() {
         final String explicitblockname = "explicitblockname";
         asciidoctor.javaExtensionRegistry().inlineMacro(explicitblockname, AnnotatedTestProcessor.class);
-        final String result = asciidoctor.convert(document(explicitblockname, "Explicit"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "Explicit"), emptyOptions());
         check("Hello EXPLICIT", result);
     }
 
     @Test
     public void testRegisterNamedClassAsInstance() {
         asciidoctor.javaExtensionRegistry().inlineMacro(new AnnotatedTestProcessor());
-        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "AnotherTest"), Options.builder());
+        final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "AnotherTest"), emptyOptions());
         check("Hello ANOTHER TEST", result);
     }
 
@@ -93,7 +93,7 @@ public void testRegisterNamedClassAsInstance() {
     public void testRegisterNamedClassAsInstanceWithExplicitName() {
         final String blockName = "somename";
         asciidoctor.javaExtensionRegistry().inlineMacro(blockName, new AnnotatedTestProcessor());
-        final String result = asciidoctor.convert(document(blockName, "YetAnotherTest"), Options.builder());
+        final String result = asciidoctor.convert(document(blockName, "YetAnotherTest"), emptyOptions());
         check("Hello YET ANOTHER TEST", result);
     }
 
@@ -107,7 +107,7 @@ public void testRegisterClassWithoutExplicitName() {
     public void testRegisterClassAsClassWithExplicitName() {
         final String explicitblockname = "anotherexplicitname";
         asciidoctor.javaExtensionRegistry().inlineMacro(explicitblockname, AbstractTestProcessor.class);
-        final String result = asciidoctor.convert(document(explicitblockname, "ExplicitClass"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "ExplicitClass"), emptyOptions());
         check("Hello EXPLICIT CLASS", result);
     }
 
@@ -115,7 +115,7 @@ public void testRegisterClassAsClassWithExplicitName() {
     public void testRegisterClassAsInstance() {
         assertThrows(AsciidoctorCoreException.class, () -> {
             asciidoctor.javaExtensionRegistry().inlineMacro(new AbstractTestProcessor());
-            asciidoctor.convert(document("foo", "HelloExplicitInstance"), Options.builder());
+            asciidoctor.convert(document("foo", "HelloExplicitInstance"), emptyOptions());
         });
     }
 
@@ -123,7 +123,7 @@ public void testRegisterClassAsInstance() {
     public void testRegisterClassAsInstanceWithExplicitName() {
         final String explicitblockname = "someexplicitname";
         asciidoctor.javaExtensionRegistry().inlineMacro(explicitblockname, new AbstractTestProcessor());
-        final String result = asciidoctor.convert(document(explicitblockname, "ExplicitInstance"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "ExplicitInstance"), emptyOptions());
         check("Hello EXPLICIT INSTANCE", result);
     }
 
@@ -137,14 +137,14 @@ public void testRegisterClassWithNameAsClass() {
     public void testRegisterClassWithNameAsClassWithExplicitName() {
         final String explicitblockname = "explicitblockname";
         asciidoctor.javaExtensionRegistry().inlineMacro(explicitblockname, TestProcessorWithName.class);
-        final String result = asciidoctor.convert(document(explicitblockname, "Explicit"), Options.builder());
+        final String result = asciidoctor.convert(document(explicitblockname, "Explicit"), emptyOptions());
         check("Hello EXPLICIT", result);
     }
 
     @Test
     public void testRegisterClassWithNameAsInstance() {
         asciidoctor.javaExtensionRegistry().inlineMacro(new TestProcessorWithName());
-        final String result = asciidoctor.convert(document(TestProcessorWithName.NAME, "AnotherTest"), Options.builder());
+        final String result = asciidoctor.convert(document(TestProcessorWithName.NAME, "AnotherTest"), emptyOptions());
         check("Hello ANOTHER TEST", result);
     }
 
@@ -152,7 +152,7 @@ public void testRegisterClassWithNameAsInstance() {
     public void testRegisterClassWithNameAsInstanceWithExplicitName() {
         final String blockName = "somename";
         asciidoctor.javaExtensionRegistry().inlineMacro(blockName, new TestProcessorWithName());
-        final String result = asciidoctor.convert(document(blockName, "YetAnotherTest"), Options.builder());
+        final String result = asciidoctor.convert(document(blockName, "YetAnotherTest"), emptyOptions());
         check("Hello YET ANOTHER TEST", result);
     }
 
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenJavaExtensionIsRegistered.java b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenJavaExtensionIsRegistered.java
index 93ee0439e..bea89cbae 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenJavaExtensionIsRegistered.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenJavaExtensionIsRegistered.java
@@ -778,8 +778,7 @@ public void an_inline_macro_with_subs_should_be_executed_when_an_inline_macro_is
         javaExtensionRegistry.inlineMacro("say", "org.asciidoctor.extension.SayMacro");
 
         String adoc = "Hello say:word[]!";
-        String content = asciidoctor.convert(adoc,
-                options().toFile(false));
+        String content = asciidoctor.convert(adoc, options().toFile(false).build());
 
         org.jsoup.nodes.Document doc = Jsoup.parse(content, "UTF-8");
         Element p = doc.getElementsByTag("p").first();
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenReaderIsManipulatedInExtension.java b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenReaderIsManipulatedInExtension.java
index 6d158631d..c9232317e 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenReaderIsManipulatedInExtension.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenReaderIsManipulatedInExtension.java
@@ -9,55 +9,53 @@
 import org.junit.jupiter.api.extension.ExtendWith;
 
 import java.io.File;
-import java.util.Map;
 
 import static org.asciidoctor.test.AsciidoctorInstance.InstanceScope.PER_METHOD;
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions;
 import static org.assertj.core.api.Assertions.assertThat;
 
 @ExtendWith({AsciidoctorExtension.class, ClasspathExtension.class})
 public class WhenReaderIsManipulatedInExtension {
 
+    private static final String RENDERSAMPLE = "rendersample.asciidoc";
+
     @AsciidoctorInstance(scope = PER_METHOD)
     private Asciidoctor asciidoctor;
 
-    @ClasspathResource("rendersample.asciidoc")
+    @ClasspathResource(RENDERSAMPLE)
     private File renderSample;
 
 
     @Test
     public void currentLineNumberShouldBeReturned() {
         var javaExtensionRegistry = asciidoctor.javaExtensionRegistry();
-
         javaExtensionRegistry.preprocessor(NumberLinesPreprocessor.class);
 
-        asciidoctor.convertFile(renderSample, Map.of());
+        asciidoctor.convertFile(renderSample, emptyOptions());
 
-        File outpuFile = new File(renderSample.getParent(), "rendersample.asciidoc");
+        File outpuFile = new File(renderSample.getParent(), RENDERSAMPLE);
         assertThat(outpuFile).exists();
     }
 
     @Test
     public void hasMoreLinesShouldBeReturned() {
         var javaExtensionRegistry = asciidoctor.javaExtensionRegistry();
-
         javaExtensionRegistry.preprocessor(HasMoreLinesPreprocessor.class);
 
-        asciidoctor.convertFile(renderSample, Map.of());
+        asciidoctor.convertFile(renderSample, emptyOptions());
 
-        File outpuFile = new File(renderSample.getParent(), "rendersample.asciidoc");
+        File outpuFile = new File(renderSample.getParent(), RENDERSAMPLE);
         assertThat(outpuFile).exists();
     }
 
     @Test
     public void isNextLineEmptyShouldBeReturned() {
         var javaExtensionRegistry = asciidoctor.javaExtensionRegistry();
-
         javaExtensionRegistry.preprocessor(NextLineEmptyPreprocessor.class);
 
-        asciidoctor.convertFile(renderSample, Map.of());
+        asciidoctor.convertFile(renderSample, emptyOptions());
 
-        File outpuFile = new File(renderSample.getParent(), "rendersample.asciidoc");
+        File outpuFile = new File(renderSample.getParent(), RENDERSAMPLE);
         assertThat(outpuFile).exists();
     }
-
 }
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenTheInlineMacroProcessorRunsTwice.java b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenTheInlineMacroProcessorRunsTwice.java
index 139936430..4db4978f1 100644
--- a/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenTheInlineMacroProcessorRunsTwice.java
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenTheInlineMacroProcessorRunsTwice.java
@@ -4,12 +4,11 @@
 import org.asciidoctor.ast.PhraseNode;
 import org.asciidoctor.ast.StructuralNode;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
+import static org.asciidoctor.util.OptionsTestHelper.emptyOptions;
 import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertThat;
 
@@ -32,7 +31,6 @@ public PhraseNode process(StructuralNode parent, String target, Map<String, Obje
     }
 
     private String convert(Asciidoctor asciidoctor) {
-        return asciidoctor.convert("example:alpha.bravo[format=test]", Collections.emptyMap());
+        return asciidoctor.convert("example:alpha.bravo[format=test]", emptyOptions());
     }
-
 }
diff --git a/asciidoctorj-core/src/test/java/org/asciidoctor/util/OptionsTestHelper.java b/asciidoctorj-core/src/test/java/org/asciidoctor/util/OptionsTestHelper.java
new file mode 100644
index 000000000..0bf80a6e5
--- /dev/null
+++ b/asciidoctorj-core/src/test/java/org/asciidoctor/util/OptionsTestHelper.java
@@ -0,0 +1,10 @@
+package org.asciidoctor.util;
+
+import org.asciidoctor.Options;
+
+public class OptionsTestHelper {
+
+    public static Options emptyOptions() {
+        return Options.builder().build();
+    }
+}
diff --git a/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/AsciidoctorInterface.java b/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/AsciidoctorInterface.java
index d0a4db892..ba1a25bdf 100644
--- a/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/AsciidoctorInterface.java
+++ b/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/AsciidoctorInterface.java
@@ -43,7 +43,8 @@ public void destroyAsciidoctorInstance() {
     public void autocloseAsciidoctorInstance() {
 //tag::autoclose[]
         try (Asciidoctor asciidoctor = Asciidoctor.Factory.create()) {
-            asciidoctor.convert("Hello World", Options.builder());
+            Options emptyOptions = Options.builder().build();
+            asciidoctor.convert("Hello World", emptyOptions);
         }
 //end::autoclose[]
     }
diff --git a/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/SimpleAsciidoctorRendering.java b/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/SimpleAsciidoctorRendering.java
index 7a915e71a..f091f4913 100644
--- a/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/SimpleAsciidoctorRendering.java
+++ b/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/SimpleAsciidoctorRendering.java
@@ -1,12 +1,11 @@
 package org.asciidoctor.integrationguide;
 
-import java.io.File;
-
 import org.asciidoctor.Asciidoctor;
 import org.asciidoctor.Options;
-import org.asciidoctor.OptionsBuilder;
 import org.asciidoctor.SafeMode;
 
+import java.io.File;
+
 public class SimpleAsciidoctorRendering {
 
     public static void main(String[] args) {
@@ -15,6 +14,7 @@ public static void main(String[] args) {
                 new File(args[0]),
                 Options.builder()                               // <3>
                         .toFile(true)
-                        .safe(SafeMode.UNSAFE));
+                        .safe(SafeMode.UNSAFE)
+                        .build());
     }
 }
diff --git a/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/extension/YellBlockProcessorTest.java b/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/extension/YellBlockProcessorTest.java
index bf1f74dbc..1d297438b 100644
--- a/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/extension/YellBlockProcessorTest.java
+++ b/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/extension/YellBlockProcessorTest.java
@@ -33,7 +33,7 @@ public void should_invoke_block_processor(@ClasspathResource("yell-block.adoc")
 
         asciidoctor.javaExtensionRegistry().block(YellBlockProcessor.class); // <1>
 
-        String result = asciidoctor.convertFile(yellblock_adoc, Options.builder().toFile(false));
+        String result = asciidoctor.convertFile(yellblock_adoc, Options.builder().toFile(false).build());
 
         assertThat(result, containsString("I REALLY MEAN IT"));              // <2>
 //end::include[]
diff --git a/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/syntaxhighlighter/HighlightJsHighlighterTest.java b/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/syntaxhighlighter/HighlightJsHighlighterTest.java
index 39ba3d9d6..7caebe58b 100644
--- a/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/syntaxhighlighter/HighlightJsHighlighterTest.java
+++ b/asciidoctorj-documentation/src/test/java/org/asciidoctor/integrationguide/syntaxhighlighter/HighlightJsHighlighterTest.java
@@ -66,7 +66,8 @@ public void should_invoke_syntax_highlighter_with_3_params() {
                 .toFile(false)
                 .attributes(Attributes.builder()
                         .sourceHighlighter("myhighlightjs")
-                        .build()));
+                        .build())
+                .build());
 
         assertThat(result,
             containsString("<script>hljs.initHighlighting()</script>"));
@@ -87,7 +88,8 @@ public void should_invoke_formatting_syntax_highlighter() {
                 .toFile(false)
                 .attributes(Attributes.builder()
                         .sourceHighlighter("myhighlightjs")
-                        .build()));
+                        .build())
+                    .build());
 
         assertThat(result,
             containsString("<script>hljs.initHighlighting()</script>"));
diff --git a/asciidoctorj-wildfly-integration-test/src/test/java/org/asciidoctor/AsciidoctorServlet.java b/asciidoctorj-wildfly-integration-test/src/test/java/org/asciidoctor/AsciidoctorServlet.java
index f0cf56a51..6435303b9 100644
--- a/asciidoctorj-wildfly-integration-test/src/test/java/org/asciidoctor/AsciidoctorServlet.java
+++ b/asciidoctorj-wildfly-integration-test/src/test/java/org/asciidoctor/AsciidoctorServlet.java
@@ -23,7 +23,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I
         resp.setStatus(200);
         try (InputStreamReader reader = new InputStreamReader(req.getInputStream());
              OutputStreamWriter writer = new OutputStreamWriter(resp.getOutputStream())) {
-            asciidoctor.convert(reader, writer, Options.builder());
+            asciidoctor.convert(reader, writer, Options.builder().build());
         }
     }
 }