html-template 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 99e549ccfeeab65c5a307442d82910d2c69fa03a
4
- data.tar.gz: c7f0bf3e17141ea27250e99ea184c61a8f85fa96
3
+ metadata.gz: 9da6acb71081dfa21baa90d4993b4b91e777bc49
4
+ data.tar.gz: 43f3da8d115fb179536ed7726256c67a020c6537
5
5
  SHA512:
6
- metadata.gz: e3a4b8328958f8934858ec3d62f906e40ce0ebc74638101bca301656319c20560ae6c748892b6ee6f0ceaa6281d063a64d256628955ab49b951ecd11a0474ddd
7
- data.tar.gz: b225712c8e413f29d4f9e76fc35c8fa38106e32cb062c77f6695e544980c087d2f733b3ebe55873bdcf98809f22f9741e9075165ef25e2e1354679a481e63d18
6
+ metadata.gz: 967ba68efbbee4e8b512ed7cbaf58a78fc32b9ac387ede73a0aac3c696442de6a1e70187561451a85459af1ea5876850985f3228d0db96d8fe606177a4b64b2d
7
+ data.tar.gz: c03eebe9085e73da5aaa2b118478404a2d6515df901d642aa50e78768191055dc9638c6f67376d0ba0b69e65cdcaae8da1a68412b28416b9b403d99dc3fb9357
@@ -15,4 +15,5 @@ test/templates/planet/foafroll.xml.tmpl
15
15
  test/templates/planet/opml.xml.tmpl
16
16
  test/templates/planet/rss10.xml.tmpl
17
17
  test/templates/planet/rss20.xml.tmpl
18
+ test/test_loop.rb
18
19
  test/test_merge.rb
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 / adoptions for
19
+ with some changes / adaptions for
20
20
  the ruby version.
21
21
 
22
22
 
@@ -9,21 +9,84 @@ require 'fileutils'
9
9
 
10
10
 
11
11
  module Enumerable
12
- class LoopMeta
13
- def initialize( total )
14
- @total = total
15
- @index = 0
16
- end
17
- def index=(value) @index=value; end
18
- end
19
-
20
- def each_with_loop( &blk )
21
- loop_meta = LoopMeta.new( size )
22
- each_with_index do |item, index|
23
- loop_meta.index = index
24
- blk.call( item, loop_meta )
25
- end
26
- end
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
- "#{ident_to_loop_it( stack[-1] )}."
331
+ "#{ident_to_loop_it( stack[-1] )}."
332
+ end
254
333
  end
255
334
 
256
335
  code = if tag == 'VAR'
@@ -2,8 +2,8 @@
2
2
 
3
3
 
4
4
  class HtmlTemplate
5
- MAJOR = 0
6
- MINOR = 2
5
+ MAJOR = 1
6
+ MINOR = 0
7
7
  PATCH = 0
8
8
  VERSION = [MAJOR,MINOR,PATCH].join('.')
9
9
 
@@ -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
@@ -93,7 +93,7 @@ TXT
93
93
  { name: 'Tracey Flick', gpa: 4.0 } ])
94
94
  puts result
95
95
 
96
- exp =<<TXT
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&#39;s Ale &amp; Pie House
125
123
  Name: Fuller&#39;s Ale &amp; Pie House
@@ -132,8 +130,8 @@ Name: Mel&#39;s Craft Beers &amp; 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.2.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 00:00:00.000000000 Z
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: