Просмотр исходного кода

Avoid requiring partials in global scope.

tags/0.2
Paul J. Davis 16 лет назад
Родитель
Сommit
3a9eda10b4
10 измененных файлов: 112 добавлений и 72 удалений
  1. +15
    -11
      README.md
  2. +1
    -0
      examples/template_partial.2.html
  3. +1
    -1
      examples/template_partial.html
  4. +5
    -4
      examples/template_partial.js
  5. +1
    -1
      examples/template_partial.txt
  6. +5
    -0
      examples/view_partial.2.html
  7. +1
    -1
      examples/view_partial.html
  8. +10
    -15
      examples/view_partial.js
  9. +18
    -21
      mustache.js
  10. +55
    -18
      test/mustache_spec.rb

+ 15
- 11
README.md Просмотреть файл

@@ -64,23 +64,27 @@ Enumerable Sections use the same syntax as condition sections do. `{{#shopping_i
### View Partials ### View Partials
mustache.js supports a quite powerful but yet simple view partial mechanism. Use the following syntax for partials: `{{<partial_name}}` mustache.js supports a quite powerful but yet simple view partial mechanism. Use the following syntax for partials: `{{<partial_name}}`


var view = {name: "Joe"}
var view = {
name: "Joe",
winnings: {
value: 1000,
taxed_value: function() {
return this.value - (this.value * 0.4);
}
}
};

var template = "Welcome, {{jow}}! {{<winnings}}" var template = "Welcome, {{jow}}! {{<winnings}}"
var partials = {winnings: "You just won ${{value}} (which is ${{taxed_value}} after tax)"};
var winnings = {value: 1000,
taxed_value: function() {
return this.value - (this.value * 0.4);
}
}
var winnings_template = "You just won ${{value}} (which is ${{taxed_value}} after tax)"
var output = Mustache.to_html(template, view)
var output = Mustache.to_html(template, view, partials)
output will be: output will be:
Welcome, Joe! You just won $1000 (which is $600 after tax) Welcome, Joe! You just won $1000 (which is $600 after tax)


You invoke a partial with `{{<name}}`. When `name` is an object, mustache.js will look for a JavaScript object called `name_template` and uses this for the template and `name` for the view. If `name` is a simple string, mustache.js will simply render the strings context like a normal template.

You invoke a partial with `{{<name}}`. Invoking the partial `name` will tell
mustache.js to look for a object in the context's property `name`. It will then
use that object as the context for the template found in `partials` for `name`.


## Escaping ## Escaping
mustache.js does escape all values when using the standard double mustache syntax. Characters which will be escaped: `& \ " < >`. To disable escaping, simply use tripple mustaches like `{{{unescaped_variable}}}`. mustache.js does escape all values when using the standard double mustache syntax. Characters which will be escaped: `& \ " < >`. To disable escaping, simply use tripple mustaches like `{{{unescaped_variable}}}`.


+ 1
- 0
examples/template_partial.2.html Просмотреть файл

@@ -0,0 +1 @@
Again, {{again}}!

+ 1
- 1
examples/template_partial.html Просмотреть файл

@@ -1,2 +1,2 @@
<h1>{{title}}</h1> <h1>{{title}}</h1>
{{<inner_partial}}
{{<partial}}

+ 5
- 4
examples/template_partial.js Просмотреть файл

@@ -1,7 +1,8 @@
var template_partial = {
var partial_context = {
title: function() { title: function() {
return "Welcome"; return "Welcome";
}
},
partial: {
again: "Goodbye"
}
} }

var inner_partial = "Again, {{title}}!";

+ 1
- 1
examples/template_partial.txt Просмотреть файл

@@ -1,2 +1,2 @@
<h1>Welcome</h1> <h1>Welcome</h1>
Again, Welcome!
Again, Goodbye!

+ 5
- 0
examples/view_partial.2.html Просмотреть файл

@@ -0,0 +1,5 @@
Hello {{name}}
You have just won ${{value}}!
{{#in_ca}}
Well, ${{ taxed_value }}, after taxes.
{{/in_ca}}

+ 1
- 1
examples/view_partial.html Просмотреть файл

@@ -1,3 +1,3 @@
<h1>{{greeting}}</h1> <h1>{{greeting}}</h1>
{{<simple}}
{{<partial}}
<h3>{{farewell}}</h3> <h3>{{farewell}}</h3>

+ 10
- 15
examples/view_partial.js Просмотреть файл

@@ -1,24 +1,19 @@
var view_partial = {
var partial_context = {
greeting: function() { greeting: function() {
return "Welcome"; return "Welcome";
}, },


farewell: function() { farewell: function() {
return "Fair enough, right?"; return "Fair enough, right?";
}
};

var simple = {
name: "Chris",
value: 10000,
taxed_value: function() {
return this.value - (this.value * 0.4);
}, },
in_ca: true

partial: {
name: "Chris",
value: 10000,
taxed_value: function() {
return this.value - (this.value * 0.4);
},
in_ca: true
}
}; };


var simple_template = "Hello {{name}}\n" +
"You have just won ${{value}}!\n" +
"{{#in_ca}}\n" +
"Well, ${{ taxed_value }}, after taxes.\n" +
"{{/in_ca}}\n";

+ 18
- 21
mustache.js Просмотреть файл

@@ -15,37 +15,33 @@ var Mustache = function() {
otag: "{{", otag: "{{",
ctag: "}}", ctag: "}}",


render: function(template, context) {
render: function(template, context, partials) {
// fail fast // fail fast
if(template.indexOf(this.otag) == -1) { if(template.indexOf(this.otag) == -1) {
return template; return template;
} }


var html = this.render_section(template, context);
return this.render_tags(html, context);
var html = this.render_section(template, context, partials);
return this.render_tags(html, context, partials);
}, },


/* /*
Tries to find a partial in the global scope and render it Tries to find a partial in the global scope and render it
*/ */
render_partial: function(name, context) {
// FIXME: too hacky
var evil_name = eval(name);
switch(typeof evil_name) {
case "string": // a string partial, we simply render
return this.render(evil_name, context);
case "object": // a view partial needs a `name_template` template
var tpl = name + "_template";
return this.render(eval(tpl), evil_name);
default: // should not happen #famouslastwords
throw("Unknown partial type.");
render_partial: function(name, context, partials) {
if(typeof(context[name]) != "object") {
throw({message: "subcontext for '" + name + "' is not an object"});
}
if(!partials || !partials[name]) {
throw({message: "unknown_partial"});
} }
return this.render(partials[name], context[name], partials);
}, },


/* /*
Renders boolean and enumerable sections Renders boolean and enumerable sections
*/ */
render_section: function(template, context) {
render_section: function(template, context, partials) {
if(template.indexOf(this.otag + "#") == -1) { if(template.indexOf(this.otag + "#") == -1) {
return template; return template;
} }
@@ -59,10 +55,11 @@ var Mustache = function() {
var value = that.find(name, context); var value = that.find(name, context);
if(that.is_array(value)) { // Enumerable, Let's loop! if(that.is_array(value)) { // Enumerable, Let's loop!
return that.map(value, function(row) { return that.map(value, function(row) {
return that.render(content, that.merge(context, that.create_context(row)));
return that.render(content, that.merge(context,
that.create_context(row)), partials);
}).join(''); }).join('');
} else if(value) { // boolean section } else if(value) { // boolean section
return that.render(content, context);
return that.render(content, context, partials);
} else { } else {
return ""; return "";
} }
@@ -72,7 +69,7 @@ var Mustache = function() {
/* /*
Replace {{foo}} and friends with values from our view Replace {{foo}} and friends with values from our view
*/ */
render_tags: function(template, context) {
render_tags: function(template, context, partials) {
var lines = template.split("\n"); var lines = template.split("\n");


var new_regex = function() { var new_regex = function() {
@@ -96,7 +93,7 @@ var Mustache = function() {
i--; i--;
return ""; return "";
case "<": // render partial case "<": // render partial
return that.render_partial(name, context);
return that.render_partial(name, context, partials);
case "{": // the triple mustache is unescaped case "{": // the triple mustache is unescaped
return that.find(name, context); return that.find(name, context);
default: // escape the value default: // escape the value
@@ -233,8 +230,8 @@ var Mustache = function() {
/* /*
Turns a template and view into HTML Turns a template and view into HTML
*/ */
to_html: function(template, view) {
return new Renderer().render(template, view);
to_html: function(template, view, partials) {
return new Renderer().render(template, view, partials);
} }
}); });
}(); }();

+ 55
- 18
test/mustache_spec.rb Просмотреть файл

@@ -7,6 +7,21 @@ testnames = Dir.glob(__DIR__ + '/../examples/*.js').map do |name|
File.basename name, '.js' File.basename name, '.js'
end end


non_partials = testnames.select{|t| not t.include? "partial"}
partials = testnames.select{|t| t.include? "partial"}

def load_test(dir, name, partial=false)
view = File.read(dir + "/../examples/#{name}.js")
template = File.read(dir + "/../examples/#{name}.html").to_json
expect = File.read(dir + "/../examples/#{name}.txt")
if not partial
[view, template, expect]
else
partial = File.read(dir + "/../examples/#{name}.2.html").to_json
[view, template, partial, expect]
end
end

describe "mustache" do describe "mustache" do
before(:all) do before(:all) do
@mustache = File.read(__DIR__ + "/../mustache.js") @mustache = File.read(__DIR__ + "/../mustache.js")
@@ -25,32 +40,54 @@ describe "mustache" do
run_js(js).should == "ERROR: Can't find x in [object Object]\n" run_js(js).should == "ERROR: Can't find x in [object Object]\n"
end end
testnames.each do |testname|
describe testname do
non_partials.each do |testname|
describe testname do
it "should generate the correct html" do it "should generate the correct html" do
view = File.read(__DIR__ + "/../examples/#{testname}.js")
template = File.read(__DIR__ + "/../examples/#{testname}.html").to_json
expect = File.read(__DIR__ + "/../examples/#{testname}.txt")

view, template, expect = load_test(__DIR__, testname)
runner = <<-JS runner = <<-JS
try {
#{@mustache}
#{view}
var template = #{template};
var result = Mustache.to_html(template, #{testname});
print(result);
} catch(e) {
print('ERROR: ' + e.message);
}
try {
#{@mustache}
#{view}
var template = #{template};
var result = Mustache.to_html(template, #{testname});
print(result);
} catch(e) {
print('ERROR: ' + e.message);
}
JS JS

run_js(runner).should == expect run_js(runner).should == expect
end end
end end
end end

partials.each do |testname|
describe testname do
it "should generate the correct html" do

view, template, partial, expect =
load_test(__DIR__, testname, true)

runner = <<-JS
try {
#{@mustache}
#{view};
var template = #{template};
var partials = {"partial": #{partial}};
var result = Mustache.to_html(template, partial_context, partials);
print(result);
} catch(e) {
print('ERROR: ' + e.message);
}
JS
run_js(runner).should == expect
end
end
end

def run_js(js) def run_js(js)
File.open("runner.js", 'w') {|f| f << js} File.open("runner.js", 'w') {|f| f << js}
`js runner.js` `js runner.js`


Загрузка…
Отмена
Сохранить