angry_mob_common_targets 0.1.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.
Files changed (104) hide show
  1. data/LICENSE +21 -0
  2. data/README.md +38 -0
  3. data/lib/common_mob.rb +9 -0
  4. data/lib/common_mob/digest.rb +43 -0
  5. data/lib/common_mob/erb.rb +72 -0
  6. data/lib/common_mob/file.rb +55 -0
  7. data/lib/common_mob/patch.rb +51 -0
  8. data/lib/common_mob/resource_locator.rb +9 -0
  9. data/lib/common_mob/shell.rb +323 -0
  10. data/lib/common_mob/template.rb +23 -0
  11. data/lib/common_mob/version.rb +3 -0
  12. data/targets/crontab_patch.rb +37 -0
  13. data/targets/extract.rb +40 -0
  14. data/targets/fetch.rb +40 -0
  15. data/targets/files.rb +244 -0
  16. data/targets/git.rb +84 -0
  17. data/targets/group.rb +33 -0
  18. data/targets/packages.rb +94 -0
  19. data/targets/ruby.rb +13 -0
  20. data/targets/services.rb +184 -0
  21. data/targets/shell.rb +43 -0
  22. data/targets/user.rb +108 -0
  23. data/vendor/mustache/CONTRIBUTORS +9 -0
  24. data/vendor/mustache/HISTORY.md +135 -0
  25. data/vendor/mustache/LICENSE +20 -0
  26. data/vendor/mustache/README.md +405 -0
  27. data/vendor/mustache/Rakefile +103 -0
  28. data/vendor/mustache/benchmarks/complex.erb +15 -0
  29. data/vendor/mustache/benchmarks/complex.haml +12 -0
  30. data/vendor/mustache/benchmarks/helper.rb +20 -0
  31. data/vendor/mustache/benchmarks/simple.erb +5 -0
  32. data/vendor/mustache/benchmarks/speed.rb +78 -0
  33. data/vendor/mustache/bin/mustache +90 -0
  34. data/vendor/mustache/contrib/mustache-mode.el +278 -0
  35. data/vendor/mustache/contrib/mustache.vim +69 -0
  36. data/vendor/mustache/examples/hash.rb +16 -0
  37. data/vendor/mustache/examples/hash.yml +5 -0
  38. data/vendor/mustache/examples/projects.mustache +26 -0
  39. data/vendor/mustache/examples/projects.yml +28 -0
  40. data/vendor/mustache/examples/self.mustache +4 -0
  41. data/vendor/mustache/examples/self.yml +3 -0
  42. data/vendor/mustache/examples/simple.mustache +10 -0
  43. data/vendor/mustache/examples/simple.rb +24 -0
  44. data/vendor/mustache/lib/mustache.rb +358 -0
  45. data/vendor/mustache/lib/mustache/context.rb +108 -0
  46. data/vendor/mustache/lib/mustache/generator.rb +160 -0
  47. data/vendor/mustache/lib/mustache/parser.rb +230 -0
  48. data/vendor/mustache/lib/mustache/sinatra.rb +180 -0
  49. data/vendor/mustache/lib/mustache/template.rb +59 -0
  50. data/vendor/mustache/lib/mustache/version.rb +3 -0
  51. data/vendor/mustache/lib/rack/bug/panels/mustache_panel.rb +81 -0
  52. data/vendor/mustache/lib/rack/bug/panels/mustache_panel/mustache_extension.rb +27 -0
  53. data/vendor/mustache/lib/rack/bug/panels/mustache_panel/view.mustache +46 -0
  54. data/vendor/mustache/man/mustache.1 +180 -0
  55. data/vendor/mustache/man/mustache.1.html +204 -0
  56. data/vendor/mustache/man/mustache.1.ron +127 -0
  57. data/vendor/mustache/man/mustache.5 +576 -0
  58. data/vendor/mustache/man/mustache.5.html +415 -0
  59. data/vendor/mustache/man/mustache.5.ron +324 -0
  60. data/vendor/mustache/mustache.gemspec +32 -0
  61. data/vendor/mustache/test/autoloading_test.rb +52 -0
  62. data/vendor/mustache/test/fixtures/comments.mustache +1 -0
  63. data/vendor/mustache/test/fixtures/comments.rb +14 -0
  64. data/vendor/mustache/test/fixtures/complex_view.mustache +17 -0
  65. data/vendor/mustache/test/fixtures/complex_view.rb +34 -0
  66. data/vendor/mustache/test/fixtures/crazy_recursive.mustache +9 -0
  67. data/vendor/mustache/test/fixtures/crazy_recursive.rb +31 -0
  68. data/vendor/mustache/test/fixtures/delimiters.mustache +8 -0
  69. data/vendor/mustache/test/fixtures/delimiters.rb +23 -0
  70. data/vendor/mustache/test/fixtures/double_section.mustache +7 -0
  71. data/vendor/mustache/test/fixtures/double_section.rb +14 -0
  72. data/vendor/mustache/test/fixtures/escaped.mustache +1 -0
  73. data/vendor/mustache/test/fixtures/escaped.rb +14 -0
  74. data/vendor/mustache/test/fixtures/inner_partial.mustache +1 -0
  75. data/vendor/mustache/test/fixtures/inner_partial.txt +1 -0
  76. data/vendor/mustache/test/fixtures/inverted_section.mustache +7 -0
  77. data/vendor/mustache/test/fixtures/inverted_section.rb +14 -0
  78. data/vendor/mustache/test/fixtures/lambda.mustache +7 -0
  79. data/vendor/mustache/test/fixtures/lambda.rb +31 -0
  80. data/vendor/mustache/test/fixtures/namespaced.mustache +1 -0
  81. data/vendor/mustache/test/fixtures/namespaced.rb +25 -0
  82. data/vendor/mustache/test/fixtures/nested_objects.mustache +17 -0
  83. data/vendor/mustache/test/fixtures/nested_objects.rb +35 -0
  84. data/vendor/mustache/test/fixtures/node.mustache +8 -0
  85. data/vendor/mustache/test/fixtures/partial_with_module.mustache +3 -0
  86. data/vendor/mustache/test/fixtures/partial_with_module.rb +37 -0
  87. data/vendor/mustache/test/fixtures/passenger.conf +5 -0
  88. data/vendor/mustache/test/fixtures/passenger.rb +27 -0
  89. data/vendor/mustache/test/fixtures/recursive.mustache +4 -0
  90. data/vendor/mustache/test/fixtures/recursive.rb +14 -0
  91. data/vendor/mustache/test/fixtures/simple.mustache +5 -0
  92. data/vendor/mustache/test/fixtures/simple.rb +26 -0
  93. data/vendor/mustache/test/fixtures/template_partial.mustache +2 -0
  94. data/vendor/mustache/test/fixtures/template_partial.rb +18 -0
  95. data/vendor/mustache/test/fixtures/template_partial.txt +4 -0
  96. data/vendor/mustache/test/fixtures/unescaped.mustache +1 -0
  97. data/vendor/mustache/test/fixtures/unescaped.rb +14 -0
  98. data/vendor/mustache/test/fixtures/utf8.mustache +3 -0
  99. data/vendor/mustache/test/fixtures/utf8_partial.mustache +1 -0
  100. data/vendor/mustache/test/helper.rb +7 -0
  101. data/vendor/mustache/test/mustache_test.rb +536 -0
  102. data/vendor/mustache/test/parser_test.rb +54 -0
  103. data/vendor/mustache/test/partial_test.rb +168 -0
  104. metadata +167 -0
