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