asciidoctor 2.0.18 → 2.0.23
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 +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
|
|