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
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
@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
@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
# File lib/asciidoctor/html5s/converter.rb, line 553 def autowidth?(node = self) node.option? :autowidth end
@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
# 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
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
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
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
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
@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
@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
@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
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
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
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
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
@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
@return [String, nil] an URL for the image's link.
# File lib/asciidoctor/html5s/converter.rb, line 457 def image_link @_html5s_image_link ||= case (link = attr(:link)) when 'none', 'false' return when 'self' image_uri(attr(:target)) when nil, '' image_uri(attr(:target)) if document.attr?('html5s-image-default-link', 'self') else link end end
@return [String, nil] a label/title of the image link.
# File lib/asciidoctor/html5s/converter.rb, line 473 def image_link_label if image_uri(attr(:target)) == image_link document.attr('html5s-image-self-link-label', 'Open the image in full size') end end
# File lib/asciidoctor/html5s/converter.rb, line 419 def link_rel rel = [ ('nofollow' if option?('nofollow')), ('noopener' if option?('noopener') || local_attr(:window) == '_blank') ].compact rel.empty? ? nil : rel.join(' ') end
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
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
@return [Logger]
# File lib/asciidoctor/html5s/converter.rb, line 62 def log ::Asciidoctor::LoggerManager.logger end
# File lib/asciidoctor/html5s/converter.rb, line 363 def nowrap? 'nowrap' if !document.attr?(:prewrap) || option?('nowrap') end
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
# File lib/asciidoctor/html5s/converter.rb, line 367 def print_item_content(item) wrap = item.blocks? && !item.blocks.all? { |b| b.is_a? ::Asciidoctor::List } [ (html_tag_if(wrap, :p) { item.text } if item.text?), item.content ].join end
@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
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
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
@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
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
# File lib/asciidoctor/html5s/converter.rb, line 510 def source_lang local_attr :language, false end
@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
# File lib/asciidoctor/html5s/converter.rb, line 557 def stretch? if !autowidth? || local_attr?('width') 'stretch' if attr? :tablepcwidth, 100 end end
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
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
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('&') '?' + str unless str.empty? end
# 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
@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
# 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
@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
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