asciidoctor 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of asciidoctor might be problematic. Click here for more details.

Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +387 -0
  3. data/README.adoc +358 -348
  4. data/asciidoctor.gemspec +30 -9
  5. data/bin/asciidoctor +3 -0
  6. data/bin/asciidoctor-safe +3 -0
  7. data/compat/asciidoc.conf +76 -4
  8. data/lib/asciidoctor.rb +174 -79
  9. data/lib/asciidoctor/abstract_block.rb +131 -101
  10. data/lib/asciidoctor/abstract_node.rb +108 -26
  11. data/lib/asciidoctor/attribute_list.rb +1 -1
  12. data/lib/asciidoctor/backends/_stylesheets.rb +204 -62
  13. data/lib/asciidoctor/backends/base_template.rb +11 -22
  14. data/lib/asciidoctor/backends/docbook45.rb +158 -163
  15. data/lib/asciidoctor/backends/docbook5.rb +103 -0
  16. data/lib/asciidoctor/backends/html5.rb +662 -445
  17. data/lib/asciidoctor/block.rb +54 -44
  18. data/lib/asciidoctor/cli/invoker.rb +41 -20
  19. data/lib/asciidoctor/cli/options.rb +66 -20
  20. data/lib/asciidoctor/debug.rb +1 -1
  21. data/lib/asciidoctor/document.rb +265 -100
  22. data/lib/asciidoctor/extensions.rb +443 -0
  23. data/lib/asciidoctor/helpers.rb +38 -6
  24. data/lib/asciidoctor/inline.rb +5 -5
  25. data/lib/asciidoctor/lexer.rb +532 -250
  26. data/lib/asciidoctor/{list_item.rb → list.rb} +33 -13
  27. data/lib/asciidoctor/path_resolver.rb +28 -2
  28. data/lib/asciidoctor/reader.rb +814 -455
  29. data/lib/asciidoctor/renderer.rb +128 -42
  30. data/lib/asciidoctor/section.rb +55 -41
  31. data/lib/asciidoctor/substituters.rb +380 -107
  32. data/lib/asciidoctor/table.rb +40 -30
  33. data/lib/asciidoctor/version.rb +1 -1
  34. data/man/asciidoctor.1 +32 -96
  35. data/man/{asciidoctor.ad → asciidoctor.adoc} +57 -48
  36. data/test/attributes_test.rb +200 -27
  37. data/test/blocks_test.rb +361 -22
  38. data/test/document_test.rb +496 -81
  39. data/test/extensions_test.rb +448 -0
  40. data/test/fixtures/basic-docinfo-footer.html +6 -0
  41. data/test/fixtures/basic-docinfo-footer.xml +8 -0
  42. data/test/fixtures/basic-docinfo.xml +3 -3
  43. data/test/fixtures/basic.asciidoc +1 -0
  44. data/test/fixtures/child-include.adoc +5 -0
  45. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +6 -0
  46. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +1 -0
  47. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +3 -0
  48. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +5 -0
  49. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +6 -0
  50. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +3 -0
  51. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +5 -0
  52. data/test/fixtures/docinfo-footer.html +1 -0
  53. data/test/fixtures/docinfo-footer.xml +9 -0
  54. data/test/fixtures/docinfo.xml +1 -0
  55. data/test/fixtures/grandchild-include.adoc +3 -0
  56. data/test/fixtures/parent-include-restricted.adoc +5 -0
  57. data/test/fixtures/parent-include.adoc +5 -0
  58. data/test/invoker_test.rb +82 -8
  59. data/test/lexer_test.rb +21 -3
  60. data/test/links_test.rb +34 -2
  61. data/test/lists_test.rb +304 -7
  62. data/test/options_test.rb +19 -3
  63. data/test/paragraphs_test.rb +13 -0
  64. data/test/paths_test.rb +22 -0
  65. data/test/preamble_test.rb +20 -0
  66. data/test/reader_test.rb +1096 -644
  67. data/test/renderer_test.rb +152 -12
  68. data/test/sections_test.rb +417 -76
  69. data/test/substitutions_test.rb +339 -138
  70. data/test/tables_test.rb +109 -4
  71. data/test/test_helper.rb +79 -13
  72. data/test/text_test.rb +111 -11
  73. metadata +54 -18
