Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add tilt

  • Loading branch information...
commit f10e56c48b63604ad307ac4ed090a824e6020204 1 parent a2a4bb4
@brianjlandau brianjlandau authored
Showing with 3,332 additions and 0 deletions.
  1. +1 −0  dependencies
  2. +18 −0 vendor/tilt-1.1/COPYING
  3. +198 −0 vendor/tilt-1.1/README.md
  4. +80 −0 vendor/tilt-1.1/Rakefile
  5. +439 −0 vendor/tilt-1.1/TEMPLATES.md
  6. +110 −0 vendor/tilt-1.1/bin/tilt
  7. +868 −0 vendor/tilt-1.1/lib/tilt.rb
  8. +68 −0 vendor/tilt-1.1/test/contest.rb
  9. +1 −0  vendor/tilt-1.1/test/markaby/locals.mab
  10. +1 −0  vendor/tilt-1.1/test/markaby/markaby.mab
  11. +1 −0  vendor/tilt-1.1/test/markaby/markaby_other_static.mab
  12. +1 −0  vendor/tilt-1.1/test/markaby/render_twice.mab
  13. +1 −0  vendor/tilt-1.1/test/markaby/scope.mab
  14. +2 −0  vendor/tilt-1.1/test/markaby/yielding.mab
  15. +44 −0 vendor/tilt-1.1/test/tilt_buildertemplate_test.rb
  16. +32 −0 vendor/tilt-1.1/test/tilt_cache_test.rb
  17. +25 −0 vendor/tilt-1.1/test/tilt_coffeescripttemplate_test.rb
  18. +86 −0 vendor/tilt-1.1/test/tilt_compilesite_test.rb
  19. +212 −0 vendor/tilt-1.1/test/tilt_erbtemplate_test.rb
  20. +136 −0 vendor/tilt-1.1/test/tilt_erubistemplate_test.rb
  21. +144 −0 vendor/tilt-1.1/test/tilt_hamltemplate_test.rb
  22. +20 −0 vendor/tilt-1.1/test/tilt_lesstemplate_test.rb
  23. +73 −0 vendor/tilt-1.1/test/tilt_liquidtemplate_test.rb
  24. +73 −0 vendor/tilt-1.1/test/tilt_markaby_test.rb
  25. +54 −0 vendor/tilt-1.1/test/tilt_nokogiritemplate_test.rb
  26. +70 −0 vendor/tilt-1.1/test/tilt_radiustemplate_test.rb
  27. +40 −0 vendor/tilt-1.1/test/tilt_rdiscounttemplate_test.rb
  28. +19 −0 vendor/tilt-1.1/test/tilt_rdoctemplate_test.rb
  29. +20 −0 vendor/tilt-1.1/test/tilt_redclothtemplate_test.rb
  30. +32 −0 vendor/tilt-1.1/test/tilt_sasstemplate_test.rb
  31. +163 −0 vendor/tilt-1.1/test/tilt_stringtemplate_test.rb
  32. +158 −0 vendor/tilt-1.1/test/tilt_template_test.rb
  33. +65 −0 vendor/tilt-1.1/test/tilt_test.rb
  34. +77 −0 vendor/tilt-1.1/tilt.gemspec
