asciidoctor 2.0.7 → 2.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +169 -7
- data/LICENSE +2 -1
- data/README-de.adoc +5 -15
- data/README-fr.adoc +4 -14
- data/README-jp.adoc +234 -186
- data/README-zh_CN.adoc +7 -17
- data/README.adoc +18 -18
- data/asciidoctor.gemspec +4 -4
- data/data/locale/attributes-ar.adoc +4 -3
- data/data/locale/attributes-bg.adoc +4 -3
- data/data/locale/attributes-ca.adoc +6 -5
- data/data/locale/attributes-cs.adoc +4 -3
- data/data/locale/attributes-da.adoc +6 -5
- data/data/locale/attributes-de.adoc +4 -4
- data/data/locale/attributes-en.adoc +4 -4
- data/data/locale/attributes-es.adoc +6 -5
- data/data/locale/attributes-fa.adoc +4 -3
- data/data/locale/attributes-fi.adoc +4 -3
- data/data/locale/attributes-fr.adoc +6 -5
- data/data/locale/attributes-hu.adoc +4 -3
- data/data/locale/attributes-id.adoc +4 -3
- data/data/locale/attributes-it.adoc +4 -3
- data/data/locale/attributes-ja.adoc +4 -3
- data/data/locale/{attributes-kr.adoc → attributes-ko.adoc} +4 -3
- data/data/locale/attributes-nb.adoc +4 -3
- data/data/locale/attributes-nl.adoc +4 -3
- data/data/locale/attributes-nn.adoc +4 -3
- data/data/locale/attributes-pl.adoc +8 -7
- data/data/locale/attributes-pt.adoc +6 -5
- data/data/locale/attributes-pt_BR.adoc +6 -5
- data/data/locale/attributes-ro.adoc +4 -3
- data/data/locale/attributes-ru.adoc +6 -5
- data/data/locale/attributes-sr.adoc +4 -4
- data/data/locale/attributes-sr_Latn.adoc +4 -4
- data/data/locale/attributes-sv.adoc +4 -4
- data/data/locale/attributes-tr.adoc +4 -3
- data/data/locale/attributes-uk.adoc +6 -5
- data/data/locale/attributes-zh_CN.adoc +4 -3
- data/data/locale/attributes-zh_TW.adoc +4 -3
- data/data/stylesheets/asciidoctor-default.css +33 -30
- data/lib/asciidoctor.rb +89 -791
- data/lib/asciidoctor/abstract_block.rb +19 -11
- data/lib/asciidoctor/abstract_node.rb +21 -15
- data/lib/asciidoctor/attribute_list.rb +59 -67
- data/lib/asciidoctor/cli/invoker.rb +2 -0
- data/lib/asciidoctor/cli/options.rb +3 -3
- data/lib/asciidoctor/convert.rb +167 -162
- data/lib/asciidoctor/converter.rb +14 -13
- data/lib/asciidoctor/converter/docbook5.rb +10 -26
- data/lib/asciidoctor/converter/html5.rb +62 -43
- data/lib/asciidoctor/converter/manpage.rb +13 -12
- data/lib/asciidoctor/converter/template.rb +6 -3
- data/lib/asciidoctor/document.rb +25 -41
- data/lib/asciidoctor/extensions.rb +3 -3
- data/lib/asciidoctor/helpers.rb +38 -39
- data/lib/asciidoctor/inline.rb +1 -1
- data/lib/asciidoctor/load.rb +101 -101
- data/lib/asciidoctor/parser.rb +30 -25
- data/lib/asciidoctor/path_resolver.rb +35 -25
- data/lib/asciidoctor/reader.rb +14 -7
- data/lib/asciidoctor/rx.rb +722 -0
- data/lib/asciidoctor/substitutors.rb +61 -39
- data/lib/asciidoctor/syntax_highlighter.rb +22 -8
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +1 -1
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +12 -4
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +7 -4
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +2 -3
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +15 -7
- data/lib/asciidoctor/table.rb +52 -23
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +6 -6
- data/man/asciidoctor.adoc +4 -3
- metadata +10 -9
@@ -85,23 +85,24 @@ module Converter
|
|
85
85
|
# Public: Derive backend traits (basebackend, filetype, outfilesuffix, htmlsyntax) from the given backend.
|
86
86
|
#
|
87
87
|
# backend - the String backend from which to derive the traits
|
88
|
+
# basebackend - the String basebackend to use in favor of deriving one from the backend (optional, default: nil)
|
88
89
|
#
|
89
90
|
# Returns the backend traits for the given backend as a [Hash].
|
90
|
-
def self.derive_backend_traits backend
|
91
|
+
def self.derive_backend_traits backend, basebackend = nil
|
91
92
|
return {} unless backend
|
92
|
-
if (
|
93
|
-
|
93
|
+
if (outfilesuffix = DEFAULT_EXTENSIONS[(basebackend ||= backend.sub TrailingDigitsRx, '')])
|
94
|
+
filetype = outfilesuffix.slice 1, outfilesuffix.length
|
94
95
|
else
|
95
|
-
|
96
|
+
outfilesuffix = %(.#{filetype = basebackend})
|
96
97
|
end
|
97
|
-
|
98
|
-
{ basebackend:
|
99
|
-
{ basebackend:
|
98
|
+
filetype == 'html' ?
|
99
|
+
{ basebackend: basebackend, filetype: filetype, htmlsyntax: 'html', outfilesuffix: outfilesuffix } :
|
100
|
+
{ basebackend: basebackend, filetype: filetype, outfilesuffix: outfilesuffix }
|
100
101
|
end
|
101
102
|
|
102
103
|
module BackendTraits
|
103
104
|
def basebackend value = nil
|
104
|
-
value ? (backend_traits[:basebackend] = value) : backend_traits[:basebackend]
|
105
|
+
value ? ((backend_traits value)[:basebackend] = value) : backend_traits[:basebackend]
|
105
106
|
end
|
106
107
|
|
107
108
|
def filetype value = nil
|
@@ -128,15 +129,15 @@ module Converter
|
|
128
129
|
@backend_traits = value || {}
|
129
130
|
end
|
130
131
|
|
131
|
-
def backend_traits
|
132
|
-
@backend_traits ||= Converter.derive_backend_traits @backend
|
132
|
+
def backend_traits basebackend = nil
|
133
|
+
@backend_traits ||= Converter.derive_backend_traits @backend, basebackend
|
133
134
|
end
|
134
135
|
|
135
136
|
alias backend_info backend_traits
|
136
137
|
|
137
138
|
# Deprecated: Use {Converter.derive_backend_traits} instead.
|
138
|
-
def self.derive_backend_traits backend
|
139
|
-
Converter.derive_backend_traits backend
|
139
|
+
def self.derive_backend_traits backend, basebackend = nil
|
140
|
+
Converter.derive_backend_traits backend, basebackend
|
140
141
|
end
|
141
142
|
end
|
142
143
|
|
@@ -148,7 +149,7 @@ module Converter
|
|
148
149
|
#
|
149
150
|
# Returns nothing.
|
150
151
|
def register_for *backends
|
151
|
-
Converter.register self, *backends
|
152
|
+
Converter.register self, *(backends.map {|backend| backend.to_s })
|
152
153
|
end
|
153
154
|
end
|
154
155
|
|
@@ -25,8 +25,8 @@ class Converter::DocBook5Converter < Converter::Base
|
|
25
25
|
MANPAGE_SECTION_TAGS = { 'section' => 'refsection', 'synopsis' => 'refsynopsisdiv' }
|
26
26
|
TABLE_PI_NAMES = ['dbhtml', 'dbfo', 'dblatex']
|
27
27
|
|
28
|
-
CopyrightRx = /^(
|
29
|
-
ImageMacroRx = /^image::?(
|
28
|
+
CopyrightRx = /^(#{CC_ANY}+?)(?: ((?:\d{4}\-)?\d{4}))?$/
|
29
|
+
ImageMacroRx = /^image::?(\S|\S#{CC_ANY}*?\S)\[(#{CC_ANY}+)?\]$/
|
30
30
|
|
31
31
|
def initialize backend, opts = {}
|
32
32
|
@backend = backend
|
@@ -35,20 +35,8 @@ class Converter::DocBook5Converter < Converter::Base
|
|
35
35
|
|
36
36
|
def convert_document node
|
37
37
|
result = ['<?xml version="1.0" encoding="UTF-8"?>']
|
38
|
-
if node.attr? 'toc'
|
39
|
-
|
40
|
-
result << %(<?asciidoc-toc maxdepth="#{node.attr 'toclevels'}"?>)
|
41
|
-
else
|
42
|
-
result << '<?asciidoc-toc?>'
|
43
|
-
end
|
44
|
-
end
|
45
|
-
if node.attr? 'sectnums'
|
46
|
-
if node.attr? 'sectnumlevels'
|
47
|
-
result << %(<?asciidoc-numbered maxdepth="#{node.attr 'sectnumlevels'}"?>)
|
48
|
-
else
|
49
|
-
result << '<?asciidoc-numbered?>'
|
50
|
-
end
|
51
|
-
end
|
38
|
+
result << ((node.attr? 'toclevels') ? %(<?asciidoc-toc maxdepth="#{node.attr 'toclevels'}"?>) : '<?asciidoc-toc?>') if node.attr? 'toc'
|
39
|
+
result << ((node.attr? 'sectnumlevels') ? %(<?asciidoc-numbered maxdepth="#{node.attr 'sectnumlevels'}"?>) : '<?asciidoc-numbered?>') if node.attr? 'sectnums'
|
52
40
|
lang_attribute = (node.attr? 'nolang') ? '' : %( xml:lang="#{node.attr 'lang', 'en'}")
|
53
41
|
if (root_tag_name = node.doctype) == 'manpage'
|
54
42
|
root_tag_name = 'refentry'
|
@@ -383,9 +371,7 @@ class Converter::DocBook5Converter < Converter::Base
|
|
383
371
|
has_body = false
|
384
372
|
result = []
|
385
373
|
pgwide_attribute = (node.option? 'pgwide') ? ' pgwide="1"' : ''
|
386
|
-
if (frame = node.attr 'frame', 'all', 'table-frame') == 'ends'
|
387
|
-
frame = 'topbot'
|
388
|
-
end
|
374
|
+
frame = 'topbot' if (frame = node.attr 'frame', 'all', 'table-frame') == 'ends'
|
389
375
|
grid = node.attr 'grid', nil, 'table-grid'
|
390
376
|
result << %(<#{tag_name = node.title? ? 'table' : 'informaltable'}#{common_attributes node.id, node.role, node.reftext}#{pgwide_attribute} frame="#{frame}" rowsep="#{['none', 'cols'].include?(grid) ? 0 : 1}" colsep="#{['none', 'rows'].include?(grid) ? 0 : 1}"#{(node.attr? 'orientation', 'landscape', 'table-orientation') ? ' orient="land"' : ''}>)
|
391
377
|
if (node.option? 'unbreakable')
|
@@ -413,12 +399,10 @@ class Converter::DocBook5Converter < Converter::Base
|
|
413
399
|
rows.each do |row|
|
414
400
|
result << '<row>'
|
415
401
|
row.each do |cell|
|
416
|
-
halign_attribute = (cell.attr? 'halign') ? %( align="#{cell.attr 'halign'}") : ''
|
417
|
-
valign_attribute = (cell.attr? 'valign') ? %( valign="#{cell.attr 'valign'}") : ''
|
418
402
|
colspan_attribute = cell.colspan ? %( namest="col_#{colnum = cell.column.attr 'colnumber'}" nameend="col_#{colnum + cell.colspan - 1}") : ''
|
419
403
|
rowspan_attribute = cell.rowspan ? %( morerows="#{cell.rowspan - 1}") : ''
|
420
404
|
# NOTE <entry> may not have whitespace (e.g., line breaks) as a direct descendant according to DocBook rules
|
421
|
-
entry_start = %(<entry#{
|
405
|
+
entry_start = %(<entry align="#{cell.attr 'halign'}" valign="#{cell.attr 'valign'}"#{colspan_attribute}#{rowspan_attribute}>)
|
422
406
|
if tsec == :head
|
423
407
|
cell_content = cell.text
|
424
408
|
else
|
@@ -499,7 +483,7 @@ class Converter::DocBook5Converter < Converter::Base
|
|
499
483
|
when :link
|
500
484
|
%(<link xl:href="#{node.target}">#{node.text}</link>)
|
501
485
|
when :bibref
|
502
|
-
%(<anchor#{common_attributes node.id, nil, "[#{node.reftext || node.id}]"}/>#{text})
|
486
|
+
%(<anchor#{common_attributes node.id, nil, (text = "[#{node.reftext || node.id}]")}/>#{text})
|
503
487
|
else
|
504
488
|
logger.warn %(unknown anchor type: #{node.type.inspect})
|
505
489
|
nil
|
@@ -529,7 +513,7 @@ class Converter::DocBook5Converter < Converter::Base
|
|
529
513
|
def convert_inline_image node
|
530
514
|
width_attribute = (node.attr? 'width') ? %( contentwidth="#{node.attr 'width'}") : ''
|
531
515
|
depth_attribute = (node.attr? 'height') ? %( contentdepth="#{node.attr 'height'}") : ''
|
532
|
-
%(<inlinemediaobject>
|
516
|
+
%(<inlinemediaobject#{common_attributes nil, node.role}>
|
533
517
|
<imageobject>
|
534
518
|
<imagedata fileref="#{node.type == 'icon' ? (node.icon_uri node.target) : (node.image_uri node.target)}"#{width_attribute}#{depth_attribute}/>
|
535
519
|
</imageobject>
|
@@ -634,7 +618,7 @@ class Converter::DocBook5Converter < Converter::Base
|
|
634
618
|
if (reftext.include? '<') && ((reftext = reftext.gsub XmlSanitizeRx, '').include? ' ')
|
635
619
|
reftext = (reftext.squeeze ' ').strip
|
636
620
|
end
|
637
|
-
reftext =
|
621
|
+
reftext = reftext.gsub '"', '"' if reftext.include? '"'
|
638
622
|
%(#{attrs} xreflabel="#{reftext}")
|
639
623
|
else
|
640
624
|
attrs
|
@@ -742,7 +726,7 @@ class Converter::DocBook5Converter < Converter::Base
|
|
742
726
|
if (cover_image.include? ':') && ImageMacroRx =~ cover_image
|
743
727
|
attrlist = $2
|
744
728
|
cover_image = doc.image_uri $1
|
745
|
-
|
729
|
+
if attrlist
|
746
730
|
attrs = (AttributeList.new attrlist).parse ['alt', 'width', 'height']
|
747
731
|
if attrs.key? 'scaledwidth'
|
748
732
|
# NOTE scalefit="1" is the default in this case
|
@@ -21,11 +21,17 @@ class Converter::Html5Converter < Converter::Base
|
|
21
21
|
#latexmath: INLINE_MATH_DELIMITERS[:latexmath] + [false],
|
22
22
|
}).default = ['', '']
|
23
23
|
|
24
|
-
DropAnchorRx = /<(?:a[
|
24
|
+
DropAnchorRx = /<(?:a\b[^>]*|\/a)>/
|
25
25
|
StemBreakRx = / *\\\n(?:\\?\n)*|\n\n+/
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
if RUBY_ENGINE == 'opal'
|
27
|
+
# NOTE In JavaScript, ^ matches the start of the string when the m flag is not set
|
28
|
+
SvgPreambleRx = /^#{CC_ALL}*?(?=<svg[\s>])/
|
29
|
+
SvgStartTagRx = /^<svg(?:\s[^>]*)?>/
|
30
|
+
else
|
31
|
+
SvgPreambleRx = /\A.*?(?=<svg[\s>])/m
|
32
|
+
SvgStartTagRx = /\A<svg(?:\s[^>]*)?>/
|
33
|
+
end
|
34
|
+
DimensionAttributeRx = /\s(?:width|height|style)=(["'])#{CC_ANY}*?\1/
|
29
35
|
|
30
36
|
def initialize backend, opts = {}
|
31
37
|
@backend = backend
|
@@ -90,6 +96,7 @@ class Converter::Html5Converter < Converter::Base
|
|
90
96
|
end
|
91
97
|
cdn_base_url = %(#{asset_uri_scheme}//cdnjs.cloudflare.com/ajax/libs)
|
92
98
|
linkcss = node.attr? 'linkcss'
|
99
|
+
max_width_attr = (node.attr? 'max-width') ? %( style="max-width: #{node.attr 'max-width'};") : ''
|
93
100
|
result = ['<!DOCTYPE html>']
|
94
101
|
lang_attribute = (node.attr? 'nolang') ? '' : %( lang="#{node.attr 'lang', 'en'}")
|
95
102
|
result << %(<html#{@xml_mode ? ' xmlns="http://www.w3.org/1999/xhtml"' : ''}#{lang_attribute}>)
|
@@ -132,7 +139,7 @@ class Converter::Html5Converter < Converter::Base
|
|
132
139
|
result << %(<link rel="stylesheet" href="#{node.normalize_web_path((node.attr 'stylesheet'), (node.attr 'stylesdir', ''))}"#{slash}>)
|
133
140
|
else
|
134
141
|
result << %(<style>
|
135
|
-
#{node.
|
142
|
+
#{node.read_contents (node.attr 'stylesheet'), start: (node.attr 'stylesdir'), warn_on_failure: true, label: 'stylesheet'}
|
136
143
|
</style>)
|
137
144
|
end
|
138
145
|
end
|
@@ -146,8 +153,8 @@ class Converter::Html5Converter < Converter::Base
|
|
146
153
|
end
|
147
154
|
end
|
148
155
|
|
149
|
-
if (syntax_hl = node.syntax_highlighter)
|
150
|
-
result << (
|
156
|
+
if (syntax_hl = node.syntax_highlighter)
|
157
|
+
result << (syntax_hl_docinfo_head_idx = result.size)
|
151
158
|
end
|
152
159
|
|
153
160
|
unless (docinfo_content = node.docinfo).empty?
|
@@ -155,29 +162,27 @@ class Converter::Html5Converter < Converter::Base
|
|
155
162
|
end
|
156
163
|
|
157
164
|
result << '</head>'
|
158
|
-
|
165
|
+
id_attr = node.id ? %( id="#{node.id}") : ''
|
159
166
|
if (sectioned = node.sections?) && (node.attr? 'toc-class') && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
|
160
167
|
classes = [node.doctype, (node.attr 'toc-class'), %(toc-#{node.attr 'toc-position', 'header'})]
|
161
168
|
else
|
162
169
|
classes = [node.doctype]
|
163
170
|
end
|
164
171
|
classes << node.role if node.role?
|
165
|
-
|
166
|
-
body_attrs << %(style="max-width: #{node.attr 'max-width'};") if node.attr? 'max-width'
|
167
|
-
result << %(<body #{body_attrs.join ' '}>)
|
172
|
+
result << %(<body#{id_attr} class="#{classes.join ' '}">)
|
168
173
|
|
169
174
|
unless (docinfo_content = node.docinfo :header).empty?
|
170
175
|
result << docinfo_content
|
171
176
|
end
|
172
177
|
|
173
178
|
unless node.noheader
|
174
|
-
result <<
|
179
|
+
result << %(<div id="header"#{max_width_attr}>)
|
175
180
|
if node.doctype == 'manpage'
|
176
181
|
result << %(<h1>#{node.doctitle} Manual Page</h1>)
|
177
182
|
if sectioned && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
|
178
183
|
result << %(<div id="toc" class="#{node.attr 'toc-class', 'toc'}">
|
179
184
|
<div id="toctitle">#{node.attr 'toc-title'}</div>
|
180
|
-
#{
|
185
|
+
#{node.converter.convert node, 'outline'}
|
181
186
|
</div>)
|
182
187
|
end
|
183
188
|
result << (generate_manname_section node) if node.attr? 'manpurpose'
|
@@ -210,19 +215,19 @@ class Converter::Html5Converter < Converter::Base
|
|
210
215
|
if sectioned && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
|
211
216
|
result << %(<div id="toc" class="#{node.attr 'toc-class', 'toc'}">
|
212
217
|
<div id="toctitle">#{node.attr 'toc-title'}</div>
|
213
|
-
#{
|
218
|
+
#{node.converter.convert node, 'outline'}
|
214
219
|
</div>)
|
215
220
|
end
|
216
221
|
end
|
217
222
|
result << '</div>'
|
218
223
|
end
|
219
224
|
|
220
|
-
result << %(<div id="content">
|
225
|
+
result << %(<div id="content"#{max_width_attr}>
|
221
226
|
#{node.content}
|
222
227
|
</div>)
|
223
228
|
|
224
229
|
if node.footnotes? && !(node.attr? 'nofootnotes')
|
225
|
-
result << %(<div id="footnotes">
|
230
|
+
result << %(<div id="footnotes"#{max_width_attr}>
|
226
231
|
<hr#{slash}>)
|
227
232
|
node.footnotes.each do |footnote|
|
228
233
|
result << %(<div class="footnote" id="_footnotedef_#{footnote.index}">
|
@@ -233,7 +238,7 @@ class Converter::Html5Converter < Converter::Base
|
|
233
238
|
end
|
234
239
|
|
235
240
|
unless node.nofooter
|
236
|
-
result <<
|
241
|
+
result << %(<div id="footer"#{max_width_attr}>)
|
237
242
|
result << '<div id="footer-text">'
|
238
243
|
result << %(#{node.attr 'version-label'} #{node.attr 'revnumber'}#{br}) if node.attr? 'revnumber'
|
239
244
|
result << %(#{node.attr 'last-update-label'} #{node.attr 'docdatetime'}) if (node.attr? 'last-update-label') && !(node.attr? 'reproducible')
|
@@ -244,8 +249,15 @@ class Converter::Html5Converter < Converter::Base
|
|
244
249
|
# JavaScript (and auxiliary stylesheets) loaded at the end of body for performance reasons
|
245
250
|
# See http://www.html5rocks.com/en/tutorials/speed/script-loading/
|
246
251
|
|
247
|
-
if syntax_hl
|
248
|
-
|
252
|
+
if syntax_hl
|
253
|
+
if syntax_hl.docinfo? :head
|
254
|
+
result[syntax_hl_docinfo_head_idx] = syntax_hl.docinfo :head, node, cdn_base_url: cdn_base_url, linkcss: linkcss, self_closing_tag_slash: slash
|
255
|
+
else
|
256
|
+
result.delete_at syntax_hl_docinfo_head_idx
|
257
|
+
end
|
258
|
+
if syntax_hl.docinfo? :footer
|
259
|
+
result << (syntax_hl.docinfo :footer, node, cdn_base_url: cdn_base_url, linkcss: linkcss, self_closing_tag_slash: slash)
|
260
|
+
end
|
249
261
|
end
|
250
262
|
|
251
263
|
if node.attr? 'stem'
|
@@ -269,7 +281,7 @@ MathJax.Hub.Config({
|
|
269
281
|
})
|
270
282
|
MathJax.Hub.Register.StartupHook("AsciiMath Jax Ready", function () {
|
271
283
|
MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {
|
272
|
-
if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains(
|
284
|
+
if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains("stemblock")) {
|
273
285
|
data.math.root.display = "block"
|
274
286
|
}
|
275
287
|
return data
|
@@ -305,7 +317,7 @@ MathJax.Hub.Register.StartupHook("AsciiMath Jax Ready", function () {
|
|
305
317
|
if node.sections? && (node.attr? 'toc') && (toc_p = node.attr 'toc-placement') != 'macro' && toc_p != 'preamble'
|
306
318
|
result << %(<div id="toc" class="toc">
|
307
319
|
<div id="toctitle">#{node.attr 'toc-title'}</div>
|
308
|
-
#{
|
320
|
+
#{node.converter.convert node, 'outline'}
|
309
321
|
</div>)
|
310
322
|
end
|
311
323
|
|
@@ -622,9 +634,7 @@ Your browser does not support the audio tag.
|
|
622
634
|
end
|
623
635
|
end
|
624
636
|
img ||= %(<img src="#{node.image_uri target}" alt="#{encode_attribute_value node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>)
|
625
|
-
if node.attr? 'link'
|
626
|
-
img = %(<a class="image" href="#{node.attr 'link'}"#{(append_link_constraint_attrs node).join}>#{img}</a>)
|
627
|
-
end
|
637
|
+
img = %(<a class="image" href="#{node.attr 'link'}"#{(append_link_constraint_attrs node).join}>#{img}</a>) if node.attr? 'link'
|
628
638
|
id_attr = node.id ? %( id="#{node.id}") : ''
|
629
639
|
classes = ['imageblock']
|
630
640
|
classes << (node.attr 'float') if node.attr? 'float'
|
@@ -683,8 +693,8 @@ Your browser does not support the audio tag.
|
|
683
693
|
open, close = BLOCK_MATH_DELIMITERS[style = node.style.to_sym]
|
684
694
|
if (equation = node.content)
|
685
695
|
if style == :asciimath && (equation.include? LF)
|
686
|
-
br = %(<br#{@void_element_slash}
|
687
|
-
equation = equation.gsub(StemBreakRx) { %(#{close}#{br * ($&.count LF)}#{open}) }
|
696
|
+
br = %(#{LF}<br#{@void_element_slash}>)
|
697
|
+
equation = equation.gsub(StemBreakRx) { %(#{close}#{br * (($&.count LF) - 1)}#{LF}#{open}) }
|
688
698
|
end
|
689
699
|
unless (equation.start_with? open) && (equation.end_with? close)
|
690
700
|
equation = %(#{open}#{equation}#{close})
|
@@ -790,7 +800,7 @@ Your browser does not support the audio tag.
|
|
790
800
|
toc = %(
|
791
801
|
<div id="toc" class="#{doc.attr 'toc-class', 'toc'}">
|
792
802
|
<div id="toctitle">#{doc.attr 'toc-title'}</div>
|
793
|
-
#{
|
803
|
+
#{doc.converter.convert doc, 'outline'}
|
794
804
|
</div>)
|
795
805
|
else
|
796
806
|
toc = ''
|
@@ -842,7 +852,8 @@ Your browser does not support the audio tag.
|
|
842
852
|
def convert_table node
|
843
853
|
result = []
|
844
854
|
id_attribute = node.id ? %( id="#{node.id}") : ''
|
845
|
-
|
855
|
+
frame = 'ends' if (frame = node.attr 'frame', 'all', 'table-frame') == 'topbot'
|
856
|
+
classes = ['tableblock', %(frame-#{frame}), %(grid-#{node.attr 'grid', 'all', 'table-grid'})]
|
846
857
|
if (stripes = node.attr 'stripes', nil, 'table-stripes')
|
847
858
|
classes << %(stripes-#{stripes})
|
848
859
|
end
|
@@ -928,7 +939,7 @@ Your browser does not support the audio tag.
|
|
928
939
|
|
929
940
|
%(<div#{id_attr} class="#{role}">
|
930
941
|
<div#{title_id_attr} class="title">#{title}</div>
|
931
|
-
#{
|
942
|
+
#{doc.converter.convert doc, 'outline', toclevels: levels}
|
932
943
|
</div>)
|
933
944
|
end
|
934
945
|
|
@@ -1083,7 +1094,7 @@ Your browser does not support the audio tag.
|
|
1083
1094
|
time_anchor = (start_t || end_t) ? %(#t=#{start_t || ''}#{end_t ? ",#{end_t}" : ''}) : ''
|
1084
1095
|
%(<div#{id_attribute}#{class_attribute}>#{title_element}
|
1085
1096
|
<div class="content">
|
1086
|
-
<video src="#{node.media_uri(node.attr 'target')}#{time_anchor}"#{width_attribute}#{height_attribute}#{poster_attribute}#{(node.option? 'autoplay') ? (append_boolean_attribute 'autoplay', xml) : ''}#{(node.option? 'nocontrols') ? '' : (append_boolean_attribute 'controls', xml)}#{(node.option? 'loop') ? (append_boolean_attribute 'loop', xml) : ''}#{preload_attribute}>
|
1097
|
+
<video src="#{node.media_uri(node.attr 'target')}#{time_anchor}"#{width_attribute}#{height_attribute}#{poster_attribute}#{(node.option? 'autoplay') ? (append_boolean_attribute 'autoplay', xml) : ''}#{(node.option? 'muted') ? (append_boolean_attribute 'muted', xml) : ''}#{(node.option? 'nocontrols') ? '' : (append_boolean_attribute 'controls', xml)}#{(node.option? 'loop') ? (append_boolean_attribute 'loop', xml) : ''}#{preload_attribute}>
|
1087
1098
|
Your browser does not support the video tag.
|
1088
1099
|
</video>
|
1089
1100
|
</div>
|
@@ -1101,8 +1112,13 @@ Your browser does not support the video tag.
|
|
1101
1112
|
attrs = node.role ? %( class="#{node.role}") : ''
|
1102
1113
|
unless (text = node.text)
|
1103
1114
|
refid = node.attributes['refid']
|
1104
|
-
if AbstractNode === (ref = (@refs ||= node.document.catalog[:refs])[refid])
|
1105
|
-
text =
|
1115
|
+
if AbstractNode === (ref = (@refs ||= node.document.catalog[:refs])[refid]) && (@resolving_xref ||= (outer = true)) && outer
|
1116
|
+
if !(text = ref.xreftext node.attr 'xrefstyle', nil, true)
|
1117
|
+
text = %([#{refid}])
|
1118
|
+
elsif text.include? '<a'
|
1119
|
+
text = text.gsub DropAnchorRx, ''
|
1120
|
+
end
|
1121
|
+
@resolving_xref = nil
|
1106
1122
|
else
|
1107
1123
|
text = %([#{refid}])
|
1108
1124
|
end
|
@@ -1138,8 +1154,10 @@ Your browser does not support the video tag.
|
|
1138
1154
|
elsif node.document.attr? 'icons'
|
1139
1155
|
src = node.icon_uri("callouts/#{node.text}")
|
1140
1156
|
%(<img src="#{src}" alt="#{node.text}"#{@void_element_slash}>)
|
1157
|
+
elsif ::Array === (guard = node.attributes['guard'])
|
1158
|
+
%(<!--<b class="conum">(#{node.text})</b>-->)
|
1141
1159
|
else
|
1142
|
-
%(#{
|
1160
|
+
%(#{guard}<b class="conum">(#{node.text})</b>)
|
1143
1161
|
end
|
1144
1162
|
end
|
1145
1163
|
|
@@ -1157,7 +1175,7 @@ Your browser does not support the video tag.
|
|
1157
1175
|
end
|
1158
1176
|
|
1159
1177
|
def convert_inline_image node
|
1160
|
-
if (type = node.type) == 'icon' && (node.document.attr? 'icons', 'font')
|
1178
|
+
if (type = node.type || 'image') == 'icon' && (node.document.attr? 'icons', 'font')
|
1161
1179
|
class_attr_val = %(fa fa-#{node.target})
|
1162
1180
|
{ 'size' => 'fa-', 'rotate' => 'fa-rotate-', 'flip' => 'fa-flip-' }.each do |key, prefix|
|
1163
1181
|
class_attr_val = %(#{class_attr_val} #{prefix}#{node.attr key}) if node.attr? key
|
@@ -1180,9 +1198,7 @@ Your browser does not support the video tag.
|
|
1180
1198
|
end
|
1181
1199
|
img ||= %(<img src="#{type == 'icon' ? (node.icon_uri target) : (node.image_uri target)}" alt="#{encode_attribute_value node.alt}"#{attrs}#{@void_element_slash}>)
|
1182
1200
|
end
|
1183
|
-
if node.attr? 'link'
|
1184
|
-
img = %(<a class="image" href="#{node.attr 'link'}"#{(append_link_constraint_attrs node).join}>#{img}</a>)
|
1185
|
-
end
|
1201
|
+
img = %(<a class="image" href="#{node.attr 'link'}"#{(append_link_constraint_attrs node).join}>#{img}</a>) if node.attr? 'link'
|
1186
1202
|
if (role = node.role)
|
1187
1203
|
if node.attr? 'float'
|
1188
1204
|
class_attr_val = %(#{type} #{node.attr 'float'} #{role})
|
@@ -1246,16 +1262,19 @@ Your browser does not support the video tag.
|
|
1246
1262
|
|
1247
1263
|
# NOTE expose read_svg_contents for Bespoke converter
|
1248
1264
|
def read_svg_contents node, target
|
1249
|
-
if (svg = node.read_contents target, start: (node.document.attr 'imagesdir'), normalize: true, label: 'SVG')
|
1265
|
+
if (svg = node.read_contents target, start: (node.document.attr 'imagesdir'), normalize: true, label: 'SVG', warn_if_empty: true)
|
1266
|
+
return if svg.empty?
|
1250
1267
|
svg = svg.sub SvgPreambleRx, '' unless svg.start_with? '<svg'
|
1251
|
-
old_start_tag = new_start_tag = nil
|
1268
|
+
old_start_tag = new_start_tag = start_tag_match = nil
|
1252
1269
|
# NOTE width, height and style attributes are removed if either width or height is specified
|
1253
1270
|
['width', 'height'].each do |dim|
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
new_start_tag =
|
1271
|
+
next unless node.attr? dim
|
1272
|
+
unless new_start_tag
|
1273
|
+
next if (start_tag_match ||= (svg.match SvgStartTagRx) || :no_match) == :no_match
|
1274
|
+
new_start_tag = (old_start_tag = start_tag_match[0]).gsub DimensionAttributeRx, ''
|
1258
1275
|
end
|
1276
|
+
# NOTE a unitless value in HTML is assumed to be px, so we can pass the value straight through
|
1277
|
+
new_start_tag = %(#{new_start_tag.chop} #{dim}="#{node.attr dim}">)
|
1259
1278
|
end
|
1260
1279
|
svg = %(#{new_start_tag}#{svg[old_start_tag.length..-1]}) if new_start_tag
|
1261
1280
|
end
|
@@ -15,9 +15,9 @@ class Converter::ManPageConverter < Converter::Base
|
|
15
15
|
ESC_BS = %(#{ESC}\\) # escaped backslash (indicates troff formatting sequence)
|
16
16
|
ESC_FS = %(#{ESC}.) # escaped full stop (indicates troff macro)
|
17
17
|
|
18
|
-
LiteralBackslashRx =
|
18
|
+
LiteralBackslashRx = /\A\\|(#{ESC})?\\/
|
19
19
|
LeadingPeriodRx = /^\./
|
20
|
-
EscapedMacroRx = /^(?:#{ESC}\\c\n)?#{ESC}\.((?:URL|MTO) "
|
20
|
+
EscapedMacroRx = /^(?:#{ESC}\\c\n)?#{ESC}\.((?:URL|MTO) "#{CC_ANY}*?" "#{CC_ANY}*?" )( |[^\s]*)(#{CC_ANY}*?)(?: *#{ESC}\\c)?$/
|
21
21
|
MockBoundaryRx = /<\/?BOUNDARY>/
|
22
22
|
EmDashCharRefRx = /—(?:​)?/
|
23
23
|
EllipsisCharRefRx = /…(?:​)?/
|
@@ -247,7 +247,9 @@ r lw(\n(.lu*75u/100u).'
|
|
247
247
|
result << %(.sp
|
248
248
|
.if n .RS 4
|
249
249
|
.nf
|
250
|
+
.fam C
|
250
251
|
#{manify node.content, whitespace: :preserve}
|
252
|
+
.fam
|
251
253
|
.fi
|
252
254
|
.if n .RE)
|
253
255
|
result.join LF
|
@@ -261,7 +263,9 @@ r lw(\n(.lu*75u/100u).'
|
|
261
263
|
result << %(.sp
|
262
264
|
.if n .RS 4
|
263
265
|
.nf
|
266
|
+
.fam C
|
264
267
|
#{manify node.content, whitespace: :preserve}
|
268
|
+
.fam
|
265
269
|
.fi
|
266
270
|
.if n .RE)
|
267
271
|
result.join LF
|
@@ -284,15 +288,16 @@ r lw(\n(.lu*75u/100u).'
|
|
284
288
|
.B #{manify node.title}
|
285
289
|
.br) if node.title?
|
286
290
|
|
291
|
+
start = (node.attr 'start', 1).to_i
|
287
292
|
node.items.each_with_index do |item, idx|
|
288
293
|
result << %(.sp
|
289
294
|
.RS 4
|
290
295
|
.ie n \\{\\
|
291
|
-
\\h'-04' #{idx +
|
296
|
+
\\h'-04' #{numeral = idx + start}.\\h'+01'\\c
|
292
297
|
.\\}
|
293
298
|
.el \\{\\
|
294
299
|
. sp -1
|
295
|
-
. IP " #{
|
300
|
+
. IP " #{numeral}." 4.2
|
296
301
|
.\\}
|
297
302
|
#{manify item.text, whitespace: :normalize})
|
298
303
|
result << item.content if item.blocks?
|
@@ -580,11 +585,7 @@ allbox tab(:);'
|
|
580
585
|
when :xref
|
581
586
|
unless (text = node.text)
|
582
587
|
refid = node.attributes['refid']
|
583
|
-
|
584
|
-
text = (ref.xreftext node.attr('xrefstyle', nil, true)) || %([#{refid}])
|
585
|
-
else
|
586
|
-
text = %([#{refid}])
|
587
|
-
end
|
588
|
+
text = %([#{refid}]) unless AbstractNode === (ref = (@refs ||= node.document.catalog[:refs])[refid]) && (@resolving_xref ||= outer = true) && outer && (text = ref.xreftext node.attr 'xrefstyle', nil, true)
|
588
589
|
end
|
589
590
|
text
|
590
591
|
when :ref, :bibref
|
@@ -699,7 +700,8 @@ allbox tab(:);'
|
|
699
700
|
str = str.tr_s WHITESPACE, ' '
|
700
701
|
end
|
701
702
|
str = str.
|
702
|
-
gsub(LiteralBackslashRx
|
703
|
+
gsub(LiteralBackslashRx) { $1 ? $& : '\\(rs' }. # literal backslash (not a troff escape sequence)
|
704
|
+
gsub(EllipsisCharRefRx, '...'). # horizontal ellipsis
|
703
705
|
gsub(LeadingPeriodRx, '\\\&.'). # leading . is used in troff for macro call or other formatting; replace with \&.
|
704
706
|
# drop orphaned \c escape lines, unescape troff macro, quote adjacent character, isolate macro line
|
705
707
|
gsub(EscapedMacroRx) { (rest = $3.lstrip).empty? ? %(.#$1"#$2") : %(.#$1"#$2"#{LF}#{rest}) }.
|
@@ -717,13 +719,12 @@ allbox tab(:);'
|
|
717
719
|
gsub('’', '\(cq'). # right single quotation mark
|
718
720
|
gsub('“', '\(lq'). # left double quotation mark
|
719
721
|
gsub('”', '\(rq'). # right double quotation mark
|
720
|
-
gsub(EllipsisCharRefRx, '...'). # horizontal ellipsis
|
721
722
|
gsub('←', '\(<-'). # leftwards arrow
|
722
723
|
gsub('→', '\(->'). # rightwards arrow
|
723
724
|
gsub('⇐', '\(lA'). # leftwards double arrow
|
724
725
|
gsub('⇒', '\(rA'). # rightwards double arrow
|
725
726
|
gsub('​', '\:'). # zero width space
|
726
|
-
gsub('&','&').
|
727
|
+
gsub('&', '&'). # literal ampersand (NOTE must take place after any other replacement that includes &)
|
727
728
|
gsub('\'', '\(aq'). # apostrophe-quote
|
728
729
|
gsub(MockBoundaryRx, ''). # mock boundary
|
729
730
|
gsub(ESC_BS, '\\'). # unescape troff backslash (NOTE update if more escapes are added)
|