mustache 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CONTRIBUTORS CHANGED
@@ -3,3 +3,4 @@
3
3
  * Magnus Holm
4
4
  * Nicolas Sanguinetti
5
5
  * Jan-Erik Rediger
6
+ * Aaron Patterson
data/HISTORY.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## 0.5.0 (2009-11-23)
2
+
3
+ * Partial classes are no longer supported. Use modules!
4
+ * Added `mustache` script for rendering templates on the command line.
5
+ * ctemplate compat: Partials are indicated by >, not <
6
+ * Bugfix: Context miss should return nil, not empty string. Fixes 1.9.x
7
+
8
+ ## 0.4.2 (2009-10-28)
9
+
10
+ * Bugfix: Ignore bad constant names when autoloading
11
+
12
+ ## 0.4.1 (2009-10-27)
13
+
14
+ * Partials now respect the `view_namespace` setting.
15
+ * Added tpl-mode.el to contrib/ for us Emacs users.
16
+ * Rack::Bug bugfix: ensure benchmark is required before using it
17
+ * Rack::Bug: truncate too-large variables (click expands them)
18
+
1
19
  ## 0.4.0 (2009-10-27)
2
20
 
3
21
  * Stopped raising context miss exceptions by default
data/README.md CHANGED
@@ -176,13 +176,32 @@ Will render as follows:
176
176
 
177
177
  ### Partials
178
178
 
179
- Partials begin with a less than sign, like `{{< box}}`.
179
+ Partials begin with a greater than sign, like `{{> box}}`.
180
180
 
181
- If a partial's view is loaded, we use that to render the HTML. If
182
- nothing is loaded we render the template directly using our current context.
181
+ It is useful to think of partials as a "template expansion" - that is,
182
+ the actual partial tag will be replaced with the content of the
183
+ partial. Therefor partials share the current context.
183
184
 
