module Asciidoctor::Html5s::Converter::Helpers

Add custom functions to this module that you want to use in your Slim templates. Within the template you can invoke them as top-level functions just like in Haml.

Constants

CDN_BASE_URI

URIs of external assets.

CURLY_QUOTES
DEFAULT_HIGHLIGHTJS_THEME

Defaults

DEFAULT_LANG
DEFAULT_SECTNUMLEVELS
DEFAULT_TOCLEVELS
FONT_AWESOME_URI
HIGHLIGHTJS_BASE_URI
KATEX_CSS_URI
KATEX_JS_URI
KATEX_RENDER_CODE
VOID_ELEMENTS

Public Instance Methods

abstract_allowed?() click to toggle source

Returns true if an abstract block is allowed in this document type, otherwise prints warning and returns false.

# File lib/asciidoctor/html5s/converter.rb, line 530
  def abstract_allowed?
    if result = (parent == document && document.doctype == 'book')
      log.warn 'asciidoctor: WARNING: abstract block cannot be used in a document
without a title when doctype is book. Excluding block content.'
    end
    !result
  end
admonition_aria() click to toggle source

@return [String, nil] WAI-ARIA role of this admonition.

# File lib/asciidoctor/html5s/converter.rb, line 440
def admonition_aria
  case attr(:name)
  when 'note'
    'note'  # https://www.w3.org/TR/wai-aria/roles#note
  when 'tip'
    'doc-tip'  # https://www.w3.org/TR/dpub-aria-1.0/#doc-tip
  when 'caution', 'important', 'warning'
    'doc-notice'  # https://www.w3.org/TR/dpub-aria-1.0/#doc-notice
  end
end
admonition_aside?() click to toggle source

@return [Boolean] should be this admonition wrapped in aside element?

# File lib/asciidoctor/html5s/converter.rb, line 434
def admonition_aside?
  %w[note tip].include? attr(:name)
end
autowidth?(node = self) click to toggle source
# File lib/asciidoctor/html5s/converter.rb, line 553
def autowidth?(node = self)
  node.option? :autowidth
end
bibref_text() click to toggle source

@return [String, nil] text of the bibref anchor, or nil if not found.

# File lib/asciidoctor/html5s/converter.rb, line 732
def bibref_text
  if ::Asciidoctor::VERSION[0] == '1'
    text
  else  # Asciidoctor >= 2.0.0
    "[#{reftext || id}]"
  end
end
block_with_caption(position = :bottom, attrs = {}) { || ... } click to toggle source
# File lib/asciidoctor/html5s/converter.rb, line 224
def block_with_caption(position = :bottom, attrs = {}, &block)
  if (klass = attrs[:class]).is_a? String
    klass = klass.split(' ')
  end
  attrs[:class] = [klass, role].flatten.uniq
  attrs[:id] = id

  if title.nil_or_empty?
    html_tag :div, attrs, yield
  else
    html_tag :figure, attrs do
      ary = [yield, html_tag(:figcaption) { captioned_title }]
      ary.reverse! if position == :top
      ary.compact.join("\n")
    end
  end
end
block_with_title(attrs = {}, title = @title) { || ... } click to toggle source

Wraps a block in a div element with the specified class and optionally the node's id and role(s). If the node's title is not empty, then a nested div with the class “title” and the title's content is added as well.

@example When @id, @role and @title attributes are set.

= block_with_title :class=>['quote-block', 'center']
  blockquote =content

<section id="myid" class="quote-block center myrole1 myrole2">
  <h6>Block Title</h6>
  <blockquote>Lorem ipsum</blockquote>
</section>

@example When @id, @role and @title attributes are empty.

= block_with_title :class=>'quote-block center', :style=>style_value(float: 'left')
  blockquote =content

<div class="quote-block center" style="float: left;">
  <blockquote>Lorem ipsum</blockquote>
</div>

@example When shorthand style for class attribute is used.

