mustache-0.99.4/0000755000175000017500000000000011643306253013367 5ustar virtualvirtualmustache-0.99.4/metadata.yml0000644000175000017500000000721311643306253015675 0ustar virtualvirtual--- !ruby/object:Gem::Specification name: mustache version: !ruby/object:Gem::Version hash: 411 prerelease: segments: - 0 - 99 - 4 version: 0.99.4 platform: ruby authors: - Chris Wanstrath - Magnus Holm - Pieter van de Bruggen autorequire: bindir: bin cert_chain: [] 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@ozmm.org executables: - mustache extensions: [] extra_rdoc_files: [] files: - README.md - Rakefile - LICENSE - lib/mustache/context.rb - lib/mustache/generator.rb - lib/mustache/parser.rb - lib/mustache/settings.rb - lib/mustache/sinatra.rb - lib/mustache/template.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 - man/mustache.5 - man/mustache.5.html - man/mustache.5.ron - test/autoloading_test.rb - test/fixtures/comments.mustache - test/fixtures/comments.rb - test/fixtures/complex_view.mustache - test/fixtures/complex_view.rb - test/fixtures/crazy_recursive.mustache - test/fixtures/crazy_recursive.rb - test/fixtures/delimiters.mustache - test/fixtures/delimiters.rb - test/fixtures/dot_notation.mustache - test/fixtures/dot_notation.rb - test/fixtures/double_section.mustache - test/fixtures/double_section.rb - test/fixtures/escaped.mustache - test/fixtures/escaped.rb - test/fixtures/inner_partial.mustache - test/fixtures/inner_partial.txt - test/fixtures/inverted_section.mustache - test/fixtures/inverted_section.rb - test/fixtures/lambda.mustache - test/fixtures/lambda.rb - test/fixtures/method_missing.rb - test/fixtures/namespaced.mustache - test/fixtures/namespaced.rb - test/fixtures/nested_objects.mustache - test/fixtures/nested_objects.rb - test/fixtures/node.mustache - test/fixtures/partial_with_module.mustache - test/fixtures/partial_with_module.rb - test/fixtures/passenger.conf - test/fixtures/passenger.rb - test/fixtures/recursive.mustache - test/fixtures/recursive.rb - test/fixtures/simple.mustache - test/fixtures/simple.rb - test/fixtures/template_partial.mustache - test/fixtures/template_partial.rb - test/fixtures/template_partial.txt - test/fixtures/unescaped.mustache - test/fixtures/unescaped.rb - test/fixtures/utf8.mustache - test/fixtures/utf8_partial.mustache - test/helper.rb - test/mustache_test.rb - test/parser_test.rb - test/partial_test.rb - test/spec_test.rb - test/template_test.rb has_rdoc: true homepage: http://github.com/defunkt/mustache licenses: [] post_install_message: rdoc_options: [] 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" requirements: [] rubyforge_project: rubygems_version: 1.5.2 signing_key: specification_version: 3 summary: Mustache is a framework-agnostic way to render logic-free views. test_files: [] mustache-0.99.4/README.md0000644000175000017500000002323111643306253014647 0ustar virtualvirtualMustache ========= Inspired by [ctemplate][1] and [et][2], 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." For a list of implementations (other than Ruby) and tips, see . Overview -------- 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. We call the Ruby class the "view" and the HTML template the "template." All your logic, decisions, and code is contained in your view. All your markup is contained in your template. The template does nothing but reference methods in your view. 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? ---- I like writing Ruby. I like writing HTML. I like writing JavaScript. I don't like writing ERB, Haml, Liquid, Django Templates, putting Ruby in my HTML, or putting JavaScript in my HTML. Usage ----- Quick example: >> require 'mustache' => true >> Mustache.render("Hello {{planet}}", :planet => "World!") => "Hello World!" We've got an `examples` folder but here's the canonical one: class Simple < Mustache def name "Chris" end def value 10_000 end def taxed_value value * 0.6 end def in_ca true end end We simply create a normal Ruby class and define methods. Some methods reference others, some return values, some return only booleans. Now let's write the template: Hello {{name}} You have just won {{value}} dollars! {{#in_ca}} Well, {{taxed_value}} dollars, after taxes. {{/in_ca}} This template references our view methods. To bring it all together, here's the code to render actual HTML; Simple.render Which returns the following: Hello Chris You have just won 10000 dollars! Well, 6000.0 dollars, after taxes. Simple. Tag Types --------- For a language-agnostic overview of Mustache's template syntax, see the `mustache(5)` manpage or . 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}}}`. 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 ---------------- ctemplate and friends want you to hand a dictionary to the template processor. Mustache supports a similar concept. Feel free to mix the class-based and this more procedural style at your leisure. Given this template (winner.mustache): Hello {{name}} You have just won {{value}} bucks! We can fill in the values at will: view = Winner.new view[:name] = 'George' view[:value] = 100 view.render Which returns: Hello George You have just won 100 bucks! We can re-use the same object, too: view[:name] = 'Tony' view.render Hello Tony You have just won 100 bucks! 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 follows the classic Ruby naming convention. TemplatePartial => ./template_partial.mustache You can set the search path using `Mustache.template_path`. It can be set on a class by class basis: class Simple < Mustache self.template_path = File.dirname(__FILE__) ... etc ... end Now `Simple` will look for `simple.mustache` in the directory it resides in, no matter the cwd. If you want to just change what template is used you can set `Mustache.template_file` directly: Simple.template_file = './blah.mustache' Mustache also allows you to define the extension it'll use. Simple.template_extension = 'xml' Given all other defaults, the above line will cause Mustache to look for './blah.xml' Feel free to set the template directly: Simple.template = 'Hi {{person}}!' Or set a different template for a single instance: Simple.new.template = 'Hi {{person}}!' Whatever works. 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, etc), check out the `view_namespace` and `view_path` settings on the `Mustache` class. They will surely provide needed assistance. Helpers ------- What about global helpers? Maybe you have a nifty `gravatar` function you want to use in all your views? No problem. This is just Ruby, after all. module ViewHelpers def gravatar gravatar_id = Digest::MD5.hexdigest(self[:email].to_s.strip.downcase) gravatar_for_id(gravatar_id) end def gravatar_for_id(gid, size = 30) "#{gravatar_host}/avatar/#{gid}?s=#{size}" end def gravatar_host @ssl ? 'https://secure.gravatar.com' : 'http://www.gravatar.com' end end Then just include it: class Simple < Mustache include ViewHelpers def name "Chris" end def value 10_000 end def taxed_value value * 0.6 end def in_ca true end def users User.all end end 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 are free to use the `initialize` method just as you would in any normal class. class Simple < Mustache include ViewHelpers def initialize(ssl = false) @ssl = ssl end ... etc ... end Now: Simple.new(request.ssl?).render Finally, our template might look like this: Sinatra ------- Mustache ships with Sinatra integration. Please see `lib/mustache/sinatra.rb` or for complete documentation. An example Sinatra application is also provided: 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 do. Basically, things are named properly now and all should be contained in a hash set using `set :mustache, hash`. [Rack::Bug][4] -------------- Mustache also ships with a `Rack::Bug` panel. In your `config.ru` add the following code: require 'rack/bug/panels/mustache_panel' use Rack::Bug::MustachePanel 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] Vim --- Thanks to [Juvenn Woo](http://github.com/juvenn) for mustache.vim. It is included under the contrib/ directory. See for installation instructions. 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 for installation instructions. TextMate -------- [Mustache.tmbundle](http://github.com/defunkt/Mustache.tmbundle) See for installation instructions. Command Line ------------ See `mustache(1)` man page or for command line docs. Installation ------------ ### [RubyGems](http://rubygems.org/) $ gem install mustache 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." Special thanks to [Magnus Holm](http://judofyr.net/) for all his awesome work on Mustache's parser. Contributing ------------ Once you've made your great commits: 1. [Fork][fk] Mustache 2. Create a topic branch - `git checkout -b my_branch` 3. Push to your branch - `git push origin my_branch` 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 ------------ To join the list simply send an email to . This will subscribe you and send you information about your subscription, including unsubscribe information. The archive can be found at . Meta ---- * Code: `git clone git://github.com/defunkt/mustache.git` * Home: * Bugs: * List: * Test: * Gems: You can also find us in `#{` on irc.freenode.net. [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/ [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 mustache-0.99.4/bin/0000755000175000017500000000000011643306253014137 5ustar virtualvirtualmustache-0.99.4/bin/mustache0000755000175000017500000000455611643306253015710 0ustar virtualvirtual#!/usr/bin/env ruby require 'yaml' require 'optparse' require 'mustache' require 'mustache/version' class Mustache class CLI # Return a structure describing the options. def self.parse_options(args) opts = OptionParser.new do |opts| opts.banner = "Usage: mustache [-c] [-t] [-r library] FILE ..." opts.separator " " opts.separator "Examples:" opts.separator " $ mustache data.yml template.mustache" opts.separator " $ cat data.yml | mustache - template.mustache" opts.separator " $ mustache -c template.mustache" opts.separator " " opts.separator " See mustache(1) or " + "http://mustache.github.com/mustache.1.html" opts.separator " for more details." opts.separator " " opts.separator "Options:" opts.on("-c", "--compile FILE", "Print the compiled Ruby for a given template.") do |file| puts Mustache::Template.new(File.read(file)).compile exit end opts.on("-t", "--tokens FILE", "Print the tokenized form of a given template.") do |file| require 'pp' pp Mustache::Template.new(File.read(file)).tokens exit end opts.on('-r', '--require LIB', 'Require a Ruby library before running.') do |lib| require lib end opts.separator "Common Options:" opts.on("-v", "--version", "Print the version") do |v| puts "Mustache v#{Mustache::Version}" exit end opts.on_tail("-h", "--help", "Show this message") do puts opts exit end end opts.separator "" 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 if doc =~ /^(\s*---(.+)---\s*)/m yaml = $2.strip template = doc.sub($1, '') YAML.each_document(yaml) do |data| puts Mustache.render(template, data) end else puts Mustache.render(doc) end end end end # Help is the default. ARGV << '-h' if ARGV.empty? && $stdin.tty? # Process options Mustache::CLI.parse_options(ARGV) if $stdin.tty? # Still here - process ARGF Mustache::CLI.process_files(ARGF) mustache-0.99.4/LICENSE0000644000175000017500000000204311643306253014373 0ustar virtualvirtualCopyright (c) 2009 Chris Wanstrath Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. mustache-0.99.4/lib/0000755000175000017500000000000011643306253014135 5ustar virtualvirtualmustache-0.99.4/lib/mustache/0000755000175000017500000000000011643306253015746 5ustar virtualvirtualmustache-0.99.4/lib/mustache/generator.rb0000644000175000017500000001272711643306253020272 0ustar virtualvirtualclass Mustache # The Generator is in charge of taking an array of Mustache tokens, # usually assembled by the Parser, and generating an interpolatable # Ruby string. This string is considered the "compiled" template # because at that point we're relying on Ruby to do the parsing and # run our code. # # For example, let's take this template: # # Hi {{thing}}! # # If we run this through the Parser we'll get these tokens: # # [:multi, # [:static, "Hi "], # [:mustache, :etag, "thing"], # [:static, "!\n"]] # # Now let's hand that to the Generator: # # >> puts Mustache::Generator.new.compile(tokens) # "Hi #{CGI.escapeHTML(ctx[:thing].to_s)}!\n" # # You can see the generated Ruby string for any template with the # mustache(1) command line tool: # # $ mustache --compile test.mustache # "Hi #{CGI.escapeHTML(ctx[:thing].to_s)}!\n" class Generator # Options are unused for now but may become useful in the future. def initialize(options = {}) @options = options end # Given an array of tokens, returns an interpolatable Ruby string. def compile(exp) "\"#{compile!(exp)}\"" end # Given an array of tokens, converts them into Ruby code. In # particular there are three types of expressions we are concerned # with: # # :multi # Mixed bag of :static, :mustache, and whatever. # # :static # Normal HTML, the stuff outside of {{mustaches}}. # # :mustache # Any Mustache tag, from sections to partials. # # To give you an idea of what you'll be dealing with take this # template: # # Hello {{name}} # You have just won ${{value}}! # {{#in_ca}} # Well, ${{taxed_value}}, after taxes. # {{/in_ca}} # # If we run this through the Parser, we'll get back this array of # tokens: # # [:multi, # [:static, "Hello "], # [:mustache, :etag, "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"]]]] def compile!(exp) case exp.first when :multi exp[1..-1].map { |e| compile!(e) }.join when :static str(exp[1]) when :mustache send("on_#{exp[1]}", *exp[2..-1]) else raise "Unhandled exp: #{exp.first}" end end # 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) # Convert the tokenized content of this section into a Ruby # string we can use. code = compile(content) # Compile the Ruby for this section now that we know what's # inside the section. ev(<<-compiled) if v = #{compile!(name)} if v == true #{code} elsif v.is_a?(Proc) t = Mustache::Template.new(v.call(#{raw.inspect}).to_s) def t.tokens(src=@source) p = Parser.new p.otag, p.ctag = #{delims.inspect} p.compile(src) end t.render(ctx.dup) else # Shortcut when passed non-array v = [v] unless v.is_a?(Array) || defined?(Enumerator) && v.is_a?(Enumerator) v.map { |h| ctx.push(h); r = #{code}; ctx.pop; r }.join end end compiled end # 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, _) # Convert the tokenized content of this section into a Ruby # string we can use. code = compile(content) # Compile the Ruby for this inverted section now that we know # what's inside. ev(<<-compiled) v = #{compile!(name)} if v.nil? || v == false || v.respond_to?(:empty?) && v.empty? #{code} end compiled end # 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) ev("ctx.partial(#{name.to_sym.inspect}, #{indentation.inspect})") end # An unescaped tag. def on_utag(name) ev(<<-compiled) v = #{compile!(name)} if v.is_a?(Proc) v = Mustache::Template.new(v.call.to_s).render(ctx.dup) end v.to_s compiled end # An escaped tag. def on_etag(name) ev(<<-compiled) v = #{compile!(name)} if v.is_a?(Proc) v = Mustache::Template.new(v.call.to_s).render(ctx.dup) end ctx.escapeHTML(v.to_s) compiled end def on_fetch(names) 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 end # An interpolation-friendly version of a string, for use within a # Ruby string. def ev(s) "#\{#{s}}" end def str(s) s.inspect[1..-2] end end end mustache-0.99.4/lib/mustache/version.rb0000644000175000017500000000006211643306253017756 0ustar virtualvirtualclass Mustache Version = VERSION = '0.99.4' end mustache-0.99.4/lib/mustache/parser.rb0000644000175000017500000001776211643306253017604 0ustar virtualvirtualrequire 'strscan' class Mustache # The Parser is responsible for taking a string template and # converting it into an array of tokens and, really, expressions. It # raises SyntaxError if there is anything it doesn't understand and # knows which sigil corresponds to which tag type. # # For example, given this template: # # Hi {{thing}}! # # Run through the Parser we'll get these tokens: # # [:multi, # [:static, "Hi "], # [:mustache, :etag, "thing"], # [:static, "!\n"]] # # You can see the array of tokens for any template with the # mustache(1) command line tool: # # $ mustache --tokens test.mustache # [:multi, [:static, "Hi "], [:mustache, :etag, "thing"], [:static, "!\n"]] class Parser # A SyntaxError is raised when the Parser comes across unclosed # tags, sections, illegal content in tags, or anything of that # sort. class SyntaxError < StandardError def initialize(message, position) @message = message @lineno, @column, @line, _ = position @stripped_line = @line.strip @stripped_column = @column - (@line.size - @line.lstrip.size) end def to_s <<-EOF #{@message} Line #{@lineno} #{@stripped_line} #{' ' * @stripped_column}^ EOF end 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 = [ '#', '^', '/', '<', '>', '=', '!' ] # 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 = [ '!', '=' ] attr_reader :scanner, :result attr_writer :otag, :ctag # Accepts an options hash which does nothing but may be used in # the future. def initialize(options = {}) @options = {} end # The opening tag delimiter. This may be changed at runtime. def otag @otag ||= '{{' end # The closing tag delimiter. This too may be changed at runtime. def ctag @ctag ||= '}}' end # Given a string template, returns an array of tokens. def compile(template) if template.respond_to?(:encoding) @encoding = template.encoding template = template.dup.force_encoding("BINARY") else @encoding = nil end # Keeps information about opened sections. @sections = [] @result = [:multi] @scanner = StringScanner.new(template) # Scan until the end of the template. until @scanner.eos? scan_tags || scan_text end if !@sections.empty? # We have parsed the whole file, but there's still opened sections. type, pos, result = @sections.pop error "Unclosed section #{type.inspect}", pos end @result end # Find {{mustaches}} and add them to the @result array. def scan_tags # Scan until we hit an opening delimiter. start_of_line = @scanner.beginning_of_line? pre_match_position = @scanner.pos last_index = @result.length return unless x = @scanner.scan(/([ \t]*)?#{Regexp.escape(otag)}/) padding = @scanner[1] || '' # Don't touch the preceding whitespace unless we're matching the start # of a new line. unless start_of_line @result << [:static, padding] unless padding.empty? pre_match_position += padding.length padding = '' end # Since {{= rewrites ctag, we store the ctag which should be used # when parsing this specific tag. current_ctag = self.ctag type = @scanner.scan(/#|\^|\/|=|!|<|>|&|\{/) @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 # We found {{ but we can't figure out what's going on inside. error "Illegal content in tag" if content.empty? 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 # 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 # 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 # from the beginning of the line, re-insert the padding as static text. if start_of_line && !@scanner.eos? if @scanner.peek(2) =~ /\r?\n/ && SKIP_WHITESPACE.include?(type) @scanner.skip(/\r?\n/) else prev.insert(last_index, [:static, padding]) unless padding.empty? end end # Store off the current scanner position now that we've closed the tag # and consumed any irrelevant whitespace. @sections.last[1] << @scanner.pos unless @sections.empty? return unless @result == [:multi] end # Try to find static text, e.g. raw HTML with no {{mustaches}}. def scan_text text = scan_until_exclusive(/(^[ \t]*)?#{Regexp.escape(otag)}/) if text.nil? # Couldn't find any otag, which means the rest is just static text. text = @scanner.rest # Mark as done. @scanner.terminate end text.force_encoding(@encoding) if @encoding @result << [:static, text] unless text.empty? end # Scans the string until the pattern is matched. Returns the substring # *excluding* the end of the match, advancing the scan pointer to that # location. If there is no match, nil is returned. def scan_until_exclusive(regexp) pos = @scanner.pos if @scanner.scan_until(regexp) @scanner.pos -= @scanner.matched.size @scanner.pre_match[pos..-1] end end # Returns [lineno, column, line] def position # The rest of the current line rest = @scanner.check_until(/\n|\Z/).to_s.chomp # What we have parsed so far parsed = @scanner.string[0...@scanner.pos] lines = parsed.split("\n") [ lines.size, lines.last.size - 1, lines.last + rest ] end # Used to quickly convert a string into a regular expression # usable by the string scanner. def regexp(thing) /#{Regexp.escape(thing)}/ end # Raises a SyntaxError. The message should be the name of the # error - other details such as line number and position are # handled for you. def error(message, pos = position) raise SyntaxError.new(message, pos) end end end mustache-0.99.4/lib/mustache/settings.rb0000644000175000017500000001233411643306253020136 0ustar virtualvirtual# Settings which can be configured for all view classes, a single # view class, or a single Mustache instance. class Mustache # # Template Path # # The template path informs your Mustache view where to look for its # corresponding template. By default it's the current directory (".") # # A class named Stat with a template_path of "app/templates" will look # for "app/templates/stat.mustache" def self.template_path @template_path ||= inheritable_config_for :template_path, '.' end def self.template_path=(path) @template_path = File.expand_path(path) @template = nil end def template_path @template_path ||= self.class.template_path end def template_path=(path) @template_path = File.expand_path(path) @template = nil end # Alias for `template_path` 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= # # Template Extension # # A Mustache template's default extension is 'mustache', but this can be changed. def self.template_extension @template_extension ||= inheritable_config_for :template_extension, 'mustache' end def self.template_extension=(template_extension) @template_extension = template_extension @template = nil end def template_extension @template_extension ||= self.class.template_extension end def template_extension=(template_extension) @template_extension = template_extension @template = nil end # # Template Name # # The template name is the Mustache template file without any # extension or other information. Defaults to `class_name`. # # You may want to change this if your class is named Stat but you want # to re-use another template. # # class Stat # self.template_name = "graphs" # use graphs.mustache # end def self.template_name @template_name || underscore end def self.template_name=(template_name) @template_name = template_name @template = nil end def template_name @template_name ||= self.class.template_name end def template_name=(template_name) @template_name = template_name @template = nil end # # Template File # # The template file is the absolute path of the file Mustache will # use as its template. By default it's ./class_name.mustache def self.template_file @template_file || "#{path}/#{template_name}.#{template_extension}" end def self.template_file=(template_file) @template_file = template_file @template = nil end # The template file is the absolute path of the file Mustache will # use as its template. By default it's ./class_name.mustache def template_file @template_file || "#{path}/#{template_name}.#{template_extension}" end def template_file=(template_file) @template_file = template_file @template = nil end # # Template # # The template is the actual string Mustache uses as its template. # There is a bit of magic here: what we get back is actually a # Mustache::Template object, but you can still safely use `template=` # with a string. def self.template @template ||= templateify(File.read(template_file)) end def self.template=(template) @template = templateify(template) end # The template can be set at the instance level. def template return @template if @template # If they sent any instance-level options use that instead of the class's. if @template_path || @template_extension || @template_name || @template_file @template = templateify(File.read(template_file)) else @template = self.class.template end end def template=(template) @template = templateify(template) end # # Raise on context miss # # Should an exception be raised when we cannot find a corresponding method # or key in the current context? By default this is false to emulate ctemplate's # behavior, but it may be useful to enable when debugging or developing. # # If set to true and there is a context miss, `Mustache::ContextMiss` will # be raised. def self.raise_on_context_miss? @raise_on_context_miss end def self.raise_on_context_miss=(boolean) @raise_on_context_miss = boolean end # Instance level version of `Mustache.raise_on_context_miss?` def raise_on_context_miss? self.class.raise_on_context_miss? || @raise_on_context_miss end def raise_on_context_miss=(boolean) @raise_on_context_miss = boolean end # # View Namespace # # The constant under which Mustache will look for views when autoloading. # By default the view namespace is `Object`, but it might be nice to set # it to something like `Hurl::Views` if your app's main namespace is `Hurl`. def self.view_namespace @view_namespace ||= inheritable_config_for(:view_namespace, Object) end def self.view_namespace=(namespace) @view_namespace = namespace end # # View Path # # Mustache searches the view path for .rb files to require when asked to find a # view class. Defaults to "." def self.view_path @view_path ||= inheritable_config_for(:view_path, '.') end def self.view_path=(path) @view_path = path end end mustache-0.99.4/lib/mustache/context.rb0000644000175000017500000001033511643306253017761 0ustar virtualvirtualclass 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`. def initialize(mustache) @stack = [mustache] end # A {{>partial}} tag translates into a call to the context's # `partial` method, which would be this sucker right here. # # 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 # Indent the partial template by the given indentation. part = mustache.partial(name).to_s.gsub(/^/, indentation) # Call the Mustache's `partial` method and render the result. result = 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. def mustache_in_stack @stack.detect { |frame| frame.is_a?(Mustache) } end # Allows customization of how Mustache escapes things. # # Returns a 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) self end alias_method :update, :push # Removes the most recently added object from the context's # internal stack. # # Returns the Context. def pop @stack.shift self end # Can be used to add a value to the context in a hash-like way. # # context[:name] = "Chris" def []=(name, value) push(name => value) end # Alias for `fetch`. def [](name) fetch(name, nil) end # 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) rescue ContextMiss false end # Similar to Hash#fetch, finds a value by `name` in the context's # stack. You may specify the default return value by passing a # second parameter. # # If no second parameter is passed (or raise_on_context_miss is # set to true), will raise a ContextMiss exception on miss. def fetch(name, default = :__raise) @stack.each do |frame| # Prevent infinite recursion. next if frame == self value = find(frame, name, :__missing) if value != :__missing return value end end if default == :__raise || mustache_in_stack.raise_on_context_miss? raise ContextMiss.new("Can't find #{name} in #{@stack.inspect}") else default end end # Finds a key in an object, using whatever method is most # appropriate. If the object is a hash, does a simple hash lookup. # 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. # # 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 end end end mustache-0.99.4/lib/mustache/template.rb0000644000175000017500000000345011643306253020110 0ustar virtualvirtualrequire 'cgi' require 'mustache/parser' require 'mustache/generator' class Mustache # A Template represents a Mustache template. It compiles and caches # a raw string template into something usable. # # The idea is this: when handed a Mustache template, convert it into # a Ruby string by transforming Mustache tags into interpolated # Ruby. # # You shouldn't use this class directly, instead: # # >> Mustache.render(template, hash) class Template attr_reader :source # Expects a Mustache template as a string along with a template # path, which it uses to find partials. def initialize(source) @source = source end # Renders the `@source` Mustache template using the given # `context`, which should be a simple hash keyed with symbols. # # The first time a template is rendered, this method is overriden # and from then on it is "compiled". Subsequent calls will skip # the compilation step and run the Ruby version of the template # directly. def render(context) # Compile our Mustache template into a Ruby string compiled = "def render(ctx) #{compile} end" # Here we rewrite ourself with the interpolated Ruby version of # our Mustache template so subsequent calls are very fast and # can skip the compilation stage. instance_eval(compiled, __FILE__, __LINE__ - 1) # Call the newly rewritten version of #render render(context) end # Does the dirty work of transforming a Mustache template into an # interpolation-friendly Ruby string. def compile(src = @source) Generator.new.compile(tokens(src)) end alias_method :to_s, :compile # Returns an array of tokens for a given template. def tokens(src = @source) Parser.new.compile(src) end end end mustache-0.99.4/lib/mustache/sinatra.rb0000644000175000017500000001502211643306253017734 0ustar virtualvirtualrequire '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 mustache-0.99.4/lib/rack/0000755000175000017500000000000011643306253015055 5ustar virtualvirtualmustache-0.99.4/lib/rack/bug/0000755000175000017500000000000011643306253015632 5ustar virtualvirtualmustache-0.99.4/lib/rack/bug/panels/0000755000175000017500000000000011643306253017114 5ustar virtualvirtualmustache-0.99.4/lib/rack/bug/panels/mustache_panel.rb0000644000175000017500000000455111643306253022436 0ustar virtualvirtualmodule 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 mustache-0.99.4/lib/rack/bug/panels/mustache_panel/0000755000175000017500000000000011643306253022104 5ustar virtualvirtualmustache-0.99.4/lib/rack/bug/panels/mustache_panel/mustache_extension.rb0000644000175000017500000000115711643306253026342 0ustar virtualvirtualif 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 mustache-0.99.4/lib/rack/bug/panels/mustache_panel/view.mustache0000644000175000017500000000136211643306253024613 0ustar virtualvirtual

Render Times

{{# times }} {{/ times }}
View Render Time
{{ key }} {{ value }}

Variables

{{# variables }} {{/ variables }}
Name Value
{{ key }} {{ value }}
mustache-0.99.4/lib/mustache.rb0000644000175000017500000002045411643306253016300 0ustar virtualvirtualrequire 'mustache/template' require 'mustache/context' require 'mustache/settings' # Mustache is the base class from which your Mustache subclasses # should inherit (though it can be used on its own). # # The typical Mustache workflow is as follows: # # * Create a Mustache subclass: class Stats < Mustache # * Create a template: stats.mustache # * Instantiate an instance: view = Stats.new # * Render that instance: view.render # # You can skip the instantiation by calling `Stats.render` directly. # # While Mustache will do its best to load and render a template for # you, this process is completely customizable using a few options. # # All settings can be overriden at the class level. # # For example, going with the above example, we can use # `Stats.template_path = "/usr/local/templates"` to specify the path # Mustache uses to find templates. # # Here are the available options: # # * template_path # # The `template_path` setting determines the path Mustache uses when # looking for a template. By default it is "." # Setting it to /usr/local/templates, for example, means (given all # other settings are default) a Mustache subclass `Stats` will try to # load /usr/local/templates/stats.mustache # # * template_extension # # The `template_extension` is the extension Mustache uses when looking # for template files. By default it is "mustache" # # * template_file # # You can tell Mustache exactly which template to us with this # setting. It can be a relative or absolute path. # # * template # # Sometimes you want Mustache to render a string, not a file. In those # cases you may set the `template` setting. For example: # # >> Mustache.render("Hello {{planet}}", :planet => "World!") # => "Hello World!" # # The `template` setting is also available on instances. # # view = Mustache.new # view.template = "Hi, {{person}}!" # view[:person] = 'Mom' # view.render # => Hi, mom! # # * view_namespace # # To make life easy on those developing Mustache plugins for web frameworks or # other libraries, Mustache will attempt to load view classes (i.e. Mustache # subclasses) using the `view_class` class method. The `view_namespace` tells # Mustache under which constant view classes live. By default it is `Object`. # # * view_path # # Similar to `template_path`, the `view_path` option tells Mustache where to look # for files containing view classes when using the `view_class` method. # 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 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.template = "Hi {{thing}}!" # @view = View.new # @view.render(:thing => :world) # # Returns a rendered String version of a template def render(data = template, ctx = {}) if data.is_a? Hash ctx = data tpl = templateify(template) elsif data.is_a? Symbol self.template_name = data tpl = templateify(template) else tpl = templateify(data) end return tpl.render(context) if ctx == {} begin context.push(ctx) tpl.render(context) ensure context.pop 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!" def [](key) context[key.to_sym] end def []=(key, value) context[key.to_sym] = value end # A helper method which gives access to the context at a given time. # Kind of a hack for now, but useful when you're in an iterating section # and want access to the hash currently being iterated over. def context @context ||= Context.new(self) end # Given a file name and an optional context, attempts to load and # render the file as a template. def self.render_file(name, context = {}) render(partial(name), context) end # Given a file name and an optional context, attempts to load and # render the file as a template. def render_file(name, context = {}) self.class.render_file(name, context) end # Given a name, attempts to read a file and return the contents as a # string. The file is not rendered, so it might contain # {{mustaches}}. # # Call `render` if you need to process it. def self.partial(name) File.read("#{template_path}/#{name}.#{template_extension}") 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) end # Override this to provide custom escaping. # # class PersonView < Mustache # def escapeHTML(str) # my_html_escape_method(str) # end # end # # Returns a String def escapeHTML(str) CGI.escapeHTML(str) end # # Private API # # When given a symbol or string representing a class, will try to produce an # appropriate view class. # e.g. # 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 # Emptiness begets emptiness. if name.to_s == '' return Mustache end file_name = underscore(name) name = "#{view_namespace}::#{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 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 rescue NameError nil 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('::') 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('/') end # Turns a string into a Mustache::Template. If passed a Template, # returns it. def self.templateify(obj) if obj.is_a?(Template) obj else Template.new(obj.to_s) end end def templateify(obj) self.class.templateify(obj) end # 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. # # Returns the inherited or default configuration setting. def self.inheritable_config_for(attr_name, default) superclass.respond_to?(attr_name) ? superclass.send(attr_name) : default end end mustache-0.99.4/man/0000755000175000017500000000000011643306253014142 5ustar virtualvirtualmustache-0.99.4/man/mustache.10000644000175000017500000000572611643306253016047 0ustar virtualvirtual.\" generated with Ronn/v0.5 .\" http://github.com/rtomayko/ronn/ . .TH "MUSTACHE" "1" "May 2010" "DEFUNKT" "Mustache Manual" . .SH "NAME" \fBmustache\fR \-\- Mustache processor . .SH "SYNOPSIS" . .nf mustache mustache \-\-compile mustache \-\-tokens . .fi . .SH "DESCRIPTION" 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. . .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. . .IP "" 4 . .nf \-\-\- names: [ {name: chris}, {name: mark}, {name: scott} ] \-\-\- . .fi . .IP "" 0 . .P 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. . .P For example: . .IP "" 4 . .nf {{#names}} Hi {{name}}! {{/names}} . .fi . .IP "" 0 . .P Now let's combine them. . .IP "" 4 . .nf $ cat data.yml \-\-\- names: [ {name: chris}, {name: mark}, {name: scott} ] \-\-\- $ cat template.mustache {{#names}} Hi {{name}}! {{/names}} $ cat data.yml template.mustache | mustache Hi chris! Hi mark! Hi scott! . .fi . .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. . .P For example: . .IP "" 4 . .nf $ cat data.yml \-\-\- name: chris \-\-\- name: mark \-\-\- name: scott \-\-\- $ cat template.mustache Hi {{name}}! $ cat data.yml template.mustache | mustache Hi chris! Hi mark! Hi scott! . .fi . .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. . .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. . .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. . .SH "INSTALLATION" If you have RubyGems installed: . .IP "" 4 . .nf gem install mustache . .fi . .IP "" 0 . .SH "EXAMPLES" . .nf $ mustache data.yml template.mustache $ cat data.yml | mustache \- template.mustache $ mustache \-c template.mustache $ cat <GitHub" } Output: * Chris * * <b>GitHub</b> * GitHub ### Sections Sections render blocks of text one 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, `{{#person}}` begins a "person" section while `{{/person}}` ends it. The behavior of the section is determined by the value of the key. **False Values or Empty Lists** If the `person` key exists and has a value of false or an empty list, the HTML between the pound and slash will not be displayed. Template: Shown. {{#nothin}} Never shown! {{/nothin}} Hash: { "person": true, } Output: Shown. **Non-Empty Lists** If the `person` key exists and has a non-false value, the HTML between the pound and slash will be rendered and displayed one or more times. 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. Template: {{#repo}} {{name}} {{/repo}} Hash: { "repo": [ { "name": "resque" }, { "name": "hub" }, { "name": "rip" }, ] } Output: resque hub rip **Lambdas** 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. `{{tags}}` will not have been expanded - the lambda should do that on its own. In this way you can implement filters or caching. Template: {{#wrapped}} {{name}} is awesome. {{/wrapped}} Hash: { "name": "Willy", "wrapped": function() { return function(text) { return "" + render(text) + "" } } } Output: Willy is awesome. **Non-False Values** When the value is non-false but not a list, it will be used as the context for a single rendering of the block. Template: {{#person?}} Hi {{name}}! {{/person?}} Hash: { "person?": { "name": "Jon" } } Output: Hi Jon! ### Inverted Sections 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 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. Template: {{#repo}} {{name}} {{/repo}} {{^repo}} No repos :( {{/repo}} Hash: { "repo": [] } Output: No repos :( ### Comments Comments begin with a bang and are ignored. The following template:

Today{{! ignore me }}.

Will render as follows:

Today.

Comments may contain newlines. ### Partials Partials begin with a greater than sign, like `{{> box}}`. Partials are rendered at runtime (as opposed to compile time), so recursive partials are possible. Just avoid infinite loops. They also inherit the calling context. Whereas in ERB you may have this: <%= partial :next_more, :start => start, :size => size %> Mustache requires only this: {{> next_more}} Why? Because the `next_more.mustache` file will inherit the `size` and `start` methods from the calling context. In this way you may want to think of partials as includes, or template expansion, even though it's not literally true. For example, this template and partial: base.mustache:

Names

{{#names}} {{> user}} {{/names}} user.mustache: {{name}} Can be thought of as a single, expanded template:

Names

{{#names}} {{name}} {{/names}} ### Set Delimiter Set Delimiter tags start with an equal sign and change the tag delimiters from `{{` and `}}` to custom strings. Consider the following contrived example: * {{default_tags}} {{=<% %>=}} * <% erb_style_tags %> <%={{ }}=%> * {{ default_tags_again }} 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. According to [ctemplates][ct], this "is useful for languages like TeX, where double-braces may occur in the text and are awkward to use for markup." Custom delimiters may not contain whitespace or the equals sign. [ct]: http://google-ctemplate.googlecode.com/svn/trunk/doc/howto.html ## COPYRIGHT Mustache is Copyright (C) 2009 Chris Wanstrath Original CTemplate by Google ## SEE ALSO mustache(1), mustache(7), mustache-0.99.4/man/mustache.50000644000175000017500000001726211643306253016051 0ustar virtualvirtual.\" generated with Ronn/v0.5 .\" http://github.com/rtomayko/ronn/ . .TH "MUSTACHE" "5" "May 2010" "DEFUNKT" "Mustache Manual" . .SH "NAME" \fBmustache\fR \-\- Logic\-less templates. . .SH "SYNOPSIS" A typical Mustache template: . .IP "" 4 . .nf Hello {{name}} You have just won {{value}} dollars! {{#in_ca}} Well, {{taxed_value}} dollars, after taxes. {{/in_ca}} . .fi . .IP "" 0 . .P Given the following hash: . .IP "" 4 . .nf { "name": "Chris", "value": 10000, "taxed_value": 10000 \- (10000 * 0.4), "in_ca": true } . .fi . .IP "" 0 . .P Will produce the following: . .IP "" 4 . .nf Hello Chris You have just won 10000 dollars! 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. . .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. . .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. . .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. . .P 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). . .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. . .P Template: . .IP "" 4 . .nf * {{name}} * {{age}} * {{company}} * {{{company}}} . .fi . .IP "" 0 . .P Hash: . .IP "" 4 . .nf { "name": "Chris", "company": "GitHub" } . .fi . .IP "" 0 . .P Output: . .IP "" 4 . .nf * Chris * * <b>GitHub</b> * GitHub . .fi . .IP "" 0 . .SS "Sections" Sections render blocks of text one 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. . .P 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. . .P Template: . .IP "" 4 . .nf Shown. {{#nothin}} Never shown! {{/nothin}} . .fi . .IP "" 0 . .P Hash: . .IP "" 4 . .nf { "person": true, } . .fi . .IP "" 0 . .P Output: . .IP "" 4 . .nf Shown. . .fi . .IP "" 0 . .P \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. . .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. . .P Template: . .IP "" 4 . .nf {{#repo}} {{name}} {{/repo}} . .fi . .IP "" 0 . .P Hash: . .IP "" 4 . .nf { "repo": [ { "name": "resque" }, { "name": "hub" }, { "name": "rip" }, ] } . .fi . .IP "" 0 . .P Output: . .IP "" 4 . .nf resque hub rip . .fi . .IP "" 0 . .P \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. . .P Template: . .IP "" 4 . .nf {{#wrapped}} {{name}} is awesome. {{/wrapped}} . .fi . .IP "" 0 . .P Hash: . .IP "" 4 . .nf { "name": "Willy", "wrapped": function() { return function(text) { return "" + render(text) + "" } } } . .fi . .IP "" 0 . .P Output: . .IP "" 4 . .nf Willy is awesome. . .fi . .IP "" 0 . .P \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. . .P Template: . .IP "" 4 . .nf {{#person?}} Hi {{name}}! {{/person?}} . .fi . .IP "" 0 . .P Hash: . .IP "" 4 . .nf { "person?": { "name": "Jon" } } . .fi . .IP "" 0 . .P Output: . .IP "" 4 . .nf Hi Jon! . .fi . .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. . .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. . .P Template: . .IP "" 4 . .nf {{#repo}} {{name}} {{/repo}} {{^repo}} No repos :( {{/repo}} . .fi . .IP "" 0 . .P Hash: . .IP "" 4 . .nf { "repo": [] } . .fi . .IP "" 0 . .P Output: . .IP "" 4 . .nf No repos :( . .fi . .IP "" 0 . .SS "Comments" Comments begin with a bang and are ignored. The following template: . .IP "" 4 . .nf

Today{{! ignore me }}.

. .fi . .IP "" 0 . .P Will render as follows: . .IP "" 4 . .nf

Today.

. .fi . .IP "" 0 . .P Comments may contain newlines. . .SS "Partials" 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. . .P They also inherit the calling context. Whereas in ERB you may have this: . .IP "" 4 . .nf <%= partial :next_more, :start => start, :size => size %> . .fi . .IP "" 0 . .P Mustache requires only this: . .IP "" 4 . .nf {{> next_more}} . .fi . .IP "" 0 . .P 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. . .P For example, this template and partial: . .IP "" 4 . .nf base.mustache:

Names

{{#names}} {{> user}} {{/names}} user.mustache: {{name}} . .fi . .IP "" 0 . .P Can be thought of as a single, expanded template: . .IP "" 4 . .nf

Names

{{#names}} {{name}} {{/names}} . .fi . .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. . .P Consider the following contrived example: . .IP "" 4 . .nf * {{default_tags}} {{=<% %>=}} * <% erb_style_tags %> <%={{ }}=%> * {{ default_tags_again }} . .fi . .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. . .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." . .P Custom delimiters may not contain whitespace or the equals sign. . .SH "COPYRIGHT" Mustache is Copyright (C) 2009 Chris Wanstrath . .P Original CTemplate by Google . .SH "SEE ALSO" mustache(1), mustache(7), \fIhttp://mustache.github.com/\fR mustache-0.99.4/man/mustache.1.ron0000644000175000017500000000535311643306253016640 0ustar virtualvirtualmustache(1) -- Mustache processor ================================= ## SYNOPSIS mustache mustache --compile mustache --tokens ## DESCRIPTION Mustache is a logic-less templating system for HTML, config files, anything. 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, ending with another `---` on a single line, e.g. --- names: [ {name: chris}, {name: mark}, {name: scott} ] --- If you are unfamiliar with YAML, it is a superset of JSON. Valid JSON should work fine. After the frontmatter should come any valid Mustache template. See mustache(5) for an overview of Mustache templates. For example: {{#names}} Hi {{name}}! {{/names}} Now let's combine them. $ cat data.yml --- names: [ {name: chris}, {name: mark}, {name: scott} ] --- $ cat template.mustache {{#names}} Hi {{name}}! {{/names}} $ cat data.yml template.mustache | mustache Hi chris! Hi mark! Hi scott! If you provide multiple YAML documents (as delimited by `---`), your template will be rendered multiple times. Like a mail merge. For example: $ cat data.yml --- name: chris --- name: mark --- name: scott --- $ cat template.mustache Hi {{name}}! $ cat data.yml template.mustache | mustache Hi chris! Hi mark! Hi scott! ## OPTIONS By default `mustache` will try to render a Mustache template using the YAML frontmatter you provide. It can do a few other things, however. * `-c`, `--compile`: 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. * `-t`, `--tokens`: 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. ## INSTALLATION If you have RubyGems installed: gem install mustache ## EXAMPLES $ mustache data.yml template.mustache $ cat data.yml | mustache - template.mustache $ mustache -c template.mustache $ cat < mustache-0.99.4/man/mustache.1.html0000644000175000017500000001260711643306253017006 0ustar virtualvirtual mustache(1) -- Mustache processor

mustache(1)

  1. mustache(1)
  2. Mustache Manual
  3. mustache(1)

NAME

mustache -- Mustache processor

SYNOPSIS

mustache <YAML> <FILE>
mustache --compile <FILE>
mustache --tokens <FILE>

DESCRIPTION

Mustache is a logic-less templating system for HTML, config files, anything.

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, ending with another --- on a single line, e.g.

---
names: [ {name: chris}, {name: mark}, {name: scott} ]
---

If you are unfamiliar with YAML, it is a superset of JSON. Valid JSON should work fine.

After the frontmatter should come any valid Mustache template. See mustache(5) for an overview of Mustache templates.

For example:

{{#names}}
  Hi {{name}}!
{{/names}}

Now let's combine them.

$ cat data.yml
---
names: [ {name: chris}, {name: mark}, {name: scott} ]
---

$ cat template.mustache
{{#names}}
  Hi {{name}}!
{{/names}}

$ cat data.yml template.mustache | mustache
Hi chris!
Hi mark!
Hi scott!

If you provide multiple YAML documents (as delimited by ---), your template will be rendered multiple times. Like a mail merge.

For example:

$ cat data.yml
---
name: chris
---
name: mark
---
name: scott
---

$ cat template.mustache
Hi {{name}}!

$ cat data.yml template.mustache | mustache
Hi chris!
Hi mark!
Hi scott!

OPTIONS

By default mustache will try to render a Mustache template using the YAML frontmatter you provide. It can do a few other things, however.

-c, --compile

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.

-t, --tokens

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.

INSTALLATION

If you have RubyGems installed:

gem install mustache

EXAMPLES

$ 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
---
data

COPYRIGHT

Mustache is Copyright (C) 2009 Chris Wanstrath

Original CTemplate by Google

SEE ALSO

mustache(5), mustache(7), gem(1), http://mustache.github.com/

  1. DEFUNKT
  2. May 2010
  3. mustache(1)
mustache-0.99.4/man/mustache.5.html0000644000175000017500000002472011643306253017011 0ustar virtualvirtual mustache(5) -- Logic-less templates.

mustache(5)

  1. mustache(5)
  2. Mustache Manual
  3. mustache(5)

NAME

mustache -- Logic-less templates.

SYNOPSIS

A typical Mustache template:

Hello {{name}}
You have just won {{value}} dollars!
{{#in_ca}}
Well, {{taxed_value}} dollars, after taxes.
{{/in_ca}}

Given the following hash:

{
  "name": "Chris",
  "value": 10000,
  "taxed_value": 10000 - (10000 * 0.4),
  "in_ca": true
}

Will produce the following:

Hello Chris
You have just won 10000 dollars!
Well, 6000.0 dollars, after taxes.

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.

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.

TAG TYPES

Tags are indicated by the double mustaches. {{person}} is a tag, as is {{#person}}. In both examples, we'd refer to person as the key or tag key. Let's talk about the different types of tags.

Variables

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.

All variables are HTML escaped by default. If you want to return unescaped HTML, use the triple mustache: {{{name}}}.

You can also use & to unescape a variable: {{& name}}. This may be useful when changing delimiters (see "Set Delimiter" below).

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.

Template:

* {{name}}
* {{age}}
* {{company}}
* {{{company}}}

Hash:

{
  "name": "Chris",
  "company": "<b>GitHub</b>"
}

Output:

* Chris
*
* &lt;b&gt;GitHub&lt;/b&gt;
* <b>GitHub</b>

Sections

Sections render blocks of text one 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, {{#person}} begins a "person" section while {{/person}} ends it.

The behavior of the section is determined by the value of the key.

False Values or Empty Lists

If the person key exists and has a value of false or an empty list, the HTML between the pound and slash will not be displayed.

Template:

Shown.
{{#nothin}}
  Never shown!
{{/nothin}}

Hash:

{
  "person": true,
}

Output:

Shown.

Non-Empty Lists

If the person key exists and has a non-false value, the HTML between the pound and slash will be rendered and displayed one or more times.

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.

Template:

{{#repo}}
  <b>{{name}}</b>
{{/repo}}

Hash:

{
  "repo": [
    { "name": "resque" },
    { "name": "hub" },
    { "name": "rip" },
  ]
}

Output:

<b>resque</b>
<b>hub</b>
<b>rip</b>

Lambdas

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. {{tags}} will not have been expanded - the lambda should do that on its own. In this way you can implement filters or caching.

Template:

{{#wrapped}}
  {{name}} is awesome.
{{/wrapped}}

Hash:

{
  "name": "Willy",
  "wrapped": function() {
    return function(text) {
      return "<b>" + render(text) + "</b>"
    }
  }
}

Output:

<b>Willy is awesome.</b>

Non-False Values

When the value is non-false but not a list, it will be used as the context for a single rendering of the block.

Template:

{{#person?}}
  Hi {{name}}!
{{/person?}}

Hash:

{
  "person?": { "name": "Jon" }
}

Output:

Hi Jon!

Inverted Sections

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 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.

Template:

{{#repo}}
  <b>{{name}}</b>
{{/repo}}
{{^repo}}
  No repos :(
{{/repo}}

Hash:

{
  "repo": []
}

Output:

No repos :(

Comments

Comments begin with a bang and are ignored. The following template:

<h1>Today{{! ignore me }}.</h1>

Will render as follows:

<h1>Today.</h1>

Comments may contain newlines.

Partials

Partials begin with a greater than sign, like {{> box}}.

Partials are rendered at runtime (as opposed to compile time), so recursive partials are possible. Just avoid infinite loops.

They also inherit the calling context. Whereas in ERB you may have this:

<%= partial :next_more, :start => start, :size => size %>

Mustache requires only this:

{{> next_more}}

Why? Because the next_more.mustache file will inherit the size and start methods from the calling context.

In this way you may want to think of partials as includes, or template expansion, even though it's not literally true.

For example, this template and partial:

base.mustache:
<h2>Names</h2>
{{#names}}
  {{> user}}
{{/names}}

user.mustache:
<strong>{{name}}</strong>

Can be thought of as a single, expanded template:

<h2>Names</h2>
{{#names}}
  <strong>{{name}}</strong>
{{/names}}

Set Delimiter

Set Delimiter tags start with an equal sign and change the tag delimiters from {{ and }} to custom strings.

Consider the following contrived example:

* {{default_tags}}
{{=<% %>=}}
* <% erb_style_tags %>
<%={{ }}=%>
* {{ default_tags_again }}

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.

According to ctemplates, this "is useful for languages like TeX, where double-braces may occur in the text and are awkward to use for markup."

Custom delimiters may not contain whitespace or the equals sign.

COPYRIGHT

Mustache is Copyright (C) 2009 Chris Wanstrath

Original CTemplate by Google

SEE ALSO

mustache(1), mustache(7), http://mustache.github.com/

  1. DEFUNKT
  2. May 2010
  3. mustache(5)
mustache-0.99.4/test/0000755000175000017500000000000011643306253014346 5ustar virtualvirtualmustache-0.99.4/test/autoloading_test.rb0000644000175000017500000000256311643306253020246 0ustar virtualvirtual$LOAD_PATH.unshift File.dirname(__FILE__) require 'helper' module TestViews; end class AutoloadingTest < Test::Unit::TestCase def setup Mustache.view_path = File.dirname(__FILE__) + '/fixtures' end def test_autoload klass = Mustache.view_class(:Comments) assert_equal Comments, klass end def test_autoload_lowercase klass = Mustache.view_class(:comments) assert_equal Comments, klass end def test_autoload_nil klass = Mustache.view_class(nil) assert_equal Mustache, klass end def test_autoload_empty_string klass = Mustache.view_class('') assert_equal Mustache, klass end def test_namespaced_autoload Mustache.view_namespace = TestViews klass = Mustache.view_class('Namespaced') assert_equal TestViews::Namespaced, klass assert_equal <<-end_render.strip, klass.render

Dragon < Tiger

end_render end def test_folder_autoload assert_equal TestViews::Namespaced, Mustache.view_class('test_views/namespaced') end def test_namespaced_partial_autoload Mustache.view_namespace = TestViews klass = Mustache.view_class(:namespaced_with_partial) assert_equal TestViews::NamespacedWithPartial, klass assert_equal <<-end_render.strip, klass.render My opinion: Again, Victory! end_render end def test_bad_constant_name assert_equal Mustache, Mustache.view_class(404) end end mustache-0.99.4/test/template_test.rb0000644000175000017500000000103111643306253017540 0ustar virtualvirtual$LOAD_PATH.unshift File.dirname(__FILE__) require 'helper' class TemplateTest < Test::Unit::TestCase def test_compile assert_equal %("foo"), Mustache::Template.new("foo").compile end def test_compile_with_source assert_equal %("bar"), Mustache::Template.new("foo").compile("bar") end def test_token assert_equal [:multi, [:static, "foo"]], Mustache::Template.new("foo").tokens end def test_token_with_source assert_equal [:multi, [:static, "bar"]], Mustache::Template.new("foo").tokens("bar") end end mustache-0.99.4/test/helper.rb0000644000175000017500000000023111643306253016146 0ustar virtualvirtualrequire 'test/unit' $LOAD_PATH.unshift File.dirname(__FILE__) + '/fixtures' Dir[File.dirname(__FILE__) + '/fixtures/*.rb'].each do |f| require f end mustache-0.99.4/test/partial_test.rb0000644000175000017500000000704411643306253017373 0ustar virtualvirtual$LOAD_PATH.unshift File.dirname(__FILE__) require 'helper' class PartialTest < Test::Unit::TestCase def test_view_partial assert_equal <<-end_partial.strip, PartialWithModule.render

Welcome

Hello Bob You have just won $100000!

Fair enough, right?

end_partial end def test_partial_with_slashes klass = Class.new(Mustache) klass.template = '{{> test/fixtures/inner_partial}}' view = klass.new view[:title] = 'success' assert_equal "Again, success!", view.render end def test_view_partial_inherits_context klass = Class.new(TemplatePartial) view = klass.new view.template_path = File.dirname(__FILE__) + '/fixtures' view[:titles] = [{:title => :One}, {:title => :Two}] view.template = <<-end_template

Context Test

    {{#titles}}
  • {{>inner_partial}}
  • {{/titles}}
end_template assert_equal <<-end_partial, view.render

Context Test

  • Again, One!
  • Again, Two!
end_partial end def test_view_partial_inherits_context_of_class_methods klass = Class.new(TemplatePartial) klass.template_path = File.dirname(__FILE__) + '/fixtures' klass.send(:define_method, :titles) do [{:title => :One}, {:title => :Two}] end view = klass.new view.template = <<-end_template

Context Test

    {{#titles}}
  • {{>inner_partial}}
  • {{/titles}}
end_template assert_equal <<-end_partial, view.render

Context Test

  • Again, One!
  • Again, Two!
end_partial end def test_template_partial assert_equal <<-end_partial.strip, TemplatePartial.render

Welcome

Again, Welcome! end_partial end def test_template_partial_with_custom_extension partial = Class.new(TemplatePartial) partial.template_extension = 'txt' partial.template_path = File.dirname(__FILE__) + '/fixtures' assert_equal <<-end_partial.strip, partial.render.strip Welcome ------- ## Again, Welcome! ## end_partial end def test_recursive_paritals assert_equal <<-end_partial, Recursive.render It works! end_partial end def test_crazy_recursive_partials assert_equal <<-end_partial.strip, CrazyRecursive.render
  • 1
    • 2
      • 3
    • 4
      • 5
        • 6
end_partial end def test_partials_use_proper_context assert_equal "OuterThing OuterThing", OuterThing.render('{{name}} {{> p}}') assert_equal "InnerThing InnerThing", InnerThing.render('{{name}} {{> p}}') assert_equal "OuterThing InnerThing InnerThing", OuterThing.render('{{name}} {{#inner}}{{name}} {{> p}}{{/inner}}') end def test_partials_render_returned_strings assert_equal "ok", MiddleThing.render('{{> some_partial }}') end end class InnerThing < Mustache def partial(p) self.class end def name; self.class end end class OuterThing < Mustache def inner InnerThing.new end def partial(p) self.class end def name; self.class end end class MiddleThing < Mustache def partial(name) "{{#{name}}}" end def some_partial; "ok" end end mustache-0.99.4/test/mustache_test.rb0000644000175000017500000003717711643306253017562 0ustar virtualvirtual# -*- coding: utf-8 -*- $LOAD_PATH.unshift File.dirname(__FILE__) require 'helper' class MustacheTest < Test::Unit::TestCase def test_instance_render klass = Class.new(Mustache) klass.template = "Hi {{thing}}!" assert_equal "Hi world!", klass.render(:thing => :world) assert_equal "Nice.", klass.render("{{compliment}}.", :compliment => "Nice") assert_equal <<-end_simple, Simple.new.render(:name => "yo", :in_ca => false) Hello yo You have just won $10000! end_simple end def test_passenger assert_equal <<-end_passenger, Passenger.to_text ServerName example.com DocumentRoot /var/www/example.com RailsEnv production end_passenger end def test_complex_view assert_equal <<-end_complex, ComplexView.render

Colors

end_complex end def test_nested_objects assert_equal <<-end_complex, NestedObjects.render

Colors

end_complex end def test_single_line_sections html = %(

) instance = Mustache.new instance.template = html instance[:no_flash] = true assert_equal %Q'

{{contact}}
{{/contact}}" assert_equal "
Call 1-888-FLOWERS\nAsk for Johnson.
", instance.render end def test_sassy_single_line_sections instance = Mustache.new instance[:full_time] = true instance.template = "\n {{#full_time}}full time{{/full_time}}\n" assert_equal "\n full time\n", instance.render end def test_sassier_single_line_sections instance = Mustache.new instance.template = "\t{{#list}}\r\n\t{{/list}}" assert_equal "", instance.render end def test_padding_before_section instance = Mustache.new instance.template = "\t{{#list}}a{{/list}}" assert_equal "\taa", instance.render(:list => [1, 2]) end def test_padding_before_section_on_eos instance = Mustache.new instance.template = "{{#list}}\n\t{{/list}}" assert_equal "", instance.render(:list => [1, 2]) end def test_two_line_sections html = %(

) instance = Mustache.new instance.template = html instance[:no_flash] = true assert_equal %Q'