Loading...

Friday, August 15, 2014

Awesome Asciidoc: Changing the FontAwesome CSS Location

To use font icons from FontAwesome we set the document attribute icons with the value font. The default link to the CSS location is https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.1.0/css/font-awesome.min.css. We can change the location for the FontAwesome CSS with document attributes.

If we want to use a different CDN to serve the CSS we can set the document attribute iconfont-cdn and set the URI as a value:

:icons: font

// Set new URI for reference to FontAwesome CSS
:iconfont-cdn: //maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css

== Sample doc

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

In the generated HTML source we see the following link element:

...
<link rel="stylesheet" href="css/fontawesome-4.1.0.css">
...

Written with Asciidoctor 1.5.0.

Awesome Asciidoc: Change URI Scheme for Assets

When we define the document attribute icons with the value font the FontAwesome fonts are loaded in the generated HTML page. In the head section of the HTML document a link element to the FontAwesome CSS on https://cdnjs.cloudflare.com/ajax/libs is added. Also when we use the highlight.js or Prettify source highlighter a link to the Javascript files on the cdnjs.cloudflare.com server is generated. We can change the value of the scheme from https to http by setting the attribute asset-uri-scheme to http. Or we can leave out the scheme so a scheme-less URI is generated for the links. A scheme-less URI provides the benefit that the same protocol of the origin HTML page is used to get the CSS or Javascript files from the cdnjs.cloudflare.com server. Remember this might provide a problem if the HTML page is opened locally.

In the next sample Asciidoc markup we change the scheme to http:

:asset-uri-scheme: http
:icons:font

== Asset URI Scheme

Sample document.

In the generated HTML we see the new scheme value:

<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.1.0/css/font-awesome.min.css">

Now we leave the value of the asset-uri-scheme attribute empty:

:asset-uri-scheme: 
:icons:font

== Asset URI Scheme

Sample document.

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

Written with Asciidoctor 1.5.0.


Gradle Goodness: Suppress Progress Logging

Gradle has some sophisticated progress logging on the console. For example we can see how much percentage of the building process is done. The percentage value is updated on the same console line. The following snippet is a sample of such output > Building 0% > :dependencies > Resolving dependencies ':compile'. The information is updated on the same line, which is really nice. But sometimes we might need to run Gradle builds on a system that doesn't support this mechanism on the console or terminal, possibly an continuous integration server. To disable the progress logging we can set the environment variable TERM to the value dumb.

Written with Gradle 2.0.


Wednesday, August 13, 2014

Awesome Asciidoc: Adding Line Numbers to Source Code Listings

When we write technical documentation with Asciidoctor we can easily include source code listings. When we use the coderay or pygments source code highlighter we can also include line numbers. We must add the attribute linenums to the listing block in our markup. This attribute is used by the source highlighters to create and format the line numbers. We can specify that the line numbers must be generated in table mode or inline mode. When the line numbers are in table mode we can select the source code without the line numbers and copy it to the clipboard. If we use inline mode the line numbers are selectable and are copied together with the selected source code to the clipboard. To specify which mode we want to use for the line numbers we use the document attribute coderay-linenums-mode or pygments-linenums-mode depending on the source highlighter we use. We can use the values table (default) or inline.

= Source code listing

Code listings look cool with Asciidoctor and {source-highlighter}.

[source,groovy,linenums]
----
// File: User.groovy
class User {
    String username
}
----

[source,asciidoc,linenums]
----
# Hello world

Asciidoc(tor) is aweseome!
----

Let's generate HTML output from this markup and use different values for the source-highlighter and ...-linenums-mode attributes. First we use the Coderay source highlighter in table mode:

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:

Written with Asciidoctor 1.5.0.

Awesome Asciidoc: Changing Highlight.js Theme

Asciidoctor is a great tool for writing technical documentation. If we have source code in the Asciidoc markup we can set the document attribute source-highlighter to pigments, coderay, prettify and highlightjs. When we use highlight.js we can also add an extra document attribute highlightjs-theme with the value of a highlight.js theme. If we do not specify the highlightjs-theme the default theme github is used.

We use the following Asciidoc markup to see how the HTML output is when we transform the markup using the HTML backend:

:source-highlighter: highlightjs

= Source code listing

Code listings look cool with Asciidoctor and highlight.js with {highlightjs-theme} theme.

[source,groovy]
----
// File: User.groovy
class User {
    String username
}
----

[source,sql]
----
CREATE TABLE USER (
    ID INT NOT NULL,
    USERNAME VARCHAR(40) NOT NULL
);
----

The following screenshots show the result of applying different themes:

For a complete list of all available themes checkout highlight.js on Github.

If we use the Prettify source code highlighter we must use the prettify-theme document attribute.

Written with Asciidoctor 1.5.0.

Tuesday, August 12, 2014

Awesome Asciidoc: 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 don't see any of the comments, not even in the HTML source:

Written with Asciidoctor 1.5.0.

Awesome Asciidoc: Links Without URI Scheme

Since Asciidoctor 1.5.0 we can use the document attribute hide-uri-scheme to turn URLs into links, where the link text is displayed without the URI scheme. This can save typing when we simply want to add a URL without any special description.

In the next Asciidoc syntax we first define URLs without the hide-uri-scheme attribute, followed by URLs after the attribute is set:

Reference to http://www.mrhaki.com is 
turned into link +
`+<a href="http://www.mrhaki.com">http://www.mrhaki.com</a>+`.

To loose URI scheme we could write the link
as http://www.mrhaki.com[www.mrhaki.com]. Or we 
can use the new attribute `hide-uri-scheme` which is
added to Asciidoctor 1.5.0.

:hide-uri-scheme:

After applying the `hide-uri-scheme` attribute
the URI scheme is removed from the text in links.
So a reference to http://www.mrhaki.com is
turned into the link +
`+<a href="http://www.mrhaki.com">www.mrhaki.com</a>+`

This also works for other URI schemes like `file`.
For example 
file:///Users/mrhaki/file.txt is translated to +
`+<a href="file:///Users/mrhaki/file.txt">/Users/mrhaki/file.txt</a>+`.

When we generate output using the HTML backend we see the following output:

Written with Asciidoctor 1.5.0.

Grails Goodness Notebook Updated

Grails Goodness Notebook is updated with the following posts:

  • Using Bintray JCenter as Repository
  • Use Spring Java Configuration
  • Conditonally Load Beans in Java Configuration Based on Grails Environment
  • Using Converter Named Configurations with Default Renderers
  • Custom Controller Class with Resource Annotation
  • Change Response Formats in RestfulController
  • Enable Accept Header for User Agent Requests
  • Exception Methods in Controllers
  • Run Groovy Scripts in Grails Context
  • Using Aliases as Command Shortcuts
  • Generate Default .gitignore Or .hgignore File
  • Extending IntegrateWith Command

Monday, August 11, 2014

Groovy Goodness: Using Layouts with MarkupTemplateEngine

The MarkupTemplateEngine added in Groovy 2.3 is very powerful. We can define layout templates with common markup we want to be used in multiple other templates. In the layout template we define placeholders for variables and content blocks surrounded by shared markup. We define values for these variables and content blocks in the actual template. We even can choose to propagate model attributes from the template to the layout template.

Let's first create a layout template with the name main.tpl:

// File: main.tpl
html {
    head {
        // Use pageTitle layout property.
        title(pageTitle)
    }
    body {
        section(id: 'main') {
            // Render mainContents layout property.
            mainContents()
        }

        section(id: 'actions') {
            // Render actions layout property.
            actions()
        }

        footer {
            // A template is also Groovy code, we can
            // define new variables or methods.
            // pubDate should be set via original template
            // model.
            def generatedOn = pubDate ?: new Date()
            p("Generated on ${dateFormat(generatedOn)}")
        }
    }
}

def dateFormat(date) {
    date.format('dd-MM-yyyy')
}

Now we can write the template that uses this layout and create a result:

// File: LayoutTemplate.groovy
import groovy.text.*
import groovy.text.markup.*

// Create engine with configuration.
TemplateConfiguration config = new TemplateConfiguration()
MarkupTemplateEngine engine = new MarkupTemplateEngine(config)     

// Create template with layout reference
// and values for layout variables.
Template template = engine.createTemplate('''\
layout 'main.tpl', 
    pageTitle: 'Welcome',
    mainContents: contents {
        h1 'Home'
    },
    actions: contents {
        ul(class: 'actions') {
            ['Home', 'About'].each { li it }
        }
    }
''')    


// Render output for template.
Writer writer = new StringWriter()                          
Writable output = template.make([:])  
output.writeTo(writer)   
String result = writer.toString()

// This is what we would expect as a result.
def expected = $/\
<html><head><title>Welcome</title></head>\
<body>\
<section id='main'><h1>Home</h1></section>\
<section id='actions'><ul><li>Home</li><li>About</li></ul></section>\
<footer><p>Generated on 11-08-2014</p></footer>\
</body></html>\
/$

assert result == expected

Notice we can assign directly a value to a layout property (pageTitle) or we can use the contents method with a closure (mainContents and actions). The value of the contents method is assigned to the layout property when the template is generated. This is useful when the value of a layout property is a closure we don't want to evaluate immediately, but when the template is generated.

We didn't specify a value for the template model property pubDate. If we want to use this property on our layout template as well, we must specify an extra argument with the layout method. The second argument must be true to instruct the layout that model properties are propagated. The default value is false:

