Code Monkey home page Code Monkey logo

mustache's Introduction

Mustache

Gem Version Build Status

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

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

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

Overview

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

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

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

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

Why?

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

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

Installation

Install the gem locally with:

$ gem install mustache

Or add it to your Gemfile:

gem "mustache", "~> 1.0"

Usage

Quick example:

>> require 'mustache'
=> true
>> Mustache.render("Hello {{planet}}", planet: "World!")
=> "Hello World!"

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

class Simple < Mustache
  def name
    "Chris"
  end

  def value
    10_000
  end

  def taxed_value
    value * 0.6
  end

  def in_ca
    true
  end
end

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

Now let's write the template:

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

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

Simple.render

Which returns the following:

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

Simple.

Tag Types

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

Escaping

Mustache does escape all values when using the standard double Mustache syntax. Characters which will be escaped: & \ " < > (as well as ' in Ruby >= 2.0). To disable escaping, simply use triple mustaches like {{{unescaped_variable}}}.

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

Dict-Style Views

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

Given this template (winner.mustache):

Hello {{name}}
You have just won {{value}} bucks!

We can fill in the values at will:

view = Winner.new
view[:name] = 'George'
view[:value] = 100
view.render

Which returns:

Hello George
You have just won 100 bucks!

We can re-use the same object, too:

view[:name] = 'Tony'
view.render # => Hello Tony\nYou have just won 100 bucks!

Templates

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

TemplatePartial => ./template_partial.mustache

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

class Simple < Mustache
  self.template_path = __dir__
end

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

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

Simple.template_file = './blah.mustache'

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

Simple.template_extension = 'xml'

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

Feel free to set the template directly:

Simple.template = 'Hi {{person}}!'

Or set a different template for a single instance:

Simple.new.template = 'Hi {{person}}!'

Whatever works.

Views

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

Helpers

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

This is just Ruby, after all.

module ViewHelpers
  def gravatar
    gravatar_id = Digest::MD5.hexdigest(self[:email].to_s.strip.downcase)
    gravatar_for_id(gravatar_id)
  end

  def gravatar_for_id(gid, size = 30)
    "#{gravatar_host}/avatar/#{gid}?s=#{size}"
  end

  def gravatar_host
    @ssl ? 'https://secure.gravatar.com' : 'http://www.gravatar.com'
  end
end

Then just include it:

class Simple < Mustache
  include ViewHelpers

  def name
    "Chris"
  end

  def value
    10_000
  end

  def taxed_value
    value * 0.6
  end

  def in_ca
    true
  end

  def users
    User.all
  end
end

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

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

class Simple < Mustache
  include ViewHelpers

  def initialize(ssl = false)
    @ssl = ssl
  end
end

Now:

Simple.new(request.ssl?).render

Finally, our template might look like this:

