temple 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -0
- data/LICENSE +20 -0
- data/README.md +246 -0
- data/Rakefile +16 -16
- data/lib/temple.rb +7 -1
- data/lib/temple/core.rb +89 -41
- data/lib/temple/engine.rb +31 -9
- data/lib/temple/engines/erb.rb +93 -0
- data/lib/temple/filters/dynamic_inliner.rb +26 -6
- data/lib/temple/filters/escapable.rb +12 -5
- data/lib/temple/filters/multi_flattener.rb +27 -0
- data/lib/temple/filters/static_merger.rb +5 -1
- data/lib/temple/generator.rb +60 -6
- data/lib/temple/parsers/erb.rb +63 -15
- data/lib/temple/utils.rb +20 -0
- data/temple.gemspec +5 -40
- data/test/engines/hello.erb +4 -0
- data/test/engines/test_erb.rb +495 -0
- data/test/engines/test_erb_m17n.rb +132 -0
- data/test/filters/test_dynamic_inliner.rb +116 -0
- data/test/filters/test_escapable.rb +28 -0
- data/test/filters/test_static_merger.rb +45 -0
- data/test/helper.rb +21 -0
- data/test/test_generator.rb +122 -0
- metadata +33 -25
- data/README +0 -7
- data/VERSION +0 -1
- data/lib/temple/filters/mustache.rb +0 -70
- data/lib/temple/parsers/mustache.rb +0 -68
- data/spec/dynamic_inliner_spec.rb +0 -79
- data/spec/escapable_spec.rb +0 -24
- data/spec/spec_helper.rb +0 -15
- data/spec/static_merger_spec.rb +0 -27
- data/spec/temple_spec.rb +0 -5
@@ -0,0 +1,132 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require File.dirname(__FILE__) + '/../helper'
|
3
|
+
|
4
|
+
if "".respond_to?(:encoding)
|
5
|
+
class TestTempleEnginesERBM17N < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
Temple::Engines::ERB.rock!
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
Temple::Engines::ERB.rock!
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_result_encoding
|
15
|
+
erb = ERB.new("hello")
|
16
|
+
assert_equal __ENCODING__, erb.result.encoding
|
17
|
+
|
18
|
+
erb = ERB.new("こんにちは".encode("EUC-JP"))
|
19
|
+
assert_equal Encoding::EUC_JP, erb.result.encoding
|
20
|
+
|
21
|
+
erb = ERB.new("\xC4\xE3\xBA\xC3".force_encoding("EUC-CN"))
|
22
|
+
assert_equal Encoding::EUC_CN, erb.result.encoding
|
23
|
+
|
24
|
+
erb = ERB.new("γεια σας".encode("ISO-8859-7"))
|
25
|
+
assert_equal Encoding::ISO_8859_7, erb.result.encoding
|
26
|
+
|
27
|
+
assert_raise(ArgumentError) {
|
28
|
+
ERB.new("こんにちは".force_encoding("ISO-2022-JP")) # dummy encoding
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_generate_magic_comment
|
33
|
+
erb = ERB.new("hello")
|
34
|
+
assert_match(/#coding:UTF-8/, erb.src)
|
35
|
+
|
36
|
+
erb = ERB.new("hello".force_encoding("EUC-JP"))
|
37
|
+
assert_match(/#coding:EUC-JP/, erb.src)
|
38
|
+
|
39
|
+
erb = ERB.new("hello".force_encoding("ISO-8859-9"))
|
40
|
+
assert_match(/#coding:ISO-8859-9/, erb.src)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_literal_encoding
|
44
|
+
erb = ERB.new("literal encoding is <%= 'hello'.encoding %>")
|
45
|
+
assert_match(/literal encoding is UTF-8/, erb.result)
|
46
|
+
|
47
|
+
erb = ERB.new("literal encoding is <%= 'こんにちは'.encoding %>".encode("EUC-JP"))
|
48
|
+
assert_match(/literal encoding is EUC-JP/, erb.result)
|
49
|
+
|
50
|
+
erb = ERB.new("literal encoding is <%= '\xC4\xE3\xBA\xC3'.encoding %>".force_encoding("EUC-CN"))
|
51
|
+
assert_match(/literal encoding is GB2312/, erb.result)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test___ENCODING__
|
55
|
+
erb = ERB.new("__ENCODING__ is <%= __ENCODING__ %>")
|
56
|
+
assert_match(/__ENCODING__ is UTF-8/, erb.result)
|
57
|
+
|
58
|
+
erb = ERB.new("__ENCODING__ is <%= __ENCODING__ %>".force_encoding("EUC-JP"))
|
59
|
+
assert_match(/__ENCODING__ is EUC-JP/, erb.result)
|
60
|
+
|
61
|
+
erb = ERB.new("__ENCODING__ is <%= __ENCODING__ %>".force_encoding("Big5"))
|
62
|
+
assert_match(/__ENCODING__ is Big5/, erb.result)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_recognize_magic_comment
|
66
|
+
erb = ERB.new(<<-EOS.encode("EUC-KR"))
|
67
|
+
<%# -*- coding: EUC-KR -*- %>
|
68
|
+
안녕하세요
|
69
|
+
EOS
|
70
|
+
assert_match(/#coding:EUC-KR/, erb.src)
|
71
|
+
assert_equal Encoding::EUC_KR, erb.result.encoding
|
72
|
+
|
73
|
+
erb = ERB.new(<<-EOS.encode("EUC-KR").force_encoding("ASCII-8BIT"))
|
74
|
+
<%#-*- coding: EUC-KR -*-%>
|
75
|
+
안녕하세요
|
76
|
+
EOS
|
77
|
+
assert_match(/#coding:EUC-KR/, erb.src)
|
78
|
+
assert_equal Encoding::EUC_KR, erb.result.encoding
|
79
|
+
|
80
|
+
erb = ERB.new(<<-EOS.encode("EUC-KR").force_encoding("ASCII-8BIT"))
|
81
|
+
<%# vim: tabsize=8 encoding=EUC-KR shiftwidth=2 expandtab %>
|
82
|
+
안녕하세요
|
83
|
+
EOS
|
84
|
+
assert_match(/#coding:EUC-KR/, erb.src)
|
85
|
+
assert_equal Encoding::EUC_KR, erb.result.encoding
|
86
|
+
|
87
|
+
erb = ERB.new(<<-EOS.encode("EUC-KR").force_encoding("ASCII-8BIT"))
|
88
|
+
<%#coding:EUC-KR %>
|
89
|
+
안녕하세요
|
90
|
+
EOS
|
91
|
+
assert_match(/#coding:EUC-KR/, erb.src)
|
92
|
+
assert_equal Encoding::EUC_KR, erb.result.encoding
|
93
|
+
|
94
|
+
erb = ERB.new(<<-EOS.encode("EUC-KR").force_encoding("EUC-JP"))
|
95
|
+
<%#coding:EUC-KR %>
|
96
|
+
안녕하세요
|
97
|
+
EOS
|
98
|
+
assert_match(/#coding:EUC-KR/, erb.src)
|
99
|
+
assert_equal Encoding::EUC_KR, erb.result.encoding
|
100
|
+
end
|
101
|
+
|
102
|
+
module M; end
|
103
|
+
def test_method_with_encoding
|
104
|
+
obj = Object.new
|
105
|
+
obj.extend(M)
|
106
|
+
|
107
|
+
erb = ERB.new(<<-EOS.encode("EUC-JP").force_encoding("ASCII-8BIT"))
|
108
|
+
<%#coding:EUC-JP %>
|
109
|
+
literal encoding is <%= 'こんにちは'.encoding %>
|
110
|
+
__ENCODING__ is <%= __ENCODING__ %>
|
111
|
+
EOS
|
112
|
+
erb.def_method(M, :m_from_magic_comment)
|
113
|
+
|
114
|
+
result = obj.m_from_magic_comment
|
115
|
+
assert_equal Encoding::EUC_JP, result.encoding
|
116
|
+
assert_match(/literal encoding is EUC-JP/, result)
|
117
|
+
assert_match(/__ENCODING__ is EUC-JP/, result)
|
118
|
+
|
119
|
+
erb = ERB.new(<<-EOS.encode("EUC-KR"))
|
120
|
+
literal encoding is <%= '안녕하세요'.encoding %>
|
121
|
+
__ENCODING__ is <%= __ENCODING__ %>
|
122
|
+
EOS
|
123
|
+
erb.def_method(M, :m_from_eval_encoding)
|
124
|
+
result = obj.m_from_eval_encoding
|
125
|
+
assert_equal Encoding::EUC_KR, result.encoding
|
126
|
+
assert_match(/literal encoding is EUC-KR/, result)
|
127
|
+
assert_match(/__ENCODING__ is EUC-KR/, result)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# vim:fileencoding=UTF-8
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../helper'
|
2
|
+
|
3
|
+
class TestTempleFiltersDynamicInliner < TestFilter(:DynamicInliner)
|
4
|
+
def test_several_statics_into_dynamic
|
5
|
+
exp = @filter.compile([:multi,
|
6
|
+
[:static, "Hello "],
|
7
|
+
[:static, "World\n "],
|
8
|
+
[:static, "Have a nice day"]
|
9
|
+
])
|
10
|
+
|
11
|
+
assert_equal([:multi,
|
12
|
+
[:dynamic, "\"Hello World\n Have a nice day\""]
|
13
|
+
], exp)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_several_dynamics_into_dynamic
|
17
|
+
exp = @filter.compile([:multi,
|
18
|
+
[:dynamic, "@hello"],
|
19
|
+
[:dynamic, "@world"],
|
20
|
+
[:dynamic, "@yeah"]
|
21
|
+
])
|
22
|
+
|
23
|
+
assert_equal([:multi,
|
24
|
+
[:dynamic, '"#{@hello}#{@world}#{@yeah}"']
|
25
|
+
], exp)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_static_and_dynamic_into_dynamic
|
29
|
+
exp = @filter.compile([:multi,
|
30
|
+
[:static, "Hello"],
|
31
|
+
[:dynamic, "@world"],
|
32
|
+
[:dynamic, "@yeah"],
|
33
|
+
[:static, "Nice"]
|
34
|
+
])
|
35
|
+
|
36
|
+
assert_equal([:multi,
|
37
|
+
[:dynamic, '"Hello#{@world}#{@yeah}Nice"']
|
38
|
+
], exp)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_static_and_dynamic_around_blocks
|
42
|
+
exp = @filter.compile([:multi,
|
43
|
+
[:static, "Hello "],
|
44
|
+
[:dynamic, "@world"],
|
45
|
+
[:block, "Oh yeah"],
|
46
|
+
[:dynamic, "@yeah"],
|
47
|
+
[:static, "Once more"]
|
48
|
+
])
|
49
|
+
|
50
|
+
assert_equal([:multi,
|
51
|
+
[:dynamic, '"Hello #{@world}"'],
|
52
|
+
[:block, "Oh yeah"],
|
53
|
+
[:dynamic, '"#{@yeah}Once more"']
|
54
|
+
], exp)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_keep_blocks_intact
|
58
|
+
exp = [:multi, [:block, 'foo']]
|
59
|
+
assert_equal(exp, @filter.compile(exp))
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_keep_single_static_intact
|
63
|
+
exp = [:multi, [:static, 'foo']]
|
64
|
+
assert_equal(exp, @filter.compile(exp))
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_keep_single_dynamic_intact
|
68
|
+
exp = [:multi, [:dynamic, 'foo']]
|
69
|
+
assert_equal(exp, @filter.compile(exp))
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_inline_inside_multi
|
73
|
+
exp = @filter.compile([:multi,
|
74
|
+
[:static, "Hello "],
|
75
|
+
[:dynamic, "@world"],
|
76
|
+
[:multi,
|
77
|
+
[:static, "Hello "],
|
78
|
+
[:dynamic, "@world"]],
|
79
|
+
[:static, "Hello "],
|
80
|
+
[:dynamic, "@world"]
|
81
|
+
])
|
82
|
+
|
83
|
+
assert_equal([:multi,
|
84
|
+
[:dynamic, '"Hello #{@world}"'],
|
85
|
+
[:multi, [:dynamic, '"Hello #{@world}"']],
|
86
|
+
[:dynamic, '"Hello #{@world}"']
|
87
|
+
], exp)
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_merge_across_newlines
|
91
|
+
exp = @filter.compile([:multi,
|
92
|
+
[:static, "Hello \n"],
|
93
|
+
[:newline],
|
94
|
+
[:dynamic, "@world"],
|
95
|
+
[:newline]
|
96
|
+
])
|
97
|
+
|
98
|
+
assert_equal([:multi,
|
99
|
+
[:dynamic, ["\"Hello \n\"", '"#{@world}"', '""'].join("\\\n")],
|
100
|
+
], exp)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_static_followed_by_newline
|
104
|
+
exp = @filter.compile([:multi,
|
105
|
+
[:static, "Hello \n"],
|
106
|
+
[:newline],
|
107
|
+
[:block, "world"]
|
108
|
+
])
|
109
|
+
|
110
|
+
assert_equal([:multi,
|
111
|
+
[:static, "Hello \n"],
|
112
|
+
[:newline],
|
113
|
+
[:block, "world"]
|
114
|
+
], exp)
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../helper'
|
2
|
+
|
3
|
+
class TestTempleFiltersEscapable < TestFilter(:Escapable)
|
4
|
+
def test_escape
|
5
|
+
exp = @filter.compile([:multi,
|
6
|
+
[:escape, [:dynamic, "@hello"]],
|
7
|
+
[:escape, [:block, "@world"]]
|
8
|
+
])
|
9
|
+
|
10
|
+
assert_equal([:multi,
|
11
|
+
[:dynamic, "CGI.escapeHTML((@hello).to_s)"],
|
12
|
+
[:block, "CGI.escapeHTML((@world).to_s)"]
|
13
|
+
], exp)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_escape_static_content
|
17
|
+
exp = @filter.compile([:multi,
|
18
|
+
[:escape, [:static, "<hello>"]],
|
19
|
+
[:escape, [:block, "@world"]]
|
20
|
+
])
|
21
|
+
|
22
|
+
assert_equal([:multi,
|
23
|
+
[:static, "<hello>"],
|
24
|
+
[:block, "CGI.escapeHTML((@world).to_s)"]
|
25
|
+
], exp)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../helper'
|
2
|
+
|
3
|
+
class TestTempleFiltersStaticMerger < TestFilter(:StaticMerger)
|
4
|
+
def test_several_statics
|
5
|
+
exp = @filter.compile([:multi,
|
6
|
+
[:static, "Hello "],
|
7
|
+
[:static, "World, "],
|
8
|
+
[:static, "Good night"]
|
9
|
+
])
|
10
|
+
|
11
|
+
assert_equal([:multi,
|
12
|
+
[:static, "Hello World, Good night"]
|
13
|
+
], exp)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_several_statics_around_block
|
17
|
+
exp = @filter.compile([:multi,
|
18
|
+
[:static, "Hello "],
|
19
|
+
[:static, "World!"],
|
20
|
+
[:block, "123"],
|
21
|
+
[:static, "Good night, "],
|
22
|
+
[:static, "everybody"]
|
23
|
+
])
|
24
|
+
|
25
|
+
assert_equal([:multi,
|
26
|
+
[:static, "Hello World!"],
|
27
|
+
[:block, "123"],
|
28
|
+
[:static, "Good night, everybody"]
|
29
|
+
], exp)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_several_statics_across_newlines
|
33
|
+
exp = @filter.compile([:multi,
|
34
|
+
[:static, "Hello "],
|
35
|
+
[:static, "World, "],
|
36
|
+
[:newline],
|
37
|
+
[:static, "Good night"]
|
38
|
+
])
|
39
|
+
|
40
|
+
assert_equal([:multi,
|
41
|
+
[:static, "Hello World, Good night"],
|
42
|
+
[:newline]
|
43
|
+
], exp)
|
44
|
+
end
|
45
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'temple'
|
4
|
+
|
5
|
+
def TestFilter(klass)
|
6
|
+
klass = Temple::Filters.const_get(klass.to_s) unless klass.is_a?(Class)
|
7
|
+
|
8
|
+
Class.new(Test::Unit::TestCase) do
|
9
|
+
define_method(:setup) do
|
10
|
+
@filter = klass.new
|
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
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
class TestTempleGenerator < Test::Unit::TestCase
|
4
|
+
class Simple < Temple::Generator
|
5
|
+
def preamble
|
6
|
+
buffer " = BUFFER"
|
7
|
+
end
|
8
|
+
|
9
|
+
def postamble
|
10
|
+
buffer
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_static(s)
|
14
|
+
"S:#{s}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_dynamic(s)
|
18
|
+
"D:#{s}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_block(s)
|
22
|
+
"B:#{s}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_simple_exp
|
27
|
+
simple = Simple.new
|
28
|
+
|
29
|
+
assert_equal("S:test", simple.compile([:static, "test"]))
|
30
|
+
assert_equal("D:test", simple.compile([:dynamic, "test"]))
|
31
|
+
assert_equal("B:test", simple.compile([:block, "test"]))
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_multi
|
35
|
+
simple = Simple.new(:buffer => "VAR")
|
36
|
+
str = simple.compile([:multi,
|
37
|
+
[:static, "static"],
|
38
|
+
[:dynamic, "dynamic"],
|
39
|
+
[:block, "block"]
|
40
|
+
])
|
41
|
+
|
42
|
+
assert_match(/VAR = BUFFER/, str)
|
43
|
+
assert_match(/VAR << \(S:static\)/, str)
|
44
|
+
assert_match(/VAR << \(D:dynamic\)/, str)
|
45
|
+
assert_match(/ B:block /, str)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_capture
|
49
|
+
simple = Simple.new(:buffer => "VAR")
|
50
|
+
str = simple.compile([:capture, "foo", [:static, "test"]])
|
51
|
+
|
52
|
+
assert_match(/foo = S:test/, str)
|
53
|
+
assert_match(/VAR\Z/, str)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_capture_with_multi
|
57
|
+
simple = Simple.new(:buffer => "VAR")
|
58
|
+
str = simple.compile([:multi,
|
59
|
+
[:static, "before"],
|
60
|
+
|
61
|
+
[:capture, "foo", [:multi,
|
62
|
+
[:static, "static"],
|
63
|
+
[:dynamic, "dynamic"],
|
64
|
+
[:block, "block"]]],
|
65
|
+
|
66
|
+
[:static, "after"]
|
67
|
+
])
|
68
|
+
|
69
|
+
assert_match(/VAR << \(S:before\)/, str)
|
70
|
+
assert_match(/foo = BUFFER/, str)
|
71
|
+
assert_match(/foo << \(S:static\)/, str)
|
72
|
+
assert_match(/foo << \(D:dynamic\)/, str)
|
73
|
+
assert_match(/ B:block /, str)
|
74
|
+
assert_match(/VAR << \(S:after\)/, str)
|
75
|
+
assert_match(/VAR\Z/, str)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_newlines
|
79
|
+
simple = Simple.new(:buffer => "VAR")
|
80
|
+
str = simple.compile([:multi,
|
81
|
+
[:static, "static"],
|
82
|
+
[:newline],
|
83
|
+
[:dynamic, "dynamic"],
|
84
|
+
[:newline],
|
85
|
+
[:block, "block"]
|
86
|
+
])
|
87
|
+
|
88
|
+
lines = str.split("\n")
|
89
|
+
assert_match(/VAR << \(S:static\)/, lines[0])
|
90
|
+
assert_match(/VAR << \(D:dynamic\)/, lines[1])
|
91
|
+
assert_match(/ B:block /, lines[2])
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_to_ruby
|
95
|
+
simple = Simple.new
|
96
|
+
|
97
|
+
{
|
98
|
+
"Hello" => 'Hello',
|
99
|
+
"Hello\r\nWorld" => 'Hello\nWorld',
|
100
|
+
"Hello\nWorld" => %w|Hello World|,
|
101
|
+
"Hello\n\r\n\nWorld" => %w|Hello \n World|,
|
102
|
+
"\r\n\nHelloWorld\n" => %w|\n HelloWorld .|,
|
103
|
+
"\nHelloWorld\r\n" => %w|. HelloWorld\n|,
|
104
|
+
}.
|
105
|
+
each do |actual, expected|
|
106
|
+
if expected.is_a?(Array)
|
107
|
+
expected = expected.map do |x|
|
108
|
+
if x == "."
|
109
|
+
# Use the dot so we can easily match a newline
|
110
|
+
# at the end or the beginning.
|
111
|
+
""
|
112
|
+
else
|
113
|
+
x
|
114
|
+
end
|
115
|
+
end.join("\n")
|
116
|
+
end
|
117
|
+
|
118
|
+
expected = '"' + expected + '"'
|
119
|
+
assert_equal(expected, simple.to_ruby(actual))
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|