Ember

eRuby template processor

Suraj N. Kurapati

03 April 2010

Document




Part 1
Welcome

Ember (EMBEdded Ruby) is an eRuby template processor that enables debugging, reduces markup, and improves composability of eRuby templates.

  • It reports correct line numbers in error message stack traces.
  • It can infer <% end %> based on indentation.
  • It can unindent block content hierarchically.
  • It completely silences code-only eRuby directives.
  • It is implemented in 364 lines of pure Ruby.







1.1  Resources




1.2  License

(the ISC license)

Copyright 2009 Suraj N. Kurapati sunaku@gmail.com

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.




Part 2
Setup







2.1  Prerequisites




2.2  Installing




Command 1.  gem install ember




2.3  Upgrading




Command 2.  gem update ember




2.4  Uninstalling




Command 3.  gem uninstall ember




Part 3
Theory







3.1  Directives

eRuby templates are plain-text documents that contain special processing instructions known as directives, which may be expressed using either standard or shorthand notation:

NotationDirectiveHeadOperationBodyTail
Standard<%XY%><%XY%>
Shorthand%XY%XY

In standard notation, the directive is composed of a head, an operation, a body, and a tail. In addition, the directive may appear anywhere in the text.

In shorthand notation, the directive is composed of a head, an operation and a body. However, the directive may only appear in the text if it occupies an entire line (arbitrary amounts of leading whitespace are permitted).

In any case, directives are atomic constructs; they cannot be nested.




3.2  Operations

The first character that follows the head of a directive is known as an operation. It prescribes how the directive should be processed:

OperationEffectExample
#The entire directive is omitted from the output.Comment directives
=The body of the directive is evaluated as Ruby code, and the result of this evaluation is inserted into the output.Vocal directives
~The body of the directive is evaluated as an eRuby template, and the result of this evaluation is inserted into the output.Dynamic template evaluation
+The body of the directive is evaluated as Ruby code, and the result of this evaluation is assumed to be a string that specifies the path (either absolute or relative to the eRuby template file in which this directive is found) to a file containing an eRuby template. This file is read and its contents are evaluated as an eRuby template, and the result of this evaluation is inserted into the output.Template file inclusion
<The body of the directive is evaluated as Ruby code, and the result of this evaluation is assumed to be a string that specifies the path (either absolute or relative to the eRuby template file in which this directive is found) to a file. This file is read and its contents are inserted into the output.Raw file inclusion
|The body of the directive is treated as the beginning of a Ruby block. The do keyword is automatically appended to the body of the directive if missing.Block directives
%One ”%” character is omitted from the head of the directive and the entire directive is inserted into the output.Escaped directives
(none of the above)The body of the directive is evaluated as Ruby code, but the result of this evaluation is not inserted into the output.Silent directives



Part 4
Usage







4.1  Shell command




Command 4.  ember --help

command
Ember - eRuby template processor

Evaluates eRuby directives in the given eRuby template and
writes the result to the standard output stream (STDOUT).

Usage:

  ember [Options] [TemplateFile]

TemplateFile:

  Path to the eRuby template file that you want to evaluate.  If
  this parameter is not specified, then the result of reading the
  standard input stream (STDIN) will be used as the eRuby template.

Options:

  -s, --shorthand:

    Treat lines beginning with zero or more whitespace
    followed by the "%" character as eRuby directives.

  -i, --infer_end:

    Add missing <% end %> directives based on indentation.

  -u, --unindent:

    Unindent the bodies of eRuby blocks.

  -c, --compile:

    Print underlying Ruby program compiled
    from the input eRuby template and exit.

  -h, --help:

    Print this message and exit.

  -v, --version:

    Print version number and exit.

See the user manual for more information:

  /home/sun/src/ember/doc/index.html

  http://snk.tuxfamily.org/lib/ember/




4.2  Ruby library

Begin by loading Ember into Ruby:

require 'rubygems' # only necessary if you are using Ruby 1.8
require 'ember'

