Slab reference

This reference guide provides a comprehensive overview of Slab's features and syntax.

Note: Slab is still a young project. The features demonstrated here work as shown, but they may not always generalize as expected.

Before reading this reference guide, you may want to start with the tutorial first.

Introduction

Slab is an alternative syntax for writing HTML, plus some programming language features (often found in templating languages, such as conditionals and loops). The slab command-line tool processes .slab files and renders them into HTML.

Slab revolves around the concept of fragments. Fragments are pieces of HTML that act like functions. You can define a fragment and then call it:

frag page
  doctype html
  body
    content

page
  h1 A title
  p A paragraph.

The above example defines a fragment named page. It then calls page, passing a block of HTML (containing a heading and a paragraph) as an argument (implicitly called content).

The slab render --pretty command can be used to transform the above code into the following HTML:

<!DOCTYPE HTML>

<body>
    <h1>
        A title
    </h1>
    <p>
        A paragraph.
    </p>
</body>

When it is not pretty-printed, it looks like this instead:

<!DOCTYPE HTML>
<body><h1>A title</h1><p>A paragraph.</p></body>

Basic syntax

Elements

At its core, Slab is a shorthand notation for representing HTML. An HTML element is written as its tag name, followed by text content, or by other elements. The tree structure is captured by indenting child elements instead of using closing tags. This syntax is identical to that used in Pug, which inspired Slab.

ul
  li Item
  li Item
  li Item
<ul>
    <li>
        Item
    </li>
    <li>
        Item
    </li>
    <li>
        Item
    </li>
</ul>

Note: We show the resulting HTML pretty-printed. In a production environment, we would generate the following instead:

<ul><li>Item</li><li>Item</li><li>Item</li></ul>

IDs and classes

To assign an ID to an element, the regular attribute notation can be used (see below). Slab also supports tacking the ID directly to the element name with a # character.

h1#title A title
<h1 id="title">
    A title
</h1>

Classes work similarly, using the . character for short notation instead.

h1.hero A title
p.lede.muted Catching summary.
<h1 class="hero">
    A title
</h1>
<p class="lede muted">
    Catching summary.
</p>

An ID or a class can also be used by itself. In this case, a div element is assumed.

.playground
  #app
<div class="playground">
    <div id="app">
    </div>
</div>

Attributes

Attributes (including IDs and classes) can be assigned to an element using a syntax similar to HTML itself, by placing them in parentheses, directly after the element name. To add multiple attributes, use a comma to separate them.

form(action='/login', method='POST')
<form action="/login" method="POST">
</form>

Comments

Comments are introduced with -- or ---, either with the comment itself on the same line, or as an indented block of text on subsequent lines.

-- A regular comment.

--- A comment in the generated HTML.

---
  Another comment
  in the generated
  HTML.

--
  Another
  regular
  comment.
<!-- A comment in the generated HTML. -->
<!-- Another comment
in the generated
HTML. -->

Fragments

Fragments are blocks of HTML that can be named and reused.

Basics

To define a new fragment, the frag keyword is used, followed by the name of the fragment, and optionally by its formal parameters (in curly braces). The body of the fragment consists of the following indented lines. To call a fragment, its name is used as a regular element and its actual arguments are introduced with the with keyword.

frag card{para}
  h1 Card
  para

card
  with para
    p A paragraph.
<h1>
    Card
</h1>
<p>
    A paragraph.
</p>

In the example above, the fragment card is defined. In its body, it itself calls another fragment, para. This fragment is passed as an argument when card is called. Arguments are indented below the call.

Implicit content argument

To make a call to a fragment look more like a regular HTML elements, indented lines below the call are passed as an argument called content. I.e. the following example is equivalent to the example above:

frag card
  h1 Card
  content

card
  p A paragraph.
<h1>
    Card
</h1>
<p>
    A paragraph.
</p>

Default arguments

Fragments can define default contents for their arguments (making them optional) by using the default keyword before calling an argument.

frag card
  h1 Card
  default content
    p Default paragraph.

card
  p Another paragraph.

card
<h1>
    Card
</h1>
<p>
    Another paragraph.
</p>
<h1>
    Card
</h1>
<p>
    Default paragraph.
</p>

Expression arguments

Fragments can also take non-fragment arguments. The expressions that can be used in Slab are documented in the Expression language section.

A fragment is defined to take (non-fragment) arguments by using parentheses directly after its name, mentioning parameter names. Similarly, when calling a fragment, (non-fragment) arguments are passed between parentheses.

frag hello(name)
  .greeting
    p Hello, #(name).
    content

hello('Alice')
  p Some content.
<div class="greeting">
    <p>
        Hello, Alice.
    </p>
    <p>
        Some content.
    </p>
</div>

Expression language

In addition to its lightweight syntax equivalent to HTML, Slab supports some constructs commonly found in programming languages.

Variable declarations

Variables are declared with the let keyword. A variable (or a more general expression) can be used as the content of an element. This is done by immediately following the element name with a = character.

let a = 1
    b = "Alice"
p= a
p= b
<p>
    1
</p>
<p>
    Alice
</p>

Expressions

Simple values (booleans, integers and string literals) are supported, as well as simple operations: addition, subtraction, multiplication, and division for integers, and comparison for all types.

let a = 1
p= a + 2 * 3
<p>
    7
</p>

Strings can be concatenated using the + operator. Integers can be converted to strings with the show function. Strings can be "converted" to booleans using the null function.

let a = 1
p= show (a + 2) + '.'
<p>
    3.
</p>

String interpolation

Expressions can be used within the text content of an element using the #(...) syntax.

let name = "Bob"
p Hello, #(name).
<p>
    Hello, Bob.
</p>

JSON support

Static JSON files can be loaded by using their relative path. This makes it easy to store and template data outside of a Slab file.

Assume a file with the following JSON content:

[
  {
    "username": "Alice",
    "email": "alice@example.com"
  },
  {
    "username": "Bob",
    "email": "bob@example.com"
  }
]

Here is an example of how to format the JSON data:

let values = ../../data/values.json
ul
  for value in values
    li= value['username']
<ul>
    <li>
        Alice
    </li>
    <li>
        Bob
    </li>
</ul>

Control flow

Slab supports conditionals and loops using if and for blocks.

Conditionals

The else branch is optional.

if true
  p A.
else
  p B.
<p>
    A.
</p>

Loops

It is possible to iterate on lists and objects. In the following example, the index and the key are optional.

ul
  for val, index in [1, 2]
    li val: #(val), index: #(index)

ul
  for val, key in {1: 'one', 2: 'two'}
    li val: #(val), key: #(key)
<ul>
    <li>
        val: 1, index: 0
    </li>
    <li>
        val: 2, index: 1
    </li>
</ul>
<ul>
    <li>
        val: one, key: 1
    </li>
    <li>
        val: two, key: 2
    </li>
</ul>

Modularity

Slab code can be split into multiple files by using include statements.

An include works by inlining the content of the included file in the including file. When the included file has a .slab extension, it is interpreted as if its code was present in the including file. In particular, any toplevel code that is not let expressions or fragment definitions will render as-if directly written in the including code, and definitions can be used in the including file.

The include syntax allows you to specify a filter. Currently, the only supported filter is :escape-html. It can be used when you want to show HTML code and also to show Slab code (i.e. disabling its interpretation). This is how the code examples on this page are shown.

include basic.slab
<ul>
    <li>
        Item
    </li>
    <li>
        Item
    </li>
    <li>
        Item
    </li>
</ul>
include:escape-html basic.slab
ul
  li Item
  li Item
  li Item