npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

rule

v1.0.5

Published

Coffeescript friendly css selector based templating

Downloads

95

Readme

rule.js

functional coffeescript templating

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

What

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">
  </span>
</div>

dom = $('.template')

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

rule.render
  content: 'a string'
  dom

Get results.

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

How

###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.

'.data'

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

'.data@type'

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

'.data@type+'

#####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'

Conditionals...

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

Loops...

'.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.

'.data':
  '.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">
  </span>
</div>
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.

rule.render
  content: 'a string'

A DOM element will be returned.

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

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

rule.render()

Or choose how you want to react.

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

The data class element is replaced with an empty string.

<div class="template">
</div>

You can render to a specific dom instance

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

Why

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.

Examples

Simple Example

Template

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

Rule Object

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

Execution

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

Embedded Object Example

Template

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

Rule Object

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

Execution

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

Iteration Example

Template

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

Rule Object

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

Execution

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

Recursion Example

Template

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

Rule Object

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

Execution

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

Requirements

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.

Size

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

Thanks to Pure for providing the inspiration.