Socket
Socket
Sign inDemoInstall

beard

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

beard - npm Package Compare versions

Comparing version 0.3.0 to 0.4.0

benchmarks.js

272

beard.js

@@ -1,188 +0,138 @@

(function(){
module.exports = function(cache = {}, lookup = path => path) {
let compiledCache = {};
let iterator = 0;
var Beard = function(cache){
this._cache = cache;
}
const Beard = function() {}
var iterator = 0;
var ignores = {};
var ignoreId = 0;
Beard.prototype = {
render: (template, data = {}) => {
iterator = 0;
return compiled(template, data)(data);
}
};
var exps = {
extend: (/{extend\s(.*?)}/),
include: (/{include\s(.*?)}/g),
block: (/{block\s+(.[^}]*)}([^]*?){endblock}/g),
ignore: (/{ignore}([^]*?){endignore}/g),
ignoreTemp: (/_ignore_([^]*?)_endignore_/g),
statement: (/\{\s*([^}]+?)\s*\}/g),
operators: (/\s+(and|or|eq|neq|is|isnt|not)\s+/g),
if: (/^if\s+([^]*)$/),
elseIf: (/^else\s+if\s+([^]*)$/),
else: (/^else$/),
for: (/^for\s+([$A-Za-z_][0-9A-Za-z_]*)(?:\s*,\s*([$A-Za-z_][0-9A-Za-z_]*))?\s+in\s+(.*)$/),
each: (/^each\s+([$A-Za-z_][0-9A-Za-z_]*)(?:\s*,\s*([$A-Za-z_][0-9A-Za-z_]*))?\s+in\s(.*)$/),
end: (/^end$/)
};
const exps = {
extends: (/\{{extends\s\'([^}}]+?)\'\}}/g),
include: (/^include\s\'([^\(]*?)\'$/g),
includeFn: (/^include\((\s?\'([^\(]*?)\'\,\s?\{([^\)]*)\})\)$/g),
block: (/{{block\s+(.[^}]*)}}([^]*?){{endblock}}/g),
statement: (/{{\s*((?!}}).+?)\s*}}/g),
if: (/^if\s+([^]*)$/),
elseIf: (/^else\s+if\s+([^]*)$/),
else: (/^else$/),
for: (/^for\s+([$A-Za-z_][0-9A-Za-z_]*)(?:\s*,\s*([$A-Za-z_][0-9A-Za-z_]*))?\s+in\s+(.*)$/),
each: (/^each\s+([$A-Za-z_][0-9A-Za-z_]*)(?:\s*,\s*([$A-Za-z_][0-9A-Za-z_]*))?\s+in\s(.*)$/),
end: (/^end$/)
};
var operators = {
and: ' && ',
or: ' || ',
eq: ' === ',
neq: ' !== ',
not: ' !',
isnt: ' != ',
is: ' == '
};
const parse = {
include: (_, path) => `_buffer += compiled("${cache[lookup(path)]}", _data)(_data)`,
includeFn: (_, __, path, data) => `_buffer += compiled("${cache[lookup(path)]}", _data)({${data}})`,
block: (_, varname, content) => `{{:var ${varname} = compiled("${content}", _data)(_data)}}{{:_data["${varname}"] = ${varname}}}`,
if: (_, statement) => `if (${statement}) {`,
elseIf: (_, statement) => `} else if (${statement}) {`,
else: () => '} else {',
end: () => '}',
var parse = {
ignore: function(_, contents) {
ignoreId += 1;
ignores[ignoreId] = contents;
return '_ignore_' + ignoreId + '_endignore_';
for: (_, key, value, object) => {
if (!value) key = (value = key, 'iterator' + iterator++);
return `for (var ${key} in ${object}){ var ${value} = ${object}[${key}];`;
},
ignoreTemp: function(_, id) {
return ignores[id];
},
each: (_, iter, value, array) => {
if (!value) iter = (value = iter, 'iterator' + iterator++);
const length = 'length' + iterator++;
return `for (var ${iter} = 0, ${length} = ${array}.length; ${iter} < ${length}; ${iter}++) { var ${value} = ${array}[${(iter)}];`;
}
};
operators: function(_, op) {
return operators[op];
},
function parser(match, inner) {
const prev = inner;
inner = inner
.replace(exps.include, parse.include)
.replace(exps.includeFn, parse.includeFn)
.replace(exps.end, parse.end)
.replace(exps.else, parse.else)
.replace(exps.elseIf, parse.elseIf)
.replace(exps.if, parse.if)
.replace(exps.each, parse.each)
.replace(exps.for, parse.for);
if: function(_, statement) {
return 'if (' + statement + ') {';
},
return `"; ${(inner === prev && !/^:/.test(inner) ? ' _buffer += ' : '')} ${inner.replace(/\t|\n|\r|^:/, '')}; _buffer += "`;
}
elseIf: function(_, statement) {
return '} else if (' + statement +') {';
},
function compiled(str, data) {
let key = hash(str);
else: function() {
return '} else {';
},
if (!compiledCache[key]) {
compiledCache[key] = compile(str);
}
for: function(_, key, value, object) {
if (!value) key = (value = key, 'iterator' + iterator++);
return 'for (var ' + key + ' in ' + object + '){' + 'var ' + value + ' = ' + object + '[' + key +'];';
},
return compiledCache[key];
}
each: function(_, iter, value, array) {
if (!value) iter = (value = iter, 'iterator' + iterator++);
var length = 'length' + iterator++;
return 'for (var ' + iter + ' = 0, ' + length + ' = ' + array + '.length; ' + iter + ' < ' + length + '; ' + iter + '++) {' + 'var ' + value + ' = ' + array + '[' + (iter) + '];';
},
function hash(str) {
let hash = 5381;
let i = str.length;
end: function() {
return '}';
while(i) {
hash = (hash * 33) ^ str.charCodeAt(--i);
}
};
Beard.prototype = {
return hash >>> 0;
}
parser: function(match, inner) {
var prev = inner;
inner = inner
.replace(exps.operators, parse.operators)
.replace(exps.end, parse.end)
.replace(exps.else, parse.else)
.replace(exps.elseIf, parse.elseIf)
.replace(exps.if, parse.if)
.replace(exps.each, parse.each)
.replace(exps.for, parse.for);
function compile(str) {
let layout;
return '";' + (inner === prev ? ' _buffer += ' : '') + inner.replace(/\t|\n|\r/, '') + '; _buffer += "';
},
str = str
.replace(exps.extends, (_, path) => {
layout = cache[lookup(path)];
return '';
})
.replace(exps.block, parse.block)
.replace(exps.statement, parser)
.replace(/_buffer_\s\+=\s"";/g, '')
.replace(/\n/g, '\\n')
.replace(/\t/g, '\\t')
.replace(/\r/g, '\\r');
parseExtend: function(template, data) {
var matches;
template = template.replace(exps.extend, function(){
matches = ([]).slice.call(arguments, 0);
return '';
});
let fn = `
function _compiledTemplate(_data){
var _buffer = "";
if (matches && matches.length) {
var path = matches[1];
var view = this._cache[path];
view = view.replace(exps.ignore, parse.ignore);
view += "{block view}" + this.preRender(template, data) + "{endblock}";
return view;
} else {
return template;
function _valForEval(val) {
if (typeof val == 'function') return val.toString();
return JSON.stringify(val);
}
},
parseInclude: function(template, data) {
return template.replace(exps.include, function(_, path){
return this.preRender(this._cache[path], data);
}.bind(this));
},
for (var prop in _data) {
if (_data.hasOwnProperty(prop)) {
eval("var " + prop + " = " + _valForEval(_data[prop]));
}
}
_buffer += "${str}";
`;
parseBlock: function(template, data) {
var matches = [];
template = template.replace(exps.block, function(){
var arr = ([]).slice.call(arguments, 0);
matches.push(arr);
return '';
});
if (layout) {
fn += `
_data['view'] = _buffer;
_buffer = compiled("${layout}", _data)(_data);
`;
}
matches.forEach(function(set){
// set[1] is the var name;
// set[2] is the var value;
data[set[1]] = this.compile(set[2])(data);
}.bind(this));
fn += `
return _buffer;
}
`;
return this.compile(template)(data);
},
try {
eval(fn);
return _compiledTemplate.bind(_compiledTemplate);
} catch (e) {
throw new Error(`Compilation error: ${fn}`);
}
}
preRender: function(template, data){
template = template.replace(exps.ignore, parse.ignore);
template = this.parseExtend(template, data);
template = this.parseInclude(template, data);
template = this.parseBlock(template, data);
return this.compile(template)(data);
},
render: function(template, data){
template = this.preRender(template, data);
template = template.replace(exps.ignoreTemp, parse.ignoreTemp);
ignoreId = 0;
ignores = {};
return template;
},
compile: function(str) {
str = str
.replace(new RegExp('\\\\', 'g'), '\\\\').replace(/"/g, '\\"')
.replace(exps.statement, this.parser)
.replace(/_buffer_\s\+=\s"";/g, '')
.replace(/(\{|\});/g, '$1')
.replace(/\n/g, '\\n')
.replace(/\t/g, '\\t')
.replace(/\r/g, '\\r');
var fn = (
'var _buffer = ""; \
for (var prop in _data_) { \
if (_data_.hasOwnProperty(prop)) this[prop] = _data_[prop]; \
} \
_buffer += "' + str + '"; \
return _buffer;'
);
try {
return new Function('_data_', fn);
} catch (e) {
throw new Error('Cant compile template:' + fn);
}
}
return new Beard();
};
if (typeof module !== 'undefined') {
module.exports = Beard;
} else {
window.Beard = Beard;
}
})();
{
"name": "beard",
"version": "0.3.0",
"description": "More than a mustache.",
"keywords": ["template engine", "node", "browser"],
"repository": "git://github.com/shanebo/beard.git",
"author": "Shane Thacker <shane@steadymade.com>",
"engine": ">= 0.4.1",
"main": "./beard"
"name": "beard",
"version": "0.4.0",
"description": "More than a mustache.",
"keywords": [
"templating engine",
"node"
],
"repository": "git://github.com/shanebo/beard.git",
"author": "Shane Thacker <shane@steadymade.com>",
"contributors": [
"Joe Osburn <joe@jnodev.com>"
],
"engine": ">= 0.4.1",
"main": "./beard",
"scripts": {
"test": "mocha"
},
"devDependencies": {
"mocha": "4.1.0",
"chai": "4.1.2",
"brisky-performance": "1.4.2"
}
}

@@ -16,32 +16,57 @@ Beard

### Syntax ###
### Install ###
Beard.render(template, view);
`npm install beard`
### Arguments ###
### API ###
``` js
const Beard = require('beard');
const engine = new Beard(cache, lookup);
engine.render(template, locals);
```
### Beard Constructor Arguments ###
**cache** - (object) An object literal containing your templates.
**lookup** - (function) A function that accepts the path value and can modify the path value before Beard looks up your template from the cache. E.g., `(path) => '/absolute/cached/path/${path}'`.
### Render Arguments ###
**template** - (string) A string to be parsed and populated by the view object.
**view** - (object) An object of data and/or methods which will populate the template string.
**locals** - (object) An object of data and/or methods which will populate the template string.
### Example ###
var Beard = require('beard');
``` js
const templates = {
'example': "{{noun}} get {{makeUpperCase('stinky')}}."
};
var view = {
noun: "Beards",
makeUpperCase: function(str){
return str.toUpperCase();
}
};
const locals = {
noun: "Beards",
makeUpperCase: function(str){
return str.toUpperCase();
}
};
var html = Beard.render('{noun} are {makeUpperCase('awesome')}!', view);
const Beard = require('beard');
const engine = new Beard(templates);
const result = engine.render("{{include 'example'}}", locals);
console.log(result); // returns 'Beards get STINKY.'
```
More docs later...
### More docs to come... ###
* cache
* optional cache lookup function
### Thanks to ###
* keeto (Mark Obcena) for the parser/compiler
* shinetech (Danny Brain) for syntax ideas
* shinetech (Danny Brain) for syntax ideas
* joeosburn (Joe Osburn) for the updated compiler, cached compiled functions, tests, and benchmarks
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc