class Awestruct::Engine

Attributes

config[R]
pipeline[R]
site[R]

Public Class Methods

instance() click to toggle source
# File lib/awestruct/engine.rb, line 35
def self.instance
  @instance
end
instance=(engine) click to toggle source
# File lib/awestruct/engine.rb, line 39
def self.instance=(engine)
  @instance = engine
end
new(config=Awestruct::Config.new) click to toggle source
# File lib/awestruct/engine.rb, line 43
def initialize(config=Awestruct::Config.new)
  Engine.instance = self
  @site = Site.new( self, config)
  @pipeline = Pipeline.new
  @site_page_loader = PageLoader.new( @site )
  @layout_page_loader = PageLoader.new( @site, :layouts )
  @config = config
end

Public Instance Methods

adjust_load_path() click to toggle source
# File lib/awestruct/engine.rb, line 262
def adjust_load_path
  ext_dir = File.join( site.config.extension_dir )
  if $LOAD_PATH.index(ext_dir).nil?
    $LOAD_PATH << ext_dir
  end
end
build_page_index() click to toggle source
# File lib/awestruct/engine.rb, line 128
def build_page_index
  site.pages_by_relative_source_path = {}
  site.pages_by_output_path = {}
  site.pages.each do |p|
    # Add the layout to the set of dependencies
    p.dependencies.add_dependency(site.layouts.find_matching(p.layout, p.output_extension))
    if p.relative_source_path
      site.pages_by_relative_source_path[ p.relative_source_path ] = p
    end
    site.pages_by_output_path[ p.output_path ] = p
  end
  site.layouts.each do |p|
    # Add the layout to the set of dependencies
    p.dependencies.add_dependency(site.layouts.find_matching(p.layout, p.output_extension))

    if p.relative_source_path
      site.pages_by_relative_source_path[ p.relative_source_path ] = p
    end
  end
end
configure_compass() click to toggle source
# File lib/awestruct/engine.rb, line 316
def configure_compass 
  site.images_dir      = File.join( site.config.dir, 'images' )
  site.fonts_dir       = File.join( site.config.dir, 'fonts' )
  site.sass_dir        = File.join( site.config.dir, 'stylesheets' )
  site.css_dir         = File.join( site.config.output_dir, 'stylesheets' )
  site.javascripts_dir = File.join( site.config.dir, 'javascripts' )

  ::Compass.configuration do |config|
    config.project_type = :stand_alone
    config.environment = site.profile
    config.project_path = site.config.dir
    config.sass_path = File.join(config.project_path, 'stylesheets')
    config.asset_host = lambda { |_| site.base_url || site.config.options.base_url || '/' }
    config.css_path = File.join(site.output_dir, 'stylesheets')
    config.javascripts_path = File.join(site.output_dir, 'javascripts')
    config.http_javascripts_dir = 'javascripts'
    config.http_stylesheets_dir = 'stylesheets'
    config.sprite_load_path = [config.images_path]
    config.http_images_dir = 'images'
    config.images_path = File.join(config.project_path, 'images')
    config.fonts_dir = 'fonts'
    config.fonts_path = File.join(config.project_path, 'fonts')
    config.http_fonts_dir = 'fonts'

    if config.generated_images_dir == config.default_for('generated_images_dir')
      config.generated_images_dir = File.join(site.output_dir, 'images')
      config.http_generated_images_dir = 'images'
    end

    config.line_comments = lambda do
      if site.profile.eql? 'production'
        return false
      else
        if site.key? :compass_line_comments
          return site.compass_line_comments 
        end
        if site.key?(:scss) && site.scss.key?(:line_comments)
          return site.scss.line_comments
        end
        if site.key?(:sass) && site.sass.key?(:line_comments)
          return site.sass.line_comments
        end
        true
      end
    end.call

    config.output_style = lambda do
      if site.profile.eql? 'production'
        return :compressed
      else
        if site.key? :compass_output_style
          return site.compass_output_style
        end
        if (site.key? :scss) && (site.scss.key? :style)
          return site.scss.style
        end
        if (site.key? :sass) && (site.sass.key? :style)
          return site.sass.style
        end
      end
      :expanded
    end.call

    config.relative_assets = false
  end

  compass_config_file = File.join(site.config.config_dir, 'compass.rb')
  if File.exist? compass_config_file
    ::Compass.add_configuration ::Compass::Configuration::FileData.new_from_file(compass_config_file) 
  end 
  ::Compass.configuration # return for use elsewhere

  # TODO: Should we add an on_stylesheet_error block?
end
create_context(page, content='') click to toggle source
# File lib/awestruct/engine.rb, line 562
def create_context(page, content='')
  page.create_context( content )
end
execute_pipeline(on_reload = false) click to toggle source
# File lib/awestruct/engine.rb, line 310
def execute_pipeline(on_reload = false)
  FileUtils.mkdir_p( site.config.output_dir )
  FileUtils.mkdir_p( site.config.tmp_dir )
  pipeline.execute( site, on_reload )
end
find_and_load_site_page(simple_path) click to toggle source
# File lib/awestruct/engine.rb, line 551
def find_and_load_site_page(simple_path)
  path_glob = File.join( site.config.input_dir, simple_path + '.*' )
  candidates = Dir[ path_glob ]
  return nil if candidates.empty?
  throw Exception.new( "too many choices for #{simple_path}" ) if candidates.size != 1
  dir_pathname = Pathname.new( site.config.dir )
  path_name = Pathname.new( candidates[0] )
  path_name.relative_path_from( dir_pathname ).to_s
  load_page( candidates[0] )
end
find_transitive_dependents(page) click to toggle source
# File lib/awestruct/engine.rb, line 566
def find_transitive_dependents(page)
  deps = Set.new 
  deps << page
  if page.dependencies.dependents.size > 0
    page.dependencies.dependents.to_a.inject(deps) do |set, p| 
      set.merge find_transitive_dependents(p)
      set
    end
  end
  deps
end
generate_output() click to toggle source
# File lib/awestruct/engine.rb, line 398
def generate_output
  FileUtils.mkdir_p( site.config.output_dir )
  return_value = [Awestruct::ExceptionHelper::EXITCODES[:success]]
  begin
    $LOG.verbose "Using the following options from site.generation: #{site.generation}" if config.verbose
    return_value = Parallel.map(@site.pages, site.generation) do |page|
      start_time = DateTime.now
      return_value = generate_page( page )
      $LOG.trace "Total time generating #{page.output_path} #{DateTime.now.to_time - start_time.to_time} seconds" if config.verbose && config.perf

      return_value
    end
  rescue Exception => e
    Awestruct::ExceptionHelper.log_error e
    return_value = [Awestruct::ExceptionHelper::EXITCODES[:generation_error]]
  end

  if return_value.nil? || return_value.include?(Awestruct::ExceptionHelper::EXITCODES[:generation_error])
    $LOG.error 'An error occurred during output generation, all pages may not have completed during generation'
    exit Awestruct::ExceptionHelper::EXITCODES[:generation_error]
  end
  site.engine.pipeline.execute_after_generation(site)
end
generate_page(page, produce_output=true) click to toggle source
# File lib/awestruct/engine.rb, line 422
def generate_page(page, produce_output=true)
  if produce_output
    generated_path = File.join( site.config.output_dir, page.output_path )
    $LOG.debug "Generating: #{generated_path}" if config.verbose && config.debug

    c = ''
    begin
      c = page.rendered_content
      c = site.engine.pipeline.apply_transformers( site, page, c )

      FileUtils.mkdir_p( File.dirname( generated_path ) )

      File.open( generated_path, 'wb' ) do |file|
        file << c
      end
    rescue Exception => e
      Awestruct::ExceptionHelper.log_building_error e, page.relative_source_path
      return Awestruct::ExceptionHelper::EXITCODES[:generation_error]
    ensure
      return Awestruct::ExceptionHelper::EXITCODES[:generation_error] if c.include? 'Backtrace:'
    end
    Awestruct::ExceptionHelper::EXITCODES[:success]
  elsif site.config.track_dependencies
    if page.dependencies.load!
      $LOG.debug "Cached:     #{generated_path}" if config.debug
    else
      $LOG.debug "Analyzing:  #{generated_path}" if config.debug
      page.rendered_content
    end
    return Awestruct::ExceptionHelper::EXITCODES[:success]
  end
