package nl.gertontenham.magnolia.templating.servlets; import com.github.jknack.handlebars.*; import com.github.jknack.handlebars.helper.PrecompileHelper; import com.github.jknack.handlebars.io.ClassPathTemplateLoader; import com.github.jknack.handlebars.io.TemplateLoader; import com.google.common.net.HttpHeaders; import freemarker.template.TemplateException; import info.magnolia.freemarker.FreemarkerHelper; import info.magnolia.i18nsystem.SimpleTranslator; import info.magnolia.module.resources.ResourceLinker; import info.magnolia.resourceloader.Resource; import nl.gertontenham.magnolia.templating.utils.HandlebarsPrecompileHelper; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.StringWriter; import java.util.HashMap; import java.util.Map; /** * Servlet endpoint for compiled handlebars templates pre-processed by Freemarker engine. */ public class HandlebarsTemplatesResourcesServlet extends FreemarkerTemplatesResourcesServlet { private static final Logger log = LoggerFactory.getLogger(HandlebarsTemplatesResourcesServlet.class); //private final FreemarkerHelper fmHelper; protected String suffix; protected String jswrapper; @Inject public HandlebarsTemplatesResourcesServlet(FreemarkerHelper fmHelper, ResourceLinker linker, SimpleTranslator simpleTranslator) { super(fmHelper, linker, simpleTranslator); //this.fmHelper = fmHelper; } @Override public void init() throws ServletException { super.init(); suffix = StringUtils.defaultIfEmpty(getInitParameter("suffix"), ".hbs"); jswrapper = StringUtils.defaultIfEmpty(getInitParameter("jswrapper"), "anonymous"); } @Override public String getResourcePathFromRequest(HttpServletRequest request) { return StringUtils.substringBeforeLast(super.getResourcePathFromRequest(request), ".") + suffix; } @Override public void serveResource(HttpServletResponse response, Resource resource) throws IOException { StringWriter freemarkerWriter = new StringWriter(); TemplateLoader loader = new ClassPathTemplateLoader(resourcesRoot, suffix); Handlebars handlebars = new Handlebars(loader); response.setDateHeader(HttpHeaders.LAST_MODIFIED, resource.getLastModified()); try { // Fetch template through Freemarker engine (server side parsing) renderFreemarker(freemarkerWriter, resource); // Compile freemarker parsed string as Inline handlebars template Template template = handlebars.compileInline(freemarkerWriter.toString()); freemarkerWriter.flush(); Context nullContext = Context.newContext(null); // Set Javascript wrapper: "none", "anonymous" and "amd" Map<String, Object> hash = new HashMap<String, Object>(); hash.put("wrapper", StringUtils.lowerCase(jswrapper)); String js = HandlebarsPrecompileHelper.INSTANCE.applyWithCurrentTemplate(requestedResourcePath, new Options .Builder(handlebars, PrecompileHelper.NAME, TagType.VAR, nullContext, template) .setHash(hash) .build()).toString(); response.setContentType("text/javascript"); response.getWriter().print(js); } catch (TemplateException e) { log.error("Error during rendering freemarker template", e); } catch (IOException e) { if (!response.isCommitted()) { response.sendError(HttpServletResponse.SC_NOT_FOUND); } } finally { freemarkerWriter.close(); } } }