Up: Nanoc
The following apparent uses of the preprocessor show up in sites’ sources (see below):
- Read from external world into config
- From environment (e.g.
NANOC_ENV) - From side-effect-free command output (e.g.
nanoc --version)
- From environment (e.g.
- Set attributes based on other attributes, identifier, or raw content
- Convert from one type to another (e.g. string to Time, or split tags string on comma)
- Not currently possible: make changes depending on item’s dependencies
- Assign next/previous item (identifier)
- Create item (not based on anything)
- Create items based on config details
- Create items based on other items (sometimes paginated)
- Items by category
- Items by language
- Items by year
- Items by tag
- Delete items that match certain criteria (e.g.
is_draft,is_published) - Generate a variant copy of an item (e.g.
.merge(offline_mode: true)) - Create a config with some preprocessing (e.g.
mangle(e-mail address)) - Fetch data from external sources (e.g. GitHub)
- … based on existing items (e.g. fetch repo info for all
item[:github_repo])
- … based on existing items (e.g. fetch repo info for all
- Delete files generated as part of another process (e.g.
output/search-index.json) - rsync static to output
- Set item attributes to be compatible with the Blogging helper
- Set item attributes to be compatible with the Sitemap helper
Sources
from: https://github.com/moll/nutikaitse/blob/master/Rules
preprocess do
@config[:env] = ENV["NANOC_ENV"] ? ENV["NANOC_ENV"].downcase : "production"
@items.each do |item|
KINDS.find do |type, path|
item[:kind] = type if item.identifier =~ path
end
LANGUAGES.find do |lang|
item[:lang] = lang if item.identifier.end_with?(".#{lang}/")
end
# is_hidden is for sidemap
item[:is_hidden] = true if item[:hidden]
end
end
from: https://github.com/avdgaag/nanoc-template
preprocess do
create_robots_txt
create_webmaster_tools_authentications
create_sitemap
end
# Preprocessor helpers
#
# This file has a collection of methods that are meant to be used in the
# preprocess-block in the Nanoc Rules file.
#
# @author Arjan van der Gaag
# Generate a sitemap.xml file using Nanoc's own xml_sitemap helper method by
# dynamically adding a new item.
#
# Make items that should not appear in the sitemap hidden. This by default
# works on all image files and typical assets, as well as error pages and
# htaccess. The is_hidden attribute is only explicitly set if it is absent,
# allowing per-file overriding.
#
# @todo extract hidden file types into configuration file?
def create_sitemap
return unless @site.config[:output_generated_assets]
@items.each do |item|
if %w{png gif jpg jpeg coffee scss sass less css xml js txt}.include?(item[:extension]) ||
item.identifier =~ /404|500|htaccess/
item[:is_hidden] = true unless item.attributes.has_key?(:is_hidden)
end
end
@items << Nanoc3::Item.new(
"<%= xml_sitemap %>",
{ :extension => 'xml', :is_hidden => true },
'/sitemap/'
)
end
# Use special settings from the site configuration to generate the files
# necessary for various webmaster tools authentications, such as the services
# from Google, Yahoo and Bing.
#
# This loops through all the items in the `webmaster_tools` setting, using
# its properties to generate a new item.
#
# See config.yaml for more documentation on the input format.
def create_webmaster_tools_authentications
return unless @site.config[:output_generated_assets]
@site.config[:webmaster_tools].each do |file|
next if file[:identifier].nil?
content = file.delete(:content)
identifier = file.delete(:identifier)
file.merge({ :is_hidden => true })
@items << Nanoc3::Item.new(
content,
file,
identifier
)
end
end
# Generate a robots.txt file in the root of the site by dynamically creating
# a new item.
#
# This will either output a default robots.txt file, that disallows all
# assets except images, and points to the sitemap file.
#
# You can override the contents of the output of this method using the site
# configuration, specifying Allow and Disallow directives. See the config.yaml
# file for more information on the expected input format.
def create_robots_txt
return unless @site.config[:output_generated_assets]
if @site.config[:robots]
content = if @site.config[:robots][:default]
<<-EOS
User-agent: *
Disallow: /assets
Allow: /assets/images
Sitemap: #{@site.config[:base_url]}/sitemap.xml
EOS
else
[
'User-Agent: *',
@site.config[:robots][:disallow].map { |l| "Disallow: #{l}" },
(@site.config[:robots][:allow] || []).map { |l| "Allow: #{l}" },
"Sitemap: #{@site.config[:robots][:sitemap]}"
].flatten.compact.join("\n")
end
@items << Nanoc3::Item.new(
content,
{ :extension => 'txt', :is_hidden => true },
'/robots/'
)
end
end
from: https://github.com/dnsimple/dnsimple-support
preprocess do
create_category_pages
end
def create_category_pages
articles_by_category.each do |category, items|
@items << Nanoc::Item.new(
"<%= render('category_index', :category => '#{category}') %>",
{
:title => "Articles in #{category}",
:h1 => "#{category} articles",
:items => items,
:categories => category
},
url_for_category(category),
:binary => false
)
end
end
from https://github.com/scheibler/nanoc-multilingual-theme/blob/master/Rules.example
preprocess do
# redirect index page
items << Nanoc::Item.new(
"<%= render 'redirect' %>", { :kind => 'redirect' }, "/")
# create various blog sites in all supported languages
# if you don't use the blog pattern at your site, you can delete the rest of the preprocess block
for language in LANGUAGE_CODE_TO_NAME_MAPPING.keys do
article_list = sorted_blog_article_list_for(language)
# blog main page
items << Nanoc::Item.new( "",
{ :kind => 'article_list', :title => 'Blog', :canonical_identifier => 'blog_home', :start_index => 0 },
"/" + language + "/blog/")
# blog index pages for older articles
article_index = @site.config[:number_of_articles_at_blog_index_page]
site_index = 2
while article_index < article_list.length
items << Nanoc::Item.new( "",
{ :kind => 'article_list', :title => translate_string(language, 'blog_title_page_number') % site_index,
:canonical_identifier => "blog_home%d" % site_index, :start_index => article_index },
"/" + language + "/blog/index-%.2d/" % site_index)
article_index += @site.config[:number_of_articles_at_blog_index_page]
site_index += 1
end
# blog rss feed
items << Nanoc::Item.new(
"<%= atom_feed :title => @site.config[:site_title], :author_name => @site.config[:site_author],
:author_uri => @site.config[:author_uri], :limit => @site.config[:number_of_rss_feed_entries],
:articles => sorted_blog_article_list_for(language_code_of(item)) %>",
{ :kind => 'feed' }, "/" + language + "/blog/feed/")
# tags main page
items << Nanoc::Item.new( "",
{ :kind => 'tag_list', :title => 'Tags', :canonical_identifier => 'tag_list', :start_index => 0 },
"/" + language + "/blog/tags/")
all_tags(language, true).each do |tag|
items << Nanoc::Item.new( "",
{ :kind => 'article_list_for_tag', :title => 'Tag %s' % tag[0], :tag => tag[0],
:count => tag[1], :canonical_identifier => 'articles_for_tag_%s' % tag[0].gsub(' ','_') },
"/" + language + "/blog/tags/" + tag[0].gsub(' ','-') + "/")
end
end
end
from: https://github.com/democratech/LaPrimaire/blob/master/Rules
preprocess do
create_robots_txt
end
def create_robots_txt
if @site.config[:robots]
content = if @site.config[:robots][:default]
<<-EOS
User-agent: *
Disallow: /admin/
Disallow: /citoyen/
EOS
else
[
'User-Agent: *',
@site.config[:robots][:disallow].map { |l| "Disallow: #{l}" },
(@site.config[:robots][:allow] || []).map { |l| "Allow: #{l}" },
"Sitemap: #{@site.config[:robots][:sitemap]}"
].flatten.compact.join("\n")
end
@items << Nanoc3::Item.new(
content,
{ :extension => 'txt', :is_hidden => true },
'/robots/'
)
end
end
from: https://github.com/blinry/morr.cc/blob/master/Rules
preprocess do
@items.each do |item|
if item[:published]
item[:published] = DateTime.parse(item[:published].to_s)
end
if item[:updated]
item[:updated] = DateTime.parse(item[:updated].to_s)
end
if item[:tags]
item[:tags] = item[:tags].split(",").map{|t| t.strip}
end
end
tags.each do |tag|
content = '<%= box(with_tag("'+tag+'")) %>'
title = "Content with tag '#{tag}'"
identifier = "/tag/#{tag}/index.md"
@items.create(content, {:title => title, :noindex => true}, identifier)
end
categories.each do |name, items|
content = "<%= box(categories[\"#{name}\"]) %>"
title = "#{name}"
identifier = "/#{name.downcase}/index.md"
@items.create(content, {:title => title, :headless => true, :noindex => true}, identifier)
end
# rebuild these variables for each compilation
$categories = nil
$things = nil
end
from: https://github.com/bobthecow/genghisapp.com/blob/master/Rules
preprocess do
config[:genghis_version] = get_genghis_version
end
from: https://github.com/nanoc/nanoc.ws/blob/master/Rules
preprocess do
config[:nanoc_version_info] = Nanoc.version_information.strip
config[:gem_version_info] = Gem::VERSION
config[:ruby_version_info] = `ruby --version`.strip
config[:generate_pdf] = !ENV['PDF'].nil?
end
from: https://github.com/ddfreyne/stoneship-site/blob/master/Rules
preprocess do
def hide_assets
items.each do |item|
if item.identifier =~ /^\/assets/
item[:is_hidden] = true
end
end
end
def delete_drafts
items.delete_if { |i| i[:is_draft] }
end
def convert_dates
items.each do |i|
if i[:published_on]
i[:published_on] = Date.parse(i[:published_on])
end
end
end
def assign_cachebuster_id
stylesheet = @items["/assets/style/style.*"]
digest = Digest::SHA1.base64digest(stylesheet.raw_content)
stylesheet[:cbid] = digest.gsub(/[^A-Za-z0-9]+/, '')
end
hide_assets
delete_drafts
convert_dates
assign_cachebuster_id
from: https://github.com/davidcox/coxlab-website/blob/master/Rules
preprocess do
news_item_years.each do |y|
@items << Nanoc3::Item.new(
"",
{ :title => "News Items from #{y}",
:year => y },
"/news/archive/#{y}/"
)
end
end
from: https://github.com/kana/hatokurandom/blob/master/Rules
preprocess do
def items.find_by_identifier(identifier)
find {|i| i.identifier == identifier} or
throw ArgumentError.new("No such item with identifier '#{identifier}'")
end
root_item = items.find_by_identifier('/')
items << Nanoc::Item.new(
root_item.raw_content,
root_item.attributes.merge({offline_mode: true}),
'/offline/'
)
end
from: https://github.com/pelletier/blog/blob/master/Rules
# Do some preprocessing on articles: inject some attributes into them.
preprocess do
items.each do |item|
# Make them articles if they are in this directory (I seriously don't want
# to type this each time a write a new one).
if item.identifier =~ %r{^/articles/(.*)$}
item[:kind] = 'article'
edited_stamp = item[:edited] or item[:edited_at]
if not edited_stamp.nil?
item[:edited_at] = Time.parse(edited_stamp)
end
end
# Add the :created_at attribute, based on the filename (thanks to Time.parse
# magic).
if item.identifier =~ %r{^/articles/\d{4}/\d{2}/(\d{4}-\d{2}-\d{2}).+$}
item[:created_at] = Time.parse($1)
end
end
end
[TODO]
from: https://github.com/oblac/jodd-site/blob/master/Rules
preprocess do
# assign a 'site_path' to each item
@items.each do |item|
collect_path(item)
end
end
def collect_path(item)
#puts item.raw_filename
path = item.identifier.to_s
# remove raw prefix
if (path.start_with?('/static/'))
path = path[7..-1]
end
# puts "---->" + path
# collect documents (format: /path/number+name.md)
ndx = path.index('+')
if (ndx != nil)
last = path.rindex('/')
key = path[0..last]
number = path[(last+1)..(ndx-1)]
path = key + path[(ndx+1)..-1]
add_doc(key, number, item)
end
# set paths
if (path.end_with?('.md'))
path = path[0..-3] + 'html'
else
index = path.rindex('.')
if (index != nil)
ext = item[:extension]
index2 = ext.rindex('.')
if (index2 != nil)
index2 += 1
ext = ext[index2..-1]
end
path = path[0..index] + ext
end
end
item[:site_path] = path
if (item[:title] == nil)
title = extract_md_title(item)
if (title != nil)
item[:title] = title
end
end
end
from: https://github.com/kana/nanoc-test/blob/master/Rules
preprocess do
def mangle(email)
sp = '<span class="nospam">␣</span>'
email.gsub(/[@.]/, "#{sp}\\0#{sp}")
end
config[:site] = begin
h = {}
h[:author] = 'Kana Natsuno'
h[:email] = mangle("kana\100whileimautomaton.net")
h[:domain] = 'whileimautomaton.net'
h[:name] = 'while ("im automaton");'
h[:prefix] = "http://#{h[:domain]}"
h[:signature] = "#{h[:author]} <#{h[:email]}>"
h[:uri] = "#{h[:prefix]}/"
h
end
config[:recent_topic_count] = 5
topics_per_month =
items
.select(&:topic?)
.group_by {|i| i.identifier.match(%r{^(/\d+/\d+/)\d+/$})[1]}
topics_per_month.each do |id, topics|
items << Nanoc::Item.new(
"",
{
:title => id.sub(%r{/(\d+)/(\d+)/}, '\1-\2'),
:topics => topics,
},
id
)
end
end
from: https://github.com/mklabs/web-learn-jquery-com/blob/master/Rules
preprocess do
@chapterOrder = [
"getting-started",
"javascript-101",
"jquery-basics",
"using-jquery-core",
"events",
"effects",
"ajax",
"plugins",
"performance",
"code-organization",
"custom-events",
"how-to"
]
@chapters = {}
@github_users = {
"jquery" => nil
}
@items.each do |item|
item[:chapter] = item[:filename].split('/')[1]
item[:chapter_title] = item[:chapter].gsub(/-/, " ").upcase
if item[:github]
@github_users[ item[:github] ] = nil
else
item[:github] = "jquery"
end
end
@github_users.each do |username, wat|
request = Curl::Easy.http_get("https://api.github.com/users/"+username)
request.perform
@github_users[ username ] = JSON.parse request.body_str
end
@groupedItems = @items.group_by {|item| item[:chapter]}
@orderedItems = []
@chapterOrder.each do |folder|
myitems = @groupedItems[ folder ]
@chapters [ folder] = {}
@chapters[ folder ][ :items ] = @groupedItems[folder].sort_by {|i| i[:section] || 0 }
@orderedItems = @orderedItems + @chapters[ folder ][ :items ]
@chapters[ folder ][ :title ] = folder.gsub(/-/, " ").upcase
@chapters[ folder ][ :folder ] = folder
end
@items.each do |item|
i = item[:ordinal_index] = @orderedItems.index(item)
if i
item[:next_item] = @orderedItems[ i+1 ]
item[:previous_item] = @orderedItems[ i-1 ]
end
item[:github_user] = @github_users[ item[:github] ]
end
@site.config[:chapters] = @chapters
@site.config[:orderedItems] = @orderedItems
end
from: https://github.com/gjtorikian/testing/blob/master/Rules
preprocess do
File.delete("output/search-index.json") if File.exists?("output/search-index.json")
end
from: https://github.com/lifepillar/nanoc4-template/blob/master/Rules
preprocess do
@config[:production] = !ENV['NANOC_ENV'].nil? && ENV['NANOC_ENV'] == 'production' # See https://github.com/nanoc/nanoc/issues/487
# See: http://nanoc.ws/docs/api/Nanoc/Helpers/Blogging.html
# Assume all items inside /blog are blog articles unless otherwise specified.
@items.select { |item| item.identifier.to_s =~ %r{^/blog/posts/.+} }.each do |item|
item[:kind] ||= 'article' # Required by Nanoc::Helpers::Blogging
end
# Assign a date to all items (not only blog posts) unless they have it already defined.
@items.each do |item|
if item.key?(:created_at)
item[:created_at] = attribute_to_time(item[:created_at])
else
item[:created_at] = Time.now
end
if item.key?(:updated_at)
item[:updated_at] = attribute_to_time(item[:updated_at])
end
end
# Build tag pages for blog posts
build_tag_pages(articles())
# Build yearly and monthly archives of blog posts
build_archives(articles())
from: https://github.com/spf13/blog.zacharyvoase.com/blob/master/Rules
preprocess do
system('rsync -a static/ output') # Copy static files.
end
from: https://github.com/bjornd/jvectormap-site
preprocess do
items.each { |i| map_preprocessing(i) if i[:map_params] || i[:map_params_variants] }
build_jvectormap
generate_doc
end
def map_preprocessing(item)
item[:map_params_variants] ||= [Hash.new]
proc_config = File.read(item.raw_filename.sub('.html', '_config.json'))
params = JSON.parse(proc_config, :symbolize_names => true)
item[:js_assets] = []
item[:map_params_variants].each_index do |index|
variant_params = params.clone
variant_params[0] = variant_params[0].merge( item[:map_params_variants][index] )
variant_params[-1][:params] = variant_params[-1][:params].merge( item[:map_params_variants][index] )
item[:map_params_variants][index][:projection] = variant_params[0][:projection]
item[:map_params_variants][index][:proc_config] = proc_config
variant_params[0][:file_name] = @config[:maps_path]+'/'+variant_params[0][:file_name]
#if @config[:maps_default_encoding] && !variant_params[-1][:params][:input_file_encoding]
# variant_params[-1][:params][:input_file_encoding] = @config[:maps_default_encoding]
#end
map_id = Digest::MD5.hexdigest(variant_params.to_json)
map_name = 'jquery-jvectormap-'+variant_params[-1][:params][:name]+'-'+variant_params[0][:projection]
output_file_path = 'tmp/'+map_id+'.js'
variant_params[-1]['file_name'] = output_file_path
if !File.exists? output_file_path
converter_command =
'echo \''+variant_params.to_json+'\' | '+
'python '+
'external/jvectormap/converter/processor.py '
system(converter_command)
end
@items << Nanoc3::Item.new(
File.open(output_file_path, "r").read,
{},
"/js/"+map_name+'/'
)
item[:map_params_variants][index][:download_link] = '/js/'+map_name+'.js'
item[:map_params_variants][index][:file_size] = File.size output_file_path
item[:map_params_variants][index][:name] = variant_params[-1][:params][:name]+'_'+variant_params[0][:projection]
item[:js_assets] << '/js/'+map_name+'.js'
if index == 0
map_content = File.read(output_file_path)
item[:regions] = JSON.parse(map_content[map_content.index('{') .. map_content.rindex('}')])['paths'].to_a.map do |region|
{code: region[0], name: region[1]['name']}
end
end
end
end
def generate_doc
hash = get_jvectormap_commit_hash
FileUtils.mkpath('tmp/doc') if !File.exists?('tmp/doc')
tmpDir = 'tmp/doc/'+hash+'/'
if !File.exists?(tmpDir)
`external/jsdoc/jsdoc -t ../jsdoc_template/ -d #{tmpDir} external/jvectormap/src/`
end
Dir.foreach(tmpDir) do |fname|
next if !['jvm-dataseries.html', 'jvm-map.html', 'jvm-multimap.html', 'jvm-proj.html', 'jvm-legend.html'].index(fname)
itemTile, itemText = File.open(tmpDir + fname, "rb").read.split("\n", 2)
@items << Nanoc3::Item.new(
itemText,
{title: itemTile, submenu: true},
"/documentation/javascript-api/"+File.basename(tmpDir + fname, '.html')+"/"
)
end
end
def build_jvectormap
hash = get_jvectormap_commit_hash
FileUtils.mkpath('tmp/jvectormap') if !File.exists?('tmp/jvectormap')
tmpFile = 'tmp/jvectormap/'+hash
if !File.exists?(tmpFile)
`external/jvectormap/build.sh #{tmpFile}`
end
js_file_name = "jquery-jvectormap-#{@config[:jvectormap_version]}.min"
@items << Nanoc3::Item.new(
File.open(tmpFile, "rb").read,
{},
"/js/#{js_file_name}/"
)
css_file_name = "jquery-jvectormap-#{@config[:jvectormap_version]}"
@items << Nanoc3::Item.new(
File.open("external/jvectormap/jquery-jvectormap.css", "rb").read,
{},
"/css/#{css_file_name}/"
)
FileUtils.mkpath('tmp/jvectormap-zip') if !File.exists?('tmp/jvectormap-zip')
FileUtils.remove(Dir.glob('tmp/jvectormap-zip/*'))
FileUtils.copy_file(tmpFile, "tmp/jvectormap-zip/#{js_file_name}.js")
FileUtils.copy_file('external/jvectormap/jquery-jvectormap.css', "tmp/jvectormap-zip/#{css_file_name}.css")
`cd tmp/jvectormap-zip; zip jquery-jvectormap-#{@config[:jvectormap_version]}.zip *.css *.js`
@items << Nanoc3::Item.new(
File.open("tmp/jvectormap-zip/jquery-jvectormap-#{@config[:jvectormap_version]}.zip", "rb").read,
{},
"/binary/jquery-jvectormap-#{@config[:jvectormap_version]}/"
)
end
from: https://github.com/coderanger/coderanger.net/blob/master/Rules
preprocess do
# Anything with an explicit published: false should vanish
items.reject! {|item| item[:published] == false}
items.each do |item|
# Extract date from filename if present
item.identifier.match(%r{(/.*)?/(\d\d\d\d-\d\d-\d\d)-(.*)/}) do |md|
item.identifier = "#{md[1]}/#{md[3]}/"
item[:date] ||= md[2]
end
# Set the kind for certin subfolders
parts = item.identifier.split('/')
if parts.length > 2
case parts[1]
when 'posts'
item[:kind] ||= 'post'
when 'talks'
item[:kind] ||= 'talk'
end
end
# Parse the date if present
item[:date] = Date.parse(item[:date]) if item[:date].is_a?(String)
# Set the extra timestamps for the Blogging helper
item[:created_at] = item[:date].to_time if item[:date]
item[:updated_at] = item[:mtime] if item[:mtime]
# Convert the identifier into the title if not present
if item[:kind]
item[:title] ||= begin
words = item.identifier.split('/').last.split('-')
words.first.capitalize! # Always cap the first word
words.each {|word| word.capitalize! if word.length > 3}
words.join(' ')
end
end
end
end
from: https://github.com/DivineDominion/nanoc-boilerplate/blob/master/Rules
preprocess do
# authors may unpublish items by setting meta attribute publish: false
items.delete_if { |item| item[:publish] == false }
end
from: https://github.com/Caster/Ploggy/blob/master/Rules
preprocess do
# setting a URL
items.select{ |item| item[:title] != nil }.each{ |item|
item[:title_full] = 'Ploggy - ' + item[:title]
splitId = item.identifier.chop.split('/')
joinId = splitId[2..-1].join('/')
item[:url] = (joinId.length > 0 ? '/' : '') + joinId + '/'
}
# Ploggy-specific handling
logs_found = 0
items.select{ |item| item.identifier.chop.split('/')[1] == 'logs' }
.each{ |item|
PloggyHelper.log_items.push(item)
logs_found += 1
}
Nanoc::CLI::Logger.instance.log(:low,
sprintf('Found %d log entries.', logs_found))
end
from: https://github.com/Caster/denvelop/blob/master/site/Rules
preprocess do
items.select{ |item| item[:title] != nil }.
each{ |item|
# set title of the item
item[:title_full] = 'Denvelop - ' + item[:title]
# build the URL of the item, which depends on the language of the
# item and the default language of the site
splitId = item.identifier.without_ext.split('/')
# special handling for index files
if splitId[-1] == 'index' then
splitId.pop
end
joinId = (splitId[2] == default_language ?
splitId[3..-1] : splitId[2..-1]).join('/')
# set the URL
item[:url] = (joinId.length > 0 ? '/' : '') + joinId + '/'
}
end
from: https://github.com/driftyco/ionic-learn/blob/master/Rules
preprocess do
video_items = items.select do |item|
split_item = item.identifier.split('/').delete_if(&:empty?)
split_item.length > 1 and split_item.first == "videos"
end
video_names = video_items.map do |item|
item.identifier.split('/').delete_if(&:empty?)[1]
end.uniq
all_formulas.each do |formula|
formula[:titles] = [formula[:name], "Formulas"]
end
video_names.each do |item|
detail_page = items[detail_identifier.call(item)]
if !detail_page.nil? && detail_attributes = detail_page.attributes
last_modified = Date.parse(detail_attributes[:date]).to_time
if detail_page[:live] == true
items << Nanoc::Item.new(
"<%= render 'video_detail' %>",
detail_attributes.merge({
titles: [detail_attributes[:name], 'Videos'],
kind: 'video',
details: detail_identifier.call(item),
transcript: transcript_identifier.call(item)
}),
video_identifier.call(item),
last_modified
)
end
end
end
video_difficulties.each do |difficulty|
items << Nanoc::Item.new(
"<%= render 'difficulty_list' %>",
{
difficulty: difficulty,
kind: 'difficulty_list',
titles: [difficulty.capitalize, 'Videos'],
body_css: 'videos'
},
"/videos/#{difficulty}/"
)
end
formula_categories.each do |category|
items << Nanoc::Item.new(
"<%= render 'category_list' %>",
{category: category,
kind: 'category_list',
titles: [category, 'Formulas'],
body_css: 'formulas'},
"/formulas/#{category.downcase.split(' ').join('-')}/"
)
end
end
from: https://github.com/EasyRPG/easyrpg.org/blob/master/Rules
preprocess do
hide_items_from_sitemap
end
def hide_items_from_sitemap
@items.each do |item|
if %w{css xml js txt}.include?(item[:extension]) || item.identifier =~ /404/
item[:is_hidden] = true if item[:is_hidden].nil?
end
end
end
from: https://github.com/seth/userprimary.net/blob/master/Rules
preprocess do
add_missing_info
create_tags_pages
create_month_archives
end
def add_missing_info
items.each do |item|
if item[:file]
# nanoc3 >= 3.1 will have this feature, add for older versions
item[:extension] ||= item[:file].path.match(/\..*$/)[0]
end
end
end
def create_tags_pages
tags = Hash.new { |h, k| h[k] = 0 }
items.each do |item|
if item[:kind] == "article"
if item[:tags]
item[:tags].each { |t| tags[t] += 1 }
end
end
end
tags.each do |tag, count|
content = %[= render('tag', :tag_name => "#{tag}", :tag_count => "#{count}")]
items << Nanoc3::Item.new(content,
{ :title => "#{tag}",
:tag_name => tag,
:tag_count => count.to_s
},
"/tags/#{tag}/")
end
end
def create_month_archives
bymonth = Hash.new { |h, k| h[k] = [] }
items.each do |item|
if item[:kind] == "article"
t = Time.parse(item[:created_at])
bymonth[t.strftime("%Y-%B")] << item
end
end
bymonth.each do |year_month, posts|
posts = posts.sort_by { |p| Time.parse(p[:created_at]) }.reverse
most_recent = Time.parse(posts.first[:created_at])
items << Nanoc3::Item.new(render('bymonth', :posts => posts,
:year_month => year_month),
{ :title => "#{year_month}",
:post_count => posts.count,
:most_recent => most_recent,
:month => most_recent.strftime("%B"),
:year => most_recent.strftime("%Y")
},
"/archives/#{year_month}/")
end
end
from: https://github.com/rvm/rvm-site/blob/master/lib/auto.rb
preprocess do
AutoHelper.new(File.dirname(__FILE__), self).auto
# TODO see https://github.com/nanoc/nanoc/pull/481
# force reload of items, does the damn warning about defining
# preprocess second time - not a problem, no loop here
#self.site.instance_variable_set(:@loaded, false)
#self.site.instance_variable_set(:@items_loaded, false)
#self.site.load
end
class AutoHelper
attr_reader :root, :site, :tags, :authors
def initialize(root, site)
@root = Pathname(root)
@site = site
@tags = []
@authors = {}
end
def parse_tags(item)
item.attributes[:tags].each { |tag| @tags << tag unless @tags.include?(tag) }
end
def parse_author(item)
authors[item.attributes[:author]] = item.attributes[:author_full]
end
def parse_site
site.items.each do |item|
parse_tags (item) if item.attributes[:tags]
parse_author(item) if item.attributes[:author]
end
end
def write_file(file, content)
file.open('w') { |file| file.write(content) }
end
def render_layout(layout_name, mapping = {})
layout = @site.layouts.find { |l| l.identifier == layout_name.cleaned_identifier }
filter = Nanoc::Filter.named('erb').new(mapping)
filter.run(layout.raw_content)
end
def create_tag_page(tag_page, tag)
write_file(tag_page, render_layout("templates/tag_page", tag: tag))
end
def create_tag_feed(feed_page, tag)
write_file(feed_page, render_layout("templates/feed", type: 'tag', filter: tag))
end
def ensure_tag_page(tags_dir, tag)
tag_page = tags_dir + "#{tag}.haml"
feed_page = tags_dir + "#{tag}_feed.haml"
create_tag_page(tag_page, tag) unless tag_page.exist?
create_tag_feed(feed_page, tag) unless feed_page.exist?
end
def ensure_tag_pages
tags_dir = root + 'content' + 'tags'
tags_dir.mkpath
tags.each do |tag|
ensure_tag_page(tags_dir, tag)
end
end
def create_author_page(author_page, author, author_full)
write_file(author_page, render_layout("templates/author_page", author: author, author_full: author_full))
end
def create_author_feed(feed_page, author, author_full)
write_file(feed_page, render_layout("templates/feed", type: 'author', filter: author))
end
def ensure_author_page(authors_dir, author, author_full)
author_page = authors_dir + "#{author}.haml"
feed_page = authors_dir + "#{author}_feed.haml"
create_author_page(author_page, author, author_full) unless author_page.exist?
create_author_feed(feed_page, author, author_full) unless feed_page.exist?
end
def ensure_author_pages
authors_dir = root + 'content' + 'authors'
authors_dir.mkpath
authors.each_pair do |author, author_full|
ensure_author_page(authors_dir, author, author_full)
end
end
def auto
parse_site
ensure_tag_pages
ensure_author_pages
end
end
from: https://github.com/yazgoo/blag/blob/master/Rules
preprocess do
# for tag in all_tags
# @items << Nanoc::Item.new("",
# {:title => tag.capitalize, :tag => tag, :layout => "tag", :extension => 'html'},
# "/blog/tags/#{tag.to_url}/")
# end
for date in get_timeline
# @items << Nanoc::Item.new("", {
# :title => "Blog posts from #{date.year}",
# :menu_title => date.year, :year => date.year,
# :layout => "timeline",
# :extension => "html"}, "/blog/#{date.year}/")
@items << Nanoc::Item.new("", {
:title => "Blog posts from #{Date::MONTHNAMES[date.month.to_i]} #{date.year}",
:menu_title => Date::MONTHNAMES[date.month.to_i],
:year => date.year,
:month => date.month,
:layout => "timeline",
:extension => "html"}, "/blog/#{date.year}/#{'%02d' % date.month}/")
end
end
from: https://github.com/martinrehfeld/inside.glnetworks.de/blob/master/Rules
preprocess do
# authors may unpublish items by setting meta attribute publish: false
items.delete_if { |item| item[:publish] == false }
# set sensible defaults for attributes
items.each do |item|
item[:is_hidden] = true if item.binary?
if item.identifier =~ %r(^/articles/) && !item.binary?
item[:kind] ||= 'article'
item[:updated_at] ||= item.mtime
end
end
create_category_pages
copy_static
end
# Create category/tag pages (uses layouts/category.haml
def create_category_pages
tags.keys.each do |tag|
items << Nanoc3::Item.new(
"= render('category', :tag => '#{tag}')",
{
:title => "Category: #{tag}",
:changefreq => 'daily',
:priority => 0.4
},
"/categories/#{tag.downcase.parameterize}/",
:binary => false
)
end
end
# Copy static assets outside of content instead of having nanoc3 process them.
def copy_static
FileUtils.cp_r 'static/.', 'output/', :preserve => true
end
from: https://github.com/github/developer.github.com/blob/master/Rules
preprocess do
add_created_at_attribute
add_kind_attribute
create_individual_blog_pages
generate_redirects(config[:redirects])
@items.each do |item|
ConrefFS.apply_attributes(@config, item, :default)
end
end
def add_created_at_attribute
@items.each do |item|
date = date_from_filename(item[:filename])
item[:created_at] = date unless date.nil?
end
end
def add_kind_attribute
@items.each do |item|
next unless item[:filename].to_s.starts_with?('content/changes/2')
item[:kind] = 'change'
end
end
module Paginate
BLOG_TYPE = 'changes'
def paginated_items(items)
items.select { |i| i.identifier =~ %r(/#{BLOG_TYPE}/\d{4}) }.sort_by { |b| Time.parse(b[:created_at].to_s) }
end
def create_individual_blog_pages
paginated_blog_items = paginated_items(items)
# create individual blog pages
blog_pages = []
blog_pages << paginated_blog_items.slice!(0...PER_PAGE) until paginated_blog_items.empty?
blog_pages.each_index do |i|
next_i = i + 1 # accounts for 0-index array
first = i * PER_PAGE
last = (next_i * PER_PAGE) - 1
@items.create(
"<%= renderp '/pagination_page.html',
:current_page => #{next_i},
:per_page => PER_PAGE,
:first => #{first}, :last => #{last} %>",
{ :title => 'GitHub API Changes', :layout => 'blog' },
"/changes/#{next_i}"
)
end
end
end
module RedirectGenerator
def generate_redirects(redirects)
redirects.each do |pairs|
pairs.each_pair do |old_url, new_url|
filename = old_url.to_s.sub(%r{/$}, '')
@items.create(
"<%= renderp '/redirect.*',
{ :new_url => '#{new_url}'
}
%>",
{ :filename => filename },
filename
)
end
end
end
end
from: https://github.com/DataDog/documentation/blob/master/Rules
preprocess do
create_redirect_pages
# def rchomp(sep = $/)
# self.start_with?(sep) ? self[sep.size..-1] : self
# end
# def snippetizer(item)
# if item["has_snippets"] == "True"
# doc = Nokogiri::HTML.fragment(item.content)
# doc.css(".snippetizer").each do |snippet|
# print snippet
# # # id = @item.identifier.gsub("(/(.+)/", "$&")
# id = item.identifier.chomp('/').rchomp('/') + '-' + snippet['id']
# # # print id
# # # print snippet.content
# new_snippet = {id => snippet.content}
# print new_snippet
# $global_snippets.merge(new_snippet)
# end
# end
# end
if ENV.has_key?('github_personal_token')
$client = $client ||= Octokit::Client.new(:access_token => ENV['github_personal_token'])
$client.user.login
end
$cbfingerprints = get_cache_bust_fingerprints()
$en_local_hash = get_local_hash('en')
$ja_local_hash = get_local_hash('ja')
$example_items = collect_example_items()
$video_items = collect_video_items()
$ja_example_items = collect_ja_example_items()
$ja_video_items = collect_ja_video_items()
$integration_items = collect_integration_items()
$ja_integration_items = collect_ja_integration_items()
$guide_items = collect_guide_items()
$ja_guide_items = collect_ja_guide_items()
create_tag_pages($example_items,{:identifier => "/examples/%%tag%%/"})
create_tag_pages($video_items,{:identifier => "/videos/%%tag%%/"})
create_tag_pages($ja_example_items,{:identifier => "/ja/examples/%%tag%%/", :template => "example-subindex-ja"})
create_tag_pages($ja_video_items,{:identifier => "/ja/videos/%%tag%%/", :template => "video-subindex-ja"})
@items.each do |item|
language = "en"
otherlang = "ja"
langpath = ""
phrases = $en_local_hash
if item.identifier.match('/ja/')
language = "ja"
otherlang = ""
langpath = "/ja"
phrases = $ja_local_hash
end
item["language"] = language
item["otherlang"] = otherlang
item["langpath"] = langpath
phrases.each do | key, val |
item[key] = val
end
# snippetizer(item)
end
end
from: https://github.com/ddfreyne/neps-site/blob/master/Rules
preprocess do
# Remove non-NEPs from /neps/*/
items.delete_if do |i|
parts = i.identifier.scan(/[^\/]+/)
parts.size == 2 && parts[0] == 'neps' && parts[1] !~ %r{^NEP-}
end
# Remove : from neps
items.each do |i|
i.identifier.sub!(':', '')
end
# Remove /neps/ prefix
items.each do |i|
i.identifier.sub!(/^\/neps/, '')
end
# Assign number and title
neps.each do |nep|
nep[:number] = nep.identifier[/\d+/].to_i
nep[:title] = nep.identifier.match(/\d+-(.*)\/$/)[1].gsub('-', ' ')
end
end
from: https://github.com/andreareginato/conference_site/blob/master/Rules
preprocess do
copy_static # add assets to the output directory
end
from: https://github.com/cdlm/website-nanoc/blob/master/rules.rb
preprocess do
# setup blog items
all_feeds.each do |feed|
feed.chain_entries
feed.set_info
feed.generate
end
# sitemap
hide_items do |item|
case item.identifier
when %r{/publications/\d\d\d\d/.*}
false
when /404|500|htaccess/, %r{/(scripts|stylesheets)/.*}
true
else
item.binary? || @site.config[:hidden_extensions].include?(item[:extension])
end
end
create_sitemap
end
def all_feeds
Enumerator.new do |feeds|
@items.each do |i|
feeds << Feed.new(@site, i) if i.feed?
end
end
end
def chain_entries
prev = nil
entries.each do |current|
unless prev.nil?
prev[:next] = current.identifier
current[:prev] = prev.identifier
end
prev = current
end
end
def set_info
entries.each do |e|
e.attributes.update(@root[:entries_info])
end
end
def generate
@site.items << archive_item unless @root[:archives].nil?
@site.items.concat yearly_archive_items unless @root[:archives_yearly].nil?
@site.items << tag_item unless @root[:tags].nil?
end
from: https://github.com/spree/spree/blob/master/guides/Rules
preprocess do
config[:deploy][:default][:region] = ENV['S3_REGION']
config[:deploy][:default][:bucket] = ENV['S3_BUCKET_NAME']
config[:deploy][:default][:aws_access_key_id] = ENV['AWS_ACCESS_KEY_ID']
config[:deploy][:default][:aws_secret_access_key] = ENV['AWS_SECRET_ACCESS_KEY']
end
from: https://github.com/matsimitsu/roytomeij.com/blob/master/Rules
preprocess do
# authors may unpublish items by setting meta attribute publish: false
items.delete_if { |item| item[:publish] == false }
copy_static
# create_tag_pages
add_update_item_attributes
end
from: https://github.com/chickenboot/vintageinvite/blob/master/Rules
preprocess do
build_tag_pages(items)
end
def all_tags(items = nil, sort = false)
items ||= @items # default to all items if no items passed
tags = {}
items.each do |i|
(i[:tags] || []).each{|t| tags[t] ||= 0; tags[t] += 1 }
end
# if sort is true, sort by item count descending
sort ? tags.sort {|tl, tr| tr[1] <=> tl[1]} : tags
end
def build_tag_pages(items)
all_tags(items).each do |tag,count|
items << Nanoc3::Item.new(
"= render('_blog_page', :tag => '#{tag}', :page_title => 'Tag: #{tag}')",
{ :title => "Tag: #{tag}" }, # , :is_hidden => true
"/blog/tags/#{tag}/", :binary => false
)
end
end
from: https://github.com/CootCraig/nanoc_blog/blob/master/blog/Rules
preprocess do
items << Nanoc::Item.new(
"",
{},
"/post_index/"
)
tag_list = Set.new
items.each do |item|
item[:tags].each do |tag|
if tag.length > 0
tag_list.add(tag.downcase)
end
end if item[:tags]
end
items << Nanoc::Item.new(
"",
{ :tag_list => tag_list },
"/tag_index/"
)
tag_list.each do |tag|
items << Nanoc::Item.new(
"",
{ :tag => tag },
"/tags/#{tag}/"
)
end
end