Compatibility - The language syntax of Blade is very similar to Jade's. Jade is
an awesome templating language, and if you are already familiar with it, getting
started with Blade should take you very little time.

Smarter file includes
Files compiled in Blade can be much smaller than Jade files when you are using file
includes because file includes happen at runtime instead of at compile-time. If you
re-use the same included file among multiple views, the included file does not need to
be reloaded.

Blocks in Blade are awesome. We removed features from Jade like explicit
template inheritance and then added features like blocks and parameterized blocks.
You might find our idea of a block to be similar to Jade's, but just wait until you
realize how much more flexible they are!

Just Functions, not mixins or partials. In Blade, there are no "mixins"
or partial templates. There are only functions, and they work just like regular JavaScript
functions that you've come to know and love. You can put your functions into separate
files and include them into other templates, you can take advantage of the arguments
Array-like Object, or whatever you want!

Other cool features For example, Blade provides a built-in syntax for taking
content rendered by a function and loading it into a variable within your view template,
allowing you to pass rendered HTML content to another function. This is just one of
the many new features you can utilize when you make the switch to Blade.

Jade vs. Blade

OK... it's admittedly not as funny as I thought it would be. But, I tried.

Project Status

I'd say that Blade is stable. There are very few (if any)
known issues, and I think that Blade
is ready for production environments. I use Blade for many of my projects.

If you find a bug, please report it here. If you include the Blade code
that failed along with the expected HTML output, that is always splendid.

By all means, please feel free to submit pull requests for new features,
new tests, or whatever! For big changes, say ~100 lines of code, you
might want to contact me first or submit an issue before getting started.

Syntax

Tags

Like Jade, a tag is simply a word. For example, the string html will render to <html></html>.

You can have 'id's:

div#awesome

which renders as <div id="awesome"></div>.

Any number of classes work, separated by a dot (.)

div.task-details.container

which renders as <div class="task-details container"></div>.

Tag attributes? Yep, they work pretty much like Jade, too.
Put attributes in parenthesis, separate attributes with a comma, space, newline, or whatever.

a(href="/homepage", onclick="return false;") renders as:

<ahref="/homepage"onclick="return false;"></a>

You can also have line feeds or weird whitespace between attributes, just like in Jade.
Whatever. This works, for example:

input(
type="text"
name="email"
value="Your email here"
)

You can also put substitute an attribute value with vanilla JS code like this:
input(type="text" name="contact-"+name value=value). For example, if you passed the object
{name: "fred", value: "testing"} to your view, the above would render to:
<input type="text" name="contact-fred" value="testing"/>

You cannot put whitespace, commas, newlines, or parentheses in the vanilla JavaScript code,
though. Blade uses these characters to separate each attribute or to end the tag definition.

And, yes... the class attribute is handled with extra special care. Pass an array or string.
Classes (delimited by ".") from before will be merged with the value of the class attribute.

Blade just assumes anything without a tag name specifier is a <div> tag.

Also, tags without matching ending tags like <img/> render properly.

Indenting

It works. You can indent with any number of spaces or with a single tab character. The
only rule is to be consistent within a given file.
Jade gives you a lot of weird indent flexibility. Blade, by design, does not.

html
head
body
#content

renders as:

<html><head></head><body><divid="content"></div></body></html>

You can start a tag name with a bashslash to escape Blade keywords.
Normally, include test would include a file, but \include test renders as:

<include>test</include>

This allows you to be flexible with tag names, so you are not restricted to rendering
HTML, for example. You can render any XML document with Blade.

Text

It works, too. Simply place content after the tag like this:

p This text is "escaped" by default. Kinda neat.

renders as:

<p>This text is &quot;escaped&quot; by default. Kinda neat.</p>

Want unescaped text? Large blocks of text? Done.
Start a line of text with a |.

p! This will be <strong>unescaped</strong> text.
|
How about a block? (this is "escaped", btw)
Yep. It just works!
Neato.

renders as:

<p>This will be <strong>unescaped</strong> text.
How about a block? (this is &quot;escaped&quot;, btw)
Yep. It just works!
Neato.</p>

Rules are:

Text is escaped by default.

Want unescaped text? Precede with a !

Precede with a = to evaluate and output some JavaScript.

Large text block? Use | and indent properly.

Unescaped text block? Use |! or even just ! works.

JavaScript code block? Use |= or even just = works.

Unescaped JavaScript code block? Yep. Use |!= or !=.

Newlines in text blocks are preserved.

Variable interpolation is supported for text blocks. Use #{var_name} notation, and
anything between the curly braces is treated as vanilla JavaScript code.

Filters are essentially functions that accept a text string and return HTML. They
cannot modify the AST directly. Also, you cannot inject JavaScript code into
filters.

You can add custom filters at compile-time using the API.

Variable interpolation is supported for certain text filters, as well. If a text
filter returns text in #{var_name} notation, then anything between the curly braces
is replaced with vanilla JavaScript code. To avoid this behavior, text filters can
either escape the #{stuff} with a backslash, or it can set its interpolation
property to false.

Code

Use dash (-) to indicate that JavaScript code follows, which will not output into
the template. As before, use equals (=) to specify code output. A few examples, please?

When inserting lines of code with -, curly braces or semicolons are inserted, as
appropriate. In the example above, we have an if statement followed by an indented
paragraph tag. In this case, Blade wraps the indented content with curly braces.
If there is no indented content beneath the line of code, then a semicolon is appended
instead.

Code that outputs (i.e. a code block or at the end of a tag).
As mentioned before, it's just like a text block, except with an =.

To comment out entire sections of Blade code, you can use non-rendering block comments
with a text block.

//-
|
anything can go here... Blade code, JavaScript code, whatever...
just make sure that the indenting is right.

or... even better... just use C-style block comments. Begin with /* to generate
a non-rendering block comment, or begin with /** to generate a regular comment.
End the comment with */. These comments are not parsed like // comments.

The above code will automatically register the 'onchange' event handler with
the corresponding input tags.

As shown in the example, your event handler may reference this (the DOM
element that triggered the event) or e (the browser's event Object). Be
aware that every browser's event Object might be slightly different,
especially in legacy browsers. In addition, if you are rendering the template
in the browser (i.e. using client-side templates), your event handler will
have access to the view's locals.

Functions

Functions are reusable mini-templates. They are similar to 'mixins' in Jade.

Note: when you define a block (see below) within a function, and you output the rendered
content to a variable, the block will be destroyed immediately after the function call.

Yes, you can use arguments within your function, just like a "real" JavaScript function.
In fact, functions are "real" JavaScript functions, so even closures work! Although, remember
that functions have access to the variables in scope at the time the function was defined, not
the variables in scope when the function is called.

Adding classes or an id to rendered function content

which would render as <div id="foobar" class="dialog foo bar">Blade is awesome</div>.

Although, if you try it with something like this, you get an error because the first
child rendered by the function is not a tag.

function dialog(msg)
= msg
call dialog("Blade is awesome")#foobar.foo.bar
//compiler might generate an error, or it might just ignore the id and classes

Dynamic file includes

include "file.blade"

This will insert "file.blade" right into the current view at runtime, as if the contents
of the included file were copied right into the current view.

If you don't know the name of the file to be included until runtime, that's no problem.
The include statement can also be followed by the name of a JavaScript variable
containing the filename to be included. These are called dynamic filename includes.

- var filename = "file.blade"
include filename

CAUTION: When using dynamic filename includes in the browser, be sure that you
have properly loaded all views that might be included into the browser's cache before
executing the view containing the dynamic filename include. See the implementation
details for a more detailed explanation.

If you do not specifiy a file extension, .blade will be appended to your string
internally.

You may also place an include inside of a function, block, or chunk.

Finally, you can specify which local variables should be passed to the included view
template by using the exposing keyword. By default, Blade will pass the parent's
local variables to the included template; however, when using the exposing keyword,
you can specify exactly which variables are to be exposed to the included template.

In the example above, variables i and text are exposed to "foobar.blade";
the header variable will not be accessible from "foobar.blade".

Blocks

Blocks allow you to mark places in your template with code that may or may not be
rendered later.

You can do a lot with blocks, including template inheritance, etc. They behave quite
differently from Jade.

There are two types of blocks: regular blocks and parameterized blocks.

Regular blocks

Regular blocks are defined using the "block" keyword followed by a block name. Then,
you optionally put indented block content below. Like this:

block regular_block
h1 Hello
p This is a test

Assuming nothing else happens to the block, it will be rendered as
<h1>Hello</h1><p>This is a test</p> as expected. Empty blocks are also permitted.
A simple, empty block looks like this: block block_name

Of course, the purpose of declaring/defining a block is to possibly modify it later.
You can modify a block using three different commands:

Use the append keyword to append to the matching block.

Use the prepend keyword to prepend to the matching block.

Use the replace keyword to replace the matching block.

Example:

append regular_block
p This is also a test

Replacing a block

Replacing a block is somewhat confusing, so I will explain further. If you replace
a block, you are not changing the location of the defined block; you are only
replacing the content of the block at its pre-defined location. If you want to change
the location of a block, simply re-define a new block (see below).

In addition, when you replace a block, all previously appended and prepended content is
lost. The behavior is usually desired, but it can sometimes be a source of confusion.

If you replace a parameterized block (described below) with a regular block, you cannot
call "render" on that block.

You can replace a regular block with a parameterized block (described below). This will
also clear the contents of the block, as expected.

Parameterized blocks

The other type of block is called a parameterized block, and it looks like this:

block param_block_yo(headerText, text)
h1= headerText
p= text

Parameterized blocks do not render automatically because they require parameters.
Therefore, assuming nothing else happens to the block, the block will not be rendered
at all.

To render a block, use the "render" keyword like this:

render param_block_yo("Some header text", 'Some "paragraph" text')

Now, assuming nothing else happens to the block, the block will be rendered as:

<h1>Some header text</h1><p>Some &quot;paragraph&quot; text</p>

You can render as many times as you wish, and by default, the rendered content will
be appended to the block. You can also prepend the rendered content to the block or
replace the contents of the block with rendered content. Here are the variations:

What happens if I define the same block more than once?

You can re-define a block that has already been defined with another "block"
statement. This completely destroys the previously defined block.
Previously executed "append", "prepend", "replace", and "render" blocks do not affect the
re-defined block.

In summary...

Use the block keyword to mark where the block will go (block definition).

Use the render keyword to render the matching "parameterized" block.
Do not use this on a regular block.

Use the append keyword to append to the matching block.

Use the prepend keyword to prepend to the matching block.

Use the replace keyword to replace the matching block.

You may not render, append to, prepend to, or replace undefined blocks. If you do so,
an error message will occur.

When you define a block within a function, and you output the function's rendered
content to a variable, the defined block will be destroyed immediately after
the function call.

Chunks

Chunks are simply functions that return HTML. They behave a bit differently than
conventional Blade functions.

Functions are called with call statements, and their rendered content is injected
right into a template. You can also capture the HTML they render by outputting to a
variable, as described above. Chunks, on the other hand, always return HTML, and they
cannot be called using call statements. The only way to render a chunk is to call it
via your code (see example below).

The above example defines a named chunk header with one parameter. Then, the chunk
is called by calling the __.chunk.header function. When defining a chunk, parameters
are optional, and if you omit the name, the chunk is simply named last.

Another example:

chunk
h1 Hello!
div
!= __.chunk.last()

renders as <div><h1>Hello!</h1></div>

If you override the templateNamespace compiler option, you will need to replace all
instances of the double underscore (__) variable with the templateNamespace variable.

API

var blade = require('blade');

blade.compile(string, [options,] cb)

Compiles a Blade template from a string.

string is a string of Blade

options include:

filename - the filename being compiled (required when using includes or the cache option)

cache - if true, the compiled template will be cached (defaults to false)

minify - if true, Blade generates a minified template without debugging
information (defaults to true if cache option is set; false, otherwise)
If UglifyJS is installed, Blade
may automatically compress or prettify the template depending on whether
minify is true or false.

includeSource - if true, Blade inserts the Blade source file directly into
the compiled template, which can further improve error reporting, although
the size of the template is increased significantly. (defaults to true if
and only if process.env.NODE_ENV is "development" and minify is false;
defaults to false, otherwise)

doctypes - use this Object instead of blade.Compiler.doctypes

selfClosingTags - use this array instead of blade.Compiler.selfClosingTags

filters - use this Object instead of blade.Compiler.filters

templateNamespace - the name of the reserved variable in the view
(defaults to two underscores: __). Other reserved names are
listed here

basedir - the base directory where Blade templates are located. This option is
primarily used by the Blade middleware to allow the Blade runtime to properly
load file includes.

cb is a function of the form: cb(err, tmpl) where err contains
any parse or compile errors and tmpl is the compiled template.
If an error occurs, err may contain the following properties:

message - The error message

expected - If the error is a 'SyntaxError', this is an array of expected tokens

found - If the error is a 'SyntaxError', this is the token that was found

filename - The filename where the error occurred

offset - The offset in the string where the error occurred

line - The line # where the error occurred

column - The column # where the error occurred

Note: if there is a problem with the Blade compiler, or more likely, if there
is a syntax error with the JavaScript code in your template, Node.js will not
provide any line number or other information about the error. At the time of this
writing, this is a limitation of the Google V8 engine.

You can render a compiled template by calling the function: tmpl(locals, cb)

locals are the local variables to be passed to the view template

cb is a function of the form function(err, html) where err contains
any runtime errors and html contains the rendered HTML.

In addition, a compiled template has these properties and methods:

template - a function that also renders the template but accepts 3 parameters:
tmpl.template(locals, runtime, cb). This simply allows you to use a custom
runtime environment, if you choose to do so.

filename - the filename of the compiled template (if provided)

dependencies - an array of files that might be included by this template at
runtime

unknownDependencies - if true, this template uses dynamic filename includes
and may include any file at any time.

toString() - a function that converts the view template function into a string
of JavaScript code. If you need a client-side template for example, you can
use this function. UglifyJS is now used
if you have it installed.

blade.compileFile(filename, [options,] cb)

Asynchronously compile a Blade template from a filename on the filesystem.

filename is the filename

options - same as blade.compile above, except filename option is always
overwritten with the filename specified. There is also a synchronous
option that will tell Blade to read and compile the file synchronously
instead of asynchronously.

cb - same as blade.compile above

blade.renderFile(filename, options, cb)

Convenience function to compile a template and render it.

filename is the filename

options - same as blade.compileFile above. This object is also passed
to the view, so it should also contain your view's local variables.
A few reserved local variables are removed
before passing the locals to the view.

cb - a function of the form function(err, html)

blade.middleware(sourcePath, options)

Express middleware for serving compiled client-side templates to the browser.
For example, if you visit the URL "/views/homepage.blade" on your server, you
can compile the view stored at sourcePath + "/homepage.blade"

sourcePath - the path on the server where your views are stored

options include:

mount - the URL path where you can request compiled views (defaults to
"/views/")

runtimeMount - the URL path where the minified Blade runtime is served
to the browser (defaults to "/blade/blade.js"). Use null to disable
this functionality.

pluginsMount - the URL path where Blade plugins will be served to the
browser (defaults to "/blade/plugins/"). Use null to disable this
functionality.

Browser Usage

The Blade compiler doesn't work on browsers yet, but the runtime should work
on every browser. That means that you can compile your templates on the server
and serve them up to any browser. Blade provides a built-in Express middleware
to do just that (see above).

Once you have the middleware setup, you can now serve your compiled Blade views
to the client. Simply include the /blade/blade.js file in your <script>
tags, and then call blade.runtime.loadTemplate.

blade.runtime.loadTemplate(filename, cb)

filename - the filename of the view you wish to retrieve, relative to the
sourcePath you setup in the Blade middleware.

Plugins

** Live UI **

Blade provides a Live UI plugin that allows Blade to support live binding. Live binding
provides automatic two-way synchronization between your models and views on a given web
page. That is, when data in your Model is updated, the rendered Blade views on the
client's browser are automatically updated with the new content, and similarly, when a
Blade view is rendered in the browser, the Blade event handlers can
update data in the model.

Complete documentation for the Live UI plugin (including several examples) can be found
on the Live UI Plugin wiki page.

Eventually, the Live UI plugin might live in a separate repository and work for any
templating language.

** definePropertyIE8 **

This plugin is a prerequisite for the Live UI plugin if you plan on using Live UI in
Internet Explorer 8.

** Extra Runtime **

Adds some additional functions to the Blade runtime that help support the Live UI plugin.
The Extra Runtime may be merged with the Live UI plugin at a later date.

Meteor Support

Blade also provides a Meteor smart package
under the meteor directory. At the time of this writing, Blade is not a part of the
Meteor core smart package list. The easiest thing to do right now is to symlink that
directory into your Meteor packages directory like this:

ln -s /path/to/.../blade/meteor /path/to/.../meteor/packages/blade

Of course, the actual path where Blade and Meteor are installed on your system may vary.
You need to replace the above command with the correct paths, as appropriate.

Implementation Details

PEG.js

The Blade parser is built using PEG.js.
Thanks to the PEG.js team for making this project much easier than I had
anticipated! To modify the parser, simply change ./lib/parser/blade-grammer.pegjs,
and the new parser will be automatically built the next time you run tests.

Running tests

To install all devDependencies, just do: npm link or install manually.
To run tests, ensure devDependencies are installed, then run: npm test

Compiler-runtime relationship

Also, I'd like to mention here that the Blade compiler and Blade runtime are rather
closely coupled. Unfortunately, that means that templates compiled with an older
Blade compiler might not be compatible with a newer runtime and vice versa.
To avoid issues, be sure that your Blade templates were compiled with the compiler of
the same version as the runtime on which they will run. If you think this is too
inconvenient, please feel free to complain, but I probably will ignore you. :)

