asciidoctor 1.5.8 → 2.0.0.rc.1
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 +162 -17
- data/LICENSE +1 -1
- data/README-de.adoc +12 -13
- data/README-fr.adoc +11 -12
- data/README-jp.adoc +11 -12
- data/README-zh_CN.adoc +12 -13
- data/README.adoc +6 -7
- data/asciidoctor.gemspec +19 -24
- data/bin/asciidoctor +5 -4
- data/data/reference/syntax.adoc +283 -0
- data/data/stylesheets/asciidoctor-default.css +56 -52
- data/data/stylesheets/coderay-asciidoctor.css +7 -9
- data/lib/asciidoctor.rb +171 -232
- data/lib/asciidoctor/abstract_block.rb +96 -105
- data/lib/asciidoctor/abstract_node.rb +118 -139
- data/lib/asciidoctor/attribute_list.rb +10 -14
- data/lib/asciidoctor/block.rb +20 -19
- data/lib/asciidoctor/callouts.rb +4 -2
- data/lib/asciidoctor/cli.rb +3 -2
- data/lib/asciidoctor/cli/invoker.rb +14 -21
- data/lib/asciidoctor/cli/options.rb +64 -54
- data/lib/asciidoctor/converter.rb +357 -185
- data/lib/asciidoctor/converter/composite.rb +40 -48
- data/lib/asciidoctor/converter/docbook5.rb +604 -640
- data/lib/asciidoctor/converter/html5.rb +949 -963
- data/lib/asciidoctor/converter/manpage.rb +569 -548
- data/lib/asciidoctor/converter/template.rb +231 -272
- data/lib/asciidoctor/core_ext.rb +5 -18
- data/lib/asciidoctor/core_ext/float/truncate.rb +19 -0
- data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
- data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
- data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
- data/lib/asciidoctor/document.rb +399 -377
- data/lib/asciidoctor/extensions.rb +72 -140
- data/lib/asciidoctor/helpers.rb +122 -83
- data/lib/asciidoctor/inline.rb +5 -1
- data/lib/asciidoctor/list.rb +13 -11
- data/lib/asciidoctor/logging.rb +17 -16
- data/lib/asciidoctor/parser.rb +390 -423
- data/lib/asciidoctor/path_resolver.rb +10 -5
- data/lib/asciidoctor/reader.rb +286 -263
- data/lib/asciidoctor/rouge_ext.rb +39 -0
- data/lib/asciidoctor/section.rb +9 -8
- data/lib/asciidoctor/stylesheets.rb +19 -37
- data/lib/asciidoctor/substitutors.rb +364 -509
- data/lib/asciidoctor/syntax_highlighter.rb +238 -0
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +87 -0
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +26 -0
- data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +27 -0
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +149 -0
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +129 -0
- data/lib/asciidoctor/table.rb +73 -66
- data/lib/asciidoctor/timings.rb +4 -2
- data/lib/asciidoctor/version.rb +2 -1
- data/lib/asciidoctor/writer.rb +30 -0
- data/man/asciidoctor.1 +19 -15
- data/man/asciidoctor.adoc +14 -12
- metadata +69 -216
- data/CONTRIBUTING.adoc +0 -185
- data/Gemfile +0 -60
- data/Rakefile +0 -129
- data/bin/asciidoctor-safe +0 -15
- data/features/open_block.feature +0 -92
- data/features/pass_block.feature +0 -66
- data/features/step_definitions.rb +0 -49
- data/features/text_formatting.feature +0 -57
- data/features/xref.feature +0 -1039
- data/lib/asciidoctor/converter/base.rb +0 -59
- data/lib/asciidoctor/converter/docbook45.rb +0 -93
- data/lib/asciidoctor/converter/factory.rb +0 -226
- data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
- data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
- data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
- data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
- data/test/api_test.rb +0 -1240
- data/test/attribute_list_test.rb +0 -242
- data/test/attributes_test.rb +0 -1623
- data/test/blocks_test.rb +0 -3870
- data/test/converter_test.rb +0 -470
- data/test/document_test.rb +0 -1853
- data/test/extensions_test.rb +0 -1560
- data/test/fixtures/asciidoc_index.txt +0 -521
- data/test/fixtures/basic-docinfo-footer.html +0 -6
- data/test/fixtures/basic-docinfo-footer.xml +0 -8
- data/test/fixtures/basic-docinfo.html +0 -1
- data/test/fixtures/basic-docinfo.xml +0 -4
- data/test/fixtures/basic.asciidoc +0 -5
- data/test/fixtures/chapter-a.adoc +0 -3
- data/test/fixtures/child-include.adoc +0 -5
- data/test/fixtures/circle.svg +0 -9
- data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
- data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
- data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
- data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
- data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
- data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
- data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
- data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
- data/test/fixtures/docinfo-footer.html +0 -1
- data/test/fixtures/docinfo-footer.xml +0 -9
- data/test/fixtures/docinfo.html +0 -1
- data/test/fixtures/docinfo.xml +0 -3
- data/test/fixtures/doctime-localtime.adoc +0 -2
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +0 -13
- data/test/fixtures/file-with-missing-include.adoc +0 -1
- data/test/fixtures/grandchild-include.adoc +0 -3
- data/test/fixtures/hello-asciidoctor.pdf +0 -69
- data/test/fixtures/include-file.asciidoc +0 -24
- data/test/fixtures/include-file.jsx +0 -8
- data/test/fixtures/include-file.ml +0 -3
- data/test/fixtures/include-file.xml +0 -5
- data/test/fixtures/lists.adoc +0 -96
- data/test/fixtures/master.adoc +0 -5
- data/test/fixtures/mismatched-end-tag.adoc +0 -7
- data/test/fixtures/other-chapters.adoc +0 -11
- data/test/fixtures/outer-include.adoc +0 -5
- data/test/fixtures/parent-include-restricted.adoc +0 -5
- data/test/fixtures/parent-include.adoc +0 -5
- data/test/fixtures/sample.asciidoc +0 -30
- data/test/fixtures/section-a.adoc +0 -4
- data/test/fixtures/stylesheets/custom.css +0 -3
- data/test/fixtures/subdir/index.adoc +0 -3
- data/test/fixtures/subdir/inner-include.adoc +0 -3
- data/test/fixtures/subdir/middle-include.adoc +0 -5
- data/test/fixtures/subs-docinfo.html +0 -2
- data/test/fixtures/subs.adoc +0 -6
- data/test/fixtures/tagged-class-enclosed.rb +0 -25
- data/test/fixtures/tagged-class.rb +0 -23
- data/test/fixtures/tip.gif +0 -0
- data/test/fixtures/unclosed-tag.adoc +0 -3
- data/test/fixtures/unexpected-end-tag.adoc +0 -4
- data/test/invoker_test.rb +0 -745
- data/test/links_test.rb +0 -855
- data/test/lists_test.rb +0 -5151
- data/test/logger_test.rb +0 -211
- data/test/manpage_test.rb +0 -660
- data/test/options_test.rb +0 -262
- data/test/paragraphs_test.rb +0 -562
- data/test/parser_test.rb +0 -742
- data/test/paths_test.rb +0 -395
- data/test/preamble_test.rb +0 -173
- data/test/reader_test.rb +0 -2161
- data/test/sections_test.rb +0 -3575
- data/test/substitutions_test.rb +0 -2066
- data/test/tables_test.rb +0 -2036
- data/test/test_helper.rb +0 -447
- data/test/text_test.rb +0 -309
@@ -1,390 +1,379 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
module Asciidoctor
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
3
|
+
# A built-in {Converter} implementation that generates HTML 5 output
|
4
|
+
# consistent with the html5 backend from AsciiDoc Python.
|
5
|
+
class Converter::Html5Converter < Converter::Base
|
6
|
+
register_for 'html5'
|
7
|
+
|
8
|
+
(QUOTE_TAGS = {
|
9
|
+
monospaced: ['<code>', '</code>', true],
|
10
|
+
emphasis: ['<em>', '</em>', true],
|
11
|
+
strong: ['<strong>', '</strong>', true],
|
12
|
+
double: ['“', '”'],
|
13
|
+
single: ['‘', '’'],
|
14
|
+
mark: ['<mark>', '</mark>', true],
|
15
|
+
superscript: ['<sup>', '</sup>', true],
|
16
|
+
subscript: ['<sub>', '</sub>', true],
|
17
|
+
asciimath: ['\$', '\$'],
|
18
|
+
latexmath: ['\(', '\)'],
|
19
|
+
# Opal can't resolve these constants when referenced here
|
20
|
+
#asciimath: INLINE_MATH_DELIMITERS[:asciimath] + [false],
|
21
|
+
#latexmath: INLINE_MATH_DELIMITERS[:latexmath] + [false],
|
22
|
+
}).default = ['', '']
|
23
|
+
|
24
|
+
DropAnchorRx = /<(?:a[^>+]+|\/a)>/
|
25
|
+
StemBreakRx = / *\\\n(?:\\?\n)*|\n\n+/
|
26
|
+
SvgPreambleRx = /\A.*?(?=<svg\b)/m
|
27
|
+
SvgStartTagRx = /\A<svg[^>]*>/
|
28
|
+
DimensionAttributeRx = /\s(?:width|height|style)=(["']).*?\1/
|
29
|
+
|
30
|
+
def initialize backend, opts = {}
|
31
|
+
@backend = backend
|
32
|
+
if opts[:htmlsyntax] == 'xml'
|
33
|
+
syntax = 'xml'
|
34
|
+
@xml_mode = true
|
35
|
+
@void_element_slash = '/'
|
36
|
+
else
|
37
|
+
syntax = 'html'
|
38
|
+
@xml_mode = nil
|
39
|
+
@void_element_slash = ''
|
32
40
|
end
|
41
|
+
init_backend_traits basebackend: 'html', filetype: 'html', htmlsyntax: syntax, outfilesuffix: '.html', supports_templates: true
|
42
|
+
end
|
33
43
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
result << %(<head>
|
44
|
+
def document node
|
45
|
+
br = %(<br#{slash = @void_element_slash}>)
|
46
|
+
unless (asset_uri_scheme = (node.attr 'asset-uri-scheme', 'https')).empty?
|
47
|
+
asset_uri_scheme = %(#{asset_uri_scheme}:)
|
48
|
+
end
|
49
|
+
cdn_base_url = %(#{asset_uri_scheme}//cdnjs.cloudflare.com/ajax/libs)
|
50
|
+
linkcss = node.attr? 'linkcss'
|
51
|
+
result = ['<!DOCTYPE html>']
|
52
|
+
lang_attribute = (node.attr? 'nolang') ? '' : %( lang="#{node.attr 'lang', 'en'}")
|
53
|
+
result << %(<html#{@xml_mode ? ' xmlns="http://www.w3.org/1999/xhtml"' : ''}#{lang_attribute}>)
|
54
|
+
result << %(<head>
|
46
55
|
<meta charset="#{node.attr 'encoding', 'UTF-8'}"#{slash}>
|
47
|
-
|
56
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge"#{slash}>
|
48
57
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"#{slash}>
|
49
58
|
<meta name="generator" content="Asciidoctor #{node.attr 'asciidoctor-version'}"#{slash}>)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
result << %(<link rel="icon" type="#{icon_type}" href="#{icon_href}"#{slash}>)
|
59
|
+
result << %(<meta name="application-name" content="#{node.attr 'app-name'}"#{slash}>) if node.attr? 'app-name'
|
60
|
+
result << %(<meta name="description" content="#{node.attr 'description'}"#{slash}>) if node.attr? 'description'
|
61
|
+
result << %(<meta name="keywords" content="#{node.attr 'keywords'}"#{slash}>) if node.attr? 'keywords'
|
62
|
+
result << %(<meta name="author" content="#{((authors = node.attr 'authors').include? '<') ? (authors.gsub XmlSanitizeRx, '') : authors}"#{slash}>) if node.attr? 'authors'
|
63
|
+
result << %(<meta name="copyright" content="#{node.attr 'copyright'}"#{slash}>) if node.attr? 'copyright'
|
64
|
+
if node.attr? 'favicon'
|
65
|
+
if (icon_href = node.attr 'favicon').empty?
|
66
|
+
icon_href, icon_type = 'favicon.ico', 'image/x-icon'
|
67
|
+
else
|
68
|
+
icon_type = (icon_ext = ::File.extname icon_href) == '.ico' ? 'image/x-icon' : %(image/#{icon_ext.slice 1, icon_ext.length})
|
62
69
|
end
|
63
|
-
result << %(<
|
70
|
+
result << %(<link rel="icon" type="#{icon_type}" href="#{icon_href}"#{slash}>)
|
71
|
+
end
|
72
|
+
result << %(<title>#{node.doctitle sanitize: true, use_fallback: true}</title>)
|
64
73
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
elsif node.attr? 'stylesheet'
|
75
|
-
if linkcss
|
76
|
-
result << %(<link rel="stylesheet" href="#{node.normalize_web_path((node.attr 'stylesheet'), (node.attr 'stylesdir', ''))}"#{slash}>)
|
77
|
-
else
|
78
|
-
result << %(<style>
|
79
|
-
#{node.read_asset node.normalize_system_path((node.attr 'stylesheet'), (node.attr 'stylesdir', '')), :warn_on_failure => true, :label => 'stylesheet'}
|
74
|
+
if DEFAULT_STYLESHEET_KEYS.include?(node.attr 'stylesheet')
|
75
|
+
if (webfonts = node.attr 'webfonts')
|
76
|
+
result << %(<link rel="stylesheet" href="#{asset_uri_scheme}//fonts.googleapis.com/css?family=#{webfonts.empty? ? 'Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700' : webfonts}"#{slash}>)
|
77
|
+
end
|
78
|
+
if linkcss
|
79
|
+
result << %(<link rel="stylesheet" href="#{node.normalize_web_path DEFAULT_STYLESHEET_NAME, (node.attr 'stylesdir', ''), false}"#{slash}>)
|
80
|
+
else
|
81
|
+
result << %(<style>
|
82
|
+
#{Stylesheets.instance.primary_stylesheet_data}
|
80
83
|
</style>)
|
81
|
-
end
|
82
84
|
end
|
83
|
-
|
84
|
-
if
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
85
|
+
elsif node.attr? 'stylesheet'
|
86
|
+
if linkcss
|
87
|
+
result << %(<link rel="stylesheet" href="#{node.normalize_web_path((node.attr 'stylesheet'), (node.attr 'stylesdir', ''))}"#{slash}>)
|
88
|
+
else
|
89
|
+
result << %(<style>
|
90
|
+
#{node.read_asset node.normalize_system_path((node.attr 'stylesheet'), (node.attr 'stylesdir', '')), warn_on_failure: true, label: 'stylesheet'}
|
91
|
+
</style>)
|
91
92
|
end
|
93
|
+
end
|
92
94
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
result << @stylesheets.embed_coderay_stylesheet
|
100
|
-
end
|
101
|
-
end
|
102
|
-
when 'pygments'
|
103
|
-
if (node.attr 'pygments-css', 'class') == 'class'
|
104
|
-
pygments_style = node.attr 'pygments-style'
|
105
|
-
if linkcss
|
106
|
-
result << %(<link rel="stylesheet" href="#{node.normalize_web_path @stylesheets.pygments_stylesheet_name(pygments_style), (node.attr 'stylesdir', ''), false}"#{slash}>)
|
107
|
-
else
|
108
|
-
result << (@stylesheets.embed_pygments_stylesheet pygments_style)
|
109
|
-
end
|
110
|
-
end
|
95
|
+
if node.attr? 'icons', 'font'
|
96
|
+
if node.attr? 'iconfont-remote'
|
97
|
+
result << %(<link rel="stylesheet" href="#{node.attr 'iconfont-cdn', %[#{cdn_base_url}/font-awesome/#{FONT_AWESOME_VERSION}/css/font-awesome.min.css]}"#{slash}>)
|
98
|
+
else
|
99
|
+
iconfont_stylesheet = %(#{node.attr 'iconfont-name', 'font-awesome'}.css)
|
100
|
+
result << %(<link rel="stylesheet" href="#{node.normalize_web_path iconfont_stylesheet, (node.attr 'stylesdir', ''), false}"#{slash}>)
|
111
101
|
end
|
102
|
+
end
|
112
103
|
|
113
|
-
|
114
|
-
|
115
|
-
|
104
|
+
if (syntax_hl = node.syntax_highlighter) && (syntax_hl.docinfo? :head)
|
105
|
+
result << (syntax_hl.docinfo :head, node, linkcss: linkcss)
|
106
|
+
end
|
116
107
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
classes
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
108
|
+
unless (docinfo_content = node.docinfo).empty?
|
109
|
+
result << docinfo_content
|
110
|
+
end
|
111
|
+
|
112
|
+
result << '</head>'
|
113
|
+
body_attrs = node.id ? [%(id="#{node.id}")] : []
|
114
|
+
if (sectioned = node.sections?) && (node.attr? 'toc-class') && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
|
115
|
+
classes = [node.doctype, (node.attr 'toc-class'), %(toc-#{node.attr 'toc-position', 'header'})]
|
116
|
+
else
|
117
|
+
classes = [node.doctype]
|
118
|
+
end
|
119
|
+
classes << node.role if node.role?
|
120
|
+
body_attrs << %(class="#{classes.join ' '}")
|
121
|
+
body_attrs << %(style="max-width: #{node.attr 'max-width'};") if node.attr? 'max-width'
|
122
|
+
result << %(<body #{body_attrs.join ' '}>)
|
123
|
+
|
124
|
+
unless (docinfo_content = node.docinfo :header).empty?
|
125
|
+
result << docinfo_content
|
126
|
+
end
|
127
|
+
|
128
|
+
unless node.noheader
|
129
|
+
result << '<div id="header">'
|
130
|
+
if node.doctype == 'manpage'
|
131
|
+
result << %(<h1>#{node.doctitle} Manual Page</h1>)
|
132
|
+
if sectioned && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
|
133
|
+
result << %(<div id="toc" class="#{node.attr 'toc-class', 'toc'}">
|
135
134
|
<div id="toctitle">#{node.attr 'toc-title'}</div>
|
136
135
|
#{outline node}
|
137
136
|
</div>)
|
137
|
+
end
|
138
|
+
result << (_generate_manname_section node) if node.attr? 'manpurpose'
|
139
|
+
else
|
140
|
+
if node.header?
|
141
|
+
result << %(<h1>#{node.header.title}</h1>) unless node.notitle
|
142
|
+
details = []
|
143
|
+
idx = 1
|
144
|
+
node.authors.each do |author|
|
145
|
+
details << %(<span id="author#{idx > 1 ? idx : ''}" class="author">#{author.name}</span>#{br})
|
146
|
+
details << %(<span id="email#{idx > 1 ? idx : ''}" class="email">#{node.sub_macros author.email}</span>#{br}) if author.email
|
147
|
+
idx += 1
|
138
148
|
end
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
details =
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
details << %(<span id="email#{idx > 1 ? idx : ''}" class="email">#{node.sub_macros author.email}</span>#{br}) if author.email
|
148
|
-
idx += 1
|
149
|
-
end
|
150
|
-
if node.attr? 'revnumber'
|
151
|
-
details << %(<span id="revnumber">#{((node.attr 'version-label') || '').downcase} #{node.attr 'revnumber'}#{(node.attr? 'revdate') ? ',' : ''}</span>)
|
152
|
-
end
|
153
|
-
if node.attr? 'revdate'
|
154
|
-
details << %(<span id="revdate">#{node.attr 'revdate'}</span>)
|
155
|
-
end
|
156
|
-
if node.attr? 'revremark'
|
157
|
-
details << %(#{br}<span id="revremark">#{node.attr 'revremark'}</span>)
|
158
|
-
end
|
159
|
-
unless details.empty?
|
160
|
-
result << '<div class="details">'
|
161
|
-
result.concat details
|
162
|
-
result << '</div>'
|
163
|
-
end
|
149
|
+
if node.attr? 'revnumber'
|
150
|
+
details << %(<span id="revnumber">#{((node.attr 'version-label') || '').downcase} #{node.attr 'revnumber'}#{(node.attr? 'revdate') ? ',' : ''}</span>)
|
151
|
+
end
|
152
|
+
if node.attr? 'revdate'
|
153
|
+
details << %(<span id="revdate">#{node.attr 'revdate'}</span>)
|
154
|
+
end
|
155
|
+
if node.attr? 'revremark'
|
156
|
+
details << %(#{br}<span id="revremark">#{node.attr 'revremark'}</span>)
|
164
157
|
end
|
158
|
+
unless details.empty?
|
159
|
+
result << '<div class="details">'
|
160
|
+
result.concat details
|
161
|
+
result << '</div>'
|
162
|
+
end
|
163
|
+
end
|
165
164
|
|
166
|
-
|
167
|
-
|
165
|
+
if sectioned && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
|
166
|
+
result << %(<div id="toc" class="#{node.attr 'toc-class', 'toc'}">
|
168
167
|
<div id="toctitle">#{node.attr 'toc-title'}</div>
|
169
168
|
#{outline node}
|
170
169
|
</div>)
|
171
|
-
end
|
172
170
|
end
|
173
|
-
result << '</div>'
|
174
171
|
end
|
172
|
+
result << '</div>'
|
173
|
+
end
|
175
174
|
|
176
|
-
|
175
|
+
result << %(<div id="content">
|
177
176
|
#{node.content}
|
178
177
|
</div>)
|
179
178
|
|
180
|
-
|
181
|
-
|
179
|
+
if node.footnotes? && !(node.attr? 'nofootnotes')
|
180
|
+
result << %(<div id="footnotes">
|
182
181
|
<hr#{slash}>)
|
183
|
-
|
184
|
-
|
182
|
+
node.footnotes.each do |footnote|
|
183
|
+
result << %(<div class="footnote" id="_footnotedef_#{footnote.index}">
|
185
184
|
<a href="#_footnoteref_#{footnote.index}">#{footnote.index}</a>. #{footnote.text}
|
186
185
|
</div>)
|
187
|
-
end
|
188
|
-
result << '</div>'
|
189
186
|
end
|
187
|
+
result << '</div>'
|
188
|
+
end
|
190
189
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
190
|
+
unless node.nofooter
|
191
|
+
result << '<div id="footer">'
|
192
|
+
result << '<div id="footer-text">'
|
193
|
+
result << %(#{node.attr 'version-label'} #{node.attr 'revnumber'}#{br}) if node.attr? 'revnumber'
|
194
|
+
result << %(#{node.attr 'last-update-label'} #{node.attr 'docdatetime'}) if (node.attr? 'last-update-label') && !(node.attr? 'reproducible')
|
195
|
+
result << '</div>'
|
196
|
+
result << '</div>'
|
197
|
+
end
|
199
198
|
|
200
|
-
|
201
|
-
|
202
|
-
end
|
199
|
+
# JavaScript (and auxiliary stylesheets) loaded at the end of body for performance reasons
|
200
|
+
# See http://www.html5rocks.com/en/tutorials/speed/script-loading/
|
203
201
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
when 'highlightjs', 'highlight.js'
|
208
|
-
highlightjs_path = node.attr 'highlightjsdir', %(#{cdn_base}/highlight.js/9.13.1)
|
209
|
-
result << %(<link rel="stylesheet" href="#{highlightjs_path}/styles/#{node.attr 'highlightjs-theme', 'github'}.min.css"#{slash}>)
|
210
|
-
result << %(<script src="#{highlightjs_path}/highlight.min.js"></script>
|
211
|
-
<script>hljs.initHighlighting()</script>)
|
212
|
-
when 'prettify'
|
213
|
-
prettify_path = node.attr 'prettifydir', %(#{cdn_base}/prettify/r298)
|
214
|
-
result << %(<link rel="stylesheet" href="#{prettify_path}/#{node.attr 'prettify-theme', 'prettify'}.min.css"#{slash}>)
|
215
|
-
result << %(<script src="#{prettify_path}/prettify.min.js"></script>
|
216
|
-
<script>prettyPrint()</script>)
|
217
|
-
end
|
202
|
+
if syntax_hl && (syntax_hl.docinfo? :footer)
|
203
|
+
result << (syntax_hl.docinfo :footer, node, cdn_base_url: cdn_base_url, linkcss: linkcss, self_closing_tag_slash: slash)
|
204
|
+
end
|
218
205
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
206
|
+
if node.attr? 'stem'
|
207
|
+
eqnums_val = node.attr 'eqnums', 'none'
|
208
|
+
eqnums_val = 'AMS' if eqnums_val.empty?
|
209
|
+
eqnums_opt = %( equationNumbers: { autoNumber: "#{eqnums_val}" } )
|
210
|
+
# IMPORTANT inspect calls on delimiter arrays are intentional for JavaScript compat (emulates JSON.stringify)
|
211
|
+
result << %(<script type="text/x-mathjax-config">
|
225
212
|
MathJax.Hub.Config({
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
213
|
+
messageStyle: "none",
|
214
|
+
tex2jax: {
|
215
|
+
inlineMath: [#{INLINE_MATH_DELIMITERS[:latexmath].inspect}],
|
216
|
+
displayMath: [#{BLOCK_MATH_DELIMITERS[:latexmath].inspect}],
|
217
|
+
ignoreClass: "nostem|nolatexmath"
|
218
|
+
},
|
219
|
+
asciimath2jax: {
|
220
|
+
delimiters: [#{BLOCK_MATH_DELIMITERS[:asciimath].inspect}],
|
221
|
+
ignoreClass: "nostem|noasciimath"
|
222
|
+
},
|
223
|
+
TeX: {#{eqnums_opt}}
|
237
224
|
});
|
238
225
|
</script>
|
239
|
-
<script src="#{
|
240
|
-
|
226
|
+
<script src="#{cdn_base_url}/mathjax/#{MATHJAX_VERSION}/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>)
|
227
|
+
end
|
241
228
|
|
242
|
-
|
243
|
-
result <<
|
244
|
-
result.join LF
|
229
|
+
unless (docinfo_content = node.docinfo :footer).empty?
|
230
|
+
result << docinfo_content
|
245
231
|
end
|
246
232
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
result << %(<h1#{id_attr}>#{node.header.title}</h1>)
|
260
|
-
end
|
233
|
+
result << '</body>'
|
234
|
+
result << '</html>'
|
235
|
+
result.join LF
|
236
|
+
end
|
237
|
+
|
238
|
+
def embedded node
|
239
|
+
result = []
|
240
|
+
if node.doctype == 'manpage'
|
241
|
+
# QUESTION should notitle control the manual page title?
|
242
|
+
unless node.notitle
|
243
|
+
id_attr = node.id ? %( id="#{node.id}") : ''
|
244
|
+
result << %(<h1#{id_attr}>#{node.doctitle} Manual Page</h1>)
|
261
245
|
end
|
246
|
+
result << (_generate_manname_section node) if node.attr? 'manpurpose'
|
247
|
+
elsif node.header? && !node.notitle
|
248
|
+
id_attr = node.id ? %( id="#{node.id}") : ''
|
249
|
+
result << %(<h1#{id_attr}>#{node.header.title}</h1>)
|
250
|
+
end
|
262
251
|
|
263
|
-
|
264
|
-
|
252
|
+
if node.sections? && (node.attr? 'toc') && (toc_p = node.attr 'toc-placement') != 'macro' && toc_p != 'preamble'
|
253
|
+
result << %(<div id="toc" class="toc">
|
265
254
|
<div id="toctitle">#{node.attr 'toc-title'}</div>
|
266
255
|
#{outline node}
|
267
256
|
</div>)
|
268
|
-
|
257
|
+
end
|
269
258
|
|
270
|
-
|
259
|
+
result << node.content
|
271
260
|
|
272
|
-
|
273
|
-
|
261
|
+
if node.footnotes? && !(node.attr? 'nofootnotes')
|
262
|
+
result << %(<div id="footnotes">
|
274
263
|
<hr#{@void_element_slash}>)
|
275
|
-
|
276
|
-
|
264
|
+
node.footnotes.each do |footnote|
|
265
|
+
result << %(<div class="footnote" id="_footnotedef_#{footnote.index}">
|
277
266
|
<a href="#_footnoteref_#{footnote.index}">#{footnote.index}</a>. #{footnote.text}
|
278
267
|
</div>)
|
279
|
-
end
|
280
|
-
result << '</div>'
|
281
268
|
end
|
282
|
-
|
283
|
-
result.join LF
|
269
|
+
result << '</div>'
|
284
270
|
end
|
285
271
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
272
|
+
result.join LF
|
273
|
+
end
|
274
|
+
|
275
|
+
def outline node, opts = {}
|
276
|
+
return unless node.sections?
|
277
|
+
sectnumlevels = opts[:sectnumlevels] || (node.document.attributes['sectnumlevels'] || 3).to_i
|
278
|
+
toclevels = opts[:toclevels] || (node.document.attributes['toclevels'] || 2).to_i
|
279
|
+
sections = node.sections
|
280
|
+
# FIXME top level is incorrect if a multipart book starts with a special section defined at level 0
|
281
|
+
result = [%(<ul class="sectlevel#{sections[0].level}">)]
|
282
|
+
sections.each do |section|
|
283
|
+
slevel = section.level
|
284
|
+
if section.caption
|
285
|
+
stitle = section.captioned_title
|
286
|
+
elsif section.numbered && slevel <= sectnumlevels
|
287
|
+
if slevel < 2 && node.document.doctype == 'book'
|
288
|
+
if section.sectname == 'chapter'
|
289
|
+
stitle = %(#{(signifier = node.document.attributes['chapter-signifier']) ? "#{signifier} " : ''}#{section.sectnum} #{section.title})
|
290
|
+
elsif section.sectname == 'part'
|
291
|
+
stitle = %(#{(signifier = node.document.attributes['part-signifier']) ? "#{signifier} " : ''}#{section.sectnum nil, ':'} #{section.title})
|
306
292
|
else
|
307
293
|
stitle = %(#{section.sectnum} #{section.title})
|
308
294
|
end
|
309
295
|
else
|
310
|
-
stitle = section.title
|
311
|
-
end
|
312
|
-
stitle = stitle.gsub DropAnchorRx, '' if stitle.include? '<a'
|
313
|
-
if slevel < toclevels && (child_toc_level = outline section, :toclevels => toclevels, :sectnumlevels => sectnumlevels)
|
314
|
-
result << %(<li><a href="##{section.id}">#{stitle}</a>)
|
315
|
-
result << child_toc_level
|
316
|
-
result << '</li>'
|
317
|
-
else
|
318
|
-
result << %(<li><a href="##{section.id}">#{stitle}</a></li>)
|
296
|
+
stitle = %(#{section.sectnum} #{section.title})
|
319
297
|
end
|
298
|
+
else
|
299
|
+
stitle = section.title
|
300
|
+
end
|
301
|
+
stitle = stitle.gsub DropAnchorRx, '' if stitle.include? '<a'
|
302
|
+
if slevel < toclevels && (child_toc_level = outline section, toclevels: toclevels, sectnumlevels: sectnumlevels)
|
303
|
+
result << %(<li><a href="##{section.id}">#{stitle}</a>)
|
304
|
+
result << child_toc_level
|
305
|
+
result << '</li>'
|
306
|
+
else
|
307
|
+
result << %(<li><a href="##{section.id}">#{stitle}</a></li>)
|
320
308
|
end
|
321
|
-
result << '</ul>'
|
322
|
-
result.join LF
|
323
309
|
end
|
310
|
+
result << '</ul>'
|
311
|
+
result.join LF
|
312
|
+
end
|
324
313
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
else
|
337
|
-
title = %(#{node.sectnum} #{node.title})
|
338
|
-
end
|
314
|
+
def section node
|
315
|
+
doc_attrs = node.document.attributes
|
316
|
+
level = node.level
|
317
|
+
if node.caption
|
318
|
+
title = node.captioned_title
|
319
|
+
elsif node.numbered && level <= (doc_attrs['sectnumlevels'] || 3).to_i
|
320
|
+
if level < 2 && node.document.doctype == 'book'
|
321
|
+
if node.sectname == 'chapter'
|
322
|
+
title = %(#{(signifier = doc_attrs['chapter-signifier']) ? "#{signifier} " : ''}#{node.sectnum} #{node.title})
|
323
|
+
elsif node.sectname == 'part'
|
324
|
+
title = %(#{(signifier = doc_attrs['part-signifier']) ? "#{signifier} " : ''}#{node.sectnum nil, ':'} #{node.title})
|
339
325
|
else
|
340
326
|
title = %(#{node.sectnum} #{node.title})
|
341
327
|
end
|
342
328
|
else
|
343
|
-
title = node.title
|
329
|
+
title = %(#{node.sectnum} #{node.title})
|
344
330
|
end
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
331
|
+
else
|
332
|
+
title = node.title
|
333
|
+
end
|
334
|
+
if node.id
|
335
|
+
id_attr = %( id="#{id = node.id}")
|
336
|
+
if doc_attrs['sectlinks']
|
337
|
+
title = %(<a class="link" href="##{id}">#{title}</a>)
|
338
|
+
end
|
339
|
+
if doc_attrs['sectanchors']
|
340
|
+
# QUESTION should we add a font-based icon in anchor if icons=font?
|
341
|
+
if doc_attrs['sectanchors'] == 'after'
|
342
|
+
title = %(#{title}<a class="anchor" href="##{id}"></a>)
|
343
|
+
else
|
344
|
+
title = %(<a class="anchor" href="##{id}"></a>#{title})
|
357
345
|
end
|
358
|
-
else
|
359
|
-
id_attr = ''
|
360
346
|
end
|
361
|
-
|
362
|
-
|
347
|
+
else
|
348
|
+
id_attr = ''
|
349
|
+
end
|
350
|
+
if level == 0
|
351
|
+
%(<h1#{id_attr} class="sect0#{(role = node.role) ? " #{role}" : ''}">#{title}</h1>
|
363
352
|
#{node.content})
|
364
|
-
|
365
|
-
|
353
|
+
else
|
354
|
+
%(<div class="sect#{level}#{(role = node.role) ? " #{role}" : ''}">
|
366
355
|
<h#{level + 1}#{id_attr}>#{title}</h#{level + 1}>
|
367
356
|
#{level == 1 ? %[<div class="sectionbody">
|
368
357
|
#{node.content}
|
369
358
|
</div>] : node.content}
|
370
359
|
</div>)
|
371
|
-
end
|
372
360
|
end
|
361
|
+
end
|
373
362
|
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
else
|
382
|
-
label = %(<img src="#{node.icon_uri name}" alt="#{node.attr 'textlabel'}"#{@void_element_slash}>)
|
383
|
-
end
|
363
|
+
def admonition node
|
364
|
+
id_attr = node.id ? %( id="#{node.id}") : ''
|
365
|
+
name = node.attr 'name'
|
366
|
+
title_element = node.title? ? %(<div class="title">#{node.title}</div>\n) : ''
|
367
|
+
if node.document.attr? 'icons'
|
368
|
+
if (node.document.attr? 'icons', 'font') && !(node.attr? 'icon')
|
369
|
+
label = %(<i class="fa icon-#{name}" title="#{node.attr 'textlabel'}"></i>)
|
384
370
|
else
|
385
|
-
label = %(<
|
371
|
+
label = %(<img src="#{node.icon_uri name}" alt="#{node.attr 'textlabel'}"#{@void_element_slash}>)
|
386
372
|
end
|
387
|
-
|
373
|
+
else
|
374
|
+
label = %(<div class="title">#{node.attr 'textlabel'}</div>)
|
375
|
+
end
|
376
|
+
%(<div#{id_attr} class="admonitionblock #{name}#{(role = node.role) ? " #{role}" : ''}">
|
388
377
|
<table>
|
389
378
|
<tr>
|
390
379
|
<td class="icon">
|
@@ -396,853 +385,850 @@ MathJax.Hub.Config({
|
|
396
385
|
</tr>
|
397
386
|
</table>
|
398
387
|
</div>)
|
399
|
-
|
388
|
+
end
|
400
389
|
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
390
|
+
def audio node
|
391
|
+
xml = @xml_mode
|
392
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
393
|
+
classes = ['audioblock', node.role].compact
|
394
|
+
class_attribute = %( class="#{classes.join ' '}")
|
395
|
+
title_element = node.title? ? %(<div class="title">#{node.title}</div>\n) : ''
|
396
|
+
start_t = node.attr 'start'
|
397
|
+
end_t = node.attr 'end'
|
398
|
+
time_anchor = (start_t || end_t) ? %(#t=#{start_t || ''}#{end_t ? ",#{end_t}" : ''}) : ''
|
399
|
+
%(<div#{id_attribute}#{class_attribute}>
|
411
400
|
#{title_element}<div class="content">
|
412
|
-
<audio src="#{node.media_uri(node.attr 'target')}#{time_anchor}"#{(node.option? 'autoplay') ? (
|
401
|
+
<audio src="#{node.media_uri(node.attr 'target')}#{time_anchor}"#{(node.option? 'autoplay') ? (_append_boolean_attribute 'autoplay', xml) : ''}#{(node.option? 'nocontrols') ? '' : (_append_boolean_attribute 'controls', xml)}#{(node.option? 'loop') ? (_append_boolean_attribute 'loop', xml) : ''}>
|
413
402
|
Your browser does not support the audio tag.
|
414
403
|
</audio>
|
415
404
|
</div>
|
416
405
|
</div>)
|
417
|
-
|
406
|
+
end
|
418
407
|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
408
|
+
def colist node
|
409
|
+
result = []
|
410
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
411
|
+
classes = ['colist', node.style, node.role].compact
|
412
|
+
class_attribute = %( class="#{classes.join ' '}")
|
413
|
+
|
414
|
+
result << %(<div#{id_attribute}#{class_attribute}>)
|
415
|
+
result << %(<div class="title">#{node.title}</div>) if node.title?
|
416
|
+
|
417
|
+
if node.document.attr? 'icons'
|
418
|
+
result << '<table>'
|
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>)
|
424
|
+
else
|
425
|
+
num_label = %(<img src="#{node.icon_uri "callouts/#{num}"}" alt="#{num}"#{@void_element_slash}>)
|
426
|
+
end
|
427
|
+
result << %(<tr>
|
439
428
|
<td>#{num_label}</td>
|
440
429
|
<td>#{item.text}#{item.blocks? ? LF + item.content : ''}</td>
|
441
430
|
</tr>)
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
431
|
+
end
|
432
|
+
result << '</table>'
|
433
|
+
else
|
434
|
+
result << '<ol>'
|
435
|
+
node.items.each do |item|
|
436
|
+
result << %(<li>
|
448
437
|
<p>#{item.text}</p>#{item.blocks? ? LF + item.content : ''}
|
449
438
|
</li>)
|
450
|
-
end
|
451
|
-
result << '</ol>'
|
452
439
|
end
|
453
|
-
|
454
|
-
result << '</div>'
|
455
|
-
result.join LF
|
440
|
+
result << '</ol>'
|
456
441
|
end
|
457
442
|
|
458
|
-
|
459
|
-
|
460
|
-
|
443
|
+
result << '</div>'
|
444
|
+
result.join LF
|
445
|
+
end
|
461
446
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
end
|
487
|
-
result << '</li>'
|
447
|
+
def dlist node
|
448
|
+
result = []
|
449
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
450
|
+
|
451
|
+
classes = case node.style
|
452
|
+
when 'qanda'
|
453
|
+
['qlist', 'qanda', node.role]
|
454
|
+
when 'horizontal'
|
455
|
+
['hdlist', node.role]
|
456
|
+
else
|
457
|
+
['dlist', node.style, node.role]
|
458
|
+
end.compact
|
459
|
+
|
460
|
+
class_attribute = %( class="#{classes.join ' '}")
|
461
|
+
|
462
|
+
result << %(<div#{id_attribute}#{class_attribute}>)
|
463
|
+
result << %(<div class="title">#{node.title}</div>) if node.title?
|
464
|
+
case node.style
|
465
|
+
when 'qanda'
|
466
|
+
result << '<ol>'
|
467
|
+
node.items.each do |terms, dd|
|
468
|
+
result << '<li>'
|
469
|
+
terms.each do |dt|
|
470
|
+
result << %(<p><em>#{dt.text}</em></p>)
|
488
471
|
end
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
result << '<table>'
|
493
|
-
if (node.attr? 'labelwidth') || (node.attr? 'itemwidth')
|
494
|
-
result << '<colgroup>'
|
495
|
-
col_style_attribute = (node.attr? 'labelwidth') ? %( style="width: #{(node.attr 'labelwidth').chomp '%'}%;") : ''
|
496
|
-
result << %(<col#{col_style_attribute}#{slash}>)
|
497
|
-
col_style_attribute = (node.attr? 'itemwidth') ? %( style="width: #{(node.attr 'itemwidth').chomp '%'}%;") : ''
|
498
|
-
result << %(<col#{col_style_attribute}#{slash}>)
|
499
|
-
result << '</colgroup>'
|
472
|
+
if dd
|
473
|
+
result << %(<p>#{dd.text}</p>) if dd.text?
|
474
|
+
result << dd.content if dd.blocks?
|
500
475
|
end
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
476
|
+
result << '</li>'
|
477
|
+
end
|
478
|
+
result << '</ol>'
|
479
|
+
when 'horizontal'
|
480
|
+
slash = @void_element_slash
|
481
|
+
result << '<table>'
|
482
|
+
if (node.attr? 'labelwidth') || (node.attr? 'itemwidth')
|
483
|
+
result << '<colgroup>'
|
484
|
+
col_style_attribute = (node.attr? 'labelwidth') ? %( style="width: #{(node.attr 'labelwidth').chomp '%'}%;") : ''
|
485
|
+
result << %(<col#{col_style_attribute}#{slash}>)
|
486
|
+
col_style_attribute = (node.attr? 'itemwidth') ? %( style="width: #{(node.attr 'itemwidth').chomp '%'}%;") : ''
|
487
|
+
result << %(<col#{col_style_attribute}#{slash}>)
|
488
|
+
result << '</colgroup>'
|
489
|
+
end
|
490
|
+
node.items.each do |terms, dd|
|
491
|
+
result << '<tr>'
|
492
|
+
result << %(<td class="hdlist1#{(node.option? 'strong') ? ' strong' : ''}">)
|
493
|
+
first_term = true
|
494
|
+
terms.each do |dt|
|
495
|
+
result << %(<br#{slash}>) unless first_term
|
496
|
+
result << dt.text
|
497
|
+
first_term = nil
|
518
498
|
end
|
519
|
-
result << '</
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
[*terms].each do |dt|
|
525
|
-
result << %(<dt#{dt_style_attribute}>#{dt.text}</dt>)
|
526
|
-
end
|
527
|
-
if dd
|
528
|
-
result << '<dd>'
|
529
|
-
result << %(<p>#{dd.text}</p>) if dd.text?
|
530
|
-
result << dd.content if dd.blocks?
|
531
|
-
result << '</dd>'
|
532
|
-
end
|
499
|
+
result << '</td>'
|
500
|
+
result << '<td class="hdlist2">'
|
501
|
+
if dd
|
502
|
+
result << %(<p>#{dd.text}</p>) if dd.text?
|
503
|
+
result << dd.content if dd.blocks?
|
533
504
|
end
|
534
|
-
result << '</
|
505
|
+
result << '</td>'
|
506
|
+
result << '</tr>'
|
535
507
|
end
|
536
|
-
|
537
|
-
|
538
|
-
result
|
508
|
+
result << '</table>'
|
509
|
+
else
|
510
|
+
result << '<dl>'
|
511
|
+
dt_style_attribute = node.style ? '' : ' class="hdlist1"'
|
512
|
+
node.items.each do |terms, dd|
|
513
|
+
terms.each do |dt|
|
514
|
+
result << %(<dt#{dt_style_attribute}>#{dt.text}</dt>)
|
515
|
+
end
|
516
|
+
if dd
|
517
|
+
result << '<dd>'
|
518
|
+
result << %(<p>#{dd.text}</p>) if dd.text?
|
519
|
+
result << dd.content if dd.blocks?
|
520
|
+
result << '</dd>'
|
521
|
+
end
|
522
|
+
end
|
523
|
+
result << '</dl>'
|
539
524
|
end
|
540
525
|
|
541
|
-
|
542
|
-
|
543
|
-
|
526
|
+
result << '</div>'
|
527
|
+
result.join LF
|
528
|
+
end
|
529
|
+
|
530
|
+
def example node
|
531
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
532
|
+
title_element = node.title? ? %(<div class="title">#{node.captioned_title}</div>\n) : ''
|
544
533
|
|
545
|
-
|
534
|
+
%(<div#{id_attribute} class="exampleblock#{(role = node.role) ? " #{role}" : ''}">
|
546
535
|
#{title_element}<div class="content">
|
547
536
|
#{node.content}
|
548
537
|
</div>
|
549
538
|
</div>)
|
550
|
-
|
539
|
+
end
|
551
540
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
541
|
+
def floating_title node
|
542
|
+
tag_name = %(h#{node.level + 1})
|
543
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
544
|
+
classes = [node.style, node.role].compact
|
545
|
+
%(<#{tag_name}#{id_attribute} class="#{classes.join ' '}">#{node.title}</#{tag_name}>)
|
546
|
+
end
|
558
547
|
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
end
|
571
|
-
end
|
572
|
-
img ||= %(<img src="#{node.image_uri target}" alt="#{encode_quotes node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>)
|
573
|
-
if node.attr? 'link', nil, false
|
574
|
-
img = %(<a class="image" href="#{node.attr 'link'}"#{(append_link_constraint_attrs node).join}>#{img}</a>)
|
548
|
+
def image node
|
549
|
+
target = node.attr 'target'
|
550
|
+
width_attr = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : ''
|
551
|
+
height_attr = (node.attr? 'height') ? %( height="#{node.attr 'height'}") : ''
|
552
|
+
if ((node.attr? 'format', 'svg') || (target.include? '.svg')) && node.document.safe < SafeMode::SECURE &&
|
553
|
+
((svg = (node.option? 'inline')) || (obj = (node.option? 'interactive')))
|
554
|
+
if svg
|
555
|
+
img = (_read_svg_contents node, target) || %(<span class="alt">#{node.alt}</span>)
|
556
|
+
elsif obj
|
557
|
+
fallback = (node.attr? 'fallback') ? %(<img src="#{node.image_uri(node.attr 'fallback')}" alt="#{_encode_attribute_value node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>) : %(<span class="alt">#{node.alt}</span>)
|
558
|
+
img = %(<object type="image/svg+xml" data="#{node.image_uri target}"#{width_attr}#{height_attr}>#{fallback}</object>)
|
575
559
|
end
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
560
|
+
end
|
561
|
+
img ||= %(<img src="#{node.image_uri target}" alt="#{_encode_attribute_value node.alt}"#{width_attr}#{height_attr}#{@void_element_slash}>)
|
562
|
+
if node.attr? 'link'
|
563
|
+
img = %(<a class="image" href="#{node.attr 'link'}"#{(_append_link_constraint_attrs node).join}>#{img}</a>)
|
564
|
+
end
|
565
|
+
id_attr = node.id ? %( id="#{node.id}") : ''
|
566
|
+
classes = ['imageblock']
|
567
|
+
classes << (node.attr 'float') if node.attr? 'float'
|
568
|
+
classes << %(text-#{node.attr 'align'}) if node.attr? 'align'
|
569
|
+
classes << node.role if node.role
|
570
|
+
class_attr = %( class="#{classes.join ' '}")
|
571
|
+
title_el = node.title? ? %(\n<div class="title">#{node.captioned_title}</div>) : ''
|
572
|
+
%(<div#{id_attr}#{class_attr}>
|
584
573
|
<div class="content">
|
585
574
|
#{img}
|
586
575
|
</div>#{title_el}
|
587
576
|
</div>)
|
588
|
-
|
577
|
+
end
|
589
578
|
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
pre_class = %( class="CodeRay highlight#{nowrap ? ' nowrap' : ''}")
|
601
|
-
when 'pygments'
|
602
|
-
if (node.document.attr? 'pygments-css', 'inline')
|
603
|
-
@pygments_bg = @stylesheets.pygments_background(node.document.attr 'pygments-style') unless defined? @pygments_bg
|
604
|
-
pre_class = %( class="pygments highlight#{nowrap ? ' nowrap' : ''}" style="background: #{@pygments_bg}")
|
605
|
-
else
|
606
|
-
pre_class = %( class="pygments highlight#{nowrap ? ' nowrap' : ''}")
|
607
|
-
end
|
608
|
-
when 'highlightjs', 'highlight.js'
|
609
|
-
pre_class = %( class="highlightjs highlight#{nowrap ? ' nowrap' : ''}")
|
610
|
-
code_attrs = %( class="language-#{language} hljs"#{code_attrs}) if language
|
611
|
-
when 'prettify'
|
612
|
-
pre_class = %( class="prettyprint highlight#{nowrap ? ' nowrap' : ''}#{(node.attr? 'linenums', nil, false) ? ' linenums' : ''}")
|
613
|
-
code_attrs = %( class="language-#{language}"#{code_attrs}) if language
|
614
|
-
when 'html-pipeline'
|
615
|
-
pre_class = language ? %( lang="#{language}") : ''
|
616
|
-
code_attrs = ''
|
617
|
-
else
|
618
|
-
pre_class = %( class="highlight#{nowrap ? ' nowrap' : ''}")
|
619
|
-
code_attrs = %( class="language-#{language}"#{code_attrs}) if language
|
620
|
-
end
|
621
|
-
pre_start = %(<pre#{pre_class}><code#{code_attrs}>)
|
622
|
-
pre_end = '</code></pre>'
|
579
|
+
def listing node
|
580
|
+
nowrap = (node.option? 'nowrap') || !(node.document.attr? 'prewrap')
|
581
|
+
if node.style == 'source'
|
582
|
+
lang = node.attr 'language'
|
583
|
+
if (syntax_hl = node.document.syntax_highlighter)
|
584
|
+
opts = syntax_hl.highlight? ? {
|
585
|
+
css_mode: ((doc_attrs = node.document.attributes)[%(#{syntax_hl.name}-css)] || :class).to_sym,
|
586
|
+
style: doc_attrs[%(#{syntax_hl.name}-style)],
|
587
|
+
} : {}
|
588
|
+
opts[:nowrap] = nowrap
|
623
589
|
else
|
624
|
-
|
625
|
-
|
590
|
+
pre_open = %(<pre class="highlight#{nowrap ? ' nowrap' : ''}"><code#{lang ? %[ class="language-#{lang}" data-lang="#{lang}"] : ''}>)
|
591
|
+
pre_close = '</code></pre>'
|
626
592
|
end
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
593
|
+
else
|
594
|
+
pre_open = %(<pre#{nowrap ? ' class="nowrap"' : ''}>)
|
595
|
+
pre_close = '</pre>'
|
596
|
+
end
|
597
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
598
|
+
title_element = node.title? ? %(<div class="title">#{node.captioned_title}</div>\n) : ''
|
599
|
+
%(<div#{id_attribute} class="listingblock#{(role = node.role) ? " #{role}" : ''}">
|
631
600
|
#{title_element}<div class="content">
|
632
|
-
#{
|
601
|
+
#{syntax_hl ? (syntax_hl.format node, lang, opts) : pre_open + (node.content || '') + pre_close}
|
633
602
|
</div>
|
634
603
|
</div>)
|
635
|
-
|
604
|
+
end
|
636
605
|
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
606
|
+
def literal node
|
607
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
608
|
+
title_element = node.title? ? %(<div class="title">#{node.title}</div>\n) : ''
|
609
|
+
nowrap = !(node.document.attr? 'prewrap') || (node.option? 'nowrap')
|
610
|
+
%(<div#{id_attribute} class="literalblock#{(role = node.role) ? " #{role}" : ''}">
|
642
611
|
#{title_element}<div class="content">
|
643
612
|
<pre#{nowrap ? ' class="nowrap"' : ''}>#{node.content}</pre>
|
644
613
|
</div>
|
645
614
|
</div>)
|
646
|
-
|
615
|
+
end
|
647
616
|
|
648
|
-
|
649
|
-
id_attribute = node.id ? %( id="#{node.id}") : ''
|
650
|
-
title_element = node.title? ? %(<div class="title">#{node.title}</div>\n) : ''
|
651
|
-
open, close = BLOCK_MATH_DELIMITERS[style = node.style.to_sym]
|
652
|
-
equation = node.content
|
617
|
+
alias pass _content_only
|
653
618
|
|
619
|
+
def stem node
|
620
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
621
|
+
title_element = node.title? ? %(<div class="title">#{node.title}</div>\n) : ''
|
622
|
+
open, close = BLOCK_MATH_DELIMITERS[style = node.style.to_sym]
|
623
|
+
if (equation = node.content)
|
654
624
|
if style == :asciimath && (equation.include? LF)
|
655
625
|
br = %(<br#{@void_element_slash}>#{LF})
|
656
626
|
equation = equation.gsub(StemBreakRx) { %(#{close}#{br * ($&.count LF)}#{open}) }
|
657
627
|
end
|
658
|
-
|
659
628
|
unless (equation.start_with? open) && (equation.end_with? close)
|
660
629
|
equation = %(#{open}#{equation}#{close})
|
661
630
|
end
|
662
|
-
|
663
|
-
|
631
|
+
else
|
632
|
+
equation = ''
|
633
|
+
end
|
634
|
+
%(<div#{id_attribute} class="stemblock#{(role = node.role) ? " #{role}" : ''}">
|
664
635
|
#{title_element}<div class="content">
|
665
636
|
#{equation}
|
666
637
|
</div>
|
667
638
|
</div>)
|
668
|
-
|
669
|
-
|
670
|
-
def olist node
|
671
|
-
result = []
|
672
|
-
id_attribute = node.id ? %( id="#{node.id}") : ''
|
673
|
-
classes = ['olist', node.style, node.role].compact
|
674
|
-
class_attribute = %( class="#{classes.join ' '}")
|
675
|
-
|
676
|
-
result << %(<div#{id_attribute}#{class_attribute}>)
|
677
|
-
result << %(<div class="title">#{node.title}</div>) if node.title?
|
678
|
-
|
679
|
-
type_attribute = (keyword = node.list_marker_keyword) ? %( type="#{keyword}") : ''
|
680
|
-
start_attribute = (node.attr? 'start') ? %( start="#{node.attr 'start'}") : ''
|
681
|
-
reversed_attribute = (node.option? 'reversed') ? (append_boolean_attribute 'reversed', @xml_mode) : ''
|
682
|
-
result << %(<ol class="#{node.style}"#{type_attribute}#{start_attribute}#{reversed_attribute}>)
|
639
|
+
end
|
683
640
|
|
684
|
-
|
641
|
+
def olist node
|
642
|
+
result = []
|
643
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
644
|
+
classes = ['olist', node.style, node.role].compact
|
645
|
+
class_attribute = %( class="#{classes.join ' '}")
|
646
|
+
|
647
|
+
result << %(<div#{id_attribute}#{class_attribute}>)
|
648
|
+
result << %(<div class="title">#{node.title}</div>) if node.title?
|
649
|
+
|
650
|
+
type_attribute = (keyword = node.list_marker_keyword) ? %( type="#{keyword}") : ''
|
651
|
+
start_attribute = (node.attr? 'start') ? %( start="#{node.attr 'start'}") : ''
|
652
|
+
reversed_attribute = (node.option? 'reversed') ? (_append_boolean_attribute 'reversed', @xml_mode) : ''
|
653
|
+
result << %(<ol class="#{node.style}"#{type_attribute}#{start_attribute}#{reversed_attribute}>)
|
654
|
+
|
655
|
+
node.items.each do |item|
|
656
|
+
if item.id
|
657
|
+
result << %(<li id="#{item.id}"#{item.role ? %[ class="#{item.role}"] : ''}>)
|
658
|
+
elsif item.role
|
659
|
+
result << %(<li class="#{item.role}">)
|
660
|
+
else
|
685
661
|
result << '<li>'
|
686
|
-
result << %(<p>#{item.text}</p>)
|
687
|
-
result << item.content if item.blocks?
|
688
|
-
result << '</li>'
|
689
662
|
end
|
690
|
-
|
691
|
-
result <<
|
692
|
-
result << '</
|
693
|
-
result.join LF
|
663
|
+
result << %(<p>#{item.text}</p>)
|
664
|
+
result << item.content if item.blocks?
|
665
|
+
result << '</li>'
|
694
666
|
end
|
695
667
|
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
668
|
+
result << '</ol>'
|
669
|
+
result << '</div>'
|
670
|
+
result.join LF
|
671
|
+
end
|
672
|
+
|
673
|
+
def open node
|
674
|
+
if (style = node.style) == 'abstract'
|
675
|
+
if node.parent == node.document && node.document.doctype == 'book'
|
676
|
+
logger.warn 'abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
|
677
|
+
''
|
678
|
+
else
|
679
|
+
id_attr = node.id ? %( id="#{node.id}") : ''
|
680
|
+
title_el = node.title? ? %(<div class="title">#{node.title}</div>\n) : ''
|
681
|
+
%(<div#{id_attr} class="quoteblock abstract#{(role = node.role) ? " #{role}" : ''}">
|
705
682
|
#{title_el}<blockquote>
|
706
683
|
#{node.content}
|
707
684
|
</blockquote>
|
708
685
|
</div>)
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
686
|
+
end
|
687
|
+
elsif style == 'partintro' && (node.level > 0 || node.parent.context != :section || node.document.doctype != 'book')
|
688
|
+
logger.error 'partintro block can only be used when doctype is book and must be a child of a book part. Excluding block content.'
|
689
|
+
''
|
690
|
+
else
|
691
|
+
id_attr = node.id ? %( id="#{node.id}") : ''
|
692
|
+
title_el = node.title? ? %(<div class="title">#{node.title}</div>\n) : ''
|
693
|
+
%(<div#{id_attr} class="openblock#{style && style != 'open' ? " #{style}" : ''}#{(role = node.role) ? " #{role}" : ''}">
|
717
694
|
#{title_el}<div class="content">
|
718
695
|
#{node.content}
|
719
696
|
</div>
|
720
697
|
</div>)
|
721
|
-
end
|
722
|
-
end
|
723
|
-
|
724
|
-
def page_break node
|
725
|
-
'<div style="page-break-after: always;"></div>'
|
726
698
|
end
|
699
|
+
end
|
727
700
|
|
728
|
-
|
729
|
-
|
730
|
-
|
701
|
+
def page_break node
|
702
|
+
'<div style="page-break-after: always;"></div>'
|
703
|
+
end
|
731
704
|
|
732
|
-
|
733
|
-
|
705
|
+
def paragraph node
|
706
|
+
if node.role
|
707
|
+
attributes = %(#{node.id ? %[ id="#{node.id}"] : ''} class="paragraph #{node.role}")
|
708
|
+
elsif node.id
|
709
|
+
attributes = %( id="#{node.id}" class="paragraph")
|
710
|
+
else
|
711
|
+
attributes = ' class="paragraph"'
|
712
|
+
end
|
713
|
+
if node.title?
|
714
|
+
%(<div#{attributes}>
|
734
715
|
<div class="title">#{node.title}</div>
|
735
716
|
<p>#{node.content}</p>
|
736
717
|
</div>)
|
737
|
-
|
738
|
-
|
718
|
+
else
|
719
|
+
%(<div#{attributes}>
|
739
720
|
<p>#{node.content}</p>
|
740
721
|
</div>)
|
741
|
-
end
|
742
722
|
end
|
723
|
+
end
|
743
724
|
|
744
|
-
|
745
|
-
|
746
|
-
|
725
|
+
def preamble node
|
726
|
+
if (doc = node.document).attr?('toc-placement', 'preamble') && doc.sections? && (doc.attr? 'toc')
|
727
|
+
toc = %(
|
747
728
|
<div id="toc" class="#{doc.attr 'toc-class', 'toc'}">
|
748
729
|
<div id="toctitle">#{doc.attr 'toc-title'}</div>
|
749
730
|
#{outline doc}
|
750
731
|
</div>)
|
751
|
-
|
752
|
-
|
753
|
-
|
732
|
+
else
|
733
|
+
toc = ''
|
734
|
+
end
|
754
735
|
|
755
|
-
|
736
|
+
%(<div id="preamble">
|
756
737
|
<div class="sectionbody">
|
757
738
|
#{node.content}
|
758
739
|
</div>#{toc}
|
759
740
|
</div>)
|
760
|
-
|
741
|
+
end
|
761
742
|
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
743
|
+
def quote node
|
744
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
745
|
+
classes = ['quoteblock', node.role].compact
|
746
|
+
class_attribute = %( class="#{classes.join ' '}")
|
747
|
+
title_element = node.title? ? %(\n<div class="title">#{node.title}</div>) : ''
|
748
|
+
attribution = (node.attr? 'attribution') ? (node.attr 'attribution') : nil
|
749
|
+
citetitle = (node.attr? 'citetitle') ? (node.attr 'citetitle') : nil
|
750
|
+
if attribution || citetitle
|
751
|
+
cite_element = citetitle ? %(<cite>#{citetitle}</cite>) : ''
|
752
|
+
attribution_text = attribution ? %(— #{attribution}#{citetitle ? "<br#{@void_element_slash}>\n" : ''}) : ''
|
753
|
+
attribution_element = %(\n<div class="attribution">\n#{attribution_text}#{cite_element}\n</div>)
|
754
|
+
else
|
755
|
+
attribution_element = ''
|
756
|
+
end
|
776
757
|
|
777
|
-
|
758
|
+
%(<div#{id_attribute}#{class_attribute}>#{title_element}
|
778
759
|
<blockquote>
|
779
760
|
#{node.content}
|
780
761
|
</blockquote>#{attribution_element}
|
781
762
|
</div>)
|
782
|
-
|
763
|
+
end
|
783
764
|
|
784
|
-
|
785
|
-
|
786
|
-
|
765
|
+
def thematic_break node
|
766
|
+
%(<hr#{@void_element_slash}>)
|
767
|
+
end
|
787
768
|
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
769
|
+
def sidebar node
|
770
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
771
|
+
title_element = node.title? ? %(<div class="title">#{node.title}</div>\n) : ''
|
772
|
+
%(<div#{id_attribute} class="sidebarblock#{(role = node.role) ? " #{role}" : ''}">
|
792
773
|
<div class="content">
|
793
774
|
#{title_element}#{node.content}
|
794
775
|
</div>
|
795
776
|
</div>)
|
777
|
+
end
|
778
|
+
|
779
|
+
def table node
|
780
|
+
result = []
|
781
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
782
|
+
classes = ['tableblock', %(frame-#{node.attr 'frame', 'all', 'table-frame'}), %(grid-#{node.attr 'grid', 'all', 'table-grid'})]
|
783
|
+
if (stripes = node.attr 'stripes', nil, 'table-stripes')
|
784
|
+
classes << %(stripes-#{stripes})
|
796
785
|
end
|
786
|
+
styles = []
|
787
|
+
if (autowidth = node.option? 'autowidth') && !(node.attr? 'width')
|
788
|
+
classes << 'fit-content'
|
789
|
+
elsif (tablewidth = node.attr 'tablepcwidth') == 100
|
790
|
+
classes << 'stretch'
|
791
|
+
else
|
792
|
+
styles << %(width: #{tablewidth}%;)
|
793
|
+
end
|
794
|
+
classes << (node.attr 'float') if node.attr? 'float'
|
795
|
+
if (role = node.role)
|
796
|
+
classes << role
|
797
|
+
end
|
798
|
+
class_attribute = %( class="#{classes.join ' '}")
|
799
|
+
style_attribute = styles.empty? ? '' : %( style="#{styles.join ' '}")
|
797
800
|
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
styles = []
|
806
|
-
if (autowidth = node.attributes['autowidth-option']) && !(node.attr? 'width', nil, false)
|
807
|
-
classes << 'fit-content'
|
808
|
-
elsif (tablewidth = node.attr 'tablepcwidth') == 100
|
809
|
-
classes << 'stretch'
|
801
|
+
result << %(<table#{id_attribute}#{class_attribute}#{style_attribute}>)
|
802
|
+
result << %(<caption class="title">#{node.captioned_title}</caption>) if node.title?
|
803
|
+
if (node.attr 'rowcount') > 0
|
804
|
+
slash = @void_element_slash
|
805
|
+
result << '<colgroup>'
|
806
|
+
if autowidth
|
807
|
+
result += (Array.new node.columns.size, %(<col#{slash}>))
|
810
808
|
else
|
811
|
-
|
812
|
-
|
813
|
-
classes << (node.attr 'float') if node.attr? 'float'
|
814
|
-
if (role = node.role)
|
815
|
-
classes << role
|
816
|
-
end
|
817
|
-
class_attribute = %( class="#{classes.join ' '}")
|
818
|
-
style_attribute = styles.empty? ? '' : %( style="#{styles.join ' '}")
|
819
|
-
|
820
|
-
result << %(<table#{id_attribute}#{class_attribute}#{style_attribute}>)
|
821
|
-
result << %(<caption class="title">#{node.captioned_title}</caption>) if node.title?
|
822
|
-
if (node.attr 'rowcount') > 0
|
823
|
-
slash = @void_element_slash
|
824
|
-
result << '<colgroup>'
|
825
|
-
if autowidth
|
826
|
-
result += (Array.new node.columns.size, %(<col#{slash}>))
|
827
|
-
else
|
828
|
-
node.columns.each do |col|
|
829
|
-
result << (col.attributes['autowidth-option'] ? %(<col#{slash}>) : %(<col style="width: #{col.attr 'colpcwidth'}%;"#{slash}>))
|
830
|
-
end
|
809
|
+
node.columns.each do |col|
|
810
|
+
result << ((col.option? 'autowidth') ? %(<col#{slash}>) : %(<col style="width: #{col.attr 'colpcwidth'}%;"#{slash}>))
|
831
811
|
end
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
812
|
+
end
|
813
|
+
result << '</colgroup>'
|
814
|
+
node.rows.to_h.each do |tsec, rows|
|
815
|
+
next if rows.empty?
|
816
|
+
result << %(<t#{tsec}>)
|
817
|
+
rows.each do |row|
|
818
|
+
result << '<tr>'
|
819
|
+
row.each do |cell|
|
820
|
+
if tsec == :head
|
821
|
+
cell_content = cell.text
|
822
|
+
else
|
823
|
+
case cell.style
|
824
|
+
when :asciidoc
|
825
|
+
cell_content = %(<div class="content">#{cell.content}</div>)
|
826
|
+
when :literal
|
827
|
+
cell_content = %(<div class="literal"><pre>#{cell.text}</pre></div>)
|
841
828
|
else
|
842
|
-
|
843
|
-
when :asciidoc
|
844
|
-
cell_content = %(<div class="content">#{cell.content}</div>)
|
845
|
-
when :verse
|
846
|
-
cell_content = %(<div class="verse">#{cell.text}</div>)
|
847
|
-
when :literal
|
848
|
-
cell_content = %(<div class="literal"><pre>#{cell.text}</pre></div>)
|
849
|
-
else
|
850
|
-
cell_content = (cell_content = cell.content).empty? ? '' : %(<p class="tableblock">#{cell_content.join '</p>
|
829
|
+
cell_content = (cell_content = cell.content).empty? ? '' : %(<p class="tableblock">#{cell_content.join '</p>
|
851
830
|
<p class="tableblock">'}</p>)
|
852
|
-
end
|
853
831
|
end
|
854
|
-
|
855
|
-
cell_tag_name = (tsec == :head || cell.style == :header ? 'th' : 'td')
|
856
|
-
cell_class_attribute = %( class="tableblock halign-#{cell.attr 'halign'} valign-#{cell.attr 'valign'}")
|
857
|
-
cell_colspan_attribute = cell.colspan ? %( colspan="#{cell.colspan}") : ''
|
858
|
-
cell_rowspan_attribute = cell.rowspan ? %( rowspan="#{cell.rowspan}") : ''
|
859
|
-
cell_style_attribute = (node.document.attr? 'cellbgcolor') ? %( style="background-color: #{node.document.attr 'cellbgcolor'};") : ''
|
860
|
-
result << %(<#{cell_tag_name}#{cell_class_attribute}#{cell_colspan_attribute}#{cell_rowspan_attribute}#{cell_style_attribute}>#{cell_content}</#{cell_tag_name}>)
|
861
832
|
end
|
862
|
-
|
833
|
+
|
834
|
+
cell_tag_name = (tsec == :head || cell.style == :header ? 'th' : 'td')
|
835
|
+
cell_class_attribute = %( class="tableblock halign-#{cell.attr 'halign'} valign-#{cell.attr 'valign'}")
|
836
|
+
cell_colspan_attribute = cell.colspan ? %( colspan="#{cell.colspan}") : ''
|
837
|
+
cell_rowspan_attribute = cell.rowspan ? %( rowspan="#{cell.rowspan}") : ''
|
838
|
+
cell_style_attribute = (node.document.attr? 'cellbgcolor') ? %( style="background-color: #{node.document.attr 'cellbgcolor'};") : ''
|
839
|
+
result << %(<#{cell_tag_name}#{cell_class_attribute}#{cell_colspan_attribute}#{cell_rowspan_attribute}#{cell_style_attribute}>#{cell_content}</#{cell_tag_name}>)
|
863
840
|
end
|
864
|
-
result <<
|
841
|
+
result << '</tr>'
|
865
842
|
end
|
843
|
+
result << %(</t#{tsec}>)
|
866
844
|
end
|
867
|
-
result << '</table>'
|
868
|
-
result.join LF
|
869
845
|
end
|
846
|
+
result << '</table>'
|
847
|
+
result.join LF
|
848
|
+
end
|
870
849
|
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
850
|
+
def toc node
|
851
|
+
unless (doc = node.document).attr?('toc-placement', 'macro') && doc.sections? && (doc.attr? 'toc')
|
852
|
+
return '<!-- toc disabled -->'
|
853
|
+
end
|
875
854
|
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
855
|
+
if node.id
|
856
|
+
id_attr = %( id="#{node.id}")
|
857
|
+
title_id_attr = %( id="#{node.id}title")
|
858
|
+
else
|
859
|
+
id_attr = ' id="toc"'
|
860
|
+
title_id_attr = ' id="toctitle"'
|
861
|
+
end
|
862
|
+
title = node.title? ? node.title : (doc.attr 'toc-title')
|
863
|
+
levels = (node.attr? 'levels') ? (node.attr 'levels').to_i : nil
|
864
|
+
role = node.role? ? node.role : (doc.attr 'toc-class', 'toc')
|
886
865
|
|
887
|
-
|
866
|
+
%(<div#{id_attr} class="#{role}">
|
888
867
|
<div#{title_id_attr} class="title">#{title}</div>
|
889
|
-
#{outline doc, :
|
868
|
+
#{outline doc, toclevels: levels}
|
890
869
|
</div>)
|
891
|
-
|
870
|
+
end
|
892
871
|
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
else
|
906
|
-
marker_checked = '<input type="checkbox" data-item-complete="1" checked> '
|
907
|
-
marker_unchecked = '<input type="checkbox" data-item-complete="0"> '
|
908
|
-
end
|
872
|
+
def ulist node
|
873
|
+
result = []
|
874
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
875
|
+
div_classes = ['ulist', node.style, node.role].compact
|
876
|
+
marker_checked = marker_unchecked = ''
|
877
|
+
if (checklist = node.option? 'checklist')
|
878
|
+
div_classes.unshift div_classes.shift, 'checklist'
|
879
|
+
ul_class_attribute = ' class="checklist"'
|
880
|
+
if node.option? 'interactive'
|
881
|
+
if @xml_mode
|
882
|
+
marker_checked = '<input type="checkbox" data-item-complete="1" checked="checked"/> '
|
883
|
+
marker_unchecked = '<input type="checkbox" data-item-complete="0"/> '
|
909
884
|
else
|
910
|
-
|
911
|
-
|
912
|
-
marker_unchecked = '<i class="fa fa-square-o"></i> '
|
913
|
-
else
|
914
|
-
marker_checked = '✓ '
|
915
|
-
marker_unchecked = '❏ '
|
916
|
-
end
|
885
|
+
marker_checked = '<input type="checkbox" data-item-complete="1" checked> '
|
886
|
+
marker_unchecked = '<input type="checkbox" data-item-complete="0"> '
|
917
887
|
end
|
888
|
+
elsif node.document.attr? 'icons', 'font'
|
889
|
+
marker_checked = '<i class="fa fa-check-square-o"></i> '
|
890
|
+
marker_unchecked = '<i class="fa fa-square-o"></i> '
|
918
891
|
else
|
919
|
-
|
892
|
+
marker_checked = '✓ '
|
893
|
+
marker_unchecked = '❏ '
|
920
894
|
end
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
895
|
+
else
|
896
|
+
ul_class_attribute = node.style ? %( class="#{node.style}") : ''
|
897
|
+
end
|
898
|
+
result << %(<div#{id_attribute} class="#{div_classes.join ' '}">)
|
899
|
+
result << %(<div class="title">#{node.title}</div>) if node.title?
|
900
|
+
result << %(<ul#{ul_class_attribute}>)
|
901
|
+
|
902
|
+
node.items.each do |item|
|
903
|
+
if item.id
|
904
|
+
result << %(<li id="#{item.id}"#{item.role ? %[ class="#{item.role}"] : ''}>)
|
905
|
+
elsif item.role
|
906
|
+
result << %(<li class="#{item.role}">)
|
907
|
+
else
|
926
908
|
result << '<li>'
|
927
|
-
if checklist && (item.attr? 'checkbox')
|
928
|
-
result << %(<p>#{(item.attr? 'checked') ? marker_checked : marker_unchecked}#{item.text}</p>)
|
929
|
-
else
|
930
|
-
result << %(<p>#{item.text}</p>)
|
931
|
-
end
|
932
|
-
result << item.content if item.blocks?
|
933
|
-
result << '</li>'
|
934
909
|
end
|
935
|
-
|
936
|
-
|
937
|
-
result << '</div>'
|
938
|
-
result.join LF
|
939
|
-
end
|
940
|
-
|
941
|
-
def verse node
|
942
|
-
id_attribute = node.id ? %( id="#{node.id}") : ''
|
943
|
-
classes = ['verseblock', node.role].compact
|
944
|
-
class_attribute = %( class="#{classes.join ' '}")
|
945
|
-
title_element = node.title? ? %(\n<div class="title">#{node.title}</div>) : ''
|
946
|
-
attribution = (node.attr? 'attribution') ? (node.attr 'attribution') : nil
|
947
|
-
citetitle = (node.attr? 'citetitle') ? (node.attr 'citetitle') : nil
|
948
|
-
if attribution || citetitle
|
949
|
-
cite_element = citetitle ? %(<cite>#{citetitle}</cite>) : ''
|
950
|
-
attribution_text = attribution ? %(— #{attribution}#{citetitle ? "<br#{@void_element_slash}>\n" : ''}) : ''
|
951
|
-
attribution_element = %(\n<div class="attribution">\n#{attribution_text}#{cite_element}\n</div>)
|
910
|
+
if checklist && (item.attr? 'checkbox')
|
911
|
+
result << %(<p>#{(item.attr? 'checked') ? marker_checked : marker_unchecked}#{item.text}</p>)
|
952
912
|
else
|
953
|
-
|
913
|
+
result << %(<p>#{item.text}</p>)
|
954
914
|
end
|
915
|
+
result << item.content if item.blocks?
|
916
|
+
result << '</li>'
|
917
|
+
end
|
955
918
|
|
956
|
-
|
919
|
+
result << '</ul>'
|
920
|
+
result << '</div>'
|
921
|
+
result.join LF
|
922
|
+
end
|
923
|
+
|
924
|
+
def verse node
|
925
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
926
|
+
classes = ['verseblock', node.role].compact
|
927
|
+
class_attribute = %( class="#{classes.join ' '}")
|
928
|
+
title_element = node.title? ? %(\n<div class="title">#{node.title}</div>) : ''
|
929
|
+
attribution = (node.attr? 'attribution') ? (node.attr 'attribution') : nil
|
930
|
+
citetitle = (node.attr? 'citetitle') ? (node.attr 'citetitle') : nil
|
931
|
+
if attribution || citetitle
|
932
|
+
cite_element = citetitle ? %(<cite>#{citetitle}</cite>) : ''
|
933
|
+
attribution_text = attribution ? %(— #{attribution}#{citetitle ? "<br#{@void_element_slash}>\n" : ''}) : ''
|
934
|
+
attribution_element = %(\n<div class="attribution">\n#{attribution_text}#{cite_element}\n</div>)
|
935
|
+
else
|
936
|
+
attribution_element = ''
|
937
|
+
end
|
938
|
+
|
939
|
+
%(<div#{id_attribute}#{class_attribute}>#{title_element}
|
957
940
|
<pre class="content">#{node.content}</pre>#{attribution_element}
|
958
941
|
</div>)
|
959
|
-
|
942
|
+
end
|
960
943
|
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
autoplay_param = ''
|
984
|
-
end
|
985
|
-
loop_param = (node.option? 'loop') ? %(#{delimiter}loop=1) : ''
|
986
|
-
%(<div#{id_attribute}#{class_attribute}>#{title_element}
|
944
|
+
def video node
|
945
|
+
xml = @xml_mode
|
946
|
+
id_attribute = node.id ? %( id="#{node.id}") : ''
|
947
|
+
classes = ['videoblock']
|
948
|
+
classes << (node.attr 'float') if node.attr? 'float'
|
949
|
+
classes << %(text-#{node.attr 'align'}) if node.attr? 'align'
|
950
|
+
classes << node.role if node.role
|
951
|
+
class_attribute = %( class="#{classes.join ' '}")
|
952
|
+
title_element = node.title? ? %(\n<div class="title">#{node.title}</div>) : ''
|
953
|
+
width_attribute = (node.attr? 'width') ? %( width="#{node.attr 'width'}") : ''
|
954
|
+
height_attribute = (node.attr? 'height') ? %( height="#{node.attr 'height'}") : ''
|
955
|
+
case node.attr 'poster'
|
956
|
+
when 'vimeo'
|
957
|
+
unless (asset_uri_scheme = (node.document.attr 'asset-uri-scheme', 'https')).empty?
|
958
|
+
asset_uri_scheme = %(#{asset_uri_scheme}:)
|
959
|
+
end
|
960
|
+
start_anchor = (node.attr? 'start') ? %(#at=#{node.attr 'start'}) : ''
|
961
|
+
delimiter = ['?']
|
962
|
+
autoplay_param = (node.option? 'autoplay') ? %(#{delimiter.pop || '&'}autoplay=1) : ''
|
963
|
+
loop_param = (node.option? 'loop') ? %(#{delimiter.pop || '&'}loop=1) : ''
|
964
|
+
muted_param = (node.option? 'muted') ? %(#{delimiter.pop || '&'}muted=1) : ''
|
965
|
+
%(<div#{id_attribute}#{class_attribute}>#{title_element}
|
987
966
|
<div class="content">
|
988
|
-
<iframe#{width_attribute}#{height_attribute} src="#{asset_uri_scheme}//player.vimeo.com/video/#{node.attr 'target'}#{
|
967
|
+
<iframe#{width_attribute}#{height_attribute} src="#{asset_uri_scheme}//player.vimeo.com/video/#{node.attr 'target'}#{autoplay_param}#{loop_param}#{muted_param}#{start_anchor}" frameborder="0"#{(node.option? 'nofullscreen') ? '' : (_append_boolean_attribute 'allowfullscreen', xml)}></iframe>
|
989
968
|
</div>
|
990
969
|
</div>)
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
970
|
+
when 'youtube'
|
971
|
+
unless (asset_uri_scheme = (node.document.attr 'asset-uri-scheme', 'https')).empty?
|
972
|
+
asset_uri_scheme = %(#{asset_uri_scheme}:)
|
973
|
+
end
|
974
|
+
rel_param_val = (node.option? 'related') ? 1 : 0
|
975
|
+
# NOTE start and end must be seconds (t parameter allows XmYs where X is minutes and Y is seconds)
|
976
|
+
start_param = (node.attr? 'start') ? %(&start=#{node.attr 'start'}) : ''
|
977
|
+
end_param = (node.attr? 'end') ? %(&end=#{node.attr 'end'}) : ''
|
978
|
+
autoplay_param = (node.option? 'autoplay') ? '&autoplay=1' : ''
|
979
|
+
loop_param = (has_loop_param = node.option? 'loop') ? '&loop=1' : ''
|
980
|
+
mute_param = (node.option? 'muted') ? '&mute=1' : ''
|
981
|
+
controls_param = (node.option? 'nocontrols') ? '&controls=0' : ''
|
982
|
+
# cover both ways of controlling fullscreen option
|
983
|
+
if node.option? 'nofullscreen'
|
984
|
+
fs_param = '&fs=0'
|
985
|
+
fs_attribute = ''
|
986
|
+
else
|
987
|
+
fs_param = ''
|
988
|
+
fs_attribute = _append_boolean_attribute 'allowfullscreen', xml
|
989
|
+
end
|
990
|
+
modest_param = (node.option? 'modest') ? '&modestbranding=1' : ''
|
991
|
+
theme_param = (node.attr? 'theme') ? %(&theme=#{node.attr 'theme'}) : ''
|
992
|
+
hl_param = (node.attr? 'lang') ? %(&hl=#{node.attr 'lang'}) : ''
|
993
|
+
|
994
|
+
# parse video_id/list_id syntax where list_id (i.e., playlist) is optional
|
995
|
+
target, list = (node.attr 'target').split '/', 2
|
996
|
+
if (list ||= (node.attr 'list'))
|
997
|
+
list_param = %(&list=#{list})
|
998
|
+
else
|
999
|
+
# parse dynamic playlist syntax: video_id1,video_id2,...
|
1000
|
+
target, playlist = target.split ',', 2
|
1001
|
+
if (playlist ||= (node.attr 'playlist'))
|
1002
|
+
# INFO playlist bar doesn't appear in Firefox unless showinfo=1 and modestbranding=1
|
1003
|
+
list_param = %(&playlist=#{playlist})
|
1018
1004
|
else
|
1019
|
-
#
|
1020
|
-
|
1021
|
-
if (playlist ||= (node.attr 'playlist', nil, false))
|
1022
|
-
# INFO playlist bar doesn't appear in Firefox unless showinfo=1 and modestbranding=1
|
1023
|
-
list_param = %(&playlist=#{playlist})
|
1024
|
-
else
|
1025
|
-
# NOTE for loop to work, playlist must be specified; use VIDEO_ID if there's no explicit playlist
|
1026
|
-
list_param = has_loop_param ? %(&playlist=#{target}) : ''
|
1027
|
-
end
|
1005
|
+
# NOTE for loop to work, playlist must be specified; use VIDEO_ID if there's no explicit playlist
|
1006
|
+
list_param = has_loop_param ? %(&playlist=#{target}) : ''
|
1028
1007
|
end
|
1008
|
+
end
|
1029
1009
|
|
1030
|
-
|
1010
|
+
%(<div#{id_attribute}#{class_attribute}>#{title_element}
|
1031
1011
|
<div class="content">
|
1032
|
-
<iframe#{width_attribute}#{height_attribute} src="#{asset_uri_scheme}//www.youtube.com/embed/#{target}?rel=#{rel_param_val}#{start_param}#{end_param}#{autoplay_param}#{loop_param}#{controls_param}#{list_param}#{fs_param}#{modest_param}#{theme_param}#{hl_param}" frameborder="0"#{fs_attribute}></iframe>
|
1012
|
+
<iframe#{width_attribute}#{height_attribute} src="#{asset_uri_scheme}//www.youtube.com/embed/#{target}?rel=#{rel_param_val}#{start_param}#{end_param}#{autoplay_param}#{loop_param}#{mute_param}#{controls_param}#{list_param}#{fs_param}#{modest_param}#{theme_param}#{hl_param}" frameborder="0"#{fs_attribute}></iframe>
|
1033
1013
|
</div>
|
1034
1014
|
</div>)
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1015
|
+
else
|
1016
|
+
poster_attribute = (val = node.attr 'poster').nil_or_empty? ? '' : %( poster="#{node.media_uri val}")
|
1017
|
+
preload_attribute = (val = node.attr 'preload').nil_or_empty? ? '' : %( preload="#{val}")
|
1018
|
+
start_t = node.attr 'start'
|
1019
|
+
end_t = node.attr 'end'
|
1020
|
+
time_anchor = (start_t || end_t) ? %(#t=#{start_t || ''}#{end_t ? ",#{end_t}" : ''}) : ''
|
1021
|
+
%(<div#{id_attribute}#{class_attribute}>#{title_element}
|
1042
1022
|
<div class="content">
|
1043
|
-
<video src="#{node.media_uri(node.attr 'target')}#{time_anchor}"#{width_attribute}#{height_attribute}#{poster_attribute}#{(node.option? 'autoplay') ? (
|
1023
|
+
<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}>
|
1044
1024
|
Your browser does not support the video tag.
|
1045
1025
|
</video>
|
1046
1026
|
</div>
|
1047
1027
|
</div>)
|
1048
|
-
end
|
1049
1028
|
end
|
1029
|
+
end
|
1050
1030
|
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
end
|
1031
|
+
def inline_anchor node
|
1032
|
+
case node.type
|
1033
|
+
when :xref
|
1034
|
+
if (path = node.attributes['path'])
|
1035
|
+
attrs = (_append_link_constraint_attrs node, node.role ? [%( class="#{node.role}")] : []).join
|
1036
|
+
text = node.text || path
|
1037
|
+
else
|
1038
|
+
attrs = node.role ? %( class="#{node.role}") : ''
|
1039
|
+
unless (text = node.text)
|
1040
|
+
refid = node.attributes['refid']
|
1041
|
+
if AbstractNode === (ref = (@refs ||= node.document.catalog[:refs])[refid])
|
1042
|
+
text = (ref.xreftext node.attr('xrefstyle', nil, true)) || %([#{refid}])
|
1043
|
+
else
|
1044
|
+
text = %([#{refid}])
|
1066
1045
|
end
|
1067
1046
|
end
|
1068
|
-
%(<a href="#{node.target}"#{attrs}>#{text}</a>)
|
1069
|
-
when :ref
|
1070
|
-
%(<a id="#{node.id}"></a>)
|
1071
|
-
when :link
|
1072
|
-
attrs = node.id ? [%( id="#{node.id}")] : []
|
1073
|
-
attrs << %( class="#{node.role}") if node.role
|
1074
|
-
attrs << %( title="#{node.attr 'title'}") if node.attr? 'title', nil, false
|
1075
|
-
%(<a href="#{node.target}"#{(append_link_constraint_attrs node, attrs).join}>#{node.text}</a>)
|
1076
|
-
when :bibref
|
1077
|
-
# NOTE technically node.text should be node.reftext, but subs have already been applied to text
|
1078
|
-
%(<a id="#{node.id}"></a>#{node.text})
|
1079
|
-
else
|
1080
|
-
logger.warn %(unknown anchor type: #{node.type.inspect})
|
1081
|
-
nil
|
1082
1047
|
end
|
1048
|
+
%(<a href="#{node.target}"#{attrs}>#{text}</a>)
|
1049
|
+
when :ref
|
1050
|
+
%(<a id="#{node.id}"></a>)
|
1051
|
+
when :link
|
1052
|
+
attrs = node.id ? [%( id="#{node.id}")] : []
|
1053
|
+
attrs << %( class="#{node.role}") if node.role
|
1054
|
+
attrs << %( title="#{node.attr 'title'}") if node.attr? 'title'
|
1055
|
+
%(<a href="#{node.target}"#{(_append_link_constraint_attrs node, attrs).join}>#{node.text}</a>)
|
1056
|
+
when :bibref
|
1057
|
+
%(<a id="#{node.id}"></a>[#{node.reftext || node.id}])
|
1058
|
+
else
|
1059
|
+
logger.warn %(unknown anchor type: #{node.type.inspect})
|
1060
|
+
nil
|
1083
1061
|
end
|
1062
|
+
end
|
1084
1063
|
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1064
|
+
def inline_break node
|
1065
|
+
%(#{node.text}<br#{@void_element_slash}>)
|
1066
|
+
end
|
1088
1067
|
|
1089
|
-
|
1090
|
-
|
1068
|
+
def inline_button node
|
1069
|
+
%(<b class="button">#{node.text}</b>)
|
1070
|
+
end
|
1071
|
+
|
1072
|
+
def inline_callout node
|
1073
|
+
if node.document.attr? 'icons', 'font'
|
1074
|
+
%(<i class="conum" data-value="#{node.text}"></i><b>(#{node.text})</b>)
|
1075
|
+
elsif node.document.attr? 'icons'
|
1076
|
+
src = node.icon_uri("callouts/#{node.text}")
|
1077
|
+
%(<img src="#{src}" alt="#{node.text}"#{@void_element_slash}>)
|
1078
|
+
else
|
1079
|
+
%(#{node.attributes['guard']}<b class="conum">(#{node.text})</b>)
|
1091
1080
|
end
|
1081
|
+
end
|
1092
1082
|
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
src = node.icon_uri("callouts/#{node.text}")
|
1098
|
-
%(<img src="#{src}" alt="#{node.text}"#{@void_element_slash}>)
|
1083
|
+
def inline_footnote node
|
1084
|
+
if (index = node.attr 'index')
|
1085
|
+
if node.type == :xref
|
1086
|
+
%(<sup class="footnoteref">[<a class="footnote" href="#_footnotedef_#{index}" title="View footnote.">#{index}</a>]</sup>)
|
1099
1087
|
else
|
1100
|
-
|
1088
|
+
id_attr = node.id ? %( id="_footnote_#{node.id}") : ''
|
1089
|
+
%(<sup class="footnote"#{id_attr}>[<a id="_footnoteref_#{index}" class="footnote" href="#_footnotedef_#{index}" title="View footnote.">#{index}</a>]</sup>)
|
1101
1090
|
end
|
1091
|
+
elsif node.type == :xref
|
1092
|
+
%(<sup class="footnoteref red" title="Unresolved footnote reference.">[#{node.text}]</sup>)
|
1102
1093
|
end
|
1094
|
+
end
|
1103
1095
|
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
id_attr = node.id ? %( id="_footnote_#{node.id}") : ''
|
1110
|
-
%(<sup class="footnote"#{id_attr}>[<a id="_footnoteref_#{index}" class="footnote" href="#_footnotedef_#{index}" title="View footnote.">#{index}</a>]</sup>)
|
1111
|
-
end
|
1112
|
-
elsif node.type == :xref
|
1113
|
-
%(<sup class="footnoteref red" title="Unresolved footnote reference.">[#{node.text}]</sup>)
|
1096
|
+
def inline_image node
|
1097
|
+
if (type = node.type) == 'icon' && (node.document.attr? 'icons', 'font')
|
1098
|
+
class_attr_val = %(fa fa-#{node.target})
|
1099
|
+
{ 'size' => 'fa-', 'rotate' => 'fa-rotate-', 'flip' => 'fa-flip-' }.each do |key, prefix|
|
1100
|
+
class_attr_val = %(#{class_attr_val} #{prefix}#{node.attr key}) if node.attr? key
|
1114
1101
|
end
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
attrs = ['width', 'height', 'title'].map {|name| (node.attr? name) ? %( #{name}="#{node.attr name}") : '' }.join
|
1130
|
-
if type != 'icon' && ((node.attr? 'format', 'svg', false) || (target.include? '.svg')) &&
|
1131
|
-
node.document.safe < SafeMode::SECURE && ((svg = (node.option? 'inline')) || (obj = (node.option? 'interactive')))
|
1132
|
-
if svg
|
1133
|
-
img = (read_svg_contents node, target) || %(<span class="alt">#{node.alt}</span>)
|
1134
|
-
elsif obj
|
1135
|
-
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>)
|
1136
|
-
img = %(<object type="image/svg+xml" data="#{node.image_uri target}"#{attrs}>#{fallback}</object>)
|
1137
|
-
end
|
1102
|
+
title_attr = (node.attr? 'title') ? %( title="#{node.attr 'title'}") : ''
|
1103
|
+
img = %(<i class="#{class_attr_val}"#{title_attr}></i>)
|
1104
|
+
elsif type == 'icon' && !(node.document.attr? 'icons')
|
1105
|
+
img = %([#{node.alt}])
|
1106
|
+
else
|
1107
|
+
target = node.target
|
1108
|
+
attrs = ['width', 'height', 'title'].map {|name| (node.attr? name) ? %( #{name}="#{node.attr name}") : '' }.join
|
1109
|
+
if type != 'icon' && ((node.attr? 'format', 'svg') || (target.include? '.svg')) &&
|
1110
|
+
node.document.safe < SafeMode::SECURE && ((svg = (node.option? 'inline')) || (obj = (node.option? 'interactive')))
|
1111
|
+
if svg
|
1112
|
+
img = (_read_svg_contents node, target) || %(<span class="alt">#{node.alt}</span>)
|
1113
|
+
elsif obj
|
1114
|
+
fallback = (node.attr? 'fallback') ? %(<img src="#{node.image_uri(node.attr 'fallback')}" alt="#{_encode_attribute_value node.alt}"#{attrs}#{@void_element_slash}>) : %(<span class="alt">#{node.alt}</span>)
|
1115
|
+
img = %(<object type="image/svg+xml" data="#{node.image_uri target}"#{attrs}>#{fallback}</object>)
|
1138
1116
|
end
|
1139
|
-
img ||= %(<img src="#{type == 'icon' ? (node.icon_uri target) : (node.image_uri target)}" alt="#{encode_quotes node.alt}"#{attrs}#{@void_element_slash}>)
|
1140
|
-
end
|
1141
|
-
if node.attr? 'link', nil, false
|
1142
|
-
img = %(<a class="image" href="#{node.attr 'link'}"#{(append_link_constraint_attrs node).join}>#{img}</a>)
|
1143
1117
|
end
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
class_attr_val = %(#{type} #{node.attr 'float'})
|
1118
|
+
img ||= %(<img src="#{type == 'icon' ? (node.icon_uri target) : (node.image_uri target)}" alt="#{_encode_attribute_value node.alt}"#{attrs}#{@void_element_slash}>)
|
1119
|
+
end
|
1120
|
+
if node.attr? 'link'
|
1121
|
+
img = %(<a class="image" href="#{node.attr 'link'}"#{(_append_link_constraint_attrs node).join}>#{img}</a>)
|
1122
|
+
end
|
1123
|
+
if (role = node.role)
|
1124
|
+
if node.attr? 'float'
|
1125
|
+
class_attr_val = %(#{type} #{node.attr 'float'} #{role})
|
1152
1126
|
else
|
1153
|
-
class_attr_val = type
|
1127
|
+
class_attr_val = %(#{type} #{role})
|
1154
1128
|
end
|
1155
|
-
|
1129
|
+
elsif node.attr? 'float'
|
1130
|
+
class_attr_val = %(#{type} #{node.attr 'float'})
|
1131
|
+
else
|
1132
|
+
class_attr_val = type
|
1156
1133
|
end
|
1134
|
+
%(<span class="#{class_attr_val}">#{img}</span>)
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
def inline_indexterm node
|
1138
|
+
node.type == :visible ? node.text : ''
|
1139
|
+
end
|
1157
1140
|
|
1158
|
-
|
1159
|
-
|
1141
|
+
def inline_kbd node
|
1142
|
+
if (keys = node.attr 'keys').size == 1
|
1143
|
+
%(<kbd>#{keys[0]}</kbd>)
|
1144
|
+
else
|
1145
|
+
%(<span class="keyseq"><kbd>#{keys.join '</kbd>+<kbd>'}</kbd></span>)
|
1160
1146
|
end
|
1147
|
+
end
|
1161
1148
|
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1149
|
+
def inline_menu node
|
1150
|
+
caret = (node.document.attr? 'icons', 'font') ? ' <i class="fa fa-angle-right caret"></i> ' : ' <b class="caret">›</b> '
|
1151
|
+
submenu_joiner = %(</b>#{caret}<b class="submenu">)
|
1152
|
+
menu = node.attr 'menu'
|
1153
|
+
if (submenus = node.attr 'submenus').empty?
|
1154
|
+
if (menuitem = node.attr 'menuitem')
|
1155
|
+
%(<span class="menuseq"><b class="menu">#{menu}</b>#{caret}<b class="menuitem">#{menuitem}</b></span>)
|
1165
1156
|
else
|
1166
|
-
%(<
|
1157
|
+
%(<b class="menuref">#{menu}</b>)
|
1167
1158
|
end
|
1159
|
+
else
|
1160
|
+
%(<span class="menuseq"><b class="menu">#{menu}</b>#{caret}<b class="submenu">#{submenus.join submenu_joiner}</b>#{caret}<b class="menuitem">#{node.attr 'menuitem'}</b></span>)
|
1168
1161
|
end
|
1162
|
+
end
|
1169
1163
|
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
if
|
1175
|
-
|
1176
|
-
%(<span class="menuseq"><b class="menu">#{menu}</b>#{caret}<b class="menuitem">#{menuitem}</b></span>)
|
1177
|
-
else
|
1178
|
-
%(<b class="menuref">#{menu}</b>)
|
1179
|
-
end
|
1164
|
+
def inline_quoted node
|
1165
|
+
open, close, tag = QUOTE_TAGS[node.type]
|
1166
|
+
if node.id
|
1167
|
+
class_attr = node.role ? %( class="#{node.role}") : ''
|
1168
|
+
if tag
|
1169
|
+
%(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close})
|
1180
1170
|
else
|
1181
|
-
%(<span
|
1171
|
+
%(<span id="#{node.id}"#{class_attr}>#{open}#{node.text}#{close}</span>)
|
1182
1172
|
end
|
1183
|
-
|
1184
|
-
|
1185
|
-
|
1186
|
-
open, close, is_tag = QUOTE_TAGS[node.type]
|
1187
|
-
class_attr = %( class="#{node.role}") if node.role
|
1188
|
-
id_attr = %( id="#{node.id}") if node.id
|
1189
|
-
if class_attr || id_attr
|
1190
|
-
if is_tag
|
1191
|
-
%(#{open.chop}#{id_attr || ''}#{class_attr || ''}>#{node.text}#{close})
|
1192
|
-
else
|
1193
|
-
%(<span#{id_attr || ''}#{class_attr || ''}>#{open}#{node.text}#{close}</span>)
|
1194
|
-
end
|
1173
|
+
elsif node.role
|
1174
|
+
if tag
|
1175
|
+
%(#{open.chop} class="#{node.role}">#{node.text}#{close})
|
1195
1176
|
else
|
1196
|
-
%(#{open}#{node.text}#{close})
|
1177
|
+
%(<span class="#{node.role}">#{open}#{node.text}#{close}</span>)
|
1197
1178
|
end
|
1179
|
+
else
|
1180
|
+
%(#{open}#{node.text}#{close})
|
1198
1181
|
end
|
1182
|
+
end
|
1199
1183
|
|
1200
|
-
|
1201
|
-
xml ? %( #{name}="#{name}") : %( #{name})
|
1202
|
-
end
|
1184
|
+
private
|
1203
1185
|
|
1204
|
-
|
1205
|
-
|
1186
|
+
def _append_boolean_attribute name, xml
|
1187
|
+
xml ? %( #{name}="#{name}") : %( #{name})
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
def _append_link_constraint_attrs node, attrs = []
|
1191
|
+
rel = 'nofollow' if node.option? 'nofollow'
|
1192
|
+
if (window = node.attributes['window'])
|
1193
|
+
attrs << %( target="#{window}")
|
1194
|
+
attrs << (rel ? %( rel="#{rel} noopener") : ' rel="noopener"') if window == '_blank' || (node.option? 'noopener')
|
1195
|
+
elsif rel
|
1196
|
+
attrs << %( rel="#{rel}")
|
1206
1197
|
end
|
1198
|
+
attrs
|
1199
|
+
end
|
1207
1200
|
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1201
|
+
def _encode_attribute_value val
|
1202
|
+
(val.include? '"') ? (val.gsub '"', '"') : val
|
1203
|
+
end
|
1204
|
+
|
1205
|
+
def _generate_manname_section node
|
1206
|
+
manname_title = node.attr 'manname-title', 'Name'
|
1207
|
+
if (next_section = node.sections[0]) && (next_section_title = next_section.title) == next_section_title.upcase
|
1208
|
+
manname_title = manname_title.upcase
|
1209
|
+
end
|
1210
|
+
manname_id_attr = (manname_id = node.attr 'manname-id') ? %( id="#{manname_id}") : ''
|
1211
|
+
%(<h2#{manname_id_attr}>#{manname_title}</h2>
|
1215
1212
|
<div class="sectionbody">
|
1216
1213
|
<p>#{node.attr 'manname'} - #{node.attr 'manpurpose'}</p>
|
1217
1214
|
</div>)
|
1218
|
-
|
1219
|
-
|
1220
|
-
def append_link_constraint_attrs node, attrs = []
|
1221
|
-
rel = 'nofollow' if node.option? 'nofollow'
|
1222
|
-
if (window = node.attributes['window'])
|
1223
|
-
attrs << %( target="#{window}")
|
1224
|
-
attrs << (rel ? %( rel="#{rel} noopener") : ' rel="noopener"') if window == '_blank' || (node.option? 'noopener')
|
1225
|
-
elsif rel
|
1226
|
-
attrs << %( rel="#{rel}")
|
1227
|
-
end
|
1228
|
-
attrs
|
1229
|
-
end
|
1215
|
+
end
|
1230
1216
|
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
end
|
1217
|
+
def _read_svg_contents node, target
|
1218
|
+
if (svg = node.read_contents target, start: (node.document.attr 'imagesdir'), normalize: true, label: 'SVG')
|
1219
|
+
svg = svg.sub SvgPreambleRx, '' unless svg.start_with? '<svg'
|
1220
|
+
old_start_tag = new_start_tag = nil
|
1221
|
+
# NOTE width, height and style attributes are removed if either width or height is specified
|
1222
|
+
['width', 'height'].each do |dim|
|
1223
|
+
if node.attr? dim
|
1224
|
+
new_start_tag = (old_start_tag = (svg.match SvgStartTagRx)[0]).gsub DimensionAttributeRx, '' unless new_start_tag
|
1225
|
+
# QUESTION should we add px since it's already the default?
|
1226
|
+
new_start_tag = %(#{new_start_tag.chop} #{dim}="#{node.attr dim}px">)
|
1242
1227
|
end
|
1243
|
-
svg = %(#{new_start_tag}#{svg[old_start_tag.length..-1]}) if new_start_tag
|
1244
1228
|
end
|
1245
|
-
svg
|
1229
|
+
svg = %(#{new_start_tag}#{svg[old_start_tag.length..-1]}) if new_start_tag
|
1246
1230
|
end
|
1231
|
+
svg
|
1247
1232
|
end
|
1248
1233
|
end
|
1234
|
+
end
|