asciidoctor-gradle-examples icon indicating copy to clipboard operation
asciidoctor-gradle-examples copied to clipboard

Example to create PDF with diagrams

Open pajoma opened this issue 9 years ago • 20 comments

Here's a working example to generate PDFs with PlantUML diagrams

buildscript {
    dependencies {
        classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.11'
    }
}



plugins {
    id 'org.asciidoctor.convert' version '1.5.3'
    id 'com.github.jruby-gradle.base' version '0.3.0'
}

apply plugin: 'java'
apply plugin: 'org.asciidoctor.convert'

version = '1.0.0-SNAPSHOT'

asciidoctorj {
    version = '1.5.4'
}

dependencies {
    gems 'rubygems:asciidoctor-diagram:1.2.0'
}

asciidoctor {
    backends 'pdf'
    dependsOn jrubyPrepareGems
    requires = ['asciidoctor-diagram']
    gemPath = jrubyPrepareGems.outputDir
    attributes  'build-gradle': file('build.gradle'),
                'source-highlighter' : 'coderay',
                'imagesdir':'images',
                'toc':'left',
                'icons': 'font',
                'setanchors':'true',
                'idprefix':'',
                'idseparator':'-',
                'docinfo1':'true'
}

Changes to the HTML5 Version

  • Increased version for plugin com.github.jruby-gradle.base to 0.3.0 due to errors (current version is 1.2.0, but won't work)
  • Increased version for plugin org.asciidoctor.convert
  • Added dependency for asciidoctorj-pdf plugin

Here is another example which uses the diagram plugin from asciidoctorj. It compiles, but I don't get how to include the images in the PDF (the generated diagram images are in the built directory, the PDF-Compiler expects them in the source directory).

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.3'
                classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.11'
                classpath 'org.asciidoctor:asciidoctorj-diagram:1.3.1'
    }
}

// apply plugin: 'org.asciidoctor.gradle.asciidoctor'  
apply plugin: 'org.asciidoctor.convert'

asciidoctorj {
    version = '1.5.4'
}

repositories {
    mavenLocal()
    jcenter()
}

resources {
    from(sourceDir) {
        include
    }
}

asciidoctor {
    backends  'pdf'
    requires ['asciidoctor-diagram']
    attributes 'build-gradle': file('build.gradle'),
            'imagesdir':'./images'
}

pajoma avatar Feb 10 '16 14:02 pajoma

@pajoma Thanks for the submission! I'm not quite clear if this is a request to add the original sample or if it is asking for help with the second sample?

rwinch avatar Feb 10 '16 15:02 rwinch

It depends ;)

If the second approach is the preferred way (which I guess it should be, since it seems cleaner without the gems), then this is a request to include it into the examples (if a solution to the image problem exists).

In the other case, see the first approach as a suggestion which could be included it to the original examples.

pajoma avatar Feb 10 '16 15:02 pajoma

Using AsciidoctorJ Diagram is the preferred method for the reason you cited (though, keep in mind, you always have the option of switching to using the gem directly...so there's no wrong way).

if a solution to the image problem exists

This is a common problem with Asciidoctor Diagram and build tools because we have a lot of different directories involved. What it comes down to is that, when running the PDF converter, the imagesoutdir attribute has to be set to somewhere in the build output directory and the imagesdir must be an absolute path that matches that location.

Unlike the HTML converter, the PDF converter has to be able to find and read the generated images in order to include them in the document. That location must be the same as for all other images (Asciidoctor only looks in one place for images). It's an engineering challenge we've yet to solve transparently.

mojavelinux avatar Feb 10 '16 21:02 mojavelinux

The provided example can be simplified to not fetch Ruby Gems, by using asciidoctorj artifacts, as suggested by @mojavelinux

buildscript {
    dependencies {
        classpath 'org.asciidoctor:asciidoctorj-pdf:1.5.0-alpha.11',
            'org.asciidoctor:asciidoctorj-diagram:1.3.1'
    }
}

plugins {
    id 'org.asciidoctor.convert' version '1.5.3'
}

repositories {
    jcenter()
}

asciidoctor {
    backends 'pdf'
    requires 'asciidoctor-diagram'
    attributes 'buildDir': buildDir
}

And as example, in src/docs/asciidoc/plantuml.adoc

= AsciiDoctor + Gradle + Plant UML
:imagesdir: {buildDir}/asciidoc/pdf

== PlantUML Diagram 

[plantuml, ./diagram, png]
.Diagram Title
....
@startuml
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response

Alice -> Bob: Another authentication Request
Alice <-- Bob: another authentication Response
@enduml

Versions

I think asciidoctor-gradle should be updated to 1.5.4 (as latest RubyGem) And asciidoctorj-diagram should be updated to 1.4.0 (as latest RubyGem)

eshepelyuk avatar Apr 29 '16 06:04 eshepelyuk

I think asciidoctor-gradle should be updated to 1.5.4 (as latest RubyGem)

I think we're still waiting on this release. It is possible to upgrade AsciidoctorJ independently of the plugin, though we probably want to keep configuration to a minimum for the example, so best to wait.

And asciidoctorj-diagram should be updated to 1.4.0 (as latest RubyGem)

:+1:

mojavelinux avatar May 02 '16 06:05 mojavelinux

I had some trouble getting this to work with multiple backends.

Ultimately I used the following Gradle:

asciidoctor.doFirst {
    // pre-process
    copy {
        from file('doc/images')
        into file("$buildDir/site/pdf/images")
        include '*.png'
    }
}
asciidoctor {
    sourceDir = file('doc')
    outputDir = file("$buildDir/site")
    separateOutputDirs = true
    logDocuments = true

    sources {
        include 'Filename.adoc'
    }

    backends 'html5', 'pdf'

    requires  'asciidoctor-diagram'
}

And added the following attributes to the document:

ifdef::backend-pdf[:imagesoutdir: ../build/site/{backend}/images]
ifdef::backend-pdf[:imagesdir: ../build/site/{backend}/images]
ifdef::backend-html5[:imagesoutdir: ../build/site/{backend}/images]
ifdef::backend-html5[:imagesdir: images]

There's probably a more elegant way, but this seems to work correctly.

So, as I understand it, what is happening is the following:

  1. The asciidoctor.doFirst block runs once before any of the backends and copies the images to build/site/pdf/images. It is necessary to do this because the Asciidoctor Gradle plugin doesn't copy the resources until after rendering the documents, but the PDF renderer needs the images copied first.
  2. As each document is processed, the diagrams are rendered into build/site/{backend}/images
  3. After each document is processed, images are copied into build/site/{backend}/images

msgilligan avatar Nov 21 '16 23:11 msgilligan

It is necessary to do this because the Asciidoctor Gradle plugin doesn't copy the resources until after rendering the documents, but the PDF renderer needs the images copied first.

That really depends on how the images are being referenced. If you are generating images into the build directory, and you want the converter to look for all images there, then yes, you need to copy the static images there before the converter runs.

mojavelinux avatar Nov 22 '16 07:11 mojavelinux

I'm trying to migrate from using the rubygems directly but diagram generation fails because /usr/bin/dot is not found. Does asciidoctorj-diagram require me to install GraphViz separately? If I do so with Homebrew it works but it means the build is not as portable as if I use Ruby.

robfletcher avatar Dec 01 '16 23:12 robfletcher

@robfletcher, yes. You have to install it separately. dot should be available from your PATH

eshepelyuk avatar Dec 01 '16 23:12 eshepelyuk

are there any updates on the handling of the image path? My HTML renders fine but the PDF renderer (alpha-15) still complains that it can't find the plantUML image in src/docs/images ...

rdmueller avatar Apr 28 '17 13:04 rdmueller

Yes.

I describe the solution in the following comment:

https://github.com/asciidoctor/asciidoctor-pdf/issues/271#issuecomment-291992364

and some more information here:

https://github.com/asciidoctor/asciidoctor-pdf/issues/495#issuecomment-292363478

mojavelinux avatar Apr 28 '17 23:04 mojavelinux

I recommend looking at what the junit5 project is doing since they have a working configuration.

mojavelinux avatar Apr 28 '17 23:04 mojavelinux

FYI I managed to create a less complex setup in https://github.com/arc42/quality-requirements. The generated PDF (and docx via pandoc) are created via TravisCI and uploaded to Github Releases for each Git tag.

aheusingfeld avatar Oct 14 '17 07:10 aheusingfeld

Another option to this is, to create a new task just for the PDF backend. The advantage is, you don't have to deal with ifdefs in the source file.

asciidoctor {
    dependsOn "asciidoctorPdf"
}

task asciidoctorPdf(type: org.asciidoctor.gradle.AsciidoctorTask) {
    group "documentation"

    requires 'asciidoctor-diagram'
    backends 'pdf'

    sources {
        include "index.adoc"
    }

    attributes = [
            "imagesoutdir"  : "$buildDir/asciidoc/pdf/images",
            "imagesdir"     : "$buildDir/asciidoc/pdf/images"
    ]
}

By the way: why couldn't this be handled by the plugin?

brnhffmnn avatar Jul 06 '18 10:07 brnhffmnn

I created a new asciidoc-diagram-to-pdf-example project in a fork and would like to make it work. After that, I would like to update the asciidoc-to-all-example project so it also uses a diagram to show how to make a single project use diagrams with output to html5 and pdf.

Is one of the examples in this issue the recommended approach?

jeffcjohnson avatar Feb 08 '19 00:02 jeffcjohnson

@jeffcjohnson You could enhance asciidoc-diagram-to-html-example to produce both html and pdf. If you aren't keen on that idea, then I'd recommend adding a separate project / folder. Feel free to submit the PR and I'm sure it will get merged.

mojavelinux avatar Jun 10 '19 04:06 mojavelinux

@mojavelinux I created the example to show how it could be done and failed. I was hoping someone that knew more about the project would be able to show where I went wrong.

jeffcjohnson avatar Jun 11 '19 12:06 jeffcjohnson

Oops, I missed that you had submitted https://github.com/asciidoctor/asciidoctor-gradle-examples/pull/49.

The reason it failed is because you were ahead of your time. Using the latest versions, it should now work. I'll give it a quick test.

mojavelinux avatar Jun 13 '19 00:06 mojavelinux

With a few upgrades, it works.

The last step would be to merge it with asciidoc-diagram-to-html-example into a single example named asciidoctor-diagram-example. I don't think the "to" part is needed. The focus is on Asciidoctor Diagram, not the output.

mojavelinux avatar Jun 13 '19 01:06 mojavelinux

@mojavelinux thank you! I will try to get your suggestions into the PR for your review.

jeffcjohnson avatar Jun 13 '19 14:06 jeffcjohnson