temple 0.2.0 → 0.3.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 (54) hide show
  1. data/.yardopts +2 -1
  2. data/CHANGES +63 -0
  3. data/EXPRESSIONS.md +250 -0
  4. data/README.md +24 -12
  5. data/lib/temple.rb +34 -18
  6. data/lib/temple/engine.rb +11 -7
  7. data/lib/temple/erb/engine.rb +5 -3
  8. data/lib/temple/erb/parser.rb +5 -2
  9. data/lib/temple/erb/template.rb +11 -0
  10. data/lib/temple/erb/trimming.rb +9 -1
  11. data/lib/temple/filter.rb +2 -0
  12. data/lib/temple/filters/control_flow.rb +43 -0
  13. data/lib/temple/filters/dynamic_inliner.rb +29 -32
  14. data/lib/temple/filters/eraser.rb +22 -0
  15. data/lib/temple/filters/escapable.rb +39 -0
  16. data/lib/temple/filters/multi_flattener.rb +4 -1
  17. data/lib/temple/filters/static_merger.rb +11 -10
  18. data/lib/temple/filters/validator.rb +15 -0
  19. data/lib/temple/generators.rb +41 -100
  20. data/lib/temple/grammar.rb +56 -0
  21. data/lib/temple/hash.rb +48 -0
  22. data/lib/temple/html/dispatcher.rb +10 -4
  23. data/lib/temple/html/fast.rb +50 -38
  24. data/lib/temple/html/filter.rb +8 -0
  25. data/lib/temple/html/pretty.rb +25 -14
  26. data/lib/temple/mixins/dispatcher.rb +103 -0
  27. data/lib/temple/{mixins.rb → mixins/engine_dsl.rb} +10 -95
  28. data/lib/temple/mixins/grammar_dsl.rb +166 -0
  29. data/lib/temple/mixins/options.rb +28 -0
  30. data/lib/temple/mixins/template.rb +25 -0
  31. data/lib/temple/templates.rb +2 -0
  32. data/lib/temple/utils.rb +11 -57
  33. data/lib/temple/version.rb +1 -1
  34. data/test/filters/test_control_flow.rb +92 -0
  35. data/test/filters/test_dynamic_inliner.rb +7 -7
  36. data/test/filters/test_eraser.rb +55 -0
  37. data/test/filters/{test_escape_html.rb → test_escapable.rb} +13 -6
  38. data/test/filters/test_multi_flattener.rb +1 -1
  39. data/test/filters/test_static_merger.rb +3 -3
  40. data/test/helper.rb +8 -0
  41. data/test/html/test_fast.rb +42 -57
  42. data/test/html/test_pretty.rb +10 -7
  43. data/test/mixins/test_dispatcher.rb +31 -0
  44. data/test/mixins/test_grammar_dsl.rb +86 -0
  45. data/test/test_engine.rb +73 -57
  46. data/test/test_erb.rb +0 -7
  47. data/test/test_filter.rb +26 -0
  48. data/test/test_generator.rb +57 -36
  49. data/test/test_grammar.rb +52 -0
  50. data/test/test_hash.rb +39 -0
  51. data/test/test_utils.rb +11 -38
  52. metadata +34 -10
  53. data/lib/temple/filters/debugger.rb +0 -26
  54. data/lib/temple/filters/escape_html.rb +0 -33
