Security News
Supply Chain Attack Detected in Solana's web3.js Library
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
@mscalora/overtemplate
Advanced tools
Yet another replacement for _.template (underscore or lodash) without unsafe evals.
A fairly simple templating system that combines the escaped and interpolated parts of Lodash/Underscore templates with simple conditional and looping over an array while conforming to Content Security Policy (CSP).
Based on Silvermine UnderTemplate which is a simple replacement for _.template
from either [Underscore][utmpl] or [Lodash][ltmpl]
that removes the features that make those libraries incompatible with Content Security
Policy (CSP).
NOTE: Version 2.0.0 introduced a breaking change in the syntax of the loop construct, the parameter separator in the for tag will be a semicolon by default instead of a comma. A new option parameterSeparator has been added to allow for separators like comma or other characters that may function better with custom expression evaluators. Passing a comma character for the parameterSeparator setting will effectively revert the syntax to be 1.x compatible.
Similar to templates in Underscore's _.template
:
let overtemplate = require('@mscalora/overtemplate'),
compiled = overtemplate('Hello <%= name %>');
console.log(compiled({ name: 'John Smith' }));
Note: syntax of tags is customizable, default syntax shown below
Syntax:
<%- expression [ | filter ... ] %>
Syntax:
<%= expression [ | filter ... ] %>
Syntax:
<% if ( expression ) %>
Syntax:
<% else %>
Syntax:
<% end %>
Syntax:
<% for ( expression ; alias ) %>
Syntax:
<% end %>
The portion of the template between the for
tag and the end
tag is rendered once for each item on the collection represented by the expression value. The expression value is expected to be 'array like'. The current item from the collection is set using the alias parameter as the property name. In addition, the following properties are set in the current data model:
Note: _first and _last will both be true for one item arrays. For example, to emit a comma between all items, use the else clause of a conditional:
const overtemplate = require('@mscalora/overtemplate');
template = '<% for (letters;item)%><%- item %><% if (item_last) %><% else %>, <% end %><% end %>',
compiled = overtemplate(template);
console.log(compiled({letters: Array.from('abc')}));
> a, b, c
The alternate syntax is provided for use when separator characters used in the default syntax might cause conflicts with template data.
Syntax:
«- expression [ ~ filter ... ] »
Syntax:
«= expression [ ~ filter ... ] »
Syntax:
« if ( expression ) »
Syntax:
« else »
Syntax:
« end »
Syntax:
« for ( expression • alias ) »
Syntax:
« end »
See the loop documentation of the default syntax section documents for usage information.
Note: The default parameter separator character for the alternate syntax is the bullet character (Mac keystroke: option-8) and the filter separator is a tilde character. The tag beginning and end characters are accessed from a typical US-EN keyboard layout with option-\ and option-shift-\.
By default, expressions resulting in Date objects are converted to a string using the .toLocaleString() method and 'Numbers' are converted to a string using template literals ${n}
. You can replace either or both of these 'formatters' in the user settings like:
function two_digit_fixed (value, data, settings, expression) {
return (Math.round(value * 100) / 100).toFixed(2);
}
const overtemplate = require('@mscalora/overtemplate');
template = '<%- num %>',
compiled = overtemplate(template, {numberFormatter: two_digit_fixed});
console.log(compiled({num: 2/3}));
Formatter functions are expected to return a string value
Clients can provide a customFormatter callback which is used for ALL expression values. If a customFormatter is passed in user settings numberFormatter and dateFormatter are not called directly but can be used in your customFormatter implementation.
Settings for callbacks:
Note: The built-in defaultFormatter will call the dateFormatter and numberFormatter in the current settings object so custom implementations of these formatters should not use this function or infinite recursion may occur. It can however be safely used by customFormatter implementations.
function pwObfuscator (v, d, s, e) {
if (/(\W|^)(password|passwd)(\W|$)/i.test(e)) {
return `${v}`.replace(/./g, '*');
}
return s.defaultFormatter(v, d, s, e);
}
function simple_date (v, d, s, e) {
if (v.getFullYear() < 1970) {
return '-invalid-';
}
return `${v.getFullYear()}-${v.getMonth()}-${v.getDate()}`;
}
function price_formatter (v, d, s, e) {
if (/price/.exec(e) && v.toFixed) {
return `$$${v.toFixed(2)}`;
}
return s.defaultFormatter(v, d, s, e);
}
Custom expression evaluators are functions with the signature:
function (expression, data, [defaultValue], [settings])
const exprEval = require('expr-eval');
function customEval (data, exp, _, __) {
return (new exprEval.Parser()).evaluate(exp, data);
}
const overtemplate = require('@mscalora/overtemplate'),
template = '<%- 17^3 + v[2].x %>',
compiled = overtemplate(template, {expressionEvaluator: customEval});
console.log(compiled({v:[1,2,{x:11.7}]}));
The expr-eval module supports custom javascript extension functions attached to the functions object of the Parser class in addition to overriding the module provided functions and operators.
const exprEval = require('expr-eval'),
exprParser = new exprEval.Parser();
// returns a dynamicly created array of counting numbers
exprParser.functions.counting = function (len) {
return Array.from({length:len},(_,i)=>i+1);
}
const overtemplate = require('@mscalora/overtemplate'),
template = '<% for (counting(n);c) %><%- c %>\n<% end %>',
customEval = (data, exp, _, __) => exprParser.evaluate(exp, data),
compiled = overtemplate(template, {expressionEvaluator: customEval});
console.log(compiled({n:5}));
Filters are a way to process interpolation tag expression values by specifying filter names in interpolation and escape tags.
<%- author.name | upperCase %>
Formatters are oriented towards global processing by data type. Since they have visibility to the raw expression text, you can create formatters to handle serialization (converting to a string) by field name, see the pwObfuscator example above.
Filters are specified in output tags in the template so more oriented to use of a value in a template.
Templating in Underscore/Lodash was operating by building up a JS function as a string. This meant that if your template referred to a variable that did not exist, you would get a JS error thrown. In this library, however, undefined variables in the template will result in an empty string being placed in that location.
By default, expression evaluation is limited to "paths" supported by the lodash get method and literal values for strings and numbers. The module is tested with custom expression evaluation using the expr-eval module. This module provides rich algebraic expressions with numbers, strings and arrays with many built-in operators and functions well beyond what's available in javascript. Expression syntax and semantics are similar to javascript but incompatible in several ways. For example, the addition operator only supports numeric values, string concatenation requires the use of a different operator. Visit the modules github page for more info: https://github.com/silentmatt/expr-eval
We rely on Lodash to provide a number of convenience functions that would require polyfills to support a wide array of browsers. To help reduce bloat, we do two things:
4.x
, meaning that if you already have it
as a dependency, we'll use your version.require('lodash/foo')
for each foo
function we need. This helps if you're
using UnderTemplate in a browserify-style environment since only the files from
Lodash that are actually needed will be included in your bundle.Pull requests with tests and documentation updates as needed
This software is released under the MIT license. See the license file for more details.
Copyrighted by Mike Scalora and original Silvermine UnderTemplate code was copyrited by Jeremy Thomerson 2018 [utmpl]: http://underscorejs.org/#template [ltmpl]: https://lodash.com/docs/#template
FAQs
Yet another replacement for _.template (underscore or lodash) without unsafe evals.
The npm package @mscalora/overtemplate receives a total of 1 weekly downloads. As such, @mscalora/overtemplate popularity was classified as not popular.
We found that @mscalora/overtemplate demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
A supply chain attack has been detected in versions 1.95.6 and 1.95.7 of the popular @solana/web3.js library.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.