temple 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/README.md +17 -18
- data/Rakefile +17 -12
- data/lib/temple.rb +19 -14
- data/lib/temple/engine.rb +13 -18
- data/lib/temple/erb/engine.rb +13 -0
- data/lib/temple/erb/parser.rb +38 -0
- data/lib/temple/erb/template.rb +7 -0
- data/lib/temple/erb/trimming.rb +33 -0
- data/lib/temple/filter.rb +7 -0
- data/lib/temple/filters/debugger.rb +15 -0
- data/lib/temple/filters/dynamic_inliner.rb +11 -19
- data/lib/temple/filters/escape_html.rb +27 -0
- data/lib/temple/filters/multi_flattener.rb +5 -13
- data/lib/temple/filters/static_merger.rb +6 -14
- data/lib/temple/{core.rb → generators.rb} +78 -37
- data/lib/temple/html/fast.rb +79 -127
- data/lib/temple/html/pretty.rb +75 -0
- data/lib/temple/mixins.rb +66 -0
- data/lib/temple/template.rb +35 -0
- data/lib/temple/utils.rb +51 -15
- data/lib/temple/version.rb +3 -0
- data/temple.gemspec +8 -13
- data/test/filters/test_dynamic_inliner.rb +42 -58
- data/test/filters/test_escape_html.rb +32 -0
- data/test/filters/test_multi_flattener.rb +33 -0
- data/test/filters/test_static_merger.rb +21 -23
- data/test/helper.rb +11 -17
- data/test/html/test_fast.rb +153 -0
- data/test/test_erb.rb +68 -0
- data/test/test_generator.rb +69 -76
- data/test/test_utils.rb +28 -0
- metadata +45 -16
- data/lib/temple/engines/erb.rb +0 -93
- data/lib/temple/generator.rb +0 -76
- data/lib/temple/parsers/erb.rb +0 -83
- data/test/engines/hello.erb +0 -4
- data/test/engines/test_erb.rb +0 -495
- data/test/engines/test_erb_m17n.rb +0 -132
- data/test/test_temple.rb +0 -28
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Temple::Filters::EscapeHTML do
|
4
|
+
before do
|
5
|
+
@filter = Temple::Filters::EscapeHTML.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should handle escape expressions' do
|
9
|
+
@filter.compile([:multi,
|
10
|
+
[:escape, :static, "a < b"],
|
11
|
+
[:escape, :dynamic, "ruby_method"]
|
12
|
+
]).should.equal [:multi,
|
13
|
+
[:static, "a < b"],
|
14
|
+
[:dynamic, "Temple::Utils.escape_html((ruby_method))"],
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should keep blocks intact' do
|
19
|
+
exp = [:multi, [:block, 'foo']]
|
20
|
+
@filter.compile(exp).should.equal exp
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should keep statics intact' do
|
24
|
+
exp = [:multi, [:static, '<']]
|
25
|
+
@filter.compile(exp).should.equal exp
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should keep dynamic intact' do
|
29
|
+
exp = [:multi, [:dynamic, 'foo']]
|
30
|
+
@filter.compile(exp).should.equal exp
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Temple::Filters::MultiFlattener do
|
4
|
+
before do
|
5
|
+
@filter = Temple::Filters::MultiFlattener.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should flatten nested multi expressions' do
|
9
|
+
@filter.compile([:multi,
|
10
|
+
[:static, "a"],
|
11
|
+
[:multi,
|
12
|
+
[:dynamic, "aa"],
|
13
|
+
[:multi,
|
14
|
+
[:static, "aaa"],
|
15
|
+
[:static, "aab"],
|
16
|
+
],
|
17
|
+
[:dynamic, "ab"],
|
18
|
+
],
|
19
|
+
[:static, "b"],
|
20
|
+
]).should.equal [:multi,
|
21
|
+
[:static, "a"],
|
22
|
+
[:dynamic, "aa"],
|
23
|
+
[:static, "aaa"],
|
24
|
+
[:static, "aab"],
|
25
|
+
[:dynamic, "ab"],
|
26
|
+
[:static, "b"],
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should return first element' do
|
31
|
+
@filter.compile([:multi, [:block, 'foo']]).should.equal [:block, 'foo']
|
32
|
+
end
|
33
|
+
end
|
@@ -1,45 +1,43 @@
|
|
1
|
-
require
|
1
|
+
require 'helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
describe Temple::Filters::StaticMerger do
|
4
|
+
before do
|
5
|
+
@filter = Temple::Filters::StaticMerger.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should merge serveral statics' do
|
9
|
+
@filter.compile([:multi,
|
6
10
|
[:static, "Hello "],
|
7
11
|
[:static, "World, "],
|
8
12
|
[:static, "Good night"]
|
9
|
-
])
|
10
|
-
|
11
|
-
assert_equal([:multi,
|
13
|
+
]).should.equal [:multi,
|
12
14
|
[:static, "Hello World, Good night"]
|
13
|
-
]
|
15
|
+
]
|
14
16
|
end
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
|
18
|
+
it 'should merge serveral statics around block' do
|
19
|
+
@filter.compile([:multi,
|
18
20
|
[:static, "Hello "],
|
19
21
|
[:static, "World!"],
|
20
22
|
[:block, "123"],
|
21
23
|
[:static, "Good night, "],
|
22
24
|
[:static, "everybody"]
|
23
|
-
])
|
24
|
-
|
25
|
-
assert_equal([:multi,
|
25
|
+
]).should.equal [:multi,
|
26
26
|
[:static, "Hello World!"],
|
27
27
|
[:block, "123"],
|
28
28
|
[:static, "Good night, everybody"]
|
29
|
-
]
|
29
|
+
]
|
30
30
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
|
32
|
+
it 'should merge serveral statics across newlines' do
|
33
|
+
@filter.compile([:multi,
|
34
34
|
[:static, "Hello "],
|
35
35
|
[:static, "World, "],
|
36
36
|
[:newline],
|
37
37
|
[:static, "Good night"]
|
38
|
-
])
|
39
|
-
|
40
|
-
assert_equal([:multi,
|
38
|
+
]).should.equal [:multi,
|
41
39
|
[:static, "Hello World, Good night"],
|
42
40
|
[:newline]
|
43
|
-
]
|
41
|
+
]
|
44
42
|
end
|
45
|
-
end
|
43
|
+
end
|
data/test/helper.rb
CHANGED
@@ -1,21 +1,15 @@
|
|
1
|
-
|
2
|
-
require 'test/unit'
|
1
|
+
require 'bacon'
|
3
2
|
require 'temple'
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
# Dummy test so Turn doesn't complain
|
14
|
-
def test_void
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.name
|
18
|
-
super || "<anonymous>"
|
19
|
-
end
|
4
|
+
module TestHelper
|
5
|
+
def with_html_safe(flag)
|
6
|
+
String.send(:define_method, :html_safe?) { flag }
|
7
|
+
yield
|
8
|
+
ensure
|
9
|
+
String.send(:undef_method, :html_safe?) if String.method_defined?(:html_safe?)
|
20
10
|
end
|
21
11
|
end
|
12
|
+
|
13
|
+
class Bacon::Context
|
14
|
+
include TestHelper
|
15
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Temple::HTML::Fast do
|
4
|
+
before do
|
5
|
+
@html = Temple::HTML::Fast.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should compile html doctype' do
|
9
|
+
@html.compile([:multi, [:html, :doctype, '5']]).should.equal [:multi, [:static, '<!DOCTYPE html>']]
|
10
|
+
@html.compile([:multi, [:html, :doctype, '1.1']]).should.equal [:multi,
|
11
|
+
[:static, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">']]
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should compile xml encoding' do
|
15
|
+
@html.compile([:html, :doctype, 'xml latin1']).should.equal [:static, "<?xml version='1.0' encoding='latin1' ?>"]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should compile html comment' do
|
19
|
+
@html.compile([:html, :comment, 'test']).should.equal [:multi, [:static, "<!--"], "test", [:static, "-->"]]
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should compile autoclosed html tag' do
|
23
|
+
@html.compile([:html, :tag,
|
24
|
+
'img', [:attrs],
|
25
|
+
false, [:multi]
|
26
|
+
]).should.equal [:multi,
|
27
|
+
[:static, "<img"],
|
28
|
+
[:attrs],
|
29
|
+
[:static, " /"],
|
30
|
+
[:static, ">"], [:multi]]
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should compile explicitly closed html tag' do
|
34
|
+
@html.compile([:html, :tag,
|
35
|
+
'closed', [:attrs],
|
36
|
+
true, [:multi]
|
37
|
+
]).should.equal [:multi,
|
38
|
+
[:static, "<closed"],
|
39
|
+
[:attrs],
|
40
|
+
[:static, " /"],
|
41
|
+
[:static, ">"], [:multi]]
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should raise error on closed tag with content' do
|
45
|
+
lambda {
|
46
|
+
@html.compile([:html, :tag,
|
47
|
+
'img', [:attrs],
|
48
|
+
false, [:content]
|
49
|
+
])
|
50
|
+
}.should.raise(RuntimeError).message.should.equal 'Closed tag img has content'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should compile html with content' do
|
54
|
+
@html.compile([:html, :tag,
|
55
|
+
'div', [:attrs],
|
56
|
+
false, [:content]
|
57
|
+
]).should.equal [:multi,
|
58
|
+
[:static, "<div"],
|
59
|
+
[:attrs],
|
60
|
+
[:static, ">"],
|
61
|
+
[:content],
|
62
|
+
[:static, "</div>"]]
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should compile html with static attrs' do
|
66
|
+
@html.compile([:html, :tag,
|
67
|
+
'div',
|
68
|
+
[:html, :staticattrs,
|
69
|
+
['id', [:static, 'test']],
|
70
|
+
['class', [:dynamic, 'block']]],
|
71
|
+
false, [:content]
|
72
|
+
]).should.equal [:multi,
|
73
|
+
[:static,
|
74
|
+
"<div"],
|
75
|
+
[:multi,
|
76
|
+
[:multi,
|
77
|
+
[:static, " "],
|
78
|
+
[:static, "class"],
|
79
|
+
[:static, "="],
|
80
|
+
[:static, "'"],
|
81
|
+
[:dynamic, "block"],
|
82
|
+
[:static, "'"]],
|
83
|
+
[:multi,
|
84
|
+
[:static, " "],
|
85
|
+
[:static, "id"],
|
86
|
+
[:static, "="],
|
87
|
+
[:static, "'"],
|
88
|
+
[:static, "test"],
|
89
|
+
[:static, "'"]]],
|
90
|
+
[:static, ">"],
|
91
|
+
[:content],
|
92
|
+
[:static, "</div>"]]
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should compile html with merged ids' do
|
96
|
+
@html.compile([:html, :tag,
|
97
|
+
'div', [:html, :staticattrs, ['id', [:static, 'a']], ['id', [:dynamic, 'b']]],
|
98
|
+
false, [:content]
|
99
|
+
]).should.equal [:multi,
|
100
|
+
[:static, "<div"],
|
101
|
+
[:multi,
|
102
|
+
[:multi,
|
103
|
+
[:static, " "],
|
104
|
+
[:static, "id"],
|
105
|
+
[:static, "="],
|
106
|
+
[:static, "'"],
|
107
|
+
[:multi,
|
108
|
+
[:static, 'a'],
|
109
|
+
[:static, '_'],
|
110
|
+
[:dynamic, 'b']],
|
111
|
+
[:static, "'"]]],
|
112
|
+
[:static, ">"],
|
113
|
+
[:content],
|
114
|
+
[:static, "</div>"]]
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should compile html with merged classes' do
|
118
|
+
@html.compile([:html, :tag,
|
119
|
+
'div', [:html, :staticattrs, ['class', [:static, 'a']], ['class', [:dynamic, 'b']]],
|
120
|
+
false, [:content]
|
121
|
+
]).should.equal [:multi,
|
122
|
+
[:static, "<div"],
|
123
|
+
[:multi,
|
124
|
+
[:multi,
|
125
|
+
[:static, " "],
|
126
|
+
[:static, "class"],
|
127
|
+
[:static, "="],
|
128
|
+
[:static, "'"],
|
129
|
+
[:multi,
|
130
|
+
[:static, 'a'],
|
131
|
+
[:static, ' '],
|
132
|
+
[:dynamic, 'b']],
|
133
|
+
[:static, "'"]]],
|
134
|
+
[:static, ">"],
|
135
|
+
[:content],
|
136
|
+
[:static, "</div>"]]
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should keep blocks intact' do
|
140
|
+
exp = [:multi, [:block, 'foo']]
|
141
|
+
@html.compile(exp).should.equal exp
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should keep statics intact' do
|
145
|
+
exp = [:multi, [:static, '<']]
|
146
|
+
@html.compile(exp).should.equal exp
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should keep dynamic intact' do
|
150
|
+
exp = [:multi, [:dynamic, 'foo']]
|
151
|
+
@html.compile(exp).should.equal exp
|
152
|
+
end
|
153
|
+
end
|
data/test/test_erb.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
class Bacon::Context
|
5
|
+
def erb(src, options = {})
|
6
|
+
Temple::ERB::Template.new(options) { src }.render
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Temple::ERB::Template do
|
11
|
+
|
12
|
+
it 'should compile erb' do
|
13
|
+
src = %q{
|
14
|
+
%% hi
|
15
|
+
= hello
|
16
|
+
<% 3.times do |n| %>
|
17
|
+
* <%= n %>
|
18
|
+
<% end %>
|
19
|
+
}
|
20
|
+
|
21
|
+
erb(src).should.equal ERB.new(src).result
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should recognize comments' do
|
25
|
+
src = %q{
|
26
|
+
hello
|
27
|
+
<%# comment -- ignored -- useful in testing %>
|
28
|
+
world}
|
29
|
+
|
30
|
+
erb(src).should.equal ERB.new(src).result
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should recognize <%% and %%>' do
|
34
|
+
src = %q{
|
35
|
+
<%%
|
36
|
+
<% if true %>
|
37
|
+
%%>
|
38
|
+
<% end %>
|
39
|
+
}
|
40
|
+
|
41
|
+
erb(src).should.equal "\n<%\n\n %>\n\n" #ERB.new(src).result
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should escape automatically' do
|
45
|
+
src = '<%= "<" %>'
|
46
|
+
ans = '<'
|
47
|
+
erb(src, :auto_escape => true).should.equal ans
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should support == to disable automatic escape' do
|
51
|
+
src = '<%== "<" %>'
|
52
|
+
ans = '<'
|
53
|
+
erb(src, :auto_escape => true).should.equal ans
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should support trim mode' do
|
57
|
+
src = %q{
|
58
|
+
%% hi
|
59
|
+
= hello
|
60
|
+
<% 3.times do |n| %>
|
61
|
+
* <%= n %>
|
62
|
+
<% end %>
|
63
|
+
}
|
64
|
+
|
65
|
+
erb(src, :trim_mode => '>').should.equal ERB.new(src, nil, '>').result
|
66
|
+
erb(src, :trim_mode => '<>').should.equal ERB.new(src, nil, '<>').result
|
67
|
+
end
|
68
|
+
end
|
data/test/test_generator.rb
CHANGED
@@ -1,101 +1,94 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
class
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
"B:#{s}"
|
23
|
-
end
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class SimpleGenerator < Temple::Generator
|
4
|
+
def preamble
|
5
|
+
"#{buffer} = BUFFER"
|
6
|
+
end
|
7
|
+
|
8
|
+
def postamble
|
9
|
+
buffer
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_static(s)
|
13
|
+
concat "S:#{s}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_dynamic(s)
|
17
|
+
concat "D:#{s}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_block(s)
|
21
|
+
"B:#{s}"
|
24
22
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
end
|
24
|
+
|
25
|
+
describe Temple::Generator do
|
26
|
+
it 'should compile simple expressions' do
|
27
|
+
gen = SimpleGenerator.new
|
28
|
+
|
29
|
+
gen.compile([:static, "test"]).should.match(/ << \(S:test\)/)
|
30
|
+
gen.compile([:dynamic, "test"]).should.match(/ << \(D:test\)/)
|
31
|
+
gen.compile([:block, "test"]).should.match(/B:test/)
|
32
32
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
str =
|
33
|
+
|
34
|
+
it 'should compile multi expression' do
|
35
|
+
gen = SimpleGenerator.new(:buffer => "VAR")
|
36
|
+
str = gen.compile([:multi,
|
37
37
|
[:static, "static"],
|
38
38
|
[:dynamic, "dynamic"],
|
39
39
|
[:block, "block"]
|
40
40
|
])
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
|
42
|
+
str.should.match(/VAR = BUFFER/)
|
43
|
+
str.should.match(/VAR << \(S:static\)/)
|
44
|
+
str.should.match(/VAR << \(D:dynamic\)/)
|
45
|
+
str.should.match(/ B:block /)
|
46
46
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
str =
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
47
|
+
|
48
|
+
it 'should compile capture' do
|
49
|
+
gen = SimpleGenerator.new(:buffer => "VAR", :capture_generator => SimpleGenerator)
|
50
|
+
str = gen.compile([:capture, "foo", [:static, "test"]])
|
51
|
+
|
52
|
+
str.should.match(/foo = BUFFER/)
|
53
|
+
str.should.match(/foo << \(S:test\)/)
|
54
|
+
str.should.match(/VAR\Z/)
|
55
55
|
end
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
str =
|
56
|
+
|
57
|
+
it 'should compile capture with multi' do
|
58
|
+
gen = SimpleGenerator.new(:buffer => "VAR", :capture_generator => SimpleGenerator)
|
59
|
+
str = gen.compile([:multi,
|
60
60
|
[:static, "before"],
|
61
|
-
|
61
|
+
|
62
62
|
[:capture, "foo", [:multi,
|
63
63
|
[:static, "static"],
|
64
64
|
[:dynamic, "dynamic"],
|
65
65
|
[:block, "block"]]],
|
66
|
-
|
66
|
+
|
67
67
|
[:static, "after"]
|
68
68
|
])
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
69
|
+
|
70
|
+
str.should.match(/VAR << \(S:before\)/)
|
71
|
+
str.should.match( /foo = BUFFER/)
|
72
|
+
str.should.match( /foo << \(S:static\)/)
|
73
|
+
str.should.match( /foo << \(D:dynamic\)/)
|
74
|
+
str.should.match( / B:block /)
|
75
|
+
str.should.match(/VAR << \(S:after\)/)
|
76
|
+
str.should.match(/VAR\Z/)
|
77
77
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
str =
|
78
|
+
|
79
|
+
it 'should compile newlines' do
|
80
|
+
gen = SimpleGenerator.new(:buffer => "VAR")
|
81
|
+
str = gen.compile([:multi,
|
82
82
|
[:static, "static"],
|
83
83
|
[:newline],
|
84
84
|
[:dynamic, "dynamic"],
|
85
85
|
[:newline],
|
86
86
|
[:block, "block"]
|
87
87
|
])
|
88
|
-
|
89
|
-
lines = str.split("\n")
|
90
|
-
assert_match(/VAR << \(S:static\)/, lines[0])
|
91
|
-
assert_match(/VAR << \(D:dynamic\)/, lines[1])
|
92
|
-
assert_match(/ B:block /, lines[2])
|
93
|
-
end
|
94
|
-
|
95
|
-
def test_to_ruby
|
96
|
-
simple = Simple.new
|
97
88
|
|
98
|
-
|
99
|
-
|
89
|
+
lines = str.split("\n")
|
90
|
+
lines[0].should.match(/VAR << \(S:static\)/)
|
91
|
+
lines[1].should.match(/VAR << \(D:dynamic\)/)
|
92
|
+
lines[2].should.match(/ B:block /)
|
100
93
|
end
|
101
94
|
end
|