move research website to my server
[web.git] / personal / _plugins / menu.rb
1 module Jekyll
2   module MenuFilter
3     def menu(input, displayurl)
4       def create_menu(pages, base, displayurl)
5         # URLs in `base`, `displayurl`, `cururl` are normalized to remove trailing slashes. This is to be able to distinguish the root of a folder from its children by the number of slashes in the URL.
6         # We need this to treat the root of a folder as a direct child of the parent folder, whereas pages within a subfolder are of course grandchildren.
7         result = Array.new
8         for page in pages
9           cururl = page['url'].chomp('/')
10           # Test if this page is a non-hidden *direct* child of `base`
11           if cururl.start_with?(base) and cururl.count('/') == base.count('/') and (not page['hide'])
12             # figure out CSS class
13             if cururl == displayurl
14               css_class = 'current'
15             elsif cururl.start_with?(displayurl)
16               css_class = 'child'
17             elsif displayurl.start_with?(cururl)
18               css_class = 'parent'
19             else
20               css_class = 'sibling'
21             end
22             # create menu node
23             menu_node = { 'url' => page['url'], 'title' => page['slug'] ? page['slug'] : (page['title'] ? page['title'] : page['url']), 'class' => css_class, 'sort' => page['sort'] ? page['sort'] : 0 }
24             # potentially recurse
25             if (css_class == 'parent' or css_class == 'current')
26               sub_nodes = create_menu(pages, cururl + "/", displayurl)
27               if sub_nodes.size > 0
28                 menu_node['sub'] = sub_nodes
29               end
30               if css_class == 'parent' and sub_nodes.all? { |page| page['class'] == 'sibling' }
31                 # we won't get closer to this URL, it doesn't exist in our page list
32                 menu_node['class'] = 'current'
33                 sub_nodes.each { |page| page['class'] = 'child' }
34               end
35             end
36             # remember the root
37             if base == ""
38               menu_node['class'] += ' root'
39             end
40             # store menu node
41             result.push(menu_node)
42           else
43             #print "Not adding: cur=", cururl, ", base=", base, ", hide=", page['hide'], "\n"
44           end
45         end
46         # sort the result before returning it
47         result.sort_by { |page| [page['sort'], page['url']] }
48       end
49       
50       create_menu(input, "", displayurl.chomp('/'))
51     end
52   end
53 end
54
55 Liquid::Template.register_filter(Jekyll::MenuFilter)