Comparing version 1.0.2 to 2.0.0
var Visitor = require('./visitor'); | ||
var TextParser = require('./parsers/text'); | ||
var VariableParser = require('./parsers/variable'); | ||
var Splitter = require('./parsers/splitter'); | ||
var ExpressionParser = require('./parsers/expression'); | ||
var ForeachParser = require('./parsers/foreach'); | ||
var SetterCompiler = require('./compiler/setter'); | ||
var uniqueName = require('./utils/uniq_name'); | ||
var size = require('./utils/size'); | ||
var indent = require('./utils/indent').indent; | ||
var indentFromSecondLine = require('./utils/indent').indentFromSecondLine; | ||
/** | ||
* Note what for local vars Monkberry uses λ which are valid ECMAScript 5.1 variable names. | ||
*/ | ||
function Compiler(name, dom) { | ||
@@ -13,6 +21,8 @@ this.name = name; | ||
this.construct = []; | ||
this.complexSetters = {}; | ||
this.setters = {}; | ||
this.variables = {}; | ||
this.controlStructures = []; | ||
this.updateActions = []; | ||
this.subTemplates = []; | ||
this.perceivedAsLibrary = false; | ||
} | ||
@@ -28,3 +38,11 @@ | ||
var walk = function (compiler) { | ||
var templates = [[compiler.name, compiler.compileTemplate()]]; | ||
var templates = []; | ||
var compiled = compiler.compileTemplate(); | ||
// Add only in template does not perceived as library. | ||
if (!compiler.perceivedAsLibrary) { | ||
templates.push([compiler.name, compiled]); | ||
} | ||
for (var sub of compiler.subTemplates) { | ||
@@ -43,3 +61,3 @@ for (var each of walk(sub)) { | ||
var fn = template[1]; | ||
parts.push(' "' + name + '": ' + indent(fn)); | ||
parts.push(' "' + name + '": ' + indentFromSecondLine(fn)); | ||
} | ||
@@ -51,8 +69,8 @@ | ||
code = 'module.exports = function (monkberry, document) {\n' | ||
+ indent('var filters = monkberry.filters;', undefined, true) + '\n' | ||
+ indent('return {\n' + code + '};', undefined, true) + '\n' | ||
+ indent('var filters = monkberry.filters;', undefined) + '\n' | ||
+ indent('return {\n' + code + '};', undefined) + '\n' | ||
+ '};\n' | ||
} else { | ||
code = '(function (monkberry, filters, document, undefined) {\n ' | ||
+ indent('monkberry.mount({\n' + code + '});') | ||
+ indentFromSecondLine('monkberry.mount({\n' + code + '});') | ||
+ '\n})(monkberry, monkberry.filters, window.document, void 0);\n'; | ||
@@ -70,3 +88,3 @@ } | ||
code += ' // Create elements\n'; | ||
code += ' var ' + indent(this.declarations.join(',\n'), 4) + ';\n'; | ||
code += ' var ' + indentFromSecondLine(this.declarations.join(',\n'), 4) + ';\n'; | ||
code += '\n'; | ||
@@ -77,3 +95,3 @@ } | ||
code += ' // Construct dom\n'; | ||
code += ' ' + indent(this.construct.join('\n'), 2) + '\n'; | ||
code += indent(this.construct.join('\n'), 2) + '\n'; | ||
code += '\n'; | ||
@@ -86,6 +104,15 @@ } | ||
if (size(this.complexSetters) > 0) { | ||
code += ' // Complex setters functions\n'; | ||
code += ' var __cache__ = view.cache = {};\n'; | ||
code += ' var λ = {\n'; | ||
code += indent(this.compileComplexSetters(), 4) + '\n'; | ||
code += ' };\n'; | ||
code += '\n'; | ||
} | ||
if (size(this.setters) > 0) { | ||
code += ' // Setters functions\n'; | ||
code += ' var set = {\n'; | ||
code += ' ' + indent(this.compileSetters(), 4) + '\n'; | ||
code += ' view.set = {\n'; | ||
code += indent(this.compileSetters(), 4) + '\n'; | ||
code += ' };\n'; | ||
@@ -95,7 +122,9 @@ code += '\n'; | ||
code += ' // Update function\n'; | ||
code += ' view.update = function (data) {\n'; | ||
code += ' ' + indent(this.compileUpdate(), 4) + '\n'; | ||
code += ' };\n'; | ||
code += '\n'; | ||
if (this.updateActions.length > 0) { | ||
code += ' // Extra update function\n'; | ||
code += ' view._update = function (__data__) {\n'; | ||
code += indent(this.compileUpdateActions(), 4) + '\n'; | ||
code += ' };\n'; | ||
code += '\n'; | ||
} | ||
@@ -114,3 +143,3 @@ code += ' // Set root nodes\n'; | ||
Object.keys(this.setters).forEach(function (key) { | ||
code.push(key + ": function (value) {\n" + indent(_this.setters[key].join(';\n'), 2, false) + ";\n}"); | ||
code.push(key + ': ' + _this.setters[key].compile()); | ||
}); | ||
@@ -120,46 +149,32 @@ return code.join(',\n'); | ||
Compiler.prototype.textNode = function (node) { | ||
var nodeName = 'text' + this.uniqid(); | ||
var textParser = this.compileVariables(node.data, function (code) { | ||
return nodeName + ".nodeValue = " + code; | ||
Compiler.prototype.compileComplexSetters = function () { | ||
var code = []; | ||
var _this = this; | ||
Object.keys(this.complexSetters).forEach(function (key) { | ||
code.push(key + ': ' + _this.complexSetters[key].compile()); | ||
}); | ||
if (textParser.variables.length > 0) { | ||
this.declarations.push(nodeName + " = document.createTextNode(" + esc(textParser.rawText()) + ")"); | ||
return nodeName; | ||
} else { | ||
return "document.createTextNode(" + esc(textParser.rawText()) + ")"; | ||
} | ||
return code.join(',\n'); | ||
}; | ||
Compiler.prototype.compileUpdate = function () { | ||
Compiler.prototype.compileUpdateActions = function () { | ||
var code = []; | ||
if (size(this.setters) > 0) { | ||
Object.keys(this.setters).forEach(function (varName) { | ||
code.push("data." + varName + " !== undefined && set." + varName + "(data." + varName + ")"); | ||
}); | ||
} | ||
for (var control of this.controlStructures) { | ||
for (var control of this.updateActions) { | ||
code.push(control); | ||
} | ||
return code.join(';\n') + (code.length ? ';' : ''); | ||
}; | ||
Compiler.prototype.compileText = function (parts, names) { | ||
var code = []; | ||
Compiler.prototype.textNode = function (node) { | ||
var nodeName = 'text' + this.uniqid(); | ||
var i = 0; | ||
for (var part of parts) { | ||
if (part !== '') { | ||
code.push(esc(part)); | ||
} | ||
if (i < names.length) { | ||
code.push(names[i++]); | ||
} | ||
var expression = this.compileExpression(new Splitter(node.data), function (code) { | ||
return nodeName + ".nodeValue = " + code; | ||
}); | ||
if (expression.variables.length > 0) { | ||
this.declarations.push(nodeName + " = document.createTextNode(" + esc(expression.rawText()) + ")"); | ||
return nodeName; | ||
} else { | ||
return "document.createTextNode(" + esc(expression.rawText()) + ")"; | ||
} | ||
return code.join(' + '); | ||
}; | ||
@@ -207,3 +222,3 @@ | ||
if (key == 'id') { | ||
var id = _this.compileVariables(attributes[key], function (code) { | ||
var id = _this.compileExpression(new Splitter(attributes[key]), function (code) { | ||
return nodeName + ".id = " + code; | ||
@@ -213,3 +228,3 @@ }); | ||
} else { | ||
var attr = _this.compileVariables(attributes[key], function (code) { | ||
var attr = _this.compileExpression(new Splitter(attributes[key]), function (code) { | ||
return nodeName + ".setAttribute('" + key + "', " + code + ")"; | ||
@@ -225,31 +240,30 @@ }); | ||
Compiler.prototype.compileVariables = function (input, callback) { | ||
var variable; | ||
var textParser = new TextParser(input); | ||
Compiler.prototype.compileExpression = function (expression, callback, dataDependent) { | ||
dataDependent = dataDependent || false; | ||
if (textParser.variables.length == 1) { | ||
if (expression.variables.length == 1) { | ||
this.onSetter(expression.variables[0]).add(callback(expression.toCode())); | ||
} else if (expression.variables.length > 1) { | ||
var complexSetter = this.onComplexSetter(expression.variables); | ||
complexSetter.add(callback(expression.toCode())); | ||
variable = textParser.variables[0]; | ||
this.variables[variable.name] = variable; | ||
this.addSetters(variable.name, callback(this.compileText(textParser.textParts, [variable.toString('value')]))); | ||
} else if (textParser.variables.length > 1) { | ||
var valueNames = []; | ||
for (variable of textParser.variables) { | ||
var valueName = variable.name + '_value' + this.uniqid(variable.name); | ||
valueNames.push(valueName); | ||
this.declarations.push(valueName + " = ''"); | ||
this.addSetters(variable.name, valueName + " = " + variable.toString('value')); | ||
if (dataDependent) { | ||
complexSetter.dataDependent(); | ||
} | ||
for (variable of textParser.getUniqueByVariableNames()) { | ||
this.variables[variable.name] = variable; | ||
this.addSetters(variable.name, callback(this.compileText(textParser.textParts, valueNames))); | ||
for (variable of expression.variables) { | ||
this.onSetter(variable).cache(); | ||
this.onSetter(variable).addComplex(expression.variables, complexSetter.name); | ||
} | ||
} | ||
return textParser; | ||
return expression; | ||
}; | ||
Compiler.prototype.directiveNode = function (node) { | ||
if (node.name == '!library') { | ||
this.perceivedAsLibrary = true; | ||
} | ||
}; | ||
Compiler.prototype.ifNode = function (node) { | ||
@@ -260,3 +274,3 @@ if (!node.attribs.test) { | ||
var variable = new VariableParser(node.attribs.test); | ||
var expression = new ExpressionParser(node.attribs.test); | ||
@@ -285,13 +299,11 @@ var templateName; | ||
this.declarations.push(childrenName + " = {}"); | ||
this.variables[variable.name] = variable; | ||
this.controlStructures.push( | ||
"if (data." + variable.name + " !== undefined) \n" + | ||
" monkberry.insert(view, " + | ||
placeholder + ", " + | ||
childrenName + ", '" + | ||
templateName + "', " + | ||
"data, " + | ||
variable.toString('data.' + variable.name) + | ||
")" | ||
); | ||
this.compileExpression(expression, function (code) { | ||
return "monkberry.insert(view, " + | ||
placeholder + ", " + | ||
childrenName + ", '" + | ||
templateName + "', " + | ||
"__data__, " + | ||
code + | ||
")" | ||
}, true); | ||
@@ -307,3 +319,3 @@ return parentNode ? null : placeholder; | ||
var foreach = new ForeachParser(node.attribs.each); | ||
var variable = foreach.variable; | ||
var expression = foreach.expression; | ||
var options = null; | ||
@@ -340,12 +352,12 @@ | ||
this.declarations.push(childrenName + " = monkberry.map()"); | ||
this.variables[variable.name] = variable; | ||
this.addSetters(variable.name, | ||
"monkberry.foreach(view, " + | ||
placeholder + ", " + | ||
childrenName + ", '" + | ||
templateName + "', " + | ||
variable.toString('value') + | ||
(options !== null ? ', ' + esc(options) : '') + | ||
")" | ||
); | ||
this.compileExpression(expression, function (code) { | ||
return "monkberry.foreach(view, " + | ||
placeholder + ", " + | ||
childrenName + ", '" + | ||
templateName + "', " + | ||
'__data__, ' + | ||
code + | ||
(options !== null ? ', ' + esc(options) : '') + | ||
")" | ||
}); | ||
@@ -373,3 +385,3 @@ return parentNode ? null : placeholder; | ||
this.declarations.push(childrenName + " = {}"); | ||
this.controlStructures.push( | ||
this.updateActions.push( | ||
"monkberry.insert(view, " + | ||
@@ -379,3 +391,3 @@ placeholder + ", " + | ||
templateName + "', " + | ||
"data, " + | ||
"__data__, " + | ||
"1" + | ||
@@ -400,9 +412,11 @@ ")" | ||
Compiler.prototype.addSetters = function (forVariable, opcode) { | ||
if (!this.setters[forVariable]) { | ||
this.setters[forVariable] = []; | ||
} | ||
this.setters[forVariable].push(opcode); | ||
Compiler.prototype.onSetter = function (variableName) { | ||
return variableName in this.setters ? this.setters[variableName] : this.setters[variableName] = new SetterCompiler([variableName]); | ||
}; | ||
Compiler.prototype.onComplexSetter = function (variables) { | ||
var name = uniqueName(variables); | ||
return name in this.complexSetters ? this.complexSetters[name] : this.complexSetters[name] = new SetterCompiler(variables); | ||
}; | ||
Compiler.prototype.uniqid = function (counter) { | ||
@@ -416,12 +430,2 @@ var name = counter || 'tag'; | ||
function indent(code, to, skip_first) { | ||
var value = to || 2; | ||
var i = skip_first === undefined ? 1 : 0; | ||
var lines = code.split('\n'); | ||
for (var len = lines.length; i < len; i++) { | ||
lines[i] = new Array(value + 1).join(' ') + lines[i]; | ||
} | ||
return lines.join('\n'); | ||
} | ||
function esc(str) { | ||
@@ -431,10 +435,2 @@ return JSON.stringify(str); | ||
function size(obj) { | ||
var size = 0, key; | ||
for (key in obj) { | ||
if (obj.hasOwnProperty(key)) size++; | ||
} | ||
return size; | ||
} | ||
module.exports = Compiler; |
var htmlparser = require('htmlparser2'); | ||
var drawTree = require('asciitree'); | ||
var Compiler = require('./compiler'); | ||
@@ -4,0 +3,0 @@ |
@@ -1,5 +0,5 @@ | ||
var VariableParser = require('./variable'); | ||
var ExpressionParser = require('./expression'); | ||
function ForeachParser(foreachString) { | ||
var parts = foreachString.split('in', 2); | ||
function ForeachParser(input) { | ||
var parts = input.split('of', 2); | ||
@@ -10,3 +10,3 @@ this.keyName = null; | ||
if (parts.length == 2) { | ||
this.variable = new VariableParser(parts[1]); | ||
this.expression = new ExpressionParser(parts[1]); | ||
var keyvalue = parts[0].split(',', 2); | ||
@@ -20,3 +20,3 @@ if (keyvalue.length == 2) { | ||
} else { | ||
this.variable = new VariableParser(foreachString); | ||
this.expression = new ExpressionParser(input); | ||
} | ||
@@ -23,0 +23,0 @@ } |
@@ -44,2 +44,4 @@ function Visitor(callback) { | ||
push(this.callback.textNode(node)); | ||
} else if (node.type === 'directive') { | ||
push(this.callback.directiveNode(node)); | ||
} else { | ||
@@ -46,0 +48,0 @@ throw new Error('Unknown node type: "' + node.type + '".'); |
102
monkberry.js
@@ -9,6 +9,6 @@ (function (document) { | ||
Monkberry.prototype.foreach = function (parent, node, map, template, data, options) { | ||
Monkberry.prototype.foreach = function (parent, node, map, template, data, array, options) { | ||
var i, j, len, childrenSize = map.length; | ||
len = childrenSize - data.length; | ||
len = childrenSize - array.length; | ||
for (i in map.items) { | ||
@@ -24,15 +24,15 @@ if (len-- > 0) { | ||
for (i in map.items) { | ||
map.items[i].update(forData(data[j], j, options)); | ||
map.items[i].update(forData(data, array[j], j, options)); | ||
j++; | ||
} | ||
for (j = childrenSize, len = data.length; j < len; j++) { | ||
// Render new view | ||
for (j = childrenSize, len = array.length; j < len; j++) { | ||
// Render new view. | ||
var view = this.render(template); | ||
// Set view hierarchy | ||
// Set view hierarchy. | ||
view.parent = parent; | ||
parent.nested.push(view); | ||
// Add nodes DOM | ||
// Add nodes DOM. | ||
if (node.nodeType == 8) { | ||
@@ -44,6 +44,6 @@ view.insertBefore(node); | ||
// Set view data (note what it must be after adding nodes to DOM) | ||
view.update(forData(data[j], j, options)); | ||
// Set view data (note what it must be after adding nodes to DOM). | ||
view.update(forData(data, array[j], j, options)); | ||
// Remember to remove from children map on view remove | ||
// Remember to remove from children map on view remove. | ||
i = map.push(view); | ||
@@ -67,10 +67,10 @@ view.onRemove = (function (i) { | ||
} else if (test) { | ||
// Render new view | ||
// Render new view. | ||
var view = this.render(template); | ||
// Set view hierarchy | ||
// Set view hierarchy. | ||
view.parent = parent; | ||
parent.nested.push(view); | ||
// Add nodes DOM | ||
// Add nodes DOM. | ||
if (node.nodeType == 8) { | ||
@@ -82,6 +82,6 @@ view.insertBefore(node); | ||
// Set view data (note what it must be after adding nodes to DOM) | ||
// Set view data (note what it must be after adding nodes to DOM). | ||
view.update(data); | ||
// Remember to remove from children map on view remove | ||
// Remember to remove child ref on remove of view. | ||
child.ref = view; | ||
@@ -138,2 +138,3 @@ view.onRemove = function () { | ||
// Some of templates mounts as factory which returns list of templates. | ||
if (typeof templates === 'function') { | ||
@@ -148,2 +149,11 @@ templates = templates(this, document); | ||
Monkberry.prototype.extend = function (obj, from) { | ||
for (var key in from) { | ||
if (from.hasOwnProperty(key)) { | ||
obj[key] = from[key]; | ||
} | ||
} | ||
return obj; | ||
}; | ||
Monkberry.prototype.view = function () { | ||
@@ -157,7 +167,10 @@ return new View; | ||
/** | ||
* Main class for view. | ||
*/ | ||
function View() { | ||
this.name = ''; // Name of template | ||
this.parent = null; // Parent view | ||
this.nested = []; // Nested views | ||
this.nodes = []; // Root DOM nodes | ||
this.name = ''; // Name of template. | ||
this.parent = null; // Parent view. | ||
this.nested = []; // Nested views. | ||
this.nodes = []; // Root DOM nodes. | ||
} | ||
@@ -171,2 +184,24 @@ | ||
View.prototype.update = function (data) { | ||
var _this = this, keys = typeof data === 'object' ? Object.keys(data) : []; | ||
if (_this.__cache__) { | ||
// Clear cache to prevent double updating. | ||
keys.forEach(function (key) { | ||
if (key in _this.__cache__) { | ||
delete _this.__cache__[key]; | ||
} | ||
}); | ||
} | ||
if (_this.set) { | ||
keys.forEach(function (key) { | ||
if (_this.set.hasOwnProperty(key)) { | ||
_this.set[key](data, data[key]); | ||
} | ||
}); | ||
} | ||
if (_this._update) { | ||
_this._update(data); | ||
} | ||
}; | ||
View.prototype.insertBefore = function (toNode) { | ||
@@ -196,3 +231,3 @@ for (var i = 0, len = this.nodes.length; i < len; i++) { | ||
View.prototype.remove = function () { | ||
// Remove appended nodes | ||
// Remove appended nodes. | ||
var i = this.nodes.length; | ||
@@ -202,7 +237,7 @@ while (i--) { | ||
} | ||
// Remove self from parent's children map | ||
// Remove self from parent's children map or child ref. | ||
if (this.onRemove) { | ||
this.onRemove(); | ||
} | ||
// Remove all nested views | ||
// Remove all nested views. | ||
i = this.nested.length; | ||
@@ -217,6 +252,10 @@ while (i--) { | ||
} | ||
// Store view in pool for reuse | ||
// Store view in pool for reuse in future. | ||
this.pool.push(this.name, this); | ||
}; | ||
/** | ||
* Pool stores pre rendered views for faster template | ||
* rendering and removed views for reuseing DOM nodes. | ||
*/ | ||
function Pool() { | ||
@@ -241,4 +280,5 @@ this.store = {}; | ||
// Helper functions for working with "map". | ||
/** | ||
* Simple Map implementation with length property. | ||
*/ | ||
function Map() { | ||
@@ -262,3 +302,2 @@ this.items = Object.create(null); | ||
} else { | ||
// TODO: Remove this in future, after API stabilization. | ||
throw new Error('You are trying to delete not existing element "' + i + '" form map.'); | ||
@@ -270,10 +309,11 @@ } | ||
* Helper function for working with foreach loops data. | ||
* Will transform data for "key, value of array" constructions. | ||
*/ | ||
function forData(data, i, options) { | ||
function forData(data, item, key, options) { | ||
if (options) { | ||
var newData = {}; | ||
newData[options.valueName] = data; | ||
var newData = data; | ||
newData[options.valueName] = item; | ||
if (options.keyName) { | ||
newData[options.keyName] = i; | ||
newData[options.keyName] = key; | ||
} | ||
@@ -283,3 +323,3 @@ | ||
} else { | ||
return data; | ||
return item; | ||
} | ||
@@ -286,0 +326,0 @@ } |
{ | ||
"name": "monkberry", | ||
"version": "1.0.2", | ||
"version": "2.0.0", | ||
"description": "JavaScript DOM Template Engine", | ||
@@ -5,0 +5,0 @@ "bin": "./bin/monkberry", |
# Monkberry | ||
[![Build Status](http://img.shields.io/travis/monkberry/monkberry.svg)](https://travis-ci.org/monkberry/monkberry) | ||
[![Build Status](https://travis-ci.org/monkberry/monkberry.svg?branch=master)](https://travis-ci.org/monkberry/monkberry) | ||
JavaScript DOM template engine. | ||
## Tests | ||
Monkberry uses [Jasmine](http://jasmine.github.io) and [testem](https://github.com/airportyh/testem). To run test locally run: | ||
``` | ||
testem ci | ||
``` |
describe('Monkberry', function () { | ||
beforeEach(function() { | ||
jasmine.addCustomEqualityTester(function (view, html) { | ||
var a, b, node = document.createElement('div'); | ||
node.innerHTML = html; | ||
a = view.dom(); | ||
b = node.childNodes[0]; | ||
return a.isEqualNode(b); | ||
}); | ||
jasmine.addMatchers(customMatchers); | ||
}); | ||
@@ -14,3 +8,3 @@ | ||
var view = monkberry.render('monkberry'); | ||
expect(view).toEqual('<div> Monkberry Moon Delight </div>'); | ||
expect(view).toBe('<div> Monkberry Moon Delight </div>'); | ||
}); | ||
@@ -24,3 +18,3 @@ | ||
}); | ||
expect(view).toEqual('<p>To understand what recursion is, you must first understand recursion.</p>'); | ||
expect(view).toBe('<p>To understand what recursion is, you must first understand recursion.</p>'); | ||
}); | ||
@@ -34,3 +28,3 @@ | ||
expect(view).toEqual('<input type="text" value="Value">'); | ||
expect(view).toBe('<input type="text" value="Value">'); | ||
}); | ||
@@ -43,3 +37,3 @@ | ||
}); | ||
expect(view).toEqual('<p>foo bar baz</p>'); | ||
expect(view).toBe('<p>foo bar baz</p>'); | ||
}); | ||
@@ -52,3 +46,3 @@ | ||
}); | ||
expect(view).toEqual('<div class="foo bar baz"></div>'); | ||
expect(view).toBe('<div class="foo bar baz"></div>'); | ||
}); | ||
@@ -63,3 +57,3 @@ | ||
}); | ||
expect(view).toEqual('<div class="first second"></div>'); | ||
expect(view).toBe('<div class="first second"></div>'); | ||
@@ -70,3 +64,3 @@ view.update({ | ||
expect(view).toEqual('<div class="updated second"></div>'); | ||
expect(view).toBe('<div class="updated second"></div>'); | ||
}); | ||
@@ -76,8 +70,127 @@ | ||
var view = monkberry.render('test6'); | ||
view.update({ | ||
list: [1, 2, 3] | ||
view.update({list: [1, 2, 3]}); | ||
expect(view).toBe('<ul><li>0:1</li><li>1:2</li><li>2:3</li></ul>'); | ||
view.update({list: [1, 3]}); | ||
expect(view).toBe('<ul><li>0:1</li><li>1:3</li></ul>'); | ||
view.update({list: ['a', 'b', 'c', 'd']}); | ||
expect(view).toBe('<ul><li>0:a</li><li>1:b</li><li>2:c</li><li>3:d</li></ul>'); | ||
}); | ||
it('should render arrays with externals', function () { | ||
var view = monkberry.render('test6.1'); | ||
view.update({list: [1, 2, 3], ext: '.js'}); | ||
expect(view).toBe('<div><p>1.js</p><p>2.js</p><p>3.js</p></div>'); | ||
}); | ||
it('should correctly work with wrappers', function () { | ||
var items = []; | ||
monkberry.wrappers['test6.for0'] = function (view) { | ||
items.push(function () { | ||
view.remove(); | ||
}); | ||
return view; | ||
}; | ||
var view = monkberry.render('test6'); | ||
view.update({list: [1, 2, 3]}); | ||
expect(view).toBe('<ul><li>0:1</li><li>1:2</li><li>2:3</li></ul>'); | ||
items[1](); | ||
expect(view).toBe('<ul><li>0:1</li><li>2:3</li></ul>'); | ||
}); | ||
it('should properly work with more then one node on topmost level', function () { | ||
var view = monkberry.render('test7'); | ||
expect(view).toBe('<p>first</p><p>second</p>'); | ||
}); | ||
it('should render custom tags', function () { | ||
var view = monkberry.render('test8', {text: 'for custom tags'}); | ||
expect(view).toBe('<div><p>for custom tags</p></div>'); | ||
}); | ||
it('should render inline custom tags', function () { | ||
var view = monkberry.render('test9', {}); | ||
expect(view).toBe('<div><p>inline</p><!--custom-inline--><p>inline</p><!--custom-inline--></div>'); | ||
}); | ||
it('should optimize <if>/<for> tag, if it is only child', function () { | ||
var view = monkberry.render('test10', {a: true, b: [1]}); | ||
expect(view).toBe('<div><p>a</p><p>b</p></div>'); | ||
}); | ||
it('should place placeholders for multiply <if> tags', function () { | ||
var view = monkberry.render('test11'); | ||
expect(view).toBe('<div><!--if--><!--if--></div>'); | ||
}); | ||
it('should place placeholders for multiply <if> and <for> tags', function () { | ||
var view = monkberry.render('test12'); | ||
expect(view).toBe('<div><!--if--><!--for--></div>'); | ||
}); | ||
it('should properly for with <if> tags', function () { | ||
var view = monkberry.render('test-if', {test: true, context: 'parent data'}); | ||
expect(view).toBe('<div> true: parent data </div>'); | ||
view.update({test: false}); | ||
expect(view).toBe('<div></div>'); | ||
view.update({test: true}); | ||
expect(view).toBe('<div> true: parent data </div>'); | ||
}); | ||
it('should properly for with filters', function () { | ||
monkberry.filters.append = function (value, text) { | ||
return value + text; | ||
}; | ||
monkberry.filters.upperCase = function (value) { | ||
return value.toUpperCase(); | ||
}; | ||
var view = monkberry.render('test-filters', {text: 'upper_'}); | ||
expect(view).toBe('<p>UPPER_CASE</p>'); | ||
}); | ||
it('should work with expressions', function () { | ||
var view = monkberry.render('test-expressions', { | ||
a: 1, | ||
b: 2, | ||
c: 100, | ||
d: 2, | ||
more: { | ||
amazing: 'a' | ||
}, | ||
features: ['b', 'c'] | ||
}); | ||
expect(view).toEqual('<ul><li>0:1</li><li>1:2</li><li>2:3</li></ul>'); | ||
expect(view).toBe('<a title="150">abc</a>'); | ||
view.update({more: {amazing: 'Amazing!'}}); | ||
expect(view).toBe('<a title="150">Amazing!bc</a>'); | ||
}); | ||
it('should work with expression in <if> tag', function () { | ||
var view = monkberry.render('test-expression-if', { | ||
array: [1, 2, 3, 4, 5], | ||
look: 3, | ||
indep: 'independent' | ||
}); | ||
expect(view).toBe('<div>(one)<!--if-->3<p>independent</p><!--if--></div>'); | ||
view.update({look: 2}); | ||
expect(view).toBe('<div>(one)<!--if-->2<p>independent</p><!--if--></div>'); | ||
view.update({look: -1}); | ||
expect(view).toBe('<div>(one)<!--if--><!--if--></div>'); | ||
view.update({array: [-1]}); | ||
expect(view).toBe('<div><!--if-->-1<p>independent</p><!--if--></div>'); | ||
}); | ||
}); |
@@ -6,6 +6,7 @@ { | ||
"spec/views.js", | ||
"spec/support/*.js", | ||
"spec/*_spec.js" | ||
], | ||
"before_tests": "bin/monkberry -o spec/views.js -- spec/views/*.html", | ||
"before_tests": "bin/monkberry -o spec/views.js -- spec/views/*.html", | ||
"on_exit": "rm spec/views.js" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
264524
43
2784
12
1
1