|
| 1 | +# Generate pages from individual records in yml files |
| 2 | +# (c) 2014-2016 Adolfo Villafiorita |
| 3 | +# Distributed under the conditions of the MIT License |
| 4 | + |
| 5 | +module Jekyll |
| 6 | + |
| 7 | + module Sanitizer |
| 8 | + # strip characters and whitespace to create valid filenames, also lowercase |
| 9 | + def sanitize_filename(name) |
| 10 | + if(name.is_a? Integer) |
| 11 | + return name.to_s |
| 12 | + end |
| 13 | + return name.downcase.strip.gsub(' ', '-').gsub(/[^\w.-]/, '') |
| 14 | + end |
| 15 | + end |
| 16 | + |
| 17 | + # this class is used to tell Jekyll to generate a page |
| 18 | + class DataPage < Page |
| 19 | + include Sanitizer |
| 20 | + |
| 21 | + # - site and base are copied from other plugins: to be honest, I am not sure what they do |
| 22 | + # |
| 23 | + # - `index_files` specifies if we want to generate named folders (true) or not (false) |
| 24 | + # - `dir` is the default output directory |
| 25 | + # - `data` is the data defined in `_data.yml` of the record for which we are generating a page |
| 26 | + # - `name` is the key in `data` which determines the output filename |
| 27 | + # - `template` is the name of the template for generating the page |
| 28 | + # - `extension` is the extension for the generated file |
| 29 | + def initialize(site, base, index_files, dir, data, name, template, extension) |
| 30 | + @site = site |
| 31 | + @base = base |
| 32 | + |
| 33 | + # @dir is the directory where we want to output the page |
| 34 | + # @name is the name of the page to generate |
| 35 | + # |
| 36 | + # the value of these variables changes according to whether we |
| 37 | + # want to generate named folders or not |
| 38 | + filename = sanitize_filename(data[name]).to_s |
| 39 | + if index_files |
| 40 | + @dir = dir + (index_files ? "/" + filename + "/" : "") |
| 41 | + @name = "index" + "." + extension.to_s |
| 42 | + else |
| 43 | + @dir = dir |
| 44 | + @name = filename + "." + extension.to_s |
| 45 | + end |
| 46 | + |
| 47 | + self.process(@name) |
| 48 | + self.read_yaml(File.join(base, '_layouts'), template + ".html") |
| 49 | + self.data['title'] = data[name] |
| 50 | + # add all the information defined in _data for the current record to the |
| 51 | + # current page (so that we can access it with liquid tags) |
| 52 | + self.data.merge!(data) |
| 53 | + end |
| 54 | + end |
| 55 | + |
| 56 | + class DataPagesGenerator < Generator |
| 57 | + safe true |
| 58 | + |
| 59 | + # generate loops over _config.yml/page_gen invoking the DataPage |
| 60 | + # constructor for each record for which we want to generate a page |
| 61 | + |
| 62 | + def generate(site) |
| 63 | + # page_gen_dirs determines whether we want to generate index pages |
| 64 | + # (name/index.html) or standard files (name.html). This information |
| 65 | + # is passed to the DataPage constructor, which sets the @dir variable |
| 66 | + # as required by this directive |
| 67 | + index_files = site.config['page_gen-dirs'] == true |
| 68 | + |
| 69 | + # data contains the specification of the data for which we want to generate |
| 70 | + # the pages (look at the README file for its specification) |
| 71 | + data = site.config['page_gen'] |
| 72 | + if data |
| 73 | + data.each do |data_spec| |
| 74 | + template = data_spec['template'] || data_spec['data'] |
| 75 | + name = data_spec['name'] |
| 76 | + dir = data_spec['dir'] || data_spec['data'] |
| 77 | + extension = data_spec['extension'] || "html" |
| 78 | + |
| 79 | + if site.layouts.key? template |
| 80 | + # records is the list of records defined in _data.yml |
| 81 | + # for which we want to generate different pages |
| 82 | + records = nil |
| 83 | + data_spec['data'].split('.').each do |level| |
| 84 | + if records.nil? |
| 85 | + records = site.data[level] |
| 86 | + else |
| 87 | + records = records[level] |
| 88 | + end |
| 89 | + end |
| 90 | + records.each do |record| |
| 91 | + site.pages << DataPage.new(site, site.source, index_files, dir, record, name, template, extension) |
| 92 | + end |
| 93 | + else |
| 94 | + puts "error. could not find template #{template}" if not site.layouts.key? template |
| 95 | + end |
| 96 | + end |
| 97 | + end |
| 98 | + end |
| 99 | + end |
| 100 | + |
| 101 | + module DataPageLinkGenerator |
| 102 | + include Sanitizer |
| 103 | + |
| 104 | + # use it like this: {{input | datapage_url: dir}} |
| 105 | + # to generate a link to a data_page. |
| 106 | + # |
| 107 | + # the filter is smart enough to generate different link styles |
| 108 | + # according to the data_page-dirs directive ... |
| 109 | + # |
| 110 | + # ... however, the filter is not smart enough to support different |
| 111 | + # extensions for filenames. |
| 112 | + # |
| 113 | + # Thus, if you use the `extension` feature of this plugin, you |
| 114 | + # need to generate the links by hand |
| 115 | + def datapage_url(input, dir) |
| 116 | + @gen_dir = Jekyll.configuration({})['page_gen-dirs'] |
| 117 | + if @gen_dir then |
| 118 | + dir + "/" + sanitize_filename(input) + "/index.html" |
| 119 | + else |
| 120 | + dir + "/" + sanitize_filename(input) + ".html" |
| 121 | + end |
| 122 | + end |
| 123 | + end |
| 124 | + |
| 125 | +end |
| 126 | + |
| 127 | +Liquid::Template.register_filter(Jekyll::DataPageLinkGenerator) |
0 commit comments