@@ -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
@@ -0,0 +1,5 @@
1
+ <VirtualHost *>
2
+ ServerName {{server}}
3
+ DocumentRoot {{deploy_to}}
4
+ RailsEnv {{stage}}
5
+ </VirtualHost>
@@ -0,0 +1,27 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'mustache'
3
+
4
+ class Passenger < Mustache
5
+ self.path = File.dirname(__FILE__)
6
+ self.template_extension = 'conf'
7
+
8
+ def server
9
+ "example.com"
10
+ end
11
+
12
+ def deploy_to
13
+ "/var/www/example.com"
14
+ end
15
+
16
+ def stage
17
+ "production"
18
+ end
19
+
20
+ def timestamp
21
+ Time.now.strftime('%Y%m%d%H%M%S')
22
+ end
23
+ end
24
+
25
+ if $0 == __FILE__
26
+ puts Passenger.to_text
27
+ end
@@ -0,0 +1,4 @@
1
+ It works!
2
+ {{#show}}
3
+ {{>recursive}}
4
+ {{/show}}
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'mustache'
3
+
4
+ class Recursive < Mustache
5
+ self.path = File.dirname(__FILE__)
6
+
7
+ def show
8
+ false
9
+ end
10
+ end
11
+
12
+ if $0 == __FILE__
13
+ puts Recursive.to_html
14
+ end
@@ -0,0 +1,5 @@
1
+ Hello {{name}}
2
+ You have just won ${{value}}!
3
+ {{#in_ca}}
4
+ Well, ${{ taxed_value }}, after taxes.
5
+ {{/in_ca}}
@@ -0,0 +1,26 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'mustache'
3
+
4
+ class Simple < Mustache
5
+ self.path = File.dirname(__FILE__)
6
+
7
+ def name
8
+ "Chris"
9
+ end
10
+
11
+ def value
12
+ 10_000
13
+ end
14
+
15
+ def taxed_value
16
+ value - (value * 0.4)
17
+ end
18
+
19
+ def in_ca
20
+ true
21
+ end
22
+ end
23
+
24
+ if $0 == __FILE__
25
+ puts Simple.to_html
26
+ end
@@ -0,0 +1,2 @@
1
+ <h1>{{title}}</h1>
2
+ {{>inner_partial}}
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'mustache'
3
+
4
+ class TemplatePartial < Mustache
5
+ self.path = File.dirname(__FILE__)
6
+
7
+ def title
8
+ "Welcome"
9
+ end
10
+
11
+ def title_bars
12
+ '-' * title.size
13
+ end
14
+ end
15
+
16
+ if $0 == __FILE__
17
+ puts TemplatePartial.to_html
18
+ end
@@ -0,0 +1,4 @@
1
+ {{title}}
2
+ {{title_bars}}
3
+
4
+ {{>inner_partial}}
@@ -0,0 +1 @@
1
+ <h1>{{{title}}}</h1>
@@ -0,0 +1,14 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+ require 'mustache'
3
+
4
+ class Unescaped < Mustache
5
+ self.path = File.dirname(__FILE__)
6
+
7
+ def title
8
+ "Bear > Shark"
9
+ end
10
+ end
11
+
12
+ if $0 == __FILE__
13
+ puts Unescaped.to_html
14
+ end
@@ -0,0 +1,3 @@
1
+ <h1>中文 {{test}}</h1>
2
+
3
+ {{> utf8_partial}}
@@ -0,0 +1 @@
1
+ <h2>中文又来啦</h2>
@@ -0,0 +1,7 @@
1
+ require 'test/unit'
2
+
3
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/fixtures'
4
+
5
+ Dir[File.dirname(__FILE__) + '/fixtures/*.rb'].each do |f|
6
+ require f
7
+ end
@@ -0,0 +1,536 @@
1
+ # -*- coding: utf-8 -*-
2
+ $LOAD_PATH.unshift File.dirname(__FILE__)
3
+ require 'helper'
4
+
5
+ class MustacheTest < Test::Unit::TestCase
6
+ def test_passenger
7
+ assert_equal <<-end_passenger, Passenger.to_text
8
+ <VirtualHost *>
9
+ ServerName example.com
10
+ DocumentRoot /var/www/example.com
11
+ RailsEnv production
12
+ </VirtualHost>
13
+ end_passenger
14
+ end
15
+
16
+ def test_complex_view
17
+ assert_equal <<-end_complex, ComplexView.render
18
+ <h1>Colors</h1>
19
+ <ul>
20
+ <li><strong>red</strong></li>
21
+ <li><a href="#Green">green</a></li>
22
+ <li><a href="#Blue">blue</a></li>
23
+ </ul>
24
+ end_complex
25
+ end
26
+
27
+ def test_nested_objects
28
+ assert_equal <<-end_complex, NestedObjects.render
29
+ <h1>Colors</h1>
30
+ <ul>
31
+ <li><strong>red</strong></li>
32
+ <li><a href="#Green">green</a></li>
33
+ <li><a href="#Blue">blue</a></li>
34
+ </ul>
35
+ end_complex
36
+ end
37
+
38
+ def test_single_line_sections
39
+ html = %(<p class="flash-notice" {{# no_flash }}style="display: none;"{{/ no_flash }}>)
40
+
41
+ instance = Mustache.new
42
+ instance.template = html
43
+ instance[:no_flash] = true
44
+ assert_equal <<-rendered.strip, instance.render
45
+ <p class="flash-notice" style="display: none;">
46
+ rendered
47
+ end
48
+
49
+ def test_two_line_sections
50
+ html = %(<p class="flash-notice" {{# no_flash }}style="display: none;"\n{{/ no_flash }}>)
51
+
52
+ instance = Mustache.new
53
+ instance.template = html
54
+ instance[:no_flash] = true
55
+ assert_equal <<-rendered.strip, instance.render
56
+ <p class="flash-notice" style="display: none;"\n>
57
+ rendered
58
+ end
59
+
60
+ def test_multi_line_sections_preserve_trailing_newline
61
+ view = Mustache.new
62
+ view.template = <<template
63
+ {{#something}}
64
+ yay
65
+ {{/something}}
66
+ Howday.
67
+ template
68
+
69
+ view[:something] = true
70
+ assert_equal <<-rendered.strip, view.render.strip
71
+ yay
72
+ Howday.
73
+ rendered
74
+ end
75
+
76
+ def test_single_line_inverted_sections
77
+ html = %(<p class="flash-notice" {{^ flash }}style="display: none;"{{/ flash }}>)
78
+
79
+ instance = Mustache.new
80
+ instance.template = html
81
+ assert_equal <<-rendered.strip, instance.render
82
+ <p class="flash-notice" style="display: none;">
83
+ rendered
84
+ end
85
+
86
+ def test_simple
87
+ assert_equal <<-end_simple, Simple.render
88
+ Hello Chris
89
+ You have just won $10000!
90
+ Well, $6000.0, after taxes.
91
+ end_simple
92
+ end
93
+
94
+ def test_hash_assignment
95
+ view = Simple.new
96
+ view[:name] = 'Bob'
97
+ view[:value] = '4000'
98
+ view[:in_ca] = false
99
+
100
+ assert_equal <<-end_simple, view.render
101
+ Hello Bob
102
+ You have just won $4000!
103
+ end_simple
104
+ end
105
+
106
+ def test_crazier_hash_assignment
107
+ view = Simple.new
108
+ view[:name] = 'Crazy'
109
+ view[:in_ca] = [
110
+ { :taxed_value => 1 },
111
+ { :taxed_value => 2 },
112
+ { :taxed_value => 3 },
113
+ ]
114
+
115
+ assert_equal <<-end_simple, view.render
116
+ Hello Crazy
117
+ You have just won $10000!
118
+ Well, $1, after taxes.
119
+ Well, $2, after taxes.
120
+ Well, $3, after taxes.
121
+ end_simple
122
+ end
123
+
124
+ def test_fileless_templates
125
+ view = Simple.new
126
+ view.template = 'Hi {{person}}!'
127
+ view[:person] = 'mom'
128
+
129
+ assert_equal 'Hi mom!', view.render
130
+ end
131
+
132
+ def test_delimiters
133
+ assert_equal <<-end_template, Delimiters.render
134
+
135
+ * It worked the first time.
136
+
137
+ * And it worked the second time.
138
+ * As well as the third.
139
+
140
+ * Then, surprisingly, it worked the final time.
141
+ end_template
142
+ end
143
+
144
+ def test_double_section
145
+ assert_equal <<-end_section.strip, DoubleSection.render.strip
146
+ * first
147
+ * second
148
+ * third
149
+ end_section
150
+ end
151
+
152
+ def test_inverted_section
153
+ assert_equal <<-end_section.strip, InvertedSection.render.strip
154
+ * first
155
+ * second
156
+ * third
157
+ end_section
158
+ end
159
+
160
+ def test_comments
161
+ assert_equal "<h1>A Comedy of Errors</h1>\n", Comments.render
162
+ end
163
+
164
+ def test_multi_linecomments
165
+ view = Comments.new
166
+ view.template = "<h1>{{title}}{{! just something interesting... \n#or not... }}</h1>\n"
167
+ assert_equal "<h1>A Comedy of Errors</h1>\n", view.render
168
+ end
169
+
170
+ def test_escaped
171
+ assert_equal '<h1>Bear &gt; Shark</h1>', Escaped.render
172
+ end
173
+
174
+ def test_unescaped
175
+ assert_equal '<h1>Bear > Shark</h1>', Unescaped.render
176
+ end
177
+
178
+ def test_unescaped_ampersand
179
+ view = Mustache.new
180
+ view.template = "<h1>{{& title}}</h1>"
181
+ view[:title] = "Bear > Shark"
182
+ assert_equal '<h1>Bear > Shark</h1>', view.render
183
+ end
184
+
185
+ def test_classify
186
+ assert_equal 'TemplatePartial', Mustache.classify('template_partial')
187
+ end
188
+
189
+ def test_underscore
190
+ assert_equal 'template_partial', Mustache.underscore('TemplatePartial')
191
+ end
192
+
193
+ def test_anon_subclass_underscore
194
+ klass = Class.new(TemplatePartial)
195
+ assert_equal 'template_partial', klass.underscore
196
+ end
197
+
198
+ def test_namespaced_underscore
199
+ assert_equal 'stat_stuff', Mustache.underscore('Views::StatStuff')
200
+ end
201
+
202
+ def test_render
203
+ assert_equal 'Hello World!', Mustache.render('Hello World!')
204
+ end
205
+
206
+ def test_render_with_params
207
+ assert_equal 'Hello World!', Mustache.render('Hello {{planet}}!', :planet => 'World')
208
+ end
209
+
210
+ def test_render_from_file
211
+ expected = <<-data
212
+ <VirtualHost *>
213
+ ServerName example.com
214
+ DocumentRoot /var/www/example.com
215
+ RailsEnv production
216
+ </VirtualHost>
217
+ data
218
+ template = File.read(File.dirname(__FILE__) + "/fixtures/passenger.conf")
219
+ assert_equal expected, Mustache.render(template, :stage => 'production',
220
+ :server => 'example.com',
221
+ :deploy_to => '/var/www/example.com' )
222
+ end
223
+
224
+ def test_doesnt_execute_what_it_doesnt_need_to
225
+ instance = Mustache.new
226
+ instance[:show] = false
227
+ instance.instance_eval do
228
+ def die
229
+ raise "bummer"
230
+ end
231
+ end
232
+ instance.template = '{{#show}} <li>{{die}}</li> {{/show}} yay'
233
+
234
+ assert_equal "yay", instance.render
235
+ end
236
+
237
+ def test_reports_unclosed_sections
238
+ instance = Mustache.new
239
+ instance[:list] = [ :item => 1234 ]
240
+ instance.template = '{{#list}} <li>{{item}}</li> {{/gist}}'
241
+
242
+ begin
243
+ instance.render
244
+ rescue => e
245
+ end
246
+
247
+ assert e.message.include?('Unclosed section')
248
+ end
249
+
250
+ def test_unclosed_sections_reports_the_line_number
251
+ instance = Mustache.new
252
+ instance[:list] = [ :item => 1234 ]
253
+ instance.template = "hi\nmom\n{{#list}} <li>{{item}}</li> {{/gist}}"
254
+
255
+ begin
256
+ instance.render
257
+ rescue => e
258
+ end
259
+
260
+ assert e.message.include?('Line 3')
261
+ end
262
+
263
+ def test_enumerable_sections_accept_a_hash_as_a_context
264
+ instance = Mustache.new
265
+ instance[:list] = { :item => 1234 }
266
+ instance.template = '{{#list}} <li>{{item}}</li> {{/list}}'
267
+
268
+ assert_equal '<li>1234</li>', instance.render.strip
269
+ end
270
+
271
+ def test_enumerable_sections_accept_a_string_keyed_hash_as_a_context
272
+ instance = Mustache.new
273
+ instance[:list] = { 'item' => 1234 }
274
+ instance.template = '{{#list}} <li>{{item}}</li> {{/list}}'
275
+
276
+ assert_equal '<li>1234</li>', instance.render.strip
277
+ end
278
+
279
+ def test_not_found_in_context_renders_empty_string
280
+ instance = Mustache.new
281
+ instance.template = '{{#list}} <li>{{item}}</li> {{/list}}'
282
+
283
+ assert_equal '', instance.render.strip
284
+ end
285
+
286
+ def test_not_found_in_nested_context_renders_empty_string
287
+ instance = Mustache.new
288
+ instance[:list] = { :item => 1234 }
289
+ instance.template = '{{#list}} <li>{{prefix}}{{item}}</li> {{/list}}'
290
+
291
+ assert_equal '<li>1234</li>', instance.render.strip
292
+ end
293
+
294
+ def test_not_found_in_context_raises_when_asked_to
295
+ instance = Mustache.new
296
+ instance.raise_on_context_miss = true
297
+ instance.template = '{{#list}} <li>{{item}}</li> {{/list}}'
298
+
299
+ assert_raises Mustache::ContextMiss do
300
+ instance.render.strip
301
+ end
302
+ end
303
+
304
+ def test_knows_when_its_been_compiled_when_set_with_string
305
+ klass = Class.new(Mustache)
306
+
307
+ assert ! klass.compiled?
308
+ klass.template = 'Hi, {{person}}!'
309
+ assert klass.compiled?
310
+ end
311
+
312
+ def test_knows_when_its_been_compiled_when_using_a_file_template
313
+ klass = Class.new(Simple)
314
+ klass.template_file = File.dirname(__FILE__) + '/fixtures/simple.mustache'
315
+
316
+ assert ! klass.compiled?
317
+ klass.render
318
+ assert klass.compiled?
319
+ end
320
+
321
+ def test_an_instance_knows_when_its_class_is_compiled
322
+ instance = Simple.new
323
+
324
+ assert ! Simple.compiled?
325
+ assert ! instance.compiled?
326
+
327
+ Simple.render
328
+
329
+ assert Simple.compiled?
330
+ assert instance.compiled?
331
+ end
332
+
333
+ def test_knows_when_its_been_compiled_at_the_instance_level
334
+ klass = Class.new(Mustache)
335
+ instance = klass.new
336
+
337
+ assert ! instance.compiled?
338
+ instance.template = 'Hi, {{person}}!'
339
+ assert instance.compiled?
340
+ end
341
+
342
+ def test_sections_returning_lambdas_get_called_with_text
343
+ view = Lambda.new
344
+ view[:name] = 'Chris'
345
+
346
+ assert_equal "Hi Chris.\nHi {{name}}.", view.render.chomp
347
+ assert_equal 1, view.calls
348
+
349
+ assert_equal "Hi Chris.\nHi {{name}}.", view.render.chomp
350
+ assert_equal 1, view.calls
351
+
352
+ assert_equal "Hi Chris.\nHi {{name}}.", view.render.chomp
353
+ assert_equal 1, view.calls
354
+ end
355
+
356
+ def test_lots_of_staches
357
+ template = "{{{{foo}}}}"
358
+
359
+ begin
360
+ Mustache.render(template, :foo => "defunkt")
361
+ rescue => e
362
+ end
363
+
364
+ assert e.message.include?("Illegal content in tag")
365
+ end
366
+
367
+ def test_liberal_tag_names
368
+ template = "{{first-name}} {{middle_name!}} {{lastName?}}"
369
+ hash = {
370
+ 'first-name' => 'chris',
371
+ 'middle_name!' => 'j',
372
+ 'lastName?' => 'strath'
373
+ }
374
+
375
+ assert_equal "chris j strath", Mustache.render(template, hash)
376
+ end
377
+
378
+ def test_nested_sections_same_names
379
+ template = <<template
380
+ {{#items}}
381
+ start
382
+ {{#items}}
383
+ {{a}}
384
+ {{/items}}
385
+ end
386
+ {{/items}}
387
+ template
388
+
389
+ data = {
390
+ "items" => [
391
+ { "items" => [ {"a" => 1}, {"a" => 2}, {"a" => 3} ] },
392
+ { "items" => [ {"a" => 4}, {"a" => 5}, {"a" => 6} ] },
393
+ { "items" => [ {"a" => 7}, {"a" => 8}, {"a" => 9} ] }
394
+ ]
395
+ }
396
+
397
+ assert_equal <<expected, Mustache.render(template, data)
398
+ start
399
+ 1
400
+ 2
401
+ 3
402
+ end
403
+ start
404
+ 4
405
+ 5
406
+ 6
407
+ end
408
+ start
409
+ 7
410
+ 8
411
+ 9
412
+ end
413
+ expected
414
+ end
415
+
416
+ def test_id_with_nested_context
417
+ html = %(<div>{{id}}</div>\n<div>{{# has_a? }}{{id}}{{/ has_a? }}</div>\n<div>{{# has_b? }}{{id}}{{/ has_b? }}</div>)
418
+
419
+ instance = Mustache.new
420
+ instance.template = html
421
+ instance[:id] = 3
422
+ instance[:has_a?] = true
423
+ instance[:has_b?] = true
424
+ assert_equal <<-rendered.strip, instance.render
425
+ <div>3</div>
426
+ <div>3</div>
427
+ <div>3</div>
428
+ rendered
429
+ end
430
+
431
+ def test_utf8
432
+ klass = Class.new(Mustache)
433
+ klass.template_name = 'utf8'
434
+ klass.template_path = 'test/fixtures'
435
+ view = klass.new
436
+ view[:test] = "中文"
437
+
438
+ assert_equal <<-rendered, view.render
439
+ <h1>中文 中文</h1>
440
+
441
+ <h2>中文又来啦</h2>
442
+ rendered
443
+ end
444
+
445
+ def test_indentation
446
+ view = Mustache.new
447
+ view[:name] = 'indent'
448
+ view[:text] = 'puts :indented!'
449
+ view.template = <<template
450
+ def {{name}}
451
+ {{text}}
452
+ end
453
+ template
454
+
455
+ assert_equal <<template, view.render
456
+ def indent
457
+ puts :indented!
458
+ end
459
+ template
460
+ end
461
+
462
+ def test_inherited_attributes
463
+ Object.const_set :TestNamespace, Module.new
464
+ base = Class.new(Mustache)
465
+ tmpl = Class.new(base)
466
+
467
+ {:template_path => File.expand_path('./foo'),
468
+ :template_extension => 'stache',
469
+ :view_namespace => TestNamespace,
470
+ :view_path => './foo'
471
+ }.each do |attr, value|
472
+ base.send("#{attr}=", value)
473
+ assert_equal value, tmpl.send(attr)
474
+ end
475
+ end
476
+ def test_array_of_arrays
477
+ template = <<template
478
+ {{#items}}
479
+ start
480
+ {{#map}}
481
+ {{a}}
482
+ {{/map}}
483
+ end
484
+ {{/items}}
485
+ template
486
+
487
+ data = {
488
+ "items" => [
489
+ [ {"a" => 1}, {"a" => 2}, {"a" => 3} ],
490
+ [ {"a" => 4}, {"a" => 5}, {"a" => 6} ],
491
+ [ {"a" => 7}, {"a" => 8}, {"a" => 9} ]
492
+ ]
493
+ }
494
+
495
+ assert_equal <<expected, Mustache.render(template, data)
496
+ start
497
+ 1
498
+ 2
499
+ 3
500
+ end
501
+ start
502
+ 4
503
+ 5
504
+ 6
505
+ end
506
+ start
507
+ 7
508
+ 8
509
+ 9
510
+ end
511
+ expected
512
+ end
513
+ def test_indentation
514
+ template = <<template
515
+ SELECT
516
+ {{#cols}}
517
+ {{name}},
518
+ {{/cols}}
519
+ FROM
520
+ DUMMY1
521
+ template
522
+
523
+ view = Mustache.new
524
+ view[:cols] = [{:name => 'Name'}, {:name => 'Age'}, {:name => 'Weight'}]
525
+ view.template = template
526
+
527
+ assert_equal <<template, view.render
528
+ SELECT
529
+ Name,
530
+ Age,
531
+ Weight,
532
+ FROM
533
+ DUMMY1
534
+ template
535
+ end
536
+ end