require 'erb' require 'fileutils' require 'tmpdir' require 'pp' module Manual DIRECTORY_ENTRIES = {} def self.traverse_data(entries, directory_sort = false, paths = [], key_paths = [], &block) entries.map do |entry| entry = entry.dup if entry[:type] == 'directory' entry[:children] = traverse_data(entry[:children], directory_sort, paths + [entry[:name]], key_paths + [entry[:key]], &block) end block_given? ? block.call(entry) : entry end end def self.traverse(path, directory_sort = false, paths = [], key_paths = [], &block) entries = Dir.glob(File.join(path,'*')) entries.sort_by! { |e| File.directory?(e) ? 1 : 0 } if directory_sort entries.map do |entry| is_dir = File.directory?(entry) data = extract_data(is_dir ? "#{entry}.html" : entry) short_title = data['menu_title'] || data['title'] name = entry[/[^\/]+$/] # filename key = name.sub(/^[0-9]+(\-|_)/,'').sub(/\.[^\.]+$/,'') # slug my_paths = paths + [name] my_key_paths = key_paths + [key] url = '/' + my_key_paths.join('/') + '/' without_extension = entry.sub(/\.[^\/\/]+$/,'') h = { name: name, title: data['title'] || key, menu_title: short_title || key, key: key, filename: entry, type: is_dir ? 'directory' : 'file', url: url } if is_dir h.update \ children: traverse(entry, directory_sort, my_paths, my_key_paths, &block) else h.update extension: File.extname(name), has_dir: File.directory?(without_extension) end if is_dir DIRECTORY_ENTRIES[url] = h end block_given? ? block.call(h) : h end.compact end def self.extract_data(filename) if File.exists?(filename) and !File.directory?(filename) and first3 = File.open(filename) { |fd| fd.read(3) } and first3 == '---' blah = filename.sub(/^_manual\//,'') page = Jekyll::Page.new(@site, '_manual', File.dirname(blah), File.basename(blah)) page.data else {} end end class ManualPage < Jekyll::Page def initialize(*args) super end end class ManualGenerator < Jekyll::Generator safe true def generate(site) source = site.config['source'] destination = site.config['destination'] manual_dir = '_manual' # now we need to turn our raw input files into something for jekyll to process # everything is in a directory with it's name and all content is in index.html files # the tmpdir gets removed at the end of this block automatically Dir.mktmpdir do |tmpdir| Manual.traverse manual_dir, true do |entry| output_filename = File.join(tmpdir, entry[:url], "index#{entry[:extension]}") FileUtils.mkdir_p File.dirname(output_filename) next unless entry[:type] == 'file' File.open(output_filename, 'w+') do |f| f << File.read(entry[:filename]) end relative_filename = File.join(entry[:url], "index#{entry[:extension]}") site.pages << Jekyll::Page.new(site, tmpdir, File.dirname(relative_filename), File.basename(relative_filename)) end end end end class ManualChildPageTag < Liquid::Tag def render(context) current = context['page.url'].sub(/[^\/]+$/,'') if entry = DIRECTORY_ENTRIES[current] path = File.join(entry[:filename], '*') entries = entry[:children].map do |child| "