asciidoctor 2.0.18 → 2.0.23

Sign up to get free protection for your applications and to get access to all the features.
@@ -39,18 +39,36 @@ class Converter::DocBook5Converter < Converter::Base
39
39
  result << ((node.attr? 'sectnumlevels') ? %(<?asciidoc-numbered maxdepth="#{node.attr 'sectnumlevels'}"?>) : '<?asciidoc-numbered?>') if node.attr? 'sectnums'
40
40
  lang_attribute = (node.attr? 'nolang') ? '' : %( xml:lang="#{node.attr 'lang', 'en'}")
41
41
  if (root_tag_name = node.doctype) == 'manpage'
42
- root_tag_name = 'refentry'
42
+ manpage = true
43
+ root_tag_name = 'article'
43
44
  end
44
45
  root_tag_idx = result.size
45
46
  id = node.id
46
- result << (document_info_tag node) unless node.noheader
47
+ abstract = find_root_abstract node
48
+ result << (document_info_tag node, abstract) unless node.noheader
49
+ if manpage
50
+ result << '<refentry>'
51
+ result << '<refmeta>'
52
+ result << %(<refentrytitle>#{node.apply_reftext_subs node.attr 'mantitle'}</refentrytitle>) if node.attr? 'mantitle'
53
+ result << %(<manvolnum>#{node.attr 'manvolnum'}</manvolnum>) if node.attr? 'manvolnum'
54
+ result << %(<refmiscinfo class="source">#{node.attr 'mansource', '&#160;'}</refmiscinfo>)
55
+ result << %(<refmiscinfo class="manual">#{node.attr 'manmanual', '&#160;'}</refmiscinfo>)
56
+ result << '</refmeta>'
57
+ result << '<refnamediv>'
58
+ result += (node.attr 'mannames').map {|n| %(<refname>#{n}</refname>) } if node.attr? 'mannames'
59
+ result << %(<refpurpose>#{node.attr 'manpurpose'}</refpurpose>) if node.attr? 'manpurpose'
60
+ result << '</refnamediv>'
61
+ end
47
62
  unless (docinfo_content = node.docinfo :header).empty?
48
63
  result << docinfo_content
49
64
  end
50
- result << node.content if node.blocks?
65
+ abstract = extract_abstract node, abstract if abstract
66
+ result << (node.blocks.map {|block| block.convert }.compact.join LF) if node.blocks?
67
+ restore_abstract abstract if abstract
51
68
  unless (docinfo_content = node.docinfo :footer).empty?
52
69
  result << docinfo_content
53
70
  end
71
+ result << '</refentry>' if manpage
54
72
  id, node.id = node.id, nil unless id
55
73
  # defer adding root tag in case document ID is auto-generated on demand
56
74
  result.insert root_tag_idx, %(<#{root_tag_name} xmlns="http://docbook.org/ns/docbook" xmlns:xl="http://www.w3.org/1999/xlink" version="5.0"#{lang_attribute}#{common_attributes id}>)
@@ -58,7 +76,15 @@ class Converter::DocBook5Converter < Converter::Base
58
76
  result.join LF
59
77
  end
60
78
 
61
- alias convert_embedded content_only
79
+ def convert_embedded node
80
+ # NOTE in DocBook 5, the root abstract must be in the info tag and is thus not part of the body
81
+ if @backend == 'docbook5' && (abstract = find_root_abstract node)
82
+ abstract = extract_abstract node, abstract
83
+ end
84
+ result = node.blocks.map {|block| block.convert }.compact.join LF
85
+ restore_abstract abstract if abstract
86
+ result
87
+ end
62
88
 
63
89
  def convert_section node
64
90
  if node.document.doctype == 'manpage'
@@ -66,7 +92,7 @@ class Converter::DocBook5Converter < Converter::Base
66
92
  else
67
93
  tag_name = node.sectname
68
94
  end
69
- title_el = node.special && (node.option? 'untitled') ? '' : %(<title>#{node.title}</title>\n)
95
+ title_el = node.special && ((node.option? 'notitle') || (node.option? 'untitled')) ? '' : %(<title>#{node.title}</title>\n)
70
96
  %(<#{tag_name}#{common_attributes node.id, node.role, node.reftext}>
71
97
  #{title_el}#{node.content}
72
98
  </#{tag_name}>)
@@ -168,27 +194,11 @@ class Converter::DocBook5Converter < Converter::Base
168
194
  end
169
195
 
170
196
  def convert_image node
171
- # NOTE according to the DocBook spec, content area, scaling, and scaling to fit are mutually exclusive
172
- # See http://tdg.docbook.org/tdg/4.5/imagedata-x.html#d0e79635
173
- if node.attr? 'scaledwidth'
174
- width_attribute = %( width="#{node.attr 'scaledwidth'}")
175
- depth_attribute = ''
176
- scale_attribute = ''
177
- elsif node.attr? 'scale'
178
- # QUESTION should we set the viewport using width and depth? (the scaled image would be contained within this box)
179
- #width_attribute = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : ''
180
- #depth_attribute = (node.attr? 'height') ? %( depth="#{node.attr 'height'}") : ''
181
- scale_attribute = %( scale="#{node.attr 'scale'}")
182
- else
183
- width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : ''
184
- depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : ''
185
- scale_attribute = ''
186
- end
187
197
  align_attribute = (node.attr? 'align') ? %( align="#{node.attr 'align'}") : ''
188
198
 
189
199
  mediaobject = %(<mediaobject>
190
200
  <imageobject>
191
- <imagedata fileref="#{node.image_uri(node.attr 'target')}"#{width_attribute}#{depth_attribute}#{scale_attribute}#{align_attribute}/>
201
+ <imagedata fileref="#{node.image_uri node.attr 'target'}"#{image_size_attributes node.attributes}#{align_attribute}/>
192
202
  </imageobject>
193
203
  <textobject><phrase>#{node.alt}</phrase></textobject>
194
204
  </mediaobject>)
@@ -248,10 +258,10 @@ class Converter::DocBook5Converter < Converter::Base
248
258
  def convert_stem node
249
259
  if (idx = node.subs.index :specialcharacters)
250
260
  node.subs.delete_at idx
251
- equation = node.content || ''
261
+ equation = node.content
252
262
  idx > 0 ? (node.subs.insert idx, :specialcharacters) : (node.subs.unshift :specialcharacters)
253
263
  else
254
- equation = node.content || ''
264
+ equation = node.content
255
265
  end
256
266
  if node.style == 'asciimath'
257
267
  # NOTE fop requires jeuclid to process mathml markup
@@ -293,13 +303,17 @@ class Converter::DocBook5Converter < Converter::Base
293
303
  def convert_open node
294
304
  case node.style
295
305
  when 'abstract'
296
- if node.parent == node.document && node.document.doctype == 'book'
297
- logger.warn 'abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
306
+ if (parent = node.parent) == node.document && node.document.doctype == 'book'
307
+ logger.warn 'abstract block cannot be used in a document without a doctitle when doctype is book. Excluding block content.'
298
308
  ''
299
309
  else
300
- %(<abstract>
310
+ result = %(<abstract>
301
311
  #{title_tag node}#{enclose_content node}
302
312
  </abstract>)
313
+ if @backend == 'docbook5' && !(node.option? 'root') && (parent.context == :open ? parent.style == 'partintro' : parent.context == :section && parent.sectname == 'partintro') && node == parent.blocks[0]
314
+ result = %(<info>\n#{result}\n</info>)
315
+ end
316
+ result
303
317
  end
304
318
  when 'partintro'
305
319
  if node.level == 0 && node.parent.context == :section && node.document.doctype == 'book'
@@ -521,11 +535,9 @@ class Converter::DocBook5Converter < Converter::Base
521
535
  end
522
536
 
523
537
  def convert_inline_image node
524
- width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : ''
525
- depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : ''
526
538
  %(<inlinemediaobject#{common_attributes nil, node.role}>
527
539
  <imageobject>
528
- <imagedata fileref="#{node.type == 'icon' ? (node.icon_uri node.target) : (node.image_uri node.target)}"#{width_attribute}#{depth_attribute}/>
540
+ <imagedata fileref="#{node.type == 'icon' ? (node.icon_uri node.target) : (node.image_uri node.target)}"#{image_size_attributes node.attributes}/>
529
541
  </imageobject>
530
542
  <textobject><phrase>#{node.alt}</phrase></textobject>
531
543
  </inlinemediaobject>)
@@ -633,6 +645,23 @@ class Converter::DocBook5Converter < Converter::Base
633
645
  end
634
646
  end
635
647
 
648
+ def image_size_attributes attributes
649
+ # NOTE according to the DocBook spec, content area, scaling, and scaling to fit are mutually exclusive
650
+ # See http://tdg.docbook.org/tdg/4.5/imagedata-x.html#d0e79635
651
+ if attributes.key? 'scaledwidth'
652
+ %( width="#{attributes['scaledwidth']}")
653
+ elsif attributes.key? 'scale'
654
+ # QUESTION should we set the viewport using width and depth? (the scaled image would be contained within this box)
655
+ #width_attribute = (attributes.key? 'width') ? %( width="#{attributes['width']}") : ''
656
+ #depth_attribute = (attributes.key? 'height') ? %( depth="#{attributes['height']}") : ''
657
+ %( scale="#{attributes['scale']}")
658
+ else
659
+ width_attribute = (attributes.key? 'width') ? %( contentwidth="#{attributes['width']}") : ''
660
+ depth_attribute = (attributes.key? 'height') ? %( contentdepth="#{attributes['height']}") : ''
661
+ %(#{width_attribute}#{depth_attribute})
662
+ end
663
+ end
664
+
636
665
  def author_tag doc, author
637
666
  result = []
638
667
  result << '<author>'
@@ -646,7 +675,7 @@ class Converter::DocBook5Converter < Converter::Base
646
675
  result.join LF
647
676
  end
648
677
 
649
- def document_info_tag doc
678
+ def document_info_tag doc, abstract
650
679
  result = ['<info>']
651
680
  unless doc.notitle
652
681
  if (title = doc.doctitle partition: true, use_fallback: true).subtitle?
@@ -700,22 +729,35 @@ class Converter::DocBook5Converter < Converter::Base
700
729
  result << docinfo_content
701
730
  end
702
731
  end
732
+ if abstract
733
+ abstract.set_option 'root'
734
+ result << (convert abstract, abstract.node_name)
735
+ abstract.remove_attr 'root-option'
736
+ end
703
737
  result << '</info>'
704
738
 
705
- if doc.doctype == 'manpage'
706
- result << '<refmeta>'
707
- result << %(<refentrytitle>#{doc.attr 'mantitle'}</refentrytitle>) if doc.attr? 'mantitle'
708
- result << %(<manvolnum>#{doc.attr 'manvolnum'}</manvolnum>) if doc.attr? 'manvolnum'
709
- result << %(<refmiscinfo class="source">#{doc.attr 'mansource', '&#160;'}</refmiscinfo>)
710
- result << %(<refmiscinfo class="manual">#{doc.attr 'manmanual', '&#160;'}</refmiscinfo>)
711
- result << '</refmeta>'
712
- result << '<refnamediv>'
713
- result += (doc.attr 'mannames').map {|n| %(<refname>#{n}</refname>) } if doc.attr? 'mannames'
714
- result << %(<refpurpose>#{doc.attr 'manpurpose'}</refpurpose>) if doc.attr? 'manpurpose'
715
- result << '</refnamediv>'
739
+ result.join LF
740
+ end
741
+
742
+ def find_root_abstract doc
743
+ return unless doc.blocks?
744
+ if (first_block = doc.blocks[0]).context == :preamble
745
+ return unless (first_block = first_block.blocks[0])
746
+ elsif first_block.context == :section
747
+ return first_block if first_block.sectname == 'abstract'
748
+ return unless first_block.sectname == 'preface' && (first_block = first_block.blocks[0])
716
749
  end
750
+ return first_block if first_block.style == 'abstract' && first_block.context == :open
751
+ end
717
752
 
718
- result.join LF
753
+ def extract_abstract document, abstract
754
+ parent = abstract.parent
755
+ parent = parent.parent while parent != document && parent.blocks.length == 1
756
+ parent.blocks.delete_at 0
757
+ end
758
+
759
+ def restore_abstract abstract
760
+ abstract.parent.blocks.insert 0, abstract
719
761
  end
720
762
 
721
763
  def get_root_document node
@@ -740,26 +782,18 @@ class Converter::DocBook5Converter < Converter::Base
740
782
 
741
783
  def cover_tag doc, face, use_placeholder = false
742
784
  if (cover_image = doc.attr %(#{face}-cover-image))
743
- width_attr = ''
744
- depth_attr = ''
745
785
  if (cover_image.include? ':') && ImageMacroRx =~ cover_image
746
- attrlist = $2
747
- cover_image = doc.image_uri $1
748
- if attrlist
749
- attrs = (AttributeList.new attrlist).parse ['alt', 'width', 'height']
750
- if attrs.key? 'scaledwidth'
751
- # NOTE scalefit="1" is the default in this case
752
- width_attr = %( width="#{attrs['scaledwidth']}")
753
- else
754
- width_attr = %( contentwidth="#{attrs['width']}") if attrs.key? 'width'
755
- depth_attr = %( contentdepth="#{attrs['height']}") if attrs.key? 'height'
756
- end
757
- end
786
+ target, attrlist = $1, $2
787
+ cover_image = doc.image_uri target
788
+ # NOTE scalefit="1" is the default for a cover image
789
+ size_attrs = image_size_attributes (AttributeList.new attrlist).parse %w(alt width height) if attrlist
790
+ else
791
+ size_attrs = ''
758
792
  end
759
793
  %(<cover role="#{face}">
760
794
  <mediaobject>
761
795
  <imageobject>
762
- <imagedata fileref="#{cover_image}"#{width_attr}#{depth_attr}/>
796
+ <imagedata fileref="#{cover_image}"#{size_attrs}/>
763
797
  </imageobject>
764
798
  </mediaobject>
765
799
  </cover>)
@@ -675,7 +675,7 @@ Your browser does not support the audio tag.
675
675
  title_element = node.title? ? %(<div class="title">#{node.captioned_title}</div>\n) : ''
676
676
  %(<div#{id_attribute} class="listingblock#{(role = node.role) ? " #{role}" : ''}">
677
677
  #{title_element}<div class="content">
678
- #{syntax_hl ? (syntax_hl.format node, lang, opts) : pre_open + (node.content || '') + pre_close}
678
+ #{syntax_hl ? (syntax_hl.format node, lang, opts) : pre_open + node.content + pre_close}
679
679
  </div>
680
680
  </div>)
681
681
  end
@@ -748,7 +748,7 @@ Your browser does not support the audio tag.
748
748
  def convert_open node
749
749
  if (style = node.style) == 'abstract'
750
750
  if node.parent == node.document && node.document.doctype == 'book'
751
- logger.warn 'abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
751
+ logger.warn 'abstract block cannot be used in a document without a doctitle when doctype is book. Excluding block content.'
752
752
  ''
753
753
  else
754
754
  id_attr = node.id ? %( id="#{node.id}") : ''
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Asciidoctor
3
- # A built-in {Converter} implementation that generates the man page (troff) format.
3
+ # A built-in {Converter} implementation that generates the man page (groff) format.
4
4
  #
5
5
  # The output of this converter adheres to the man definition as defined by
6
6
  # groff and uses the manpage output of the DocBook toolchain as a foundation.
@@ -28,7 +28,7 @@ class Converter::ManPageConverter < Converter::Base
28
28
  EllipsisCharRefRx = /&#8230;(?:&#8203;)?/
29
29
  WrappedIndentRx = /#{CG_BLANK}*#{LF}#{CG_BLANK}*/
30
30
  XMLMarkupRx = /&#?[a-z\d]+;|</
31
- PCDATAFilterRx = /(&#?[a-z\d]+;|<[^>]+>)|([^&<]+)/
31
+ PCDATAFilterRx = %r((&#?[a-z\d]+;|<#{ESC}\\f\(CR.*?</#{ESC}\\fP>|<[^>]+>)|([^&<]+))
32
32
 
33
33
  def initialize backend, opts = {}
34
34
  @backend = backend
@@ -39,7 +39,7 @@ class Converter::ManPageConverter < Converter::Base
39
39
  unless node.attr? 'mantitle'
40
40
  raise 'asciidoctor: ERROR: doctype must be set to manpage when using manpage backend'
41
41
  end
42
- mantitle = node.attr 'mantitle'
42
+ mantitle = (node.attr 'mantitle').gsub InvalidSectionIdCharsRx, ''
43
43
  manvolnum = node.attr 'manvolnum', '1'
44
44
  manname = node.attr 'manname', mantitle
45
45
  manmanual = node.attr 'manmanual'
@@ -236,7 +236,7 @@ r lw(\n(.lu*75u/100u).'
236
236
  result << (node.title? ? %(.sp
237
237
  .B #{manify node.captioned_title}
238
238
  .br) : '.sp')
239
- result << %([#{node.alt}])
239
+ result << %([#{manify node.alt}])
240
240
  result.join LF
241
241
  end
242
242
 
@@ -432,7 +432,7 @@ allbox tab(:);'
432
432
  when :literal
433
433
  cell_content = %(.nf#{LF}#{manify cell.text, whitespace: :preserve}#{LF}.fi)
434
434
  else
435
- cell_content = manify cell.content.join, whitespace: :normalize
435
+ cell_content = cell.content.map {|p| manify p, whitespace: :normalize }.join %(#{LF}.sp#{LF})
436
436
  end
437
437
  row_text[row_index] << %(#{cell_content}#{LF})
438
438
  else # tsec == :head || tsec == :foot
@@ -476,21 +476,14 @@ allbox tab(:);'
476
476
  end unless rows.empty?
477
477
  end
478
478
 
479
- #row_header.each do |row|
480
- # result << LF
481
- # row.each_with_index do |cell, i|
482
- # result << (cell.join ' ')
483
- # result << ' ' if row.size > i + 1
484
- # end
485
- #end
486
- # FIXME temporary fix to get basic table to display
487
- result << LF
488
- result << ('lt ' * row_header[0].size).chop
489
-
490
- result << %(.#{LF})
491
- row_text.each do |row|
492
- result << row.join
479
+ if node.has_header_option && (header_row_text = row_text[0])
480
+ result << %(#{LF}#{row_header[0].join ' '}.)
481
+ result << %(#{LF}#{header_row_text.join})
482
+ result << '.T&'
483
+ row_text = row_text.slice 1, row_text.length
493
484
  end
485
+ result << %(#{LF}#{row_header[0].map { 'lt' }.join ' '}.#{LF})
486
+ row_text.each {|row| result << row.join }
494
487
  result << %(.TE#{LF}.sp)
495
488
  result.join
496
489
  end
@@ -706,46 +699,44 @@ allbox tab(:);'
706
699
  def manify str, opts = {}
707
700
  case opts.fetch :whitespace, :collapse
708
701
  when :preserve
709
- str = str.gsub TAB, ET
702
+ str = (str.gsub TAB, ET).gsub(/(^)? +/) { $1 ? $& : %(#{ESC_BS}&#{$&}) }
710
703
  when :normalize
711
704
  str = str.gsub WrappedIndentRx, LF
712
705
  else
713
706
  str = str.tr_s WHITESPACE, ' '
714
707
  end
715
- str = str
716
- .gsub(LiteralBackslashRx) { $1 ? $& : '\\(rs' } # literal backslash (not a troff escape sequence)
717
- .gsub(EllipsisCharRefRx, '...') # horizontal ellipsis
718
- .gsub(LeadingPeriodRx, '\\\&.') # leading . is used in troff for macro call or other formatting; replace with \&.
719
- .gsub(EscapedMacroRx) do # drop orphaned \c escape lines, unescape troff macro, quote adjacent character, isolate macro line
720
- (rest = $3.lstrip).empty? ? %(.#{$1}"#{$2}") : %(.#{$1}"#{$2.rstrip}"#{LF}#{rest})
721
- end
722
- .gsub('-', '\-')
723
- .gsub('&lt;', '<')
724
- .gsub('&gt;', '>')
725
- .gsub('&#43;', '+') # plus sign; alternately could use \c(pl
726
- .gsub('&#160;', '\~') # non-breaking space
727
- .gsub('&#169;', '\(co') # copyright sign
728
- .gsub('&#174;', '\(rg') # registered sign
729
- .gsub('&#8482;', '\(tm') # trademark sign
730
- .gsub('&#176;', '\(de') # degree sign
731
- .gsub('&#8201;', ' ') # thin space
732
- .gsub('&#8211;', '\(en') # en dash
733
- .gsub(EmDashCharRefRx, '\(em') # em dash
734
- .gsub('&#8216;', '\(oq') # left single quotation mark
735
- .gsub('&#8217;', '\(cq') # right single quotation mark
736
- .gsub('&#8220;', '\(lq') # left double quotation mark
737
- .gsub('&#8221;', '\(rq') # right double quotation mark
738
- .gsub('&#8592;', '\(<-') # leftwards arrow
739
- .gsub('&#8594;', '\(->') # rightwards arrow
740
- .gsub('&#8656;', '\(lA') # leftwards double arrow
741
- .gsub('&#8658;', '\(rA') # rightwards double arrow
742
- .gsub('&#8203;', '\:') # zero width space
743
- .gsub('&amp;', '&') # literal ampersand (NOTE must take place after any other replacement that includes &)
744
- .gsub('\'', '\*(Aq') # apostrophe / neutral single quote
745
- .gsub(MockMacroRx, '\1') # mock boundary
746
- .gsub(ESC_BS, '\\') # unescape troff backslash (NOTE update if more escapes are added)
747
- .gsub(ESC_FS, '.') # unescape full stop in troff commands (NOTE must take place after gsub(LeadingPeriodRx))
748
- .rstrip # strip trailing space
708
+ str = str.
709
+ gsub(LiteralBackslashRx) { $1 ? $& : '\\(rs' }. # literal backslash (not a troff escape sequence)
710
+ gsub(EllipsisCharRefRx, '...'). # horizontal ellipsis
711
+ gsub(LeadingPeriodRx, '\\\&.'). # leading . is used in troff for macro call or other formatting; replace with \&.
712
+ gsub(EscapedMacroRx) { (rest = $3.lstrip).empty? ? %(.#{$1}"#{$2}") : %(.#{$1}"#{$2.rstrip}"#{LF}#{rest}) }. # drop orphaned \c escape lines, unescape troff macro, quote adjacent character, isolate macro line
713
+ gsub('-', '\-').
714
+ gsub('&lt;', '<').
715
+ gsub('&gt;', '>').
716
+ gsub('&#43;', '+'). # plus sign; alternately could use \c(pl
717
+ gsub('&#160;', '\~'). # non-breaking space
718
+ gsub('&#169;', '\(co'). # copyright sign
719
+ gsub('&#174;', '\(rg'). # registered sign
720
+ gsub('&#8482;', '\(tm'). # trademark sign
721
+ gsub('&#176;', '\(de'). # degree sign
722
+ gsub('&#8201;', ' '). # thin space
723
+ gsub('&#8211;', '\(en'). # en dash
724
+ gsub(EmDashCharRefRx, '\(em'). # em dash
725
+ gsub('&#8216;', '\(oq'). # left single quotation mark
726
+ gsub('&#8217;', '\(cq'). # right single quotation mark
727
+ gsub('&#8220;', '\(lq'). # left double quotation mark
728
+ gsub('&#8221;', '\(rq'). # right double quotation mark
729
+ gsub('&#8592;', '\(<-'). # leftwards arrow
730
+ gsub('&#8594;', '\(->'). # rightwards arrow
731
+ gsub('&#8656;', '\(lA'). # leftwards double arrow
732
+ gsub('&#8658;', '\(rA'). # rightwards double arrow
733
+ gsub('&#8203;', '\:'). # zero width space
734
+ gsub('&amp;', '&'). # literal ampersand (NOTE must take place after any other replacement that includes &)
735
+ gsub('\'', '\*(Aq'). # apostrophe / neutral single quote
736
+ gsub(MockMacroRx, '\1'). # mock boundary
737
+ gsub(ESC_BS, '\\'). # unescape troff backslash (NOTE update if more escapes are added)
738
+ gsub(ESC_FS, '.'). # unescape full stop in troff commands (NOTE must take place after gsub(LeadingPeriodRx))
739
+ rstrip # strip trailing space
749
740
  opts[:append_newline] ? %(#{str}#{LF}) : str
750
741
  end
751
742
 
@@ -29,7 +29,7 @@ class Converter::TemplateConverter < Converter::Base
29
29
  erb: { trim: 0 },
30
30
  # TODO line 466 of haml/compiler.rb sorts the attributes; file an issue to make this configurable
31
31
  # NOTE AsciiDoc syntax expects HTML/XML output to use double quotes around attribute values
32
- haml: { format: :xhtml, attr_wrapper: '"', escape_attrs: false, ugly: true },
32
+ haml: { format: :xhtml, attr_wrapper: '"', escape_html: false, escape_attrs: false, ugly: true },
33
33
  slim: { disable_escape: true, sort_attrs: false, pretty: false },
34
34
  }
35
35
 
@@ -227,6 +227,7 @@ class Converter::TemplateConverter < Converter::Base
227
227
  Helpers.require_library 'haml' unless defined? ::Haml::Engine
228
228
  # NOTE Haml 5 dropped support for pretty printing
229
229
  @engine_options[extsym].delete :ugly if defined? ::Haml::TempleEngine
230
+ @engine_options[extsym][:attr_quote] = @engine_options[extsym].delete :attr_wrapper unless defined? ::Haml::Options
230
231
  @active_engines[extsym] = true
231
232
  end
232
233
  when :erb
@@ -1109,6 +1109,9 @@ module Extensions
1109
1109
  # Public: Checks whether any {BlockProcessor} extensions are registered to
1110
1110
  # handle the specified block name appearing on the specified context.
1111
1111
  #
1112
+ # This method assumes you've called blocks? first to check whether any
1113
+ # block extensions are registered.
1114
+ #
1112
1115
  # Returns the [Extension] proxy object for the BlockProcessor that matches
1113
1116
  # the block name and context or false if no match is found.
1114
1117
  def registered_for_block? name, context
@@ -1124,6 +1127,9 @@ module Extensions
1124
1127
  #
1125
1128
  # name - the String or Symbol (coersed to a Symbol) macro name
1126
1129
  #
1130
+ # This method assumes you've called blocks? first to check whether any
1131
+ # block extensions are registered.
1132
+ #
1127
1133
  # Returns the [Extension] object stored in the registry that proxies the
1128
1134
  # corresponding BlockProcessor or nil if a match is not found.
1129
1135
  def find_block_extension name
@@ -1200,6 +1206,9 @@ module Extensions
1200
1206
  #
1201
1207
  # name - the String or Symbol (coersed to a Symbol) macro name
1202
1208
  #
1209
+ # This method assumes you've called block_macros? first to check whether any
1210
+ # block macro extensions are registered.
1211
+ #
1203
1212
  # Returns the [Extension] proxy object for the BlockMacroProcessor that matches
1204
1213
  # the macro name or false if no match is found.
1205
1214
  #--
@@ -1213,6 +1222,9 @@ module Extensions
1213
1222
  #
1214
1223
  # name - the String or Symbol (coersed to a Symbol) macro name
1215
1224
  #
1225
+ # This method assumes you've called block_macros? first to check whether any
1226
+ # block macro extensions are registered.
1227
+ #
1216
1228
  # Returns the [Extension] object stored in the registry that proxies the
1217
1229
  # corresponding BlockMacroProcessor or nil if a match is not found.
1218
1230
  def find_block_macro_extension name
@@ -1289,6 +1301,9 @@ module Extensions
1289
1301
  #
1290
1302
  # name - the String or Symbol (coersed to a Symbol) macro name
1291
1303
  #
1304
+ # This method assumes you've called inline_macros? first to check whether any
1305
+ # inline macro extensions are registered.
1306
+ #
1292
1307
  # Returns the [Extension] proxy object for the InlineMacroProcessor that matches
1293
1308
  # the macro name or false if no match is found.
1294
1309
  def registered_for_inline_macro? name
@@ -1300,6 +1315,9 @@ module Extensions
1300
1315
  #
1301
1316
  # name - the String or Symbol (coersed to a Symbol) macro name
1302
1317
  #
1318
+ # This method assumes you've called inline_macros? first to check whether any
1319
+ # inline macro extensions are registered.
1320
+ #
1303
1321
  # Returns the [Extension] object stored in the registry that proxies the
1304
1322
  # corresponding InlineMacroProcessor or nil if a match is not found.
1305
1323
  def find_inline_macro_extension name
@@ -1309,6 +1327,9 @@ module Extensions
1309
1327
  # Public: Retrieves the {Extension} proxy objects for all
1310
1328
  # InlineMacroProcessor instances in this registry.
1311
1329
  #
1330
+ # This method assumes you've called inline_macros? first to check whether any
1331
+ # inline macro extensions are registered.
1332
+ #
1312
1333
  # Returns an [Array] of Extension proxy objects.
1313
1334
  def inline_macros
1314
1335
  @inline_macro_extensions.values
@@ -120,8 +120,14 @@ module Helpers
120
120
  # str - the String to check
121
121
  #
122
122
  # returns true if the String is a URI, false if it is not
123
- def uriish? str
124
- (str.include? ':') && (UriSniffRx.match? str)
123
+ if ::RUBY_ENGINE == 'jruby'
124
+ def uriish? str
125
+ (str.include? ':') && !(str.start_with? 'uri:classloader:') && (UriSniffRx.match? str)
126
+ end
127
+ else
128
+ def uriish? str
129
+ (str.include? ':') && (UriSniffRx.match? str)
130
+ end
125
131
  end
126
132
 
127
133
  # Internal: Encode a URI component String for safe inclusion in a URI.
@@ -139,10 +145,13 @@ module Helpers
139
145
  })
140
146
  )
141
147
  end
148
+ elsif (CGI = ::CGI).respond_to? :escapeURIComponent
149
+ def encode_uri_component str
150
+ CGI.escapeURIComponent str
151
+ end
142
152
  else
143
- CGI = ::CGI
144
153
  def encode_uri_component str
145
- CGI.escape str
154
+ (CGI.escape str).gsub '+', '%20'
146
155
  end
147
156
  end
148
157
 
@@ -40,6 +40,7 @@ class MemoryLogger < ::Logger
40
40
  attr_reader :messages
41
41
 
42
42
  def initialize
43
+ super nil
43
44
  self.level = WARN
44
45
  @messages = []
45
46
  end
@@ -67,6 +68,7 @@ class NullLogger < ::Logger
67
68
  attr_reader :max_severity
68
69
 
69
70
  def initialize
71
+ super nil
70
72
  self.level = WARN
71
73
  end
72
74