0.10.5 • Published 11 years ago

Templ8 v0.10.5

Weekly downloads
38
License
-
Repository
github
Last release
11 years ago

#TODO:

  • documentation is not yet complete
  • add unit tests (already have tests: just wanting to port them from my own framework to an existing one like JSTestDriver or something).

Templ8

Templ8 as you can probably guess is a JavaScript template engine, with a Django'ish style of syntax.

It's fast, light weight and unlike a lot of other JavaScript template engines: Templ8 does not use the JavaScript with statement. This actually makes Templ8 parse templates faster than it would if it did use the with statement!

Templ8 does not restrict you to generating HTML. All outputs are strings so if you want to generate HTML, CSS, JavaScript or whatever, the choice is yours...

Usage

Templ8 is avaiable as a Node JS module as well as a browser micro-framework.

Node

Installation

   npm install Templ8

Requiring

   var Templ8 = require( 'Templ8' );

Browser

You have 2 options.

  1. Templ8.js/ Templ8.min.js are the dev/ prod versions optimised for modern browsers (i.e. browsers that have implemented all of the items in kangax's es5 compatability table).
  2. Templ8.shim.js/ Templ8.shim.min.js are as above, except that wedgES – only an extra 1.6kb – has been included to enable backwards compatibility with older browsers.

NOTE: Safari <= 5.1.3 still has not implemented Function.prototype.bind so you will need to use Templ8.shim.js for Safari.

NOTE: The shimmed methods will not overwrite any native implementations.

File size

API

If all you want to do is swap out values you can use one of the following two smaller template functions.

<static> Templ8.format( template:String, param1:String, param2:String, ..., paramN:String ):String

This function takes a minimum of two parameters. The first is the template you want perform substitutions over.

The template should use zero based tokens, e.g. {0}, {1} ... {N} that increment for each argument passed to the function.

e.g.

    Templ8.format( 'Hello {0}! Nice {1} we\'re having.', 'world', 'day' );

returns: Hello world! Nice day we're having.


 

<static> Templ8.gsub( template:String, dict:Object, pattern:RegExp ):String

gsub works similarly to format only it takes an Object with the values you want to substitute, instead of a sequence of parameters. Actually format calls gsub internally.

e.g.

    Templ8.gsub( 'Hello {name}! Nice {time} we\'re having.', { name : 'world', time : 'day' } );

returns: Hello world! Nice day we're having.

The default pattern for substitutions is /\{([^\}]+)\}/g. However, you can supply a third argument to gsub which is your own custom pattern to use instead of the default.

If you want to do fancy stuff, you'll want to use the Templ8 constructor.


 

new Templ8( template:String, options:Object )

The Templ8 constructor actually takes an arbitrary number of String arguments which form the template body.

The last argument to the Templ8 can -- optionally -- be a configuration Object which defines any custom Filters you want to use for this Templ8 and any sub Templates it contains.

It also accepts the following four parameters (needless to say that these cannot be used as Filter names):


 

Templ8 instance methods

To keep it simple, a Templ8 instance only contains one method.

parse( dictionary:Object ):String

This method accepts one parameter: an Object of values you want to substitute and returns a String of the parsed Templ8.

Any tokens in the Templ8 that do not have a dictionary value will use the fallback value described above,


 

Templ8 variables

basic global variables

$_

This is based on perl's $_ and is a reference to the the current dictionary value being parsed.

For instance if you are in a loop, rather than access the value using iter.current you could also access it via $_.

e.g. instead of this:

    {[ iter.current|parse:'sub_template' for each ( items ) ]}

or this:

    {[ item|parse:'sub_template' for each ( item in items ) ]}

you could do this:

    {[ $_|parse:'sub_template' for each ( items ) ]}
iter

This is the current iterator being parsed. It is an instance of an internal class called Iter. Iter instances are created internally, when you use a {% for %} loop or an Array Comprehension {[ for each ]} tag you should not need to create one yourself.

It has the following properties available for both Arrays and Objects:

It has the following extra properties available for Objects:

It also has the following two methods:


 

Templ8 internal variables

Along with the above Templ8 has some internal variables accessible for the more advanced user, should they require access to them.

$C or __CONTEXT__

Templ8 does not use the JavaScript with statement. It implements its own version of a with statement using an internal class called ContextStack.

It has five methods (you should NOT call these if you DO NOT know what you're doing):

__OUTPUT__

This is where all parsed template output is stored. It is an instance of an internal class call Output.

It has two methods:

__ASSERT__

This is a reference to Templ8.Assertions.

__FILTER__

This is a reference to Templ8.Filters.

__UTIL__

This is a reference to the internal utility functions used by Templ8.


 

Tags & Statements

Tag: {{}} - Interpolation

This tag is used for interpolating dictionary values with their respective template tokens. At it simplest a tag which will be replaced by a dictionary value foo would look something like this:

    var tpl = new Templ8( '{{foo}}' );
    tpl.parse( { foo : 'bar' } ); // returns: bar
Accessing nested values

If your dictionary contains nested objects you can easily access nested values like you would in regular JavaScript.

    var tpl = new Templ8( '{{some.nested.value}}' );
    tpl.parse( { some : { nested : { value : 'foo' } } } ); // returns: foo

You can also similarly access values from Array's in the same way:

    var tpl = new Templ8( '{{some.nested.1.value}}' );
    tpl.parse( { some : { nested : [{ value : 'lorem' },{ value : 'ipsum' },{ value : 'dolor' }] } } ); // returns: ispum
Filtering

This is all well and good, but at some point we will want to manipulate the values in our dictionary Objects in some way or another.

Templ8 provides a very simple and powerful method for doing so based on Django's pipe syntax for filtering values.

It is probably most easily illustrated with an example showing the pipe syntax converted to JavaScript. So:

    {{value|truncate:30|bold|wrap:"(", ")"|paragraph}}

Would translate to something like this:

	value = truncate( value, 30 );
	value = bold( value );
	value = wrap( value, '(', ')' );
	value = paragraph( value );
	
	// or 
	
	paragraph( wrap( bold( truncate( value, 30 ) ), '(', ')' ) );

The most important thing to note is that the first value passed to the filter is always the value being parsed by the template, the arguments passed to each filter will always come after the value being parsed.

One line statements

As well as standard template conditionals, Templ8 introduces one line statements, because, hey it's JavaScript and we like to keep things concise.

If you only want to parse a value if a certain condition is met, rather than writing block if tags around it, you can include it in your interpolation tag like so:

    {{value if value|exists}}

Which translates to something like this:

    if ( exists( value ) ) { value; }

Notice how you can use the same pipe syntax for conditionals. Templ8's internals work out whether your method is an assertion or a filter and reference the appropriate method.

You can also use ordinary JavaScript conditions if you want to, as well as an unless statement; and filtering is still ok too.

A more complex example would be:

    {{value|truncate:30|bold|wrap:"(", ")"|paragraph unless value == null}}

Translating to something like:

    if ( !( value == null ) ) { 
       paragraph( wrap( bold( truncate( value, 30 ) ), '(', ')' ) ); 
    }

Tag: {%%} - Evaluation

This tag is used in conjunction with the above tag to give you access to more powerful conditional statements, iteration and sub templates.

if/ unless/ elseif/ else/ endif Statements

Just like regular JavaScript Templ8 features conditional statements. It also introduces the unless statement based off Perl.

Every open if/ unless statement must end with an endif statement -- with any number ofelseifs in between; an optional else is also allowed just before endif.

The reason for the endif statement is that Templ8 does not use braces to encapsulate block statements, so it requires a flag to let the parser know when to close a block.

Note: elseif should be written as one word, no spaces. It can also be written as elsif, again, based off Perl.

An example would be:

    {% if value == 'foo' %}
        <h1>{{value|bold}}</h1>
    {% elseif value == 'bar' %}
        <h2>{{value|italics}}</h2>
    {% else %}
        {{value}}
    {% endif %}

Translating to:

    if ( value == 'foo' ) { 
        '<h1>' + bold( value ) + '</h1>';
    }
    else if ( value == 'bar' ) {
        '<h2>' + italics( value ) + '</h2>';
    }
    else { value; }
for/ forempty/ endfor Statements

The for statement allows you to iterate over Arrays as well as Objects. There are a number of options available with the for statement.

Just like the if statement the for statement must end with an endfor statement to tell the parser that the statement block is ending.

You can also include a forempty statement which will be used in the case where an Array/ Object is either empty or the item you are trying to iterate over is not iterable, e.g. a Number or Date. forempty is not mandatory.

The iter variable mentioned above is the standard way to access any and all properties you require while iterating over an Array/ Object.

You can also use $_ to access the current value being iterated over.

However you can also assign your own variable names to the for. e.g.

    {% for item in items %}
        {{item}}
    {% forempty %}
        No items
    {% endfor %}

Will assign the current value being iterated over to the variable item, which is accessible as demonstrated.

    {% for [key, value] in items %}
        {{key}}. {{value}}
    {% endfor %}

Will assign the current value being iterated over to the variable value. If you are iterating over an Array then the variable key will be the zero based index of the the current item being iterated over. If you are iterating over an Object then the variable key will be the the key name of the current item being iterted over.

If you want to limit the number of items you are iterating over you can do so by using brackets to specify the range of items to iterate over.

    {% for item in items [..10] %}
        {{item}}
    {% endfor %}

Will iterate over items 0 to 10, so the first 11 items in the Array/ Object.

    {% for item in items [5..10] %}
        {{item}}
    {% endfor %}

Will iterate over items 5 to 10.

    {% for item in items [5..] %}
        {{item}}
    {% endfor %}

Will iterate over all items starting from the 6th item in the Array/ Object.

If you are nesting for statements you can access the parent iter Object by using the syntax iter.parent this will maintain state no matter how deep you nest.

sub/ endsub templates

TODO

Tag: {[]} - Array Comprehensions

TODO

Tag: {::} - Executing Arbitrary JavaScript

TODO

Tag: {##} - Comments

TODO

Adding your own Tags and/ or Statements

TODO


 

Examples (by tag)

Tag: {{}}

Replacing values

    var tpl = new Templ8( '{{value}}' );

    tpl.parse( { value : 'github.com' } ); // returns: *github.com*
Filtering values
    var tpl = new Templ8( '{{value|truncate:30|bold|link:"http://github.com"}}' );

    tpl.parse( { value : 'github.com is great for sharing your code with other people.' } ); 

returns the String:

	<a href="http://github.com"><strong>github.com is great for sharin...</strong></a>
One line if statement
    var tpl = new Templ8( '{{value if value|notEmpty}}' );
    
    tpl.parse( { value : 'github.com' } ); // returns: *github.com*

    tpl.parse( {} );                       // returns: empty String ( "" )
One line unless statement
   var tpl = new Templ8( '{{value unless value|equals:"foo"}}' );

    tpl.parse( { value : 'github.com' } ); // returns: *github.com*

    tpl.parse( { value : 'foo' } );        // returns: empty String ( "" )

 

Tag {%%}

conditions: if|unless/ elseif/ else/ endif

    var tpl = new Templ8(
        '{% if value == "foo" || value == "bar" %}',
            '{{value}}',
        '{% elseif value != "lorem ipsum" %}',
            '{{value|bold}}',
        '{% elseif value|notEmpty %}',
            '{{value|italics}}',
        '{% else %}',
            'No value',
        '{% endif %}'
    );

    tpl.parse( { value : 'foo' } );            // returns: foo

    tpl.parse( { value : 'lorem ipsum' } );    // returns: <strong>lorem ipsum</strong>

    tpl.parse( { value : 'dolor sit amet' } ); // returns: <em>dolor sit amet</em>

    tpl.parse( {} );                           // returns: No Value

iterating: for/ forempty/ endfor

    var tpl = new Templ8(
	    '{% for item in items %}',
            '<p>{{item}}</p>',
        '{% forempty %}',
            '<p><strong>No items</strong></p>',
        '{% endfor %}' 
    );

    tpl.parse( { items : ['one', 'two', 'three'] } );               // returns: <p>one</p><p>two</p><p>three</p>

    tpl.parse( { items : { "one" : 1, "two" : 2, "three" : 3 } } ); // returns: <p>1</p><p>2</p><p>3</p>

    tpl.parse( {} );                                                // returns: <p><strong>No items</strong></p>
    
    tpl.parse( { items : foo } );                                   // returns: <p><strong>No items</strong></p>

sub/ endsub templates

    var tpl = new Templ8(
        '{% sub list_item %}', '<li>{{$_}}</li>', '{% endsub %}', 
        '<ul>{[ item|parse:"list_item" for each ( item in items ) ]}</ul>'
    );

	tpl.parse( { items : ['one', 'two', 'three'] } );

returns the String:

	<ul><li>one</li><li>two</li><li>three</li></ul>

 

Tag {[]} (Array comprehensions or one line for loops)

    var tpl_foo = new Templ8( { id : 'foo' }, '<em>{{val}}</em>' ), 
        tpl_bar = new Templ8( { id : 'bar' }, '<strong>{{val}}</strong>' ), 
        tpl     = new Templ8( '{[ v|parse:k|paragraph for each ( [k,v] in items ) if ( k|isTPL ) ]}' );

    tpl.parse( {
        foo  : { val : 'foo' }, 	
        bar  : { val : 'bar' }, 
        greg : { val : 'not gonna happen' }
    } );

returns the String:

	<p><em>foo</em></p><p><strong>bar</strong></p>

as greg does not exist as a template (poor greg), the value is not rendered...


 

Tag {::}

Allows you to execute arbitrary JavaScript.

    var tpl = new Templ8( '{: aribtrarily.executing.nasty.code.isFun(); :}' );

 

Tag {##}

Allows you to add comments in your template.

    var tpl = new Templ8( '{# doing something complex and describing it is sensible, but not probable #}' );

License

(The MIT License)

Copyright © 2011 christos "constantology" constandinou http://muigui.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

0.10.5

11 years ago

0.10.4

11 years ago

0.10.3

11 years ago

0.10.2

11 years ago

0.10.1

11 years ago

0.10.0

11 years ago

0.9.26

11 years ago

0.9.25

11 years ago

0.9.24

11 years ago

0.9.23

11 years ago

0.9.22

11 years ago

0.9.21

11 years ago

0.9.20

11 years ago

0.9.19

12 years ago

0.9.18

12 years ago

0.9.17

12 years ago

0.9.16

12 years ago

0.9.15

12 years ago

0.9.14

12 years ago

0.9.13

12 years ago

0.9.12

12 years ago

0.9.11

12 years ago

0.9.9

12 years ago

0.9.8

12 years ago

0.9.7

12 years ago

0.9.6

12 years ago

0.9.5

12 years ago

0.9.4

12 years ago

0.9.3

12 years ago

0.9.2

12 years ago

0.9.1

12 years ago

0.9.0

12 years ago

0.8.0

12 years ago

0.7.2

12 years ago

0.7.1

12 years ago

0.7.0

12 years ago

0.6.0

12 years ago

0.5.0

12 years ago

0.3.0

13 years ago

0.2.1

13 years ago

0.2.0

13 years ago

0.1.9

13 years ago

0.1.8

13 years ago

0.1.7

13 years ago