Features & Documentation

Malline is strongly influenced by cgi.rb and Markaby, so the main syntax may be quite familiar to any Ruby on Rails user. Check out alternatives to Malline.

All these HTML blocks are real renders of corresponding ruby block. However, the html outputs have been automatically filtered though XML Indent to make HTML look nice. That have caused some extra whitespace, that doesn't occur in unfiltered Malline output.

On this page

Tags

Just write name of the tag like it was a method, and it will be rendered. Attributes can be given as a hash. If the first parameter is a String, it will start the contents of the tag.

Hello world

1
2
# Lets say hello to the world
div 'Hello world', :title => 'Hello'

<div title="Hello">Hello world</div>

Too simple? Let's make nested tags. They are obviously represented as blocks

Nested tags

1
2
3
4
5
6
div do
    span 'text'
    div 'foo' do
        span 'bar', :style => 'color: red'
    end
end
1
2
3
4
5
6
<div>
    <span>text</span>
    <div>
        foo<span style="color: red">bar</span>
    </div>
</div>

The most common HTML attributes are class and id, so there is a little shortcut for them

Classes

1
2
3
4
5
6
# These two things are the same
div :class => 'page'
div.page

# You can even give more than one class
div.foo.bar.many
1
2
3
<div class="page"></div>
<div class="page"></div>
<div class="foo bar many"></div>

IDs

1
2
3
# id:s are given by shouting loud enough
div.page!
div.foo.page!.bar
1
2
<div id="page"></div>
<div class="foo bar" id="page"></div>

Text

Normal text blocks can be printed with method _ or it's alias txt!

Actually you could combine your localization plugin with this same method.

Normal text

1
2
3
4
p do
    hr
    _'This is some text.'
end
1
2
3
<p>
    <hr/>This is some text.
</p>

Escaping

Normally all texts are escaped correctly

HTML escaping

1
2
3
4
p 'Do you know, that 2 < 5?', :title => '2 < 5'
p do
    _'Me & Myself & Malline'
end
1
2
<p title="2 &lt; 5">Do you know, that 2 &lt; 5?</p>
<p>Me &amp; Myself &amp; Malline</p>

Predictably there is a way to render text without any escaping or other processing.

self << stuff

1
2
self << '<tag/>'
p { self << '<tag/>' }
1
2
3
4
<tag/>
<p>
    <tag/>
</p>

Helpers

Real usage for self << are helper methods, that render html directly.

These method are of course build-in methods or defined in app/helpers/, but as an example they are defined inline here.

helper methods I

1
2
3
4
5
def rot13 name
    '<div>' + (name.tr "A-Za-z", "N-ZA-Mn-za-m") + '</div>'
end

self << rot13('secret stuff')

<div>frperg fghss</div>

Sometimes you need to use methods a lot, so there is a shortcut for self << helper:

helper methods shortcut

1
2
3
4
5
p do
    # These two do exactly the same
    self << link_to('Frontpage', '/')
    _link_to('Frontpage', '/')
end
1
2
3
<p>
    <a href="/">Frontpage</a><a href="/">Frontpage</a>
</p>

However, in Ruby on Rails all helper methods are included in current view, so they can also use Malline! This is a preferred way to create your own methods. No more helper methods that return ugly HTML strings.

helper methods II

1
2
3
4
5
def rot13 name
    div name.tr("A-Za-z", "N-ZA-Mn-za-m")
end

rot13('frperg fghss')

<div>secret stuff</div>

Capture

Malline can do the same trick that can be done with Erb and Rails CaptureHelper. You can save a output of a one block to variable, and use it later. content_for uses this technique, so it works also.

Capturing output

1
2
3
4
5
6
7
8
9
10
11
@foo = capture do
    div do
        img :src => '/images/image.png', :alt => 'nice image'
        br
        span.caption 'Taken at the location of the event'
    end
end

h4 'Captured'
self << @foo
_'EOF'
1
2
3
4
5
6
<h4>Captured</h4>
<div>
    <img src="/images/image.png" alt="nice image"/><br/>
    <span class="caption">Taken at the location of the event</span>
</div>
EOF

Whitespace-modifier

Sometimes it's annoying to write all extra whitespaces everywhere, so elements wont be glued together. That can also done automatically with :whitespace -option.

Whitespace

1
2
3
4
5
6
7
8
9
# Without automatic whitespace
div do
    _'This is'; strong 'so'; _'cool.'
end

# With automatic whitespace
div :whitespace do
    _'This is'; strong 'so'; _'cool.'
end
1
2
3
4
5
6
<div>
    This is<strong>so</strong>cool.
</div>
<div>
     This is <strong>so</strong> cool.
</div>

XHTML module

You can use Malline with any XML language, but there is a special build-in language plugin for XHTML. It's enabled by default, see configuration options for more info.

XHTML

1
2
3
4
5
6
7
8
9
10
11
# When using xhtml and Malline strict mode, no other tags can be used but XHTML tags.
# See Rails integration for more info about configuration options
xhtml do
    head
    body do
        # Malline recognizes all self closing tags
        hr
        div
        br
    end
end
1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
        <title></title>
        <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
    </head>
    <body>
        <hr/><div></div><br/>
    </body>
</html>

Non strict mode

Like I said earlier, you can use any XML-language, if you set strict mode off.

SVG image

1
2
3
4
5
6
svg :width => 400, :height => 300, :version => 1.1, :xmlns => 'http://www.w3.org/2000/svg' do
    (1..4).each do |i|
        circle :cx => 100+50*i, :cy => 150, :r => 60-i*2,
            :stroke => :black, :fill => [:blue, :red][i%2]
    end
end
1
2
3
4
5
6
<svg width="400" version="1.1" xmlns="http://www.w3.org/2000/svg" height="300">
    <circle cy="150" stroke="black" fill="red" r="58" cx="150"/>
    <circle cy="150" stroke="black" fill="blue" r="56" cx="200"/>
    <circle cy="150" stroke="black" fill="red" r="54" cx="250"/>
    <circle cy="150" stroke="black" fill="blue" r="52" cx="300"/>
</svg>

FormBuilder

Forms are quite boring components of web pages, so somebody very smart or lazy person invented FormBuilder. Unfortunately form_for have it's own magical ERB-output features, so it needed little tweaking in Malline. Please notice that form_for is not a normal helper method and thus it's not rendered with self << or prefix "_". Malline automatically emulates ERB and captures output correctly. The syntax with FormBuilder with Malline is very clean and foolproof.

Contents of RAILS_ROOT/app/views/comments/_form.mn:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
label 'Name', :for => :comment_name
f.text_field :name
br

label 'Title', :for => :comment_title
f.text_field :title
br

label 'Home page', :for => :comment_homepage
f.text_field :homepage
br

label 'Message', :for => :comment_msg
f.text_area :msg, :cols => 60, :rows => 10
br

form_for & co

1
2
3
4
5
6
# This is the real code used on this page.
# Or it was until I put these comments here, sorry.
form_for :comment, Comment.new, :url => edit_url do |f|
    _render :partial => 'comments/form', :locals => { :f => f }
    input.submit :type => :submit, :value => 'Send'
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<form action="http://www.malline.org/edit" method="post">
    <label for="comment_name">Name</label>
    <input id="comment_name" name="comment[name]" size="30" type="text" />
    <br/>
    <label for="comment_title">Title</label>
    <input id="comment_title" name="comment[title]" size="30" type="text" value="" />
    <br/>
    <label for="comment_homepage">Home page</label>
    <input id="comment_homepage" name="comment[homepage]" size="30" type="text" />
    <br/>
    <label for="comment_msg">Message</label>
    <textarea cols="60" id="comment_msg" name="comment[msg]" rows="10"></textarea><br/>
    <input class="submit" type="submit" value="Send"/>
</form>

Caching

Page caching and Action caching are very simple caching solutions, since they work the same way regardless of the underlying template system. So obviously they work like you have get used to.

Much more interesting thing is Fragment caching, since it works inside the templates. Malline comes with a custom fragment caching code, that works exactly the same way than the ERB version but works with Malline. However, it's not compatible with ERB fragment caching, at least not in all situations.

Fragment caching

1
2
3
4
5
6
7
8
9
10
div do
    cache "stuff" do
        # This block is evaluated only if no cache with keyword stuff is found
        # After evaluation the block is saved to cache
        # If caching is not enabled, the cache block acts invisible
        h4 'Some partial stuff'
        _render :partial => 'examples/partial'
    end
    _'dynamic content'
end
1
2
3
4
<div>
    <h4>Some partial stuff</h4>
    <div>I always thought something was fundamentally wrong with the universe.</div>dynamic content
</div>

Contents of RAILS_ROOT/tmp/cache/stuff.cache:

1
2
<h4>Some partial stuff</h4>
<div>I always thought something was fundamentally wrong with the universe.</div>

Demo

How to make lists

1
2
3
4
5
6
7
8
9
10
11
12
13
@elements = %w{ these are some sample list elements }
filter = /s../

div.lists! do
    h2 "Cool, you have #{@elements.size} elements!"
    ul do
        @elements.each do |name|
            li name do
                _' [matches filter]' if name =~ filter
            end    
        end
    end
end unless @elements.empty?
1
2
3
4
5
6
7
8
9
10
11
<div id="lists">
    <h2>Cool, you have 6 elements!</h2>
    <ul>
        <li>these</li>
        <li>are</li>
        <li>some [matches filter]</li>
        <li>sample [matches filter]</li>
        <li>list</li>
        <li>elements</li>
    </ul>
</div>

See more practical examples/demos on Beast demo -page »


No comments
Write a one

Write a new comment on this page