UNPKG

muban-convert-hbs

Version:

Convert muban hbs templates to htl, django, twig and others.

243 lines (198 loc) 6.92 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.IterationType = exports.Scope = exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); /** * Holds information about the current Handlebars Context. * A new context is created when traversing inside a block that introduces new variables, e.g. 'each' * * Creating a child context is done by calling context.createChildContext([variables in scope]). * This will clone the current context, append the new scope, and increase the depth */ var Context = /*#__PURE__*/ function () { /** * A list of scopes, length should correspond with `depth-1` */ /** * Context depth, will be increased when creating a child context */ /** * object will be shared between parent and child contexts */ function Context() { Object.defineProperty(this, "scopes", { configurable: true, enumerable: true, writable: true, value: void 0 }); Object.defineProperty(this, "depth", { configurable: true, enumerable: true, writable: true, value: void 0 }); Object.defineProperty(this, "shared", { configurable: true, enumerable: true, writable: true, value: void 0 }); // create empty scope at root level this.scopes = [new Scope([])]; // set initial depth to 0 this.depth = 0; this.shared = { ifCounter: 0 }; } /** * Add new values to the context and return the new context. The current context remains untouched. * @param {string[]} variables * @param replacements * @return {Context} A new context. */ var _proto = Context.prototype; _proto.createChildContext = function createChildContext(variables, replacements) { var context = this.clone(); context.scopes.push(new Scope(variables, replacements)); ++context.depth; return context; }; /** * Gets the scope for a given depth * * @param {number} depth * @return {Scope} */ _proto.getScope = function getScope(depth) { return this.scopes[depth]; }; _proto.getCurrentScope = function getCurrentScope() { return this.scopes[this.scopes.length - 1]; }; /** * Gets all the available variables available in the scopes up to the given depth. * Can be used to see if a variable is explicitly referencing a scope variable * @param {number} depth * @return {Array<string>} */ _proto.getScopesToDepth = function getScopesToDepth(depth) { // NOTE: contains duplicates, but doesn't matter var mergedScope = { variables: [], replacements: [] }; this.scopes.slice(0, depth + 1).forEach(function (scope) { if (scope.variables) { var _mergedScope$variable; (_mergedScope$variable = mergedScope.variables).push.apply(_mergedScope$variable, scope.variables); } if (scope.replacements) { mergedScope.replacements = (0, _extends2.default)({}, mergedScope.replacements, scope.replacements); } }); return mergedScope; }; _proto.getScopedVariable = function getScopedVariable(path) { // get the depth the variable is referencing (path.depth is higher when using ../) var varDepth = this.depth - path.depth; // console.log('getScopedVariable', path); if (varDepth === 0) { // upper level is root, which has no scope vars, so do early exit return path.parts.join('.'); } // if the variable doesn't match anything explicitly, and is not in the root scope, // we must prepend it with the current scope value (at least for 'each' blocks) var currentScope = this.getScope(varDepth); // {{ this }} if (path.parts.length === 0) { return currentScope.value; } // {{ @key }} if (path.original === '@key') { // when no key is provided by `|value key|`, it will be added in the output template by default if (!currentScope.key) { currentScope.iterateAsObject(); } return currentScope.key || 'key'; } // get the scope by traversing up to a certain parent depth // when using ../ in the variable, the depth will lower // this will build op all explicit scope variables from the root up to the provided depth var _getScopesToDepth = this.getScopesToDepth(varDepth), variables = _getScopesToDepth.variables, replacements = _getScopesToDepth.replacements; // if the first path of the variable already in the current scope, or any parents if (variables.includes(path.parts[0])) { var match = path.parts.join('.'); if (match in replacements) { return replacements[match]; } return match; } // console.log(' >> ', currentScope.value, path.parts); return [currentScope.value, path.parts].join('.'); }; // clone the current Context _proto.clone = function clone() { var context = new Context(); context.scopes = this.scopes.concat(); context.depth = this.depth; context.shared = this.shared; return context; }; return Context; }(); /** * Internal scope class, created when increasing the context depth. * Contains all the variables in the new scope. */ exports.default = Context; var Scope = /*#__PURE__*/ function () { // alias vars for easy reference, these ones are for the `each` loop function Scope(variables, replacements) { Object.defineProperty(this, "iterationType", { configurable: true, enumerable: true, writable: true, value: IterationType.ARRAY }); Object.defineProperty(this, "variables", { configurable: true, enumerable: true, writable: true, value: void 0 }); Object.defineProperty(this, "replacements", { configurable: true, enumerable: true, writable: true, value: void 0 }); Object.defineProperty(this, "value", { configurable: true, enumerable: true, writable: true, value: void 0 }); Object.defineProperty(this, "key", { configurable: true, enumerable: true, writable: true, value: void 0 }); this.variables = variables; this.replacements = replacements; // NOTE: might require additional info if we handle other type of blockParam variables this.value = this.variables[0]; this.key = this.variables[1] || undefined; } var _proto2 = Scope.prototype; _proto2.iterateAsObject = function iterateAsObject() { this.iterationType = IterationType.OBJECT; }; return Scope; }(); exports.Scope = Scope; var IterationType; exports.IterationType = IterationType; (function (IterationType) { IterationType[IterationType["ARRAY"] = 'array'] = "ARRAY"; IterationType[IterationType["OBJECT"] = 'object'] = "OBJECT"; })(IterationType || (exports.IterationType = IterationType = {}));