UNPKG

nunjucks

Version:

A powerful templating engine with inheritance, asynchronous control, and more (jinja2 inspired)

350 lines (346 loc) 10.5 kB
'use strict'; function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } var _require = require('./object'), Obj = _require.Obj; function traverseAndCheck(obj, type, results) { if (obj instanceof type) { results.push(obj); } if (obj instanceof Node) { obj.findAll(type, results); } } var Node = /*#__PURE__*/function (_Obj) { _inheritsLoose(Node, _Obj); function Node() { return _Obj.apply(this, arguments) || this; } var _proto = Node.prototype; _proto.init = function init(lineno, colno) { var _arguments = arguments, _this = this; for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } this.lineno = lineno; this.colno = colno; this.fields.forEach(function (field, i) { // The first two args are line/col numbers, so offset by 2 var val = _arguments[i + 2]; // Fields should never be undefined, but null. It makes // testing easier to normalize values. if (val === undefined) { val = null; } _this[field] = val; }); }; _proto.findAll = function findAll(type, results) { var _this2 = this; results = results || []; if (this instanceof NodeList) { this.children.forEach(function (child) { return traverseAndCheck(child, type, results); }); } else { this.fields.forEach(function (field) { return traverseAndCheck(_this2[field], type, results); }); } return results; }; _proto.iterFields = function iterFields(func) { var _this3 = this; this.fields.forEach(function (field) { func(_this3[field], field); }); }; return Node; }(Obj); // Abstract nodes var Value = /*#__PURE__*/function (_Node) { _inheritsLoose(Value, _Node); function Value() { return _Node.apply(this, arguments) || this; } _createClass(Value, [{ key: "typename", get: function get() { return 'Value'; } }, { key: "fields", get: function get() { return ['value']; } }]); return Value; }(Node); // Concrete nodes var NodeList = /*#__PURE__*/function (_Node2) { _inheritsLoose(NodeList, _Node2); function NodeList() { return _Node2.apply(this, arguments) || this; } var _proto2 = NodeList.prototype; _proto2.init = function init(lineno, colno, nodes) { _Node2.prototype.init.call(this, lineno, colno, nodes || []); }; _proto2.addChild = function addChild(node) { this.children.push(node); }; _createClass(NodeList, [{ key: "typename", get: function get() { return 'NodeList'; } }, { key: "fields", get: function get() { return ['children']; } }]); return NodeList; }(Node); var Root = NodeList.extend('Root'); var Literal = Value.extend('Literal'); var _Symbol = Value.extend('Symbol'); var Group = NodeList.extend('Group'); var ArrayNode = NodeList.extend('Array'); var Pair = Node.extend('Pair', { fields: ['key', 'value'] }); var Dict = NodeList.extend('Dict'); var LookupVal = Node.extend('LookupVal', { fields: ['target', 'val'] }); var If = Node.extend('If', { fields: ['cond', 'body', 'else_'] }); var IfAsync = If.extend('IfAsync'); var InlineIf = Node.extend('InlineIf', { fields: ['cond', 'body', 'else_'] }); var For = Node.extend('For', { fields: ['arr', 'name', 'body', 'else_'] }); var AsyncEach = For.extend('AsyncEach'); var AsyncAll = For.extend('AsyncAll'); var Macro = Node.extend('Macro', { fields: ['name', 'args', 'body'] }); var Caller = Macro.extend('Caller'); var Import = Node.extend('Import', { fields: ['template', 'target', 'withContext'] }); var FromImport = /*#__PURE__*/function (_Node3) { _inheritsLoose(FromImport, _Node3); function FromImport() { return _Node3.apply(this, arguments) || this; } var _proto3 = FromImport.prototype; _proto3.init = function init(lineno, colno, template, names, withContext) { _Node3.prototype.init.call(this, lineno, colno, template, names || new NodeList(), withContext); }; _createClass(FromImport, [{ key: "typename", get: function get() { return 'FromImport'; } }, { key: "fields", get: function get() { return ['template', 'names', 'withContext']; } }]); return FromImport; }(Node); var FunCall = Node.extend('FunCall', { fields: ['name', 'args'] }); var Filter = FunCall.extend('Filter'); var FilterAsync = Filter.extend('FilterAsync', { fields: ['name', 'args', 'symbol'] }); var KeywordArgs = Dict.extend('KeywordArgs'); var Block = Node.extend('Block', { fields: ['name', 'body'] }); var Super = Node.extend('Super', { fields: ['blockName', 'symbol'] }); var TemplateRef = Node.extend('TemplateRef', { fields: ['template'] }); var Extends = TemplateRef.extend('Extends'); var Include = Node.extend('Include', { fields: ['template', 'ignoreMissing'] }); var Set = Node.extend('Set', { fields: ['targets', 'value'] }); var Switch = Node.extend('Switch', { fields: ['expr', 'cases', 'default'] }); var Case = Node.extend('Case', { fields: ['cond', 'body'] }); var Output = NodeList.extend('Output'); var Capture = Node.extend('Capture', { fields: ['body'] }); var TemplateData = Literal.extend('TemplateData'); var UnaryOp = Node.extend('UnaryOp', { fields: ['target'] }); var BinOp = Node.extend('BinOp', { fields: ['left', 'right'] }); var In = BinOp.extend('In'); var Is = BinOp.extend('Is'); var Or = BinOp.extend('Or'); var And = BinOp.extend('And'); var Not = UnaryOp.extend('Not'); var Add = BinOp.extend('Add'); var Concat = BinOp.extend('Concat'); var Sub = BinOp.extend('Sub'); var Mul = BinOp.extend('Mul'); var Div = BinOp.extend('Div'); var FloorDiv = BinOp.extend('FloorDiv'); var Mod = BinOp.extend('Mod'); var Pow = BinOp.extend('Pow'); var Neg = UnaryOp.extend('Neg'); var Pos = UnaryOp.extend('Pos'); var Compare = Node.extend('Compare', { fields: ['expr', 'ops'] }); var CompareOperand = Node.extend('CompareOperand', { fields: ['expr', 'type'] }); var CallExtension = Node.extend('CallExtension', { init: function init(ext, prop, args, contentArgs) { this.parent(); this.extName = ext.__name || ext; this.prop = prop; this.args = args || new NodeList(); this.contentArgs = contentArgs || []; this.autoescape = ext.autoescape; }, fields: ['extName', 'prop', 'args', 'contentArgs'] }); var CallExtensionAsync = CallExtension.extend('CallExtensionAsync'); // This is hacky, but this is just a debugging function anyway function print(str, indent, inline) { var lines = str.split('\n'); lines.forEach(function (line, i) { if (line && (inline && i > 0 || !inline)) { process.stdout.write(' '.repeat(indent)); } var nl = i === lines.length - 1 ? '' : '\n'; process.stdout.write("" + line + nl); }); } // Print the AST in a nicely formatted tree format for debuggin function printNodes(node, indent) { indent = indent || 0; print(node.typename + ': ', indent); if (node instanceof NodeList) { print('\n'); node.children.forEach(function (n) { printNodes(n, indent + 2); }); } else if (node instanceof CallExtension) { print(node.extName + "." + node.prop + "\n"); if (node.args) { printNodes(node.args, indent + 2); } if (node.contentArgs) { node.contentArgs.forEach(function (n) { printNodes(n, indent + 2); }); } } else { var nodes = []; var props = null; node.iterFields(function (val, fieldName) { if (val instanceof Node) { nodes.push([fieldName, val]); } else { props = props || {}; props[fieldName] = val; } }); if (props) { print(JSON.stringify(props, null, 2) + '\n', null, true); } else { print('\n'); } nodes.forEach(function (_ref) { var fieldName = _ref[0], n = _ref[1]; print("[" + fieldName + "] =>", indent + 2); printNodes(n, indent + 4); }); } } module.exports = { Node: Node, Root: Root, NodeList: NodeList, Value: Value, Literal: Literal, Symbol: _Symbol, Group: Group, Array: ArrayNode, Pair: Pair, Dict: Dict, Output: Output, Capture: Capture, TemplateData: TemplateData, If: If, IfAsync: IfAsync, InlineIf: InlineIf, For: For, AsyncEach: AsyncEach, AsyncAll: AsyncAll, Macro: Macro, Caller: Caller, Import: Import, FromImport: FromImport, FunCall: FunCall, Filter: Filter, FilterAsync: FilterAsync, KeywordArgs: KeywordArgs, Block: Block, Super: Super, Extends: Extends, Include: Include, Set: Set, Switch: Switch, Case: Case, LookupVal: LookupVal, BinOp: BinOp, In: In, Is: Is, Or: Or, And: And, Not: Not, Add: Add, Concat: Concat, Sub: Sub, Mul: Mul, Div: Div, FloorDiv: FloorDiv, Mod: Mod, Pow: Pow, Neg: Neg, Pos: Pos, Compare: Compare, CompareOperand: CompareOperand, CallExtension: CallExtension, CallExtensionAsync: CallExtensionAsync, printNodes: printNodes };