com.squarespace.template.cli.TemplateC Maven / Gradle / Ivy
/**
* Copyright, 2015, Squarespace, Inc.
*
* 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.
*/
package com.squarespace.template.cli;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import org.apache.commons.io.IOUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.squarespace.template.BuildProperties;
import com.squarespace.template.CodeException;
import com.squarespace.template.CompiledTemplate;
import com.squarespace.template.Compiler;
import com.squarespace.template.Context;
import com.squarespace.template.FormatterTable;
import com.squarespace.template.GeneralUtils;
import com.squarespace.template.Instruction;
import com.squarespace.template.JsonUtils;
import com.squarespace.template.PredicateTable;
import com.squarespace.template.ReferenceScanner;
import com.squarespace.template.TreeEmitter;
import com.squarespace.template.plugins.CoreFormatters;
import com.squarespace.template.plugins.CorePredicates;
import net.sourceforge.argparse4j.ArgumentParsers;
import net.sourceforge.argparse4j.impl.Arguments;
import net.sourceforge.argparse4j.inf.ArgumentParser;
import net.sourceforge.argparse4j.inf.ArgumentParserException;
import net.sourceforge.argparse4j.inf.Namespace;
/**
* Command line template compiler.
*/
public class TemplateC {
private static final String TEMPLATE_REPOSITORY = "http://github.com/squarespace/squarespace-template";
private static final String PROGRAM_NAME = "templatec";
public static void main(String[] args) {
TemplateC command = new TemplateC();
command.execute(args);
}
protected void execute(String[] args) {
String version = buildVersion();
ArgumentParser parser = ArgumentParsers.newArgumentParser(PROGRAM_NAME)
.description("Compile template files")
.version(version);
parser.addArgument("--version", "-v")
.action(Arguments.version())
.help("Show the version and exit");
parser.addArgument("--stats", "-s")
.action(Arguments.storeTrue())
.help("Dump stats for the template");
parser.addArgument("--tree", "-t")
.action(Arguments.storeTrue())
.help("Dump the syntax tree for the template");
parser.addArgument("--json", "-j")
.type(String.class)
.help("JSON tree");
parser.addArgument("--partials", "-p")
.type(String.class)
.help("JSON partials");
parser.addArgument("template")
.type(String.class)
.help("Template source");
int exitCode = 1;
try {
Namespace res = parser.parseArgs(args);
if (res.getBoolean("stats")) {
exitCode = stats(res.getString("template"));
} else if (res.getBoolean("tree")) {
exitCode = tree(res.getString("template"));
} else {
exitCode = compile(res.getString("template"), res.getString("json"), res.getString("partials"));
}
} catch (CodeException | IOException e) {
System.err.println(e.getMessage());
} catch (ArgumentParserException e) {
parser.handleError(e);
System.exit(1);
} finally {
System.exit(exitCode);
}
}
/**
* Compile a template against a given json tree and emit the result.
*/
protected int compile(String templatePath, String jsonPath, String partialsPath)
throws CodeException, IOException {
String template = readFile(templatePath);
String json = "{}";
if (jsonPath != null) {
json = readFile(jsonPath);
}
String partials = null;
if (partialsPath != null) {
partials = readFile(partialsPath);
}
CompiledTemplate compiled = compiler().compile(template, false);
Instruction code = compiled.code();
// Parse the JSON context
JsonNode jsonTree = null;
try {
jsonTree = JsonUtils.decode(json);
} catch (IllegalArgumentException e) {
System.err.println("Caught error trying to parse JSON: " + e.getCause().getMessage());
return 1;
}
// Parse the optional JSON partials dictionary.
JsonNode partialsTree = null;
if (partials != null) {
try {
partialsTree = JsonUtils.decode(partials);
if (!(partialsTree instanceof ObjectNode)) {
System.err.println("Partials map JSON must be an object. Found " + partialsTree.getNodeType());
return 1;
}
} catch (IllegalArgumentException e) {
System.err.println("Caught error trying to parse partials: " + e.getCause().getMessage());
return 1;
}
}
// Perform the compile.
Context context = compiler().newExecutor()
.code(code)
.json(jsonTree)
.partialsMap((ObjectNode)partialsTree)
.execute();
// If compile was successful, print the output.
System.out.print(context.buffer().toString());
return 0;
}
/**
* Scan the compiled template and print statistics.
*/
protected int stats(String templatePath) throws CodeException, IOException {
String template = readFile(templatePath);
CompiledTemplate compiled = compiler().compile(template, false);
ReferenceScanner scanner = new ReferenceScanner();
scanner.extract(compiled.code());
ObjectNode report = scanner.references().report();
String result = GeneralUtils.jsonPretty(report);
System.out.println(result);
return 0;
}
/**
* Print the syntax tree for the given template.
*/
protected int tree(String templatePath) throws CodeException, IOException {
String template = readFile(templatePath);
CompiledTemplate compiled = compiler().compile(template, false);
StringBuilder buf = new StringBuilder();
TreeEmitter.emit(compiled.code(), 0, buf);
System.out.println(buf.toString());
return 0;
}
protected Compiler compiler() {
FormatterTable formatterTable = new FormatterTable();
formatterTable.register(new CoreFormatters());
PredicateTable predicateTable = new PredicateTable();
predicateTable.register(new CorePredicates());
return new Compiler(formatterTable, predicateTable);
}
protected String readFile(String rawPath) throws IOException {
try (Reader reader = new InputStreamReader(new FileInputStream(rawPath), "UTF-8")) {
return IOUtils.toString(reader);
}
}
/**
* Build the version string.
*/
protected String buildVersion() {
StringBuilder buf = new StringBuilder();
buf.append("${prog} version ")
.append(BuildProperties.version())
.append('\n');
buf.append(" repository: ").append(TEMPLATE_REPOSITORY).append('\n');
buf.append(" build date: ").append(BuildProperties.date()).append('\n');
buf.append(" build commit: ").append(BuildProperties.commit()).append('\n');
return buf.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy