Slim test suite

You can run this testsuite with rake test:literate.

We use pretty mode in the test suite to make the output more readable. Pretty mode is enabled by setting the option

:pretty => true

Line indicators

In this section we test all line indicators.

Text |

A text blocks starts with the | as line indicator.

| Text block

renders as

Text block

You can add leading or trailing white space with the < and > markers:

|< Text with leading whitespace.
|  Text with leading whitespace.
|> Text with trailing whitespace.
|<> Text with both leading and trailing whitespace.

renders as

 Text with leading whitespace. Text with leading whitespace.Text with trailing whitespace.  Text with both leading and trailing whitespace. 

Multiple lines can be indented beneath the first text line.

|  Text
    block

     with

    multiple
   lines

renders as

 Text
  block

   with

  multiple
 lines

The first line of a text block determines the indentation.

|

   Text
    block

     with

    multiple
   lines

renders as

Text
 block

  with

 multiple
lines
|><

   Text
    block

     with

    multiple
   lines

renders as

 Text
 block

  with

 multiple
lines 

You can nest text blocks beneath tags.

body
  | Text

renders as

<body>
  Text
</body>

You can embed html code in the text which is not escaped.

| <a href="http://github.com/slim-template/slim">github.com/slim-template/slim</a>

renders as

<a href="http://github.com/slim-template/slim">github.com/slim-template/slim</a>
|<a href="http://github.com/slim-template/slim">github.com/slim-template/slim</a>

renders as

<a href="http://github.com/slim-template/slim">github.com/slim-template/slim</a>

Text with trailing white space '

A text blocks with trailing white space starts with the ' as line indicator.

' Text block

renders as

Text block 

This is especially useful if you use tags behind a text block.

' Link to
a href="http://github.com/slim-template/slim" github.com/slim-template/slim

renders as

Link to <a href="http://github.com/slim-template/slim">github.com/slim-template/slim</a>

Multiple lines can be indented beneath the first text line.

'  Text
    block

     with

    multiple
   lines

renders as

 Text
  block

   with

  multiple
 lines 

The first line of a text block determines the indentation.

'

   Text
    block

     with

    multiple
   lines

renders as

Text
 block

  with

 multiple
lines 

Inline HTML <

HTML can be written directly.

<a href="http://github.com/slim-template/slim">github.com/slim-template/slim</a>

renders as

<a href="http://github.com/slim-template/slim">github.com/slim-template/slim</a>

HTML tags allow nested blocks inside.

<html>
  <head>
    title Example
  </head>
  body
    - if true
      | yes
    - else
      | no
</html>

renders as

<html><head><title>Example</title></head>
<body>
  yes
</body>
</html>

Control code -

The dash - denotes arbitrary control code.

- greeting = 'Hello, World!'
- if false
  | Not true
- else
  = greeting

renders as

Hello, World!

Complex code can be broken with backslash \.

- greeting = 'Hello, '+\
     \
    'World!'
- if false
  | Not true
- else
  = greeting

renders as

Hello, World!

You can also write loops like this

- items = [{name: 'table', price: 10}, {name: 'chair', price: 5}]
table#items
  - for item in items do
    tr
      td.name = item[:name]
      td.price = item[:price]

which renders as

<table id="items">
  <tr>
    <td class="name">
      table
    </td>
    <td class="price">
      10
    </td>
  </tr>
  <tr>
    <td class="name">
      chair
    </td>
    <td class="price">
      5
    </td>
  </tr>
</table>

The do keyword can be omitted.

- items = [{name: 'table', price: 10}, {name: 'chair', price: 5}]
table#items
  - for item in items
    tr
      td.name = item[:name]
      td.price = item[:price]

which renders as

<table id="items">
  <tr>
    <td class="name">
      table
    </td>
    <td class="price">
      10
    </td>
  </tr>
  <tr>
    <td class="name">
      chair
    </td>
    <td class="price">
      5
    </td>
  </tr>
</table>

Output =

The equal sign = produces dynamic output.

= 7*7

renders as

49

Dynamic output is escaped by default.

= '<script>evil();</script>'

renders as

&lt;script&gt;evil();&lt;/script&gt;

Long code lines can be broken with \.

= (0..10).map do |i|\
  2**i \
end.join(', ')

renders as

1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024

You don't need the explicit \ if the line ends with a comma ,.

ruby:
  def self.test(*args)
    args.join('-')
  end
= test('arg1',
'arg2',
'arg3')