// File: LayoutTemplate.groovy
import groovy.text.*
import groovy.text.markup.*

// Create engine with configuration.
TemplateConfiguration config = new TemplateConfiguration()
MarkupTemplateEngine engine = new MarkupTemplateEngine(config)     

// Create template with layout reference
// and values for layout variables.
Template template = engine.createTemplate('''\
layout 'main.tpl', true,
    pageTitle: 'Welcome',
    mainContents: contents {
        h1 'Home'
    },
    actions: contents {
        ul(class: 'actions') {
            ['Home', 'About'].each { li it }
        }
    }
''')    


// Render output for template.
Writer writer = new StringWriter()                          
Writable output = template.make(pubDate: Date.parse('yyyyMMdd', '20140801'))  
//Writable output = template.make([:])  
output.writeTo(writer)   
String result = writer.toString()

// This is what we would expect as a result.
def expected = $/\
<html><head><title>Welcome</title></head>\
<body>\
<section id='main'><h1>Home</h1></section>\
<section id='actions'><ul><li>Home</li><li>About</li></ul></section>\
<footer><p>Generated on 01-08-2014</p></footer>\
</body></html>\
/$

assert result == expected

Code written with Groovy 2.3.6.

Gradle Goodness: Getting More Dependency Insight

In most of our projects we have dependencies on other code, like libraries or other projects. Gradle has a nice DSL to define dependencies. Dependencies are grouped in dependency configurations. These configuration can be created by ourselves or added via a plugin. Once we have defined our dependencies we get a nice overview of all dependencies in our project with the dependencies task. We can add the optional argument --configuration to only see dependencies for the given configuration. But we can even check for a specific dependency where it is used, any transitive dependencies and how the version is resolved.

In the following sample build we define a compile dependency on Spring Boot and SLF4J API. The SLF4J API is also a transitive dependency for the Spring Boot dependency, so we can see how the dependencyInsight tasks shows a version conflict.

apply plugin: 'java'

// Set Bintray JCenter as repository.
repositories.jcenter()

dependencies {
    // Set dependency for Spring Boot
    compile "org.springframework.boot:spring-boot-starter-web:1.1.5.RELEASE"
    
    // Set dependency for SLF4J with conflicting version.
    compile 'org.slf4j:slf4j-api:1.7.1'
}

Now let's run the dependencyInsight task for the dependency SLF4J API in the compile configuration:

$ gradle -q dependencyInsight --configuration compile --dependency slf4j-api
org.slf4j:slf4j-api:1.7.7 (conflict resolution)
+--- org.slf4j:jcl-over-slf4j:1.7.7
|    \--- org.springframework.boot:spring-boot-starter-logging:1.1.5.RELEASE
|         \--- org.springframework.boot:spring-boot-starter:1.1.5.RELEASE
|              \--- org.springframework.boot:spring-boot-starter-web:1.1.5.RELEASE
|                   \--- compile
+--- org.slf4j:jul-to-slf4j:1.7.7
|    \--- org.springframework.boot:spring-boot-starter-logging:1.1.5.RELEASE (*)
\--- org.slf4j:log4j-over-slf4j:1.7.7
     \--- org.springframework.boot:spring-boot-starter-logging:1.1.5.RELEASE (*)

org.slf4j:slf4j-api:1.7.1 -> 1.7.7
\--- compile

org.slf4j:slf4j-api:1.7.6 -> 1.7.7
\--- ch.qos.logback:logback-classic:1.1.2
     \--- org.springframework.boot:spring-boot-starter-logging:1.1.5.RELEASE
          \--- org.springframework.boot:spring-boot-starter:1.1.5.RELEASE
               \--- org.springframework.boot:spring-boot-starter-web:1.1.5.RELEASE
                    \--- compile

(*) - dependencies omitted (listed previously)

In the output we can see slf4j-api is referenced three times, once as a transitive dependency for jcl-over-slf4j, jul-to-slf4j and log4j-over-slf4j, once as transitive dependency for logback-classic and once as a direct dependency for the compile configuration. We also see the version is bumped to 1.7.7 where necessary, because the transitive dependency of jcl-over-slf4j defines the newest version.

The value we use for the --dependency option is used to do partial matching in the group, name or version properties of the dependencies. For example to see an insight in all dependencies with logging we can invoke $ gradle dependencyInsight --dependency logging.

We can also get an HTML report page with an overview of all dependencies. To get dependency insight we must click on the desired dependency from the HTML page and we get a similar output as via the command-line. First we must add the project-report plugin to our project. Next we invoke the dependencyReport task. When the task is finished we can open build/reports/project/dependencies/index.html in our web browser. When we navigate to the compile configuration and click on the slf4j-api dependency we get the following output:

Written with Gradle 2.0.