Beruflich Dokumente
Kultur Dokumente
This is a Leanpub book. Leanpub empowers authors and publishers with the Lean
Publishing process. Lean Publishing is the act of publishing an in-progress ebook using
lightweight tools and many iterations to get reader feedback, pivot until you have the
right book and build traction once you do.
2015 - 2016 Hubert A. Klein Ikkink (mrhaki)
Contents
About Me . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ii
Tables . . . . . . . . . . . . . . . . . . . . . . .
Changing Table and Column Width . . .
Table Column and Cell Alignment . . . .
Changing the Grid and Frame of Tables .
Span Cell over Rows and Columns . . . .
Repeating Cell Contents . . . . . . . . . .
Using Asciidoc in Tables . . . . . . . . . .
Styling Columns and Cells in Tables . . .
Escaping Pipe Symbol in Tables . . . . .
CSV and DSV Tables . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
3
5
8
10
11
13
16
17
Source code . . . . . . . . . . . . . . . . . . . . . . . .
Change Source Code Indentation . . . . . . . .
Adding Line Numbers to Source Code Listings
Include Partial Parts from Code Samples . . . .
Include Only Certain Lines from Included Files
Explain Code with Callouts . . . . . . . . . . . .
Highlight Lines In Source Code Listings . . . .
Changing Highlight.js Theme . . . . . . . . . . .
Source Syntax Highlighting With Prism . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
20
20
21
23
24
25
26
28
30
Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Use Asciidoctor Diagram with Gradle . . . . . . . . . . .
Write Extensions Using Groovy (or Java) . . . . . . . . .
Use Inline Extension DSL with Gradle . . . . . . . . . . .
Using Ruby Extensions With Asciidoctor Gradle Plugin
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
34
34
36
39
41
Miscellaneous . . . . . . . . . . . . . . . . . . . . .
Using Comments . . . . . . . . . . . . . . . . .
Which Asciidoctor Version is Used? . . . . . .
Disable Last Updated Text in Footer . . . . . .
Adding Custom Content to Head and Footer .
Include Raw HTML . . . . . . . . . . . . . . . .
Use Inline Icons . . . . . . . . . . . . . . . . . .
Changing the FontAwesome CSS Location . .
Change URI Scheme for Assets . . . . . . . . .
Replacements For Text To Symbols . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
43
43
44
44
45
47
48
50
51
52
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CONTENTS
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
52
53
55
57
59
60
61
62
63
64
65
68
69
70
71
73
76
77
78
79
81
84
86
87
About Me
I am born in 1973 and live in Tilburg, the Netherlands, with my beautiful wife and three
gorgeous children. I am also known as mrhaki, which is simply the initials of his name
prepended by mr. The following Groovy snippets shows how the alias comes together:
['Hubert', 'Alexander', 'Klein', 'Ikkink'].inject('mr') { alias, name ->
alias += name[0].toLowerCase()
}
(How cool is Groovy that we can express this in a simple code sample ;-) )
I studied Information Systems and Management at the Tilburg University. After finishing
my studies I started to work at a company which specialized in knowledge-based software.
There I started writing my first Java software (yes, an applet!) in 1996. Over the years my
focus switched from applets, to servlets, to Java Enterprise Edition applications, to Springbased software.
In 2008 I wanted to have fun again when writing software. The larger projects I was working
on were more about writing configuration XML files, tuning performance and less about
real development. So I started to look around and noticed Groovy as a good language to
learn about. I could still use existing Java code, libraries, and my Groovy classes in Java.
The learning curve isnt steep and to support my learning phase I wrote down interesting
Groovy facts in my blog with the title Groovy Goodness. I post small articles with a lot of
code samples to understand how to use Groovy. Since November 2011 I am also a DZone
Most Valuable Blogger (MVB); DZone also posts my blog items on their site.
In 2010, 2011, 2012, 2013 and 2014 I was invited to speak at Gr8Conf in Copenhagen,
Denmark. This is a very good conference with all the project leaders of Groovy and Groovyrelated projects. In 2014 I also spoke at the Gr8Conf US. In 2015 I got a change to speak at
the Greach conference in Madrid. A very nice conference with all Groovy related subjects.
In November 2010 I presented a Gradle talk at the J-Fall conference of the Dutch Java User
Group. In November 2011 I presented about the new features in Groovy 1.8 at the same
conference. During the 2013 edition I presented a hands-on Gradle workshop and in 2014
I gave a talk about AsciiDoctor. The conference is visited by 1000 Java developers and I got
the chance to educate some of them about the greatness of Gradle and Groovy.
I work for a company called JDriven in the Netherlands. JDriven focuses on technologies
that simplify and improve development of enterprise applications. Employees of JDriven
have years of experience with Java and related technologies and are all eager to learn about
new technologies. I work on projects using Grails and Java combined with Groovy and
Gradle.
Introduction
When I started to learn about Asciidoctor I wrote done little code snippets with features
of Asciidoctor I found interesting. To access my notes from different locations I wrote the
snippets with a short explanation in a blog: Messages from mrhaki. I labeled the post as
Awesome Asciidoctor, because I thought this is awesome stuff, and that is how the Awesome
Asciidoctor series began.
A while ago I bundled all my blog Groovy Goodness blog posts in a book published at
Leanpub. Leanpub is very easy to use and I could use Markdown to write the content,
which I really liked as a developer. So it felt natural to also bundle the Grails Goodness
blog posts and Gradle Goodness blog posts at Leanpub.
In this book the blog posts are bundled and categorized into sections. Within each section
blog posts that cover similar features are grouped. The book is intended to browse through
the subjects. You should be able to just open the book at a random page and learn more
about Asciidoctor. Maybe pick it up once in a while and learn a bit more about known and
lesser known features of Asciidoctor.
I hope you will enjoy reading the book and it will help you with learning about Asciidoctor,
so you can apply all the awesomeness in your projects.
Code samples
Code samples in the book can contain a backslash (\) at the end of the line to
denote the line actually continues. This character is not part of the code, but for
better formatting of the code blocks in the book the line is split. If you want to
use the code you must keep this in mind.
Tables
Changing Table and Column Width
When we define a table in Asciidoctor the columns all have the same width and the table
will the whole width of the page. Of course we can change this when we define the table.
We can change the table width with the width attribute. We specify the column width with
the cols attribute.
First we will change the width of the columns. We can specify proportional integer values
or a percentage to specify the width of a column. In the following sample Asciidoctor file
we use proportional values in the first table. The first column has value 1 and the second
column value 3. This means the second column should be 3 times as wide as the first
column. In the second table the column width is defined with percentage values. The first
column should occupy 60% of the table width and the last column the rest.
// Define table with proportional column width.
.Table with relative column widths (1,3)
[cols="1,3"]
|===
| Name | Description
| Asciidoctor
| Awesome way to write documentation
|===
When we transform the Asciidoctor source to HTML we get the following result:
Tables
We see in the examples that the width of the table is the same as the width of the page. To
make a smaller table we set the width attribute for a table. The value must be a percentage.
Lets create a sample Asciidoctor file and define a table with a width of 50%:
// Define table with default width for comparison.
.Table full width (default)
|===
| Name | Description
| Asciidoctor
| Awesome way to write documentation
|===
And if we look at the generated HTML for example we can see the second table is half the
width of the first:
Tables
[cols="^,<,>", options="header"]
|===
| Name
| Description
| Version
Tables
| Asciidoctor
| Awesome way to write documentation
| 1.5.0
|===
When we create HTML output from this source we get the following output:
We have now defined the horizontal alignment. To include vertical alignment we must
add dot (.) to the horizontal alignment value and then the vertical alignment value. The
following vertical alignment values can be used:
<: top align values (default)
>: bottom align values
: center values
In the following sample Asciidoctor file we add vertical alignment configuration to our
previous table:
// File: table.adoc
//
//
//
//
[cols="^.>,<.<,>.^", options="header"]
|===
| Name
| Description
| Version
| Asciidoctor
| Awesome way to write documentation
| 1.5.0
|===
We get the following HTML table when we process that source file:
Tables
Finally we can alter the horizontal and vertical alignment per cell. We use the alignment
configuration symbols before the pipe symbol (|) of a cell definition. This overrules any
alignment configuration set in the cols definition. In the next Asciidoctor file we combine
all these settings for a table:
// File: table.adoc
//
//
//
//
//
//
[cols="3*", options="header"]
|===
^| Name
^| Description
^| Version
>| Asciidoctor
| Awesome way to write documentation
^.^| 1.5.0
|===
And when we look at the output we see all alignment configuration applied to our table:
Tables
To change the inner grid of a table we use the grids table attribute. The default value all
displays a grid for columns and rows inside the table. The value cols only displays a grid
between columns, value rows display a grid between rows and with value none there will
be no grid inside our table.
The following Asciidoc sample shows the definition of four tables with different values for
the cols table attribute:
.Table with top and bottom frame (topbot)
[frame="topbot"]
|===
| Name | Description
| Asciidoctor
| Awesome way to write documentation
|===
When we generate output using the HTML backend we get the following result:
Tables
In the next sample we have four tables with different values for the cols attribute:
.Table with no grid (none)
[grid="none", frame="none"]
|===
| Name | Description
| Asciidoctor
| Awesome way to write documentation
|===
.Table with only columns grid (cols)
[grid="cols", frame="none"]
|===
| Name | Description
| Asciidoctor
| Awesome way to write documentation
|===
.Table with only rows grid (rows)
[grid="rows", frame="none"]
|===
| Name | Description
| Asciidoctor
| Awesome way to write documentation
|===
.Table with default rows and columns grid (all)
[grid="all", frame="none"]
Tables
|===
| Name | Description
| Asciidoctor
| Awesome way to write documentation
|===
And we get the following output when we transform this source to HTML:
Tables
Tables
10
Tables
11
|===
When we generate a HTML document from this source we see the following result:
Tables
12
:icons: font
// Simple table where we apply some
// Asciidoc markup in the cell contents.
|===
| Name | Description
| Asciidoctor
| NOTE: *Awesome* way to write documentation
|===
When we transform this Asciidoctor source to HTML we see the following output:
Notice that we dont get a nice image for our NOTE is not shown as image when it used in a
table cell.
To change this behavior we can configure the table. We can configure a column to have
Asciidoc content that needs to be interpreted or we can configure at cell level we want the
contents to be interpreted as Asciidoc. We use the character a in the cols attribute when
we define the table. Or we use the character a before the table cell separator (|). In the
next sample Asciidoctor file we use both ways to make sure the cell contents is Asciidoc
markup that needs to be transformed as well:
:icons: font
// We use the cols attribute for our table
// and specify that the contents of the second
// column is Asciidoc markup.
[cols=",a"]
|===
| Name | Description
| Asciidoctor
| NOTE: *Awesome* way to write documentation
|===
13
Tables
//
//
//
a|
|===
Once we have defined the table we get the following generated HTML:
e: emphasized
a: Asciidoc markup
m: monospace
h: header style, all column values are styled as header
s: strong
l: literal, text is shown in monospace font and line breaks are kept
d: default
v: verse, keeps line breaks
The following Asciidoctor source uses the different styles as cols attribute values:
Tables
14
When we transform this into HTML using the Asciidoctor HTML backend we get the
following result:
Tables
15
We can also override a column styling per cell. We must put the correct styling character
before the pipe symbol (|), so the contents of the cell is styled differently:
Table with row style e,a,m in second row
|===
| Emphasized | Asciidoc | Monospaced
| Asciidoctor
| NOTE: *Awesome* way to write documentation
| It is just code
e| Asciidoctor
a| NOTE: *Awesome* way to write documentation
m| It is just code
|===
And the following HTML is generated when we process this Asciidoctor source:
Tables
16
Tables
17
Tables
18
= Tables
== CSV table
//
//
//
//
//
,===
Writing tools, Awesomeness
Asciidoctor, Oh yeah!
MS Word, No!
,===
The previous samples used a comma to separate values, but we can also use colon (:). The
next sample contains tables defined with DSV:
== DSV table
[format="dsv", options="header"]
|===
Writing tools:Awesomeness
Asciidoctor:Oh yeah!
MS Word:No!
|===
// Alternative syntax:
:===
Writing tools: Awesomeness
Asciidoctor: Oh yeah!
MS Word: No!
:===
With the include directive we can also include data from an external CSV of DSV file to
create a table (of course also the traditional pipe-symbol separated format can be in an
external file):
Tables
19
Source code
Change Source Code Indentation
Writing documentation and including source files is made very easy in Asciidoc and
Asciidoctor. We can use the include macro to include a source file in our documentation.
This way we can write source code, test the code (preferable automated) and the code in
our documentation always works and will be up to date. We can use the indent attribute
when we include source code to change the indentation. Tab characters are replaced with
4 spaces when we use the indent attribute. We can specify the number of spaces the code
needs to be indented with a value of 0 or greater.
The following sample Asciidoc markup will remove all indentation of the original code
block which is indented with 4 spaces, because we use the value 0:
[source,groovy,indent=0]
---def sample = (1..4).collect { it * 2 }
assert sample == [2,4,6,8]
----
The code still looks indented, but that is done via CSS styling. The padding is set to a value
greater than 0, but we can change that of course with our own CSS stylesheet.
In the following sample we set the indent attribute with the value 8:
[source,groovy,indent=8]
---def sample = (1..4).collect { it * 2 }
assert sample == [2,4,6,8]
----
In the final sample we use the include macro to include source code. We can still use the
indent attribute like we did with the inline code samples:
Source code
21
[source,groovy,indent=3]
include::indent.groovy[]
Lets generate HTML output from this markup and use different values for the sourcehighlighter and ...-linenums-mode attributes. First we use the Coderay source highlighter
in table mode:
Source code
22
If we use inline mode (:coderay-linenums-mode: inline), we can see the line numbers are
selected as well when we select the source code:
The following screenshots use the Pygments source highlighter with first a table mode for
the line numbers and then inline mode:
Source code
23
Source code
24
// File: Sample.groovy
package com.mrhaki.blog.groovy
class Sample {
// tag::helloMethod[]
String hello() {
'Asciidoc rules!'
}
// end::helloMethod[]
}
In our Asciidoc document we use the following syntax to include only the hello() method:
== Sample Asciidoc
[source,groovy]
.Sample.groovy
---include::Sample.groovy[tags=helloMethod]
----
This will result in the following HTML if we use Asciidoctor with the pretty-print syntax
highlighter:
<div class="listingblock">
<div class="title">Sample.groovy</div>
<div class="content">
<pre class="prettyprint groovy language-groovy"><code>
String hello() {
'Asciidoc rules!'
}
</code>
</pre>
</div>
</div>
</div>
Source code
25
And when we generate an HTML version of our markup we see that only part of the original
source file is included in the output:
Source code
26
enclosed in < and > brackets. The explanation for the markers follows a code listing in
a callout list. Here we use the same marker and add extra text to explain the code. We can
put the markers in comments in our code so we can use the markers in existing code.
Suppose we have the following piece of documentation where we add two markers (in
comments) to some Groovy source code:
[source,groovy]
---package com.mrhaki.adoc
class Sample {
String username // <1>
String toString() {
"${username?.toUpperCase() ?: 'not-defined'}" // <2>
}
}
---<1> Simple property definition where Groovy will generate the +setUsername+ and +getUsername+ met\
hods.
<2> Return username in upper case if set, otherwise return +not-defined+.
When we generate this into an HTML document with the prettify syntax highlighter and
icon font we get the following output:
Source code
27
First we must add the document attribute source-highlighter and use the value coderay or
pygments. When we use Coderay we must also enable the line numbers for the source code
listing, because Coderay will highlight the line numbers in the output. Pygments highlight
the whole line, with or without line numbers in the output. Therefore we choose Pygments
in our example. To highlight certain lines in the source code output we use the highlight
attribute for the source code block. We can specify single line numbers separated by a
comma (,) or semi colon (;). If we use a comma we must enclose the value of the highlight
attribute in quotes. To define a range of line numbers we can define the start and end line
numbers with a hyphen in between (eg. 5-10 to highlight lines 5 to 10). To unhighlight a
line we must prefix it with a exclamation mark (!). For example the following value for the
highlight attribute highlights the lines 2, 3 to 7 and not 5: [source,highlight=1;3-7;!5].
In the following example markup we have a source code block where we highlight the lines
7 to 9. We use Pygments as syntax highlighter:
= Source highlight lines
:source-highlighter: pygments
:pygments-style: emacs
:icons: font
== Creating an application
To create a simple Ratpack application we write
the following code:
.Simple Groovy Ratpack application
[source,groovy,linenums,highlight='7-9']
---package com.mrhaki
import static ratpack.groovy.Groovy.ratpack
ratpack {
handlers {
get {
render "Hello World!" // <1>
}
}
}
---<1> Render output
If we look at the generated HTML we can see lines 7, 8 and 9 are differently styled:
Source code
28
Source code
---[source,sql]
---CREATE TABLE USER (
ID INT NOT NULL,
USERNAME VARCHAR(40) NOT NULL
);
----
29
Source code
30
Source code
In the following markup we have two source code listings in Java and Groovy:
= Source highlights with Prism
// Set default language for source code listings to java.
:source-language: java
// Include docinfo.html for Prism CSS file and
// include docinfo-footer.html for Prism Javascript.
:docinfo1:
== Creating an application
To create a simple Ratpack application we write
the following code:
.Simple Java Ratpack application
[source]
---package com.mrhaki;
import ratpack.server.RatpackServer;
public class Main {
public static void main(String... args) throws Exception {
RatpackServer.start(server ->
server
.handlers(chain ->
chain
.get(ctx -> ctx.render("Hello World!"))));
}
}
---.Simple Groovy Ratpack application
[source,groovy]
---package com.mrhaki
import static ratpack.groovy.Groovy.ratpack
ratpack {
handlers {
get {
render "Hello World!"
}
}
}
----
31
Source code
32
This fits perfectly with Prism. Prism expects this format to apply the syntax highlighting.
So we only have to add the Prism Javascript and CSS files to the generated HTML file. We
download the Prism Javascript and CSS file from the Prism download site. We save the
Javascript file as prism.js and the CSS file as prism.css. Next we create a docinfo.html to
include a reference to the prism.css file:
<link href="prism.css" rel="stylesheet" />
<style>
/* Override Asciidoctor CSS to get the correct background */
.listingblock pre[class^="highlight "] {
background: #272822;
}
</style>
In our markup we have the document attribute docinfo1 set. This means the files docinfo.html
and docinfo-footer.html are included in the generated HTML output. Lets see the result
in a web browser:
Source code
33
Extensions
Use Asciidoctor Diagram with Gradle
Since Asciidoctor 1.5.0 we can use extensions when we write AsciiDoc documents. These
extensions can be written in Ruby or any JVM language. If we use Gradle and the Asciidoctor Gradle plugin to transform our documents we can use both extensions. Of course an
extension written in for example Java or Groovy can be included as a regular dependency in
our build configuration. As the extension is on the classpath of the asciidoctor task then it
can be used. When the extension is a Ruby extension and available as a Ruby gem we need
some more configuration in our build file. To use an Asciidoctor extension written in Ruby
in our build we must first make sure that we can download the extension. Then we can
configure the asciidoctor task from the Asciidoctor Gradle plugin to use the extension.
Lets start with a sample Asciidoctor document which uses the Asciidoctor Diagram
extension. With this extension we can embed diagrams as text in our document and get
graphical images as output.
= Sample diagram
:imagesdir: images
== Ditaa
// Sample diagram from Asciidoctor Diagram website
// http://asciidoctor.org/docs/asciidoctor-diagram/
[ditaa, "asciidoctor-diagram-process"]
....
+-------------+
| Asciidoctor |-------+
|
diagram
|
|
+-------------+
| PNG out
^
|
| ditaa in
|
|
v
+--------+
+--------+----+
/---------------\
|
|---+ Asciidoctor +--->|
|
| Text |
+-------------+
|
Beautiful
|
|Document|
|
!magic!
|
|
Output
|
|
{d}|
|
|
|
|
+---+----+
+-------------+
\---------------/
:
^
|
Lots of work
|
+-----------------------------------+
....
Next we create our Gradle build file. We must apply the Asciidoctor Gradle plugin so we
can transform our AsciiDoc documents. And we must apply the JRuby Gradle plugin so we
Extensions
35
can download Ruby gems and use them from the asciidoctor task. The JRuby plugin adds
a gems dependency configuration, which we can use to define the Ruby gems we need. The
task jrubyPrepareGems is also added by the plugin and this task will download the gems and
extract them in our project build directory. In our asciidoctor task that is added by the
Asciidoctor plugin we use the requires property to specify which gem is needed. We also
set the gemPath property to the directory which contains the downloaded and extracted
Ruby gems. The following build file defines the plugins and configures the tasks we need
so we can use Asciidoctor Diagram:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.0'
classpath 'com.github.jruby-gradle:jruby-gradle-plugin:0.1.5'
}
}
// Plugin so we can render AsciiDoc documents.
apply plugin: 'org.asciidoctor.gradle.asciidoctor'
// Plugin so we can use Ruby gems when rendering documents.
apply plugin: 'com.github.jruby-gradle.base'
dependencies {
// gems dependency configuration is added by
// jruby-gradle-plugin. Here we define
// the gems we need in our build.
gems 'rubygems:asciidoctor-diagram:1.2.0'
}
asciidoctorj {
// We can change the AsciidoctorJ
// dependency version.
version = '1.5.1'
}
asciidoctor {
// jrubyPrepareGems task is added by the JRuby
// plugin and will download Ruby gems we have
// defined in the gems dependency configuration.
dependsOn jrubyPrepareGems
// Asciidoctor task needs the
// asciidoctor-diagram gem, we installed
// with the jrubyPrepareGems task and
// gems dependency configuration.
requires = ['asciidoctor-diagram']
// Set path to find gems to directory
// used by jrubyPrepareGems task.
gemPath = jrubyPrepareGems.outputDir
Extensions
36
}
defaultTasks 'asciidoctor'
To generate our sample document we only have to run $ gradle from the command line.
After the documents are generated we can the result in the build/asciidoc directory of
our project. The following screenshot shows the generated HTML:
Extensions
37
Inline macro processor: Registers a custom inline macro and process it (e.g., btn:[Save])
Include processor: Processes the include::[] macro
To write an extension in Groovy (or Java) we must write our implementation class for a
specific extension point and we must register the class so AsciidoctorJ knows the class
can be used. Registering the implementation is very simple, because it is using the Java
Service Provider. This means we have to place a file in the META-INF/services directory on
the classpath. The contents of the file is the class name of the implementation class.
Lets start with the Asciidoc markup and then write an implementation to process the inline
macro twitter that is used:
= Groovy Inline Macro
Sample document to show extension for Asciidoctor written in Groovy.
// Here we use the twitter: macro.
// The implementation is done in Groovy.
With the twitter macro we can create links to the user's Twitter page like twitter:mrhaki[].
Extensions
38
We have the implementation class so now we can register the class with Asciidoctor. To
register our custom extensions we need to implement the ExtensionRegistry interface. We
implement the register method where we can couple our extension class to Asciidoctor.
// File: src/main/groovy/com/mrhaki/asciidoctor/extension/TwitterMacroExtension.groovy
package com.mrhaki.asciidoctor.extension
import org.asciidoctor.extension.spi.ExtensionRegistry
import org.asciidoctor.extension.JavaExtensionRegistry
import org.asciidoctor.Asciidoctor
import groovy.transform.CompileStatic
@CompileStatic
class TwitterMacroExtension implements ExtensionRegistry {
@Override
void register(final Asciidoctor asciidoctor) {
final JavaExtensionRegistry javaExtensionRegistry = asciidoctor.javaExtensionRegistry()
javaExtensionRegistry.inlineMacro 'twitter', TwitterMacro
}
}
The class that registers our extension must be available via the Java Service Provider so
it is automatically registered within the JVM used to run Asciidoctor. Therefore we need
to create the file META-INF/services/org.asciidoctor.extension.spi.ExtensionRegistry
with the following contents:
# File: src/main/resources/META-INF/services/org.asciidoctor.extension.spi.ExtensionRegistry
com.mrhaki.asciidoctor.extension.TwitterMacroExtension
We have taken all steps necessary to have our inline macro implementation. We must
compile the Groovy classes and add those with the Java Service Provider file to the
classpath. We can package the files in a JAR file and define a dependency on the JAR file in
our project. If we use Gradle and the Gradle Asciidoctor plugin we can also add the source
files to the buildSrc directory of our project. The files will be compiled and added to the
classpath of the Gradle project.
With the following Gradle build file we can process Asciidoc markup and execute the
twitter inline macro. We store the source files in the buildSrc directory.
Extensions
39
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.0'
}
}
apply plugin: 'org.asciidoctor.gradle.asciidoctor'
The build file in the buildSrc directory has a dependency on AsciidoctorJ. This module
makes it possible to run Asciidoctor on the JVM.
// File: buildSrc/build.gradle.
apply plugin: 'groovy'
repositories {
jcenter()
}
dependencies {
compile 'org.asciidoctor:asciidoctorj:1.5.0'
}
Lets see part of the HTML that is generated if we transform the Asciidoc markup that is
shown at the beginning of this blog post. The twitter inline macro is transformed into a
link to the Twitter page of the user:
...
<div class="paragraph">
<p>With the twitter macro we can create links to the user's Twitter page like <a href="http://www\
.twitter.com/mrhaki">@mrhaki</a>.</p>
</div>
...
40
Extensions
= Sample
This is an issue issue:PRJ-100[].
Now we write the following Gradle build file. First we include the Gradle Asciidoctor plugin.
Then we can use the extensions configuration method to add our code for the inline
macro. If we would write another type of extension we could still use the same place to
add it, but then we dont use inlinemacro.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.2'
}
}
// Apply the Asciidoctor Gradle plugin.
apply plugin: 'org.asciidoctor.convert'
asciidoctor {
// Here we can add the code for extensions we write.
extensions {
// Implementation for inline macro to replace
// issue:<issue-id>[] with a link to the issue.
inlinemacro (name: "issue") {
parent, target, attributes ->
options = [
"type": ":link",
"target": "http://issue-server/browse/${target}".toString()
]
// Create the link to the issue.
createInline(parent, "anchor", target, attributes, options).render()
}
}
}
Lets transform our sample Asciidoctor markup to HTML. We see the following result:
Extensions
41
extension.rb
sample.adoc
twemoji-awesome.css
emoji-inline-macro.rb
1 directory, 4 files
In our build file we configure the asciidoctor task and use the requires method to define
a dependency on the Ruby emoji-inline-macro.rb file:
// File: build.gradle
plugins {
id 'org.asciidoctor.convert' version '1.5.3'
}
asciidoctor {
// Add requirement on Ruby extension.
requires './lib/emoji-inline-macro.rb'
}
We are done. Next we create a sample Asciidoc markup document with the following
content:
Extensions
= Asciidoctor is awesome!
Writing with Asciidoctor makes me feel emoji:sunny[5x]
This sample is written while Devoxx BE is in progress, so
@DevoxxPeople: Enjoy your emoji:beers[]
We get the following HTML5 output when we run the asciidoctor task:
42
Miscellaneous
Using Comments
We can add comments to our Asciidoc markup. The comments will not be added to
generated output. We can add both single and multiline comments in the markup. Single
line comments start with a double slash (//). Multiline comments are enclosed in a block
of four forward slashes (////).
The following sample markup defines Asciidoc markup with comments:
= Asciidoctor comments
// Paragraph with some text.
Writing documentation is fun with Asciidoctor.
* Item A
* Item B
// Divide lists with a single line comment.
// Now we have two lists, otherwise it would
// be a single list with 4 items.
* Item 1
* Item 2
////
With four forward slashed we can
start a multiline comment.
And we close it with another
four forward slashes.
////
Asciidoc is really like _programming_ documentation.
When we generate HTML output we dont see any of the comments, not even in the HTML
source:
Miscellaneous
44
And we get the following HTML content once we have generated HTML from our Asciidoc
source code:
Miscellaneous
45
:last-update-label!:
= Change footer
To disable the _Last updated_ text
in the footer we disable the document
attribute `last-update-label`.
---// Disable last updated text.
:last-update-label!:
----
Miscellaneous
46
Miscellaneous
47
Miscellaneous
48
The generated HTML will execute the Javascript and we get the following output:
We can also add raw HTML inline in our Asciidoc markup. We can enclose the HTML in
triple plus signs (+++) or use the pass:[] macro. The following sample shows the markup
where both methods are used:
We can also use passthrough inline macros to have raw HTML in the output.
For example with three plus symbols we can +++<em>emphasize text</em>+++.
Or we can use the inline macro syntax with the +pass+ name to pass:[<strong>make text strong</str\
ong>].
Miscellaneous
49
:icons: font
icon:comment[] This is a comment icon
icon:file[] And a file icon
We can specify CSS classes using the role attribute for the macro. But together with the
HTML backend and font-based icons we can also use other attributes: size, rotate and
flip. The size attribute can specified without the attribute name if we use it as the first
attribute:
// Change icon size
icon:comment[4x] This is a comment icon
// Alternative icon:comment[size="4x"]
// Possible values: large, 2x, 3x, 4x, 5x
// Flip and rotate
icon:file[flip="vertical", rotate="180", role="lime"] And a file icon
// Possible flip values: vertical, horizontal
// Possible rotate values: 90, 180, 270
When we want to use an inline icon as a link we can use the attributes link and window:
Miscellaneous
50
Image based icons have the following attributes, like an image: alt, width, height, title,
role.
Code written and generated with Asciidoctor 0.1.4.
Original blog post written on June 19, 2014.
To reference the FontAwesome CSS from a relative location from our generated HTML
page we can first unset the attribute iconfont-remote and set the attribute iconfont-name:
:icons: font
// First unset attribute to remotely link FontAwesome CSS
:iconfont-remote!:
// Specify name of FontAwesome CSS.
:iconfont-name: fontawesome-4.1.0
// We can optionally set the directory where CSS is stored.
:stylesdir: css
== Sample doc
Miscellaneous
51
The generated HTML now contains a link to the FontAwesome CSS with a scheme-less
URI:
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.1.0/css/font-awesome\
.min.css">
Miscellaneous
52
Miscellaneous
53
Miscellaneous
54
Now we make the first section title discrete by applying the discrete attribute:
:toc:
= Section example
[discrete]
== Introduction
Simple introduction section.
== More
There is more information in this document.
We generate the document again as HTML and this time we see the section title is no
longer in the table of contents:
Miscellaneous
55
Miscellaneous
56
import ratpack.server.RatpackServer;
public class Main {
public static void main(String... args) throws Exception {
RatpackServer.start(server ->
server
.handlers(chain ->
chain
.get(ctx -> ctx.render("Hello World!"))));
}
}
---.Simple Groovy Ratpack application
[source,groovy]
---package com.mrhaki
import static ratpack.groovy.Groovy.ratpack
ratpack {
handlers {
get {
render "Hello World!"
}
}
}
----
When we generate the HTML for this markup we see the caption for the two listing blocks:
Miscellaneous
57
To disable the listing captions we must negate the document attribute: :!listing-caption:.
Written with Asciidoctor 1.5.4.
Original blog post written on September 26, 2016.
Miscellaneous
58
attribute for the include directive. In the following sample document we include other
files with a level 0 heading:
// File: book.adoc
= Include other files
// Include section numbers.
:sectnums:
// The file `chapter1.adoc` has a level 0 heading.
// To make sure it can be included we
// increase the level offset.
:leveloffset: +1
include::chapter1.adoc[]
// Reset level offset.
:leveloffset: -1
// Or use :leveloffset: 0
// We can also use the `leveloffset` attribute
// of the `include` directive. The level offset
// is then automatically reset.
include::chapter2.adoc[leveloffset=+2]
// File: chapter2.adoc
= First chapter
Sample document to be included.
When we transform book.adoc to HTML with Asciidoctor we get the following result:
Miscellaneous
59
Miscellaneous
60
When we transform this to HTML with Asciidoctor we get the following result:
Miscellaneous
61
When we generate output using the HTML backend we see the following output:
The following HTML is generated when we use Asciidoctor with the HTML backend:
Miscellaneous
62
<div class="paragraph">
<p><a href="http://mrhaki.blogspot.com" target="_blank">Messages from mrhaki</a></p>
</div>
<div class="paragraph">
<p><a href="http://mrhaki.blogspot.com" class="ext-link" target="_blank">Messages from mrhaki</a>\
</p>
</div>
Miscellaneous
63
Miscellaneous
64
:grailsVersion: 2.3.8
[subs="attributes"]
---$ grails -version
Grails version: {grailsVersion}
----
The generated HTML now shows that the attribute value is used:
Alternative ways to define the listing block with the subs attribute. These will render the
same result:
[listing,subs="attributes"]
$ grails -version
Grails version: {grailsVersion}
[subs="attributes"]
$ grails -version
Grails version: {grailsVersion}
If we generate HTML with Asciidoctor we get the following output and notice that
attrValue is changed to attrvalue (lower case v):
Miscellaneous
65
If we add the escape character no attribute substitution will take place, even if we assign
a value to the attribute attrValue:
:attrValue: sample
This is a sample where we include +"${}"+ as a Groovy GString sample.
The sample +"$\{attrValue}"+ should be unchanged in the output.
If we want to include some content if the attribute is not set we use ifndef:
ifndef::sample[Content is shown when sample attribute is NOT set]
ifndef::sample[]
Content is shown when sample attribute is NOT set
endif::sample[]
We can even use multiple attributes for these macros. If the attribute names are ,
separated only one of the attributes need to be set to include the content. If we use the +
separator all attributes must be set to include the content.
In the following sample Asciidoc markup we see several usages of the ifdef and ifndef
macros:
Miscellaneous
66
|===
| Attributes
|
ifdef::intermediate[:intermediate:]
ifndef::intermediate[:intermediate!:]
|
ifdef::advanced[:advanced:]
ifndef::advanced[:advanced!:]
|===
ifdef::advanced[]
This is only visible if we
set the advanced attribute.
endif::advanced[]
ifdef::intermediate,advanced[]
Here is some content for the
intermediate or advanced readers,
which is visible if the attributes
intermediate or advanced are set.
endif::intermediate,advanced[]
ifdef::intermediate+advanced[]
Here is some content for the
intermediate and advanced readers,
which is visible if the attributes
intermediate AND advanced are set.
endif::intermediate+advanced[]
If we generate HTML output and set and unset the intermediate and advanced document
attributes we see that content is included or not:
Miscellaneous
67
Finally with Asciidoctor we can use the ifeval macro to evaluate the value of attributes.
If the expression evaluates to true the content is included otherwise it is skipped. The
following sample evaluate the version document attribute and shows different content
based on the value:
Miscellaneous
68
|===
| Attributes
|
:version: {version}
|===
ifeval::[{version} >= 1]
We are live!
endif::[]
ifeval::[{version} < 1]
Still developing...
endif::[]
Lets generate HTML with different values for the version attribute:
Miscellaneous
69
:blogpost: http://mrhaki.blogspot.com/2014/08/awesome-asciidoc-check-if-document-is.html
= Asciidoc on GitHub
Sample document for {blogpost}[Aweseome Asciidoc blog post].
ifdef::env-github[]
This line is only visible if the document is on GitHub.
GitHub is using Asciidoctor {asciidoctor-version}.
endif::env-github[]
ifndef::env-github[This line is visible if not rendered on GitHub.]
// File: sample.adoc
include::_attrs.adoc[]
== Sample
Miscellaneous
70
From the command line we can invoke the asciidoctor command. We also check the
directory and see there is only the file sample.html:
$ asciidoctor sample.adoc
$ ls
_attrs.adoc sample.adoc sample.html
$
The following screenshot shows how the sample.html looks like in a web browser:
Miscellaneous
71
Miscellaneous
72
backend to generate HTML the result will be a pre block enclosed in some div sections
with a couple CSS classes applied. If we want to add our own CSS classes to the generated
output we can apply so-called roles to our block.
In the following Asciidoc markup we apply a role with the name console to a listing block.
Remember we can use the same syntax for other types of blocks as well.
[source,role="console"]
---$ ls
index.adoc
$
----
If we generate HTML we get the following HTML code. Notice the class attribute of the
first div contains console:
<div class="listingblock console">
<div class="content">
<pre class="prettyprint"><code>$ ls
index.adoc
$</code></pre>
</div>
</div>
We can use an alternate syntax which resembles CSS classes closely. We can use dot (.)
followed by the role name.
[source.console]
---$ ls
index.adoc
$
----
If we want to apply multiple roles (CSS classes) we can specify the names separated by
spaces in the role attribute or chain the names with .:
[source.console.shell]
---$ ls
index.adoc
$
---// Or use role attribute:
[source,role="console shell"]
---$ ls
index.adoc
$
----
Miscellaneous
73
By specifying role values we can customize how the output looks with different implementation for the CSS classes that we want.
Code generated by Asciidoctor 0.1.4.
Original blog post written on June 16, 2014.
Miscellaneous
74
Miscellaneous
75
Miscellaneous
76
If we set the options attribute with the value nowrap the long lines are no longer wrapped
and we get a horizontal scrollbar to see the complete code listing:
Miscellaneous
77
[source,groovy,options="nowrap"]
---class GroovyHelloWorld {
def sayHello(final String message = 'world') { // Set default argument value for message argument
"Hello $message !"
}
}
----
The following screenshot shows a horizontal scrollbar when we want to see the rest of the
line:
Creating a Checklist
Creating a list with Asciidoctor markup is easy. To create an unordered we need to start a
line with an asterisk (*) or hypen (-). We can add some extra markup to create a checked
list. If we add two square brackets ([]) to the list item we have a checklist. To have an
unchecked item we use a space, for a checked item we can use a lowercase x (x) or an
asterisk (*).
In the next example we define a shopping cart list with Asciidoctor markup:
== Checklist
.Shopping cart
* [x] Milk // Checked with x
* [ ] Sugar // Unchecked
* [*] Chocolate // Checked with *
Miscellaneous
78
If we use font-based icons with the document attribute :icons: font the checkboxes are
rendered using fonts:
The checkboxes are now simply output in the HTML file. We can add an options attribute
to our list to make the checkboxes interactive:
== Checklist
// Make interactive checklist.
[options="interactive"]
.Shopping cart
* [x] Milk
* [ ] Sugar
* [*] Chocolate
If we transform this markup to HTML we see the following in our web browser:
Miscellaneous
79
== Numbered List
.Default
. Makes writing easy
.. Keep focus
.. Syntax
. Different output formats
// Start this list from 10.
[start=10]
.Start from 10
. Makes writing easy
// We can use it on all levels.
[start=10]
.. Keep focus
.. Syntax
. Different output formats
Miscellaneous
80
is used in the caption as well. We can customize the caption label, figure counter, caption
text or disable the figure caption using a combination of document and image attributes.
We have the following Asciidoctor markup. We include several images and customize the
figure caption settings. To change the caption label (Figure) we set a different value for the
document attribute figure-caption. In our example we use the value Logo. Any captions
following this definition will have the label Logo.
To use a separate counter we can use a counter attribute inside the caption attribute for
our image. In our example we use this for the Gradle logo. If we want to use another caption
text instead of the block title we can use the title attribute for an image.
Finally to disable all figure captions we negate the figure-caption document attribute.
= Figure caption
// Default the figure caption
// label is Figure.
.SDKMAN!
image::./sdkman-logo.png[]
// Set caption for figures
// for the rest of the document
// to the value Logo.
:figure-caption: Logo
// The figure caption label is Logo.
.Groovy
image::./groovy-logo.png[]
// Custom caption label for this image
// where we can still use a counter.
.Gradle
image::./gradle-logo.png[caption="Logo 1-{counter:logo}"]
// Instead of using the image block
// title in the caption we define
// our own caption text with the title
// attribute.
.Ratpack
image::./ratpack-logo.png[title="Ratpack library"]
// Disable all captions for figures.
:!figure-caption:
.Grails
image::./grails-logo.png[]
Miscellaneous
81
Miscellaneous
82
link, but if we rely on the default behaviour we create a title for our section including the
caption label and number. This way the created link points to the correct section and the
text contains the caption text and number for that section.
In the following example markup we can see how we can use the caption label and section
counter as attributes in the title. We do this with the title attribute of a section. By using
the single quotes we tell Asciidoctor to interpret the attributes. We must also make sure
we set the caption attribute to an empty string value. This disables the default caption
creation of Asciidoctor for our section. Finally we need to provide an ID for the section
using the #ID syntax:
= Code examples
// Enable the captions for listing blocks.
:listing-caption: Listing
== Creating an application
To create a simple Ratpack application we write
the following code:
// Our listing block has an id of SimpleJavaApp,
// so we can reference it as a link.
// The link text is the title of this listing block.
// We use the listing caption support of Asciidoctor
// in our title with the attributes listing-caption
// and counter:refnum. The value of listing-caption
// is defined with a document attribute (Listing)
// and counter:refnum contains the counter value
// for listing blocks.
// Finally we empty the caption attribute, otherwise
// the default caption rule is used to show Level {counter}.
[#SimpleJavaApp,source,java,caption='',title='{listing-caption} {counter:refnum}. Simple Java Rat\
pack application']
---package com.mrhaki;
import ratpack.server.RatpackServer;
public class Main {
public static void main(String... args) throws Exception {
RatpackServer.start(server ->
server
.handlers(chain ->
chain
.get(ctx -> ctx.render("Hello World!"))));
}
}
---// A second section also with an ID
// and custom caption and title attributes.
[#SimpleGroovyApp,source,groovy,caption='',title='{listing-caption} {counter:refnum}. Simple Groo\
vy Ratpack application']
---package com.mrhaki
Miscellaneous
When we generate a HTML version of this markup we get the following result:
83
Miscellaneous
84
Miscellaneous
85
:caution-caption:
:example-caption:
:figure-caption:
:important-caption:
:last-update-label:
:manname-title:
:note-caption:
:table-caption:
:tip-caption:
:toc-title:
:untitled-label:
:version-label:
:warning-caption:
This mechanism can be used to provide messages for other languages than English. The
Asciidoctor Github repository contains a file with already translated values for a lot of languages. We include this document in our own Asciidoctor markup and we set the document
attribute lang with the value we want, eg. nl. In the following example document we include the file https://raw.githubusercontent.com/asciidoctor/asciidoctor/v1.5.5/data/locale/attri
Miscellaneous
86
= Asciidoctor
// Set lang document attribute.
// This attribute is used in the
// included document attributes.adoc.
:lang: nl
// Include translations for built-in captions and labels.
// To make the inclusion with a URI work we must
// run Asciidoctor with attribute allow-uri-read:
// $ asciidoctor -a allow-uri-read sample.adoc
:i18n-labels-uri: https://raw.githubusercontent.com/asciidoctor/asciidoctor/v1.5.5/data/locale
include::{i18n-labels-uri}/attributes.adoc[]
// Simple caution block, where caption
// should be replaced by Dutch text.
CAUTION: Simpel bericht met `lang` document attribuut: {lang}.
// Labels for example blocks are also
// translated.
.Titel
====
Bijvoorbeeld label voor voorbeelden is ook aangepast.
====
When we invoke Asciidoctor via the command line we must add the option -a allow-uriread to the remote document is included. The following screenshot shows the output:
Miscellaneous
87
When we transform this to HTML with the built-in HTML5 templates we get the following
output:
Miscellaneous
88
In the following Java source code we have Javadoc comments with Asciidoctor syntax. We
have document attributes, list, styling, include macro, table and asciidoctor-diagram code
in our Javadoc. Notice that we dont have the clutter of HTML tags we normally we would
have if we write Javadoc.
package com.mrhaki.sample;
/**
* = Application
*
* Project version: {projectVersion}.
*
* Sample Java application in project {projectName}
* to show Asciidoclet as replacement for the
* default Javadoclet.
*
* We can apply Asciidoc syntax in our Javadoclet
* comments, like:
*
* - `code`
* - **bold**
* - _italics_
*
* include::./src/main/javadoc/usage.adoc[]
*
* [plantuml]
* ....
* hide footbox
*
* actor Client
* Client -> Application : main()
* ....
*
* @author mrhaki
* @version 1.0
*/
public class Application {
/**
* Main method to start the application.
*
* The following arguments are allowed
* (easy Asciidoc table syntax):
*
* |===
* | Name | Description
*
* | --help
* | Getting more help about the application.
*
* | --info
* | Show extra logging information
*
* |===
*
Miscellaneous
89
*/
public static void main(final String... arguments) {
System.out.println("Application started...");
}
}
Next we create a Gradle build file and configure the javadoc task to use the Asciidoclet
Javadoc doclet. In our Java class we also used the asciidoctor-diagram support and
therefore we also need to set up the Gradle jruby plugin.
plugins {
// jruby plugin needed for asciidoctor-diagram gem.
id 'com.github.jruby-gradle.base' version '0.1.5'
}
apply plugin: 'java'
version = '1.2.1'
ext {
asciidoctorDocletVersion = '1.5.2'
}
configurations {
// Extra configuration to assign Asciidoclet dependencies to.
// This way the dependency will not interfer with oterh configurations.
asciidoctorDoclet
}
repositories.jcenter()
dependencies {
// Define dependencies for Asciidoclet.
asciidoctorDoclet group: 'org.asciidoctor',
name: 'asciidoclet',
version: project.asciidoctorDocletVersion
// Define dependency on asciidoctor-diagram Ruby gem.
// Only needed when we want to use asciidoctor-diagram in our Javadoc.
gems 'rubygems:asciidoctor-diagram:1.2.0'
}
// Download required gems. Only when we need gems in our Javadoc.
javadoc.dependsOn jrubyPrepareGems
javadoc {
// Configure Javadoc options.
options.with {
// Configure Asciidoclet class path and class name
// for the Javadoc task.
docletpath = configurations.asciidoctorDoclet.files.asType(List)
doclet = 'org.asciidoctor.Asciidoclet'
// Set base dir. E.g. used for include directives.
Miscellaneous
90
When we run the javadoc task we get the generated output. For example part of the
generated documentation for our Application class looks like this:
Miscellaneous
91
Miscellaneous
92
Remember this only applies to Javadoc. If we write Groovy code and use Groovydoc to
generate documentation we cannot use Asciidoclet.
Written with Asciidoclet 1.5.2 and Gradle 2.7.
Original blog post written on October 12, 2015.