@@ -1,3 +1,3 @@
1
1
  module Temple
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -0,0 +1,92 @@
1
+ require 'helper'
2
+
3
+ describe Temple::Filters::ControlFlow do
4
+ before do
5
+ @filter = Temple::Filters::ControlFlow.new
6
+ end
7
+
8
+ it 'should process blocks' do
9
+ @filter.call([:block, 'loop do',
10
+ [:static, 'Hello']
11
+ ]).should.equal [:multi,
12
+ [:code, 'loop do'],
13
+ [:static, 'Hello'],
14
+ [:code, 'end']]
15
+ end
16
+
17
+ it 'should process if' do
18
+ @filter.call([:if, 'condition',
19
+ [:static, 'Hello']
20
+ ]).should.equal [:multi,
21
+ [:code, 'if condition'],
22
+ [:static, 'Hello'],
23
+ [:code, 'end']
24
+ ]
25
+ end
26
+
27
+ it 'should process if with else' do
28
+ @filter.call([:if, 'condition',
29
+ [:static, 'True'],
30
+ [:static, 'False']
31
+ ]).should.equal [:multi,
32
+ [:code, 'if condition'],
33
+ [:static, 'True'],
34
+ [:code, 'else'],
35
+ [:static, 'False'],
36
+ [:code, 'end']
37
+ ]
38
+ end
39
+
40
+ it 'should create elsif' do
41
+ @filter.call([:if, 'condition1',
42
+ [:static, '1'],
43
+ [:if, 'condition2',
44
+ [:static, '2'],
45
+ [:static, '3']]
46
+ ]).should.equal [:multi,
47
+ [:code, 'if condition1'],
48
+ [:static, '1'],
49
+ [:code, 'elsif condition2'],
50
+ [:static, '2'],
51
+ [:code, 'else'],
52
+ [:static, '3'],
53
+ [:code, 'end']
54
+ ]
55
+ end
56
+
57
+ it 'should process cond' do
58
+ @filter.call([:cond,
59
+ ['cond1', [:exp11], [:exp12]],
60
+ ['cond2', [:exp2]],
61
+ [:else, [:exp3]],
62
+ ]).should.equal [:multi,
63
+ [:code, 'case'],
64
+ [:code, 'when cond1'],
65
+ [:exp11],
66
+ [:exp12],
67
+ [:code, 'when cond2'],
68
+ [:exp2],
69
+ [:code, 'else'],
70
+ [:exp3],
71
+ [:code, 'end']
72
+ ]
73
+ end
74
+
75
+ it 'should process case' do
76
+ @filter.call([:case, 'var',
77
+ ['Array', [:exp11], [:exp12]],
78
+ ['String', [:exp2]],
79
+ [:else, [:exp3]],
80
+ ]).should.equal [:multi,
81
+ [:code, 'case (var)'],
82
+ [:code, 'when Array'],
83
+ [:exp11],
84
+ [:exp12],
85
+ [:code, 'when String'],
86
+ [:exp2],
87
+ [:code, 'else'],
88
+ [:exp3],
89
+ [:code, 'end']
90
+ ]
91
+ end
92
+ end
@@ -30,22 +30,22 @@ describe Temple::Filters::DynamicInliner do
30
30
  ]).should.equal [:multi, [:dynamic, '"Hello#{@world}#{@yeah}Nice"']]
31
31
  end
32
32
 
33
- it 'should merge statics and dynamics around a block' do
33
+ it 'should merge statics and dynamics around a code' do
34
34
  exp = @filter.call([:multi,
35
35
  [:static, "Hello "],
36
36
  [:dynamic, "@world"],
37
- [:block, "Oh yeah"],
37
+ [:code, "Oh yeah"],
38
38
  [:dynamic, "@yeah"],
39
39
  [:static, "Once more"]
40
40
  ]).should.equal [:multi,
41
41
  [:dynamic, '"Hello #{@world}"'],
42
- [:block, "Oh yeah"],
42
+ [:code, "Oh yeah"],
43
43
  [:dynamic, '"#{@yeah}Once more"']
44
44
  ]
45
45
  end
46
46
 
47
- it 'should keep blocks intact' do
48
- exp = [:multi, [:block, 'foo']]
47
+ it 'should keep codes intact' do
48
+ exp = [:multi, [:code, 'foo']]
49
49
  @filter.call(exp).should.equal exp
50
50
  end
51
51
 
@@ -90,11 +90,11 @@ describe Temple::Filters::DynamicInliner do
90
90
  @filter.call([:multi,
91
91
  [:static, "Hello \n"],
92
92
  [:newline],
93
- [:block, "world"]
93
+ [:code, "world"]
94
94
  ]).should.equal [:multi,
95
95
  [:static, "Hello \n"],
96
96
  [:newline],
97
- [:block, "world"]
97
+ [:code, "world"]
98
98
  ]
