
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
paperclip-fast
Advanced tools
Paperclip is a very fast template engine for JavaScript.
Paperclip templates are translated from HTML, straight to JavaScript - this also includes data-bindings. For example, here's a template:
hello {{name}}!
Here's the templated translated to JavaScript:
module.exports = (function(fragment, block, element, text, comment, parser, modifiers) {
return fragment([text("hello "), block({
'value': {
run: function() {
return this.context.name;
},
refs: [ ["name"] ]
}
})]);
});
Pretty clear what's going on. Here's what we know at a glance:
cloneNode() whenever a template is used.As it turns out, the method above for generating templates is very efficient. Essentially, paperclip does the least amount of work necessary to update the DOM since it know where everything is.
Paperclip will also lazily batch DOM changes together into one update, and run them on requestAnimationFrame. This kind of optimization is similar to how layout engines work, and helps prevent unnecessary performance penalties in the browser.
npm install paperclip --save-exact
Creates a new template
var pc = require("paperclip");
var template = pc.template("hello {{name}}!");
context - Object, or BindableObject
binds the template to a context, and returns a document fragment
var pc = require("paperclip");
var template = pc.template("hello {{name}}!");
var view = template.bind({ name: "Bull Murray" });
document.body.appendChild(view.render()); // will show "hello Bill Murray"
registers a new modifier. Here's a markdown example:
var pc = require("paperclip");
pc.modifier("markdown", require("marked"));
var template = pc.template("{{ content | markdown }}");
document.body.appendChild(template.bind({
content: "hello **world**!"
}).render());
Variable blocks as placeholders for information that might change. For example:
hello {{ name.first }} {{ name.last }}!
You can also specify blocks within attributes.
my favorite color is <span style="color: {{color}}">{{color}}</span>
Paperclip also supports inline javascript. For example:
hello {{ message || "World" }}! <br />
inline-json {{ {'5+10 is':5+10, 'message is defined?' : message ? 'yes' : 'no' } | json }}
Modifiers format data in a variable block. A good example of this might be presenting data to the user depending on their locale, or parsing data into markdown. Here are a few examples of how you can use modifiers:
Converting content to markdown:
{{ html: content | markdown }}
Uppercasing & converting to markdown:
{{ html: content | uppercase | markdown }}
Modifiers with parameters:
A human that is {{age}} years old is like a {{ age | divide(5.6) }} year old dog!
Paperclip comes with various binding operators that give you full control over how references are handled. You can easily specify whether to bind one way, two ways, or not at all. Here's the basic syntax:
Two-way binding:
<input class="form-control" data-bind="{{ model: <~>fullName }}" />
Bind input value to fullName only:
<input class="form-control" data-bind="{{ model: ~>fullName }}" />
Bind fullName to input value only:
<input class="form-control" data-bind="{{ model: <~fullName }}" />
Unbound helper - don't watch for any changes:
{{ ~fullName }}
Similar to escaping content in mustache ({{{content}}}). Good for security.
Unsafe:
{{ html: content }} <br />
Safe:
{{ content }} <br />
Conditional block helper
<input type="text" class="form-control" placeholder="What's your age?" data-bind="{{ model: <~>age }}"></input>
{{#if: age >= 18 }}
You're legally able to vote in the U.S.
{{/elseif: age > 16 }}
You're almost old enough to vote in the U.S.
{{/else}}
You're too young to vote in the U.S.
{{/}}
data-bind attributes are inspired by knockout.js. This is useful if you want to attach behavior to any DOM element.
Input data-binding
<input type="text" class="form-control" placeholder="Type in a message" data-bind="{{ model: <~>message }}"></input>
<h3>{{message}}</h3>
Notice the <~> operator. This tells paperclip to bind both ways. See binding operators for more info.
Executed when an event is fired on the DOM element. Here are all the available events:
onChange - called when an element changesonClick - called when an element is clickedonLoad - called when an element loads - useful for <img />onSubmit - called on submit - useful for <form />onMouseDown - called on mouse downonMouseUp - called on mouse uponMouseOver - called on mouse overonMouseOut - called on mouse outonKeyDown - called on key downonKeyUp - called on key uponEnter - called on enter key uponDelete - called on delete key up<input type="text" class="form-control" placeholder="Type in a message" data-bind="{{ onEnter: enterPressed = true, focus: true }}"></input>
{{#if: enterPressed }}
enter pressed
{{/}}
Toggles the display mode of a given element. This is similar to the {{if:expression}} conditional helper.
Sets the css of a given element. For example:
how hot is it (fahrenheit)?: <input type="text" class="form-control" data-bind="{{ model: <~>temp }}"></input> <br />
<style type="text/css">
.cool { color: blue; }
.warm { color: yellow; }
.hot { color: red; }
</style>
<strong data-bind="{{
css: {
cool : temp > 0 || !temp,
warm : temp > 60,
hot : temp > 90
}
}}">
{{
temp > 60 ?
temp > 90 ? "it's hot" : "it's warm" :
"it's cool"
}}
</strong>
Sets the style of a given element.
color: <input type="text" data-bind="{{ model: <~>color }}" class="form-control"></input> <br />
size: <input type="text" data-bind="{{ model: <~>size }}" class="form-control"></input> <br />
<span data-bind="{{
style: {
color : color,
'font-size' : size
}
}}">Hello World</span>
Toggles the enabled state of an element.
<button data-bind={{ disable: !formIsValid }}>Sign Up</button>
Focuses cursor on an element.
<input data-bind={{ focus: true }}></input>
Registers a new block binding class. Block bindings allow you to modify how templates behave. Some examples
include the {{#if:condition}}{{/}}, and {{html:content}}.
Base class to extend when creating custom block bindings. Here's an example for a components binding:
var pc = require("paperclip");
var ComponentBlockBinding = pc.BaseBlockBinding.extend({
bind: function (context) {
this.view = this.template.bind();
this.section.appendChild(this.view.render());
pc.BaseBlockBinding.prototype.bind.call(this, context);
},
_onChange: function (properties) {
this.view.context.setProperties(properties);
}
});
pc.blockBinding("hello", ComponentBlockBinding.extend({
hello: pc.template("hello <strong>{{message}}</strong>!")
});
template:
{{ hello: { message: "world" }}}
Called when the block is added, and bound to the DOM. This is where you initialize your binding.
Be sure to call paperclip.BaseBlockBinding.prototype.bind.call(this, context) if you override.
this method
Called when the block is removed from the DOM. This is a cleanup method.
Called whenever the properties change for the block binding. These properties are defined in the template. Here's the syntax:
{{blockName: blockProperties }}
the node factory for creating elements. Use this to make your block binding compatible with the NodeJS and the browser.
the name registered for the block binding
the document section which contains all the elements
the content template - this might be undefined if your block binding doesn't have {{#block:properties}}content{{/}}.
The child block template. Used in the conditional block.
FAQs
controller logic:
We found that paperclip-fast 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
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.