temple 0.1.3 → 0.1.4
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/.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
|