Search

Dark theme | Light theme
Showing posts with label AwesomeAsciidoctor:Markup. Show all posts
Showing posts with label AwesomeAsciidoctor:Markup. Show all posts

December 10, 2019

Awesome Asciidoctor: Auto Number Callouts

In a previous post we learned about callouts in Asciidoctor to add explanation to source code. While surfing the Internet I came upon the following blog post by Alex Soto: Auto-numbered Callouts in Asciidoctor. I turns out that since Asciidoctor 1.5.8 we can use a dot (.) instead of explicit numbers to have automatic increasing numbering for the callouts.

Let's take our example from the earlier blog post and now use auto numbered callouts:

= Callout sample
:source-highlighter: prettify
:icons: font

[source,groovy]
----
package com.mrhaki.adoc

class Sample {
    String username // <.>

    String toString() {
        "${username?.toUpperCase() ?: 'not-defined'}" // <.>
    }
}
----
<.> Simple property definition where Groovy will generate the `setUsername` and `getUsername` methods.
<.> Return username in upper case if set, otherwise return `not-defined`.

When we convert this markup to HTML we get the following result:

This makes it very easy to add new callouts without having to change all numbers we first typed by hand.

Written with Asciidoctor 2.0.9

May 24, 2019

Awesome Asciidoctor: Include Asciidoc Markup With Listing or Literal Blocks Inside Listing or Literal Block

If we want to include Asciidoc markup as source language and show the markup without transforming it we can use a listing or literal block. For example we are using Asciidoc markup to write a document about Asciidoctor and want to include some Asciidoc markup examples. If the markup contains sections like a listing or literal block and it is enclosed in a listing or literal block, the tranformation goes wrong. Because the beginning of the included listing or literal block is seen as the ending of the enclosing listing or literal block. Let's see what goes wrong with an example where we have the following Asciidoc markup:

In the following example we see a listing block that can be defined in Asciidoc markup.

[source,asciidoc]
----
= Sample document

We can include listing blocks which are ideal for including source code.

.A listing block
----
public class Sample { }
----

.A literal block
....
public class Sample { }
....

Asciidoctor awesomeness!
----

When we transform this to HTML we get the following output:

We can use nested listing or literal blocks where we have to add an extra hyphen or dot to the nested block, but then the Asciidoc markup we want to show as an example is not correct anymore. It turns out we can also add an extra hyphen or dot to the enclosing listing or literal block to transform our markup correctly. So in our example we add an extra hyphen to the outer listing block:

In the following example we see a listing block that can be defined in Asciidoc markup.

[source,asciidoc]
// This time we have 5 hyphens.
-----
= Sample document

We can include listing blocks which are ideal for including source code.

.A listing block
----
public class Sample { }
----

.A literal block
....
public class Sample { }
....

Asciidoctor awesomeness!
-----

The transformed HTML looks like this:

If our sample markup we want to show only contains a listing block we could have enclosed it in a literal block to get the same result or sample markup of a literal block could be in a listing block.
But in our example we have both a listing and literal block so we needed another solution to get the desired result.

Written with Asciidoctor 2.0.9.

May 22, 2019

Awesome Asciidoctor: Don't Wrap Lines in All Listing or Literal Blocks of Document

In a previous post we learned about setting the value of options attribute to nowrap on listing and literal blocks, so the lines in the block are not wrapped. In the comments a user suggested another option to disable line wrapping for all listing and literal blocks in the document by using the document attribute prewrap. We must negate the document attribute, :prewrap!:, to disable all wrapping. If we place this document attribute at the top of our Asciidoctor document it is applied for the whole document. We can also place it at other places in the document to change the setting for all listing and literal blocks following the prewrap document attribute. To enable wrapping again we set :prewrap: (leaving out the exclamation mark).

In the following example we have markup with a listing, literal and example block and we use the document attribute :prewrap!: to disable the wrapping for the listing and literal blocks:

= Wrapping lines sample

// Disable wrapping in listing and literal blocks.
:prewrap!:

== Listing

[.groovy]
----
class GroovyHelloWorld {
    String sayHello(final String message = 'world') { // Set default argument value for message argument
        "Hello $message !"
     }
}
----

== Literal

....
class GroovyHelloWorld {
    String sayHello(final String message = 'world') { // Set default argument value for message argument
        "Hello $message !"
     }
}
....

== Example

====
// We use spacing to mimic a code block.
class GroovyHelloWorld { +
{nbsp}{nbsp}{nbsp}{nbsp}String sayHello(final String message = 'world') { // Set default argument value for message argument +
{nbsp}{nbsp}{nbsp}{nbsp}{nbsp}{nbsp}{nbsp}{nbsp}"Hello $message !" +
{nbsp}{nbsp}{nbsp}{nbsp}} +
}
====

When we create HTML from this markup we get the following output:

The code in the listing and literal blocks is now not wrapped, but continues on the same line.

Written with Asciidoctor 2.0.2.

March 28, 2019

Awesome Asciidoctor: Collapsible Content

Since Asciidoctor 2.0.0 we can add the collapsible option to an example block. When the markup is generated to HTML we get a HTML details and summary section. The content of the example block is collapsed (default behaviour because it is in a details section) and a clickable text is available to open the collapsed block (the summary section), so we can see the actual content. The text we can click on is by default Details, but we can change that by setting the title of the example block. Then the title is used as the text to click on to open the collapsed content.

The following example markup has two collapsible blocks with and without a title:

= Sample
:nofooter:
:source-highlighter: highlightjs

== Collapse

[%collapsible]
====
Example block turns into collapsible summary/details.
====

== Exercise

. Implement the `Application` class with `main(String[] args)` method.

=== Solution

// The title attribute is used as
// clickable text to open the example block.
.Click to see solution
[%collapsible]
====
[,java]
----
package mrhaki;

import io.micronaut.runtime.Micronaut;

public class Application {

    public static void main(String[] args) {
        Micronaut.run(Application.class);
    }
}
----
====

When we generate this markup to HTML we get the following result:

And when we expand the collapsible content we see:

Written with Asciidoctor 2.0.2.

October 16, 2017

Awesome Asciidoctor: Use Only Block As List Item

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:

= Simple steps

We need to type the following commands to generated a HTML version
of our Asciidoctor source document:

. {blank}
+
----
$ asciidoctor sample.adoc
$
----
. {blank}
+
----
$ ls
sample.adoc      sample.html
$
----
. {blank}
+
----
$ open sample.html
$
----

When we generate a HTML version we get the following result:

Written with Asciidoctor 1.5.6.1.

October 12, 2017

Awesome Asciidoctor: Prevent Transformation of URL to Hyperlink

Normally if we type an URL in Asciidoctor that starts with a scheme Asciidoctor knows about, the URL is turned into a hyperlink. The following schemes are recognized by Asciidoctor:

  • http
  • https
  • ftp
  • irc
  • mailto
  • email@email.com

If we want to keep our URL as text and not a link we must prepend our URL with a backslash (\). This way Asciidoctor will not transform the URL to a hyperlink in our output.

In the following example we have URL that is transformed to a link, followed by the same URL but with a backslash (\) before it, that is not transformed:

== URL not as a link

The URL http://www.asciidoctor.org  should
be turned into a hyperlink.

But now the URL \http://www.asciidoctor.org should
just be text and not a hyperlink.

If we transform our document to HTML with Asciidoctor we get the following result:

Written with Asciidoctor 1.5.6.1.

October 3, 2017

Awesome Asciidoctor: Using Paragraphs in Lists With List Item Continuation

When we write a list in Asciidoctor we can simply create a list item by starting the line with a dot (.). To create a another list item we simply start a new line with a dot (.). But what if we want to add a list item with multiple paragraphs, or text and a source code block element. We can use the list item continuation (+) to indicate to Asciidoctor we want to keep these together for a single list item.

In the following example we have a list in Asciidoctor markup. The second list item has multiple paragraphs , the third item has an extra admonition block and the fourth item contains a source code block:

:icons: font

== List continuation

When we have a list item that has for example multiple paragraphs,
we can use Asciidoctor's list continuation feature. We place a
`+` symbol between the paragraphs to indicate the paragraphs
belong to a single list item.

=== Sample list

. A very simple first item
. This item consists of two paragraphs.
+
By adding the `+` symbol we indicate this
paragraph also belongs to the second list item.
. We can even add for example an admonition.
+
TIP: Did you know Asciidoctor is awesome?
. A small code example:
+
[source,groovy]
----
println 'Groovy rocks!'
----
. Let's end with a simple list item.

Let's generate this Asciidoctor markup to HTML and we see the following result:

We see how the extra paragraph, admonition and source code are part of a single list item.

Written with Asciidoctor 1.5.6.1.

April 26, 2017

Awesome Asciidoctor: Nested Tables

Defining tables in Asciidoctor is very easy. The start and end of the table are defined by |===. But if we want to add a new table to a table cell we cannot use the same syntax. To define a nested table we must replace the | separator with !. So instead of |=== to indicate the table boundaries we use !===. Also the cell separators are now ! instead of |. Finally we must make sure the table cell or column supports Asciidoc markup, so the table is properly created. We must configure the cell or column with a so the nested table is created.

In the following example Asciidoctor markup we have a simple table with a nested table in the second column and row. Notice we can still apply all table configuration to the nested table as well:

= Tables

== Nested tables

To nest a table in a table we must
use `!` as table separator instead of `|`.
Also the type of the column or cell
must be set to `a` so Asciidoc markup
is processed.

[cols="1,2a"]
|===
| Col 1 | Col 2

| Cell 1.1
| Cell 1.2

| Cell 2.1
| Cell 2.2

[cols="2,1"]
!===
! Col1 ! Col2

! C11
! C12

!===

|===

When we run Asciidoctor to create HTML for this markup we get the following result:

Written with Asciidoctor 1.5.5.

January 2, 2017

Awesome Asciidoctor: Using Filename Starting With Dot As Block Title

Adding a block title in Asciidoctor is easily done by adding a line at the top of the block that starts with a dot (.). The text following the dot is then used as the title of the block. But if the text of the title itself starts with a dot (.) Asciidoctor get's confused. For example if we want to use a filename that starts with a dot (.filename) we must use different syntax to set the block title with the filename.

In the next Ascciidoc markup sample we use different ways to set the block title for a code block with a filename that starts with a dot. First we use the title attribute for the block. Another solution is to use the Unicode value for the dot. Next we enclose the filename in back ticks (`) which also formats the filename with a monotype font. We can also separate the first dot with the dotted filename with the document attribute {blank}. Also we can define the dot as document attribute and use it in the title. And finally we can define the filename via a document attribute and reference the document attribute in the block title:

= Filenames starting with dot (.)

Several samples showing how to set block title when title starts with dot (`.`).

Code block title is filename that starts with dot (`.`), which confuses the parser:

[source,json]
// Title cannot be parsed correctly
// because of the 2 dots.
..eslintrc
----
{
    "key": "value"
}
----

Using explicit title attribute:

// Instead of using . notation
// for block title, we use the
// explicit block attribute
// title definition.
[source,json,title='.eslintrc']
----
{
    "key": "value"
}
----

Use Unicode value for dot:

[source,json]
// Use hexadecimal Unicode replacement for
// starting dot (.) in filename.
.&#x002E;eslintrc
// (Or with decimals: .&#46;eslintrc)
----
{
    "key": "value"
}
----

Format filename as code:

[source,json]
// Put filename between back ticks (`)
// and title is recognized again and
// nicely formatted with monotype font.
.`.eslintrc`
----
{
    "key": "value"
}
----

Using `\{blank}` document attribute to separate
title dot and filename:

[source,json]
// Separate title and filename with
// {blank} document attribute.
.{blank}.eslintrc
----
{
    "key": "value"
}
----

Using document attribute to define dot and use with filename:

[source,json]
// Section title is also parsed correctly
// if we use a document attribute
// to reflect dot.
:dot: .
.{dot}eslintrc
----
{
    "key": "value"
}
----

Using document attribute to set filename:

[source,json]
// Section title is also parsed correctly
// if we use a document attribute
// with the filename.
:snippetFilename: .eslintrc
.{snippetFilename}
----
{
    "key": "value"
}
----

[source,json]
// We can re-use the same document attribute
// for other code sections.
:snippetFilename: .jslintrc
.{snippetFilename}
----
{
    "key": "value"
}
----

When we generate a HTML version of this markup we get the following result:

Written with Asciidoctor 1.5.4

October 4, 2016

Awesome Asciidoctor: Source Syntax Highlighting With Prism

Asciidoctor has built-in support for a couple of source syntax highlighting libraries like Coderay, Pygments, highlight.js and prettify. In this post we learn how to use the Javascript library Prism to do the syntax highlighting for our source blocks. Because Prism is a Javascript library we must remember this only works for the HTML backend of Asciidoctor.

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!"
        }
    }
}
----

Each source listing is transformed to HTML with the following structure:

<pre class="highlight"><code class="language-{language}" data-lang="{language}">
{code}
</code></pre>

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>

We also create the file docinfo-footer.html to reference prism.js:

<script src="prism.js"></script>

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. Let's see the result in a web browser:

Written with Asciidoctor 1.5.4.

September 26, 2016

Awesome Asciidoctor: Trick To Use Caption Labels And Numbers In References

In Asciidoctor we can add an anchor with an ID to a section or title and then reference it in a link. The title of the section is used as link text. We can alter that when we define the 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 Ratpack 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 Groovy Ratpack application']
----
package com.mrhaki

import static ratpack.groovy.Groovy.ratpack

ratpack {
    handlers {
        get {
            render "Hello World!"
        }
    }
}
----

// In these paragraphs we create a link to the sections with
// id's SimpleJavaApp and SimpleGroovyApp. The text of the links
// will be Listing 1. Simple Java Ratpack application and
// Listing 2. Simple Groovy Ratpack application.
As we can see in <<SimpleJavaApp>> the code is simple. The configuration
of the Ratpack application is done using a series of methods.

With the Groovy code in <<SimpleGroovyApp>> we can use a DSL to define
the application. This results in even better readable code.

When we generate a HTML version of this markup we get the following result:

Written with Asciidoctor 1.5.4.

Awesome Asciidoctor: Use Captions For Listing Blocks

Asciidoctor has some built-in attributes to work with captions for certain content blocks. For example the table-section attribute defines the caption label (by default Table) that is prefixed to a counter for all tables in the document. When we transform our markup Asciidoctor will insert the text Table followed by the table number. By default the caption for listing blocks is disabled, but we can easily enable it with the listing-caption attribute.

In the following markup we enable the caption for listing blocks and set the value to Listing. This will add the text Listing followed by the listing section counter to the output.

= Code examples
// Enable numbered captions
// for listing blocks.
// We define the constant Listing
// as a caption value. This will be
// followed by a counter.
:listing-caption: Listing

== Creating an application

To create a simple Ratpack application we write
the following code:

.Simple Java Ratpack application
[source,java]
----
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!"
        }
    }
}
----

When we generate the HTML for this markup we see the caption for the two listing blocks:

To disable the listing captions we must negate the document attribute: :!listing-caption:.

Written with Asciidoctor 1.5.4.

Awesome Asciidoctor: Customize the Figure Captions

With Asciidoctor we can use images in our documents with the image directive. When the document is converted each image gets a caption. By default the caption label is Figure followed a number for the position of the image in the document. So the first image has a caption Figure 1.. If we add a block title (text prefixed with a .) to the image then that text 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[]

When we transform this markup to HTML we get the following output:


Written with Asciidoctor 1.5.4.

September 16, 2016

Awesome Asciidoctor: Use Counters in Markup

In Asciidoctor we can create a document attribute as a counter attribute. The attribute is automatically incremented each time we use it in our markup. We can choose to use numbers or characters. Only latin characters from 'a' to 'z' or 'A' to 'Z' are allowed. By default the counter will start at 1, but we can define another start value when we use the counter attribute for the first time.

To define a counter attribute we must prefix the attribute name with counter:. Each time we use this syntax with the counter: prefix the value is incremented and displayed. To only display the current value, without incrementing, we simply refer to the document attribute without the counter: prefix. For example if we want to add a counter attribute with the name steps we would use the following markup in Asciidoctor: {counter:steps}.

To increment the counter without display it we must replace counter: with counter2:. The value of the attribute is incremented but not displayed. So to increment our steps attribute we would use the syntax: {counter2:steps}. To get the current value without incrementing we simply use {steps}.

To start with a different value than 1 we can suffix the attribute name with :<:start-value>. Let's look at how we would create the steps counter attribute starting from 100: {counter:steps:100}. To have a counter with letters we define the start value as a letter from which we want to count: {counter:steps:A}.

In the following example markup we see different usages of the counter support in Asciidoctor:

== Counters

In Asciidoctor we can use counters. To use them
we ({counter:usage}) use a document attribute
prefixed with `counter:` and ({counter:usage}) use it again
to increment the counter.

Instead of numbers we can use characters. To use them
we ({counter:usageChar:A}) use a document attribute
prefixed with `counter:` and suffix `:A` and ({counter:usageChar}) use it again
to increment the counter.

=== Current value

Current value for a counter can be obtained by just referring to document attribute name. 
Value counter is *{usage}*.

=== Increment

{counter2:usage} We can also increment the counter without displaying the value. 
On the next increment the value is *{counter:usage}*.

=== Start at

To start at another number than 1 we can specify the starting counter value as 
a suffix to the counter attribute as `:<start>`.

{counter:sample:10}. do something followed by {counter:sample}. something else.

When we transform this to HTML with Asciidoctor we get the following result:


Written with Asciidoctor 1.5.4.

September 15, 2016

Awesome Asciidoctor: Replacements For Text To Symbols

With Asciidoctor we can use text to describe a symbol in our markup. The text is automatically transformed to a Unicode replacement. For example if we use the text (C) it is converted to &#169; which is the copyright symbol: ©.

In the following sample we see all the symbol replacements:

Written with Asciidoctor 1.5.2.