Permalink
Fetching contributors…
Cannot retrieve contributors at this time
1291 lines (945 sloc) 19.3 KB

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

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

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://slim-lang.com">slim-lang.com</a>

renders as

<a href="http://slim-lang.com">slim-lang.com</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://slim-lang.com" slim-lang.com

renders as

Link to <a href="http://slim-lang.com">slim-lang.com</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://slim-lang.com">slim-lang.com</a>

renders as

<a href="http://slim-lang.com">slim-lang.com</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 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 legacy syntax =' is also supported.

=' 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 legacy syntax ==' is also supported.

==' '<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 >. The legacy syntax with ' is also supported.

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

renders as

<a class="test" id="closed" /> <a class="test" id="closed" /> <a href="url1">Link1</a>  <a href="url1">Link1</a><a href="url2">Link2</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://slim-lang.com" class="important") Link
li
  a[href="http://slim-lang.com" class="important"] Link
li
  a{href="http://slim-lang.com" class="important"} Link

renders as

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

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

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

     class="important") Link

renders as

<a class="important" href="http://slim-lang.com">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://slim-lang.com" title='Slim Homepage' Goto the Slim homepage

renders as

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

You can use text interpolation in the quoted attributes:

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

renders as

<a href="http://slim-lang.com">Goto the slim-lang.com</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 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://slim-lang.com/" Slim-lang.com

renders as

<a class="menu highlight" href="http://slim-lang.com/">Slim-lang.com</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 a_unless_current
    @page_current ? {tag: 'span'} : {tag: 'a', href: 'http://slim-lang.com/'}
  end
- @page_current = true
*a_unless_current Link
- @page_current = false
*a_unless_current Link

renders as

<span>Link</span><a href="http://slim-lang.com/">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.

.-test text
#test- text
.--a#b- text
.a--test-123#--b 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>

Text interpolation

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

- user="John Doe <john@doe.net>"
h1 Welcome #{user}!

renders as

<h1>
  Welcome John Doe &lt;john@doe.net&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