Slim

Slim is a template language whose goal is to reduce the view syntax to the essential parts without becoming cryptic. It started as an exercise to see how much could be removed from a standard html template (<, >, closing tags, etc...). As more people took an interest in Slim, the functionality grew and so did the flexibility of the syntax.

A short list of the features...

Elegant syntax

Short syntax without closing tags (Using indentation instead)

HTML style mode with closing tags

Configurable shortcut tags (# for <div id="..."> and . for <div class="..."> in the default configuration)

Introduction

What is Slim?

Slim is a fast, lightweight templating engine with support for Rails 3 and later. It has been heavily tested on all major ruby implementations. We use
continuous integration (travis-ci).

Slim's core syntax is guided by one thought: "What's the minimum required to make this work".

As more people have contributed to Slim, there have been syntax additions influenced from their use of Haml and Jade. The Slim team is open to these additions because we know beauty is in the eye of the beholder.

Slim uses Temple for parsing/compilation and is also integrated into Tilt, so it can be used together with Sinatra or plain Rack.

The architecture of Temple is very flexible and allows the extension of the parsing and compilation process without monkey-patching. This is used
by the logic less plugin and the translator plugin which provides I18n. In logic-less mode you can use Slim if you like the Slim syntax to build your HTML but don't want to write Ruby in your templates.

Why use Slim?

Slim allows you to write very minimal templates which are easy to maintain and pretty much guarantees that you write well-formed HTML and XML

The Slim syntax is aesthetic and makes it more fun to write templates. Since you can use Slim as a drop-in replacement in all the major frameworks it is easy to adopt.

The Slim architecture is very flexible and allows you to write syntax extensions and plugins.

Yes, Slim is speedy! Slim was developed right from the start with performance in mind.
Benchmarks are done for every commit at http://travis-ci.org/slim-template/slim.
Don't trust the numbers? That's as it should be. Please try the benchmark rake task yourself!

However in our opinion you should use Slim because of its features and syntax. We just ensure that Slim doesn't have a negative impact on the performance of your application.

How to start?

Install Slim as a gem:

geminstallslim

Include Slim in your Gemfile with gem 'slim' or require it with require 'slim'. That's it! Now, just use the .slim extension and you're good to go.

Syntax example

Here's a quick example to demonstrate what a Slim template looks like:

Indentation matters, but the indentation depth can be chosen as you like. If you want to first indent 2 spaces, then 5 spaces, it's your choice. To nest markup you only need to indent by one space, the rest is gravy.

Line indicators

Verbatim text |

The pipe tells Slim to just copy the line. It essentially escapes any processing.
Each following line that is indented greater than the pipe is copied over.

body
p
|
This is a test of the text block.

The parsed result of the above:

<body><p>This is a test of the text block.</p></body>

If the text starts on the same line, the left margin is set at the indent of the pipe + one space.
Any additional spaces will be copied over.

body
p
| This line is on the left margin.
This line will have one space in front of it.
This line will have two spaces in front of it.
And so on...

Control code -

The dash denotes control code. Examples of control code are loops and conditionals. end is forbidden behind -. Blocks are defined only by indentation.
If your ruby code needs to use multiple lines, append a backslash \ at the end of the lines. If your line ends with comma , (e.g because of a method call) you don't need the additional backslash before the linebreak.

body
- if articles.empty?
| No inventory

Output =

The equals sign tells Slim it's a Ruby call that produces output to add to the buffer. If your ruby code needs to use multiple lines, append a backslash \ at the end of the lines. For example:

= javascript_include_tag \
"jquery",
"application"

If your line ends with comma , (e.g because of a method call) you don't need the additional backslash before the linebreak. For trailing or leading whitespace the modifiers > and < are supported.

Output with trailing white space =>. Same as the single equals sign (=), except that it adds a trailing white space.

Output with leading white space =<. Same as the single equals sign (=), except that it adds a leading white space.

Output without HTML escaping ==

Same as the single equals sign (=), but does not go through the escape_html method. For trailing or leading whitespace the modifiers > and < are supported.

Output without HTML escaping and trailing white space ==>. Same as the double equals sign (==), except that it adds a trailing white space.

Output without HTML escaping and leading white space ==<. Same as the double equals sign (==), except that it adds a leading white space.

Code comment /

Use the forward slash for code comments - anything after it won't get displayed in the final render. Use / for code comments and /! for html comments

body
p
/ This line won't get displayed.
Neither does this line.
/! This will get displayed as html comments.

The parsed result of the above:

<body><p><!--This will get displayed as html comments.--></p></body>

HTML comment /!

Use the forward slash immediately followed by an exclamation mark for html comments (<!-- ... -->).

IE conditional comment /[...]

/[if IE]
p Get a better browser.

This renders as:

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

HTML tags

<!DOCTYPE> declaration

The doctype keyword can be used to generate the complex doctypes in a very simple manner.

Shortcuts

Tag shortcuts

You can define custom tag shortcuts by setting the option :shortcut. In Rails apps, you need to put this code for your shortcuts into an initializer like config/initializers/slim.rb. In Sinatra, you simply add the same configuration anywhere below the line where you require 'slim'.

Helpers, capturing and includes

If you use Slim you might want to extend your template with some helpers. Assume that you have the following helper

moduleHelpersdefheadline(&block)ifdefined?(::Rails)# In Rails we have to use capture!
"<h1>#{capture(&block)}</h1>"else# If we are using Slim without a framework (Plain Tilt),
# this works directly.
"<h1>#{yield}</h1>"endendend

which is included in the scope that executes the Slim template code. The helper can then be used in the Slim template as follows

p
= headline do
' Hello
= user.name

The content in the do block is then captured automatically and passed to the helper via yield. As a syntactic
sugar you can omit the do keyword and write only

p
= headline
' Hello
= user.name

Capturing to local variables

Using the Binding you can capture to local variables as follows:

moduleHelpersdefcapture_to_local(var,&block)set_var=block.binding.eval("lambda {|x| #{var} = x }")# In Rails we have to use capture!
# If we are using Slim without a framework (Plain Tilt),
# you can just yield to get the captured block.
set_var.call(defined?(::Rails)?capture(&block):yield)endend

The helper can then be used in the Slim template as follows

/ The captured_content variable must be known by the Binding beforehand.
= capture_to_local captured_content=:captured_content
p This will be captured in the variable captured_content
= captured_content

Another interesting use case is to use an enumerable and capture for each element. The helper could look like this

Include helper

If you want includes which are processed at compile time, you can take a look at Include partials.
However you can also execute subtemplates at runtime (similar to Rails' #render). You have to write your own include helper:

However this helper doesn't do any caching. You should therefore implement a more intelligent version of the helper which
fits your purposes. You should also be aware that most frameworks already bring their own include helper, e.g. Rails has render.

Text interpolation

Use standard Ruby interpolation. The text will be html escaped by default, but you can avoid escaping by using double braces.

body
h1 Welcome #{current_user.name} to the show.
| Unescaped #{{content}} is also possible.

To escape the interpolation (i.e. render as is)

body
h1 Welcome \#{current_user.name} to the show.

Embedded engines (Markdown, ...)

Thanks to Tilt, Slim has extensive support for embedding other template engines.

You can also specify HTML attributes for the following embedded engines:

Javascript

CSS

CoffeeScript

LESS

SASS

SCSS

Example:

scss class="myClass":
$color: #f00;
body { color: $color; }

This will generate the following HTML:

<style class="myClass" type="text/css">body{color:red}</style>

Configuring Slim

Slim and the underlying Temple framework are highly configurable.
The way how you configure Slim depends a bit on the compilation mechanism (Rails or Tilt). It is always possible to set default options per Slim::Engine class. This can be done in Rails' environment files. For instance, in config/environments/development.rb you probably want:

Default options

# Indent html for pretty debugging and do not sort attributes
Slim::Engine.set_optionspretty:true,sort_attrs:false

The other possibility is to set the options per thread which is interesting mostly for Rails:

Slim::Engine.with_options(option_hash)do# Any Slim engines which are created here use the option_hash
# For example in Rails:
render:page,layout:trueend

You have to be aware that the compiled engine code and the options are cached per template in Rails and you cannot change the option afterwards.

# First render call
Slim::Engine.with_options(pretty:true)dorender:page,layout:trueend# Second render call
Slim::Engine.with_options(pretty:false)dorender:page,layout:true# :pretty is still true because it is cached
end

Available options

The following options are exposed by the Slim::Engine and can be set with Slim::Engine.set_options.
There are a lot of them but the good thing is, that Slim checks the configuration keys and reports an error if you try to use an invalid configuration key.

Type

Name

Default

Purpose

String

:file

nil

Name of parsed file, set automatically by Slim::Template

Integer

:tabsize

4

Number of white spaces per tab (used by the parser)

String

:encoding

"utf-8"

Set encoding of template

String

:default_tag

"div"

Default tag to be used if tag name is omitted

Hash

:shortcut

=> {attr: 'class', '#' => 'id'}

Attribute shortcuts

Hash

:code_attr_delims

=> ')', '[' => ']', '{' => ''}

Attribute delimiters for Ruby code attributes

Hash

:attr_list_delims

=> ')', '[' => ']', '{' => ''}

