Class: Showoff::Compiler::Glossary

Inherits:
Object
  • Object
show all
Defined in:
lib/showoff/compiler/glossary.rb

Overview

adds glossary processing to the compiler

Class Method Summary collapse

Class Method Details

.generatePage!(doc) ⇒ Nokogiri::HTML::DocumentFragment

Generate and add the glossary page

Parameters:

  • doc (Nokogiri::HTML::DocumentFragment)

    The presentation document

Returns:

  • (Nokogiri::HTML::DocumentFragment)

    The presentation DOM with the glossary page rendered.

See Also:



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# 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) ⇒ Nokogiri::HTML::DocumentFragment

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

Parameters:

  • doc (Nokogiri::HTML::DocumentFragment)

    The slide document

Returns:

  • (Nokogiri::HTML::DocumentFragment)

    The slide DOM with all glossary entries rendered.

See Also:



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 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