asciidoctor / asciidoctorj-pdf

AsciidoctorJ PDF bundles the Asciidoctor PDF RubyGem (asciidoctor-pdf) so it can be loaded into the JVM using JRuby.
Apache License 2.0
35 stars 17 forks source link

Can't use reader/writer `convert` with asciidoctorj-pdf #63

Open veselov opened 3 years ago

veselov commented 3 years ago

In my application, I'm converting docs based on streams, and not necessarily files.

Attempt to use a convert function with reader/writer API:

Writer it = new StringWriter()
doctor.convert(reader, writer, Options.builder().backend("pdf").toStream(it).build())

gets me this:

Caused by: org.jruby.exceptions.TypeError: (TypeError) cannot convert instance of class org.jruby.gen.RubyObject50 to class java.lang.String

I guess, the binary output of PDF itn's really suitable for writing into a Writer anyway, which is fair. So I've tried this:

OutputStream it = new ByteArrayOutputStream()
doctor.convert(reader, null, Options.builder().backend("pdf").toStream(it).build())

This got me:

Caused by: java.lang.NullPointerException at org.asciidoctor.jruby.internal.IOUtils.writeFull (IOUtils.java:28) at org.asciidoctor.jruby.internal.JRubyAsciidoctor.convert (JRubyAsciidoctor.java:353) at org.asciidoctor.jruby.internal.JRubyAsciidoctor.convert (JRubyAsciidoctor.java:358) at org.asciidoctor.Asciidoctor$convert$1.call (Unknown Source)

Which may be an AsciiDoctor issue, with conflicting instructions of the output; this also tells me that even if I gave it a dummy writer, it would have failed with the same type error.

Finally, this is the only way this agreed to work:

OutputStream it = new ByteArrayOutputStream()
doctor.convertFile(file.toFile(), Options.builder().backend("pdf").toStream(it).build())

But that requires me to have a file, which I may have to create for just a purpose of running the converter.

I understand this may really be rooted in AsciiDoctorJ code, and not in this extension, but I was wondering if something can be done about it.

robertpanzer commented 3 years ago
Writer it = new StringWriter()
doctor.convert(reader, writer, Options.builder().backend("pdf").toStream(it).build())

Yes, for pdf writing to a write does not work since PDF is a binary format.

OutputStream it = new ByteArrayOutputStream()
doctor.convert(reader, null, Options.builder().backend("pdf").toStream(it).build())

This function does (unfortunately) not delegate to the stream option, but writes the rendered String (yes) to the Writer, which also won't work here.

OutputStream it = new ByteArrayOutputStream()
doctor.convertFile(file.toFile(), Options.builder().backend("pdf").toStream(it).build())

That is one option, alternatively you can also pass a String, there is a test case for that here: https://github.com/asciidoctor/asciidoctorj/blob/aeb6a04d44542c3827aa6228b8748c4f312a6b46/asciidoctorj-distribution/src/test/groovy/org/asciidoctor/diagram/WhenAPdfDocumentIsRenderedToStream.groovy#L84

I agree that it would be great to pass a Reader as input, even if it internally also results in having to collect it to a string.