html-template 0.2.0 → 1.0.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.
- checksums.yaml +4 -4
- data/Manifest.txt +1 -0
- data/README.md +1 -1
- data/lib/html/template.rb +103 -24
- data/lib/html/template/version.rb +2 -2
- data/test/test_loop.rb +228 -0
- data/test/test_merge.rb +5 -7
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9da6acb71081dfa21baa90d4993b4b91e777bc49
|
4
|
+
data.tar.gz: 43f3da8d115fb179536ed7726256c67a020c6537
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 967ba68efbbee4e8b512ed7cbaf58a78fc32b9ac387ede73a0aac3c696442de6a1e70187561451a85459af1ea5876850985f3228d0db96d8fe606177a4b64b2d
|
7
|
+
data.tar.gz: c03eebe9085e73da5aaa2b118478404a2d6515df901d642aa50e78768191055dc9638c6f67376d0ba0b69e65cdcaae8da1a68412b28416b9b403d99dc3fb9357
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -16,7 +16,7 @@ Note: The original [`HTML::Template`](https://metacpan.org/pod/HTML::Template) p
|
|
16
16
|
(in Perl with a first 1.0 release in 1999!)
|
17
17
|
and the documentation here
|
18
18
|
is mostly a copy from the original
|
19
|
-
with some changes /
|
19
|
+
with some changes / adaptions for
|
20
20
|
the ruby version.
|
21
21
|
|
22
22
|
|
data/lib/html/template.rb
CHANGED
@@ -9,21 +9,84 @@ require 'fileutils'
|
|
9
9
|
|
10
10
|
|
11
11
|
module Enumerable
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
12
|
+
class LoopMeta
|
13
|
+
def initialize( total )
|
14
|
+
@total = total
|
15
|
+
end
|
16
|
+
|
17
|
+
def index=(value)
|
18
|
+
@index = value;
|
19
|
+
@counter = @index+1
|
20
|
+
|
21
|
+
## assume first item (index 0/counter 1) is odd - why? why not?
|
22
|
+
## 0 % 2 => 0 (odd) -- first
|
23
|
+
## 1 % 2 => 1 (even) -- second
|
24
|
+
## 2 % 2 => 0
|
25
|
+
## 3 % 2 => 1
|
26
|
+
## etc.
|
27
|
+
@odd = (@index % 2) == 0
|
28
|
+
@even = !@odd
|
29
|
+
|
30
|
+
if @index == 0
|
31
|
+
@first = true
|
32
|
+
@inner = false
|
33
|
+
@outer = true
|
34
|
+
@last = (@total-1) == 0
|
35
|
+
elsif @index == (@total-1)
|
36
|
+
@first = false
|
37
|
+
@inner = false
|
38
|
+
@outer = true
|
39
|
+
@last = true
|
40
|
+
else
|
41
|
+
@first = false
|
42
|
+
@inner = true
|
43
|
+
@outer = false
|
44
|
+
@last = false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
attr_reader :index
|
49
|
+
attr_reader :counter
|
50
|
+
attr_reader :odd
|
51
|
+
attr_reader :even
|
52
|
+
attr_reader :first
|
53
|
+
attr_reader :inner
|
54
|
+
attr_reader :outer
|
55
|
+
attr_reader :last
|
56
|
+
|
57
|
+
alias_method :odd?, :odd
|
58
|
+
alias_method :even?, :even
|
59
|
+
alias_method :first?, :first
|
60
|
+
alias_method :inner?, :inner
|
61
|
+
alias_method :outer?, :outer
|
62
|
+
alias_method :last?, :last
|
63
|
+
|
64
|
+
alias_method :__index__, :index
|
65
|
+
alias_method :__counter__, :counter
|
66
|
+
alias_method :__odd__, :odd
|
67
|
+
alias_method :__even__, :even
|
68
|
+
alias_method :__first__, :first
|
69
|
+
alias_method :__inner__, :inner
|
70
|
+
alias_method :__outer__, :outer
|
71
|
+
alias_method :__last__, :last
|
72
|
+
|
73
|
+
alias_method :__INDEX__, :index
|
74
|
+
alias_method :__COUNTER__, :counter
|
75
|
+
alias_method :__ODD__, :odd
|
76
|
+
alias_method :__EVEN__, :even
|
77
|
+
alias_method :__FIRST__, :first
|
78
|
+
alias_method :__INNER__, :inner
|
79
|
+
alias_method :__OUTER__, :outer
|
80
|
+
alias_method :__LAST__, :last
|
81
|
+
end
|
82
|
+
|
83
|
+
def each_with_loop( &blk )
|
84
|
+
loop_meta = LoopMeta.new( size )
|
85
|
+
each_with_index do |item, index|
|
86
|
+
loop_meta.index = index
|
87
|
+
blk.call( item, loop_meta )
|
88
|
+
end
|
89
|
+
end
|
27
90
|
end
|
28
91
|
|
29
92
|
|
@@ -38,28 +101,28 @@ class HtmlTemplate
|
|
38
101
|
class Configuration
|
39
102
|
def debug=(value) @debug = value; end
|
40
103
|
def debug?() @debug || false; end
|
41
|
-
|
104
|
+
|
42
105
|
def strict=(value) @strict = value; end
|
43
106
|
def strict?() @strict || true; end
|
44
107
|
|
45
108
|
def loop_vars=(value) @loop_vars = value; end
|
46
109
|
def loop_vars?() @loop_vars || true; end
|
47
110
|
end # class Configuration
|
48
|
-
|
111
|
+
|
49
112
|
## lets you use
|
50
113
|
## HtmlTemplate.configure do |config|
|
51
114
|
## config.debug = true
|
52
115
|
## config.strict = true
|
53
116
|
## end
|
54
|
-
|
117
|
+
|
55
118
|
def self.configure
|
56
119
|
yield( config )
|
57
120
|
end
|
58
|
-
|
121
|
+
|
59
122
|
def self.config
|
60
123
|
@config ||= Configuration.new
|
61
124
|
end
|
62
|
-
|
125
|
+
|
63
126
|
|
64
127
|
attr_reader :text ## returns converted template text (with "breaking" comments!!!)
|
65
128
|
attr_reader :template ## return "inner" (erb) template object
|
@@ -88,7 +151,7 @@ class HtmlTemplate
|
|
88
151
|
if @errors.size > 0
|
89
152
|
puts "!! ERROR - #{@errors.size} conversion / syntax error(s):"
|
90
153
|
pp @errors
|
91
|
-
|
154
|
+
|
92
155
|
raise if strict? ## todo - find a good Error - StandardError - why? why not?
|
93
156
|
end
|
94
157
|
|
@@ -105,10 +168,10 @@ class HtmlTemplate
|
|
105
168
|
(?<ident>#{IDENT})
|
106
169
|
(\s+
|
107
170
|
(?<escape>ESCAPE)
|
108
|
-
|
171
|
+
\s*=\s*(
|
109
172
|
(?<q>['"])(?<format>#{ESCAPES})\k<q> # note: allow single or double enclosing quote (but MUST match)
|
110
173
|
| (?<format>#{ESCAPES}) # note: support without quotes too
|
111
|
-
)
|
174
|
+
)
|
112
175
|
)?
|
113
176
|
>}x
|
114
177
|
|
@@ -246,11 +309,27 @@ class HtmlTemplate
|
|
246
309
|
ctx = if stack.empty?
|
247
310
|
''
|
248
311
|
else
|
312
|
+
## check for special loop variables
|
313
|
+
if loop_vars? &&
|
314
|
+
['__INDEX__',
|
315
|
+
'__COUNTER__',
|
316
|
+
'__INDEX__',
|
317
|
+
'__COUNTER__',
|
318
|
+
'__ODD__',
|
319
|
+
'__EVEN__',
|
320
|
+
'__FIRST__',
|
321
|
+
'__INNER__',
|
322
|
+
'__OUTER__',
|
323
|
+
'__LAST__'
|
324
|
+
].include?( ident )
|
325
|
+
"#{ident_to_loop_it( stack[-1] )}_loop."
|
326
|
+
else
|
249
327
|
## assume plural ident e.g. channels
|
250
328
|
## cut-off last char, that is,
|
251
329
|
## the plural s channels => channel
|
252
330
|
## note: ALWAYS downcase (auto-generated) loop iterator/pass name
|
253
|
-
|
331
|
+
"#{ident_to_loop_it( stack[-1] )}."
|
332
|
+
end
|
254
333
|
end
|
255
334
|
|
256
335
|
code = if tag == 'VAR'
|
data/test/test_loop.rb
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
###
|
2
|
+
# to run use
|
3
|
+
# ruby -I ./lib -I ./test test/test_loop.rb
|
4
|
+
|
5
|
+
require 'helper'
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
class TestLoop < MiniTest::Test
|
10
|
+
|
11
|
+
def test_loop_meta
|
12
|
+
[].each_with_loop do |item, item_loop|
|
13
|
+
assert false ## empty loop; fail/error if we get here
|
14
|
+
end
|
15
|
+
|
16
|
+
[{index: 0,
|
17
|
+
counter: 1,
|
18
|
+
odd: true,
|
19
|
+
even: false,
|
20
|
+
first: true,
|
21
|
+
inner: false,
|
22
|
+
outer: true,
|
23
|
+
last: true}].each_with_loop do |item, item_loop|
|
24
|
+
assert_equal item[:index], item_loop.index
|
25
|
+
assert_equal item[:counter], item_loop.counter
|
26
|
+
assert item_loop.odd? == item[:odd]
|
27
|
+
assert item_loop.even? == item[:even]
|
28
|
+
assert item_loop.first? == item[:first]
|
29
|
+
assert item_loop.inner? == item[:inner]
|
30
|
+
assert item_loop.outer? == item[:outer]
|
31
|
+
assert item_loop.last? == item[:last]
|
32
|
+
end
|
33
|
+
|
34
|
+
[{index: 0,
|
35
|
+
counter: 1,
|
36
|
+
odd: true,
|
37
|
+
even: false,
|
38
|
+
first: true,
|
39
|
+
inner: false,
|
40
|
+
outer: true,
|
41
|
+
last: false},
|
42
|
+
{index: 1,
|
43
|
+
counter: 2,
|
44
|
+
odd: false,
|
45
|
+
even: true,
|
46
|
+
first: false,
|
47
|
+
inner: true,
|
48
|
+
outer: false,
|
49
|
+
last: false},
|
50
|
+
{index: 2,
|
51
|
+
counter: 3,
|
52
|
+
odd: true,
|
53
|
+
even: false,
|
54
|
+
first: false,
|
55
|
+
inner: false,
|
56
|
+
outer: true,
|
57
|
+
last: true}].each_with_loop do |item, item_loop|
|
58
|
+
assert_equal item[:index], item_loop.index
|
59
|
+
assert_equal item[:counter], item_loop.counter
|
60
|
+
assert item_loop.odd? == item[:odd]
|
61
|
+
assert item_loop.even? == item[:even]
|
62
|
+
assert item_loop.first? == item[:first]
|
63
|
+
assert item_loop.inner? == item[:inner]
|
64
|
+
assert item_loop.outer? == item[:outer]
|
65
|
+
assert item_loop.last? == item[:last]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def test_loop_example
|
71
|
+
t = HtmlTemplate.new( <<TXT )
|
72
|
+
<TMPL_LOOP foos>
|
73
|
+
<TMPL_IF __FIRST__>
|
74
|
+
This only outputs on the first pass.
|
75
|
+
</TMPL_IF>
|
76
|
+
<TMPL_IF __ODD__>
|
77
|
+
This outputs every other pass, on the odd passes.
|
78
|
+
</TMPL_IF>
|
79
|
+
<TMPL_UNLESS __ODD__>
|
80
|
+
This outputs every other pass, on the even passes.
|
81
|
+
</TMPL_UNLESS>
|
82
|
+
<TMPL_IF __INNER__>
|
83
|
+
This outputs on passes that are neither first nor last.
|
84
|
+
</TMPL_IF>
|
85
|
+
|
86
|
+
This is pass number <TMPL_VAR __COUNTER__>.
|
87
|
+
|
88
|
+
<TMPL_IF __LAST__>
|
89
|
+
This only outputs on the last pass.
|
90
|
+
</TMPL_IF>
|
91
|
+
</TMPL_LOOP>
|
92
|
+
TXT
|
93
|
+
|
94
|
+
pp t.names
|
95
|
+
puts "---"
|
96
|
+
|
97
|
+
puts t.text
|
98
|
+
puts "---"
|
99
|
+
|
100
|
+
assert_equal <<TXT, t.text
|
101
|
+
<% foos.each_with_loop do |foo, foo_loop| %>
|
102
|
+
<% if foo_loop.__FIRST__ %>
|
103
|
+
This only outputs on the first pass.
|
104
|
+
<% end %>
|
105
|
+
<% if foo_loop.__ODD__ %>
|
106
|
+
This outputs every other pass, on the odd passes.
|
107
|
+
<% end %>
|
108
|
+
<% unless foo_loop.__ODD__ %>
|
109
|
+
This outputs every other pass, on the even passes.
|
110
|
+
<% end %>
|
111
|
+
<% if foo_loop.__INNER__ %>
|
112
|
+
This outputs on passes that are neither first nor last.
|
113
|
+
<% end %>
|
114
|
+
|
115
|
+
This is pass number <%= foo_loop.__COUNTER__ %>.
|
116
|
+
|
117
|
+
<% if foo_loop.__LAST__ %>
|
118
|
+
This only outputs on the last pass.
|
119
|
+
<% end %>
|
120
|
+
<% end %>
|
121
|
+
TXT
|
122
|
+
|
123
|
+
result = t.render( foos: [{ name: 'Dave Grohl' },
|
124
|
+
{ name: 'Nate Mendel' },
|
125
|
+
{ name: 'Pat Smear' },
|
126
|
+
{ name: 'Taylor Hawkins' },
|
127
|
+
{ name: 'Chris Shiflett' },
|
128
|
+
{ name: 'Rami Jaffee' }] )
|
129
|
+
puts result
|
130
|
+
|
131
|
+
assert_equal <<TXT, result
|
132
|
+
This only outputs on the first pass.
|
133
|
+
This outputs every other pass, on the odd passes.
|
134
|
+
|
135
|
+
This is pass number 1.
|
136
|
+
|
137
|
+
This outputs every other pass, on the even passes.
|
138
|
+
This outputs on passes that are neither first nor last.
|
139
|
+
|
140
|
+
This is pass number 2.
|
141
|
+
|
142
|
+
This outputs every other pass, on the odd passes.
|
143
|
+
This outputs on passes that are neither first nor last.
|
144
|
+
|
145
|
+
This is pass number 3.
|
146
|
+
|
147
|
+
This outputs every other pass, on the even passes.
|
148
|
+
This outputs on passes that are neither first nor last.
|
149
|
+
|
150
|
+
This is pass number 4.
|
151
|
+
|
152
|
+
This outputs every other pass, on the odd passes.
|
153
|
+
This outputs on passes that are neither first nor last.
|
154
|
+
|
155
|
+
This is pass number 5.
|
156
|
+
|
157
|
+
This outputs every other pass, on the even passes.
|
158
|
+
|
159
|
+
This is pass number 6.
|
160
|
+
|
161
|
+
This only outputs on the last pass.
|
162
|
+
TXT
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
def test_loop_inner
|
167
|
+
t = HtmlTemplate.new( <<TXT )
|
168
|
+
<TMPL_LOOP feeds>
|
169
|
+
<TMPL_VAR title>
|
170
|
+
<TMPL_VAR updated>
|
171
|
+
<TMPL_LOOP items>
|
172
|
+
<TMPL_VAR title>
|
173
|
+
<TMPL_VAR updated>
|
174
|
+
</TMPL_LOOP>
|
175
|
+
</TMPL_LOOP>
|
176
|
+
TXT
|
177
|
+
|
178
|
+
pp t.names
|
179
|
+
puts "---"
|
180
|
+
|
181
|
+
puts t.text
|
182
|
+
puts "---"
|
183
|
+
|
184
|
+
assert_equal <<TXT, t.text
|
185
|
+
<% feeds.each_with_loop do |feed, feed_loop| %>
|
186
|
+
<%= feed.title %>
|
187
|
+
<%= feed.updated %>
|
188
|
+
<% feed.items.each_with_loop do |item, item_loop| %>
|
189
|
+
<%= item.title %>
|
190
|
+
<%= item.updated %>
|
191
|
+
<% end %>
|
192
|
+
<% end %>
|
193
|
+
TXT
|
194
|
+
|
195
|
+
result = t.render( feeds: [{ title: 'Feed 1', updated: Date.new(2010,1,3),
|
196
|
+
items: [{ title: 'Item 1.1', updated: Date.new(2010,1,1)},
|
197
|
+
{ title: 'Item 1.2', updated: Date.new(2010,1,2)}]},
|
198
|
+
{ title: 'Feed 2', updated: Date.new(2020,1,3),
|
199
|
+
items: [{ title: 'Item 2.1', updated: Date.new(2020,1,1)},
|
200
|
+
{ title: 'Item 2.2', updated: Date.new(2020,1,2)}]}] )
|
201
|
+
|
202
|
+
result = result.gsub( /^[ ]+$/, '' ) ## note: remove spaces in empty lines (only with spaces)
|
203
|
+
puts result
|
204
|
+
|
205
|
+
assert_equal <<TXT, result
|
206
|
+
Feed 1
|
207
|
+
2010-01-03
|
208
|
+
|
209
|
+
Item 1.1
|
210
|
+
2010-01-01
|
211
|
+
|
212
|
+
Item 1.2
|
213
|
+
2010-01-02
|
214
|
+
|
215
|
+
Feed 2
|
216
|
+
2020-01-03
|
217
|
+
|
218
|
+
Item 2.1
|
219
|
+
2020-01-01
|
220
|
+
|
221
|
+
Item 2.2
|
222
|
+
2020-01-02
|
223
|
+
|
224
|
+
TXT
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
end # class TestLoop
|
data/test/test_merge.rb
CHANGED
@@ -93,7 +93,7 @@ TXT
|
|
93
93
|
{ name: 'Tracey Flick', gpa: 4.0 } ])
|
94
94
|
puts result
|
95
95
|
|
96
|
-
|
96
|
+
assert_equal <<TXT, result
|
97
97
|
<p>
|
98
98
|
Name: Bluto Blutarsky<br/>
|
99
99
|
GPA: 0.0
|
@@ -103,12 +103,10 @@ Name: Tracey Flick<br/>
|
|
103
103
|
GPA: 4.0
|
104
104
|
</p>
|
105
105
|
TXT
|
106
|
-
|
107
|
-
assert_equal exp, result
|
108
106
|
end
|
109
107
|
|
110
108
|
|
111
|
-
def test_escape
|
109
|
+
def test_escape
|
112
110
|
t = HtmlTemplate.new( <<TXT )
|
113
111
|
<TMPL_LOOP pubs>
|
114
112
|
Name: <TMPL_VAR name>
|
@@ -119,7 +117,7 @@ Name: <TMPL_VAR name ESCAPE='HTML'>
|
|
119
117
|
</TMPL_LOOP>
|
120
118
|
TXT
|
121
119
|
|
122
|
-
exp =<<TXT
|
120
|
+
exp =<<TXT
|
123
121
|
Name: Fuller's Ale & Pie House
|
124
122
|
Name: Fuller's Ale & Pie House
|
125
123
|
Name: Fuller's Ale & Pie House
|
@@ -132,8 +130,8 @@ Name: Mel's Craft Beers & Diner
|
|
132
130
|
|
133
131
|
TXT
|
134
132
|
|
135
|
-
assert_equal exp, t.render( pubs: [{ name: "Fuller's Ale & Pie House" },
|
136
|
-
{ name: "Mel's Craft Beers & Diner" }])
|
133
|
+
assert_equal exp, t.render( pubs: [{ name: "Fuller's Ale & Pie House" },
|
134
|
+
{ name: "Mel's Craft Beers & Diner" }])
|
137
135
|
end
|
138
136
|
|
139
137
|
end # class TestMerge
|
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: 1.0.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-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rdoc
|
@@ -65,6 +65,7 @@ files:
|
|
65
65
|
- test/templates/planet/opml.xml.tmpl
|
66
66
|
- test/templates/planet/rss10.xml.tmpl
|
67
67
|
- test/templates/planet/rss20.xml.tmpl
|
68
|
+
- test/test_loop.rb
|
68
69
|
- test/test_merge.rb
|
69
70
|
homepage: https://github.com/feedreader/pluto
|
70
71
|
licenses:
|