184
- In this way partials can reference variables or sections the calling
185
- view defines.
185
+ For example, this template and partial:
186
+
187
+ base.mustache
188
+ Names:
189
+ {{# names }}
190
+ {{> user }}
191
+ {{/ names }}
192
+
193
+ user.mustache:
194
+ <strong>{{ name }}</strong>
195
+
196
+ Can be thought of as a single, expanded template:
197
+
198
+ Names:
199
+ {{# names }}
200
+ <strong>{{ name }}</strong>
201
+ {{/ names }}
202
+
203
+ Have partial-specific code you want to share between view classes?
204
+ Consider using a module and including it.
186
205
 
187
206
 
188
207
  ### Set Delimiter
@@ -376,7 +395,7 @@ An example Sinatra application is also provided:
376
395
 
377
396
 
378
397
  [Rack::Bug][4]
379
- ---------
398
+ --------------
380
399
 
381
400
  Mustache also ships with a `Rack::Bug` panel. In your `config.ru` add
382
401
  the following code:
@@ -399,6 +418,64 @@ Thanks to [Juvenn Woo](http://github.com/juvenn) for mustache.vim. It
399
418
  is included under the contrib/ directory.
400
419
 
401
420
 
421
+ Emacs
422
+ -----
423
+
424
+ tpl-mode.el is included under the contrib/ directory for any Emacs users.
425
+ Based on Google's tpl-mode for ctemplates, it adds support for Mustache's
426
+ more lenient tag values and includes a few commands for your editing pleasure.
427
+
428
+
429
+ TextMate
430
+ --------
431
+
432
+ Check out Tekkub's
433
+ [Mustache.tmbundle](http://github.com/tekkub/Mustache.tmbundle).
434
+
435
+
436
+ Command Line
437
+ ------------
438
+
439
+ Mustache includes a `mustache` script for rendering templates on the
440
+ command line. This can be useful when designing HTML that will
441
+ eventually be included in a website: instead of having to format the
442
+ HTML as Mustache later, you can do it now!
443
+
444
+ The script expects a Mustache template on STDIN with YAML
445
+ frontmatter. An example looks like this:
446
+
447
+ $ cat complete.mustache
448
+ ---
449
+ names: [ {name: chris}, {name: mark}, {name: scott} ]
450
+ ---
451
+ {{#names}}
452
+ Hi {{name}}!
453
+ {{/names}}
454
+
455
+ $ cat complete.mustache | mustache
456
+ Hi chris!
457
+ Hi mark!
458
+ Hi scott!
459
+
460
+ It's probably more useful to keep the YAML and HTML in separate files,
461
+ though. Luckily `cat` works great for this, too:
462
+
463
+ $ cat data.yml
464
+ ---
465
+ names: [ {name: chris}, {name: mark}, {name: scott} ]
466
+ ---
467
+
468
+ $ cat template.mustache
469
+ {{#names}}
470
+ Hi {{name}}!
471
+ {{/names}}
472
+
473
+ $ cat data.yml template.mustache | mustache
474
+ Hi chris!
475
+ Hi mark!
476
+ Hi scott!
477
+
478
+
402
479
  Installation
403
480
  ------------
404
481
 
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ task :gem => [ :gemspec, :build ]
15
15
  desc "Launch Kicker (like autotest)"
16
16
  task :kicker do
17
17
  puts "Kicking... (ctrl+c to cancel)"
18
- exec "kicker -e rake test lib"
18
+ exec "kicker -e rake test lib examples"
19
19
  end
20
20
 
21
21
  begin
@@ -46,6 +46,7 @@ desc "Push a new version to Gemcutter"
46
46
  task :publish => [ :test, :gemspec, :build ] do
47
47
  system "git tag v#{Mustache::Version}"
48
48
  system "git push origin v#{Mustache::Version}"
49
+ system "git push origin master"
49
50
  system "gem push pkg/mustache-#{Mustache::Version}.gem"
50
51
  system "git clean -fd"
51
52
  exec "rake pages"
data/bin/mustache ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mustache'
4
+ require 'yaml'
5
+
6
+ if STDIN.stat.size > 0
7
+ doc = STDIN.read
8
+ if doc =~ /^(\s*---(.*)---\s*)/m
9
+ data = YAML.load($2.strip)
10
+ puts Mustache.render(doc.sub($1, ''), data)
11
+ else
12
+ puts doc
13
+ end
14
+ else
15
+ puts <<-usage
16
+ Usage: cat data.yml template.mustache | mustache
17
+
18
+ Expects a single Mustache template on STDIN complete with YAML
19
+ frontmatter.
20
+
21
+ Runs template.mustache through Mustache, using the data in data.yml to
22
+ replace sections and variables. Useful when developing templates
23
+ before hooking them into your website or whatnot.
24
+
25
+ The data.yml file should start with --- on a single line and end with
26
+ --- on a single line, e.g.
27
+
28
+ ---
29
+ names: [ {name: chris}, {name: mark}, {name: scott} ]
30
+ ---
31
+
32
+ The converted document will be printed on STDOUT.
33
+ usage
34
+ end
@@ -0,0 +1,274 @@
1
+ ;;; tpl-mode.el -- a major mode for editing Google CTemplate files.
2
+ ;;; By Tony Gentilcore, July 2006
3
+ ;;;
4
+ ;;; Very minor, backwards compatible changes added for Mustache compatibility
5
+ ;;; by Chris Wanstrath, October 2009
6
+ ;;;
7
+ ;;; TO USE:
8
+ ;;; 1) Copy this file somewhere you in emacs load-path. To see what
9
+ ;;; your load-path is, run inside emacs: C-h v load-path<RET>
10
+ ;;; 2) Add the following two lines to your .emacs file:
11
+ ;;; (setq auto-mode-alist (cons '("\\.tpl$" . tpl-mode) auto-mode-alist))
12
+ ;;; (autoload 'tpl-mode "tpl-mode" "Major mode for editing CTemplate files." t)
13
+ ;;; 3) Optionally (but recommended), add this third line as well:
14
+ ;;; (add-hook 'tpl-mode-hook '(lambda () (font-lock-mode 1)))
15
+ ;;; ---
16
+ ;;;
17
+ ;;; While the CTemplate language can be used for any types of text,
18
+ ;;; this mode is intended for using CTemplate to write HTML.
19
+ ;;;
20
+ ;;; The indentation still has minor bugs due to the fact that
21
+ ;;; templates do not require valid HTML.
22
+ ;;;
23
+ ;;; It would be nice to be able to highlight attributes of HTML tags,
24
+ ;;; however this is difficult due to the presence of CTemplate symbols
25
+ ;;; embedded within attributes.
26
+
27
+ (eval-when-compile
28
+ (require 'font-lock))
29
+
30
+ (defgroup tpl-mode nil
31
+ "Major mode for editing Google CTemplate and Mustache files"
32
+ :group 'languages)
33
+
34
+ (defvar tpl-mode-version "1.1"
35
+ "Version of `tpl-mode.el'.")
36
+
37
+ (defvar tpl-mode-abbrev-table nil
38
+ "Abbrev table for use in tpl-mode buffers.")
39
+
40
+ (define-abbrev-table 'tpl-mode-abbrev-table ())
41
+
42
+ (defcustom tpl-mode-hook nil
43
+ "*Hook that runs upon entering tpl-mode."
44
+ :type 'hook)
45
+
46
+ (defvar tpl-mode-map nil
47
+ "Keymap for tpl-mode major mode")
48
+
49
+ (if tpl-mode-map
50
+ nil
51
+ (setq tpl-mode-map (make-sparse-keymap)))
52
+
53
+ (define-key tpl-mode-map "\t" 'tpl-indent-command)
54
+ (define-key tpl-mode-map "\C-m" 'reindent-then-newline-and-indent)
55
+ (define-key tpl-mode-map "\C-ct" 'tpl-insert-tag)
56
+ (define-key tpl-mode-map "\C-cv" 'tpl-insert-variable)
57
+ (define-key tpl-mode-map "\C-cs" 'tpl-insert-section)
58
+
59
+
60
+ (defvar tpl-mode-syntax-table nil
61
+ "Syntax table in use in tpl-mode buffers.")
62
+
63
+ ;; Syntax table.
64
+ (if tpl-mode-syntax-table
65
+ nil
66
+ (setq tpl-mode-syntax-table (make-syntax-table text-mode-syntax-table))
67
+ (modify-syntax-entry ?< "(> " tpl-mode-syntax-table)
68
+ (modify-syntax-entry ?> ")< " tpl-mode-syntax-table)
69
+ (modify-syntax-entry ?\" ". " tpl-mode-syntax-table)
70
+ (modify-syntax-entry ?\\ ". " tpl-mode-syntax-table)
71
+ (modify-syntax-entry ?' "w " tpl-mode-syntax-table))
72
+
73
+ (defvar tpl-basic-offset 2
74
+ "The basic indentation offset.")
75
+
76
+ ;; Constant regular expressions to identify template elements.
77
+ (defconst tpl-mode-tpl-token "[a-zA-Z][a-zA-Z0-9_:=\?!-]*?")
78
+ (defconst tpl-mode-section (concat "\\({{[#/]\s*"
79
+ tpl-mode-tpl-token
80
+ "\s*}}\\)"))
81
+ (defconst tpl-mode-open-section (concat "\\({{#\s*"
82
+ tpl-mode-tpl-token
83
+ "\s*}}\\)"))
84
+ (defconst tpl-mode-close-section (concat "{{/\\(\s*"
85
+ tpl-mode-tpl-token
86
+ "\s*\\)}}"))
87
+ ;; TODO(tonyg) Figure out a way to support multiline comments.
88
+ (defconst tpl-mode-comment "\\({{!.*?}}\\)")
89
+ (defconst tpl-mode-include (concat "\\({{>\s*"
90
+ tpl-mode-tpl-token
91
+ "\s*}}\\)"))
92
+ (defconst tpl-mode-variable (concat "\\({{\s*"
93
+ tpl-mode-tpl-token
94
+ "\s*}}\\)"))
95
+ (defconst tpl-mode-builtins
96
+ (concat
97
+ "\\({{\\<\s*"
98
+ (regexp-opt
99
+ '("BI_NEWLINE" "BI_SPACE")
100
+ t)
101
+ "\s*\\>}}\\)"))
102
+ (defconst tpl-mode-close-section-at-start (concat "^[ \t]*?"
103
+ tpl-mode-close-section))
104
+
105
+ ;; Constant regular expressions to identify html tags.
106
+ ;; Taken from HTML 4.01 / XHTML 1.0 Reference found at:
107
+ ;; http://www.w3schools.com/tags/default.asp.
108
+ (defconst tpl-mode-html-constant "\\(&#?[a-z0-9]\\{2,5\\};\\)")
109
+ (defconst tpl-mode-pair-tag
110
+ (concat
111
+ "\\<"
112
+ (regexp-opt
113
+ '("a" "abbr" "acronym" "address" "applet" "area" "b" "bdo"
114
+ "big" "blockquote" "body" "button" "caption" "center" "cite"
115
+ "code" "col" "colgroup" "dd" "del" "dfn" "dif" "div" "dl"
116
+ "dt" "em" "fieldset" "font" "form" "frame" "frameset" "h1"
117
+ "h2" "h3" "h4" "h5" "h6" "head" "html" "i" "iframe" "ins"
118
+ "kbd" "label" "legend" "li" "link" "map" "menu" "noframes"
119
+ "noscript" "object" "ol" "optgroup" "option" "p" "pre" "q"
120
+ "s" "samp" "script" "select" "small" "span" "strike"
121
+ "strong" "style" "sub" "sup" "table" "tbody" "td" "textarea"
122
+ "tfoot" "th" "thead" "title" "tr" "tt" "u" "ul" "var")
123
+ t)
124
+ "\\>"))
125
+ (defconst tpl-mode-standalone-tag
126
+ (concat
127
+ "\\<"
128
+ (regexp-opt
129
+ '("base" "br" "hr" "img" "input" "meta" "param")
130
+ t)
131
+ "\\>"))
132
+ (defconst tpl-mode-open-tag (concat "<\\("
133
+ tpl-mode-pair-tag
134
+ "\\)"))
135
+ (defconst tpl-mode-close-tag (concat "</\\("
136
+ tpl-mode-pair-tag
137
+ "\\)>"))
138
+ (defconst tpl-mode-close-tag-at-start (concat "^[ \t]*?"
139
+ tpl-mode-close-tag))
140
+
141
+ (defconst tpl-mode-blank-line "^[ \t]*?$")
142
+ (defconst tpl-mode-dangling-open (concat "\\("
143
+ tpl-mode-open-section
144
+ "\\)\\|\\("
145
+ tpl-mode-open-tag
146
+ "\\)[^/]*$"))
147
+
148
+ (defun tpl-indent-command ()
149
+ "Command for indenting text. Just calls tpl-indent."
150
+ (interactive)
151
+ (tpl-indent))
152
+
153
+ (defun tpl-insert-tag (tag)
154
+ "Inserts an HTML tag."
155
+ (interactive "sTag: ")
156
+ (tpl-indent)
157
+ (insert (concat "<" tag ">"))
158
+ (insert "\n\n")
159
+ (insert (concat "</" tag ">"))
160
+ (tpl-indent)
161
+ (forward-line -1)
162
+ (tpl-indent))
163
+
164
+ (defun tpl-insert-variable (variable)
165
+ "Inserts a tpl variable."
166
+ (interactive "sVariable: ")
167
+ (insert (concat "{{" variable "}}")))
168
+
169
+ (defun tpl-insert-section (section)
170
+ "Inserts a tpl section."
171
+ (interactive "sSection: ")
172
+ (tpl-indent)
173
+ (insert (concat "{{#" section "}}\n"))
174
+ (insert "\n")
175
+ (insert (concat "{{/" section "}}"))
176
+ (tpl-indent)
177
+ (forward-line -1)
178
+ (tpl-indent))
179
+
180
+ ;; Function to control indenting.
181
+ (defun tpl-indent ()
182
+ "Indent current line"
183
+ ;; Set the point to beginning of line.
184
+ (beginning-of-line)
185
+ ;; If we are at the beginning of the file, indent to 0.
186
+ (if (bobp)
187
+ (indent-line-to 0)
188
+ (let ((tag-stack 1) (close-tag "") (cur-indent 0) (old-pnt (point-marker))
189
+ (close-at-start) (open-token) (dangling-open))
190
+ (progn
191
+ ;; Determine if this is a template line or an html line.
192
+ (if (looking-at "^[ \t]*?{{")
193
+ (setq close-at-start tpl-mode-close-section-at-start
194
+ open-token "{{#")
195
+ (setq close-at-start tpl-mode-close-tag-at-start
196
+ open-token "<"))
197
+ ;; If there is a closing tag at the start of the line, search back
198
+ ;; for its opener and indent to that level.
199
+ (if (looking-at close-at-start)
200
+ (progn
201
+ (save-excursion
202
+ (setq close-tag (match-string 1))
203
+ ;; Keep searching for a match for the close tag until
204
+ ;; the tag-stack is 0.
205
+ (while (and (not (bobp))
206
+ (> tag-stack 0)
207
+ (re-search-backward (concat open-token
208
+ "\\(/?\\)"
209
+ close-tag) nil t))
210
+ (if (string-equal (match-string 1) "/")
211
+ ;; We found another close tag, so increment tag-stack.
212
+ (setq tag-stack (+ tag-stack 1))
213
+ ;; We found an open tag, so decrement tag-stack.
214
+ (setq tag-stack (- tag-stack 1)))
215
+ (setq cur-indent (current-indentation))))
216
+ (if (> tag-stack 0)
217
+ (save-excursion
218
+ (forward-line -1)
219
+ (setq cur-indent (current-indentation)))))
220
+ ;; This was not a closing tag, so we check if the previous line
221
+ ;; was an opening tag.
222
+ (save-excursion
223
+ ;; Keep moving back until we find a line that is not blank
224
+ (while (progn
225
+ (forward-line -1)
226
+ (and (not (bobp)) (looking-at tpl-mode-blank-line))))
227
+ (setq cur-indent (current-indentation))
228
+ (if (re-search-forward tpl-mode-dangling-open old-pnt t)
229
+ (setq cur-indent (+ cur-indent tpl-basic-offset)))))
230
+ ;; Finally, we execute the actual indentation.
231
+ (if (> cur-indent 0)
232
+ (indent-line-to cur-indent)
233
+ (indent-line-to 0))))))
234
+
235
+ ;; controls highlighting
236
+ (defconst tpl-mode-font-lock-keywords
237
+ (list
238
+ (list tpl-mode-section
239
+ '(1 font-lock-keyword-face))
240
+ (list tpl-mode-comment
241
+ '(1 font-lock-comment-face))
242
+ (list tpl-mode-include
243
+ '(1 font-lock-builtin-face))
244
+ (list tpl-mode-builtins
245
+ '(1 font-lock-variable-name-face))
246
+ (list tpl-mode-variable
247
+ '(1 font-lock-reference-face))
248
+ (list (concat "</?\\(" tpl-mode-pair-tag "\\)")
249
+ '(1 font-lock-function-name-face))
250
+ (list (concat "<\\(" tpl-mode-standalone-tag "\\)")
251
+ '(1 font-lock-function-name-face))
252
+ (list tpl-mode-html-constant
253
+ '(1 font-lock-variable-name-face))))
254
+
255
+ (put 'tpl-mode 'font-lock-defaults '(tpl-font-lock-keywords nil t))
256
+
257
+ (defun tpl-mode ()
258
+ "Major mode for editing Google CTemplate file."
259
+ (interactive)
260
+ (kill-all-local-variables)
261
+ (use-local-map tpl-mode-map)
262
+ (setq major-mode 'tpl-mode)
263
+ (setq mode-name "tpl-mode")
264
+ (setq local-abbrev-table tpl-mode-abbrev-table)
265
+ (setq indent-tabs-mode nil)
266
+ (set-syntax-table tpl-mode-syntax-table)
267
+ ;; show trailing whitespace, but only when the user can fix it
268
+ (setq show-trailing-whitespace (not buffer-read-only))
269
+ (make-local-variable 'indent-line-function)
270
+ (setq indent-line-function 'tpl-indent)
271
+ (setq font-lock-defaults '(tpl-mode-font-lock-keywords))
272
+ (run-hooks 'tpl-mode-hook))
273
+
274
+ (provide 'tpl-mode)
@@ -9,8 +9,16 @@ module TestViews
9
9
  "Dragon < Tiger"
10
10
  end
11
11
  end
12
- end
13
12
 
13
+ class NamespacedWithPartial < Mustache
14
+ self.path = File.dirname(__FILE__)
15
+ self.template = "My opinion: {{>inner_partial}}"
16
+
17
+ def title
18
+ "Victory"
19
+ end
20
+ end
21
+ end
14
22
 
15
23
  if $0 == __FILE__
16
24
  puts TestViews::Namespaced.to_html
@@ -0,0 +1,3 @@
1
+ <h1>{{greeting}}</h1>
2
+ {{>simple}}
3
+ <h3>{{farewell}}</h3>
@@ -0,0 +1,37 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'mustache'
3
+
4
+ module SimpleView
5
+ def name
6
+ "Bob"
7
+ end
8
+
9
+ def value
10
+ 100_000
11
+ end
12
+
13
+ def taxed_value
14
+ value - (value * 0.4)
15
+ end
16
+
17
+ def in_ca
18
+ false
19
+ end
20
+ end
21
+
22
+ class PartialWithModule < Mustache
23
+ include SimpleView
24
+ self.path = File.dirname(__FILE__)
25
+
26
+ def greeting
27
+ "Welcome"
28
+ end
29
+
30
+ def farewell
31
+ "Fair enough, right?"
32
+ end
33
+ end
34
+
35
+ if $0 == __FILE__
36
+ puts PartialWithModule.to_html
37
+ end
@@ -1,2 +1,2 @@
1
1
  <h1>{{title}}</h1>
2
- {{<inner_partial}}
2
+ {{>inner_partial}}
@@ -1,4 +1,4 @@
1
1
  {{title}}
2
2
  {{title_bars}}
3
3
 
4
- {{<inner_partial}}
4
+ {{>inner_partial}}
@@ -27,7 +27,7 @@ class Mustache
27
27
  elsif @mustache.raise_on_context_miss?
28
28
  raise ContextMiss.new("Can't find #{name} in #{@mustache.inspect}")
29
29
  else
30
- ''
30
+ nil
31
31
  end
32
32
  end
33
33
  end
@@ -103,10 +103,10 @@ class Mustache
103
103
  # 1. Escaped variable tags - {{var}}
104
104
  # 2. Unescaped variable tags - {{{var}}}
105
105
  # 3. Comment variable tags - {{! comment}
106
- # 4. Partial tags - {{< partial_name }}
106
+ # 4. Partial tags - {{> partial_name }}
107
107
  def compile_tags(src)
108
108
  res = ""
109
- while src =~ /#{otag}(#|=|!|<|\{)?(.+?)\1?#{ctag}+/
109
+ while src =~ /#{otag}(#|=|!|<|>|\{)?(.+?)\1?#{ctag}+/
110
110
  res << str($`)
111
111
  case $1
112
112
  when '#'
@@ -117,7 +117,7 @@ class Mustache
117
117
  # ignore comments
118
118
  when '='
119
119
  self.otag, self.ctag = $2.strip.split(' ', 2)
120
- when '<'
120
+ when '>', '<'
121
121
  res << compile_partial($2.strip)
122
122
  when '{'
123
123
  res << utag($2.strip)
@@ -131,13 +131,8 @@ class Mustache
131
131
 
132
132
  # Partials are basically a way to render views from inside other views.
133
133
  def compile_partial(name)
134
- klass = Mustache.classify(name)
135
- if Object.const_defined?(klass)
136
- ev("#{klass}.render")
137
- else
138
- src = File.read("#{@template_path}/#{name}.#{@template_extension}")
139
- compile(src)[1..-2]
140
- end
134
+ src = File.read("#{@template_path}/#{name}.#{@template_extension}")
135
+ compile(src)[1..-2]
141
136
  end
142
137
 
143
138
  # Generate a temporary id, used when compiling code.
@@ -1,3 +1,3 @@
1
1
  class Mustache
2
- Version = '0.4.0'
2
+ Version = '0.5.0'
3
3
  end
data/lib/mustache.rb CHANGED
@@ -192,6 +192,8 @@ class Mustache
192
192
  else
193
193
  Mustache
194
194
  end
195
+ rescue NameError
196
+ Mustache
195
197
  end
196
198
 
197
199
  # Should an exception be raised when we cannot find a corresponding method
@@ -1,4 +1,6 @@
1
1
  if defined? Mustache
2
+ require 'benchmark'
3
+
2
4
  Mustache.class_eval do
3
5
  alias_method :real_render, :render
4
6
 
@@ -1,3 +1,17 @@
1
+ <script type="text/javascript">
2
+ $(function() {
3
+ $('#mustache_variables .variable').each(function() {
4
+ var el = $(this)
5
+ if (el.text().length > 500) {
6
+ var txt = el.text()
7
+ el.click(function() {
8
+ $(this).text(txt)
9
+ }).text( el.text().slice(0, 500) + '...' )
10
+ }
11
+ })
12
+ });
13
+ </script>
14
+
1
15
  <h3>Render Times</h3>
2
16
 
3
17
  <table>
@@ -16,7 +30,7 @@
16
30
 
17
31
  <h3>Variables</h3>
18
32
 
19
- <table>
33
+ <table id="mustache_variables">
20
34
  <tr>
21
35
  <th>Name</th>
22
36
  <th>Value</th>
@@ -25,7 +39,7 @@
25
39
  {{# variables }}
26
40
  <tr>
27
41
  <td>{{ key }}</td>
28
- <td>{{ value }}</td>
42
+ <td class="variable">{{ value }}</td>
29
43
  </tr>
30
44
  {{/ variables }}
31
45
  </table>
@@ -1,4 +1,5 @@
1
- require 'test/unit'
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
+ require 'helper'
2
3
 
3
4
  module TestViews; end
4
5
 
@@ -35,4 +36,17 @@ class AutoloadingTest < Test::Unit::TestCase
35
36
  <h1>Dragon &lt; Tiger</h1>
36
37
  end_render
37
38
  end
39
+
40
+ def test_namespaced_partial_autoload
41
+ Mustache.view_namespace = TestViews
42
+ klass = Mustache.view_class(:namespaced_with_partial)
43
+ assert_equal TestViews::NamespacedWithPartial, klass
44
+ assert_equal <<-end_render.strip, klass.render
45
+ My opinion: Again, Victory!
46
+ end_render
47
+ end
48
+
49
+ def test_bad_constant_name
50
+ assert_equal Mustache, Mustache.view_class(404)
51
+ end
38
52
  end
data/test/helper.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'test/unit'
2
+
3
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../examples'
4
+ require 'simple'
5
+ require 'complex_view'
6
+ require 'partial_with_module'
7
+ require 'template_partial'
8
+ require 'escaped'
9
+ require 'unescaped'
10
+ require 'comments'
11
+ require 'passenger'
12
+ require 'delimiters'
13
+ require 'double_section'
@@ -1,16 +1,5 @@
1
- require 'test/unit'
2
-
3
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/../examples'
4
- require 'simple'
5
- require 'complex_view'
6
- require 'view_partial'
7
- require 'template_partial'
8
- require 'escaped'
9
- require 'unescaped'
10
- require 'comments'
11
- require 'passenger'
12
- require 'delimiters'
13
- require 'double_section'
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
+ require 'helper'
14
3
 
15
4
  class MustacheTest < Test::Unit::TestCase
16
5
  def test_passenger
@@ -113,46 +102,15 @@ end_simple
113
102
  assert_equal 'Hi mom!', view.render
114
103
  end
115
104
 
116
- def test_view_partial
117
- assert_equal <<-end_partial.strip, ViewPartial.render
118
- <h1>Welcome</h1>
119
- Hello Chris
120
- You have just won $10000!
121
- Well, $6000.0, after taxes.
122
-
123
- <h3>Fair enough, right?</h3>
124
- end_partial
125
- end
126
-
127
- def test_template_partial
128
- assert_equal <<-end_partial.strip, TemplatePartial.render
129
- <h1>Welcome</h1>
130
- Again, Welcome!
131
- end_partial
132
- end
133
-
134
- def test_template_partial_with_custom_extension
135
- partial = Class.new(TemplatePartial)
136
- partial.template_extension = 'txt'
137
- partial.template_path = File.dirname(__FILE__) + '/../examples'
138
-
139
- assert_equal <<-end_partial.strip, partial.render.strip
140
- Welcome
141
- -------
142
-
143
- ## Again, Welcome! ##
144
- end_partial
145
- end
146
-
147
105
  def test_delimiters
148
- assert_equal <<-end_partial, Delimiters.render
106
+ assert_equal <<-end_template, Delimiters.render
149
107
 
150
108
  * It worked the first time.
151
109
 
152
110
  * And it worked the second time.
153
111
 
154
112
  * Then, surprisingly, it worked the third time.
155
- end_partial
113
+ end_template
156
114
  end
157
115
 
158
116
  def test_double_section
@@ -0,0 +1,80 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
+ require 'helper'
3
+
4
+ class PartialTest < Test::Unit::TestCase
5
+ def test_view_partial
6
+ assert_equal <<-end_partial.strip, PartialWithModule.render
7
+ <h1>Welcome</h1>
8
+ Hello Bob
9
+ You have just won $100000!
10
+
11
+ <h3>Fair enough, right?</h3>
12
+ end_partial
13
+ end
14
+
15
+ def test_view_partial_inherits_context
16
+ klass = Class.new(TemplatePartial)
17
+ klass.template_path = File.dirname(__FILE__) + '/../examples'
18
+ view = klass.new
19
+ view[:titles] = [{:title => :One}, {:title => :Two}]
20
+ view.template = <<-end_template
21
+ <h1>Context Test</h1>
22
+ <ul>
23
+ {{#titles}}
24
+ <li>{{>inner_partial}}</li>
25
+ {{/titles}}
26
+ </ul>
27
+ end_template
28
+ assert_equal <<-end_partial, view.render
29
+ <h1>Context Test</h1>
30
+ <ul>
31
+ <li>Again, One!</li>
32
+ <li>Again, Two!</li>
33
+ </ul>
34
+ end_partial
35
+ end
36
+
37
+ def test_view_partial_inherits_context_of_class_methods
38
+ klass = Class.new(TemplatePartial)
39
+ klass.template_path = File.dirname(__FILE__) + '/../examples'
40
+ klass.send(:define_method, :titles) do
41
+ [{:title => :One}, {:title => :Two}]
42
+ end
43
+ view = klass.new
44
+ view.template = <<-end_template
45
+ <h1>Context Test</h1>
46
+ <ul>
47
+ {{#titles}}
48
+ <li>{{>inner_partial}}</li>
49
+ {{/titles}}
50
+ </ul>
51
+ end_template
52
+ assert_equal <<-end_partial, view.render
53
+ <h1>Context Test</h1>
54
+ <ul>
55
+ <li>Again, One!</li>
56
+ <li>Again, Two!</li>
57
+ </ul>
58
+ end_partial
59
+ end
60
+
61
+ def test_template_partial
62
+ assert_equal <<-end_partial.strip, TemplatePartial.render
63
+ <h1>Welcome</h1>
64
+ Again, Welcome!
65
+ end_partial
66
+ end
67
+
68
+ def test_template_partial_with_custom_extension
69
+ partial = Class.new(TemplatePartial)
70
+ partial.template_extension = 'txt'
71
+ partial.template_path = File.dirname(__FILE__) + '/../examples'
72
+
73
+ assert_equal <<-end_partial.strip, partial.render.strip
74
+ Welcome
75
+ -------
76
+
77
+ ## Again, Welcome! ##
78
+ end_partial
79
+ end
80
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mustache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
@@ -9,14 +9,14 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-27 00:00:00 -07:00
13
- default_executable:
12
+ date: 2009-11-23 00:00:00 -08:00
13
+ default_executable: mustache
14
14
  dependencies: []
15
15
 
16
16
  description: Mustache is a framework-agnostic way to render logic-free views.
17
17
  email: chris@ozmm.org
18
- executables: []
19
-
18
+ executables:
19
+ - mustache
20
20
  extensions: []
21
21
 
22
22
  extra_rdoc_files:
@@ -35,7 +35,9 @@ files:
35
35
  - benchmarks/helper.rb
36
36
  - benchmarks/simple.erb
37
37
  - benchmarks/speed.rb
38
+ - bin/mustache
38
39
  - contrib/mustache.vim
40
+ - contrib/tpl-mode.el
39
41
  - examples/comments.mustache
40
42
  - examples/comments.rb
41
43
  - examples/complex_view.mustache
@@ -50,6 +52,8 @@ files:
50
52
  - examples/inner_partial.txt
51
53
  - examples/namespaced.mustache
52
54
  - examples/namespaced.rb
55
+ - examples/partial_with_module.mustache
56
+ - examples/partial_with_module.rb
53
57
  - examples/passenger.conf
54
58
  - examples/passenger.rb
55
59
  - examples/simple.mustache
@@ -59,8 +63,6 @@ files:
59
63
  - examples/template_partial.txt
60
64
  - examples/unescaped.mustache
61
65
  - examples/unescaped.rb
62
- - examples/view_partial.mustache
63
- - examples/view_partial.rb
64
66
  - lib/mustache.rb
65
67
  - lib/mustache/context.rb
66
68
  - lib/mustache/sinatra.rb
@@ -70,7 +72,9 @@ files:
70
72
  - lib/rack/bug/panels/mustache_panel/mustache_extension.rb
71
73
  - lib/rack/bug/panels/mustache_panel/view.mustache
72
74
  - test/autoloading_test.rb
75
+ - test/helper.rb
73
76
  - test/mustache_test.rb
77
+ - test/partial_test.rb
74
78
  has_rdoc: true
75
79
  homepage: http://github.com/defunkt/mustache
76
80
  licenses: []
@@ -101,15 +105,17 @@ specification_version: 3
101
105
  summary: Mustache is a framework-agnostic way to render logic-free views.
102
106
  test_files:
103
107
  - test/autoloading_test.rb
108
+ - test/helper.rb
104
109
  - test/mustache_test.rb
110
+ - test/partial_test.rb
105
111
  - examples/comments.rb
106
112
  - examples/complex_view.rb
107
113
  - examples/delimiters.rb
108
114
  - examples/double_section.rb
109
115
  - examples/escaped.rb
110
116
  - examples/namespaced.rb
117
+ - examples/partial_with_module.rb
111
118
  - examples/passenger.rb
112
119
  - examples/simple.rb
113
120
  - examples/template_partial.rb
114
121
  - examples/unescaped.rb
115
- - examples/view_partial.rb
@@ -1,3 +0,0 @@
1
- <h1>{{greeting}}</h1>
2
- {{<simple}}
3
- <h3>{{farewell}}</h3>
@@ -1,18 +0,0 @@
1
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
- require 'mustache'
3
-
4
- class ViewPartial < Mustache
5
- self.path = File.dirname(__FILE__)
6
-
7
- def greeting
8
- "Welcome"
9
- end
10
-
11
- def farewell
12
- "Fair enough, right?"
13
- end
14
- end
15
-
16
- if $0 == __FILE__
17
- puts ViewPartial.to_html
18
- end