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.
- 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
|
|