asciidoctor 1.5.8 → 2.0.0.rc.1
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 +162 -17
- data/LICENSE +1 -1
- data/README-de.adoc +12 -13
- data/README-fr.adoc +11 -12
- data/README-jp.adoc +11 -12
- data/README-zh_CN.adoc +12 -13
- data/README.adoc +6 -7
- data/asciidoctor.gemspec +19 -24
- data/bin/asciidoctor +5 -4
- data/data/reference/syntax.adoc +283 -0
- data/data/stylesheets/asciidoctor-default.css +56 -52
- data/data/stylesheets/coderay-asciidoctor.css +7 -9
- data/lib/asciidoctor.rb +171 -232
- data/lib/asciidoctor/abstract_block.rb +96 -105
- data/lib/asciidoctor/abstract_node.rb +118 -139
- data/lib/asciidoctor/attribute_list.rb +10 -14
- data/lib/asciidoctor/block.rb +20 -19
- data/lib/asciidoctor/callouts.rb +4 -2
- data/lib/asciidoctor/cli.rb +3 -2
- data/lib/asciidoctor/cli/invoker.rb +14 -21
- data/lib/asciidoctor/cli/options.rb +64 -54
- data/lib/asciidoctor/converter.rb +357 -185
- data/lib/asciidoctor/converter/composite.rb +40 -48
- data/lib/asciidoctor/converter/docbook5.rb +604 -640
- data/lib/asciidoctor/converter/html5.rb +949 -963
- data/lib/asciidoctor/converter/manpage.rb +569 -548
- data/lib/asciidoctor/converter/template.rb +231 -272
- data/lib/asciidoctor/core_ext.rb +5 -18
- data/lib/asciidoctor/core_ext/float/truncate.rb +19 -0
- data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
- data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
- data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
- data/lib/asciidoctor/document.rb +399 -377
- data/lib/asciidoctor/extensions.rb +72 -140
- data/lib/asciidoctor/helpers.rb +122 -83
- data/lib/asciidoctor/inline.rb +5 -1
- data/lib/asciidoctor/list.rb +13 -11
- data/lib/asciidoctor/logging.rb +17 -16
- data/lib/asciidoctor/parser.rb +390 -423
- data/lib/asciidoctor/path_resolver.rb +10 -5
- data/lib/asciidoctor/reader.rb +286 -263
- data/lib/asciidoctor/rouge_ext.rb +39 -0
- data/lib/asciidoctor/section.rb +9 -8
- data/lib/asciidoctor/stylesheets.rb +19 -37
- data/lib/asciidoctor/substitutors.rb +364 -509
- data/lib/asciidoctor/syntax_highlighter.rb +238 -0
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +87 -0
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +26 -0
- data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +27 -0
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +149 -0
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +129 -0
- data/lib/asciidoctor/table.rb +73 -66
- data/lib/asciidoctor/timings.rb +4 -2
- data/lib/asciidoctor/version.rb +2 -1
- data/lib/asciidoctor/writer.rb +30 -0
- data/man/asciidoctor.1 +19 -15
- data/man/asciidoctor.adoc +14 -12
- metadata +69 -216
- data/CONTRIBUTING.adoc +0 -185
- data/Gemfile +0 -60
- data/Rakefile +0 -129
- data/bin/asciidoctor-safe +0 -15
- data/features/open_block.feature +0 -92
- data/features/pass_block.feature +0 -66
- data/features/step_definitions.rb +0 -49
- data/features/text_formatting.feature +0 -57
- data/features/xref.feature +0 -1039
- data/lib/asciidoctor/converter/base.rb +0 -59
- data/lib/asciidoctor/converter/docbook45.rb +0 -93
- data/lib/asciidoctor/converter/factory.rb +0 -226
- data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
- data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
- data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
- data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
- data/test/api_test.rb +0 -1240
- data/test/attribute_list_test.rb +0 -242
- data/test/attributes_test.rb +0 -1623
- data/test/blocks_test.rb +0 -3870
- data/test/converter_test.rb +0 -470
- data/test/document_test.rb +0 -1853
- data/test/extensions_test.rb +0 -1560
- data/test/fixtures/asciidoc_index.txt +0 -521
- data/test/fixtures/basic-docinfo-footer.html +0 -6
- data/test/fixtures/basic-docinfo-footer.xml +0 -8
- data/test/fixtures/basic-docinfo.html +0 -1
- data/test/fixtures/basic-docinfo.xml +0 -4
- data/test/fixtures/basic.asciidoc +0 -5
- data/test/fixtures/chapter-a.adoc +0 -3
- data/test/fixtures/child-include.adoc +0 -5
- data/test/fixtures/circle.svg +0 -9
- data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
- data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
- data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
- data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
- data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
- data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
- data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
- data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
- data/test/fixtures/docinfo-footer.html +0 -1
- data/test/fixtures/docinfo-footer.xml +0 -9
- data/test/fixtures/docinfo.html +0 -1
- data/test/fixtures/docinfo.xml +0 -3
- data/test/fixtures/doctime-localtime.adoc +0 -2
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +0 -13
- data/test/fixtures/file-with-missing-include.adoc +0 -1
- data/test/fixtures/grandchild-include.adoc +0 -3
- data/test/fixtures/hello-asciidoctor.pdf +0 -69
- data/test/fixtures/include-file.asciidoc +0 -24
- data/test/fixtures/include-file.jsx +0 -8
- data/test/fixtures/include-file.ml +0 -3
- data/test/fixtures/include-file.xml +0 -5
- data/test/fixtures/lists.adoc +0 -96
- data/test/fixtures/master.adoc +0 -5
- data/test/fixtures/mismatched-end-tag.adoc +0 -7
- data/test/fixtures/other-chapters.adoc +0 -11
- data/test/fixtures/outer-include.adoc +0 -5
- data/test/fixtures/parent-include-restricted.adoc +0 -5
- data/test/fixtures/parent-include.adoc +0 -5
- data/test/fixtures/sample.asciidoc +0 -30
- data/test/fixtures/section-a.adoc +0 -4
- data/test/fixtures/stylesheets/custom.css +0 -3
- data/test/fixtures/subdir/index.adoc +0 -3
- data/test/fixtures/subdir/inner-include.adoc +0 -3
- data/test/fixtures/subdir/middle-include.adoc +0 -5
- data/test/fixtures/subs-docinfo.html +0 -2
- data/test/fixtures/subs.adoc +0 -6
- data/test/fixtures/tagged-class-enclosed.rb +0 -25
- data/test/fixtures/tagged-class.rb +0 -23
- data/test/fixtures/tip.gif +0 -0
- data/test/fixtures/unclosed-tag.adoc +0 -3
- data/test/fixtures/unexpected-end-tag.adoc +0 -4
- data/test/invoker_test.rb +0 -745
- data/test/links_test.rb +0 -855
- data/test/lists_test.rb +0 -5151
- data/test/logger_test.rb +0 -211
- data/test/manpage_test.rb +0 -660
- data/test/options_test.rb +0 -262
- data/test/paragraphs_test.rb +0 -562
- data/test/parser_test.rb +0 -742
- data/test/paths_test.rb +0 -395
- data/test/preamble_test.rb +0 -173
- data/test/reader_test.rb +0 -2161
- data/test/sections_test.rb +0 -3575
- data/test/substitutions_test.rb +0 -2066
- data/test/tables_test.rb +0 -2036
- data/test/test_helper.rb +0 -447
- data/test/text_test.rb +0 -309
@@ -1,7 +1,6 @@
|
|
1
|
-
#
|
2
|
-
require 'asciidoctor'
|
1
|
+
# frozen_string_literal: true
|
2
|
+
(require 'asciidoctor' unless defined? Asciidoctor.load) unless RUBY_ENGINE == 'opal'
|
3
3
|
|
4
|
-
# encoding: UTF-8
|
5
4
|
module Asciidoctor
|
6
5
|
# Extensions provide a way to participate in the parsing and converting
|
7
6
|
# phases of the AsciiDoc processor or extend the AsciiDoc syntax.
|
@@ -57,27 +56,23 @@ module Extensions
|
|
57
56
|
config[key] = default_value
|
58
57
|
end
|
59
58
|
|
60
|
-
#
|
59
|
+
# Mixes the DSL class for this processor into this processor class or instance.
|
61
60
|
#
|
62
|
-
# This method automatically detects whether to use the include or extend keyword
|
63
|
-
# based on what is appropriate.
|
61
|
+
# This method automatically detects whether to use the include or extend keyword to mix in the module.
|
64
62
|
#
|
65
63
|
# NOTE Inspiration for this DSL design comes from https://corcoran.io/2013/09/04/simple-pattern-ruby-dsl/
|
66
64
|
#
|
67
|
-
# Returns
|
68
|
-
def
|
69
|
-
if
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
#extend const_get :DSL if constants(false).grep :DSL
|
76
|
-
extend const_get :DSL if constants.grep :DSL
|
65
|
+
# Returns self
|
66
|
+
def enable_dsl
|
67
|
+
if const_defined? :DSL
|
68
|
+
if singleton_class?
|
69
|
+
include const_get :DSL
|
70
|
+
else
|
71
|
+
extend const_get :DSL
|
72
|
+
end
|
77
73
|
end
|
78
74
|
end
|
79
|
-
alias
|
80
|
-
alias include_dsl use_dsl
|
75
|
+
alias use_dsl enable_dsl
|
81
76
|
end
|
82
77
|
|
83
78
|
# Public: Get the configuration Hash for this processor instance.
|
@@ -92,7 +87,7 @@ module Extensions
|
|
92
87
|
end
|
93
88
|
|
94
89
|
def process *args
|
95
|
-
raise ::NotImplementedError, %(
|
90
|
+
raise ::NotImplementedError, %(#{Processor} subclass #{self.class} must implement the ##{__method__} method)
|
96
91
|
end
|
97
92
|
|
98
93
|
# QUESTION should attributes be an option instead of a parameter?
|
@@ -156,7 +151,7 @@ module Extensions
|
|
156
151
|
end
|
157
152
|
|
158
153
|
def create_block parent, context, source, attrs, opts = {}
|
159
|
-
Block.new parent, context, { :
|
154
|
+
Block.new parent, context, { source: source, attributes: attrs }.merge(opts)
|
160
155
|
end
|
161
156
|
|
162
157
|
# Public: Creates a list node and links it to the specified parent.
|
@@ -250,20 +245,20 @@ module Extensions
|
|
250
245
|
def process *args, &block
|
251
246
|
if block_given?
|
252
247
|
raise ::ArgumentError, %(wrong number of arguments (given #{args.size}, expected 0)) unless args.empty?
|
248
|
+
unless block.binding && self == block.binding.receiver
|
249
|
+
# NOTE remap self in process method to processor instance
|
250
|
+
context = self
|
251
|
+
block.define_singleton_method(:call) {|*m_args| context.instance_exec(*m_args, &block) }
|
252
|
+
end
|
253
253
|
@process_block = block
|
254
254
|
# TODO enable if we want to support passing proc or lambda as argument instead of block
|
255
255
|
#elsif ::Proc === args[0]
|
256
|
-
#
|
257
|
-
#
|
258
|
-
# @process_block = block
|
256
|
+
# raise ::ArgumentError, %(wrong number of arguments (given #{args.size - 1}, expected 0)) unless args.size == 1
|
257
|
+
# @process_block = args.shift
|
259
258
|
elsif defined? @process_block
|
260
|
-
# NOTE Proc automatically expands a single array argument
|
261
|
-
# ...but lambda doesn't (and we want to accept lambdas too)
|
262
|
-
# TODO need a test for this!
|
263
259
|
@process_block.call(*args)
|
264
260
|
else
|
265
|
-
#
|
266
|
-
raise ::NotImplementedError
|
261
|
+
raise ::NotImplementedError, %(#{self.class} ##{__method__} method called before being registered)
|
267
262
|
end
|
268
263
|
end
|
269
264
|
|
@@ -291,28 +286,25 @@ module Extensions
|
|
291
286
|
option :name, value
|
292
287
|
end
|
293
288
|
end
|
294
|
-
# NOTE match_name may get deprecated
|
295
|
-
alias match_name named
|
296
289
|
|
297
290
|
def content_model value
|
298
291
|
option :content_model, value
|
299
292
|
end
|
300
293
|
alias parse_content_as content_model
|
301
|
-
alias parses_content_as content_model
|
302
|
-
#alias parse_as content_model
|
303
|
-
#alias parsed_as content_model
|
304
294
|
|
305
|
-
def
|
295
|
+
def positional_attributes *value
|
306
296
|
option :pos_attrs, value.flatten
|
307
297
|
end
|
308
|
-
alias
|
309
|
-
alias
|
298
|
+
alias name_positional_attributes positional_attributes
|
299
|
+
# NOTE positional_attrs alias is deprecated
|
300
|
+
alias positional_attrs positional_attributes
|
310
301
|
|
311
302
|
def default_attrs value
|
312
303
|
option :default_attrs, value
|
313
304
|
end
|
305
|
+
alias default_attributes default_attrs
|
314
306
|
|
315
|
-
def
|
307
|
+
def resolve_attributes *args
|
316
308
|
# NOTE assume true as default value; rewrap single-argument string or symbol
|
317
309
|
if (args = args.fetch 0, true).respond_to? :to_sym
|
318
310
|
args = [args]
|
@@ -325,15 +317,15 @@ module Extensions
|
|
325
317
|
names, defaults = [], {}
|
326
318
|
args.each do |arg|
|
327
319
|
if (arg = arg.to_s).include? '='
|
328
|
-
name, value = arg.
|
320
|
+
name, _, value = arg.partition '='
|
329
321
|
if name.include? ':'
|
330
|
-
idx, name = name.
|
322
|
+
idx, _, name = name.partition ':'
|
331
323
|
idx = idx == '@' ? names.size : idx.to_i
|
332
324
|
names[idx] = name
|
333
325
|
end
|
334
326
|
defaults[name] = value
|
335
327
|
elsif arg.include? ':'
|
336
|
-
idx, name = arg.
|
328
|
+
idx, _, name = arg.partition ':'
|
337
329
|
idx = idx == '@' ? names.size : idx.to_i
|
338
330
|
names[idx] = name
|
339
331
|
else
|
@@ -346,7 +338,7 @@ module Extensions
|
|
346
338
|
names, defaults = [], {}
|
347
339
|
args.each do |key, val|
|
348
340
|
if (name = key.to_s).include? ':'
|
349
|
-
idx, name = name.
|
341
|
+
idx, _, name = name.partition ':'
|
350
342
|
idx = idx == '@' ? names.size : idx.to_i
|
351
343
|
names[idx] = name
|
352
344
|
end
|
@@ -358,8 +350,8 @@ module Extensions
|
|
358
350
|
raise ::ArgumentError, %(unsupported attributes specification for macro: #{args.inspect})
|
359
351
|
end
|
360
352
|
end
|
361
|
-
# NOTE
|
362
|
-
alias resolve_attributes
|
353
|
+
# NOTE resolves_attributes alias is deprecated
|
354
|
+
alias resolves_attributes resolve_attributes
|
363
355
|
end
|
364
356
|
|
365
357
|
# Public: Preprocessors are run after the source text is split into lines and
|
@@ -377,7 +369,7 @@ module Extensions
|
|
377
369
|
# Preprocessor implementations must extend the Preprocessor class.
|
378
370
|
class Preprocessor < Processor
|
379
371
|
def process document, reader
|
380
|
-
raise ::NotImplementedError, %(
|
372
|
+
raise ::NotImplementedError, %(#{Preprocessor} subclass #{self.class} must implement the ##{__method__} method)
|
381
373
|
end
|
382
374
|
end
|
383
375
|
Preprocessor::DSL = DocumentProcessorDsl
|
@@ -394,7 +386,7 @@ module Extensions
|
|
394
386
|
# QUESTION should the tree processor get invoked after parse header too?
|
395
387
|
class TreeProcessor < Processor
|
396
388
|
def process document
|
397
|
-
raise ::NotImplementedError, %(
|
389
|
+
raise ::NotImplementedError, %(#{TreeProcessor} subclass #{self.class} must implement the ##{__method__} method)
|
398
390
|
end
|
399
391
|
end
|
400
392
|
TreeProcessor::DSL = DocumentProcessorDsl
|
@@ -419,7 +411,7 @@ module Extensions
|
|
419
411
|
# Postprocessor implementations must Postprocessor.
|
420
412
|
class Postprocessor < Processor
|
421
413
|
def process document, output
|
422
|
-
raise ::NotImplementedError, %(
|
414
|
+
raise ::NotImplementedError, %(#{Postprocessor} subclass #{self.class} must implement the ##{__method__} method)
|
423
415
|
end
|
424
416
|
end
|
425
417
|
Postprocessor::DSL = DocumentProcessorDsl
|
@@ -437,7 +429,7 @@ module Extensions
|
|
437
429
|
# TODO add file extension or regexp as shortcut for handles? method
|
438
430
|
class IncludeProcessor < Processor
|
439
431
|
def process document, reader, target, attributes
|
440
|
-
raise ::NotImplementedError, %(
|
432
|
+
raise ::NotImplementedError, %(#{IncludeProcessor} subclass #{self.class} must implement the ##{__method__} method)
|
441
433
|
end
|
442
434
|
|
443
435
|
def handles? target
|
@@ -483,7 +475,7 @@ module Extensions
|
|
483
475
|
end
|
484
476
|
|
485
477
|
def process document
|
486
|
-
raise ::NotImplementedError, %(
|
478
|
+
raise ::NotImplementedError, %(#{DocinfoProcessor} subclass #{self.class} must implement the ##{__method__} method)
|
487
479
|
end
|
488
480
|
end
|
489
481
|
|
@@ -539,7 +531,7 @@ module Extensions
|
|
539
531
|
end
|
540
532
|
|
541
533
|
def process parent, reader, attributes
|
542
|
-
raise ::NotImplementedError, %(
|
534
|
+
raise ::NotImplementedError, %(#{BlockProcessor} subclass #{self.class} must implement the ##{__method__} method)
|
543
535
|
end
|
544
536
|
end
|
545
537
|
|
@@ -551,7 +543,7 @@ module Extensions
|
|
551
543
|
end
|
552
544
|
alias on_contexts contexts
|
553
545
|
alias on_context contexts
|
554
|
-
alias
|
546
|
+
alias bind_to contexts
|
555
547
|
end
|
556
548
|
BlockProcessor::DSL = BlockProcessorDsl
|
557
549
|
|
@@ -565,14 +557,14 @@ module Extensions
|
|
565
557
|
end
|
566
558
|
|
567
559
|
def process parent, target, attributes
|
568
|
-
raise ::NotImplementedError, %(
|
560
|
+
raise ::NotImplementedError, %(#{MacroProcessor} subclass #{self.class} must implement the ##{__method__} method)
|
569
561
|
end
|
570
562
|
end
|
571
563
|
|
572
564
|
module MacroProcessorDsl
|
573
565
|
include SyntaxProcessorDsl
|
574
566
|
|
575
|
-
def
|
567
|
+
def resolve_attributes *args
|
576
568
|
if args.size == 1 && !args[0]
|
577
569
|
option :content_model, :text
|
578
570
|
return
|
@@ -580,8 +572,8 @@ module Extensions
|
|
580
572
|
super
|
581
573
|
option :content_model, :attributes
|
582
574
|
end
|
583
|
-
# NOTE
|
584
|
-
alias resolve_attributes
|
575
|
+
# NOTE resolves_attributes alias is deprecated
|
576
|
+
alias resolves_attributes resolve_attributes
|
585
577
|
end
|
586
578
|
|
587
579
|
# Public: BlockMacroProcessors are used to handle block macros that have a
|
@@ -622,16 +614,16 @@ module Extensions
|
|
622
614
|
module InlineMacroProcessorDsl
|
623
615
|
include MacroProcessorDsl
|
624
616
|
|
625
|
-
def
|
617
|
+
def format value
|
626
618
|
option :format, value
|
627
619
|
end
|
628
|
-
alias
|
620
|
+
alias match_format format
|
621
|
+
# NOTE using_format alias is deprecated
|
622
|
+
alias using_format format
|
629
623
|
|
630
|
-
def
|
624
|
+
def match value
|
631
625
|
option :regexp, value
|
632
626
|
end
|
633
|
-
alias match matches
|
634
|
-
alias matching matches
|
635
627
|
end
|
636
628
|
InlineMacroProcessor::DSL = InlineMacroProcessorDsl
|
637
629
|
|
@@ -965,7 +957,7 @@ module Extensions
|
|
965
957
|
# docinfo_processor MetaRobotsDocinfoProcessor
|
966
958
|
#
|
967
959
|
# # as an instance of a DocinfoProcessor subclass with an explicit location
|
968
|
-
# docinfo_processor JQueryDocinfoProcessor.new, :
|
960
|
+
# docinfo_processor JQueryDocinfoProcessor.new, location: :footer
|
969
961
|
#
|
970
962
|
# # as a name of a DocinfoProcessor subclass
|
971
963
|
# docinfo_processor 'MetaRobotsDocinfoProcessor'
|
@@ -1319,30 +1311,27 @@ module Extensions
|
|
1319
1311
|
def add_document_processor kind, args, &block
|
1320
1312
|
kind_name = kind.to_s.tr '_', ' '
|
1321
1313
|
kind_class_symbol = kind_name.split.map {|it| it.capitalize }.join.to_sym
|
1322
|
-
kind_class = Extensions.const_get kind_class_symbol
|
1323
|
-
kind_java_class = (defined? ::AsciidoctorJ) ? (::AsciidoctorJ::Extensions.const_get kind_class_symbol) : nil
|
1314
|
+
kind_class = Extensions.const_get kind_class_symbol, false
|
1315
|
+
kind_java_class = (defined? ::AsciidoctorJ) ? (::AsciidoctorJ::Extensions.const_get kind_class_symbol, false) : nil
|
1324
1316
|
kind_store = instance_variable_get(%(@#{kind}_extensions).to_sym) || instance_variable_set(%(@#{kind}_extensions).to_sym, [])
|
1325
1317
|
# style 1: specified as block
|
1326
1318
|
extension = if block_given?
|
1327
1319
|
config = resolve_args args, 1
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
# NOTE kind_class.contants(false) doesn't exist in Ruby 1.8.7
|
1335
|
-
processor.extend kind_class.const_get :DSL if kind_class.constants.grep :DSL
|
1336
|
-
processor.instance_exec(&block)
|
1337
|
-
processor.freeze
|
1320
|
+
(processor = kind_class.new config).singleton_class.enable_dsl
|
1321
|
+
if block.arity == 0
|
1322
|
+
processor.instance_exec(&block)
|
1323
|
+
else
|
1324
|
+
yield processor
|
1325
|
+
end
|
1338
1326
|
unless processor.process_block_given?
|
1339
1327
|
raise ::ArgumentError, %(No block specified to process #{kind_name} extension at #{block.source_location})
|
1340
1328
|
end
|
1329
|
+
processor.freeze
|
1341
1330
|
ProcessorExtension.new kind, processor
|
1342
1331
|
else
|
1343
1332
|
processor, config = resolve_args args, 2
|
1344
1333
|
# style 2: specified as Class or String class name
|
1345
|
-
if (processor_class =
|
1334
|
+
if (processor_class = Helpers.resolve_class processor)
|
1346
1335
|
unless processor_class < kind_class || (kind_java_class && processor_class < kind_java_class)
|
1347
1336
|
raise ::ArgumentError, %(Invalid type for #{kind_name} extension: #{processor})
|
1348
1337
|
end
|
@@ -1365,24 +1354,18 @@ module Extensions
|
|
1365
1354
|
|
1366
1355
|
def add_syntax_processor kind, args, &block
|
1367
1356
|
kind_name = kind.to_s.tr '_', ' '
|
1368
|
-
kind_class_symbol = (kind_name.split.map {|it| it.capitalize }
|
1369
|
-
kind_class = Extensions.const_get kind_class_symbol
|
1370
|
-
kind_java_class = (defined? ::AsciidoctorJ) ? (::AsciidoctorJ::Extensions.const_get kind_class_symbol) : nil
|
1357
|
+
kind_class_symbol = (kind_name.split.map {|it| it.capitalize } << 'Processor').join.to_sym
|
1358
|
+
kind_class = Extensions.const_get kind_class_symbol, false
|
1359
|
+
kind_java_class = (defined? ::AsciidoctorJ) ? (::AsciidoctorJ::Extensions.const_get kind_class_symbol, false) : nil
|
1371
1360
|
kind_store = instance_variable_get(%(@#{kind}_extensions).to_sym) || instance_variable_set(%(@#{kind}_extensions).to_sym, {})
|
1372
1361
|
# style 1: specified as block
|
1373
1362
|
if block_given?
|
1374
1363
|
name, config = resolve_args args, 2
|
1375
|
-
processor = kind_class.new as_symbol
|
1376
|
-
|
1377
|
-
#class << processor
|
1378
|
-
# include_dsl
|
1379
|
-
#end
|
1380
|
-
# NOTE kind_class.contants(false) doesn't exist in Ruby 1.8.7
|
1381
|
-
processor.extend kind_class.const_get :DSL if kind_class.constants.grep :DSL
|
1382
|
-
if block.arity == 1
|
1383
|
-
yield processor
|
1384
|
-
else
|
1364
|
+
(processor = kind_class.new (as_symbol name), config).singleton_class.enable_dsl
|
1365
|
+
if block.arity == 0
|
1385
1366
|
processor.instance_exec(&block)
|
1367
|
+
else
|
1368
|
+
yield processor
|
1386
1369
|
end
|
1387
1370
|
unless (name = as_symbol processor.name)
|
1388
1371
|
raise ::ArgumentError, %(No name specified for #{kind_name} extension at #{block.source_location})
|
@@ -1395,7 +1378,7 @@ module Extensions
|
|
1395
1378
|
else
|
1396
1379
|
processor, name, config = resolve_args args, 3
|
1397
1380
|
# style 2: specified as Class or String class name
|
1398
|
-
if (processor_class =
|
1381
|
+
if (processor_class = Helpers.resolve_class processor)
|
1399
1382
|
unless processor_class < kind_class || (kind_java_class && processor_class < kind_java_class)
|
1400
1383
|
raise ::ArgumentError, %(Class specified for #{kind_name} extension does not inherit from #{kind_class}: #{processor})
|
1401
1384
|
end
|
@@ -1453,13 +1436,11 @@ module Extensions
|
|
1453
1436
|
|
1454
1437
|
def create name = nil, &block
|
1455
1438
|
if block_given?
|
1456
|
-
Registry.new
|
1439
|
+
Registry.new (name || generate_name) => block
|
1457
1440
|
else
|
1458
1441
|
Registry.new
|
1459
1442
|
end
|
1460
1443
|
end
|
1461
|
-
# Deprecated: Use create instead of build_registry
|
1462
|
-
alias build_registry create
|
1463
1444
|
|
1464
1445
|
# Public: Registers an extension Group that subsequently registers a
|
1465
1446
|
# collection of extensions.
|
@@ -1501,7 +1482,7 @@ module Extensions
|
|
1501
1482
|
resolved_group = block
|
1502
1483
|
elsif (group = args.pop)
|
1503
1484
|
# QUESTION should we instantiate the group class here or defer until activation??
|
1504
|
-
resolved_group = (resolve_class group) || group
|
1485
|
+
resolved_group = (Helpers.resolve_class group) || group
|
1505
1486
|
else
|
1506
1487
|
raise ::ArgumentError, %(Extension group to register not specified)
|
1507
1488
|
end
|
@@ -1529,55 +1510,6 @@ module Extensions
|
|
1529
1510
|
names.each {|group| @groups.delete group.to_sym }
|
1530
1511
|
nil
|
1531
1512
|
end
|
1532
|
-
|
1533
|
-
# Internal: Resolve the specified object as a Class
|
1534
|
-
#
|
1535
|
-
# object - The object to resolve as a Class
|
1536
|
-
#
|
1537
|
-
# Returns a Class if the specified object is a Class (but not a Module) or
|
1538
|
-
# a String that resolves to a Class; otherwise, nil
|
1539
|
-
def resolve_class object
|
1540
|
-
case object
|
1541
|
-
when ::Class
|
1542
|
-
object
|
1543
|
-
when ::String
|
1544
|
-
class_for_name object
|
1545
|
-
end
|
1546
|
-
end
|
1547
|
-
|
1548
|
-
# Public: Resolves the Class object for the qualified name.
|
1549
|
-
#
|
1550
|
-
# Returns Class
|
1551
|
-
if ::RUBY_MIN_VERSION_2
|
1552
|
-
def class_for_name qualified_name
|
1553
|
-
resolved = ::Object.const_get qualified_name, false
|
1554
|
-
raise unless ::Class === resolved
|
1555
|
-
resolved
|
1556
|
-
rescue
|
1557
|
-
raise ::NameError, %(Could not resolve class for name: #{qualified_name})
|
1558
|
-
end
|
1559
|
-
elsif ::RUBY_MIN_VERSION_1_9
|
1560
|
-
def class_for_name qualified_name
|
1561
|
-
resolved = (qualified_name.split '::').reduce ::Object do |current, name|
|
1562
|
-
name.empty? ? current : (current.const_get name, false)
|
1563
|
-
end
|
1564
|
-
raise unless ::Class === resolved
|
1565
|
-
resolved
|
1566
|
-
rescue
|
1567
|
-
raise ::NameError, %(Could not resolve class for name: #{qualified_name})
|
1568
|
-
end
|
1569
|
-
else
|
1570
|
-
def class_for_name qualified_name
|
1571
|
-
resolved = (qualified_name.split '::').reduce ::Object do |current, name|
|
1572
|
-
# NOTE on Ruby 1.8, const_defined? only checks for constant in current scope
|
1573
|
-
name.empty? ? current : ((current.const_defined? name) ? (current.const_get name) : raise)
|
1574
|
-
end
|
1575
|
-
raise unless ::Class === resolved
|
1576
|
-
resolved
|
1577
|
-
rescue
|
1578
|
-
raise ::NameError, %(Could not resolve class for name: #{qualified_name})
|
1579
|
-
end
|
1580
|
-
end
|
1581
1513
|
end
|
1582
1514
|
end
|
1583
1515
|
end
|
data/lib/asciidoctor/helpers.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
module Asciidoctor
|
3
|
+
# Internal: Except where noted, a module that contains internal helper functions.
|
3
4
|
module Helpers
|
4
5
|
# Internal: Require the specified library using Kernel#require.
|
5
6
|
#
|
@@ -43,85 +44,63 @@ module Helpers
|
|
43
44
|
nil
|
44
45
|
end
|
45
46
|
|
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
|
-
if COERCE_ENCODING
|
71
|
-
utf8 = ::Encoding::UTF_8
|
72
|
-
if (leading_2_bytes = leading_bytes.slice 0, 2) == BOM_BYTES_UTF_16LE
|
73
|
-
# HACK Ruby messes up trailing whitespace on UTF-16LE, so reencode whole document first
|
74
|
-
data = data.join
|
75
|
-
return (((data.force_encoding ::Encoding::UTF_16LE).slice 1, data.length).encode utf8).each_line.map {|line| line.rstrip }
|
76
|
-
elsif leading_2_bytes == BOM_BYTES_UTF_16BE
|
77
|
-
data[0] = (first_line.force_encoding ::Encoding::UTF_16BE).slice 1, first_line.length
|
78
|
-
return data.map {|line| ((line.force_encoding ::Encoding::UTF_16BE).encode utf8).rstrip }
|
79
|
-
elsif leading_bytes == BOM_BYTES_UTF_8
|
80
|
-
data[0] = (first_line.force_encoding utf8).slice 1, first_line.length
|
81
|
-
end
|
82
|
-
|
83
|
-
data.map {|line| line.encoding == utf8 ? line.rstrip : (line.force_encoding utf8).rstrip }
|
84
|
-
else
|
85
|
-
# Ruby 1.8 has no built-in re-encoding, so no point in removing the UTF-16 BOMs
|
86
|
-
data[0] = first_line.slice 3, first_line.length if leading_bytes == BOM_BYTES_UTF_8
|
47
|
+
# Internal: Prepare the source data Array for parsing.
|
48
|
+
#
|
49
|
+
# Encodes the data to UTF-8, if necessary, and removes any trailing
|
50
|
+
# whitespace from every line.
|
51
|
+
#
|
52
|
+
# If a BOM is found at the beginning of the data, a best attempt is made to
|
53
|
+
# encode it to UTF-8 from the specified source encoding.
|
54
|
+
#
|
55
|
+
# data - the source data Array to prepare (no nil entries allowed)
|
56
|
+
#
|
57
|
+
# returns a String Array of prepared lines
|
58
|
+
def self.prepare_source_array data
|
59
|
+
return [] if data.empty?
|
60
|
+
if (leading_2_bytes = (leading_bytes = (first = data[0]).unpack 'C3').slice 0, 2) == BOM_BYTES_UTF_16LE
|
61
|
+
data[0] = first.byteslice 2, first.bytesize
|
62
|
+
# NOTE you can't split a UTF-16LE string using .lines when encoding is UTF-8; doing so will cause this line to fail
|
63
|
+
return data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16LE).rstrip }
|
64
|
+
elsif leading_2_bytes == BOM_BYTES_UTF_16BE
|
65
|
+
data[0] = first.byteslice 2, first.bytesize
|
66
|
+
return data.map {|line| (line.encode UTF_8, ::Encoding::UTF_16BE).rstrip }
|
67
|
+
elsif leading_bytes == BOM_BYTES_UTF_8
|
68
|
+
data[0] = first.byteslice 3, first.bytesize
|
69
|
+
end
|
70
|
+
if first.encoding == UTF_8
|
87
71
|
data.map {|line| line.rstrip }
|
72
|
+
else
|
73
|
+
data.map {|line| (line.encode UTF_8).rstrip }
|
88
74
|
end
|
89
75
|
end
|
90
76
|
|
91
|
-
#
|
77
|
+
# Internal: Prepare the source data String for parsing.
|
92
78
|
#
|
93
|
-
#
|
94
|
-
#
|
79
|
+
# Encodes the data to UTF-8, if necessary, splits it into an array, and
|
80
|
+
# removes any trailing whitespace from every line.
|
95
81
|
#
|
96
|
-
# If a BOM is
|
97
|
-
#
|
82
|
+
# If a BOM is found at the beginning of the data, a best attempt is made to
|
83
|
+
# encode it to UTF-8 from the specified source encoding.
|
98
84
|
#
|
99
|
-
# data -
|
85
|
+
# data - the source data String to prepare
|
100
86
|
#
|
101
|
-
# returns a String Array of
|
102
|
-
def self.
|
87
|
+
# returns a String Array of prepared lines
|
88
|
+
def self.prepare_source_string data
|
103
89
|
return [] if data.nil_or_empty?
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
data = data.encoding == utf8 ? (data.slice 1, data.length) : ((data.force_encoding utf8).slice 1, data.length)
|
114
|
-
else
|
115
|
-
data = data.force_encoding utf8 unless data.encoding == utf8
|
116
|
-
end
|
117
|
-
else
|
118
|
-
# Ruby 1.8 has no built-in re-encoding, so no point in removing the UTF-16 BOMs
|
119
|
-
data = data.slice 3, data.length if leading_bytes == BOM_BYTES_UTF_8
|
90
|
+
if (leading_2_bytes = (leading_bytes = data.unpack 'C3').slice 0, 2) == BOM_BYTES_UTF_16LE
|
91
|
+
data = (data.byteslice 2, data.bytesize).encode UTF_8, ::Encoding::UTF_16LE
|
92
|
+
elsif leading_2_bytes == BOM_BYTES_UTF_16BE
|
93
|
+
data = (data.byteslice 2, data.bytesize).encode UTF_8, ::Encoding::UTF_16BE
|
94
|
+
elsif leading_bytes == BOM_BYTES_UTF_8
|
95
|
+
data = data.byteslice 3, data.bytesize
|
96
|
+
data = data.encode UTF_8 unless data.encoding == UTF_8
|
97
|
+
elsif data.encoding != UTF_8
|
98
|
+
data = data.encode UTF_8
|
120
99
|
end
|
121
|
-
data.each_line
|
100
|
+
[].tap {|lines| data.each_line {|line| lines << line.rstrip } }
|
122
101
|
end
|
123
102
|
|
124
|
-
#
|
103
|
+
# Internal: Efficiently checks whether the specified String resembles a URI
|
125
104
|
#
|
126
105
|
# Uses the Asciidoctor::UriSniffRx regex to check whether the String begins
|
127
106
|
# with a URI prefix (e.g., http://). No validation of the URI is performed.
|
@@ -133,7 +112,7 @@ module Helpers
|
|
133
112
|
(str.include? ':') && (UriSniffRx.match? str)
|
134
113
|
end
|
135
114
|
|
136
|
-
#
|
115
|
+
# Internal: Efficiently retrieves the URI prefix of the specified String
|
137
116
|
#
|
138
117
|
# Uses the Asciidoctor::UriSniffRx regex to match the URI prefix in the
|
139
118
|
# specified String (e.g., http://), if present.
|
@@ -145,16 +124,35 @@ module Helpers
|
|
145
124
|
(str.include? ':') && UriSniffRx =~ str ? $& : nil
|
146
125
|
end
|
147
126
|
|
148
|
-
#
|
149
|
-
|
127
|
+
# Internal: Encode a URI component String for safe inclusion in a URI.
|
128
|
+
#
|
129
|
+
# str - the URI component String to encode
|
130
|
+
#
|
131
|
+
# Returns the String with all reserved URI characters encoded (e.g., /, &, =, space, etc).
|
132
|
+
if RUBY_ENGINE == 'opal'
|
133
|
+
def self.encode_uri_component str
|
134
|
+
# patch necessary to adhere with RFC-3986 (and thus CGI.escape)
|
135
|
+
# see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#Description
|
136
|
+
%x(
|
137
|
+
return encodeURIComponent(str).replace(/%20|[!'()*]/g, function (m) {
|
138
|
+
return m === '%20' ? '+' : '%' + m.charCodeAt(0).toString(16)
|
139
|
+
})
|
140
|
+
)
|
141
|
+
end
|
142
|
+
else
|
143
|
+
CGI = ::CGI
|
144
|
+
def self.encode_uri_component str
|
145
|
+
CGI.escape str
|
146
|
+
end
|
147
|
+
end
|
150
148
|
|
151
|
-
#
|
149
|
+
# Internal: Encode a URI String (namely the path portion).
|
152
150
|
#
|
153
|
-
# str - the String to
|
151
|
+
# str - the String to encode
|
154
152
|
#
|
155
|
-
# Returns the String with all
|
156
|
-
def self.
|
157
|
-
str.
|
153
|
+
# Returns the String with all spaces replaced with %20.
|
154
|
+
def self.encode_uri str
|
155
|
+
(str.include? ' ') ? (str.gsub ' ', '%20') : str
|
158
156
|
end
|
159
157
|
|
160
158
|
# Public: Removes the file extension from filename and returns the result
|
@@ -163,7 +161,7 @@ module Helpers
|
|
163
161
|
#
|
164
162
|
# Examples
|
165
163
|
#
|
166
|
-
# Helpers.rootname
|
164
|
+
# Helpers.rootname 'part1/chapter1.adoc'
|
167
165
|
# # => "part1/chapter1"
|
168
166
|
#
|
169
167
|
# Returns the String filename with the file extension removed
|
@@ -179,14 +177,14 @@ module Helpers
|
|
179
177
|
#
|
180
178
|
# Examples
|
181
179
|
#
|
182
|
-
# Helpers.basename
|
180
|
+
# Helpers.basename 'images/tiger.png', true
|
183
181
|
# # => "tiger"
|
184
182
|
#
|
185
|
-
# Helpers.basename
|
183
|
+
# Helpers.basename 'images/tiger.png', '.png'
|
186
184
|
# # => "tiger"
|
187
185
|
#
|
188
186
|
# Returns the String filename with leading directories removed and, if specified, the extension removed
|
189
|
-
def self.basename
|
187
|
+
def self.basename filename, drop_ext = nil
|
190
188
|
if drop_ext
|
191
189
|
::File.basename filename, (drop_ext == true ? (::File.extname filename) : drop_ext)
|
192
190
|
else
|
@@ -194,6 +192,7 @@ module Helpers
|
|
194
192
|
end
|
195
193
|
end
|
196
194
|
|
195
|
+
# Internal: Make a directory, ensuring all parent directories exist.
|
197
196
|
def self.mkdir_p dir
|
198
197
|
unless ::File.directory? dir
|
199
198
|
unless (parent_dir = ::File.dirname dir) == '.'
|
@@ -212,16 +211,56 @@ module Helpers
|
|
212
211
|
'L' => 50, 'XL' => 40, 'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1
|
213
212
|
}
|
214
213
|
|
215
|
-
# Converts an integer to a Roman numeral.
|
214
|
+
# Internal: Converts an integer to a Roman numeral.
|
216
215
|
#
|
217
216
|
# val - the [Integer] value to convert
|
218
217
|
#
|
219
218
|
# Returns the [String] roman numeral for this integer
|
220
219
|
def self.int_to_roman val
|
221
|
-
ROMAN_NUMERALS.map
|
220
|
+
ROMAN_NUMERALS.map do |l, i|
|
222
221
|
repeat, val = val.divmod i
|
223
222
|
l * repeat
|
224
|
-
|
223
|
+
end.join
|
224
|
+
end
|
225
|
+
|
226
|
+
# Internal: Get the next value in the sequence.
|
227
|
+
#
|
228
|
+
# Handles both integer and character sequences.
|
229
|
+
#
|
230
|
+
# current - the value to increment as a String or Integer
|
231
|
+
#
|
232
|
+
# returns the next value in the sequence according to the current value's type
|
233
|
+
def self.nextval current
|
234
|
+
if ::Integer === current
|
235
|
+
current + 1
|
236
|
+
else
|
237
|
+
intval = current.to_i
|
238
|
+
if intval.to_s != current.to_s
|
239
|
+
(current[0].ord + 1).chr
|
240
|
+
else
|
241
|
+
intval + 1
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Internal: Resolve the specified object as a Class
|
247
|
+
#
|
248
|
+
# object - The Object to resolve as a Class
|
249
|
+
#
|
250
|
+
# Returns a Class if the specified object is a Class (but not a Module) or
|
251
|
+
# a String that resolves to a Class; otherwise, nil
|
252
|
+
def self.resolve_class object
|
253
|
+
::Class === object ? object : (::String === object ? (class_for_name object) : nil)
|
254
|
+
end
|
255
|
+
|
256
|
+
# Internal: Resolves a Class object (not a Module) for the qualified name.
|
257
|
+
#
|
258
|
+
# Returns Class
|
259
|
+
def self.class_for_name qualified_name
|
260
|
+
raise unless ::Class === (resolved = ::Object.const_get qualified_name, false)
|
261
|
+
resolved
|
262
|
+
rescue
|
263
|
+
raise ::NameError, %(Could not resolve class for name: #{qualified_name})
|
225
264
|
end
|
226
265
|
end
|
227
266
|
end
|