View
1  dependencies
@@ -14,3 +14,4 @@ webrat 0.7.2 (test) git://github.com/brynary/webrat.git
mocha 0.9.8 (test)
factory_girl 1.2.3 (test)
haml 2.2.24
+tilt 1.1
View
18 vendor/tilt-1.1/COPYING
@@ -0,0 +1,18 @@
+Copyright (c) 2010 Ryan Tomayko <http://tomayko.com/about>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
198 vendor/tilt-1.1/README.md
@@ -0,0 +1,198 @@
+Tilt
+====
+
+Tilt is a thin interface over a bunch of different Ruby template engines in
+an attempt to make their usage as generic possible. This is useful for web
+frameworks, static site generators, and other systems that support multiple
+template engines but don't want to code for each of them individually.
+
+The following features are supported for all template engines (assuming the
+feature is relevant to the engine):
+
+ * Custom template evaluation scopes / bindings
+ * Ability to pass locals to template evaluation
+ * Support for passing a block to template evaluation for "yield"
+ * Backtraces with correct filenames and line numbers
+ * Template file caching and reloading
+ * Fast, method-based template source compilation
+
+The primary goal is to get all of the things listed above right for all
+template engines included in the distribution.
+
+Support for these template engines is included with the package:
+
+ ENGINE FILE EXTENSIONS REQUIRED LIBRARIES
+ -------------------------- ----------------- ----------------------------
+ ERB .erb none (included ruby stdlib)
+ Interpolated String .str none (included ruby core)
+ Haml .haml haml
+ Sass .sass haml
+ Less CSS .less less
+ Builder .builder builder
+ Liquid .liquid liquid
+ RDiscount .markdown rdiscount
+ RedCloth .textile redcloth
+ RDoc .rdoc rdoc
+ Radius .radius radius
+ Markaby .mab markaby
+ Nokogiri .nokogiri nokogiri
+ CoffeeScript .coffee coffee-script (+node coffee)
+
+See [TEMPLATES.md][t] for detailed information on template engine
+options and supported features.
+
+[t]: http://github.com/rtomayko/tilt/blob/master/TEMPLATES.md
+ "Tilt Template Engine Documentation"
+
+Basic Usage
+-----------
+
+Instant gratification:
+
+ require 'erb'
+ require 'tilt'
+ template = Tilt.new('templates/foo.erb')
+ => #<Tilt::ERBTemplate @file="templates/foo.rb" ...>
+ output = template.render
+ => "Hello world!"
+
+It's recommended that calling programs explicitly require template engine
+libraries (like 'erb' above) at load time. Tilt attempts to lazy require the
+template engine library the first time a template is created but this is
+prone to error in threaded environments.
+
+The `Tilt` module contains generic implementation classes for all supported
+template engines. Each template class adheres to the same interface for
+creation and rendering. In the instant gratification example, we let Tilt
+determine the template implementation class based on the filename, but
+`Tilt::Template` implementations can also be used directly:
+
+ template = Tilt::HamlTemplate.new('templates/foo.haml')
+ output = template.render
+
+The `render` method takes an optional evaluation scope and locals hash
+arguments. Here, the template is evaluated within the context of the
+`Person` object with locals `x` and `y`:
+
+ template = Tilt::ERBTemplate.new('templates/foo.erb')
+ joe = Person.find('joe')
+ output = template.render(joe, :x => 35, :y => 42)
+
+If no scope is provided, the template is evaluated within the context of an
+object created with `Object.new`.
+
+A single `Template` instance's `render` method may be called multiple times
+with different scope and locals arguments. Continuing the previous example,
+we render the same compiled template but this time in jane's scope:
+
+ jane = Person.find('jane')
+ output = template.render(jane, :x => 22, :y => nil)
+
+Blocks can be passed to `render` for templates that support running
+arbitrary ruby code (usually with some form of `yield`). For instance,
+assuming the following in `foo.erb`:
+
+ Hey <%= yield %>!
+
+The block passed to `render` is called on `yield`:
+
+ template = Tilt::ERBTemplate.new('foo.erb')
+ template.render { 'Joe' }
+ # => "Hey Joe!"
+
+Template Mappings
+-----------------
+
+The `Tilt` module includes methods for associating template implementation
+classes with filename patterns and for locating/instantiating template
+classes based on those associations.
+
+The `Tilt::register` method associates a filename pattern with a specific
+template implementation. To use ERB for files ending in a `.bar` extension:
+
+ >> Tilt.register 'bar', Tilt::ERBTemplate
+ >> Tilt.new('views/foo.bar')
+ => #<Tilt::ERBTemplate @file="views/foo.bar" ...>
+
+Retrieving the template class for a file or file extension:
+
+ >> Tilt['foo.bar']
+ => Tilt::ERBTemplate
+ >> Tilt['haml']
+ => Tilt::HamlTemplate
+
+It's also possible to register template file mappings that are more specific
+than a file extension. To use Erubis for `bar.erb` but ERB for all other `.erb`
+files:
+
+ >> Tilt.register 'bar.erb', Tilt::ErubisTemplate
+ >> Tilt.new('views/foo.erb')
+ => Tilt::ERBTemplate
+ >> Tilt.new('views/bar.erb')
+ => Tilt::ErubisTemplate
+
+The template class is determined by searching for a series of decreasingly
+specific name patterns. When creating a new template with
+`Tilt.new('views/foo.html.erb')`, we check for the following template
+mappings:
+
+ 1. `views/foo.html.erb`
+ 2. `foo.html.erb`
+ 3. `html.erb`
+ 4. `erb`
+
+`Tilt::register` can also be used to select between alternative template
+engines. To use Erubis instead of ERB for `.erb` files:
+
+ Tilt.register 'erb', Tilt::ErubisTemplate
+
+Or, use BlueCloth for markdown instead of RDiscount:
+
+ Tilt.register 'markdown', Tilt::BlueClothTemplate
+
+Template Compilation
+--------------------
+
+Tilt can compile generated Ruby source code produced by template engines and
+reuse on subsequent template invocations. Benchmarks show this yields a 5x-10x
+performance increase over evaluating the Ruby source on each invocation.
+
+Template compilation is currently supported for these template engines:
+StringTemplate, ERB, Erubis, Haml, and Builder.
+
+To enable template compilation, the `Tilt::CompileSite` module must be mixed in
+to the scope object passed to the template's `#render` method. This can be
+accomplished by including (with `Module#include`) the module in the class used
+for scope objects or by extending (with `Object#extend`) scope objects before
+passing to `Template#render`:
+
+ require 'tilt'
+
+ template = Tilt::ERBTemplate.new('foo.erb')
+
+ # Slow. Uses Object#instance_eval to process template
+ class Scope
+ end
+ scope = Scope.new
+ template.render(scope)
+
+ # Fast. Uses compiled template and Object#send to process template
+ class Scope
+ include Tilt::CompileSite
+ end
+ scope = Scope.new
+ template.render(scope)
+
+ # Also fast, though a bit a slower due to having to extend each time
+ scope = Object.new
+ scope.extend Tilt::CompileSite
+ template.render(scope)
+
+When the `Tilt::CompileSite` module is not present, template execution falls
+back to evaluating the template from source on each invocation.
+
+LICENSE
+-------
+
+Tilt is Copyright (c) 2010 [Ryan Tomayko](http://tomayko.com/about) and
+distributed under the MIT license. See the `COPYING` file for more info.
View
80 vendor/tilt-1.1/Rakefile
@@ -0,0 +1,80 @@
+require 'rake/testtask'
+task :default => :test
+
+# SPECS =====================================================================
+
+desc 'Generate test coverage report'
+task :rcov do
+ sh "rcov -Ilib:test test/*_test.rb"
+end
+
+desc 'Run tests (default)'
+Rake::TestTask.new(:test) do |t|
+ t.test_files = FileList['test/*_test.rb']
+ t.ruby_opts = ['-Itest']
+ t.ruby_opts << '-rubygems' if defined? Gem
+end
+
+# PACKAGING =================================================================
+
+begin
+ require 'rubygems'
+rescue LoadError
+end
+
+if defined?(Gem)
+ SPEC = eval(File.read('tilt.gemspec'))
+
+ def package(ext='')
+ "pkg/tilt-#{SPEC.version}" + ext
+ end
+
+ desc 'Build packages'
+ task :package => %w[.gem .tar.gz].map {|e| package(e)}
+
+ desc 'Build and install as local gem'
+ task :install => package('.gem') do
+ sh "gem install #{package('.gem')}"
+ end
+
+ directory 'pkg/'
+
+ file package('.gem') => %w[pkg/ tilt.gemspec] + SPEC.files do |f|
+ sh "gem build tilt.gemspec"
+ mv File.basename(f.name), f.name
+ end
+
+ file package('.tar.gz') => %w[pkg/] + SPEC.files do |f|
+ sh "git archive --format=tar HEAD | gzip > #{f.name}"
+ end
+
+ desc 'Upload gem and tar.gz distributables to rubyforge'
+ task :release => [package('.gem'), package('.tar.gz')] do |t|
+ sh <<-SH
+ rubyforge add_release sinatra tilt #{SPEC.version} #{package('.gem')} &&
+ rubyforge add_file sinatra tilt #{SPEC.version} #{package('.tar.gz')}
+ SH
+ end
+end
+
+# GEMSPEC ===================================================================
+
+file 'tilt.gemspec' => FileList['{lib,test}/**','Rakefile'] do |f|
+ # read version from tilt.rb
+ version = File.read('lib/tilt.rb')[/VERSION = '(.*)'/] && $1
+ # read spec file and split out manifest section
+ spec = File.
+ read(f.name).
+ sub(/s\.version\s*=\s*'.*'/, "s.version = '#{version}'")
+ parts = spec.split(" # = MANIFEST =\n")
+ # determine file list from git ls-files
+ files = `git ls-files`.
+ split("\n").sort.reject{ |file| file =~ /^\./ }.
+ map{ |file| " #{file}" }.join("\n")
+ # piece file back together and write...
+ parts[1] = " s.files = %w[\n#{files}\n ]\n"
+ spec = parts.join(" # = MANIFEST =\n")
+ spec.sub!(/s.date = '.*'/, "s.date = '#{Time.now.strftime("%Y-%m-%d")}'")
+ File.open(f.name, 'w') { |io| io.write(spec) }
+ puts "updated #{f.name}"
+end
View
439 vendor/tilt-1.1/TEMPLATES.md
@@ -0,0 +1,439 @@
+Tilt Templates
+==============
+
+While all Tilt templates use the same basic interface for template loading and
+evaluation, each varies in its capabilities and available options. Detailed
+documentation on each supported template engine is provided below.
+
+ * [ERB](#erb) - `Tilt::ERBTemplate`
+ * [Erubis](#erubis) - `Tilt::ErubisTemplate`
+ * [Haml](#haml) - `Tilt::HamlTemplate`
+ * [Liquid](#liquid) - `Tilt::LiquidTemplate`
+
+Tilt includes support for CSS processors like [lesscss](http://lesscss.org)
+and [sass](http://sass-lang.com/), in addition, it also supports simple
+text formats.
+
+ * Less - `Tilt::LessTemplate`
+ * Sass - `Tilt::SassTemplate`
+ * [Markdown](#markdown) - `Tilt::RDiscountTemplate`
+ * [RDoc](#rdoc) - `Tilt::RDocTemplate`
+
+<a name='erb'></a>
+ERB (`erb`, `rhtml`)
+--------------------
+
+An easy to use but powerful templating system for Ruby.
+
+### Example
+
+ Hello <%= world %>!
+
+### Usage
+
+The `Tilt::ERBTemplate` class is registered for all files ending in `.erb` or
+`.rhtml` by default. ERB templates support custom evaluation scopes and locals:
+
+ >> require 'erb'
+ >> template = Tilt.new('hello.html.erb', :trim => '<>')
+ => #<Tilt::ERBTemplate @file='hello.html.erb'>
+ >> template.render(self, :world => 'World!')
+ => "Hello World!"
+
+Or, use the `Tilt::ERBTemplate` class directly to process strings:
+
+ require 'erb'
+ template = Tilt::ERBTemplate.new(nil, :trim => '<>') { "Hello <%= world %>!" }
+ template.render(self, :world => 'World!')
+
+__NOTE:__ It's suggested that your program `require 'erb'` at load time when
+using this template engine within a threaded environment.
+
+### Options
+
+#### `:trim => '-'`
+
+The ERB trim mode flags. This is a string consisting
+of any combination of the following characters:
+
+ * `'>'` omits newlines for lines ending in `>`
+ * `'<>'` omits newlines for lines starting with `<%` and ending in `%>`
+ * `'-'` omits newlines for lines ending in `-%>`.
+ * `'%'` enables processing of lines beginning with `%`
+
+#### `:safe => nil`
+
+The `$SAFE` level; when set, ERB code will be run in a
+separate thread with `$SAFE` set to the provided level.
+
+#### `:outvar => '_erbout'`
+
+The name of the variable used to accumulate template output. This can be
+any valid Ruby expression but must be assignable. By default a local
+variable named `_erbout` is used.
+
+### See also
+
+ * [ERB documentation](http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html)
+
+
+<a name='erubis'></a>
+Erubis (`erubis`)
+-----------------
+
+Erubis is a fast, secure, and very extensible implementation of eRuby.
+
+### Usage
+
+To use Erubis instead of ERB for all `.erb` and `.rhtml` files, register
+the extensions as follows:
+
+ Tilt.register 'erb', Tilt::ErubisTemplate
+ Tilt.register 'rhtml', Tilt::ErubisTemplate
+
+### Options
+
+#### `:engine_class => Erubis::Eruby`
+
+Allows you to specify a custom engine class to use instead of the
+default which is `Erubis::Eruby`.
+
+#### `:escape_html => false`
+
+When `true`, `Erubis::EscapedEruby` will be used as the engine class
+instead of the default. All content within `<%= %>` blocks will be
+automatically html escaped.
+
+#### `:outvar => '_erbout'`
+
+The name of the variable used to accumulate template output. This can be
+any valid Ruby expression but must be assignable. By default a local
+variable named `_erbout` is used.
+
+#### `:pattern => '<% %>'`
+
+Set pattern for embedded Ruby code.
+
+See the [ERB](#erb) template documentation for examples, usage, and options.
+
+#### `:trim => true`
+
+Delete spaces around '<% %>'. (But, spaces around '<%= %>' are preserved.)
+
+### See also
+
+ * [Erubis Home](http://www.kuwata-lab.com/erubis/)
+ * [Erubis User's Guide](http://www.kuwata-lab.com/erubis/users-guide.html)
+
+__NOTE:__ It's suggested that your program `require 'erubis'` at load time when
+using this template engine within a threaded environment.
+
+<a name='haml'></a>
+Haml (`haml`)
+-------------
+
+Haml is a markup language that’s used to cleanly and simply describe the HTML of
+any web document without the use of inline code. Haml functions as a replacement
+for inline page templating systems such as PHP, ASP, and ERB, the templating
+language used in most Ruby on Rails applications. However, Haml avoids the
+need for explicitly coding HTML into the template, because it itself is a
+description of the HTML, with some code to generate dynamic content.
+([more](http://haml-lang.com/about.html))
+
+
+### Example
+
+ %html
+ %head
+ %title= @title
+ %body
+ %h1
+ Hello
+ = world + '!'
+
+### Usage
+
+The `Tilt::HamlTemplate` class is registered for all files ending in `.haml`
+by default. Haml templates support custom evaluation scopes and locals:
+
+ >> require 'haml'
+ >> template = Tilt.new('hello.haml')
+ => #<Tilt::HamlTemplate @file='hello.haml'>
+ >> @title = "Hello Haml!"
+ >> template.render(self, :world => 'Haml!')
+ => "
+ <html>
+ <head>
+ <title>Hello Haml!</title>
+ </head>
+ <body>
+ <h1>Hello Haml!</h1>
+ </body>
+ </html>"
+
+Or, use the `Tilt::HamlTemplate` class directly to process strings:
+
+ >> require 'haml'
+ >> template = Tilt::HamlTemplate.new { "%h1= 'Hello Haml!'" }
+ => #<Tilt::HamlTemplate @file=nil ...>
+ >> template.render
+ => "<h1>Hello Haml!</h1>"
+
+__NOTE:__ It's suggested that your program `require 'haml'` at load time when
+using this template engine within a threaded environment.
+
+### Options
+
+#### `:format => :xhtml`
+
+Determines the output format. The default is `:xhtml`. Other options are
+`:html4` and `:html5`, which are identical to `:xhtml` except there are no
+self-closing tags, the XML prolog is ignored and correct DOCTYPEs are generated.
+
+#### `:escape_html => false`
+
+Sets whether or not to escape HTML-sensitive characters in script. If this is
+true, `=` behaves like `&=;` otherwise, it behaves like `!=`. Note that if this
+is set, `!=` should be used for yielding to subtemplates and rendering partials.
+Defaults to false.
+
+#### `:ugly => false`
+
+If set to true, Haml makes no attempt to properly indent or format the HTML
+output. This causes the rendering to be done much quicker than it would
+otherwise, but makes viewing the source unpleasant. Defaults to false.
+
+#### `:suppress_eval => false`
+
+Whether or not attribute hashes and Ruby scripts designated by `=` or `~` should
+be evaluated. If this is true, said scripts are rendered as empty strings.
+Defaults to false.
+
+#### `:attr_wrapper => "'"`
+
+The character that should wrap element attributes. This defaults to `'` (an
+apostrophe). Characters of this type within the attributes will be escaped (e.g.
+by replacing them with `&apos;`) if the character is an apostrophe or a
+quotation mark.
+
+#### `:autoclose => %w[meta img link br hr input area param col base]`
+
+A list of tag names that should be automatically self-closed if they have no
+content. Defaults to `['meta', 'img', 'link', 'br', 'hr', 'input', 'area',
+'param', 'col', 'base']`.
+
+#### `:preserve => %w[textarea pre]`
+
+A list of tag names that should automatically have their newlines preserved
+using the `Haml::Helpers#preserve` helper. This means that any content given on
+the same line as the tag will be preserved. For example, `%textarea= "Foo\nBar"`
+compiles to `<textarea>Foo&#x000A;Bar</textarea>`. Defaults to `['textarea',
+'pre']`.
+
+#### `:encoding => 'utf-8'`
+
+The encoding to use for the HTML output. Only available in Ruby 1.9 or higher.
+This can be a string or an Encoding Object. Note that Haml does not
+automatically re-encode Ruby values; any strings coming from outside the
+application should be converted before being passed into the Haml template.
+Defaults to `Encoding.default_internal` or, if that's not set, `"utf-8"`.
+
+### See also
+
+ * [#haml.docs](http://haml-lang.com/docs.html)
+ * [Haml Tutorial](http://haml-lang.com/tutorial.html)
+ * [Haml Reference](http://haml-lang.com/docs/yardoc/HAML_REFERENCE.md.html)
+ * [Whitespace Preservation](http://haml-lang.com/docs/yardoc/HAML_REFERENCE.md.html#whitespace_preservation)
+
+
+<a name='liquid'></a>
+Liquid (`liquid`)
+-----------------
+
+Liquid is for rendering safe templates which cannot affect the security
+of the server they are rendered on.
+
+### Example
+
+ <html>
+ <head>
+ <title>{{ title }}</title>
+ </head>
+ <body>
+ <h1>Hello {{ world }}!</h1>
+ </body>
+ </html>
+
+### Usage
+
+`Tilt::LiquidTemplate` is registered for all files ending in `.liquid` by
+default. Liquid templates support locals and objects that respond to
+`#to_h` as scopes:
+
+ >> require 'liquid'
+ >> require 'tilt'
+ >> template = Tilt.new('hello.liquid')
+ => #<Tilt::LiquidTemplate @file='hello.liquid'>
+ >> scope = { :title => "Hello Liquid Templates" }
+ >> template.render(nil, :world => "Liquid")
+ => "
+ <html>
+ <head>
+ <title>Hello Liquid Templates</title>
+ </head>
+ <body>
+ <h1>Hello Liquid!</h1>
+ </body>
+ </html>"
+
+Or, use `Tilt::LiquidTemplate` directly to process strings:
+
+ >> require 'haml'
+ >> template = Tilt::HamlTemplate.new { "<h1>Hello Liquid!</h1>" }
+ => #<Tilt::LiquidTemplate @file=nil ...>
+ >> template.render
+ => "<h1>Hello Liquid!</h1>"
+
+__NOTE:__ It's suggested that your program `require 'liquid'` at load
+time when using this template engine within a threaded environment.
+
+### See also
+
+ * [Liquid for Programmers](http://wiki.github.com/tobi/liquid/liquid-for-programmers)
+ * [Liquid Docs](http://liquid.rubyforge.org/)
+ * GitHub: [tobi/liquid](http://github.com/tobi/liquid/)
+
+<a name='markdown'></a>
+Markdown (`markdown`, `md`, `mkd`)
+----------------------------------
+
+Markdown is a lightweight markup language, created by John Gruber and
+Aaron Swartz. For any markup that is not covered by Markdown’s syntax,
+HTML is used. Marking up plain text with Markdown markup is easy and
+Markdown formatted texts are readable.
+
+Markdown formatted texts are converted to HTML with the [RDiscount][]
+engine, which is a Ruby extension over the fast [Discount][] C library.
+
+### Example
+
+ Hello Markdown Templates
+ ========================
+
+ Hello World. This is a paragraph.
+
+### Usage
+
+To wrap a Markdown formatted document with a layout:
+
+ require 'erubis'
+ require 'rdiscount'
+ layout = Tilt::ErubisTemplate.new(nil, :pattern => '\{% %\}') do
+ "<!doctype html><title></title>{%= yield %}"
+ end
+ data = Tilt::RDiscountTemplate.new { "# hello tilt" }
+ layout.render { data.render }
+ # => "<!doctype html><title></title><h1>hello tilt</h1>\n"
+
+__NOTE:__ It's suggested that your program `require 'rdiscount'` at load time
+when using this template engine in a threaded environment.
+
+### Options
+
+RDiscount supports a variety of flags that control its behavior:
+
+#### `:smart => true|false`
+
+Set `true` to enable [Smarty Pants](http://daringfireball.net/projects/smartypants/)
+style punctuation replacement.
+
+#### `:filter_html => true|false`
+
+Set `true` disallow raw HTML in Markdown contents. HTML is converted to
+literal text by escaping `<` characters.
+
+### See also
+
+ * [Markdown Syntax Documentation][markdown syntax]
+ * GitHub: [rtomayko/rdiscount][rdiscount]
+
+[discount]: http://www.pell.portland.or.us/~orc/Code/discount/ "Discount"
+[rdiscount]: http://github.com/rtomayko/rdiscount/ "RDiscount"
+[markdown syntax]: (http://daringfireball.net/projects/markdown/syntax/) "Markdown Syntax"
+
+
+<a name='rdoc'></a>
+RDoc (`rdoc`)
+-------------
+
+RDoc is the simple text markup system that comes with Ruby's standard
+library.
+
+### Usage
+
+__NOTE:__ It's suggested that your program `require 'rdoc/markup'` and
+`require 'rdoc/markup/to_html'` at load time when using this template
+engine in a threaded environment.
+
+### Example
+
+ = Hello RDoc Templates
+
+ Hello World. This is a paragraph.
+
+### See also
+
+ * [RDoc](http://rdoc.sourceforge.net/doc/index.html)
+
+
+<a name='radius'></a>
+Radius (`radius`)
+-----------------
+
+Radius is the template language used by Radiant CMS. It is a tag
+language designed to be valid XML/HTML.
+
+### Example
+
+ <html>
+ <body>
+ <h1><r:title /></h1>
+ <ul class="<r:type />">
+ <r:repeat times="3">
+ <li><r:hello />!</li>
+ </r:repeat>
+ </ul>
+ <r:yield />
+ </body>
+ </html>
+
+### Usage
+
+To render a template such as the one above.
+
+ scope = OpenStruct.new
+ scope.title = "Radius Example"
+ scope.hello = "Hello, World!"
+
+ require 'radius'
+ template = Tilt::RadiusTemplate.new('example.radius', :tag_prefix=>'r')
+ template.render(scope, :type=>'hlist'){ "Jackpot!" }
+
+The result will be:
+
+ <html>
+ <body>
+ <h1>Radius Example</h1>
+ <ul class="hlist">
+ <li>Hello, World!</li>
+ <li>Hello, World!</li>
+ <li>Hello, World!</li>
+ </ul>
+ Jackpot!
+ </body>
+ </html>
+
+### See also
+
+* [Radius](http://radius.rubyforge.org/)
+* [Radiant](http://radiantcms.org/)
View
110 vendor/tilt-1.1/bin/tilt
@@ -0,0 +1,110 @@
+#!/usr/bin/env ruby
+require 'ostruct'
+require 'optparse'
+require 'tilt'
+
+usage = <<USAGE
+Usage: tilt <options> <file>
+Process template <file> and write output to stdout. With no <file> or
+when <file> is '-', read template from stdin and use the --type option
+to determine the template's type.
+
+Options
+ -l, --list List template engines + file patterns and exit
+ -t, --type=<pattern> Use this template engine; required if no <file>
+ -y, --layout=<file> Use <file> as a layout template
+
+ -D<name>=<value> Define variable <name> as <value>
+ -o, --vars=<ruby> Evaluate <ruby> to Hash and use for variables
+
+ -h, --help Show this help message
+
+Convert markdown to HTML:
+ $ tilt foo.markdown > foo.html
+
+Process ERB template:
+ $ echo "Answer: <%= 2 + 2 %>" | tilt -t erb
+ Answer: 4
+
+Define variables:
+ $ echo "Answer: <%= 2 + n %>" | tilt --locals="{:n=>40, :x=>0}"
+ Answer: 42
+ $ echo "Answer: <%= 2 + n %>" | tilt -Dn=40 -Dx=0
+ Answer: 42
+USAGE
+
+script_name = File.basename($0)
+pattern = nil
+layout = nil
+locals = {}
+
+ARGV.options do |o|
+ o.program_name = script_name
+
+ # list all available template engines
+ o.on("-l", "--list") do
+ groups = {}
+ Tilt.mappings.each do |pattern,engine|
+ key = engine.name.split('::').last.sub(/Template$/, '')
+ (groups[key] ||= []) << pattern
+ end
+ groups.sort { |(k1,v1),(k2,v2)| k1 <=> k2 }.each do |engine,files|
+ printf "%-15s %s\n", engine, files.sort.join(', ')
+ end
+ exit
+ end
+
+ # the template type / pattern
+ o.on("-t", "--type=PATTERN", String) do |val|
+ abort "unknown template type: #{val}" if Tilt[val].nil?
+ pattern = val
+ end
+
+ # pass template output into the specified layout template
+ o.on("-y", "--layout=FILE", String) do |file|
+ paths = [file, "~/.tilt/#{file}", "/etc/tilt/#{file}"]
+ layout = paths.
+ map { |p| File.expand_path(p) }.
+ find { |p| File.exist?(p) }
+ abort "no such layout: #{file}" if layout.nil?
+ end
+
+ # define a local variable
+ o.on("-D", "--define=PAIR", String) do |pair|
+ key, value = pair.split(/[=:]/, 2)
+ locals[key.to_sym] = value
+ end
+
+ # define local variables using a Ruby hash
+ o.on("--vars=RUBY") do |ruby|
+ hash = eval(ruby)
+ abort "vars must be a Hash, not #{hash.inspect}" if !hash.is_a?(Hash)
+ hash.each { |key, value| locals[key.to_sym] = value }
+ end
+
+ o.on_tail("-h", "--help") { puts usage; exit }
+
+ o.parse!
+end
+
+file = ARGV.first || '-'
+pattern = file if pattern.nil?
+abort "template type not given. see: #{$0} --help" if ['-', ''].include?(pattern)
+
+engine = Tilt[pattern]
+abort "template engine not found for: #{pattern}" if engine.nil?
+
+template =
+ engine.new(file) {
+ if file == '-'
+ $stdin.read
+ else
+ File.read(file)
+ end
+ }
+output = template.render(self, locals)
+
+# process layout
+output = Tilt.new(layout).render(self, locals) { output } if layout
+
+$stdout.write(output)
View
868 vendor/tilt-1.1/lib/tilt.rb
@@ -0,0 +1,868 @@
+require 'digest/md5'
+
+module Tilt
+ VERSION = '1.1'
+
+ @template_mappings = {}
+
+ # Hash of template path pattern => template implementation class mappings.
+ def self.mappings
+ @template_mappings
+ end
+
+ # Register a template implementation by file extension.
+ def self.register(ext, template_class)
+ ext = ext.to_s.sub(/^\./, '')
+ mappings[ext.downcase] = template_class
+ end
+
+ # Returns true when a template exists on an exact match of the provided file extension
+ def self.registered?(ext)
+ mappings.key?(ext.downcase)
+ end
+
+ # Create a new template for the given file using the file's extension
+ # to determine the the template mapping.
+ def self.new(file, line=nil, options={}, &block)
+ if template_class = self[file]
+ template_class.new(file, line, options, &block)
+ else
+ fail "No template engine registered for #{File.basename(file)}"
+ end
+ end
+
+ # Lookup a template class for the given filename or file
+ # extension. Return nil when no implementation is found.
+ def self.[](file)
+ pattern = file.to_s.downcase
+ unless registered?(pattern)
+ pattern = File.basename(pattern)
+ pattern.sub!(/^[^.]*\.?/, '') until (pattern.empty? || registered?(pattern))
+ end
+ @template_mappings[pattern]
+ end
+
+ # Mixin allowing template compilation on scope objects.
+ #
+ # Including this module in scope objects passed to Template#render
+ # causes template source to be compiled to methods the first time they're
+ # used. This can yield significant (5x-10x) performance increases for
+ # templates that support it (ERB, Erubis, Builder).
+ #
+ # It's also possible (though not recommended) to include this module in
+ # Object to enable template compilation globally. The downside is that
+ # the template methods will polute the global namespace and could lead to
+ # unexpected behavior.
+ module CompileSite
+ def __tilt__
+ end
+ end
+
+ # Base class for template implementations. Subclasses must implement
+ # the #prepare method and one of the #evaluate or #precompiled_template
+ # methods.
+ class Template
+ # Template source; loaded from a file or given directly.
+ attr_reader :data
+
+ # The name of the file where the template data was loaded from.
+ attr_reader :file
+
+ # The line number in #file where template data was loaded from.
+ attr_reader :line
+
+ # A Hash of template engine specific options. This is passed directly
+ # to the underlying engine and is not used by the generic template
+ # interface.
+ attr_reader :options
+
+ # Used to determine if this class's initialize_engine method has
+ # been called yet.
+ @engine_initialized = false
+ class << self
+ attr_accessor :engine_initialized
+ alias engine_initialized? engine_initialized
+ end
+
+ # Create a new template with the file, line, and options specified. By
+ # default, template data is read from the file. When a block is given,
+ # it should read template data and return as a String. When file is nil,
+ # a block is required.
+ #
+ # All arguments are optional.
+ def initialize(file=nil, line=1, options={}, &block)
+ @file, @line, @options = nil, 1, {}
+
+ [options, line, file].compact.each do |arg|
+ case
+ when arg.respond_to?(:to_str) ; @file = arg.to_str
+ when arg.respond_to?(:to_int) ; @line = arg.to_int
+ when arg.respond_to?(:to_hash) ; @options = arg.to_hash.dup
+ else raise TypeError
+ end
+ end
+
+ raise ArgumentError, "file or block required" if (@file || block).nil?
+
+ # call the initialize_engine method if this is the very first time
+ # an instance of this class has been created.
+ if !self.class.engine_initialized?
+ initialize_engine
+ self.class.engine_initialized = true
+ end
+
+ # used to generate unique method names for template compilation
+ @stamp = (Time.now.to_f * 10000).to_i
+ @compiled_method_names = {}
+
+ # load template data and prepare
+ @reader = block || lambda { |t| File.read(@file) }
+ @data = @reader.call(self)
+ prepare
+ end
+
+ # Render the template in the given scope with the locals specified. If a
+ # block is given, it is typically available within the template via
+ # +yield+.
+ def render(scope=Object.new, locals={}, &block)
+ evaluate scope, locals || {}, &block
+ end
+
+ # The basename of the template file.
+ def basename(suffix='')
+ File.basename(file, suffix) if file
+ end
+
+ # The template file's basename with all extensions chomped off.
+ def name
+ basename.split('.', 2).first if basename
+ end
+
+ # The filename used in backtraces to describe the template.
+ def eval_file
+ file || '(__TEMPLATE__)'
+ end
+
+ protected
+ # Called once and only once for each template subclass the first time
+ # the template class is initialized. This should be used to require the
+ # underlying template library and perform any initial setup.
+ def initialize_engine
+ end
+
+ # Like Kernel::require but issues a warning urging a manual require when
+ # running under a threaded environment.
+ def require_template_library(name)
+ if Thread.list.size > 1
+ warn "WARN: tilt autoloading '#{name}' in a non thread-safe way; " +
+ "explicit require '#{name}' suggested."
+ end
+ require name
+ end
+
+ # Do whatever preparation is necessary to setup the underlying template
+ # engine. Called immediately after template data is loaded. Instance
+ # variables set in this method are available when #evaluate is called.
+ #
+ # Subclasses must provide an implementation of this method.
+ def prepare
+ if respond_to?(:compile!)
+ # backward compat with tilt < 0.6; just in case
+ warn 'Tilt::Template#compile! is deprecated; implement #prepare instead.'
+ compile!
+ else
+ raise NotImplementedError
+ end
+ end
+
+ # Process the template and return the result. When the scope mixes in
+ # the Tilt::CompileSite module, the template is compiled to a method and
+ # reused given identical locals keys. When the scope object
+ # does not mix in the CompileSite module, the template source is
+ # evaluated with instance_eval. In any case, template executation
+ # is guaranteed to be performed in the scope object with the locals
+ # specified and with support for yielding to the block.
+ def evaluate(scope, locals, &block)
+ if scope.respond_to?(:__tilt__)
+ method_name = compiled_method_name(locals.keys)
+ if scope.respond_to?(method_name)
+ scope.send(method_name, locals, &block)
+ else
+ compile_template_method(method_name, locals)
+ scope.send(method_name, locals, &block)
+ end
+ else
+ evaluate_source(scope, locals, &block)
+ end
+ end
+
+ # Generates all template source by combining the preamble, template, and
+ # postamble and returns a two-tuple of the form: [source, offset], where
+ # source is the string containing (Ruby) source code for the template and
+ # offset is the integer line offset where line reporting should begin.
+ #
+ # Template subclasses may override this method when they need complete
+ # control over source generation or want to adjust the default line
+ # offset. In most cases, overriding the #precompiled_template method is
+ # easier and more appropriate.
+ def precompiled(locals)
+ preamble = precompiled_preamble(locals)
+ parts = [
+ preamble,
+ precompiled_template(locals),
+ precompiled_postamble(locals)
+ ]
+ [parts.join("\n"), preamble.count("\n") + 1]
+ end
+
+ # A string containing the (Ruby) source code for the template. The
+ # default Template#evaluate implementation requires either this method
+ # or the #precompiled method be overridden. When defined, the base
+ # Template guarantees correct file/line handling, locals support, custom
+ # scopes, and support for template compilation when the scope object
+ # allows it.
+ def precompiled_template(locals)
+ raise NotImplementedError
+ end
+
+ # Generates preamble code for initializing template state, and performing
+ # locals assignment. The default implementation performs locals
+ # assignment only. Lines included in the preamble are subtracted from the
+ # source line offset, so adding code to the preamble does not effect line
+ # reporting in Kernel::caller and backtraces.
+ def precompiled_preamble(locals)
+ locals.map { |k,v| "#{k} = locals[:#{k}]" }.join("\n")
+ end
+
+ # Generates postamble code for the precompiled template source. The
+ # string returned from this method is appended to the precompiled
+ # template source.
+ def precompiled_postamble(locals)
+ ''
+ end
+
+ # The unique compiled method name for the locals keys provided.
+ def compiled_method_name(locals_keys)
+ @compiled_method_names[locals_keys] ||=
+ generate_compiled_method_name(locals_keys)
+ end
+
+ private
+ # Evaluate the template source in the context of the scope object.
+ def evaluate_source(scope, locals, &block)
+ source, offset = precompiled(locals)
+ scope.instance_eval(source, eval_file, line - offset)
+ end
+
+ # JRuby doesn't allow Object#instance_eval to yield to the block it's
+ # closed over. This is by design and (ostensibly) something that will
+ # change in MRI, though no current MRI version tested (1.8.6 - 1.9.2)
+ # exhibits the behavior. More info here:
+ #
+ # http://jira.codehaus.org/browse/JRUBY-2599
+ #
+ # Additionally, JRuby's eval line reporting is off by one compared to
+ # all MRI versions tested.
+ #
+ # We redefine evaluate_source to work around both issues.
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
+ undef evaluate_source
+ def evaluate_source(scope, locals, &block)
+ source, offset = precompiled(locals)
+ file, lineno = eval_file, (line - offset) - 1
+ scope.instance_eval { Kernel::eval(source, binding, file, lineno) }
+ end
+ end
+
+ def generate_compiled_method_name(locals_keys)
+ parts = [object_id, @stamp] + locals_keys.map { |k| k.to_s }.sort
+ digest = Digest::MD5.hexdigest(parts.join(':'))
+ "__tilt_#{digest}"
+ end
+
+ def compile_template_method(method_name, locals)
+ source, offset = precompiled(locals)
+ offset += 5
+ CompileSite.class_eval <<-RUBY, eval_file, line - offset
+ def #{method_name}(locals)
+ Thread.current[:tilt_vars] = [self, locals]
+ class << self
+ this, locals = Thread.current[:tilt_vars]
+ this.instance_eval do
+ #{source}
+ end
+ end
+ end
+ RUBY
+ ObjectSpace.define_finalizer self,
+ Template.compiled_template_method_remover(CompileSite, method_name)
+ end
+
+ def self.compiled_template_method_remover(site, method_name)
+ proc { |oid| garbage_collect_compiled_template_method(site, method_name) }
+ end
+
+ def self.garbage_collect_compiled_template_method(site, method_name)
+ site.module_eval do
+ begin
+ remove_method(method_name)
+ rescue NameError
+ # method was already removed (ruby >= 1.9)
+ end
+ end
+ end
+
+ # Special case Ruby 1.9.1's broken yield.
+ #
+ # http://github.com/rtomayko/tilt/commit/20c01a5
+ # http://redmine.ruby-lang.org/issues/show/3601
+ #
+ # Remove when 1.9.2 dominates 1.9.1 installs in the wild.
+ if RUBY_VERSION =~ /^1.9.1/
+ undef compile_template_method
+ def compile_template_method(method_name, locals)
+ source, offset = precompiled(locals)
+ offset += 1
+ CompileSite.module_eval <<-RUBY, eval_file, line - offset
+ def #{method_name}(locals)
+ #{source}
+ end
+ RUBY
+ ObjectSpace.define_finalizer self,
+ Template.compiled_template_method_remover(CompileSite, method_name)
+ end
+ end
+ end
+
+ # Extremely simple template cache implementation. Calling applications
+ # create a Tilt::Cache instance and use #fetch with any set of hashable
+ # arguments (such as those to Tilt.new):
+ # cache = Tilt::Cache.new
+ # cache.fetch(path, line, options) { Tilt.new(path, line, options) }
+ #
+ # Subsequent invocations return the already loaded template object.
+ class Cache
+ def initialize
+ @cache = {}
+ end
+
+ def fetch(*key)
+ @cache[key] ||= yield
+ end
+
+ def clear
+ @cache = {}
+ end
+ end
+
+
+ # Template Implementations ================================================
+
+
+ # The template source is evaluated as a Ruby string. The #{} interpolation
+ # syntax can be used to generated dynamic output.
+ class StringTemplate < Template
+ def prepare
+ @code = "%Q{#{data}}"
+ end
+
+ def precompiled_template(locals)
+ @code
+ end
+ end
+ register 'str', StringTemplate
+
+
+ # ERB template implementation. See:
+ # http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html
+ class ERBTemplate < Template
+ @@default_output_variable = '_erbout'
+
+ def self.default_output_variable
+ @@default_output_variable
+ end
+
+ def self.default_output_variable=(name)
+ @@default_output_variable = name
+ end
+
+ def initialize_engine
+ return if defined? ::ERB
+ require_template_library 'erb'
+ end
+
+ def prepare
+ @outvar = options[:outvar] || self.class.default_output_variable
+ @engine = ::ERB.new(data, options[:safe], options[:trim], @outvar)
+ end
+
+ def precompiled_template(locals)
+ source = @engine.src
+ source
+ end
+
+ def precompiled_preamble(locals)
+ <<-RUBY
+ begin
+ __original_outvar = #{@outvar} if defined?(#{@outvar})
+ #{super}
+ RUBY
+ end
+
+ def precompiled_postamble(locals)
+ <<-RUBY
+ #{super}
+ ensure
+ #{@outvar} = __original_outvar
+ end
+ RUBY
+ end
+
+ # ERB generates a line to specify the character coding of the generated
+ # source in 1.9. Account for this in the line offset.
+ if RUBY_VERSION >= '1.9.0'
+ def precompiled(locals)
+ source, offset = super
+ [source, offset + 1]
+ end
+ end
+ end
+
+ %w[erb rhtml].each { |ext| register ext, ERBTemplate }
+
+
+ # Erubis template implementation. See:
+ # http://www.kuwata-lab.com/erubis/
+ #
+ # ErubisTemplate supports the following additional options, which are not
+ # passed down to the Erubis engine:
+ #
+ # :engine_class allows you to specify a custom engine class to use
+ # instead of the default (which is ::Erubis::Eruby).
+ #
+ # :escape_html when true, ::Erubis::EscapedEruby will be used as
+ # the engine class instead of the default. All content
+ # within <%= %> blocks will be automatically html escaped.
+ class ErubisTemplate < ERBTemplate
+ def initialize_engine
+ return if defined? ::Erubis
+ require_template_library 'erubis'
+ end
+
+ def prepare
+ @options.merge!(:preamble => false, :postamble => false)
+ @outvar = options.delete(:outvar) || self.class.default_output_variable
+ engine_class = options.delete(:engine_class)
+ engine_class = ::Erubis::EscapedEruby if options.delete(:escape_html)
+ @engine = (engine_class || ::Erubis::Eruby).new(data, options)
+ end
+
+ def precompiled_preamble(locals)
+ [super, "#{@outvar} = _buf = ''"].join("\n")
+ end
+
+ def precompiled_postamble(locals)
+ ["_buf", super].join("\n")
+ end
+
+ # Erubis doesn't have ERB's line-off-by-one under 1.9 problem.
+ # Override and adjust back.
+ if RUBY_VERSION >= '1.9.0'
+ def precompiled(locals)
+ source, offset = super
+ [source, offset - 1]
+ end
+ end
+ end
+ register 'erubis', ErubisTemplate
+
+
+ # Haml template implementation. See:
+ # http://haml.hamptoncatlin.com/
+ class HamlTemplate < Template
+ def initialize_engine
+ return if defined? ::Haml::Engine
+ require_template_library 'haml'
+ end
+
+ def prepare
+ options = @options.merge(:filename => eval_file, :line => line)
+ @engine = ::Haml::Engine.new(data, options)
+ end
+
+ def evaluate(scope, locals, &block)
+ if @engine.respond_to?(:precompiled_method_return_value, true)
+ super
+ else
+ @engine.render(scope, locals, &block)
+ end
+ end
+
+ # Precompiled Haml source. Taken from the precompiled_with_ambles
+ # method in Haml::Precompiler:
+ # http://github.com/nex3/haml/blob/master/lib/haml/precompiler.rb#L111-126
+ def precompiled_template(locals)
+ @engine.precompiled
+ end
+
+ def precompiled_preamble(locals)
+ local_assigns = super
+ @engine.instance_eval do
+ <<-RUBY
+ begin
+ extend Haml::Helpers
+ _hamlout = @haml_buffer = Haml::Buffer.new(@haml_buffer, #{options_for_buffer.inspect})
+ _erbout = _hamlout.buffer
+ __in_erb_template = true
+ _haml_locals = locals
+ #{local_assigns}
+ RUBY
+ end
+ end
+
+ def precompiled_postamble(locals)
+ @engine.instance_eval do
+ <<-RUBY
+ #{precompiled_method_return_value}
+ ensure
+ @haml_buffer = @haml_buffer.upper
+ end
+ RUBY
+ end
+ end
+ end
+ register 'haml', HamlTemplate
+
+
+ # Sass template implementation. See:
+ # http://haml.hamptoncatlin.com/
+ #
+ # Sass templates do not support object scopes, locals, or yield.
+ class SassTemplate < Template
+ def initialize_engine
+ return if defined? ::Sass::Engine
+ require_template_library 'sass'
+ end
+
+ def prepare
+ @engine = ::Sass::Engine.new(data, sass_options)
+ end
+
+ def evaluate(scope, locals, &block)
+ @output ||= @engine.render
+ end
+
+ private
+ def sass_options
+ options.merge(:filename => eval_file, :line => line, :syntax => :sass)
+ end
+ end
+ register 'sass', SassTemplate
+
+ # Sass's new .scss type template implementation.
+ class ScssTemplate < SassTemplate
+ private
+ def sass_options
+ options.merge(:filename => eval_file, :line => line, :syntax => :scss)
+ end
+ end
+ register 'scss', ScssTemplate
+
+ # Lessscss template implementation. See:
+ # http://lesscss.org/
+ #
+ # Less templates do not support object scopes, locals, or yield.
+ class LessTemplate < Template
+ def initialize_engine
+ return if defined? ::Less::Engine
+ require_template_library 'less'
+ end
+
+ def prepare
+ @engine = ::Less::Engine.new(data)
+ end
+
+ def evaluate(scope, locals, &block)
+ @engine.to_css
+ end
+ end
+ register 'less', LessTemplate
+
+
+ # CoffeeScript template implementation. See:
+ # http://coffeescript.org/
+ #
+ # CoffeeScript templates do not support object scopes, locals, or yield.
+ class CoffeeScriptTemplate < Template
+ @@default_no_wrap = false
+
+ def self.default_no_wrap
+ @@default_no_wrap
+ end
+
+ def self.default_no_wrap=(value)
+ @@default_no_wrap = value
+ end
+
+ def initialize_engine
+ return if defined? ::CoffeeScript
+ require_template_library 'coffee_script'
+ end
+
+ def prepare
+ @no_wrap = options.key?(:no_wrap) ? options[:no_wrap] :
+ self.class.default_no_wrap
+ end
+
+ def evaluate(scope, locals, &block)
+ @output ||= CoffeeScript.compile(data, :no_wrap => @no_wrap)
+ end
+ end
+ register 'coffee', CoffeeScriptTemplate
+
+
+ # Nokogiri template implementation. See:
+ # http://nokogiri.org/
+ class NokogiriTemplate < Template
+ def initialize_engine
+ return if defined?(::Nokogiri)
+ require_template_library 'nokogiri'
+ end
+
+ def prepare; end
+
+ def evaluate(scope, locals, &block)
+ xml = ::Nokogiri::XML::Builder.new
+ if data.respond_to?(:to_str)
+ locals[:xml] = xml
+ super(scope, locals, &block)
+ elsif data.kind_of?(Proc)
+ data.call(xml)
+ end
+ xml.to_xml
+ end
+
+ def precompiled_template(locals)
+ data.to_str
+ end
+ end
+ register 'nokogiri', NokogiriTemplate
+
+ # Builder template implementation. See:
+ # http://builder.rubyforge.org/
+ class BuilderTemplate < Template
+ def initialize_engine
+ return if defined?(::Builder)
+ require_template_library 'builder'
+ end
+
+ def prepare
+ end
+
+ def evaluate(scope, locals, &block)
+ xml = ::Builder::XmlMarkup.new(:indent => 2)
+ if data.respond_to?(:to_str)
+ locals[:xml] = xml
+ super(scope, locals, &block)
+ elsif data.kind_of?(Proc)
+ data.call(xml)
+ end
+ xml.target!
+ end
+
+ def precompiled_template(locals)
+ data.to_str
+ end
+ end
+ register 'builder', BuilderTemplate
+
+
+ # Liquid template implementation. See:
+ # http://liquid.rubyforge.org/
+ #
+ # Liquid is designed to be a *safe* template system and threfore
+ # does not provide direct access to execuatable scopes. In order to
+ # support a +scope+, the +scope+ must be able to represent itself
+ # as a hash by responding to #to_h. If the +scope+ does not respond
+ # to #to_h it will be ignored.
+ #
+ # LiquidTemplate does not support yield blocks.
+ #
+ # It's suggested that your program require 'liquid' at load
+ # time when using this template engine.
+ class LiquidTemplate < Template
+ def initialize_engine
+ return if defined? ::Liquid::Template
+ require_template_library 'liquid'
+ end
+
+ def prepare
+ @engine = ::Liquid::Template.parse(data)
+ end
+
+ def evaluate(scope, locals, &block)
+ locals = locals.inject({}){ |h,(k,v)| h[k.to_s] = v ; h }
+ if scope.respond_to?(:to_h)
+ scope = scope.to_h.inject({}){ |h,(k,v)| h[k.to_s] = v ; h }
+ locals = scope.merge(locals)
+ end
+ locals['yield'] = block.nil? ? '' : yield
+ locals['content'] = locals['yield']
+ @engine.render(locals)
+ end
+ end
+ register 'liquid', LiquidTemplate
+
+
+ # Discount Markdown implementation. See:
+ # http://github.com/rtomayko/rdiscount
+ #
+ # RDiscount is a simple text filter. It does not support +scope+ or
+ # +locals+. The +:smart+ and +:filter_html+ options may be set true
+ # to enable those flags on the underlying RDiscount object.
+ class RDiscountTemplate < Template
+ def flags
+ [:smart, :filter_html].select { |flag| options[flag] }
+ end
+
+ def initialize_engine
+ return if defined? ::RDiscount
+ require_template_library 'rdiscount'
+ end
+
+ def prepare
+ @engine = RDiscount.new(data, *flags)
+ @output = nil
+ end
+
+ def evaluate(scope, locals, &block)
+ @output ||= @engine.to_html
+ end
+ end
+ register 'markdown', RDiscountTemplate
+ register 'mkd', RDiscountTemplate
+ register 'md', RDiscountTemplate
+
+
+ # RedCloth implementation. See:
+ # http://redcloth.org/
+ class RedClothTemplate < Template
+ def initialize_engine
+ return if defined? ::RedCloth
+ require_template_library 'redcloth'
+ end
+
+ def prepare
+ @engine = RedCloth.new(data)
+ @output = nil
+ end
+
+ def evaluate(scope, locals, &block)
+ @output ||= @engine.to_html
+ end
+ end
+ register 'textile', RedClothTemplate
+
+
+ # RDoc template. See:
+ # http://rdoc.rubyforge.org/
+ #
+ # It's suggested that your program require 'rdoc/markup' and
+ # 'rdoc/markup/to_html' at load time when using this template
+ # engine.
+ class RDocTemplate < Template
+ def initialize_engine
+ return if defined?(::RDoc::Markup)
+ require_template_library 'rdoc/markup'
+ require_template_library 'rdoc/markup/to_html'
+ end
+
+ def prepare
+ markup = RDoc::Markup::ToHtml.new
+ @engine = markup.convert(data)
+ @output = nil
+ end
+
+ def evaluate(scope, locals, &block)
+ @output ||= @engine.to_s
+ end
+ end
+ register 'rdoc', RDocTemplate
+
+
+ # Radius Template
+ # http://github.com/jlong/radius/
+ class RadiusTemplate < Template
+ def initialize_engine
+ return if defined? ::Radius
+ require_template_library 'radius'
+ end
+
+ def prepare
+ end
+
+ def evaluate(scope, locals, &block)
+ context = Class.new(Radius::Context).new
+ context.define_tag("yield") do
+ block.call
+ end
+ locals.each do |tag, value|
+ context.define_tag(tag) do
+ value
+ end
+ end
+ (class << context; self; end).class_eval do
+ define_method :tag_missing do |tag, attr|
+ scope.__send__(tag) # any way to support attr as args?
+ end
+ end
+ options = {:tag_prefix => 'r'}.merge(@options)
+ parser = Radius::Parser.new(context, options)
+ parser.parse(data)
+ end
+ end
+ register 'radius', RadiusTemplate
+
+
+ # Markaby
+ # http://github.com/markaby/markaby
+ class MarkabyTemplate < Template
+ def self.builder_class
+ @builder_class ||= Class.new(Markaby::Builder) do
+ def __capture_markaby_tilt__(&block)
+ __run_markaby_tilt__ do
+ text capture(&block)
+ end
+ end
+ end
+ end
+
+ def initialize_engine
+ return if defined? ::Markaby
+ require_template_library 'markaby'
+ end
+
+ def prepare
+ end
+
+ def evaluate(scope, locals, &block)
+ builder = self.class.builder_class.new({}, scope)
+ builder.locals = locals
+
+ if block
+ builder.instance_eval <<-CODE, __FILE__, __LINE__
+ def __run_markaby_tilt__
+ #{data}
+ end
+ CODE
+
+ builder.__capture_markaby_tilt__(&block)
+ else
+ builder.instance_eval(data, __FILE__, __LINE__)
+ end
+
+ builder.to_s
+ end
+ end
+ register 'mab', MarkabyTemplate
+end
View
68 vendor/tilt-1.1/test/contest.rb
@@ -0,0 +1,68 @@
+require "test/unit"
+
+# Test::Unit loads a default test if the suite is empty, whose purpose is to
+# fail. Since having empty contexts is a common practice, we decided to
+# overwrite TestSuite#empty? in order to allow them. Having a failure when no
+# tests have been defined seems counter-intuitive.
+class Test::Unit::TestSuite
+ def empty?
+ false
+ end
+end
+
+# Contest adds +teardown+, +test+ and +context+ as class methods, and the
+# instance methods +setup+ and +teardown+ now iterate on the corresponding
+# blocks. Note that all setup and teardown blocks must be defined with the
+# block syntax. Adding setup or teardown instance methods defeats the purpose
+# of this library.
+class Test::Unit::TestCase
+ def self.setup(&block)
+ define_method :setup do
+ super(&block)
+ instance_eval(&block)
+ end
+ end
+
+ def self.teardown(&block)
+ define_method :teardown do
+ instance_eval(&block)
+ super(&block)
+ end
+ end
+
+ def self.context(name, &block)
+ subclass = Class.new(self)
+ remove_tests(subclass)
+ subclass.class_eval(&block) if block_given?
+ const_set(context_name(name), subclass)
+ end
+
+ def self.test(name, &block)
+ define_method(test_name(name), &block)
+ end
+
+ class << self
+ alias_method :should, :test
+ alias_method :describe, :context
+ end
+
+private
+
+ def self.context_name(name)
+ "Test#{sanitize_name(name).gsub(/(^| )(\w)/) { $2.upcase }}".to_sym
+ end
+
+ def self.test_name(name)
+ "test_#{sanitize_name(name).gsub(/\s+/,'_')}".to_sym
+ end
+
+ def self.sanitize_name(name)
+ name.gsub(/\W+/, ' ').strip
+ end
+
+ def self.remove_tests(subclass)
+ subclass.public_instance_methods.grep(/^test_/).each do |meth|
+ subclass.send(:undef_method, meth.to_sym)
+ end
+ end
+end
View
1  vendor/tilt-1.1/test/markaby/locals.mab
@@ -0,0 +1 @@
+li foo
View
1  vendor/tilt-1.1/test/markaby/markaby.mab
@@ -0,0 +1 @@
+text "hello from markaby!"
View
1  vendor/tilt-1.1/test/markaby/markaby_other_static.mab
@@ -0,0 +1 @@
+text "_why?"
View
1  vendor/tilt-1.1/test/markaby/render_twice.mab
@@ -0,0 +1 @@
+text "foo"
View
1  vendor/tilt-1.1/test/markaby/scope.mab
@@ -0,0 +1 @@
+li foo
View
2  vendor/tilt-1.1/test/markaby/yielding.mab
@@ -0,0 +1,2 @@
+text("Hey ")
+yield
View
44 vendor/tilt-1.1/test/tilt_buildertemplate_test.rb
@@ -0,0 +1,44 @@
+require 'contest'
+require 'tilt'
+
+begin
+ require 'builder'
+ class BuilderTemplateTest < Test::Unit::TestCase
+ test "registered for '.builder' files" do
+ assert_equal Tilt::BuilderTemplate, Tilt['test.builder']
+ assert_equal Tilt::BuilderTemplate, Tilt['test.xml.builder']
+ end
+
+ test "preparing and evaluating the template on #render" do
+ template = Tilt::BuilderTemplate.new { |t| "xml.em 'Hello World!'" }
+ assert_equal "<em>Hello World!</em>\n", template.render
+ end
+
+ test "passing locals" do
+ template = Tilt::BuilderTemplate.new { "xml.em('Hey ' + name + '!')" }
+ assert_equal "<em>Hey Joe!</em>\n", template.render(Object.new, :name => 'Joe')
+ end
+
+ test "evaluating in an object scope" do
+ template = Tilt::BuilderTemplate.new { "xml.em('Hey ' + @name + '!')" }
+ scope = Object.new
+ scope.instance_variable_set :@name, 'Joe'
+ assert_equal "<em>Hey Joe!</em>\n", template.render(scope)
+ end
+
+ test "passing a block for yield" do
+ template = Tilt::BuilderTemplate.new { "xml.em('Hey ' + yield + '!')" }
+ assert_equal "<em>Hey Joe!</em>\n", template.render { 'Joe' }
+ end
+
+ test "block style templates" do
+ template =
+ Tilt::BuilderTemplate.new do |t|
+ lambda { |xml| xml.em('Hey Joe!') }
+ end
+ assert_equal "<em>Hey Joe!</em>\n", template.render
+ end
+ end
+rescue LoadError
+ warn "Tilt::BuilderTemplate (disabled)"
+end
View
32 vendor/tilt-1.1/test/tilt_cache_test.rb
@@ -0,0 +1,32 @@
+require 'contest'
+require 'tilt'
+
+class TiltCacheTest < Test::Unit::TestCase
+ setup { @cache = Tilt::Cache.new }
+
+ test "caching with single simple argument to #fetch" do
+ template = nil
+ result = @cache.fetch('hello') { template = Tilt::StringTemplate.new {''} }
+ assert_same template, result
+ result = @cache.fetch('hello') { fail 'should be cached' }
+ assert_same template, result
+ end
+
+ test "caching with multiple complex arguments to #fetch" do
+ template = nil
+ result = @cache.fetch('hello', {:foo => 'bar', :baz => 'bizzle'}) { template = Tilt::StringTemplate.new {''} }
+ assert_same template, result
+ result = @cache.fetch('hello', {:foo => 'bar', :baz => 'bizzle'}) { fail 'should be cached' }
+ assert_same template, result
+ end
+
+ test "clearing the cache with #clear" do
+ template, other = nil
+ result = @cache.fetch('hello') { template = Tilt::StringTemplate.new {''} }
+ assert_same template, result
+
+ @cache.clear
+ result = @cache.fetch('hello') { other = Tilt::StringTemplate.new {''} }
+ assert_same other, result
+ end
+end
View
25 vendor/tilt-1.1/test/tilt_coffeescripttemplate_test.rb
@@ -0,0 +1,25 @@
+require 'contest'
+require 'tilt'
+
+begin
+ require 'coffee_script'
+
+ class CoffeeScriptTemplateTest < Test::Unit::TestCase
+ test "is registered for '.coffee' files" do
+ assert_equal Tilt::CoffeeScriptTemplate, Tilt['test.coffee']
+ end
+
+ test "compiles and evaluates the template on #render" do
+ template = Tilt::CoffeeScriptTemplate.new { |t| "puts 'Hello, World!'\n" }
+ assert_equal "(function() {\n puts('Hello, World!');\n})();\n", template.render
+ end
+
+ test "disabling coffee-script wrapper" do
+ template = Tilt::CoffeeScriptTemplate.new(:no_wrap => true) { |t| "puts 'Hello, World!'\n" }
+ assert_equal "puts('Hello, World!');", template.render
+ end
+ end
+
+rescue LoadError => boom
+ warn "Tilt::CoffeeScriptTemplate (disabled)\n"
+end
View
86 vendor/tilt-1.1/test/tilt_compilesite_test.rb
@@ -0,0 +1,86 @@
+require 'contest'
+require 'tilt'
+require 'thread'
+
+class CompileSiteTest < Test::Unit::TestCase
+ def setup
+ GC.start
+ end
+
+ class CompilingTemplate < Tilt::Template
+ def prepare
+ end
+
+ def precompiled_template(locals)
+ @data.inspect
+ end
+ end
+
+ class Scope
+ include Tilt::CompileSite
+ end
+
+ test "compiling template source to a method" do
+ template = CompilingTemplate.new { |t| "Hello World!" }
+ template.render(Scope.new)
+ method_name = template.send(:compiled_method_name, [])
+ method_name = method_name.to_sym if Symbol === Kernel.methods.first
+ assert Tilt::CompileSite.instance_methods.include?(method_name),
+ "CompileSite.instance_methods.include?(#{method_name.inspect})"
+ assert Scope.new.respond_to?(method_name),
+ "scope.respond_to?(#{method_name.inspect})"
+ end
+
+ test 'garbage collecting compiled methods' do
+ template = CompilingTemplate.new { '' }
+ method_name = template.send(:compiled_method_name, [])
+ template.render(Scope.new)
+ assert Scope.new.respond_to?(method_name)
+ Tilt::Template.send(
+ :garbage_collect_compiled_template_method,
+ Tilt::CompileSite,
+ method_name
+ )
+ assert !Scope.new.respond_to?(method_name), "compiled method not removed"
+ end
+
+ def self.create_and_destroy_template
+ template = CompilingTemplate.new { 'Hello World' }
+ template.render(Scope.new)
+ method_name = template.send(:compiled_method_name, [])
+ method_name = method_name.to_sym if Symbol === Kernel.methods.first
+ [template.object_id, method_name]
+ end
+
+ finalized_object_id, finalized_method_name = create_and_destroy_template
+
+ test "triggering compiled method gc finalizer" do
+ assert !Tilt::CompileSite.instance_methods.include?(finalized_method_name),
+ "CompileSite.instance_methods.include?(#{finalized_method_name.inspect})"
+ assert !Scope.new.respond_to?(finalized_method_name),
+ "Scope.new.respond_to?(#{finalized_method_name.inspect})"
+ end
+
+ # This test attempts to surface issues with compiling templates from
+ # multiple threads.
+ test "using compiled templates from multiple threads" do
+ template = CompilingTemplate.new { 'template' }
+ main_thread = Thread.current
+ 10.times do |i|
+ threads =
+ (1..50).map do |j|
+ Thread.new {
+ begin
+ locals = { "local#{i}" => 'value' }
+ res = template.render(self, locals)
+ thread_id = Thread.current.object_id
+ res = template.render(self, "local#{thread_id.to_s}" => 'value')
+ rescue => boom
+ main_thread.raise(boom)
+ end
+ }
+ end
+ threads.each { |t| t.join }
+ end
+ end
+end
View
212 vendor/tilt-1.1/test/tilt_erbtemplate_test.rb
@@ -0,0 +1,212 @@
+require 'contest'
+require 'tilt'
+require 'erb'
+
+class ERBTemplateTest < Test::Unit::TestCase
+ test "registered for '.erb' files" do
+ assert_equal Tilt::ERBTemplate, Tilt['test.erb']
+ assert_equal Tilt::ERBTemplate, Tilt['test.html.erb']
+ end
+
+ test "registered for '.rhtml' files" do
+ assert_equal Tilt::ERBTemplate, Tilt['test.rhtml']
+ end
+
+ test "loading and evaluating templates on #render" do
+ template = Tilt::ERBTemplate.new { |t| "Hello World!" }
+ assert_equal "Hello World!", template.render
+ end
+
+ test "passing locals" do
+ template = Tilt::ERBTemplate.new { 'Hey <%= name %>!' }
+ assert_equal "Hey Joe!", template.render(Object.new, :name => 'Joe')
+ end
+
+ test "evaluating in an object scope" do
+ template = Tilt::ERBTemplate.new { 'Hey <%= @name %>!' }
+ scope = Object.new
+ scope.instance_variable_set :@name, 'Joe'
+ assert_equal "Hey Joe!", template.render(scope)
+ end
+
+ class MockOutputVariableScope
+ attr_accessor :exposed_buffer
+ end
+
+ test "exposing the buffer to the template by default" do
+ begin
+ Tilt::ERBTemplate.default_output_variable = '@_out_buf'
+ template = Tilt::ERBTemplate.new { '<% self.exposed_buffer = @_out_buf %>hey' }
+ scope = MockOutputVariableScope.new
+ template.render(scope)
+ assert_not_nil scope.exposed_buffer
+ assert_equal scope.exposed_buffer, 'hey'
+ ensure
+ Tilt::ERBTemplate.default_output_variable = '_erbout'
+ end
+ end
+
+ test "passing a block for yield" do
+ template = Tilt::ERBTemplate.new { 'Hey <%= yield %>!' }
+ assert_equal "Hey Joe!", template.render { 'Joe' }
+ end
+
+ test "backtrace file and line reporting without locals" do
+ data = File.read(__FILE__).split("\n__END__\n").last
+ fail unless data[0] == ?<
+ template = Tilt::ERBTemplate.new('test.erb', 11) { data }
+ begin
+ template.render
+ fail 'should have raised an exception'
+ rescue => boom
+ assert_kind_of NameError, boom
+ line = boom.backtrace.first
+ file, line, meth = line.split(":")
+ assert_equal 'test.erb', file
+ assert_equal '13', line
+ end
+ end
+
+ test "backtrace file and line reporting with locals" do
+ data = File.read(__FILE__).split("\n__END__\n").last
+ fail unless data[0] == ?<
+ template = Tilt::ERBTemplate.new('test.erb', 1) { data }
+ begin
+ template.render(nil, :name => 'Joe', :foo => 'bar')
+ fail 'should have raised an exception'
+ rescue => boom
+ assert_kind_of RuntimeError, boom
+ line = boom.backtrace.first
+ file, line, meth = line.split(":")
+ assert_equal 'test.erb', file
+ assert_equal '6', line
+ end
+ end
+
+ test "default non-stripping trim mode" do
+ template = Tilt.new('test.erb', 1) { "\n<%= 1 + 1 %>\n" }
+ assert_equal "\n2\n", template.render
+ end
+
+ test "stripping trim mode" do
+ template = Tilt.new('test.erb', 1, :trim => '-') { "\n<%= 1 + 1 -%>\n" }
+ assert_equal "\n2", template.render
+ end
+
+ test "shorthand whole line syntax trim mode" do
+ template = Tilt.new('test.erb', :trim => '%') { "\n% if true\nhello\n%end\n" }
+ assert_equal "\nhello\n", template.render
+ end
+
+ test "using an instance variable as the outvar" do
+ template = Tilt::ERBTemplate.new(nil, :outvar => '@buf') { "<%= 1 + 1 %>" }
+ scope = Object.new
+ scope.instance_variable_set(:@buf, 'original value')
+ assert_equal '2', template.render(scope)
+ assert_equal 'original value', scope.instance_variable_get(:@buf)
+ end
+end
+
+class CompiledERBTemplateTest < Test::Unit::TestCase
+ def teardown
+ GC.start
+ end
+
+ class Scope
+ include Tilt::CompileSite
+ end
+
+ test "compiling template source to a method" do
+ template = Tilt::ERBTemplate.new { |t| "Hello World!" }
+ template.render(Scope.new)
+ method_name = template.send(:compiled_method_name, [])
+ method_name = method_name.to_sym if Symbol === Kernel.methods.first
+ assert Tilt::CompileSite.instance_methods.include?(method_name),
+ "CompileSite.instance_methods.include?(#{method_name.inspect})"
+ assert Scope.new.respond_to?(method_name),
+ "scope.respond_to?(#{method_name.inspect})"
+ end
+
+ test "loading and evaluating templates on #render" do
+ template = Tilt::ERBTemplate.new { |t| "Hello World!" }
+ assert_equal "Hello World!", template.render(Scope.new)
+ assert_equal "Hello World!", template.render(Scope.new)
+ end
+
+ test "passing locals" do
+ template = Tilt::ERBTemplate.new { 'Hey <%= name %>!' }
+ assert_equal "Hey Joe!", template.render(Scope.new, :name => 'Joe')
+ end
+
+ test "evaluating in an object scope" do
+ template = Tilt::ERBTemplate.new { 'Hey <%= @name %>!' }
+ scope = Scope.new
+ scope.instance_variable_set :@name, 'Joe'
+ assert_equal "Hey Joe!", template.render(scope)
+ scope.instance_variable_set :@name, 'Jane'
+ assert_equal "Hey Jane!", template.render(scope)
+ end
+
+ test "passing a block for yield" do
+ template = Tilt::ERBTemplate.new { 'Hey <%= yield %>!' }
+ assert_equal "Hey Joe!", template.render(Scope.new) { 'Joe' }
+ assert_equal "Hey Jane!", template.render(Scope.new) { 'Jane' }
+ end
+
+ test "backtrace file and line reporting without locals" do
+ data = File.read(__FILE__).split("\n__END__\n").last
+ fail unless data[0] == ?<
+ template = Tilt::ERBTemplate.new('test.erb', 11) { data }
+ begin
+ template.render(Scope.new)
+ fail 'should have raised an exception'
+ rescue => boom
+ assert_kind_of NameError, boom
+ line = boom.backtrace.first
+ file, line, meth = line.split(":")
+ assert_equal 'test.erb', file
+ assert_equal '13', line
+ end
+ end
+
+ test "backtrace file and line reporting with locals" do
+ data = File.read(__FILE__).split("\n__END__\n").last
+ fail unless data[0] == ?<
+ template = Tilt::ERBTemplate.new('test.erb') { data }
+ begin
+ template.render(Scope.new, :name => 'Joe', :foo => 'bar')
+ fail 'should have raised an exception'
+ rescue => boom
+ assert_kind_of RuntimeError, boom
+ line = boom.backtrace.first
+ file, line, meth = line.split(":")
+ assert_equal 'test.erb', file
+ assert_equal '6', line
+ end
+ end
+
+ test "default non-stripping trim mode" do
+ template = Tilt.new('test.erb') { "\n<%= 1 + 1 %>\n" }
+ assert_equal "\n2\n", template.render(Scope.new)
+ end
+
+ test "stripping trim mode" do
+ template = Tilt.new('test.erb', :trim => '-') { "\n<%= 1 + 1 -%>\n" }
+ assert_equal "\n2", template.render(Scope.new)
+ end
+
+ test "shorthand whole line syntax trim mode" do
+ template = Tilt.new('test.erb', :trim => '%') { "\n% if true\nhello\n%end\n" }
+ assert_equal "\nhello\n", template.render(Scope.new)
+ end
+end
+
+__END__
+<html>
+<body>
+ <h1>Hey <%= name %>!</h1>
+
+
+ <p><% fail %></p>
+</body>
+</html>
View
136 vendor/tilt-1.1/test/tilt_erubistemplate_test.rb
@@ -0,0 +1,136 @@
+require 'contest'
+require 'tilt'
+
+begin
+ require 'erubis'
+ class ErubisTemplateTest < Test::Unit::TestCase
+ test "registered for '.erubis' files" do
+ assert_equal Tilt::ErubisTemplate, Tilt['test.erubis']
+ assert_equal Tilt::ErubisTemplate, Tilt['test.html.erubis']
+ end
+
+ test "preparing and evaluating templates on #render" do
+ template = Tilt::ErubisTemplate.new { |t| "Hello World!" }
+ assert_equal "Hello World!", template.render
+ end
+
+ test "passing locals" do
+ template = Tilt::ErubisTemplate.new { 'Hey <%= name %>!' }
+ assert_equal "Hey Joe!", template.render(Object.new, :name => 'Joe')
+ end
+
+ test "evaluating in an object scope" do
+ template = Tilt::ErubisTemplate.new { 'Hey <%= @name %>!' }
+ scope = Object.new
+ scope.instance_variable_set :@name, 'Joe'
+ assert_equal "Hey Joe!", template.render(scope)
+ end
+
+ class MockOutputVariableScope
+ attr_accessor :exposed_buffer
+ end
+
+ test "exposing the buffer to the template by default" do
+ begin
+ Tilt::ErubisTemplate.default_output_variable = '@_out_buf'
+ template = Tilt::ErubisTemplate.new { '<% self.exposed_buffer = @_out_buf %>hey' }
+ scope = MockOutputVariableScope.new
+ template.render(scope)
+ assert_not_nil scope.exposed_buffer
+ assert_equal scope.exposed_buffer, 'hey'
+ ensure
+ Tilt::ErubisTemplate.default_output_variable = '_erbout'
+ end
+ end
+
+ test "passing a block for yield" do
+ template = Tilt::ErubisTemplate.new { 'Hey <%= yield %>!' }
+ assert_equal "Hey Joe!", template.render { 'Joe' }
+ end
+
+ test "backtrace file and line reporting without locals" do
+ data = File.read(__FILE__).split("\n__END__\n").last
+ fail unless data[0] == ?<
+ template = Tilt::ErubisTemplate.new('test.erubis', 11) { data }
+ begin
+ template.render
+ fail 'should have raised an exception'
+ rescue => boom
+ assert_kind_of NameError, boom
+ line = boom.backtrace.first
+ file, line, meth = line.split(":")
+ assert_equal 'test.erubis', file
+ assert_equal '13', line
+ end
+ end
+
+ test "backtrace file and line reporting with locals" do
+ data = File.read(__FILE__).split("\n__END__\n").last
+ fail unless data[0] == ?<
+ template = Tilt::ErubisTemplate.new('test.erubis', 1) { data }
+ begin
+ template.render(nil, :name => 'Joe', :foo => 'bar')
+ fail 'should have raised an exception'
+ rescue => boom
+ assert_kind_of RuntimeError, boom
+ line = boom.backtrace.first
+ file, line, meth = line.split(":")
+ assert_equal 'test.erubis', file
+ assert_equal '6', line
+ end
+ end
+
+ test "erubis template options" do
+ template = Tilt::ErubisTemplate.new(nil, :pattern => '\{% %\}') { 'Hey {%= @name %}!' }
+ scope = Object.new
+ scope.instance_variable_set :@name, 'Joe'
+ assert_equal "Hey Joe!", template.render(scope)
+ end
+
+ test "using an instance variable as the outvar" do
+ template = Tilt::ErubisTemplate.new(nil, :outvar => '@buf') { "<%= 1 + 1 %>" }
+ scope = Object.new
+ scope.instance_variable_set(:@buf, 'original value')
+ assert_equal '2', template.render(scope)
+ assert_equal 'original value', scope.instance_variable_get(:@buf)
+ end
+
+ test "using Erubis::EscapedEruby subclass via :engine_class option" do
+ template = Tilt::ErubisTemplate.new(nil, :engine_class => ::Erubis::EscapedEruby) { |t| %(<%= "<p>Hello World!</p>" %>) }
+ assert_equal "&lt;p&gt;Hello World!&lt;/p&gt;", template.render
+ end
+
+ test "using :escape_html => true option" do
+ template = Tilt::ErubisTemplate.new(nil, :escape_html => true) { |t| %(<%= "<p>Hello World!</p>" %>) }
+ assert_equal "&lt;p&gt;Hello World!&lt;/p&gt;", template.render
+ end
+
+ test "using :escape_html => false option" do
+ template = Tilt::ErubisTemplate.new(nil, :escape_html => false) { |t| %(<%= "<p>Hello World!</p>" %>) }
+ assert_equal "<p>Hello World!</p>", template.render
+ end
+
+ test "erubis default does not escape html" do
+ template = Tilt::ErubisTemplate.new { |t| %(<%= "<p>Hello World!</p>" %>) }
+ assert_equal "<p>Hello World!</p>", template.render
+ end
+
+ test "does not modify options argument" do
+ options_hash = {:escape_html => true}
+ template = Tilt::ErubisTemplate.new(nil, options_hash) { |t| "Hello World!" }
+ assert_equal({:escape_html => true}, options_hash)
+ end
+ end
+rescue LoadError => boom
+ warn "Tilt::ErubisTemplate (disabled)\n"
+end
+