UNPKG

liquid-node

Version:

Node.js port of Tobias Lütke's Liquid template engine.

350 lines (323 loc) 11 kB
// Generated by CoffeeScript 1.10.0 (function() { var Context, Liquid, slice = [].slice, hasProp = {}.hasOwnProperty; Liquid = require("../liquid"); module.exports = Context = (function() { function Context(engine, environments, outerScope, registers, rethrowErrors) { var ref; if (environments == null) { environments = {}; } if (outerScope == null) { outerScope = {}; } if (registers == null) { registers = {}; } if (rethrowErrors == null) { rethrowErrors = false; } this.environments = Liquid.Helpers.flatten([environments]); this.scopes = [outerScope]; this.registers = registers; this.errors = []; this.rethrowErrors = rethrowErrors; this.strainer = (ref = engine != null ? new engine.Strainer(this) : void 0) != null ? ref : {}; this.squashInstanceAssignsWithEnvironments(); } Context.prototype.registerFilters = function() { var filter, filters, i, k, len, v; filters = 1 <= arguments.length ? slice.call(arguments, 0) : []; for (i = 0, len = filters.length; i < len; i++) { filter = filters[i]; for (k in filter) { if (!hasProp.call(filter, k)) continue; v = filter[k]; if (v instanceof Function) { this.strainer[k] = v; } } } }; Context.prototype.handleError = function(e) { this.errors.push(e); if (this.rethrowErrors) { throw e; } if (e instanceof Liquid.SyntaxError) { return "Liquid syntax error: " + e.message; } else { return "Liquid error: " + e.message; } }; Context.prototype.invoke = function() { var args, available, method, methodName; methodName = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : []; method = this.strainer[methodName]; if (method instanceof Function) { return method.apply(this.strainer, args); } else { available = Object.keys(this.strainer); throw new Liquid.FilterNotFound("Unknown filter `" + methodName + "`, available: [" + (available.join(', ')) + "]"); } }; Context.prototype.push = function(newScope) { if (newScope == null) { newScope = {}; } this.scopes.unshift(newScope); if (this.scopes.length > 100) { throw new Error("Nesting too deep"); } }; Context.prototype.merge = function(newScope) { var k, results, v; if (newScope == null) { newScope = {}; } results = []; for (k in newScope) { if (!hasProp.call(newScope, k)) continue; v = newScope[k]; results.push(this.scopes[0][k] = v); } return results; }; Context.prototype.pop = function() { if (this.scopes.length <= 1) { throw new Error("ContextError"); } return this.scopes.shift(); }; Context.prototype.lastScope = function() { return this.scopes[this.scopes.length - 1]; }; Context.prototype.stack = function(newScope, f) { var popLater, result; if (newScope == null) { newScope = {}; } popLater = false; try { if (arguments.length < 2) { f = newScope; newScope = {}; } this.push(newScope); result = f(); if ((result != null ? result.nodeify : void 0) != null) { popLater = true; result.nodeify((function(_this) { return function() { return _this.pop(); }; })(this)); } return result; } finally { if (!popLater) { this.pop(); } } }; Context.prototype.clearInstanceAssigns = function() { return this.scopes[0] = {}; }; Context.prototype.set = function(key, value) { return this.scopes[0][key] = value; }; Context.prototype.get = function(key) { return this.resolve(key); }; Context.prototype.hasKey = function(key) { return Promise.resolve(this.resolve(key)).then(function(v) { return v != null; }); }; Context.Literals = { 'null': null, 'nil': null, '': null, 'true': true, 'false': false }; Context.prototype.resolve = function(key) { var hi, lo, match; if (Liquid.Context.Literals.hasOwnProperty(key)) { return Liquid.Context.Literals[key]; } else if (match = /^'(.*)'$/.exec(key)) { return match[1]; } else if (match = /^"(.*)"$/.exec(key)) { return match[1]; } else if (match = /^(\d+)$/.exec(key)) { return Number(match[1]); } else if (match = /^\((\S+)\.\.(\S+)\)$/.exec(key)) { lo = this.resolve(match[1]); hi = this.resolve(match[2]); return Promise.all([lo, hi]).then(function(arg) { var hi, lo; lo = arg[0], hi = arg[1]; lo = Number(lo); hi = Number(hi); if (isNaN(lo) || isNaN(hi)) { return []; } return new Liquid.Range(lo, hi + 1); }); } else if (match = /^(\d[\d\.]+)$/.exec(key)) { return Number(match[1]); } else { return this.variable(key); } }; Context.prototype.findVariable = function(key) { var variable, variableScope; variableScope = void 0; variable = void 0; this.scopes.some(function(scope) { if (scope.hasOwnProperty(key)) { variableScope = scope; return true; } }); if (variableScope == null) { this.environments.some((function(_this) { return function(env) { variable = _this.lookupAndEvaluate(env, key); if (variable != null) { return variableScope = env; } }; })(this)); } if (variableScope == null) { if (this.environments.length > 0) { variableScope = this.environments[this.environments.length - 1]; } else if (this.scopes.length > 0) { variableScope = this.scopes[this.scopes.length - 1]; } else { throw new Error("No scopes to find variable in."); } } if (variable == null) { variable = this.lookupAndEvaluate(variableScope, key); } return Promise.resolve(variable).then((function(_this) { return function(v) { return _this.liquify(v); }; })(this)); }; Context.prototype.variable = function(markup) { return Promise.resolve().then((function(_this) { return function() { var firstPart, iterator, mapper, match, object, parts, squareBracketed; parts = Liquid.Helpers.scan(markup, Liquid.VariableParser); squareBracketed = /^\[(.*)\]$/; firstPart = parts.shift(); if (match = squareBracketed.exec(firstPart)) { firstPart = match[1]; } object = _this.findVariable(firstPart); if (parts.length === 0) { return object; } mapper = function(part, object) { if (object == null) { return Promise.resolve(object); } return Promise.resolve(object).then(_this.liquify.bind(_this)).then(function(object) { var bracketMatch; if (object == null) { return object; } bracketMatch = squareBracketed.exec(part); if (bracketMatch) { part = _this.resolve(bracketMatch[1]); } return Promise.resolve(part).then(function(part) { var isArrayAccess, isObjectAccess, isSpecialAccess; isArrayAccess = Array.isArray(object) && isFinite(part); isObjectAccess = object instanceof Object && ((typeof object.hasKey === "function" ? object.hasKey(part) : void 0) || part in object); isSpecialAccess = !bracketMatch && object && (Array.isArray(object) || Object.prototype.toString.call(object) === "[object String]") && ["size", "first", "last"].indexOf(part) >= 0; if (isArrayAccess || isObjectAccess) { return Promise.resolve(_this.lookupAndEvaluate(object, part)).then(_this.liquify.bind(_this)); } else if (isSpecialAccess) { switch (part) { case "size": return _this.liquify(object.length); case "first": return _this.liquify(object[0]); case "last": return _this.liquify(object[object.length - 1]); default: /* @covignore */ throw new Error("Unknown special accessor: " + part); } } }); }); }; iterator = function(object, index) { if (index < parts.length) { return mapper(parts[index], object).then(function(object) { return iterator(object, index + 1); }); } else { return Promise.resolve(object); } }; return iterator(object, 0)["catch"](function(err) { throw new Error("Couldn't walk variable: " + markup + ": " + err); }); }; })(this)); }; Context.prototype.lookupAndEvaluate = function(obj, key) { if (obj instanceof Liquid.Drop) { return obj.get(key); } else { return obj != null ? obj[key] : void 0; } }; Context.prototype.squashInstanceAssignsWithEnvironments = function() { var lastScope; lastScope = this.lastScope(); return Object.keys(lastScope).forEach((function(_this) { return function(key) { return _this.environments.some(function(env) { if (env.hasOwnProperty(key)) { lastScope[key] = _this.lookupAndEvaluate(env, key); return true; } }); }; })(this)); }; Context.prototype.liquify = function(object) { return Promise.resolve(object).then((function(_this) { return function(object) { if (object == null) { return object; } else if (typeof object.toLiquid === "function") { object = object.toLiquid(); } else if (typeof object === "object") { true; } else if (typeof object === "function") { object = ""; } else { Object.prototype.toString.call(object); } if (object instanceof Liquid.Drop) { object.context = _this; } return object; }; })(this)); }; return Context; })(); }).call(this); //# sourceMappingURL=context.js.map