99
99
  end
100
100
  end
@@ -0,0 +1,55 @@
1
+ require 'helper'
2
+
3
+ describe Temple::Filters::Eraser do
4
+ it 'should respect keep' do
5
+ eraser = Temple::Filters::Eraser.new(:keep => [:a])
6
+ eraser.call([:multi,
7
+ [:a],
8
+ [:b],
9
+ [:c]
10
+ ]).should.equal [:multi,
11
+ [:a],
12
+ [:multi],
13
+ [:multi]
14
+ ]
15
+ end
16
+
17
+ it 'should respect erase' do
18
+ eraser = Temple::Filters::Eraser.new(:erase => [:a])
19
+ eraser.call([:multi,
20
+ [:a],
21
+ [:b],
22
+ [:c]
23
+ ]).should.equal [:multi,
24
+ [:multi],
25
+ [:b],
26
+ [:c]
27
+ ]
28
+ end
29
+
30
+ it 'should choose erase over keep' do
31
+ eraser = Temple::Filters::Eraser.new(:keep => [:a, :b], :erase => [:a])
32
+ eraser.call([:multi,
33
+ [:a],
34
+ [:b],
35
+ [:c]
36
+ ]).should.equal [:multi,
37
+ [:multi],
38
+ [:b],
39
+ [:multi]
40
+ ]
41
+ end
42
+
43
+ it 'should erase nested types' do
44
+ eraser = Temple::Filters::Eraser.new(:erase => [[:a, :b]])
45
+ eraser.call([:multi,
46
+ [:a, :a],
47
+ [:a, :b],
48
+ [:b]
49
+ ]).should.equal [:multi,
50
+ [:a, :a],
51
+ [:multi],
52
+ [:b]
53
+ ]
54
+ end
55
+ end
@@ -6,9 +6,9 @@ class HtmlSafeString < String
6
6
  end
7
7
  end
8
8
 
9
- describe Temple::Filters::EscapeHTML do
9
+ describe Temple::Filters::Escapable do
10
10
  before do
11
- @filter = Temple::Filters::EscapeHTML.new
11
+ @filter = Temple::Filters::Escapable.new
12
12
  end
13
13
 
14
14
  it 'should handle escape expressions' do
@@ -22,8 +22,8 @@ describe Temple::Filters::EscapeHTML do
22
22
  ]
23
23
  end
24
24
 
25
- it 'should keep blocks intact' do
26
- exp = [:multi, [:block, 'foo']]
25
+ it 'should keep codes intact' do
26
+ exp = [:multi, [:code, 'foo']]
27
27
  @filter.call(exp).should.equal exp
28
28
  end
29
29
 
@@ -38,9 +38,16 @@ describe Temple::Filters::EscapeHTML do
38
38
  end
39
39
 
40
40
  it 'should have use_html_safe option' do
41
- filter = Temple::Filters::EscapeHTML.new(:use_html_safe => true)
41
+ filter = Temple::Filters::Escapable.new(:use_html_safe => true)
42
42
  filter.call([:escape, true,
43
- [:static, HtmlSafeString.new("a < b")],
43
+ [:static, HtmlSafeString.new("a < b")]
44
44
  ]).should.equal [:static, "a < b"]
45
45
  end
46
+
47
+ it 'should support censoring' do
48
+ filter = Temple::Filters::Escapable.new(:escape_code => '(%s).gsub("Temple sucks", "Temple rocks")')
49
+ filter.call([:escape, true,
50
+ [:static, "~~ Temple sucks ~~"]
51
+ ]).should.equal [:static, "~~ Temple rocks ~~"]
52
+ end
46
53
  end
@@ -28,6 +28,6 @@ describe Temple::Filters::MultiFlattener do
28
28
  end
29
29
 
30
30
  it 'should return first element' do
31
- @filter.call([:multi, [:block, 'foo']]).should.equal [:block, 'foo']
31
+ @filter.call([:multi, [:code, 'foo']]).should.equal [:code, 'foo']
32
32
  end
33
33
  end
@@ -15,16 +15,16 @@ describe Temple::Filters::StaticMerger do
15
15
  ]
