asciidoctor 2.0.10 → 2.0.17
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 +294 -30
- data/LICENSE +1 -1
- data/README-de.adoc +16 -20
- data/README-fr.adoc +15 -22
- data/README-jp.adoc +15 -26
- data/README-zh_CN.adoc +21 -25
- data/README.adoc +161 -138
- data/asciidoctor.gemspec +6 -13
- 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 +8 -7
- 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-th.adoc +23 -0
- data/data/locale/attributes-tr.adoc +4 -3
- data/data/locale/attributes-uk.adoc +6 -5
- data/data/locale/attributes-vi.adoc +23 -0
- 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 +76 -76
- data/data/stylesheets/coderay-asciidoctor.css +9 -9
- data/lib/asciidoctor/abstract_block.rb +20 -13
- data/lib/asciidoctor/abstract_node.rb +23 -12
- data/lib/asciidoctor/attribute_list.rb +64 -72
- data/lib/asciidoctor/block.rb +6 -6
- data/lib/asciidoctor/cli/invoker.rb +3 -2
- data/lib/asciidoctor/cli/options.rb +32 -31
- data/lib/asciidoctor/convert.rb +168 -162
- data/lib/asciidoctor/converter/docbook5.rb +49 -34
- data/lib/asciidoctor/converter/html5.rb +180 -139
- data/lib/asciidoctor/converter/manpage.rb +118 -90
- data/lib/asciidoctor/converter/template.rb +15 -13
- data/lib/asciidoctor/converter.rb +19 -16
- data/lib/asciidoctor/core_ext/hash/merge.rb +1 -1
- data/lib/asciidoctor/document.rb +77 -86
- data/lib/asciidoctor/extensions.rb +22 -16
- data/lib/asciidoctor/helpers.rb +20 -15
- data/lib/asciidoctor/list.rb +2 -6
- data/lib/asciidoctor/load.rb +103 -101
- data/lib/asciidoctor/logging.rb +10 -8
- data/lib/asciidoctor/parser.rb +211 -220
- data/lib/asciidoctor/path_resolver.rb +17 -15
- data/lib/asciidoctor/reader.rb +87 -79
- data/lib/asciidoctor/rx.rb +9 -7
- data/lib/asciidoctor/section.rb +7 -0
- data/lib/asciidoctor/substitutors.rb +167 -148
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +3 -2
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +13 -5
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +7 -4
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +19 -11
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +35 -20
- data/lib/asciidoctor/syntax_highlighter.rb +16 -16
- data/lib/asciidoctor/table.rb +70 -43
- data/lib/asciidoctor/timings.rb +3 -3
- data/lib/asciidoctor/version.rb +1 -1
- data/lib/asciidoctor.rb +45 -19
- data/man/asciidoctor.1 +29 -31
- data/man/asciidoctor.adoc +35 -29
- metadata +17 -70
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Asciidoctor
|
3
3
|
# Public: Methods to perform substitutions on lines of AsciiDoc text. This module
|
4
|
-
# is
|
4
|
+
# is intended to be mixed-in to Section and Block to provide operations for performing
|
5
5
|
# the necessary substitutions.
|
6
6
|
module Substitutors
|
7
7
|
SpecialCharsRx = /[<&>]/
|
@@ -330,13 +330,13 @@ module Substitutors
|
|
330
330
|
# NOTE for convenience, map content (unparsed attrlist) to target when format is short
|
331
331
|
target ||= ext_config[:format] == :short ? content : target
|
332
332
|
end
|
333
|
-
if
|
334
|
-
if (inline_subs = replacement.attributes.delete 'subs')
|
335
|
-
replacement.text = apply_subs replacement.text,
|
333
|
+
if Inline === (replacement = extension.process_method[self, target, attributes])
|
334
|
+
if (inline_subs = replacement.attributes.delete 'subs') && (inline_subs = expand_subs inline_subs, 'custom inline macro')
|
335
|
+
replacement.text = apply_subs replacement.text, inline_subs
|
336
336
|
end
|
337
337
|
replacement.convert
|
338
338
|
elsif replacement
|
339
|
-
logger.info %(expected substitution value for custom inline macro to be of type Inline; got #{replacement.class}: #{match})
|
339
|
+
logger.info { %(expected substitution value for custom inline macro to be of type Inline; got #{replacement.class}: #{match}) }
|
340
340
|
replacement
|
341
341
|
else
|
342
342
|
''
|
@@ -445,23 +445,16 @@ module Substitutors
|
|
445
445
|
# indexterm:[Tigers,Big cats]
|
446
446
|
if (attrlist = normalize_text $2, true, true).include? '='
|
447
447
|
if (primary = (attrs = (AttributeList.new attrlist, self).parse)[1])
|
448
|
-
attrs['terms'] =
|
449
|
-
if (secondary = attrs[2])
|
450
|
-
terms << secondary
|
451
|
-
if (tertiary = attrs[3])
|
452
|
-
terms << tertiary
|
453
|
-
end
|
454
|
-
end
|
448
|
+
attrs['terms'] = [primary]
|
455
449
|
if (see_also = attrs['see-also'])
|
456
450
|
attrs['see-also'] = (see_also.include? ',') ? (see_also.split ',').map {|it| it.lstrip } : [see_also]
|
457
451
|
end
|
458
452
|
else
|
459
|
-
attrs = { 'terms' =>
|
453
|
+
attrs = { 'terms' => attrlist }
|
460
454
|
end
|
461
455
|
else
|
462
|
-
attrs = { 'terms' => (
|
456
|
+
attrs = { 'terms' => (split_simple_csv attrlist) }
|
463
457
|
end
|
464
|
-
#doc.register :indexterms, terms
|
465
458
|
(Inline.new self, :indexterm, nil, attributes: attrs).convert
|
466
459
|
when 'indexterm2'
|
467
460
|
# honor the escape
|
@@ -474,34 +467,33 @@ module Substitutors
|
|
474
467
|
attrs['see-also'] = (see_also.include? ',') ? (see_also.split ',').map {|it| it.lstrip } : [see_also]
|
475
468
|
end
|
476
469
|
end
|
477
|
-
#doc.register :indexterms, [term]
|
478
470
|
(Inline.new self, :indexterm, term, attributes: attrs, type: :visible).convert
|
479
471
|
else
|
480
|
-
|
472
|
+
encl_text = $3
|
481
473
|
# honor the escape
|
482
474
|
if $&.start_with? RS
|
483
475
|
# escape concealed index term, but process nested flow index term
|
484
|
-
if (
|
485
|
-
|
476
|
+
if (encl_text.start_with? '(') && (encl_text.end_with? ')')
|
477
|
+
encl_text = encl_text.slice 1, encl_text.length - 2
|
486
478
|
visible, before, after = true, '(', ')'
|
487
479
|
else
|
488
480
|
next $&.slice 1, $&.length
|
489
481
|
end
|
490
482
|
else
|
491
483
|
visible = true
|
492
|
-
if
|
493
|
-
if
|
494
|
-
|
484
|
+
if encl_text.start_with? '('
|
485
|
+
if encl_text.end_with? ')'
|
486
|
+
encl_text, visible = (encl_text.slice 1, encl_text.length - 2), false
|
495
487
|
else
|
496
|
-
|
488
|
+
encl_text, before, after = (encl_text.slice 1, encl_text.length), '(', ''
|
497
489
|
end
|
498
|
-
elsif
|
499
|
-
|
490
|
+
elsif encl_text.end_with? ')'
|
491
|
+
encl_text, before, after = encl_text.chop, '', ')'
|
500
492
|
end
|
501
493
|
end
|
502
494
|
if visible
|
503
495
|
# ((Tigers))
|
504
|
-
if (term = normalize_text
|
496
|
+
if (term = normalize_text encl_text, true).include? ';&'
|
505
497
|
if term.include? ' >> '
|
506
498
|
term, _, see = term.partition ' >> '
|
507
499
|
attrs = { 'see' => see }
|
@@ -510,12 +502,11 @@ module Substitutors
|
|
510
502
|
attrs = { 'see-also' => see_also }
|
511
503
|
end
|
512
504
|
end
|
513
|
-
#doc.register :indexterms, [term]
|
514
505
|
subbed_term = (Inline.new self, :indexterm, term, attributes: attrs, type: :visible).convert
|
515
506
|
else
|
516
507
|
# (((Tigers,Big cats)))
|
517
508
|
attrs = {}
|
518
|
-
if (terms = normalize_text
|
509
|
+
if (terms = normalize_text encl_text, true).include? ';&'
|
519
510
|
if terms.include? ' >> '
|
520
511
|
terms, _, see = terms.partition ' >> '
|
521
512
|
attrs['see'] = see
|
@@ -524,8 +515,7 @@ module Substitutors
|
|
524
515
|
attrs['see-also'] = see_also
|
525
516
|
end
|
526
517
|
end
|
527
|
-
attrs['terms'] =
|
528
|
-
#doc.register :indexterms, terms
|
518
|
+
attrs['terms'] = split_simple_csv terms
|
529
519
|
subbed_term = (Inline.new self, :indexterm, nil, attributes: attrs).convert
|
530
520
|
end
|
531
521
|
before ? %(#{before}#{subbed_term}#{after}) : subbed_term
|
@@ -542,20 +532,24 @@ module Substitutors
|
|
542
532
|
end
|
543
533
|
|
544
534
|
prefix, suffix = $1, ''
|
545
|
-
# NOTE if $4 is set,
|
535
|
+
# NOTE if $4 is set, we're looking at a formal macro (e.g., https://example.org[])
|
546
536
|
if $4
|
547
537
|
prefix = '' if prefix == 'link:'
|
548
|
-
|
538
|
+
link_text = nil if (link_text = $4).empty?
|
549
539
|
else
|
550
|
-
# invalid macro syntax (link: prefix w/o trailing square brackets)
|
551
|
-
# FIXME we probably shouldn't even get here
|
552
|
-
|
553
|
-
|
540
|
+
# invalid macro syntax (link: prefix w/o trailing square brackets or enclosed in double quotes)
|
541
|
+
# FIXME we probably shouldn't even get here when the link: prefix is present; the regex is doing too much
|
542
|
+
case prefix
|
543
|
+
when 'link:', ?", ?'
|
544
|
+
next $&
|
545
|
+
end
|
554
546
|
case $3
|
555
|
-
when ')'
|
556
|
-
# move trailing ) out of URL
|
547
|
+
when ')', '?', '!'
|
557
548
|
target = target.chop
|
558
|
-
suffix = ')'
|
549
|
+
if (suffix = $3) == ')' && (target.end_with? '.', '?', '!')
|
550
|
+
suffix = target[-1] + suffix
|
551
|
+
target = target.chop
|
552
|
+
end
|
559
553
|
# NOTE handle case when modified target is a URI scheme (e.g., http://)
|
560
554
|
next $& if target.end_with? '://'
|
561
555
|
when ';'
|
@@ -588,26 +582,37 @@ module Substitutors
|
|
588
582
|
end
|
589
583
|
|
590
584
|
attrs, link_opts = nil, { type: :link }
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
585
|
+
|
586
|
+
if link_text
|
587
|
+
new_link_text = link_text = link_text.gsub ESC_R_SB, R_SB if link_text.include? R_SB
|
588
|
+
if !doc.compat_mode && (link_text.include? '=')
|
589
|
+
# NOTE if an equals sign (=) is present, extract attributes from link text
|
590
|
+
link_text, attrs = extract_attributes_from_text link_text, ''
|
591
|
+
new_link_text = link_text
|
595
592
|
link_opts[:id] = attrs['id']
|
596
593
|
end
|
597
594
|
|
598
|
-
if
|
599
|
-
|
595
|
+
if link_text.end_with? '^'
|
596
|
+
new_link_text = link_text = link_text.chop
|
600
597
|
if attrs
|
601
598
|
attrs['window'] ||= '_blank'
|
602
599
|
else
|
603
600
|
attrs = { 'window' => '_blank' }
|
604
601
|
end
|
605
602
|
end
|
606
|
-
end
|
607
603
|
|
608
|
-
|
604
|
+
if new_link_text && new_link_text.empty?
|
605
|
+
# NOTE it's not possible for the URI scheme to be bare in this case
|
606
|
+
link_text = (doc_attrs.key? 'hide-uri-scheme') ? (target.sub UriSniffRx, '') : target
|
607
|
+
bare = true
|
608
|
+
end
|
609
|
+
else
|
609
610
|
# NOTE it's not possible for the URI scheme to be bare in this case
|
610
|
-
|
611
|
+
link_text = (doc_attrs.key? 'hide-uri-scheme') ? (target.sub UriSniffRx, '') : target
|
612
|
+
bare = true
|
613
|
+
end
|
614
|
+
|
615
|
+
if bare
|
611
616
|
if attrs
|
612
617
|
attrs['role'] = (attrs.key? 'role') ? %(bare #{attrs['role']}) : 'bare'
|
613
618
|
else
|
@@ -617,7 +622,7 @@ module Substitutors
|
|
617
622
|
|
618
623
|
doc.register :links, (link_opts[:target] = target)
|
619
624
|
link_opts[:attributes] = attrs if attrs
|
620
|
-
%(#{prefix}#{(Inline.new self, :anchor,
|
625
|
+
%(#{prefix}#{(Inline.new self, :anchor, link_text, link_opts).convert}#{suffix})
|
621
626
|
end
|
622
627
|
end
|
623
628
|
|
@@ -633,11 +638,12 @@ module Substitutors
|
|
633
638
|
target = $2
|
634
639
|
end
|
635
640
|
attrs, link_opts = nil, { type: :link }
|
636
|
-
unless (
|
637
|
-
|
641
|
+
unless (link_text = $3).empty?
|
642
|
+
link_text = link_text.gsub ESC_R_SB, R_SB if link_text.include? R_SB
|
638
643
|
if mailto
|
639
|
-
if !doc.compat_mode && (
|
640
|
-
|
644
|
+
if !doc.compat_mode && (link_text.include? ',')
|
645
|
+
# NOTE if a comma (,) is present, extract attributes from link text
|
646
|
+
link_text, attrs = extract_attributes_from_text link_text, ''
|
641
647
|
link_opts[:id] = attrs['id']
|
642
648
|
if attrs.key? 2
|
643
649
|
if attrs.key? 3
|
@@ -647,13 +653,14 @@ module Substitutors
|
|
647
653
|
end
|
648
654
|
end
|
649
655
|
end
|
650
|
-
elsif !doc.compat_mode && (
|
651
|
-
|
656
|
+
elsif !doc.compat_mode && (link_text.include? '=')
|
657
|
+
# NOTE if an equals sign (=) is present, extract attributes from link text
|
658
|
+
link_text, attrs = extract_attributes_from_text link_text, ''
|
652
659
|
link_opts[:id] = attrs['id']
|
653
660
|
end
|
654
661
|
|
655
|
-
if
|
656
|
-
|
662
|
+
if link_text.end_with? '^'
|
663
|
+
link_text = link_text.chop
|
657
664
|
if attrs
|
658
665
|
attrs['window'] ||= '_blank'
|
659
666
|
else
|
@@ -662,17 +669,17 @@ module Substitutors
|
|
662
669
|
end
|
663
670
|
end
|
664
671
|
|
665
|
-
if
|
672
|
+
if link_text.empty?
|
666
673
|
# mailto is a special case, already processed
|
667
674
|
if mailto
|
668
|
-
|
675
|
+
link_text = mailto_text
|
669
676
|
else
|
670
677
|
if doc_attrs.key? 'hide-uri-scheme'
|
671
|
-
if (
|
672
|
-
|
678
|
+
if (link_text = target.sub UriSniffRx, '').empty?
|
679
|
+
link_text = target
|
673
680
|
end
|
674
681
|
else
|
675
|
-
|
682
|
+
link_text = target
|
676
683
|
end
|
677
684
|
if attrs
|
678
685
|
attrs['role'] = (attrs.key? 'role') ? %(bare #{attrs['role']}) : 'bare'
|
@@ -685,7 +692,7 @@ module Substitutors
|
|
685
692
|
# QUESTION should a mailto be registered as an e-mail address?
|
686
693
|
doc.register :links, (link_opts[:target] = target)
|
687
694
|
link_opts[:attributes] = attrs if attrs
|
688
|
-
Inline.new(self, :anchor,
|
695
|
+
Inline.new(self, :anchor, link_text, link_opts).convert
|
689
696
|
end
|
690
697
|
end
|
691
698
|
|
@@ -732,15 +739,17 @@ module Substitutors
|
|
732
739
|
|
733
740
|
attrs = {}
|
734
741
|
if (refid = $1)
|
735
|
-
|
736
|
-
|
742
|
+
if refid.include? ','
|
743
|
+
refid, _, link_text = refid.partition ','
|
744
|
+
link_text = nil if (link_text = link_text.lstrip).empty?
|
745
|
+
end
|
737
746
|
else
|
738
747
|
macro = true
|
739
748
|
refid = $2
|
740
|
-
if (
|
741
|
-
|
742
|
-
# NOTE if an
|
743
|
-
|
749
|
+
if (link_text = $3)
|
750
|
+
link_text = link_text.gsub ESC_R_SB, R_SB if link_text.include? R_SB
|
751
|
+
# NOTE if an equals sign (=) is present, extract attributes from link text
|
752
|
+
link_text, attrs = extract_attributes_from_text link_text if !doc.compat_mode && (link_text.include? '=')
|
744
753
|
end
|
745
754
|
end
|
746
755
|
|
@@ -794,7 +803,7 @@ module Substitutors
|
|
794
803
|
refid, path, target = nil, nil, '#'
|
795
804
|
end
|
796
805
|
else
|
797
|
-
refid, path = path, %(#{doc.attributes['relfileprefix']}#{path}#{src2src ? (doc.attributes.fetch 'relfilesuffix', doc.outfilesuffix) : ''})
|
806
|
+
refid, path = path, %(#{doc.attributes['relfileprefix'] || ''}#{path}#{src2src ? (doc.attributes.fetch 'relfilesuffix', doc.outfilesuffix) : ''})
|
798
807
|
if fragment
|
799
808
|
refid, target = %(#{refid}##{fragment}), %(#{path}##{fragment})
|
800
809
|
else
|
@@ -804,7 +813,7 @@ module Substitutors
|
|
804
813
|
# handles: id (in compat mode or when natural xrefs are disabled)
|
805
814
|
elsif doc.compat_mode || !Compliance.natural_xrefs
|
806
815
|
refid, target = fragment, %(##{fragment})
|
807
|
-
logger.info %(possible invalid reference: #{refid}) if logger.info? && doc.catalog[:refs][refid]
|
816
|
+
logger.info %(possible invalid reference: #{refid}) if logger.info? && !doc.catalog[:refs][refid]
|
808
817
|
# handles: id
|
809
818
|
elsif doc.catalog[:refs][fragment]
|
810
819
|
refid, target = fragment, %(##{fragment})
|
@@ -819,7 +828,7 @@ module Substitutors
|
|
819
828
|
attrs['path'] = path
|
820
829
|
attrs['fragment'] = fragment
|
821
830
|
attrs['refid'] = refid
|
822
|
-
Inline.new(self, :anchor,
|
831
|
+
Inline.new(self, :anchor, link_text, type: :xref, target: target, attributes: attrs).convert
|
823
832
|
end
|
824
833
|
end
|
825
834
|
|
@@ -831,7 +840,7 @@ module Substitutors
|
|
831
840
|
# footnoteref
|
832
841
|
if $1
|
833
842
|
if $3
|
834
|
-
id,
|
843
|
+
id, content = $3.split ',', 2
|
835
844
|
logger.warn %(found deprecated footnoteref macro: #{$&}; use footnote macro with target instead) unless doc.compat_mode
|
836
845
|
else
|
837
846
|
next $&
|
@@ -839,33 +848,31 @@ module Substitutors
|
|
839
848
|
# footnote
|
840
849
|
else
|
841
850
|
id = $2
|
842
|
-
|
851
|
+
content = $3
|
843
852
|
end
|
844
853
|
|
845
854
|
if id
|
846
|
-
if
|
847
|
-
|
855
|
+
if (footnote = doc.footnotes.find {|candidate| candidate.id == id })
|
856
|
+
index, content = footnote.index, footnote.text
|
857
|
+
type, target, id = :xref, id, nil
|
858
|
+
elsif content
|
859
|
+
content = restore_passthroughs(normalize_text content, true, true)
|
848
860
|
index = doc.counter('footnote-number')
|
849
|
-
doc.register(:footnotes, Document::Footnote.new(index, id,
|
861
|
+
doc.register(:footnotes, Document::Footnote.new(index, id, content))
|
850
862
|
type, target = :ref, nil
|
851
863
|
else
|
852
|
-
|
853
|
-
|
854
|
-
else
|
855
|
-
logger.warn %(invalid footnote reference: #{id})
|
856
|
-
index, text = nil, id
|
857
|
-
end
|
858
|
-
type, target, id = :xref, id, nil
|
864
|
+
logger.warn %(invalid footnote reference: #{id})
|
865
|
+
type, target, content, id = :xref, id, id, nil
|
859
866
|
end
|
860
|
-
elsif
|
861
|
-
|
867
|
+
elsif content
|
868
|
+
content = restore_passthroughs(normalize_text content, true, true)
|
862
869
|
index = doc.counter('footnote-number')
|
863
|
-
doc.register(:footnotes, Document::Footnote.new(index, id,
|
870
|
+
doc.register(:footnotes, Document::Footnote.new(index, id, content))
|
864
871
|
type = target = nil
|
865
872
|
else
|
866
873
|
next $&
|
867
874
|
end
|
868
|
-
Inline.new(self, :footnote,
|
875
|
+
Inline.new(self, :footnote, content, attributes: { 'index' => index }, id: id, target: target, type: type).convert
|
869
876
|
end
|
870
877
|
end
|
871
878
|
|
@@ -917,7 +924,7 @@ module Substitutors
|
|
917
924
|
# use sub since it might be behind a line comment
|
918
925
|
$&.sub RS, ''
|
919
926
|
else
|
920
|
-
Inline.new(self, :callout, $4 == '.' ? (autonum += 1).to_s : $4, id: @document.callouts.read_next_id, attributes: { 'guard' => $1 }).convert
|
927
|
+
Inline.new(self, :callout, $4 == '.' ? (autonum += 1).to_s : $4, id: @document.callouts.read_next_id, attributes: { 'guard' => $1 || ($3 == '--' ? ['<!--', '-->'] : nil) }).convert
|
921
928
|
end
|
922
929
|
end
|
923
930
|
end
|
@@ -933,7 +940,7 @@ module Substitutors
|
|
933
940
|
# process_callouts - a Boolean flag indicating whether callout marks should be located and substituted
|
934
941
|
#
|
935
942
|
# Returns the highlighted source code, if a syntax highlighter is defined on the document, otherwise the source with
|
936
|
-
# verbatim
|
943
|
+
# verbatim substitutions applied
|
937
944
|
def highlight_source source, process_callouts
|
938
945
|
# NOTE the call to highlight? is a defensive check since, normally, we wouldn't arrive here unless it returns true
|
939
946
|
return sub_source source, process_callouts unless (syntax_hl = @document.syntax_highlighter) && syntax_hl.highlight?
|
@@ -942,10 +949,11 @@ module Substitutors
|
|
942
949
|
|
943
950
|
doc_attrs = @document.attributes
|
944
951
|
syntax_hl_name = syntax_hl.name
|
945
|
-
if (linenums_mode = (attr? 'linenums') ? (doc_attrs[%(#{syntax_hl_name}-linenums-mode)] || :table).to_sym : nil)
|
946
|
-
|
952
|
+
if (linenums_mode = (attr? 'linenums') ? (doc_attrs[%(#{syntax_hl_name}-linenums-mode)] || :table).to_sym : nil) &&
|
953
|
+
(start_line_number = (attr 'start', 1).to_i) < 1
|
954
|
+
start_line_number = 1
|
947
955
|
end
|
948
|
-
highlight_lines = resolve_lines_to_highlight source, (attr 'highlight') if attr? 'highlight'
|
956
|
+
highlight_lines = resolve_lines_to_highlight source, (attr 'highlight'), start_line_number if attr? 'highlight'
|
949
957
|
|
950
958
|
highlighted, source_offset = syntax_hl.highlight self, source, (attr 'language'),
|
951
959
|
callouts: callout_marks,
|
@@ -968,9 +976,10 @@ module Substitutors
|
|
968
976
|
#
|
969
977
|
# source - The String source.
|
970
978
|
# spec - The lines specifier (e.g., "1-5, !2, 10" or "1..5;!2;10")
|
979
|
+
# start - The line number of the first line (optional, default: false)
|
971
980
|
#
|
972
981
|
# Returns an [Array] of unique, sorted line numbers.
|
973
|
-
def resolve_lines_to_highlight source, spec
|
982
|
+
def resolve_lines_to_highlight source, spec, start = nil
|
974
983
|
lines = []
|
975
984
|
spec = spec.delete ' ' if spec.include? ' '
|
976
985
|
((spec.include? ',') ? (spec.split ',') : (spec.split ';')).map do |entry|
|
@@ -979,28 +988,29 @@ module Substitutors
|
|
979
988
|
negate = true
|
980
989
|
end
|
981
990
|
if (delim = (entry.include? '..') ? '..' : ((entry.include? '-') ? '-' : nil))
|
982
|
-
from,
|
991
|
+
from, _, to = entry.partition delim
|
983
992
|
to = (source.count LF) + 1 if to.empty? || (to = to.to_i) < 0
|
984
|
-
line_nums = (from.to_i..to).to_a
|
985
993
|
if negate
|
986
|
-
lines -=
|
994
|
+
lines -= (from.to_i..to).to_a
|
987
995
|
else
|
988
|
-
lines.
|
989
|
-
end
|
990
|
-
else
|
991
|
-
if negate
|
992
|
-
lines.delete entry.to_i
|
993
|
-
else
|
994
|
-
lines << entry.to_i
|
996
|
+
lines |= (from.to_i..to).to_a
|
995
997
|
end
|
998
|
+
elsif negate
|
999
|
+
lines.delete entry.to_i
|
1000
|
+
elsif !lines.include?(line = entry.to_i)
|
1001
|
+
lines << line
|
996
1002
|
end
|
997
1003
|
end
|
998
|
-
lines.
|
1004
|
+
# If the start attribute is defined, then the lines to highlight specified by the provided spec should be relative to the start value.
|
1005
|
+
unless (shift = start ? start - 1 : 0) == 0
|
1006
|
+
lines = lines.map {|it| it - shift }
|
1007
|
+
end
|
1008
|
+
lines.sort
|
999
1009
|
end
|
1000
1010
|
|
1001
1011
|
# Public: Extract the passthrough text from the document for reinsertion after processing.
|
1002
1012
|
#
|
1003
|
-
# text - The String from which to extract passthrough
|
1013
|
+
# text - The String from which to extract passthrough fragments
|
1004
1014
|
#
|
1005
1015
|
# Returns the String text with passthrough regions substituted with placeholders
|
1006
1016
|
def extract_passthroughs text
|
@@ -1112,7 +1122,7 @@ module Substitutors
|
|
1112
1122
|
end
|
1113
1123
|
subs = $2
|
1114
1124
|
content = normalize_text $3, nil, true
|
1115
|
-
# NOTE drop enclosing $ signs around latexmath for backwards compatibility with AsciiDoc
|
1125
|
+
# NOTE drop enclosing $ signs around latexmath for backwards compatibility with AsciiDoc.py
|
1116
1126
|
content = content.slice 1, content.length - 2 if type == :latexmath && (content.start_with? '$') && (content.end_with? '$')
|
1117
1127
|
subs = subs ? (resolve_pass_subs subs) : ((@document.basebackend? 'html') ? BASIC_SUBS : nil)
|
1118
1128
|
passthrus[passthru_key = passthrus.size] = { text: content, subs: subs, type: type }
|
@@ -1207,7 +1217,7 @@ module Substitutors
|
|
1207
1217
|
end
|
1208
1218
|
end
|
1209
1219
|
return unless candidates
|
1210
|
-
# weed out invalid options and remove duplicates (order is preserved; first
|
1220
|
+
# weed out invalid options and remove duplicates (order is preserved; first occurrence wins)
|
1211
1221
|
resolved = candidates & SUB_OPTIONS[type]
|
1212
1222
|
unless (candidates - resolved).empty?
|
1213
1223
|
invalid = candidates - resolved
|
@@ -1226,17 +1236,17 @@ module Substitutors
|
|
1226
1236
|
resolve_subs subs, :inline, nil, 'passthrough macro'
|
1227
1237
|
end
|
1228
1238
|
|
1229
|
-
# Public: Expand all groups in the subs list and return. If no subs are
|
1239
|
+
# Public: Expand all groups in the subs list and return. If no subs are resolved, return nil.
|
1230
1240
|
#
|
1231
|
-
# subs - The substitutions to expand; can be a Symbol, Symbol Array or
|
1241
|
+
# subs - The substitutions to expand; can be a Symbol, Symbol Array, or String
|
1242
|
+
# subject - The String to use in log messages to communicate the subject for which subs are being resolved (default: nil)
|
1232
1243
|
#
|
1233
1244
|
# Returns a Symbol Array of substitutions to pass to apply_subs or nil if no substitutions were resolved.
|
1234
|
-
def expand_subs subs
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
else
|
1245
|
+
def expand_subs subs, subject = nil
|
1246
|
+
case subs
|
1247
|
+
when ::Symbol
|
1248
|
+
subs == :none ? nil : SUB_GROUPS[subs] || [subs]
|
1249
|
+
when ::Array
|
1240
1250
|
expanded_subs = []
|
1241
1251
|
subs.each do |key|
|
1242
1252
|
unless key == :none
|
@@ -1247,8 +1257,9 @@ module Substitutors
|
|
1247
1257
|
end
|
1248
1258
|
end
|
1249
1259
|
end
|
1250
|
-
|
1251
1260
|
expanded_subs.empty? ? nil : expanded_subs
|
1261
|
+
else
|
1262
|
+
resolve_subs subs, :inline, nil, subject
|
1252
1263
|
end
|
1253
1264
|
end
|
1254
1265
|
|
@@ -1270,7 +1281,7 @@ module Substitutors
|
|
1270
1281
|
# NOTE :literal with listparagraph-option gets folded into text of list item later
|
1271
1282
|
default_subs = @context == :verse ? NORMAL_SUBS : VERBATIM_SUBS
|
1272
1283
|
when :raw
|
1273
|
-
# TODO make pass subs a compliance setting; AsciiDoc
|
1284
|
+
# TODO make pass subs a compliance setting; AsciiDoc.py performs :attributes and :macros on a pass block
|
1274
1285
|
default_subs = @context == :stem ? BASIC_SUBS : NO_SUBS
|
1275
1286
|
else
|
1276
1287
|
return @subs
|
@@ -1321,10 +1332,23 @@ module Substitutors
|
|
1321
1332
|
|
1322
1333
|
private
|
1323
1334
|
|
1335
|
+
# This method is used in cases when the attrlist can be mixed with the text of a macro.
|
1336
|
+
# If no attributes are detected aside from the first positional attribute, and the first positional
|
1337
|
+
# attribute matches the attrlist, then the original text is returned.
|
1338
|
+
def extract_attributes_from_text text, default_text = nil
|
1339
|
+
attrlist = (text.include? LF) ? (text.tr LF, ' ') : text
|
1340
|
+
if (resolved_text = (attrs = (AttributeList.new attrlist, self).parse)[1])
|
1341
|
+
# NOTE if resolved text remains unchanged, clear attributes and return unparsed text
|
1342
|
+
resolved_text == attrlist ? [text, attrs.clear] : [resolved_text, attrs]
|
1343
|
+
else
|
1344
|
+
[default_text, attrs]
|
1345
|
+
end
|
1346
|
+
end
|
1347
|
+
|
1324
1348
|
# Internal: Extract the callout numbers from the source to prepare it for syntax highlighting.
|
1325
1349
|
def extract_callouts source
|
1326
1350
|
callout_marks = {}
|
1327
|
-
lineno = 0
|
1351
|
+
autonum = lineno = 0
|
1328
1352
|
last_lineno = nil
|
1329
1353
|
callout_rx = (attr? 'line-comment') ? CalloutExtractRxMap[attr 'line-comment'] : CalloutExtractRx
|
1330
1354
|
# extract callout marks, indexed by line number
|
@@ -1336,7 +1360,7 @@ module Substitutors
|
|
1336
1360
|
# use sub since it might be behind a line comment
|
1337
1361
|
$&.sub RS, ''
|
1338
1362
|
else
|
1339
|
-
(callout_marks[lineno] ||= []) << [$1, $4]
|
1363
|
+
(callout_marks[lineno] ||= []) << [$1 || ($3 == '--' ? ['<!--', '-->'] : nil), $4 == '.' ? (autonum += 1).to_s : $4]
|
1340
1364
|
last_lineno = lineno
|
1341
1365
|
''
|
1342
1366
|
end
|
@@ -1358,15 +1382,15 @@ module Substitutors
|
|
1358
1382
|
else
|
1359
1383
|
preamble = ''
|
1360
1384
|
end
|
1361
|
-
|
1385
|
+
lineno = 0
|
1362
1386
|
preamble + ((source.split LF, -1).map do |line|
|
1363
1387
|
if (conums = callout_marks.delete lineno += 1)
|
1364
1388
|
if conums.size == 1
|
1365
|
-
guard,
|
1366
|
-
%(#{line}#{Inline.new(self, :callout,
|
1389
|
+
guard, numeral = conums[0]
|
1390
|
+
%(#{line}#{Inline.new(self, :callout, numeral, id: @document.callouts.read_next_id, attributes: { 'guard' => guard }).convert})
|
1367
1391
|
else
|
1368
|
-
%(#{line}#{conums.map do |guard_it,
|
1369
|
-
Inline.new(self, :callout,
|
1392
|
+
%(#{line}#{conums.map do |guard_it, numeral_it|
|
1393
|
+
Inline.new(self, :callout, numeral_it, id: @document.callouts.read_next_id, attributes: { 'guard' => guard_it }).convert
|
1370
1394
|
end.join ' '})
|
1371
1395
|
end
|
1372
1396
|
else
|
@@ -1453,33 +1477,28 @@ module Substitutors
|
|
1453
1477
|
#
|
1454
1478
|
# Returns a Hash of attributes (role and id only)
|
1455
1479
|
def parse_quoted_text_attributes str
|
1456
|
-
return {} if (str = str.rstrip).empty?
|
1457
1480
|
# NOTE attributes are typically resolved after quoted text, so substitute eagerly
|
1458
1481
|
str = sub_attributes str if str.include? ATTR_REF_HEAD
|
1459
1482
|
# for compliance, only consider first positional attribute (very unlikely)
|
1460
1483
|
str = str.slice 0, (str.index ',') if str.include? ','
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1484
|
+
if (str = str.strip).empty?
|
1485
|
+
{}
|
1486
|
+
elsif (str.start_with? '.', '#') && Compliance.shorthand_property_syntax
|
1487
|
+
before, _, after = str.partition '#'
|
1488
|
+
attrs = {}
|
1489
|
+
if after.empty?
|
1490
|
+
attrs['role'] = (before.tr '.', ' ').lstrip if before.length > 1
|
1467
1491
|
else
|
1468
|
-
|
1469
|
-
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
roles.concat more_roles
|
1492
|
+
id, _, roles = after.partition '.'
|
1493
|
+
attrs['id'] = id unless id.empty?
|
1494
|
+
if roles.empty?
|
1495
|
+
attrs['role'] = (before.tr '.', ' ').lstrip if before.length > 1
|
1496
|
+
elsif before.length > 1
|
1497
|
+
attrs['role'] = ((before + '.' + roles).tr '.', ' ').lstrip
|
1498
|
+
else
|
1499
|
+
attrs['role'] = roles.tr '.', ' '
|
1500
|
+
end
|
1478
1501
|
end
|
1479
|
-
|
1480
|
-
attrs = {}
|
1481
|
-
attrs['id'] = id if id
|
1482
|
-
attrs['role'] = roles.join ' ' unless roles.empty?
|
1483
1502
|
attrs
|
1484
1503
|
else
|
1485
1504
|
{ 'role' => str }
|
@@ -1513,7 +1532,7 @@ module Substitutors
|
|
1513
1532
|
case c
|
1514
1533
|
when ','
|
1515
1534
|
if quote_open
|
1516
|
-
accum
|
1535
|
+
accum += c
|
1517
1536
|
else
|
1518
1537
|
values << accum.strip
|
1519
1538
|
accum = ''
|
@@ -1521,7 +1540,7 @@ module Substitutors
|
|
1521
1540
|
when '"'
|
1522
1541
|
quote_open = !quote_open
|
1523
1542
|
else
|
1524
|
-
accum
|
1543
|
+
accum += c
|
1525
1544
|
end
|
1526
1545
|
end
|
1527
1546
|
values << accum.strip
|