Groovy Goodness: Use Custom Template Class with MarkupTemplateEngine
Since Groovy 2.3 we can use the new MarkupTemplateEngine
to generate XML/HTML content. The engine compiles the template for better performance and optionally provides type checking on model attributes used in the template. We can configure the template engine to use a custom base template class instead of the default BaseTemplate
. In our custom template class we can add new methods that can be invoked from our template content.
Let's create a new base template class with an icon
method to output valid FontAwesome markup:
// File: FontAwesomeTemplate.groovy
package com.mrhaki.groovy.tmpl
import groovy.text.markup.*
import groovy.text.*
abstract class FontAwesomeTemplate extends BaseTemplate {
FontAwesomeTemplate(
final MarkupTemplateEngine templateEngine,
final Map model,
final Map<String,String> modelTypes,
final TemplateConfiguration configuration) {
super(templateEngine, model, modelTypes, configuration)
}
/**
* Generate FontAwesome markup.
*
* @param icon Name of the icon, will be prefixed with 'fa-'.
* @param attributes Optional extra attributes, will be added to markup
* and prefixed with 'fa-'.
* @return Span element with class attribute value for FontAwesome
*/
String icon(final String icon, final String[] attributes = []) {
// Prefix attribute names with fa-.
final faAttributes = attributes.collect { "fa-$it" }
// Create markup.
$//$
}
}
Now we can create a new MarkupTemplateEngine
and use our FontAwesomeTemplate
class as the base template. We assign our template class to the baseTemplateClass
property of TemplateConfiguration
:
import com.mrhaki.groovy.tmpl.*
import groovy.text.*
import groovy.text.markup.*
// Create configuration and set
// base template class to
// FontAwesomeTemplate.
TemplateConfiguration config = new TemplateConfiguration(
baseTemplateClass: FontAwesomeTemplate
)
// Create engine with configuration.
MarkupTemplateEngine engine = new MarkupTemplateEngine(config)
// Create template with text using
// the icon method.
Template template = engine.createTemplate('''
ul {
// Use the name of the icon as argument
// for the icon method.
li icon('cloud')
// Any extra arguments are assumed
// to be FontAwesome attributes.
li icon('pencil', 'large', 'rotate-90')
}
// If we want to use the icon method in between
// text we must use the ${stringOf notation}.
p "This is a ${stringOf {icon('home')}} home icon."
// Or use yieldUnescaped method.
p {
yield "This is a "
yieldUnescaped icon('cog')
yield " settings icon."
}
''')
// 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.
// (/ is the continuation character, so it is
// actually all one line)
def expected = $/\\
\\
\\
\\
\\
This is a home icon.
\\
This is a settings icon.
\\
/$
assert result == expected
Code written with Groovy 2.3.6.