renders as

arg1-arg2-arg3

You can also disable HTML escaping globally by setting the option

:disable_escape => true
= '<script>evil();</script>'

renders as

<script>evil();</script>

The equal sign with modifier => produces dynamic output with a trailing white space.

=> 7*7

renders as

49 
=< 7*7

renders as

 49

The equal sign with modifier =< produces dynamic output with a leading white space.

=< 7*7

renders as

 49

The equal sign with modifiers =<> produces dynamic output with a leading and trailing white space.

=<> 7*7

renders as

 49 

Output without HTML escaping ==

The double equal sign == produces dynamic output without HTML escaping.

== '<script>evil();</script>'

renders as

<script>evil();</script>

The option option

:disable_escape => true

doesn't affect the output of ==.

== '<script>evil();</script>'

renders as

<script>evil();</script>

The double equal sign with modifier ==> produces dynamic output without HTML escaping and trailing white space.

==> '<script>evil();</script>'

renders as

<script>evil();</script> 

The option option

:disable_escape => true

doesn't affect the output of ==.

==> '<script>evil();</script>'

renders as

<script>evil();</script> 

Code comment /

Code comments begin with / and produce no output.

/ Comment
body
  / Another comment
    with

    multiple lines
  p Hello!

renders as

<body>
  <p>
    Hello!
  </p>
</body>

HTML comment /!

Code comments begin with /!.

/! Comment
body
  /! Another comment
     with multiple lines
  p Hello!
  /!
      First line determines indentation

      of the comment

renders as

<!--Comment-->
<body>
  <!--Another comment
  with multiple lines-->
  <p>
    Hello!
  </p>
  <!--First line determines indentation

  of the comment-->
</body>

IE conditional comment /[...]

/[if IE]
    p Get a better browser.

renders as

<!--[if IE]>
<p>
  Get a better browser.
</p>
<![endif]-->

HTML tags

Doctype tags

The doctype tag is a special tag which can be used to generate the complex doctypes in a very simple way.

You can output the XML version using the doctype tag.

doctype xml
doctype xml ISO-8859-1

renders as

<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="iso-8859-1" ?>

In XHTML mode the following doctypes are supported:

doctype html
doctype 5
doctype 1.1
doctype strict
doctype frameset
doctype mobile
doctype basic
doctype transitional

renders as

<!DOCTYPE html>
<!DOCTYPE html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

If we activate HTML mode with the option

:format => :html

the following doctypes are supported:

doctype html
doctype 5
doctype strict
doctype frameset
doctype transitional

renders as

<!DOCTYPE html>
<!DOCTYPE html>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

Closed tags

You can close tags explicitly by appending a trailing /.

div id="not-closed"
.closed/
#closed/
div id="closed"/

renders as

<div id="not-closed"></div>
<div class="closed" />
<div id="closed" />
<div id="closed" />

Note, that this is usually not necessary since the standard html tags (img, br, ...) are closed automatically.

img src="image.png"

renders as

<img src="image.png" />

Trailing and leading whitespace

You can force a trailing whitespace behind a tag by adding >.

a#closed> class="test" /
a#closed> class="test"/
a> href='url1' Link1
a< href='url1' Link1

renders as

<a class="test" id="closed" /> <a class="test" id="closed" /> <a href="url1">Link1</a>  <a href="url1">Link1</a>

If you combine > and => only one trailing whitespace is added.

a> => 'Text1'
a => 'Text2'
a> = 'Text3'
a>= 'Text4'
a=> 'Text5'
a<= 'Text6'
a=< 'Text7'

renders as

<a>Text1</a> <a>Text2</a> <a>Text3</a> <a>Text4</a> <a>Text5</a>  <a>Text6</a> <a>Text7</a>

You can force a leading whitespace before a tag by adding <.

a#closed< class="test" /
a#closed< class="test"/
a< href='url1' Link1
a< href='url2' Link2
 <a class="test" id="closed" /> <a class="test" id="closed" /> <a href="url1">Link1</a> <a href="url2">Link2</a>

You can also combine both.

a#closed<> class="test" /
a#closed>< class="test"/
a<> href='url1' Link1
a<> href='url2' Link2
 <a class="test" id="closed" />  <a class="test" id="closed" />  <a href="url1">Link1</a>  <a href="url2">Link2</a> 

Inline tags

Sometimes you may want to be a little more compact and inline the tags.

ul
  li.first: a href="/first" First
  li: a href="/second" Second

renders as

<ul>
  <li class="first">
    <a href="/first">First</a>
  </li>
  <li>
    <a href="/second">Second</a>
  </li>
</ul>

For readability, don't forget you can wrap the attributes.

ul
  li.first: a(href="/first") First
  li: a(href="/second") Second

renders as

<ul>
  <li class="first">
    <a href="/first">First</a>
  </li>
  <li>
    <a href="/second">Second</a>
  </li>
</ul>

Text content

Dynamic content =

Attributes

Attribute wrapper

If a delimiter makes the syntax more readable for you, you can use the characters {...}, (...), [...] to wrap the attributes.

li
  a(href="http://github.com/slim-template/slim" class="important") Link
li
  a[href="http://github.com/slim-template/slim" class="important"] Link
li
  a{href="http://github.com/slim-template/slim" class="important"} Link

renders as

<li>
  <a class="important" href="http://github.com/slim-template/slim">Link</a>
</li>
<li>
  <a class="important" href="http://github.com/slim-template/slim">Link</a>
</li>
<li>
  <a class="important" href="http://github.com/slim-template/slim">Link</a>
</li>

If you wrap the attributes, you can spread them across multiple lines:

a(href="http://github.com/slim-template/slim"

     class="important") Link

renders as

<a class="important" href="http://github.com/slim-template/slim">Link</a>
dl(
  itemprop='address'
  itemscope
  itemtype='http://schema.org/PostalAddress'
)

renders as

<dl itemprop="address" itemscope="" itemtype="http://schema.org/PostalAddress"></dl>

You may use spaces around the wrappers and assignments:

h1 id = "logo" Logo
h2 [ id = "tagline" ] Tagline

renders as

<h1 id="logo">
  Logo
</h1>
<h2 id="tagline">
  Tagline
</h2>

Quoted attributes

You can use single or double quotes for simple text attributes.

a href="http://github.com/slim-template/slim" title='Slim Homepage' Goto the Slim homepage

renders as

<a href="http://github.com/slim-template/slim" title="Slim Homepage">Goto the Slim homepage</a>

You can use text interpolation in the quoted attributes:

- url='github.com/slim-template/slim'
a href="http://#{url}" Goto the #{url}
a href="{"test"}" Test of quoted text in braces

renders as

<a href="http://github.com/slim-template/slim">Goto the github.com/slim-template/slim</a><a href="{&quot;test&quot;}">Test of quoted text in braces</a>

The attribute value will be escaped by default. Use == if you want to disable escaping in the attribute.

li
  a href='&' Link
li
  a href=="&amp;" Link

renders as

<li>
  <a href="&amp;">Link</a>
</li>
<li>
  <a href="&amp;">Link</a>
</li>

You can use newlines in quoted attributes

a data-title="help" data-content="extremely long help text that goes on
  and one and one and then starts over...." Link

renders as

<a data-content="extremely long help text that goes on
and one and one and then starts over...." data-title="help">Link</a>

You can break quoted attributes with an backslash \

a data-title="help" data-content="extremely long help text that goes on\
  and one and one and then starts over...." Link

renders as

<a data-content="extremely long help text that goes on and one and one and then starts over...." data-title="help">Link</a>

Ruby attributes

Long ruby attributes can be broken with backslash \

a href=1+\
   1 Link

renders as

<a href="2">Link</a>

You don't need the explicit \ if the line ends with a comma ,.

ruby:
  def self.test(*args)
    args.join('-')
  end
a href=test('arg1',
'arg2',
'arg3') Link

renders as

<a href="arg1-arg2-arg3">Link</a>

Boolean attributes

The attribute values true, false and nil are interpreted as booleans. If you use the attribut wrapper you can omit the attribute assigment.

- true_value1 = ""
- true_value2 = true
input type="text" disabled=true_value1
input type="text" disabled=true_value2
input type="text" disabled="disabled"
input type="text" disabled=true
input(type="text" disabled)

renders as

<input disabled="" type="text" /><input disabled="" type="text" /><input disabled="disabled" type="text" /><input disabled="" type="text" /><input disabled="" type="text" />
- false_value1 = false
- false_value2 = nil
input type="text" disabled=false_value1
input type="text" disabled=false_value2
input type="text"
input type="text" disabled=false
input type="text" disabled=nil

renders as

<input type="text" /><input type="text" /><input type="text" /><input type="text" /><input type="text" />

