asciidoctor 2.0.13 → 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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +151 -30
  3. data/LICENSE +1 -1
  4. data/README-de.adoc +9 -12
  5. data/README-fr.adoc +9 -12
  6. data/README-jp.adoc +10 -13
  7. data/README-zh_CN.adoc +9 -12
  8. data/README.adoc +40 -19
  9. data/asciidoctor.gemspec +2 -9
  10. data/data/locale/attributes-fr.adoc +2 -2
  11. data/data/locale/attributes-th.adoc +23 -0
  12. data/data/locale/attributes-vi.adoc +23 -0
  13. data/data/stylesheets/asciidoctor-default.css +54 -53
  14. data/data/stylesheets/coderay-asciidoctor.css +9 -9
  15. data/lib/asciidoctor/abstract_block.rb +11 -9
  16. data/lib/asciidoctor/abstract_node.rb +9 -8
  17. data/lib/asciidoctor/attribute_list.rb +1 -1
  18. data/lib/asciidoctor/block.rb +6 -6
  19. data/lib/asciidoctor/cli/invoker.rb +1 -2
  20. data/lib/asciidoctor/cli/options.rb +25 -25
  21. data/lib/asciidoctor/convert.rb +1 -0
  22. data/lib/asciidoctor/converter/docbook5.rb +45 -26
  23. data/lib/asciidoctor/converter/html5.rb +130 -102
  24. data/lib/asciidoctor/converter/manpage.rb +69 -64
  25. data/lib/asciidoctor/converter/template.rb +12 -13
  26. data/lib/asciidoctor/converter.rb +6 -4
  27. data/lib/asciidoctor/core_ext/hash/merge.rb +1 -1
  28. data/lib/asciidoctor/document.rb +61 -57
  29. data/lib/asciidoctor/extensions.rb +20 -12
  30. data/lib/asciidoctor/list.rb +2 -6
  31. data/lib/asciidoctor/load.rb +11 -9
  32. data/lib/asciidoctor/logging.rb +10 -8
  33. data/lib/asciidoctor/parser.rb +177 -193
  34. data/lib/asciidoctor/path_resolver.rb +3 -3
  35. data/lib/asciidoctor/reader.rb +73 -72
  36. data/lib/asciidoctor/rx.rb +5 -4
  37. data/lib/asciidoctor/section.rb +7 -0
  38. data/lib/asciidoctor/substitutors.rb +121 -121
  39. data/lib/asciidoctor/syntax_highlighter/coderay.rb +2 -1
  40. data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +1 -1
  41. data/lib/asciidoctor/syntax_highlighter/pygments.rb +16 -7
  42. data/lib/asciidoctor/syntax_highlighter/rouge.rb +2 -1
  43. data/lib/asciidoctor/syntax_highlighter.rb +8 -11
  44. data/lib/asciidoctor/table.rb +18 -20
  45. data/lib/asciidoctor/timings.rb +3 -3
  46. data/lib/asciidoctor/version.rb +1 -1
  47. data/lib/asciidoctor.rb +10 -10
  48. data/man/asciidoctor.1 +26 -28
  49. data/man/asciidoctor.adoc +33 -27
  50. metadata +8 -62
@@ -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 intented to be mixed-in to Section and Block to provide operations for performing
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 (Inline === (replacement = extension.process_method[self, target, attributes]))
334
- if (inline_subs = replacement.attributes.delete 'subs')
335
- replacement.text = apply_subs replacement.text, (expand_subs inline_subs)
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'] = terms = [primary]
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' => (terms = attrlist) }
453
+ attrs = { 'terms' => attrlist }
460
454
  end
461
455
  else
462
- attrs = { 'terms' => (terms = split_simple_csv attrlist) }
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
- text = $3
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 (text.start_with? '(') && (text.end_with? ')')
485
- text = text.slice 1, text.length - 2
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 text.start_with? '('
493
- if text.end_with? ')'
494
- text, visible = (text.slice 1, text.length - 2), false
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
- text, before, after = (text.slice 1, text.length), '(', ''
488
+ encl_text, before, after = (encl_text.slice 1, encl_text.length), '(', ''
497
489
  end
