Haml Sucks for Content

I am not writing this blog post in HTML, and I’m certainly not writing it in Haml. I’m using Markdown. Markdown is a great syntax for content. It’s so good at it, that all of the content for the Haml website is written in markdown.

When I say content, I mean the meat of a web page. The stuff that is left after you take away the header, footer, sidebar, ads, etc. The stuff the user is there to read. Don’t use Haml for adding markup to your inline content.

Paragraph of Content in Haml
%p
  Please,
  %strong
    For the love of
    = succeed "," do
      %a(href="http://www.god.com/") God
  don't use
  %a(href="http://haml-lang.com") Haml
  for marking-up your content!
 
Paragraph of Content in Markdown
Please, **For the love of [God](http://www.god.com/),**
don't use [Haml](http://haml-lang.com) for marking-up your content!

Haml is for Layout & Design

Haml’s use of CSS syntax for IDs and class names should make it very clear: The markup you write in Haml is intended to be styled by your stylesheets. Conversely, content does not usually have specific styling - it is styled by tags.

Haml documents do two things to make you faster:

  1. Make the structure of the document obvious by forcing indentation.
  2. Make it easier to switch between styles and markup.

Work-Arounds

When I asked Nathan, the man behind both Haml & Sass, if he would mind it if I wrote this post he responded:

No, it’s true.

Nathan’s acknowledgment of Haml’s weaknesses is one of its strengths. He has done a lot to sand down Haml’s rough edges over the two years I’ve been following Haml’s development. But first and foremost, I think there is a misconception that Haml’s indentation-based tags are the only way to create markup in a Haml document. This is not true. Here are several ways you can embed inline content within a Haml document:

• Inline your HTML

That’s right. Just put some HTML into your Haml document. Don’t be afraid, it’ll be just fine.

Inline HTML
%p
  Please, For the love of God,
  don't use Haml for marking-up your content!

• Use Filters

Haml lets you pass any block of content through a filter. If you find yourself thinking that Haml is getting in the way, that’s probably because you aren’t using a filter. In any filter, you can use #{} to insert output from code. The following filters are available for processing your content:

  • :plain – Simply passes the filtered text through to the generated HTML.
  • :cdata – Surrounds the filtered text with a CDATA escape.
  • :escaped – Works the same as :plain, but HTML-escapes the text before placing it in the document.
  • :erb – Parses the filtered text with ERB – the Rails default template engine.
  • :textile – Parses the filtered text with Textile. Only works if RedCloth is installed.
  • :markdown – Parses the filtered text with Markdown. Only works if RDiscount, RPeg-Markdown, Maruku, or BlueCloth are installed
  • :maruku – Parses the filtered text with Maruku, which has some non-standard extensions to Markdown.
Inline Markdown
.content
  :markdown
    Please, **For the love of [God](http://www.god.com/),**
    don't use [Haml](http://haml-lang.com) for marking-up your content!

• Partials

Haml is framework agnostic, but at least within rails, the framework will compile partials and insert the compiled content into your page. At Caring.com we use the Amor rails plugin for markdown content. This makes it easy for us to compose templates, partials, and layouts of different formats into a single page.

Haml with Rails Partials
.content= render :partial => "some_content"
 
_some_content.html.md
Please, **For the love of [God](http://www.god.com/),**
don't use [Haml](http://haml-lang.com) for marking-up your content!

Some Other Haml “Gotchas”

So let’s just get it all out on the table. Haml is really good at what it is good at, but it is really bad at some other things. Here they are in no particular order:

• Preformatted Content

Haml’s default mode is to pretty-print your output. This wreaks havoc with preformatted text in <pre> and <textarea> tags. Haml provides a :preserve filter that inserts the filtered text into the output with whitespace preserved. For some reason, it still never quite works right for me. So I’ve found that the simplest way is to just turn the pretty-printer off by adding this to my environment.rb:

Haml::Template.options[:ugly] = true

More on Whitespace Preservation.

• Performance

The :ugly option was actually added to make haml faster. With it on, Haml is approximately the same speed as ERB. With it off, Haml is 2.8 times slower than ERB. NOTE: the production environment default is to turn :ugly on.

But with tools like firebug, I just don’t see the point in having pretty-printed html even in development. So again, I recommend you just turn :ugly on and treat it is a debugging tool.

• Stand-Alone

Haml comes with a command line tool that lets you process Haml files into HTML. This is useful for small, quick documents, but it’s not the basis for a website. Haml is a templating engine and it doesn’t provide many of the facilities you need for building a maintainable website. If you want to build a static site with Haml, please consider using one the following:

• Out of Order Processing

You cannot use haml to emit malformed HTML. This is a feature, but it is sometimes in the way. For instance a nice trick in ERB is to join an array like so:

<ul><li><%= @items.map{|item| item.name}.join("</li><li>") %></li><ul>

Haml’s answer to this is the list_of helper. Which is pretty nice for blocks of formatted code.

%ul= list_of(@items) do |item|
  = item.name

Unfortunately, this helper assumes you’re generating a list and requires that you pass a block even when the array consists of simple strings.

• Multiline Code

Haml is meant to be a designer-friendly template format, and as such it encourages code that is readable by folks with a minimal understanding of code APIs. One of the ways Haml encourages this is by making it hard to write code that continues on the next line. Multiline code ends with a | at the end of the line. Example.

If You Must

If you decide that you’re going to write some inline markup with Haml anyway (hey, some folks are masochists), then you should read up on Haml’s precede and succeed helpers as well as the alligator operators: < and >. May God have mercy on your soul.

Conclusion

Despite its flaws, Haml is a very nice template language that optimizes the work my team and I do on a daily basis. We recommend it often. But the goal is that coding will be faster, easier and more enjoyable. If you have a different technology that fits better with how you think, then you should use that. But if you find Haml documents to be easier to read, but that you find yourself fighting it to make the output you need, then I hope this post has helped you understand how to play to Haml’s strengths and avoid its weaknesses.

What I hope is clear is that if your job is to produce content, then Haml is probably not the template language for you.

Postscript

Some might think because of my involvement in Sass that I’m equally involved in Haml. This is not the case. Most, if not all, of my Haml patches have been to help it support Sass better. I’m just an experienced Haml user who wants to be honest about Haml’s Pros and Cons.