If html5 is activated the attributes are written as standalone.

:format => :html
- true_value1 = ""
- true_value2 = true
input type="text" disabled=true_value1
input type="text" disabled=true_value2
input type="text" disabled="disabled"
input type="text" disabled=true
input(type="text" disabled)

renders as

<input disabled="" type="text"><input disabled type="text"><input disabled="disabled" type="text"><input disabled type="text"><input disabled type="text">

Attribute merging

You can configure attributes to be merged if multiple are given (See option :merge_attrs). In the default configuration this is done for class attributes with the white space as delimiter.

a.menu class="highlight" href="http://github.com/slim-template/slim/" github.com/slim-template/slim

renders as

<a class="menu highlight" href="http://github.com/slim-template/slim/">github.com/slim-template/slim</a>

You can also use an Array as attribute value and the array elements will be merged using the delimiter.

- classes = [:alpha, :beta]
span class=["first","highlight"] class=classes First
span class=:second,:highlight class=classes Second

renders as

<span class="first highlight alpha beta">First</span><span class="second highlight alpha beta">Second</span>

Splat attributes *

Dynamic tags *

You can create completely dynamic tags using the splat attributes. Just create a method which returns a hash with the :tag key.

ruby:
  def self.a_unless_current
    @page_current ? {tag: 'span'} : {tag: 'a', href: 'http://github.com/slim-template/slim/'}
  end
- @page_current = true
*a_unless_current Link
- @page_current = false
*a_unless_current Link

renders as

<span>Link</span><a href="http://github.com/slim-template/slim/">Link</a>

Shortcuts

Tag shortcuts

We add tag shortcuts by setting the option :shortcut.

:shortcut => {'c' => {tag: 'container'}, 'sec' => {tag:'section'}, '#' => {attr: 'id'}, '.' => {attr: 'class'} }
sec: c.content Text

renders to

<section>
  <container class="content">Text</container>
</section>

Attribute shortcuts

We add & to create a shortcut for the input elements with type attribute by setting the option :shortcut.

:shortcut => {'&' => {tag: 'input', attr: 'type'}, '#' => {attr: 'id'}, '.' => {attr: 'class'} }
&text name="user"
&password name="pw"
&submit.CLASS#ID

renders to

<input name="user" type="text" /><input name="pw" type="password" /><input class="CLASS" id="ID" type="submit" />

This is stupid, but you can also use multiple character shortcuts.

:shortcut => {'&' => {tag: 'input', attr: 'type'}, '#<' => {attr: 'id'}, '#>' => {attr: 'class'} }
&text name="user"
&password name="pw"
&submit#>CLASS#<ID

renders to

<input name="user" type="text" /><input name="pw" type="password" /><input class="CLASS" id="ID" type="submit" />

You can also set multiple attributes per shortcut.

:shortcut => {'.' => {attr: %w(id class)} }
.test

renders to

<div class="test" id="test"></div>

Shortcuts can also have multiple characters.

:shortcut => {'.' => {attr: 'class'}, '#' => {attr: 'id'}, '.#' => {attr: %w(class id)} }
.#test
.test
#test

renders to

<div class="test" id="test"></div>
<div class="test"></div>
<div id="test"></div>

ID shortcut and class shortcut .

ID and class shortcuts can contain dashes, slashes with digits, and colons.

.-test text
#test- text
.--a#b- text
.a--test-123#--b text
.a-1/2#b-1/2 text
.ab:c-test#d:e text

renders as

<div class="-test">
  text
</div>
<div id="test-">
  text
</div>
<div class="--a" id="b-">
  text
</div>
<div class="a--test-123" id="--b">
  text
</div>
<div class="a-1/2" id="b-1/2">
  text
</div>
<div class="ab:c-test" id="d:e">
  text
</div>

Text interpolation

Use standard Ruby interpolation. The text will be html escaped by default.

- user="John Doe <[email protected]>"
h1 Welcome #{user}!

renders as

<h1>
  Welcome John Doe &lt;[email protected]&gt;!
</h1>

Pretty printing of XML

We can enable XML mode with

:format => :xml
doctype xml
document
  closed-element/
  element(boolean-attribute)
    child attribute="value"
      | content
<?xml version="1.0" encoding="utf-8" ?>
<document>
  <closed-element />
  <element boolean-attribute="">
    <child attribute="value">
      content
    </child>
  </element>
</document>

Embedded engines

Configuring Slim

Plugins