html-template 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +0 -1
- data/README.md +23 -24
- data/lib/html/template/version.rb +1 -1
- data/lib/html/template.rb +137 -35
- data/test/helper.rb +1 -0
- data/test/templates/planet/basic/index.html.tmpl +3 -3
- data/test/templates/planet/fancy/index.html.tmpl +2 -2
- data/test/test_merge.rb +52 -13
- metadata +2 -3
- data/test/templates/planet/README.md +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99e549ccfeeab65c5a307442d82910d2c69fa03a
|
4
|
+
data.tar.gz: c7f0bf3e17141ea27250e99ea184c61a8f85fa96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3a4b8328958f8934858ec3d62f906e40ce0ebc74638101bca301656319c20560ae6c748892b6ee6f0ceaa6281d063a64d256628955ab49b951ecd11a0474ddd
|
7
|
+
data.tar.gz: b225712c8e413f29d4f9e76fc35c8fa38106e32cb062c77f6695e544980c087d2f733b3ebe55873bdcf98809f22f9741e9075165ef25e2e1354679a481e63d18
|
data/Manifest.txt
CHANGED
@@ -8,7 +8,6 @@ test/helper.rb
|
|
8
8
|
test/templates/opml.xml
|
9
9
|
test/templates/opml.xml.erb
|
10
10
|
test/templates/opml.xml.tmpl
|
11
|
-
test/templates/planet/README.md
|
12
11
|
test/templates/planet/atom.xml.tmpl
|
13
12
|
test/templates/planet/basic/index.html.tmpl
|
14
13
|
test/templates/planet/fancy/index.html.tmpl
|
data/README.md
CHANGED
@@ -23,15 +23,17 @@ the ruby version.
|
|
23
23
|
|
24
24
|
First you make a template - this is just a normal HTML file with a few extra tags, the simplest being `<TMPL_VAR>`
|
25
25
|
|
26
|
-
For example, `
|
26
|
+
For example, `test.html.tmpl`:
|
27
27
|
|
28
28
|
```
|
29
|
-
<
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
<html>
|
30
|
+
<head><title>Test Template</title></head>
|
31
|
+
<body>
|
32
|
+
My Home Directory is <TMPL_VAR home>
|
33
|
+
<p>
|
34
|
+
My Path is set to <TMPL_VAR path>
|
35
|
+
</body>
|
36
|
+
</html>
|
35
37
|
```
|
36
38
|
|
37
39
|
Now you can use it in your script:
|
@@ -39,26 +41,23 @@ Now you can use it in your script:
|
|
39
41
|
``` ruby
|
40
42
|
require 'html/template'
|
41
43
|
|
42
|
-
template = HtmlTemplate.new( filename: '
|
44
|
+
template = HtmlTemplate.new( filename: 'test.html.tmpl' )
|
43
45
|
|
44
|
-
puts template.render(
|
45
|
-
|
46
|
-
]
|
47
|
-
)
|
46
|
+
puts template.render( home: ENV['HOME'],
|
47
|
+
path: ENV['PATH'] )
|
48
48
|
```
|
49
49
|
|
50
50
|
If all is well in the universe this should output something like this:
|
51
51
|
|
52
|
-
```
|
52
|
+
``` html
|
53
|
+
<html>
|
54
|
+
<head><title>Test Template</title></head>
|
55
|
+
<body>
|
56
|
+
My Home Directory is /home/alice
|
53
57
|
<p>
|
54
|
-
|
55
|
-
|
56
|
-
</
|
57
|
-
|
58
|
-
<p>
|
59
|
-
Name: Tracey Flick<br>
|
60
|
-
GPA: 4.0
|
61
|
-
</p>
|
58
|
+
My Path is set to /bin;/usr/bin
|
59
|
+
</body>
|
60
|
+
</html>
|
62
61
|
```
|
63
62
|
|
64
63
|
|
@@ -143,7 +142,7 @@ puts template.result( employees: [ { name: 'Sam', job: 'programmer' },
|
|
143
142
|
|
144
143
|
The output is:
|
145
144
|
|
146
|
-
```
|
145
|
+
``` html
|
147
146
|
<p>
|
148
147
|
Name: Sam<br>
|
149
148
|
Job: programmer
|
@@ -162,7 +161,7 @@ and then iterates over the loop body producing output.
|
|
162
161
|
**Loop Context Variables**
|
163
162
|
|
164
163
|
Inside a loop extra variables that depend on the loop's context
|
165
|
-
are made available. These are:
|
164
|
+
are made available if the `loop_vars` option is set to true (yes, true by default). These are:
|
166
165
|
|
167
166
|
`__FIRST__`
|
168
167
|
|
@@ -329,7 +328,7 @@ puts HtmlTemplate.new( <<TXT ).text
|
|
329
328
|
TXT
|
330
329
|
```
|
331
330
|
|
332
|
-
will print if debugging is turned on:
|
331
|
+
will print if debugging is turned on (e.g. `HtmlTemplate.config.debug = true`):
|
333
332
|
|
334
333
|
```
|
335
334
|
line 4 - match <TMPL_VAR name ESCAPE="HTML"> replacing with: <%=h name %>
|
data/lib/html/template.rb
CHANGED
@@ -16,13 +16,13 @@ module Enumerable
|
|
16
16
|
end
|
17
17
|
def index=(value) @index=value; end
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def each_with_loop( &blk )
|
21
21
|
loop_meta = LoopMeta.new( size )
|
22
22
|
each_with_index do |item, index|
|
23
23
|
loop_meta.index = index
|
24
24
|
blk.call( item, loop_meta )
|
25
|
-
end
|
25
|
+
end
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -35,55 +35,100 @@ require 'html/template/version' # note: let version always get first
|
|
35
35
|
|
36
36
|
class HtmlTemplate
|
37
37
|
|
38
|
+
class Configuration
|
39
|
+
def debug=(value) @debug = value; end
|
40
|
+
def debug?() @debug || false; end
|
41
|
+
|
42
|
+
def strict=(value) @strict = value; end
|
43
|
+
def strict?() @strict || true; end
|
44
|
+
|
45
|
+
def loop_vars=(value) @loop_vars = value; end
|
46
|
+
def loop_vars?() @loop_vars || true; end
|
47
|
+
end # class Configuration
|
48
|
+
|
49
|
+
## lets you use
|
50
|
+
## HtmlTemplate.configure do |config|
|
51
|
+
## config.debug = true
|
52
|
+
## config.strict = true
|
53
|
+
## end
|
54
|
+
|
55
|
+
def self.configure
|
56
|
+
yield( config )
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.config
|
60
|
+
@config ||= Configuration.new
|
61
|
+
end
|
62
|
+
|
63
|
+
|
38
64
|
attr_reader :text ## returns converted template text (with "breaking" comments!!!)
|
39
|
-
attr_reader :template ## return "inner" (erb) template object
|
65
|
+
attr_reader :template ## return "inner" (erb) template object
|
40
66
|
attr_reader :errors
|
67
|
+
attr_reader :names ## for debugging - returns all referenced / used names in VAR/IF/UNLESS/LOOP/etc.
|
68
|
+
|
69
|
+
## config convenience (shortcut) helpers
|
70
|
+
def config() self.class.config; end
|
71
|
+
def debug?() config.debug?; end
|
72
|
+
|
73
|
+
def strict?() @strict; end
|
74
|
+
def loop_vars?() @loop_vars; end
|
41
75
|
|
42
|
-
def initialize( text=nil, filename: nil )
|
76
|
+
def initialize( text=nil, filename: nil, strict: config.strict?, loop_vars: config.loop_vars? )
|
43
77
|
if text.nil? ## try to read file (by filename)
|
44
78
|
text = File.open( filename, 'r:utf-8' ) { |f| f.read }
|
45
79
|
end
|
46
80
|
|
81
|
+
## options
|
82
|
+
@strict = strict
|
83
|
+
@loop_vars = loop_vars
|
84
|
+
|
47
85
|
## todo/fix: add filename to ERB too (for better error reporting)
|
48
|
-
@text, @errors = convert( text ) ## note: keep a copy of the converted template text
|
49
|
-
|
86
|
+
@text, @errors, @names = convert( text ) ## note: keep a copy of the converted template text
|
87
|
+
|
50
88
|
if @errors.size > 0
|
51
89
|
puts "!! ERROR - #{@errors.size} conversion / syntax error(s):"
|
52
90
|
pp @errors
|
53
|
-
|
91
|
+
|
92
|
+
raise if strict? ## todo - find a good Error - StandardError - why? why not?
|
54
93
|
end
|
55
94
|
|
56
95
|
@template = ERB.new( @text, nil, '%<>' )
|
57
96
|
end
|
58
97
|
|
59
98
|
|
99
|
+
|
100
|
+
IDENT = '[a-zA-Z_][a-zA-Z0-9_]*'
|
101
|
+
ESCAPES = 'HTML|NONE'
|
102
|
+
|
60
103
|
VAR_RE = %r{<TMPL_(?<tag>VAR)
|
61
|
-
\s
|
62
|
-
(?<ident
|
63
|
-
(\s
|
104
|
+
\s+
|
105
|
+
(?<ident>#{IDENT})
|
106
|
+
(\s+
|
64
107
|
(?<escape>ESCAPE)
|
65
|
-
=
|
66
|
-
|
108
|
+
=(
|
109
|
+
(?<q>['"])(?<format>#{ESCAPES})\k<q> # note: allow single or double enclosing quote (but MUST match)
|
110
|
+
| (?<format>#{ESCAPES}) # note: support without quotes too
|
111
|
+
)
|
67
112
|
)?
|
68
113
|
>}x
|
69
114
|
|
70
115
|
IF_OPEN_RE = %r{(?<open><)TMPL_(?<tag>IF|UNLESS)
|
71
|
-
\s
|
72
|
-
(?<ident
|
116
|
+
\s+
|
117
|
+
(?<ident>#{IDENT})
|
73
118
|
>}x
|
74
119
|
|
75
120
|
IF_CLOSE_RE = %r{(?<close></)TMPL_(?<tag>IF|UNLESS)
|
76
|
-
(\s
|
77
|
-
(?<ident
|
78
|
-
)? # note: allow optional identifier
|
121
|
+
(\s+
|
122
|
+
(?<ident>#{IDENT})
|
123
|
+
)? # note: allow optional identifier
|
79
124
|
>}x
|
80
|
-
|
125
|
+
|
81
126
|
ELSE_RE = %r{<TMPL_(?<tag>ELSE)
|
82
127
|
>}x
|
83
128
|
|
84
129
|
LOOP_OPEN_RE = %r{(?<open><)TMPL_(?<tag>LOOP)
|
85
|
-
\s
|
86
|
-
(?<ident
|
130
|
+
\s+
|
131
|
+
(?<ident>#{IDENT})
|
87
132
|
>}x
|
88
133
|
|
89
134
|
LOOP_CLOSE_RE = %r{(?<close></)TMPL_(?<tag>LOOP)
|
@@ -91,7 +136,7 @@ class HtmlTemplate
|
|
91
136
|
|
92
137
|
CATCH_OPEN_RE = %r{(?<open><)TMPL_(?<unknown>[^>]+?)
|
93
138
|
>}x
|
94
|
-
|
139
|
+
|
95
140
|
CATCH_CLOSE_RE = %r{(?<close></)TMPL_(?<unknown>[^>]+?)
|
96
141
|
>}x
|
97
142
|
|
@@ -106,7 +151,7 @@ class HtmlTemplate
|
|
106
151
|
CATCH_CLOSE_RE )
|
107
152
|
|
108
153
|
|
109
|
-
def to_recursive_ostruct( o )
|
154
|
+
def to_recursive_ostruct( o )
|
110
155
|
if o.is_a?( Array )
|
111
156
|
o.reduce( [] ) do |ary, item|
|
112
157
|
ary << to_recursive_ostruct( item )
|
@@ -125,8 +170,47 @@ class HtmlTemplate
|
|
125
170
|
end
|
126
171
|
|
127
172
|
|
173
|
+
class Names
|
174
|
+
def initialize
|
175
|
+
@names = Hash.new
|
176
|
+
end
|
177
|
+
|
178
|
+
def to_h() @names; end
|
179
|
+
|
180
|
+
def add( scope, ident, tag )
|
181
|
+
## e.g. scope e.g. ['feeds'] or ['feeds','items'] - is a stack / array
|
182
|
+
## ident e.g. title - is a string
|
183
|
+
## tag e.g. $VAR/$LOOP/$IF/$UNLESS - is a string
|
184
|
+
h = fetch( scope, ident )
|
185
|
+
h[ tag ] ||= 0
|
186
|
+
h[ tag ] += 1
|
187
|
+
end
|
188
|
+
|
189
|
+
private
|
190
|
+
def fetch( scope, ident )
|
191
|
+
## fetch name in scoped hierarchy
|
192
|
+
## if first time than setup new empty hash
|
193
|
+
h = @names
|
194
|
+
scope.each do |name|
|
195
|
+
h = h[name] ||= {}
|
196
|
+
end
|
197
|
+
h[ ident ] ||= {}
|
198
|
+
end
|
199
|
+
end ## class Names
|
200
|
+
|
201
|
+
|
202
|
+
def ident_to_loop_it( ident ) # make loop iterator (e.g. Channels => channel and so on)
|
203
|
+
## assume plural ident e.g. channels
|
204
|
+
## cut-off last char, that is,
|
205
|
+
## the plural s channels => channel
|
206
|
+
## note: ALWAYS downcase (auto-generated) loop iterator/pass name
|
207
|
+
ident[0..-2].downcase
|
208
|
+
end
|
209
|
+
|
210
|
+
|
128
211
|
def convert( text )
|
129
|
-
errors = []
|
212
|
+
errors = [] # note: reset global errros list
|
213
|
+
names = Names.new ## keep track of all referenced / used names in VAR/IF/UNLESS/LOOP/etc.
|
130
214
|
|
131
215
|
stack = []
|
132
216
|
|
@@ -138,7 +222,7 @@ class HtmlTemplate
|
|
138
222
|
lineno += 1
|
139
223
|
|
140
224
|
if line.lstrip.start_with?( '#' ) ## or make it tripple ### - why? why not?
|
141
|
-
buf << "%#{line.lstrip}"
|
225
|
+
buf << "%#{line.lstrip}"
|
142
226
|
elsif line.strip.empty?
|
143
227
|
buf << line
|
144
228
|
else
|
@@ -159,9 +243,19 @@ class HtmlTemplate
|
|
159
243
|
## note: peek; get top stack item
|
160
244
|
## if top level (stack empty) => nothing
|
161
245
|
## otherwise => channel. or item. etc. (with trailing dot included!)
|
162
|
-
ctx = stack.empty?
|
246
|
+
ctx = if stack.empty?
|
247
|
+
''
|
248
|
+
else
|
249
|
+
## assume plural ident e.g. channels
|
250
|
+
## cut-off last char, that is,
|
251
|
+
## the plural s channels => channel
|
252
|
+
## note: ALWAYS downcase (auto-generated) loop iterator/pass name
|
253
|
+
"#{ident_to_loop_it( stack[-1] )}."
|
254
|
+
end
|
163
255
|
|
164
256
|
code = if tag == 'VAR'
|
257
|
+
names.add( stack, ident, '$VAR' )
|
258
|
+
|
165
259
|
if escape && format == 'HTML'
|
166
260
|
## check or use long form e.g. CGI.escapeHTML - why? why not?
|
167
261
|
"<%=h #{ctx}#{ident} %>"
|
@@ -169,20 +263,28 @@ class HtmlTemplate
|
|
169
263
|
"<%= #{ctx}#{ident} %>"
|
170
264
|
end
|
171
265
|
elsif tag == 'LOOP' && tag_open
|
266
|
+
names.add( stack, ident, '$LOOP' )
|
267
|
+
|
172
268
|
## assume plural ident e.g. channels
|
173
269
|
## cut-off last char, that is, the plural s channels => channel
|
174
270
|
## note: ALWAYS downcase (auto-generated) loop iterator/pass name
|
175
|
-
it = ident
|
176
|
-
stack.push(
|
177
|
-
|
271
|
+
it = ident_to_loop_it( ident )
|
272
|
+
stack.push( ident )
|
273
|
+
if loop_vars?
|
274
|
+
"<% #{ctx}#{ident}.each_with_loop do |#{it}, #{it}_loop| %>"
|
275
|
+
else
|
276
|
+
"<% #{ctx}#{ident}.each do |#{it}| %>"
|
277
|
+
end
|
178
278
|
elsif tag == 'LOOP' && tag_close
|
179
279
|
stack.pop
|
180
280
|
"<% end %>"
|
181
281
|
elsif tag == 'IF' && tag_open
|
282
|
+
names.add( stack, ident, '$IF' )
|
182
283
|
"<% if #{ctx}#{ident} %>"
|
183
|
-
|
184
|
-
|
185
|
-
|
284
|
+
elsif tag == 'UNLESS' && tag_open
|
285
|
+
names.add( stack, ident, '$UNLESS' )
|
286
|
+
"<% unless #{ctx}#{ident} %>"
|
287
|
+
elsif (tag == 'IF' || tag == 'UNLESS') && tag_close
|
186
288
|
"<% end %>"
|
187
289
|
elsif tag == 'ELSE'
|
188
290
|
"<% else %>"
|
@@ -200,13 +302,13 @@ class HtmlTemplate
|
|
200
302
|
raise ArgumentError ## unknown tag #{tag}
|
201
303
|
end
|
202
304
|
|
203
|
-
puts " line #{lineno} - match #{m[0]} replacing with: #{code}"
|
305
|
+
puts " line #{lineno} - match #{m[0]} replacing with: #{code}" if debug?
|
204
306
|
code
|
205
307
|
|
206
308
|
end
|
207
309
|
end
|
208
310
|
end # each_line
|
209
|
-
[buf, errors]
|
311
|
+
[buf, errors, names.to_h]
|
210
312
|
end # method convert
|
211
313
|
|
212
314
|
|
@@ -229,9 +331,9 @@ class HtmlTemplate
|
|
229
331
|
hash[key] = to_recursive_ostruct( val )
|
230
332
|
hash
|
231
333
|
end
|
232
|
-
|
334
|
+
|
233
335
|
## (auto-)convert array and hash values to ostruct
|
234
|
-
## for easy dot (.) access
|
336
|
+
## for easy dot (.) access
|
235
337
|
## e.g. student.name instead of student[:name]
|
236
338
|
|
237
339
|
@template.result( Context.new( **kwargs ).get_binding )
|
data/test/helper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
<!DOCTYPE HTML
|
1
|
+
<!DOCTYPE HTML>
|
2
2
|
<html>
|
3
3
|
|
4
4
|
### Planet HTML template.
|
@@ -22,7 +22,7 @@
|
|
22
22
|
|
23
23
|
<head>
|
24
24
|
<title><TMPL_VAR name></title>
|
25
|
-
<meta
|
25
|
+
<meta charset="utf-8">
|
26
26
|
<meta name="generator" content="<TMPL_VAR generator ESCAPE="HTML">">
|
27
27
|
</head>
|
28
28
|
|
@@ -85,4 +85,4 @@
|
|
85
85
|
</p>
|
86
86
|
</body>
|
87
87
|
|
88
|
-
</html>
|
88
|
+
</html>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<!DOCTYPE HTML
|
1
|
+
<!DOCTYPE HTML>
|
2
2
|
<html>
|
3
3
|
|
4
4
|
### Fancy Planet HTML template.
|
@@ -13,7 +13,7 @@
|
|
13
13
|
|
14
14
|
<head>
|
15
15
|
<title><TMPL_VAR name></title>
|
16
|
-
<meta
|
16
|
+
<meta charset="utf-8">
|
17
17
|
<meta name="generator" content="<TMPL_VAR generator ESCAPE="HTML">">
|
18
18
|
<link rel="stylesheet" href="planet.css" type="text/css">
|
19
19
|
<TMPL_IF feedtype>
|
data/test/test_merge.rb
CHANGED
@@ -78,24 +78,63 @@ print $template->output;
|
|
78
78
|
=end
|
79
79
|
|
80
80
|
def test_students_example
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
</TMPL_LOOP>
|
81
|
+
t = HtmlTemplate.new( <<TXT )
|
82
|
+
<TMPL_LOOP students>
|
83
|
+
<p>
|
84
|
+
Name: <TMPL_VAR name><br/>
|
85
|
+
GPA: <TMPL_VAR gpa>
|
86
|
+
</p>
|
87
|
+
</TMPL_LOOP>
|
89
88
|
TXT
|
90
89
|
|
91
|
-
t = HtmlTemplate.new( tmpl )
|
92
90
|
puts t.text
|
93
91
|
puts "---"
|
94
|
-
|
95
|
-
|
92
|
+
result = t.render( students: [ { name: 'Bluto Blutarsky', gpa: 0.0 },
|
93
|
+
{ name: 'Tracey Flick', gpa: 4.0 } ])
|
94
|
+
puts result
|
95
|
+
|
96
|
+
exp =<<TXT
|
97
|
+
<p>
|
98
|
+
Name: Bluto Blutarsky<br/>
|
99
|
+
GPA: 0.0
|
100
|
+
</p>
|
101
|
+
<p>
|
102
|
+
Name: Tracey Flick<br/>
|
103
|
+
GPA: 4.0
|
104
|
+
</p>
|
105
|
+
TXT
|
106
|
+
|
107
|
+
assert_equal exp, result
|
108
|
+
end
|
96
109
|
|
97
110
|
|
98
|
-
|
99
|
-
|
111
|
+
def test_escape
|
112
|
+
t = HtmlTemplate.new( <<TXT )
|
113
|
+
<TMPL_LOOP pubs>
|
114
|
+
Name: <TMPL_VAR name>
|
115
|
+
Name: <TMPL_VAR name ESCAPE=HTML>
|
116
|
+
Name: <TMPL_VAR name ESCAPE="HTML">
|
117
|
+
Name: <TMPL_VAR name ESCAPE='HTML'>
|
118
|
+
|
119
|
+
</TMPL_LOOP>
|
120
|
+
TXT
|
121
|
+
|
122
|
+
exp =<<TXT
|
123
|
+
Name: Fuller's Ale & Pie House
|
124
|
+
Name: Fuller's Ale & Pie House
|
125
|
+
Name: Fuller's Ale & Pie House
|
126
|
+
Name: Fuller's Ale & Pie House
|
127
|
+
|
128
|
+
Name: Mel's Craft Beers & Diner
|
129
|
+
Name: Mel's Craft Beers & Diner
|
130
|
+
Name: Mel's Craft Beers & Diner
|
131
|
+
Name: Mel's Craft Beers & Diner
|
132
|
+
|
133
|
+
TXT
|
134
|
+
|
135
|
+
assert_equal exp, t.render( pubs: [{ name: "Fuller's Ale & Pie House" },
|
136
|
+
{ name: "Mel's Craft Beers & Diner" }])
|
100
137
|
end
|
101
138
|
|
139
|
+
end # class TestMerge
|
140
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: html-template
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rdoc
|
@@ -58,7 +58,6 @@ files:
|
|
58
58
|
- test/templates/opml.xml
|
59
59
|
- test/templates/opml.xml.erb
|
60
60
|
- test/templates/opml.xml.tmpl
|
61
|
-
- test/templates/planet/README.md
|
62
61
|
- test/templates/planet/atom.xml.tmpl
|
63
62
|
- test/templates/planet/basic/index.html.tmpl
|
64
63
|
- test/templates/planet/fancy/index.html.tmpl
|