-
Notifications
You must be signed in to change notification settings - Fork 12
Home
Bliss is a JavaScript-based template engine, inspired by ASP.NET Razor and Play! Framework.
Using Bliss, developers can utilize two very familiar languages: HTML and JavaScript. There is no hurdle in learning a new syntax or language, it is just JavaScript and HTML. Using Bliss's compact and expressive syntax, it minimizes keystrokes and enables a more fluid template coding experience. A bonus is that you can edit the templates in most text editors without any special extensions (as long as you name your templates with a .js.html
extension).
- Overview
- Syntax: The '@' Character
- Looping
- Conditionals
- Reusable Blocks as Functions
- Comments
- Composing
- Template Scope and Context
- Configuration
Bliss templates are simple text files containing JavaScript and HTML. The templates get compiled into JavaScript functions, which can be executed like any other function.
The following are the contents of orders.js.html
:
@!(customer,orders)
<h1>Welcome @customer.name!</h1>
<ul>
@orders.forEach(function(order){
<li>@order.title</li>
})
</ul>
You can then compile the template and receive the function to execute:
Bliss = require('bliss');
bliss = new Bliss();
template = bliss.compileFile('orders');
output = template(customer,orders);
You can also simply call render
with the template name and the parameters:
output = bliss.render('orders',customer,orders);
Bliss uses the @
as the single special character. Every time this character is encountered, it indicates the beginning of a JavaScript statement.
Hello @customer.name!
^^^^^^^^^^^^^
JavaScript
Bliss is able to detect simple statements. If you want to evaluate expressions, then you will need to wrap them in '(' and ')' (parenthesis):
Hello @(customer.firstName + customer.lastName)!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
JavaScript
You may also use block statements within {
and }
(curly braces):
@{name = customer.firstName + customer.lastName}
Hello @(name)!
You may also escape the @
by using @@
:
bob@@example.com
A template is a JavaScript function, as such, you can declare parameters for the template on the first line of the template:
@!(customer,orders)
You may also use the arguments
variable available to all JavaScript functions.
You can use JavaScript loop constructs (for, do-while, while), for comprehension and iterator functions.
<ul>
@products.forEach(function(product){
<li>@product.name ($@product.price)</li>
})
</ul>
Which is similar to:
<ul>
@for(var p=0; p<products.length; p++) {
@{product = products[p]}
<li>@product.name ($@product.price)</li>
}
</ul>
If statements are available:
@if (items) {
<h1>Nothing to display</h1>
}
else {
<h1>@items.length items!</h1>
}
You can declare functions within you templates and reuse them:
@function display(product) {
<li>@product.name ($@product.price)</li>
}
<ul>
@products.forEach(display)
</ul>
Comments should be wrapped in @*
and *@
:
@***********************
* Comment
***********************@
Template, being simple functions, can be composed in multiple ways using the @render()
function. The first argument to @render()
is the template file path. The subsequent arguments are the template parameters.
@render('layout',function(){
@render('sidebar');
... contents ...
})
Let's declare a layout.js.html
as:
@!(title,body)
<!DOCTYPE html>
<html>
<head>
<title>@title</title>
</head>
<body>
@body()
</body>
</html>
You will notice the template takes two parameter: a title and a body. The body will contain content which needs to be rendered, which means it should be a function. You can use the layout as:
@render("Home",function(){
<h1>Home page</h1>
})
You may want additional blocks in the layout, such a a sidebar, so you can declare the layout as:
@!(title,body,sidebar)
<!DOCTYPE html>
<html>
<head>
<title>@title</title>
</head>
<body>
<section id="sidebar">@sidebar()</section>
<section id="body">@body()<section>
</body>
</html>
And you can use the layout as:
@function sidebar() {
<h1>Sidebar</h1>
}
@function body() {
<h1>Home page</h1>
}
@render('layout',body,sidebar)
Partials are pieces of content which can be included into a page. Usually, these are small reusable pieces.
<section id="sidebar>
@render("sidebar")
</section>
Templates run in their own scope, thus not making global variables inaccessible during template execution.
You can expose variables to the template by adding them to the template's context. You can define a global context, used by all templates or a per-template context.
### Global ContextWhen you create a new Bliss instance, you can pass it a literal object containing a context. For example, I want to expose "underscore" as "_" to all templates:
bliss = new Bliss({
context: {
_: _
}
});
Each template compiled by this Bliss instance will have access to "_" as a global variable.
### Template ContextYou may also specify a context during template compilation. The template context will be merged with the global context.
bliss.compileFile("mytemplate.js.html",{
context: {
_: _
}
});
The Bliss engine allows some customization. Bliss accepts a literal object containing configuration options when creating a new instance:
bliss = new Bliss({
ext: ".js.html",
cacheEnabled: true,
context: {}
});
The following are the configuration options available:
### extThe file extension for template files. The default is js.html
.
Enables/disables template caching. The default is true
.
Context to be used by all templates compiled by the instance. The default is {}
. See Global Context for more information.