1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
|
require 'test_helper'
require 'asciidoctor/extensions'
class SamplePreprocessor < Asciidoctor::Extensions::Preprocessor
end
class SampleIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
end
class SampleTreeprocessor < Asciidoctor::Extensions::Treeprocessor
end
class SamplePostprocessor < Asciidoctor::Extensions::Postprocessor
end
class SampleBlock < Asciidoctor::Extensions::BlockProcessor
end
class SampleBlockMacro < Asciidoctor::Extensions::BlockMacroProcessor
end
class SampleInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
end
class ScrubHeaderPreprocessor < Asciidoctor::Extensions::Preprocessor
def process reader, lines
while !lines.empty? && !lines.first.start_with?('=')
lines.shift
reader.advance
end
#lines
reader
end
end
class BoilerplateTextIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
def handles? target
target.end_with? '.txt'
end
def process reader, target, attributes
case target
when 'lorem-ipsum.txt'
content = ["Lorem ipsum dolor sit amet...\n"]
reader.push_include content, target, target, 1, attributes
else
nil
end
end
end
class ReplaceAuthorTreeprocessor < Asciidoctor::Extensions::Treeprocessor
def process
@document.attributes['firstname'] = 'Ghost'
@document.attributes['author'] = 'Ghost Writer'
end
end
class StripAttributesPostprocessor < Asciidoctor::Extensions::Postprocessor
def process output
output.gsub(/<(\w+).*?>/m, "<\\1>")
end
end
class UppercaseBlock < Asciidoctor::Extensions::BlockProcessor
def process parent, reader, attributes
Asciidoctor::Block.new parent, :paragraph, :source => reader.lines.map {|line| line.upcase }
end
end
class SnippetMacro < Asciidoctor::Extensions::BlockMacroProcessor
def process parent, target, attributes
Asciidoctor::Block.new parent, :pass, :content_model => :raw, :source => %(<script src="http://example.com/#{target}.js"></script>)
end
end
class TemperatureMacro < Asciidoctor::Extensions::InlineMacroProcessor
def process parent, target, attributes
temperature_unit = @document.attr('temperature-unit', 'C')
c = target.to_f
if temperature_unit == 'C'
text = %(#{c} °C)
elsif temperature_unit == 'F'
f = c * 1.8 + 32
text = %(#{f} °F)
else
text = target
end
text
end
end
class SampleExtension < Asciidoctor::Extensions::Extension
def self.activate(registry, document)
document.attributes['activate-method-called'] = ''
registry.preprocessor SamplePreprocessor
end
end
context 'Extensions' do
context 'Register' do
test 'should register extension class' do
begin
Asciidoctor::Extensions.register SampleExtension
assert_not_nil Asciidoctor::Extensions.registered
assert_equal 1, Asciidoctor::Extensions.registered.size
assert_equal SampleExtension, Asciidoctor::Extensions.registered.first
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should be able to self register extension class' do
begin
SampleExtension.register
assert_not_nil Asciidoctor::Extensions.registered
assert_equal 1, Asciidoctor::Extensions.registered.size
assert_equal SampleExtension, Asciidoctor::Extensions.registered.first
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should register extension class from string' do
begin
Asciidoctor::Extensions.register 'SampleExtension'
assert_not_nil Asciidoctor::Extensions.registered
assert_equal 1, Asciidoctor::Extensions.registered.size
assert_equal SampleExtension, Asciidoctor::Extensions.registered.first
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should register extension block' do
begin
Asciidoctor::Extensions.register do |document|
end
assert_not_nil Asciidoctor::Extensions.registered
assert_equal 1, Asciidoctor::Extensions.registered.size
assert Asciidoctor::Extensions.registered.first.is_a?(Proc)
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should get class for name' do
clazz = Asciidoctor::Extensions.class_for_name('Asciidoctor::Extensions')
assert_not_nil clazz
assert_equal Asciidoctor::Extensions, clazz
end
end
context 'Activate' do
test 'should call activate on extension class' do
begin
doc = Asciidoctor::Document.new
Asciidoctor::Extensions.register SampleExtension
registry = Asciidoctor::Extensions::Registry.new doc
assert doc.attr? 'activate-method-called'
assert registry.preprocessors?
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should invoke extension block' do
begin
doc = Asciidoctor::Document.new
Asciidoctor::Extensions.register do |document|
document.attributes['block-called'] = ''
preprocessor SamplePreprocessor
end
registry = Asciidoctor::Extensions::Registry.new doc
assert doc.attr? 'block-called'
assert registry.preprocessors?
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should create registry in Document if extensions are loaded' do
begin
SampleExtension.register
doc = Asciidoctor::Document.new
assert doc.extensions?
assert doc.extensions.is_a? Asciidoctor::Extensions::Registry
ensure
Asciidoctor::Extensions.unregister_all
end
end
end
context 'Instantiate' do
test 'should instantiate preprocessors' do
registry = Asciidoctor::Extensions::Registry.new
registry.preprocessor SamplePreprocessor
assert registry.preprocessors?
processors = registry.load_preprocessors Asciidoctor::Document.new
assert_equal 1, processors.size
assert processors.first.is_a? SamplePreprocessor
end
test 'should instantiate include processors' do
registry = Asciidoctor::Extensions::Registry.new
registry.include_processor SampleIncludeProcessor
assert registry.include_processors?
processors = registry.load_include_processors Asciidoctor::Document.new
assert_equal 1, processors.size
assert processors.first.is_a? SampleIncludeProcessor
end
test 'should instantiate treeprocessors' do
registry = Asciidoctor::Extensions::Registry.new
registry.treeprocessor SampleTreeprocessor
assert registry.treeprocessors?
processors = registry.load_treeprocessors Asciidoctor::Document.new
assert_equal 1, processors.size
assert processors.first.is_a? SampleTreeprocessor
end
test 'should instantiate postprocessors' do
registry = Asciidoctor::Extensions::Registry.new
registry.postprocessor SamplePostprocessor
assert registry.postprocessors?
processors = registry.load_postprocessors Asciidoctor::Document.new
assert_equal 1, processors.size
assert processors.first.is_a? SamplePostprocessor
end
test 'should instantiate block processor' do
registry = Asciidoctor::Extensions::Registry.new
registry.block :sample, SampleBlock
assert registry.blocks?
assert registry.processor_registered_for_block? :sample, :paragraph
processor = registry.load_block_processor :sample, Asciidoctor::Document.new
assert processor.is_a? SampleBlock
end
test 'should not match block processor for unsupported context' do
registry = Asciidoctor::Extensions::Registry.new
registry.block :sample, SampleBlock
assert !(registry.processor_registered_for_block? :sample, :sidebar)
end
test 'should instantiate block macro processor' do
registry = Asciidoctor::Extensions::Registry.new
registry.block_macro 'sample', SampleBlockMacro
assert registry.block_macros?
assert registry.processor_registered_for_block_macro? 'sample'
processor = registry.load_block_macro_processor 'sample', Asciidoctor::Document.new
assert processor.is_a? SampleBlockMacro
end
test 'should instantiate inline macro processor' do
registry = Asciidoctor::Extensions::Registry.new
registry.inline_macro 'sample', SampleInlineMacro
assert registry.inline_macros?
assert registry.processor_registered_for_inline_macro? 'sample'
processor = registry.load_inline_macro_processor 'sample', Asciidoctor::Document.new
assert processor.is_a? SampleInlineMacro
end
end
context 'Integration' do
test 'should invoke preprocessors before parsing document' do
input = <<-EOS
junk line
= Document Title
sample content
EOS
begin
Asciidoctor::Extensions.register do |document|
preprocessor ScrubHeaderPreprocessor
end
doc = document_from_string input
assert doc.has_header?
assert_equal 'Document Title', doc.doctitle
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should invoke include processor to process include macro' do
input = <<-EOS
before
include::lorem-ipsum.txt[]
after
EOS
begin
Asciidoctor::Extensions.register do |document|
include_processor BoilerplateTextIncludeProcessor
end
result = render_string input, :safe => :server
assert_css '.paragraph > p', result, 3
assert result.include?('before')
assert result.include?('Lorem ipsum')
assert result.include?('after')
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should invoke treeprocessors after parsing document' do
input = <<-EOS
= Document Title
Doc Writer
content
EOS
begin
Asciidoctor::Extensions.register do |document|
treeprocessor ReplaceAuthorTreeprocessor
end
doc = document_from_string input
assert_equal 'Ghost Writer', doc.author
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should invoke postprocessors after rendering document' do
input = <<-EOS
* one
* two
* three
EOS
begin
Asciidoctor::Extensions.register do |document|
postprocessor StripAttributesPostprocessor
end
output = render_string input
assert_no_match(/<div class="ulist">/, output)
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should invoke processor for custom block' do
input = <<-EOS
[yell]
Hi there!
EOS
begin
Asciidoctor::Extensions.register do |document|
block :yell, UppercaseBlock
end
output = render_embedded_string input
assert_xpath '//p', output, 1
assert_xpath '//p[text()="HI THERE!"]', output, 1
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should invoke processor for custom block macro' do
input = <<-EOS
snippet::12345[]
EOS
begin
Asciidoctor::Extensions.register do |document|
block_macro :snippet, SnippetMacro
end
output = render_embedded_string input
assert output.include?('<script src="http://example.com/12345.js"></script>')
ensure
Asciidoctor::Extensions.unregister_all
end
end
test 'should invoke processor for custom inline macro' do
input = <<-EOS
Room temperature is degrees:25[].
EOS
begin
Asciidoctor::Extensions.register do |document|
inline_macro :degrees, TemperatureMacro
end
output = render_embedded_string input, :attributes => {'temperature-unit' => 'F'}
assert output.include?('Room temperature is 77.0 °F.')
ensure
Asciidoctor::Extensions.unregister_all
end
end
end
end
|