asciidoctor 1.5.5 → 1.5.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of asciidoctor might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +216 -1
- data/CONTRIBUTING.adoc +2 -2
- data/Gemfile +20 -1
- data/LICENSE.adoc +1 -1
- data/README-fr.adoc +4 -3
- data/README-jp.adoc +11 -10
- data/README-zh_CN.adoc +4 -3
- data/README.adoc +17 -202
- data/Rakefile +41 -25
- data/asciidoctor.gemspec +9 -10
- data/data/locale/attributes.adoc +216 -34
- data/data/stylesheets/asciidoctor-default.css +23 -16
- data/features/step_definitions.rb +15 -19
- data/features/xref.feature +584 -20
- data/lib/asciidoctor.rb +292 -278
- data/lib/asciidoctor/abstract_block.rb +155 -94
- data/lib/asciidoctor/abstract_node.rb +108 -94
- data/lib/asciidoctor/attribute_list.rb +30 -22
- data/lib/asciidoctor/block.rb +7 -7
- data/lib/asciidoctor/cli/invoker.rb +47 -34
- data/lib/asciidoctor/cli/options.rb +22 -11
- data/lib/asciidoctor/converter.rb +3 -3
- data/lib/asciidoctor/converter/base.rb +2 -2
- data/lib/asciidoctor/converter/composite.rb +1 -1
- data/lib/asciidoctor/converter/docbook45.rb +2 -2
- data/lib/asciidoctor/converter/docbook5.rb +132 -87
- data/lib/asciidoctor/converter/factory.rb +0 -1
- data/lib/asciidoctor/converter/html5.rb +116 -98
- data/lib/asciidoctor/converter/manpage.rb +51 -52
- data/lib/asciidoctor/converter/template.rb +47 -36
- data/lib/asciidoctor/core_ext.rb +8 -2
- data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +4 -0
- data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +6 -0
- data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +5 -0
- data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +1 -1
- data/lib/asciidoctor/core_ext/1.8.7/string/{limit.rb → limit_bytesize.rb} +7 -6
- data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +6 -0
- data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +1 -1
- data/lib/asciidoctor/core_ext/nil_or_empty.rb +5 -5
- data/lib/asciidoctor/core_ext/regexp/is_match.rb +3 -0
- data/lib/asciidoctor/core_ext/string/{limit.rb → limit_bytesize.rb} +2 -2
- data/lib/asciidoctor/document.rb +216 -213
- data/lib/asciidoctor/extensions.rb +318 -185
- data/lib/asciidoctor/helpers.rb +35 -35
- data/lib/asciidoctor/inline.rb +32 -1
- data/lib/asciidoctor/list.rb +22 -6
- data/lib/asciidoctor/parser.rb +1008 -1038
- data/lib/asciidoctor/path_resolver.rb +46 -50
- data/lib/asciidoctor/reader.rb +275 -251
- data/lib/asciidoctor/section.rb +86 -58
- data/lib/asciidoctor/stylesheets.rb +6 -6
- data/lib/asciidoctor/substitutors.rb +567 -649
- data/lib/asciidoctor/table.rb +163 -108
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +18 -16
- data/man/asciidoctor.adoc +15 -13
- data/test/attributes_test.rb +138 -22
- data/test/blocks_test.rb +377 -97
- data/test/converter_test.rb +13 -0
- data/test/document_test.rb +244 -34
- data/test/extensions_test.rb +409 -42
- data/test/fixtures/asciidoc_index.txt +521 -0
- data/test/fixtures/basic-docinfo-footer.html +6 -0
- data/test/fixtures/basic-docinfo-footer.xml +8 -0
- data/test/fixtures/basic-docinfo.html +1 -0
- data/test/fixtures/basic-docinfo.xml +4 -0
- data/test/fixtures/basic.asciidoc +5 -0
- data/test/fixtures/chapter-a.adoc +3 -0
- data/test/fixtures/child-include.adoc +5 -0
- data/test/fixtures/circle.svg +9 -0
- data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +6 -0
- data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +6 -0
- data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +1 -0
- data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +3 -0
- data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +5 -0
- data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +6 -0
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +3 -0
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +5 -0
- data/test/fixtures/custom-docinfodir/basic-docinfo.html +1 -0
- data/test/fixtures/custom-docinfodir/docinfo.html +1 -0
- data/test/fixtures/docinfo-footer.html +1 -0
- data/test/fixtures/docinfo-footer.xml +9 -0
- data/test/fixtures/docinfo.html +1 -0
- data/test/fixtures/docinfo.xml +3 -0
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +13 -0
- data/test/fixtures/grandchild-include.adoc +3 -0
- data/test/fixtures/hello-asciidoctor.pdf +69 -0
- data/test/fixtures/include-file.asciidoc +24 -0
- data/test/fixtures/include-file.ml +3 -0
- data/test/fixtures/include-file.xml +5 -0
- data/test/fixtures/master.adoc +5 -0
- data/test/fixtures/mismatched-end-tag.adoc +7 -0
- data/test/fixtures/parent-include-restricted.adoc +5 -0
- data/test/fixtures/parent-include.adoc +5 -0
- data/test/fixtures/sample.asciidoc +26 -0
- data/test/fixtures/stylesheets/custom.css +3 -0
- data/test/fixtures/subs-docinfo.html +2 -0
- data/test/fixtures/subs.adoc +7 -0
- data/test/fixtures/tagged-class-enclosed.rb +26 -0
- data/test/fixtures/tagged-class.rb +23 -0
- data/test/fixtures/tip.gif +0 -0
- data/test/invoker_test.rb +82 -4
- data/test/links_test.rb +312 -37
- data/test/lists_test.rb +204 -25
- data/test/manpage_test.rb +191 -4
- data/test/options_test.rb +18 -1
- data/test/paragraphs_test.rb +32 -7
- data/test/parser_test.rb +150 -30
- data/test/paths_test.rb +47 -13
- data/test/preamble_test.rb +1 -1
- data/test/reader_test.rb +366 -126
- data/test/sections_test.rb +203 -56
- data/test/substitutions_test.rb +339 -131
- data/test/tables_test.rb +315 -15
- data/test/test_helper.rb +400 -0
- data/test/text_test.rb +5 -5
- metadata +110 -22
@@ -4,20 +4,20 @@ module Asciidoctor
|
|
4
4
|
# consistent with the html5 backend from AsciiDoc Python.
|
5
5
|
class Converter::Html5Converter < Converter::BuiltIn
|
6
6
|
(QUOTE_TAGS = {
|
7
|
+
:monospaced => ['<code>', '</code>', true],
|
7
8
|
:emphasis => ['<em>', '</em>', true],
|
8
9
|
:strong => ['<strong>', '</strong>', true],
|
9
|
-
:monospaced => ['<code>', '</code>', true],
|
10
|
-
:superscript => ['<sup>', '</sup>', true],
|
11
|
-
:subscript => ['<sub>', '</sub>', true],
|
12
10
|
:double => ['“', '”', false],
|
13
11
|
:single => ['‘', '’', false],
|
14
12
|
:mark => ['<mark>', '</mark>', true],
|
15
|
-
:
|
16
|
-
:
|
13
|
+
:superscript => ['<sup>', '</sup>', true],
|
14
|
+
:subscript => ['<sub>', '</sub>', true],
|
15
|
+
:asciimath => ['\$', '\$', false],
|
16
|
+
:latexmath => ['\(', '\)', false]
|
17
17
|
# Opal can't resolve these constants when referenced here
|
18
18
|
#:asciimath => INLINE_MATH_DELIMITERS[:asciimath] + [false],
|
19
19
|
#:latexmath => INLINE_MATH_DELIMITERS[:latexmath] + [false]
|
20
|
-
}).default = [
|
20
|
+
}).default = ['', '', false]
|
21
21
|
|
22
22
|
SvgPreambleRx = /\A.*?(?=<svg\b)/m
|
23
23
|
SvgStartTagRx = /\A<svg[^>]*>/
|
@@ -30,7 +30,6 @@ module Asciidoctor
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def document node
|
33
|
-
result = []
|
34
33
|
slash = @void_element_slash
|
35
34
|
br = %(<br#{slash}>)
|
36
35
|
unless (asset_uri_scheme = (node.attr 'asset-uri-scheme', 'https')).empty?
|
@@ -38,7 +37,7 @@ module Asciidoctor
|
|
38
37
|
end
|
39
38
|
cdn_base = %(#{asset_uri_scheme}//cdnjs.cloudflare.com/ajax/libs)
|
40
39
|
linkcss = node.safe >= SafeMode::SECURE || (node.attr? 'linkcss')
|
41
|
-
result
|
40
|
+
result = ['<!DOCTYPE html>']
|
42
41
|
lang_attribute = (node.attr? 'nolang') ? nil : %( lang="#{node.attr 'lang', 'en'}")
|
43
42
|
result << %(<html#{@xml_mode ? ' xmlns="http://www.w3.org/1999/xhtml"' : nil}#{lang_attribute}>)
|
44
43
|
result << %(<head>
|
@@ -49,8 +48,16 @@ module Asciidoctor
|
|
49
48
|
result << %(<meta name="application-name" content="#{node.attr 'app-name'}"#{slash}>) if node.attr? 'app-name'
|
50
49
|
result << %(<meta name="description" content="#{node.attr 'description'}"#{slash}>) if node.attr? 'description'
|
51
50
|
result << %(<meta name="keywords" content="#{node.attr 'keywords'}"#{slash}>) if node.attr? 'keywords'
|
52
|
-
result << %(<meta name="author" content="#{node.attr 'authors'}"#{slash}>) if node.attr? 'authors'
|
51
|
+
result << %(<meta name="author" content="#{((authors = node.attr 'authors').include? '<') ? (authors.gsub XmlSanitizeRx, '') : authors}"#{slash}>) if node.attr? 'authors'
|
53
52
|
result << %(<meta name="copyright" content="#{node.attr 'copyright'}"#{slash}>) if node.attr? 'copyright'
|
53
|
+
if node.attr? 'favicon'
|
54
|
+
if (icon_href = node.attr 'favicon').empty?
|
55
|
+
icon_href, icon_type = 'favicon.ico', 'image/x-icon'
|
56
|
+
else
|
57
|
+
icon_type = (icon_ext = ::File.extname icon_href) == '.ico' ? 'image/x-icon' : %(image/#{icon_ext[1..-1]})
|
58
|
+
end
|
59
|
+
result << %(<link rel="shortcut icon" type="#{icon_type}" href="#{icon_href}">)
|
60
|
+
end
|
54
61
|
result << %(<title>#{node.doctitle :sanitize => true, :use_fallback => true}</title>)
|
55
62
|
|
56
63
|
if DEFAULT_STYLESHEET_KEYS.include?(node.attr 'stylesheet')
|
@@ -67,7 +74,7 @@ module Asciidoctor
|
|
67
74
|
result << %(<link rel="stylesheet" href="#{node.normalize_web_path((node.attr 'stylesheet'), (node.attr 'stylesdir', ''))}"#{slash}>)
|
68
75
|
else
|
69
76
|
result << %(<style>
|
70
|
-
#{node.read_asset node.normalize_system_path((node.attr 'stylesheet'), (node.attr 'stylesdir', '')), :warn_on_failure => true}
|
77
|
+
#{node.read_asset node.normalize_system_path((node.attr 'stylesheet'), (node.attr 'stylesdir', '')), :warn_on_failure => true, :label => 'stylesheet'}
|
71
78
|
</style>)
|
72
79
|
end
|
73
80
|
end
|
@@ -207,7 +214,7 @@ module Asciidoctor
|
|
207
214
|
# See http://www.html5rocks.com/en/tutorials/speed/script-loading/
|
208
215
|
case highlighter
|
209
216
|
when 'highlightjs', 'highlight.js'
|
210
|
-
highlightjs_path = node.attr 'highlightjsdir', %(#{cdn_base}/highlight.js/
|
217
|
+
highlightjs_path = node.attr 'highlightjsdir', %(#{cdn_base}/highlight.js/9.12.0)
|
211
218
|
result << %(<link rel="stylesheet" href="#{highlightjs_path}/styles/#{node.attr 'highlightjs-theme', 'github'}.min.css"#{slash}>)
|
212
219
|
result << %(<script src="#{highlightjs_path}/highlight.min.js"></script>
|
213
220
|
<script>hljs.initHighlighting()</script>)
|
@@ -243,7 +250,7 @@ MathJax.Hub.Config({
|
|
243
250
|
|
244
251
|
result << '</body>'
|
245
252
|
result << '</html>'
|
246
|
-
result *
|
253
|
+
result * LF
|
247
254
|
end
|
248
255
|
|
249
256
|
def embedded node
|
@@ -286,38 +293,39 @@ MathJax.Hub.Config({
|
|
286
293
|
result << '</div>'
|
287
294
|
end
|
288
295
|
|
289
|
-
result *
|
296
|
+
result * LF
|
290
297
|
end
|
291
298
|
|
292
299
|
def outline node, opts = {}
|
293
300
|
return unless node.sections?
|
294
301
|
sectnumlevels = opts[:sectnumlevels] || (node.document.attr 'sectnumlevels', 3).to_i
|
295
302
|
toclevels = opts[:toclevels] || (node.document.attr 'toclevels', 2).to_i
|
296
|
-
result = []
|
297
303
|
sections = node.sections
|
298
|
-
# FIXME
|
299
|
-
|
300
|
-
slevel = (first_section = sections[0]).level
|
301
|
-
slevel = 1 if slevel == 0 && first_section.special
|
302
|
-
result << %(<ul class="sectlevel#{slevel}">)
|
304
|
+
# FIXME top level is incorrect if a multipart book starts with a special section defined at level 0
|
305
|
+
result = [%(<ul class="sectlevel#{sections[0].level}">)]
|
303
306
|
sections.each do |section|
|
304
|
-
|
305
|
-
if section.
|
306
|
-
|
307
|
+
slevel = section.level
|
308
|
+
if section.caption
|
309
|
+
stitle = section.captioned_title
|
310
|
+
elsif section.numbered && slevel <= sectnumlevels
|
311
|
+
stitle = %(#{section.sectnum} #{section.title})
|
312
|
+
else
|
313
|
+
stitle = section.title
|
314
|
+
end
|
315
|
+
if slevel < toclevels && (child_toc_level = outline section, :toclevels => toclevels, :secnumlevels => sectnumlevels)
|
316
|
+
result << %(<li><a href="##{section.id}">#{stitle}</a>)
|
307
317
|
result << child_toc_level
|
308
318
|
result << '</li>'
|
309
319
|
else
|
310
|
-
result << %(<li><a href="##{section.id}">#{
|
320
|
+
result << %(<li><a href="##{section.id}">#{stitle}</a></li>)
|
311
321
|
end
|
312
322
|
end
|
313
323
|
result << '</ul>'
|
314
|
-
result *
|
324
|
+
result * LF
|
315
325
|
end
|
316
326
|
|
317
327
|
def section node
|
318
328
|
slevel = node.level
|
319
|
-
# QUESTION should the check for slevel be done in section?
|
320
|
-
slevel = 1 if slevel == 0 && node.special
|
321
329
|
htag = %(h#{slevel + 1})
|
322
330
|
id_attr = anchor = link_start = link_end = nil
|
323
331
|
if node.id
|
@@ -356,20 +364,20 @@ MathJax.Hub.Config({
|
|
356
364
|
id_attr = node.id ? %( id="#{node.id}") : nil
|
357
365
|
name = node.attr 'name'
|
358
366
|
title_element = node.title? ? %(<div class="title">#{node.title}</div>\n) : nil
|
359
|
-
|
367
|
+
if node.document.attr? 'icons'
|
360
368
|
if (node.document.attr? 'icons', 'font') && !(node.attr? 'icon')
|
361
|
-
%(<i class="fa icon-#{name}" title="#{node.
|
369
|
+
label = %(<i class="fa icon-#{name}" title="#{node.attr 'textlabel'}"></i>)
|
362
370
|
else
|
363
|
-
%(<img src="#{node.icon_uri name}" alt="#{node.
|
371
|
+
label = %(<img src="#{node.icon_uri name}" alt="#{node.attr 'textlabel'}"#{@void_element_slash}>)
|
364
372
|
end
|
365
373
|
else
|
366
|
-
%(<div class="title">#{node.
|
374
|
+
label = %(<div class="title">#{node.attr 'textlabel'}</div>)
|
367
375
|
end
|
368
376
|
%(<div#{id_attr} class="admonitionblock #{name}#{(role = node.role) && " #{role}"}">
|
369
377
|
<table>
|
370
378
|
<tr>
|
371
379
|
<td class="icon">
|
372
|
-
#{
|
380
|
+
#{label}
|
373
381
|
</td>
|
374
382
|
<td class="content">
|
375
383
|
#{title_element}#{node.content}
|
@@ -384,10 +392,13 @@ MathJax.Hub.Config({
|
|
384
392
|
id_attribute = node.id ? %( id="#{node.id}") : nil
|
385
393
|
classes = ['audioblock', node.role].compact
|
386
394
|
class_attribute = %( class="#{classes * ' '}")
|
387
|
-
title_element = node.title? ? %(<div class="title">#{node.
|
395
|
+
title_element = node.title? ? %(<div class="title">#{node.title}</div>\n) : nil
|
396
|
+
start_t = node.attr 'start', nil, false
|
397
|
+
end_t = node.attr 'end', nil, false
|
398
|
+
time_anchor = (start_t || end_t) ? %(#t=#{start_t}#{end_t ? ',' : nil}#{end_t}) : nil
|
388
399
|
%(<div#{id_attribute}#{class_attribute}>
|
389
400
|
#{title_element}<div class="content">
|
390
|
-
<audio src="#{node.media_uri(node.attr 'target')}"#{(node.option? 'autoplay') ? (append_boolean_attribute 'autoplay', xml) : nil}#{(node.option? 'nocontrols') ? nil : (append_boolean_attribute 'controls', xml)}#{(node.option? 'loop') ? (append_boolean_attribute 'loop', xml) : nil}>
|
401
|
+
<audio src="#{node.media_uri(node.attr 'target')}#{time_anchor}"#{(node.option? 'autoplay') ? (append_boolean_attribute 'autoplay', xml) : nil}#{(node.option? 'nocontrols') ? nil : (append_boolean_attribute 'controls', xml)}#{(node.option? 'loop') ? (append_boolean_attribute 'loop', xml) : nil}>
|
391
402
|
Your browser does not support the audio tag.
|
392
403
|
</audio>
|
393
404
|
</div>
|
@@ -405,34 +416,32 @@ Your browser does not support the audio tag.
|
|
405
416
|
|
406
417
|
if node.document.attr? 'icons'
|
407
418
|
result << '<table>'
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
%(<i class="conum" data-value="#{num}"></i><b>#{num}</b>)
|
419
|
+
font_icons, num = (node.document.attr? 'icons', 'font'), 0
|
420
|
+
node.items.each do |item|
|
421
|
+
num += 1
|
422
|
+
if font_icons
|
423
|
+
num_label = %(<i class="conum" data-value="#{num}"></i><b>#{num}</b>)
|
414
424
|
else
|
415
|
-
%(<img src="#{node.icon_uri "callouts/#{num}"}" alt="#{num}"#{@void_element_slash}>)
|
425
|
+
num_label = %(<img src="#{node.icon_uri "callouts/#{num}"}" alt="#{num}"#{@void_element_slash}>)
|
416
426
|
end
|
417
427
|
result << %(<tr>
|
418
|
-
<td>#{
|
419
|
-
<td>#{item.text}</td>
|
428
|
+
<td>#{num_label}</td>
|
429
|
+
<td>#{item.text}#{item.blocks? ? LF + item.content : ''}</td>
|
420
430
|
</tr>)
|
421
431
|
end
|
422
|
-
|
423
432
|
result << '</table>'
|
424
433
|
else
|
425
434
|
result << '<ol>'
|
426
435
|
node.items.each do |item|
|
427
436
|
result << %(<li>
|
428
|
-
<p>#{item.text}</p
|
437
|
+
<p>#{item.text}</p>#{item.blocks? ? LF + item.content : ''}
|
429
438
|
</li>)
|
430
439
|
end
|
431
440
|
result << '</ol>'
|
432
441
|
end
|
433
442
|
|
434
443
|
result << '</div>'
|
435
|
-
result *
|
444
|
+
result * LF
|
436
445
|
end
|
437
446
|
|
438
447
|
def dlist node
|
@@ -515,14 +524,14 @@ Your browser does not support the audio tag.
|
|
515
524
|
end
|
516
525
|
|
517
526
|
result << '</div>'
|
518
|
-
result *
|
527
|
+
result * LF
|
519
528
|
end
|
520
529
|
|
521
530
|
def example node
|
522
531
|
id_attribute = node.id ? %( id="#{node.id}") : nil
|
523
532
|
title_element = node.title? ? %(<div class="title">#{node.captioned_title}</div>\n) : nil
|
524
533
|
|
525
|
-
%(<div#{id_attribute} class="#{(role = node.role)
|
534
|
+
%(<div#{id_attribute} class="exampleblock#{(role = node.role) && " #{role}"}">
|
526
535
|
#{title_element}<div class="content">
|
527
536
|
#{node.content}
|
528
537
|
</div>
|
@@ -543,15 +552,16 @@ Your browser does not support the audio tag.
|
|
543
552
|
if ((node.attr? 'format', 'svg', false) || (target.include? '.svg')) && node.document.safe < SafeMode::SECURE &&
|
544
553
|
((svg = (node.option? 'inline')) || (obj = (node.option? 'interactive')))
|
545
554
|
if svg
|
546
|
-
img = (read_svg_contents node, target) || %(<span class="alt">#{node.
|
555
|
+
img = (read_svg_contents node, target) || %(<span class="alt">#{node.alt}</span>)
|
547
556
|
elsif obj
|
548
|
-
fallback = (node.attr? 'fallback') ? %(<img src="#{node.image_uri(node.attr 'fallback')}" alt="#{node.
|
557
|
+
fallback = (node.attr? 'fallback') ? %(<img src="#{node.image_uri(node.attr 'fallback')}" alt="#{encode_quotes node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>) : %(<span class="alt">#{node.alt}</span>)
|
549
558
|
img = %(<object type="image/svg+xml" data="#{node.image_uri target}"#{width_attr}#{height_attr}>#{fallback}</object>)
|
550
559
|
end
|
551
560
|
end
|
552
|
-
img ||= %(<img src="#{node.image_uri target}" alt="#{node.
|
553
|
-
if
|
554
|
-
|
561
|
+
img ||= %(<img src="#{node.image_uri target}" alt="#{encode_quotes node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>)
|
562
|
+
if node.attr? 'link'
|
563
|
+
window_attr = %( target="#{window = node.attr 'window'}"#{window == '_blank' || (node.option? 'noopener') ? ' rel="noopener"' : ''}) if node.attr? 'window'
|
564
|
+
img = %(<a class="image" href="#{node.attr 'link'}"#{window_attr}>#{img}</a>)
|
555
565
|
end
|
556
566
|
id_attr = node.id ? %( id="#{node.id}") : nil
|
557
567
|
classes = ['imageblock', node.role].compact
|
@@ -583,9 +593,9 @@ Your browser does not support the audio tag.
|
|
583
593
|
pre_class = %( class="pygments highlight#{nowrap ? ' nowrap' : nil}")
|
584
594
|
when 'highlightjs', 'highlight.js'
|
585
595
|
pre_class = %( class="highlightjs highlight#{nowrap ? ' nowrap' : nil}")
|
586
|
-
code_attrs = %( class="language-#{language}"#{code_attrs}) if language
|
596
|
+
code_attrs = %( class="language-#{language} hljs"#{code_attrs}) if language
|
587
597
|
when 'prettify'
|
588
|
-
pre_class = %( class="prettyprint highlight#{nowrap ? ' nowrap' : nil}#{(node.attr? 'linenums') ? ' linenums' : nil}")
|
598
|
+
pre_class = %( class="prettyprint highlight#{nowrap ? ' nowrap' : nil}#{(node.attr? 'linenums', nil, false) ? ' linenums' : nil}")
|
589
599
|
code_attrs = %( class="language-#{language}"#{code_attrs}) if language
|
590
600
|
when 'html-pipeline'
|
591
601
|
pre_class = language ? %( lang="#{language}") : nil
|
@@ -630,7 +640,7 @@ Your browser does not support the audio tag.
|
|
630
640
|
equation = %(#{open}#{equation}#{close})
|
631
641
|
end
|
632
642
|
|
633
|
-
%(<div#{id_attribute} class="#{(role = node.role)
|
643
|
+
%(<div#{id_attribute} class="stemblock#{(role = node.role) && " #{role}"}">
|
634
644
|
#{title_element}<div class="content">
|
635
645
|
#{equation}
|
636
646
|
</div>
|
@@ -660,7 +670,7 @@ Your browser does not support the audio tag.
|
|
660
670
|
|
661
671
|
result << '</ol>'
|
662
672
|
result << '</div>'
|
663
|
-
result *
|
673
|
+
result * LF
|
664
674
|
end
|
665
675
|
|
666
676
|
def open node
|
@@ -758,7 +768,7 @@ Your browser does not support the audio tag.
|
|
758
768
|
def sidebar node
|
759
769
|
id_attribute = node.id ? %( id="#{node.id}") : nil
|
760
770
|
title_element = node.title? ? %(<div class="title">#{node.title}</div>\n) : nil
|
761
|
-
%(<div#{id_attribute} class="#{(role = node.role)
|
771
|
+
%(<div#{id_attribute} class="sidebarblock#{(role = node.role) && " #{role}"}">
|
762
772
|
<div class="content">
|
763
773
|
#{title_element}#{node.content}
|
764
774
|
</div>
|
@@ -800,9 +810,10 @@ Your browser does not support the audio tag.
|
|
800
810
|
end
|
801
811
|
end
|
802
812
|
result << '</colgroup>'
|
803
|
-
|
813
|
+
node.rows.by_section.each do |tsec, rows|
|
814
|
+
next if rows.empty?
|
804
815
|
result << %(<t#{tsec}>)
|
805
|
-
|
816
|
+
rows.each do |row|
|
806
817
|
result << '<tr>'
|
807
818
|
row.each do |cell|
|
808
819
|
if tsec == :head
|
@@ -816,10 +827,8 @@ Your browser does not support the audio tag.
|
|
816
827
|
when :literal
|
817
828
|
cell_content = %(<div class="literal"><pre>#{cell.text}</pre></div>)
|
818
829
|
else
|
819
|
-
cell_content = ''
|
820
|
-
|
821
|
-
cell_content = %(#{cell_content}<p class="tableblock">#{text}</p>)
|
822
|
-
end
|
830
|
+
cell_content = (cell_content = cell.content).empty? ? '' : %(<p class="tableblock">#{cell_content * '</p>
|
831
|
+
<p class="tableblock">'}</p>)
|
823
832
|
end
|
824
833
|
end
|
825
834
|
|
@@ -836,7 +845,7 @@ Your browser does not support the audio tag.
|
|
836
845
|
end
|
837
846
|
end
|
838
847
|
result << '</table>'
|
839
|
-
result *
|
848
|
+
result * LF
|
840
849
|
end
|
841
850
|
|
842
851
|
def toc node
|
@@ -868,7 +877,7 @@ Your browser does not support the audio tag.
|
|
868
877
|
marker_checked = nil
|
869
878
|
marker_unchecked = nil
|
870
879
|
if (checklist = node.option? 'checklist')
|
871
|
-
div_classes.
|
880
|
+
div_classes.unshift div_classes.shift, 'checklist'
|
872
881
|
ul_class_attribute = ' class="checklist"'
|
873
882
|
if node.option? 'interactive'
|
874
883
|
if @xml_mode
|
@@ -907,7 +916,7 @@ Your browser does not support the audio tag.
|
|
907
916
|
|
908
917
|
result << '</ul>'
|
909
918
|
result << '</div>'
|
910
|
-
result *
|
919
|
+
result * LF
|
911
920
|
end
|
912
921
|
|
913
922
|
def verse node
|
@@ -935,7 +944,7 @@ Your browser does not support the audio tag.
|
|
935
944
|
id_attribute = node.id ? %( id="#{node.id}") : nil
|
936
945
|
classes = ['videoblock', node.role].compact
|
937
946
|
class_attribute = %( class="#{classes * ' '}")
|
938
|
-
title_element = node.title? ? %(\n<div class="title">#{node.
|
947
|
+
title_element = node.title? ? %(\n<div class="title">#{node.title}</div>) : nil
|
939
948
|
width_attribute = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : nil
|
940
949
|
height_attribute = (node.attr? 'height') ? %( height="#{node.attr 'height'}") : nil
|
941
950
|
case node.attr 'poster'
|
@@ -998,13 +1007,14 @@ Your browser does not support the audio tag.
|
|
998
1007
|
</div>
|
999
1008
|
</div>)
|
1000
1009
|
else
|
1001
|
-
poster_attribute =
|
1010
|
+
poster_attribute = (val = node.attr 'poster', nil, false).nil_or_empty? ? nil : %( poster="#{node.media_uri val}")
|
1011
|
+
preload_attribute = (val = node.attr 'preload', nil, false).nil_or_empty? ? nil : %( preload="#{val}")
|
1002
1012
|
start_t = node.attr 'start', nil, false
|
1003
1013
|
end_t = node.attr 'end', nil, false
|
1004
1014
|
time_anchor = (start_t || end_t) ? %(#t=#{start_t}#{end_t ? ',' : nil}#{end_t}) : nil
|
1005
1015
|
%(<div#{id_attribute}#{class_attribute}>#{title_element}
|
1006
1016
|
<div class="content">
|
1007
|
-
<video src="#{node.media_uri(node.attr 'target')}#{time_anchor}"#{width_attribute}#{height_attribute}#{poster_attribute}#{(node.option? 'autoplay') ? (append_boolean_attribute 'autoplay', xml) : nil}#{(node.option? 'nocontrols') ? nil : (append_boolean_attribute 'controls', xml)}#{(node.option? 'loop') ? (append_boolean_attribute 'loop', xml) : nil}>
|
1017
|
+
<video src="#{node.media_uri(node.attr 'target')}#{time_anchor}"#{width_attribute}#{height_attribute}#{poster_attribute}#{(node.option? 'autoplay') ? (append_boolean_attribute 'autoplay', xml) : nil}#{(node.option? 'nocontrols') ? nil : (append_boolean_attribute 'controls', xml)}#{(node.option? 'loop') ? (append_boolean_attribute 'loop', xml) : nil}#{preload_attribute}>
|
1008
1018
|
Your browser does not support the video tag.
|
1009
1019
|
</video>
|
1010
1020
|
</div>
|
@@ -1013,27 +1023,29 @@ Your browser does not support the video tag.
|
|
1013
1023
|
end
|
1014
1024
|
|
1015
1025
|
def inline_anchor node
|
1016
|
-
target = node.target
|
1017
1026
|
case node.type
|
1018
1027
|
when :xref
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1028
|
+
unless (text = node.text)
|
1029
|
+
if AbstractNode === (ref = node.document.catalog[:refs][refid = node.attributes['refid']])
|
1030
|
+
text = ref.xreftext((@xrefstyle ||= node.document.attributes['xrefstyle'])) || %([#{refid}])
|
1031
|
+
else
|
1032
|
+
text = %([#{refid}])
|
1033
|
+
end
|
1034
|
+
end
|
1035
|
+
%(<a href="#{node.target}">#{text}</a>)
|
1024
1036
|
when :ref
|
1025
|
-
%(<a id="#{
|
1037
|
+
%(<a id="#{node.id}"></a>)
|
1026
1038
|
when :link
|
1027
|
-
attrs = []
|
1028
|
-
attrs << %( id="#{node.id}") if node.id
|
1039
|
+
attrs = node.id ? [%( id="#{node.id}")] : []
|
1029
1040
|
if (role = node.role)
|
1030
1041
|
attrs << %( class="#{role}")
|
1031
1042
|
end
|
1032
1043
|
attrs << %( title="#{node.attr 'title'}") if node.attr? 'title', nil, false
|
1033
|
-
attrs << %( target="#{node.attr 'window'}") if node.attr? 'window', nil, false
|
1034
|
-
%(<a href="#{target}"#{attrs.join}>#{node.text}</a>)
|
1044
|
+
attrs << %( target="#{window = node.attr 'window'}"#{window == '_blank' || (node.option? 'noopener') ? ' rel="noopener"' : ''}) if node.attr? 'window', nil, false
|
1045
|
+
%(<a href="#{node.target}"#{attrs.join}>#{node.text}</a>)
|
1035
1046
|
when :bibref
|
1036
|
-
|
1047
|
+
# NOTE technically node.text should be node.reftext, but subs have already been applied to text
|
1048
|
+
%(<a id="#{node.id}"></a>#{node.text})
|
1037
1049
|
else
|
1038
1050
|
warn %(asciidoctor: WARNING: unknown anchor type: #{node.type.inspect})
|
1039
1051
|
end
|
@@ -1059,7 +1071,7 @@ Your browser does not support the video tag.
|
|
1059
1071
|
end
|
1060
1072
|
|
1061
1073
|
def inline_footnote node
|
1062
|
-
if (index = node.attr 'index')
|
1074
|
+
if (index = node.attr 'index', nil, false)
|
1063
1075
|
if node.type == :xref
|
1064
1076
|
%(<sup class="footnoteref">[<a class="footnote" href="#_footnote_#{index}" title="View footnote.">#{index}</a>]</sup>)
|
1065
1077
|
else
|
@@ -1080,23 +1092,23 @@ Your browser does not support the video tag.
|
|
1080
1092
|
title_attr = (node.attr? 'title') ? %( title="#{node.attr 'title'}") : nil
|
1081
1093
|
img = %(<i class="#{class_attr_val}"#{title_attr}></i>)
|
1082
1094
|
elsif type == 'icon' && !(node.document.attr? 'icons')
|
1083
|
-
img = %([#{node.
|
1095
|
+
img = %([#{node.alt}])
|
1084
1096
|
else
|
1085
1097
|
target = node.target
|
1086
1098
|
attrs = ['width', 'height', 'title'].map {|name| (node.attr? name) ? %( #{name}="#{node.attr name}") : nil }.join
|
1087
1099
|
if type != 'icon' && ((node.attr? 'format', 'svg', false) || (target.include? '.svg')) &&
|
1088
1100
|
node.document.safe < SafeMode::SECURE && ((svg = (node.option? 'inline')) || (obj = (node.option? 'interactive')))
|
1089
1101
|
if svg
|
1090
|
-
img = (read_svg_contents node, target) || %(<span class="alt">#{node.
|
1102
|
+
img = (read_svg_contents node, target) || %(<span class="alt">#{node.alt}</span>)
|
1091
1103
|
elsif obj
|
1092
|
-
fallback = (node.attr? 'fallback') ? %(<img src="#{node.image_uri(node.attr 'fallback')}" alt="#{node.
|
1104
|
+
fallback = (node.attr? 'fallback') ? %(<img src="#{node.image_uri(node.attr 'fallback')}" alt="#{encode_quotes node.alt}"#{attrs}#{@void_element_slash}>) : %(<span class="alt">#{node.alt}</span>)
|
1093
1105
|
img = %(<object type="image/svg+xml" data="#{node.image_uri target}"#{attrs}>#{fallback}</object>)
|
1094
1106
|
end
|
1095
1107
|
end
|
1096
|
-
img ||= %(<img src="#{type == 'icon' ? (node.icon_uri target) : (node.image_uri target)}" alt="#{node.
|
1108
|
+
img ||= %(<img src="#{type == 'icon' ? (node.icon_uri target) : (node.image_uri target)}" alt="#{encode_quotes node.alt}"#{attrs}#{@void_element_slash}>)
|
1097
1109
|
end
|
1098
1110
|
if node.attr? 'link'
|
1099
|
-
window_attr = (node.attr
|
1111
|
+
window_attr = %( target="#{window = node.attr 'window'}"#{window == '_blank' || (node.option? 'noopener') ? ' rel="noopener"' : ''}) if node.attr? 'window'
|
1100
1112
|
img = %(<a class="image" href="#{node.attr 'link'}"#{window_attr}>#{img}</a>)
|
1101
1113
|
end
|
1102
1114
|
class_attr_val = (role = node.role) ? %(#{type} #{role}) : type
|
@@ -1112,30 +1124,32 @@ Your browser does not support the video tag.
|
|
1112
1124
|
if (keys = node.attr 'keys').size == 1
|
1113
1125
|
%(<kbd>#{keys[0]}</kbd>)
|
1114
1126
|
else
|
1115
|
-
|
1116
|
-
%(<span class="keyseq">#{key_combo}</span>)
|
1127
|
+
%(<span class="keyseq"><kbd>#{keys * '</kbd>+<kbd>'}</kbd></span>)
|
1117
1128
|
end
|
1118
1129
|
end
|
1119
1130
|
|
1120
1131
|
def inline_menu node
|
1132
|
+
caret = (node.document.attr? 'icons', 'font') ? ' <i class="fa fa-angle-right caret"></i> ' : ' <b class="caret">›</b> '
|
1133
|
+
submenu_joiner = %(</b>#{caret}<b class="submenu">)
|
1121
1134
|
menu = node.attr 'menu'
|
1122
|
-
if
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1135
|
+
if (submenus = node.attr 'submenus').empty?
|
1136
|
+
if (menuitem = node.attr 'menuitem', nil, false)
|
1137
|
+
%(<span class="menuseq"><b class="menu">#{menu}</b>#{caret}<b class="menuitem">#{menuitem}</b></span>)
|
1138
|
+
else
|
1139
|
+
%(<b class="menuref">#{menu}</b>)
|
1140
|
+
end
|
1127
1141
|
else
|
1128
|
-
%(<span class="menu">#{menu}</span>)
|
1142
|
+
%(<span class="menuseq"><b class="menu">#{menu}</b>#{caret}<b class="submenu">#{submenus * submenu_joiner}</b>#{caret}<b class="menuitem">#{node.attr 'menuitem'}</b></span>)
|
1129
1143
|
end
|
1130
1144
|
end
|
1131
1145
|
|
1132
1146
|
def inline_quoted node
|
1133
1147
|
open, close, is_tag = QUOTE_TAGS[node.type]
|
1134
|
-
if
|
1148
|
+
if node.role
|
1135
1149
|
if is_tag
|
1136
|
-
quoted_text = %(#{open.chop} class="#{role}">#{node.text}#{close})
|
1150
|
+
quoted_text = %(#{open.chop} class="#{node.role}">#{node.text}#{close})
|
1137
1151
|
else
|
1138
|
-
quoted_text = %(<span class="#{role}">#{open}#{node.text}#{close}</span>)
|
1152
|
+
quoted_text = %(<span class="#{node.role}">#{open}#{node.text}#{close}</span>)
|
1139
1153
|
end
|
1140
1154
|
else
|
1141
1155
|
quoted_text = %(#{open}#{node.text}#{close})
|
@@ -1148,6 +1162,10 @@ Your browser does not support the video tag.
|
|
1148
1162
|
xml ? %( #{name}="#{name}") : %( #{name})
|
1149
1163
|
end
|
1150
1164
|
|
1165
|
+
def encode_quotes val
|
1166
|
+
(val.include? '"') ? (val.gsub '"', '"') : val
|
1167
|
+
end
|
1168
|
+
|
1151
1169
|
def read_svg_contents node, target
|
1152
1170
|
if (svg = node.read_contents target, :start => (node.document.attr 'imagesdir'), :normalize => true, :label => 'SVG')
|
1153
1171
|
svg = svg.sub SvgPreambleRx, '' unless svg.start_with? '<svg'
|