jekyll-datapage_gen-rocha-patch-001

Created Diff never expires
0 removals
211 lines
22 additions
228 lines
# coding: utf-8
# coding: utf-8
# Generate pages from individual records in yml files
# Generate pages from individual records in yml files
# (c) 2014-2020 Adolfo Villafiorita
# (c) 2014-2020 Adolfo Villafiorita
# Distributed under the conditions of the MIT License
# Distributed under the conditions of the MIT License


module Jekyll
module Jekyll


module Sanitizer
module Sanitizer
# strip characters and whitespace to create valid filenames, also lowercase
# strip characters and whitespace to create valid filenames, also lowercase
def sanitize_filename(name)
def sanitize_filename(name)
if(name.is_a? Integer)
if(name.is_a? Integer)
return name.to_s
return name.to_s
end
end
return name.tr(
return name.tr(
"ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÑñÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž",
"ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÑñÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž",
"AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz"
"AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz"
).downcase.strip.gsub(' ', '-').gsub(/[^\w.-]/, '')
).downcase.strip.gsub(' ', '-').gsub(/[^\w.-]/, '')
end
end
end
end
# this class is used to tell Jekyll to generate a page
# this class is used to tell Jekyll to generate a page
class DataPage < Page
class DataPage < Page
include Sanitizer
include Sanitizer
# - site and base are copied from other plugins: to be honest, I am not sure what they do
# - site and base are copied from other plugins: to be honest, I am not sure what they do
#
#
# - `index_files` specifies if we want to generate named folders (true) or not (false)
# - `index_files` specifies if we want to generate named folders (true) or not (false)
# - `dir` is the default output directory
# - `dir` is the default output directory
# - `dir_expr` is an expression for generating the output directory
# - `page_data_prefix` is the prefix used to output the page data
# - `page_data_prefix` is the prefix used to output the page data
# - `data` is the data of the record for which we are generating a page
# - `data` is the data of the record for which we are generating a page
# - `name` is the key in `data` which determines the output filename
# - `name` is the key in `data` which determines the output filename
# - `name_expr` is an expression for generating the output filename
# - `name_expr` is an expression for generating the output filename
# - `title` is the key in `data` which determines the page title
# - `title` is the key in `data` which determines the page title
# - `title_expr` is an expression for generating the page title
# - `title_expr` is an expression for generating the page title
# - `template` is the name of the template for generating the page
# - `template` is the name of the template for generating the page
# - `extension` is the extension for the generated file
# - `extension` is the extension for the generated file
def initialize(site, base, index_files, dir, page_data_prefix, data, name, name_expr, title, title_expr, template, extension, debug)
def initialize(site, base, index_files, dir, dir_expr, page_data_prefix, data, name, name_expr, title, title_expr, template, extension, debug)
@site = site
@site = site
@base = base
@base = base
if debug
if debug
puts "debug (datapage-gen) Record read:"
puts "debug (datapage-gen) Record read:"
puts ">> #{data}"
puts ">> #{data}"
puts "debug (datapage-gen) Configuration variables:"
puts "debug (datapage-gen) Configuration variables:"
[:index_files, :dir, :page_data_prefix, :name, :name_expr, :title, :title_expr, :template, :extension].each do |variable|
[:index_files, :dir, :dir_expr, :page_data_prefix, :name, :name_expr, :title, :title_expr, :template, :extension].each do |variable|
puts ">> #{variable}: #{eval(variable.to_s)}"
puts ">> #{variable}: #{eval(variable.to_s)}"
end
end
end
end
# @dir is the directory where we want to output the page
# @dir is the directory where we want to output the page
# @name is the name of the page to generate
# @name is the name of the page to generate
# @name_expr is an expression for generating the name of the page
# @name_expr is an expression for generating the name of the page
#
#
# the value of these variables changes according to whether we
# the value of these variables changes according to whether we
# want to generate named folders or not
# want to generate named folders or not
if name_expr
if name_expr
record = data
record = data
raw_filename = eval(name_expr)
raw_filename = eval(name_expr)
if raw_filename == nil
if raw_filename == nil
puts "error (datapage-gen). name_expr '#{name_expr}' generated an empty value in record #{data}"
puts "error (datapage-gen). name_expr '#{name_expr}' generated an empty value in record #{data}"
return
return
end
end
puts "debug (datapage-gen). using name_expr: '#{raw_filename}' (sanitized) will be used as the filename" if debug
puts "debug (datapage-gen). using name_expr: '#{raw_filename}' (sanitized) will be used as the filename" if debug
else
else
raw_filename = data[name]
raw_filename = data[name]
if raw_filename == nil
if raw_filename == nil
puts "error (datapage-gen). empty value for field '#{name}' in record #{data}"
puts "error (datapage-gen). empty value for field '#{name}' in record #{data}"
return
return
end
end
puts "debug (datapage-gen). using name field: '#{raw_filename}' (sanitized) will be used as the filename" if debug
puts "debug (datapage-gen). using name field: '#{raw_filename}' (sanitized) will be used as the filename" if debug
end
end
if title_expr
if title_expr
record = data
record = data
raw_title = eval(title_expr)
raw_title = eval(title_expr)
if raw_title == nil
if raw_title == nil
puts "error (datapage-gen). title_expr '#{title_expr}' generated an empty value in record #{data}"
puts "error (datapage-gen). title_expr '#{title_expr}' generated an empty value in record #{data}"
return
return
end
end
puts "debug (datapage-gen). using title_expr: '#{raw_title}' will be used the page title" if debug
puts "debug (datapage-gen). using title_expr: '#{raw_title}' will be used the page title" if debug
else
else
raw_title = data[title]
raw_title = data[title]
if raw_title == nil
if raw_title == nil
raw_title = raw_filename # for backwards compatibility
raw_title = raw_filename # for backwards compatibility
puts "debug (datapage-gen). empty title field: falling back to filename for the page title" if debug
puts "debug (datapage-gen). empty title field: falling back to filename for the page title" if debug
end
end
puts "debug (datapage-gen). will use '#{raw_title}' as the page title" if debug
puts "debug (datapage-gen). will use '#{raw_title}' as the page title" if debug
end
end
filename = sanitize_filename(raw_filename).to_s
filename = sanitize_filename(raw_filename).to_s
@dir = dir + (index_files ? "/" + filename + "/" : "")
# Old option, without dir_expr
# @dir = dir + (index_files ? "/" + filename + "/" : "")

if dir_expr
record = data
raw_dir = eval(dir_expr)
if raw_dir == nil
puts "error (datapage-gen). raw_dir '#{raw_dir}' generated an empty value in record #{data}"
return
end
@dir = raw_dir + (index_files ? "/" + filename + "/" : "")
puts "debug (datapage-gen). using raw_dir: '#{raw_dir}' will be used the directory output" if debug
else
@dir = dir + (index_files ? "/" + filename + "/" : "")
end

@name = (index_files ? "index" : filename) + "." + extension.to_s
@name = (index_files ? "index" : filename) + "." + extension.to_s
self.process(@name)
self.process(@name)
if @site.layouts[template].path.end_with? 'html'
if @site.layouts[template].path.end_with? 'html'
@path = @site.layouts[template].path.dup
@path = @site.layouts[template].path.dup
else
else
@path = File.join(@site.layouts[template].path, @site.layouts[template].name)
@path = File.join(@site.layouts[template].path, @site.layouts[template].name)
end
end
base_path = @site.layouts[template].path
base_path = @site.layouts[template].path
base_path.slice! @site.layouts[template].name
base_path.slice! @site.layouts[template].name
self.read_yaml(base_path, @site.layouts[template].name)
self.read_yaml(base_path, @site.layouts[template].name)
self.data['title'] = raw_title
self.data['title'] = raw_title
# add all the information defined in _data for the current record to the
# add all the information defined in _data for the current record to the
# current page (so that we can access it with liquid tags)
# current page (so that we can access it with liquid tags)
if page_data_prefix
if page_data_prefix
self.data[page_data_prefix] = data
self.data[page_data_prefix] = data
else
else
if data.key?('name')
if data.key?('name')
data['_name'] = data['name']
data['_name'] = data['name']
end
end
self.data.merge!(data)
self.data.merge!(data)
end
end
end
end
end
end
class JekyllDatapageGenerator < Generator
class JekyllDatapageGenerator < Generator
safe true
safe true
# the function =generate= loops over the =_config.yml/page_gen=
# the function =generate= loops over the =_config.yml/page_gen=
# specification, determining what sets of pages have to be generated,
# specification, determining what sets of pages have to be generated,
# reading the data for each set and invoking the =DataPage=
# reading the data for each set and invoking the =DataPage=
# constructor for each record found in the data
# constructor for each record found in the data
def generate(site)
def generate(site)
# page_gen-dirs is a global option which determines whether we want to
# page_gen-dirs is a global option which determines whether we want to
# generate index pages (name/index.html) or HTML files (name.html) for
# generate index pages (name/index.html) or HTML files (name.html) for
# all sets
# all sets
index_files = site.config['page_gen-dirs'] == true
index_files = site.config['page_gen-dirs'] == true
# data contains the specification of all the datasets for which we want
# data contains the specification of all the datasets for which we want
# to generate individual pages (look at the README file for its documentation)
# to generate individual pages (look at the README file for its documentation)
data = site.config['page_gen']
data = site.config['page_gen']
if data
if data
data.each do |data_spec|
data.each do |data_spec|
index_files_for_this_data = data_spec['index_files'] != nil ? data_spec['index_files'] : index_files
index_files_for_this_data = data_spec['index_files'] != nil ? data_spec['index_files'] : index_files
template = data_spec['template'] || data_spec['data']
template = data_spec['template'] || data_spec['data']
name = data_spec['name']
name = data_spec['name']
name_expr = data_spec['name_expr']
name_expr = data_spec['name_expr']
title = data_spec['title']
title = data_spec['title']
title_expr = data_spec['title_expr']
title_expr = data_spec['title_expr']
dir = data_spec['dir'] || data_spec['data']
dir = data_spec['dir'] || data_spec['data']
dir_expr = data_spec['dir_expr']
extension = data_spec['extension'] || "html"
extension = data_spec['extension'] || "html"
page_data_prefix = data_spec['page_data_prefix']
page_data_prefix = data_spec['page_data_prefix']
debug = data_spec['debug']
debug = data_spec['debug']
if not site.layouts.key? template
if not site.layouts.key? template
puts "error (datapage-gen). could not find template #{template}. Skipping dataset #{name}."
puts "error (datapage-gen). could not find template #{template}. Skipping dataset #{name}."
else
else
# records is the list of records for which we want to generate
# records is the list of records for which we want to generate
# individual pages
# individual pages
records = nil
records = nil
data_spec['data'].split('.').each do |level|
data_spec['data'].split('.').each do |level|
if records.nil?
if records.nil?
records = site.data[level]
records = site.data[level]
else
else
records = records[level]
records = records[level]
end
end
end
end
if (records.kind_of?(Hash))
if (records.kind_of?(Hash))
records = records.values
records = records.values
end
end
# apply filtering conditions:
# apply filtering conditions:
# - filter requires the name of a boolean field
# - filter requires the name of a boolean field
# - filter_condition evals a ruby expression which can use =record= as argument
# - filter_condition evals a ruby expression which can use =record= as argument
records = records.select { |record| record[data_spec['filter']] } if data_spec['filter']
records = records.select { |record| record[data_spec['filter']] } if data_spec['filter']
records = records.select { |record| eval(data_spec['filter_condition']) } if data_spec['filter_condition']
records = records.select { |record| eval(data_spec['filter_condition']) } if data_spec['filter_condition']
# we now have the list of all records for which we want to generate individual pages
# we now have the list of all records for which we want to generate individual pages
# iterate and call the constructor
# iterate and call the constructor
records.each do |record|
records.each do |record|
site.pages << DataPage.new(site, site.source, index_files_for_this_data, dir, page_data_prefix, record, name, name_expr, title, title_expr, template, extension, debug)
site.pages << DataPage.new(site, site.source, index_files_for_this_data, dir, dir_expr, page_data_prefix, record, name, name_expr, title, title_expr, template, extension, debug)
end
end
end
end
end
end
end
end
end
end
end
end
module DataPageLinkGenerator
module DataPageLinkGenerator
include Sanitizer
include Sanitizer
# use it like this: {{input | datapage_url: dir}}
# use it like this: {{input | datapage_url: dir}}
# to generate a link to a data_page.
# to generate a link to a data_page.
#
#
# the filter is smart enough to generate different link styles
# the filter is smart enough to generate different link styles
# according to the data_page-dirs directive ...
# according to the data_page-dirs directive ...
#
#
# ... however, the filter is not smart enough to support different
# ... however, the filter is not smart enough to support different
# extensions for filenames.
# extensions for filenames.
#
#
# Thus, if you use the `extension` feature of this plugin, you
# Thus, if you use the `extension` feature of this plugin, you
# need to generate the links by hand
# need to generate the links by hand
def datapage_url(input, dir)
def datapage_url(input, dir)
extension = @context.registers[:site].config['page_gen-dirs'] ? '/' : '.html'
extension = @context.registers[:site].config['page_gen-dirs'] ? '/' : '.html'
"#{dir}/#{sanitize_filename(input)}#{extension}"
"#{dir}/#{sanitize_filename(input)}#{extension}"
end
end
end
end
end
end
Liquid::Template.register_filter(Jekyll::DataPageLinkGenerator)
Liquid::Template.register_filter(Jekyll::DataPageLinkGenerator)