summaryrefslogtreecommitdiffstats
path: root/docs/compiler-api.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/compiler-api.md')
-rw-r--r--docs/compiler-api.md224
1 files changed, 224 insertions, 0 deletions
diff --git a/docs/compiler-api.md b/docs/compiler-api.md
new file mode 100644
index 0000000..7e89b01
--- /dev/null
+++ b/docs/compiler-api.md
@@ -0,0 +1,224 @@
+# Handlebars Compiler APIs
+
+There are a number of formal APIs that tool implementors may interact with.
+
+## AST
+
+Other tools may interact with the formal AST as defined below. Any JSON structure matching this pattern may be used and passed into the `compile` and `precompile` methods in the same way as the text for a template.
+
+AST structures may be generated either with the `Handlebars.parse` method and then manipulated, via the `Handlebars.AST` objects of the same name, or constructed manually as a generic JavaScript object matching the structure defined below.
+
+```javascript
+var ast = Handlebars.parse(myTemplate);
+
+// Modify ast
+
+Handlebars.precompile(ast);
+```
+
+
+### Basic
+
+```java
+interface Node {
+ type: string;
+ loc: SourceLocation | null;
+}
+
+interface SourceLocation {
+ source: string | null;
+ start: Position;
+ end: Position;
+}
+
+interface Position {
+ line: uint >= 1;
+ column: uint >= 0;
+}
+```
+
+### Programs
+
+```java
+interface Program <: Node {
+ type: "Program";
+ body: [ Statement ];
+
+ blockParams: [ string ];
+ strip: StripFlags | null;
+}
+```
+
+### Statements
+
+```java
+interface Statement <: Node {
+ strip: StripFlags | null;
+}
+
+interface MustacheStatement <: Statement {
+ type: "MustacheStatement";
+ sexpr: Subexpression;
+ escaped: boolean;
+}
+
+interface BlockStatement <: Statement {
+ type: "BlockStatement";
+ sexpr: Subexpression;
+ program: Program;
+ inverse: Program | null;
+}
+
+interface PartialStatement <: Statement {
+ type: "PartialStatement";
+ sexpr: Subexpression;
+
+ indent: string;
+}
+
+interface ContentStatement <: Statement {
+ type: "ContentStatement";
+ value: string;
+ original: string;
+}
+
+interface CommentStatement <: Statement {
+ type: "CommentStatement";
+ value: string;
+}
+```
+
+### Expressions
+
+```java
+interface Expression <: Node { }
+```
+
+##### Subexpressions
+
+```java
+interface SubExpression <: Expression {
+ type: "SubExpression";
+ path: PathExpression;
+ params: [ Expression ];
+ hash: Hash;
+
+ isHelper: true | null;
+}
+```
+
+`isHelper` is not required and is used to disambiguate between cases such as `{{foo}}` and `(foo)`, which have slightly different call behaviors.
+
+##### Paths
+
+```java
+interface PathExpression <: Expression {
+ type: "PathExpression";
+ data: boolean;
+ depth: uint >= 0;
+ parts: [ string ];
+ original: string;
+}
+```
+
+- `data` is true when the given expression is a `@data` reference.
+- `depth` is an integer representation of which context the expression references. `0` represents the current context, `1` would be `../`, etc.
+- `parts` is an array of the names in the path. `foo.bar` would be `['foo', 'bar']`. Scope references, `.`, `..`, and `this` should be omitted from this array.
+- `original` is the path as entered by the user. Separator and scope references are left untouched.
+
+
+##### Literals
+
+```java
+interface Literal <: Expression { }
+
+interface StringLiteral <: Literal {
+ type: "StringLiteral";
+ value: string;
+ original: string;
+}
+
+interface BooleanLiteral <: Literal {
+ type: "BooleanLiteral";
+ value: boolean;
+ original: boolean;
+}
+
+interface NumberLiteral <: Literal {
+ type: "NumberLiteral";
+ value: number;
+ original: number;
+}
+```
+
+
+### Miscellaneous
+
+```java
+interface Hash <: Node {
+ type: "Hash";
+ pairs: [ HashPair ];
+}
+
+interface HashPair <: Node {
+ type: "HashPair";
+ key: string;
+ value: Expression;
+}
+
+interface StripFlags {
+ left: boolean;
+ right: boolean;
+}
+```
+
+`StripFlags` are used to signify whitespace control character that may have been entered on a given statement.
+
+TODO : Document what the flags mean or drop this from things like Program.
+
+## AST Visitor
+
+`Handlebars.Visitor` is available as a base class for general interaction with AST structures. This will by default traverse the entire tree and individual methods may be overridden to provide specific responses to particular nodes.
+
+Recording all referenced partial names:
+
+```javascript
+var Visitor = Handlebars.Visitor;
+
+function ImportScanner() {
+ this.partials = [];
+}
+ImportScanner.prototype = new Visitor();
+
+ImportScanner.prototype.PartialStatement = function(partial) {
+ this.partials.push({request: partial.sexpr.original});
+
+ Visitor.prototype.PartialStatement.call(this, partial);
+};
+
+var scanner = new ImportScanner();
+scanner.accept(ast);
+```
+
+## JavaScript Compiler
+
+The `Handlebars.JavaScriptCompiler` object has a number of methods that may be customized to alter the output of the compiler:
+
+```javascript
+function MyCompiler() {
+ Handlebars.JavaScriptCompiler.apply(this, arguments);
+}
+MyCompiler.prototype = Object.create(Handlebars.JavaScriptCompiler);
+
+MyCompiler.nameLookup = function(parent, name, type) {
+ if (type === 'partial') {
+ return 'MyPartialList[' + JSON.stringify(name) ']';
+ } else {
+ return Handlebars.JavaScriptCompiler.prototype.nameLookup.call(this, parent, name, type);
+ }
+};
+
+var env = Handlebars.create();
+env.JavaScriptCompiler = MyCompiler;
+env.compile('my template');
+```