lib/index.js
/**
* Exposed module for creating and rendering templates.
*
* @module index
* @requires grammar
* @requires tokenizer
* @requires tree
* @requires compiler
* @requires shared/register_partial
* @requires shared/register_filter
* @requires shared/get_partial
* @requires shared/get_filter
* @requires utils/type
*/
define(function(require, exports, module) {
"use strict";
var Grammar = require("./grammar");
var Tokenizer = require("./tokenizer");
var Tree = require("./tree");
var Compiler = require("./compiler");
// Shared.
var registerPartial = require("./shared/register_partial");
var registerFilter = require("./shared/register_filter");
var getPartial = require("./shared/get_partial");
var getFilter = require("./shared/get_filter");
// Utils.
var type = require("./utils/type");
var defaults = require("./utils/defaults");
// These are the custom delimiters that will always be falled back on for
// every template. They can be overwritten in the settings object.
var defaultDelimiters = {
START_RAW: "{{{",
END_RAW: "}}}",
START_PROP: "{{",
END_PROP: "}}",
START_EXPR: "{%",
END_EXPR: "%}",
COMMENT: "--",
FILTER: "|"
};
/**
* Represents a Combyne template.
*
* @class Combyne
* @param {string} template - The template to compile.
* @param {object} data - Optional data to compile.
* @memberOf module:index
*/
function Combyne(template, data) {
// Allow this method to run standalone.
if (!(this instanceof Combyne)) {
return new Combyne(template, data);
}
// Expose the template for easier accessing and mutation.
this.template = template;
// Default the data to an empty object.
this.data = data || {};
// Internal use only. Stores the partials and filters.
this._partials = {};
this._filters = {};
// Ensure the template is a String.
if (type(this.template) !== "string") {
throw new Error("Template must be a String.");
}
// Normalize the delimiters with the defaults, to ensure a full object.
var delimiters = defaults(Combyne.settings.delimiters, defaultDelimiters);
// Create a new grammar with the delimiters.
var grammar = new Grammar(delimiters).escape();
// Break down the template into a series of tokens.
var stack = new Tokenizer(this.template, grammar).parse();
// Take the stack and create something resembling an AST.
var tree = new Tree(stack).make();
// Expose the internal tree and stack.
this.tree = tree;
this.stack = stack;
// Compile the template function from the tree.
this.compiler = new Compiler(tree);
// Update the source.
this.source = this.compiler.source;
}
/**
* Register a partial into the template.
*
* @memberOf module:index.Combyne
* @see {@link module:shared/register_partial}
*/
Combyne.prototype.registerPartial = registerPartial;
/**
* Register a filter into the template.
*
* @memberOf module:index.Combyne
* @see {@link module:shared/register_filter}
*/
Combyne.prototype.registerFilter = registerFilter;
/**
* Get a partial from the template.
*
* @memberOf module:index.Combyne
* @see {@link module:shared/get_partial}
*/
Combyne.prototype.getPartial = getPartial;
/**
* Get a filter from the template.
*
* @memberOf module:index.Combyne
* @see {@link module:shared/get_filter}
*/
Combyne.prototype.getFilter = getFilter;
/**
* Expose the global template settings.
*
* @memberOf module:index.Combyne
* @type {object}
*/
Combyne.settings = {};
/**
* Render the template with data.
*
* @memberOf module:index.Combyne
* @param {object} data - The data to provide to the template.
* @return {string} Rendered template.
*/
Combyne.prototype.render = function(data) {
// Override the template data if provided.
this.data = data || this.data;
// Execute the template function with the correct data.
return this.compiler.func(this.data, this);
};
/**
* Attach the version number.
*
* @memberOf module:index.Combyne
* @type {string}
*/
Combyne.VERSION = "2.0.0";
module.exports = Combyne;
});