Search

Dark theme | Light theme

January 26, 2016

Groovy Goodness: Customise Groovydoc Output With Gradle

When we write our Groovy application we of course add documentation to our classes. If we use Gradle to build our project we can run the groovydoc task that is added by the Groovy plugin to generate documentation. We can set document and windows titles and a footer for the generated documentation by changing some properties of the groovydoc task. If we want some further customisation we must take some extra steps. The groovydoc task uses the GroovyDoc tool that is bundled with the Groovy library. GroovyDoc tool uses the GStringTemplateEngine to generate the documentation. The default template files are stored in the package org.codehaus.tools.groovydoc.gstringTemplates. The following files are in the package:

└── org
    └── codehaus
        └── groovy
            └── tools
                └── groovydoc
                    └── gstringTemplates
                        ├── classLevel
                        │   └── classDocName.html
                        ├── packageLevel
                        │   ├── package-frame.html
                        │   └── package-summary.html
                        └── topLevel
                            ├── allclasses-frame.html
                            ├── deprecated-list.html
                            ├── help-doc.html
                            ├── index-all.html
                            ├── index.html
                            ├── overview-frame.html
                            ├── overview-summary.html
                            └── stylesheet.css

We can write our own template files if we follow the same package structure and file names. Then when we run the GroovyDoc tool we must make sure our custom template files are used instead of the default ones. If we place our custom files in the class path of the GroovyDoc tool before the Groovy library then our custom files are used. In our Gradle project we can create a new source set that will contain our custom template files. Then we configure the classpath property of the groovydoc task and prepend it with the output of our source set. This way we can override the default implementation.

Let's change the classDocName.html template. We make a directory src/groovydoc. Here we create the directories org/codehaus/groovy/tools/groovy/gstringTemplates/classLevel. Inside the directory we create the file classDocName.html. We use the contents from the default classDocName.html found in the Groovy library and make some small changes. We want to add a Gravatar image to the Authors section. In our source code we must use the @author tag and include the e-mail address of the user between square brackets. For example @author Hubert Klein Ikkink [actual-email-address]. In our template file we will look for the value between the square brackets and replace it with a <img/> HTML tag referencing the Gravatar image.

...
<% if (classDoc.commentText()) { 

   def commentText = classDoc.commentText().replaceAll(/\[(.*)\]/) {
        def md5 = java.security.MessageDigest.getInstance("MD5").digest(it[1].getBytes("UTF-8")).encodeHex()
        "<img src=\"http://www.gravatar.com/avatar/${md5}?s=24\"/>"
   }

%>
            
    <p>${commentText}</p>
<% } %>
...

We also include a custom header. We set the value via our Gradle build file and it is available in our template file as props.header:

...
<% if (props.header) { %>
${props.header}
<% } %> ...

To make CSS changes we add the file stylesheet.css in the directory src/groovydoc/org/codehaus/groovy/tools/groovy/gstringTemplates/topLevel. Also here we can use the file from the Groovy library as starting point and make changes in it.

We make the following Gradle build file to support our custom template and reconfigure the groovydoc task:

plugins {
    id "groovy"
}

// Here we add a new SourceSet
// that has a resources directory
// at 'src/groovydoc'. This directory
// contains Groovydoc template files
// we want to override for our project.
sourceSets {
    groovydoc {
        resources {
            srcDir 'src/groovydoc'
        }
    }
}

// Customize groovydoc task that is
// added by the Groovy plugin.
groovydoc {
    // Set document and window titles.
    docTitle = "Sample GroovyDoc"
    windowTitle = "Example customizing GroovyDoc"
    
    // Set custom header. We will include this
    // in the changed classDocName.html file.
    header = '''\
        <img src="http://www.mrhaki.com/images/haki-logo-black-64.png"/>
        <h2>Sample project</h2>
        '''.stripIndent()
    
    // Set custom footer for generated documentation.
    footer = """\
        <div class="custom-footer">
            Generated on: ${new Date().format('yyyy-MM-dd HH:mm:ss')}
        </div>""".stripIndent()

    // Change classpath property and include
    // the output of the SourceSet groovydoc.
    // The output contains the changed stylesheet
    // and template file and must be first in the classpath
    // before the files that are bundled with Groovy.
    classpath = sourceSets.groovydoc.output + classpath
}

repositories {
    jcenter()
}

dependencies {
    compile "org.codehaus.groovy:groovy-all:2.4.5"
}

When we make some small changes to stylesheet.css and run the groovydoc task we see the following example output:

Notice we have our custom header, the Gravatar image and custom CSS.

Written with Groovy 2.4.5.