class Showoff::Compiler::Glossary

adds glossary processing to the compiler

Public Class Methods

generatePage!(doc) click to toggle source

Generate and add the glossary page

@param doc [Nokogiri::HTML::DocumentFragment]

The presentation document

@return [Nokogiri::HTML::DocumentFragment]

The presentation DOM with the glossary page rendered.

@see

https://github.com/puppetlabs/showoff/blob/3f43754c84f97be4284bb34f9bc7c42175d45226/lib/showoff.rb#L770-L810
# File lib/showoff/compiler/glossary.rb, line 86
def self.generatePage!(doc)
    doc.search('.slide.glossary .content').each do |glossary|
      name = (glossary.attr('class').split - ['content', 'glossary']).first
      list = Nokogiri::XML::Node.new('ul', doc)
      list.add_class('glossary terms')
      seen = []

      doc.search('.callout.glossary').each do |item|
        target = (item.attr('class').split - ['callout', 'glossary']).first

        # if the name matches or if we didn't name it to begin with.
        next unless target == name

        # the definition can exist in multiple places, so de-dup it here
        term = item.attr('data-term')
        next if seen.include? term
        seen << term

        # excrutiatingly find the parent slide content and grab the ref
        # in a library less shitty, this would be something like
        # $(this).parent().siblings('.content').attr('ref')
        href = nil
        item.ancestors('.slide').first.traverse do |element|
          next if element['class'].nil?
          next unless element['class'].split.include? 'content'

          href = element.attr('ref').gsub('/', '_')
        end

        text   = item.attr('data-text')
        link   = item.attr('data-target')
        page   = glossary.attr('ref')
        anchor = "#{page}+#{link}"
        next if href.nil? or text.nil? or link.nil?

        entry = Nokogiri::XML::Node.new('li', doc)

        label = Nokogiri::XML::Node.new('a', doc)
        label.add_class('label')
        label.set_attribute('id', anchor)
        label.content = term

        link = Nokogiri::XML::Node.new('a', doc)
        label.add_class('return')
        link.set_attribute('href', "##{href}")
        link.content = '↩'

        entry.add_child(label)
        entry.add_child(Nokogiri::XML::Text.new(text, doc))
        entry.add_child(link)

        list.add_child(entry)
      end

      glossary.add_child(list)
    end

    # now fix all the links to point to the glossary page
    doc.search('a').each do |link|
      next if link['href'].nil?
      next unless link['href'].start_with? 'glossary://'

      href = link['href']
      href.slice!('glossary://')

      parts  = href.split('/')
      target = parts.pop
      name   = parts.pop # either the glossary name or nil

      classes = name.nil? ? ".slide.glossary" : ".slide.glossary.#{name}"
      href    = doc.at("#{classes} .content").attr('ref') rescue nil

      link['href'] = "##{href}+#{target}"
    end

    doc
end
render!(doc) click to toggle source

Scan for glossary links and add definitions. This does not create the glossary page at the end.

@param doc [Nokogiri::HTML::DocumentFragment]

The slide document

@return [Nokogiri::HTML::DocumentFragment]

The slide DOM with all glossary entries rendered.

@see

https://github.com/puppetlabs/showoff/blob/3f43754c84f97be4284bb34f9bc7c42175d45226/lib/showoff.rb#L650-L706
# File lib/showoff/compiler/glossary.rb, line 15
def self.render!(doc)

  # Find all callout style definitions on the slide and add links to the glossary page
  doc.search('.callout.glossary').each do |item|
    next unless item.content =~ /^([^|]+)\|([^:]+):(.*)$/
    item['data-term']   = $1
    item['data-target'] = $2
    item['data-text']   = $3.strip
    item.content        = $3.strip

    glossary = (item.attr('class').split - ['callout', 'glossary']).first
    address  = glossary ? "#{glossary}/#{$2}" : $2

    link = Nokogiri::XML::Node.new('a', doc)
    link.add_class('processed label')
    link.set_attribute('href', "glossary://#{address}")
    link.content = $1

    item.prepend_child(link)
  end

  # Find glossary links and add definitions to the notes
  doc.search('a').each do |link|
    next unless link['href']
    next unless link['href'].start_with? 'glossary://'
    next if link.classes.include? 'processed'

    link.add_class('term')

    term = link.content
    text = link['title']
    href = link['href']

    parts  = href.split('/')
    target = parts.pop
    name   = parts.pop # either the glossary name or nil

    label = link.clone
    label.add_class('label processed')

    definition = Nokogiri::XML::Node.new('p', doc)
    definition.add_class("callout glossary #{name}")
    definition.set_attribute('data-term', term)
    definition.set_attribute('data-text', text)
    definition.set_attribute('data-target', target)
    definition.content = text
    definition.prepend_child(label)

    # @todo this duplication is annoying but it makes it less order dependent
    doc.add_child '<div class="notes-section notes"></div>' if doc.search('div.notes-section.notes').empty?
    doc.add_child '<div class="notes-section handouts"></div>' if doc.search('div.notes-section.handouts').empty?

    [doc.css('div.notes-section.notes'), doc.css('div.notes-section.handouts')].each do |section|
      section.first.add_child(definition.clone)
    end

  end

  doc
end