end
generate_page_and_dependencies(page) click to toggle source
# File lib/awestruct/engine.rb, line 466
def generate_page_and_dependencies(page)

  if page.nil?
    return
  end

  if !page.output_path.nil? && !page.is_partial? && !page.__is_layout
    generate_page_internal(page)
  end

  regen_pages = page_dependencies( page )

  $LOG.debug 'Starting regeneration of content dependent pages:' if regen_pages.size > 0 && config.debug

  regen_pages.each do |p|
    $LOG.info "Regenerating page #{p.output_path}"
    generate_page_internal(p)
  end

  regen_pages
end
generate_page_internal(p) click to toggle source
# File lib/awestruct/engine.rb, line 524
def generate_page_internal(p)
  unless p.output_path.nil? || p.__is_layout || !p.stale_output?(p.output_path)
    generate_page( p )
  end
end
load_default_site_yaml(profile = nil) click to toggle source
# File lib/awestruct/engine.rb, line 166
def load_default_site_yaml(profile = nil)
  default_site_yaml_path = File.join( File.dirname( __FILE__ ), 'config', 'default-site.yml' )
  load_site_yaml( default_site_yaml_path, profile )
end
load_page(path, options={}) click to toggle source

compat with awestruct 0.2.x

# File lib/awestruct/engine.rb, line 534
def load_page(path, options={})
  page = @site_page_loader.load_page( path )
  if options[:relative_path]
    fixed_relative_path = ( options[:relative_path].nil? ? nil : File.join( '', options[:relative_path] ) )
    page.relative_path = fixed_relative_path
  end
  page
end
load_pages() click to toggle source
# File lib/awestruct/engine.rb, line 391
def load_pages
  $LOG.debug "layout_page_loader.load_all :post" if config.debug
  @layout_page_loader.load_all( :post )
  $LOG.debug "site_page_loader.load_all :inline" if config.debug 
  @site_page_loader.load_all( :inline )
end
load_pipeline() click to toggle source
# File lib/awestruct/engine.rb, line 284
def load_pipeline
  ext_dir = File.join( site.config.extension_dir )
  pipeline_file = File.join( ext_dir, 'pipeline.rb' )
  if File.exist?(pipeline_file)
    p = eval(File.read( pipeline_file ), nil, pipeline_file, 1)
    p.before_all_extensions.each do |e|
      pipeline.add_before_extension( e )
    end
    p.extensions.each do |e|
      pipeline.extension( e )
    end
    p.after_all_extensions.each do |e|
      pipeline.add_after_extension( e )
    end
    p.helpers.each do |h|
      pipeline.helper( h )
    end
    p.transformers.each do |t|
      pipeline.transformer( t )
    end
    p.after_generation_extensions.each do |e|
      pipeline.add_after_generation_extension( e )
    end
  end
end
load_site_page(relative_path) click to toggle source
# File lib/awestruct/engine.rb, line 543
def load_site_page(relative_path)
  if Pathname.new(relative_path).absolute?
    load_page( relative_path )
  else
    load_page( Pathname.new(File.join(site.config.dir, relative_path)) )
  end