@@ -0,0 +1,448 @@
1
+ require 'test_helper'
2
+ require 'asciidoctor/extensions'
3
+
4
+ class SamplePreprocessor < Asciidoctor::Extensions::Preprocessor
5
+ end
6
+
7
+ class SampleIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
8
+ end
9
+
10
+ class SampleTreeprocessor < Asciidoctor::Extensions::Treeprocessor
11
+ end
12
+
13
+ class SamplePostprocessor < Asciidoctor::Extensions::Postprocessor
14
+ end
15
+
16
+ class SampleBlock < Asciidoctor::Extensions::BlockProcessor
17
+ end
18
+
19
+ class SampleBlockMacro < Asciidoctor::Extensions::BlockMacroProcessor
20
+ end
21
+
22
+ class SampleInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
23
+ end
24
+
25
+ class ScrubHeaderPreprocessor < Asciidoctor::Extensions::Preprocessor
26
+ def process reader, lines
27
+ while !lines.empty? && !lines.first.start_with?('=')
28
+ lines.shift
29
+ reader.advance
30
+ end
31
+ #lines
32
+ reader
33
+ end
34
+ end
35
+
36
+ class BoilerplateTextIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
37
+ def handles? target
38
+ target.end_with? '.txt'
39
+ end
40
+
41
+ def process reader, target, attributes
42
+ case target
43
+ when 'lorem-ipsum.txt'
44
+ content = ["Lorem ipsum dolor sit amet...\n"]
45
+ reader.push_include content, target, target, 1, attributes
46
+ else
47
+ nil
48
+ end
49
+ end
50
+ end
51
+
52
+ class ReplaceAuthorTreeprocessor < Asciidoctor::Extensions::Treeprocessor
53
+ def process
54
+ @document.attributes['firstname'] = 'Ghost'
55
+ @document.attributes['author'] = 'Ghost Writer'
56
+ end
57
+ end
58
+
59
+ class StripAttributesPostprocessor < Asciidoctor::Extensions::Postprocessor
60
+ def process output
61
+ output.gsub(/<(\w+).*?>/m, "<\\1>")
62
+ end
63
+ end
64
+
65
+ class UppercaseBlock < Asciidoctor::Extensions::BlockProcessor
66
+ def process parent, reader, attributes
67
+ Asciidoctor::Block.new parent, :paragraph, :source => reader.lines.map {|line| line.upcase }
68
+ end
69
+ end
70
+
71
+ class SnippetMacro < Asciidoctor::Extensions::BlockMacroProcessor
72
+ def process parent, target, attributes
73
+ Asciidoctor::Block.new parent, :pass, :content_model => :raw, :source => %(<script src="http://example.com/#{target}.js"></script>)
74
+ end
75
+ end
76
+
77
+ class TemperatureMacro < Asciidoctor::Extensions::InlineMacroProcessor
78
+ def process parent, target, attributes
79
+ temperature_unit = @document.attr('temperature-unit', 'C')
80
+ c = target.to_f
81
+ if temperature_unit == 'C'
82
+ text = %(#{c} &#176;C)
83
+ elsif temperature_unit == 'F'
84
+ f = c * 1.8 + 32
85
+ text = %(#{f} &#176;F)
86
+ else
87
+ text = target
88
+ end
89
+
90
+ text
91
+ end
92
+ end
93
+
94
+ class SampleExtension < Asciidoctor::Extensions::Extension
95
+ def self.activate(registry, document)
96
+ document.attributes['activate-method-called'] = ''
97
+ registry.preprocessor SamplePreprocessor
98
+ end
99
+ end
100
+
101
+ context 'Extensions' do
102
+ context 'Register' do
103
+ test 'should register extension class' do
104
+ begin
105
+ Asciidoctor::Extensions.register SampleExtension
106
+ assert_not_nil Asciidoctor::Extensions.registered
107
+ assert_equal 1, Asciidoctor::Extensions.registered.size
108
+ assert_equal SampleExtension, Asciidoctor::Extensions.registered.first
109
+ ensure
110
+ Asciidoctor::Extensions.unregister_all
111
+ end
112
+ end
113
+
114
+ test 'should be able to self register extension class' do
115
+ begin
116
+ SampleExtension.register
117
+ assert_not_nil Asciidoctor::Extensions.registered
118
+ assert_equal 1, Asciidoctor::Extensions.registered.size
119
+ assert_equal SampleExtension, Asciidoctor::Extensions.registered.first
120
+ ensure
121
+ Asciidoctor::Extensions.unregister_all
122
+ end
123
+ end
124
+
125
+ test 'should register extension class from string' do
126
+ begin
127
+ Asciidoctor::Extensions.register 'SampleExtension'
128
+ assert_not_nil Asciidoctor::Extensions.registered
129
+ assert_equal 1, Asciidoctor::Extensions.registered.size
130
+ assert_equal SampleExtension, Asciidoctor::Extensions.registered.first
131
+ ensure
132
+ Asciidoctor::Extensions.unregister_all
133
+ end
134
+ end
135
+
136
+ test 'should register extension block' do
137
+ begin
138
+ Asciidoctor::Extensions.register do |document|
139
+ end
140
+ assert_not_nil Asciidoctor::Extensions.registered
141
+ assert_equal 1, Asciidoctor::Extensions.registered.size
142
+ assert Asciidoctor::Extensions.registered.first.is_a?(Proc)
143
+ ensure
144
+ Asciidoctor::Extensions.unregister_all
145
+ end
146
+ end
147
+
148
+ test 'should get class for top-level class name' do
149
+ clazz = Asciidoctor::Extensions.class_for_name('Asciidoctor')
150
+ assert_not_nil clazz
151
+ assert_equal Asciidoctor, clazz
152
+ end
153
+
154
+ test 'should get class for class name in module' do
155
+ clazz = Asciidoctor::Extensions.class_for_name('Asciidoctor::Extensions')
156
+ assert_not_nil clazz
157
+ assert_equal Asciidoctor::Extensions, clazz
158
+ end
159
+
160
+ test 'should get class for class name resolved from root' do
161
+ clazz = Asciidoctor::Extensions.class_for_name('::Asciidoctor::Extensions')
162
+ assert_not_nil clazz
163
+ assert_equal Asciidoctor::Extensions, clazz
164
+ end
165
+
166
+ test 'should raise exception if cannot find class for name' do
167
+ begin
168
+ Asciidoctor::Extensions.class_for_name('InvalidModule::InvalidClass')
169
+ flunk 'Expecting RuntimeError to be raised'
170
+ rescue RuntimeError => e
171
+ assert_equal 'Could not resolve class for name: InvalidModule::InvalidClass', e.message
172
+ end
173
+ end
174
+
175
+ test 'should resolve class if class is given' do
176
+ clazz = Asciidoctor::Extensions.resolve_class(Asciidoctor::Extensions)
177
+ assert_not_nil clazz
178
+ assert_equal Asciidoctor::Extensions, clazz
179
+ end
180
+
181
+ test 'should resolve class if class from string' do
182
+ clazz = Asciidoctor::Extensions.resolve_class('Asciidoctor::Extensions')
183
+ assert_not_nil clazz
184
+ assert_equal Asciidoctor::Extensions, clazz
185
+ end
186
+ end
187
+
188
+ context 'Activate' do
189
+ test 'should call activate on extension class' do
190
+ begin
191
+ doc = Asciidoctor::Document.new
192
+ Asciidoctor::Extensions.register SampleExtension
193
+ registry = Asciidoctor::Extensions::Registry.new doc
194
+ assert doc.attr? 'activate-method-called'
195
+ assert registry.preprocessors?
196
+ ensure
197
+ Asciidoctor::Extensions.unregister_all
198
+ end
199
+ end
200
+
201
+ test 'should invoke extension block' do
202
+ begin
203
+ doc = Asciidoctor::Document.new
204
+ Asciidoctor::Extensions.register do |document|
205
+ document.attributes['block-called'] = ''
206
+ preprocessor SamplePreprocessor
207
+ end
208
+ registry = Asciidoctor::Extensions::Registry.new doc
209
+ assert doc.attr? 'block-called'
210
+ assert registry.preprocessors?
211
+ ensure
212
+ Asciidoctor::Extensions.unregister_all
213
+ end
214
+ end
215
+
216
+ test 'should create registry in Document if extensions are loaded' do
217
+ begin
218
+ SampleExtension.register
219
+ doc = Asciidoctor::Document.new
220
+ assert doc.extensions?
221
+ assert doc.extensions.is_a? Asciidoctor::Extensions::Registry
222
+ ensure
223
+ Asciidoctor::Extensions.unregister_all
224
+ end
225
+
226
+ end
227
+ end
228
+
229
+ context 'Instantiate' do
230
+ test 'should instantiate preprocessors' do
231
+ registry = Asciidoctor::Extensions::Registry.new
232
+ registry.preprocessor SamplePreprocessor
233
+ assert registry.preprocessors?
234
+ processors = registry.load_preprocessors Asciidoctor::Document.new
235
+ assert_equal 1, processors.size
236
+ assert processors.first.is_a? SamplePreprocessor
237
+ end
238
+
239
+ test 'should instantiate include processors' do
240
+ registry = Asciidoctor::Extensions::Registry.new
241
+ registry.include_processor SampleIncludeProcessor
242
+ assert registry.include_processors?
243
+ processors = registry.load_include_processors Asciidoctor::Document.new
244
+ assert_equal 1, processors.size
245
+ assert processors.first.is_a? SampleIncludeProcessor
246
+ end
247
+
248
+ test 'should instantiate treeprocessors' do
249
+ registry = Asciidoctor::Extensions::Registry.new
250
+ registry.treeprocessor SampleTreeprocessor
251
+ assert registry.treeprocessors?
252
+ processors = registry.load_treeprocessors Asciidoctor::Document.new
253
+ assert_equal 1, processors.size
254
+ assert processors.first.is_a? SampleTreeprocessor
255
+ end
256
+
257
+ test 'should instantiate postprocessors' do
258
+ registry = Asciidoctor::Extensions::Registry.new
259
+ registry.postprocessor SamplePostprocessor
260
+ assert registry.postprocessors?
261
+ processors = registry.load_postprocessors Asciidoctor::Document.new
262
+ assert_equal 1, processors.size
263
+ assert processors.first.is_a? SamplePostprocessor
264
+ end
265
+
266
+ test 'should instantiate block processor' do
267
+ registry = Asciidoctor::Extensions::Registry.new
268
+ registry.block :sample, SampleBlock
269
+ assert registry.blocks?
270
+ assert registry.processor_registered_for_block? :sample, :paragraph
271
+ processor = registry.load_block_processor :sample, Asciidoctor::Document.new
272
+ assert processor.is_a? SampleBlock
273
+ end
274
+
275
+ test 'should not match block processor for unsupported context' do
276
+ registry = Asciidoctor::Extensions::Registry.new
277
+ registry.block :sample, SampleBlock
278
+ assert !(registry.processor_registered_for_block? :sample, :sidebar)
279
+ end
280
+
281
+ test 'should instantiate block macro processor' do
282
+ registry = Asciidoctor::Extensions::Registry.new
283
+ registry.block_macro 'sample', SampleBlockMacro
284
+ assert registry.block_macros?
285
+ assert registry.processor_registered_for_block_macro? 'sample'
286
+ processor = registry.load_block_macro_processor 'sample', Asciidoctor::Document.new
287
+ assert processor.is_a? SampleBlockMacro
288
+ end
289
+
290
+ test 'should instantiate inline macro processor' do
291
+ registry = Asciidoctor::Extensions::Registry.new
292
+ registry.inline_macro 'sample', SampleInlineMacro
293
+ assert registry.inline_macros?
294
+ assert registry.processor_registered_for_inline_macro? 'sample'
295
+ processor = registry.load_inline_macro_processor 'sample', Asciidoctor::Document.new
296
+ assert processor.is_a? SampleInlineMacro
297
+ end
298
+
299
+ test 'should allow processors to be registered by a string name' do
300
+ registry = Asciidoctor::Extensions::Registry.new
301
+ registry.preprocessor 'SamplePreprocessor'
302
+ assert registry.preprocessors?
303
+ processors = registry.load_preprocessors Asciidoctor::Document.new
304
+ assert_equal 1, processors.size
305
+ assert processors.first.is_a? SamplePreprocessor
306
+ end
307
+ end
308
+
309
+ context 'Integration' do
310
+ test 'should invoke preprocessors before parsing document' do
311
+ input = <<-EOS
312
+ junk line
313
+
314
+ = Document Title
315
+
316
+ sample content
317
+ EOS
318
+
319
+ begin
320
+ Asciidoctor::Extensions.register do |document|
321
+ preprocessor ScrubHeaderPreprocessor
322
+ end
323
+
324
+ doc = document_from_string input
325
+ assert doc.has_header?
326
+ assert_equal 'Document Title', doc.doctitle
327
+ ensure
328
+ Asciidoctor::Extensions.unregister_all
329
+ end
330
+ end
331
+
332
+ test 'should invoke include processor to process include macro' do
333
+ input = <<-EOS
334
+ before
335
+
336
+ include::lorem-ipsum.txt[]
337
+
338
+ after
339
+ EOS
340
+
341
+ begin
342
+ Asciidoctor::Extensions.register do |document|
343
+ include_processor BoilerplateTextIncludeProcessor
344
+ end
345
+
346
+ result = render_string input, :safe => :server
347
+ assert_css '.paragraph > p', result, 3
348
+ assert result.include?('before')
349
+ assert result.include?('Lorem ipsum')
350
+ assert result.include?('after')
351
+ ensure
352
+ Asciidoctor::Extensions.unregister_all
353
+ end
354
+ end
355
+
356
+ test 'should invoke treeprocessors after parsing document' do
357
+ input = <<-EOS
358
+ = Document Title
359
+ Doc Writer
360
+
361
+ content
362
+ EOS
363
+
364
+ begin
365
+ Asciidoctor::Extensions.register do |document|
366
+ treeprocessor ReplaceAuthorTreeprocessor
367
+ end
368
+
369
+ doc = document_from_string input
370
+ assert_equal 'Ghost Writer', doc.author
371
+ ensure
372
+ Asciidoctor::Extensions.unregister_all
373
+ end
374
+ end
375
+
376
+ test 'should invoke postprocessors after rendering document' do
377
+ input = <<-EOS
378
+ * one
379
+ * two
380
+ * three
381
+ EOS
382
+
383
+ begin
384
+ Asciidoctor::Extensions.register do |document|
385
+ postprocessor StripAttributesPostprocessor
386
+ end
387
+
388
+ output = render_string input
389
+ assert_no_match(/<div class="ulist">/, output)
390
+ ensure
391
+ Asciidoctor::Extensions.unregister_all
392
+ end
393
+ end
394
+
395
+ test 'should invoke processor for custom block' do
396
+ input = <<-EOS
397
+ [yell]
398
+ Hi there!
399
+ EOS
400
+
401
+ begin
402
+ Asciidoctor::Extensions.register do |document|
403
+ block :yell, UppercaseBlock
404
+ end
405
+
406
+ output = render_embedded_string input
407
+ assert_xpath '//p', output, 1
408
+ assert_xpath '//p[text()="HI THERE!"]', output, 1
409
+ ensure
410
+ Asciidoctor::Extensions.unregister_all
411
+ end
412
+ end
413
+
414
+ test 'should invoke processor for custom block macro' do
415
+ input = <<-EOS
416
+ snippet::12345[]
417
+ EOS
418
+
419
+ begin
420
+ Asciidoctor::Extensions.register do |document|
421
+ block_macro :snippet, SnippetMacro
422
+ end
423
+
424
+ output = render_embedded_string input
425
+ assert output.include?('<script src="http://example.com/12345.js"></script>')
426
+ ensure
427
+ Asciidoctor::Extensions.unregister_all
428
+ end
429
+ end
430
+
431
+ test 'should invoke processor for custom inline macro' do
432
+ input = <<-EOS
433
+ Room temperature is degrees:25[].
434
+ EOS
435
+
436
+ begin
437
+ Asciidoctor::Extensions.register do |document|
438
+ inline_macro :degrees, TemperatureMacro
439
+ end
440
+
441
+ output = render_embedded_string input, :attributes => {'temperature-unit' => 'F'}
442
+ assert output.include?('Room temperature is 77.0 &#176;F.')
443
+ ensure
444
+ Asciidoctor::Extensions.unregister_all
445
+ end
446
+ end
447
+ end
448
+ end
@@ -0,0 +1,6 @@
1
+ <script>
2
+ (function() {
3
+ var p1 = document.createElement('script'); p1.async = true; p1.src = 'https://apis.google.com/js/plusone.js';
4
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(p1, s);
5
+ })();
6
+ </script>