498
- elsif text.end_with? ')'
499
- text, before, after = text.chop, '', ')'
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 text, true).include? ';&'
496
+ if (term = normalize_text encl_text, true).include? ';&'
505
497
  if term.include? ' &gt;&gt; '
506
498
  term, _, see = term.partition ' &gt;&gt; '
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 text, true).include? ';&'
509
+ if (terms = normalize_text encl_text, true).include? ';&'
519
510
  if terms.include? ' &gt;&gt; '
520
511
  terms, _, see = terms.partition ' &gt;&gt; '
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'] = terms = split_simple_csv 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
@@ -545,7 +535,7 @@ module Substitutors
545
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
- text = $4
538
+ link_text = nil if (link_text = $4).empty?
549
539
  else
550
540
  # invalid macro syntax (link: prefix w/o trailing square brackets or enclosed in double quotes)
551
541
  # FIXME we probably shouldn't even get here when the link: prefix is present; the regex is doing too much
@@ -553,12 +543,13 @@ module Substitutors
553
543
  when 'link:', ?", ?'
554
544
  next $&
555
545
  end
556
- text = ''
557
546
  case $3
558
- when ')'
559
- # move trailing ) out of URL
547
+ when ')', '?', '!'
560
548
  target = target.chop
561
- suffix = ')'
549
+ if (suffix = $3) == ')' && (target.end_with? '.', '?', '!')
550
+ suffix = target[-1] + suffix
551
+ target = target.chop
552
+ end
562
553
  # NOTE handle case when modified target is a URI scheme (e.g., http://)
563
554
  next $& if target.end_with? '://'
564
555
  when ';'
@@ -591,27 +582,37 @@ module Substitutors
591
582
  end
592
583
 
593
584
  attrs, link_opts = nil, { type: :link }
594
- unless text.empty?
595
- text = text.gsub ESC_R_SB, R_SB if text.include? R_SB
596
- if !doc.compat_mode && (text.include? '=')
597
- # NOTE if an equals sign (=) is present, extract attributes from text
598
- text, attrs = extract_attributes_from_text text, ''
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
599
592
  link_opts[:id] = attrs['id']
600
593
  end
601
594
 
602
- if text.end_with? '^'
603
- text = text.chop
595
+ if link_text.end_with? '^'
596
+ new_link_text = link_text = link_text.chop
604
597
  if attrs
605
598
  attrs['window'] ||= '_blank'
606
599
  else
607
600
  attrs = { 'window' => '_blank' }
608
601
  end
609
602
  end
610
- end
611
603
 
612
- if text.empty?
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
613
610
  # NOTE it's not possible for the URI scheme to be bare in this case
614
- text = (doc_attrs.key? 'hide-uri-scheme') ? (target.sub UriSniffRx, '') : target
611
+ link_text = (doc_attrs.key? 'hide-uri-scheme') ? (target.sub UriSniffRx, '') : target
612
+ bare = true
613
+ end
614
+
615
+ if bare
615
616
  if attrs
