Skip to content

Instantly share code, notes, and snippets.

@melix
Last active August 12, 2019 01:04
Show Gist options
  • Save melix/240e961b6cce70d37592 to your computer and use it in GitHub Desktop.
Save melix/240e961b6cce70d37592 to your computer and use it in GitHub Desktop.
An example of improved template composition using fragments and the MarkupTemplateEngine
html {
head {
title(title)
}
body {
content()
}
}
import groovy.text.Template
import groovy.text.markup.BaseTemplate
import groovy.text.markup.MarkupTemplateEngine
import groovy.text.markup.TemplateConfiguration
abstract class LayoutAwareTemplate extends BaseTemplate {
private final MarkupTemplateEngine engine
private final Map<String, Template> cachedFragments
private final Map<String, String> modelTypes
LayoutAwareTemplate(
final MarkupTemplateEngine templateEngine,
final Map model,
final Map<String, String> modelTypes,
final TemplateConfiguration configuration) {
super(templateEngine, model, modelTypes, configuration)
this.cachedFragments = [:].withDefault { String tpl ->
templateEngine.createTemplate(new StringReader(tpl))
}
this.engine = templateEngine
this.modelTypes = modelTypes
}
Object fragment(Map model, String tpl) {
// todo: merge models or not?
cachedFragments[tpl].make(model).writeTo(out)
this
}
Object layout(Map model, String templateName) {
// todo: merge models or not?
URL resource = engine.resolveTemplate(templateName)
engine.createTypeCheckedModelTemplate(resource, modelTypes).make(model).writeTo(out)
this
}
Closure contents(Closure cl) {
{ args -> cl(args)
''
}
}
}
void fragmentExample() {
def config = new TemplateConfiguration()
config.baseTemplateClass = LayoutAwareTemplate
MarkupTemplateEngine engine = new MarkupTemplateEngine(config)
def template = engine.createTemplate '''
html {
body {
[Index: 'index.html',
Page1: 'page.html',
Page2: 'page2.html'].each { k,v ->
fragment(page:v,title:k, 'a(href:page, title)')
}
}
}
'''
StringWriter rendered = new StringWriter()
template.make().writeTo(rendered)
assert rendered.toString() == "<html><body><a href='index.html'>Index</a><a href='page.html'>Page1</a><a href='page2.html'>Page2</a></body></html>"
}
void layoutExample() {
def config = new TemplateConfiguration()
config.baseTemplateClass = LayoutAwareTemplate
MarkupTemplateEngine engine = new MarkupTemplateEngine(config)
def template = engine.createTemplate '''
layout 'body.tpl', content: contents {
div {
p('This is the body')
}
}, title: 'This is the title'
'''
StringWriter rendered = new StringWriter()
template.make().writeTo(rendered)
assert rendered.toString() == "<html><head><title>This is the title</title></head><body><div><p>This is the body</p></body></div></html>"
}
layoutExample()
@melix
Copy link
Author

melix commented May 15, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment