Skip to content


Folders and files

Last commit message
Last commit date

Latest commit


Repository files navigation


functional coffeescript templating

rule = new Rule
  '.title': ->@title ? 'rule.js'
  '.description': ['rule.js ', 'is ', 'a ', 'templating ', 'library.']


Rule is a templating library that uses css selectors to select elements, and then applies a value to that element. That value can be a string, DOM element, array, function, object, or even another rule. Strings are inserted as text nodes to protect against XSS. DOM elements can be created however you want. Iteration is done by returning an array. Functions are evaluated and can return any other type (even another function). A rule will be evaluated and return a DOM element. The power of the library comes from combining these fundamental types. For example, a function can return an array, of rules that evaluate to DOM elements. How you use these types is up to you and the possibilities are endless.

The precompiled version is available in the downloads tab.

###Rule Choose where your data goes and how...

rule = new Rule
  '.data': ->@content

###Template Use whatever DOM object you want, made however you want...

<div class="template">
  <span class="data">

dom = $('.template')

###Execution Build the populated template with the data you pass it...

  content: 'a string'

Get results.

<div class="template">
  <span class="data">
    'a string'


###Rules The Rule constructor takes an object, and an optional template

rule = new Rule
  '.data': ->@content
  document.querySelector 'div'

####Keys The key is a selector for the element to populate.


You can add @[attribute] to select the attribute within the selector.


You can add a position to point where to add the data to.


#####Positions -: insert as previous sibling node or concatenate before with a space for attributes

+: insert as next sibling node or concatenate after with a space for attributes

=: replace the selected node with a new node

<: insert as first child node or concatenate immediately before for attributes

>: insert as last child node or concatenate immediately after for attributes

####Values Rules can have a variety of values. #####Functions The value can be a function. The 'this' context is the data, and its return value gets parsed again.

'.data': ->@content

You can do whatever coffeescript can do

'.data': ->@content ? 'default'


'.data': ->if @hidden then 'hidden' else 'show'


'.data': ->item for item in @list

Even another function...

'.data': -> ->'inner'

#####Arrays Each element in an array will be inserted in order to the given position

'.data': ['R','U','L','E']

The values in the array can be anything

'.data': [->@a,->@b,->@c]

A Function can return an array

'.data': ->item for item in @list

It can be processed by another rule first

'.data': ->itemRule.render item for item in @list

#####Rules A rule can be another rule.

If it has a template, it will render with that.

If it doesn't, it will use the current selection of the rule and modify that

#####Objects You can have an object within the object. It is made into a new rule and the parent selector is the template root.

  '.inner': ->@content

#####HTML Elements and jQuery (or compatible) objects The passed in object will be added as it is.

#####Objects with toString An object that overrides toString will have their toString method called.

Some objects that override toString are Strings, Numbers, and Booleans.

They can also be your own.

###Template The template can be whatever DOM object you want.

<div class="template">
  <span class="content">
dom = document.querySelector '.template'

It can also be an array of elements

<div class="article"></div>
<div class="article"></div>
<div class="article"></div>
dom = document.querySelectorAll '.article'

It can also be a jQuery (or compatible) object

$ '<div><span></span></div>'

###Execution Pass whatever data you want to your Rule.

  content: 'a string'

A DOM element will be returned.

<div class="template">
  <span class="data">
    'a string'

If the data isn't there, it's just ignored


Or choose how you want to react.

'.data=' ->@content ? ''

The data class element is replaced with an empty string.

<div class="template">

You can render to a specific dom instance

rule.render {}, document.querySelectorAll('.container')


With rule you can seperate your DOM from your mappings, from your data. With generic selectors you can change your DOM structure, and keep the same mappings, or change the mappings for a new data type and keep the same structure. They are no longer tied together, and you can use them how you like. With coffeescript you can have succinct code, with infinite power. Just use it wisely.

Rule Object methods

new Rule(rule, [template]): create a new Rule based on the rule object given in, and an optional template. The template must be either an HTMLElement, an array of HTMLElements, or a jQuery compatible object that supports a 'get' method that returns an array of HTMLElements

.render(data, [element]): create an html element with the given data. If an optional element is given then apply modifications directly to it. The element parameter must meet the same type requirements of a template

Rule Static methods

Rule.split(selector): takes a rule selector string in the format of [selector]?(@[attribute])?[-+<>=]? and splits it into an array of [selector, attribute, position]. If one of the sections are not there it will be returned as undefined

Rule.parse(rule, data, selection): takes the rule object binding and returns the data bound content based on its type. The return value will be either a Node object, a String, or an array of Node objects or Strings

Rule.add(content, selection, [attribute], [position]): adds content to a selection or its attribute at the given position. The selection and any added siblings will be returned.


Simple Example


<div class="simple">
  <span class="content"></span>

Rule Object

simple = new Rule
  '.content': ->@content
  $ '.simple'


($ 'body').append simple.render
    content: 'test'

Embedded Object Example


<div class="book">
  <h1 class="title"></h1>
  <div class="author">
    <div class="name">
      <span class="first"></span>
      <span class="last"></span>

Rule Object

book = new Rule
  '.title': ->@title
      '.first': ->@author.first
      '.last': ->@author.last
  $ '.book'


($ 'body').append book.render
  title: 'The Hobbit'
    first: 'J. R. R.'
    last: 'Tolkien'

Iteration Example


<ul class="list">
  <li class="item"><span class="content"></span></li>

Rule Object

itemRule = new Rule
  '.content': ->@content ? 'default'
  $ '.list'
listRule = new Rule
  '.': ->itemRule.render item for item in @list
  $ '.list > .item'


($ 'body').append listRule.render
  list: [{content: 'hello'}, {content: 'world'}, {}]

Recursion Example


<ul class="recursive">
  <li class="location"></li>
  <div class="list"></div>

Rule Object

recursive = new Rule
  '.location': ->@location
  '.list=': ->if @list then recursive.render item for item in @list
  $ '.recursive'


($ 'body').append recursive.render
  location: 'USA'
        location: 'California'
            { location: 'San Diego' }
            { location: 'San Francisco' }
            { location: 'San Jose' }
        location: 'Nevada'
            { location: 'Reno' }
            { location: 'Las Vegas' }


Rule has no hard requirements and will work as is on newer browsers. 'indexOf' and 'querySelectorAll' are used but fallbacks are exposed if the browser does not support those methods. For querySelectorAll, if the browser does not support it, a jQuery compatible library may be used that correctly implements wrapping an HTMLElement or array of HTMLElements with '$', the 'find' method, and the 'get' method.


Rule attempts to be as simplistic and small as possible while still providing a large amount of flexibility and power

Here is a minified gzipped size comparison to some other client side templating libraries

rule: 1.08 kb

mustache: 2.01 kb

pure: 4.21 kb

jade: 8.19 kb


Thanks to Pure for providing the inspiration.