asciidoctor 2.0.6 → 2.0.11
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 +159 -6
- data/LICENSE +2 -1
- data/README-de.adoc +5 -5
- data/README-fr.adoc +4 -4
- data/README-jp.adoc +248 -183
- data/README-zh_CN.adoc +6 -6
- data/README.adoc +17 -11
- data/asciidoctor.gemspec +8 -8
- 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 +29 -26
- data/lib/asciidoctor.rb +94 -1098
- 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 +8 -8
- data/lib/asciidoctor/convert.rb +198 -0
- data/lib/asciidoctor/converter.rb +14 -13
- data/lib/asciidoctor/converter/docbook5.rb +9 -25
- data/lib/asciidoctor/converter/html5.rb +65 -42
- data/lib/asciidoctor/converter/manpage.rb +13 -12
- data/lib/asciidoctor/converter/template.rb +6 -3
- data/lib/asciidoctor/document.rb +40 -48
- 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 +117 -0
- data/lib/asciidoctor/parser.rb +29 -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 +62 -40
- 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 +18 -11
- data/lib/asciidoctor/table.rb +49 -20
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +17 -17
- data/man/asciidoctor.adoc +15 -14
- metadata +12 -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
|
@@ -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,15 +1262,22 @@ 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
1271
|
if node.attr? dim
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
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, ''
|
1275
|
+
end
|
1276
|
+
unless (dim_val = node.attr dim).end_with? '%'
|
1277
|
+
# QUESTION should we add px since it's already the default?
|
1278
|
+
dim_val += 'px'
|
1279
|
+
end
|
1280
|
+
new_start_tag = %(#{new_start_tag.chop} #{dim}="#{dim_val}">)
|
1258
1281
|
end
|
1259
1282
|
end
|
1260
1283
|
svg = %(#{new_start_tag}#{svg[old_start_tag.length..-1]}) if new_start_tag
|
@@ -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)
|