asciidoctor 1.5.8 → 2.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|