micromustache
Advanced tools
Comparing version 3.0.4 to 4.0.0
{ | ||
"name": "micromustache", | ||
"version": "3.0.4", | ||
"version": "4.0.0", | ||
"homepage": "https://github.com/userpixel/micromustache", | ||
@@ -5,0 +5,0 @@ "description": "A faster and smaller subimplementation of the {{mustache}} template engine for JavaScript", |
{ | ||
"name": "micromustache", | ||
"version": "3.0.4", | ||
"version": "4.0.0", | ||
"description": "A faster and smaller subimplementation of the {{mustache}} template engine for JavaScript", | ||
@@ -20,3 +20,3 @@ "keywords": [ | ||
"chai": "^3.5.0", | ||
"mocha": "^2.5.3", | ||
"mocha": "^3.0.0", | ||
"mustache": "^2.2.1", | ||
@@ -23,0 +23,0 @@ "uglify-js": "^2.7.0", |
101
README.md
@@ -14,2 +14,15 @@ [![GitHub issues](https://img.shields.io/github/issues/userpixel/micromustache.svg?style=flat-square)](https://github.com/userpixel/micromustache/issues) | ||
- [Features](#features) | ||
- [Tradeoffs](#tradeoffs) | ||
- [API](#api) | ||
- [render()](#micromustacherender) | ||
- [Differences with MustacheJS](#differences-with-mustachejs-render-method) | ||
- [compile()](#micromustachecompile) | ||
- [to_html()](#micromustacheto_html) | ||
- [Tests](#tests) | ||
- [FAQ](#faq) | ||
- [License](#license) | ||
## Features | ||
* No dependencies | ||
@@ -22,6 +35,9 @@ * Works in node (CommonJS) and Browser (AMD, global, Browserify/WebPack) | ||
**Tradeoff** | ||
But wait, don't ES6 Template literals solve the same problem? Read FAQ at the end of this page. | ||
Micromustache achieves faster speed and smaller size by dropping: | ||
## Tradeoffs | ||
Micromustache achieves faster speed and smaller size by dropping the following | ||
features from MustacheJS: | ||
* Array iterations: *{{# ...}}* | ||
@@ -46,11 +62,18 @@ * Partials: *{{> ...}}* | ||
/** | ||
* @param template {string} the template containing one or more {{variableNames}} | ||
* @param [view={}] {object} an optional object containing values for every variable names | ||
* that is used in the template | ||
* @return {string} template where its variable names replaced with corresponding values. | ||
* If a value is not found or is invalid, it will be assumed empty string ''. | ||
* If the value is an object itself, it'll be stringified by JSON. | ||
* @param {string} template - the template containing one or | ||
* more {{variableNames}} | ||
* @param {Object} [view={}] - an optional object containing values for | ||
* every variable names that is used in the template. If it's omitted, | ||
* it'll be assumed an empty object. | ||
* @param {GeneralValueFn} [generalValueFn] an optional function that will be | ||
* called for every key to generate a value. If the result is undefined | ||
* we'll proceed with the default value resolution algorithm. | ||
* This function runs in the context of view. | ||
* @returns {string} template where its variable names replaced with | ||
* corresponding values. If a value is not found or is invalid, it will | ||
* be assumed empty string ''. If the value is an object itself, it'll | ||
* be stringified by JSON. | ||
* In case of a JSON error the result will look like "{...}". | ||
*/ | ||
micromustache.render(template, view); | ||
micromustache.render(template, view, generalValueFn); | ||
``` | ||
@@ -79,2 +102,5 @@ | ||
*Note: if a key is missing or null, it'll be treated as it contained a value | ||
of empty string (i.e. the {{variableName}} will be removed from the template).* | ||
You can easily reference deep object hierarchies: | ||
@@ -117,12 +143,13 @@ | ||
/** | ||
* @param key {String} variable name for the current scope. | ||
* @callback ValueFn | ||
* @param {string} key - variable name for the current scope. | ||
* For hierarchical names like {{a.b.c}} the key can be 'a' or 'b' or 'c' | ||
* @param currentScope {Object} the current object that the variable is | ||
* @param {Object} currentScope - the current object that the variable is | ||
* supposed to resolved from | ||
* @param path {String[]} useful for hierarchical objects. | ||
* @param {string[]} path - useful for hierarchical objects. | ||
* for example a variable name like {{a.b.c}} sets the | ||
* path to ['a', 'b', 'c'] | ||
* @param currentPointer {Number} the array index to where in the path we are at the | ||
* moment. This is usually path.length - 1 | ||
* @return {String|Number|Boolean|Object} the value to be interpolated | ||
* @param {number} currentPointer - the array index to where in the path we are | ||
* at the moment. This is usually path.length - 1 | ||
* @returns {string|number|boolean|Object} the value to be interpolated | ||
*/ | ||
@@ -169,4 +196,5 @@ function toUpper (key, currentScope, path, currentPointer) { | ||
/** | ||
* @param template {string} same as the template parameter to .render() | ||
* @return compiler(view) {function} a function that accepts a view and returns a rendered template | ||
* @param {string} template - same as the template parameter to .render() | ||
* @returns {function} a function that accepts a view object and returns a | ||
* rendered template string | ||
*/ | ||
@@ -195,3 +223,3 @@ micromustache.compile(template); | ||
Download from [browser directory](https://github.com/userpixel/micromustache/tree/master/browser) | ||
There are 4 ways to get the library: | ||
@@ -210,2 +238,16 @@ [npm](https://npmjs.org/package/micromustache): | ||
[CDN](https://cdnjs.com/libraries/micromustache): | ||
````HTML | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/micromustache/3.0.4/micromustache.js"></script> | ||
```` | ||
Download directly from [browser directory](https://github.com/userpixel/micromustache/tree/master/browser) | ||
Clone this Git repo: | ||
````bash | ||
git clone https://github.com/userpixel/micromustache | ||
```` | ||
# Tests | ||
@@ -225,2 +267,25 @@ | ||
# FAQ | ||
**Q. What about [ES6 template literals](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals) | ||
(AKA "template strings")? | ||
Aren't they gonna deprecate this library?** | ||
A. The expressions in a string literal can't reference values from outside its scope. | ||
Therefore it is not possible to simply pass an object and resolve variables from its keys. | ||
The [tagged template literals](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals) | ||
cover part of the functionality but they: | ||
* are not Mustache-compatible | ||
* require compilation for Android and IE | ||
However, since when they are natively supported by the runtime, they have a | ||
great performance and if you learn to use the native way of doing things, | ||
you don't have to learn an ever-changing library, though their functionality is | ||
more limited than MustacheJS. | ||
# License | ||
MIT | ||
# TODO | ||
@@ -227,0 +292,0 @@ |
/** | ||
* @callback GeneralValueFn | ||
* | ||
* @param {string} key - variable name before being parsed. | ||
* For example: {a.b.c} -> 'a.b.c', { x } -> 'x' | ||
* @returns {string|number|boolean|Object|undefined} the value to be | ||
* interpolated. If the function returns undefined, the value resolution | ||
* algorithm will go ahead with the default behaviour (resolving the | ||
* variable name from the provided object). | ||
*/ | ||
/** | ||
* @callback ValueFn | ||
* | ||
* @param {string} key - variable name for the current scope. | ||
* For hierarchical names like {{a.b.c}} the key can be 'a' or 'b' or 'c' | ||
* @param {Object} currentScope - the current object that the variable is | ||
* supposed to resolved from | ||
* @param {string[]} path - useful for hierarchical objects. | ||
* for example a variable name like {{a.b.c}} sets the | ||
* path to ['a', 'b', 'c'] | ||
* @param {number} currentPointer - the array index to where in the path we are | ||
* at the moment. This is usually path.length - 1 | ||
* @returns {string|number|boolean|Object} the value to be interpolated | ||
*/ | ||
/** | ||
* Replaces every {{variable}} inside the template with values provided by view | ||
* If the value is a function, call it passing the name of the variable as the only argument. | ||
* If the value is a function, call it passing the name of the variable as the | ||
* only argument. | ||
* | ||
* @param template {string} the template containing one or more {{variableNames}} | ||
* @param [view={}] {object} an optional object containing values for every variable names | ||
* that is used in the template | ||
* @return {string} template where its variable names replaced with corresponding values. | ||
* If a value is not found or is invalid, it will be assumed empty string ''. | ||
* If the value is an object itself, it'll be stringified by JSON. In case of a JSON error the result will look like "{JSON_ERROR: ... }". | ||
* @param {string} template - the template containing one or | ||
* more {{variableNames}} | ||
* @param {Object} [view={}] - an optional object containing values for | ||
* every variable names that is used in the template. If it's omitted, | ||
* it'll be assumed an empty object. | ||
* @param {GeneralValueFn} [generalValueFn] - an optional function that will be | ||
* called for every key to generate a value. If the result is undefined | ||
* we'll proceed with the default value resolution algorithm. | ||
* This function runs in the context of view. | ||
* @returns {string} - template where its variable names replaced with | ||
* corresponding values. If a value is not found or is invalid, it will | ||
* be assumed empty string ''. If the value is an object itself, it'll | ||
* be stringified by JSON. | ||
* In case of a JSON error the result will look like "{...}". | ||
*/ | ||
function render(template, view) { | ||
function render (template, view, generalValueFn) { | ||
//don't touch the template if it is not a string | ||
@@ -17,2 +52,8 @@ if (typeof template !== 'string') { | ||
} | ||
// if view is omitted but generalValueFn is set | ||
if (typeof view === 'function' && typeof generalValueFn === 'undefined') { | ||
generalValueFn = view; | ||
} | ||
//if view is not a valid object, assume it is an empty object | ||
@@ -23,19 +64,33 @@ //which effectively removes all variable interpolations | ||
} | ||
return template.replace(/\{\{\s*(.*?)\s*\}\}/g, function(match, varName) { | ||
return template.replace(/\{\{\s*(.*?)\s*\}\}/g, function (match, varName) { | ||
if (generalValueFn) { | ||
var generalValueFnResult = generalValueFn(view, varName); | ||
if (typeof generalValueFnResult !== 'undefined') { | ||
return valueFnResultToString(generalValueFnResult); | ||
} | ||
} | ||
var path = varName.split('.'); | ||
function resolve(currentScope, pathIndex) { | ||
function resolve (currentScope, pathIndex) { | ||
if (currentScope === null) { | ||
return ''; | ||
} | ||
var key = path[pathIndex]; | ||
var value = currentScope[key]; | ||
var typeofValue = typeof value; | ||
if (typeofValue === 'function') { | ||
//if the value is a function, call it passing the variable name | ||
return valueFnResultToString(value.call(view, key, currentScope, path, pathIndex)); | ||
return valueFnResultToString( | ||
value.call(view, key, currentScope, path, pathIndex) | ||
); | ||
} else if (typeofValue === 'object') { | ||
pathIndex++; | ||
// If it's a leaf and still an object, just stringify it | ||
return pathIndex < path.length ? resolve(value, pathIndex) : valueFnResultToString(value); | ||
return pathIndex < path.length ? | ||
resolve(value, pathIndex) : | ||
valueFnResultToString(value); | ||
} else { | ||
@@ -53,11 +108,15 @@ return valueFnResultToString(value); | ||
* for a particular template that accepts data and returnes the rendered string. | ||
* It doesn't make the code faster since the compiler still uses render internally. | ||
* It doesn't make the code faster since the compiler still uses render | ||
* internally. | ||
* | ||
* @param template {string} same as the template parameter to render() | ||
* @return compiler(view) {function} a function that accepts a view and returns a rendered template | ||
* @param {string} template - same as the template parameter to .render() | ||
* @param {GeneralValueFn} [generalValueFn] - same as the parameter to .render() | ||
* @returns {function} - a function that accepts a view object and returns a | ||
* rendered template string template | ||
*/ | ||
function compile (template) { | ||
//create and return a function that will always apply this template under the hood | ||
function compile (template, generalValueFn) { | ||
// Create and return a function that will always apply this template | ||
// and generalValueFn under the hood | ||
return function compiler (view) { | ||
return render (template, view); | ||
return render (template, view, generalValueFn); | ||
}; | ||
@@ -74,6 +133,16 @@ } | ||
// null is an object but is falsy. Swallow null | ||
if (value === null) { | ||
return ''; | ||
} else { | ||
// Convert the object to json without throwing | ||
try { | ||
return JSON.stringify(value); | ||
} catch (jsonError) { | ||
return '{...}'; | ||
} | ||
} | ||
return value ? toJsonPolitely(value) : ''; | ||
default: | ||
// Anything else will be replaced with an empty string | ||
// For example: undefined, date, regexp, etc). | ||
// For example: undefined, Symbol, etc. | ||
return ''; | ||
@@ -83,12 +152,3 @@ } | ||
// Converts an object to json without throwing | ||
function toJsonPolitely (obj) { | ||
try { | ||
return JSON.stringify(obj); | ||
} catch (jsonError) { | ||
return '{...}'; | ||
} | ||
} | ||
exports.to_html = exports.render = render; | ||
exports.compile = compile; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
78162
267
286