Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Mustache is a simple, restricted, fast template language inspired by ctemplate. There is a great introduction to the language here on github. And a nice overview of the different tags at the ruby implementation.
Amulet began as a fork of the v2 branch of raycmorgan's Mu. I eventually changed so much of the API that I decided to rename it. Amulet attempts/intends to implement all of the Mustache specification, except that it does not always honor the whitespace requirements, which, for the purposes of HTML, does not matter. (Obeying the white-space conventions is on the to-do list.)
layout.mu
<!DOCTYPE html>
<meta name="engine" content="amulet">
<div id="container">
{{<}}
</div>
hello.mu
<p>Hello world!</p>
fib.mu
<h2>{{header}}</h2> {{{spacer}}}
<!-- the spacers are there just to convince
your browser that it has enough content
to merit rendering -->
<p>One: {{one}}</p> {{{spacer}}}
<p>Ten: {{ten}}</p> {{{spacer}}}
<p>Hundred: {{hundred}}</p> {{{spacer}}}
<p>Thousand: {{thousand}}</p>
app.js
var amulet = require('amulet');
var spacer = (new Array(100)).join(' ');
require('http').createServer(function(req, res) {
if (req.url === '/fib') {
res.writeHead(200, {'Content-Type': 'text/html'});
var context = {header: 'Fibonacci sequence', spacer: spacer};
var renderer = amulet.render(res, ['layout.mu', 'fib.mu'], context, true);
var a = 0, b = 1, c = -1, i = 0;
(function next() {
for (var j = 0; j < 500000; j++) {
var dummy = Math.random();
}
c = a + b;
a = b;
b = c;
if (i === 1)
renderer.extendContext({one: c});
if (i === 10)
renderer.extendContext({ten: c});
if (i === 100)
renderer.extendContext({hundred: c});
if (i === 1000)
renderer.extendContext({thousand: c});
i++;
if (i < 1001)
process.nextTick(next);
})();
}
else {
amulet.render(res, ['layout.mu', 'hello.mu']);
}
}).listen(8080);
This example code can be found in example/
The main function, amulet.render
, can be called in a few variations. The basic signature is function(output, templates, context, asap, callback)
, but a number of the arguments are optional (output
is the only required argument):
With callback:
amulet.render(res, ['layout.mu', 'page.mu'], context, true, function() {
console.log("Done rendering!");
});
asap
defaults to false:
amulet.render(res, 'static.mu', function() { console.log("Done!"); });
With single template:
var renderer = amulet.render(res, 'one.mu', {first: 'Chris'}, true);
amulet.render
always returns a Renderer object, which is useful if you want a way to add context or force it to end.
one.mu
<h3>{{first}} {{last}}</h3>
<p>{{description}}</p>
app.js (snippet):
renderer.extendContext({last: 'Brown'});
At this point, the renderer would output up to the <p>
and then pause, waiting for the description variable to be filled.
But if you decide you want it to skip over the missing variables,
as any basic Mustache spec would do:
renderer.force();
Which sets asap
to false, and immediately streams through the rest of your template.
Mu is faster for certain benchmarks, because the template rendering itself is synchronous. Amulet does everything A.S.A.P. (as soon as possible), so it will start rendering your templates before any of your context variables are available, only halting when it encounters a missing variable. This functionality is optional -- if you want to render a template with one command, you still can.
PHP appears so fast (while sucking so much at everything else) because it renders as soon as possible, so that the top 90% of the page gets rendered before some cpu-intensive bit gets called to render the footer. That's what Amulet does, too, basically.
Like Mu, Amulet
Beyond Mu, Amulet
Amulet is Mustache and then some:
If a method is in global scope, you can pipe a variable through it:
<pre>{{{doc | JSON.stringify}}}</pre>
Which would return something like
<pre>{"_id": "0x1"}</pre>
Instead of having to nest sections to dig into an object:
{{#obj}}
{{#prop}}
{{val}}
{{/prop}}
{{/obj}}
You can just dot a path. Like javascript.
{{obj.prop.val}}
Don't repeat yourself; namely, don't use XML-type redundancy. A Mustache template is a directed acyclic graph (DAG), i.e. a tree, meaning that a closing node is never ambiguous. You needn't tell the Amulet parser what you're closing. It already knows.
{{#obj}}
{{#prop}}
{{val}}
{{/}}
{{/}}
When rendering a template hierarchy, use a <
in your master layout (the opposite of the partial symbol >
):
layout.mu
<!DOCTYPE html>
{{<}}
index.mu
<p>Just the facts.</p>
Output of amulet.render(response, ['layout.mu', 'index.mu'])
:
<!DOCTYPE html>
<p>Just the facts.</p>
To make it easier to remember what <
does, you can also write {{<yield}}
or even {{<yield/>}}
to make your syntax highlighter happy. As soon as the parser sees the <
character, it will skip to the end of the mustache tag.
To keep better track of scope, you can name your sectioned variables with the ->
symbol:
{{#people -> person}}
{{person.first_name}}
{{/}}
Otherwise, you can access the local scope nakedly or with a _
:
{{#people}}
{{_.first_name}}
{{last_name}}
{{/}}
There are 14 failing tests right now. but it's not a big deal, since those are all edge cases of the formal Mustache spec.
You'll need to grab the submodules along with the repository to run tests:
git clone --recursive https://github.com/chbrown/amulet.git
Or if you've already cloned the repository:
git submodule update --init --recursive
And then just run tap test
in the root directory (i.e., in the same directory as this README.md
file).
Copyright © 2011–2013 Christopher Brown. MIT Licensed.
FAQs
As-soon-as-possible streaming async mustache templating
The npm package amulet receives a total of 4 weekly downloads. As such, amulet popularity was classified as not popular.
We found that amulet 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.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.