# Haml (HTML Abstraction Markup Language) Haml is a markup language that's used to cleanly and simply describe the HTML of any web document, without the use of inline code. Haml functions as a replacement for inline page templating systems such as PHP, ERB, and ASP. However, Haml avoids the need for explicitly coding HTML into the template, because it is actually an abstract description of the HTML, with some code to generate dynamic content. ## Features * Whitespace active * Well-formatted markup * DRY * Follows CSS conventions * Integrates Ruby code * Implements Rails templates with the .haml extension ## Using Haml Haml can be used in three ways: * as a command-line tool, * as a plugin for Ruby on Rails, * and as a standalone Ruby module. The first step for all of these is to install the Haml gem: gem install haml To run Haml from the command line, just use haml input.haml output.html Use `haml --help` for full documentation. To use Haml with Rails, add the following line to the Gemfile: gem "haml" Once it's installed, all view files with the `".html.haml"` extension will be compiled using Haml. You can access instance variables in Haml templates the same way you do in ERB templates. Helper methods are also available in Haml templates. For example: # file: app/controllers/movies_controller.rb class MoviesController < ApplicationController def index @title = "Teen Wolf" end end -# file: app/views/movies/index.html.haml #content .title %h1= @title = link_to 'Home', home_url may be compiled to:
Haml code!
\n" ### Options Haml understands various configuration options that affect its performance and output. In Rails, options can be set by setting the {Haml::Template#options Haml::Template.options} hash in an initializer: ```ruby # config/initializers/haml.rb Haml::Template.options[:format] = :html5 # Avoid escaping attributes which are already escaped Haml::Template.options[:escape_attrs] = :once ``` Outside Rails, you can set them by configuring them globally in Haml::Options.defaults: ```ruby Haml::Options.defaults[:format] = :html5 ``` In sinatra specifically, you can set them in global config with: ```ruby set :haml, { escape_html: true } ``` Finally, you can also set them by passing an options hash to {Haml::Engine#initialize}. For the complete list of available options, please see {Haml::Options}. ### Encodings Haml supports the same sorts of encoding-declaration comments that Ruby does. Although both Ruby and Haml support several different styles, the easiest it just to add `-# coding: encoding-name` at the beginning of the Haml template (it must come before all other lines). This will tell Haml that the template is encoded using the named encoding. By default, the HTML generated by Haml has the same encoding as the Haml template. However, if `Encoding.default_internal` is set, Haml will attempt to use that instead. In addition, the {Haml::Options#encoding `:encoding` option} can be used to specify an output encoding manually. Note that, like Ruby, Haml does not support templates encoded in UTF-16 or UTF-32, since these encodings are not compatible with ASCII. It is possible to use these as the output encoding, though. ## Plain Text A substantial portion of any HTML document is its content, which is plain old text. Any Haml line that's not interpreted as something else is taken to be plain text, and passed through unmodified. For example: %gee %whiz Wow this is cool! is compiled to:
The magical fruit
And: %img %img> %img is compiled to: And: %p<= "Foo\nBar" is compiled to:Foo!
Foo Bar
And finally: %img %pre>< foo bar %img is compiled to:foo bar### Object Reference: `[]` Square brackets follow a tag definition and contain a Ruby object that is used to set the class and id of that tag. The class is set to the object's class (transformed to use underlines rather than camel case) and the id is set to the object's class, followed by the value of its `#to_key` or `#id` method (in that order). This is most useful for elements that represent instances of Active Model models. Additionally, the second argument (if present) will be used as a prefix for both the id and class attributes. For example: # file: app/controllers/users_controller.rb def show @user = CrazyUser.find(15) end -# file: app/views/users/show.haml %div[@user, :greeting] %bar[290]/ Hello! is compiled to:
Sign my guestbook
You can also specify the specific doctype after the `!!!` When the {Haml::Options#format `:format`} is set to `:xhtml`. The following doctypes are supported: `!!!` : XHTML 1.0 Transitionalfoo
bar
You can also nest text beneath a silent comment. None of this text will be rendered. For example: %p foo -# This won't be displayed Nor will this Nor will this. %p bar is compiled to:foo
bar
## Ruby Evaluation ### Inserting Ruby: `=` {#inserting_ruby} The equals character is followed by Ruby code. This code is evaluated and the output is inserted into the document. For example: %p = ['hi', 'there', 'reader!'].join " " = "yo" is compiled to:hi there reader! yo
If the {Haml::Options#escape_html `:escape_html`} option is set, `=` will sanitize any HTML-sensitive characters generated by the script. For example: = '' would be compiled to <script>alert("I'm evil!");</script> `=` can also be used at the end of a tag to insert Ruby code within that tag. For example: %p= "hello" would be compiled to:hello
A line of Ruby code can be stretched over multiple lines as long as each line but the last ends with a comma. For example: = link_to_remote "Add to cart", :url => { :action => "add", :id => product.id }, :update => { :success => "cart", :failure => "error" } Note that it's illegal to nest code within a tag that ends with `=`. ### Running Ruby: `-` The hyphen character is also followed by Ruby code. This code is evaluated but *not* inserted into the document. **It is not recommended that you use this widely; almost all processing code and logic should be restricted to Controllers, Helpers, or partials.** For example: - foo = "hello" - foo << " there" - foo << " you!" %p= foo is compiled to:hello there you!
A line of Ruby code can be stretched over multiple lines as long as each line but the last ends with a comma. For example: - links = {:home => "/", :docs => "/docs", :about => "/about"} #### Ruby Blocks Ruby blocks, like XHTML tags, don't need to be explicitly closed in Haml. Rather, they're automatically closed, based on indentation. A block begins whenever the indentation is increased after a Ruby evaluation command. It ends when the indentation decreases (as long as it's not an `else` clause or something similar). For example: - (42...47).each do |i| %p= i %p See, I can count! is compiled to:42
43
44
45
46
See, I can count!
Another example: %p - case 2 - when 1 = "1!" - when 2 = "2?" - when 3 = "3." is compiled to:2?
### Whitespace Preservation: `~` {#tilde} `~` works just like `=`, except that it runs {Haml::Helpers#find\_and\_preserve} on its input. For example, ~ "Foo\nBar\nBaz" is the same as: = find_and_preserve("Foo\n
Bar\nBaz") and is compiled to: Foo
Bar BazSee also [Whitespace Preservation](#whitespace_preservation). ### Ruby Interpolation: `#{}` Ruby code can also be interpolated within plain text using `#{}`, similarly to Ruby string interpolation. For example, %p This is #{h quality} cake! is the same as %p= "This is #{h quality} cake!" and might compile to:
This is scrumptious cake!
Backslashes can be used to escape `#{}` strings, but they don't act as escapes anywhere else in the string. For example: %p Look at \\#{h word} lack of backslash: \#{foo} And yon presence thereof: \{foo} might compile to:Look at \yon lack of backslash: #{foo} And yon presence thereof: \{foo}
Interpolation can also be used within [filters](#filters). For example: :javascript $(document).ready(function() { alert(#{@message.to_json}); }); might compile to: #### Gotchas Haml uses an overly simplistic regular expression to identify string interpolation rather than a full-blown Ruby parser. This is fast and works for most code but you may have errors with code like the following: %span #{'{'} This code will generate a syntax error, complaining about unbalanced brackets. In cases like this, the recommended workaround is output the code as a Ruby string to force Haml to parse the code with Ruby. %span= "#{'{'}" ### Escaping HTML: `&=` {#escaping_html} An ampersand followed by one or two equals characters evaluates Ruby code just like the equals without the ampersand, but sanitizes any HTML-sensitive characters in the result of the code. For example: &= "I like cheese & crackers" compiles to I like cheese & crackers If the {Haml::Options#escape_html `:escape_html`} option is set, `&=` behaves identically to `=`. `&` can also be used on its own so that `#{}` interpolation is escaped. For example, & I like #{"cheese & crackers"} compiles to: I like cheese & crackers ### Unescaping HTML: `!=` {#unescaping_html} An exclamation mark followed by one or two equals characters evaluates Ruby code just like the equals would, but never sanitizes the HTML. By default, the single equals doesn't sanitize HTML either. However, if the {Haml::Options#escape_html `:escape_html`} option is set, `=` will sanitize the HTML, but `!=` still won't. For example, if `:escape_html` is set: = "I feel !" != "I feel !" compiles to I feel <strong>! I feel ! `!` can also be used on its own so that `#{}` interpolation is unescaped. For example, ! I feel #{""}! compiles to I feel ! ## Filters {#filters} The colon character designates a filter. This allows you to pass an indented block of text as input to another filtering program and add the result to the output of Haml. The syntax is simply a colon followed by the name of the filter. For example: %p :markdown # Greetings Hello, *World* is compiled to:
Hello, World
Filters can have Ruby code interpolated with `#{}`. For example: - flavor = "raspberry" #content :textile I *really* prefer _#{flavor}_ jam. is compiled toI really prefer raspberry jam.