Last active
August 12, 2019 01:04
-
-
Save melix/240e961b6cce70d37592 to your computer and use it in GitHub Desktop.
An example of improved template composition using fragments and the MarkupTemplateEngine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html { | |
head { | |
title(title) | |
} | |
body { | |
content() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See also groovy/groovy-core#418