asciidoctor 2.0.9 → 2.0.14
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/CHANGELOG.adoc +193 -16
- data/LICENSE +1 -1
- data/README-de.adoc +12 -13
- data/README-fr.adoc +11 -15
- data/README-jp.adoc +242 -185
- data/README-zh_CN.adoc +17 -18
- data/README.adoc +133 -131
- data/asciidoctor.gemspec +6 -6
- data/data/locale/attributes-ar.adoc +4 -3
- data/data/locale/attributes-be.adoc +23 -0
- data/data/locale/attributes-bg.adoc +4 -3
- data/data/locale/attributes-ca.adoc +6 -5
- data/data/locale/attributes-cs.adoc +4 -3
- data/data/locale/attributes-da.adoc +6 -5
- data/data/locale/attributes-de.adoc +4 -4
- data/data/locale/attributes-en.adoc +4 -4
- data/data/locale/attributes-es.adoc +6 -5
- data/data/locale/attributes-fa.adoc +4 -3
- data/data/locale/attributes-fi.adoc +4 -3
- data/data/locale/attributes-fr.adoc +6 -5
- data/data/locale/attributes-hu.adoc +4 -3
- data/data/locale/attributes-id.adoc +4 -3
- data/data/locale/attributes-it.adoc +6 -5
- data/data/locale/attributes-ja.adoc +4 -3
- data/data/locale/{attributes-kr.adoc → attributes-ko.adoc} +4 -3
- data/data/locale/attributes-nb.adoc +4 -3
- data/data/locale/attributes-nl.adoc +6 -5
- data/data/locale/attributes-nn.adoc +4 -3
- data/data/locale/attributes-pl.adoc +8 -7
- data/data/locale/attributes-pt.adoc +6 -5
- data/data/locale/attributes-pt_BR.adoc +6 -5
- data/data/locale/attributes-ro.adoc +4 -3
- data/data/locale/attributes-ru.adoc +6 -5
- data/data/locale/attributes-sr.adoc +4 -4
- data/data/locale/attributes-sr_Latn.adoc +4 -4
- data/data/locale/attributes-sv.adoc +4 -4
- data/data/locale/attributes-tr.adoc +4 -3
- data/data/locale/attributes-uk.adoc +6 -5
- data/data/locale/attributes-zh_CN.adoc +4 -3
- data/data/locale/attributes-zh_TW.adoc +4 -3
- data/data/reference/syntax.adoc +14 -7
- data/data/stylesheets/asciidoctor-default.css +30 -30
- data/lib/asciidoctor.rb +40 -14
- data/lib/asciidoctor/abstract_block.rb +9 -4
- data/lib/asciidoctor/abstract_node.rb +16 -6
- data/lib/asciidoctor/attribute_list.rb +63 -71
- data/lib/asciidoctor/cli/invoker.rb +2 -0
- data/lib/asciidoctor/cli/options.rb +10 -9
- data/lib/asciidoctor/convert.rb +167 -162
- data/lib/asciidoctor/converter.rb +13 -12
- data/lib/asciidoctor/converter/docbook5.rb +5 -9
- data/lib/asciidoctor/converter/html5.rb +58 -45
- data/lib/asciidoctor/converter/manpage.rb +61 -38
- data/lib/asciidoctor/converter/template.rb +3 -0
- data/lib/asciidoctor/document.rb +44 -51
- data/lib/asciidoctor/extensions.rb +2 -4
- data/lib/asciidoctor/helpers.rb +20 -15
- data/lib/asciidoctor/load.rb +102 -101
- data/lib/asciidoctor/parser.rb +40 -32
- data/lib/asciidoctor/path_resolver.rb +14 -12
- data/lib/asciidoctor/reader.rb +20 -13
- data/lib/asciidoctor/rx.rb +7 -6
- data/lib/asciidoctor/substitutors.rb +69 -50
- data/lib/asciidoctor/syntax_highlighter.rb +15 -7
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +1 -1
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +12 -4
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +7 -4
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +6 -7
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +33 -19
- data/lib/asciidoctor/table.rb +52 -23
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +8 -8
- data/man/asciidoctor.adoc +4 -4
- metadata +16 -15
@@ -257,6 +257,9 @@ class Converter::TemplateConverter < Converter::Base
|
|
257
257
|
if !name || name == 'erb'
|
258
258
|
require 'erb' unless defined? ::ERB.version
|
259
259
|
[::Tilt::ERBTemplate, {}]
|
260
|
+
elsif name == 'erubi'
|
261
|
+
Helpers.require_library 'erubi' unless defined? ::Erubis::Engine
|
262
|
+
[::Tilt::ErubiTemplate, {}]
|
260
263
|
elsif name == 'erubis'
|
261
264
|
Helpers.require_library 'erubis' unless defined? ::Erubis::FastEruby
|
262
265
|
[::Tilt::ErubisTemplate, { engine_class: ::Erubis::FastEruby }]
|
data/lib/asciidoctor/document.rb
CHANGED
@@ -259,12 +259,14 @@ class Document < AbstractBlock
|
|
259
259
|
options[:catalog_assets] = true if parent_doc.options[:catalog_assets]
|
260
260
|
@catalog = parent_doc.catalog.merge footnotes: []
|
261
261
|
# QUESTION should we support setting attribute in parent document from nested document?
|
262
|
-
|
263
|
-
@attribute_overrides = attr_overrides = parent_doc.attributes.merge
|
264
|
-
parent_doctype = attr_overrides.delete 'doctype'
|
262
|
+
@attribute_overrides = attr_overrides = (parent_doc.instance_variable_get :@attribute_overrides).merge parent_doc.attributes
|
265
263
|
attr_overrides.delete 'compat-mode'
|
264
|
+
parent_doctype = attr_overrides.delete 'doctype'
|
265
|
+
attr_overrides.delete 'notitle'
|
266
|
+
attr_overrides.delete 'showtitle'
|
267
|
+
# QUESTION if toc is hard unset in parent document, should it be hard unset in nested document?
|
266
268
|
attr_overrides.delete 'toc'
|
267
|
-
attr_overrides.delete 'toc-placement'
|
269
|
+
@attributes['toc-placement'] = (attr_overrides.delete 'toc-placement') || 'auto'
|
268
270
|
attr_overrides.delete 'toc-position'
|
269
271
|
@safe = parent_doc.safe
|
270
272
|
@attributes['compat-mode'] = '' if (@compat_mode = parent_doc.compat_mode)
|
@@ -326,7 +328,7 @@ class Document < AbstractBlock
|
|
326
328
|
@sourcemap = options[:sourcemap]
|
327
329
|
@timings = options.delete :timings
|
328
330
|
@path_resolver = PathResolver.new
|
329
|
-
initialize_extensions = (defined? ::Asciidoctor::Extensions) ?
|
331
|
+
initialize_extensions = (defined? ::Asciidoctor::Extensions) || (options.key? :extensions) ? ::Asciidoctor::Extensions : nil
|
330
332
|
@extensions = nil # initialize furthur down if initialize_extensions is true
|
331
333
|
options[:standalone] = options[:header_footer] if (options.key? :header_footer) && !(options.key? :standalone)
|
332
334
|
end
|
@@ -339,61 +341,46 @@ class Document < AbstractBlock
|
|
339
341
|
(@options = options).freeze
|
340
342
|
|
341
343
|
attrs = @attributes
|
342
|
-
|
343
|
-
|
344
|
-
|
344
|
+
unless parent_doc
|
345
|
+
attrs['attribute-undefined'] = Compliance.attribute_undefined
|
346
|
+
attrs['attribute-missing'] = Compliance.attribute_missing
|
347
|
+
attrs.update DEFAULT_ATTRIBUTES
|
348
|
+
# TODO if lang attribute is set, @safe mode < SafeMode::SERVER, and !parent_doc,
|
349
|
+
# load attributes from data/locale/attributes-<lang>.adoc
|
350
|
+
end
|
351
|
+
|
345
352
|
if standalone
|
346
|
-
attrs['copycss'] = ''
|
347
353
|
# sync embedded attribute with :standalone option value
|
348
354
|
attr_overrides['embedded'] = nil
|
355
|
+
attrs['copycss'] = ''
|
356
|
+
attrs['iconfont-remote'] = ''
|
357
|
+
attrs['stylesheet'] = ''
|
358
|
+
attrs['webfonts'] = ''
|
349
359
|
else
|
350
|
-
attrs['notitle'] = ''
|
351
360
|
# sync embedded attribute with :standalone option value
|
352
361
|
attr_overrides['embedded'] = ''
|
362
|
+
if (attr_overrides.key? 'showtitle') && (attr_overrides.keys & %w(notitle showtitle))[-1] == 'showtitle'
|
363
|
+
attr_overrides['notitle'] = { nil => '', false => '@', '@' => false}[attr_overrides['showtitle']]
|
364
|
+
elsif attr_overrides.key? 'notitle'
|
365
|
+
attr_overrides['showtitle'] = { nil => '', false => '@', '@' => false}[attr_overrides['notitle']]
|
366
|
+
else
|
367
|
+
attrs['notitle'] = ''
|
368
|
+
end
|
353
369
|
end
|
354
|
-
attrs['stylesheet'] = ''
|
355
|
-
attrs['webfonts'] = ''
|
356
|
-
attrs['prewrap'] = ''
|
357
|
-
attrs['attribute-undefined'] = Compliance.attribute_undefined
|
358
|
-
attrs['attribute-missing'] = Compliance.attribute_missing
|
359
|
-
attrs['iconfont-remote'] = ''
|
360
|
-
|
361
|
-
# language strings
|
362
|
-
# TODO load these based on language settings
|
363
|
-
attrs['caution-caption'] = 'Caution'
|
364
|
-
attrs['important-caption'] = 'Important'
|
365
|
-
attrs['note-caption'] = 'Note'
|
366
|
-
attrs['tip-caption'] = 'Tip'
|
367
|
-
attrs['warning-caption'] = 'Warning'
|
368
|
-
attrs['example-caption'] = 'Example'
|
369
|
-
attrs['figure-caption'] = 'Figure'
|
370
|
-
#attrs['listing-caption'] = 'Listing'
|
371
|
-
attrs['table-caption'] = 'Table'
|
372
|
-
attrs['toc-title'] = 'Table of Contents'
|
373
|
-
#attrs['preface-title'] = 'Preface'
|
374
|
-
attrs['section-refsig'] = 'Section'
|
375
|
-
attrs['part-refsig'] = 'Part'
|
376
|
-
attrs['chapter-refsig'] = 'Chapter'
|
377
|
-
attrs['appendix-caption'] = attrs['appendix-refsig'] = 'Appendix'
|
378
|
-
attrs['untitled-label'] = 'Untitled'
|
379
|
-
attrs['version-label'] = 'Version'
|
380
|
-
attrs['last-update-label'] = 'Last updated'
|
381
370
|
|
382
371
|
attr_overrides['asciidoctor'] = ''
|
383
372
|
attr_overrides['asciidoctor-version'] = ::Asciidoctor::VERSION
|
384
373
|
|
385
374
|
attr_overrides['safe-mode-name'] = (safe_mode_name = SafeMode.name_for_value @safe)
|
386
|
-
attr_overrides[
|
375
|
+
attr_overrides[%(safe-mode-#{safe_mode_name})] = ''
|
387
376
|
attr_overrides['safe-mode-level'] = @safe
|
388
377
|
|
389
|
-
# the only way to set the max-include-depth attribute is via the API; default to 64 like AsciiDoc
|
378
|
+
# the only way to set the max-include-depth attribute is via the API; default to 64 like AsciiDoc.py
|
390
379
|
attr_overrides['max-include-depth'] ||= 64
|
391
380
|
|
392
381
|
# the only way to set the allow-uri-read attribute is via the API; disabled by default
|
393
382
|
attr_overrides['allow-uri-read'] ||= nil
|
394
383
|
|
395
|
-
attr_overrides['user-home'] = USER_HOME
|
396
|
-
|
397
384
|
# remap legacy attribute names
|
398
385
|
attr_overrides['sectnums'] = attr_overrides.delete 'numbered' if attr_overrides.key? 'numbered'
|
399
386
|
attr_overrides['hardbreaks-option'] = attr_overrides.delete 'hardbreaks' if attr_overrides.key? 'hardbreaks'
|
@@ -429,7 +416,7 @@ class Document < AbstractBlock
|
|
429
416
|
attr_overrides['docfile'] = attr_overrides['docfile'][(attr_overrides['docdir'].length + 1)..-1]
|
430
417
|
end
|
431
418
|
attr_overrides['docdir'] = ''
|
432
|
-
attr_overrides['user-home']
|
419
|
+
attr_overrides['user-home'] ||= '.'
|
433
420
|
if @safe >= SafeMode::SECURE
|
434
421
|
attr_overrides['max-attribute-value-size'] = 4096 unless attr_overrides.key? 'max-attribute-value-size'
|
435
422
|
# assign linkcss (preventing css embedding) unless explicitly disabled from the commandline or API
|
@@ -438,6 +425,8 @@ class Document < AbstractBlock
|
|
438
425
|
# restrict document from enabling icons
|
439
426
|
attr_overrides['icons'] ||= nil
|
440
427
|
end
|
428
|
+
else
|
429
|
+
attr_overrides['user-home'] ||= USER_HOME
|
441
430
|
end
|
442
431
|
|
443
432
|
# the only way to set the max-attribute-value-size attribute is via the API; disabled by default
|
@@ -505,10 +494,10 @@ class Document < AbstractBlock
|
|
505
494
|
::AsciidoctorJ::Extensions::ExtensionRegistry === ext_registry)
|
506
495
|
@extensions = ext_registry.activate self
|
507
496
|
end
|
508
|
-
elsif
|
497
|
+
elsif (ext_block = options[:extensions]).nil?
|
498
|
+
@extensions = Extensions::Registry.new.activate self unless Extensions.groups.empty?
|
499
|
+
elsif ::Proc === ext_block
|
509
500
|
@extensions = Extensions.create(&ext_block).activate self
|
510
|
-
elsif !Extensions.groups.empty?
|
511
|
-
@extensions = Extensions::Registry.new.activate self
|
512
501
|
end
|
513
502
|
end
|
514
503
|
|
@@ -577,13 +566,17 @@ class Document < AbstractBlock
|
|
577
566
|
# returns the next number in the sequence for the specified counter
|
578
567
|
def counter name, seed = nil
|
579
568
|
return @parent_document.counter name, seed if @parent_document
|
580
|
-
if (
|
581
|
-
|
569
|
+
if (locked = attribute_locked? name) && (curr_val = @counters[name])
|
570
|
+
next_val = @counters[name] = Helpers.nextval curr_val
|
571
|
+
elsif !(curr_val = @attributes[name]).nil_or_empty?
|
572
|
+
next_val = @counters[name] = Helpers.nextval curr_val
|
582
573
|
elsif seed
|
583
|
-
|
574
|
+
next_val = @counters[name] = seed == seed.to_i.to_s ? seed.to_i : seed
|
584
575
|
else
|
585
|
-
|
576
|
+
next_val = @counters[name] = 1
|
586
577
|
end
|
578
|
+
@attributes[name] = next_val unless locked
|
579
|
+
next_val
|
587
580
|
end
|
588
581
|
|
589
582
|
# Public: Increment the specified counter and store it in the block's attributes
|
@@ -772,7 +765,7 @@ class Document < AbstractBlock
|
|
772
765
|
end
|
773
766
|
|
774
767
|
def notitle
|
775
|
-
|
768
|
+
@attributes.key? 'notitle'
|
776
769
|
end
|
777
770
|
|
778
771
|
def noheader
|
@@ -1217,7 +1210,7 @@ class Document < AbstractBlock
|
|
1217
1210
|
when '', 'font'
|
1218
1211
|
else
|
1219
1212
|
attrs['icons'] = ''
|
1220
|
-
attrs['icontype'] = icons_val
|
1213
|
+
attrs['icontype'] = icons_val unless icons_val == 'image'
|
1221
1214
|
end
|
1222
1215
|
end
|
1223
1216
|
|
@@ -425,7 +425,7 @@ module Extensions
|
|
425
425
|
# TIP: Postprocessors can also be used to relocate assets needed by the published
|
426
426
|
# document.
|
427
427
|
#
|
428
|
-
# Postprocessor implementations must Postprocessor.
|
428
|
+
# Postprocessor implementations must extend Postprocessor.
|
429
429
|
class Postprocessor < Processor
|
430
430
|
def process document, output
|
431
431
|
raise ::NotImplementedError, %(#{Postprocessor} subclass #{self.class} must implement the ##{__method__} method)
|
@@ -610,7 +610,7 @@ module Extensions
|
|
610
610
|
#--
|
611
611
|
# TODO break this out into different pattern types
|
612
612
|
# for example, FullInlineMacro, ShortInlineMacro (no target) and other patterns
|
613
|
-
# FIXME for inline
|
613
|
+
# FIXME for inline macro, we need to have some way to specify the text as a passthrough
|
614
614
|
class InlineMacroProcessor < MacroProcessor
|
615
615
|
@@rx_cache = {}
|
616
616
|
|
@@ -1021,8 +1021,6 @@ module Extensions
|
|
1021
1021
|
else
|
1022
1022
|
@docinfo_processor_extensions
|
1023
1023
|
end
|
1024
|
-
else
|
1025
|
-
nil
|
1026
1024
|
end
|
1027
1025
|
end
|
1028
1026
|
|
data/lib/asciidoctor/helpers.rb
CHANGED
@@ -56,25 +56,27 @@ module Helpers
|
|
56
56
|
# If a BOM is found at the beginning of the data, a best attempt is made to
|
57
57
|
# encode it to UTF-8 from the specified source encoding.
|
58
58
|
#
|
59
|
-
# data
|
59
|
+
# data - the source data Array to prepare (no nil entries allowed)
|
60
|
+
# trim_end - whether to trim whitespace from the end of each line;
|
61
|
+
# (true cleans all whitespace; false only removes trailing newline) (default: true)
|
60
62
|
#
|
61
63
|
# returns a String Array of prepared lines
|
62
|
-
def prepare_source_array data
|
64
|
+
def prepare_source_array data, trim_end = true
|
63
65
|
return [] if data.empty?
|
64
66
|
if (leading_2_bytes = (leading_bytes = (first = data[0]).unpack 'C3').slice 0, 2) == BOM_BYTES_UTF_16LE
|
65
67
|
data[0] = first.byteslice 2, first.bytesize
|
66
68
|
# NOTE you can't split a UTF-16LE string using .lines when encoding is UTF-8; doing so will cause this line to fail
|
67
|
-
return data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16LE).rstrip }
|
69
|
+
return trim_end ? data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16LE).rstrip } : data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16LE).chomp }
|
68
70
|
elsif leading_2_bytes == BOM_BYTES_UTF_16BE
|
69
71
|
data[0] = first.byteslice 2, first.bytesize
|
70
|
-
return data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16BE).rstrip }
|
72
|
+
return trim_end ? data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16BE).rstrip } : data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16BE).chomp }
|
71
73
|
elsif leading_bytes == BOM_BYTES_UTF_8
|
72
74
|
data[0] = first.byteslice 3, first.bytesize
|
73
75
|
end
|
74
76
|
if first.encoding == UTF_8
|
75
|
-
data.map {|line| line.rstrip }
|
77
|
+
trim_end ? data.map {|line| line.rstrip } : data.map {|line| line.chomp }
|
76
78
|
else
|
77
|
-
data.map {|line| (line.encode UTF_8).rstrip }
|
79
|
+
trim_end ? data.map {|line| (line.encode UTF_8).rstrip } : data.map {|line| (line.encode UTF_8).chomp }
|
78
80
|
end
|
79
81
|
end
|
80
82
|
|
@@ -86,10 +88,12 @@ module Helpers
|
|
86
88
|
# If a BOM is found at the beginning of the data, a best attempt is made to
|
87
89
|
# encode it to UTF-8 from the specified source encoding.
|
88
90
|
#
|
89
|
-
# data
|
91
|
+
# data - the source data String to prepare
|
92
|
+
# trim_end - whether to trim whitespace from the end of each line;
|
93
|
+
# (true cleans all whitespace; false only removes trailing newline) (default: true)
|
90
94
|
#
|
91
95
|
# returns a String Array of prepared lines
|
92
|
-
def prepare_source_string data
|
96
|
+
def prepare_source_string data, trim_end = true
|
93
97
|
return [] if data.nil_or_empty?
|
94
98
|
if (leading_2_bytes = (leading_bytes = data.unpack 'C3').slice 0, 2) == BOM_BYTES_UTF_16LE
|
95
99
|
data = (data.byteslice 2, data.bytesize).encode UTF_8, ::Encoding::UTF_16LE
|
@@ -101,7 +105,11 @@ module Helpers
|
|
101
105
|
elsif data.encoding != UTF_8
|
102
106
|
data = data.encode UTF_8
|
103
107
|
end
|
104
|
-
|
108
|
+
if trim_end
|
109
|
+
[].tap {|lines| data.each_line {|line| lines << line.rstrip } }
|
110
|
+
else
|
111
|
+
[].tap {|lines| data.each_line {|line| lines << line.chomp } }
|
112
|
+
end
|
105
113
|
end
|
106
114
|
|
107
115
|
# Internal: Efficiently checks whether the specified String resembles a URI
|
@@ -266,13 +274,10 @@ module Helpers
|
|
266
274
|
def nextval current
|
267
275
|
if ::Integer === current
|
268
276
|
current + 1
|
277
|
+
elsif (intval = current.to_i).to_s == current.to_s
|
278
|
+
intval + 1
|
269
279
|
else
|
270
|
-
|
271
|
-
if intval.to_s != current.to_s
|
272
|
-
(current[0].ord + 1).chr
|
273
|
-
else
|
274
|
-
intval + 1
|
275
|
-
end
|
280
|
+
current.succ
|
276
281
|
end
|
277
282
|
end
|
278
283
|
|
data/lib/asciidoctor/load.rb
CHANGED
@@ -1,117 +1,118 @@
|
|
1
1
|
module Asciidoctor
|
2
|
-
|
2
|
+
class << self
|
3
|
+
# Public: Parse the AsciiDoc source input into a {Document}
|
4
|
+
#
|
5
|
+
# Accepts input as an IO (or StringIO), String or String Array object. If the
|
6
|
+
# input is a File, the object is expected to be opened for reading and is not
|
7
|
+
# closed afterwards by this method. Information about the file (filename,
|
8
|
+
# directory name, etc) gets assigned to attributes on the Document object.
|
9
|
+
#
|
10
|
+
# input - the AsciiDoc source as a IO, String or Array.
|
11
|
+
# options - a String, Array or Hash of options to control processing (default: {})
|
12
|
+
# String and Array values are converted into a Hash.
|
13
|
+
# See {Document#initialize} for details about these options.
|
14
|
+
#
|
15
|
+
# Returns the Document
|
16
|
+
def load input, options = {}
|
17
|
+
options = options.merge
|
3
18
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
# input is a File, the object is expected to be opened for reading and is not
|
8
|
-
# closed afterwards by this method. Information about the file (filename,
|
9
|
-
# directory name, etc) gets assigned to attributes on the Document object.
|
10
|
-
#
|
11
|
-
# input - the AsciiDoc source as a IO, String or Array.
|
12
|
-
# options - a String, Array or Hash of options to control processing (default: {})
|
13
|
-
# String and Array values are converted into a Hash.
|
14
|
-
# See {Document#initialize} for details about these options.
|
15
|
-
#
|
16
|
-
# Returns the Document
|
17
|
-
def load input, options = {}
|
18
|
-
options = options.merge
|
19
|
-
|
20
|
-
if (timings = options[:timings])
|
21
|
-
timings.start :read
|
22
|
-
end
|
19
|
+
if (timings = options[:timings])
|
20
|
+
timings.start :read
|
21
|
+
end
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
if (options.key? :logger) && (logger = options[:logger]) != LoggerManager.logger
|
24
|
+
LoggerManager.logger = logger || NullLogger.new
|
25
|
+
end
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
27
|
+
if !(attrs = options[:attributes])
|
28
|
+
attrs = {}
|
29
|
+
elsif ::Hash === attrs
|
30
|
+
attrs = attrs.merge
|
31
|
+
elsif (defined? ::Java::JavaUtil::Map) && ::Java::JavaUtil::Map === attrs
|
32
|
+
attrs = attrs.dup
|
33
|
+
elsif ::Array === attrs
|
34
|
+
attrs = {}.tap do |accum|
|
35
|
+
attrs.each do |entry|
|
36
|
+
k, _, v = entry.partition '='
|
37
|
+
accum[k] = v
|
38
|
+
end
|
39
39
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
40
|
+
elsif ::String === attrs
|
41
|
+
# condense and convert non-escaped spaces to null, unescape escaped spaces, then split on null
|
42
|
+
attrs = {}.tap do |accum|
|
43
|
+
attrs.gsub(SpaceDelimiterRx, '\1' + NULL).gsub(EscapedSpaceRx, '\1').split(NULL).each do |entry|
|
44
|
+
k, _, v = entry.partition '='
|
45
|
+
accum[k] = v
|
46
|
+
end
|
47
47
|
end
|
48
|
+
elsif (attrs.respond_to? :keys) && (attrs.respond_to? :[])
|
49
|
+
# coerce attrs to a real Hash
|
50
|
+
attrs = {}.tap {|accum| attrs.keys.each {|k| accum[k] = attrs[k] } }
|
51
|
+
else
|
52
|
+
raise ::ArgumentError, %(illegal type for attributes option: #{attrs.class.ancestors.join ' < '})
|
48
53
|
end
|
49
|
-
elsif (attrs.respond_to? :keys) && (attrs.respond_to? :[])
|
50
|
-
# coerce attrs to a real Hash
|
51
|
-
attrs = {}.tap {|accum| attrs.keys.each {|k| accum[k] = attrs[k] } }
|
52
|
-
else
|
53
|
-
raise ::ArgumentError, %(illegal type for attributes option: #{attrs.class.ancestors.join ' < '})
|
54
|
-
end
|
55
54
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
55
|
+
if ::File === input
|
56
|
+
# File#mtime on JRuby for Windows doesn't honor TZ environment variable; see https://github.com/jruby/jruby/issues/6659
|
57
|
+
options[:input_mtime] = RUBY_ENGINE == 'jruby' ? (::Time.at input.mtime.to_i) : input.mtime
|
58
|
+
# NOTE defer setting infile and indir until we get a better sense of their purpose
|
59
|
+
# TODO cli checks if input path can be read and is file, but might want to add check to API too
|
60
|
+
attrs['docfile'] = input_path = ::File.absolute_path input.path
|
61
|
+
attrs['docdir'] = ::File.dirname input_path
|
62
|
+
attrs['docname'] = Helpers.basename input_path, (attrs['docfilesuffix'] = Helpers.extname input_path)
|
63
|
+
source = input.read
|
64
|
+
elsif input.respond_to? :read
|
65
|
+
# NOTE tty, pipes & sockets can't be rewound, but can't be sniffed easily either
|
66
|
+
# just fail the rewind operation silently to handle all cases
|
67
|
+
input.rewind rescue nil
|
68
|
+
source = input.read
|
69
|
+
elsif ::String === input
|
70
|
+
source = input
|
71
|
+
elsif ::Array === input
|
72
|
+
source = input.drop 0
|
73
|
+
elsif input
|
74
|
+
raise ::ArgumentError, %(unsupported input type: #{input.class})
|
75
|
+
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
77
|
+
if timings
|
78
|
+
timings.record :read
|
79
|
+
timings.start :parse
|
80
|
+
end
|
81
81
|
|
82
|
-
|
83
|
-
|
82
|
+
options[:attributes] = attrs
|
83
|
+
doc = options[:parse] == false ? (Document.new source, options) : (Document.new source, options).parse
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
85
|
+
timings.record :parse if timings
|
86
|
+
doc
|
87
|
+
rescue => ex
|
88
|
+
begin
|
89
|
+
context = %(asciidoctor: FAILED: #{attrs['docfile'] || '<stdin>'}: Failed to load AsciiDoc document)
|
90
|
+
if ex.respond_to? :exception
|
91
|
+
# The original message must be explicitly preserved when wrapping a Ruby exception
|
92
|
+
wrapped_ex = ex.exception %(#{context} - #{ex.message})
|
93
|
+
# JRuby automatically sets backtrace; MRI did not until 2.6
|
94
|
+
wrapped_ex.set_backtrace ex.backtrace
|
95
|
+
else
|
96
|
+
# Likely a Java exception class
|
97
|
+
wrapped_ex = ex.class.new context, ex
|
98
|
+
wrapped_ex.stack_trace = ex.stack_trace
|
99
|
+
end
|
100
|
+
rescue
|
101
|
+
wrapped_ex = ex
|
99
102
|
end
|
100
|
-
|
101
|
-
wrapped_ex = ex
|
103
|
+
raise wrapped_ex
|
102
104
|
end
|
103
|
-
raise wrapped_ex
|
104
|
-
end
|
105
105
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
106
|
+
# Public: Parse the contents of the AsciiDoc source file into an Asciidoctor::Document
|
107
|
+
#
|
108
|
+
# input - the String AsciiDoc source filename
|
109
|
+
# options - a String, Array or Hash of options to control processing (default: {})
|
110
|
+
# String and Array values are converted into a Hash.
|
111
|
+
# See Asciidoctor::Document#initialize for details about options.
|
112
|
+
#
|
113
|
+
# Returns the Asciidoctor::Document
|
114
|
+
def load_file filename, options = {}
|
115
|
+
::File.open(filename, FILE_READ_MODE) {|file| load file, options }
|
116
|
+
end
|
116
117
|
end
|
117
118
|
end
|