Skip to content
ZeroServer.tools

HAML to HTML

Convert HAML templates to HTML — tags, classes, IDs, both attribute syntaxes, filters and doctypes, with the errors Haml would report.

or drop a file here

What is HAML?

HAML (HTML Abstraction Markup Language) is a Ruby-ecosystem template language that uses indentation instead of closing tags. Popular in Ruby on Rails apps, it eliminates boilerplate: %h1.title Hello maps to <h1 class="title">Hello</h1>. This converter follows the rules of Haml itself, version 7.5, for tags, classes, IDs, both attribute syntaxes, whitespace removal, comments, doctypes and the :css, :javascript and :plain filters, and lists the errors Haml would raise, line by line. Ruby code (= and -) is shown as an HTML comment where its output would go, since it needs a server to run.

Built and maintained by Meet Shah · Last updated

What this tool is used for

  • Understanding an existing HAML template by seeing the markup it produces.
  • Migrating a Ruby view off HAML onto plain templates.
  • Debugging nesting in a HAML file where indentation has gone wrong.
  • Converting a snippet from a tutorial into ordinary HTML.
  • Checking what attributes a HAML shorthand actually generates.

How it works in practice

A worked example

A front-end developer is moving the header partial of a Rails app's HAML views into a static HTML prototype for a new marketing page, without installing Ruby to render it.

Input
%header.site-header
  %a.logo{href: "/"}
    %img{src: "/logo.svg", alt: "Acme"}
  %nav#main-nav
    %ul.nav-links
      %li
        %a{href: "/pricing"} Pricing
      - if current_user
        %li
          %a{href: "/account"} Account
      - else
        %li
          %a{href: "/login"} Sign in
Output
<header class="site-header">
  <a class="logo" href="/">
    <img src="/logo.svg" alt="Acme" />
  </a>
  <nav id="main-nav">
    <ul class="nav-links">
      <li>
        <a href="/pricing">Pricing</a>
      </li>
      <!-- [dynamic: - if current_user] -->
        <li>
          <a href="/account">Account</a>
        </li>
      <!-- [dynamic: - else] -->
        <li>
          <a href="/login">Sign in</a>
        </li>
    </ul>
  </nav>
</header>

Each tag line became one element: the dot shorthand became a class, #main-nav became an id and the braces became ordinary attributes, so %a.logo{href: "/"} turned into <a class="logo" href="/">. None of the closing tags are in the source. An element with its text on the same line is closed on that line, and one with indented children stays open until a later line starts at the same depth or further out, with anything still open closed when the input ends, which is why the indentation has to be consistent. The image line came out with a trailing slash because img is on the converter's list of void elements, which never take a closing tag in HTML. Haml itself treats img as empty by default, so the source needs no slash, and the HTML specification says a slash on a void element has no effect of any kind.

The edge case that catches people

Both branches of the if and else are in the output, so a browser showing this HTML displays the Account link and the Sign in link together. In Haml, a line starting with a hyphen is Ruby that runs without printing anything, and which branch appears is decided each time the template is rendered. The converter has no Ruby to run, so it turns each such line, along with any equals-sign line that is more than a plain literal, into an HTML comment marking where the code was, and then emits the indented lines beneath it whatever the condition says. Delete the branch you do not want before converting, or remove its list item from the output afterwards.

When not to use this tool

Do not use it for templates that do real work in Ruby. Lines that print a value with an equals sign, helper calls such as link_to, instance variables, interpolation and the :markdown, :sass and :erb filters all need a Ruby runtime, and the converter can only leave a placeholder comment or the Ruby source itself where their output should be. For those, open the page in the running application and copy the markup the browser received, or, for a template that does not depend on Rails helpers, render it with the Haml gem, whose command-line tool has a render command that prints the HTML for a file. The converter is meant for the static structure of a template, its tags, classes, ids and attributes, where it saves reading the nesting by eye.

Frequently Asked Questions

What is HAML?
An indentation-based templating language for Ruby, designed to remove closing tags entirely — nesting is expressed by whitespace, so the structure is visible in the shape of the file. %h1 is an h1 element and its children are simply indented under it.
How are classes and IDs written?
With CSS-style shorthand appended to the tag: %h1.hero#main is <h1 class="hero" id="main">. A bare .card with no tag defaults to a div, which is why HAML files contain so few explicit divs.
What does the trailing slash mean?
It closes an element that has no content, so no closing tag follows. Haml does that by itself for void elements such as br, img and input, so they need no slash. On other tags, such as an SVG path, this converter writes <path />, where Haml's HTML format prints an unclosed <path>. Text after the slash is an error.
What is !!! 5?
The doctype declaration, producing <!DOCTYPE html>. In Haml's default HTML format the number changes nothing, so a bare !!! gives the same line, while !!! Strict, !!! Frameset and !!! Transitional give the HTML 4.01 doctypes. !!! XML writes nothing at all.
Is HAML still used?
Mainly in older Rails applications. Newer Ruby projects tend to use ERB or Slim, and the wider industry has moved to component frameworks where markup and logic live together. Conversion to HTML is usually part of migrating away from it.

Common errors and gotchas

  • Mixing tabs and spaces, which HAML treats as a structural error rather than a style issue.
  • Assuming Ruby interpolation converts, since it needs the runtime and cannot be resolved statically.
  • Expecting :markdown, :sass or :erb blocks to render. Each needs Ruby or a compiler, so the converter keeps their content in a comment, while :css and :javascript convert.
  • Overlooking that a single indentation mistake reparents an entire block.
  • Expecting helper calls to render, when they are application code rather than markup.
  • Writing - end to close a block, as in ERB. Haml rejects it, because un-indenting is what ends a block.
  • Putting a slash on a tag that is not void, such as %div/, which leaves the element open in a browser instead of empty.

Related Converters tools

Private & free — this tool runs entirely in your browser.

IndieKit — Ship your Next.js startup in days.affiliate