aboutsummaryrefslogtreecommitdiff
path: root/_plugins/toc.rb
blob: 80acc829e0bc55c7bdb639f27a754c0601ffa513 (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
63
64
require 'nokogiri'

module Jekyll
	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
end

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