KnockOff
KnockoutJS to TAssembly compiler.
- Compiles a basic subset of KnockoutJS functionality to TAssembly, a simple JSON-based intermediate template representation.
- Builds a HTML5 DOM internally, ensures proper nesting.
- TAssembly performs context-sensitive escaping of all user-provided data.
- The overall solution is the fastest JS templating library in our micro-benchmarks, but yet provides the security benefits of much more expensive DOM templating libraries.
Usage
Simple example:
var ko = ; var template = ko model = id: "myId" body: "some text" ; console;
Compile to TAssembly for later execution:
var ko = ; var tassemblyTemplate = ko;// ["<div",["attr",{"id":"m.id"}],">",["text","m.body"],"</div>"]console;
Compile all the way to a function, and pass in TAssembly compilation options:
var ko = ; var options = // Define globals accessible as $.* in any scope globals: { return x; } // Define partial templates. // This one uses the global echo function defined above. partials: userTpl: '<span data-bind="text: $.echo(name)"></span>' ; // Our simple template using KnockOut syntax, and referencing the partialvar templateString = '<div data-bind="template: { name: \'userTpl\', data: user }"></div>'; // Now compile the template & options into a function.// Uses TAssembly internally, use toTAssembly option for TAssembly output.var templateFn = ko; // A simple model objectvar model = user: name: "Foo" ; // Now execute the template with the model.// Prints: <div><span>Foo</span></div>console;
Partials are expected to be in KnockOff syntax, and will be compiled to TAssembly automatically.
KnockOff spec
KnockOff supports a subset of KnockOut functionality. The biggest differences are:
-
No reactivity. KnockOff aims for speed and one-shot operation.
-
Limited expression syntax. KnockOut supports arbitrary JS, while we restrict ourselves to literals (including objects), model access and function calls. The usual KnockOut model accessors are supported. In addition, a global
$
object is defined, which can be populated with theglobals
compile time option.
text
Emit text content. HTML-sensitive chars are escaped. Options is a single expression:
See also the KnockOut docs for text
.
foreach
Iterate over an array. The view model '$data' in each iteration is each member of the array.
If each array element is an object, its members will be directly accessible in the loop's view model:
You can pass in the name of a partial instead of the inline template.
$index
, $parent
and other context properties work just like in
KnockOut.
See also the KnockOut docs for foreach
.
template
Calls a template (inline or name of a partial) with a given model.
See also the KnockOut docs for template
.
with
The with binding creates a new binding context, so that descendant elements
are bound in the context of a specified object. It evaluates a nested block
iff
the model object is truish.
See also the KnockOut docs for with
.
if
Evaluates a block or template if an expression is true.
Here is a message. Astonishing.
See also the KnockOut docs for if
.
ifnot
Evaluates a block or template if an expression is false.
No message to display.
See also the KnockOut docs for ifnot
.
attr
Emit one or more HTML attributes. Automatic context-sensitive escaping is applied to href, src and style attributes.
Report
See also the KnockOut docs for attr
.
visible
Hides a block using CSS if the condition is falsy.
You will see this message only when "shouldShowMessage" holds a true value.
Currently this uses display: none !important;
inline, but we could also
add a class instead. Let us know which you prefer.
See also the KnockOut docs for visible
.
Virtual elements / container-less syntax
You can use Knockout's comment syntax to apply control flow bindings (if
,
ifnot
, foreach
, with
) to arbitrary content outside of elements:
This item always appears <!-- ko if: someExpressionGoesHere --> I want to make this item present/absent dynamically <!-- /ko -->
See also the KnockOut docs for
if
and other
control flow bindings.
Model access and expressions
KnockOff supports a restricted set of simple JS expressions. These are a subset of KnockOut's arbitrary JS. A KnockOff expression will normally also be a valid KnockOut expression.
- Literals:
- Number
2
or3.4
- Quoted string
'Some string literal'
- Object
{foo: 'bar', baz: someVar}
- Number
- Variable access with dot notation:
foo.bar
- Array references:
users[user]
- Function calls:
$.i18n('username', {foo: bar} )
; nesting and multiple parameters supported
Expressions have access to a handful of variables defined in the current context:
$data
- current view model$root
- root (topmost) view model$parent
- parent view model$parents
- array of parent view models$parentContext
- parent context object$index
- current iteration index in foreach$
- globals defined at compile time; typically used for helper functions which should not be part of the model (i18n etc). This is an extension over KnockOut, which can be replicated there using expression rewriting.