mustache 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.4.1 (2009-10-27)
2
+
3
+ * Partials now respect the `view_namespace` setting.
4
+ * Added tpl-mode.el to contrib/ for us Emacs users.
5
+ * Rack::Bug bugfix: ensure benchmark is required before using it
6
+ * Rack::Bug: truncate too-large variables (click expands them)
7
+
1
8
  ## 0.4.0 (2009-10-27)
2
9
 
3
10
  * Stopped raising context miss exceptions by default
data/README.md CHANGED
@@ -399,6 +399,14 @@ Thanks to [Juvenn Woo](http://github.com/juvenn) for mustache.vim. It
399
399
  is included under the contrib/ directory.
400
400
 
401
401
 
402
+ Emacs
403
+ ----
404
+
405
+ tpl-mode.el is included under the contrib/ directory for any Emacs users.
406
+ Based on Google's tpl-mode for ctemplates, it adds support for Mustache's
407
+ more lenient tag values and includes a few commands for your editing pleasure.
408
+
409
+
402
410
  Installation
403
411
  ------------
404
412
 
@@ -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,19 @@ module TestViews
9
9
  "Dragon < Tiger"
10
10
  end
11
11
  end
12
- end
13
12
 
13
+ class NamespacedWithPartial < Mustache
14
+ self.template = "My opinion: {{<MyPartial}}"
15
+ end
16
+
17
+ class MyPartial < Mustache
18
+ self.template = "{{exclamation}}!"
19
+
20
+ def exclamation
21
+ :Victory
22
+ end
23
+ end
24
+ end
14
25
 
15
26
  if $0 == __FILE__
16
27
  puts TestViews::Namespaced.to_html
@@ -131,8 +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)
134
+ klass = Mustache.view_class(name)
135
+ if klass != Mustache
136
136
  ev("#{klass}.render")
137
137
  else
138
138
  src = File.read("#{@template_path}/#{name}.#{@template_extension}")
@@ -1,3 +1,3 @@
1
1
  class Mustache
2
- Version = '0.4.0'
2
+ Version = '0.4.1'
3
3
  end
@@ -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>
@@ -33,6 +33,15 @@ class AutoloadingTest < Test::Unit::TestCase
33
33
  assert_equal TestViews::Namespaced, klass
34
34
  assert_equal <<-end_render.strip, klass.render
35
35
  <h1>Dragon &lt; Tiger</h1>
36
+ end_render
37
+ end
38
+
39
+ def test_namespaced_partial_autoload
40
+ Mustache.view_namespace = TestViews
41
+ klass = Mustache.view_class(:namespaced_with_partial)
42
+ assert_equal TestViews::NamespacedWithPartial, klass
43
+ assert_equal <<-end_render.strip, klass.render
44
+ My opinion: Victory!
36
45
  end_render
37
46
  end
38
47
  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.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wanstrath
@@ -36,6 +36,7 @@ files:
36
36
  - benchmarks/simple.erb
37
37
  - benchmarks/speed.rb
38
38
  - contrib/mustache.vim
39
+ - contrib/tpl-mode.el
39
40
  - examples/comments.mustache
40
41
  - examples/comments.rb
41
42
  - examples/complex_view.mustache