Attribute list delimiter

Array<Symbol,String>

:enable_engines

nil (All enabled)

List of enabled embedded engines (whitelist)

Array<Symbol,String>

:disable_engines

nil (None disabled)

List of disabled embedded engines (blacklist)

Boolean

:disable_capture

false (true in Rails)

Disable capturing in blocks (blocks write to the default buffer

Boolean

:disable_escape

false

Disable automatic escaping of strings

Boolean

:use_html_safe

false (true in Rails)

Use String#html_safe? from ActiveSupport (Works together with :disable_escape)

Symbol

:format

:xhtml

HTML output format (Possible formats :html, :xhtml, :xml)

String

:attr_quote

'"'

Character to wrap attributes in html (can be ' or ")

Hash

:merge_attrs

=> ' '

Joining character used if multiple html attributes are supplied (e.g. class="class1 class2")

Array<String>

:hyphen_attrs

%w(data)

Attributes which will be hyphenated if a Hash is given (e.g. data=a:1,b:2 will render as data-a="1" data-b="2")

Boolean

:sort_attrs

true

Sort attributes by name

Symbol

:js_wrapper

nil

Wrap javascript by :comment, :cdata or :both. You can also :guess the wrapper based on :format.

There are more options which are supported by the Temple filters but which are not exposed and are not officially supported. You
have to take a look at the Slim and Temple code for that.

Option priority and inheritance

For developers who know more about Slim and Temple architecture it is possible to override default
options at different positions. Temple uses an inheritance mechanism to allow subclasses to override
options of the superclass. The option priorities are as follows:

Sinatra

Rails

Rails generators are provided by slim-rails. slim-rails
is not necessary to use Slim in Rails though. Just install Slim and add it to your Gemfile with gem 'slim'.
Then just use the .slim extension and you're good to go.

Streaming

HTTP streaming is enabled by default if you use a Rails version which supports it. However you have to be aware that streaming only improves the perceived
performance. The rendering time in total will increase. If you want to disable it use:

Angular2

Slim now supports Angular2 syntax. But you need to set some configuration options:

splat_prefix option

This option tells parser what syntax to use for splat attributes.
Default value is asterisk: splat_prefix: '*'
Asterisk is also used in Angular2 for structural directives such as *ngIf and others, so default configuration causes a conflict between slim and angular2 syntax.

There are two ways to resolve it:

Set splat_prefix to any custom value, double asterisk, for example: splat_prefix: '**'. Now structural directives should work as expected. Remember that now splat attributes should be written with new custom prefix before them.

Use alternative directive syntax without asterisk.

Attribute delimeters

Angular and slim both uses brackets in their syntax. So there are also two ways:

Template Converters (HAML, ERB, ...)

Testing

Benchmarks

Yes, Slim is one of the fastest Ruby template engines out there!
In production mode Slim is nearly as fast as Erubis (which is the fastest template engine).
But we would be happy if you chose Slim also for any other reason, we assure
you performance will not be an obstacle.

Run the benchmarks with rake bench. You can add the option slow to
run the slow parsing benchmark which needs more time. You can also increase the number of iterations.