Instantiate an Ember template processor:

source   = "your eRuby template here"
options  = { :unindent => true, :shorthand => true }
template = Ember::Template.new(source, options)

Inspect the Ruby program that was compiled (and is used) by the Ember template processor to evaluate the eRuby template given as input:

puts template.program

View the result of evaluating the eRuby template:

puts template.render

See the API documentation for more information.




Example 1.  An empty template

Begin with an empty template:

The above template compiles into:

(_erbout = []; _erbout << "\n"
; _erbout.join)

And renders as:




Example 2.  Comment directives

Add comment directives:

<%# this is a comment %>
%# this is also a comment

<%# this
is
a
multi-line comment %>

With {:shorthand=>true} options, the above template compiles into:

(_erbout = []; _erbout << "\n"
_erbout << "\n"
_erbout << "\n"
      
  
 
                   
; _erbout.join)

And renders as:




Example 3.  Escaped directives

Add escaped directives:

<%% this is an escaped directive %>
%% this is an escaped directive

With {:shorthand=>true} options, the above template compiles into:

(_erbout = []; _erbout << "<% this is an escaped directive %>\n"
_erbout << "% this is an escaped directive\n"
; _erbout.join)

And renders as:

<% this is an escaped directive %>
% this is an escaped directive



Example 4.  Vocal directives

Add vocal directives, which produce output:

<%= "hello" %>
%= "world"

With {:shorthand=>true} options, the above template compiles into:

(_erbout = []; _erbout << ( "hello" ) << "\n"
_erbout << ( "world") << "\n"
; _erbout.join)

And renders as:

hello
world



Example 5.  Silent directives

Add silent directives, which do not produce output:

<% a = "hello" %>
% b = "world"

<%= a %>
%= b

With {:shorthand=>true} options, the above template compiles into:

(_erbout = [];  a = "hello" 
 b = "world"
_erbout << "\n"
_erbout << ( a ) << "\n"
_erbout << ( b) << "\n"
; _erbout.join)

And renders as:

hello
world



Example 6.  Block directives

Add some Ruby blocks:

% words = %w[hello world]

<% words.each do |w| %>
  <%= w %>
<% end %>

% words.each do |w|
  %= w
% end

%|words.each |w|
  %= w
% end

With {:shorthand=>true} options, the above template compiles into:

(_erbout = [];  words = %w[hello world]
_erbout << "\n"
 words.each do |w| 
_erbout << "  " << ( w ) << "\n"
 end 
_erbout << "\n"
 words.each do |w|
_erbout << "  " << ( w) << "\n"
 end
_erbout << "\n"
words.each do |w|
_erbout << "  " << ( w) << "\n"
 end
; _erbout.join)

And renders as:

  hello
  world

  hello
  world

  hello
  world



Example 7.  Infer block endings

Omit <% end %> directives from the template:

% words = %w[hello world]

<% words.each do |w| %>
  <%= w %>

% words.each do |w|
  %= w

%|words.each |w|
  %= w

With {:shorthand=>true, :infer_end=>true} options, the above template compiles into:

(_erbout = [];  words = %w[hello world]
_erbout << "\n"
 words.each do |w| 
_erbout << "  " << ( w ) << "\n"
end; _erbout << "\n"
 words.each do |w|
_erbout << "  " << ( w) << "\n"
end; _erbout << "\n"
words.each do |w|
_erbout << "  " << ( w) << "\n"
end; _erbout.join)

And renders as:

  hello
  world

  hello
  world

  hello
  world



Example 8.  Raw file inclusion

When doc/example.txt contains:

This is a plain-text file.  Notice that <%=
"eRuby directives" %> have no effect here!

And the eRuby template is:

<%< "doc/example.txt" %>

%< "doc/example.txt"

With {:shorthand=>true, :source_file=>"./USAGE"} options, the above template compiles into:

(_erbout = []; _erbout << (::Ember::Template.read_file(( "doc/example.txt" ), {:shorthand=>true, :source_file=>"./USAGE"})) << "\n"
_erbout << "\n"
_erbout << (::Ember::Template.read_file(( "doc/example.txt"), {:shorthand=>true, :source_file=>"./USAGE"})) << "\n"
; _erbout.join)

And renders as:

This is a plain-text file.  Notice that <%=
"eRuby directives" %> have no effect here!

This is a plain-text file.  Notice that <%=
"eRuby directives" %> have no effect here!



Example 9.  Template file inclusion

When doc/example.erb contains:

This is an eRuby template.  Notice that <%=
"eRuby directives" %> do take effect here!

And the eRuby template is:

<%+ "doc/example.erb" %>

%+ "doc/example.erb"

With {:shorthand=>true, :source_file=>"./USAGE"} options, the above template compiles into:

(_erbout = []; ::Ember::Template.load_file(( "doc/example.erb" ), {:shorthand=>true, :source_file=>"./USAGE"}.merge!(:continue_result => true)).render(nil, 71510250); _erbout << "\n"
_erbout << "\n"
::Ember::Template.load_file(( "doc/example.erb"), {:shorthand=>true, :source_file=>"./USAGE"}.merge!(:continue_result => true)).render(nil, 71510250); _erbout << "\n"
; _erbout.join)

And renders as:

This is an eRuby template.  Notice that eRuby directives do take effect here!

This is an eRuby template.  Notice that eRuby directives do take effect here!



Example 10.  Dynamic template evaluation

<%~ "%= 2 + 2" %>

%~ "%= 2 + 2"

With {:shorthand=>true} options, the above template compiles into:

(_erbout = []; ::Ember::Template.new(( "%= 2 + 2" ), {:shorthand=>true}.merge!(:continue_result => true)).render(nil, 70643216); _erbout << "\n"
_erbout << "\n"
::Ember::Template.new(( "%= 2 + 2"), {:shorthand=>true}.merge!(:continue_result => true)).render(nil, 70643216); _erbout << "\n"
; _erbout.join)

And renders as:

4

4



Part 5
History







5.1  Version 0.1.0 (2010-04-03)

This release improves the handling of eRuby comment directives, fixes a bug in the <% end %> inference logic, and performs some minor housekeeping.




New features

  • Single-line comment directives are now ignored (treated like no-ops) in input templates. This allows us to surround eRuby block directives with section separators made from single-line comment directives:

    %|some_block_directive
    
      Inside some_block_directive.
    
    %#-----------------------------------------------------------------
    
      Still inside some_block_directive!
    
      %#---------------------------------------------------------------
      %| nested_block_directive
      %#---------------------------------------------------------------
    
        Inside nested_block_directive.



Bug fixes

  • <% end %> inference did not work for blocks beginning with def, class, and module keywords.



Housekeeping

  • Upgrade to Inochi 2.0.0-rc3. This project no longer depends on the “inochi” or “trollop” gems at runtime.



5.2  Version 0.0.1 (2009-10-03)

This release improves Ruby 1.9 support and revises the user manual.




Bug fixes

  • Nested templates could not access parent’s binding in Ruby 1.9



Housekeeping

  • Use simpler Copyright reminder at the top of every file.

  • Rename internal Program class’ methods to be self-documenting.

  • Open source is for fun, so be nice: speak of “related works” instead of “competitors”.




5.3  Version 0.0.0 (2009-02-13)

This is the first public release of Ember. Enjoy!



This document was generated by ERBook 9.2.1 (2009-11-18) on Sat Apr 3 14:23:08 2010 using the following resources.

Resource Origin License
here_frag command important warning caution note tip quote nav_here nav_prev nav_next nav_list Tango Icon Theme

© 2005 Tango Desktop Project

Creative Commons Attribution-ShareAlike 2.5 License Agreement
hyperlink MediaWiki Monobook Skin

© 2007 MediaWiki contributors

GNU General Public License, version 2

Valid XHTML 1.0 Strict Valid CSS 3!