Simple, Tiny, Fast (enough)
Example usage (in CoffeeScript):
blam(->
html(
head(
title( "Hello" )
script( src:"/my-script.js" )
)
body(
article( id:"main",
section.content(
p("Loading...")
)
aside.sidebar( "Nav here" )
)
)
)
)
You can use it in JavaScript too (but it's much prettier in CoffeeScript):
blam(function(){
return html(
head(
title( "Hello" ),
script({ src: "/my-script.js" }),
),
body(
article({ id: "main" },
section.content(
p("Loading...")
),
aside.sidebar( "Nav here")
)
)
)
});
If you like, you can compile string templates as well (you'll need to use the javascript syntax):
<script type="text/blam" id="my_template">
article.container(
section.main(
p("Hello!")
),
aside.sidebar(
ul(
li("Navigation, mayhaps?")
)
)
)
</script>
<script>
var template_string= document.getElementById('my_template');
// Render it...
var html= blam( template_string );
// Or if you're gonna reuse the template, you should probably compile it:
var template= blam.compile( template_string );
// then however many times you want
var html= template();
</script>
Clocks in at ~1K minified and gzipped.
MIT Licensed.
Unit tests can be found at: darthapo.github.com/blam.js/test
Please let me know if any of the tests break in your browser!
If the first argument to a tag block is an object literal then its key/value pairs are used as tag attributes.
blam ->
div( id:"posts", 'data-role':"post",
p("content here...")
)
# => '<div id="posts" data-role="post"><p>content here...</p></div>'
Blam will pass initial arguments on to the markup block:
blam name:'Matt', (user)->
div( id:'user-block',
p("Hello ", user.name)
)
Markup blocks can be "compiled" into an executable function (good for often repeated bits of code):
template= blam.compile (user)->
div( id:'user-block',
p("Hello ", user.name)
)
html+= template(user) for user in all_users
For array elements you can use the each
tag:
template= blam.compile (users)->
div( id:'user-block',
each(users, (user)->
p("Hello ", user.name)
)
)
html+= template(all_users)
You can create partials/custom tags:
blam.define 'layout', ->
article.container(
header( h1( "My App" ) )
section.body( __(arguments) )
footer( p("© me!") )
)
You can then use it like a tag:
blam @posts, (posts)->
layout(
div.posts(
each(posts, (post)->
div.entry( post.body )
)
)
)
You can turn off the fancy auto css class support:
blam.fancy(no)
# You have to use the attributes hash to add classnames now:
blam ->
div( class:'my-class', "Content")
You can add a single object to a markup block's scope when pre-compiling templates:
data=
name: 'He'
age: 'Old Enough'
template= blam.scope(data).compile ->
div( name, " is ", age )
html= template()
#=> "<div>He is Old Enough</div>"
class TweetView extends Backbone.View
@template: blam.compile (tweet)->
div.tweet(
img.avatar(
src: tweet.profile_image_url
alt: tweet.from_user_name
)
div.status(
tweet.status
)
div.footer(
"@"
tweet.from_user
" said on "
tweet.created_at
)
)
render: ->
@$el.html TweetView.template( @model.toJSON() )
Blam is available as an npm package as well. To install:
npm install blam
Or, use the -g
option to install it globally:
npm install blam -g
Then require
it as per usual in node:
var blam= require('blam').blam;
blam.compile(function(){ return div("etc...") })
-
Need to cleanup this ReadMe and create some proper docs.
-
Would like to support all the modern browsers and possibly as far back as IE8?
-
Need to test AMD support.
-
Extract and expose tag building helpers.
No! They're just misunderstood. Blam.js is a good example of why they are useful as language features. They allow excellent DSL generation.
That having been said, it is a good rule of thumb that if you don't know when is best to use them; don't.