Calmdevelopment

Keep calm and code. Or do some other stuff.


A little example how to handle custom dates with jbake, using groovy MarkupTemplateEngine, to generate a valid sitemap and atom feed.

Show the world you updated a post

Lets say you wrote a blog post a while ago, maybe September 2016, but you want to update a detail you have missed.

Introduce a new Property

So you open your post update it and add a new jbake Property to your header.

Frank Becker
2016-09-21
:jbake-updated: 16.10.2016 (1)
:jbake-type: post
:jbake-language: en
:jbake-tags: jbake,asciidoctor,asciidoctor-diagram
:jbake-status: published
:jbake-description: How to use asciidoctor-diagram with jbake
:jbake-users-question: https://groups.google.com/d/msg/jbake-user/qjS_ojssKF0/hz60cvI-EgAJ
:bintray-gradle-plugin: https://bintray.com/calmdev/gradle-plugins/jbake-gradle-plugin
:github-pull: https://github.com/jbake-org/jbake/pull/269
:asciidoctor-diagram: https://github.com/asciidoctor/asciidoctor-diagram
:jbake-gradle-plugin: https://github.com/jbake-org/jbake-gradle-plugin
1 A Property called updated with a date String dd.MM.yyyy

Use the property to render the date

Extend your template to show when the post was updated.

A subtemplate representing a post (src/jbake/templates/bricks/post-brick.tpl)
import java.text.SimpleDateFormat

div(class:"row"){
    div(class:"small-12 middle-12 large-12 columns"){
        article(class:"wrap"){
            header{
                div(class:"row"){
                    div(class:"small-3 medium-1 large-1 columns"){
                        include template: 'bricks/date.tpl'
                    }

                    div(class:"small-9 medium-11 large-11 columns"){
                        include template: 'bricks/post-title.tpl'
                    }
                }
                div(class:'row') {
                    div(class:"small-offset-3 medium-offset-1 large-offset-1 small-6 medium-6 large-6 columns") {
                        model.put('tagList',post.tags)
                        include template: 'bricks/tags.tpl'
                    }
                    div(class:"small-3 medium-3 large-3 columns text-right") {
                        if( post.updated ){ (1)
                            strong('Updated: ')
                            yield post.updated
                        }
                    }
                }
                hr()
            }

            div(class:"row"){
                div(class:"columns"){
                    yieldUnescaped post.body
                }
            }
        }
    }
}
1 Render updated property only if set in the post

Add format Strings to your configuration

As you want to render the date in different formats I recommend to add the format strings to your configuration.

That way you can reuse them in different templates.

Adding format strings to the gradle configuration
jbake{
  version = "2.5.1"
  asciidoctorjVersion = "1.5.4.1"
  configuration['blog.title'] = "calmdevelopment"
  configuration['blog.description'] = "'A personal Blog. Mostly about tech stuff. groovy, gradle, asciidoctor, jbake and other interesting stuff that crosses my path...'"
  configuration['db.store'] = "local"
  configuration['db.path']= "build/cache"
  configuration['site.host'] = config.server.url
  configuration['render.tags'] = true
  configuration['site.contextPath'] = config.server.contextPath
  configuration['foundation.version'] = foundationVersion
  configuration['twitter.user'] = "@knarfancho"
  configuration['asciidoctor.option.requires'] = "asciidoctor-diagram"
  configuration['asciidoctor.attributes'] = [
    "sourceDir=${projectDir}",
    "imagesdir=${config.server.contextPath}img",
    "imagesoutdir=${bake.input}/assets/img",
    "source-highlighter=highlight.js",
    "icons=font"
  ]
  configuration['feed.timestamp'] = "yyyy-MM-dd\'T\'HH:mm:ss\'Z\'" (1)
  configuration['sitemap.format'] = 'yyyy-MM-dd' (2)
  configuration['updated.format'] = "dd.MM.yyyy" (3)
}
1 A date format for atom feeds
2 A date format for the sitemap
3 The date format I’m using for the updated property

Update sitemap template

Change the sitemap template to use the updated property to set the last modification date of your post.

The sitemap template (src/jbake/templates/sitemap.tpl)
import java.text.SimpleDateFormat (1)

xmlDeclaration()
urlset( xmlns:'http://www.sitemaps.org/schemas/sitemap/0.9'){
    published_content.each {content ->
        url {

            Date dateUpdated (2)
            if ( content.updated ) { (3)
                dateUpdated = new SimpleDateFormat(config.updated_format).parse(content.updated) (4)
            }

    	    loc("${config.site_host}${config.site_contextPath}${content.uri}")
    	    lastmod("${dateUpdated?dateUpdated.format(config.sitemap_format):content.date.format(config.sitemap_format)}") (5)
        }
    }
}
1 import SimpleDateFormat to format and parse a date string
2 declare a Date variable
3 try to convert the date string if the updated property is set
4 parse the updated date string and format with updated.format from configuration
5 ternary condition to use dateUpdated or the post date to format with sitemap.format from configuration

Update feed template

Now do the same for the feed template.

The sitemap template (src/jbake/templates/feed.tpl)
import java.text.SimpleDateFormat (1)

yieldUnescaped "<?xml version='1.0' encoding='UTF-8'?>"
newLine()
feed(xmlns:"http://www.w3.org/2005/Atom"){

    title("${config.blog_title}")
    newLine()
    link(href:"${config.site_host}${config.site_contextPath}")
    newLine()
    link(rel:"self", type:"application/atom+xml", href:"${config.site_host}${config.site_contextPath}${config.feed_file}")
    newLine()
    subtitle("${config.blog_subtitle?:""}")
    newLine()
    updated("${published_date.format(config.feed_format)}")
    newLine()
    id("tag:${config.feed_id},${published_date.format('yyyy:MM')}")
    newLine()
    published_posts.each {post ->
        entry{
          title("${post.title}")
          newLine()
          author{
              name("${post.author}")
          }
          newLine()
          link(href:"${config.site_host}${config.site_contextPath}${post.uri}")
          newLine()

          Date dateUpdated (2)
          if ( post.updated ) { (3)
              dateUpdated = new SimpleDateFormat(config.updated_format).parse(post.updated) (4)
          }

          updated("${dateUpdated?dateUpdated.format(config.feed_format):post.date.format(config.feed_format)}") (5)
          newLine()
          id("${config.site_host}${config.site_contextPath}${post.uri}")
          newLine()
          post.tags.each { tag ->
            category(term:"${tag}")
            newLine()
          }
          content(type:"html") {
            yield post.body
          }
        }
        newLine()
    }
}
1 import SimpleDateFormat to format and parse a date string
2 declare a Date variable
3 try to convert the date string if the updated property is set
4 parse the updated date string and format with updated.format from configuration
5 ternary condition to use dateUpdated or the post date to format with feed.format from configuration

That’s it!

2014 - 2017 | Mixed with Foundation v6.2.3 | Baked with JBake v2.5.1