templates/helpers.rb in asciidoctor-revealjs-4.0.1 vs templates/helpers.rb in asciidoctor-revealjs-4.1.0.rc2
- old
+ new
@@ -31,15 +31,15 @@
# Ex: a feature is enabled globally but can be disabled using a data- attribute on individual items
# :revealjs_previewlinks: True
# then link::example.com[Link text, preview=false]
# Here the template must have data-preview-link="false" not just no data-preview-link attribute
def bool_data_attr val
- return false if !attr?(val)
+ return false unless attr?(val)
if attr(val).downcase == 'false' || attr(val) == '0'
- return 'false'
+ 'false'
else
- return true
+ true
end
end
# false needs to be verbatim everything else is a string.
# Calling side isn't responsible for quoting so we are doing it here
@@ -70,38 +70,111 @@
# @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.
#
-
def html_tag(name, attributes = {}, content = nil)
attrs = attributes.inject([]) do |attrs, (k, v)|
- next attrs if !v || v.nil_or_empty?
+ next attrs unless v && (v == true || !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?
+ content ||= (yield if block_given?)
%(<#{name}#{attrs_str}>#{content}</#{name}>)
end
end
+ #
+ # Extracts data- attributes from the attributes.
+ # @param attributes [Hash] (default: {})
+ # @return [Hash] a Hash that contains only data- attributes
+ #
+ def data_attrs(attributes)
+ # key can be an Integer (for positional attributes)
+ attributes.map { |key, value| (key == 'step') ? ['data-fragment-index', value] : [key, value] }
+ .to_h
+ .select { |key, _| key.to_s.start_with?('data-') }
+ end
+
+
+ #
+ # Wrap an inline text in a <span> element if the node contains a role, an id or data- attributes.
+ # @param content [#to_s] the content; +nil+ to call the block. (default: nil).
+ # @return [String] the content or the content wrapped in a <span> element as string
+ #
+ def inline_text_container(content = nil)
+ data_attrs = data_attrs(@attributes)
+ classes = [role, ('fragment' if (option? :step) || (attr? 'step') || (roles.include? 'step'))].compact
+ if !roles.empty? || !data_attrs.empty? || !@id.nil?
+ html_tag('span', { :id => @id, :class => classes }.merge(data_attrs), (content || (yield if block_given?)))
+ else
+ content || (yield if block_given?)
+ end
+ end
+
+
##
# Returns corrected section level.
#
# @param sec [Asciidoctor::Section] the section node (default: self).
# @return [Integer]
#
def section_level(sec = self)
@_section_level ||= (sec.level == 0 && sec.special) ? 1 : sec.level
end
+ ##
+ # Display footnotes per slide
+ #
+ @@slide_footnotes = {}
+ @@section_footnotes = {}
+
+ def slide_footnote(footnote)
+ footnote_parent = footnote.parent
+ # footnotes declared on the section title are processed during the parsing/substitution.
+ # as a result, we need to store them to display them on the right slide/section
+ if footnote_parent.instance_of?(::Asciidoctor::Section)
+ footnote_parent_object_id = footnote_parent.object_id
+ section_footnotes = (@@section_footnotes[footnote_parent_object_id] || [])
+ footnote_index = section_footnotes.length + 1
+ attributes = footnote.attributes.merge({ 'index' => footnote_index })
+ inline_footnote = Asciidoctor::Inline.new(footnote_parent, footnote.context, footnote.text, :attributes => attributes)
+ section_footnotes << Asciidoctor::Document::Footnote.new(inline_footnote.attr(:index), inline_footnote.id, inline_footnote.text)
+ @@section_footnotes[footnote_parent_object_id] = section_footnotes
+ inline_footnote
+ else
+ parent = footnote.parent
+ until parent == nil || parent.instance_of?(::Asciidoctor::Section)
+ parent = parent.parent
+ end
+ # check if there is any footnote attached on the section title
+ section_footnotes = parent != nil ? @@section_footnotes[parent.object_id] || [] : []
+ initial_index = footnote.attr(:index)
+ # reset the footnote numbering to 1 on each slide
+ # make sure that if a footnote is used more than once it will use the same index/number
+ slide_index = (existing_footnote = @@slide_footnotes[initial_index]) ? existing_footnote.index : @@slide_footnotes.length + section_footnotes.length + 1
+ attributes = footnote.attributes.merge({ 'index' => slide_index })
+ inline_footnote = Asciidoctor::Inline.new(footnote_parent, footnote.context, footnote.text, :attributes => attributes)
+ @@slide_footnotes[initial_index] = Asciidoctor::Document::Footnote.new(inline_footnote.attr(:index), inline_footnote.id, inline_footnote.text)
+ inline_footnote
+ end
+ end
+
+ def clear_slide_footnotes
+ @@slide_footnotes = {}
+ end
+
+ def slide_footnotes(section)
+ section_object_id = section.object_id
+ section_footnotes = @@section_footnotes[section_object_id] || []
+ section_footnotes + @@slide_footnotes.values
+ end
##
# Returns the captioned section's title, optionally numbered.
#
# @param sec [Asciidoctor::Section] the section node (default: self).