Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reuse Asciidoctor Ruby invoker #1249

Merged
merged 5 commits into from
Dec 16, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions asciidoctorj-api/src/main/java/org/asciidoctor/Options.java
Original file line number Diff line number Diff line change
@@ -6,12 +6,13 @@
/**
* AsciidoctorJ conversion options.
* <p>
* See https://docs.asciidoctor.org/asciidoctor/latest/api/options/ for further
* See <a href="https://docs.asciidoctor.org/asciidoctor/latest/api/options/">https://docs.asciidoctor.org/asciidoctor/latest/api/options/</a> for further
* details.
*/
public class Options {

public static final String IN_PLACE = "in_place";
public static final String WARNINGS = "warnings";
public static final String ATTRIBUTES = "attributes";
public static final String TEMPLATE_DIRS = "template_dirs";
public static final String TEMPLATE_ENGINE = "template_engine";
@@ -24,10 +25,10 @@ public class Options {
public static final String ERUBY = "eruby";
public static final String CATALOG_ASSETS = "catalog_assets";
public static final String COMPACT = "compact";
public static final String SOURCE_DIR = "source_dir";
public static final String BACKEND = "backend";
public static final String DOCTYPE = "doctype";
public static final String BASEDIR = "base_dir";
public static final String TRACE = "trace";
public static final String TEMPLATE_CACHE = "template_cache";
public static final String SOURCE = "source";
public static final String PARSE = "parse";
@@ -160,10 +161,6 @@ public void setCompact(boolean compact) {
this.options.put(COMPACT, compact);
}

public void setSourceDir(String srcDir) {
this.options.put(SOURCE_DIR, srcDir);
}

public void setBackend(String backend) {
this.options.put(BACKEND, backend);
}
19 changes: 2 additions & 17 deletions asciidoctorj-api/src/main/java/org/asciidoctor/OptionsBuilder.java
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@

import java.io.File;
import java.io.OutputStream;
import java.util.Map;

/**
* Fluent Options API for AsciidoctorJ.
@@ -160,7 +159,7 @@ public OptionsBuilder toStream(OutputStream toStream) {
* @return this instance.
*/
public OptionsBuilder toDir(File directory) {
this.options.setToDir(directory.getAbsolutePath());
this.options.setToDir(directory.getPath());
return this;
}

@@ -265,20 +264,6 @@ public OptionsBuilder parseHeaderOnly(boolean parseHeaderOnly) {
return this;
}

/**
* Source directory.
*
* This must be used alongside {@link #toDir(File)}.
*
* @param srcDir
* source directory.
* @return this instance.
*/
public OptionsBuilder sourceDir(File srcDir) {
this.options.setSourceDir(srcDir.getAbsolutePath());
return this;
}

/**
* Sets a custom or unlisted option.
*
@@ -301,7 +286,7 @@ public OptionsBuilder option(String option, Object value) {
* @return this instance.
*/
public OptionsBuilder baseDir(File baseDir) {
this.options.setBaseDir(baseDir.getAbsolutePath());
this.options.setBaseDir(baseDir.getPath());
return this;
}

Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
package org.asciidoctor.cli;

import com.beust.jcommander.Parameter;
import org.asciidoctor.*;
import org.asciidoctor.Attributes;
import org.asciidoctor.AttributesBuilder;
import org.asciidoctor.Options;
import org.asciidoctor.SafeMode;
import org.asciidoctor.log.Severity;
import org.jruby.Ruby;
import org.jruby.RubyHash;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

public class AsciidoctorCliOptions {

public static final String LOAD_PATHS = "-I";
public static final String REQUIRE = "-r";
public static final String QUIET = "-q";
public static final String WARNINGS = "-w";
public static final String ATTRIBUTE = "-a";
public static final String HELP = "-h";
public static final String DESTINATION_DIR = "-D";
@@ -47,7 +54,7 @@ public class AsciidoctorCliOptions {
private boolean version = false;

@Parameter(names = {BACKEND, "--backend"}, description = "set output format backend")
private String backend = "html5";
private String backend;

@Parameter(names = {DOCTYPE, "--doctype"}, description = "document type to use when rendering output: [article, book, inline] (default: article)")
private String doctype;
@@ -70,8 +77,8 @@ public class AsciidoctorCliOptions {
@Parameter(names = {SECTION_NUMBERS, "--section-numbers"}, description = "auto-number section titles; disabled by default")
private boolean sectionNumbers = false;

@Parameter(names = {"--eruby"}, description = "specify eRuby implementation to render built-in templates: [erb, erubis]")
private String eruby = "erb";
@Parameter(names = {"--eruby"}, description = "specify eRuby implementation to render built-in templates: [erb, erubis]; default erb")
private String eruby;

@Parameter(names = {COMPACT, "--compact"}, description = "compact the output by removing blank lines")
private boolean compact = false;
@@ -103,6 +110,9 @@ public class AsciidoctorCliOptions {
@Parameter(names = {QUIET, "--quiet"}, description = "suppress warnings")
private boolean quiet = false;

@Parameter(names = {WARNINGS, "--warnings"}, description = "suppress warnings")
private boolean warnings = false;

@Parameter(names = {"--failure-level"}, converter = SeverityConverter.class, description = "set minimum log level that yields a non-zero exit code.")
private Severity failureLevel = Severity.FATAL;

@@ -266,88 +276,77 @@ private boolean isInPlaceRequired() {
return !isOutFileOption() && !isDestinationDirOption() && !isOutputStdout();
}

public Options parse() throws IOException {
OptionsBuilder optionsBuilder = Options.builder()
.backend(this.backend)
.safe(this.safeMode)
.eruby(this.eruby)
.option(Options.STANDALONE, true);
public RubyHash parse(Ruby ruby) throws IOException {

if (isDoctypeOption()) {
optionsBuilder.docType(this.doctype);
}
RubyHash opts = new RubyHash(ruby);
Map attributes = buildAttributes();

if (isInputStdin()) {
optionsBuilder.toStream(System.out);
if (outFile == null) {
outFile = "-";
}
}
opts.put(ruby.newSymbol(Options.STANDALONE), true);
opts.put(ruby.newSymbol(Options.WARNINGS), false);

if (isOutFileOption() && !isOutputStdout()) {
optionsBuilder.toFile(new File(this.outFile));
if (this.backend != null) {
attributes.put(Options.BACKEND, this.backend);
}

if (isOutputStdout()) {
optionsBuilder.toStream(System.out);
if (this.doctype != null) {
attributes.put(Options.DOCTYPE, this.doctype);
}
if (this.embedded) {
opts.put(ruby.newSymbol(Options.STANDALONE), false);
}
if (this.outFile != null) {
opts.put(ruby.newSymbol("output_file"), this.outFile);
}

if (this.safe) {
optionsBuilder.safe(SafeMode.SAFE);
opts.put(ruby.newSymbol(Options.SAFE), SafeMode.SAFE.getLevel());
}

if (this.embedded) {
optionsBuilder.option(Options.STANDALONE, false);
if (this.safeMode != null) {
opts.put(ruby.newSymbol("safe"), this.safeMode.getLevel());
}

if (this.noHeaderFooter) {
optionsBuilder.option(Options.STANDALONE, false);
opts.put(ruby.newSymbol(Options.STANDALONE), false);
}

if (this.compact) {
optionsBuilder.compact(this.compact);
if (this.sectionNumbers) {
attributes.put("sectnums", "");
}

if (isBaseDirOption()) {
optionsBuilder.baseDir(new File(this.baseDir).getCanonicalFile());
if (this.eruby != null) {
opts.put(ruby.newSymbol(Options.ERUBY), this.eruby);
}
if (isTemplateDirOption()) {
opts.put(ruby.newSymbol(Options.TEMPLATE_DIRS), this.templateDir.toArray(new String[0]));
}

if (isTemplateEngineOption()) {
optionsBuilder.templateEngine(this.templateEngine);
opts.put(ruby.newSymbol(Options.TEMPLATE_ENGINE), this.templateEngine);
}

if (isTemplateDirOption()) {
for (String templateDir : this.templateDir) {
optionsBuilder.templateDirs(new File(templateDir).getCanonicalFile());
}
if (this.baseDir != null) {
opts.put(ruby.newSymbol(Options.BASEDIR), this.baseDir);
}

if (isDestinationDirOption() && !isOutputStdout()) {
optionsBuilder.toDir(new File(this.destinationDir).getCanonicalFile());

if (isSourceDirOption()) {
optionsBuilder.sourceDir(new File(this.sourceDir).getCanonicalFile());
}
if (this.destinationDir != null) {
opts.put(ruby.newSymbol("destination_dir"), this.destinationDir);
}

if (isInPlaceRequired()) {
optionsBuilder.inPlace(true);
if (this.trace) {
opts.put(ruby.newSymbol(Options.TRACE), true);
}

Attributes attributesBuilder = buildAttributes();
if (this.sectionNumbers) {
attributesBuilder.setSectionNumbers(this.sectionNumbers);
if (this.timings) {
opts.put(ruby.newSymbol("timings"), true);
}
if (this.warnings) {
opts.put(ruby.newSymbol(Options.WARNINGS), true);
}
if (!attributes.isEmpty()) {
opts.put(ruby.newSymbol(Options.ATTRIBUTES), attributes);
}
if (this.isSourceDirOption()) {
opts.put(ruby.newSymbol("source_dir"), this.sourceDir);
}
optionsBuilder.attributes(attributesBuilder);
return optionsBuilder.build();
return opts;
}

/**
* Returns the attributes injected as List<String> into a structured
* {@link Attributes} instance.
*/
// FIXME Should be private, made protected for testing.
Attributes buildAttributes() {
Map buildAttributes() {
final AttributesBuilder attributesBuilder = Attributes.builder();
for (String attribute : attributes) {
int separatorIndex = attribute.indexOf(ATTRIBUTE_SEPARATOR);
@@ -359,7 +358,7 @@ Attributes buildAttributes() {
attributesBuilder.attribute(attribute);
}
}
return attributesBuilder.build();
return attributesBuilder.build().map();
}

private List<String> splitByPathSeparator(String path) {
Loading