Monday, January 10, 2011

Learning Haml

ERb is the default markup language with Ruby on Rails. However it is not your only choice. While playing around with a rails project I came across Haml. I decided to give it a try, and I am glad that I did. Just like rails opened my eyes as to how clean a web framework could be, Haml has shown me how clean a markup language can be.

Rather than using the XML paradigm of open and close tags, it uses the Python approach of indentation to mark blocks. I'll give an example to show what I mean. Here is the HTML for a simple web page:
  1 <html> 
  2   <head> 
  3     <title>Hello World</title> 
  4   </head> 
  5   <body> 
  6     <h1>Hello World</h1> 
  7     <div id='mainContent'> 
  8       This is a sample html page. 
  9     </div> 
 10   </body> 
 11 </html> 
Before I show the Haml equivalent, I'd like to point out something. In the above HTML example there are 60 characters of content (the 'Hello World's and 'mainContent' and 'This is a sample html page.') and 80 characters of markup! This verbosity in the markup is one of the ugliest things in XML and HTML. You have to work to find the content amidst all the markup.

Here is the Haml that generates the equivalent HTML.
  1 %html 
  2   %head 
  3     %title Hello World 
  4   %body 
  5     %h1 Hello World 
  6     #mainContent 
  7       This is a sample html page.

As you can see, it is much terser. For the same 60 characters of content there are only 25 characters of markup. (I am slightly cheating by not counting whitespace, but I had the same whitespace in the HTML to help make it readable, even though it wasn't required, so I think it is fair to not count it).

Haml Markup
As you probably figured out from the above example, the primary markup is the %.  %tagname creates HTML that looks like: <tagname></tagname> Any content that is either on the same line as this tag (like title and h1 in the example above) or indented on following lines (like head and body) gets placed between the opening and closing tags.

Attributes can be specified via a ruby style hash.  So a tag like:
<img alt="Some Text" height="100" width="75" src="image.jpg" />
could be specified like:
%img{:alt=>"Some Text", :height=>100, :width=>75, :src=>"image.jpg"}
Since id and class are such common attributes, they can be specified similar to how they are specified in CSS.
<div class="myClass" id="myId">
can be written:
%div.myClass#myId
Haml has also decided that div is the main structural component of a page, and therefore is implicit if you specify and id or class without a tag.  i.e. the above div could also be written
.myClass#myId
Of course Haml is intended to be used with rails which means that you can embed ruby into your Haml document. Any line that begins with '=', or any tag that ends with '=' is assumed to be ruby and evaluated.  i.e.
%h1= 5+3
= 2*2*2
results in HTML
<h1>8</h1>
8
Any line that being with '-' evaluates the ruby without placing the results in the HTML. This is useful for control flow. For example:
%ul
  - (1..4).each do |i|
    %li= i
creates the HTML:
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

The above examples aren't intended as a full lesson on Haml, just a teaser to give you an idea of what it looks like. If you want to learn Haml you can look at the reference material at http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html. Unfortunately, Haml is currently tied to Ruby on Rails. Hopefully similarly clean/terse markup languages will be created for other frameworks.

2 comments:

David Barr said...

This makes all the sense in the world, though moving to a language where whitespace matters will be a shift, I'll have to check this out.

Michael Haddox-Schatz said...

I really would like to see other non-verbose markup languages that compile to html. I can envision a similar language that uses curly braces to mark blocks rather than indenting while still providing brevity to the markup. Though without actually seeing it, I am not sure how ugly (or not) that might be.