end
load_site_yaml(yaml_path, profile = nil) click to toggle source
# File lib/awestruct/engine.rb, line 182
def load_site_yaml(yaml_path, profile = nil)
  if File.exist?(yaml_path)
    begin
      data = Awestruct.yaml_load( ERB.new(File.read( yaml_path, :encoding => 'bom|utf-8' ), trim_mode: '<>').result)
      if profile
        # JP: Interpolation now turned off by default, turn it per page if needed
        site.interpolate = false
        profile_data = {}
        data.each do |k,v|
          if (k == 'profiles') && (!profile.nil?)
            profile_data = ( v[profile] || {} )
          else
            site.send( "#{k}=", merge_data( site.send( "#{k}" ), v ) )
          end
        end if data
        site.profile = profile
        profile_data.each do |k,v|
          site.send( "#{k}=", merge_data( site.send( "#{k}" ), v ) )
        end
      else
        data.each do |k,v|
          site.send( "#{k}=", v )
        end if data
      end
    rescue Exception => e
      ExceptionHelper.log_building_error e, yaml_path
      ExceptionHelper.mark_failed
    end
  end
end
load_user_site_yaml(profile = nil) click to toggle source
# File lib/awestruct/engine.rb, line 171
def load_user_site_yaml(profile = nil)
  site_yaml_path = File.join( site.config.config_dir, 'site.yml' )
  load_site_yaml( site_yaml_path, profile )
end
load_yaml(yaml_path) click to toggle source
# File lib/awestruct/engine.rb, line 213
def load_yaml(yaml_path)
  begin
    data = Awestruct.yaml_load( ERB.new(File.read( yaml_path ), trim_mode: '<>').result )
  rescue Exception => e
    ExceptionHelper.log_building_error e, yaml_path
    ExceptionHelper.mark_failed
  end
  name = File.basename( yaml_path, '.yml' )
  site.send( "#{name}=", massage_yaml( data ) )
end
load_yamls() click to toggle source
# File lib/awestruct/engine.rb, line 176
def load_yamls
  Dir[ File.join( site.config.config_dir, '*.yml' ) ].each do |yaml_path|
    load_yaml( yaml_path ) unless ( File.basename( yaml_path ) == 'site.yml' )
  end
end
massage_yaml(obj) click to toggle source
# File lib/awestruct/engine.rb, line 244
def massage_yaml(obj)
  result = obj
  case ( obj )
    when Hash
      result = {}
      obj.each do |k,v|
        result[k] = massage_yaml(v)
      end
      result = AStruct.new( result ).cascade_for_nils!
    when Array
      result = []
      obj.each do |v|
        result << massage_yaml(v)
      end
  end
  result
end
merge_data(existing, new) click to toggle source
# File lib/awestruct/engine.rb, line 224
def merge_data(existing, new)
  if existing.kind_of? Hash
    result = existing.inject({}) do |merged, (k,v)|
      if new.has_key? k
        if v.kind_of? Hash
          merged[k] = merge_data(v, new.delete(k))
        else
          merged[k] = new.delete(k)
        end
      else
        merged[k] = v
      end
      merged
    end
    result.merge new
  else
    new
  end
end
page_by_source_path(path) click to toggle source

path - relative to output dir

# File lib/awestruct/engine.rb, line 456
def page_by_source_path(path)
  if path.include? '_layout'
    site.layouts.find { |p| p.source_path.to_s.include? path }
  elsif path.include? '_partial'
    site.partials.find { |p| p.source_path.to_s.include? path }
  else
    site.pages.find { |p| p.source_path.to_s.include? path }
  end
end
page_dependencies(page) click to toggle source
# File lib/awestruct/engine.rb, line 488
def page_dependencies(page)
  regen_pages = Set.new [ page ] 
  regen_pages.merge page.dependencies.dependents

  # doing this in case someone has used key dependencies
  page.dependencies.key_dependents.each do |kd|
    if kd.is_a? Page
      regen_pages << kd
    end    
  end

  temp_set = Set.new
  regen_pages.each do |p|
    temp_set.merge find_transitive_dependents(page) 
  end

  regen_pages.merge temp_set