16
16
  end
17
17
 
18
- it 'should merge serveral statics around block' do
18
+ it 'should merge serveral statics around code' do
19
19
  @filter.call([:multi,
20
20
  [:static, "Hello "],
21
21
  [:static, "World!"],
22
- [:block, "123"],
22
+ [:code, "123"],
23
23
  [:static, "Good night, "],
24
24
  [:static, "everybody"]
25
25
  ]).should.equal [:multi,
26
26
  [:static, "Hello World!"],
27
- [:block, "123"],
27
+ [:code, "123"],
28
28
  [:static, "Good night, everybody"]
29
29
  ]
30
30
  end
data/test/helper.rb CHANGED
@@ -8,6 +8,14 @@ module TestHelper
8
8
  ensure
9
9
  String.send(:undef_method, :html_safe?) if String.method_defined?(:html_safe?)
10
10
  end
11
+
12
+ def grammar_validate(grammar, exp, message)
13
+ lambda { grammar.validate!(exp) }.should.raise(Temple::InvalidExpression).message.should.equal message
14
+ end
15
+
16
+ def erb(src, options = {})
17
+ Temple::ERB::Template.new(options) { src }.render
18
+ end
11
19
  end
12
20
 
13
21
  class Bacon::Context
@@ -17,44 +17,32 @@ describe Temple::HTML::Fast do
17
17
  end
18
18
 
19
19
  it 'should compile html comment' do
20
- @html.call([:html, :comment, 'test']).should.equal [:multi, [:static, "<!--"], "test", [:static, "-->"]]
20
+ @html.call([:html, :comment, [:static, 'test']]).should.equal [:multi, [:static, "<!--"], [:static, "test"], [:static, "-->"]]
21
21
  end
22
22
 
23
23
  it 'should compile autoclosed html tag' do
24
24
  @html.call([:html, :tag,
25
25
  'img', [:attrs],
26
- false, [:multi]
26
+ [:multi, [:newline]]
27
27
  ]).should.equal [:multi,
28
28
  [:static, "<img"],
29
29
  [:attrs],
30
- [:static, " /"],
31
- [:static, ">"], [:multi]]
30
+ [:static, " />"],
31
+ [:multi, [:newline]]]
32
32
  end
33
33
 
34
34
  it 'should compile explicitly closed html tag' do
35
35
  @html.call([:html, :tag,
36
- 'closed', [:attrs],
37
- true, [:multi]
36
+ 'closed', [:attrs]
38
37
  ]).should.equal [:multi,
39
38
  [:static, "<closed"],
40
39
  [:attrs],
41
- [:static, " /"],
42
- [:static, ">"], [:multi]]
43
- end
44
-
45
- it 'should raise error on closed tag with content' do
46
- lambda {
47
- @html.call([:html, :tag,
48
- 'img', [:attrs],
49
- false, [:content]
50
- ])
51
- }.should.raise(RuntimeError).message.should.equal 'Closed tag img has content'
40
+ [:static, " />"]]
52
41
  end
53
42
 
54
43
  it 'should compile html with content' do
