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 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: