Skip to content

Commit

Permalink
Accept null as empty content for load and convert
Browse files Browse the repository at this point in the history
Both empty and null String are accepted as valid for load/convert methods
for safety.
* Minor Javadoc fixed
* Integrate WhenDocumentIsLoaded into WhenAsciiDocIsLoadedToDocument

Fixes asciidoctor#1146
  • Loading branch information
abelsromero committed Mar 21, 2023
1 parent c8daaab commit 70695a3
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 186 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Improvement::
* Expose `sectnum` property in Section interface (#1121)
* Replace use of deprecated 'numbered' attribute by 'sectnums' (#1123) (@abelsromero)
* Expose `source` and `source_lines` use of deprecated 'numbered' in Document interface (#1145) (@abelsromero)
* Accept 'null' as valid input (same as empty string) for load and convert String methods (#) (@abelsromero)

Bug Fixes::

Expand Down
24 changes: 12 additions & 12 deletions asciidoctorj-api/src/main/java/org/asciidoctor/Asciidoctor.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
public interface Asciidoctor extends AutoCloseable {

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as String object.
Expand All @@ -44,7 +44,7 @@ public interface Asciidoctor extends AutoCloseable {
String convert(String content, Map<String, Object> options);

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as String object.
Expand All @@ -60,7 +60,7 @@ public interface Asciidoctor extends AutoCloseable {
<T> T convert(String content, Map<String, Object> options, Class<T> expectedResult);

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as String object.
Expand All @@ -72,7 +72,7 @@ public interface Asciidoctor extends AutoCloseable {
String convert(String content, Options options);

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as String object.
Expand All @@ -86,7 +86,7 @@ public interface Asciidoctor extends AutoCloseable {
<T> T convert(String content, Options options, Class<T> expectedResult);

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as String object.
Expand All @@ -100,7 +100,7 @@ public interface Asciidoctor extends AutoCloseable {
String convert(String content, OptionsBuilder options);

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as String object.
Expand Down Expand Up @@ -162,7 +162,7 @@ void convert(Reader contentReader, Writer rendererWriter,
OptionsBuilder options) throws IOException;

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as File.
Expand All @@ -188,7 +188,7 @@ void convert(Reader contentReader, Writer rendererWriter,
String convertFile(File file, Map<String, Object> options);

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as File.
Expand Down Expand Up @@ -217,7 +217,7 @@ void convert(Reader contentReader, Writer rendererWriter,


/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as File.
Expand All @@ -241,7 +241,7 @@ void convert(Reader contentReader, Writer rendererWriter,
String convertFile(File file, Options options);

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as File.
Expand All @@ -267,7 +267,7 @@ void convert(Reader contentReader, Writer rendererWriter,
<T> T convertFile(File file, Options options, Class<T> expectedResult);

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as File.
Expand All @@ -293,7 +293,7 @@ void convert(Reader contentReader, Writer rendererWriter,
String convertFile(File file, OptionsBuilder options);

/**
* Parse the AsciiDoc source input into an Document {@link Document} and
* Parse the AsciiDoc source input into a Document {@link Document} and
* convert it to the specified backend format.
* <p>
* Accepts input as File.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.io.InputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.Objects;
import java.util.Scanner;

public class IOUtils {
Expand All @@ -13,13 +14,14 @@ private IOUtils() {
}

public static String readFull(InputStream inputStream) {
try (Scanner scanner = new Scanner(inputStream).useDelimiter("\\A")){
try (Scanner scanner = new Scanner(inputStream).useDelimiter("\\A")) {
return scanner.next();
}
}

public static String readFull(Reader reader) {
try (Scanner scanner = new Scanner(reader).useDelimiter("\\A")){
Objects.requireNonNull(reader, "reader");
try (Scanner scanner = new Scanner(reader).useDelimiter("\\A")) {
return scanner.next();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ public <T> T convert(String content, Map<String, Object> options, Class<T> expec
try {

IRubyObject object = getAsciidoctorModule().callMethod("convert",
rubyRuntime.newString(content), rubyHash);
Optional.ofNullable(content).map(rubyRuntime::newString).orElse(null), rubyHash);
if (NodeConverter.NodeType.DOCUMENT_CLASS.isInstance(object)) {
// If a document is rendered to a file Asciidoctor returns the document, we return null
return null;
Expand Down Expand Up @@ -468,7 +468,7 @@ public Document load(String content, Map<String, Object> options) {
public Document load(String content, Options options) {
RubyHash rubyHash = RubyHashUtil.convertMapToRubyHashWithSymbols(rubyRuntime, options.map());
return (Document) NodeConverter.createASTNode(getAsciidoctorModule().callMethod("load",
rubyRuntime.newString(content), rubyHash));
Optional.ofNullable(content).map(rubyRuntime::newString).orElse(null), rubyHash));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,38 @@
package org.asciidoctor;

import static org.asciidoctor.AttributesBuilder.attributes;
import static org.asciidoctor.OptionsBuilder.options;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.collection.IsArrayWithSize.arrayWithSize;
import static org.junit.Assert.assertThat;
import static org.xmlmatchers.xpath.HasXPath.hasXPath;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;

import com.google.common.io.CharStreams;
import org.asciidoctor.arquillian.api.Unshared;
import org.asciidoctor.jruby.AsciiDocDirectoryWalker;
import org.asciidoctor.jruby.internal.AsciidoctorCoreException;
import org.asciidoctor.util.ClasspathResources;
import org.assertj.core.api.Assertions;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.xml.sax.SAXException;

import com.google.common.io.CharStreams;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import java.io.*;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import static org.asciidoctor.AttributesBuilder.attributes;
import static org.asciidoctor.OptionsBuilder.options;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.Matchers.isEmptyString;
import static org.hamcrest.collection.IsArrayWithSize.arrayWithSize;
import static org.junit.Assert.assertThat;
import static org.xmlmatchers.xpath.HasXPath.hasXPath;

@RunWith(Arquillian.class)
public class WhenAnAsciidoctorClassIsInstantiated {
Expand All @@ -54,6 +46,47 @@ public class WhenAnAsciidoctorClassIsInstantiated {
@ArquillianResource(Unshared.class)
private Asciidoctor asciidoctor;

@Test
public void should_accept_empty_string_as_empty_content_when_output_is_String() {
Options basicOptions = Options.builder().build();
String result = asciidoctor.convert("", basicOptions);

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);

assertThat(result, isEmptyString());
}

@Test
public void should_accept_null_string_as_empty_content_when_output_is_File() {
File expectedFile = new File(testFolder.getRoot(), "expected_empty.html");
Options options = Options.builder()
.safe(SafeMode.UNSAFE)
.toFile(expectedFile)
.build();
String renderContent = asciidoctor.convert(null, options);

assertThat(expectedFile.exists(), is(true));
assertThat(renderContent, is(nullValue()));
}

@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));

Assertions.assertThat(throwable)
.isInstanceOf(NullPointerException.class)
.hasMessage("reader");
}

@Test
public void content_should_be_read_from_reader_and_written_to_writer() throws IOException, SAXException,
ParserConfigurationException {
Expand All @@ -78,8 +111,7 @@ public void file_document_should_be_rendered_into_default_backend() throws IOExc
}

@Test
public void file_document_should_be_rendered_into_current_directory_using_options_class()
throws FileNotFoundException, IOException, SAXException, ParserConfigurationException {
public void file_document_should_be_rendered_into_current_directory_using_options_class() {

Options options = options().inPlace(true).get();
File inputFile = classpath.getResource("rendersample.asciidoc");
Expand All @@ -94,8 +126,7 @@ public void file_document_should_be_rendered_into_current_directory_using_option
}

@Test
public void file_document_should_be_rendered_into_current_directory() throws FileNotFoundException, IOException,
SAXException, ParserConfigurationException {
public void file_document_should_be_rendered_into_current_directory() {

File inputFile = classpath.getResource("rendersample.asciidoc");
String renderContent = asciidoctor.convertFile(inputFile, options()
Expand All @@ -110,8 +141,7 @@ public void file_document_should_be_rendered_into_current_directory() throws Fil
}

@Test
public void file_document_should_be_rendered_into_foreign_directory() throws FileNotFoundException, IOException,
SAXException, ParserConfigurationException {
public void file_document_should_be_rendered_into_foreign_directory() {

Map<String, Object> options = options().inPlace(false).safe(SafeMode.UNSAFE).toDir(testFolder.getRoot())
.asMap();
Expand Down Expand Up @@ -140,8 +170,7 @@ public void file_document_should_be_rendered_from_base_dir() throws IOException
}

@Test
public void file_document_should_be_rendered_into_foreign_directory_using_options_class()
throws FileNotFoundException, IOException, SAXException, ParserConfigurationException {
public void file_document_should_be_rendered_into_foreign_directory_using_options_class() {

Options options = options().inPlace(false).safe(SafeMode.UNSAFE).toDir(testFolder.getRoot()).get();

Expand All @@ -154,8 +183,7 @@ public void file_document_should_be_rendered_into_foreign_directory_using_option
}

@Test
public void docbook_document_should_be_rendered_into_current_directory() throws FileNotFoundException, IOException,
SAXException, ParserConfigurationException {
public void docbook_document_should_be_rendered_into_current_directory() {

Map<String, Object> attributes = attributes().backend("docbook").asMap();
Map<String, Object> options = options().inPlace(true).attributes(attributes).asMap();
Expand All @@ -172,8 +200,7 @@ public void docbook_document_should_be_rendered_into_current_directory() throws
}

@Test
public void docbook_document_should_be_rendered_into_current_directory_using_options_class()
throws FileNotFoundException, IOException, SAXException, ParserConfigurationException {
public void docbook_document_should_be_rendered_into_current_directory_using_options_class() {

Attributes attributes = attributes().backend("docbook").get();
Options options = options().inPlace(true).attributes(attributes).get();
Expand All @@ -190,8 +217,7 @@ public void docbook_document_should_be_rendered_into_current_directory_using_opt
}

@Test
public void docbook_document_should_be_rendered_into_current_directory_using_options_backend_attribute()
throws FileNotFoundException, IOException, SAXException, ParserConfigurationException {
public void docbook_document_should_be_rendered_into_current_directory_using_options_backend_attribute() {

Options options = options().inPlace(true).backend("docbook").get();

Expand Down
Loading

0 comments on commit 70695a3

Please sign in to comment.