October 30, 2017

With the Asciidoctor diagram extension we can include diagrams that are written in plain text. For example PlantUML or Ditaa diagrams. The extension offers a block processor where we include the diagram definitions in our Asciidoctor document. But there is also a block macro processor. With the block macro processor we can refer to an external file. The file is processed and the resulting image is in our output document.

In the following example we see how to use the block macro for a Ditaa diagram:

= Diagram Block Macro
There is another way to use the diagram
extension instead of via a block definition. We
can use a block macro to refer to an external
file that has the diagram definition.
The name of the diagram extension is the
block macro name. For example for a Ditaa diagram
we use `ditaa::` and for PlantUML
we use `plantuml::`. This is followed
by a filename of the file that contains the
diagram source.
We can define attributes just like with the
block definition. The first positional attribute
define the filename. Or we use the attribute
name `target` to set the output filename. The second
positional attribute is the file format. Instead
we can use the attribute `format`.
In the next example we use a block macro
to include a Ditaa diagram definition:
// The first positional attribute is the
// file target name (or we use attribute target),
// the second positional attribute is the
// file format (or use attribute format).
// Other attributes can also be defined.
ditaa::sample.ditaa[ditaa-diagram, png, round-corners="true"]
Written with Asciidoctor {asciidoctor-version}.

October 27, 2017

In our Groovy scripts we can use the @Grab annotation. With this annotation we define dependencies for our script and they will be automatically downloaded and added to the class path when we run our script. When we use IntelliJ IDEA we can use a nice intention that is part of the IntelliJ IDEA Groovy support to download the dependencies from our IDE editor. IDEA downloads the dependencies and add it to the project module dependencies. This is useful, because this will also adds code completion for the classes in the dependency to our editor.

Let's see this with a little example. We have the following Groovy script in our Groovy project in IntelliJ IDEA:

We place the cursor on the @Grab annotation and enable the intention popup using Alt+Enter (check Keymap Reference for the key combination). We select the option from the popup:

IntelliJ IDEA downloads the dependency. When we look at our Project Structure and at the Module Dependencies we see the downloaded dependency:

In our example we added the Groovy script to a Groovy project in IntelliJ IDEA. When the project is a Gradle or Maven project we must make sure Ivy is part of the compile class path, because otherwise IntelliJ IDEA cannot download the dependencies using this intention. For example we could add to a Gradle build file the following dependency compileOnly 'org.apache.ivy:ivy:2.4.0'.

October 23, 2017

PlantUML has a built-in icon set we can use in our diagram definitions. The icon set is open source icon set OpenIconic. We refer to an icon using the syntax <&iconName>.We can use an icon everywhere where we can use text in our diagrams.

October 19, 2017

PlantUML supports sprites to be used in diagrams. A sprite is text encoded monochrome graphic we can reference using the syntax <$spriteName>. The sprite is defined using hexadecimal values. We can define a set of hexadecimal values to create our sprite, but we can also generate the correct values from for example a PNG image.

We start with a simple example where we create a small triangle using hexadecimal values:

Let's generate a PNG image from this PlantUML definition and we get the following result:

If we have already an image we want to turn into a sprite we can use the command-line option -encodesprite when we run PlantUML. As option we must specify the gray level for our sprite. We can choose for level 4, 8 or 16. If we place the letter z after the number the sprite definition is compressed. PlantUML will output to the console the sprite definition that we can use in our PlantUML definition file. We get the best result if the original image is grayscale.

October 18, 2017

In a previous post we learned how to use a together block to keep elements together. We can also layout elements in a different way: using hidden lines. We define our elements and by using the keyword [hidden] in our line definition the elements are layout as if there was a line, but we don't see it. This gives us great flexibility on how we layout our elements.

In the following sample we first have a PlantUML definition where we rely on the default layout:

We want the Logging component at the bottom right corner of the Core Components. Using a visible line we would connect the BackendClient to the Logging component. This would place the Logging component beneath the BackendClient, just like we want. So we add a connecting line and we add the [hidden] attribute on our line definition. The Logging component is placed where we want and we don't see the line supporting this:

October 17, 2017

We have a lot of ways to customize our PlantUML diagrams. We can change the colors and we can even set gradients as color. A gradient has two colors and a direction. The direction of the gradient is set by the separator between the two colors. We can use the following separators to set the gradient direction:

/: direction top left to bottom right

\: direction bottom left to top right

|: direction left to right

-: direction top to bottom

In the following example PlantUML diagram definition we apply different gradient directions and different colors:

@startuml
title Gradient
skinparam defaultTextAlignment center
skinparam RectangleFontSize 20
skinparam TitleFontStyle bold
skinparam TitleFontColor #e723e7
' Define two colors for a gradient
' and use - for left to right.
skinparam BackgroundColor #e2e2e2-#afafaf
' Define two colors for a gradient
' and use / for top left to bottom right.
skinparam RectangleBackgroundColor #ffd200/#8cfcff
rectangle A [
From top left
to bottom right
]
' Use \ for bottom left to top right
rectangle B #ffd200\8cfcff [
From bottom left
to top right
]
' Use | for left to right
rectangle C #ffd200|8cfcff [
From left
to right
]
' Use | for top to bottom
rectangle D #ffd200-8cfcff [
From top
to bottom
]
@enduml

When we convert this PlantUML syntax to a PNG image we get the following result:

If a class implements the Closeable interface Groovy adds the withCloseable method to the class. The withCloseable method has a closure as argument. The code in the closure is executed and then the implementation of the close method of the Closeable interface is invoked. The Closeable object is passed as argument to the closure, so we can refer to it inside the closure.

In the following example we have two objects that implement the Closeable interface. By using withCloseable we know for sure the close method is invoked after all the code in the closure is executed:

@Grab(group='org.apache.httpcomponents', module='httpclient', version='4.5.3')
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.client.methods.HttpGet
// HttpClientBuilder.create().build() returns a CloseableHttpClient
// that implements the Closeable interface. Therefore we can use
// the withCloseable method to make sure the client is closed
// after the closure code is executed.
HttpClientBuilder.create().build().withCloseable { client ->
final request = new HttpGet('http://www.mrhaki.com')
// The execute method returns a CloseableHttpResponse object
// that implements the Closeable interface. We can use
// withCloseable method to make sure the response is closed
// after the closure code is executed.
client.execute(request).withCloseable { response ->
assert response.statusLine.statusCode == 200
}
}

October 16, 2017

When we define a list in Asciidoctor we usually have a list item that is a paragraph. But if we want to have a block as list item we need to add an extra {blank} element to make sure the block is parsed correctly as list item. Because a list item starts with a . or a * at the beginning of a line and a block also is defined on the beginning of the line, we must add the extra {blank} element. Together with the list item continuation (+) we can have a list with blocks.

In the following example we define a numbered list with three listing blocks:

October 13, 2017

PlantUML has some features that come from the underlying software to create diagrams. Graphviz is used by PlantUML and we can use Graphviz features in our PlantUML diagrams. For example we can align multi-line text of labels to be either center (default), left or right aligned using a Graphviz feature. When we want to text to be center aligned we simply use the new-line character \n. If we want to have our text left aligned we use \l instead of \n. And to right align the text we use \r.

In the following example we have three labels that are center, left and right aligned: