Module: Keynote::Rumble

Included in:
Presenter
Defined in:
lib/keynote/rumble.rb

Overview

HTML markup in Ruby.

To invoke Rumble, call the ‘build_html` method in a presenter.

## 1. Syntax

There are four basic forms:

“‘ruby tagname(content)

tagname(content, attributes)

tagname do

content

end

tagname(attributes) do

content

end “‘

Example:

“‘ ruby build_html do

div :id => :content do
  h1 'Hello World', :class => :main
end

end “‘

“‘ html <div id=“content”>

<h1 class="main">Hello World</h1>

</div> “‘

## 2. Element classes and IDs

You can easily add classes and IDs by hooking methods onto the container:

“‘ ruby div.content! do

h1.main 'Hello World'

end “‘

You can mix and match as you’d like (‘div.klass.klass1.id!`), but you can only provide content and attributes on the last call:

“‘ ruby # This is not valid: form(:action => :post).world do

input

end

# But this is: form.world(:action => :post) do

input

end “‘

## 3. Text

Sometimes you need to insert plain text:

“‘ruby p.author do

text 'Written by '
a 'Bluebie', :href => 'http://creativepony.com/'
br
text link_to 'Home', '/'

end “‘

“‘ html <p class=“author”>

Written by
<a href="http://creativepony.com/">Bluebie</a>
<br>
<a href="/">Home</a>

</p> “‘

You can also insert literal text by returning it from a block (or passing it as a parameter to the non-block form of a tag method):

“‘ ruby p.author do

link_to 'Home', '/'

end “‘

“‘ html <p class=“author”>

<a href="/">Home</a>

</p> “‘

Be aware that Rumble ignores the string in a block if there’s other tags there:

“‘ ruby div.comment do

div.author "BitPuffin"
"<p>Silence!</p>"

end “‘

“‘ html <div class=“comment”>

<div class="author">BitPuffin</div>

</div> “‘

## 4. Escaping

The version of Rumble that’s embedded in Keynote follows normal Rails escaping rules. When text enters Rumble (by returning it from a block, passing it as a parameter to a tag method, or using the ‘text` method), it’s escaped if and only if ‘html_safe?` returns false. That means that Rails helpers generally don’t need special treatment, but strings need to have ‘html_safe` called on them to avoid escaping.

## 5. In practice

“‘ ruby class ArticlePresenter < Keynote::Presenter

presents :article

def published_at
  build_html do
    div.published_at do
      span.date publication_date
      span.time publication_time
    end
  end
end

def publication_date
  article.published_at.strftime("%A, %B %e").squeeze(" ")
end

def publication_time
  article.published_at.strftime("%l:%M%p").delete(" ")
end

end “‘

See Also:

Author:

  • Rumble is © 2011 Magnus Holm (github.com/judofyr).

  • Documentation mostly borrowed from Mab, © 2012 Magnus Holm.

Defined Under Namespace

Classes: Context, Error, Tag

Constant Summary collapse

BASIC =

A basic set of commonly-used HTML tags. These are included as methods on all presenters by default.

%w[a b br button del div em form h1 h2 h3 h4 h5 h6 hr i img input
label li link ol optgroup option p pre script select span strong sub sup
table tbody td textarea tfoot th thead time tr ul]
COMPLETE =

A more complete set of HTML5 tags. You can use these by calling ‘use_html_5_tags` in a presenter’s class body.

%w[abbr acronym address applet area article aside audio base
basefont bdo big blockquote body canvas caption center cite code col
colgroup command datalist dd details dfn dir dl dt embed fieldset
figcaption figure font footer frame frameset head header hgroup iframe
ins keygen kbd legend map mark menu meta meter nav noframes noscript
object output param progress q rp rt ruby s samp section small source
strike style summary title tt u var video wbr xmp]
SELFCLOSING =
%w[base meta link hr br param img area input col frame]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.define_tags(base, tags) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
# File 'lib/keynote/rumble.rb', line 188

def self.define_tags(base, tags)
  tags.each do |tag|
    sc = SELFCLOSING.include?(tag).inspect

    base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
      def #{tag}(*args, &blk)                   # def a(*args, &blk)
        rumble_tag :#{tag}, #{sc}, *args, &blk  #   rumble_tag :a, false, *args, &blk
      end                                       # end
    RUBY
  end
end

.html_escape(s) ⇒ Object

We need our own copy of this, the normal Rails html_escape helper, so that we can access it from inside Tag objects.



208
209
210
211
212
213
214
215
# File 'lib/keynote/rumble.rb', line 208

def self.html_escape(s)
  s = s.to_s
  if s.html_safe?
    s
  else
    s.gsub(/[&"'><]/, ERB::Util::HTML_ESCAPE).html_safe
  end
end

.included(base) ⇒ Object



183
184
185
# File 'lib/keynote/rumble.rb', line 183

def self.included(base)
  define_tags(base, BASIC)
end

.use_html_5_tags(base) ⇒ Object



201
202
203
# File 'lib/keynote/rumble.rb', line 201

def self.use_html_5_tags(base)
  define_tags(base, COMPLETE)
end

Instance Method Details

#build_htmlObject

Generate HTML using Rumble tag methods. If tag methods are called outside a ‘build_html` block, they’ll raise an exception.



364
365
366
367
368
369
370
371
# File 'lib/keynote/rumble.rb', line 364

def build_html
  if defined?(@rumble_context)
    ctx = @rumble_context
  end
  @rumble_context = Context.new
  yield
  rumble_cleanup(ctx).to_s
end

#rumble_cleanup(value = nil) ⇒ Object



391
392
393
394
395
# File 'lib/keynote/rumble.rb', line 391

def rumble_cleanup(value = nil)
  defined?(@rumble_context) ? @rumble_context : nil
ensure
  @rumble_context = value
end

#rumble_contextObject



386
387
388
# File 'lib/keynote/rumble.rb', line 386

def rumble_context
  defined?(@rumble_context) ? @rumble_context : nil
end

#text(str = nil, &blk) ⇒ Object

Generate a text node. This is helpful in situations where an element contains both text and markup.



375
376
377
378
379
380
381
382
383
# File 'lib/keynote/rumble.rb', line 375

def text(str = nil, &blk)
  str = Rumble.html_escape(str || blk.call)

  if defined?(@rumble_context) && @rumble_context
    @rumble_context << str
  else
    str
  end
end