asciidoctor / asciidoctorj

:coffee: Java bindings for Asciidoctor. Asciidoctor on the JVM!
http://asciidoctor.org
Apache License 2.0
625 stars 173 forks source link

Converting to pdf stream #304

Open johncarl81 opened 9 years ago

johncarl81 commented 9 years ago

Today we attempted to write a asciidoc -> pdf stream in a web application. @shannong and I ended up with the following solution:

String output = Asciidoctor.Factory.create()
    .convertFile(new File("input.asciidoc"), 
        OptionsBuilder.options().backend("pdf"));

This results in a pdf file (input.pdf) being generated in the root of the project. What I would expect from this API is output would either include the contents of the pdf, or something similar. What is returned is actually null because the following adapter code in JRubyAsciidoctor:

    private String returnExpectedValue(Object object) {
        return object instanceof String?object.toString():null;
    }

What we need is a stream from Asciidoctor containing the pdf so we can stream it out to the user. I'd prefer is this was contained in memory and not have to use the disk as a buffer. Can we change the api to accommodate?

mojavelinux commented 9 years ago

While I'm sure this is not yet supported, your hypothesis is slightly incorrect. You first need to specify that you don't want to write to a file:

Object result = Asciidoctor.Factory.create()
    .convertFile(new File("input.asciidoc"), 
        OptionsBuilder.options().backend("pdf").toFile(false));

This is where the problem comes in. When toFile is set to false, the result depends on the converter. At the moment, the PDF converter will return the Converter instance, which is also a Prawn Document object. If you manage to get a handle on that object, you can call render to get the PDF as a String.

The return value of convert and convertFile is being tracked in #234.

mojavelinux commented 9 years ago

This is where we need to allow the type to be coerced in a type-safe way as described in #234. Of course, that argument needs to be optional.

I'd really like to get feedback from the community of Java API designers on this one because this is a tricky one to get right and we want to make the API better, not more complex.

johncarl81 commented 9 years ago

I commented on this in #234... I'm very naive to the ruby code behind Asciidoctorj, but would returning an OutputStream make sense here? You could easily map a String to an OutputStream and it would accommodate pretty much any other binary format.

mojavelinux commented 9 years ago

That's very much a possibility.

johncarl81 commented 9 years ago

For our use case that would work beautifully, especially if it is backed by memory and not the file system.

johncarl81 commented 8 years ago

@robertpanzer, looking over #356, should we be able to write a pdf to a byte array using a registered Converter in the upcoming 1.6 release?

robertpanzer commented 8 years ago

It should be possible. But it would require to have an own Java implementation of the converter that delegates to the asciidoctor-pdf converter and implements the write() method appropriately.

Maybe this could even be the default converter for asciidoctorj-pdf and be an added value when using AsciidoctorJ. @mojavelinux Wdyt?

mojavelinux commented 8 years ago

@johncarl81 @robertpanzer That's certainly reasonable. Ideally, we want to avoid having too much integration code, but in this case there is a real integration concern here and that is enough to warrant an intermediary class in AsciidoctorJ, I suppose.