UNPKG

bem-xjst

Version:

Declarative Template Engine for the browser and server

145 lines (116 loc) 3.45 kB
var utils = require('./utils'); var Match = require('./match').Match; var tree = require('./tree'); var Template = tree.Template; var PropertyMatch = tree.PropertyMatch; var CompilerOptions = tree.CompilerOptions; function Entity(bemxjst, block, elem, templates) { this.bemxjst = bemxjst; this.block = null; this.elem = null; // Compiler options via `xjstOptions()` this.options = {}; // `true` if entity has just a default renderer for `def()` mode this.canFlush = true; // "Fast modes" this.def = new Match(this); this.mix = new Match(this, 'mix'); this.js = new Match(this, 'js'); this.mods = new Match(this, 'mods'); this.elemMods = new Match(this, 'elemMods'); this.content = new Match(this, 'content'); // "Slow modes" this.rest = {}; // Initialize this.init(block, elem); this.initModes(templates); } exports.Entity = Entity; Entity.prototype.init = function(block, elem) { this.block = block; this.elem = elem; }; Entity.prototype._keys = { content: 1, mix: 1, js: 1, mods: 1, elemMods: 1 }; Entity.prototype._initRest = function(key) { if (key === 'default') { this.rest[key] = this.def; } else if (this._keys[key]) { this.rest[key] = this[key]; } else { this.rest[key] = this.rest[key] || new Match(this, key); } }; Entity.prototype.initModes = function(templates) { /* jshint maxdepth : false */ for (var i = 0; i < templates.length; i++) { var template = templates[i]; for (var j = template.predicates.length - 1; j >= 0; j--) { var pred = template.predicates[j]; if (!(pred instanceof PropertyMatch)) continue; if (pred.key !== '_mode') continue; template.predicates.splice(j, 1); this._initRest(pred.value); // All templates should go there anyway this.rest[pred.value].push(template); break; } if (j === -1) this.def.push(template); // Merge compiler options for (var j = template.predicates.length - 1; j >= 0; j--) { var pred = template.predicates[j]; if (!(pred instanceof CompilerOptions)) continue; this.options = utils.extend(this.options, pred.options); } } }; Entity.prototype.prepend = function(other) { // Prepend to the slow modes, fast modes are in this hashmap too anyway var keys = Object.keys(this.rest); for (var i = 0; i < keys.length; i++) { var key = keys[i]; if (!other.rest[key]) continue; this.rest[key].prepend(other.rest[key]); } // Add new slow modes keys = Object.keys(other.rest); for (var i = 0; i < keys.length; i++) { var key = keys[i]; if (this.rest[key]) continue; this._initRest(key); this.rest[key].prepend(other.rest[key]); } }; // NOTE: This could be potentially compiled into inlined invokations Entity.prototype.run = function(context) { if (this.def.count !== 0) return this.def.exec(context); return this.defaultBody(context); }; function contentMode() { return this.ctx.content; } Entity.prototype.setDefaults = function() { // Default .content() template for applyNext() if (this.content.count !== 0) this.content.push(new Template([], contentMode)); // .def() default if (this.def.count !== 0) { this.canFlush = this.options.flush || false; var self = this; this.def.push(new Template([], function defaultBodyProxy() { return self.defaultBody(this); })); } };