12 HAML
On this page:
12.1 Syntax
haml

12 HAML🔗

 (require koyo/haml) package: koyo-lib

haml is a convenience macro for generating xexprs with less boilerplate. Its syntax is inspired by haml – whence its name – but if you’ve used Clojure’s hiccup or any similar templating language (like jade or pug), then haml will feel familiar to you.

12.1 Syntax🔗

syntax

(haml element ...+)

 
element = (selector maybe-attributes element ...)
  | (unless cond-expr e0 e ...)
  | (when cond-expr e0 e ...)
  | &html-entity-name
  | ,@expr
  | expr
     
selector = :tag-name
  | .class-name
  | .class-name-1.class-name-2.class-name-n#id
  | :tag-name.class-name
  | :tag-name.class-name#id
     
maybe-attributes = 
  | ([:attribute-name maybe-expr] ...)
Produces an x-expression.

Literal numbers and strings are returned unmodified:

> (haml 1)

1

> (haml "hello")

"hello"

Identifiers that start with an & character are converted to symbols with the initial & removed:

> (haml &mdash)

'mdash

Other identifiers are evaluated from the enclosing environment:

> (let ([a-symbol 'mdash])
    (haml a-symbol))

'mdash

Element tags start with a colon:

> (haml
   (:h1 "Hello World"))

'(h1 () "Hello World")

Id and class attributes can be attached to a tag via a shorthand syntax:

> (haml
   (:h1.title#main-title "Hello World"))

'(h1 ((id "main-title") (class "title")) "Hello World")

Tag names are optional if a class name is provided, in which case the tag defaults to div:

> (haml
   (.content
    (:h1.title "Hello World")))

'(div ((class "content")) (h1 ((class "title")) "Hello World"))

Repeated attributes are concatenated into a single value:

> (haml
   (.content
    (:h1.title
     ([:class "hello"]
      [:data-example "1"]
      [:data-example "2"])
     "Hello World")))

'(div ((class "content")) (h1 ((class "title hello") (data-example "1 2")) "Hello World"))

Lists of elements can be spliced in using the ,@e syntax:

> (haml
   (.content
    (:ul.items
     ,@(for/list ([it '("a" "b" "c")])
         `(li ,it)))))

'(div ((class "content")) (ul ((class "items")) (li "a") (li "b") (li "c")))

Expressions that don’t parse as elements are evaluated in place at runtime:

> (define (say-hi name)
    (format "Hi, ~a!" name))
> (haml
   (:h1 (say-hi "Bogdan")))

'(h1 () "Hi, Bogdan!")

The when and unless forms are special-cased so that they automatically splice their result, if any, into the enclosing expression:

> (for ([v '(#t #f)])
    (println
     (haml
      (:h1 (when v "a") "title"))))

'(h1 () "a" "title")

'(h1 () "title")

Passing multiple elements to the haml macro produces a list of xexpr?s:

> (haml
   (:li "a")
   (:li "b"))

'((li () "a") (li () "b"))

Changed in version 0.10 of package koyo-lib: when, unless and unquote-splicing are now recognized by binding. The @-style splicing syntax is no longer supported.
Changed in version 0.17: Element attributes may now begin with an @ symbol.