ad_hoc_template 0.0.1 → 0.1.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/.gitignore +2 -0
- data/Gemfile +1 -1
- data/README.md +1 -2
- data/ad_hoc_template.gemspec +1 -1
- data/lib/ad_hoc_template/command_line_interface.rb +94 -7
- data/lib/ad_hoc_template/parser.rb +160 -0
- data/lib/ad_hoc_template/record_reader.rb +281 -0
- data/lib/ad_hoc_template/version.rb +1 -1
- data/lib/ad_hoc_template.rb +29 -176
- data/spec/ad_hoc_template_spec.rb +308 -141
- data/spec/command_line_interface_spec.rb +393 -34
- data/spec/parser_spec.rb +399 -0
- data/spec/record_reader_spec.rb +377 -0
- metadata +11 -6
data/spec/parser_spec.rb
ADDED
@@ -0,0 +1,399 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'ad_hoc_template'
|
5
|
+
|
6
|
+
describe AdHocTemplate do
|
7
|
+
describe AdHocTemplate::Parser do
|
8
|
+
describe "with the default tag type" do
|
9
|
+
it "returns a tree of TagNode and Leaf" do
|
10
|
+
expect(AdHocTemplate::Parser.parse("a test string with tags (<% the first tag %> and <% the second tag %>) in it")).to eq([["a test string with tags ("],
|
11
|
+
[[" the first tag "]],
|
12
|
+
[" and "],
|
13
|
+
[[" the second tag "]],
|
14
|
+
[") in it"]])
|
15
|
+
end
|
16
|
+
|
17
|
+
it "allows to have a nested tag" do
|
18
|
+
expect(AdHocTemplate::Parser.parse("a test string with a nested tag; <% an outer tag and <% an inner tag %> %>")).to eq([["a test string with a nested tag; "],
|
19
|
+
[[" an outer tag and "],
|
20
|
+
[[" an inner tag "]],
|
21
|
+
[" "]]])
|
22
|
+
end
|
23
|
+
|
24
|
+
it "may have iteration tags." do
|
25
|
+
tree = AdHocTemplate::Parser.parse("a test string with a nested tag: <%# an iteration tag and <% an inner tag %> #%> and <% another tag %>")
|
26
|
+
expect(tree).to eq([["a test string with a nested tag: "],
|
27
|
+
[[" an iteration tag and "],
|
28
|
+
[[" an inner tag "]],
|
29
|
+
[" "]],
|
30
|
+
[" and "],
|
31
|
+
[[" another tag "]]])
|
32
|
+
expect(tree[1]).to be_a_kind_of(AdHocTemplate::Parser::IterationTagNode)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "may contain lines that consist only of an iteration tag" do
|
36
|
+
tree = AdHocTemplate::Parser.parse("<%#iterations
|
37
|
+
content
|
38
|
+
#%>
|
39
|
+
")
|
40
|
+
expect(tree).to eq([[["content\n"]]])
|
41
|
+
end
|
42
|
+
|
43
|
+
it "must return an empty array when template is an empty string" do
|
44
|
+
tree = AdHocTemplate::Parser.parse("")
|
45
|
+
expect(tree).to eq([])
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
it "does not remove indents from the lines which contain only iteration tag" do
|
50
|
+
template_without_indent = <<TEMPLATE_WITHOUT_INDENT
|
51
|
+
A template with an iteration tag
|
52
|
+
|
53
|
+
<%#
|
54
|
+
This part will be repeated with <!--% variable %-->
|
55
|
+
#%>
|
56
|
+
|
57
|
+
TEMPLATE_WITHOUT_INDENT
|
58
|
+
|
59
|
+
template_with_indent = <<TEMPLATE
|
60
|
+
A template with an iteration tag
|
61
|
+
|
62
|
+
<%#
|
63
|
+
This part will be repeated with <!--% variable %-->
|
64
|
+
#%>
|
65
|
+
|
66
|
+
TEMPLATE
|
67
|
+
|
68
|
+
without_indent = AdHocTemplate::Parser.parse(template_without_indent)
|
69
|
+
with_indent = AdHocTemplate::Parser.parse(template_with_indent)
|
70
|
+
|
71
|
+
expect(with_indent).not_to eq(without_indent)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "with the square brackets tag type" do
|
76
|
+
it "returns a tree of TagNode and Leaf" do
|
77
|
+
expect(AdHocTemplate::Parser.parse("a test string with tags ([[ the first tag ]] and [[ the second tag ]]) in it", :square_brackets)).to eq([["a test string with tags ("],
|
78
|
+
[[" the first tag "]],
|
79
|
+
[" and "],
|
80
|
+
[[" the second tag "]],
|
81
|
+
[") in it"]])
|
82
|
+
end
|
83
|
+
|
84
|
+
it "allows to have a nested tag" do
|
85
|
+
expect(AdHocTemplate::Parser.parse("a test string with a nested tag; [[ an outer tag and [[ an inner tag ]] ]]", :square_brackets)).to eq([["a test string with a nested tag; "],
|
86
|
+
[[" an outer tag and "],
|
87
|
+
[[" an inner tag "]],
|
88
|
+
[" "]]])
|
89
|
+
end
|
90
|
+
|
91
|
+
it "may have iteration tags." do
|
92
|
+
tree = AdHocTemplate::Parser.parse("a test string with a nested tag: [[# an iteration tag and [[ an inner tag ]] #]] and [[ another tag ]]", :square_brackets)
|
93
|
+
expect(tree).to eq([["a test string with a nested tag: "],
|
94
|
+
[[" an iteration tag and "],
|
95
|
+
[[" an inner tag "]],
|
96
|
+
[" "]],
|
97
|
+
[" and "],
|
98
|
+
[[" another tag "]]])
|
99
|
+
expect(tree[1]).to be_a_kind_of(AdHocTemplate::Parser::IterationTagNode)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "may contain lines that consist only of an iteration tag" do
|
103
|
+
tree = AdHocTemplate::Parser.parse("[[#iterations
|
104
|
+
content
|
105
|
+
#]]
|
106
|
+
", :square_brackets)
|
107
|
+
expect(tree).to eq([[["content\n"]]])
|
108
|
+
end
|
109
|
+
|
110
|
+
it "must return an empty array when template is an empty string" do
|
111
|
+
tree = AdHocTemplate::Parser.parse("", :square_brackets)
|
112
|
+
expect(tree).to eq([])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "with the curly brackets tag type" do
|
117
|
+
it "returns a tree of TagNode and Leaf" do
|
118
|
+
expect(AdHocTemplate::Parser.parse("a test string with tags ({{ the first tag }} and {{ the second tag }}) in it", :curly_brackets)).to eq([["a test string with tags ("],
|
119
|
+
[[" the first tag "]],
|
120
|
+
[" and "],
|
121
|
+
[[" the second tag "]],
|
122
|
+
[") in it"]])
|
123
|
+
end
|
124
|
+
|
125
|
+
it "allows to have a nested tag" do
|
126
|
+
expect(AdHocTemplate::Parser.parse("a test string with a nested tag; {{ an outer tag and {{ an inner tag }} }}", :curly_brackets)).to eq([["a test string with a nested tag; "],
|
127
|
+
[[" an outer tag and "],
|
128
|
+
[[" an inner tag "]],
|
129
|
+
[" "]]])
|
130
|
+
end
|
131
|
+
|
132
|
+
it "may have iteration tags." do
|
133
|
+
tree = AdHocTemplate::Parser.parse("a test string with a nested tag: {{# an iteration tag and {{ an inner tag }} #}} and {{ another tag }}", :curly_brackets)
|
134
|
+
expect(tree).to eq([["a test string with a nested tag: "],
|
135
|
+
[[" an iteration tag and "],
|
136
|
+
[[" an inner tag "]],
|
137
|
+
[" "]],
|
138
|
+
[" and "],
|
139
|
+
[[" another tag "]]])
|
140
|
+
expect(tree[1]).to be_a_kind_of(AdHocTemplate::Parser::IterationTagNode)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "may contain lines that consist only of an iteration tag" do
|
144
|
+
tree = AdHocTemplate::Parser.parse("{{#iterations
|
145
|
+
content
|
146
|
+
#}}
|
147
|
+
", :curly_brackets)
|
148
|
+
expect(tree).to eq([[["content\n"]]])
|
149
|
+
end
|
150
|
+
|
151
|
+
it "must return an empty array when template is an empty string" do
|
152
|
+
tree = AdHocTemplate::Parser.parse("", :curly_brackets)
|
153
|
+
expect(tree).to eq([])
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it("spaces at the head of a line should be preserved when the line is just after a start tag of IterationTagNode") do
|
158
|
+
tree = AdHocTemplate::Parser.parse("<%#iteration\n the second line\nthe third line")
|
159
|
+
expect(tree).to eq([[[" the second line\nthe third line"]]])
|
160
|
+
end
|
161
|
+
|
162
|
+
it("should not add a newline at the head of IterationTagNode when the type of the node is not specified") do
|
163
|
+
tree = AdHocTemplate::Parser.parse("a test string with tags\n<%#iteration_block\nthe value of sub_key1 is <%= sub_key1 %>.\n<%#\n the value of sub_key2 is <%= sub_key2 %>.\n#%>\n#%>")
|
164
|
+
expect(tree).to eq([["a test string with tags\n"], [["the value of sub_key1 is "], [["sub_key1 "]], [".\n"], [[" the value of sub_key2 is "], [["sub_key2 "]], [".\n"]]]])
|
165
|
+
end
|
166
|
+
|
167
|
+
describe "with the xml_like1 tag type" do
|
168
|
+
it "returns a tree of TagNode and Leaf" do
|
169
|
+
expect(AdHocTemplate::Parser.parse("a test string with tags (<!--% the first tag %--> and <!--% the second tag %-->) in it", :xml_like1)).to eq([["a test string with tags ("],
|
170
|
+
[[" the first tag "]],
|
171
|
+
[" and "],
|
172
|
+
[[" the second tag "]],
|
173
|
+
[") in it"]])
|
174
|
+
end
|
175
|
+
|
176
|
+
it "allows to have a nested tag" do
|
177
|
+
expect(AdHocTemplate::Parser.parse("a test string with a nested tag; <!--% an outer tag and <!--% an inner tag %--> %-->", :xml_like1)).to eq([["a test string with a nested tag; "],
|
178
|
+
[[" an outer tag and "],
|
179
|
+
[[" an inner tag "]],
|
180
|
+
[" "]]])
|
181
|
+
end
|
182
|
+
|
183
|
+
it "may have iteration tags." do
|
184
|
+
tree = AdHocTemplate::Parser.parse("a test string with a nested tag: <iterate> an iteration tag and <!--% an inner tag %--> </iterate> and <!--% another tag %-->", :xml_like1)
|
185
|
+
expect(tree).to eq([["a test string with a nested tag: "],
|
186
|
+
[[" an iteration tag and "],
|
187
|
+
[[" an inner tag "]],
|
188
|
+
[" "]],
|
189
|
+
[" and "],
|
190
|
+
[[" another tag "]]])
|
191
|
+
expect(tree[1]).to be_a_kind_of(AdHocTemplate::Parser::IterationTagNode)
|
192
|
+
end
|
193
|
+
|
194
|
+
it "may contain lines that consist only of an iteration tag" do
|
195
|
+
tree = AdHocTemplate::Parser.parse("<iterate>iterations
|
196
|
+
content
|
197
|
+
</iterate>
|
198
|
+
", :xml_like1)
|
199
|
+
expect(tree).to eq([[["content\n"]]])
|
200
|
+
end
|
201
|
+
|
202
|
+
it "must return an empty array when template is an empty string" do
|
203
|
+
tree = AdHocTemplate::Parser.parse("", :xml_like1)
|
204
|
+
expect(tree).to eq([])
|
205
|
+
end
|
206
|
+
|
207
|
+
it("spaces at the head of a line should be preserved when the line is just after a start tag of IterationTagNode") do
|
208
|
+
tree = AdHocTemplate::Parser.parse("<iterate>iteration\n the second line\nthe third line</iterate>", :xml_like1)
|
209
|
+
expect(tree).to eq([[[" the second line\nthe third line"]]])
|
210
|
+
end
|
211
|
+
|
212
|
+
it("should not add a newline at the head of IterationTagNode when the type of the node is not specified") do
|
213
|
+
tree = AdHocTemplate::Parser.parse("a test string with tags\n<iterate>iteration_block\nthe value of sub_key1 is <!--%= sub_key1 %-->.\n<iterate>\n the value of sub_key2 is <!--%= sub_key2 %-->.\n</iterate>\n</iterate>", :xml_like1)
|
214
|
+
expect(tree).to eq([["a test string with tags\n"], [["the value of sub_key1 is "], [["sub_key1 "]], [".\n"], [[" the value of sub_key2 is "], [["sub_key2 "]], [".\n"]]]])
|
215
|
+
end
|
216
|
+
|
217
|
+
it "removes indents from the lines which contain only iteration tag" do
|
218
|
+
template_without_indent = <<TEMPLATE_WITHOUT_INDENT
|
219
|
+
A template with an iteration tag
|
220
|
+
|
221
|
+
<iterate>
|
222
|
+
This part will be repeated with <!--% variable %-->
|
223
|
+
</iterate>
|
224
|
+
|
225
|
+
TEMPLATE_WITHOUT_INDENT
|
226
|
+
|
227
|
+
template_with_indent = <<TEMPLATE
|
228
|
+
A template with an iteration tag
|
229
|
+
|
230
|
+
<iterate>
|
231
|
+
This part will be repeated with <!--% variable %-->
|
232
|
+
</iterate>
|
233
|
+
|
234
|
+
TEMPLATE
|
235
|
+
|
236
|
+
without_indent = AdHocTemplate::Parser.parse(template_without_indent, :xml_like1)
|
237
|
+
with_indent = AdHocTemplate::Parser.parse(template_with_indent, :xml_like1)
|
238
|
+
|
239
|
+
expect(with_indent).to eq(without_indent)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe "with the xml_like2 tag type" do
|
244
|
+
it "returns a tree of TagNode and Leaf" do
|
245
|
+
expect(AdHocTemplate::Parser.parse("a test string with tags (<fill> the first tag </fill> and <fill> the second tag </fill>) in it", :xml_like2)).to eq([["a test string with tags ("],
|
246
|
+
[[" the first tag "]],
|
247
|
+
[" and "],
|
248
|
+
[[" the second tag "]],
|
249
|
+
[") in it"]])
|
250
|
+
end
|
251
|
+
|
252
|
+
it "allows to have a nested tag" do
|
253
|
+
expect(AdHocTemplate::Parser.parse("a test string with a nested tag; <fill> an outer tag and <fill> an inner tag </fill> </fill>", :xml_like2)).to eq([["a test string with a nested tag; "],
|
254
|
+
[[" an outer tag and "],
|
255
|
+
[[" an inner tag "]],
|
256
|
+
[" "]]])
|
257
|
+
end
|
258
|
+
|
259
|
+
it "may have iteration tags." do
|
260
|
+
tree = AdHocTemplate::Parser.parse("a test string with a nested tag: <iterate> an iteration tag and <fill> an inner tag </fill> </iterate> and <fill> another tag </fill>", :xml_like2)
|
261
|
+
expect(tree).to eq([["a test string with a nested tag: "],
|
262
|
+
[[" an iteration tag and "],
|
263
|
+
[[" an inner tag "]],
|
264
|
+
[" "]],
|
265
|
+
[" and "],
|
266
|
+
[[" another tag "]]])
|
267
|
+
expect(tree[1]).to be_a_kind_of(AdHocTemplate::Parser::IterationTagNode)
|
268
|
+
end
|
269
|
+
|
270
|
+
it "may contain lines that consist only of an iteration tag" do
|
271
|
+
tree = AdHocTemplate::Parser.parse("<iterate>iterations
|
272
|
+
content
|
273
|
+
</iterate>
|
274
|
+
", :xml_like2)
|
275
|
+
expect(tree).to eq([[["content\n"]]])
|
276
|
+
end
|
277
|
+
|
278
|
+
it "must return an empty array when template is an empty string" do
|
279
|
+
tree = AdHocTemplate::Parser.parse("", :xml_like2)
|
280
|
+
expect(tree).to eq([])
|
281
|
+
end
|
282
|
+
|
283
|
+
it("spaces at the head of a line should be preserved when the line is just after a start tag of IterationTagNode") do
|
284
|
+
tree = AdHocTemplate::Parser.parse("<iterate>iteration\n the second line\nthe third line</iterate>", :xml_like2)
|
285
|
+
expect(tree).to eq([[[" the second line\nthe third line"]]])
|
286
|
+
end
|
287
|
+
|
288
|
+
it("should not add a newline at the head of IterationTagNode when the type of the node is not specified") do
|
289
|
+
tree = AdHocTemplate::Parser.parse("a test string with tags\n<iterate>iteration_block\nthe value of sub_key1 is <fill>= sub_key1 </fill>.\n<iterate>\n the value of sub_key2 is <fill>= sub_key2 </fill>.\n</iterate>\n</iterate>", :xml_like2)
|
290
|
+
expect(tree).to eq([["a test string with tags\n"], [["the value of sub_key1 is "], [["sub_key1 "]], [".\n"], [[" the value of sub_key2 is "], [["sub_key2 "]], [".\n"]]]])
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
describe "with the xml_comment_like tag type" do
|
295
|
+
it "returns a tree of TagNode and Leaf" do
|
296
|
+
expect(AdHocTemplate::Parser.parse("a test string with tags (<!--% the first tag %--> and <!--% the second tag %-->) in it", :xml_comment_like)).to eq([["a test string with tags ("],
|
297
|
+
[[" the first tag "]],
|
298
|
+
[" and "],
|
299
|
+
[[" the second tag "]],
|
300
|
+
[") in it"]])
|
301
|
+
end
|
302
|
+
|
303
|
+
it "allows to have a nested tag" do
|
304
|
+
expect(AdHocTemplate::Parser.parse("a test string with a nested tag; <!--% an outer tag and <!--% an inner tag %--> %-->", :xml_comment_like)).to eq([["a test string with a nested tag; "],
|
305
|
+
[[" an outer tag and "],
|
306
|
+
[[" an inner tag "]],
|
307
|
+
[" "]]])
|
308
|
+
end
|
309
|
+
|
310
|
+
it "may have iteration tags." do
|
311
|
+
tree = AdHocTemplate::Parser.parse("a test string with a nested tag: <!--%iterate%--> an iteration tag and <!--% an inner tag %--> <!--%/iterate%--> and <!--% another tag %-->", :xml_comment_like)
|
312
|
+
expect(tree).to eq([["a test string with a nested tag: "],
|
313
|
+
[[" an iteration tag and "],
|
314
|
+
[[" an inner tag "]],
|
315
|
+
[" "]],
|
316
|
+
[" and "],
|
317
|
+
[[" another tag "]]])
|
318
|
+
expect(tree[1]).to be_a_kind_of(AdHocTemplate::Parser::IterationTagNode)
|
319
|
+
end
|
320
|
+
|
321
|
+
it "may contain lines that consist only of an iteration tag" do
|
322
|
+
tree = AdHocTemplate::Parser.parse("<!--%iterate%-->iterations
|
323
|
+
content
|
324
|
+
<!--%/iterate%-->
|
325
|
+
", :xml_comment_like)
|
326
|
+
expect(tree).to eq([[["content\n"]]])
|
327
|
+
end
|
328
|
+
|
329
|
+
it "must return an empty array when template is an empty string" do
|
330
|
+
tree = AdHocTemplate::Parser.parse("", :xml_comment_like)
|
331
|
+
expect(tree).to eq([])
|
332
|
+
end
|
333
|
+
|
334
|
+
it("spaces at the head of a line should be preserved when the line is just after a start tag of IterationTagNode") do
|
335
|
+
tree = AdHocTemplate::Parser.parse("<!--%iterate%-->iteration\n the second line\nthe third line<!--%/iterate%-->", :xml_comment_like)
|
336
|
+
expect(tree).to eq([[[" the second line\nthe third line"]]])
|
337
|
+
end
|
338
|
+
|
339
|
+
it("should not add a newline at the head of IterationTagNode when the type of the node is not specified") do
|
340
|
+
tree = AdHocTemplate::Parser.parse("a test string with tags\n<!--%iterate%-->iteration_block\nthe value of sub_key1 is <!--%= sub_key1 %-->.\n<!--%iterate%-->\n the value of sub_key2 is <!--%= sub_key2 %-->.\n<!--%/iterate%-->\n<!--%/iterate%-->", :xml_comment_like)
|
341
|
+
expect(tree).to eq([["a test string with tags\n"], [["the value of sub_key1 is "], [["sub_key1 "]], [".\n"], [[" the value of sub_key2 is "], [["sub_key2 "]], [".\n"]]]])
|
342
|
+
end
|
343
|
+
|
344
|
+
it "removes indents from the lines which contain only iteration tag" do
|
345
|
+
template_without_indent = <<TEMPLATE_WITHOUT_INDENT
|
346
|
+
A template with an iteration tag
|
347
|
+
|
348
|
+
<!--%iterate%-->
|
349
|
+
This part will be repeated with <!--% variable %-->
|
350
|
+
<!--%/iterate%-->
|
351
|
+
|
352
|
+
TEMPLATE_WITHOUT_INDENT
|
353
|
+
|
354
|
+
template_with_indent = <<TEMPLATE
|
355
|
+
A template with an iteration tag
|
356
|
+
|
357
|
+
<!--%iterate%-->
|
358
|
+
This part will be repeated with <!--% variable %-->
|
359
|
+
<!--%/iterate%-->
|
360
|
+
|
361
|
+
TEMPLATE
|
362
|
+
|
363
|
+
without_indent = AdHocTemplate::Parser.parse(template_without_indent, :xml_comment_like)
|
364
|
+
with_indent = AdHocTemplate::Parser.parse(template_with_indent, :xml_comment_like)
|
365
|
+
|
366
|
+
expect(with_indent).to eq(without_indent)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
describe ".register_user_defined_tag_type" do
|
371
|
+
it "allow to defined a tag type in YAML format" do
|
372
|
+
tag_type_config = <<CONFIG
|
373
|
+
tag_name: xml_like3
|
374
|
+
tag: ["<!--%", "%-->"]
|
375
|
+
iteration_tag: ["<repeat>", "</repeat>"]
|
376
|
+
remove_indent: true
|
377
|
+
CONFIG
|
378
|
+
AdHocTemplate::Parser.register_user_defined_tag_type(tag_type_config)
|
379
|
+
defined_tag_type = AdHocTemplate::Parser::TagType[:xml_like3]
|
380
|
+
expect(defined_tag_type.iteration_start).to eq('<repeat>')
|
381
|
+
expect(defined_tag_type.iteration_end).to eq('</repeat>')
|
382
|
+
expect(defined_tag_type.remove_iteration_indent).to eq(true)
|
383
|
+
end
|
384
|
+
|
385
|
+
it "raises an error if a given definition does not contain sufficient information" do
|
386
|
+
tag_type_config = <<CONFIG
|
387
|
+
tag_name:
|
388
|
+
tag: ["<!--%", "%-->"]
|
389
|
+
iteration_tag: ["<repeat>", "</repeat>"]
|
390
|
+
remove_indent: true
|
391
|
+
CONFIG
|
392
|
+
expect {
|
393
|
+
AdHocTemplate::Parser.register_user_defined_tag_type(tag_type_config)
|
394
|
+
}.to raise_error(AdHocTemplate::Parser::UserDefinedTagTypeConfigError,
|
395
|
+
'"tag_name" should be defined.')
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|