data_page_generator.rb 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. # -*- coding: utf-8 -*-
  2. # -*- frozen_string_literal: true -*-
  3. # Generate pages from individual records in yml files
  4. # (c) 2014-2016 Adolfo Villafiorita
  5. # Distributed under the conditions of the MIT License
  6. # As found in:
  7. # https://github.com/avillafiorita/jekyll-datapage_gen/blob/c23af65c5273366bf10487ac18449e46f72e9a1c/data_page_generator.rb
  8. module Jekyll
  9. module Sanitizer
  10. # strip characters and whitespace to create valid filenames, also lowercase
  11. def sanitize_filename(name)
  12. if(name.is_a? Integer)
  13. return name.to_s
  14. end
  15. return name.tr(
  16. "ÀÁÂÃÄÅàáâãäåĀāĂ㥹ÇçĆćĈĉĊċČčÐðĎďĐđÈÉÊËèéêëĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħÌÍÎÏìíîïĨĩĪīĬĭĮįİıĴĵĶķĸĹĺĻļĽľĿŀŁłÑñŃńŅņŇňʼnŊŋÑñÒÓÔÕÖØòóôõöøŌōŎŏŐőŔŕŖŗŘřŚśŜŝŞşŠšſŢţŤťŦŧÙÚÛÜùúûüŨũŪūŬŭŮůŰűŲųŴŵÝýÿŶŷŸŹźŻżŽž",
  17. "AAAAAAaaaaaaAaAaAaCcCcCcCcCcDdDdDdEEEEeeeeEeEeEeEeEeGgGgGgGgHhHhIIIIiiiiIiIiIiIiIiJjKkkLlLlLlLlLlNnNnNnNnnNnNnOOOOOOooooooOoOoOoRrRrRrSsSsSsSssTtTtTtUUUUuuuuUuUuUuUuUuUuWwYyyYyYZzZzZz"
  18. ).downcase.strip.gsub(' ', '-').gsub(/[^\w.-]/, '')
  19. end
  20. end
  21. # this class is used to tell Jekyll to generate a page
  22. class DataPage < Page
  23. include Sanitizer
  24. # - site and base are copied from other plugins: to be honest, I am not sure what they do
  25. #
  26. # - `index_files` specifies if we want to generate named folders (true) or not (false)
  27. # - `dir` is the default output directory
  28. # - `data` is the data defined in `_data.yml` of the record for which we are generating a page
  29. # - `name` is the key in `data` which determines the output filename
  30. # - `template` is the name of the template for generating the page
  31. # - `extension` is the extension for the generated file
  32. def initialize(site, base, index_files, dir, data, name, template, extension)
  33. @site = site
  34. @base = base
  35. # @dir is the directory where we want to output the page
  36. # @name is the name of the page to generate
  37. #
  38. # the value of these variables changes according to whether we
  39. # want to generate named folders or not
  40. filename = sanitize_filename(data[name]).to_s
  41. @dir = dir + (index_files ? "/" + filename + "/" : "")
  42. @name = (index_files ? "index" : filename) + "." + extension.to_s
  43. self.process(@name)
  44. self.read_yaml(File.join(base, '_layouts'), template + ".html")
  45. self.data['title'] = data[name]
  46. # add all the information defined in _data for the current record to the
  47. # current page (so that we can access it with liquid tags)
  48. self.data.merge!(data)
  49. end
  50. end
  51. class DataPagesGenerator < Generator
  52. safe true
  53. # generate loops over _config.yml/page_gen invoking the DataPage
  54. # constructor for each record for which we want to generate a page
  55. def generate(site)
  56. # page_gen_dirs determines whether we want to generate index pages
  57. # (name/index.html) or standard files (name.html). This information
  58. # is passed to the DataPage constructor, which sets the @dir variable
  59. # as required by this directive
  60. index_files = site.config['page_gen-dirs'] == true
  61. # data contains the specification of the data for which we want to generate
  62. # the pages (look at the README file for its specification)
  63. data = site.config['page_gen']
  64. if data
  65. data.each do |data_spec|
  66. index_files_for_this_data = data_spec['index_files'] != nil ? data_spec['index_files'] : index_files
  67. template = data_spec['template'] || data_spec['data']
  68. name = data_spec['name']
  69. dir = data_spec['dir'] || data_spec['data']
  70. extension = data_spec['extension'] || "html"
  71. if site.layouts.key? template
  72. # records is the list of records defined in _data.yml
  73. # for which we want to generate different pages
  74. records = nil
  75. data_spec['data'].split('.').each do |level|
  76. if records.nil?
  77. records = site.data[level]
  78. else
  79. records = records[level]
  80. end
  81. end
  82. # apply filtering conditions:
  83. # - filter requires the name of a boolean field
  84. # - filter_condition evals a ruby expression
  85. records = records.select { |r| r[data_spec['filter']] } if data_spec['filter']
  86. records = records.select { |record| eval(data_spec['filter_condition']) } if data_spec['filter_condition']
  87. records.each do |record|
  88. site.pages << DataPage.new(site, site.source, index_files_for_this_data, dir, record, name, template, extension)
  89. end
  90. else
  91. puts "error. could not find template #{template}" if not site.layouts.key? template
  92. end
  93. end
  94. end
  95. end
  96. end
  97. module DataPageLinkGenerator
  98. include Sanitizer
  99. # use it like this: {{input | datapage_url: dir}}
  100. # to generate a link to a data_page.
  101. #
  102. # the filter is smart enough to generate different link styles
  103. # according to the data_page-dirs directive ...
  104. #
  105. # ... however, the filter is not smart enough to support different
  106. # extensions for filenames.
  107. #
  108. # Thus, if you use the `extension` feature of this plugin, you
  109. # need to generate the links by hand
  110. def datapage_url(input, dir)
  111. extension = Jekyll.configuration({})['page_gen-dirs'] ? '/' : '.html'
  112. "#{dir}/#{sanitize_filename(input)}#{extension}"
  113. end
  114. end
  115. end
  116. Liquid::Template.register_filter(Jekyll::DataPageLinkGenerator)