= block_with_title 'quote-block center'
  blockquote =content

<div class="quote-block center">
  <blockquote>Lorem ipsum</blockquote>
</div>

@param attrs [Hash, String] the tag's attributes as Hash),

or the tag's class if it's not a Hash.

@param title [String, nil] the title. @yield The block of Slim/HTML code within the tag (optional). @return [String] a rendered HTML fragment.

# File lib/asciidoctor/html5s/converter.rb, line 205
def block_with_title(attrs = {}, title = @title, &block)
  if (klass = attrs[:class]).is_a? String
    klass = klass.split(' ')
  end
  attrs[:class] = [klass, role].flatten.uniq
  attrs[:id] = id

  if title.nil_or_empty?
    # XXX quick hack
    nested = is_a?(::Asciidoctor::List) &&
        (parent.is_a?(::Asciidoctor::ListItem) || parent.is_a?(::Asciidoctor::List))
    html_tag_if !nested, :div, attrs, yield
  else
    html_tag :section, attrs do
      [html_tag(:h6, {class: 'block-title'}, title), yield].join("\n")
    end
  end
end
callout_list() click to toggle source

Returns the callout list attached to this listing node, or nil if none.

Note: This variable is set by extension {Asciidoctor::Html5s::AttachedColistTreeprocessor}.

@return [Asciidoctor::List, nil]

# File lib/asciidoctor/html5s/converter.rb, line 506
def callout_list
  @html5s_colist
end
capture(&block) click to toggle source

Captures the given block for later yield.

@example Basic capture usage.

- capture
  img src=image_uri
- if title?
  figure.image
    - yield_capture
    figcaption =captioned_title
- else
  - yield_capture

@example Capture with passing parameters.

- capture do |id|
  img src=image_uri
- if title?
  figure id=@id
    - yield_capture
    figcaption =caption
- else
  - yield_capture @id

@see yield_capture

# File lib/asciidoctor/html5s/converter.rb, line 90
def capture(&block)
  @_html5s_capture = block
  nil
end
delimit_stem(equation, type) click to toggle source

Delimite the given equation as a STEM of the specified type.

Note: This is not needed nor used for KaTeX, but keep this for the case user wants to use a different method.