end
run(profile, base_url, default_base_url, force=false, generate=true) click to toggle source
# File lib/awestruct/engine.rb, line 56
def run(profile, base_url, default_base_url, force=false, generate=true)
  start_time = DateTime.now
  $LOG.verbose 'adjust_load_path' if config.verbose
  adjust_load_path
  $LOG.trace "Total time in adjust_load_path: #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf

  $LOG.verbose 'load_default_site_yaml' if config.verbose
  start_time = DateTime.now
  load_default_site_yaml( profile )
  $LOG.trace "Total time in load_default_site_yaml #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf

  $LOG.verbose 'load_user_site_yaml -- profile' if config.verbose
  start_time = DateTime.now
  load_user_site_yaml( profile )
  $LOG.trace "Total time in load_user_site_yaml #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf

  $LOG.verbose 'set_base_url' if config.verbose
  start_time = DateTime.now
  set_base_url( base_url, default_base_url )
  $LOG.trace "Total time in set_base_url #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf

  $LOG.verbose 'load_yamls' if config.verbose
  start_time = DateTime.now
  load_yamls
  $LOG.trace "Total time in load_yamls #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf

  $LOG.verbose 'load_pipeline' if config.verbose
  start_time = DateTime.now
  load_pipeline
  $LOG.trace "Total time in load_pipeline #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf

  $LOG.verbose 'load_pages' if config.verbose
  start_time = DateTime.now
  load_pages
  $LOG.trace "Total time in load_pages #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf

  $LOG.verbose 'execute_pipeline' if config.verbose
  $LOG.info 'Executing pipeline...'
  start_time = DateTime.now
  execute_pipeline(false)
  $LOG.trace "Total time in execute_pipeline #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf

  begin
    if defined?(::Compass)
      $LOG.verbose 'configure_compass' if config.verbose
      start_time = DateTime.now
      configure_compass
      $LOG.trace "Total time in configure_compass #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf
    end
  rescue LoadError
    # doesn't matter if we can't load it
  end
  $LOG.verbose 'set_urls' if config.verbose
  start_time = DateTime.now
  set_urls( site.pages )
  $LOG.trace "Total time in set_urls #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf

  $LOG.verbose 'build_page_index' if config.verbose
  start_time = DateTime.now
  build_page_index
  $LOG.trace "Total time in build_page_index #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf

  if generate
    $LOG.debug 'generate_output' if config.debug
    $LOG.info 'Generating pages...'
    start_time = DateTime.now
    generate_output
    $LOG.trace "Total time in generate_output #{DateTime.now.to_time - start_time.to_time} seconds" if config.perf
  end
  Awestruct::ExceptionHelper::EXITCODES[:success]
end
run_auto_for_non_page(file, generate = true) click to toggle source
# File lib/awestruct/engine.rb, line 507
def run_auto_for_non_page(file, generate = true)
  if File.extname(file) == '.rb'
    load file
  end
  @pipeline = Pipeline.new
  load_yamls
  load_pipeline
  execute_pipeline(true)

  if generate
    site.pages.each do |p|
      generate_page_internal(p)
    end
  end
  site.pages
end
set_base_url(base_url, default_base_url) click to toggle source
# File lib/awestruct/engine.rb, line 149
def set_base_url(base_url, default_base_url)
  if base_url
    site.base_url = base_url
  end

  if site.base_url.nil?
    site.base_url = default_base_url
  end

  if site.base_url
    if site.base_url =~ /^(.*)\/$/
      site.base_url = $1
    end
  end

end
set_urls(pages) click to toggle source
# File lib/awestruct/engine.rb, line 269
def set_urls(pages)
  pages.each do |page|
    $LOG.debug "relative_source_path #{page.relative_source_path}" if config.debug
    page_path = page.output_path
    if page_path =~ /^\//
      page.url = page_path
    else
      page.url = "/#{page_path}"
    end
    if page.url =~ /^(.*\/)index.html$/
      page.url = $1
    end
  end
end