55
44
  @html.call([:html, :tag,
56
- 'div', [:attrs],
57
- false, [:content]
45
+ 'div', [:attrs], [:content]
58
46
  ]).should.equal [:multi,
59
47
  [:static, "<div"],
60
48
  [:attrs],
@@ -66,31 +54,24 @@ describe Temple::HTML::Fast do
66
54
  it 'should compile html with static attrs' do
67
55
  @html.call([:html, :tag,
68
56
  'div',
69
- [:html, :staticattrs,
70
- ['id', [:static, 'test']],
71
- ['class', [:dynamic, 'block']]],
72
- false, [:content]
57
+ [:html, :attrs,
58
+ [:html, :attr, 'id', [:static, 'test']],
59
+ [:html, :attr, 'class', [:dynamic, 'block']]],
60
+ [:content]
73
61
  ]).should.equal [:multi,
74
62
  [:static,
75
63
  "<div"],
76
64
  [:multi,
77
65
  [:multi,
78
- [:capture, "_temple_htmlattr1",
66
+ [:capture, "_temple_html_fast1",
79
67
  [:dynamic, "block"]],
80
- [:block, "unless _temple_htmlattr1.empty?"],
81
- [:multi,
82
- [:static, " "],
83
- [:static, "class"],
84
- [:static, "="],
85
- [:static, "'"],
86
- [:dynamic, "_temple_htmlattr1"],
87
- [:static, "'"]],
88
- [:block, "end"]],
68
+ [:if, "!_temple_html_fast1.empty?",
69
+ [:multi,
70
+ [:static, " class='"],
71
+ [:dynamic, "_temple_html_fast1"],
72
+ [:static, "'"]]]],
89
73
  [:multi,
90
- [:static, " "],
91
- [:static, "id"],
92
- [:static, "="],
93
- [:static, "'"],
74
+ [:static, " id='"],
94
75
  [:static, "test"],
95
76
  [:static, "'"]]],
96
77
  [:static, ">"],
@@ -100,20 +81,22 @@ describe Temple::HTML::Fast do
100
81
 
101
82
  it 'should compile html with merged ids' do
102
83
  @html.call([:html, :tag,
103
- 'div', [:html, :staticattrs, ['id', [:static, 'a']], ['id', [:dynamic, 'b']]],
104
- false, [:content]
84
+ 'div',
85
+ [:html, :attrs, [:html, :attr, 'id', [:static, 'a']], [:html, :attr, 'id', [:dynamic, 'b']]],
86
+ [:content]
105
87
  ]).should.equal [:multi,
106
88
  [:static, "<div"],
107
89
  [:multi,
108
90
  [:multi,
109
- [:static, " "],
110
- [:static, "id"],
111
- [:static, "="],
112
- [:static, "'"],
91
+ [:static, " id='"],
113
92
  [:multi,
114
- [:static, 'a'],
115
- [:static, '_'],
116
- [:dynamic, 'b']],
93
+ [:static, "a"],
94
+ [:capture, "_temple_html_fast1",
95
+ [:dynamic, "b"]],
96
+ [:if, "!_temple_html_fast1.empty?",
97
+ [:multi,
98
+ [:static, "_"],
99
+ [:dynamic, "_temple_html_fast1"]]]],
117
100
  [:static, "'"]]],
118
101
  [:static, ">"],
119
102
  [:content],
@@ -122,28 +105,30 @@ describe Temple::HTML::Fast do
122
105
 
123
106
  it 'should compile html with merged classes' do
124
107
  @html.call([:html, :tag,
125
- 'div', [:html, :staticattrs, ['class', [:static, 'a']], ['class', [:dynamic, 'b']]],
126
- false, [:content]
108
+ 'div',
109
+ [:html, :attrs, [:html, :attr, 'class', [:static, 'a']], [:html, :attr, 'class', [:dynamic, 'b']]],
110
+ [:content]
127
111
  ]).should.equal [:multi,
128
112
  [:static, "<div"],
129
113
  [:multi,
130
114
  [:multi,
131
- [:static, " "],
132
- [:static, "class"],
133
- [:static, "="],
134
- [:static, "'"],
115
+ [:static, " class='"],
135
116
  [:multi,
136
- [:static, 'a'],
137
- [:static, ' '],
138
- [:dynamic, 'b']],
117
+ [:static, "a"],
118
+ [:capture, "_temple_html_fast1",
119
+ [:dynamic, "b"]],
120
+ [:if, "!_temple_html_fast1.empty?",
121
+ [:multi,
122
+ [:static, " "],
123
+ [:dynamic, "_temple_html_fast1"]]]],
139
124
  [:static, "'"]]],
140
125
  [:static, ">"],
141
126
  [:content],
142
127
  [:static, "</div>"]]
143
128
  end
144
129
 
145
- it 'should keep blocks intact' do
146
- exp = [:multi, [:block, 'foo']]
130
+ it 'should keep codes intact' do
131
+ exp = [:multi, [:code, 'foo']]
147
132
  @html.call(exp).should.equal exp
148
133
  end
149
134