616
617
  attrs['role'] = (attrs.key? 'role') ? %(bare #{attrs['role']}) : 'bare'
617
618
  else
@@ -621,7 +622,7 @@ module Substitutors
621
622
 
622
623
  doc.register :links, (link_opts[:target] = target)
623
624
  link_opts[:attributes] = attrs if attrs
624
- %(#{prefix}#{(Inline.new self, :anchor, text, link_opts).convert}#{suffix})
625
+ %(#{prefix}#{(Inline.new self, :anchor, link_text, link_opts).convert}#{suffix})
625
626
  end
626
627
  end
627
628
 
@@ -637,12 +638,12 @@ module Substitutors
637
638
  target = $2
638
639
  end
639
640
  attrs, link_opts = nil, { type: :link }
640
- unless (text = $3).empty?
641
- text = text.gsub ESC_R_SB, R_SB if text.include? R_SB
641
+ unless (link_text = $3).empty?
642
+ link_text = link_text.gsub ESC_R_SB, R_SB if link_text.include? R_SB
642
643
  if mailto
643
- if !doc.compat_mode && (text.include? ',')
644
- # NOTE if a comma (,) is present, extract attributes from text
645
- text, attrs = extract_attributes_from_text text, ''
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, ''
646
647
  link_opts[:id] = attrs['id']
647
648
  if attrs.key? 2
648
649
  if attrs.key? 3
@@ -652,14 +653,14 @@ module Substitutors
652
653
  end
653
654
  end
654
655
  end
655
- elsif !doc.compat_mode && (text.include? '=')
656
- # NOTE if an equals sign (=) is present, extract attributes from text
657
- text, attrs = extract_attributes_from_text text, ''
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, ''
658
659
  link_opts[:id] = attrs['id']
659
660
  end
660
661
 
661
- if text.end_with? '^'
662
- text = text.chop
662
+ if link_text.end_with? '^'
663
+ link_text = link_text.chop
663
664
  if attrs
664
665
  attrs['window'] ||= '_blank'
665
666
  else
@@ -668,17 +669,17 @@ module Substitutors
668
669
  end
669
670
  end
670
671
 
671
- if text.empty?
672
+ if link_text.empty?
672
673
  # mailto is a special case, already processed
673
674
  if mailto
674
- text = mailto_text
675
+ link_text = mailto_text
675
676
  else
676
677
  if doc_attrs.key? 'hide-uri-scheme'
677
- if (text = target.sub UriSniffRx, '').empty?
678
- text = target
678
+ if (link_text = target.sub UriSniffRx, '').empty?
679
+ link_text = target
679
680
  end
680
681
  else
681
- text = target
682
+ link_text = target
682
683
  end
683
684
  if attrs
684
685
  attrs['role'] = (attrs.key? 'role') ? %(bare #{attrs['role']}) : 'bare'
@@ -691,7 +692,7 @@ module Substitutors
691
692
  # QUESTION should a mailto be registered as an e-mail address?
692
693
  doc.register :links, (link_opts[:target] = target)
693
694
  link_opts[:attributes] = attrs if attrs
694
- Inline.new(self, :anchor, text, link_opts).convert
695
+ Inline.new(self, :anchor, link_text, link_opts).convert
695
696
  end
696
697
  end
697
698
 
@@ -738,15 +739,17 @@ module Substitutors
738
739
 
739
740
  attrs = {}
740
741
  if (refid = $1)
741
- refid, text = refid.split ',', 2
742
- text = text.lstrip if text
742
+ if refid.include? ','
743
+ refid, _, link_text = refid.partition ','
744
+ link_text = nil if (link_text = link_text.lstrip).empty?
745
+ end
743
746
  else
744
747
  macro = true
745
748
  refid = $2
746
- if (text = $3)
747
- text = text.gsub ESC_R_SB, R_SB if text.include? R_SB
748
- # NOTE if an equals sign (=) is present, extract attributes from text
749
- text, attrs = extract_attributes_from_text text if !doc.compat_mode && (text.include? '=')
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? '=')
750
753
  end
751
754
  end
752
755
 
@@ -800,7 +803,7 @@ module Substitutors
800
803
  refid, path, target = nil, nil, '#'
801
804
  end
802
805
  else
803
- 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) : ''})
804
807
  if fragment
