├── deps.rip ├── docs ├── created.rid ├── favicon.ico ├── i │ ├── arrows.png │ ├── tree_bg.png │ └── results_bg.png ├── apple-touch-icon.png ├── index.html ├── js │ └── main.js ├── css │ ├── reset.css │ ├── main.css │ └── panel.css ├── files │ ├── lib │ │ ├── mustache │ │ │ ├── context_rb.html │ │ │ ├── version_rb.html │ │ │ ├── generator_rb.html │ │ │ ├── parser_rb.html │ │ │ ├── sinatra_rb.html │ │ │ └── template_rb.html │ │ ├── mustache_rb.html │ │ └── rack │ │ │ └── bug │ │ │ └── panels │ │ │ ├── mustache_panel_rb.html │ │ │ └── mustache_panel │ │ │ ├── mustache_extension_rb.html │ │ │ └── view_mustache.html │ ├── CONTRIBUTORS.html │ ├── LICENSE.html │ ├── HISTORY_md.html │ └── README_md.html ├── classes │ ├── Rack.html │ ├── Rack │ │ ├── Bug.html │ │ └── Bug │ │ │ ├── MustachePanel │ │ │ └── View.html │ │ │ └── MustachePanel.html │ ├── Mustache │ │ ├── ContextMiss.html │ │ ├── Sinatra.html │ │ ├── Parser │ │ │ └── SyntaxError.html │ │ ├── Template.html │ │ └── Sinatra │ │ │ └── Helpers.html │ └── Object.html └── panel │ ├── tree.js │ └── index.html ├── json.mustache ├── README.md ├── template.mustache ├── tom.coffee ├── Rakefile ├── burt.css ├── data.rb ├── tom.js ├── data.yml ├── extras ├── highlight.css ├── highlight.js └── mustache.js ├── index.mustache ├── index.html ├── mustache.1.html └── mustache.5.html /deps.rip: -------------------------------------------------------------------------------- 1 | hpricot 0.8.2 2 | mustache 0.11.0 3 | -------------------------------------------------------------------------------- /docs/created.rid: -------------------------------------------------------------------------------- 1 | Sun, 11 Apr 2010 14:18:30 -0400 2 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcherry/mustache.github.com/master/docs/favicon.ico -------------------------------------------------------------------------------- /docs/i/arrows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcherry/mustache.github.com/master/docs/i/arrows.png -------------------------------------------------------------------------------- /docs/i/tree_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcherry/mustache.github.com/master/docs/i/tree_bg.png -------------------------------------------------------------------------------- /docs/i/results_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcherry/mustache.github.com/master/docs/i/results_bg.png -------------------------------------------------------------------------------- /docs/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcherry/mustache.github.com/master/docs/apple-touch-icon.png -------------------------------------------------------------------------------- /json.mustache: -------------------------------------------------------------------------------- 1 | { 2 | "header": "Colors", 3 | "items": [ 4 | {"name": "red", "first": true, "url": "#Red"}, 5 | {"name": "green", "link": true, "url": "#Green"}, 6 | {"name": "blue", "link": true, "url": "#Blue"} 7 | ], 8 | "empty": false 9 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | I am 2 | 3 | Want your implementation listed on this site? 4 | 5 | 1. Add it to 6 | 2. Send a [message](https://github.com/inbox/new/defunkt) to defunkt 7 | 8 | That's it! 9 | -------------------------------------------------------------------------------- /template.mustache: -------------------------------------------------------------------------------- 1 | {{=| |=}} 2 |

{{header}}

3 | {{#bug}} 4 | {{/bug}} 5 | 6 | {{#items}} 7 | {{#first}} 8 |
  • {{name}}
  • 9 | {{/first}} 10 | {{#link}} 11 |
  • {{name}}
  • 12 | {{/link}} 13 | {{/items}} 14 | 15 | {{#empty}} 16 |

    The list is empty.

    17 | {{/empty}} 18 | |={{ }}=| -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | RDoc Documentation 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/js/main.js: -------------------------------------------------------------------------------- 1 | function toggleSource( id ) 2 | { 3 | var $src = $('#' + id).toggle(); 4 | $('#l_' + id).html($src.css('display') == 'none' ? 'show' : 'hide'); 5 | } 6 | 7 | function openCode( url ) 8 | { 9 | window.open( url, "SOURCE_CODE", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=480,width=750" ).focus(); 10 | } 11 | 12 | 13 | window.highlight = function(url) { 14 | var hash = url.match(/#([^#]+)$/) 15 | if(hash) { 16 | $('a[name=' + hash[1] + ']').parent().effect('highlight', {}, 'slow') 17 | } 18 | } 19 | 20 | $(function() { 21 | highlight('#' + location.hash); 22 | }); 23 | -------------------------------------------------------------------------------- /tom.coffee: -------------------------------------------------------------------------------- 1 | # Scrolls the window to element at the specified speed: 2 | # $('element').scrollTo(speed) 3 | $.fn.scrollTo: (speed) -> 4 | target: this 5 | container:'html,body' 6 | 7 | offset: $(target).offset().top - 30 8 | $(container).animate({scrollTop: offset}, speed or 1000) 9 | this 10 | 11 | $ -> 12 | $('#demo').click -> 13 | $('#demo-box').toggle() 14 | if $('#demo-box:visible').length > 0 15 | $('#demo').scrollTo(1) 16 | window.location.hash: '#demo' 17 | else 18 | window.location.hash: '' 19 | false 20 | 21 | $('#demo').click() if window.location.hash is "#demo" 22 | 23 | $('.run').click -> 24 | template: $('.template').val() 25 | json: $.parseJSON $('.json').val() 26 | html: Mustache.to_html(template, json).replace(/^\s*/mg, '') 27 | 28 | $('.html').text(html).scrollTo(1) 29 | Highlight.highlightDocument() 30 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | task :default => :test 2 | task :test do 3 | # nothing 4 | end 5 | 6 | desc "Build & open index.html in your browser with `open(1)`" 7 | task :open do 8 | exec "rake build:html && open index.html" 9 | end 10 | 11 | desc "Build JavaScript" 12 | task "build:coffee" do 13 | sh "coffee --no-wrap *.coffee" 14 | end 15 | 16 | desc "Build data.yml" 17 | task "build:data" do 18 | ruby "-rubygems data.rb > data.yml" 19 | end 20 | 21 | desc "Build index.html" 22 | task "build:html" do 23 | sh "cat data.yml index.mustache | mustache > index.html" 24 | end 25 | 26 | desc "Build the whole site" 27 | task :build => [ "build:coffee", "build:data", "build:html" ] 28 | 29 | desc "Build and print the index.html" 30 | task :print => "build:html" do 31 | exec "cat index.html" 32 | end 33 | 34 | desc "Publish gh-pages to GitHub" 35 | task :publish do 36 | exec "rake build && git push origin gh-pages" 37 | end 38 | -------------------------------------------------------------------------------- /burt.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Georgia; 3 | color: #333; 4 | } 5 | 6 | #logo { 7 | color: #000; 8 | height: 180px; 9 | width: 200px; 10 | -webkit-transform: rotate(-90deg); 11 | -moz-transform: rotate(-90deg); 12 | text-align: center; 13 | display: block; 14 | font-size: 250px; 15 | font-family: Georgia; 16 | margin: 0 auto; 17 | margin-bottom: -30px; 18 | } 19 | 20 | #content { 21 | width: 600px; 22 | margin: 0 auto; 23 | } 24 | 25 | p { 26 | font-size: 30px; 27 | margin-bottom: 20px; 28 | text-align: left; 29 | } 30 | 31 | label { 32 | 33 | } 34 | 35 | textarea, .html { 36 | border: 1px solid #bbb; 37 | padding: 5px; 38 | width: 100%; 39 | height: 350px; 40 | font-size: 18px; 41 | font-family: Inconsolata, monaco, courier; 42 | margin-bottom: 20px; 43 | } 44 | 45 | .json { 46 | margin-bottom: 0; 47 | } 48 | 49 | .run { 50 | margin-bottom: 20px; 51 | font-size: 130%; 52 | } 53 | -------------------------------------------------------------------------------- /data.rb: -------------------------------------------------------------------------------- 1 | # Usage: ruby data.rb > data.yml 2 | # 3 | # Generates data.yml for use with index.mustache 4 | 5 | require 'hpricot' 6 | require 'open-uri' 7 | require 'yaml' 8 | 9 | class Data 10 | def self.save(file) 11 | File.open(file, "w") { |f| f.puts build } 12 | end 13 | 14 | def self.build 15 | hash.to_yaml + "\---" 16 | end 17 | 18 | def self.hash 19 | hash = { 'languages' => [] } 20 | languages = hash['languages'] 21 | seen = [] 22 | 23 | doc = Hpricot(open"https://github.com/defunkt/mustache/wiki/Other-Mustache-implementations") 24 | doc.search("#template li").each do |lib| 25 | lang = lib.innerText.scan(/\(.+?\)/).to_s.gsub(/\(|\)/, '') 26 | next if seen.include?(lang) 27 | seen << lang 28 | 29 | link = lib.at('a')['href'] 30 | languages << { :url => link, :name => lang } 31 | 32 | # node is special 33 | if lang == "node.js" 34 | hash['last_language'] = languages.pop 35 | end 36 | end 37 | 38 | hash 39 | end 40 | end 41 | 42 | if $0 == __FILE__ 43 | puts Data.build 44 | # puts YAML.load(Data.build.to_s).inspect 45 | end 46 | -------------------------------------------------------------------------------- /docs/css/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ */ 2 | /* v1.0 | 20080212 */ 3 | 4 | html, body, div, span, applet, object, iframe, 5 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 6 | a, abbr, acronym, address, big, cite, code, 7 | del, dfn, em, font, img, ins, kbd, q, s, samp, 8 | small, strike, strong, sub, sup, tt, var, 9 | b, u, i, center, 10 | dl, dt, dd, ol, ul, li, 11 | fieldset, form, label, legend, 12 | table, caption, tbody, tfoot, thead, tr, th, td { 13 | margin: 0; 14 | padding: 0; 15 | border: 0; 16 | outline: 0; 17 | font-size: 100%; 18 | vertical-align: baseline; 19 | background: transparent; 20 | } 21 | body { 22 | line-height: 1; 23 | } 24 | ol, ul { 25 | list-style: none; 26 | } 27 | blockquote, q { 28 | quotes: none; 29 | } 30 | blockquote:before, blockquote:after, 31 | q:before, q:after { 32 | content: ''; 33 | content: none; 34 | } 35 | 36 | /* remember to define focus styles! */ 37 | :focus { 38 | outline: 0; 39 | } 40 | 41 | /* remember to highlight inserts somehow! */ 42 | ins { 43 | text-decoration: none; 44 | } 45 | del { 46 | text-decoration: line-through; 47 | } 48 | 49 | /* tables still need 'cellspacing="0"' in the markup */ 50 | table { 51 | border-collapse: collapse; 52 | border-spacing: 0; 53 | } -------------------------------------------------------------------------------- /tom.js: -------------------------------------------------------------------------------- 1 | //### 2 | // Scrolls the window to element: 3 | // $('element').scrollTo() 4 | // $('element').scrollTo(speed) 5 | // 6 | // Scrolls element1 to element2: 7 | // $('element1').scrollTo($('element2')) 8 | // $('element1').scrollTo($('element2'), speed) 9 | $.fn.scrollTo = function scrollTo(speed) { 10 | var container, offset, target; 11 | target = this; 12 | container = 'html,body'; 13 | offset = $(target).offset().top - 30; 14 | $(container).animate({ 15 | scrollTop: offset 16 | }, speed || 1000); 17 | return this; 18 | }; 19 | $(function() { 20 | $('#demo').click(function() { 21 | $('#demo-box').toggle(); 22 | if ($('#demo-box:visible').length > 0) { 23 | $('#demo').scrollTo(1); 24 | window.location.hash = '#demo'; 25 | } else { 26 | window.location.hash = ''; 27 | } 28 | return false; 29 | }); 30 | if (window.location.hash === "#demo") { 31 | $('#demo').click(); 32 | } 33 | return $('.run').click(function() { 34 | var html, json, template; 35 | template = $('.template').val(); 36 | json = $.parseJSON($('.json').val()); 37 | html = Mustache.to_html(template, json).replace(/^\s*/mg, ''); 38 | $('.html').text(html).scrollTo(1); 39 | return Highlight.highlightDocument(); 40 | }); 41 | }); -------------------------------------------------------------------------------- /data.yml: -------------------------------------------------------------------------------- 1 | --- 2 | last_language: 3 | :url: https://github.com/raycmorgan/Mu 4 | :name: node.js 5 | languages: 6 | - :url: https://github.com/janl/mustache.js 7 | :name: JavaScript 8 | - :url: https://github.com/defunkt/pystache 9 | :name: Python 10 | - :url: https://github.com/mojombo/mustache.erl 11 | :name: Erlang 12 | - :url: https://github.com/bobthecow/mustache.php 13 | :name: PHP 14 | - :url: https://github.com/pvande/Template-Mustache 15 | :name: Perl 16 | - :url: https://github.com/groue/GRMustache 17 | :name: Objective-C 18 | - :url: https://github.com/spullara/mustache.java 19 | :name: Java 20 | - :url: https://github.com/jdiamond/Nustache 21 | :name: .NET 22 | - :url: https://github.com/samskivert/jmustache 23 | :name: Android 24 | - :url: https://github.com/mrtazz/plustache 25 | :name: C++ 26 | - :url: https://github.com/hoisie/mustache.go/ 27 | :name: Go 28 | - :url: https://github.com/nrk/hige 29 | :name: Lua 30 | - :url: https://github.com/joshthecoder/mustang 31 | :name: ooc 32 | - :url: https://github.com/hyakugei/mustache.as 33 | :name: ActionScript 34 | - :url: https://github.com/pmcelhaney/Mustache.cfc 35 | :name: ColdFusion 36 | - :url: https://github.com/scalate/scalate 37 | :name: Scala 38 | - :url: https://github.com/fhd/clostache 39 | :name: Clojure 40 | - :url: https://github.com/vspy/mustache 41 | :name: Fantom 42 | - :url: https://github.com/pvande/Milk 43 | :name: CoffeeScript 44 | - :url: https://github.com/repeatedly/mustache4d 45 | :name: D 46 | --- 47 | -------------------------------------------------------------------------------- /docs/files/lib/mustache/context_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | context.rb 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
    Classes and Modules
    44 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
    57 |
    58 | 59 | -------------------------------------------------------------------------------- /docs/files/lib/mustache/version_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | version.rb 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
    Classes and Modules
    44 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
    57 |
    58 | 59 | -------------------------------------------------------------------------------- /docs/files/lib/mustache/generator_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | generator.rb 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
    Classes and Modules
    44 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 |
    57 |
    58 | 59 | -------------------------------------------------------------------------------- /docs/classes/Rack.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Rack 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 28 |
    29 |
    30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
    Classes and Modules
    46 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 |
    59 |
    60 | 61 | -------------------------------------------------------------------------------- /docs/panel/tree.js: -------------------------------------------------------------------------------- 1 | var tree = [["","","files",[["CONTRIBUTORS","files/CONTRIBUTORS.html","",[]],["HISTORY.md","files/HISTORY_md.html","",[]],["LICENSE","files/LICENSE.html","",[]],["README.md","files/README_md.html","",[]],["","","lib",[["","","mustache",[["context.rb","files/lib/mustache/context_rb.html","",[]],["generator.rb","files/lib/mustache/generator_rb.html","",[]],["parser.rb","files/lib/mustache/parser_rb.html","",[]],["sinatra.rb","files/lib/mustache/sinatra_rb.html","",[]],["template.rb","files/lib/mustache/template_rb.html","",[]],["version.rb","files/lib/mustache/version_rb.html","",[]]]],["mustache.rb","files/lib/mustache_rb.html","",[]],["","","rack",[["","","bug",[["","","panels",[["","","mustache_panel",[["mustache_extension.rb","files/lib/rack/bug/panels/mustache_panel/mustache_extension_rb.html","",[]],["view.mustache","files/lib/rack/bug/panels/mustache_panel/view_mustache.html","",[]]]],["mustache_panel.rb","files/lib/rack/bug/panels/mustache_panel_rb.html","",[]]]]]]]]]]]],["Mustache","classes/Mustache.html"," < Object",[["Context","classes/Mustache/Context.html"," < Object",[]],["ContextMiss","classes/Mustache/ContextMiss.html"," < RuntimeError",[]],["Generator","classes/Mustache/Generator.html"," < Object",[]],["Parser","classes/Mustache/Parser.html"," < Object",[["SyntaxError","classes/Mustache/Parser/SyntaxError.html"," < StandardError",[]]]],["Sinatra","classes/Mustache/Sinatra.html","",[["Helpers","classes/Mustache/Sinatra/Helpers.html","",[]]]],["Template","classes/Mustache/Template.html"," < Object",[]]]],["Object","classes/Object.html"," < Object",[]],["Rack","classes/Rack.html","",[["Bug","classes/Rack/Bug.html","",[["MustachePanel","classes/Rack/Bug/MustachePanel.html"," < Panel",[["View","classes/Rack/Bug/MustachePanel/View.html"," < Mustache",[]]]]]]]]] -------------------------------------------------------------------------------- /docs/classes/Rack/Bug.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Rack::Bug 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 28 |
    29 |
    30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
    Classes and Modules
    46 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 |
    59 |
    60 | 61 | -------------------------------------------------------------------------------- /docs/files/lib/mustache/parser_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | parser.rb 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 | 30 | 31 |
    Required Files
    32 |
      33 | 34 |
    • strscan
    • 35 | 36 |
    37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
    Classes and Modules
    51 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 66 | -------------------------------------------------------------------------------- /docs/files/lib/mustache_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | mustache.rb 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 | 30 | 31 |
    Required Files
    32 |
      33 | 34 |
    • mustache/template
    • 35 | 36 |
    • mustache/context
    • 37 | 38 |
    39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |
    Classes and Modules
    53 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 68 | -------------------------------------------------------------------------------- /docs/files/CONTRIBUTORS.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | CONTRIBUTORS 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 |
    30 |
      31 |
    • Chris Wanstrath 32 | 33 |
    • 34 |
    • Francesc Esplugas 35 | 36 |
    • 37 |
    • Magnus Holm 38 | 39 |
    • 40 |
    • Nicolas Sanguinetti 41 | 42 |
    • 43 |
    • Nathan Weizenbaum 44 | 45 |
    • 46 |
    • Jan-Erik Rediger 47 | 48 |
    • 49 |
    • Michael Daines 50 | 51 |
    • 52 |
    • Aaron Patterson 53 | 54 |
    • 55 |
    • Harry Vangberg 56 | 57 |
    • 58 |
    59 | 60 |
    61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 |
    83 |
    84 | 85 | -------------------------------------------------------------------------------- /docs/files/lib/mustache/sinatra_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | sinatra.rb 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 | 30 | 31 |
    Required Files
    32 |
      33 | 34 |
    • sinatra/base
    • 35 | 36 |
    • mustache
    • 37 | 38 |
    39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |
    Classes and Modules
    53 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 |
    66 |
    67 | 68 | -------------------------------------------------------------------------------- /docs/files/lib/mustache/template_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | template.rb 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 | 30 | 31 |
    Required Files
    32 |
      33 | 34 |
    • cgi
    • 35 | 36 |
    • mustache/parser
    • 37 | 38 |
    • mustache/generator
    • 39 | 40 |
    41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
    Classes and Modules
    55 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
    68 |
    69 | 70 | -------------------------------------------------------------------------------- /docs/files/lib/rack/bug/panels/mustache_panel_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | mustache_panel.rb 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 | 30 | 31 |
    Required Files
    32 |
      33 | 34 |
    • rack/bug/panels/mustache_panel/mustache_extension
    • 35 | 36 |
    37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
    Classes and Modules
    51 |
      52 | 53 |
    • MODULE Rack
    • 54 | 55 |
    56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 66 | -------------------------------------------------------------------------------- /docs/files/lib/rack/bug/panels/mustache_panel/mustache_extension_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | mustache_extension.rb 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 | 30 | 31 |
    Required Files
    32 |
      33 | 34 |
    • benchmark
    • 35 | 36 |
    37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
    Classes and Modules
    51 |
      52 | 53 |
    • CLASS Object
    • 54 | 55 |
    56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 66 | -------------------------------------------------------------------------------- /docs/classes/Mustache/ContextMiss.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Mustache::ContextMiss 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 34 |
    35 |
    36 | 37 |
    38 |

    39 | A ContextMiss is raised whenever a 40 | tag’s target can not be found in the current context if `Mustache#raise_on_context_miss?` is set 42 | to true. 43 |

    44 |

    45 | For example, if your View class does not respond to `music` but your 46 | template contains a `{{music}}` tag this exception will be raised. 47 |

    48 |

    49 | By default it is not raised. See Mustache.raise_on_context_miss. 51 |

    52 | 53 |
    54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
    76 |
    77 | 78 | -------------------------------------------------------------------------------- /docs/files/LICENSE.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | LICENSE 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 |
    30 |

    31 | Copyright © 2009 Chris Wanstrath 32 |

    33 |

    34 | Permission is hereby granted, free of charge, to any person obtaining a 35 | copy of this software and associated documentation files (the 36 | “Software”), to deal in the Software without restriction, 37 | including without limitation the rights to use, copy, modify, merge, 38 | publish, distribute, sublicense, and/or sell copies of the Software, and to 39 | permit persons to whom the Software is furnished to do so, subject to the 40 | following conditions: 41 |

    42 |

    43 | The above copyright notice and this permission notice shall be included in 44 | all copies or substantial portions of the Software. 45 |

    46 |

    47 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 48 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 50 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 51 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 52 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 53 | USE OR OTHER DEALINGS IN THE SOFTWARE. 54 |

    55 | 56 |
    57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 |
    79 |
    80 | 81 | -------------------------------------------------------------------------------- /docs/panel/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | layout 8 | 9 | 10 | 11 | 12 | 13 | 14 | 49 | 50 | 51 |
    52 |
    53 |
    54 | 55 | 56 | 59 |
    57 | 58 |
    60 |
    61 |
    62 |
      63 |
    64 |
    65 |
    66 |
      67 |
    68 |
    69 |
    70 | 71 | 72 | -------------------------------------------------------------------------------- /docs/files/lib/rack/bug/panels/mustache_panel/view_mustache.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | view.mustache 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 |
    30 |

    31 | 46 |

    47 |

    48 |

    Render Times

    49 |

    50 |

    51 | 52 |

    53 |
     54 |   <tr>
     55 |     <th>View</th>
     56 |     <th>Render Time</th>
     57 |   </tr>
     58 | 
     59 |   {{# times }}
     60 |     <tr>
     61 |       <td>{{ key }}</td>
     62 |       <td>{{ value }}</td>
     63 |     </tr>
     64 |   {{/ times }}
     65 | 
    66 |

    67 |

    68 |

    69 |

    70 |

    Variables

    71 |

    72 |

    73 | 74 |

    75 |
     76 |   <tr>
     77 |     <th>Name</th>
     78 |     <th>Value</th>
     79 |   </tr>
     80 | 
     81 |   {{# variables }}
     82 |     <tr>
     83 |       <td>{{ key }}</td>
     84 |       <td class="variable">{{ value }}</td>
     85 |     </tr>
     86 |   {{/ variables }}
     87 | 
    88 |

    89 |

    90 |

    91 | 92 |
    93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
    115 |
    116 | 117 | -------------------------------------------------------------------------------- /extras/highlight.css: -------------------------------------------------------------------------------- 1 | pre.sh_sourceCode { 2 | background-color: white; 3 | color: black; 4 | font-style: normal; 5 | font-weight: normal; 6 | } 7 | 8 | pre.sh_sourceCode .sh_keyword { color: blue; font-weight: bold; } /* language keywords */ 9 | pre.sh_sourceCode .sh_type { color: darkgreen; } /* basic types */ 10 | pre.sh_sourceCode .sh_usertype { color: teal; } /* user defined types */ 11 | pre.sh_sourceCode .sh_string { color: red; font-family: monospace; } /* strings and chars */ 12 | pre.sh_sourceCode .sh_regexp { color: orange; font-family: monospace; } /* regular expressions */ 13 | pre.sh_sourceCode .sh_specialchar { color: pink; font-family: monospace; } /* e.g., \n, \t, \\ */ 14 | pre.sh_sourceCode .sh_comment { color: brown; font-style: italic; } /* comments */ 15 | pre.sh_sourceCode .sh_number { color: purple; } /* literal numbers */ 16 | pre.sh_sourceCode .sh_preproc { color: darkblue; font-weight: bold; } /* e.g., #include, import */ 17 | pre.sh_sourceCode .sh_symbol { color: darkred; } /* e.g., <, >, + */ 18 | pre.sh_sourceCode .sh_function { color: black; font-weight: bold; } /* function calls and declarations */ 19 | pre.sh_sourceCode .sh_cbracket { color: red; } /* block brackets (e.g., {, }) */ 20 | pre.sh_sourceCode .sh_todo { font-weight: bold; background-color: cyan; } /* TODO and FIXME */ 21 | 22 | /* Predefined variables and functions (for instance glsl) */ 23 | pre.sh_sourceCode .sh_predef_var { color: darkblue; } 24 | pre.sh_sourceCode .sh_predef_func { color: darkblue; font-weight: bold; } 25 | 26 | /* for OOP */ 27 | pre.sh_sourceCode .sh_classname { color: teal; } 28 | 29 | /* line numbers (not yet implemented) */ 30 | pre.sh_sourceCode .sh_linenum { color: black; font-family: monospace; } 31 | 32 | /* Internet related */ 33 | pre.sh_sourceCode .sh_url { color: blue; text-decoration: underline; font-family: monospace; } 34 | 35 | /* for ChangeLog and Log files */ 36 | pre.sh_sourceCode .sh_date { color: blue; font-weight: bold; } 37 | pre.sh_sourceCode .sh_time, pre.sh_sourceCode .sh_file { color: darkblue; font-weight: bold; } 38 | pre.sh_sourceCode .sh_ip, pre.sh_sourceCode .sh_name { color: darkgreen; } 39 | 40 | /* for Prolog, Perl... */ 41 | pre.sh_sourceCode .sh_variable { color: darkgreen; } 42 | 43 | /* for LaTeX */ 44 | pre.sh_sourceCode .sh_italics { color: darkgreen; font-style: italic; } 45 | pre.sh_sourceCode .sh_bold { color: darkgreen; font-weight: bold; } 46 | pre.sh_sourceCode .sh_underline { color: darkgreen; text-decoration: underline; } 47 | pre.sh_sourceCode .sh_fixed { color: green; font-family: monospace; } 48 | pre.sh_sourceCode .sh_argument { color: darkgreen; } 49 | pre.sh_sourceCode .sh_optionalargument { color: purple; } 50 | pre.sh_sourceCode .sh_math { color: orange; } 51 | pre.sh_sourceCode .sh_bibtex { color: blue; } 52 | 53 | /* for diffs */ 54 | pre.sh_sourceCode .sh_oldfile { color: orange; } 55 | pre.sh_sourceCode .sh_newfile { color: darkgreen; } 56 | pre.sh_sourceCode .sh_difflines { color: blue; } 57 | 58 | /* for css */ 59 | pre.sh_sourceCode .sh_selector { color: purple; } 60 | pre.sh_sourceCode .sh_property { color: blue; } 61 | pre.sh_sourceCode .sh_value { color: darkgreen; font-style: italic; } 62 | 63 | /* other */ 64 | pre.sh_sourceCode .sh_section { color: black; font-weight: bold; } 65 | pre.sh_sourceCode .sh_paren { color: red; } 66 | pre.sh_sourceCode .sh_attribute { color: darkgreen; } 67 | -------------------------------------------------------------------------------- /index.mustache: -------------------------------------------------------------------------------- 1 | 2 | 36 | 37 | 38 | {{ mustache }} 39 | 40 | 41 | 42 | 43 | 44 |
    45 |

    Logic-less templates.

    46 | 47 |

    48 | Available in 49 | Ruby, 50 | {{#languages}} 51 | {{name}}, 52 | {{/languages}} 53 | {{#last_language}} 54 | and for 55 | {{name}}. 56 | {{/last_language}} 57 |

    58 | 59 |

    60 | Works great with 61 | TextMate, 62 | Vim, 63 | Emacs, 64 | and 65 | Coda. 66 |

    67 | 68 |

    69 | The Manual: 70 | mustache(5) 71 | and 72 | mustache(1) 73 |

    74 | 75 |

    76 | Demo 77 |

    78 | 79 | 91 |
    92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /docs/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "Helvetica Neue", Arial, sans-serif; 3 | background: #FFF; 4 | color: #000; 5 | margin: 0px; 6 | font-size: 0.82em; 7 | line-height: 1.25em; 8 | } 9 | 10 | a { 11 | color: #00F; 12 | text-decoration: none; 13 | } 14 | 15 | a:hover { 16 | color: #333; 17 | background: #FE8; 18 | } 19 | 20 | p { 21 | margin-bottom: 1em; 22 | } 23 | 24 | h1 { 25 | font-size: 2.1em; 26 | font-weight: normal; 27 | line-height: 1.2em; 28 | margin: 1.4em 0 0.7em 0; 29 | } 30 | 31 | h2 { 32 | font-size: 1.6em; 33 | margin: 1.8em 0 0.8em 0; 34 | font-weight: normal; 35 | line-height: 1.2em; 36 | } 37 | 38 | h3 { 39 | font-size: 1.4em; 40 | color:#555; 41 | margin: 1.4em 0 0.7em 0; 42 | font-weight: normal; 43 | } 44 | 45 | h4 { 46 | margin: 1.4em 0 0.5em 0; 47 | font-size: 1em; 48 | } 49 | 50 | table 51 | { 52 | margin-bottom: 1em; 53 | } 54 | 55 | td, th 56 | { 57 | padding: 0 0.7em 0.3em 0; 58 | } 59 | 60 | th 61 | { 62 | font-weight: bold; 63 | } 64 | 65 | .clear 66 | { 67 | clear: both; 68 | width: 0; height: 0; 69 | } 70 | 71 | dt 72 | { 73 | margin-bottom: 0.3em; 74 | font-weight: bold; 75 | } 76 | 77 | dd 78 | { 79 | margin-left: 2em; 80 | margin-bottom: 1em; 81 | } 82 | 83 | dd p 84 | { 85 | margin-top: 0.6em; 86 | } 87 | 88 | li 89 | { 90 | margin: 0 0 0.5em 2em; 91 | } 92 | 93 | ul li 94 | { 95 | list-style: disc; 96 | } 97 | 98 | ol li 99 | { 100 | list-style: decimal; 101 | } 102 | 103 | .banner 104 | { 105 | background: #EDF3FE; 106 | border-bottom: 1px solid #ccc; 107 | padding: 1em 2em 0.5em 2em; 108 | } 109 | .banner h1 110 | { 111 | font-size: 1.2em; 112 | margin: 0; 113 | } 114 | 115 | .banner h1 .type 116 | { 117 | font-size: 0.833em; 118 | display:block; 119 | } 120 | 121 | .banner h1 .type, 122 | .banner h1 .parent 123 | { 124 | color: #666; 125 | } 126 | 127 | .banner ul 128 | { 129 | margin-top: 0.3em; 130 | margin-bottom: 0; 131 | font-size: 0.85em; 132 | } 133 | 134 | .banner li 135 | { 136 | list-style: none; 137 | margin-left: 0; 138 | margin-bottom: 0; 139 | } 140 | 141 | pre 142 | { 143 | margin-bottom: 1em; 144 | } 145 | 146 | .methods dt 147 | { 148 | width: 1em; 149 | font-size: 1.5em; 150 | color:#AAA; 151 | position: absolute; 152 | font-weight: normal; 153 | margin: 0; 154 | } 155 | 156 | .methods dd 157 | { 158 | margin-left: 2.5em; 159 | min-height: 1.8em; 160 | -height: 1.8em; 161 | padding-bottom: 0.8em; 162 | } 163 | 164 | 165 | .methods ul li 166 | { 167 | margin-right: 0.7em; 168 | margin-left: 0; 169 | list-style: none; 170 | display: inline; 171 | } 172 | 173 | #content { 174 | margin: 2em; 175 | margin-left: 3.5em; 176 | margin-right: 3.5em; 177 | } 178 | 179 | 180 | .sectiontitle { 181 | margin-top: 2em; 182 | margin-bottom: 1.3em; 183 | margin-left: -1.2em; 184 | font-size: 1.2em; 185 | padding: 0 0 0.25em 0; 186 | font-weight: bold; 187 | border-bottom: 1px solid #000; 188 | } 189 | 190 | .attr-rw { 191 | padding-right: 1em; 192 | text-align: center; 193 | color: #055; 194 | } 195 | 196 | .attr-name { 197 | font-weight: bold; 198 | padding-right: 1em; 199 | } 200 | 201 | .attr-desc { 202 | } 203 | 204 | tt { 205 | font-size: 1.15em; 206 | } 207 | 208 | .attr-value { 209 | font-family: monospace; 210 | padding-left: 1em; 211 | font-size: 1.15em; 212 | } 213 | 214 | .dyn-source { 215 | display: none; 216 | background: #fffde8; 217 | color: #000; 218 | border: #ffe0bb dotted 1px; 219 | margin: 0.5em 2em 0.5em 0; 220 | padding: 0.5em; 221 | } 222 | 223 | .dyn-source .cmt { 224 | color: #00F; 225 | font-style: italic; 226 | } 227 | 228 | .dyn-source .kw { 229 | color: #070; 230 | font-weight: bold; 231 | } 232 | 233 | .description pre { 234 | padding: 0.5em; 235 | border: #ffe0bb dotted 1px; 236 | background: #fffde8; 237 | } 238 | 239 | .method { 240 | margin-bottom: 2em; 241 | } 242 | .method .description, 243 | .method .sourcecode 244 | { 245 | margin-left: 1.2em; 246 | } 247 | .method h4 248 | { 249 | border-bottom: 1px dotted #999; 250 | padding: 0 0 0.2em 0; 251 | margin-bottom: 0.8em; 252 | font-size: 1.1em; 253 | color:#333; 254 | } 255 | .method .title { 256 | border-bottom: 1px dotted #666; 257 | padding: 0 0 0.15em 0; 258 | margin: 0 0 0.5em 0; 259 | font-size: 1.2em; 260 | line-height: 1.25em; 261 | } 262 | 263 | .method .sourcecode p.source-link { 264 | text-indent: 0em; 265 | margin-top: 0.5em; 266 | } 267 | 268 | .method .aka { 269 | margin-top: 0.3em; 270 | margin-left: 1em; 271 | font-style: italic; 272 | text-indent: 2em; 273 | } 274 | 275 | .method .source-link 276 | { 277 | font-size: 0.85em; 278 | } -------------------------------------------------------------------------------- /docs/classes/Mustache/Sinatra.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Mustache::Sinatra 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 28 |
    29 |
    30 | 31 |
    32 |

    33 | Support for Mustache in your Sinatra app. 35 |

    36 |
     37 |   require 'mustache/sinatra'
     38 | 
     39 |   class Hurl < Sinatra::Base
     40 |     register Mustache::Sinatra
     41 | 
     42 |     set :mustache, {
     43 |       # Should be the path to your .mustache template files.
     44 |       :templates => "path/to/mustache/templates",
     45 | 
     46 |       # Should be the path to your .rb Mustache view files.
     47 |       :views => "path/to/mustache/views",
     48 | 
     49 |       # This tells Mustache where to look for the Views module,
     50 |       # under which your View classes should live. By default it's
     51 |       # the class of your app - in this case `Hurl`. That is, for an :index
     52 |       # view Mustache will expect Hurl::Views::Index by default.
     53 |       # If our Sinatra::Base subclass was instead Hurl::App,
     54 |       # we'd want to do `set :namespace, Hurl::App`
     55 |       :namespace => Hurl
     56 |     }
     57 | 
     58 |     get '/stats' do
     59 |       mustache :stats
     60 |     end
     61 |   end
     62 | 
    63 |

    64 | As noted above, Mustache will look for 65 | `Hurl::Views::Index` when `mustache :index` is called. 66 |

    67 |

    68 | If no `Views::Stats` class exists Mustache 69 | will render the template file directly. 70 |

    71 |

    72 | You can indeed use layouts with this library. Where you’d normally 73 | <%= yield %> you instead {{{yield}}} - the body of the subview is set to 74 | the `yield` variable and made available to you. 75 |

    76 | 77 |
    78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 |
    Methods
    88 |
    89 | 90 |
    R
    91 |
    92 | 97 |
    98 | 99 |
    100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 |
    Classes and Modules
    108 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 |
    Class Public methods
    121 | 122 |
    123 |
    124 | 125 | registered(app) 126 | 127 |
    128 | 129 |
    130 |

    131 | Called when you `register Mustache::Sinatra` in your Sinatra app. 133 |

    134 | 135 |
    136 | 137 | 138 | 139 | 140 |
    141 | 147 |
    148 |
    # File lib/mustache/sinatra.rb, line 150
    149 |     def self.registered(app)
    150 |       app.helpers Mustache::Sinatra::Helpers
    151 |     end
    152 |
    153 |
    154 | 155 |
    156 | 157 |
    158 |
    159 | 160 | -------------------------------------------------------------------------------- /extras/highlight.js: -------------------------------------------------------------------------------- 1 | var Highlight = (function() { 2 | if(!this.sh_languages){this.sh_languages={}}var sh_requests={};function sh_isEmailAddress(a){if(/^mailto:/.test(a)){return false}return a.indexOf("@")!==-1}function sh_setHref(b,c,d){var a=d.substring(b[c-2].pos,b[c-1].pos);if(a.length>=2&&a.charAt(0)==="<"&&a.charAt(a.length-1)===">"){a=a.substr(1,a.length-2)}if(sh_isEmailAddress(a)){a="mailto:"+a}b[c-2].node.href=a}function sh_konquerorExec(b){var a=[""];a.index=b.length;a.input=b;return a}function sh_highlightString(B,o){if(/Konqueror/.test(navigator.userAgent)){if(!o.konquered){for(var F=0;FI){x(g.substring(I,E.index),null)}var e=O[u];var J=e[1];var b;if(J instanceof Array){for(var L=0;L0){var e=b.split(" ");for(var c=0;c0){a.push(e[c])}}}return a}function sh_addClass(c,a){var d=sh_getClasses(c);for(var b=0;b element with class="'+h+'", but no such language exists'}}break}}}}; 3 | if(!this.sh_languages){this.sh_languages={}}sh_languages.html=[[[/<\?xml/g,"sh_preproc",1,1],[//g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",5,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",5,1]],[[/\?>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",2]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",2]],[[/-->/g,"sh_comment",-2],[/ 36 | 37 | 38 | {{ mustache }} 39 | 40 | 41 | 42 | 43 | 44 |
    45 |

    Logic-less templates.

    46 | 47 |

    48 | Available in 49 | Ruby, 50 | JavaScript, 51 | Python, 52 | Erlang, 53 | PHP, 54 | Perl, 55 | Objective-C, 56 | Java, 57 | .NET, 58 | Android, 59 | C++, 60 | Go, 61 | Lua, 62 | ooc, 63 | ActionScript, 64 | ColdFusion, 65 | Scala, 66 | Clojure, 67 | Fantom, 68 | CoffeeScript, 69 | D, 70 | and for 71 | node.js. 72 |

    73 | 74 |

    75 | Works great with 76 | TextMate, 77 | Vim, 78 | Emacs, 79 | and 80 | Coda. 81 |

    82 | 83 |

    84 | The Manual: 85 | mustache(5) 86 | and 87 | mustache(1) 88 |

    89 | 90 |

    91 | Demo 92 |

    93 | 94 | 131 |
    132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /docs/classes/Mustache/Parser/SyntaxError.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Mustache::Parser::SyntaxError 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 34 |
    35 |
    36 | 37 |
    38 |

    39 | A SyntaxError is raised when the Parser comes across unclosed tags, sections, 41 | illegal content in tags, or anything of that sort. 42 |

    43 | 44 |
    45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
    Methods
    55 |
    56 | 57 |
    N
    58 |
    59 |
      60 | 61 |
    • new
    • 62 | 63 |
    64 |
    65 | 66 |
    T
    67 |
    68 |
      69 | 70 |
    • to_s
    • 71 | 72 |
    73 |
    74 | 75 |
    76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
    Class Public methods
    90 | 91 |
    92 |
    93 | 94 | new(message, position) 95 | 96 |
    97 | 98 | 99 | 100 | 101 |
    102 | 108 |
    109 |
    # File lib/mustache/parser.rb, line 30
    110 |       def initialize(message, position)
    111 |         @message = message
    112 |         @lineno, @column, @line = position
    113 |         @stripped_line = @line.strip
    114 |         @stripped_column = @column - (@line.size - @line.lstrip.size)
    115 |       end
    116 |
    117 |
    118 | 119 |
    120 | 121 |
    Instance Public methods
    122 | 123 |
    124 |
    125 | 126 | to_s() 127 | 128 |
    129 | 130 | 131 | 132 | 133 |
    134 | 140 |
    141 |
    # File lib/mustache/parser.rb, line 37
    142 |       def to_s
    143 |         "\#{@message}\nLine \#{@lineno}\n\#{@stripped_line}\n\#{' ' * @stripped_column}^\n"
    144 |       end
    145 |
    146 |
    147 | 148 |
    149 | 150 |
    151 |
    152 | 153 | -------------------------------------------------------------------------------- /mustache.1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | mustache(1) -- Mustache processor 7 | 53 | 54 | 55 |
    56 | 57 |

    mustache(1)

    58 | 59 |
      60 |
    1. mustache(1)
    2. 61 |
    3. Mustache Manual
    4. 62 |
    5. mustache(1)
    6. 63 |
    64 | 65 |

    NAME

    66 |

    mustache -- Mustache processor

    67 | 68 |

    SYNOPSIS

    69 | 70 |
    mustache <YAML> <FILE>
     71 | mustache --compile <FILE>
     72 | mustache --tokens <FILE>
     73 | 
    74 | 75 |

    DESCRIPTION

    76 | 77 |

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

    79 | 80 |

    The mustache command processes a Mustache template preceded by YAML 81 | frontmatter from standard input and prints one or more documents to 82 | standard output.

    83 | 84 |

    YAML frontmatter beings with --- on a single line, followed by YAML, 85 | ending with another --- on a single line, e.g.

    86 | 87 |
    ---
     88 | names: [ {name: chris}, {name: mark}, {name: scott} ]
     89 | ---
     90 | 
    91 | 92 |

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

    94 | 95 |

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

    97 | 98 |

    For example:

    99 | 100 |
    {{#names}}
    101 |   Hi {{name}}!
    102 | {{/names}}
    103 | 
    104 | 105 |

    Now let's combine them.

    106 | 107 |
    $ cat data.yml
    108 | ---
    109 | names: [ {name: chris}, {name: mark}, {name: scott} ]
    110 | ---
    111 | 
    112 | $ cat template.mustache
    113 | {{#names}}
    114 |   Hi {{name}}!
    115 | {{/names}}
    116 | 
    117 | $ cat data.yml template.mustache | mustache
    118 | Hi chris!
    119 | Hi mark!
    120 | Hi scott!
    121 | 
    122 | 123 |

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

    125 | 126 |

    For example:

    127 | 128 |
    $ cat data.yml
    129 | ---
    130 | name: chris
    131 | ---
    132 | name: mark
    133 | ---
    134 | name: scott
    135 | ---
    136 | 
    137 | $ cat template.mustache
    138 | Hi {{name}}!
    139 | 
    140 | $ cat data.yml template.mustache | mustache
    141 | Hi chris!
    142 | Hi mark!
    143 | Hi scott!
    144 | 
    145 | 146 |

    OPTIONS

    147 | 148 |

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

    150 | 151 |
    152 |
    -c, --compile

    Print the compiled Ruby version of a given template. This is the 153 | code that is actually used when rendering a template into a 154 | string. Useful for debugging but only if you are familiar with 155 | Mustache's internals.

    156 |
    -t, --tokens

    Print the tokenized form of a given Mustache template. This can be 157 | used to understand how Mustache parses a template. The tokens are 158 | handed to a generator which compiles them into a Ruby 159 | string. Syntax errors and confused tags, therefor, can probably be 160 | identified by examining the tokens produced.

    161 |
    162 | 163 | 164 |

    INSTALLATION

    165 | 166 |

    If you have RubyGems installed:

    167 | 168 |
    gem install mustache
    169 | 
    170 | 171 |

    EXAMPLES

    172 | 173 |
    $ mustache data.yml template.mustache
    174 | $ cat data.yml | mustache - template.mustache
    175 | $ mustache -c template.mustache
    176 | $ cat <<data | ruby mustache - template.mustache
    177 | ---
    178 | name: Bob
    179 | age: 30
    180 | ---
    181 | data
    182 | 
    183 | 184 |

    COPYRIGHT

    185 | 186 |

    Mustache is Copyright (C) 2009 Chris Wanstrath

    187 | 188 |

    Original CTemplate by Google

    189 | 190 |

    SEE ALSO

    191 | 192 |

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

    194 | 195 | 196 |
      197 |
    1. DEFUNKT
    2. 198 |
    3. April 2010
    4. 199 |
    5. mustache(1)
    6. 200 |
    201 | 202 |
    203 | 204 | 205 | -------------------------------------------------------------------------------- /docs/classes/Object.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Object 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 32 |
    33 |
    34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
    Methods
    44 |
    45 | 46 |
    #
    47 |
    48 |
      49 | 50 |
    • []
    • 51 | 52 |
    53 |
    54 | 55 |
    R
    56 |
    57 | 62 |
    63 | 64 |
    65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 |
    Instance Public methods
    79 | 80 |
    81 |
    82 | 83 | [](name) 84 | 85 |
    86 | 87 | 88 | 89 | 90 |
    91 | 97 |
    98 |
    # File lib/rack/bug/panels/mustache_panel/mustache_extension.rb, line 22
     99 |     def [](name)
    100 |       return real_get(name) if name == :yield || !@mustache.respond_to?(name)
    101 |       Rack::Bug::MustachePanel.variables[name] = real_get(name)
    102 |     end
    103 |
    104 |
    105 | 106 |
    107 | 108 |
    109 |
    110 | 111 | render(*args, &block) 112 | 113 |
    114 | 115 | 116 | 117 | 118 |
    119 | 125 |
    126 |
    # File lib/rack/bug/panels/mustache_panel/mustache_extension.rb, line 7
    127 |     def render(*args, &block)
    128 |       out = ''
    129 |       Rack::Bug::MustachePanel.times[self.class.name] = Benchmark.realtime do
    130 |         out = real_render(*args, &block)
    131 |       end
    132 |       out
    133 |     end
    134 |
    135 |
    136 | 137 |
    138 | 139 |
    140 |
    141 | 142 | -------------------------------------------------------------------------------- /docs/files/HISTORY_md.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | HISTORY.md 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 |
    30 |

    0.10.0 (2010-04-02)

    31 | 32 |
      33 |
    • Added Inverted Sections (^). See mustache(5) for details.
    • 34 |
    • Added Template#source for accessing the template's string source.
    • 35 |
    • Bugfix: 1.9 encoding fix
    • 36 |
    • Sinatra Bugfix: 1.9 compat
    • 37 |
    38 | 39 | 40 |

    0.9.2 (2010-03-29)

    41 | 42 |
      43 |
    • Sinatra: Bugfix for mustache :view, :layout => true
    • 44 |
    • Mustache class now implements partial so you can call super 45 | when providing a custom partial method.
    • 46 |
    • Bugfix: Allow slashes in tags, especially partials.
    • 47 |
    48 | 49 | 50 |

    0.9.1 (2010-03-27)

    51 | 52 |
      53 |
    • Bugfix: Partials use the nearest context when being rendered.
    • 54 |
    • Bugfix: Partials returned by the partial method are now rendered.
    • 55 |
    56 | 57 | 58 |

    0.9.0 (2010-03-26)

    59 | 60 |
      61 |
    • New, cleaner parser by Magnus Holm!
    • 62 |
    • Improved error messages!
    • 63 |
    • Bugfixes!
    • 64 |
    • Faster runtime!
    • 65 |
    • Sinatra 1.0 compatibility with layout tag overriding!
    • 66 |
    67 | 68 | 69 |

    0.7.0 (2010-03-25)

    70 | 71 |
      72 |
    • Mustache.compile for compiling a template into Ruby.
    • 73 |
    • mustache -c FILE to see a template's compiled Ruby.
    • 74 |
    • Recursive partial support.
    • 75 |
    • Added & as an alias for the triple mustache (unescaped HTML).
    • 76 |
    • Simpler examples. Old examples are now test fixtures.
    • 77 |
    78 | 79 | 80 |

    0.6.0 (2010-03-08)

    81 | 82 |
      83 |
    • Ruby objects can be used in sections, not just hashes. See 84 | http://github.com/defunkt/mustache/commit/9477619638
    • 85 |
    • As a result, TypeError is no longer thrown when hashes are not 86 | passed.
    • 87 |
    • mustache(1) man page is now included
    • 88 |
    • mustache(5) man page is now included
    • 89 |
    • tpl-mode.el has been renamed mustache-mode.el
    • 90 |
    • Improved README
    • 91 |
    92 | 93 | 94 |

    0.5.1 (2009-12-15)

    95 | 96 |
      97 |
    • Added "mail merge" functionality to mustache script.
    • 98 |
    • Support for multi-line tags (useful for comments)
    • 99 |
    • Sinatra Bugfix: Use Sinatra app's view path, not Sinatra base class'.
    • 100 |
    101 | 102 | 103 |

    0.5.0 (2009-11-23)

    104 | 105 |
      106 |
    • Partial classes are no longer supported. Use modules!
    • 107 |
    • Added mustache script for rendering templates on the command line.
    • 108 |
    • ctemplate compat: Partials are indicated by >, not <
    • 109 |
    • Bugfix: Context miss should return nil, not empty string. Fixes 1.9.x
    • 110 |
    111 | 112 | 113 |

    0.4.2 (2009-10-28)

    114 | 115 |
      116 |
    • Bugfix: Ignore bad constant names when autoloading
    • 117 |
    118 | 119 | 120 |

    0.4.1 (2009-10-27)

    121 | 122 |
      123 |
    • Partials now respect the view_namespace setting.
    • 124 |
    • Added tpl-mode.el to contrib/ for us Emacs users.
    • 125 |
    • Rack::Bug bugfix: ensure benchmark is required before using it
    • 126 |
    • Rack::Bug: truncate too-large variables (click expands them)
    • 127 |
    128 | 129 | 130 |

    0.4.0 (2009-10-27)

    131 | 132 |
      133 |
    • Stopped raising context miss exceptions by default
    • 134 |
    • Added Mustache.raise_on_context_miss setting (defaults to false)
    • 135 |
    • Throw Mustache::ContextMiss when raise_on_context_miss is true and 136 | we encounter a miss.
    • 137 |
    • The default template extension is now "mustache" (instead of "html").
    • 138 |
    • Added the view_namespace and view_path settings to Mustache
    • 139 |
    • Added Mustache.view_class method which autoloads a class using the 140 | new view_namespace and view_path settings. Should be used by 141 | plugin developers.
    • 142 |
    • Updated the Sinatra extension to use the new view_class method
    • 143 |
    • Unclosed sections now throw a helpful error message
    • 144 |
    • Report line numbers on unclosed section errors
    • 145 |
    • Added Rack::Bug panel
    • 146 |
    147 | 148 | 149 |

    0.3.2 (2009-10-19)

    150 | 151 |
      152 |
    • Bugfix: Partials in Sinatra were using the wrong path.
    • 153 |
    154 | 155 | 156 |

    0.3.1 (2009-10-19)

    157 | 158 |
      159 |
    • Added mustache.vim to contrib/ (Thanks Juvenn Woo!)
    • 160 |
    • Support string keys in contexts (not just symbol keys).
    • 161 |
    • Bugfix: # and / were not permitted in tag names. Now they are.
    • 162 |
    • Bugfix: Partials in Sinatra needed to know their extension and path
    • 163 |
    • Bugfix: Using the same boolean section twice was failing
    • 164 |
    165 | 166 | 167 |

    0.3.0 (2009-10-14)

    168 | 169 |
      170 |
    • Set Delimiter tags are now supported. See the README
    • 171 |
    • Improved error message when an enumerable section did not return all 172 | hashes.
    • 173 |
    • Added a shortcut: if a section's value is a single hash, treat is as 174 | a one element array whose value is the hash.
    • 175 |
    • Bugfix: String templates set at the class level were not compiled
    • 176 |
    • Added a class-level compiled? method for checking if a template 177 | has been compiled.
    • 178 |
    • Added an instance-level compiled? method.
    • 179 |
    • Cache template compilation in Sinatra
    • 180 |
    181 | 182 | 183 |

    0.2.2 (2009-10-11)

    184 | 185 |
      186 |
    • Improved documentation
    • 187 |
    • Fixed single line sections
    • 188 |
    • Broke preserved indentation (issue #2)
    • 189 |
    190 | 191 | 192 |

    0.2.1 (2009-10-11)

    193 | 194 |
      195 |
    • Mustache.underscore can now be called without an argument
    • 196 |
    • Settings now mostly live at the class level, excepting template
    • 197 |
    • Any setting changes causes the template to be recompiled
    • 198 |
    199 | 200 | 203 | 204 |
    205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 |
    227 |
    228 | 229 | -------------------------------------------------------------------------------- /docs/classes/Rack/Bug/MustachePanel/View.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Rack::Bug::MustachePanel::View 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 34 |
    35 |
    36 | 37 |
    38 |

    39 | The view is responsible for rendering our panel. While Rack::Bug takes care of the nav, the content 41 | rendered by View is used for the panel itself. 42 |

    43 | 44 |
    45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
    Methods
    55 |
    56 | 57 |
    T
    58 |
    59 |
      60 | 61 |
    • times
    • 62 | 63 |
    64 |
    65 | 66 |
    V
    67 |
    68 | 73 |
    74 | 75 |
    76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
    Instance Public methods
    90 | 91 |
    92 |
    93 | 94 | times() 95 | 96 |
    97 | 98 |
    99 |

    100 | We track the render times of all the Mustache views on this page load. 102 |

    103 | 104 |
    105 | 106 | 107 | 108 | 109 |
    110 | 116 |
    117 |
    # File lib/rack/bug/panels/mustache_panel.rb, line 22
    118 |         def times
    119 |           MustachePanel.times.map do |key, value|
    120 |             { :key => key, :value => value }
    121 |           end
    122 |         end
    123 |
    124 |
    125 | 126 |
    127 | 128 |
    129 |
    130 | 131 | variables() 132 | 133 |
    134 | 135 |
    136 |

    137 | Any variables used in this page load are collected and displayed. 138 |

    139 | 140 |
    141 | 142 | 143 | 144 | 145 |
    146 | 152 |
    153 |
    # File lib/rack/bug/panels/mustache_panel.rb, line 29
    154 |         def variables
    155 |           vars = MustachePanel.variables.sort_by { |key, _| key.to_s }
    156 |           vars.map do |key, value|
    157 |             # Arrays can get too huge. Just show the first 10 to give you
    158 |             # some idea.
    159 |             if value.is_a?(Array) && value.size > 10
    160 |               size = value.size
    161 |               value = value.first(10)
    162 |               value << "...and #{size - 10} more"
    163 |             end
    164 | 
    165 |             { :key => key, :value => value.inspect }
    166 |           end
    167 |         end
    168 |
    169 |
    170 | 171 |
    172 | 173 |
    174 |
    175 | 176 | -------------------------------------------------------------------------------- /docs/css/panel.css: -------------------------------------------------------------------------------- 1 | /* Panel (begin) */ 2 | .panel 3 | { 4 | position: absolute; 5 | width: 100%; 6 | height: 100%; 7 | top: 0; 8 | left: 0; 9 | background: #FFF; 10 | z-index: 2; 11 | font-family: "Helvetica Neue", "Arial", sans-serif; 12 | //zoom: 1; 13 | } 14 | 15 | .panel_tree .results, 16 | .panel_results .tree 17 | { 18 | display: none; 19 | } 20 | 21 | /* Header with search box (begin) */ 22 | .panel .header 23 | { 24 | width: 100%; 25 | height: 29px; 26 | border-bottom: 1px solid #666; 27 | position: relative; 28 | left: 0; top: 0; 29 | background: #e8e8e8; 30 | } 31 | 32 | .panel .header div 33 | { 34 | margin: 0 7px; 35 | } 36 | .panel .header table 37 | { 38 | height: 29px; 39 | width: 100%; 40 | } 41 | 42 | .panel .header table td 43 | { 44 | vertical-align: middle; 45 | text-align: middle; 46 | } 47 | 48 | .panel .header label 49 | { 50 | position: absolute; 51 | font-size: 12px; 52 | line-height: 29px; 53 | margin-left: 3px; 54 | color: #999; 55 | cursor: text; 56 | } 57 | 58 | .panel .header table input 59 | { 60 | width: 100%; 61 | box-sizing: border-box; 62 | -moz-box-sizing: border-box; 63 | -webkit-box-sizing: border-box; 64 | display: inline-block; 65 | -webkit-appearance: searchfield; 66 | height: 22px; 67 | //height: auto; 68 | } 69 | 70 | /* Header with search box (end) */ 71 | 72 | 73 | /* Results (begin) */ 74 | .panel .result 75 | { 76 | position: absolute; 77 | top: 30px; 78 | bottom: 0; 79 | left: 0; 80 | width: 100%; 81 | //height: expression((this.parentNode.offsetHeight - 31)); 82 | overflow-y: scroll; 83 | overflow-x: hidden; 84 | -overflow-y: hidden; 85 | background: #EDF3FE url(../i/results_bg.png); 86 | z-index: 2; 87 | //zoom:1; 88 | } 89 | 90 | .panel .result ul 91 | { 92 | font-size: 0.8em; 93 | width: 100%; 94 | background: #EDF3FE url(../i/results_bg.png); 95 | //zoom:1; 96 | } 97 | 98 | .panel .result ul li 99 | { 100 | height: 46px; 101 | -height: 50px; 102 | //display: inline; 103 | //width: 100%; 104 | //zoom: 1; 105 | overflow: hidden; 106 | padding: 4px 10px 0 10px; 107 | cursor: pointer; 108 | } 109 | 110 | .panel .result ul li h1 111 | { 112 | font-size: 13px; 113 | font-weight: normal; 114 | color: #333; 115 | margin-bottom: 2px; 116 | white-space: nowrap; 117 | } 118 | 119 | .panel .result ul li p 120 | { 121 | font-size: 11px; 122 | color: #333; 123 | margin-bottom: 2px; 124 | white-space: nowrap; 125 | } 126 | 127 | .panel .result ul li h1 i, 128 | .panel .result ul li p.snippet 129 | { 130 | color: #999; 131 | } 132 | 133 | .panel .result ul li b 134 | { 135 | color: #000; 136 | } 137 | 138 | .panel .result ul li.current 139 | { 140 | background: #3875D7; 141 | } 142 | 143 | .panel .result ul li.current h1, 144 | .panel .result ul li.current p 145 | { 146 | color: #DDD; 147 | } 148 | 149 | .panel .result ul li.current h1 i, 150 | .panel .result ul li.current p.snippet 151 | { 152 | color: #AAA; 153 | } 154 | 155 | .panel .result ul li.current b 156 | { 157 | color: #FFF; 158 | } 159 | 160 | 161 | .panel .result ul li:hover, 162 | .panel .result ul li.selected 163 | { 164 | background: #d0d0d0; 165 | } 166 | 167 | .panel .result ul li.current:hover 168 | { 169 | background: #2965C0; 170 | } 171 | 172 | .panel .result ul li .badge 173 | { 174 | margin-right: 0.4em; 175 | margin-left: -0.2em; 176 | padding: 0 0.2em; 177 | color: #000; 178 | } 179 | 180 | .panel .result ul li .badge_1 181 | { 182 | background: #ACDBF4; 183 | } 184 | 185 | .panel .result ul li.current .badge_1 186 | { 187 | background: #97BFD7; 188 | } 189 | 190 | .panel .result ul li .badge_2 191 | { 192 | background: #ACF3C3; 193 | } 194 | 195 | .panel .result ul li.current .badge_2 196 | { 197 | background: #98D7AC; 198 | } 199 | 200 | .panel .result ul li .badge_3 201 | { 202 | background: #E0F3AC; 203 | } 204 | 205 | .panel .result ul li.current .badge_3 206 | { 207 | background: #C4D798; 208 | } 209 | 210 | .panel .result ul li .badge_4 211 | { 212 | background: #D7CA98; 213 | } 214 | 215 | .panel .result ul li.current .badge_4 216 | { 217 | background: #A6B0AC; 218 | } 219 | 220 | .panel .result ul li .badge_5 221 | { 222 | background: #F3C8AC; 223 | } 224 | 225 | .panel .result ul li.current .badge_5 226 | { 227 | background: #D7B198; 228 | } 229 | 230 | .panel .result ul li .badge_6 231 | { 232 | background: #F3ACC3; 233 | } 234 | 235 | .panel .result ul li.current .badge_6 236 | { 237 | background: #D798AB; 238 | } 239 | 240 | /* Results (end) */ 241 | 242 | /* Tree (begin) */ /**/ 243 | .panel .tree 244 | { 245 | position: absolute; 246 | top: 30px; 247 | bottom: 0; 248 | left: 0; 249 | width: 100%; 250 | //zoom: 1; 251 | //height: expression((this.parentNode.offsetHeight - 31)); 252 | overflow-y: scroll; 253 | overflow-x: hidden; 254 | -overflow-y: hidden; 255 | background: #EDF3FE url(../i/tree_bg.png); 256 | z-index: 30; 257 | } 258 | 259 | .panel .tree ul 260 | { 261 | background: #EDF3FE url(../i/tree_bg.png); 262 | } 263 | 264 | .panel .tree li 265 | { 266 | cursor: pointer; 267 | overflow: hidden; 268 | //height: 23px; 269 | //display: inline; 270 | //zoom: 1; 271 | //width: 100%; 272 | } 273 | 274 | 275 | .panel .tree li .content 276 | { 277 | padding-left: 18px; 278 | padding-top: 5px; 279 | height: 18px; 280 | overflow: hidden; 281 | position: relative; 282 | } 283 | 284 | .panel .tree li .icon 285 | { 286 | width: 10px; 287 | height: 9px; 288 | background: url(../i/arrows.png); 289 | background-position: 0 -9px; 290 | position: absolute; 291 | left: 1px; 292 | top: 8px; 293 | cursor: default; 294 | } 295 | 296 | .panel .tree li.closed .icon 297 | { 298 | background-position: 0 0; 299 | } 300 | 301 | .panel .tree ul li h1 302 | { 303 | font-size: 13px; 304 | font-weight: normal; 305 | color: #000; 306 | margin-bottom: 2px; 307 | white-space: nowrap; 308 | } 309 | 310 | .panel .tree ul li p 311 | { 312 | font-size: 11px; 313 | color: #666; 314 | margin-bottom: 2px; 315 | white-space: nowrap; 316 | } 317 | 318 | .panel .tree ul li h1 i 319 | { 320 | color: #999; 321 | font-style: normal; 322 | } 323 | 324 | .panel .tree ul li.empty 325 | { 326 | cursor: text; 327 | } 328 | 329 | .panel .tree ul li.empty h1, 330 | .panel .tree ul li.empty p 331 | { 332 | color: #666; 333 | font-style: italic; 334 | } 335 | 336 | .panel .tree ul li.current 337 | { 338 | background: #3875D7; 339 | } 340 | 341 | .panel .tree ul li.current .icon 342 | { 343 | background-position: -10px -9px; 344 | } 345 | 346 | .panel .tree ul li.current.closed .icon 347 | { 348 | background-position: -10px 0; 349 | } 350 | 351 | .panel .tree ul li.current h1 352 | { 353 | color: #FFF; 354 | } 355 | 356 | .panel .tree ul li.current p 357 | { 358 | color: #CCC; 359 | } 360 | 361 | .panel .tree ul li.current.empty h1, 362 | .panel .tree ul li.current.empty p 363 | { 364 | color: #999; 365 | } 366 | 367 | .panel .tree ul li:hover 368 | { 369 | background: #d0d0d0; 370 | } 371 | 372 | .panel .tree ul li.current:hover 373 | { 374 | background: #2965C0; 375 | } 376 | 377 | .panel .tree .stopper 378 | { 379 | display: none; 380 | } 381 | /* Tree (end) */ /**/ 382 | 383 | /* Panel (end) */ -------------------------------------------------------------------------------- /mustache.5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | mustache(5) -- Logic-less templates. 7 | 53 | 54 | 55 |
    56 | 57 |

    mustache(5)

    58 | 59 |
      60 |
    1. mustache(5)
    2. 61 |
    3. Mustache Manual
    4. 62 |
    5. mustache(5)
    6. 63 |
    64 | 65 |

    NAME

    66 |

    mustache -- Logic-less templates.

    67 | 68 |

    SYNOPSIS

    69 | 70 |

    A typical Mustache template:

    71 | 72 |
    Hello {{name}}
     73 | You have just won ${{value}}!
     74 | {{#in_ca}}
     75 | Well, ${{taxed_value}}, after taxes.
     76 | {{/in_ca}}
     77 | 
    78 | 79 |

    Given the following hash:

    80 | 81 |
    {
     82 |   "name": "Chris",
     83 |   "value": 10000,
     84 |   "taxed_value": 10000 - (10000 * 0.4),
     85 |   "in_ca": true
     86 | }
     87 | 
    88 | 89 |

    Will produce the following:

    90 | 91 |
    Hello Chris
     92 | You have just won $10000!
     93 | Well, $6000.0, after taxes.
     94 | 
    95 | 96 |

    DESCRIPTION

    97 | 98 |

    Mustache can be used for HTML, config files, source code - 99 | anything. It works by expanding tags in a template using values 100 | provided in a hash or object.

    101 | 102 |

    We call it "logic-less" because there are no if statements, else 103 | clauses, or for loops. Instead there are only tags. Some tags are 104 | replaced with a value, some nothing, and others a series of 105 | values. This document explains the different types of Mustache tags.

    106 | 107 |

    TAG TYPES

    108 | 109 |

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

    112 | 113 |

    Variables

    114 | 115 |

    The most basic tag type is the variable. A {{name}} tag in a basic 116 | template will try to find the name key in the current context. If 117 | there is no name key, nothing will be rendered.

    118 | 119 |

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

    121 | 122 |

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

    124 | 125 |

    By default a variable "miss" returns an empty string. This can usually 126 | be configured in your Mustache library. The Ruby version of Mustache 127 | supports raising an exception in this situation, for instance.

    128 | 129 |

    Template:

    130 | 131 |
    * {{name}}
    132 | * {{age}}
    133 | * {{company}}
    134 | * {{{company}}}
    135 | 
    136 | 137 |

    Hash:

    138 | 139 |
    {
    140 |   "name": "Chris",
    141 |   "company": "<b>GitHub</b>"
    142 | }
    143 | 
    144 | 145 |

    Output:

    146 | 147 |
    * Chris
    148 | *
    149 | * &lt;b&gt;GitHub&lt;/b&gt;
    150 | * <b>GitHub</b>
    151 | 
    152 | 153 |

    Sections

    154 | 155 |

    Sections render blocks of text one or more times, depending on the 156 | value of the key in the current context.

    157 | 158 |

    A section begins with a pound and ends with a slash. That is, 159 | {{#person}} begins a "person" section while {{/person}} ends it.

    160 | 161 |

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

    162 | 163 |

    False Values or Empty Lists

    164 | 165 |

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

    167 | 168 |

    Template:

    169 | 170 |
    Shown.
    171 | {{#nothin}}
    172 |   Never shown!
    173 | {{/nothin}}
    174 | 
    175 | 176 |

    Hash:

    177 | 178 |
    {
    179 |   "person": true,
    180 | }
    181 | 
    182 | 183 |

    Output:

    184 | 185 |
    Shown.
    186 | 
    187 | 188 |

    Non-Empty Lists

    189 | 190 |

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

    192 | 193 |

    When the value is a non-empty list, the text in the block will be 194 | displayed once for each item in the list. The context of the block 195 | will be set to the current item for each iteration. In this way we can 196 | loop over collections.

    197 | 198 |

    Template:

    199 | 200 |
    {{#repo}}
    201 |   <b>{{name}}</b>
    202 | {{/repo}}
    203 | 
    204 | 205 |

    Hash:

    206 | 207 |
    {
    208 |   "repo": [
    209 |     { "name": "resque" },
    210 |     { "name": "hub" },
    211 |     { "name": "rip" },
    212 |   ]
    213 | }
    214 | 
    215 | 216 |

    Output:

    217 | 218 |
    <b>resque</b>
    219 | <b>hub</b>
    220 | <b>rip</b>
    221 | 
    222 | 223 |

    Lambdas

    224 | 225 |

    When the value is a callable object, such as a function or lambda, the 226 | object will be invoked and passed the block of text. The text passed 227 | is the literal block, unrendered. {{tags}} will not have been expanded 228 | - the lambda should do that on its own. In this way you can implement 229 | filters or caching.

    230 | 231 |

    Template:

    232 | 233 |
    {{#wrapped}}
    234 |   {{name}} is awesome.
    235 | {{/wrapped}}
    236 | 
    237 | 238 |

    Hash:

    239 | 240 |
    {
    241 |   "name": "Willy",
    242 |   "wrapped": function() {
    243 |     return function(text) {
    244 |       return "<b>" + render(text) + "</b>"
    245 |     }
    246 |   }
    247 | }
    248 | 
    249 | 250 |

    Output:

    251 | 252 |
    <b>Willy is awesome.</b>
    253 | 
    254 | 255 |

    Non-False Values

    256 | 257 |

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

    259 | 260 |

    Template:

    261 | 262 |
    {{#person?}}
    263 |   Hi {{name}}!
    264 | {{/person?}}
    265 | 
    266 | 267 |

    Hash:

    268 | 269 |
    {
    270 |   "person?": { "name": "Jon" }
    271 | }
    272 | 
    273 | 274 |

    Output:

    275 | 276 |
    Hi Jon!
    277 | 
    278 | 279 |

    Inverted Sections

    280 | 281 |

    An inverted section begins with a caret (hat) and ends with a 282 | slash. That is {{^person}} begins a "person" inverted section while 283 | {{/person}} ends it.

    284 | 285 |

    While sections can be used to render text one or more times based on the 286 | value of the key, inverted sections may render text once based 287 | on the inverse value of the key. That is, they will be rendered 288 | if the key doesn't exist, is false, or is an empty list.

    289 | 290 |

    Template:

    291 | 292 |
    {{#repo}}
    293 |   <b>{{name}}</b>
    294 | {{/repo}}
    295 | {{^repo}}
    296 |   No repos :(
    297 | {{/repo}}
    298 | 
    299 | 300 |

    Hash:

    301 | 302 |
    {
    303 |   "repo": []
    304 | }
    305 | 
    306 | 307 |

    Output:

    308 | 309 |
    No repos :(
    310 | 
    311 | 312 |

    Comments

    313 | 314 |

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

    315 | 316 |
    <h1>Today{{! ignore me }}.</h1>
    317 | 
    318 | 319 |

    Will render as follows:

    320 | 321 |
    <h1>Today.</h1>
    322 | 
    323 | 324 |

    Comments may contain newlines.

    325 | 326 |

    Partials

    327 | 328 |

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

    329 | 330 |

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

    332 | 333 |

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

    335 | 336 |
    <%= partial :next_more, :start => start, :size => size %>
    337 | 
    338 | 339 |

    Mustache requires only this:

    340 | 341 |
    {{> next_more}}
    342 | 
    343 | 344 |

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

    346 | 347 |

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

    349 | 350 |

    For example, this template and partial:

    351 | 352 |
    base.mustache:
    353 | <h2>Names</h2>
    354 | {{#names}}
    355 |   {{> user}}
    356 | {{/names}}
    357 | 
    358 | user.mustache:
    359 | <strong>{{name}}</strong>
    360 | 
    361 | 362 |

    Can be thought of as a single, expanded template:

    363 | 364 |
    <h2>Names</h2>
    365 | {{#names}}
    366 |   <strong>{{name}}</strong>
    367 | {{/names}}
    368 | 
    369 | 370 |

    Set Delimiter

    371 | 372 |

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

    374 | 375 |

    Consider the following contrived example:

    376 | 377 |
    * {{default_tags}}
    378 | {{=<% %>=}}
    379 | * <% erb_style_tags %>
    380 | <%={{ }}=%>
    381 | * {{ default_tags_again }}
    382 | 
    383 | 384 |

    Here we have a list with three items. The first item uses the default 385 | tag style, the second uses erb style as defined by the Set Delimiter 386 | tag, and the third returns to the default style after yet another Set 387 | Delimiter declaration.

    388 | 389 |

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

    392 | 393 |

    Custom delimiters may not contain whitespace or the equals sign.

    394 | 395 |

    COPYRIGHT

    396 | 397 |

    Mustache is Copyright (C) 2009 Chris Wanstrath

    398 | 399 |

    Original CTemplate by Google

    400 | 401 |

    SEE ALSO

    402 | 403 |

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

    405 | 406 | 407 |
      408 |
    1. DEFUNKT
    2. 409 |
    3. April 2010
    4. 410 |
    5. mustache(5)
    6. 411 |
    412 | 413 |
    414 | 415 | 416 | -------------------------------------------------------------------------------- /docs/classes/Mustache/Template.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Mustache::Template 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 34 |
    35 |
    36 | 37 |
    38 |

    39 | A Template represents a Mustache template. It compiles and caches a raw 41 | string template into something usable. 42 |

    43 |

    44 | The idea is this: when handed a Mustache 45 | template, convert it into a Ruby string by transforming Mustache tags into interpolated Ruby. 47 |

    48 |

    49 | You shouldn’t use this class directly, instead: 50 |

    51 |

    52 | >> Mustache.render(template, hash) 53 |

    54 | 55 |
    56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 |
    Methods
    66 |
    67 | 68 |
    C
    69 |
    70 | 75 |
    76 | 77 |
    N
    78 |
    79 |
      80 | 81 |
    • new
    • 82 | 83 |
    84 |
    85 | 86 |
    R
    87 |
    88 | 93 |
    94 | 95 |
    T
    96 |
    97 | 104 |
    105 | 106 |
    107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 |
    Attributes
    119 | 120 | 121 | 122 | 125 | 126 | 127 | 128 | 129 |
    123 | [R] 124 | source
    130 | 131 | 132 | 133 |
    Class Public methods
    134 | 135 |
    136 |
    137 | 138 | new(source) 139 | 140 |
    141 | 142 |
    143 |

    144 | Expects a Mustache template as a string 145 | along with a template path, which it uses to find partials. 146 |

    147 | 148 |
    149 | 150 | 151 | 152 | 153 |
    154 | 160 |
    161 |
    # File lib/mustache/template.rb, line 22
    162 |     def initialize(source)
    163 |       @source = source
    164 |       @tmpid = 0
    165 |     end
    166 |
    167 |
    168 | 169 |
    170 | 171 |
    Instance Public methods
    172 | 173 |
    174 |
    175 | 176 | compile(src = @source) 177 | 178 |
    179 | 180 |
    181 |

    182 | Does the dirty work of transforming a Mustache template into an 184 | interpolation-friendly Ruby string. 185 |

    186 | 187 |
    188 | 189 | 190 |
    191 | This method is also aliased as 192 | 193 | to_s 194 | 195 |
    196 | 197 | 198 | 199 |
    200 | 206 |
    207 |
    # File lib/mustache/template.rb, line 49
    208 |     def compile(src = @source)
    209 |       Generator.new.compile(tokens)
    210 |     end
    211 |
    212 |
    213 | 214 |
    215 | 216 |
    217 |
    218 | 219 | render(context) 220 | 221 |
    222 | 223 |
    224 |

    225 | Renders the `@source` Mustache template 226 | using the given `context`, which should be a simple hash keyed with 227 | symbols. 228 |

    229 |

    230 | The first time a template is rendered, this method is overriden and from 231 | then on it is “compiled”. Subsequent calls will skip the 232 | compilation step and run the Ruby version of the template directly. 233 |

    234 | 235 |
    236 | 237 | 238 | 239 | 240 |
    241 | 247 |
    248 |
    # File lib/mustache/template.rb, line 34
    249 |     def render(context)
    250 |       # Compile our Mustache template into a Ruby string
    251 |       compiled = "def render(ctx) #{compile} end"
    252 | 
    253 |       # Here we rewrite ourself with the interpolated Ruby version of
    254 |       # our Mustache template so subsequent calls are very fast and
    255 |       # can skip the compilation stage.
    256 |       instance_eval(compiled, __FILE__, __LINE__ - 1)
    257 | 
    258 |       # Call the newly rewritten version of #render
    259 |       render(context)
    260 |     end
    261 |
    262 |
    263 | 264 |
    265 | 266 |
    267 |
    268 | 269 | to_s(src = @source) 270 | 271 |
    272 | 273 |
    274 |

    275 | Alias for compile 276 |

    277 | 278 |
    279 | 280 | 281 | 282 |
    283 | 284 |
    285 |
    286 | 287 | tokens(src = @source) 288 | 289 |
    290 | 291 |
    292 |

    293 | Returns an array of tokens for a given template. 294 |

    295 | 296 |
    297 | 298 | 299 | 300 | 301 |
    302 | 308 |
    309 |
    # File lib/mustache/template.rb, line 55
    310 |     def tokens(src = @source)
    311 |       Parser.new.compile(src)
    312 |     end
    313 |
    314 |
    315 | 316 |
    317 | 318 |
    319 |
    320 | 321 | -------------------------------------------------------------------------------- /extras/mustache.js: -------------------------------------------------------------------------------- 1 | /* 2 | mustache.js — Logic-less templates in JavaScript 3 | 4 | See http://mustache.github.com/ for more info. 5 | */ 6 | 7 | var Mustache = function () { 8 | var _toString = Object.prototype.toString; 9 | 10 | Array.isArray = Array.isArray || function (obj) { 11 | return _toString.call(obj) == "[object Array]"; 12 | } 13 | 14 | var _trim = String.prototype.trim, trim; 15 | 16 | if (_trim) { 17 | trim = function (text) { 18 | return text == null ? "" : _trim.call(text); 19 | } 20 | } else { 21 | var trimLeft, trimRight; 22 | 23 | // IE doesn't match non-breaking spaces with \s. 24 | if ((/\S/).test("\xA0")) { 25 | trimLeft = /^[\s\xA0]+/; 26 | trimRight = /[\s\xA0]+$/; 27 | } else { 28 | trimLeft = /^\s+/; 29 | trimRight = /\s+$/; 30 | } 31 | 32 | trim = function (text) { 33 | return text == null ? "" : 34 | text.toString().replace(trimLeft, "").replace(trimRight, ""); 35 | } 36 | } 37 | 38 | var escapeMap = { 39 | "&": "&", 40 | "<": "<", 41 | ">": ">", 42 | '"': '"', 43 | "'": ''' 44 | }; 45 | 46 | function escapeHTML(string) { 47 | return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) { 48 | return escapeMap[s] || s; 49 | }); 50 | } 51 | 52 | var regexCache = {}; 53 | var Renderer = function () {}; 54 | 55 | Renderer.prototype = { 56 | otag: "{{", 57 | ctag: "}}", 58 | pragmas: {}, 59 | buffer: [], 60 | pragmas_implemented: { 61 | "IMPLICIT-ITERATOR": true 62 | }, 63 | context: {}, 64 | 65 | render: function (template, context, partials, in_recursion) { 66 | // reset buffer & set context 67 | if (!in_recursion) { 68 | this.context = context; 69 | this.buffer = []; // TODO: make this non-lazy 70 | } 71 | 72 | // fail fast 73 | if (!this.includes("", template)) { 74 | if (in_recursion) { 75 | return template; 76 | } else { 77 | this.send(template); 78 | return; 79 | } 80 | } 81 | 82 | // get the pragmas together 83 | template = this.render_pragmas(template); 84 | 85 | // render the template 86 | var html = this.render_section(template, context, partials); 87 | 88 | // render_section did not find any sections, we still need to render the tags 89 | if (html === false) { 90 | html = this.render_tags(template, context, partials, in_recursion); 91 | } 92 | 93 | if (in_recursion) { 94 | return html; 95 | } else { 96 | this.sendLines(html); 97 | } 98 | }, 99 | 100 | /* 101 | Sends parsed lines 102 | */ 103 | send: function (line) { 104 | if (line !== "") { 105 | this.buffer.push(line); 106 | } 107 | }, 108 | 109 | sendLines: function (text) { 110 | if (text) { 111 | var lines = text.split("\n"); 112 | for (var i = 0; i < lines.length; i++) { 113 | this.send(lines[i]); 114 | } 115 | } 116 | }, 117 | 118 | /* 119 | Looks for %PRAGMAS 120 | */ 121 | render_pragmas: function (template) { 122 | // no pragmas 123 | if (!this.includes("%", template)) { 124 | return template; 125 | } 126 | 127 | var that = this; 128 | var regex = this.getCachedRegex("render_pragmas", function (otag, ctag) { 129 | return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g"); 130 | }); 131 | 132 | return template.replace(regex, function (match, pragma, options) { 133 | if (!that.pragmas_implemented[pragma]) { 134 | throw({message: 135 | "This implementation of mustache doesn't understand the '" + 136 | pragma + "' pragma"}); 137 | } 138 | that.pragmas[pragma] = {}; 139 | if (options) { 140 | var opts = options.split("="); 141 | that.pragmas[pragma][opts[0]] = opts[1]; 142 | } 143 | return ""; 144 | // ignore unknown pragmas silently 145 | }); 146 | }, 147 | 148 | /* 149 | Tries to find a partial in the curent scope and render it 150 | */ 151 | render_partial: function (name, context, partials) { 152 | name = trim(name); 153 | if (!partials || partials[name] === undefined) { 154 | throw({message: "unknown_partial '" + name + "'"}); 155 | } 156 | if (!context || typeof context[name] != "object") { 157 | return this.render(partials[name], context, partials, true); 158 | } 159 | return this.render(partials[name], context[name], partials, true); 160 | }, 161 | 162 | /* 163 | Renders inverted (^) and normal (#) sections 164 | */ 165 | render_section: function (template, context, partials) { 166 | if (!this.includes("#", template) && !this.includes("^", template)) { 167 | // did not render anything, there were no sections 168 | return false; 169 | } 170 | 171 | var that = this; 172 | 173 | var regex = this.getCachedRegex("render_section", function (otag, ctag) { 174 | // This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder 175 | return new RegExp( 176 | "^([\\s\\S]*?)" + // all the crap at the beginning that is not {{*}} ($1) 177 | 178 | otag + // {{ 179 | "(\\^|\\#)\\s*(.+)\\s*" + // #foo (# == $2, foo == $3) 180 | ctag + // }} 181 | 182 | "\n*([\\s\\S]*?)" + // between the tag ($2). leading newlines are dropped 183 | 184 | otag + // {{ 185 | "\\/\\s*\\3\\s*" + // /foo (backreference to the opening tag). 186 | ctag + // }} 187 | 188 | "\\s*([\\s\\S]*)$", // everything else in the string ($4). leading whitespace is dropped. 189 | 190 | "g"); 191 | }); 192 | 193 | 194 | // for each {{#foo}}{{/foo}} section do... 195 | return template.replace(regex, function (match, before, type, name, content, after) { 196 | // before contains only tags, no sections 197 | var renderedBefore = before ? that.render_tags(before, context, partials, true) : "", 198 | 199 | // after may contain both sections and tags, so use full rendering function 200 | renderedAfter = after ? that.render(after, context, partials, true) : "", 201 | 202 | // will be computed below 203 | renderedContent, 204 | 205 | value = that.find(name, context); 206 | 207 | if (type === "^") { // inverted section 208 | if (!value || Array.isArray(value) && value.length === 0) { 209 | // false or empty list, render it 210 | renderedContent = that.render(content, context, partials, true); 211 | } else { 212 | renderedContent = ""; 213 | } 214 | } else if (type === "#") { // normal section 215 | if (Array.isArray(value)) { // Enumerable, Let's loop! 216 | renderedContent = that.map(value, function (row) { 217 | return that.render(content, that.create_context(row), partials, true); 218 | }).join(""); 219 | } else if (that.is_object(value)) { // Object, Use it as subcontext! 220 | renderedContent = that.render(content, that.create_context(value), 221 | partials, true); 222 | } else if (typeof value == "function") { 223 | // higher order section 224 | renderedContent = value.call(context, content, function (text) { 225 | return that.render(text, context, partials, true); 226 | }); 227 | } else if (value) { // boolean section 228 | renderedContent = that.render(content, context, partials, true); 229 | } else { 230 | renderedContent = ""; 231 | } 232 | } 233 | 234 | return renderedBefore + renderedContent + renderedAfter; 235 | }); 236 | }, 237 | 238 | /* 239 | Replace {{foo}} and friends with values from our view 240 | */ 241 | render_tags: function (template, context, partials, in_recursion) { 242 | // tit for tat 243 | var that = this; 244 | 245 | var new_regex = function () { 246 | return that.getCachedRegex("render_tags", function (otag, ctag) { 247 | return new RegExp(otag + "(=|!|>|&|\\{|%)?([^#\\^]+?)\\1?" + ctag + "+", "g"); 248 | }); 249 | }; 250 | 251 | var regex = new_regex(); 252 | var tag_replace_callback = function (match, operator, name) { 253 | switch(operator) { 254 | case "!": // ignore comments 255 | return ""; 256 | case "=": // set new delimiters, rebuild the replace regexp 257 | that.set_delimiters(name); 258 | regex = new_regex(); 259 | return ""; 260 | case ">": // render partial 261 | return that.render_partial(name, context, partials); 262 | case "{": // the triple mustache is unescaped 263 | case "&": // & operator is an alternative unescape method 264 | return that.find(name, context); 265 | default: // escape the value 266 | return escapeHTML(that.find(name, context)); 267 | } 268 | }; 269 | var lines = template.split("\n"); 270 | for(var i = 0; i < lines.length; i++) { 271 | lines[i] = lines[i].replace(regex, tag_replace_callback, this); 272 | if (!in_recursion) { 273 | this.send(lines[i]); 274 | } 275 | } 276 | 277 | if (in_recursion) { 278 | return lines.join("\n"); 279 | } 280 | }, 281 | 282 | set_delimiters: function (delimiters) { 283 | var dels = delimiters.split(" "); 284 | this.otag = this.escape_regex(dels[0]); 285 | this.ctag = this.escape_regex(dels[1]); 286 | }, 287 | 288 | escape_regex: function (text) { 289 | // thank you Simon Willison 290 | if (!arguments.callee.sRE) { 291 | var specials = [ 292 | '/', '.', '*', '+', '?', '|', 293 | '(', ')', '[', ']', '{', '}', '\\' 294 | ]; 295 | arguments.callee.sRE = new RegExp( 296 | '(\\' + specials.join('|\\') + ')', 'g' 297 | ); 298 | } 299 | return text.replace(arguments.callee.sRE, '\\$1'); 300 | }, 301 | 302 | /* 303 | find `name` in current `context`. That is find me a value 304 | from the view object 305 | */ 306 | find: function (name, context) { 307 | name = trim(name); 308 | 309 | // Checks whether a value is thruthy or false or 0 310 | function is_kinda_truthy(bool) { 311 | return bool === false || bool === 0 || bool; 312 | } 313 | 314 | var value; 315 | 316 | // check for dot notation eg. foo.bar 317 | if (name.match(/([a-z_]+)\./ig)) { 318 | var childValue = this.walk_context(name, context); 319 | if (is_kinda_truthy(childValue)) { 320 | value = childValue; 321 | } 322 | } else { 323 | if (is_kinda_truthy(context[name])) { 324 | value = context[name]; 325 | } else if (is_kinda_truthy(this.context[name])) { 326 | value = this.context[name]; 327 | } 328 | } 329 | 330 | if (typeof value == "function") { 331 | return value.apply(context); 332 | } 333 | if (value !== undefined) { 334 | return value; 335 | } 336 | // silently ignore unkown variables 337 | return ""; 338 | }, 339 | 340 | walk_context: function (name, context) { 341 | var path = name.split('.'); 342 | // if the var doesn't exist in current context, check the top level context 343 | var value_context = (context[path[0]] != undefined) ? context : this.context; 344 | var value = value_context[path.shift()]; 345 | while (value != undefined && path.length > 0) { 346 | value_context = value; 347 | value = value[path.shift()]; 348 | } 349 | // if the value is a function, call it, binding the correct context 350 | if (typeof value == "function") { 351 | return value.apply(value_context); 352 | } 353 | return value; 354 | }, 355 | 356 | // Utility methods 357 | 358 | /* includes tag */ 359 | includes: function (needle, haystack) { 360 | return haystack.indexOf(this.otag + needle) != -1; 361 | }, 362 | 363 | // by @langalex, support for arrays of strings 364 | create_context: function (_context) { 365 | if (this.is_object(_context)) { 366 | return _context; 367 | } else { 368 | var iterator = "."; 369 | if (this.pragmas["IMPLICIT-ITERATOR"]) { 370 | iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator; 371 | } 372 | var ctx = {}; 373 | ctx[iterator] = _context; 374 | return ctx; 375 | } 376 | }, 377 | 378 | is_object: function (a) { 379 | return a && typeof a == "object"; 380 | }, 381 | 382 | /* 383 | Why, why, why? Because IE. Cry, cry cry. 384 | */ 385 | map: function (array, fn) { 386 | if (typeof array.map == "function") { 387 | return array.map(fn); 388 | } else { 389 | var r = []; 390 | var l = array.length; 391 | for(var i = 0; i < l; i++) { 392 | r.push(fn(array[i])); 393 | } 394 | return r; 395 | } 396 | }, 397 | 398 | getCachedRegex: function (name, generator) { 399 | var byOtag = regexCache[this.otag]; 400 | if (!byOtag) { 401 | byOtag = regexCache[this.otag] = {}; 402 | } 403 | 404 | var byCtag = byOtag[this.ctag]; 405 | if (!byCtag) { 406 | byCtag = byOtag[this.ctag] = {}; 407 | } 408 | 409 | var regex = byCtag[name]; 410 | if (!regex) { 411 | regex = byCtag[name] = generator(this.otag, this.ctag); 412 | } 413 | 414 | return regex; 415 | } 416 | }; 417 | 418 | return({ 419 | name: "mustache.js", 420 | version: "0.4.0", 421 | 422 | /* 423 | Turns a template and view into HTML 424 | */ 425 | to_html: function (template, view, partials, send_fun) { 426 | var renderer = new Renderer(); 427 | if (send_fun) { 428 | renderer.send = send_fun; 429 | } 430 | renderer.render(template, view || {}, partials); 431 | if (!send_fun) { 432 | return renderer.buffer.join("\n"); 433 | } 434 | } 435 | }); 436 | }(); 437 | -------------------------------------------------------------------------------- /docs/classes/Rack/Bug/MustachePanel.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Rack::Bug::MustachePanel 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 34 |
    35 |
    36 | 37 |
    38 |

    39 | MustachePanel is a Rack::Bug panel which tracks the time spent 41 | rendering Mustache views as well as all 42 | the variables accessed during view rendering. 43 |

    44 |

    45 | It can be used to track down slow partials and ensure you’re only 46 | generating data you need. 47 |

    48 |

    49 | Also, it’s fun. 50 |

    51 | 52 |
    53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    Methods
    63 |
    64 | 65 |
    C
    66 |
    67 | 72 |
    73 | 74 |
    H
    75 |
    76 | 81 |
    82 | 83 |
    N
    84 |
    85 |
      86 | 87 |
    • name
    • 88 | 89 |
    90 |
    91 | 92 |
    R
    93 |
    94 |
      95 | 96 |
    • reset
    • 97 | 98 |
    99 |
    100 | 101 |
    T
    102 |
    103 |
      104 | 105 |
    • times
    • 106 | 107 |
    108 |
    109 | 110 |
    V
    111 |
    112 | 117 |
    118 | 119 |
    120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 |
    Classes and Modules
    128 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 |
    Class Public methods
    141 | 142 |
    143 |
    144 | 145 | reset() 146 | 147 |
    148 | 149 |
    150 |

    151 | Clear out our page load-specific variables. 152 |

    153 | 154 |
    155 | 156 | 157 | 158 | 159 |
    160 | 166 |
    167 |
    # File lib/rack/bug/panels/mustache_panel.rb, line 46
    168 |       def self.reset
    169 |         Thread.current["rack.bug.mustache.times"] = {}
    170 |         Thread.current["rack.bug.mustache.vars"] = {}
    171 |       end
    172 |
    173 |
    174 | 175 |
    176 | 177 |
    178 |
    179 | 180 | times() 181 | 182 |
    183 | 184 |
    185 |

    186 | The view render times for this page load 187 |

    188 | 189 |
    190 | 191 | 192 | 193 | 194 |
    195 | 201 |
    202 |
    # File lib/rack/bug/panels/mustache_panel.rb, line 52
    203 |       def self.times
    204 |         Thread.current["rack.bug.mustache.times"] ||= {}
    205 |       end
    206 |
    207 |
    208 | 209 |
    210 | 211 |
    212 |
    213 | 214 | variables() 215 | 216 |
    217 | 218 |
    219 |

    220 | The variables used on this page load 221 |

    222 | 223 |
    224 | 225 | 226 | 227 | 228 |
    229 | 235 |
    236 |
    # File lib/rack/bug/panels/mustache_panel.rb, line 57
    237 |       def self.variables
    238 |         Thread.current["rack.bug.mustache.vars"] ||= {}
    239 |       end
    240 |
    241 |
    242 | 243 |
    244 | 245 |
    Instance Public methods
    246 | 247 |
    248 |
    249 | 250 | content() 251 | 252 |
    253 | 254 |
    255 |

    256 | The content of our Rack::Bug panel 257 |

    258 | 259 |
    260 | 261 | 262 | 263 | 264 |
    265 | 271 |
    272 |
    # File lib/rack/bug/panels/mustache_panel.rb, line 74
    273 |       def content
    274 |         View.render
    275 |       ensure
    276 |         self.class.reset
    277 |       end
    278 |
    279 |
    280 | 281 |
    282 | 283 |
    284 |
    285 | 286 | heading() 287 | 288 |
    289 | 290 |
    291 |

    292 | The string used for our tab in Rack::Bug’s navigation bar 293 |

    294 | 295 |
    296 | 297 | 298 | 299 | 300 |
    301 | 307 |
    308 |
    # File lib/rack/bug/panels/mustache_panel.rb, line 67
    309 |       def heading
    310 |         "{{%.2fms}}" % self.class.times.values.inject(0.0) do |sum, obj|
    311 |           sum + obj
    312 |         end
    313 |       end
    314 |
    315 |
    316 | 317 |
    318 | 319 |
    320 |
    321 | 322 | name() 323 | 324 |
    325 | 326 |
    327 |

    328 | The name of this Rack::Bug panel 329 |

    330 | 331 |
    332 | 333 | 334 | 335 | 336 |
    337 | 343 |
    344 |
    # File lib/rack/bug/panels/mustache_panel.rb, line 62
    345 |       def name
    346 |         "mustache"
    347 |       end
    348 |
    349 |
    350 | 351 |
    352 | 353 |
    354 |
    355 | 356 | -------------------------------------------------------------------------------- /docs/files/README_md.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | README.md 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 25 | 26 |
    27 |
    28 | 29 |
    30 |

    Mustache

    31 | 32 |

    Inspired by ctemplate and et, Mustache is a 33 | framework-agnostic way to render logic-free views.

    34 | 35 |

    As ctemplates says, "It emphasizes separating logic from presentation: 36 | it is impossible to embed application logic in this template language."

    37 | 38 |

    For a list of implementations (other than Ruby) and tips, see 39 | http://mustache.github.com/.

    40 | 41 |

    Overview

    42 | 43 |

    Think of Mustache as a replacement for your views. Instead of views 44 | consisting of ERB or HAML with random helpers and arbitrary logic, 45 | your views are broken into two parts: a Ruby class and an HTML 46 | template.

    47 | 48 |

    We call the Ruby class the "view" and the HTML template the 49 | "template."

    50 | 51 |

    All your logic, decisions, and code is contained in your view. All 52 | your markup is contained in your template. The template does nothing 53 | but reference methods in your view.

    54 | 55 |

    This strict separation makes it easier to write clean templates, 56 | easier to test your views, and more fun to work on your app's front end.

    57 | 58 |

    Why?

    59 | 60 |

    I like writing Ruby. I like writing HTML. I like writing JavaScript.

    61 | 62 |

    I don't like writing ERB, Haml, Liquid, Django Templates, putting Ruby 63 | in my HTML, or putting JavaScript in my HTML.

    64 | 65 |

    Usage

    66 | 67 |

    Quick example:

    68 | 69 |
    >> require 'mustache'
     70 | => true
     71 | >> Mustache.render("Hello {{planet}}", :planet => "World!")
     72 | => "Hello World!"
     73 | 
    74 | 75 |

    We've got an examples folder but here's the canonical one:

    76 | 77 |
    class Simple < Mustache
     78 |   def name
     79 |     "Chris"
     80 |   end
     81 | 
     82 |   def value
     83 |     10_000
     84 |   end
     85 | 
     86 |   def taxed_value
     87 |     value - (value * 0.4)
     88 |   end
     89 | 
     90 |   def in_ca
     91 |     true
     92 |   end
     93 | end
     94 | 
    95 | 96 |

    We simply create a normal Ruby class and define methods. Some methods 97 | reference others, some return values, some return only booleans.

    98 | 99 |

    Now let's write the template:

    100 | 101 |
    Hello {{name}}
    102 | You have just won ${{value}}!
    103 | {{#in_ca}}
    104 | Well, ${{taxed_value}}, after taxes.
    105 | {{/in_ca}}
    106 | 
    107 | 108 |

    This template references our view methods. To bring it all together, 109 | here's the code to render actual HTML;

    110 | 111 |
    Simple.render
    112 | 
    113 | 114 |

    Which returns the following:

    115 | 116 |
    Hello Chris
    117 | You have just won $10000!
    118 | Well, $6000.0, after taxes.
    119 | 
    120 | 121 |

    Simple.

    122 | 123 |

    Tag Types

    124 | 125 |

    For a language-agnostic overview of Mustache's template syntax, see 126 | the mustache(5) manpage or 127 | http://mustache.github.com/mustache.5.html.

    128 | 129 |

    Escaping

    130 | 131 |

    Mustache does escape all values when using the standard double 132 | Mustache syntax. Characters which will be escaped: & \ " < >. To 133 | disable escaping, simply use tripple mustaches like 134 | {{{unescaped_variable}}}.

    135 | 136 |

    Example: Using {{variable}} inside a template for 5 > 2 will 137 | result in 5 &gt; 2, where as the usage of {{{variable}}} will 138 | result in 5 > 2.

    139 | 140 |

    Dict-Style Views

    141 | 142 |

    ctemplate and friends want you to hand a dictionary to the template 143 | processor. Mustache supports a similar concept. Feel free to mix the 144 | class-based and this more procedural style at your leisure.

    145 | 146 |

    Given this template (winner.mustache):

    147 | 148 |
    Hello {{name}}
    149 | You have just won ${{value}}!
    150 | 
    151 | 152 |

    We can fill in the values at will:

    153 | 154 |
    view = Winner.new
    155 | view[:name] = 'George'
    156 | view[:value] = 100
    157 | view.render
    158 | 
    159 | 160 |

    Which returns:

    161 | 162 |
    Hello George
    163 | You have just won $100!
    164 | 
    165 | 166 |

    We can re-use the same object, too:

    167 | 168 |
    view[:name] = 'Tony'
    169 | view.render
    170 | Hello Tony
    171 | You have just won $100!
    172 | 
    173 | 174 |

    Templates

    175 | 176 |

    A word on templates. By default, a view will try to find its template 177 | on disk by searching for an HTML file in the current directory that 178 | follows the classic Ruby naming convention.

    179 | 180 |
    TemplatePartial => ./template_partial.mustache
    181 | 
    182 | 183 |

    You can set the search path using Mustache.template_path. It can be set on a 184 | class by class basis:

    185 | 186 |
    class Simple < Mustache
    187 |   self.template_path = File.dirname(__FILE__)
    188 |   ... etc ...
    189 | end
    190 | 
    191 | 192 |

    Now Simple will look for simple.mustache in the directory it resides 193 | in, no matter the cwd.

    194 | 195 |

    If you want to just change what template is used you can set 196 | Mustache.template_file directly:

    197 | 198 |
    Simple.template_file = './blah.mustache'
    199 | 
    200 | 201 |

    Mustache also allows you to define the extension it'll use.

    202 | 203 |
    Simple.template_extension = 'xml'
    204 | 
    205 | 206 |

    Given all other defaults, the above line will cause Mustache to look 207 | for './blah.xml'

    208 | 209 |

    Feel free to set the template directly:

    210 | 211 |
    Simple.template = 'Hi {{person}}!'
    212 | 
    213 | 214 |

    Or set a different template for a single instance:

    215 | 216 |
    Simple.new.template = 'Hi {{person}}!'
    217 | 
    218 | 219 |

    Whatever works.

    220 | 221 |

    Views

    222 | 223 |

    Mustache supports a bit of magic when it comes to views. If you're 224 | authoring a plugin or extension for a web framework (Sinatra, Rails, 225 | etc), check out the view_namespace and view_path settings on the 226 | Mustache class. They will surely provide needed assistance.

    227 | 228 |

    Helpers

    229 | 230 |

    What about global helpers? Maybe you have a nifty gravatar function 231 | you want to use in all your views? No problem.

    232 | 233 |

    This is just Ruby, after all.

    234 | 235 |
    module ViewHelpers
    236 |   def gravatar(email, size = 30)
    237 |     gravatar_id = Digest::MD5.hexdigest(email.to_s.strip.downcase)
    238 |     gravatar_for_id(gravatar_id, size)
    239 |   end
    240 | 
    241 |   def gravatar_for_id(gid, size = 30)
    242 |     "#{gravatar_host}/avatar/#{gid}?s=#{size}"
    243 |   end
    244 | 
    245 |   def gravatar_host
    246 |     @ssl ? 'https://secure.gravatar.com' : 'http://www.gravatar.com'
    247 |   end
    248 | end
    249 | 
    250 | 251 |

    Then just include it:

    252 | 253 |
    class Simple < Mustache
    254 |   include ViewHelpers
    255 | 
    256 |   def name
    257 |     "Chris"
    258 |   end
    259 | 
    260 |   def value
    261 |     10_000
    262 |   end
    263 | 
    264 |   def taxed_value
    265 |     value - (value * 0.4)
    266 |   end
    267 | 
    268 |   def in_ca
    269 |     true
    270 |   end
    271 | end
    272 | 
    273 | 274 |

    Great, but what about that @ssl ivar in gravatar_host? There are 275 | many ways we can go about setting it.

    276 | 277 |

    Here's on example which illustrates a key feature of Mustache: you 278 | are free to use the initialize method just as you would in any 279 | normal class.

    280 | 281 |
    class Simple < Mustache
    282 |   include ViewHelpers
    283 | 
    284 |   def initialize(ssl = false)
    285 |     @ssl = ssl
    286 |   end
    287 | 
    288 |   ... etc ...
    289 | end
    290 | 
    291 | 292 |

    Now:

    293 | 294 |
    Simple.new(request.ssl?).render
    295 | 
    296 | 297 |

    Convoluted but you get the idea.

    298 | 299 |

    Sinatra

    300 | 301 |

    Mustache ships with Sinatra integration. Please see 302 | lib/mustache/sinatra.rb or 303 | http://github.com/defunkt/mustache/blob/master/lib/mustache/sinatra.rb 304 | for complete documentation.

    305 | 306 |

    An example Sinatra application is also provided: 307 | http://github.com/defunkt/mustache-sinatra-example

    308 | 309 |

    If you are upgrading to Sinatra 1.0 and Mustache 0.9.0+ from Mustache 310 | 0.7.0 or lower, the settings have changed. But not that much.

    311 | 312 |

    See this diff for what you need to 313 | do. Basically, things are named properly now and all should be 314 | contained in a hash set using set :mustache, hash.

    315 | 316 |

    Rack::Bug

    317 | 318 |

    Mustache also ships with a Rack::Bug panel. In your config.ru add 319 | the following code:

    320 | 321 |
    require 'rack/bug/panels/mustache_panel'
    322 | use Rack::Bug::MustachePanel
    323 | 
    324 | 325 |

    Using Rails? Add this to your initializer or environment file:

    326 | 327 |
    require 'rack/bug/panels/mustache_panel'
    328 | config.middleware.use "Rack::Bug::MustachePanel"
    329 | 
    330 | 331 |

    Rack::Bug

    332 | 333 |

    Vim

    334 | 335 |

    Thanks to Juvenn Woo for mustache.vim. It 336 | is included under the contrib/ directory.

    337 | 338 |

    See http://gist.github.com/323622 for installation instructions.

    339 | 340 |

    Emacs

    341 | 342 |

    mustache-mode.el is included under the contrib/ directory for any 343 | Emacs users. Based on Google's tpl-mode for ctemplates, it adds 344 | support for Mustache's more lenient tag values and includes a few 345 | commands for your editing pleasure.

    346 | 347 |

    See http://gist.github.com/323619 for installation instructions.

    348 | 349 |

    TextMate

    350 | 351 |

    Mustache.tmbundle

    352 | 353 |

    See http://gist.github.com/323624 for installation instructions.

    354 | 355 |

    Command Line

    356 | 357 |

    See mustache(1) man page or 358 | http://mustache.github.com/mustache.1.html 359 | for command line docs.

    360 | 361 |

    Installation

    362 | 363 |

    RubyGems

    364 | 365 |
    $ gem install mustache
    366 | 
    367 | 368 |

    Acknowledgements

    369 | 370 |

    Thanks to Tom Preston-Werner for showing 371 | me ctemplate and Leah Culver for the name "Mustache."

    372 | 373 |

    Special thanks to Magnus Holm for all his 374 | awesome work on Mustache's parser.

    375 | 376 |

    Contributing

    377 | 378 |

    Once you've made your great commits:

    379 | 380 |
      381 |
    1. Fork Mustache
    2. 382 |
    3. Create a topic branch - git checkout -b my_branch
    4. 383 |
    5. Push to your branch - git push origin my_branch
    6. 384 |
    7. Create an Issue with a link to your branch
    8. 385 |
    9. That's it!
    10. 386 |
    387 | 388 | 389 |

    You might want to checkout Resque's Contributing wiki page for information 390 | on coding standards, new features, etc.

    391 | 392 |

    Mailing List

    393 | 394 |

    To join the list simply send an email to mustache@librelist.com. This 395 | will subscribe you and send you information about your subscription, 396 | including unsubscribe information.

    397 | 398 |

    The archive can be found at http://librelist.com/browser/.

    399 | 400 |

    Meta

    401 | 402 | 410 | 411 | 412 |

    You can also find us in #{ on irc.freenode.net.

    413 | 416 | 417 |
    418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 |
    440 |
    441 | 442 | -------------------------------------------------------------------------------- /docs/classes/Mustache/Sinatra/Helpers.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Mustache::Sinatra::Helpers 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 28 |
    29 |
    30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
    Methods
    40 |
    41 | 42 |
    C
    43 |
    44 | 49 |
    50 | 51 |
    M
    52 |
    53 | 60 |
    61 | 62 |
    63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 |
    Instance Public methods
    77 | 78 |
    79 |
    80 | 81 | compile_mustache(view, options = {}) 82 | 83 |
    84 | 85 |
    86 |

    87 | Given a view name and settings, finds and prepares an appropriate view 88 | class for this view. 89 |

    90 | 91 |
    92 | 93 | 94 | 95 | 96 |
    97 | 103 |
    104 |
    # File lib/mustache/sinatra.rb, line 117
    105 |       def compile_mustache(view, options = {})
    106 |         options[:templates] ||= settings.views if settings.respond_to?(:views)
    107 |         options[:namespace] ||= self.class
    108 | 
    109 |         factory = Class.new(Mustache) do
    110 |           self.view_namespace = options[:namespace]
    111 |           self.view_path      = options[:views]
    112 |         end
    113 | 
    114 |         # Try to find the view class for a given view, e.g.
    115 |         # :view => Hurl::Views::Index.
    116 |         klass = factory.view_class(view)
    117 | 
    118 |         # If there is no view class, issue a warning and use the one
    119 |         # we just generated to cache the compiled template.
    120 |         if klass == Mustache
    121 |           warn "No view class found for #{view} in #{factory.view_path}"
    122 |           klass = factory
    123 | 
    124 |           # If this is a generic view class make sure we set the
    125 |           # template name as it was given. That is, an anonymous
    126 |           # subclass of Mustache won't know how to find the
    127 |           # "index.mustache" template unless we tell it to.
    128 |           klass.template_name = view.to_s
    129 |         end
    130 | 
    131 |         # Set the template path and return our class.
    132 |         klass.template_path = options[:templates] if options[:templates]
    133 |         klass
    134 |       end
    135 |
    136 |
    137 | 138 |
    139 | 140 |
    141 |
    142 | 143 | mustache(template, options={}, locals={}) 144 | 145 |
    146 | 147 |
    148 |

    149 | Call this in your Sinatra routes. 150 |

    151 | 152 |
    153 | 154 | 155 | 156 | 157 |
    158 | 164 |
    165 |
    # File lib/mustache/sinatra.rb, line 45
    166 |       def mustache(template, options={}, locals={})
    167 |         # Locals can be passed as options under the :locals key.
    168 |         locals.update(options.delete(:locals) || {})
    169 | 
    170 |         # Grab any user-defined settings.
    171 |         if settings.respond_to?(:mustache)
    172 |           options = settings.send(:mustache).merge(options)
    173 |         end
    174 | 
    175 |         # Find and cache the view class we want. This ensures the
    176 |         # compiled template is cached, too - no looking up and
    177 |         # compiling templates on each page load.
    178 |         klass = mustache_class(template, options)
    179 | 
    180 |         # If they aren't explicitly disabling layouts, try to find
    181 |         # one.
    182 |         if options[:layout] != false
    183 |           # Let the user pass in a layout name.
    184 |           layout_name = options[:layout]
    185 | 
    186 |           # If all they said was `true` (or nothing), default to :layout.
    187 |           layout_name = :layout if layout_name == true || !layout_name
    188 | 
    189 |           # If they passed a layout name use that.
    190 |           layout = mustache_class(layout_name, options)
    191 | 
    192 |           # If it's just an anonymous subclass then don't bother, otherwise
    193 |           # give us a layout instance.
    194 |           if layout.name && layout.name.empty?
    195 |             layout = nil
    196 |           else
    197 |             layout = layout.new
    198 |           end
    199 | 
    200 |           # Does the view subclass the layout? If so we'll use the
    201 |           # view to render the layout so you can override layout
    202 |           # methods in your view - tricky.
    203 |           view_subclasses_layout = klass < layout.class if layout
    204 |         end
    205 | 
    206 |         # Create a new instance for playing with.
    207 |         instance = klass.new
    208 | 
    209 |         # Copy instance variables set in Sinatra to the view
    210 |         instance_variables.each do |name|
    211 |           instance.instance_variable_set(name, instance_variable_get(name))
    212 |         end
    213 | 
    214 |         # Render with locals.
    215 |         rendered = instance.render(instance.template, locals)
    216 | 
    217 |         # Now render the layout with the view we just rendered, if we
    218 |         # need to.
    219 |         if layout && view_subclasses_layout
    220 |           rendered = instance.render(layout.template, :yield => rendered)
    221 |         elsif layout
    222 |           rendered = layout.render(layout.template, :yield => rendered)
    223 |         end
    224 | 
    225 |         # That's it.
    226 |         rendered
    227 |       end
    228 |
    229 |
    230 | 231 |
    232 | 233 |
    234 |
    235 | 236 | mustache_class(template, options) 237 | 238 |
    239 | 240 |
    241 |

    242 | Returns a View class for a given template name. 243 |

    244 | 245 |
    246 | 247 | 248 | 249 | 250 |
    251 | 257 |
    258 |
    # File lib/mustache/sinatra.rb, line 109
    259 |       def mustache_class(template, options)
    260 |         @template_cache.fetch(:mustache, template) do
    261 |           compile_mustache(template, options)
    262 |         end
    263 |       end
    264 |
    265 |
    266 | 267 |
    268 | 269 |
    270 |
    271 | 272 | --------------------------------------------------------------------------------