com.github.jknack.handlebars.maven.PrecompilePlugin Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of handlebars-maven-plugin Show documentation
Show all versions of handlebars-maven-plugin Show documentation
Compile Handlebars templates to JavaScript
/**
* Copyright (c) 2012-2015 Edgar Espina
*
* This file is part of Handlebars.java.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This copy of Woodstox XML processor is licensed under the
* Apache (Software) License, version 2.0 ("the License").
* See the License for details about distribution rights, and the
* specific rights regarding derivate works.
*
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/
*
* A copy is also included in the downloadable source code package
* containing Woodstox, in file "ASL2.0", under the same directory
* as this file.
*/
package com.github.jknack.handlebars.maven;
import static org.apache.commons.lang3.StringUtils.join;
import static org.apache.commons.lang3.Validate.notNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import com.github.jknack.handlebars.Context;
import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Helper;
import com.github.jknack.handlebars.HelperRegistry;
import com.github.jknack.handlebars.Options;
import com.github.jknack.handlebars.TagType;
import com.github.jknack.handlebars.Template;
import com.github.jknack.handlebars.helper.I18nHelper;
import com.github.jknack.handlebars.helper.PrecompileHelper;
import com.github.jknack.handlebars.io.FileTemplateLoader;
import com.google.javascript.jscomp.CheckLevel;
import com.google.javascript.jscomp.ClosureCodingConvention;
import com.google.javascript.jscomp.CompilationLevel;
import com.google.javascript.jscomp.Compiler;
import com.google.javascript.jscomp.CompilerOptions;
import com.google.javascript.jscomp.DiagnosticGroups;
import com.google.javascript.jscomp.JSError;
import com.google.javascript.jscomp.Result;
import com.google.javascript.jscomp.SourceFile;
/**
* Compile Handlebars templates to JavaScript using Rhino.
*
* @author edgar.espina
* @since 1.1.0
*/
@Mojo(name = "precompile", defaultPhase = LifecyclePhase.PREPARE_PACKAGE, threadSafe = true)
public class PrecompilePlugin extends HandlebarsPlugin {
/**
* A prefix location, default is ${basedir}/src/main/webapp.
*/
@Parameter(defaultValue = "${basedir}/src/main/webapp")
private String prefix;
/**
* The file extension, default is: .hbs.
*/
@Parameter(defaultValue = ".hbs")
private String suffix = ".hbs";
/**
* The template files to precompile.
*/
@Parameter
private List templates;
/**
* The output file.
*/
@Parameter(defaultValue = "${project.build.directory}/${project.build.finalName}/js/helpers.js")
private String output;
/**
* The handlebars js file.
*/
@Parameter(defaultValue = "/handlebars-v4.0.4.js")
private String handlebarsJsFile;
/**
* True, if the handlebars.runtime.js file need to be included in the output. Default is: false.
*/
@Parameter
private String runtime;
/**
* Minimize the output. Default is: false.
*/
@Parameter
private boolean minimize;
/**
* True, if the output should be in the AMD format. Default is false.
*/
@Parameter
private boolean amd;
/**
* The encoding char set. Default is: UTF-8.
*/
@Parameter
private String encoding = "UTF-8";
@Override
protected void doExecute() throws Exception {
notNull(prefix, "The prefix parameter is required.");
notNull(output, "The output parameter is required.");
File basedir = new File(prefix);
File output = new File(this.output);
boolean error = true;
PrintWriter writer = null;
InputStream runtimeIS = null;
try {
String realPrefix = basedir.getPath();
Handlebars handlebars = new Handlebars(new FileTemplateLoader(basedir, suffix));
handlebars.handlebarsJsFile(handlebarsJsFile);
final List extras = new ArrayList();
@SuppressWarnings("unchecked")
List classpathElements = project.getRuntimeClasspathElements();
final URL[] classpath = new URL[classpathElements.size()];
for (int i = 0; i < classpath.length; i++) {
classpath[i] = new File(classpathElements.get(i)).toURI().toURL();
}
i18nJs(handlebars, extras, classpath);
i18n(handlebars);
/**
* Silent any missing helper.
*/
silentHelpers(handlebars);
File parent = output.getParentFile();
if (parent != null && !parent.exists()) {
parent.mkdirs();
}
writer = new PrintWriter(output, encoding);
if (runtime != null) {
runtimeIS = new FileInputStream(new File(runtime));
IOUtil.copy(runtimeIS, writer);
}
List files;
if (templates != null && templates.size() > 0) {
files = new ArrayList();
for (String templateName : templates) {
File file = FileUtils.getFile(basedir + File.separator + templateName + suffix);
if (file.exists()) {
files.add(file);
}
}
} else {
files = FileUtils.getFiles(basedir, "**/*" + suffix, null);
}
Collections.sort(files);
getLog().info("Compiling templates...");
getLog().debug("Options:");
getLog().debug(" output: " + output);
getLog().debug(" prefix: " + realPrefix);
getLog().debug(" suffix: " + suffix);
getLog().debug(" minimize: " + minimize);
getLog().debug(" runtime: " + runtime);
if (!amd) {
writer.append("(function () {\n");
}
Context nullContext = Context.newContext(null);
for (File file : files) {
String templateName = file.getPath().replace(realPrefix, "").replace(suffix, "");
if (templateName.startsWith(File.separator)) {
templateName = templateName.substring(File.separator.length());
}
templateName = templateName.replace(File.separator, "/");
getLog().debug("compiling: " + templateName);
handlebars.compile(templateName).apply(nullContext);
Template template = handlebars.compileInline("{{precompile \"" + templateName + "\"}}");
Map hash = new HashMap();
hash.put("wrapper", amd ? "amd" : "none");
Options opts = new Options
.Builder(handlebars, PrecompileHelper.NAME, TagType.VAR, nullContext, template)
.setHash(hash)
.build();
writer.append("// Source: ").append(file.getPath()).append("\n");
writer.append(PrecompileHelper.INSTANCE.apply(templateName, opts).toString())
.append("\n\n");
}
// extras
for (CharSequence extra : extras) {
writer.append(extra).append("\n");
}
if (!amd) {
writer.append("\n})();");
}
writer.flush();
IOUtil.close(writer);
if (minimize) {
minimize(output);
}
if (files.size() > 0) {
getLog().info(" templates were saved in: " + output);
error = false;
} else {
getLog().warn(" no templates were found");
}
} finally {
IOUtil.close(runtimeIS);
IOUtil.close(writer);
if (error) {
output.delete();
}
}
}
/**
* Silent any missing helper.
*
* @param handlebars The handlebars object.
*/
private void silentHelpers(final Handlebars handlebars) {
handlebars.registerHelper(HelperRegistry.HELPER_MISSING, new Helper