asciidoctor 2.0.18 → 2.0.23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +129 -7
- data/README-de.adoc +2 -1
- data/README-fr.adoc +2 -1
- data/README-jp.adoc +2 -1
- data/README-zh_CN.adoc +2 -1
- data/README.adoc +10 -8
- data/asciidoctor.gemspec +3 -3
- data/data/locale/attributes-sw.adoc +23 -0
- data/data/reference/syntax.adoc +1 -1
- data/data/stylesheets/asciidoctor-default.css +6 -8
- data/lib/asciidoctor/abstract_block.rb +1 -0
- data/lib/asciidoctor/abstract_node.rb +6 -6
- data/lib/asciidoctor/block.rb +1 -1
- data/lib/asciidoctor/converter/docbook5.rb +92 -58
- data/lib/asciidoctor/converter/html5.rb +2 -2
- data/lib/asciidoctor/converter/manpage.rb +45 -54
- data/lib/asciidoctor/converter/template.rb +2 -1
- data/lib/asciidoctor/extensions.rb +21 -0
- data/lib/asciidoctor/helpers.rb +13 -4
- data/lib/asciidoctor/logging.rb +2 -0
- data/lib/asciidoctor/parser.rb +69 -37
- data/lib/asciidoctor/path_resolver.rb +11 -2
- data/lib/asciidoctor/reader.rb +26 -12
- data/lib/asciidoctor/rx.rb +16 -16
- data/lib/asciidoctor/substitutors.rb +111 -115
- data/lib/asciidoctor/table.rb +22 -13
- data/lib/asciidoctor/version.rb +1 -1
- data/lib/asciidoctor.rb +2 -3
- data/man/asciidoctor.1 +7 -6
- data/man/asciidoctor.adoc +1 -1
- metadata +9 -8
@@ -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
|
-
|
42
|
+
manpage = true
|
43
|
+
root_tag_name = 'article'
|
43
44
|
end
|
44
45
|
root_tag_idx = result.size
|
45
46
|
id = node.id
|
46
|
-
|
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', ' '}</refmiscinfo>)
|
55
|
+
result << %(<refmiscinfo class="manual">#{node.attr 'manmanual', ' '}</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
|
-
|
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
|
-
|
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
|
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
|
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)}"#{
|
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
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
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
|
-
|
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
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
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}"#{
|
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 +
|
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
|
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 (
|
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 = /…(?:​)?/
|
29
29
|
WrappedIndentRx = /#{CG_BLANK}*#{LF}#{CG_BLANK}*/
|
30
30
|
XMLMarkupRx = /&#?[a-z\d]+;|</
|
31
|
-
PCDATAFilterRx =
|
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 =
|
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
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
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
|
-
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
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('<', '<').
|
715
|
+
gsub('>', '>').
|
716
|
+
gsub('+', '+'). # plus sign; alternately could use \c(pl
|
717
|
+
gsub(' ', '\~'). # non-breaking space
|
718
|
+
gsub('©', '\(co'). # copyright sign
|
719
|
+
gsub('®', '\(rg'). # registered sign
|
720
|
+
gsub('™', '\(tm'). # trademark sign
|
721
|
+
gsub('°', '\(de'). # degree sign
|
722
|
+
gsub(' ', ' '). # thin space
|
723
|
+
gsub('–', '\(en'). # en dash
|
724
|
+
gsub(EmDashCharRefRx, '\(em'). # em dash
|
725
|
+
gsub('‘', '\(oq'). # left single quotation mark
|
726
|
+
gsub('’', '\(cq'). # right single quotation mark
|
727
|
+
gsub('“', '\(lq'). # left double quotation mark
|
728
|
+
gsub('”', '\(rq'). # right double quotation mark
|
729
|
+
gsub('←', '\(<-'). # leftwards arrow
|
730
|
+
gsub('→', '\(->'). # rightwards arrow
|
731
|
+
gsub('⇐', '\(lA'). # leftwards double arrow
|
732
|
+
gsub('⇒', '\(rA'). # rightwards double arrow
|
733
|
+
gsub('​', '\:'). # zero width space
|
734
|
+
gsub('&', '&'). # 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
|
data/lib/asciidoctor/helpers.rb
CHANGED
@@ -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
|
-
|
124
|
-
|
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
|
|
data/lib/asciidoctor/logging.rb
CHANGED
@@ -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
|
|