lib/compiler.rb in nanoc-1.1.3 vs lib/compiler.rb in nanoc-1.2
- old
+ new
@@ -1,53 +1,159 @@
module Nanoc
class Compiler
DEFAULT_CONFIG = { :output_dir => 'output' }
- DEFAULT_PAGE = { :filters => [], :extension => 'html', :order => 0, :layout => "default" }
+ FILE_TYPES = {
+ '.erb' => :eruby,
+ '.rhtml' => :eruby,
+ '.haml' => :haml,
+ '.mab' => :markaby,
+ '.liquid' => :liquid
+ }
+
+ PAGE_DEFAULTS = {
+ :custom_path => nil,
+ :extension => 'html',
+ :filters => [],
+ :is_draft => false,
+ :layout => 'default',
+ :order => 0
+ }
+
def initialize
Nanoc.ensure_in_site
@config = DEFAULT_CONFIG.merge(YAML.load_file_and_clean('config.yaml'))
- @global_page = DEFAULT_PAGE.merge(YAML.load_file_and_clean('meta.yaml'))
+ @global_page = PAGE_DEFAULTS.merge(YAML.load_file_and_clean('meta.yaml'))
end
def run
+ # Require all Ruby source files in lib/
Dir['lib/*.rb'].each { |f| require f }
+ # Copy assets to output directory
+ copy_assets
+
+ # Compile all pages
pages = compile_pages(uncompiled_pages)
+
+ # Put pages in their layouts
pages.each do |page|
- content = (page[:layout].nil? ? "<%= @page[:content] %>" : File.read("layouts/#{page[:layout]}.erb")).eruby(page.merge({ :page => page, :pages => pages })) # fallback for nanoc 1.0
+ # Prepare layout content
+ content = nil
+ context = { :page => page.merge(:_content_filename => nil), :pages => pages }
+ layout = layout_for_page(page)
+ begin
+ case layout[:type]
+ when :eruby
+ content = layout[:content].eruby(context)
+ when :haml
+ content = layout[:content].haml(context)
+ when :markaby
+ content = layout[:content].markaby(context)
+ when :liquid
+ content = layout[:content].liquid(context)
+ end
+ rescue => exception
+ $stderr.puts "Exception occured while layouting page" +
+ "'#{page[:_content_filename]}' in layout '#{page[:layout]}':" unless $quiet
+ $stderr.puts exception unless $quiet
+ $stderr.puts exception.backtrace.join("\n") unless $quiet
+ exit
+ end
+
+ # Write page with layout
FileManager.create_file(path_for_page(page)) { content }
end
end
private
+ # Copies the contents of the assets directory into the output directory
+ def copy_assets
+ Dir['assets/*'].each { |f| FileUtils.remove_entry_secure(f.sub('assets/', 'output/'), true) }
+ FileUtils.cp_r(Dir['assets/*'], 'output') if File.directory?('assets') and !Dir['assets/*'].empty?
+ end
+
+ # Returns a list of uncompiled pages
def uncompiled_pages
- Dir['content/**/meta.yaml'].collect do |filename|
+ # Read all meta files
+ pages = Dir['content/**/meta.yaml'].collect do |filename|
+ # Read the meta file
page = @global_page.merge(YAML.load_file_and_clean(filename))
+
+ # Fix the path
page[:path] = filename.sub(/^content/, '').sub('meta.yaml', '')
+ # Get the content filename
content_filenames = Dir[filename.sub('meta.yaml', File.basename(File.dirname(filename)) + '.*')].reject { |f| f =~ /~$/ }
content_filenames += Dir["#{File.dirname(filename)}/index.*"] # fallback for nanoc 1.0
content_filenames.ensure_single('content files', File.dirname(filename))
page[:_content_filename] = content_filenames[0]
page
- end.compact.reject { |page| page[:is_draft] }.sort do |x,y|
- x[:order].to_i == y[:order].to_i ? x[:path] <=> y[:path] : x[:order].to_i <=> y[:order].to_i
end
+
+ # Ignore drafts
+ pages.reject! { |page| page[:is_draft] }
+
+ # Sort pages by order and by path
+ pages.sort! do |x,y|
+ if x[:order].to_i == y[:order].to_i
+ x[:path] <=> y[:path]
+ else
+ x[:order].to_i <=> y[:order].to_i
+ end
+ end
+
+ pages
end
+ # Returns the layout for the given page
+ def layout_for_page(a_page)
+ if a_page[:layout].nil?
+ { :type => :eruby, :content => "<%= @page[:content] %>" }
+ else
+ filenames = Dir["layouts/#{a_page[:layout]}.*"]
+ filenames.ensure_single('layout files', a_page[:layout])
+ filename = filenames[0]
+
+ { :type => FILE_TYPES[File.extname(filename)], :content => File.read(filename) }
+ end
+ end
+
+ # Returns the path for the given page
def path_for_page(a_page)
- @config[:output_dir] + ( a_page[:custom_path].nil? ? a_page[:path] + 'index.' + a_page[:extension] : a_page[:custom_path] )
+ if a_page[:custom_path].nil?
+ @config[:output_dir] + a_page[:path] + 'index.' + a_page[:extension]
+ else
+ @config[:output_dir] + a_page[:custom_path]
+ end
end
+ # Compiles the given pages and returns the compiled pages
def compile_pages(a_pages)
a_pages.inject([]) do |pages, page|
- content = File.read(page[:_content_filename]).filter(page[:filters], :eruby_context => { :page => page, :pages => pages })
- pages + [ page.merge( { :content => content, :_content_filename => nil }) ]
+ # Read page
+ content = File.read(page[:_content_filename])
+
+ # Filter page
+ begin
+ content = content.filter(page[:filters], :assigns => { :page => Page.new(page), :pages => pages })
+ rescue Exception => exception
+ $stderr.puts "Exception occured while compiling page" +
+ "'#{page[:_content_filename]}':" unless $quiet
+ $stderr.puts exception unless $quiet
+ $stderr.puts exception.backtrace.join("\n") unless $quiet
+ exit
+ end
+
+ # Create compiled page
+ compiled_page = page.merge( :content => content )
+
+ # Remember page
+ pages + [ Page.new(compiled_page) ]
end
end
end
end