<ul>
  {{# users}}
    <li><img src="{{ gravatar }}"> {{ login }}</li>
  {{/ users}}
</ul>

Integrations

Sinatra

Sinatra integration is available with the mustache-sinatra gem.

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

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

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

Mustache also provides a Rack::Bug panel. First you have to install the rack-bug-mustache_panel gem, then in your config.ru add the following code:

require 'rack/bug/panels/mustache_panel'
use Rack::Bug::MustachePanel

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

require 'rack/bug/panels/mustache_panel'
config.middleware.use "Rack::Bug::MustachePanel"

Rack::Bug

Vim

vim-mustache-handlebars is available at mustache/vim-mustache-handlebars

Emacs

mustache-mode.el is available at mustache/emacs

TextMate

Mustache.tmbundle

See https://gist.github.com/defunkt/323624 for installation instructions.

Command Line

See mustache(1) man page or http://mustache.github.io/mustache.1.html for command line docs.

Acknowledgements

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

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

Contributing

Once you've made your great commits:

  1. Fork Mustache
  2. Create a topic branch - git checkout -b my_branch
  3. Push to your branch - git push origin my_branch
  4. Create an Issue with a link to your branch
  5. That's it!

Mailing List

~~To join the list simply send an email to [email protected]. This will subscribe you and send you information about your subscription, including unsubscribe information.

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

The mailing list hasn't been updated in quite a while, please join us on Gitter or IRC:

Join the chat at https://gitter.im/mustache/mustache

#{ on Freenode

Meta

mustache's People

Contributors

adamnbowen avatar agrimm avatar badboy avatar bayan avatar benubois avatar bobthecow avatar defunkt avatar ernie avatar evilstreak avatar foca avatar homu avatar hugopeixoto avatar ioquatix avatar jgonggrijp avatar josh avatar judofyr avatar justblackbird avatar lawrencepit avatar locks avatar lstrzebinczyk avatar lwoggardner avatar maciej-sz avatar markusharmsen avatar mdavidn avatar mjackson avatar nex3 avatar nuclearsandwich avatar pvande avatar tenderlove avatar trans avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mustache's Issues

Boolean blocks should support non-match blocks

The one thing into which I frequently run is the inability to specify what might be thought of as an else clause for boolean (conditional) blocks. Many constructions which naturally lend themselves to this sort of if key … else <default> end expansion are very difficult to accomplish otherwise, and effectively apply pressure to push this logic up into the model, itself (to return conditionally there, even if is just an artifact of the linguistic or design structure of the template).

I recognize that this effectively imparts some more logic to these so-called "logicless" templates, but it remains purely declarative (which I think is your real point, since after all boolean and enumerable blocks absolutely are "logic")—no side effects, no mutability, and none of the other imperative mess—and very much in the same vein as the existing boolean and enumerable blocks, while significantly increasing the expressibility of the language.

Does this seem like a reasonable and conservative addition? Am I crazy? Is it totally unnecessary/dangerous/liable to kill babies, or just not something to which anyone has yet gotten around?

Better Context Behavior w.r.t. Partials

The ability to put Mustaches anywhere in the context stack is nice, but why must a Mustache instance always be at the base of the stack?

Similarly, why are partials resolved only by that base Mustache, rather than searching the stack?

These may be silly questions, but it seems like a good deal of code reuse could be had from a more general approach.

accessing.stuff.with.dots

It would be cool to be able to do {{user.name}} (dot notation access) so it would return user[:name] where user is a method in view returning a Hash. It should also accept statements with more dots like: {{user.address.city}}.

Recursive partials

Right now it seems that Mustache will include partials even if they are wrapped in a {{#whatever}} ... {{/whatever}} block that evaluates to false or an empty array. Because of that, Mustache can't handle recursive partials (partial including itself), as it will keep recursively including the partial until the stack level gets too deep and an error is raised.

Recursive partials would be really useful for hierarchical/nested things (like lists, trees, threaded comments, etc.). But I worry that it would require a significant change to the template engine. Mustache would have to evaluate the template as it compiles it, which might make things more complicated and/or slower.

Is support for recursive partials something you would consider implementing / accepting as a patch? Any ideas on how best to implement it? Or suggestions for a way to work around the lack?

Weird bug in parsing utf-8 template with partial.

http://gist.github.com/346676#file_test_working.mustache

The code above can be parsed nicely:

$ mustache -c test.mustache
"<h1>中文 #{CGI.escapeHTML(ctx[:test].to_s)}</h1>\n"

http://gist.github.com/346676#file_test_not_working.mustache
http://gist.github.com/346676#file_testing.mustache

Add the partial...

$ mustache -c test.mustache
"<h1>中文 #{CGI.escapeHTML(ctx[:test].to_s)}>\n\n#{ctx.partial(:testing)}\n"

The h1 close tag is missing.

If we extend the utf-8 text.

$ mustache -c test.mustache
"<h1>中文中文中文中文中文 #{CGI.escapeHTML(ctx[:test].to_s)}{{> testing}}\n"

It will ignore the partial tag.

Language-agnostic Test Suite

The test suite needs to be rewritten to work in any language.

That is, I should be able to run the same Mustache tests against a Python implementation, JS implementation, etc.

I'm thinking you just specify a "runner" (e.g. ./bin/mustache) and the tests use a template + dictionary then compare the output to a static HTML file.

recommended method for accessing the sinatra session in view classes?

I wanted to have a helper for authentication related stuff such as current_user and logged_in, etc.

I put these in a Mustache helper module and I also include that in my sinatra app to make them available there.

However in order for the helper's methods to be aware of the sinatra session, I had to set

before do
@session = session
end

Would it make sense to copy a reference to the session in mustache views?

Section Separator Support

In this branch I have added support for section separators, as I wanted to format some plain text
documents and didn't want the separator to appear after the last element. This was done in the style of:

Special Markers
http://google-ctemplate.googlecode.com/svn/trunk/doc/reference.html

I have:

  1. Added a test
  2. Updated the docs
  3. Changed the code ;)

If there is something you don't like about the implementation please let me know... I'm more then willing to fix it.

Branch:
http://github.com/ericdwhite/mustache/tree/separator-support

Section Separators

It is possible to define a section separator to use when processing arrays of elements. This is useful when you want to ensure the separator does not appear after the last element.

The section separators must be named after the section they belong to and follow the convention: section_name + '_separator'.

Example:

Given this template

  • {{#names}}{{to_s}}{{#names_separator}}, {{/names_separator}}{{/names}}

And and a context

{names => [:jim, :alice, :ron]}

The result is

  • jim, alice, ron

This has been implemented in the sprit of: Special Markers
http://google-ctemplate.googlecode.com/svn/trunk/doc/reference.html

use { for extensions ?

can we optionally use { for the mostache extension, e.g. index.html.{

:):)

seems ok on osx, and according to wikipedia is ok for windows (tho I can't test that)

sinatra pre 1.0 template path not being set for partials (non partial templates seem to work fine)

Hello, I tried the Sinatra prerelease gem on a sinatra+mustache app that is working in the latest stable release, and it's not seeing the settings I have set for the template path (for partials). Just thought I'd mention this here in case anyone knows of a fix or config change, etc.

For example, the following settings:

set :views, File.dirname(FILE) + '/foo/templates'
set :mustaches, File.dirname(FILE) + '/foo/views'

results in the following error:

No such file or directory - ./my_partial.mustache

The first line of the backtrace is:

 .gem/ruby/1.9.1/gems/mustache-0.5.1/lib/mustache/template.rb in read
  src = File.read("#{@template_path}/#{name}.#{@template_extension}")

Syntax idea: "{{key?}}" for checking whether "key" is non-empty

I'm hitting a repetitive and tedious pattern while writing mustache templates. Let me explain.

First of all, let me state that I absolutely love the lists sections feature of mustache (example taken from man page):

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

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

However, in HTML, lists are usually, well, lists. And chances are they are a part of some context. Real-world example:

<h2>Related posts:</h2>

<ul>
  {{#related_posts}}
  <li>{{ title }}</li>
  {{/related_posts}}
</ul>

Now, the pattern I mentioned starts to arise when handling empty lists. In the last example, an empty list would still render the H2 and empty UL tags. We have to write a new section to encompass the context of related posts:

{{#has_related_posts}}
<h2>Related posts:</h2>
<ul>...</ul>
{{/has_related_posts}}

And we have to get back to the view and actually implement the "has_related_posts" key/method. In ruby Mustache views, I regularly finish up with a bunch of these extra methods all sharing a similar implementation: checking for list.empty?.

My idea for a new syntax to eliminated this pattern is this:

{{#related_posts?}}
<h2>Related posts:</h2>
<ul>...</ul>
{{/related_posts?}}

If the "related_posts?" key/method doesn't exist, mustache would check "related_posts" and return true for non-blank values. In short, adding a question mark to the end would ensure that a boolean is returned. Empty lists would always be false, empty strings might too (like ActiveSupport blank? semantics).

The man page already has an example of using keys that end with a question mark:

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

I don't think this is a very good example of some best practice; the question mark here is entirely superfluous. Mustache has the opportunity to declare some semantics for the question mark, same as in Ruby language.

The question remains whether this warrants extending the spec? Because this behavior could, theoretically, be implemented entirely in the view—in Ruby it could be powered by method_missing. Other implementations could, when sending a hash of key-value pairs for rendering, make an additional pass and add extra boolean values for each of the existing keys. All this is definitely possible for the user—I'm just wondering if it would be a good idea for the spec.

mustache bin fails with cat & pipe

using

cat names.yml names.mustache | mustache

just prints the help.

I checked the code and found out that the line

# bin/mustache:6
if STDIN.stat.size > 0

never evaluates to true, STDIN.stat.size is always 0 for me.

Then I changed the Code to

if !STDIN.tty?
  # ...

and it works for me.
I don't know if this causes more problems than it fixes.

"empty" section tag

When declaring a section, it'd be nice to have an if empty/else tag, like django's {% empty %} tag. Something like:

{{# collection }}
  <li>{{ name }}</li>
{{~ collection }}
  Nothing to see here.
{{/ collection }}

As to what symbol should be used, no idea. I'd actually like to use ! for this, # for comments, and something else for new sections/booleans (maybe ?). But that's just me :)

tests fail with ruby 1.9

example/complex.rb fails with
complex.rb:4:in `

': superclass mismatch for class Complex (TypeError)

my ruby version:
[~]% ruby -v
ruby 1.9.1p243 (2009-07-16 revision 24175) [i686-linux]
works with
ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-linux]

lazily loaded template values/iterations (aka, proc values)

So I'm building a system whereby I'm essentially letting end-users upload mustache templates that will get rendered according to a certain View class context. Said view class does not have advance knowledge of everything the template will want to render; it provides an API of sorts that the template can use, but some methods are rather expensive to compute and giving the template all of these values up front can be a bit expensive and it doesn't necessarily need to be.

Liquid solves this problem by evaluating proc values as it finds them and replacing the proc with the value it returns, and then using that. Mustache doesn't really handle procs at all; it either tries to call #each or #to_s on them and this does not work as one might expect.

When you're been using mustache for apps where the view class knows exactly what the template wants (or can provide anything it might want inexpensively) this isn't an issue. When you're providing more of a template API you don't really have that luxury.

There are three ways to handle this problem with Mustache:

  1. scan the template looking for the values it wants and compute those up-front. This degenerates quickly when dealing with sub-templates or iterator values.

  2. provide a special type of proc that handles #each by calling itself and making sure the response into an array of hashes, and handles #to_s by calling itself and returning the value as a string. This requires either monkeypatching Proc, which presents a lot of problems, or subclassing Proc, which excludes the use of lambda, and presents its own problems. The subclassing option is what I'm doing now.

  3. modify mustache to handle procs by calling them when it encounters them, and handling the results appropriately.

If such a patch to Mustache would be welcome I will be happy to provide with tests and documentation, but before embarking on such an endeavor I would like to know the patch would be accepted. Please advise, thanks.

Mustache#render doesn't pop the context when done

9477619 introduced new semantic of Context#update which now pushes the value onto a stack.

Mustache#render still uses Context#update, but doesn't pop it after the template has been rendered. This causes the stack to grow by one every time you render it which means it's both a memory leak and a performance issue.

Fix:

def render(data = template, ctx = {})
  templateify(data).render(context.update(ctx))
ensure
  context.pop
end

Versioned Specification

As independent implementations of Mustache take hold, it might be nice to have a formal, versioned specification (and perhaps a forum for discussion of improvements). In particular, versioning the specification should provide contractual anchors for alternate implementations to adhere to, improving consistency and portability for templates.

Rails integration...

Are you currently working on Rails integration?

Rails integration seems very simple. All template logic now goes into the helper files.

I'm happy to help, but don't want to duplicate any current work.

Cheers,

Multiline tags (especially comments)

I'd like to request that template tags be allowed to span multiple lines. Mostly this is useful for long comments, such as an overview of how the template works. I believe that ctemplate currently allows multiline tags, so it would be nice for compatibility, too.

The implementation seems trivial. It works fine for me by just making the regexp in Mustache#compile_tags a multiline regexp:

diff --git a/lib/mustache/template.rb b/lib/mustache/template.rb
index 3b67193..5c60337 100644
--- a/lib/mustache/template.rb
+++ b/lib/mustache/template.rb
@@ -106,7 +106,7 @@ class Mustache
     #4. Partial tags - {{> partial_name }}
     def compile_tags(src)
       res = ""
-      while src =~ /#{otag}(#|=|!|<|>|\{)?(.+?)\1?#{ctag}+/
+      while src =~ /#{otag}(#|=|!|<|>|\{)?(.+?)\1?#{ctag}+/m
         res << str($`)
         case $1
         when '#'

Whitespace inside Mustache tags?

As a matter of formal specification, should newlines be considered valid inside a Mustache tag?

ruby -I lib -r mustache -e 'puts Mustache.render("I have {{\n content \n}} in me.", { :content => "newlines" })'
# => "I have newlines in me."

ruby -I lib -r mustache -e 'puts Mustache.render("I have a {{ new\nline }} in me.", { :"new\nline" => "newline" })'
# => Unclosed tag (Mustache::Parser::SyntaxError)

For-Newlines:

  • It's currently half-permitted (inside a tag, not inside a tag name).
  • For longer tags, including verbose pragma attributes and cascaded.attribute.lookups, this permits clarity.
    • Obviously, neither of those cases are currently supported.
  • Comments can be multi-line.
  • Disallowing them might be unnecessarily restrictive.

Against-Newlines:

  • It's currently half-disallowed.
  • Memory requirements are increased, since the template must be parsed as a single large string.
  • Templates may become less readable.
    • Admittedly, this is somewhat an eye-of-the-beholder issue, but the design of the language so far rests on a Grandma-simplicity.
  • Parser designs are somewhat restricted.
    • As a contrived example, without newlines, a parser could be implemented line-wise via Map-Reduce, because newlines would "never" break tags apart.
      • This could be guaranteed by partially pre-parsing the code, but the expense would negate any potential gain.

I would vote against permitting newlines inside Mustache tags, but I'm curious holding out for an official verdict.

Comments can't contain character '#' or '/'

First of all: awesome library, thanx!

While playing around I found the characters # and / to mess up with the comments:
>> Mustache.render('{{! see issue # 13}}')
=> "{{! see issue # 13}}"
>> Mustache.render('{{! see http://..}}')
=> "{{! see http://.. }}"
expected in both cases: ""

UTF-8 characters and nested sections

Using UTF-8 characters in a nested section will chop of the first characters of the text following the section. For example, the following code:

# encoding: utf-8
require 'rubygems'
require 'mustache'

template = '<ul>
{{#items}}
  <li>
    {{#visible}}
      When this is printed, because it contains an "é", the first character of the next list item will be removed.
    {{/visible}}
  <li>
{{/items}}
</ul>'

items = [
  { :visible => true },
]
puts Mustache.render template, {:items=>items}

You would expect to render this:

<ul>
    <li>
        When this is printed, because it contains an "é", the first character of the next list item will be removed.
        <li>
    </ul>

But instead, you get this:

<ul>
    <li>
        When this is printed, because it contains an "é", the first character of the next list item will be removed.
        li>
    </ul>

Spec

We need a Mustache spec.

Broken Settings in Sinatra / Tilt Integration

via @mislav:

Sinatra + Tilt are not making "views", "namespace" and "mustaches" settings available to Mustache. Instead, Sinatra forwards all settings nested under the name of the view engine to Tilt. Examples:

set :erb, { :outvar => "_erb_buffer" }
set :haml, { :format => :html5 }
set :mustache, { :namespace => Object }

I like that each engine's settings are namespaced, so I think docs and default settings in Mustache should be updated to use this syntax.

Idea: mustHAML?

Hi Chris,

What I really love about HAML is it's shorthand notation for HTML tags (%h1, %p, etc.). What I really digg about Mustache is the separation of logic and template.

How about combining these strengths so I can write my Mustache templates in HAML style shorthand, mustHAML so to speak? Or is this already possible?

If I wasn't a total Ruby n00b I would give it a try myself :)

Cheers,
Sebastiaan

Changing tag delimiters breaks sections

Currently, if you change tag delimiters and attempt to use the new delimiters to start a section, Mustache dies.

The reasoning comes from the fact that sections are handled in #compile_sections, before the alternate delimiter is set up under #compile_tags. This behavior alone might be "acceptable", were it not for the fact that the first occurrence of a section begin with the new delimiters reports (incorrectly) that the tag is not closed.

ruby -r mustache -e 'Mustache.render("{{=<% %>=}}  Hi, <%# person %> <% name %> <%/ person %> !", { :person => { :name => "Your name" } });'
# => in `compile_tags': line 1: #person is not closed (Mustache::Template::UnclosedSection)

Slashes in partial names break the parser

In pre-0.9.0 versions of mustache, the following tag worked perfectly:

{{> shared/header}}

Now in versions 0.9.0 and 0.9.1, mustache complains:

$ mustache -t default.mustache
/Users/dave/.rvm/gems/ruby-1.8.7-p248/gems/mustache-0.9.1/lib/mustache/parser.rb:213:in `error': Unclosed tag (Mustache::Parser::SyntaxError)
  Line 3
    {{> shared/head}}
        from /Users/dave/.rvm/gems/ruby-1.8.7-p248/gems/mustache-0.9.1/lib/mustache/parser.rb:158:in `scan_tags'
        from /Users/dave/.rvm/gems/ruby-1.8.7-p248/gems/mustache-0.9.1/lib/mustache/parser.rb:85:in `compile'
        from /Users/dave/.rvm/gems/ruby-1.8.7-p248/gems/mustache-0.9.1/lib/mustache/template.rb:54:in `tokens'
        from /Users/dave/.rvm/gems/ruby-1.8.7-p248/gems/mustache-0.9.1/bin/mustache:41
        from /Users/dave/.rvm/rubies/ruby-1.8.7-p248/lib/ruby/1.8/optparse.rb:1298:in `call'
        from /Users/dave/.rvm/rubies/ruby-1.8.7-p248/lib/ruby/1.8/optparse.rb:1298:in `parse_in_order'
        from /Users/dave/.rvm/rubies/ruby-1.8.7-p248/lib/ruby/1.8/optparse.rb:1254:in `catch'
        from /Users/dave/.rvm/rubies/ruby-1.8.7-p248/lib/ruby/1.8/optparse.rb:1254:in `parse_in_order'
        from /Users/dave/.rvm/rubies/ruby-1.8.7-p248/lib/ruby/1.8/optparse.rb:1248:in `order!'
        from /Users/dave/.rvm/rubies/ruby-1.8.7-p248/lib/ruby/1.8/optparse.rb:1339:in `permute!'
        from /Users/dave/.rvm/rubies/ruby-1.8.7-p248/lib/ruby/1.8/optparse.rb:1360:in `parse!'
        from /Users/dave/.rvm/gems/ruby-1.8.7-p248/gems/mustache-0.9.1/bin/mustache:60:in `parse_options'
        from /Users/dave/.rvm/gems/ruby-1.8.7-p248/gems/mustache-0.9.1/bin/mustache:86
        from /Users/dave/.rvm/gems/ruby-1.8.7-p248/bin/mustache:19:in `load'
        from /Users/dave/.rvm/gems/ruby-1.8.7-p248/bin/mustache:19

I've tested on ruby 1.8.7 and 1.9.1, same problem.

partials don't inherit context?

Here's an example:

test.rb

class Page < Mustache
  self.template = "{{#articles}}{{<article}}{{/articles}}"

  def articles
    [{:title => "test"}]
  end
end

class Article < Mustache; end

puts Page.render

article.mustache

<h1>{{title}}</h1>

output:

<h1></h1>

It seems like the partial is rendered out of context, through Mustache.render, or like the context isn't passed, as #compile is called directly..

Change indicators

People are asking for this and I think it'd be cool. Basically Mustache should let you change indicators.

You could switch section indicators from # and / to < and >, then switch comment tag types from using ! to #. Combined with #8 Mustache's syntax would then be incredibly flexible.

Usage Guide

Documentation walking through installation of Mustache and setup in a normal Rack application.

Should be generic enough to work for any web framework.

view class usage pattern

question: will the view class of the surrounding template be usable from within a partial? what about the view class of the layout? It would also be nice to be able to override a method of the view class of the outer template (or layout) by writing a method with the same name in the inner view class... as in def title;end to set the default title w/ the layout's view class but override it if desired in the template's view class...

just a thought, please delete/ignore if it's not in the spirit of mustache to do this sort of thing.

proper indentation

the generated HTML should be indented correctly.

for example examples/complex.rb shows this:

Colors


it should be like this

Colors


C Implementation

I could whip up a quick peg/leg parser if your interested? at least then we can abstract the parser from the language implementation

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.