def document node
result = []
slash = @void_element_slash
br = %(<br#{slash}>)
unless (asset_uri_scheme = (node.attr 'asset-uri-scheme', 'https')).empty?
asset_uri_scheme = %(#{asset_uri_scheme}:)
end
cdn_base = %(#{asset_uri_scheme}//cdnjs.cloudflare.com/ajax/libs)
linkcss = node.safe >= SafeMode::SECURE || (node.attr? 'linkcss')
result << '<!DOCTYPE html>'
lang_attribute = (node.attr? 'nolang') ? nil : %( lang="#{node.attr 'lang', 'en'}")
result << %(<html#{@xml_mode ? ' xmlns="http://www.w3.org/1999/xhtml"' : nil}#{lang_attribute}>)
result << %(<head>
<meta charset="#{node.attr 'encoding', 'UTF-8'}"#{slash}>
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"#{slash}><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0"#{slash}>
<meta name="generator" content="Asciidoctor #{node.attr 'asciidoctor-version'}"#{slash}>)
result << %(<meta name="application-name" content="#{node.attr 'app-name'}"#{slash}>) if node.attr? 'app-name'
result << %(<meta name="description" content="#{node.attr 'description'}"#{slash}>) if node.attr? 'description'
result << %(<meta name="keywords" content="#{node.attr 'keywords'}"#{slash}>) if node.attr? 'keywords'
result << %(<meta name="author" content="#{node.attr 'authors'}"#{slash}>) if node.attr? 'authors'
result << %(<meta name="copyright" content="#{node.attr 'copyright'}"#{slash}>) if node.attr? 'copyright'
result << %(<title>#{node.doctitle :sanitize => true, :use_fallback => true}</title>)
if DEFAULT_STYLESHEET_KEYS.include?(node.attr 'stylesheet')
if (webfonts = node.attr 'webfonts')
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}>)
end
if linkcss
result << %(<link rel="stylesheet" href="#{node.normalize_web_path DEFAULT_STYLESHEET_NAME, (node.attr 'stylesdir', ''), false}"#{slash}>)
else
result << @stylesheets.embed_primary_stylesheet
end
elsif node.attr? 'stylesheet'
if linkcss
result << %(<link rel="stylesheet" href="#{node.normalize_web_path((node.attr 'stylesheet'), (node.attr 'stylesdir', ''))}"#{slash}>)
else
result << %(<style>
#{node.read_asset node.normalize_system_path((node.attr 'stylesheet'), (node.attr 'stylesdir', '')), :warn_on_failure => true}
</style>)
end
end
if node.attr? 'icons', 'font'
if node.attr? 'iconfont-remote'
result << %(<link rel="stylesheet" href="#{node.attr 'iconfont-cdn', %[#{cdn_base}/font-awesome/4.5.0/css/font-awesome.min.css]}"#{slash}>)
else
iconfont_stylesheet = %(#{node.attr 'iconfont-name', 'font-awesome'}.css)
result << %(<link rel="stylesheet" href="#{node.normalize_web_path iconfont_stylesheet, (node.attr 'stylesdir', ''), false}"#{slash}>)
end
end
case (highlighter = node.attr 'source-highlighter')
when 'coderay'
if (node.attr 'coderay-css', 'class') == 'class'
if linkcss
result << %(<link rel="stylesheet" href="#{node.normalize_web_path @stylesheets.coderay_stylesheet_name, (node.attr 'stylesdir', ''), false}"#{slash}>)
else
result << @stylesheets.embed_coderay_stylesheet
end
end
when 'pygments'
if (node.attr 'pygments-css', 'class') == 'class'
pygments_style = node.attr 'pygments-style'
if linkcss
result << %(<link rel="stylesheet" href="#{node.normalize_web_path @stylesheets.pygments_stylesheet_name(pygments_style), (node.attr 'stylesdir', ''), false}"#{slash}>)
else
result << (@stylesheets.embed_pygments_stylesheet pygments_style)
end
end
end
unless (docinfo_content = node.docinfo).empty?
result << docinfo_content
end
result << '</head>'
body_attrs = []
body_attrs << %(id="#{node.id}") if node.id
if (sectioned = node.sections?) && (node.attr? 'toc-class') && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
body_attrs << %(class="#{node.doctype} #{node.attr 'toc-class'} toc-#{node.attr 'toc-position', 'header'}")
else
body_attrs << %(class="#{node.doctype}")
end
body_attrs << %(style="max-width: #{node.attr 'max-width'};") if node.attr? 'max-width'
result << %(<body #{body_attrs * ' '}>)
unless node.noheader
result << '<div id="header">'
if node.doctype == 'manpage'
result << %(<h1>#{node.doctitle} Manual Page</h1>)
if sectioned && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
result << %(<div id="toc" class="#{node.attr 'toc-class', 'toc'}">
<div id="toctitle">#{node.attr 'toc-title'}</div>
#{outline node}
</div>)
end
result << %(<h2>#{node.attr 'manname-title'}</h2>
<div class="sectionbody">
<p>#{node.attr 'manname'} - #{node.attr 'manpurpose'}</p>
</div>)
else
if node.has_header?
result << %(<h1>#{node.header.title}</h1>) unless node.notitle
details = []
if node.attr? 'author'
details << %(<span id="author" class="author">#{node.attr 'author'}</span>#{br})
if node.attr? 'email'
details << %(<span id="email" class="email">#{node.sub_macros(node.attr 'email')}</span>#{br})
end
if (authorcount = (node.attr 'authorcount').to_i) > 1
(2..authorcount).each do |idx|
details << %(<span id="author#{idx}" class="author">#{node.attr "author_#{idx}"}</span>#{br})
if node.attr? %(email_#{idx})
details << %(<span id="email#{idx}" class="email">#{node.sub_macros(node.attr "email_#{idx}")}</span>#{br})
end
end
end
end
if node.attr? 'revnumber'
details << %(<span id="revnumber">#{((node.attr 'version-label') || '').downcase} #{node.attr 'revnumber'}#{(node.attr? 'revdate') ? ',' : ''}</span>)
end
if node.attr? 'revdate'
details << %(<span id="revdate">#{node.attr 'revdate'}</span>)
end
if node.attr? 'revremark'
details << %(#{br}<span id="revremark">#{node.attr 'revremark'}</span>)
end
unless details.empty?
result << '<div class="details">'
result.concat details
result << '</div>'
end
end
if sectioned && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
result << %(<div id="toc" class="#{node.attr 'toc-class', 'toc'}">
<div id="toctitle">#{node.attr 'toc-title'}</div>
#{outline node}
</div>)
end
end
result << '</div>'
end
result << %(<div id="content">
#{node.content}
</div>)
if node.footnotes? && !(node.attr? 'nofootnotes')
result << %(<div id="footnotes">
<hr#{slash}>)
node.footnotes.each do |footnote|
result << %(<div class="footnote" id="_footnote_#{footnote.index}">
<a href="#_footnoteref_#{footnote.index}">#{footnote.index}</a>. #{footnote.text}
</div>)
end
result << '</div>'
end
unless node.nofooter
result << '<div id="footer">'
result << '<div id="footer-text">'
result << %(#{node.attr 'version-label'} #{node.attr 'revnumber'}#{br}) if node.attr? 'revnumber'
result << %(#{node.attr 'last-update-label'} #{node.attr 'docdatetime'}) if (node.attr? 'last-update-label') && !(node.attr? 'reproducible')
result << '</div>'
result << '</div>'
end
unless (docinfo_content = node.docinfo :footer).empty?
result << docinfo_content
end
case highlighter
when 'highlightjs', 'highlight.js'
highlightjs_path = node.attr 'highlightjsdir', %(#{cdn_base}/highlight.js/8.9.1)
result << %(<link rel="stylesheet" href="#{highlightjs_path}/styles/#{node.attr 'highlightjs-theme', 'github'}.min.css"#{slash}>)
result << %(<script src="#{highlightjs_path}/highlight.min.js"></script>
<script>hljs.initHighlighting()</script>)
when 'prettify'
prettify_path = node.attr 'prettifydir', %(#{cdn_base}/prettify/r298)
result << %(<link rel="stylesheet" href="#{prettify_path}/#{node.attr 'prettify-theme', 'prettify'}.min.css"#{slash}>)
result << %(<script src="#{prettify_path}/prettify.min.js"></script>
<script>prettyPrint()</script>)
end
if node.attr? 'stem'
eqnums_val = node.attr 'eqnums', 'none'
eqnums_val = 'AMS' if eqnums_val == ''
eqnums_opt = %( equationNumbers: { autoNumber: "#{eqnums_val}" } )
result << %(<script type="text/x-mathjax-config">
MathJax.Hub.Config({
messageStyle: "none",
tex2jax: {
inlineMath: [#{INLINE_MATH_DELIMITERS[:latexmath].inspect}],
displayMath: [#{BLOCK_MATH_DELIMITERS[:latexmath].inspect}],
ignoreClass: "nostem|nolatexmath"
},
asciimath2jax: {
delimiters: [#{BLOCK_MATH_DELIMITERS[:asciimath].inspect}],
ignoreClass: "nostem|noasciimath"
},
TeX: {#{eqnums_opt}}
});
</script>
<script src="#{cdn_base}/mathjax/2.6.0/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>)
end
result << '</body>'
result << '</html>'
result * EOL
end