805
808
  refid, target = %(#{refid}##{fragment}), %(#{path}##{fragment})
806
809
  else
@@ -825,7 +828,7 @@ module Substitutors
825
828
  attrs['path'] = path
826
829
  attrs['fragment'] = fragment
827
830
  attrs['refid'] = refid
828
- Inline.new(self, :anchor, text, type: :xref, target: target, attributes: attrs).convert
831
+ Inline.new(self, :anchor, link_text, type: :xref, target: target, attributes: attrs).convert
829
832
  end
830
833
  end
831
834
 
@@ -837,7 +840,7 @@ module Substitutors
837
840
  # footnoteref
838
841
  if $1
839
842
  if $3
840
- id, text = $3.split ',', 2
843
+ id, content = $3.split ',', 2
841
844
  logger.warn %(found deprecated footnoteref macro: #{$&}; use footnote macro with target instead) unless doc.compat_mode
842
845
  else
843
846
  next $&
@@ -845,31 +848,31 @@ module Substitutors
845
848
  # footnote
846
849
  else
847
850
  id = $2
848
- text = $3
851
+ content = $3
849
852
  end
850
853
 
851
854
  if id
852
855
  if (footnote = doc.footnotes.find {|candidate| candidate.id == id })
853
- index, text = footnote.index, footnote.text
856
+ index, content = footnote.index, footnote.text
854
857
  type, target, id = :xref, id, nil
855
- elsif text
856
- text = restore_passthroughs(normalize_text text, true, true)
858
+ elsif content
859
+ content = restore_passthroughs(normalize_text content, true, true)
857
860
  index = doc.counter('footnote-number')
858
- doc.register(:footnotes, Document::Footnote.new(index, id, text))
861
+ doc.register(:footnotes, Document::Footnote.new(index, id, content))
859
862
  type, target = :ref, nil
860
863
  else
861
864
  logger.warn %(invalid footnote reference: #{id})
862
- type, target, text, id = :xref, id, id, nil
865
+ type, target, content, id = :xref, id, id, nil
863
866
  end
864
- elsif text
865
- text = restore_passthroughs(normalize_text text, true, true)
867
+ elsif content
868
+ content = restore_passthroughs(normalize_text content, true, true)
866
869
  index = doc.counter('footnote-number')
867
- doc.register(:footnotes, Document::Footnote.new(index, id, text))
870
+ doc.register(:footnotes, Document::Footnote.new(index, id, content))
868
871
  type = target = nil
869
872
  else
870
873
  next $&
871
874
  end
872
- Inline.new(self, :footnote, text, attributes: { 'index' => index }, id: id, target: target, type: type).convert
875
+ Inline.new(self, :footnote, content, attributes: { 'index' => index }, id: id, target: target, type: type).convert
873
876
  end
874
877
  end
875
878
 
@@ -937,7 +940,7 @@ module Substitutors
937
940
  # process_callouts - a Boolean flag indicating whether callout marks should be located and substituted
938
941
  #
939
942
  # Returns the highlighted source code, if a syntax highlighter is defined on the document, otherwise the source with
940
- # verbatim substituions applied
943
+ # verbatim substitutions applied
941
944
  def highlight_source source, process_callouts
942
945
  # NOTE the call to highlight? is a defensive check since, normally, we wouldn't arrive here unless it returns true
943
946
  return sub_source source, process_callouts unless (syntax_hl = @document.syntax_highlighter) && syntax_hl.highlight?
@@ -946,8 +949,9 @@ module Substitutors
946
949
 
947
950
  doc_attrs = @document.attributes
948
951
  syntax_hl_name = syntax_hl.name
949
- if (linenums_mode = (attr? 'linenums') ? (doc_attrs[%(#{syntax_hl_name}-linenums-mode)] || :table).to_sym : nil)
950
- start_line_number = 1 if (start_line_number = (attr 'start', 1).to_i) < 1
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
951
955
  end
952
956
  highlight_lines = resolve_lines_to_highlight source, (attr 'highlight'), start_line_number if attr? 'highlight'
953
957
 
@@ -984,7 +988,7 @@ module Substitutors
984
988
  negate = true
985
989
  end
986
990
  if (delim = (entry.include? '..') ? '..' : ((entry.include? '-') ? '-' : nil))
987
- from, delim, to = entry.partition delim
991
+ from, _, to = entry.partition delim
988
992
  to = (source.count LF) + 1 if to.empty? || (to = to.to_i) < 0
989
993
  if negate
990
994
  lines -= (from.to_i..to).to_a
@@ -1006,7 +1010,7 @@ module Substitutors
1006
1010
 
1007
1011
  # Public: Extract the passthrough text from the document for reinsertion after processing.
1008
1012
  #
1009
- # text - The String from which to extract passthrough fragements
1013
+ # text - The String from which to extract passthrough fragments
1010
1014
  #
1011
1015
  # Returns the String text with passthrough regions substituted with placeholders
1012
1016
  def extract_passthroughs text
@@ -1118,7 +1122,7 @@ module Substitutors
1118
1122
  end
1119
1123
  subs = $2
1120
1124
  content = normalize_text $3, nil, true
1121
- # NOTE drop enclosing $ signs around latexmath for backwards compatibility with AsciiDoc Python
1125
+ # NOTE drop enclosing $ signs around latexmath for backwards compatibility with AsciiDoc.py
1122
1126
  content = content.slice 1, content.length - 2 if type == :latexmath && (content.start_with? '$') && (content.end_with? '$')
1123
1127
  subs = subs ? (resolve_pass_subs subs) : ((@document.basebackend? 'html') ? BASIC_SUBS : nil)
1124
1128
  passthrus[passthru_key = passthrus.size] = { text: content, subs: subs, type: type }
@@ -1213,7 +1217,7 @@ module Substitutors
1213
1217
  end
1214
1218
  end
1215
1219
  return unless candidates
1216
- # weed out invalid options and remove duplicates (order is preserved; first occurence wins)
1220
+ # weed out invalid options and remove duplicates (order is preserved; first occurrence wins)
1217
1221
  resolved = candidates & SUB_OPTIONS[type]
1218
1222
  unless (candidates - resolved).empty?
1219
1223
  invalid = candidates - resolved
@@ -1232,17 +1236,17 @@ module Substitutors
1232
1236
  resolve_subs subs, :inline, nil, 'passthrough macro'
1233
1237
  end
1234
1238
 
1235
- # Public: Expand all groups in the subs list and return. If no subs are resolve, return nil.
1239
+ # Public: Expand all groups in the subs list and return. If no subs are resolved, return nil.
1236
1240
  #
1237
- # subs - The substitutions to expand; can be a Symbol, Symbol Array or nil
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)
1238
1243
  #
1239
1244
  # Returns a Symbol Array of substitutions to pass to apply_subs or nil if no substitutions were resolved.
1240
- def expand_subs subs
1241
- if ::Symbol === subs
1242
- unless subs == :none
1243
- SUB_GROUPS[subs] || [subs]
1244
- end
1245
- 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
1246
1250
  expanded_subs = []
1247
1251
  subs.each do |key|
1248
1252
  unless key == :none
@@ -1253,8 +1257,9 @@ module Substitutors
1253
1257
  end
1254
1258
  end
1255
1259
  end
1256
-
1257
1260
  expanded_subs.empty? ? nil : expanded_subs
1261
+ else
1262
+ resolve_subs subs, :inline, nil, subject
1258
1263
  end
1259
1264
  end
1260
1265
 
@@ -1276,7 +1281,7 @@ module Substitutors
1276
1281
  # NOTE :literal with listparagraph-option gets folded into text of list item later
1277
1282
  default_subs = @context == :verse ? NORMAL_SUBS : VERBATIM_SUBS
1278
1283
  when :raw
1279
- # TODO make pass subs a compliance setting; AsciiDoc Python performs :attributes and :macros on a pass block
1284
+ # TODO make pass subs a compliance setting; AsciiDoc.py performs :attributes and :macros on a pass block
1280
1285
  default_subs = @context == :stem ? BASIC_SUBS : NO_SUBS
1281
1286
  else
1282
1287
  return @subs
@@ -1472,33 +1477,28 @@ module Substitutors
1472
1477
  #
1473
1478
  # Returns a Hash of attributes (role and id only)
1474
1479
  def parse_quoted_text_attributes str
1475
- return {} if (str = str.rstrip).empty?
1476
1480
  # NOTE attributes are typically resolved after quoted text, so substitute eagerly
1477
1481
  str = sub_attributes str if str.include? ATTR_REF_HEAD
1478
1482
  # for compliance, only consider first positional attribute (very unlikely)
1479
1483
  str = str.slice 0, (str.index ',') if str.include? ','
1480
-
1481
- if (str.start_with? '.', '#') && Compliance.shorthand_property_syntax
1482
- segments = str.split '#', 2
1483
-
1484
- if segments.size > 1
1485
- id, *more_roles = segments[1].split('.')
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
1486
1491
  else
1487
- more_roles = []
1488
- end
1489
-
1490
- roles = segments[0].empty? ? [] : segments[0].split('.')
1491
- if roles.size > 1
1492
- roles.shift
1493
- end
1494
-
1495
- if more_roles.size > 0
1496
- 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
1497
1501
  end
1498
-
1499
- attrs = {}
1500
- attrs['id'] = id if id
1501
- attrs['role'] = roles.join ' ' unless roles.empty?
1502
1502
  attrs
1503
1503
  else
1504
1504
  { 'role' => str }
@@ -1532,7 +1532,7 @@ module Substitutors
1532
1532
  case c
1533
1533
  when ','
1534
1534
  if quote_open
1535
- accum = accum + c
1535
+ accum += c
1536
1536
  else
1537
1537
  values << accum.strip
1538
1538
  accum = ''
@@ -1540,7 +1540,7 @@ module Substitutors
1540
1540
  when '"'
1541
1541
  quote_open = !quote_open
1542
1542
  else
1543
- accum = accum + c
1543
+ accum += c
1544
1544
  end
1545
1545
  end
1546
1546
  values << accum.strip
@@ -78,7 +78,8 @@ class SyntaxHighlighter::CodeRayAdapter < SyntaxHighlighter::Base
78
78
  end
79
79
 
80
80
  extend Styles # exports static methods
81
- include Loader, Styles # adds methods to instance
81
+ include Styles # adds methods to instance
82
+ include Loader # adds methods to instance
82
83
 
83
84
  CodeCellStartTagCs = '<td class="code"><pre>'
84
85
 
@@ -9,7 +9,7 @@ class SyntaxHighlighter::HighlightJsAdapter < SyntaxHighlighter::Base
9
9
  end
10
10
 
11
11
  def format node, lang, opts
12
- super node, lang, (opts.merge transform: proc {|_, code| code['class'] = %(language-#{lang || 'none'} hljs) } )
12
+ super node, lang, (opts.merge transform: proc {|_, code| code['class'] = %(language-#{lang || 'none'} hljs) })
13
13
  end
14
14
 
15
15
  def docinfo? location
@@ -33,13 +33,19 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
33
33
  highlighted = highlighted.sub WrapperTagRx, PreTagCs
34
34
  opts[:callouts] ? [highlighted, (idx = highlighted.index CodeCellStartTagCs) ? idx + CodeCellStartTagCs.length : nil] : highlighted
35
35
  else
36
- node.sub_specialchars source # handles nil response from ::Pygments::Lexer#highlight
36
+ node.sub_source source, false # handles nil response from ::Pygments::Lexer#highlight
37
37
  end
38
38
  elsif (highlighted = lexer.highlight source, options: highlight_opts)
39
- highlighted = highlighted.gsub StyledLinenoSpanTagRx, LinenoSpanTagCs if linenos && noclasses
39
+ if linenos
40
+ if noclasses
41
+ highlighted = highlighted.gsub StyledLinenoSpanTagRx, LinenoSpanTagCs
42
+ elsif highlighted.include? LegacyLinenoSpanStartTagCs
43
+ highlighted = highlighted.gsub LegacyLinenoSpanTagRx, LinenoSpanTagCs
44
+ end
45
+ end
40
46
  highlighted.sub WrapperTagRx, '\1'
41
47
  else
42
- node.sub_specialchars source # handles nil response from ::Pygments::Lexer#highlight
48
+ node.sub_source source, false # handles nil response from ::Pygments::Lexer#highlight
43
49
  end
44
50
  end
45
51
 
@@ -114,6 +120,7 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
114
120
  end
115
121
  @@stylesheet_cache = ::Hash.new do |cache, key|
116
122
  if (stylesheet = ::Pygments.css BASE_SELECTOR, classprefix: TOKEN_CLASS_PREFIX, style: key)
123
+ stylesheet = stylesheet.slice (stylesheet.index BASE_SELECTOR), stylesheet.length unless stylesheet.start_with? BASE_SELECTOR
117
124
  @@stylesheet_cache = cache.merge key => stylesheet
118
125
  stylesheet
119
126
  end
@@ -122,18 +129,20 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
122
129
  DEFAULT_STYLE = 'default'
123
130
  BASE_SELECTOR = 'pre.pygments'
124
131
  TOKEN_CLASS_PREFIX = 'tok-'
125
-
126
132
  BaseStyleRx = /^#{BASE_SELECTOR.gsub '.', '\\.'} +\{([^}]+?)\}/
127
133
 
128
134
  private_constant :BASE_SELECTOR, :TOKEN_CLASS_PREFIX, :BaseStyleRx
129
135
  end
130
136
 
131
137
  extend Styles # exports static methods
132
- include Loader, Styles # adds methods to instance
138
+ include Styles # adds methods to instance
139
+ include Loader # adds methods to instance
133
140
 
134
141
  CodeCellStartTagCs = '<td class="code">'
142
+ LegacyLinenoSpanStartTagCs = '<span class="lineno">'
143
+ LegacyLinenoSpanTagRx = %r(#{LegacyLinenoSpanStartTagCs}( *\d+) ?</span>)
135
144
  LinenoColumnStartTagsCs = '<td class="linenos"><div class="linenodiv"><pre>'
136
- LinenoSpanTagCs = '<span class="lineno">\1 </span>'
145
+ LinenoSpanTagCs = '<span class="linenos">\1</span>'
137
146
  PreTagCs = '<pre>\1</pre>'
138
147
  StyledLinenoColumnStartTagsRx = /<td><div class="linenodiv" style="[^"]+?"><pre style="[^"]+?">/
139
148
  StyledLinenoSpanTagRx = %r((?<=^|<span></span>)<span style="[^"]+">( *\d+) ?</span>)
@@ -143,6 +152,6 @@ class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
143
152
  # NOTE initial <span></span> preserves leading blank lines
144
153
  WrapperTagRx = %r(<div class="#{WRAPPER_CLASS}"><pre\b[^>]*?>(.*)</pre></div>\n*)m
145
154
 
146
- private_constant :CodeCellStartTagCs, :LinenoColumnStartTagsCs, :LinenoSpanTagCs, :PreTagCs, :StyledLinenoColumnStartTagsRx, :StyledLinenoSpanTagRx, :WrapperTagRx, :WRAPPER_CLASS
155
+ private_constant :CodeCellStartTagCs, :LegacyLinenoSpanStartTagCs, :LegacyLinenoSpanTagRx, :LinenoColumnStartTagsCs, :LinenoSpanTagCs, :PreTagCs, :StyledLinenoColumnStartTagsRx, :StyledLinenoSpanTagRx, :WrapperTagRx, :WRAPPER_CLASS
147
156
  end
148
157
  end
@@ -133,7 +133,8 @@ class SyntaxHighlighter::RougeAdapter < SyntaxHighlighter::Base
133
133
  end
134
134
 
135
135
  extend Styles # exports static methods
136
- include Loader, Styles # adds methods to instance
136
+ include Styles # adds methods to instance
137
+ include Loader # adds methods to instance
137
138
 
138
139
  CodeCellStartTagCs = '<td class="code">'
139
140