Simon Heimlicher

Simon Heimlicher's Homepage

Directory Listing Plugin for Jekyll

This is a liquid plugin that allows displaying an unordered list of pages and directories beneath the directory containing the source file.

Jekyll Plugin directory_listing.rb
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# Title: Directory Listing Plugin for Jekyll
# Author: Simon Heimlicher http://simon.heimlicher.com
# Description: Display list of pages and directories beneath current directory
# Configuration: You can set default title in _config.yml as follows:
#    directory_listing_title: "Contents: "
#    directory_listing_prefix: "Contents of "
#
# Syntax {% directory_listing Title of Listing %}
#
# Example 1:
# {% directory_listing Further reading: %}
#

require 'pathname'

module Jekyll
  class Page
    def source_path
      # File.join(@dir, @name).gsub(/^\/*/,'')
      File.join(@dir, @name).sub(%r{^/*},'')
    end
    def parent
      @dir.sub(%r{^/*},'')
    end
  end
  class IncludeListingTag < Liquid::Tag
    include TemplateWrapper
    def initialize(tag_name, markup, tokens)
      @title = nil
      @file = nil
      if markup.strip =~ /\s*lang:(\w+)/i
        @filetype = $1
        markup = markup.strip.sub(/lang:\w+/i,'')
      end
      if markup.strip =~ /(.*)?(\s+|^)(\/*\S+)/i
        @title = $1 || nil
        @file = $3
      end
      super
    end

    def add_item(page)
      if page.index?
        title = page.parent
      else
        title = page.basename
      end
      # Try to read title from source file
      source_file = File.join(@source,page.source_path)
      if File.exists?(source_file)
        content = File.read(source_file)

        if content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
          content = $POSTMATCH
          begin
            data = YAML.load($1)
          rescue => e
            puts "YAML Exception reading #{name}: #{e.message}"
          end
        end

        if data['title']
          title = data['title']
        end
      else
        puts "File not found: #{source_file}"
      end
      s = "<li><a href=\"/#{page.parent}#{page.url}\">#{title}</a></li>"
    end

    def render(context)
      site = context.registers[:site]
      @source = site.source
      site_pages = context.environments.first['site']['pages']
      @page = context.environments.first['page']
      @title = @page["title"]
      @url = @page["url"]
      @dir = @url.sub(%r{\A/?(.+?)/[^/]*\z},'\1')
      @title ||= (context.registers[:site].config['directory_listing_title'] ||
      context.registers[:site].config['directory_listing_prefix']+@dir || @dir)
      html = '<ul>'
      folders = []
      pages = []
      site_pages.each do |page|
        next unless page.parent && page.parent.match(%r{^#{@dir}(/[A-Za-z][^/]+)?$})
        if page.index?
          relative_dir = page.parent.match(%r{^#{@dir}/([A-Za-z][^/]+)$})
          if relative_dir && relative_dir[1]
            html += self.add_item(page)
          end
        elsif page.parent == @dir
          html += self.add_item(page)
        end
      end
      html += '</ul>'

      safe_wrap(html)
    end
  end
end

Liquid::Template.register_tag('directory_listing', Jekyll::IncludeListingTag)

Comments