Add script based templating support
This commit adds support for script based templating. Any templating
library running on top of a JSR-223 ScriptEngine that implements
Invocable like Nashorn or JRuby could be used.
For example, in order to render Mustache templates thanks to the Nashorn
Javascript engine provided with Java 8+, you should declare the following
configuration:
@Configuration
@EnableWebMvc
public class MustacheConfig extends WebMvcConfigurerAdapter {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.scriptTemplate();
}
@Bean
public ScriptTemplateConfigurer configurer() {
ScriptTemplateConfigurer configurer = new ScriptTemplateConfigurer();
configurer.setEngineName("nashorn");
configurer.setScripts("mustache.js");
configurer.setRenderObject("Mustache");
configurer.setRenderFunction("render");
return configurer;
}
}
The XML counterpart is:
<beans>
<mvc:annotation-driven />
<mvc:view-resolvers>
<mvc:script-template />
</mvc:view-resolvers>
<mvc:script-template-configurer engine-name="nashorn" render-object="Mustache" render-function="render">
<mvc:script location="mustache.js" />
</mvc:script-template-configurer>
</beans>
Tested with:
- Handlebars running on Nashorn
- Mustache running on Nashorn
- React running on Nashorn
- EJS running on Nashorn
- ERB running on JRuby
- String templates running on Jython
Issue: SPR-12266
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
<mvc:freemarker />
|
||||
<mvc:velocity />
|
||||
<mvc:groovy />
|
||||
<mvc:script-template />
|
||||
</mvc:view-resolvers>
|
||||
|
||||
<mvc:tiles-configurer check-refresh="true">
|
||||
@@ -40,5 +41,7 @@
|
||||
|
||||
<mvc:groovy-configurer />
|
||||
|
||||
<mvc:script-template-configurer engine-name="nashorn" render-function="render"/>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<mvc:freemarker prefix="freemarker-" suffix=".freemarker" view-names="my*,*Report" />
|
||||
<mvc:velocity cache-views="false" />
|
||||
<mvc:groovy />
|
||||
<mvc:script-template />
|
||||
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" />
|
||||
<ref bean="customResolver" />
|
||||
</mvc:view-resolvers>
|
||||
@@ -33,5 +34,9 @@
|
||||
|
||||
<mvc:groovy-configurer resource-loader-path="/test" cache-templates="false" auto-indent="true" />
|
||||
|
||||
<mvc:script-template-configurer engine-name="nashorn" render-object="Mustache" render-function="render" charset="ISO-8859-1" resource-loader-path="classpath:">
|
||||
<mvc:script location="/META-INF/resources/webjars/mustachejs/0.8.2/mustache.js" />
|
||||
</mvc:script-template-configurer>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
require 'erb'
|
||||
require 'ostruct'
|
||||
require 'java'
|
||||
|
||||
# Renders an ERB template against a hashmap of variables.
|
||||
# template should be a Java InputStream
|
||||
def render(template, variables)
|
||||
context = OpenStruct.new(variables).instance_eval do
|
||||
variables.each do |k, v|
|
||||
instance_variable_set(k, v) if k[0] == '@'
|
||||
end
|
||||
|
||||
def partial(partial_name, options={})
|
||||
new_variables = marshal_dump.merge(options[:locals] || {})
|
||||
Java::Pavo::ERB.render(partial_name, new_variables)
|
||||
end
|
||||
|
||||
binding
|
||||
end
|
||||
ERB.new(template).result(context);
|
||||
end
|
||||
@@ -0,0 +1 @@
|
||||
<html><head><title><%= title %></title></head><body><p><%= body %></p></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
var window = {};
|
||||
@@ -0,0 +1,5 @@
|
||||
// TODO Manage compiled template cache
|
||||
function render(template, model) {
|
||||
var compiledTemplate = Handlebars.compile(template);
|
||||
return compiledTemplate(model);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<html><head><title>{{title}}</title></head><body><p>{{body}}</p></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
<html><head><title>{{title}}</title></head><body><p>{{body}}</p></body></html>
|
||||
@@ -0,0 +1,5 @@
|
||||
from string import Template
|
||||
|
||||
def render(template, model):
|
||||
s = Template(template)
|
||||
return s.substitute(model)
|
||||
@@ -0,0 +1 @@
|
||||
<html><head><title>$title</title></head><body><p>$body</p></body></html>
|
||||
@@ -0,0 +1,5 @@
|
||||
var global = this;
|
||||
var console = {};
|
||||
console.debug = print;
|
||||
console.warn = print;
|
||||
console.log = print;
|
||||
@@ -0,0 +1,13 @@
|
||||
function render(template, model) {
|
||||
// Create a real Javascript Object from the model Map
|
||||
var data = {};
|
||||
for(var k in model) data[k]=model[k];
|
||||
var element = React.createElement(eval(template), data);
|
||||
// Should use React.renderToString in production
|
||||
return React.renderToStaticMarkup(element);
|
||||
}
|
||||
|
||||
function renderJsx(template, model) {
|
||||
var jsTemplate = JSXTransformer.transform(template).code;
|
||||
return render(jsTemplate, model);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
React.createClass({
|
||||
render: function() {
|
||||
return React.createElement("html", null, React.createElement("head", null, React.createElement("title", null, this.props.title)), React.createElement("body", null, React.createElement("p", null, this.props.body)));
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
React.createClass({
|
||||
render: function() {
|
||||
return <html><head><title>{this.props.title}</title></head><body><p>{this.props.body}</p></body></html>
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user