require 'set'
IGNORED_PAGES = Set['sitemap.xml']
LANGS = Set['en', 'pt', 'fr', 'eo'] # jp zh es de
module Jekyll
class Linter < Generator
safe true
priority :high
def insert_id(name, document)
lang = document.data['lang']
ref = document.data['ref']
id = "#{name}:#{lang}:#{ref}"
if @known_ids.include? id then
raise "Duplicate ID found: '#{id}'"
else
@known_ids.add id
end
end
def assert_unique_ids(site)
@known_ids = Set[]
site.collections.each do |name, collection|
collection.docs.each do |document|
unless document.data['generated'] then
insert_id name, document
end
end
end
site.pages.each do |page|
unless IGNORED_PAGES.include? page.path
unless page.data['generated'] then
insert_id 'page', page
end
end
end
end
def slugify(s)
s.ljust(100)
.gsub(/[\W]+/, ' ')
.strip
.gsub(/\s\s+/, '-')
.downcase
.gsub(' ', '-')
.gsub('_', '-')
end
def assert(value, message)
unless value
raise message
end
value
end
def assert_field(document, field)
f = document.data[field]
raise "Undefined '#{field}' for #{document.path}" unless f
f
end
COLLECTION_LAYOUTS = {
'page' => 'page',
'articles' => 'post',
'pastebins' => 'post',
'tils' => 'post',
'slides' => 'slides',
'podcasts' => 'cast',
'screencasts' => 'cast'
}
def assert_frontmatter_fields(site, name, document)
title = assert_field document, 'title'
lang = assert_field document, 'lang'
ref = assert_field document, 'ref'
layout = assert_field document, 'layout'
date = document.date.strftime('%Y-%m-%d') unless layout == 'page'
slug = layout == 'page' ? ref : assert_field(document, 'slug')
extension = name == 'slides' ? 'slides' : 'md'
unless LANGS.member? lang
raise "Invalid lang '#{lang}' in #{document.path}"
end
if COLLECTION_LAYOUTS[name] != layout
raise "Layout mismatch: expected '#{COLLECTION_LAYOUTS[name]}', got '#{layout}' for #{document.path}"
end
if lang == 'en'
unless ['index', 'root', 'tils'].include? ref
if slugify(title) != ref then
raise "#{ref} isn't a slug of the title.\nref: '#{ref}'\ntitle slug: '#{slugify(title)}'"
p slugify(title)
end
end
end
unless layout == 'page' then
path = "_#{name}/#{date}-#{slug}.#{extension}"
unless path == document.relative_path then
raise "date/filename mismatch:\ndate+slug: #{path}\nfilename: #{document.relative_path}"
end
if lang == 'en' then
unless ref == slug then
raise "ref/slug mismatch:\nref: #{ref}\nslug: #{slug}"
end
end
end
if name == 'podcasts' then
flac = "resources/podcasts/#{date}-#{slug}.flac"
unless File.exist? flac then
raise "Missing FLAC file '#{flac}'"
end
end
if name == 'screencasts' then
mkv = "resources/screencasts/#{date}-#{slug}.mkv"
unless File.exist? mkv then
raise "Missing MKV file '#{mkv}'"
end
end
end
def assert_frontmatter(site)
site.collections.each do |name, collection|
collection.docs.each do |document|
unless document.data['generated']
assert_frontmatter_fields site, name, document
end
end
end
site.pages.each do |page|
unless IGNORED_PAGES.include? page.path
unless page.data['generated']
assert_frontmatter_fields site, 'page', page
end
end
end
end
def assert_git_annex(site)
url = site.config['url']
stdout = `git annex find --not --in web`
if stdout != '' or not $?.success? then
puts 'Files in Git Annex not published to "web" remote:'
puts stdout
puts 'Add them with:'
stdout.strip.split('\n').each do |file|
puts " git annex addurl --file #{file} #{url}/#{file}"
end
raise 'Build again after files above are added'
end
end
def generate(site)
assert_unique_ids(site)
assert_frontmatter(site)
assert_git_annex(site)
end
end
end