module StaticMatic class Base # Directories generated for a new site setup @@base_dirs = %w{ site/ site/stylesheets site/images site/javascripts src/ src/pages/ src/layouts src/stylesheets } # Templates for setup and their location @@templates = { 'application.haml' => 'layouts', 'application.sass' => 'stylesheets', 'index.haml' => 'pages' } def initialize(base_dir) @base_dir = base_dir @src_dir = "#{@base_dir}/src" @site_dir = "#{@base_dir}/site" @templates_dir = File.dirname(__FILE__) + '/templates' @layout = "application" @scope = Object.new @scope.instance_variable_set("@base_dir", @base_dir) end def base_dir @base_dir end def run(command) valid_commands = ['build', 'setup', 'preview'] if valid_commands.include?(command) send(command) else puts "#{command} is not a valid StaticMatic command" end end def build build_css build_html end def setup if !File.exists?(@base_dir) Dir.mkdir(@base_dir) end @@base_dirs.each do |directory| directory = "#{@base_dir}/#{directory}" if !File.exists?(directory) Dir.mkdir(directory) puts "created #{directory}" end end @@templates.each do |template, destination| copy_file("#{@templates_dir}/#{template}", "#{@src_dir}/#{destination}") end puts "Done" end def preview puts "StaticMatic Preview Server Starting..." StaticMatic::Server.start(@base_dir) end def copy_file(from, to) FileUtils.cp(from, to) end def save_page(filename, content) filename = "#{filename}" generate_site_file(filename, 'html', content) end def save_stylesheet(filename, content) filename = "stylesheets/#{filename}" generate_site_file(filename, 'css', content) end def generate_site_file(filename, extension, content) path = File.join(@site_dir,"#{filename}.#{extension}") File.open(path, 'w+') do |f| f << content end puts "created #{path}" end def source_for_layout layout_template = "#{@src_dir}/layouts/#{@layout}.haml" if File.exists?(layout_template) File.read(layout_template) else raise StaticMatic::Error.new("", layout_template, "Layout not found") end end # Generate html from source file: # generate_html("index.haml") def generate_html(source_file) full_file_path = "#{@src_dir}/pages/#{source_file}.haml" begin page = Haml::Engine.new(File.read(full_file_path), :locals => {:base_dir => base_dir}) html = page.render(@scope) # TODO: DRY this up if @scope.instance_variable_get("@layout") @layout = @scope.instance_variable_get("@layout") end html rescue Haml::Error => haml_error raise StaticMatic::Error.new(haml_error.haml_line, full_file_path, haml_error.message) end end def generate_html_with_layout(source) begin generated_content = generate_html(source) Haml::Engine.new(source_for_layout, :locals => {:base_dir => base_dir}).render(@scope) { generated_content } rescue StaticMatic::Error => staticmatic_error # Catch any errors from the actual template - otherwise the error will be assumed to be from the # layout raise staticmatic_error rescue Haml::Error => haml_error raise StaticMatic::Error.new(haml_error.haml_line, "Layout: #{@layout}", haml_error.message) end end def generate_css(source) full_file_path = "#{@src_dir}/stylesheets/#{source}.sass" begin stylesheet = Sass::Engine.new(File.read(full_file_path)) stylesheet.to_css rescue Sass::Error => sass_error raise StaticMatic::Error.new(sass_error.sass_line, full_file_path, sass_error.message) end end def template_exists?(name) File.exists?("#{@src_dir}/pages/#{name}.haml") || File.exists?("#{@src_dir}/stylesheets/#{name}.sass") end # Build HTML from the source files def build_html Dir["#{@src_dir}/pages/**/*.haml"].each do |path| template = source_template_from_path(path) save_page(template, generate_html_with_layout(template)) # reset the layout for the next page @scope.instance_variable_set("@layout", "application") end end # Build CSS from the source files def build_css Dir["#{@src_dir}/stylesheets/**/*.sass"].each do |path| template = source_template_from_path(path) save_stylesheet(template, generate_css(template)) end end # Returns a raw template name from a source file path: # source_template_from_path("/path/to/site/src/stylesheets/application.sass") -> "application" def source_template_from_path(path) File.basename(path).chomp(File.extname(path)) end class << self def base_dirs @@base_dirs end end end end