temple 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +2 -1
- data/CHANGES +63 -0
- data/EXPRESSIONS.md +250 -0
- data/README.md +24 -12
- data/lib/temple.rb +34 -18
- data/lib/temple/engine.rb +11 -7
- data/lib/temple/erb/engine.rb +5 -3
- data/lib/temple/erb/parser.rb +5 -2
- data/lib/temple/erb/template.rb +11 -0
- data/lib/temple/erb/trimming.rb +9 -1
- data/lib/temple/filter.rb +2 -0
- data/lib/temple/filters/control_flow.rb +43 -0
- data/lib/temple/filters/dynamic_inliner.rb +29 -32
- data/lib/temple/filters/eraser.rb +22 -0
- data/lib/temple/filters/escapable.rb +39 -0
- data/lib/temple/filters/multi_flattener.rb +4 -1
- data/lib/temple/filters/static_merger.rb +11 -10
- data/lib/temple/filters/validator.rb +15 -0
- data/lib/temple/generators.rb +41 -100
- data/lib/temple/grammar.rb +56 -0
- data/lib/temple/hash.rb +48 -0
- data/lib/temple/html/dispatcher.rb +10 -4
- data/lib/temple/html/fast.rb +50 -38
- data/lib/temple/html/filter.rb +8 -0
- data/lib/temple/html/pretty.rb +25 -14
- data/lib/temple/mixins/dispatcher.rb +103 -0
- data/lib/temple/{mixins.rb → mixins/engine_dsl.rb} +10 -95
- data/lib/temple/mixins/grammar_dsl.rb +166 -0
- data/lib/temple/mixins/options.rb +28 -0
- data/lib/temple/mixins/template.rb +25 -0
- data/lib/temple/templates.rb +2 -0
- data/lib/temple/utils.rb +11 -57
- data/lib/temple/version.rb +1 -1
- data/test/filters/test_control_flow.rb +92 -0
- data/test/filters/test_dynamic_inliner.rb +7 -7
- data/test/filters/test_eraser.rb +55 -0
- data/test/filters/{test_escape_html.rb → test_escapable.rb} +13 -6
- data/test/filters/test_multi_flattener.rb +1 -1
- data/test/filters/test_static_merger.rb +3 -3
- data/test/helper.rb +8 -0
- data/test/html/test_fast.rb +42 -57
- data/test/html/test_pretty.rb +10 -7
- data/test/mixins/test_dispatcher.rb +31 -0
- data/test/mixins/test_grammar_dsl.rb +86 -0
- data/test/test_engine.rb +73 -57
- data/test/test_erb.rb +0 -7
- data/test/test_filter.rb +26 -0
- data/test/test_generator.rb +57 -36
- data/test/test_grammar.rb +52 -0
- data/test/test_hash.rb +39 -0
- data/test/test_utils.rb +11 -38
- metadata +34 -10
- data/lib/temple/filters/debugger.rb +0 -26
- data/lib/temple/filters/escape_html.rb +0 -33
data/lib/temple/version.rb
CHANGED
@@ -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
|
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
|
-
[:
|
37
|
+
[:code, "Oh yeah"],
|
38
38
|
[:dynamic, "@yeah"],
|
39
39
|
[:static, "Once more"]
|
40
40
|
]).should.equal [:multi,
|
41
41
|
[:dynamic, '"Hello #{@world}"'],
|
42
|
-
[:
|
42
|
+
[:code, "Oh yeah"],
|
43
43
|
[:dynamic, '"#{@yeah}Once more"']
|
44
44
|
]
|
45
45
|
end
|
46
46
|
|
47
|
-
it 'should keep
|
48
|
-
exp = [:multi, [:
|
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
|
-
[:
|
93
|
+
[:code, "world"]
|
94
94
|
]).should.equal [:multi,
|
95
95
|
[:static, "Hello \n"],
|
96
96
|
[:newline],
|
97
|
-
[:
|
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::
|
9
|
+
describe Temple::Filters::Escapable do
|
10
10
|
before do
|
11
|
-
@filter = Temple::Filters::
|
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
|
26
|
-
exp = [:multi, [:
|
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::
|
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
|
@@ -15,16 +15,16 @@ describe Temple::Filters::StaticMerger do
|
|
15
15
|
]
|
16
16
|
end
|
17
17
|
|
18
|
-
it 'should merge serveral statics around
|
18
|
+
it 'should merge serveral statics around code' do
|
19
19
|
@filter.call([:multi,
|
20
20
|
[:static, "Hello "],
|
21
21
|
[:static, "World!"],
|
22
|
-
[:
|
22
|
+
[:code, "123"],
|
23
23
|
[:static, "Good night, "],
|
24
24
|
[:static, "everybody"]
|
25
25
|
]).should.equal [:multi,
|
26
26
|
[:static, "Hello World!"],
|
27
|
-
[:
|
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
|
data/test/html/test_fast.rb
CHANGED
@@ -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
|
-
|
26
|
+
[:multi, [:newline]]
|
27
27
|
]).should.equal [:multi,
|
28
28
|
[:static, "<img"],
|
29
29
|
[:attrs],
|
30
|
-
[:static, "
|
31
|
-
[:
|
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, :
|
70
|
-
['id', [:static, 'test']],
|
71
|
-
['class', [:dynamic, 'block']]],
|
72
|
-
|
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, "
|
66
|
+
[:capture, "_temple_html_fast1",
|
79
67
|
[:dynamic, "block"]],
|
80
|
-
[:
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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',
|
104
|
-
|
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,
|
115
|
-
[:
|
116
|
-
|
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',
|
126
|
-
|
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,
|
137
|
-
[:
|
138
|
-
|
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
|
146
|
-
exp = [:multi, [:
|
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
|
|