[DRE-commits] [ruby-mustache] 01/09: Imported Upstream version 1.0.1
Sebastien Badia
sbadia-guest at moszumanska.debian.org
Fri Apr 10 14:57:52 UTC 2015
This is an automated email from the git hooks/post-receive script.
sbadia-guest pushed a commit to branch master
in repository ruby-mustache.
commit f4c52cf69d7546dde983ee47bdb55f42f3690d3e
Author: Sebastien Badia <seb at sebian.fr>
Date: Fri Apr 10 15:50:30 2015 +0200
Imported Upstream version 1.0.1
---
README.md | 160 ++++++++---------
Rakefile | 18 +-
bin/mustache | 30 ++--
lib/mustache.rb | 178 +++++++++----------
lib/mustache/context.rb | 112 +++++++-----
lib/mustache/context_miss.rb | 14 ++
lib/mustache/enumerable.rb | 3 +
lib/mustache/generator.rb | 63 +++----
lib/mustache/parser.rb | 193 +++++++++++++++------
lib/mustache/settings.rb | 3 +-
lib/mustache/sinatra.rb | 186 --------------------
lib/mustache/template.rb | 72 ++++++++
lib/mustache/utils.rb | 31 ++++
lib/mustache/version.rb | 2 +-
lib/rack/bug/panels/mustache_panel.rb | 81 ---------
.../panels/mustache_panel/mustache_extension.rb | 27 ---
lib/rack/bug/panels/mustache_panel/view.mustache | 46 -----
man/mustache.1 | 65 +++----
man/mustache.1.html | 167 +++++++++---------
man/mustache.1.ron | 8 +-
man/mustache.5 | 135 ++++++--------
man/mustache.5.html | 185 ++++++++++----------
man/mustache.5.ron | 22 +--
metadata.yml | 189 +++++++++++++-------
test/autoloading_test.rb | 5 +-
test/fixtures/comments.rb | 1 -
test/fixtures/complex_view.rb | 1 -
test/fixtures/crazy_recursive.rb | 1 -
test/fixtures/delimiters.rb | 1 -
test/fixtures/dot_notation.rb | 1 -
test/fixtures/double_section.rb | 1 -
test/fixtures/inverted_section.rb | 1 -
test/fixtures/lambda.rb | 1 -
test/fixtures/liberal.mustache | 1 +
test/fixtures/liberal.rb | 21 +++
test/fixtures/method_missing.rb | 1 -
test/fixtures/namespaced.rb | 1 -
test/fixtures/nested_objects.rb | 1 -
test/fixtures/partial_with_module.rb | 1 -
test/fixtures/passenger.rb | 1 -
test/fixtures/recursive.rb | 1 -
test/fixtures/simple.rb | 1 -
test/fixtures/simply_complicated.mustache | 25 +++
test/fixtures/template_partial.rb | 1 -
test/fixtures/unescaped.rb | 1 -
test/helper.rb | 5 +-
test/mustache_test.rb | 130 +++++++++++---
test/parser_test.rb | 33 +++-
test/partial_test.rb | 7 +-
test/spec_test.rb | 10 +-
test/template_test.rb | 38 +++-
51 files changed, 1170 insertions(+), 1112 deletions(-)
diff --git a/README.md b/README.md
index 2b9177b..6d7c661 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
-Mustache
-=========
+# Mustache
+
+[![Join the chat at https://gitter.im/mustache/mustache](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mustache/mustache?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Inspired by [ctemplate][1] and [et][2], Mustache is a
framework-agnostic way to render logic-free views.
@@ -8,11 +9,10 @@ As ctemplates says, "It emphasizes separating logic from presentation:
it is impossible to embed application logic in this template language."
For a list of implementations (other than Ruby) and tips, see
-<http://mustache.github.com/>.
+<http://mustache.github.io/>.
-Overview
---------
+## Overview
Think of Mustache as a replacement for your views. Instead of views
consisting of ERB or HAML with random helpers and arbitrary logic,
@@ -30,8 +30,7 @@ This strict separation makes it easier to write clean templates,
easier to test your views, and more fun to work on your app's front end.
-Why?
-----
+## Why?
I like writing Ruby. I like writing HTML. I like writing JavaScript.
@@ -39,8 +38,18 @@ I don't like writing ERB, Haml, Liquid, Django Templates, putting Ruby
in my HTML, or putting JavaScript in my HTML.
-Usage
------
+## Installation
+
+Install the gem locally with:
+
+ $ gem install mustache
+
+Or add it to your `gemspec`:
+
+ s.add_dependency "mustache", "~> 1.0"
+
+
+## Usage
Quick example:
@@ -94,29 +103,26 @@ Which returns the following:
Simple.
-Tag Types
----------
+## Tag Types
For a language-agnostic overview of Mustache's template syntax, see
the `mustache(5)` manpage or
-<http://mustache.github.com/mustache.5.html>.
+<http://mustache.github.io/mustache.5.html>.
-Escaping
---------
+## Escaping
Mustache does escape all values when using the standard double
-Mustache syntax. Characters which will be escaped: `& \ " < >`. To
-disable escaping, simply use tripple mustaches like
-`{{{unescaped_variable}}}`.
+Mustache syntax. Characters which will be escaped: `& \ " < >` (as
+well as `'` in Ruby `>= 2.0`). To disable escaping, simply use triple
+mustaches like `{{{unescaped_variable}}}`.
Example: Using `{{variable}}` inside a template for `5 > 2` will
result in `5 > 2`, where as the usage of `{{{variable}}}` will
result in `5 > 2`.
-Dict-Style Views
-----------------
+## Dict-Style Views
ctemplate and friends want you to hand a dictionary to the template
processor. Mustache supports a similar concept. Feel free to mix the
@@ -147,8 +153,7 @@ We can re-use the same object, too:
You have just won 100 bucks!
-Templates
----------
+## Templates
A word on templates. By default, a view will try to find its template
on disk by searching for an HTML file in the current directory that
@@ -190,8 +195,7 @@ Or set a different template for a single instance:
Whatever works.
-Views
------
+## Views
Mustache supports a bit of magic when it comes to views. If you're
authoring a plugin or extension for a web framework (Sinatra, Rails,
@@ -199,8 +203,7 @@ etc), check out the `view_namespace` and `view_path` settings on the
`Mustache` class. They will surely provide needed assistance.
-Helpers
--------
+## Helpers
What about global helpers? Maybe you have a nifty `gravatar` function
you want to use in all your views? No problem.
@@ -251,7 +254,7 @@ Then just include it:
Great, but what about that `@ssl` ivar in `gravatar_host`? There are
many ways we can go about setting it.
-Here's on example which illustrates a key feature of Mustache: you
+Here's an example which illustrates a key feature of Mustache: you
are free to use the `initialize` method just as you would in any
normal class.
@@ -278,30 +281,28 @@ Finally, our template might look like this:
</ul>
-Sinatra
--------
+## Integrations
-Mustache ships with Sinatra integration. Please see
-`lib/mustache/sinatra.rb` or
-<http://github.com/defunkt/mustache/blob/master/lib/mustache/sinatra.rb>
-for complete documentation.
+### Sinatra
+
+Sinatra integration is available with the
+[mustache-sinatra gem](https://github.com/mustache/mustache-sinatra).
An example Sinatra application is also provided:
-<http://github.com/defunkt/mustache-sinatra-example>
+<https://github.com/defunkt/mustache-sinatra-example>
If you are upgrading to Sinatra 1.0 and Mustache 0.9.0+ from Mustache
0.7.0 or lower, the settings have changed. But not that much.
-See [this diff](http://gist.github.com/345490) for what you need to
+See [this diff][diff] for what you need to
do. Basically, things are named properly now and all should be
contained in a hash set using `set :mustache, hash`.
-[Rack::Bug][4]
---------------
+### [Rack::Bug][4]
-Mustache also ships with a `Rack::Bug` panel. In your `config.ru` add
-the following code:
+Mustache also provides a `Rack::Bug` panel.
+First you have to install the `rack-bug-mustache_panel` gem, then in your `config.ru` add the following code:
require 'rack/bug/panels/mustache_panel'
use Rack::Bug::MustachePanel
@@ -311,65 +312,41 @@ Using Rails? Add this to your initializer or environment file:
require 'rack/bug/panels/mustache_panel'
config.middleware.use "Rack::Bug::MustachePanel"
-[![Rack::Bug](http://img.skitch.com/20091027-xyf4h1yxnefpp7usyddrcmc7dn.png)][5]
-
+![Rack::Bug][5]
-Vim
----
-Thanks to [Juvenn Woo](http://github.com/juvenn) for mustache.vim. It
-is included under the contrib/ directory.
+### Vim
-See <http://gist.github.com/323622> for installation instructions.
+vim-mustache-handlebars is available at [mustache/vim-mustache-handlebars][vim]
+### Emacs
-Emacs
------
+mustache-mode.el is available at [mustache/emacs][emacs]
-mustache-mode.el is included under the contrib/ directory for any
-Emacs users. Based on Google's tpl-mode for ctemplates, it adds
-support for Mustache's more lenient tag values and includes a few
-commands for your editing pleasure.
-See <http://gist.github.com/323619> for installation instructions.
+### TextMate
+[Mustache.tmbundle][tmbundle]
-TextMate
---------
+See <https://gist.github.com/defunkt/323624> for installation instructions.
-[Mustache.tmbundle](http://github.com/defunkt/Mustache.tmbundle)
-See <http://gist.github.com/323624> for installation instructions.
+### Command Line
-
-Command Line
-------------
-
-See `mustache(1)` man page or
-<http://mustache.github.com/mustache.1.html>
+See `mustache(1)` man page or <http://mustache.github.io/mustache.1.html>
for command line docs.
-Installation
-------------
-
-### [RubyGems](http://rubygems.org/)
-
- $ gem install mustache
+## Acknowledgements
-
-Acknowledgements
-----------------
-
-Thanks to [Tom Preston-Werner](http://github.com/mojombo) for showing
-me ctemplate and [Leah Culver](http://github.com/leah) for the name "Mustache."
+Thanks to [Tom Preston-Werner](https://github.com/mojombo) for showing
+me ctemplate and [Leah Culver](https://github.com/leah) for the name "Mustache."
Special thanks to [Magnus Holm](http://judofyr.net/) for all his
awesome work on Mustache's parser.
-Contributing
-------------
+## Contributing
Once you've made your great commits:
@@ -379,37 +356,36 @@ Once you've made your great commits:
4. Create an [Issue][is] with a link to your branch
5. That's it!
-You might want to checkout Resque's [Contributing][cb] wiki page for information
-on coding standards, new features, etc.
-
-Mailing List
-------------
+## Mailing List
To join the list simply send an email to <mustache at librelist.com>. This
will subscribe you and send you information about your subscription,
including unsubscribe information.
-The archive can be found at <http://librelist.com/browser/>.
+The archive can be found at <http://librelist.com/browser/mustache/>.
-Meta
-----
+## Meta
-* Code: `git clone git://github.com/defunkt/mustache.git`
-* Home: <http://mustache.github.com>
-* Bugs: <http://github.com/defunkt/mustache/issues>
+* Code: `git clone https://github.com/mustache/mustache.git`
+* Home: <http://mustache.github.io>
+* Bugs: <https://github.com/mustache/mustache/issues>
* List: <mustache at librelist.com>
-* Test: <http://runcoderun.com/defunkt/mustache>
* Gems: <http://rubygems.org/gems/mustache>
-You can also find us in `#{` on irc.freenode.net.
+You can also find us in #{ on [irc.freenode.net][irc].
+
[1]: http://code.google.com/p/google-ctemplate/
[2]: http://www.ivan.fomichev.name/2008/05/erlang-template-engine-prototype.html
[3]: http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html
-[4]: http://github.com/brynary/rack-bug/
+[4]: https://github.com/brynary/rack-bug/
[5]: http://img.skitch.com/20091027-n8pxwwx8r61tc318a15q1n6m14.png
-[cb]: http://wiki.github.com/defunkt/resque/contributing
[fk]: http://help.github.com/forking/
-[is]: http://github.com/defunkt/mustache/issues
+[is]: https://github.com/defunkt/mustache/issues
+[irc]: irc://irc.freenode.net/#{
+[vim]: https://github.com/mustache/vim-mustache-handlebars
+[emacs]: https://github.com/mustache/vim-mustache-handlebars
+[tmbundle]: https://github.com/defunkt/Mustache.tmbundle
+[diff]: https://gist.github.com/defunkt/345490
diff --git a/Rakefile b/Rakefile
index f4110d7..e0ba999 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,5 +1,5 @@
require 'rake/testtask'
-require 'rake/rdoctask'
+require 'rdoc/task'
#
# Helpers
@@ -16,18 +16,10 @@ end
task :default => :test
-if command? :turn
- desc "Run tests"
- task :test do
- suffix = "-n #{ENV['TEST']}" if ENV['TEST']
- sh "turn test/*.rb #{suffix}"
- end
-else
- Rake::TestTask.new do |t|
- t.libs << 'lib'
- t.pattern = 'test/**/*_test.rb'
- t.verbose = false
- end
+Rake::TestTask.new do |t|
+ t.libs << 'lib'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = false
end
diff --git a/bin/mustache b/bin/mustache
index 6a9b141..0141c69 100755
--- a/bin/mustache
+++ b/bin/mustache
@@ -49,7 +49,7 @@ class Mustache
opts.separator "Common Options:"
opts.on("-v", "--version", "Print the version") do |v|
- puts "Mustache v#{Mustache::Version}"
+ puts "Mustache v#{Mustache::VERSION}"
exit
end
@@ -64,20 +64,24 @@ class Mustache
opts.parse!(args)
end
- # Does the dirty work of reading files from STDIN and the command
- # line then processing them. The meat of this script, if you will.
- def self.process_files(input_stream)
- doc = input_stream.read
+ # Does the dirty work of reading files from the command line then
+ # processing them. The meat of this script, if you will.
+ def self.process_files(input_files)
+ doc = input_files.file.read
- if doc =~ /^(\s*---(.+)---\s*)/m
- yaml = $2.strip
- template = doc.sub($1, '')
+ yaml = nil
+ begin
+ yaml = YAML.load_stream(doc)
+ rescue
+ abort "Unable to parse yaml!"
+ end
- YAML.each_document(yaml) do |data|
- puts Mustache.render(template, data)
- end
- else
+ if yaml.nil?
puts Mustache.render(doc)
+ else
+ template = input_files.skip.file.read
+
+ puts Mustache.render template, yaml.compact.reduce(&:merge)
end
end
end
@@ -89,6 +93,6 @@ ARGV << '-h' if ARGV.empty? && $stdin.tty?
# Process options
Mustache::CLI.parse_options(ARGV) if $stdin.tty?
-# Still here - process ARGF
+# Still here - process rest of ARGF
Mustache::CLI.process_files(ARGF)
diff --git a/lib/mustache.rb b/lib/mustache.rb
index ea64fd4..03c705c 100644
--- a/lib/mustache.rb
+++ b/lib/mustache.rb
@@ -1,6 +1,8 @@
+require 'mustache/enumerable'
require 'mustache/template'
require 'mustache/context'
require 'mustache/settings'
+require 'mustache/utils'
# Mustache is the base class from which your Mustache subclasses
# should inherit (though it can be used on its own).
@@ -40,7 +42,7 @@ require 'mustache/settings'
#
# * template_file
#
-# You can tell Mustache exactly which template to us with this
+# You can tell Mustache exactly which template to use with this
# setting. It can be a relative or absolute path.
#
# * template
@@ -72,48 +74,46 @@ require 'mustache/settings'
#
class Mustache
- #
- # Public API
- #
-
# Instantiates an instance of this class and calls `render` with
# the passed args.
#
- # Returns a rendered String version of a template
+ # @return A rendered String version of a template.
def self.render(*args)
new.render(*args)
end
- class << self
- alias_method :to_html, :render
- alias_method :to_text, :render
- end
-
# Parses our fancy pants template file and returns normal file with
# all special {{tags}} and {{#sections}}replaced{{/sections}}.
#
- # data - A String template or a Hash context. If a Hash is given,
- # we'll try to figure out the template from the class.
- # ctx - A Hash context if `data` is a String template.
- #
# Examples
#
- # @view.render("Hi {{thing}}!", :thing => :world)
+ # @view.render("Hi {{thing}}!", :thing => :world)
#
- # View.template = "Hi {{thing}}!"
- # @view = View.new
- # @view.render(:thing => :world)
+ # View.template = "Hi {{thing}}!"
+ # @view = View.new
+ # @view.render(:thing => :world)
#
- # Returns a rendered String version of a template
+ # @param [String,Hash] data A String template or a Hash context.
+ # If a Hash is given, we'll try to figure
+ # out the template from the class.
+ # @param [Hash] ctx A Hash context if `data` is a String template.
+ #
+ # @return [String] Returns a rendered version of a template.
def render(data = template, ctx = {})
- if data.is_a? Hash
+ case data
+ when Hash
ctx = data
- tpl = templateify(template)
- elsif data.is_a? Symbol
+ when Symbol
self.template_name = data
- tpl = templateify(template)
+ end
+
+ tpl = case data
+ when Hash
+ templateify(template)
+ when Symbol
+ templateify(template)
else
- tpl = templateify(data)
+ templateify(data)
end
return tpl.render(context) if ctx == {}
@@ -126,15 +126,13 @@ class Mustache
end
end
- alias_method :to_html, :render
- alias_method :to_text, :render
-
# Context accessors.
#
- # view = Mustache.new
- # view[:name] = "Jon"
- # view.template = "Hi, {{name}}!"
- # view.render # => "Hi, Jon!"
+ # Example:
+ # view = Mustache.new
+ # view[:name] = "Jon"
+ # view.template = "Hi, {{name}}!"
+ # view.render # => "Hi, Jon!"
def [](key)
context[key.to_sym]
end
@@ -168,33 +166,48 @@ class Mustache
#
# Call `render` if you need to process it.
def self.partial(name)
- File.read("#{template_path}/#{name}.#{template_extension}")
+ self.new.partial(name)
end
# Override this in your subclass if you want to do fun things like
# reading templates from a database. It will be rendered by the
# context, so all you need to do is return a string.
def partial(name)
- self.class.partial(name)
+ path = "#{template_path}/#{name}.#{template_extension}"
+
+ begin
+ File.read(path)
+ rescue
+ raise if raise_on_context_miss?
+ ""
+ end
end
# Override this to provide custom escaping.
#
- # class PersonView < Mustache
- # def escapeHTML(str)
- # my_html_escape_method(str)
+ # Example:
+ #
+ # class PersonView < Mustache
+ # def escapeHTML(str)
+ # my_html_escape_method(str)
+ # end
# end
- # end
#
- # Returns a String
+ # @param [String] str String to escape.
+ #
+ # @return [String] Escaped HTML.
def escapeHTML(str)
CGI.escapeHTML(str)
end
+ # Has this instance or its class already compiled a template?
+ def compiled?
+ (@template && @template.is_a?(Template)) || self.class.compiled?
+ end
+
+
+ private
- #
- # Private API
- #
# When given a symbol or string representing a class, will try to produce an
# appropriate view class.
@@ -202,89 +215,60 @@ class Mustache
# Mustache.view_namespace = Hurl::Views
# Mustache.view_class(:Partial) # => Hurl::Views::Partial
def self.view_class(name)
- if name != classify(name.to_s)
- name = classify(name.to_s)
- end
+ name = classify(name.to_s)
# Emptiness begets emptiness.
- if name.to_s == ''
- return Mustache
- end
+ return Mustache if name.to_s.empty?
- file_name = underscore(name)
name = "#{view_namespace}::#{name}"
+ const = rescued_const_get(name)
- if const = const_get!(name)
- const
- elsif File.exists?(file = "#{view_path}/#{file_name}.rb")
- require "#{file}".chomp('.rb')
- const_get!(name) || Mustache
- else
- Mustache
- end
+ return const if const
+
+ const_from_file(name)
end
- # Supercharged version of Module#const_get.
- #
- # Always searches under Object and can find constants by their full name,
- # e.g. Mustache::Views::Index
- #
- # name - The full constant name to find.
- #
- # Returns the constant if found
- # Returns nil if nothing is found
- def self.const_get!(name)
- name.split('::').inject(Object) do |klass, name|
- klass.const_get(name)
- end
+ def self.rescued_const_get name
+ const_get(name, true) || Mustache
rescue NameError
nil
end
+ def self.const_from_file name
+ file_name = underscore(name)
+ file_path = "#{view_path}/#{file_name}.rb"
+
+ return Mustache unless File.exists?(file_path)
+
+ require file_path.chomp('.rb')
+ rescued_const_get(name)
+ end
+
# Has this template already been compiled? Compilation is somewhat
# expensive so it may be useful to check this before attempting it.
def self.compiled?
@template.is_a? Template
end
- # Has this instance or its class already compiled a template?
- def compiled?
- (@template && @template.is_a?(Template)) || self.class.compiled?
- end
# template_partial => TemplatePartial
# template/partial => Template::Partial
def self.classify(underscored)
- underscored.split('/').map do |namespace|
- namespace.split(/[-_]/).map do |part|
- part[0] = part[0].chr.upcase; part
- end.join
- end.join('::')
+ Mustache::Utils::String.new(underscored).classify
end
# TemplatePartial => template_partial
# Template::Partial => template/partial
# Takes a string but defaults to using the current class' name.
def self.underscore(classified = name)
- classified = name if classified.to_s.empty?
classified = superclass.name if classified.to_s.empty?
- string = classified.dup.split("#{view_namespace}::").last
-
- string.split('::').map do |part|
- part[0] = part[0].chr.downcase
- part.gsub(/[A-Z]/) { |s| "_#{s.downcase}"}
- end.join('/')
+ Mustache::Utils::String.new(classified).underscore(view_namespace)
end
- # Turns a string into a Mustache::Template. If passed a Template,
- # returns it.
+ # @param [Template,String] obj Turns `obj` into a template
def self.templateify(obj)
- if obj.is_a?(Template)
- obj
- else
- Template.new(obj.to_s)
- end
+ obj.is_a?(Template) ? obj : Template.new(obj)
end
def templateify(obj)
@@ -294,10 +278,12 @@ class Mustache
# Return the value of the configuration setting on the superclass, or return
# the default.
#
- # attr_name - Symbol name of the attribute. It should match the instance variable.
- # default - Default value to use if the superclass does not respond.
+ # @param [Symbol] attr_name Name of the attribute. It should match
+ # the instance variable.
+ # @param [Object] default Default value to use if the superclass does
+ # not respond.
#
- # Returns the inherited or default configuration setting.
+ # @return Inherited or default configuration setting.
def self.inheritable_config_for(attr_name, default)
superclass.respond_to?(attr_name) ? superclass.send(attr_name) : default
end
diff --git a/lib/mustache/context.rb b/lib/mustache/context.rb
index 977098c..06efbfc 100644
--- a/lib/mustache/context.rb
+++ b/lib/mustache/context.rb
@@ -1,18 +1,16 @@
+require 'mustache/context_miss'
+
class Mustache
- # A ContextMiss is raised whenever a tag's target can not be found
- # in the current context if `Mustache#raise_on_context_miss?` is
- # set to true.
- #
- # For example, if your View class does not respond to `music` but
- # your template contains a `{{music}}` tag this exception will be raised.
- #
- # By default it is not raised. See Mustache.raise_on_context_miss.
- class ContextMiss < RuntimeError; end
# A Context represents the context which a Mustache template is
# executed within. All Mustache tags reference keys in the Context.
+ #
class Context
- # Expect to be passed an instance of `Mustache`.
+
+ # Initializes a Mustache::Context.
+ #
+ # @param [Mustache] mustache A Mustache instance.
+ #
def initialize(mustache)
@stack = [mustache]
end
@@ -23,6 +21,7 @@ class Mustache
# If the Mustache view handling the rendering (e.g. the view
# representing your profile page or some other template) responds
# to `partial`, we call it and render the result.
+ #
def partial(name, indentation = '')
# Look for the first Mustache in the stack.
mustache = mustache_in_stack
@@ -31,37 +30,50 @@ class Mustache
part = mustache.partial(name).to_s.gsub(/^/, indentation)
# Call the Mustache's `partial` method and render the result.
- result = mustache.render(part, self)
+ mustache.render(part, self)
end
- # Find the first Mustache in the stack. If we're being rendered
- # inside a Mustache object as a context, we'll use that one.
+ # Find the first Mustache in the stack.
+ #
+ # If we're being rendered inside a Mustache object as a context,
+ # we'll use that one.
+ #
+ # @return [Mustache] First Mustache in the stack.
+ #
def mustache_in_stack
- @stack.detect { |frame| frame.is_a?(Mustache) }
+ @mustache_in_stack ||= @stack.find { |frame| frame.is_a?(Mustache) }
end
# Allows customization of how Mustache escapes things.
#
- # Returns a String.
+ # @param [String] str String to escape.
+ #
+ # @return [String] Escaped HTML string.
+ #
def escapeHTML(str)
mustache_in_stack.escapeHTML(str)
end
# Adds a new object to the context's internal stack.
#
- # Returns the Context.
- def push(new)
- @stack.unshift(new)
+ # @param [Object] new_obj Object to be added to the internal stack.
+ #
+ # @return [Context] Returns the Context.
+ #
+ def push(new_obj)
+ @stack.unshift(new_obj)
+ @mustache_in_stack = nil
self
end
- alias_method :update, :push
# Removes the most recently added object from the context's
# internal stack.
#
- # Returns the Context.
+ # @return [Context] Returns the Context.
+ #
def pop
@stack.shift
+ @mustache_in_stack = nil
self
end
@@ -80,7 +92,7 @@ class Mustache
# Do we know about a particular key? In other words, will calling
# `context[key]` give us a result that was set. Basically.
def has_key?(key)
- !!fetch(key)
+ !!fetch(key, false)
rescue ContextMiss
false
end
@@ -97,9 +109,7 @@ class Mustache
next if frame == self
value = find(frame, name, :__missing)
- if value != :__missing
- return value
- end
+ return value if value != :__missing
end
if default == :__raise || mustache_in_stack.raise_on_context_miss?
@@ -114,29 +124,41 @@ class Mustache
# If it's an object that responds to the key as a method call,
# invokes that method. You get the idea.
#
- # obj - The object to perform the lookup on.
- # key - The key whose value you want.
- # default - An optional default value, to return if the
- # key is not found.
+ # @param [Object] obj The object to perform the lookup on.
+ # @param [String,Symbol] key The key whose value you want
+ # @param [Object] default An optional default value, to return if the key is not found.
+ #
+ # @return [Object] The value of key in object if it is found, and default otherwise.
#
- # Returns the value of key in obj if it is found and default otherwise.
def find(obj, key, default = nil)
- hash = obj.respond_to?(:has_key?)
-
- if hash && obj.has_key?(key)
- obj[key]
- elsif hash && obj.has_key?(key.to_s)
- obj[key.to_s]
- elsif !hash && obj.respond_to?(key)
- meth = obj.method(key) rescue proc { obj.send(key) }
- if meth.arity == 1
- meth.to_proc
- else
- meth[]
- end
- else
- default
- end
+ return find_in_hash(obj.to_hash, key, default) if obj.respond_to?(:to_hash)
+
+ key = to_tag(key)
+ return default unless obj.respond_to?(key)
+
+ meth = obj.method(key) rescue proc { obj.send(key) }
+ meth.arity == 1 ? meth.to_proc : meth.call
+ end
+
+ def current
+ @stack.first
+ end
+
+
+ private
+
+
+ # If a class, we need to find tags (methods) per Parser::ALLOWED_CONTENT.
+ def to_tag key
+ key.to_s.include?('-') ? key.to_s.tr('-', '_') : key
+ end
+
+ # Fetches a hash key if it exists, or returns the given default.
+ def find_in_hash(obj, key, default)
+ return obj[key] if obj.has_key?(key)
+ return obj[key.to_s] if obj.has_key?(key.to_s)
+
+ obj.fetch(key, default)
end
end
end
diff --git a/lib/mustache/context_miss.rb b/lib/mustache/context_miss.rb
new file mode 100644
index 0000000..c092c9a
--- /dev/null
+++ b/lib/mustache/context_miss.rb
@@ -0,0 +1,14 @@
+class Mustache
+
+ # A ContextMiss is raised whenever a tag's target can not be found
+ # in the current context if `Mustache#raise_on_context_miss?` is
+ # set to true.
+ #
+ # For example, if your View class does not respond to `music` but
+ # your template contains a `{{music}}` tag this exception will be raised.
+ #
+ # By default it is not raised. See Mustache.raise_on_context_miss.
+ #
+ class ContextMiss < RuntimeError; end
+
+end
diff --git a/lib/mustache/enumerable.rb b/lib/mustache/enumerable.rb
new file mode 100644
index 0000000..5be1930
--- /dev/null
+++ b/lib/mustache/enumerable.rb
@@ -0,0 +1,3 @@
+class Mustache
+ Enumerable = Module.new
+end
diff --git a/lib/mustache/generator.rb b/lib/mustache/generator.rb
index 43554ef..a23eb70 100644
--- a/lib/mustache/generator.rb
+++ b/lib/mustache/generator.rb
@@ -37,6 +37,10 @@ class Mustache
"\"#{compile!(exp)}\""
end
+
+ private
+
+
# Given an array of tokens, converts them into Ruby code. In
# particular there are three types of expressions we are concerned
# with:
@@ -64,21 +68,26 @@ class Mustache
#
# [:multi,
# [:static, "Hello "],
- # [:mustache, :etag, "name"],
+ # [:mustache, :etag,
+ # [:mustache, :fetch, ["name"]]],
# [:static, "\nYou have just won $"],
- # [:mustache, :etag, "value"],
- # [:static, "!\n"],
- # [:mustache,
- # :section,
- # "in_ca",
- # [:multi,
- # [:static, "Well, $"],
- # [:mustache, :etag, "taxed_value"],
- # [:static, ", after taxes.\n"]]]]
+ # [:mustache, :etag,
+ # [:mustache, :fetch, ["value"]]],
+ # [:static, "!\n"],
+ # [:mustache,
+ # :section,
+ # [:mustache, :fetch, ["in_ca"]],
+ # [:multi,
+ # [:static, "Well, $"],
+ # [:mustache, :etag,
+ # [:mustache, :fetch, ["taxed_value"]]],
+ # [:static, ", after taxes.\n"]],
+ # "Well, ${{taxed_value}}, after taxes.\n",
+ # ["{{", "}}"]]]
def compile!(exp)
case exp.first
when :multi
- exp[1..-1].map { |e| compile!(e) }.join
+ exp[1..-1].reduce("") { |sum, e| sum << compile!(e) }
when :static
str(exp[1])
when :mustache
@@ -90,7 +99,7 @@ class Mustache
# Callback fired when the compiler finds a section token. We're
# passed the section name and the array of tokens.
- def on_section(name, content, raw, delims)
+ def on_section(name, offset, content, raw, delims)
# Convert the tokenized content of this section into a Ruby
# string we can use.
code = compile(content)
@@ -111,7 +120,7 @@ class Mustache
t.render(ctx.dup)
else
# Shortcut when passed non-array
- v = [v] unless v.is_a?(Array) || defined?(Enumerator) && v.is_a?(Enumerator)
+ v = [v] unless v.is_a?(Array) || v.is_a?(Mustache::Enumerable) || defined?(Enumerator) && v.is_a?(Enumerator)
v.map { |h| ctx.push(h); r = #{code}; ctx.pop; r }.join
end
@@ -121,7 +130,7 @@ class Mustache
# Fired when we find an inverted section. Just like `on_section`,
# we're passed the inverted section name and the array of tokens.
- def on_inverted_section(name, content, raw, _)
+ def on_inverted_section(name, offset, content, raw, delims)
# Convert the tokenized content of this section into a Ruby
# string we can use.
code = compile(content)
@@ -139,12 +148,12 @@ class Mustache
# Fired when the compiler finds a partial. We want to return code
# which calls a partial at runtime instead of expanding and
# including the partial's body to allow for recursive partials.
- def on_partial(name, indentation)
+ def on_partial(name, offset, indentation)
ev("ctx.partial(#{name.to_sym.inspect}, #{indentation.inspect})")
end
# An unescaped tag.
- def on_utag(name)
+ def on_utag(name, offset)
ev(<<-compiled)
v = #{compile!(name)}
if v.is_a?(Proc)
@@ -155,7 +164,7 @@ class Mustache
end
# An escaped tag.
- def on_etag(name)
+ def on_etag(name, offset)
ev(<<-compiled)
v = #{compile!(name)}
if v.is_a?(Proc)
@@ -166,20 +175,16 @@ class Mustache
end
def on_fetch(names)
+ return "ctx.current" if names.empty?
+
names = names.map { |n| n.to_sym }
- if names.length == 0
- "ctx[:to_s]"
- elsif names.length == 1
- "ctx[#{names.first.to_sym.inspect}]"
- else
- initial, *rest = names
- <<-compiled
- #{rest.inspect}.inject(ctx[#{initial.inspect}]) { |value, key|
- value && ctx.find(value, key)
- }
- compiled
- end
+ initial, *rest = names
+ <<-compiled
+ #{rest.inspect}.reduce(ctx[#{initial.inspect}]) { |value, key|
+ value && ctx.find(value, key)
+ }
+ compiled
end
# An interpolation-friendly version of a string, for use within a
diff --git a/lib/mustache/parser.rb b/lib/mustache/parser.rb
index 705419b..8462e1e 100644
--- a/lib/mustache/parser.rb
+++ b/lib/mustache/parser.rb
@@ -44,19 +44,46 @@ EOF
end
end
+ # The sigil types which are valid after an opening `{{`
+ VALID_TYPES = [ '#', '^', '/', '=', '!', '<', '>', '&', '{' ].map &:freeze
+
+ def self.valid_types
+ @valid_types ||= Regexp.new(VALID_TYPES.map { |t| Regexp.escape(t) }.join('|') )
+ end
+
+ # Add a supported sigil type (with optional aliases) to the Parser.
+ #
+ # Requires a block, which will be sent the following parameters:
+ #
+ # * content - The raw content of the tag
+ # * fetch- A mustache context fetch expression for the content
+ # * padding - Indentation whitespace from the currently-parsed line
+ # * pre_match_position - Location of the scanner before a match was made
+ #
+ # The provided block will be evaluated against the current instance of
+ # Parser, and may append to the Parser's @result as needed.
+ def self.add_type(*types, &block)
+ types = types.map(&:to_s)
+ type, *aliases = types
+ method_name = "scan_tag_#{type}".to_sym
+ define_method(method_name, &block)
+ aliases.each { |a| alias_method "scan_tag_#{a}", method_name }
+ types.each { |t| VALID_TYPES << t unless VALID_TYPES.include?(t) }
+ @valid_types = nil
+ end
+
# After these types of tags, all whitespace until the end of the line will
# be skipped if they are the first (and only) non-whitespace content on
# the line.
- SKIP_WHITESPACE = [ '#', '^', '/', '<', '>', '=', '!' ]
+ SKIP_WHITESPACE = [ '#', '^', '/', '<', '>', '=', '!' ].map(&:freeze)
# The content allowed in a tag name.
ALLOWED_CONTENT = /(\w|[?!\/.-])*/
# These types of tags allow any content,
# the rest only allow ALLOWED_CONTENT.
- ANY_CONTENT = [ '!', '=' ]
+ ANY_CONTENT = [ '!', '=' ].map(&:freeze)
- attr_reader :scanner, :result
attr_writer :otag, :ctag
# Accepts an options hash which does nothing but may be used in
@@ -77,11 +104,11 @@ EOF
# Given a string template, returns an array of tokens.
def compile(template)
+ @encoding = nil
+
if template.respond_to?(:encoding)
@encoding = template.encoding
template = template.dup.force_encoding("BINARY")
- else
- @encoding = nil
end
# Keeps information about opened sections.
@@ -96,13 +123,34 @@ EOF
if !@sections.empty?
# We have parsed the whole file, but there's still opened sections.
- type, pos, result = @sections.pop
+ type, pos, _ = @sections.pop
error "Unclosed section #{type.inspect}", pos
end
@result
end
+
+ private
+
+
+ def content_tags type, current_ctag
+ if ANY_CONTENT.include?(type)
+ r = /\s*#{regexp(type)}?#{regexp(current_ctag)}/
+ scan_until_exclusive(r)
+ else
+ @scanner.scan(ALLOWED_CONTENT)
+ end
+ end
+
+ def dispatch_based_on_type type, content, fetch, padding, pre_match_position
+ send("scan_tag_#{type}", content, fetch, padding, pre_match_position)
+ end
+
+ def find_closing_tag scanner, current_ctag
+ error "Unclosed tag" unless scanner.scan(regexp(current_ctag))
+ end
+
# Find {{mustaches}} and add them to the @result array.
def scan_tags
# Scan until we hit an opening delimiter.
@@ -124,17 +172,12 @@ EOF
# Since {{= rewrites ctag, we store the ctag which should be used
# when parsing this specific tag.
current_ctag = self.ctag
- type = @scanner.scan(/#|\^|\/|=|!|<|>|&|\{/)
+ type = @scanner.scan(self.class.valid_types)
@scanner.skip(/\s*/)
# ANY_CONTENT tags allow any character inside of them, while
# other tags (such as variables) are more strict.
- if ANY_CONTENT.include?(type)
- r = /\s*#{regexp(type)}?#{regexp(current_ctag)}/
- content = scan_until_exclusive(r)
- else
- content = @scanner.scan(ALLOWED_CONTENT)
- end
+ content = content_tags(type, current_ctag)
# We found {{ but we can't figure out what's going on inside.
error "Illegal content in tag" if content.empty?
@@ -142,52 +185,18 @@ EOF
fetch = [:mustache, :fetch, content.split('.')]
prev = @result
- # Based on the sigil, do what needs to be done.
- case type
- when '#'
- block = [:multi]
- @result << [:mustache, :section, fetch, block]
- @sections << [content, position, @result]
- @result = block
- when '^'
- block = [:multi]
- @result << [:mustache, :inverted_section, fetch, block]
- @sections << [content, position, @result]
- @result = block
- when '/'
- section, pos, result = @sections.pop
- raw = @scanner.pre_match[pos[3]...pre_match_position] + padding
- (@result = result).last << raw << [self.otag, self.ctag]
-
- if section.nil?
- error "Closing unopened #{content.inspect}"
- elsif section != content
- error "Unclosed section #{section.inspect}", pos
- end
- when '!'
- # ignore comments
- when '='
- self.otag, self.ctag = content.split(' ', 2)
- when '>', '<'
- @result << [:mustache, :partial, content, padding]
- when '{', '&'
- # The closing } in unescaped tags is just a hack for
- # aesthetics.
- type = "}" if type == "{"
- @result << [:mustache, :utag, fetch]
- else
- @result << [:mustache, :etag, fetch]
- end
+ dispatch_based_on_type(type, content, fetch, padding, pre_match_position)
+
+ # The closing } in unescaped tags is just a hack for
+ # aesthetics.
+ type = "}" if type == "{"
# Skip whitespace and any balancing sigils after the content
# inside this tag.
@scanner.skip(/\s+/)
@scanner.skip(regexp(type)) if type
- # Try to find the closing tag.
- unless close = @scanner.scan(regexp(current_ctag))
- error "Unclosed tag"
- end
+ find_closing_tag(@scanner, current_ctag)
# If this tag was the only non-whitespace content on this line, strip
# the remaining whitespace. If not, but we've been hanging on to padding
@@ -234,6 +243,10 @@ EOF
end
end
+ def offset
+ position[0, 2]
+ end
+
# Returns [lineno, column, line]
def position
# The rest of the current line
@@ -259,5 +272,79 @@ EOF
def error(message, pos = position)
raise SyntaxError.new(message, pos)
end
+
+
+ #
+ # Scan tags
+ #
+ # These methods are called in `scan_tags`. Because they contain nonstandard
+ # characters in their method names, they are aliased to
+ # better named methods.
+ #
+
+
+ # This function handles the cases where the scanned tag does not have
+ # a type.
+ def scan_tag_ content, fetch, padding, pre_match_position
+ @result << [:mustache, :etag, fetch, offset]
+ end
+
+
+ def scan_tag_block content, fetch, padding, pre_match_position
+ block = [:multi]
+ @result << [:mustache, :section, fetch, offset, block]
+ @sections << [content, position, @result]
+ @result = block
+ end
+ alias_method :'scan_tag_#', :scan_tag_block
+
+
+ def scan_tag_inverted content, fetch, padding, pre_match_position
+ block = [:multi]
+ @result << [:mustache, :inverted_section, fetch, offset, block]
+ @sections << [content, position, @result]
+ @result = block
+ end
+ alias_method :'scan_tag_^', :scan_tag_inverted
+
+
+ def scan_tag_close content, fetch, padding, pre_match_position
+ section, pos, result = @sections.pop
+ raw = @scanner.pre_match[pos[3]...pre_match_position] + padding
+ (@result = result).last << raw << [self.otag, self.ctag]
+
+ if section.nil?
+ error "Closing unopened #{content.inspect}"
+ elsif section != content
+ error "Unclosed section #{section.inspect}", pos
+ end
+ end
+ alias_method :'scan_tag_/', :scan_tag_close
+
+
+ def scan_tag_comment content, fetch, padding, pre_match_position
+ end
+ alias_method :'scan_tag_!', :scan_tag_comment
+
+
+ def scan_tag_delimiter content, fetch, padding, pre_match_position
+ self.otag, self.ctag = content.split(' ', 2)
+ end
+ alias_method :'scan_tag_=', :scan_tag_delimiter
+
+
+ def scan_tag_open_partial content, fetch, padding, pre_match_position
+ @result << [:mustache, :partial, content, offset, padding]
+ end
+ alias_method :'scan_tag_<', :scan_tag_open_partial
+ alias_method :'scan_tag_>', :scan_tag_open_partial
+
+
+ def scan_tag_unescaped content, fetch, padding, pre_match_position
+ @result << [:mustache, :utag, fetch, offset]
+ end
+ alias_method :'scan_tag_{', :'scan_tag_unescaped'
+ alias_method :'scan_tag_&', :'scan_tag_unescaped'
+
end
end
diff --git a/lib/mustache/settings.rb b/lib/mustache/settings.rb
index 21d32f9..883a766 100644
--- a/lib/mustache/settings.rb
+++ b/lib/mustache/settings.rb
@@ -24,6 +24,7 @@ class Mustache
def template_path
@template_path ||= self.class.template_path
end
+ alias_method :path, :template_path
def template_path=(path)
@template_path = File.expand_path(path)
@@ -34,13 +35,11 @@ class Mustache
def self.path
template_path
end
- alias_method :path, :template_path
# Alias for `template_path`
def self.path=(path)
self.template_path = path
end
- alias_method :path=, :template_path=
#
diff --git a/lib/mustache/sinatra.rb b/lib/mustache/sinatra.rb
deleted file mode 100644
index 05e0705..0000000
--- a/lib/mustache/sinatra.rb
+++ /dev/null
@@ -1,186 +0,0 @@
-require 'sinatra/base'
-require 'mustache'
-
-class Mustache
- # Support for Mustache in your Sinatra app.
- #
- # require 'mustache/sinatra'
- #
- # class Hurl < Sinatra::Base
- # register Mustache::Sinatra
- #
- # set :mustache, {
- # # Should be the path to your .mustache template files.
- # :templates => "path/to/mustache/templates",
- #
- # # Should be the path to your .rb Mustache view files.
- # :views => "path/to/mustache/views",
- #
- # # This tells Mustache where to look for the Views module,
- # # under which your View classes should live. By default it's
- # # the class of your app - in this case `Hurl`. That is, for an :index
- # # view Mustache will expect Hurl::Views::Index by default.
- # # If our Sinatra::Base subclass was instead Hurl::App,
- # # we'd want to do `set :namespace, Hurl::App`
- # :namespace => Hurl
- # }
- #
- # get '/stats' do
- # mustache :stats
- # end
- # end
- #
- # As noted above, Mustache will look for `Hurl::Views::Index` when
- # `mustache :index` is called.
- #
- # If no `Views::Stats` class exists Mustache will render the template
- # file directly.
- #
- # You can indeed use layouts with this library. Where you'd normally
- # <%= yield %> you instead {{{yield}}} - the body of the subview is
- # set to the `yield` variable and made available to you.
- module Sinatra
- module Helpers
- # Call this in your Sinatra routes.
- def mustache(template, options={}, locals={})
- # Locals can be passed as options under the :locals key.
- locals.update(options.delete(:locals) || {})
-
- # Grab any user-defined settings.
- if settings.respond_to?(:mustache)
- options = settings.send(:mustache).merge(options)
- end
-
- # If they aren't explicitly disabling layouts, try to find
- # one.
- if options[:layout] != false
- # Let the user pass in a layout name.
- layout_name = options[:layout]
-
- # If all they said was `true` (or nothing), default to :layout.
- layout_name = :layout if layout_name == true || !layout_name
-
- # If they passed a layout name use that.
- layout = mustache_class(layout_name, options)
-
- # If it's just an anonymous subclass then don't bother, otherwise
- # give us a layout instance.
- if layout.name && layout.name.empty?
- layout = nil
- else
- layout = layout.new
- end
- end
-
- # Find and cache the view class we want. This ensures the
- # compiled template is cached, too - no looking up and
- # compiling templates on each page load.
- klass = mustache_class(template, options)
-
- # Does the view subclass the layout? If so we'll use the
- # view to render the layout so you can override layout
- # methods in your view - tricky.
- view_subclasses_layout = klass < layout.class if layout
-
- # Create a new instance for playing with.
- instance = klass.new
-
- # Copy instance variables set in Sinatra to the view
- instance_variables.each do |name|
- instance.instance_variable_set(name, instance_variable_get(name))
- end
-
- # Render with locals.
- rendered = instance.render(instance.template, locals)
-
- # Now render the layout with the view we just rendered, if we
- # need to.
- if layout && view_subclasses_layout
- rendered = instance.render(layout.template, :yield => rendered)
- elsif layout
- rendered = layout.render(layout.template, :yield => rendered)
- end
-
- # That's it.
- rendered
- end
-
- # Returns a View class for a given template name.
- def mustache_class(template, options = {})
- @template_cache.fetch(:mustache, template) do
- compile_mustache(template, options)
- end
- end
-
- # Given a view name and settings, finds and prepares an
- # appropriate view class for this view.
- def compile_mustache(view, options = {})
- options[:templates] ||= settings.views if settings.respond_to?(:views)
- options[:namespace] ||= self.class
-
- unless options[:namespace].to_s.include? 'Views'
- options[:namespace] = options[:namespace].const_get(:Views)
- end
-
- factory = Class.new(Mustache) do
- self.view_namespace = options[:namespace]
- self.view_path = options[:views]
- end
-
- # If we were handed :"positions.atom" or some such as the
- # template name, we need to remember the extension.
- if view.to_s.include?('.')
- view, ext = view.to_s.split('.')
- end
-
- # Try to find the view class for a given view, e.g.
- # :view => Hurl::Views::Index.
- klass = factory.view_class(view)
- klass.view_namespace = options[:namespace]
- klass.view_path = options[:views]
-
- # If there is no view class, issue a warning and use the one
- # we just generated to cache the compiled template.
- if klass == Mustache
- warn "No view class found for #{view} in #{factory.view_path}"
- klass = factory
-
- # If this is a generic view class make sure we set the
- # template name as it was given. That is, an anonymous
- # subclass of Mustache won't know how to find the
- # "index.mustache" template unless we tell it to.
- klass.template_name = view.to_s
- elsif ext
- # We got an ext (like "atom"), so look for an "Atom" class
- # under the current View's namespace.
- #
- # So if our template was "positions.atom", try to find
- # Positions::Atom.
- if klass.const_defined?(ext_class = ext.capitalize)
- # Found Positions::Atom - set it
- klass = klass.const_get(ext_class)
- else
- # Didn't find Positions::Atom - create it by creating an
- # anonymous subclass of Positions and setting that to
- # Positions::Atom.
- new_class = Class.new(klass)
- new_class.template_name = "#{view}.#{ext}"
- klass.const_set(ext_class, new_class)
- klass = new_class
- end
- end
-
- # Set the template path and return our class.
- klass.template_path = options[:templates] if options[:templates]
- klass
- end
- end
-
- # Called when you `register Mustache::Sinatra` in your Sinatra app.
- def self.registered(app)
- app.helpers Mustache::Sinatra::Helpers
- end
- end
-end
-
-Sinatra.register Mustache::Sinatra
diff --git a/lib/mustache/template.rb b/lib/mustache/template.rb
index 837cff5..e3b1119 100644
--- a/lib/mustache/template.rb
+++ b/lib/mustache/template.rb
@@ -51,8 +51,80 @@ class Mustache
alias_method :to_s, :compile
# Returns an array of tokens for a given template.
+ #
+ # @return [Array] Array of tokens.
+ #
def tokens(src = @source)
Parser.new.compile(src)
end
+
+ # Returns an array of tags.
+ #
+ # Tags that belong to sections will be of the form `section1.tag`.
+ #
+ # @return [Array] Returns an array of tags.
+ #
+ def tags
+ Template.recursor(tokens, []) do |token, section|
+ if [:etag, :utag].include?(token[1])
+ [ new_token=nil, new_section=nil, result=((section + [token[2][2][0]]).join('.')), stop=true ]
+ elsif [:section, :inverted_section].include?(token[1])
+ [ new_token=token[4], new_section=(section + [token[2][2][0]]), result=nil, stop=false ]
+ else
+ [ new_token=token, new_section=section, result=nil, stop=false ]
+ end
+ end.flatten.reject(&:nil?).uniq
+ end
+
+ # Returns an array of sections.
+ #
+ # Sections that belong to other sections will be of the form `section1.childsection`
+ #
+ # @return [Array] Returns an array of section.
+ #
+ def sections
+ Template.recursor(tokens, []) do |token, section|
+ if [:section, :inverted_section].include?(token[1])
+ new_section=(section + [token[2][2][0]])
+ [ new_token=token[4], new_section, result=new_section.join('.'), stop=false ]
+ else
+ [ new_token=token, new_section=section, result=nil, stop=false ]
+ end
+ end.flatten.reject(&:nil?).uniq
+ end
+
+ # Returns an array of partials.
+ #
+ # Partials that belong to sections are included, but the section name is not preserved
+ #
+ # @return [Array] Returns an array of partials.
+ #
+ def partials
+ Template.recursor(tokens, []) do |token, section|
+ if token[1] == :partial
+ [ new_token=token, new_section=section, result=token[2], stop=true ]
+ else
+ [ new_token=token, new_section=section, result=nil, stop=false ]
+ end
+ end.flatten.reject(&:nil?).uniq
+ end
+
+
+ private
+
+
+ # Simple recursive iterator for tokens
+ def self.recursor(toks, section, &block)
+ toks.map do |token|
+ next unless token.is_a? Array
+
+ if token.first == :mustache
+ new_token, new_section, result, stop = yield(token, section)
+ [ result ] + ( stop ? [] : recursor(new_token, new_section, &block))
+ else
+ recursor(token, section, &block)
+ end
+ end
+ end
end
end
diff --git a/lib/mustache/utils.rb b/lib/mustache/utils.rb
new file mode 100644
index 0000000..782797e
--- /dev/null
+++ b/lib/mustache/utils.rb
@@ -0,0 +1,31 @@
+class Mustache
+ module Utils
+ class String
+ def initialize string
+ @string = string
+ end
+
+ def classify
+ @string.split('/').map do |namespace|
+ namespace.split(/[-_]/).map do |part|
+ part[0] = part.chars.first.upcase
+ part
+ end.join
+ end.join('::')
+ end
+
+ def underscore(view_namespace)
+ @string
+ .dup
+ .split("#{view_namespace}::")
+ .last
+ .split('::')
+ .map do |part|
+ part[0] = part[0].downcase
+ part.gsub(/[A-Z]/) { |s| "_" << s.downcase }
+ end
+ .join('/')
+ end
+ end
+ end
+end
diff --git a/lib/mustache/version.rb b/lib/mustache/version.rb
index 23d1abb..585dc84 100644
--- a/lib/mustache/version.rb
+++ b/lib/mustache/version.rb
@@ -1,3 +1,3 @@
class Mustache
- Version = VERSION = '0.99.4'
+ VERSION = '1.0.1'
end
diff --git a/lib/rack/bug/panels/mustache_panel.rb b/lib/rack/bug/panels/mustache_panel.rb
deleted file mode 100644
index cc2f73b..0000000
--- a/lib/rack/bug/panels/mustache_panel.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-module Rack
- module Bug
- # MustachePanel is a Rack::Bug panel which tracks the time spent rendering
- # Mustache views as well as all the variables accessed during view
- # rendering.
- #
- # It can be used to track down slow partials and ensure you're only
- # generating data you need.
- #
- # Also, it's fun.
- class MustachePanel < Panel
- require "rack/bug/panels/mustache_panel/mustache_extension"
-
- # The view is responsible for rendering our panel. While Rack::Bug
- # takes care of the nav, the content rendered by View is used for
- # the panel itself.
- class View < Mustache
- self.path = ::File.dirname(__FILE__) + '/mustache_panel'
-
- # We track the render times of all the Mustache views on this
- # page load.
- def times
- MustachePanel.times.map do |key, value|
- { :key => key, :value => value }
- end
- end
-
- # Any variables used in this page load are collected and displayed.
- def variables
- vars = MustachePanel.variables.sort_by { |key, _| key.to_s }
- vars.map do |key, value|
- # Arrays can get too huge. Just show the first 10 to give you
- # some idea.
- if value.is_a?(Array) && value.size > 10
- size = value.size
- value = value.first(10)
- value << "...and #{size - 10} more"
- end
-
- { :key => key, :value => value.inspect }
- end
- end
- end
-
- # Clear out our page load-specific variables.
- def self.reset
- Thread.current["rack.bug.mustache.times"] = {}
- Thread.current["rack.bug.mustache.vars"] = {}
- end
-
- # The view render times for this page load
- def self.times
- Thread.current["rack.bug.mustache.times"] ||= {}
- end
-
- # The variables used on this page load
- def self.variables
- Thread.current["rack.bug.mustache.vars"] ||= {}
- end
-
- # The name of this Rack::Bug panel
- def name
- "mustache"
- end
-
- # The string used for our tab in Rack::Bug's navigation bar
- def heading
- "{{%.2fms}}" % self.class.times.values.inject(0.0) do |sum, obj|
- sum + obj
- end
- end
-
- # The content of our Rack::Bug panel
- def content
- View.render
- ensure
- self.class.reset
- end
- end
- end
-end
diff --git a/lib/rack/bug/panels/mustache_panel/mustache_extension.rb b/lib/rack/bug/panels/mustache_panel/mustache_extension.rb
deleted file mode 100644
index 5f4762f..0000000
--- a/lib/rack/bug/panels/mustache_panel/mustache_extension.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-if defined? Mustache
- require 'benchmark'
-
- Mustache.class_eval do
- alias_method :real_render, :render
-
- def render(*args, &block)
- out = ''
- Rack::Bug::MustachePanel.times[self.class.name] = Benchmark.realtime do
- out = real_render(*args, &block)
- end
- out
- end
-
- alias_method :to_html, :render
- alias_method :to_text, :render
- end
-
- Mustache::Context.class_eval do
- alias_method :real_get, :[]
-
- def [](name)
- return real_get(name) if name == :yield || !@mustache.respond_to?(name)
- Rack::Bug::MustachePanel.variables[name] = real_get(name)
- end
- end
-end
diff --git a/lib/rack/bug/panels/mustache_panel/view.mustache b/lib/rack/bug/panels/mustache_panel/view.mustache
deleted file mode 100644
index b9b6d05..0000000
--- a/lib/rack/bug/panels/mustache_panel/view.mustache
+++ /dev/null
@@ -1,46 +0,0 @@
-<script type="text/javascript">
-$(function() {
- $('#mustache_variables .variable').each(function() {
- var el = $(this)
- if (el.text().length > 500) {
- var txt = el.text()
- el.click(function() {
- $(this).text(txt)
- }).text( el.text().slice(0, 500) + '...' )
- }
- })
-});
-</script>
-
-<h3>Render Times</h3>
-
-<table>
- <tr>
- <th>View</th>
- <th>Render Time</th>
- </tr>
-
- {{# times }}
- <tr>
- <td>{{ key }}</td>
- <td>{{ value }}</td>
- </tr>
- {{/ times }}
-</table>
-
-<h3>Variables</h3>
-
-<table id="mustache_variables">
- <tr>
- <th>Name</th>
- <th>Value</th>
- </tr>
-
- {{# variables }}
- <tr>
- <td>{{ key }}</td>
- <td class="variable">{{ value }}</td>
- </tr>
- {{/ variables }}
-</table>
-
diff --git a/man/mustache.1 b/man/mustache.1
index 67b29f9..96ef6bd 100644
--- a/man/mustache.1
+++ b/man/mustache.1
@@ -1,10 +1,10 @@
-.\" generated with Ronn/v0.5
-.\" http://github.com/rtomayko/ronn/
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "MUSTACHE" "1" "May 2010" "DEFUNKT" "Mustache Manual"
+.TH "MUSTACHE" "1" "October 2014" "DEFUNKT" "Mustache Manual"
.
.SH "NAME"
-\fBmustache\fR \-\- Mustache processor
+\fBmustache\fR \- Mustache processor
.
.SH "SYNOPSIS"
.
@@ -17,17 +17,13 @@ mustache \-\-tokens <FILE>
.fi
.
.SH "DESCRIPTION"
-Mustache is a logic\-less templating system for HTML, config files,
-anything.
+Mustache is a logic\-less templating system for HTML, config files, anything\.
.
.P
-The \fBmustache\fR command processes a Mustache template preceded by YAML
-frontmatter from standard input and prints one or more documents to
-standard output.
+The \fBmustache\fR command processes a Mustache template preceded by YAML frontmatter from standard input and prints one or more documents to standard output\.
.
.P
-YAML frontmatter beings with \fB\-\-\-\fR on a single line, followed by YAML,
-ending with another \fB\-\-\-\fR on a single line, e.g.
+YAML frontmatter begins with \fB\-\-\-\fR on a single line, followed by YAML, ending with another \fB\-\-\-\fR on a single line, e\.g\.
.
.IP "" 4
.
@@ -42,12 +38,10 @@ names: [ {name: chris}, {name: mark}, {name: scott} ]
.IP "" 0
.
.P
-If you are unfamiliar with YAML, it is a superset of JSON. Valid JSON
-should work fine.
+If you are unfamiliar with YAML, it is a superset of JSON\. Valid JSON should work fine\.
.
.P
-After the frontmatter should come any valid Mustache template. See
-mustache(5) for an overview of Mustache templates.
+After the frontmatter should come any valid Mustache template\. See mustache(5) for an overview of Mustache templates\.
.
.P
For example:
@@ -65,23 +59,23 @@ For example:
.IP "" 0
.
.P
-Now let's combine them.
+Now let\'s combine them\.
.
.IP "" 4
.
.nf
-$ cat data.yml
+$ cat data\.yml
\-\-\-
names: [ {name: chris}, {name: mark}, {name: scott} ]
\-\-\-
-$ cat template.mustache
+$ cat template\.mustache
{{#names}}
Hi {{name}}!
{{/names}}
-$ cat data.yml template.mustache | mustache
+$ cat data\.yml template\.mustache | mustache
Hi chris!
Hi mark!
Hi scott!
@@ -91,8 +85,7 @@ Hi scott!
.IP "" 0
.
.P
-If you provide multiple YAML documents (as delimited by \fB\-\-\-\fR), your
-template will be rendered multiple times. Like a mail merge.
+If you provide multiple YAML documents (as delimited by \fB\-\-\-\fR), your template will be rendered multiple times\. Like a mail merge\.
.
.P
For example:
@@ -101,7 +94,7 @@ For example:
.
.nf
-$ cat data.yml
+$ cat data\.yml
\-\-\-
name: chris
\-\-\-
@@ -110,10 +103,10 @@ name: mark
name: scott
\-\-\-
-$ cat template.mustache
+$ cat template\.mustache
Hi {{name}}!
-$ cat data.yml template.mustache | mustache
+$ cat data\.yml template\.mustache | mustache
Hi chris!
Hi mark!
Hi scott!
@@ -123,23 +116,15 @@ Hi scott!
.IP "" 0
.
.SH "OPTIONS"
-By default \fBmustache\fR will try to render a Mustache template using the
-YAML frontmatter you provide. It can do a few other things, however.
+By default \fBmustache\fR will try to render a Mustache template using the YAML frontmatter you provide\. It can do a few other things, however\.
.
.TP
\fB\-c\fR, \fB\-\-compile\fR
-Print the compiled Ruby version of a given template. This is the
-code that is actually used when rendering a template into a
-string. Useful for debugging but only if you are familiar with
-Mustache's internals.
+Print the compiled Ruby version of a given template\. This is the code that is actually used when rendering a template into a string\. Useful for debugging but only if you are familiar with Mustache\'s internals\.
.
.TP
\fB\-t\fR, \fB\-\-tokens\fR
-Print the tokenized form of a given Mustache template. This can be
-used to understand how Mustache parses a template. The tokens are
-handed to a generator which compiles them into a Ruby
-string. Syntax errors and confused tags, therefor, can probably be
-identified by examining the tokens produced.
+Print the tokenized form of a given Mustache template\. This can be used to understand how Mustache parses a template\. The tokens are handed to a generator which compiles them into a Ruby string\. Syntax errors and confused tags, therefore, can probably be identified by examining the tokens produced\.
.
.SH "INSTALLATION"
If you have RubyGems installed:
@@ -158,10 +143,10 @@ gem install mustache
.
.nf
-$ mustache data.yml template.mustache
-$ cat data.yml | mustache \- template.mustache
-$ mustache \-c template.mustache
-$ cat <<data | ruby mustache \- template.mustache
+$ mustache data\.yml template\.mustache
+$ cat data\.yml | mustache \- template\.mustache
+$ mustache \-c template\.mustache
+$ cat <<data | ruby mustache \- template\.mustache
\-\-\-
name: Bob
age: 30
@@ -177,4 +162,4 @@ Mustache is Copyright (C) 2009 Chris Wanstrath
Original CTemplate by Google
.
.SH "SEE ALSO"
-mustache(5), mustache(7), gem(1), \fIhttp://mustache.github.com/\fR
+mustache(5), gem(1), \fIhttp://mustache\.github\.io/\fR
diff --git a/man/mustache.1.html b/man/mustache.1.html
index fb3e88b..5d3eb47 100644
--- a/man/mustache.1.html
+++ b/man/mustache.1.html
@@ -2,77 +2,86 @@
<html>
<head>
<meta http-equiv='content-type' value='text/html;charset=utf8'>
- <meta name='generator' value='Ronn/v0.5'>
- <title>mustache(1) -- Mustache processor</title>
- <style type='text/css'>
- body {margin:0}
- #man, #man code, #man pre, #man tt, #man kbd, #man samp {
- font-family:consolas,monospace;
- font-size:16px;
- line-height:1.3;
- color:#343331;
- background:#fff; }
- #man { max-width:89ex; text-align:justify; margin:0 25px 25px 25px }
- #man h1, #man h2, #man h3 { color:#232221;clear:left }
- #man h1 { font-size:28px; margin:15px 0 30px 0; text-align:center }
- #man h2 { font-size:18px; margin-bottom:0; margin-top:10px; line-height:1.3; }
- #man h3 { font-size:16px; margin:0 0 0 4ex; }
- #man p, #man ul, #man ol, #man dl, #man pre { margin:0 0 18px 0; }
- #man pre {
- color:#333231;
- background:#edeceb;
- padding:5px 7px;
- margin:0px 0 20px 0;
- border-left:2ex solid #ddd}
- #man pre + h2, #man pre + h3 {
- margin-top:22px;
- }
- #man h2 + pre, #man h3 + pre {
- margin-top:5px;
- }
- #man > p, #man > ul, #man > ol, #man > dl, #man > pre { margin-left:8ex; }
- #man dt { margin:0; clear:left }
- #man dt.flush { float:left; width:8ex }
- #man dd { margin:0 0 0 9ex }
- #man code, #man strong, #man b { font-weight:bold; color:#131211; }
- #man pre code { font-weight:normal; color:#232221; background:inherit }
- #man em, var, u {
- font-style:normal; color:#333231; border-bottom:1px solid #999; }
- #man h1.man-title { display:none; }
- #man ol.man, #man ol.man li { margin:2px 0 10px 0; padding:0;
- float:left; width:33%; list-style-type:none;
- text-transform:uppercase; font-size:18px; color:#999;
- letter-spacing:1px;}
- #man ol.man { width:100%; }
- #man ol.man li.tl { text-align:left }
- #man ol.man li.tc { text-align:center;letter-spacing:4px }
- #man ol.man li.tr { text-align:right }
- #man ol.man a { color:#999 }
- #man ol.man a:hover { color:#333231 }
+ <meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>
+ <title>mustache(1) - Mustache processor</title>
+ <style type='text/css' media='all'>
+ /* style: man */
+ body#manpage {margin:0}
+ .mp {max-width:100ex;padding:0 9ex 1ex 4ex}
+ .mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
+ .mp h2 {margin:10px 0 0 0}
+ .mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
+ .mp h3 {margin:0 0 0 4ex}
+ .mp dt {margin:0;clear:left}
+ .mp dt.flush {float:left;width:8ex}
+ .mp dd {margin:0 0 0 9ex}
+ .mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
+ .mp pre {margin-bottom:20px}
+ .mp pre+h2,.mp pre+h3 {margin-top:22px}
+ .mp h2+pre,.mp h3+pre {margin-top:5px}
+ .mp img {display:block;margin:auto}
+ .mp h1.man-title {display:none}
+ .mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
+ .mp h2 {font-size:16px;line-height:1.25}
+ .mp h1 {font-size:20px;line-height:2}
+ .mp {text-align:justify;background:#fff}
+ .mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
+ .mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
+ .mp u {text-decoration:underline}
+ .mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
+ .mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
+ .mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
+ .mp b.man-ref {font-weight:normal;color:#434241}
+ .mp pre {padding:0 4ex}
+ .mp pre code {font-weight:normal;color:#434241}
+ .mp h2+pre,h3+pre {padding-left:0}
+ ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
+ ol.man-decor {width:100%}
+ ol.man-decor li.tl {text-align:left}
+ ol.man-decor li.tc {text-align:center;letter-spacing:4px}
+ ol.man-decor li.tr {text-align:right;float:right}
</style>
</head>
-<body>
-<div id='man'>
-
-<h1 class='man-title'>mustache(1)</h1>
-
-<ol class='head man'>
- <li class='tl'>mustache(1)</li>
- <li class='tc'>Mustache Manual</li>
- <li class='tr'>mustache(1)</li>
-</ol>
-
-<h2 id='NAME'>NAME</h2>
-<p><code>mustache</code> -- Mustache processor</p>
-
-<h2>SYNOPSIS</h2>
+<!--
+ The following styles are deprecated and will be removed at some point:
+ div#man, div#man ol.man, div#man ol.head, div#man ol.man.
+
+ The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
+ .man-navigation should be used instead.
+-->
+<body id='manpage'>
+ <div class='mp' id='man'>
+
+ <div class='man-navigation' style='display:none'>
+ <a href="#NAME">NAME</a>
+ <a href="#SYNOPSIS">SYNOPSIS</a>
+ <a href="#DESCRIPTION">DESCRIPTION</a>
+ <a href="#OPTIONS">OPTIONS</a>
+ <a href="#INSTALLATION">INSTALLATION</a>
+ <a href="#EXAMPLES">EXAMPLES</a>
+ <a href="#COPYRIGHT">COPYRIGHT</a>
+ <a href="#SEE-ALSO">SEE ALSO</a>
+ </div>
+
+ <ol class='man-decor man-head man head'>
+ <li class='tl'>mustache(1)</li>
+ <li class='tc'>Mustache Manual</li>
+ <li class='tr'>mustache(1)</li>
+ </ol>
+
+ <h2 id="NAME">NAME</h2>
+<p class="man-name">
+ <code>mustache</code> - <span class="man-whatis">Mustache processor</span>
+</p>
+
+<h2 id="SYNOPSIS">SYNOPSIS</h2>
<pre><code>mustache <YAML> <FILE>
mustache --compile <FILE>
mustache --tokens <FILE>
</code></pre>
-<h2>DESCRIPTION</h2>
+<h2 id="DESCRIPTION">DESCRIPTION</h2>
<p>Mustache is a logic-less templating system for HTML, config files,
anything.</p>
@@ -81,7 +90,7 @@ anything.</p>
frontmatter from standard input and prints one or more documents to
standard output.</p>
-<p>YAML frontmatter beings with <code>---</code> on a single line, followed by YAML,
+<p>YAML frontmatter begins with <code>---</code> on a single line, followed by YAML,
ending with another <code>---</code> on a single line, e.g.</p>
<pre><code>---
@@ -93,7 +102,7 @@ names: [ {name: chris}, {name: mark}, {name: scott} ]
should work fine.</p>
<p>After the frontmatter should come any valid Mustache template. See
-mustache(5) for an overview of Mustache templates.</p>
+<a class="man-ref" href="mustache.5.ron.html">mustache<span class="s">(5)</span></a> for an overview of Mustache templates.</p>
<p>For example:</p>
@@ -143,7 +152,7 @@ Hi mark!
Hi scott!
</code></pre>
-<h2>OPTIONS</h2>
+<h2 id="OPTIONS">OPTIONS</h2>
<p>By default <code>mustache</code> will try to render a Mustache template using the
YAML frontmatter you provide. It can do a few other things, however.</p>
@@ -156,19 +165,19 @@ Mustache's internals.</p></dd>
<dt><code>-t</code>, <code>--tokens</code></dt><dd><p>Print the tokenized form of a given Mustache template. This can be
used to understand how Mustache parses a template. The tokens are
handed to a generator which compiles them into a Ruby
-string. Syntax errors and confused tags, therefor, can probably be
+string. Syntax errors and confused tags, therefore, can probably be
identified by examining the tokens produced.</p></dd>
</dl>
-<h2>INSTALLATION</h2>
+<h2 id="INSTALLATION">INSTALLATION</h2>
<p>If you have RubyGems installed:</p>
<pre><code>gem install mustache
</code></pre>
-<h2>EXAMPLES</h2>
+<h2 id="EXAMPLES">EXAMPLES</h2>
<pre><code>$ mustache data.yml template.mustache
$ cat data.yml | mustache - template.mustache
@@ -181,24 +190,24 @@ age: 30
data
</code></pre>
-<h2>COPYRIGHT</h2>
+<h2 id="COPYRIGHT">COPYRIGHT</h2>
<p>Mustache is Copyright (C) 2009 Chris Wanstrath</p>
<p>Original CTemplate by Google</p>
-<h2>SEE ALSO</h2>
+<h2 id="SEE-ALSO">SEE ALSO</h2>
-<p>mustache(5), mustache(7), gem(1),
-<a href="http://mustache.github.com/">http://mustache.github.com/</a></p>
+<p><a class="man-ref" href="mustache.5.ron.html">mustache<span class="s">(5)</span></a>, <span class="man-ref">gem<span class="s">(1)</span></span>,
+<a href="http://mustache.github.io/" data-bare-link="true">http://mustache.github.io/</a></p>
-<ol class='foot man'>
- <li class='tl'>DEFUNKT</li>
- <li class='tc'>May 2010</li>
- <li class='tr'>mustache(1)</li>
-</ol>
+ <ol class='man-decor man-foot man foot'>
+ <li class='tl'>DEFUNKT</li>
+ <li class='tc'>October 2014</li>
+ <li class='tr'>mustache(1)</li>
+ </ol>
-</div>
+ </div>
</body>
</html>
diff --git a/man/mustache.1.ron b/man/mustache.1.ron
index 6d91a70..efd644b 100644
--- a/man/mustache.1.ron
+++ b/man/mustache.1.ron
@@ -17,7 +17,7 @@ The `mustache` command processes a Mustache template preceded by YAML
frontmatter from standard input and prints one or more documents to
standard output.
-YAML frontmatter beings with `---` on a single line, followed by YAML,
+YAML frontmatter begins with `---` on a single line, followed by YAML,
ending with another `---` on a single line, e.g.
---
@@ -90,7 +90,7 @@ YAML frontmatter you provide. It can do a few other things, however.
Print the tokenized form of a given Mustache template. This can be
used to understand how Mustache parses a template. The tokens are
handed to a generator which compiles them into a Ruby
- string. Syntax errors and confused tags, therefor, can probably be
+ string. Syntax errors and confused tags, therefore, can probably be
identified by examining the tokens produced.
@@ -123,5 +123,5 @@ Original CTemplate by Google
## SEE ALSO
-mustache(5), mustache(7), gem(1),
-<http://mustache.github.com/>
+mustache(5), gem(1),
+<http://mustache.github.io/>
diff --git a/man/mustache.5 b/man/mustache.5
index 60f457f..b652ec7 100644
--- a/man/mustache.5
+++ b/man/mustache.5
@@ -1,10 +1,10 @@
-.\" generated with Ronn/v0.5
-.\" http://github.com/rtomayko/ronn/
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "MUSTACHE" "5" "May 2010" "DEFUNKT" "Mustache Manual"
+.TH "MUSTACHE" "5" "October 2014" "DEFUNKT" "Mustache Manual"
.
.SH "NAME"
-\fBmustache\fR \-\- Logic\-less templates.
+\fBmustache\fR \- Logic\-less templates\.
.
.SH "SYNOPSIS"
A typical Mustache template:
@@ -16,7 +16,7 @@ A typical Mustache template:
Hello {{name}}
You have just won {{value}} dollars!
{{#in_ca}}
-Well, {{taxed_value}} dollars, after taxes.
+Well, {{taxed_value}} dollars, after taxes\.
{{/in_ca}}
.
.fi
@@ -33,7 +33,7 @@ Given the following hash:
{
"name": "Chris",
"value": 10000,
- "taxed_value": 10000 \- (10000 * 0.4),
+ "taxed_value": 10000 \- (10000 * 0\.4),
"in_ca": true
}
.
@@ -50,45 +50,32 @@ Will produce the following:
Hello Chris
You have just won 10000 dollars!
-Well, 6000.0 dollars, after taxes.
+Well, 6000\.0 dollars, after taxes\.
.
.fi
.
.IP "" 0
.
.SH "DESCRIPTION"
-Mustache can be used for HTML, config files, source code \-
-anything. It works by expanding tags in a template using values
-provided in a hash or object.
+Mustache can be used for HTML, config files, source code \- anything\. It works by expanding tags in a template using values provided in a hash or object\.
.
.P
-We call it "logic\-less" because there are no if statements, else
-clauses, or for loops. Instead there are only tags. Some tags are
-replaced with a value, some nothing, and others a series of
-values. This document explains the different types of Mustache tags.
+We call it "logic\-less" because there are no if statements, else clauses, or for loops\. Instead there are only tags\. Some tags are replaced with a value, some nothing, and others a series of values\. This document explains the different types of Mustache tags\.
.
.SH "TAG TYPES"
-Tags are indicated by the double mustaches. \fB{{person}}\fR is a tag, as
-is \fB{{#person}}\fR. In both examples, we'd refer to \fBperson\fR as the key
-or tag key. Let's talk about the different types of tags.
+Tags are indicated by the double mustaches\. \fB{{person}}\fR is a tag, as is \fB{{#person}}\fR\. In both examples, we\'d refer to \fBperson\fR as the key or tag key\. Let\'s talk about the different types of tags\.
.
.SS "Variables"
-The most basic tag type is the variable. A \fB{{name}}\fR tag in a basic
-template will try to find the \fBname\fR key in the current context. If
-there is no \fBname\fR key, nothing will be rendered.
+The most basic tag type is the variable\. A \fB{{name}}\fR tag in a basic template will try to find the \fBname\fR key in the current context\. If there is no \fBname\fR key, the parent contexts will be checked recursively\. If the top context is reached and the \fBname\fR key is still not found, nothing will be rendered\.
.
.P
-All variables are HTML escaped by default. If you want to return
-unescaped HTML, use the triple mustache: \fB{{{name}}}\fR.
+All variables are HTML escaped by default\. If you want to return unescaped HTML, use the triple mustache: \fB{{{name}}}\fR\.
.
.P
-You can also use \fB&\fR to unescape a variable: \fB{{& name}}\fR. This may be
-useful when changing delimiters (see "Set Delimiter" below).
+You can also use \fB&\fR to unescape a variable: \fB{{& name}}\fR\. This may be useful when changing delimiters (see "Set Delimiter" below)\.
.
.P
-By default a variable "miss" returns an empty string. This can usually
-be configured in your Mustache library. The Ruby version of Mustache
-supports raising an exception in this situation, for instance.
+By default a variable "miss" returns an empty string\. This can usually be configured in your Mustache library\. The Ruby version of Mustache supports raising an exception in this situation, for instance\.
.
.P
Template:
@@ -139,21 +126,19 @@ Output:
.IP "" 0
.
.SS "Sections"
-Sections render blocks of text one or more times, depending on the
-value of the key in the current context.
+Sections render blocks of text zero or more times, depending on the value of the key in the current context\.
.
.P
-A section begins with a pound and ends with a slash. That is, \fB{{#person}}\fR begins a "person" section while \fB{{/person}}\fR ends it.
+A section begins with a pound and ends with a slash\. That is, \fB{{#person}}\fR begins a "person" section while \fB{{/person}}\fR ends it\.
.
.P
-The behavior of the section is determined by the value of the key.
+The behavior of the section is determined by the value of the key\.
.
.P
\fBFalse Values or Empty Lists\fR
.
.P
-If the \fBperson\fR key exists and has a value of false or an empty
-list, the HTML between the pound and slash will not be displayed.
+If the \fBperson\fR key exists and has a value of false or an empty list, the HTML between the pound and slash will not be displayed\.
.
.P
Template:
@@ -162,10 +147,10 @@ Template:
.
.nf
-Shown.
-{{#nothin}}
+Shown\.
+{{#person}}
Never shown!
-{{/nothin}}
+{{/person}}
.
.fi
.
@@ -179,7 +164,7 @@ Hash:
.nf
{
- "person": true,
+ "person": false
}
.
.fi
@@ -193,7 +178,7 @@ Output:
.
.nf
-Shown.
+Shown\.
.
.fi
.
@@ -203,14 +188,10 @@ Shown.
\fBNon\-Empty Lists\fR
.
.P
-If the \fBperson\fR key exists and has a non\-false value, the HTML between
-the pound and slash will be rendered and displayed one or more times.
+If the \fBperson\fR key exists and has a non\-false value, the HTML between the pound and slash will be rendered and displayed one or more times\.
.
.P
-When the value is a non\-empty list, the text in the block will be
-displayed once for each item in the list. The context of the block
-will be set to the current item for each iteration. In this way we can
-loop over collections.
+When the value is a non\-empty list, the text in the block will be displayed once for each item in the list\. The context of the block will be set to the current item for each iteration\. In this way we can loop over collections\.
.
.P
Template:
@@ -238,7 +219,7 @@ Hash:
"repo": [
{ "name": "resque" },
{ "name": "hub" },
- { "name": "rip" },
+ { "name": "rip" }
]
}
.
@@ -265,11 +246,7 @@ Output:
\fBLambdas\fR
.
.P
-When the value is a callable object, such as a function or lambda, the
-object will be invoked and passed the block of text. The text passed
-is the literal block, unrendered. \fB{{tags}}\fR will not have been expanded
-\- the lambda should do that on its own. In this way you can implement
-filters or caching.
+When the value is a callable object, such as a function or lambda, the object will be invoked and passed the block of text\. The text passed is the literal block, unrendered\. \fB{{tags}}\fR will not have been expanded \- the lambda should do that on its own\. In this way you can implement filters or caching\.
.
.P
Template:
@@ -279,7 +256,7 @@ Template:
.nf
{{#wrapped}}
- {{name}} is awesome.
+ {{name}} is awesome\.
{{/wrapped}}
.
.fi
@@ -296,7 +273,7 @@ Hash:
{
"name": "Willy",
"wrapped": function() {
- return function(text) {
+ return function(text, render) {
return "<b>" + render(text) + "</b>"
}
}
@@ -313,7 +290,7 @@ Output:
.
.nf
-<b>Willy is awesome.</b>
+<b>Willy is awesome\.</b>
.
.fi
.
@@ -323,8 +300,7 @@ Output:
\fBNon\-False Values\fR
.
.P
-When the value is non\-false but not a list, it will be used as the
-context for a single rendering of the block.
+When the value is non\-false but not a list, it will be used as the context for a single rendering of the block\.
.
.P
Template:
@@ -370,14 +346,10 @@ Hi Jon!
.IP "" 0
.
.SS "Inverted Sections"
-An inverted section begins with a caret (hat) and ends with a
-slash. That is \fB{{^person}}\fR begins a "person" inverted section while \fB{{/person}}\fR ends it.
+An inverted section begins with a caret (hat) and ends with a slash\. That is \fB{{^person}}\fR begins a "person" inverted section while \fB{{/person}}\fR ends it\.
.
.P
-While sections can be used to render text one or more times based on the
-value of the key, inverted sections may render text once based
-on the inverse value of the key. That is, they will be rendered
-if the key doesn't exist, is false, or is an empty list.
+While sections can be used to render text zero or more times based on the value of the key, inverted sections may render text once based on the inverse value of the key\. That is, they will be rendered if the key doesn\'t exist, is false, or is an empty list\.
.
.P
Template:
@@ -426,13 +398,13 @@ No repos :(
.IP "" 0
.
.SS "Comments"
-Comments begin with a bang and are ignored. The following template:
+Comments begin with a bang and are ignored\. The following template:
.
.IP "" 4
.
.nf
-<h1>Today{{! ignore me }}.</h1>
+<h1>Today{{! ignore me }}\.</h1>
.
.fi
.
@@ -445,25 +417,23 @@ Will render as follows:
.
.nf
-<h1>Today.</h1>
+<h1>Today\.</h1>
.
.fi
.
.IP "" 0
.
.P
-Comments may contain newlines.
+Comments may contain newlines\.
.
.SS "Partials"
-Partials begin with a greater than sign, like \fB{{> box}}\fR.
+Partials begin with a greater than sign, like \fB{{> box}}\fR\.
.
.P
-Partials are rendered at runtime (as opposed to compile time), so
-recursive partials are possible. Just avoid infinite loops.
+Partials are rendered at runtime (as opposed to compile time), so recursive partials are possible\. Just avoid infinite loops\.
.
.P
-They also inherit the calling context. Whereas in ERB you may have
-this:
+They also inherit the calling context\. Whereas in ERB you may have this:
.
.IP "" 4
.
@@ -489,11 +459,10 @@ Mustache requires only this:
.IP "" 0
.
.P
-Why? Because the \fBnext_more.mustache\fR file will inherit the \fBsize\fR and \fBstart\fR methods from the calling context.
+Why? Because the \fBnext_more\.mustache\fR file will inherit the \fBsize\fR and \fBstart\fR methods from the calling context\.
.
.P
-In this way you may want to think of partials as includes, or template
-expansion, even though it's not literally true.
+In this way you may want to think of partials as includes, or template expansion, even though it\'s not literally true\.
.
.P
For example, this template and partial:
@@ -502,13 +471,13 @@ For example, this template and partial:
.
.nf
-base.mustache:
+base\.mustache:
<h2>Names</h2>
{{#names}}
{{> user}}
{{/names}}
-user.mustache:
+user\.mustache:
<strong>{{name}}</strong>
.
.fi
@@ -532,8 +501,7 @@ Can be thought of as a single, expanded template:
.IP "" 0
.
.SS "Set Delimiter"
-Set Delimiter tags start with an equal sign and change the tag
-delimiters from \fB{{\fR and \fB}}\fR to custom strings.
+Set Delimiter tags start with an equal sign and change the tag delimiters from \fB{{\fR and \fB}}\fR to custom strings\.
.
.P
Consider the following contrived example:
@@ -553,18 +521,13 @@ Consider the following contrived example:
.IP "" 0
.
.P
-Here we have a list with three items. The first item uses the default
-tag style, the second uses erb style as defined by the Set Delimiter
-tag, and the third returns to the default style after yet another Set
-Delimiter declaration.
+Here we have a list with three items\. The first item uses the default tag style, the second uses erb style as defined by the Set Delimiter tag, and the third returns to the default style after yet another Set Delimiter declaration\.
.
.P
-According to \fIctemplates\fR, this "is useful for languages like TeX, where
-double\-braces may occur in the text and are awkward to use for
-markup."
+According to ctemplates \fIhttp://google\-ctemplate\.googlecode\.com/svn/trunk/doc/howto\.html\fR, this "is useful for languages like TeX, where double\-braces may occur in the text and are awkward to use for markup\."
.
.P
-Custom delimiters may not contain whitespace or the equals sign.
+Custom delimiters may not contain whitespace or the equals sign\.
.
.SH "COPYRIGHT"
Mustache is Copyright (C) 2009 Chris Wanstrath
@@ -573,4 +536,4 @@ Mustache is Copyright (C) 2009 Chris Wanstrath
Original CTemplate by Google
.
.SH "SEE ALSO"
-mustache(1), mustache(7), \fIhttp://mustache.github.com/\fR
+mustache(1), \fIhttp://mustache\.github\.io/\fR
diff --git a/man/mustache.5.html b/man/mustache.5.html
index 1e81e46..951dee3 100644
--- a/man/mustache.5.html
+++ b/man/mustache.5.html
@@ -2,70 +2,77 @@
<html>
<head>
<meta http-equiv='content-type' value='text/html;charset=utf8'>
- <meta name='generator' value='Ronn/v0.5'>
- <title>mustache(5) -- Logic-less templates.</title>
- <style type='text/css'>
- body {margin:0}
- #man, #man code, #man pre, #man tt, #man kbd, #man samp {
- font-family:consolas,monospace;
- font-size:16px;
- line-height:1.3;
- color:#343331;
- background:#fff; }
- #man { max-width:89ex; text-align:justify; margin:0 25px 25px 25px }
- #man h1, #man h2, #man h3 { color:#232221;clear:left }
- #man h1 { font-size:28px; margin:15px 0 30px 0; text-align:center }
- #man h2 { font-size:18px; margin-bottom:0; margin-top:10px; line-height:1.3; }
- #man h3 { font-size:16px; margin:0 0 0 4ex; }
- #man p, #man ul, #man ol, #man dl, #man pre { margin:0 0 18px 0; }
- #man pre {
- color:#333231;
- background:#edeceb;
- padding:5px 7px;
- margin:0px 0 20px 0;
- border-left:2ex solid #ddd}
- #man pre + h2, #man pre + h3 {
- margin-top:22px;
- }
- #man h2 + pre, #man h3 + pre {
- margin-top:5px;
- }
- #man > p, #man > ul, #man > ol, #man > dl, #man > pre { margin-left:8ex; }
- #man dt { margin:0; clear:left }
- #man dt.flush { float:left; width:8ex }
- #man dd { margin:0 0 0 9ex }
- #man code, #man strong, #man b { font-weight:bold; color:#131211; }
- #man pre code { font-weight:normal; color:#232221; background:inherit }
- #man em, var, u {
- font-style:normal; color:#333231; border-bottom:1px solid #999; }
- #man h1.man-title { display:none; }
- #man ol.man, #man ol.man li { margin:2px 0 10px 0; padding:0;
- float:left; width:33%; list-style-type:none;
- text-transform:uppercase; font-size:18px; color:#999;
- letter-spacing:1px;}
- #man ol.man { width:100%; }
- #man ol.man li.tl { text-align:left }
- #man ol.man li.tc { text-align:center;letter-spacing:4px }
- #man ol.man li.tr { text-align:right }
- #man ol.man a { color:#999 }
- #man ol.man a:hover { color:#333231 }
+ <meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>
+ <title>mustache(5) - Logic-less templates.</title>
+ <style type='text/css' media='all'>
+ /* style: man */
+ body#manpage {margin:0}
+ .mp {max-width:100ex;padding:0 9ex 1ex 4ex}
+ .mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
+ .mp h2 {margin:10px 0 0 0}
+ .mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
+ .mp h3 {margin:0 0 0 4ex}
+ .mp dt {margin:0;clear:left}
+ .mp dt.flush {float:left;width:8ex}
+ .mp dd {margin:0 0 0 9ex}
+ .mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
+ .mp pre {margin-bottom:20px}
+ .mp pre+h2,.mp pre+h3 {margin-top:22px}
+ .mp h2+pre,.mp h3+pre {margin-top:5px}
+ .mp img {display:block;margin:auto}
+ .mp h1.man-title {display:none}
+ .mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
+ .mp h2 {font-size:16px;line-height:1.25}
+ .mp h1 {font-size:20px;line-height:2}
+ .mp {text-align:justify;background:#fff}
+ .mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
+ .mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
+ .mp u {text-decoration:underline}
+ .mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
+ .mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
+ .mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
+ .mp b.man-ref {font-weight:normal;color:#434241}
+ .mp pre {padding:0 4ex}
+ .mp pre code {font-weight:normal;color:#434241}
+ .mp h2+pre,h3+pre {padding-left:0}
+ ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
+ ol.man-decor {width:100%}
+ ol.man-decor li.tl {text-align:left}
+ ol.man-decor li.tc {text-align:center;letter-spacing:4px}
+ ol.man-decor li.tr {text-align:right;float:right}
</style>
</head>
-<body>
-<div id='man'>
-
-<h1 class='man-title'>mustache(5)</h1>
-
-<ol class='head man'>
- <li class='tl'>mustache(5)</li>
- <li class='tc'>Mustache Manual</li>
- <li class='tr'>mustache(5)</li>
-</ol>
-
-<h2 id='NAME'>NAME</h2>
-<p><code>mustache</code> -- Logic-less templates.</p>
-
-<h2>SYNOPSIS</h2>
+<!--
+ The following styles are deprecated and will be removed at some point:
+ div#man, div#man ol.man, div#man ol.head, div#man ol.man.
+
+ The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
+ .man-navigation should be used instead.
+-->
+<body id='manpage'>
+ <div class='mp' id='man'>
+
+ <div class='man-navigation' style='display:none'>
+ <a href="#NAME">NAME</a>
+ <a href="#SYNOPSIS">SYNOPSIS</a>
+ <a href="#DESCRIPTION">DESCRIPTION</a>
+ <a href="#TAG-TYPES">TAG TYPES</a>
+ <a href="#COPYRIGHT">COPYRIGHT</a>
+ <a href="#SEE-ALSO">SEE ALSO</a>
+ </div>
+
+ <ol class='man-decor man-head man head'>
+ <li class='tl'>mustache(5)</li>
+ <li class='tc'>Mustache Manual</li>
+ <li class='tr'>mustache(5)</li>
+ </ol>
+
+ <h2 id="NAME">NAME</h2>
+<p class="man-name">
+ <code>mustache</code> - <span class="man-whatis">Logic-less templates.</span>
+</p>
+
+<h2 id="SYNOPSIS">SYNOPSIS</h2>
<p>A typical Mustache template:</p>
@@ -93,7 +100,7 @@ You have just won 10000 dollars!
Well, 6000.0 dollars, after taxes.
</code></pre>
-<h2>DESCRIPTION</h2>
+<h2 id="DESCRIPTION">DESCRIPTION</h2>
<p>Mustache can be used for HTML, config files, source code -
anything. It works by expanding tags in a template using values
@@ -104,17 +111,19 @@ clauses, or for loops. Instead there are only tags. Some tags are
replaced with a value, some nothing, and others a series of
values. This document explains the different types of Mustache tags.</p>
-<h2>TAG TYPES</h2>
+<h2 id="TAG-TYPES">TAG TYPES</h2>
<p>Tags are indicated by the double mustaches. <code>{{person}}</code> is a tag, as
is <code>{{#person}}</code>. In both examples, we'd refer to <code>person</code> as the key
or tag key. Let's talk about the different types of tags.</p>
-<h3>Variables</h3>
+<h3 id="Variables">Variables</h3>
<p>The most basic tag type is the variable. A <code>{{name}}</code> tag in a basic
template will try to find the <code>name</code> key in the current context. If
-there is no <code>name</code> key, nothing will be rendered.</p>
+there is no <code>name</code> key, the parent contexts will be checked recursively.
+If the top context is reached and the <code>name</code> key is still not found,
+nothing will be rendered.</p>
<p>All variables are HTML escaped by default. If you want to return
unescaped HTML, use the triple mustache: <code>{{{name}}}</code>.</p>
@@ -150,9 +159,9 @@ supports raising an exception in this situation, for instance.</p>
* <b>GitHub</b>
</code></pre>
-<h3>Sections</h3>
+<h3 id="Sections">Sections</h3>
-<p>Sections render blocks of text one or more times, depending on the
+<p>Sections render blocks of text zero or more times, depending on the
value of the key in the current context.</p>
<p>A section begins with a pound and ends with a slash. That is,
@@ -168,15 +177,15 @@ list, the HTML between the pound and slash will not be displayed.</p>
<p>Template:</p>
<pre><code>Shown.
-{{#nothin}}
+{{#person}}
Never shown!
-{{/nothin}}
+{{/person}}
</code></pre>
<p>Hash:</p>
<pre><code>{
- "person": true,
+ "person": false
}
</code></pre>
@@ -208,7 +217,7 @@ loop over collections.</p>
"repo": [
{ "name": "resque" },
{ "name": "hub" },
- { "name": "rip" },
+ { "name": "rip" }
]
}
</code></pre>
@@ -240,7 +249,7 @@ filters or caching.</p>
<pre><code>{
"name": "Willy",
"wrapped": function() {
- return function(text) {
+ return function(text, render) {
return "<b>" + render(text) + "</b>"
}
}
@@ -276,13 +285,13 @@ context for a single rendering of the block.</p>
<pre><code>Hi Jon!
</code></pre>
-<h3>Inverted Sections</h3>
+<h3 id="Inverted-Sections">Inverted Sections</h3>
<p>An inverted section begins with a caret (hat) and ends with a
slash. That is <code>{{^person}}</code> begins a "person" inverted section while
<code>{{/person}}</code> ends it.</p>
-<p>While sections can be used to render text one or more times based on the
+<p>While sections can be used to render text zero or more times based on the
value of the key, inverted sections may render text once based
on the inverse value of the key. That is, they will be rendered
if the key doesn't exist, is false, or is an empty list.</p>
@@ -309,7 +318,7 @@ if the key doesn't exist, is false, or is an empty list.</p>
<pre><code>No repos :(
</code></pre>
-<h3>Comments</h3>
+<h3 id="Comments">Comments</h3>
<p>Comments begin with a bang and are ignored. The following template:</p>
@@ -323,7 +332,7 @@ if the key doesn't exist, is false, or is an empty list.</p>
<p>Comments may contain newlines.</p>
-<h3>Partials</h3>
+<h3 id="Partials">Partials</h3>
<p>Partials begin with a greater than sign, like <code>{{> box}}</code>.</p>
@@ -367,7 +376,7 @@ user.mustache:
{{/names}}
</code></pre>
-<h3>Set Delimiter</h3>
+<h3 id="Set-Delimiter">Set Delimiter</h3>
<p>Set Delimiter tags start with an equal sign and change the tag
delimiters from <code>{{</code> and <code>}}</code> to custom strings.</p>
@@ -392,24 +401,24 @@ markup."</p>
<p>Custom delimiters may not contain whitespace or the equals sign.</p>
-<h2>COPYRIGHT</h2>
+<h2 id="COPYRIGHT">COPYRIGHT</h2>
<p>Mustache is Copyright (C) 2009 Chris Wanstrath</p>
<p>Original CTemplate by Google</p>
-<h2>SEE ALSO</h2>
+<h2 id="SEE-ALSO">SEE ALSO</h2>
-<p>mustache(1), mustache(7),
-<a href="http://mustache.github.com/">http://mustache.github.com/</a></p>
+<p><a class="man-ref" href="mustache.1.ron.html">mustache<span class="s">(1)</span></a>,
+<a href="http://mustache.github.io/" data-bare-link="true">http://mustache.github.io/</a></p>
-<ol class='foot man'>
- <li class='tl'>DEFUNKT</li>
- <li class='tc'>May 2010</li>
- <li class='tr'>mustache(5)</li>
-</ol>
+ <ol class='man-decor man-foot man foot'>
+ <li class='tl'>DEFUNKT</li>
+ <li class='tc'>October 2014</li>
+ <li class='tr'>mustache(5)</li>
+ </ol>
-</div>
+ </div>
</body>
</html>
diff --git a/man/mustache.5.ron b/man/mustache.5.ron
index 91d4aa1..755db9e 100644
--- a/man/mustache.5.ron
+++ b/man/mustache.5.ron
@@ -50,7 +50,9 @@ or tag key. Let's talk about the different types of tags.
The most basic tag type is the variable. A `{{name}}` tag in a basic
template will try to find the `name` key in the current context. If
-there is no `name` key, nothing will be rendered.
+there is no `name` key, the parent contexts will be checked recursively.
+If the top context is reached and the `name` key is still not found,
+nothing will be rendered.
All variables are HTML escaped by default. If you want to return
unescaped HTML, use the triple mustache: `{{{name}}}`.
@@ -86,7 +88,7 @@ Output:
### Sections
-Sections render blocks of text one or more times, depending on the
+Sections render blocks of text zero or more times, depending on the
value of the key in the current context.
A section begins with a pound and ends with a slash. That is,
@@ -102,14 +104,14 @@ list, the HTML between the pound and slash will not be displayed.
Template:
Shown.
- {{#nothin}}
+ {{#person}}
Never shown!
- {{/nothin}}
+ {{/person}}
Hash:
{
- "person": true,
+ "person": false
}
Output:
@@ -138,7 +140,7 @@ Hash:
"repo": [
{ "name": "resque" },
{ "name": "hub" },
- { "name": "rip" },
+ { "name": "rip" }
]
}
@@ -167,7 +169,7 @@ Hash:
{
"name": "Willy",
"wrapped": function() {
- return function(text) {
+ return function(text, render) {
return "<b>" + render(text) + "</b>"
}
}
@@ -205,7 +207,7 @@ An inverted section begins with a caret (hat) and ends with a
slash. That is `{{^person}}` begins a "person" inverted section while
`{{/person}}` ends it.
-While sections can be used to render text one or more times based on the
+While sections can be used to render text zero or more times based on the
value of the key, inverted sections may render text once based
on the inverse value of the key. That is, they will be rendered
if the key doesn't exist, is false, or is an empty list.
@@ -320,5 +322,5 @@ Original CTemplate by Google
## SEE ALSO
-mustache(1), mustache(7),
-<http://mustache.github.com/>
+mustache(1),
+<http://mustache.github.io/>
diff --git a/metadata.yml b/metadata.yml
index f7ec2ab..e4d71dd 100644
--- a/metadata.yml
+++ b/metadata.yml
@@ -1,62 +1,143 @@
---- !ruby/object:Gem::Specification
+--- !ruby/object:Gem::Specification
name: mustache
-version: !ruby/object:Gem::Version
- hash: 411
- prerelease:
- segments:
- - 0
- - 99
- - 4
- version: 0.99.4
+version: !ruby/object:Gem::Version
+ version: 1.0.1
platform: ruby
-authors:
+authors:
- Chris Wanstrath
- Magnus Holm
- Pieter van de Bruggen
+- Ricardo Mendes
autorequire:
bindir: bin
cert_chain: []
+date: 2015-02-23 00:00:00.000000000 Z
+dependencies:
+- !ruby/object:Gem::Dependency
+ name: bundler
+ requirement: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '1.6'
+ type: :development
+ prerelease: false
+ version_requirements: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '1.6'
+- !ruby/object:Gem::Dependency
+ name: rake
+ requirement: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '10.3'
+ type: :development
+ prerelease: false
+ version_requirements: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '10.3'
+- !ruby/object:Gem::Dependency
+ name: minitest
+ requirement: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '5.4'
+ type: :development
+ prerelease: false
+ version_requirements: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '5.4'
+- !ruby/object:Gem::Dependency
+ name: benchmark-ips
+ requirement: !ruby/object:Gem::Requirement
+ requirements:
+ - - ! '>='
+ - !ruby/object:Gem::Version
+ version: '0'
+ type: :development
+ prerelease: false
+ version_requirements: !ruby/object:Gem::Requirement
+ requirements:
+ - - ! '>='
+ - !ruby/object:Gem::Version
+ version: '0'
+- !ruby/object:Gem::Dependency
+ name: rdoc
+ requirement: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '4.1'
+ type: :development
+ prerelease: false
+ version_requirements: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '4.1'
+- !ruby/object:Gem::Dependency
+ name: ronn
+ requirement: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '0.7'
+ type: :development
+ prerelease: false
+ version_requirements: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '0.7'
+description: ! 'Inspired by ctemplate, Mustache is a framework-agnostic way to render
-date: 2011-05-26 00:00:00 -07:00
-default_executable:
-dependencies: []
-
-description: |
- Inspired by ctemplate, Mustache is a framework-agnostic way to render
logic-free views.
-
+
+
As ctemplates says, "It emphasizes separating logic from presentation:
+
it is impossible to embed application logic in this template
+
language.
-
+
+
Think of Mustache as a replacement for your views. Instead of views
+
consisting of ERB or HAML with random helpers and arbitrary logic,
+
your views are broken into two parts: a Ruby class and an HTML
+
template.
-email: chris at ozmm.org
-executables:
+'
+email: rokusu at gmail.com
+executables:
- mustache
extensions: []
-
extra_rdoc_files: []
-
-files:
+files:
+- LICENSE
- README.md
- Rakefile
-- LICENSE
+- bin/mustache
+- lib/mustache.rb
- lib/mustache/context.rb
+- lib/mustache/context_miss.rb
+- lib/mustache/enumerable.rb
- lib/mustache/generator.rb
- lib/mustache/parser.rb
- lib/mustache/settings.rb
-- lib/mustache/sinatra.rb
- lib/mustache/template.rb
+- lib/mustache/utils.rb
- lib/mustache/version.rb
-- lib/mustache.rb
-- lib/rack/bug/panels/mustache_panel/mustache_extension.rb
-- lib/rack/bug/panels/mustache_panel/view.mustache
-- lib/rack/bug/panels/mustache_panel.rb
-- bin/mustache
- man/mustache.1
- man/mustache.1.html
- man/mustache.1.ron
@@ -84,6 +165,8 @@ files:
- test/fixtures/inverted_section.rb
- test/fixtures/lambda.mustache
- test/fixtures/lambda.rb
+- test/fixtures/liberal.mustache
+- test/fixtures/liberal.rb
- test/fixtures/method_missing.rb
- test/fixtures/namespaced.mustache
- test/fixtures/namespaced.rb
@@ -98,6 +181,7 @@ files:
- test/fixtures/recursive.rb
- test/fixtures/simple.mustache
- test/fixtures/simple.rb
+- test/fixtures/simply_complicated.mustache
- test/fixtures/template_partial.mustache
- test/fixtures/template_partial.rb
- test/fixtures/template_partial.txt
@@ -111,39 +195,28 @@ files:
- test/partial_test.rb
- test/spec_test.rb
- test/template_test.rb
-has_rdoc: true
-homepage: http://github.com/defunkt/mustache
-licenses: []
-
+homepage: https://github.com/mustache/mustache
+licenses:
+- MIT
+metadata: {}
post_install_message:
rdoc_options: []
-
-require_paths:
+require_paths:
- lib
-required_ruby_version: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ">="
- - !ruby/object:Gem::Version
- hash: 3
- segments:
- - 0
- version: "0"
-required_rubygems_version: !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - ">="
- - !ruby/object:Gem::Version
- hash: 3
- segments:
- - 0
- version: "0"
+required_ruby_version: !ruby/object:Gem::Requirement
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ version: '2.0'
+required_rubygems_version: !ruby/object:Gem::Requirement
+ requirements:
+ - - ! '>='
+ - !ruby/object:Gem::Version
+ version: '0'
requirements: []
-
rubyforge_project:
-rubygems_version: 1.5.2
+rubygems_version: 2.4.5
signing_key:
-specification_version: 3
+specification_version: 4
summary: Mustache is a framework-agnostic way to render logic-free views.
test_files: []
-
diff --git a/test/autoloading_test.rb b/test/autoloading_test.rb
index cade6d4..0a7ad76 100644
--- a/test/autoloading_test.rb
+++ b/test/autoloading_test.rb
@@ -1,9 +1,8 @@
-$LOAD_PATH.unshift File.dirname(__FILE__)
-require 'helper'
+require_relative 'helper'
module TestViews; end
-class AutoloadingTest < Test::Unit::TestCase
+class AutoloadingTest < Minitest::Test
def setup
Mustache.view_path = File.dirname(__FILE__) + '/fixtures'
end
diff --git a/test/fixtures/comments.rb b/test/fixtures/comments.rb
index 7b2bebd..d9535d8 100644
--- a/test/fixtures/comments.rb
+++ b/test/fixtures/comments.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class Comments < Mustache
diff --git a/test/fixtures/complex_view.rb b/test/fixtures/complex_view.rb
index 99d5c46..980933e 100644
--- a/test/fixtures/complex_view.rb
+++ b/test/fixtures/complex_view.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class ComplexView < Mustache
diff --git a/test/fixtures/crazy_recursive.rb b/test/fixtures/crazy_recursive.rb
index 36574ff..405aad7 100644
--- a/test/fixtures/crazy_recursive.rb
+++ b/test/fixtures/crazy_recursive.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class CrazyRecursive < Mustache
diff --git a/test/fixtures/delimiters.rb b/test/fixtures/delimiters.rb
index 884b098..ec98952 100644
--- a/test/fixtures/delimiters.rb
+++ b/test/fixtures/delimiters.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class Delimiters < Mustache
diff --git a/test/fixtures/dot_notation.rb b/test/fixtures/dot_notation.rb
index 1bafb01..70c09cd 100644
--- a/test/fixtures/dot_notation.rb
+++ b/test/fixtures/dot_notation.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class DotNotation < Mustache
diff --git a/test/fixtures/double_section.rb b/test/fixtures/double_section.rb
index d46d8c9..c196235 100644
--- a/test/fixtures/double_section.rb
+++ b/test/fixtures/double_section.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class DoubleSection < Mustache
diff --git a/test/fixtures/inverted_section.rb b/test/fixtures/inverted_section.rb
index de57909..d3e7740 100644
--- a/test/fixtures/inverted_section.rb
+++ b/test/fixtures/inverted_section.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class InvertedSection < Mustache
diff --git a/test/fixtures/lambda.rb b/test/fixtures/lambda.rb
index 930cdce..82f2571 100644
--- a/test/fixtures/lambda.rb
+++ b/test/fixtures/lambda.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class Lambda < Mustache
diff --git a/test/fixtures/liberal.mustache b/test/fixtures/liberal.mustache
new file mode 100644
index 0000000..b6c52f0
--- /dev/null
+++ b/test/fixtures/liberal.mustache
@@ -0,0 +1 @@
+{{first-name}} {{middle_name!}} {{lastName?}}
diff --git a/test/fixtures/liberal.rb b/test/fixtures/liberal.rb
new file mode 100644
index 0000000..843a33a
--- /dev/null
+++ b/test/fixtures/liberal.rb
@@ -0,0 +1,21 @@
+require 'mustache'
+
+class Liberal < Mustache
+ self.path = File.dirname(__FILE__)
+
+ def first_name
+ "kevin"
+ end
+
+ def middle_name!
+ 'j'
+ end
+
+ def lastName?
+ 'sheurs'
+ end
+end
+
+if $0 == __FILE__
+ puts Liberal.to_html
+end
diff --git a/test/fixtures/method_missing.rb b/test/fixtures/method_missing.rb
index 6d27d8f..5a49dd4 100644
--- a/test/fixtures/method_missing.rb
+++ b/test/fixtures/method_missing.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class MethodMissing < Mustache
diff --git a/test/fixtures/namespaced.rb b/test/fixtures/namespaced.rb
index 742f325..d81321f 100644
--- a/test/fixtures/namespaced.rb
+++ b/test/fixtures/namespaced.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
module TestViews
diff --git a/test/fixtures/nested_objects.rb b/test/fixtures/nested_objects.rb
index dd5afb2..031ec96 100644
--- a/test/fixtures/nested_objects.rb
+++ b/test/fixtures/nested_objects.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
require 'ostruct'
diff --git a/test/fixtures/partial_with_module.rb b/test/fixtures/partial_with_module.rb
index 511ab75..d4fe4c2 100644
--- a/test/fixtures/partial_with_module.rb
+++ b/test/fixtures/partial_with_module.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
module SimpleView
diff --git a/test/fixtures/passenger.rb b/test/fixtures/passenger.rb
index 79312a8..cbbad4b 100644
--- a/test/fixtures/passenger.rb
+++ b/test/fixtures/passenger.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class Passenger < Mustache
diff --git a/test/fixtures/recursive.rb b/test/fixtures/recursive.rb
index 595d0c6..74b00f5 100644
--- a/test/fixtures/recursive.rb
+++ b/test/fixtures/recursive.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class Recursive < Mustache
diff --git a/test/fixtures/simple.rb b/test/fixtures/simple.rb
index 8072466..ee753d5 100644
--- a/test/fixtures/simple.rb
+++ b/test/fixtures/simple.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class Simple < Mustache
diff --git a/test/fixtures/simply_complicated.mustache b/test/fixtures/simply_complicated.mustache
new file mode 100644
index 0000000..0297d13
--- /dev/null
+++ b/test/fixtures/simply_complicated.mustache
@@ -0,0 +1,25 @@
+Hi there {{yourname}}. Your home directory is {{HOME}}.
+
+{{#friend}}
+Your friend is named {{name}}
+ {{#morr}}
+ Hey {{word}} {{up}} {{{awesomesauce}}}.
+ {{/morr}}
+ {{^morr}}
+ Booooo. {{hiss}}
+ {{/morr}}
+ {{notinmorr}}
+ {{> partial1}}
+{{/friend}}
+{{^friend}}
+You have no friends, {{person}}. You suck.
+{{/friend}}
+
+{{> partial2}}
+{{! comments are awesome }}
+
+{{={% %}=}}
+
+{%love%}
+{%={{ }}=%}
+{{{triplestash}}}
diff --git a/test/fixtures/template_partial.rb b/test/fixtures/template_partial.rb
index c2d460e..49f3cf2 100644
--- a/test/fixtures/template_partial.rb
+++ b/test/fixtures/template_partial.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class TemplatePartial < Mustache
diff --git a/test/fixtures/unescaped.rb b/test/fixtures/unescaped.rb
index 538ada8..c0b8852 100644
--- a/test/fixtures/unescaped.rb
+++ b/test/fixtures/unescaped.rb
@@ -1,4 +1,3 @@
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
require 'mustache'
class Unescaped < Mustache
diff --git a/test/helper.rb b/test/helper.rb
index 8412a64..81112cd 100644
--- a/test/helper.rb
+++ b/test/helper.rb
@@ -1,6 +1,7 @@
-require 'test/unit'
+require 'minitest/autorun'
-$LOAD_PATH.unshift File.dirname(__FILE__) + '/fixtures'
+require "codeclimate-test-reporter"
+CodeClimate::TestReporter.start
Dir[File.dirname(__FILE__) + '/fixtures/*.rb'].each do |f|
require f
diff --git a/test/mustache_test.rb b/test/mustache_test.rb
index 82ee522..e05cfcb 100644
--- a/test/mustache_test.rb
+++ b/test/mustache_test.rb
@@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
-$LOAD_PATH.unshift File.dirname(__FILE__)
-require 'helper'
+require_relative 'helper'
-class MustacheTest < Test::Unit::TestCase
+class MustacheTest < Minitest::Test
def test_instance_render
klass = Class.new(Mustache)
klass.template = "Hi {{thing}}!"
@@ -15,7 +14,7 @@ end_simple
end
def test_passenger
- assert_equal <<-end_passenger, Passenger.to_text
+ assert_equal <<-end_passenger, Passenger.render
<VirtualHost *>
ServerName example.com
DocumentRoot /var/www/example.com
@@ -279,14 +278,19 @@ data
RailsEnv production
</VirtualHost>
data
- old_path, Mustache.template_path = Mustache.template_path, File.dirname(__FILE__) + "/fixtures"
- old_extension, Mustache.template_extension = Mustache.template_extension, "conf"
+ old_path = Mustache.template_path
+ old_extension = Mustache.template_extension
- assert_equal expected, Mustache.render(:passenger, :stage => 'production',
- :server => 'example.com',
- :deploy_to => '/var/www/example.com' )
-
- Mustache.template_path, Mustache.template_extension = old_path, old_extension
+ begin
+ Mustache.template_path = File.dirname(__FILE__) + "/fixtures"
+ Mustache.template_extension = "conf"
+
+ assert_equal expected, Mustache.render(:passenger, :stage => 'production',
+ :server => 'example.com',
+ :deploy_to => '/var/www/example.com')
+ ensure
+ Mustache.template_path, Mustache.template_extension = old_path, old_extension
+ end
end
def test_doesnt_execute_what_it_doesnt_need_to
@@ -344,6 +348,63 @@ data
assert_equal ' <li>1234</li> ', instance.render
end
+ def test_enumerable_sections_enumerate_mustache_enumerables
+ person = Struct.new(:name, :age)
+ people_array = []
+ people_array << person.new('Juliet', 13)
+ people_array << person.new('Romeo', 16)
+ people = Class.new do
+ include Enumerable
+ include Mustache::Enumerable
+
+ def initialize array
+ @people = array
+ end
+
+ def each *args, &block
+ @people.each *args, &block
+ end
+ end
+
+ view = Mustache.new
+ view[:people] = people.new(people_array)
+ view.template = <<-TEMPLATE
+{{#people}}
+{{name}} is {{age}}
+{{/people}}
+ TEMPLATE
+ assert_equal <<-EXPECTED, view.render
+Juliet is 13
+Romeo is 16
+ EXPECTED
+ end
+
+ def test_enumerable_sections_do_not_enumerate_untagged_enumerables
+ people = Struct.new(:first, :second, :third)
+ person = Struct.new(:name, :age)
+
+ view = Mustache.new
+ view[:people] = people.new(person.new("Mercutio", 17), person.new("Tybalt", 20), person.new("Benvolio", 15))
+ view.template = <<-TEMPLATE
+{{#people}}
+{{#first}}
+{{name}} is {{age}}
+{{/first}}
+{{#second}}
+{{name}} is {{age}}
+{{/second}}
+{{#third}}
+{{name}} is {{age}}
+{{/third}}
+{{/people}}
+ TEMPLATE
+ assert_equal <<-EXPECTED, view.render
+Mercutio is 17
+Tybalt is 20
+Benvolio is 15
+ EXPECTED
+ end
+
def test_not_found_in_context_renders_empty_string
instance = Mustache.new
instance.template = '{{#list}} <li>{{item}}</li> {{/list}}'
@@ -372,7 +433,7 @@ data
def test_knows_when_its_been_compiled_when_set_with_string
klass = Class.new(Mustache)
- assert ! klass.compiled?
+ refute klass.compiled?
klass.template = 'Hi, {{person}}!'
assert klass.compiled?
end
@@ -381,28 +442,29 @@ data
klass = Class.new(Simple)
klass.template_file = File.dirname(__FILE__) + '/fixtures/simple.mustache'
- assert ! klass.compiled?
+ refute klass.compiled?
klass.render
assert klass.compiled?
end
def test_an_instance_knows_when_its_class_is_compiled
- instance = Simple.new
+ klass = Class.new(Simple)
+ instance = klass.new
- assert ! Simple.compiled?
- assert ! instance.compiled?
+ refute klass.compiled?, "Simple was already compiled (from class)."
+ refute instance.compiled?, "Simple was already compiled (from instance)."
- Simple.render
+ klass.render
- assert Simple.compiled?
- assert instance.compiled?
+ assert klass.compiled?, "Simple was not compiled (from class)."
+ assert instance.compiled?, "Simple was not compiled (from instance)."
end
def test_knows_when_its_been_compiled_at_the_instance_level
klass = Class.new(Mustache)
instance = klass.new
- assert ! instance.compiled?
+ refute instance.compiled?
instance.template = 'Hi, {{person}}!'
assert instance.compiled?
end
@@ -454,6 +516,12 @@ data
assert_equal "chris j strath", Mustache.render(template, hash)
end
+ def test_liberal_tag_names_in_class
+ assert_equal <<-end_liberal, Liberal.render
+kevin j sheurs
+end_liberal
+ end
+
def test_nested_sections_same_names
template = <<template
{{#items}}
@@ -614,7 +682,8 @@ text
assert_equal value, tmpl.send(attr)
end
end
- def test_array_of_arrays
+
+ def test_array_of_arrays
template = <<template
{{#items}}
start
@@ -651,7 +720,8 @@ start
end
expected
end
- def test_indentation_again
+
+ def test_indentation_again
template = <<template
SELECT
{{#cols}}
@@ -674,4 +744,20 @@ FROM
DUMMY1
template
end
+
+ def test_cast_to_hash_in_context
+ hashlike = Object.new
+ def hashlike.title
+ 'title'
+ end
+ def hashlike.to_hash
+ { title: 'title' }
+ end
+
+ template = '%%{{title}}%%'
+
+ assert_equal '%%title%%', Mustache.render(template, hashlike)
+
+ end
+
end
diff --git a/test/parser_test.rb b/test/parser_test.rb
index 48111d1..38a6012 100644
--- a/test/parser_test.rb
+++ b/test/parser_test.rb
@@ -1,7 +1,21 @@
-$LOAD_PATH.unshift File.dirname(__FILE__)
-require 'helper'
+require_relative 'helper'
+
+class ParserTest < Minitest::Test
+
+ def test_parser_extension
+ parser = Mustache::Parser.new
+ parser.instance_variable_set :@result, 'zomg'
+ Mustache::Parser.add_type(:'@', :'$') do |*args|
+ [:mustache, :at_sign, @result, *args]
+ end
+ assert_match Mustache::Parser.valid_types, '@'
+ assert_match Mustache::Parser.valid_types, '$'
+ assert_equal [:mustache, :at_sign, 'zomg', 1, 2, 3],
+ parser.send('scan_tag_@', 1, 2, 3)
+ assert_equal [:mustache, :at_sign, 'zomg', 1, 2, 3],
+ parser.send('scan_tag_$', 1, 2, 3)
+ end
-class ParserTest < Test::Unit::TestCase
def test_parser
lexer = Mustache::Parser.new
tokens = lexer.compile(<<-EOF)
@@ -22,29 +36,32 @@ EOF
expected = [:multi,
[:static, "<h1>"],
- [:mustache, :etag, [:mustache, :fetch, ["header"]]],
+ [:mustache, :etag, [:mustache, :fetch, ["header"]], [1, 11]],
[:static, "</h1>\n"],
[:mustache,
:section,
[:mustache, :fetch, ["items"]],
+ [2, 7],
[:multi,
[:mustache,
:section,
[:mustache, :fetch, ["first"]],
+ [3, 7],
[:multi,
[:static, " <li><strong>"],
- [:mustache, :etag, [:mustache, :fetch, ["name"]]],
+ [:mustache, :etag, [:mustache, :fetch, ["name"]], [4, 19]],
[:static, "</strong></li>\n"]],
%Q' <li><strong>{{name}}</strong></li>\n',
%w[{{ }}]],
[:mustache,
:section,
[:mustache, :fetch, ["link"]],
+ [6, 6],
[:multi,
[:static, " <li><a href=\""],
- [:mustache, :etag, [:mustache, :fetch, ["url"]]],
+ [:mustache, :etag, [:mustache, :fetch, ["url"]], [7, 19]],
[:static, "\">"],
- [:mustache, :etag, [:mustache, :fetch, ["name"]]],
+ [:mustache, :etag, [:mustache, :fetch, ["name"]], [7, 29]],
[:static, "</a></li>\n"]],
%Q' <li><a href="{{url}}">{{name}}</a></li>\n',
%w[{{ }}]]],
@@ -54,6 +71,7 @@ EOF
[:mustache,
:section,
[:mustache, :fetch, ["empty"]],
+ [11, 7],
[:multi, [:static, "<p>The list is empty.</p>\n"]],
%Q'<p>The list is empty.</p>\n',
%w[{{ }}]]]
@@ -69,6 +87,7 @@ EOF
[:mustache,
:section,
[:mustache, :fetch, ["list"]],
+ [1, 6],
[:multi, [:static, "\t"]],
"\t",
%w[{{ }}]]]
diff --git a/test/partial_test.rb b/test/partial_test.rb
index 93310b5..b510140 100644
--- a/test/partial_test.rb
+++ b/test/partial_test.rb
@@ -1,7 +1,6 @@
-$LOAD_PATH.unshift File.dirname(__FILE__)
-require 'helper'
+require_relative 'helper'
-class PartialTest < Test::Unit::TestCase
+class PartialTest < Minitest::Test
def test_view_partial
assert_equal <<-end_partial.strip, PartialWithModule.render
<h1>Welcome</h1>
@@ -87,7 +86,7 @@ Welcome
end_partial
end
- def test_recursive_paritals
+ def test_recursive_partials
assert_equal <<-end_partial, Recursive.render
It works!
end_partial
diff --git a/test/spec_test.rb b/test/spec_test.rb
index d20263e..4f015ea 100644
--- a/test/spec_test.rb
+++ b/test/spec_test.rb
@@ -1,16 +1,16 @@
require 'mustache'
require 'tmpdir'
require 'yaml'
-require 'test/unit'
+require 'minitest/autorun'
-# Automatically process !code types into Proc objects
-YAML::add_builtin_type('code') { |_, val| eval(val['ruby']) }
+# Calls appropriate method on YAML. See: https://gist.github.com/tenderlove/958999ab4240b93bd3cd
+YAML.add_domain_type(nil, 'code') { |_, val| eval(val['ruby']) }
# A simple base class for Mustache specs.
# Creates a partials directory, then points a (dynamic) subclass of Mustache at
# that directory before each test; the partials directory is destroyed after
# each test is run.
-class MustacheSpec < Test::Unit::TestCase
+class MustacheSpec < Minitest::Test
def setup
@partials = File.join(File.dirname(__FILE__), 'partials')
Dir.mkdir(@partials)
@@ -59,7 +59,7 @@ Dir[spec_files].each do |file|
test_suite.class_eval do
spec['tests'].each do |test|
- define_method :"test - #{test['name']}" do
+ define_method :"test_spec - #{test['name']}" do
setup_partials(test)
assert_mustache_spec(test)
end
diff --git a/test/template_test.rb b/test/template_test.rb
index f01e9de..474dd4c 100644
--- a/test/template_test.rb
+++ b/test/template_test.rb
@@ -1,7 +1,6 @@
-$LOAD_PATH.unshift File.dirname(__FILE__)
-require 'helper'
+require_relative 'helper'
-class TemplateTest < Test::Unit::TestCase
+class TemplateTest < Minitest::Test
def test_compile
assert_equal %("foo"), Mustache::Template.new("foo").compile
end
@@ -18,3 +17,36 @@ class TemplateTest < Test::Unit::TestCase
assert_equal [:multi, [:static, "bar"]], Mustache::Template.new("foo").tokens("bar")
end
end
+
+class TemplateTest2 < Minitest::Test
+ def setup
+ @@template_text ||= File.read(File.dirname(__FILE__) + "/fixtures/simply_complicated.mustache")
+ @template = Mustache::Template.new(@@template_text)
+ end
+
+ def test_tags
+ assert_equal [
+ "yourname",
+ "HOME",
+ "friend.name",
+ "friend.morr.word",
+ "friend.morr.up",
+ "friend.morr.awesomesauce",
+ "friend.morr.hiss",
+ "friend.notinmorr",
+ "friend.person",
+ "love",
+ "triplestash"
+ ], @template.tags
+ end
+
+ def test_partials
+ assert_equal ["partial1", "partial2"], @template.partials
+ end
+
+ def test_sections
+ assert_equal ["friend", "friend.morr"], @template.sections
+ end
+end
+
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-mustache.git
More information about the Pkg-ruby-extras-commits
mailing list