class Asciidoctor::Converter::Html5Converter

A built-in {Converter} implementation that generates HTML 5 output consistent with the html5 backend from AsciiDoc Python.

Constants

DimensionAttributeRx
QUOTE_TAGS
SvgPreambleRx
SvgStartTagRx

Public Class Methods

new(backend, opts = {}) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 25
def initialize backend, opts = {}
  @xml_mode = opts[:htmlsyntax] == 'xml'
  @void_element_slash = @xml_mode ? '/' : nil
  @stylesheets = Stylesheets.instance
end

Public Instance Methods

admonition(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 354
    def admonition node
      id_attr = node.id ? %Q( id="#{node.id}") : nil
      name = node.attr 'name'
      title_element = node.title? ? %Q(<div class="title">#{node.title}</div>\n) : nil
      caption = if node.document.attr? 'icons'
        if (node.document.attr? 'icons', 'font') && !(node.attr? 'icon')
          %Q(<i class="fa icon-#{name}" title="#{node.caption}"></i>)
        else
          %Q(<img src="#{node.icon_uri name}" alt="#{node.caption}"#{@void_element_slash}>)
        end
      else
        %Q(<div class="title">#{node.caption}</div>)
      end
      %Q(<div#{id_attr} class="admonitionblock #{name}#{(role = node.role) && " #{role}"}">
<table>
<tr>
<td class="icon">
#{caption}
</td>
<td class="content">
#{title_element}#{node.content}
</td>
</tr>
</table>
</div>)
    end
append_boolean_attribute(name, xml) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1146
def append_boolean_attribute name, xml
  xml ? %Q( #{name}="#{name}") : %Q( #{name})
end
audio(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 381
    def audio node
      xml = @xml_mode
      id_attribute = node.id ? %Q( id="#{node.id}") : nil
      classes = ['audioblock', node.role].compact
      class_attribute = %Q( class="#{classes * ' '}")
      title_element = node.title? ? %Q(<div class="title">#{node.captioned_title}</div>\n) : nil
      %Q(<div#{id_attribute}#{class_attribute}>
#{title_element}<div class="content">
<audio src="#{node.media_uri(node.attr 'target')}"#{(node.option? 'autoplay') ? (append_boolean_attribute 'autoplay', xml) : nil}#{(node.option? 'nocontrols') ? nil : (append_boolean_attribute 'controls', xml)}#{(node.option? 'loop') ? (append_boolean_attribute 'loop', xml) : nil}>
Your browser does not support the audio tag.
</audio>
</div>
</div>)
    end
colist(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 396
    def colist node
      result = []
      id_attribute = node.id ? %Q( id="#{node.id}") : nil
      classes = ['colist', node.style, node.role].compact
      class_attribute = %Q( class="#{classes * ' '}")

      result << %Q(<div#{id_attribute}#{class_attribute}>)
      result << %Q(<div class="title">#{node.title}</div>) if node.title?

      if node.document.attr? 'icons'
        result << '<table>'

        font_icons = node.document.attr? 'icons', 'font'
        node.items.each_with_index do |item, i|
          num = i + 1
          num_element = if font_icons
            %Q(<i class="conum" data-value="#{num}"></i><b>#{num}</b>)
          else
            %Q(<img src="#{node.icon_uri "callouts/#{num}"}" alt="#{num}"#{@void_element_slash}>)
          end
          result << %Q(<tr>
<td>#{num_element}</td>
<td>#{item.text}</td>
</tr>)
        end

        result << '</table>'
      else
        result << '<ol>'
        node.items.each do |item|
          result << %Q(<li>
<p>#{item.text}</p>
</li>)
        end
        result << '</ol>'
      end

      result << '</div>'
      result * EOL
    end
dlist(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 437
def dlist node
  result = []
  id_attribute = node.id ? %Q( id="#{node.id}") : nil

  classes = case node.style
  when 'qanda'
    ['qlist', 'qanda', node.role]
  when 'horizontal'
    ['hdlist', node.role]
  else
    ['dlist', node.style, node.role]
  end.compact

  class_attribute = %Q( class="#{classes * ' '}")

  result << %Q(<div#{id_attribute}#{class_attribute}>)
  result << %Q(<div class="title">#{node.title}</div>) if node.title?
  case node.style
  when 'qanda'
    result << '<ol>'
    node.items.each do |terms, dd|
      result << '<li>'
      [*terms].each do |dt|
        result << %Q(<p><em>#{dt.text}</em></p>)
      end
      if dd
        result << %Q(<p>#{dd.text}</p>) if dd.text?
        result << dd.content if dd.blocks?
      end
      result << '</li>'
    end
    result << '</ol>'
  when 'horizontal'
    slash = @void_element_slash
    result << '<table>'
    if (node.attr? 'labelwidth') || (node.attr? 'itemwidth')
      result << '<colgroup>'
      col_style_attribute = (node.attr? 'labelwidth') ? %Q( style="width: #{(node.attr 'labelwidth').chomp '%'}%;") : nil
      result << %Q(<col#{col_style_attribute}#{slash}>)
      col_style_attribute = (node.attr? 'itemwidth') ? %Q( style="width: #{(node.attr 'itemwidth').chomp '%'}%;") : nil
      result << %Q(<col#{col_style_attribute}#{slash}>)
      result << '</colgroup>'
    end
    node.items.each do |terms, dd|
      result << '<tr>'
      result << %Q(<td class="hdlist1#{(node.option? 'strong') ? ' strong' : nil}">)
      terms_array = [*terms]
      last_term = terms_array[-1]
      terms_array.each do |dt|
        result << dt.text
        result << %Q(<br#{slash}>) if dt != last_term
      end
      result << '</td>'
      result << '<td class="hdlist2">'
      if dd
        result << %Q(<p>#{dd.text}</p>) if dd.text?
        result << dd.content if dd.blocks?
      end
      result << '</td>'
      result << '</tr>'
    end
    result << '</table>'
  else
    result << '<dl>'
    dt_style_attribute = node.style ? nil : ' class="hdlist1"'
    node.items.each do |terms, dd|
      [*terms].each do |dt|
        result << %Q(<dt#{dt_style_attribute}>#{dt.text}</dt>)
      end
      if dd
        result << '<dd>'
        result << %Q(<p>#{dd.text}</p>) if dd.text?
        result << dd.content if dd.blocks?
        result << '</dd>'
      end
    end
    result << '</dl>'
  end

  result << '</div>'
  result * EOL
end
document(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 31
    def document node
      result = []
      slash = @void_element_slash
      br = %Q(<br#{slash}>)
      unless (asset_uri_scheme = (node.attr 'asset-uri-scheme', 'https')).empty?
        asset_uri_scheme = %Q(#{asset_uri_scheme}:)
      end
      cdn_base = %Q(#{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 : %Q( lang="#{node.attr 'lang', 'en'}")
      result << %Q(<html#{@xml_mode ? ' xmlns="http://www.w3.org/1999/xhtml"' : nil}#{lang_attribute}>)
      result << %Q(<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 << %Q(<meta name="application-name" content="#{node.attr 'app-name'}"#{slash}>) if node.attr? 'app-name'
      result << %Q(<meta name="description" content="#{node.attr 'description'}"#{slash}>) if node.attr? 'description'
      result << %Q(<meta name="keywords" content="#{node.attr 'keywords'}"#{slash}>) if node.attr? 'keywords'
      result << %Q(<meta name="author" content="#{node.attr 'authors'}"#{slash}>) if node.attr? 'authors'
      result << %Q(<meta name="copyright" content="#{node.attr 'copyright'}"#{slash}>) if node.attr? 'copyright'
      result << %Q(<title>#{node.doctitle :sanitize => true, :use_fallback => true}</title>)

      if DEFAULT_STYLESHEET_KEYS.include?(node.attr 'stylesheet')
        if (webfonts = node.attr 'webfonts')
          result << %Q(<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 << %Q(<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 << %Q(<link rel="stylesheet" href="#{node.normalize_web_path((node.attr 'stylesheet'), (node.attr 'stylesdir', ''))}"#{slash}>)
        else
          result << %Q(<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 << %Q(<link rel="stylesheet" href="#{node.attr 'iconfont-cdn', %[#{cdn_base}/font-awesome/4.6.3/css/font-awesome.min.css]}"#{slash}>)
        else
          iconfont_stylesheet = %Q(#{node.attr 'iconfont-name', 'font-awesome'}.css)
          result << %Q(<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 << %Q(<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 << %Q(<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 << %Q(id="#{node.id}") if node.id
      if (sectioned = node.sections?) && (node.attr? 'toc-class') && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
        body_attrs << %Q(class="#{node.doctype} #{node.attr 'toc-class'} toc-#{node.attr 'toc-position', 'header'}")
      else
        body_attrs << %Q(class="#{node.doctype}")
      end
      body_attrs << %Q(style="max-width: #{node.attr 'max-width'};") if node.attr? 'max-width'
      result << %Q(<body #{body_attrs * ' '}>)

      unless node.noheader
        result << '<div id="header">'
        if node.doctype == 'manpage'
          result << %Q(<h1>#{node.doctitle} Manual Page</h1>)
          if sectioned && (node.attr? 'toc') && (node.attr? 'toc-placement', 'auto')
            result << %Q(<div id="toc" class="#{node.attr 'toc-class', 'toc'}">
<div id="toctitle">#{node.attr 'toc-title'}</div>
#{outline node}
</div>)
          end
          # QUESTION should this h2 have an auto-generated id?
          result << %Q(<h2>#{node.attr 'manname-title'}</h2>
<div class="sectionbody">
<p>#{node.attr 'manname'} - #{node.attr 'manpurpose'}</p>
</div>)
        else
          if node.has_header?
            result << %Q(<h1>#{node.header.title}</h1>) unless node.notitle
            details = []
            if node.attr? 'author'
              details << %Q(<span id="author" class="author">#{node.attr 'author'}</span>#{br})
              if node.attr? 'email'
                details << %Q(<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 << %Q(<span id="author#{idx}" class="author">#{node.attr "author_#{idx}"}</span>#{br})
                  if node.attr? %Q(email_#{idx})
                    details << %Q(<span id="email#{idx}" class="email">#{node.sub_macros(node.attr "email_#{idx}")}</span>#{br})
                  end
                end
              end
            end
            if node.attr? 'revnumber'
              details << %Q(<span id="revnumber">#{((node.attr 'version-label') || '').downcase} #{node.attr 'revnumber'}#{(node.attr? 'revdate') ? ',' : ''}</span>)
            end
            if node.attr? 'revdate'
              details << %Q(<span id="revdate">#{node.attr 'revdate'}</span>)
            end
            if node.attr? 'revremark'
              details << %Q(#{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 << %Q(<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 << %Q(<div id="content">
#{node.content}
</div>)

      if node.footnotes? && !(node.attr? 'nofootnotes')
        result << %Q(<div id="footnotes">
<hr#{slash}>)
        node.footnotes.each do |footnote|
          result << %Q(<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 << %Q(#{node.attr 'version-label'} #{node.attr 'revnumber'}#{br}) if node.attr? 'revnumber'
        result << %Q(#{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

      # Load Javascript at the end of body for performance
      # See http://www.html5rocks.com/en/tutorials/speed/script-loading/
      case highlighter
      when 'highlightjs', 'highlight.js'
        highlightjs_path = node.attr 'highlightjsdir', %Q(#{cdn_base}/highlight.js/8.9.1)
        result << %Q(<link rel="stylesheet" href="#{highlightjs_path}/styles/#{node.attr 'highlightjs-theme', 'github'}.min.css"#{slash}>)
        result << %Q(<script src="#{highlightjs_path}/highlight.min.js"></script>
<script>hljs.initHighlighting()</script>)
      when 'prettify'
        prettify_path = node.attr 'prettifydir', %Q(#{cdn_base}/prettify/r298)
        result << %Q(<link rel="stylesheet" href="#{prettify_path}/#{node.attr 'prettify-theme', 'prettify'}.min.css"#{slash}>)
        result << %Q(<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.empty?
        eqnums_opt = %Q( equationNumbers: { autoNumber: "#{eqnums_val}" } )
        # IMPORTANT inspect calls on delimiter arrays are intentional for JavaScript compat (emulates JSON.stringify)
        result << %Q(<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
embedded(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 248
    def embedded node
      result = []
      if node.doctype == 'manpage'
        # QUESTION should notitle control the manual page title?
        unless node.notitle
          id_attr = node.id ? %Q( id="#{node.id}") : nil
          result << %Q(<h1#{id_attr}>#{node.doctitle} Manual Page</h1>)
        end
        # QUESTION should this h2 have an auto-generated id?
        result << %Q(<h2>#{node.attr 'manname-title'}</h2>
<div class="sectionbody">
<p>#{node.attr 'manname'} - #{node.attr 'manpurpose'}</p>
</div>)
      else
        if node.has_header? && !node.notitle
          id_attr = node.id ? %Q( id="#{node.id}") : nil
          result << %Q(<h1#{id_attr}>#{node.header.title}</h1>)
        end
      end

      if node.sections? && (node.attr? 'toc') && (toc_p = node.attr 'toc-placement') != 'macro' && toc_p != 'preamble'
        result << %Q(<div id="toc" class="toc">
<div id="toctitle">#{node.attr 'toc-title'}</div>
#{outline node}
</div>)
      end

      result << node.content

      if node.footnotes? && !(node.attr? 'nofootnotes')
        result << %Q(<div id="footnotes">
<hr#{@void_element_slash}>)
        node.footnotes.each do |footnote|
          result << %Q(<div class="footnote" id="_footnote_#{footnote.index}">
<a href="#_footnoteref_#{footnote.index}">#{footnote.index}</a>. #{footnote.text}
</div>)
        end
        result << '</div>'
      end

      result * EOL
    end
example(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 520
    def example node
      id_attribute = node.id ? %Q( id="#{node.id}") : nil
      title_element = node.title? ? %Q(<div class="title">#{node.captioned_title}</div>\n) : nil

      %Q(<div#{id_attribute} class="#{(role = node.role) ? ['exampleblock', role] * ' ' : 'exampleblock'}">
#{title_element}<div class="content">
#{node.content}
</div>
</div>)
    end
floating_title(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 531
def floating_title node
  tag_name = %Q(h#{node.level + 1})
  id_attribute = node.id ? %Q( id="#{node.id}") : nil
  classes = [node.style, node.role].compact
  %Q(<#{tag_name}#{id_attribute} class="#{classes * ' '}">#{node.title}</#{tag_name}>)
end
image(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 538
    def image node
      target = node.attr 'target'
      width_attr = (node.attr? 'width') ? %Q( width="#{node.attr 'width'}") : nil
      height_attr = (node.attr? 'height') ? %Q( height="#{node.attr 'height'}") : nil
      if ((node.attr? 'format', 'svg', false) || (target.include? '.svg')) && node.document.safe < SafeMode::SECURE &&
          ((svg = (node.option? 'inline')) || (obj = (node.option? 'interactive')))
        if svg
          img = (read_svg_contents node, target) || %Q(<span class="alt">#{node.attr 'alt'}</span>)
        elsif obj
          fallback = (node.attr? 'fallback') ? %Q(<img src="#{node.image_uri(node.attr 'fallback')}" alt="#{node.attr 'alt'}"#{width_attr}#{height_attr}#{@void_element_slash}>) : %Q(<span class="alt">#{node.attr 'alt'}</span>)
          img = %Q(<object type="image/svg+xml" data="#{node.image_uri target}"#{width_attr}#{height_attr}>#{fallback}</object>)
        end
      end
      img ||= %Q(<img src="#{node.image_uri target}" alt="#{node.attr 'alt'}"#{width_attr}#{height_attr}#{@void_element_slash}>)
      if (link = node.attr 'link')
        img = %Q(<a class="image" href="#{link}">#{img}</a>)
      end
      id_attr = node.id ? %Q( id="#{node.id}") : nil
      classes = ['imageblock', node.role].compact
      class_attr = %Q( class="#{classes * ' '}")
      styles = []
      styles << %Q(text-align: #{node.attr 'align'}) if node.attr? 'align'
      styles << %Q(float: #{node.attr 'float'}) if node.attr? 'float'
      style_attr = styles.empty? ? nil : %Q( style="#{styles * ';'}")
      title_el = node.title? ? %Q(\n<div class="title">#{node.captioned_title}</div>) : nil
      %Q(<div#{id_attr}#{class_attr}#{style_attr}>
<div class="content">
#{img}
</div>#{title_el}
</div>)
    end
inline_anchor(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1014
def inline_anchor node
  target = node.target
  case node.type
  when :xref
    refid = node.attributes['refid'] || target
    # NOTE we lookup text in converter because DocBook doesn't need this logic
    text = node.text || (node.document.references[:ids][refid] || %Q([#{refid}]))
    # FIXME shouldn't target be refid? logic seems confused here
    %Q(<a href="#{target}">#{text}</a>)
  when :ref
    %Q(<a id="#{target}"></a>)
  when :link
    attrs = []
    attrs << %Q( id="#{node.id}") if node.id
    if (role = node.role)
      attrs << %Q( class="#{role}")
    end
    attrs << %Q( title="#{node.attr 'title'}") if node.attr? 'title', nil, false
    attrs << %Q( target="#{node.attr 'window'}") if node.attr? 'window', nil, false
    %Q(<a href="#{target}"#{attrs.join}>#{node.text}</a>)
  when :bibref
    %Q(<a id="#{target}"></a>[#{target}])
  else
    warn %Q(asciidoctor: WARNING: unknown anchor type: #{node.type.inspect})
  end
end
inline_break(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1041
def inline_break node
  %Q(#{node.text}<br#{@void_element_slash}>)
end
inline_button(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1045
def inline_button node
  %Q(<b class="button">#{node.text}</b>)
end
inline_callout(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1049
def inline_callout node
  if node.document.attr? 'icons', 'font'
    %Q(<i class="conum" data-value="#{node.text}"></i><b>(#{node.text})</b>)
  elsif node.document.attr? 'icons'
    src = node.icon_uri("callouts/#{node.text}")
    %Q(<img src="#{src}" alt="#{node.text}"#{@void_element_slash}>)
  else
    %Q(<b class="conum">(#{node.text})</b>)
  end
end
inline_footnote(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1060
def inline_footnote node
  if (index = node.attr 'index')
    if node.type == :xref
      %Q(<sup class="footnoteref">[<a class="footnote" href="#_footnote_#{index}" title="View footnote.">#{index}</a>]</sup>)
    else
      id_attr = node.id ? %Q( id="_footnote_#{node.id}") : nil
      %Q(<sup class="footnote"#{id_attr}>[<a id="_footnoteref_#{index}" class="footnote" href="#_footnote_#{index}" title="View footnote.">#{index}</a>]</sup>)
    end
  elsif node.type == :xref
    %Q(<sup class="footnoteref red" title="Unresolved footnote reference.">[#{node.text}]</sup>)
  end
end
inline_image(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1073
def inline_image node
  if (type = node.type) == 'icon' && (node.document.attr? 'icons', 'font')
    class_attr_val = %Q(fa fa-#{node.target})
    {'size' => 'fa-', 'rotate' => 'fa-rotate-', 'flip' => 'fa-flip-'}.each do |key, prefix|
      class_attr_val = %Q(#{class_attr_val} #{prefix}#{node.attr key}) if node.attr? key
    end
    title_attr = (node.attr? 'title') ? %Q( title="#{node.attr 'title'}") : nil
    img = %Q(<i class="#{class_attr_val}"#{title_attr}></i>)
  elsif type == 'icon' && !(node.document.attr? 'icons')
    img = %Q([#{node.attr 'alt'}])
  else
    target = node.target
    attrs = ['width', 'height', 'title'].map {|name| (node.attr? name) ? %Q( #{name}="#{node.attr name}") : nil }.join
    if type != 'icon' && ((node.attr? 'format', 'svg', false) || (target.include? '.svg')) &&
        node.document.safe < SafeMode::SECURE && ((svg = (node.option? 'inline')) || (obj = (node.option? 'interactive')))
      if svg
        img = (read_svg_contents node, target) || %Q(<span class="alt">#{node.attr 'alt'}</span>)
      elsif obj
        fallback = (node.attr? 'fallback') ? %Q(<img src="#{node.image_uri(node.attr 'fallback')}" alt="#{node.attr 'alt'}"#{attrs}#{@void_element_slash}>) : %Q(<span class="alt">#{node.attr 'alt'}</span>)
        img = %Q(<object type="image/svg+xml" data="#{node.image_uri target}"#{attrs}>#{fallback}</object>)
      end
    end
    img ||= %Q(<img src="#{type == 'icon' ? (node.icon_uri target) : (node.image_uri target)}" alt="#{node.attr 'alt'}"#{attrs}#{@void_element_slash}>)
  end
  if node.attr? 'link'
    window_attr = (node.attr? 'window') ? %Q( target="#{node.attr 'window'}") : nil
    img = %Q(<a class="image" href="#{node.attr 'link'}"#{window_attr}>#{img}</a>)
  end
  class_attr_val = (role = node.role) ? %Q(#{type} #{role}) : type
  style_attr = (node.attr? 'float') ? %Q( style="float: #{node.attr 'float'}") : nil
  %Q(<span class="#{class_attr_val}"#{style_attr}>#{img}</span>)
end
inline_indexterm(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1106
def inline_indexterm node
  node.type == :visible ? node.text : ''
end
inline_kbd(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1110
def inline_kbd node
  if (keys = node.attr 'keys').size == 1
    %Q(<kbd>#{keys[0]}</kbd>)
  else
    key_combo = keys.map {|key| %Q(<kbd>#{key}</kbd>+) }.join.chop
    %Q(<span class="keyseq">#{key_combo}</span>)
  end
end
inline_menu(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1119
def inline_menu node
  menu = node.attr 'menu'
  if !(submenus = node.attr 'submenus').empty?
    submenu_path = submenus.map {|submenu| %Q(<span class="submenu">#{submenu}</span>&#160;&#9656; ) }.join.chop
    %Q(<span class="menuseq"><span class="menu">#{menu}</span>&#160;&#9656; #{submenu_path} <span class="menuitem">#{node.attr 'menuitem'}</span></span>)
  elsif (menuitem = node.attr 'menuitem')
    %Q(<span class="menuseq"><span class="menu">#{menu}</span>&#160;&#9656; <span class="menuitem">#{menuitem}</span></span>)
  else
    %Q(<span class="menu">#{menu}</span>)
  end
end
inline_quoted(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1131
def inline_quoted node
  open, close, is_tag = QUOTE_TAGS[node.type]
  if (role = node.role)
    if is_tag
      quoted_text = %Q(#{open.chop} class="#{role}">#{node.text}#{close})
    else
      quoted_text = %Q(<span class="#{role}">#{open}#{node.text}#{close}</span>)
    end
  else
    quoted_text = %Q(#{open}#{node.text}#{close})
  end

  node.id ? %Q(<a id="#{node.id}"></a>#{quoted_text}) : quoted_text
end
listing(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 570
    def listing node
      nowrap = !(node.document.attr? 'prewrap') || (node.option? 'nowrap')
      if node.style == 'source'
        if (language = node.attr 'language', nil, false)
          code_attrs = %Q( data-lang="#{language}")
        else
          code_attrs = nil
        end
        case node.document.attr 'source-highlighter'
        when 'coderay'
          pre_class = %Q( class="CodeRay highlight#{nowrap ? ' nowrap' : nil}")
        when 'pygments'
          pre_class = %Q( class="pygments highlight#{nowrap ? ' nowrap' : nil}")
        when 'highlightjs', 'highlight.js'
          pre_class = %Q( class="highlightjs highlight#{nowrap ? ' nowrap' : nil}")
          code_attrs = %Q( class="language-#{language}"#{code_attrs}) if language
        when 'prettify'
          pre_class = %Q( class="prettyprint highlight#{nowrap ? ' nowrap' : nil}#{(node.attr? 'linenums') ? ' linenums' : nil}")
          code_attrs = %Q( class="language-#{language}"#{code_attrs}) if language
        when 'html-pipeline'
          pre_class = language ? %Q( lang="#{language}") : nil
          code_attrs = nil
        else
          pre_class = %Q( class="highlight#{nowrap ? ' nowrap' : nil}")
          code_attrs = %Q( class="language-#{language}"#{code_attrs}) if language
        end
        pre_start = %Q(<pre#{pre_class}><code#{code_attrs}>)
        pre_end = '</code></pre>'
      else
        pre_start = %Q(<pre#{nowrap ? ' class="nowrap"' : nil}>)
        pre_end = '</pre>'
      end

      id_attribute = node.id ? %Q( id="#{node.id}") : nil
      title_element = node.title? ? %Q(<div class="title">#{node.captioned_title}</div>\n) : nil
      %Q(<div#{id_attribute} class="listingblock#{(role = node.role) && " #{role}"}">
#{title_element}<div class="content">
#{pre_start}#{node.content}#{pre_end}
</div>
</div>)
    end
literal(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 612
    def literal node
      id_attribute = node.id ? %Q( id="#{node.id}") : nil
      title_element = node.title? ? %Q(<div class="title">#{node.title}</div>\n) : nil
      nowrap = !(node.document.attr? 'prewrap') || (node.option? 'nowrap')
      %Q(<div#{id_attribute} class="literalblock#{(role = node.role) && " #{role}"}">
#{title_element}<div class="content">
<pre#{nowrap ? ' class="nowrap"' : nil}>#{node.content}</pre>
</div>
</div>)
    end
olist(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 639
def olist node
  result = []
  id_attribute = node.id ? %Q( id="#{node.id}") : nil
  classes = ['olist', node.style, node.role].compact
  class_attribute = %Q( class="#{classes * ' '}")

  result << %Q(<div#{id_attribute}#{class_attribute}>)
  result << %Q(<div class="title">#{node.title}</div>) if node.title?

  type_attribute = (keyword = node.list_marker_keyword) ? %Q( type="#{keyword}") : nil
  start_attribute = (node.attr? 'start') ? %Q( start="#{node.attr 'start'}") : nil
  reversed_attribute = (node.option? 'reversed') ? (append_boolean_attribute 'reversed', @xml_mode) : nil
  result << %Q(<ol class="#{node.style}"#{type_attribute}#{start_attribute}#{reversed_attribute}>)

  node.items.each do |item|
    result << '<li>'
    result << %Q(<p>#{item.text}</p>)
    result << item.content if item.blocks?
    result << '</li>'
  end

  result << '</ol>'
  result << '</div>'
  result * EOL
end
open(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 665
    def open node
      if (style = node.style) == 'abstract'
        if node.parent == node.document && node.document.doctype == 'book'
          warn 'asciidoctor: WARNING: abstract block cannot be used in a document without a title when doctype is book. Excluding block content.'
          ''
        else
          id_attr = node.id ? %Q( id="#{node.id}") : nil
          title_el = node.title? ? %Q(<div class="title">#{node.title}</div>\n) : nil
          %Q(<div#{id_attr} class="quoteblock abstract#{(role = node.role) && " #{role}"}">
#{title_el}<blockquote>
#{node.content}
</blockquote>
</div>)
        end
      elsif style == 'partintro' && (node.level > 0 || node.parent.context != :section || node.document.doctype != 'book')
        warn 'asciidoctor: ERROR: partintro block can only be used when doctype is book and it\s a child of a book part. Excluding block content.'
        ''
      else
          id_attr = node.id ? %Q( id="#{node.id}") : nil
          title_el = node.title? ? %Q(<div class="title">#{node.title}</div>\n) : nil
        %Q(<div#{id_attr} class="openblock#{style && style != 'open' ? " #{style}" : ''}#{(role = node.role) && " #{role}"}">
#{title_el}<div class="content">
#{node.content}
</div>
</div>)
      end
    end
outline(node, opts = {}) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 291
def outline node, opts = {}
  return unless node.sections?
  sectnumlevels = opts[:sectnumlevels] || (node.document.attr 'sectnumlevels', 3).to_i
  toclevels = opts[:toclevels] || (node.document.attr 'toclevels', 2).to_i
  result = []
  sections = node.sections
  # FIXME the level for special sections should be set correctly in the model
  # slevel will only be 0 if we have a book doctype with parts
  slevel = (first_section = sections[0]).level
  slevel = 1 if slevel == 0 && first_section.special
  result << %Q(<ul class="sectlevel#{slevel}">)
  sections.each do |section|
    section_num = (section.numbered && !section.caption && section.level <= sectnumlevels) ? %Q(#{section.sectnum} ) : nil
    if section.level < toclevels && (child_toc_level = outline section, :toclevels => toclevels, :secnumlevels => sectnumlevels)
      result << %Q(<li><a href="##{section.id}">#{section_num}#{section.captioned_title}</a>)
      result << child_toc_level
      result << '</li>'
    else
      result << %Q(<li><a href="##{section.id}">#{section_num}#{section.captioned_title}</a></li>)
    end
  end
  result << '</ul>'
  result * EOL
end
page_break(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 693
def page_break node
  '<div style="page-break-after: always;"></div>'
end
paragraph(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 697
    def paragraph node
      class_attribute = node.role ? %Q(class="paragraph #{node.role}") : 'class="paragraph"'
      attributes = node.id ? %Q(id="#{node.id}" #{class_attribute}) : class_attribute

      if node.title?
        %Q(<div #{attributes}>
<div class="title">#{node.title}</div>
<p>#{node.content}</p>
</div>)
      else
        %Q(<div #{attributes}>
<p>#{node.content}</p>
</div>)
      end
    end
preamble(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 713
    def preamble node
      if (doc = node.document).attr?('toc-placement', 'preamble') && doc.sections? && (doc.attr? 'toc')
        toc = %Q(
<div id="toc" class="#{doc.attr 'toc-class', 'toc'}">
<div id="toctitle">#{doc.attr 'toc-title'}</div>
#{outline doc}
</div>)
      else
        toc = nil
      end

      %Q(<div id="preamble">
<div class="sectionbody">
#{node.content}
</div>#{toc}
</div>)
    end
quote(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 731
    def quote node
      id_attribute = node.id ? %Q( id="#{node.id}") : nil
      classes = ['quoteblock', node.role].compact
      class_attribute = %Q( class="#{classes * ' '}")
      title_element = node.title? ? %Q(\n<div class="title">#{node.title}</div>) : nil
      attribution = (node.attr? 'attribution') ? (node.attr 'attribution') : nil
      citetitle = (node.attr? 'citetitle') ? (node.attr 'citetitle') : nil
      if attribution || citetitle
        cite_element = citetitle ? %Q(<cite>#{citetitle}</cite>) : nil
        attribution_text = attribution ? %Q(&#8212; #{attribution}#{citetitle ? "<br#{@void_element_slash}>\n" : nil}) : nil
        attribution_element = %Q(\n<div class="attribution">\n#{attribution_text}#{cite_element}\n</div>)
      else
        attribution_element = nil
      end

      %Q(<div#{id_attribute}#{class_attribute}>#{title_element}
<blockquote>
#{node.content}
</blockquote>#{attribution_element}
</div>)
    end
read_svg_contents(node, target) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 1150
def read_svg_contents node, target
  if (svg = node.read_contents target, :start => (node.document.attr 'imagesdir'), :normalize => true, :label => 'SVG')
    svg = svg.sub SvgPreambleRx, '' unless svg.start_with? '<svg'
    old_start_tag = new_start_tag = nil
    # NOTE width, height and style attributes are removed if either width or height is specified
    ['width', 'height'].each do |dim|
      if node.attr? dim
        new_start_tag = (old_start_tag = (svg.match SvgStartTagRx)[0]).gsub DimensionAttributeRx, '' unless new_start_tag
        # QUESTION should we add px since it's already the default?
        new_start_tag = %Q(#{new_start_tag.chop} #{dim}="#{node.attr dim}px">)
      end
    end
    svg = %Q(#{new_start_tag}#{svg[old_start_tag.length..-1]}) if new_start_tag
  end
  svg
end
section(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 316
    def section node
      slevel = node.level
      # QUESTION should the check for slevel be done in section?
      slevel = 1 if slevel == 0 && node.special
      htag = %Q(h#{slevel + 1})
      id_attr = anchor = link_start = link_end = nil
      if node.id
        id_attr = %Q( id="#{id = node.id}")
        if (doc = node.document).attr? 'sectanchors'
          anchor = %Q(<a class="anchor" href="##{id}"></a>)
          # possible idea - anchor icons GitHub-style
          #if doc.attr? 'icons', 'font'
          #  anchor = %(<a class="anchor" href="##{id}"><i class="fa fa-anchor"></i></a>)
          #else
          #  anchor = %(<a class="anchor" href="##{id}"></a>)
          #end
        end
        if doc.attr? 'sectlinks'
          link_start = %Q(<a class="link" href="##{id}">)
          link_end = '</a>'
        end
      end

      if slevel == 0
        %Q(<h1#{id_attr} class="sect0">#{anchor}#{link_start}#{node.title}#{link_end}</h1>
#{node.content})
      else
        class_attr = (role = node.role) ? %Q( class="sect#{slevel} #{role}") : %Q( class="sect#{slevel}")
        sectnum = if node.numbered && !node.caption && slevel <= (node.document.attr 'sectnumlevels', 3).to_i
          %Q(#{node.sectnum} )
        end
        %Q(<div#{class_attr}>
<#{htag}#{id_attr}>#{anchor}#{link_start}#{sectnum}#{node.captioned_title}#{link_end}</#{htag}>
#{slevel == 1 ? %[<div class="sectionbody">\n#{node.content}\n</div>] : node.content}
</div>)
      end
    end
sidebar(node) click to toggle source
stem(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 623
    def stem node
      id_attribute = node.id ? %Q( id="#{node.id}") : nil
      title_element = node.title? ? %Q(<div class="title">#{node.title}</div>\n) : nil
      open, close = BLOCK_MATH_DELIMITERS[node.style.to_sym]

      unless ((equation = node.content).start_with? open) && (equation.end_with? close)
        equation = %Q(#{open}#{equation}#{close})
      end

      %Q(<div#{id_attribute} class="#{(role = node.role) ? ['stemblock', role] * ' ' : 'stemblock'}">
#{title_element}<div class="content">
#{equation}
</div>
</div>)
    end
table(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 767
def table node
  result = []
  id_attribute = node.id ? %Q( id="#{node.id}") : nil
  classes = ['tableblock', %Q(frame-#{node.attr 'frame', 'all'}), %Q(grid-#{node.attr 'grid', 'all'})]
  styles = []
  unless (node.option? 'autowidth') && !(node.attr? 'width', nil, false)
    if node.attr? 'tablepcwidth', 100
      classes << 'spread'
    else
      styles << %Q(width: #{node.attr 'tablepcwidth'}%;)
    end
  end
  if (role = node.role)
    classes << role
  end
  class_attribute = %Q( class="#{classes * ' '}")
  styles << %Q(float: #{node.attr 'float'};) if node.attr? 'float'
  style_attribute = styles.empty? ? nil : %Q( style="#{styles * ' '}")

  result << %Q(<table#{id_attribute}#{class_attribute}#{style_attribute}>)
  result << %Q(<caption class="title">#{node.captioned_title}</caption>) if node.title?
  if (node.attr 'rowcount') > 0
    slash = @void_element_slash
    result << '<colgroup>'
    if node.option? 'autowidth'
      tag = %Q(<col#{slash}>)
      node.columns.size.times do
        result << tag
      end
    else
      node.columns.each do |col|
        result << %Q(<col style="width: #{col.attr 'colpcwidth'}%;"#{slash}>)
      end
    end
    result << '</colgroup>'
    [:head, :foot, :body].select {|tsec| !node.rows[tsec].empty? }.each do |tsec|
      result << %Q(<t#{tsec}>)
      node.rows[tsec].each do |row|
        result << '<tr>'
        row.each do |cell|
          if tsec == :head
            cell_content = cell.text
          else
            case cell.style
            when :asciidoc
              cell_content = %Q(<div>#{cell.content}</div>)
            when :verse
              cell_content = %Q(<div class="verse">#{cell.text}</div>)
            when :literal
              cell_content = %Q(<div class="literal"><pre>#{cell.text}</pre></div>)
            else
              cell_content = ''
              cell.content.each do |text|
                cell_content = %Q(#{cell_content}<p class="tableblock">#{text}</p>)
              end
            end
          end

          cell_tag_name = (tsec == :head || cell.style == :header ? 'th' : 'td')
          cell_class_attribute = %Q( class="tableblock halign-#{cell.attr 'halign'} valign-#{cell.attr 'valign'}")
          cell_colspan_attribute = cell.colspan ? %Q( colspan="#{cell.colspan}") : nil
          cell_rowspan_attribute = cell.rowspan ? %Q( rowspan="#{cell.rowspan}") : nil
          cell_style_attribute = (node.document.attr? 'cellbgcolor') ? %Q( style="background-color: #{node.document.attr 'cellbgcolor'};") : nil
          result << %Q(<#{cell_tag_name}#{cell_class_attribute}#{cell_colspan_attribute}#{cell_rowspan_attribute}#{cell_style_attribute}>#{cell_content}</#{cell_tag_name}>)
        end
        result << '</tr>'
      end
      result << %Q(</t#{tsec}>)
    end
  end
  result << '</table>'
  result * EOL
end
thematic_break(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 753
def thematic_break node
  %Q(<hr#{@void_element_slash}>)
end
toc(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 841
    def toc node
      unless (doc = node.document).attr?('toc-placement', 'macro') && doc.sections? && (doc.attr? 'toc')
        return '<!-- toc disabled -->'
      end

      if node.id
        id_attr = %Q( id="#{node.id}")
        title_id_attr = %Q( id="#{node.id}title")
      else
        id_attr = ' id="toc"'
        title_id_attr = ' id="toctitle"'
      end
      title = node.title? ? node.title : (doc.attr 'toc-title')
      levels = (node.attr? 'levels') ? (node.attr 'levels').to_i : nil
      role = node.role? ? node.role : (doc.attr 'toc-class', 'toc')

      %Q(<div#{id_attr} class="#{role}">
<div#{title_id_attr} class="title">#{title}</div>
#{outline doc, :toclevels => levels}
</div>)
    end
ulist(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 863
def ulist node
  result = []
  id_attribute = node.id ? %Q( id="#{node.id}") : nil
  div_classes = ['ulist', node.style, node.role].compact
  marker_checked = nil
  marker_unchecked = nil
  if (checklist = node.option? 'checklist')
    div_classes.insert 1, 'checklist'
    ul_class_attribute = ' class="checklist"'
    if node.option? 'interactive'
      if @xml_mode
        marker_checked = '<input type="checkbox" data-item-complete="1" checked="checked"/> '
        marker_unchecked = '<input type="checkbox" data-item-complete="0"/> '
      else
        marker_checked = '<input type="checkbox" data-item-complete="1" checked> '
        marker_unchecked = '<input type="checkbox" data-item-complete="0"> '
      end
    else
      if node.document.attr? 'icons', 'font'
        marker_checked = '<i class="fa fa-check-square-o"></i> '
        marker_unchecked = '<i class="fa fa-square-o"></i> '
      else
        marker_checked = '&#10003; '
        marker_unchecked = '&#10063; '
      end
    end
  else
    ul_class_attribute = node.style ? %Q( class="#{node.style}") : nil
  end
  result << %Q(<div#{id_attribute} class="#{div_classes * ' '}">)
  result << %Q(<div class="title">#{node.title}</div>) if node.title?
  result << %Q(<ul#{ul_class_attribute}>)

  node.items.each do |item|
    result << '<li>'
    if checklist && (item.attr? 'checkbox')
      result << %Q(<p>#{(item.attr? 'checked') ? marker_checked : marker_unchecked}#{item.text}</p>)
    else
      result << %Q(<p>#{item.text}</p>)
    end
    result << item.content if item.blocks?
    result << '</li>'
  end

  result << '</ul>'
  result << '</div>'
  result * EOL
end
verse(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 912
    def verse node
      id_attribute = node.id ? %Q( id="#{node.id}") : nil
      classes = ['verseblock', node.role].compact
      class_attribute = %Q( class="#{classes * ' '}")
      title_element = node.title? ? %Q(\n<div class="title">#{node.title}</div>) : nil
      attribution = (node.attr? 'attribution') ? (node.attr 'attribution') : nil
      citetitle = (node.attr? 'citetitle') ? (node.attr 'citetitle') : nil
      if attribution || citetitle
        cite_element = citetitle ? %Q(<cite>#{citetitle}</cite>) : nil
        attribution_text = attribution ? %Q(&#8212; #{attribution}#{citetitle ? "<br#{@void_element_slash}>\n" : nil}) : nil
        attribution_element = %Q(\n<div class="attribution">\n#{attribution_text}#{cite_element}\n</div>)
      else
        attribution_element = nil
      end

      %Q(<div#{id_attribute}#{class_attribute}>#{title_element}
<pre class="content">#{node.content}</pre>#{attribution_element}
</div>)
    end
video(node) click to toggle source
# File lib/asciidoctor/converter/html5.rb, line 932
    def video node
      xml = @xml_mode
      id_attribute = node.id ? %Q( id="#{node.id}") : nil
      classes = ['videoblock', node.role].compact
      class_attribute = %Q( class="#{classes * ' '}")
      title_element = node.title? ? %Q(\n<div class="title">#{node.captioned_title}</div>) : nil
      width_attribute = (node.attr? 'width') ? %Q( width="#{node.attr 'width'}") : nil
      height_attribute = (node.attr? 'height') ? %Q( height="#{node.attr 'height'}") : nil
      case node.attr 'poster'
      when 'vimeo'
        unless (asset_uri_scheme = (node.document.attr 'asset-uri-scheme', 'https')).empty?
          asset_uri_scheme = %Q(#{asset_uri_scheme}:)
        end
        start_anchor = (node.attr? 'start', nil, false) ? %Q(#at=#{node.attr 'start'}) : nil
        delimiter = '?'
        autoplay_param = (node.option? 'autoplay') ? %Q(#{delimiter}autoplay=1) : nil
        delimiter = '&amp;' if autoplay_param
        loop_param = (node.option? 'loop') ? %Q(#{delimiter}loop=1) : nil
        %Q(<div#{id_attribute}#{class_attribute}>#{title_element}
<div class="content">
<iframe#{width_attribute}#{height_attribute} src="#{asset_uri_scheme}//player.vimeo.com/video/#{node.attr 'target'}#{start_anchor}#{autoplay_param}#{loop_param}" frameborder="0"#{(node.option? 'nofullscreen') ? nil : (append_boolean_attribute 'allowfullscreen', xml)}></iframe>
</div>
</div>)
      when 'youtube'
        unless (asset_uri_scheme = (node.document.attr 'asset-uri-scheme', 'https')).empty?
          asset_uri_scheme = %Q(#{asset_uri_scheme}:)
        end
        rel_param_val = (node.option? 'related') ? 1 : 0
        # NOTE start and end must be seconds (t parameter allows XmYs where X is minutes and Y is seconds)
        start_param = (node.attr? 'start', nil, false) ? %Q(&amp;start=#{node.attr 'start'}) : nil
        end_param = (node.attr? 'end', nil, false) ? %Q(&amp;end=#{node.attr 'end'}) : nil
        autoplay_param = (node.option? 'autoplay') ? '&amp;autoplay=1' : nil
        loop_param = (node.option? 'loop') ? '&amp;loop=1' : nil
        controls_param = (node.option? 'nocontrols') ? '&amp;controls=0' : nil
        # cover both ways of controlling fullscreen option
        if node.option? 'nofullscreen'
          fs_param = '&amp;fs=0'
          fs_attribute = nil
        else
          fs_param = nil
          fs_attribute = append_boolean_attribute 'allowfullscreen', xml
        end
        modest_param = (node.option? 'modest') ? '&amp;modestbranding=1' : nil
        theme_param = (node.attr? 'theme', nil, false) ? %Q(&amp;theme=#{node.attr 'theme'}) : nil
        hl_param = (node.attr? 'lang') ? %Q(&amp;hl=#{node.attr 'lang'}) : nil

        # parse video_id/list_id syntax where list_id (i.e., playlist) is optional
        target, list = (node.attr 'target').split '/', 2
        if (list ||= (node.attr 'list', nil, false))
          list_param = %Q(&amp;list=#{list})
        else
          # parse dynamic playlist syntax: video_id1,video_id2,...
          target, playlist = target.split ',', 2
          if (playlist ||= (node.attr 'playlist', nil, false))
            # INFO playlist bar doesn't appear in Firefox unless showinfo=1 and modestbranding=1
            list_param = %Q(&amp;playlist=#{playlist})
          else
            # NOTE for loop to work, playlist must be specified; use VIDEO_ID if there's no explicit playlist
            list_param = loop_param ? %Q(&amp;playlist=#{target}) : nil
          end
        end

        %Q(<div#{id_attribute}#{class_attribute}>#{title_element}
<div class="content">
<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>
</div>
</div>)
      else
        poster_attribute = %Q(#{poster = node.attr 'poster'}).empty? ? nil : %Q( poster="#{node.media_uri poster}")
        start_t = node.attr 'start', nil, false
        end_t = node.attr 'end', nil, false
        time_anchor = (start_t || end_t) ? %Q(#t=#{start_t}#{end_t ? ',' : nil}#{end_t}) : nil
        %Q(<div#{id_attribute}#{class_attribute}>#{title_element}
<div class="content">
<video src="#{node.media_uri(node.attr 'target')}#{time_anchor}"#{width_attribute}#{height_attribute}#{poster_attribute}#{(node.option? 'autoplay') ? (append_boolean_attribute 'autoplay', xml) : nil}#{(node.option? 'nocontrols') ? nil : (append_boolean_attribute 'controls', xml)}#{(node.option? 'loop') ? (append_boolean_attribute 'loop', xml) : nil}>
Your browser does not support the video tag.
</video>
</div>
</div>)
      end
    end