@param equation [String] the equation to delimite. @param type [#to_sym] the type of the STEM renderer (latexmath, or asciimath). @return [String] the delimited equation.

# File lib/asciidoctor/html5s/converter.rb, line 252
def delimit_stem(equation, type)
  if (@_html5s_stem_type ||= document.attr('html5s-force-stem-type'))
    type = @_html5s_stem_type
  end

  if is_a? ::Asciidoctor::Block
    open, close = ::Asciidoctor::BLOCK_MATH_DELIMITERS[type.to_sym]
  else
    open, close = ::Asciidoctor::INLINE_MATH_DELIMITERS[type.to_sym]
  end

  if !equation.start_with?(open) || !equation.end_with?(close)
    equation = [open, equation, close].join
  end
  equation
end
double_quoted(text) click to toggle source

@param text [String] the text to wrap in double quotes. @return [String] quoted text.

# File lib/asciidoctor/html5s/converter.rb, line 759
def double_quoted(text)
  quotes = CURLY_QUOTES[attr(:lang, DEFAULT_LANG, true)]
  "#{quotes[2]}#{text}#{quotes[3]}"
end
footnote_id(index = local_attr(:index)) click to toggle source

@param index [Integer] the footnote's index. @return [String] footnote id to be used in a link.

# File lib/asciidoctor/html5s/converter.rb, line 352
def footnote_id(index = local_attr(:index))
  "_footnote_#{index}"
end
footnoteref_id(index = local_attr(:index)) click to toggle source

@param index (see footnote_id) @return [String] footnoteref id to be used in a link.

# File lib/asciidoctor/html5s/converter.rb, line 359
def footnoteref_id(index = local_attr(:index))
  "_footnoteref_#{index}"
end
formatted_source() click to toggle source

See {Asciidoctor::SyntaxHighlighter#format}.

@return [String, nil] a rendered HTML.

# File lib/asciidoctor/html5s/converter.rb, line 487
def formatted_source
  hl = document.syntax_highlighter or return nil

  opts = { nowrap: nowrap? }
  if hl.highlight?
    opts[:css_mode] = document.attr("#{hl.name}-css", :class).to_sym
    opts[:style] = document.attr("#{hl.name}-style")
  end

  hl.format(self, source_lang, opts)
end
html_meta_if(name, content) click to toggle source

Returns HTML meta tag if the given content is not nil.

@param name [#to_s] the name for the metadata. @param content [#to_s, nil] the value of the metadata, or nil. @return [String, nil] the meta tag, or nil if the content is nil.

# File lib/asciidoctor/html5s/converter.rb, line 634
def html_meta_if(name, content)
  %(<meta name="#{name}" content="#{content}">) if content
end
html_tag(name, attributes = {}, content = nil) { || ... } click to toggle source

Creates an HTML tag with the given name and optionally attributes. Can take a block that will run between the opening and closing tags.

@param name [#to_s] the name of the tag. @param attributes [Hash] (default: {}) @param content [#to_s] the content; nil to call the block. (default: nil). @yield The block of Slim/HTML code within the tag (optional). @return [String] a rendered HTML element.

# File lib/asciidoctor/html5s/converter.rb, line 115
def html_tag(name, attributes = {}, content = nil)
  attrs = attributes.inject([]) do |attrs, (k, v)|
    next attrs if !v || v.nil_or_empty?
    v = v.compact.join(' ') if v.is_a? Array
    attrs << (v == true ? k : %(#{k}="#{v}"))
  end
  attrs_str = attrs.empty? ? '' : ' ' + attrs.join(' ')

  if VOID_ELEMENTS.include? name.to_s
    %(<#{name}#{attrs_str}>)
  else
    content ||= yield if block_given?
    %(<#{name}#{attrs_str}>#{content}</#{name}>)
  end
end
html_tag_if(condition, name, attributes = {}, content = nil) { || ... } click to toggle source

Conditionally wraps a block in an element. If condition is true then it renders the specified tag with optional attributes and the given block inside, otherwise it just renders the block.

For example:

= html_tag_if link?, 'a', {class: 'image', href: (attr :link)}
  img src='./img/tux.png'

will produce:

<a href="http://example.org" class="image">
  <img src="./img/tux.png">
</a>

if link? is truthy, and just

<img src="./img/tux.png">

otherwise.

@param condition [Boolean] the condition to test to determine whether to

render the enclosing tag.

@param name (see html_tag) @param attributes (see html_tag) @param content (see html_tag) @yield (see html_tag) @return [String] a rendered HTML fragment.

# File lib/asciidoctor/html5s/converter.rb, line 161
def html_tag_if(condition, name, attributes = {}, content = nil, &block)
  if condition
    html_tag name, attributes, content, &block
  else
    content || yield
  end
end
icon_fa_classes() click to toggle source

@return [Array] style classes for a Font Awesome icon.

# File lib/asciidoctor/html5s/converter.rb, line 745
def icon_fa_classes
  [ "fa fa-#{target}",
    ("fa-#{attr :size}" if attr? :size),
    ("fa-rotate-#{attr :rotate}" if attr? :rotate),
    ("fa-flip-#{attr :flip}" if attr? :flip)
  ].compact
end
local_attr(name, default_val = nil) click to toggle source

Gets the value of the specified attribute in this node.

This is just an alias for attr method with disabled inherit to make it more clear.

@param name [String, Symbol] the name of the attribute to lookup. @param default_val the value to return if the attribute is not found. @return value of the attribute or default_val if not found.

# File lib/asciidoctor/html5s/converter.rb, line 329
def local_attr(name, default_val = nil)
  attr(name, default_val, false)
end
local_attr?(name, expect_val = nil) click to toggle source

Checks if the attribute is defined on this node, optionally performing a comparison of its value if expect_val is not nil.

This is just an alias for attr? method with disabled inherit to make it more clear.

@param name [String, Symbol] the name of the attribute to lookup. @param default_val the expected value of the attribute. @return [Boolean] whether the attribute exists and, if expect_val is

specified, whether the value of the attribute matches the +expect_val+.
# File lib/asciidoctor/html5s/converter.rb, line 345
def local_attr?(name, expect_val = nil)
  attr?(name, expect_val, false)
end
log() click to toggle source

@return [Logger]

# File lib/asciidoctor/html5s/converter.rb, line 62
def log
  ::Asciidoctor::LoggerManager.logger
end
nowrap?() click to toggle source
# File lib/asciidoctor/html5s/converter.rb, line 363
def nowrap?
  'nowrap' if !document.attr?(:prewrap) || option?('nowrap')
end
partintro_allowed?() click to toggle source

Returns true if a partintro block is allowed in this context, otherwise prints warning and returns false.

# File lib/asciidoctor/html5s/converter.rb, line 541
  def partintro_allowed?
    if result = (level != 0 || parent.context != :section || document.doctype != 'book')
      log.warn "asciidoctor: ERROR: partintro block can only be used when doctype
is book and must be a child of a book part. Excluding block content."
    end
    !result
  end
print_item_content(item) click to toggle source
revdate_iso() click to toggle source

@return [String, nil] the revision date in ISO 8601, or nil if not

available or in invalid format.
# File lib/asciidoctor/html5s/converter.rb, line 621
def revdate_iso
  ::Date.parse(revdate).iso8601 if defined? ::Date
rescue ArgumentError
  nil
end
section_level(sec = self) click to toggle source

Returns corrected section level.

@param sec [Asciidoctor::Section] the section node (default: self). @return [Integer]

# File lib/asciidoctor/html5s/converter.rb, line 378
def section_level(sec = self)
  (sec.level == 0 && sec.special) ? 1 : sec.level
end
section_title(sec = self, drop_anchors: false) click to toggle source

Returns the captioned section's title, optionally numbered.

@param sec [Asciidoctor::Section] the section node (default: self). @param drop_anchors [Boolean] Remove +<a>+ tags from the title? @return [String]

# File lib/asciidoctor/html5s/converter.rb, line 389
def section_title(sec = self, drop_anchors: false)
  title =
    if sec.caption
      sec.captioned_title
    elsif sec.numbered && sec.level <= document.attr(:sectnumlevels, DEFAULT_SECTNUMLEVELS).to_i
      if sec.level < 2 && document.doctype == 'book' && %w[chapter part].include?(sec.sectname)
        signifier = document.attr("#{sec.sectname}-signifier")
        sectnum = sec.sectname == 'part' ? sec.sectnum(nil, ':') : sec.sectnum
        "#{signifier&.+ ' '}#{sectnum} #{sec.title}"
      else
        "#{sec.sectnum} #{sec.title}"
      end
    else
      sec.title
    end

  if drop_anchors && title.include?('<a')
    title.gsub(/<(?:a[^>+]+|\/a)>/, '')
  else
    title
  end
end
single_quoted(text) click to toggle source

@param text [String] the text to wrap in single quotes. @return [String] quoted text.

# File lib/asciidoctor/html5s/converter.rb, line 766
def single_quoted(text)
  quotes = CURLY_QUOTES[attr(:lang, DEFAULT_LANG, true)]
  "#{quotes[0]}#{text}#{quotes[1]}"
end
source_code_class() click to toggle source

This is needed only for Asciidoctor <2.0.0.

# File lib/asciidoctor/html5s/converter.rb, line 515
def source_code_class
  if document.attr? 'source-highlighter', 'highlightjs'
    "language-#{source_lang || 'none'} hljs"
  elsif source_lang
    "language-#{source_lang}"
  end
end
source_lang() click to toggle source
# File lib/asciidoctor/html5s/converter.rb, line 510
def source_lang
  local_attr :language, false
end
stem_lang() click to toggle source

@return [String] language of STEM block or inline node (tex or asciimath).

# File lib/asciidoctor/html5s/converter.rb, line 414
def stem_lang
  value = (inline? ? type : style).to_s
  value == 'latexmath' ? 'tex' : value
end
stretch?() click to toggle source
# File lib/asciidoctor/html5s/converter.rb, line 557
def stretch?
  if !autowidth? || local_attr?('width')
    'stretch' if attr? :tablepcwidth, 100
  end
end
style_value(declarations) click to toggle source

Formats the given hash as CSS declarations for an inline style.

@example

style_value(text_align: 'right', float: 'left')
=> "text-align: right; float: left;"

style_value(text_align: nil, float: 'left')
=> "float: left;"

style_value(width: [90, '%'], height: '50px')
=> "width: 90%; height: 50px;"

style_value(width: ['120px', 'px'])
=> "width: 90px;"

style_value(width: [nil, 'px'])
=> nil

@param declarations [Hash] @return [String, nil]

# File lib/asciidoctor/html5s/converter.rb, line 291
def style_value(declarations)
  decls = []

  declarations.each do |prop, value|
    next if value.nil?

    if value.is_a? Array
      value, unit = value
      next if value.nil?
      value = value.to_s + unit unless value.end_with? unit
    end
    prop = prop.to_s.gsub('_', '-')
    decls << "#{prop}: #{value}"
  end

  decls.empty? ? nil : decls.join('; ') + ';'
end
styles_and_scripts() click to toggle source

Returns formatted style/link and script tags for header.

# File lib/asciidoctor/html5s/converter.rb, line 639
def styles_and_scripts
  scripts = []
  styles = []
  tags = []

  stylesheet = attr :stylesheet
  stylesdir = attr :stylesdir, ''
  default_style = ::Asciidoctor::DEFAULT_STYLESHEET_KEYS.include? stylesheet
  ss = ::Asciidoctor::Stylesheets.instance

  if attr?(:linkcss)
    path = default_style ? ::Asciidoctor::DEFAULT_STYLESHEET_NAME : stylesheet
    styles << { href: [stylesdir, path] }
  elsif default_style
    styles << { text: ss.primary_stylesheet_data }
  else
    styles << { text: read_asset(normalize_system_path(stylesheet, stylesdir), true) }
  end

  if attr? :icons, 'font'
    if attr? 'iconfont-remote'
      styles << { href: attr('iconfont-cdn', FONT_AWESOME_URI) }
    else
      styles << { href: [stylesdir, "#{attr 'iconfont-name', 'font-awesome'}.css"] }
    end
  end

  if attr? 'stem'
    styles << { href: KATEX_CSS_URI }
    scripts << { src: KATEX_JS_URI }
    scripts << { text: KATEX_RENDER_CODE }
  end

  if !defined?(::Asciidoctor::SyntaxHighlighter)  # Asciidoctor <2.0.0
    if attr? 'source-highlighter', 'highlightjs'
      hjs_base = attr :highlightjsdir, HIGHLIGHTJS_BASE_URI
      hjs_theme = attr 'highlightjs-theme', DEFAULT_HIGHLIGHTJS_THEME

      scripts << { src: [hjs_base, 'highlight.min.js'] }
      scripts << { text: 'hljs.initHighlightingOnLoad()' }
      styles  << { href: [hjs_base, "styles/#{hjs_theme}.min.css"] }
    end
  end

  styles.each do |item|
    if item.key?(:text)
      tags << html_tag(:style) { item[:text] }
    else
      tags << html_tag(:link, rel: 'stylesheet', href: urlize(*item[:href]))
    end
  end

  scripts.each do |item|
    if item.key? :text
      tags << html_tag(:script, type: item[:type]) { item[:text] }
    else
      tags << html_tag(:script, type: item[:type], src: urlize(*item[:src]))
    end
  end

  if defined?(::Asciidoctor::SyntaxHighlighter) && (hl = syntax_highlighter)  # Asciidoctor >=2.0.0
    # XXX: We don't care about the declared location and put all to head.
    [:head, :footer].each do |location|
      if hl.docinfo?(location)
        tags << hl.docinfo(location, self, cdn_base_url: CDN_BASE_URI, linkcss: attr?(:linkcss))
      end
    end
  end

  tags.join("\n")
end
url_query(params) click to toggle source

Formats URL query parameters.

# File lib/asciidoctor/html5s/converter.rb, line 605
def url_query(params)
  str = params.map { |k, v|
    next if v.nil? || v.to_s.empty?
    [k, v] * '='
  }.compact.join('&amp;')

  '?' + str unless str.empty?
end
urlize(*segments) click to toggle source
# File lib/asciidoctor/html5s/converter.rb, line 309
def urlize(*segments)
  path = segments * '/'
  if path.start_with? '//'
    @_html5s_uri_scheme ||= document.attr('asset-uri-scheme', 'https')
    path = "#{@_html5s_uri_scheme}:#{path}" unless @_html5s_uri_scheme.empty?
  end
  normalize_web_path path
end
video_iframe?() click to toggle source

@return [Boolean] true if the video should be embedded in an iframe.

# File lib/asciidoctor/html5s/converter.rb, line 568
def video_iframe?
  ['vimeo', 'youtube'].include? attr(:poster)
end
video_uri() click to toggle source
# File lib/asciidoctor/html5s/converter.rb, line 572
def video_uri
  case attr(:poster, '').to_sym
  when :vimeo
    params = {
      autoplay: (1 if option? 'autoplay'),
      loop:     (1 if option? 'loop'),
      muted:    (1 if option? 'muted')
    }
    start_anchor = "#at=#{attr :start}" if attr? :start
    "//player.vimeo.com/video/#{attr :target}#{start_anchor}#{url_query params}"

  when :youtube
    video_id, list_id = attr(:target).split('/', 2)
    params = {
      rel:      0,
      start:    (attr :start),
      end:      (attr :end),
      list:     (attr :list, list_id),
      autoplay: (1 if option? 'autoplay'),
      loop:     (1 if option? 'loop'),
      muted:    (1 if option? 'muted'),
      controls: (0 if option? 'nocontrols')
    }
    "//www.youtube.com/embed/#{video_id}#{url_query params}"
  else
    anchor = [attr(:start), attr(:end)].join(',').chomp(',')
    anchor = '' if anchor == ','  # XXX: https://github.com/opal/opal/issues/1902
    anchor = '#t=' + anchor unless anchor.empty?
    media_uri "#{attr :target}#{anchor}"
  end
end
xref_text() click to toggle source

@return [String] text of the xref anchor.

# File lib/asciidoctor/html5s/converter.rb, line 716
def xref_text
  str =
    if text
      text
    elsif (path = local_attr :path)
      path
    else
      ref = document.catalog[:refs][attr :refid]
      if ref.kind_of? Asciidoctor::AbstractNode
        ref.xreftext(attr(:xrefstyle, nil, true))
      end
    end
  (str || "[#{attr :refid}]").tr_s("\n", ' ')
end
yield_capture(*params) click to toggle source

Yields the captured block (see {#capture}).

@param *params parameters to pass to the block. @return A content of the captured block. @see capture

# File lib/asciidoctor/html5s/converter.rb, line 101
def yield_capture(*params)
  @_html5s_capture.call(*params) if @_html5s_capture
end