My website EmmanuelRosa.com is written using the Grain framework. While writing articles for my site I discovered that the process of writing one article often leads to the need to write other related articles. Ideally, these articles would be linked together, making it easy to navigate from one to the other. This is especially important in articles which are part of a series. This got me thinking about ways I can code something now and have it take effect in the future. And so it was decided: I wanted a way to create a link into the future.

The future article

The idea was simple. Upon determining that I would likely create a related article in the future, I'd add a special kind of link pointing to it. When generating the website, Grain would check if the linked-to article exists. If so, it would render some content. Otherwise it would render alternative content.

This special type of link is implemented with a taglib I named id.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.emmanuelrosa.grain.taglibs

import com.sysgears.grain.taglib.GrainTagLib
import groovy.util.logging.Slf4j

/**
 * A Grain taglib for tags that should be included in Grain. 
 */
@Slf4j
class CustomGrainTagLib {
    private GrainTagLib taglib

    public CustomGrainTagLib(GrainTagLib taglib) {
        this.taglib = taglib
    }

    /**
     * Returns the url of the (first) resource with the specified id.
     *
     * If a Closure is provided and the url is found, the Closure
     * is called with the url as its parameter and the the return value
     * of the Closure is returned. If a Closure is not provided 
     * and the url is found, the url is returned.
     *
     * If the url is not found null is returned.
     * 
     * @param id REQUIRED of the resource to return.
     * @param closure OPTIONAL called if the url is found
     */
    def id = { String id, Closure closure = null ->
        if(!id) throw new IllegalArgumentException('Missing required resource ID')

        def url = taglib.site.resources.find { it.id == id }?.url

        if(!url) log.warn "No resource found for id: $id"
        if(url) url = taglib.link(url)
        if(url && closure) closure(url)
        else url
    }
}

The id taglib expects an identifier and an optional Closure. When invoked, it searches for a page with the specified id in the page's YAML header. If a matching page is not found, the taglib returns null. Otherwise it will either return the URL to the page, or call the provided Closure with the URL.

An example where I've used this taglib is in my recent article The State of Things. In it I have this closing paragraph:

1
2
3
4
I think the run-time state machine is rather neat. Particularly the fact that it can easily be reused to implement any 
number of state machines. However, there's one thing that bugs me about it: building one is rather yucky. 
<%= id('state-machine-builder') { url -> "Check out [part 2] ($url) " } ?: 'Tune in next week ' %> to see a better way 
to *build* run-time state machines.

Note that the actual content is all on one line, unlike the rendering shown above.

The last sentence changes depending on whether an article with the id state-machine-builder exists. Lets take a closer look at just the Groovy code:

1
id('state-machine-builder') {url -> "Check out [part 2] ($url) " } ?: 'Tune in next week '

When the state machine builder page is found the Closure is called, which then returns Markdown content with a link to the page. Otherwise it returns a simple: Tune in next week. In practice this means that upon publishing the follow-up article, the original article gets rendered with a link to the new article. I don't have to remember to go back and add the link!

Don't forget to publish

It's common for me to draft multiple articles simultaneously. Not literally simultaneously; you know what I mean. Obviously this makes it quite possible to accidentally forget to publish an article. Grain blog posts contain a published YAML attribute. Usually this attribute is treated as a Boolean; the article is published when set to true. And so it was, until I got my hands on it:

1
2
3
4
5
6
7
8
9
10
11
12
13
private def filterPublished = { Map it ->
    if(site.show_unpublished) {
        it
    } else if(it.published instanceof String) {
        try {
            Date.parse(site.datetime_format, it.published) <= currentDate ? it : null
        } catch (java.text.ParseException e) { 
            null 
        }
    } else {
        it.published != false ? it : null
    }
}

I modified the ResourceMapper to accept a String-formatted date so that articles are published once the publication date has arrived.

1
2
3
4
5
6
7
8
9
10
---
layout: post
title: "Not Having to Remember"
description: There's no need to remind yourself to do something when you can code for it right now. 
date: "2015-12-21 19:24"
author:
categories: []
comments: true
published: "2016-01-01 00:00"
---

It's time-sensitive

As I began publishing articles on my newsletter, I learned that among other rendering anomalies, my Graphviz and PlantUML diagrams do not render properly. I'm using a taglib to process the diagram's source code and render it as SVG content. Apparently email clients don't know what to do with SVG images. So I added a temporary message to the page new subscribers see:

1
2
3
4
5
6
7
8
<% if(Date.parse(site.datetime_format, "2016-03-01 00:00") >= new Date()) { %>
### For what it's worth

*You'll notice my articles render... well... not as sexy as I'd like, in your mail box. 
The diagrams are a particular problem because they are in SVG format; Web browsers are OK with this, but email clients are not.*

*But I'm working on it.*
<% } %>

I'm assuming that I'll have the issues resolved within a few months so I set it and forgot it.

That's all folks

When planning out my site, I knew from the start that I wanted something programmable. I wanted to write content as if I were coding. And I'm glad to say Grain has delivered. I look forward to coding more and remembering less.