aboutsummaryrefslogtreecommitdiff
path: root/_plugins/toc.rb
blob: 09ef946db17ea80aacb24c2f18476dac4ff1b333 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
require 'nokogiri'

class TOC < Liquid::Tag
	def render context
		# load HTML into nokogiri
		html = context.registers[:page]['content']
		doc = Nokogiri::HTML(html)

		# enumerate over all h1-4 headings
		@els = doc.css("h1, h2, h3, h4")
		toc = output_toc()
		return '' if toc.empty?
		return '<aside id="toc" class="plainlink">%s</aside>' % [ toc ]
	end

	def output_toc
		# empty toc (this check prevents crash)
		return "" if @els.length == 0

		output = '<ul>'

		current_level = el_level(@els[0])

		while @els.length > 0
			el = @els[0]
			el_next = @els[1]
			level = el_level(el)
			level_next = el_level(el_next || el) # || el to prevent crash on end of list

			if level >= level_next
				output += '<li>'
			else
				output += '<li class="stub"><details>'
				output += '<summary>'
			end

			output += '<a href="#%s">%s</a>' % [ el['id'], el.inner_html ]
			@els.shift()

			if level >= level_next
				output += '</li>'
			else
				output += '</summary>'
				output += output_toc
				output += '</details></li>'
			end

			break if level_next < level
		end

		output += '</ul>'

		return output
	end

	def el_level el
		return Integer(el.name[1..])
	end
end

Liquid::Template.register_tag('toc', TOC)