File Includes

Included Blade templates MUST be loaded synchronously, and if this is not possible, an
error will be thrown. Obviously, when rendering views on the server, this is not a
problem since Node provides synchronous file system calls; however, on the client, it is
only possible to include a file synchronously when the file is already in the browser's
cache. When the name of the file to be included is known at compile-time (i.e. you are
not using a dynamic filename include), the compiler will notify the Blade middleware
of a particular view's dependencies. This allows the client-side template loader to
also load and cache any dependent views in advance, preventing any issues from occurring.
Nevertheless, when dynamic filename includes are used, the compiler has no way of
determining which views will be included at runtime, and if a dynamically included view
is not loaded into the browser's cache when the include statement is reached, the
included view must be be loaded asynchronously and, as such, an error will be thrown.

Loading and compiling files synchronously may temporarily reduce your application's
responsiveness, but because compiled views are often cached, this is not really much
of an issue.

Event Handlers

Event handlers in Blade work by injecting the event handler function as an HTML comment
directly before the bound element. Then, the appropriate event attribute (i.e.
onclick, onchange, etc.) on the element is set to call blade.runtime.trigger. The
trigger function basically grabs the HTML comment, passes the contents through eval(),
and binds the event handler directly to the element. This means that the event handlers
work on templates rendered on the browser or on the server. Everything gets wired up the
first time that the event occurs on the browser.

The Blade runtime also keeps track of any event handlers bound to a specific element
by assigning each element an 'id' attribute, if necessary. When the view has
finished rendering, the Blade runtime will pass a bunch of information (chunks, blocks,
functions, or event handlers that were defined, etc.) to the 3rd (undocumented) argument
of the render callback function. If you are rendering Blade templates on the browser,
you can access the list of event handlers and bind the defined event handler directly
to the element by looking up the element by its 'id' instead of letting the trigger
function do its magic. The advantage of binding direclty to the defined event handler is
that (thanks to closures) you can still reference the locals that were passed to your
view and modify them, as needed... directly from your event handler. This allows your view
code to automatically synchronize with your model, providing one-way view-to-model
synchronization capabilties. Very cool! For examples of this and for more information,
check out the Live UI plugin.