Security News
tea.xyz Spam Plagues npm and RubyGems Package Registries
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
Readme
A simple and powerful templating engine that supports:
$ npm install jnr
var jnr = require('jnr');
Use the render
function to apply tags in the template with supplied data.
var result = jnr.render(template, data);
Wrap variable names in {{
double curly brackets }}
.
{{page.greeting}}
Welcome
Conditional logic is defined by if
, elseif
and else
tags.
{{if user.logged_in}}
Log out
{{else}}
Log in
{{/if}}
Log out
The each
... as
tag is used to loop arrays and objects.
{{each pets as pet}}
- {{pet.name}} ${{pet.price}}
{{/each}}
- Hamster $25.95
- Guinea Pig $18.80
- Parrot $23.33
Object property names can be accessed by supplying a second property.
{ scores: { Fred: 8, Barney: 4, Wilma: 5 } }
{{each scores as name,score}}
- {{name}} got {{score}}
{{/each}}
- Fred got 8
- Barney got 4
- Wilma got 5
Array indexes can be accessed the same way.
{ names: [ 'Fred', 'Barney', 'Wilma' ] }
{{each names as index,name}}
{{index}}) {{name}}
{{/each}}
0) Fred
1) Barney
2) Wilma
If the expression is followed by a ?
and it is not defined, it will not output and will not throw an error.
Hello {{username?}}
Hello
Optionals can also be used to test conditional statements.
{{if user.cart?}}
View cart ({{user.cart.length}})
{{else}}
Log in to view cart
{{/if}}
View cart (5)
Optional variables can be chained using double quotes ??
.
If the first expression isn't set the second (and third etc) will be used.
Oh hi {{user.nickname??user.firstname??user.surname}}
Oh hi Marcus
Ternary operators can be used for shorthand conditional output.
Don't forget your {{weather.isRainy?packItem.rainy:packItem.sunny}}
Don't forget your umbrella
Supported operators inlcude ==
,!=
,>
,>=
,<
,<=
{{if user.cart.length > 0}}
View cart ({{user.cart.length}})
{{else}}
Cart is empty
{{/if}}
Cart is empty
A filter is a function that modifies the data sent to it, filters are separated by the pipe |
character.
{{variable|filterName}}
Filters are applied according to the type of data sent to it. Read more about filters here.
{cents:1012344}
{{cents}} cents is {{cents|$currency}}
1012344 cents is $10,123.44
Separate successive filters with pipe char |
and they will be applied in order.
{{message|uppercase|hyphenate)}}
GREEN-EGGS-AND-HAM
Extra arguments can be supplied to the filter using the following format:
{{variable|filterName1:extraArg1,extraArg2|filterName2:extraArg1,extraArg2}}
Eg:
{name:'Ken',surname:'Jones'}}
{{name|concat:'-',surname|lowercase}}
ken-jones
Output blocks can have a filter applied using the filter|%filter_name%
tag.
{{filter|md}}
### {{title}}
This is *rendered* as **HTML**.
{{/filter}}
<h3>Welcome!</h3>
<p>This is <em>rendered</em> as <strong>HTML</strong>.</p>
Complex expressions are safely resolved using safe-eval library.
Brackets, maths functions, filters, single and double quotes and variable names are all supported.
{price_cents_ex:1848, tax_rate:.1}
Price: {{'$' + Math.round(price_cents_ex*(1+tax_rate))/100 + " inc tax"}}
Price: $20.33 inc tax
Variables can be set using the set
tag. Dot syntax is supported.
{cart:[{price:1.32},{price:2.33},{price:5.43}]}
{{set cart_total=0}}
{{each cart as item}}
{{set cart_total=cart_total + item.price}}
{{/each}}
Total: {{'$' + cart_total}}
Total: $9.08
Blocks of the template can be captured to a variable using set %var_name%=...|%filters%
.
{{set receipt=...|uppercase}}
{{set cart_total=0}}
{{each cart as index,item}}
{{set cart_total=cart_total + item.price}}
Item {{index+1}} price is {{'$' + item.price}}
{{/each}}
Total is {{'$' + cart_total}}
{{/set}}
{{receipt}}
ITEM 1 PRICE IS $1.32
ITEM 2 PRICE IS $2.33
ITEM 3 PRICE IS $5.43
TOTAL IS $9.08
Plus equal (+=
) assignment is supported, eg. {{set receipt+=...}}
.
Template data can be loaded from other files efficiently using the syntax {{>filename.ext}}
.
First register any directories that contain the content to include:
jnr.registerIncludePath(path.join(__dirname,'inc'));
jnr.registerIncludePath(path.join(__dirname,'partials'));
Then call in the include:
{{>footer.md}}
If no extension is used, the default extension .jnr
will be assumed.
Sub-directories in the include path are supported.
{{>path/to/footer.md}}
Filters can be applied to the result.
{{>footer.md|filter1|filter2}}
Included files can include other files if required.
To perform the file operations using async operations, use the renderPromise
method.
jnr.renderPromise(tpl, data, options).then(console.log, console.error);
The contents of each file path are stored in memory for future reference by the jnr
instance.
Global options can be set for all future renders by overriding the jnr.options
property.
jnr.options = {filter:'clean|md', stripWhitespace:true}
Calling jnr.resetOptions()
will revert jnr.options
back to default settings.
Options can also be custom set for each render by passing in as an argument. These will override the global options.
jnr.render(template, data, {filter:'clean|md', stripWhitespace:'tags'})
Options can also be included as a top level property of the data parameter.
jnr.render(template, {var:'abc', options:{filter:'clean|md', stripWhitespace:'tags'})
options.filter
Apply global render filter to strings using the option property filter
. Will be applied to every string that is rendered.
jnr.render(template, data, {filter:'clean|md'})
options.stripWhitespace
This option defines how whitespace will be handled by rendering.
'all'
or true
Aggressively remove whitespace from all rendered strings using the option property stripWhitespace
. This will apply the string filter stripWhitespace
after rendering and applying any global filters.'tags'
Remove whitespace created by template tag declarations, will also collapse tabs contained within set
,if
,else
clauses.'none'
or false
No changes to whitespace will be made.jnr.render(template, data, {stripWhitespace:true}) // Same as 'all'
hello
{{if true}}
there !
{{/if}}
hello
there !
options.returnData
If set to true
the render function will return an object with 2 properties:
render.result
the result of the renderrender.data
a copy of the supplied data object including any set
variablesThis will allow access to the result of any set
declarations that occurred during a render.
{{set inlineMeta=...|yaml}}
men: [John Smith, Bill Jones]
women:
- Mary Smith
- {{firstName}} Williams
{{/set}}
var result = jnr.render(exp, data, {returnData:true});
console.log(result.data.inlineMeta.men[1]);
Bill Jones
Custom template tags can be defined using jnr.setTags(%opening_tag%,%closing_tag%)
jnr.setTags('%','%')
%page.greeting%
Welcome
data.options
take precedence over options
render param, cssmin
filter added, docs updated.jsmin
filter, filters accept curly brace object arguments {foo:bar}
. Docs update.+=
assignment support for set.tags
mode now collapses tabs. Single char var names not rendering bug fix.registerFilter()
added with new datatypes *
, arr
and obj
elseif
added[]
, mixed numeric and constant evalFAQs
A simple and powerful templating system supporting conditional logic, optional chaining, nested data sources, non string templates, ternary operators, looping control flow and custom processing functions.
The npm package jnr receives a total of 0 weekly downloads. As such, jnr popularity was classified as not popular.
We found that jnr 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
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
Security News
As cyber threats become more autonomous, AI-powered defenses are crucial for businesses to stay ahead of attackers who can exploit software vulnerabilities at scale.
Security News
UnitedHealth Group disclosed that the ransomware attack on Change Healthcare compromised protected health information for millions in the U.S., with estimated costs to the company expected to reach $1 billion.