class Amber::Site

Attributes

continue_on_error[RW]
page_list[RW]
root[RW]

Public Class Methods

new(root_dir) click to toggle source
# File lib/amber/site.rb, line 15
def initialize(root_dir)
  @continue_on_error = true
  @config = SiteConfiguration.load(self, root_dir)
end

Public Instance Methods

add_config(config) click to toggle source
# File lib/amber/site.rb, line 20
def add_config(config)
  @config.children << config
end
all_pages() click to toggle source
# File lib/amber/site.rb, line 108
def all_pages
  @page_list
end
clear() click to toggle source
# File lib/amber/site.rb, line 63
def clear
  Dir.glob("#{@config.dest_dir}/*").each do |file|
    FileUtils.rm_r(file)
  end
end
find_page(filter) click to toggle source
# File lib/amber/site.rb, line 104
def find_page(filter)
  find_pages(filter)
end
find_page_by_name(name) click to toggle source
# File lib/amber/site.rb, line 124
def find_page_by_name(name)
  @pages_by_name[name]
end
find_page_by_path(path, locale=I18n.default_locale) click to toggle source
# File lib/amber/site.rb, line 112
def find_page_by_path(path, locale=I18n.default_locale)
  if locale.is_a? String
    if I18n.locale_available?(locale)
      locale = locale.to_sym
    end
  end
  if path.is_a? Array
    path = path.join('/')
  end
  @pages_by_locale_path[locale][path] || @pages_by_path[path]
end
find_pages(filter) click to toggle source

find pages by a filter. filter is a string composing a path segment. For example:

"chat/security"

Which would match “/services/chat/security” but not “/services/security”

# File lib/amber/site.rb, line 83
def find_pages(filter)
  filter = filter.downcase
  if filter =~ /\//
    path = filter.split('/').map{|segment| segment.gsub(/[^0-9a-z_-]/, '')}
    path_str = path.join('/')
    if (page = @pages_by_path[path_str])
      page
    elsif matched_path = @page_paths.grep(/#{Regexp.escape(path_str)}/).first
      @pages_by_path[matched_path]
    elsif page = @pages_by_name[path.last]
      page
    else
      nil
    end
  elsif @pages_by_path[filter]
    @pages_by_path[filter]
  else
    @pages_by_name[filter]
  end
end
load_pages() click to toggle source
# File lib/amber/site.rb, line 24
def load_pages
  @root          = nil
  @pages_by_path = {}  # hash of pages keyed by page path
  @pages_by_name = {}  # hash of pages keyed by page name
  @page_list     = PageArray.new
  @dir_list      = []  # an array of non-page directories
  @page_paths    = []  # an array of page paths, used for greping through paths.

  # some paths are specific to only one locale (e.g aliases)
  @pages_by_locale_path = POSSIBLE_LANGUAGES.keys.inject(Hash.new({})) {|h,locale| h[locale] = {}; h}

  add_configuration(@config)
end
render() click to toggle source

def reload_pages_if_needed

if @pages_by_path.nil? || @config.pages_changed?
  puts "Reloading pages ................."
  load_pages
end

end

# File lib/amber/site.rb, line 45
def render
  @page_list.each do |page|
    page.render_to_file(@config.dest_dir)
    putc '.'; $stdout.flush
  end
  @dir_list.each do |directory|
    src = File.join(@config.pages_dir, directory)
    dst = File.join(@config.dest_dir, directory)
    Render::Asset.render_dir(src, dst)
    putc '.'; $stdout.flush
  end
  if @config.short_paths
    render_short_path_symlinks
  end
  Render::Apache.write_htaccess(@config, @config.pages_dir, @config.dest_dir)
  puts
end
shortest_path(page) click to toggle source

returns the shortest possible path for a page, such that the path doesn't collide with another page or another page's aliases.

# File lib/amber/site.rb, line 132
def shortest_path(page)
  path_so_far = []
  page.path.reverse.each do |path_segment|
    path_so_far.push(path_segment)
    path_str = path_so_far.join('/')
    if @pages_by_path[path_str].nil? && short_paths[path_str] == page
      return path_so_far
    end
  end
  return []
end
with_destination(new_dest) { || ... } click to toggle source
# File lib/amber/site.rb, line 69
def with_destination(new_dest)
  dest_dir = @config.dest_dir
  @config.dest_dir = new_dest
  yield
  @config.dest_dir = dest_dir
end

Private Instance Methods

add_aliases(locale, page, path_hash) click to toggle source

registers a page's aliases with the site

# File lib/amber/site.rb, line 197
def add_aliases(locale, page, path_hash)
  page.aliases(locale).each do |alias_path|
    alias_path_str = alias_path.join('/')
    if path_hash[alias_path_str]
      Amber.logger.warn "WARNING: page `#{page.path.join('/')}` has alias `#{alias_path_str}`, but this path is already taken by `#{path_hash[alias_path_str].path.join('/')}` (locale = #{locale})."
    else
      path_hash[alias_path_str] = page
    end
  end
end
add_configuration(config) click to toggle source
# File lib/amber/site.rb, line 146
def add_configuration(config)
  config.reset_timestamp

  # create base_page
  base_page = begin
    if config.path.nil?
      @root = StaticPage.new(nil, 'root', config.pages_dir)
      add_page(@root)
      @root
    else
      name = File.basename(config.path)
      sub_root = StaticPage.new(find_parent(config.path), name, config.pages_dir, config.path_prefix)
      add_page(sub_root)
      sub_root
    end
  end
  base_page.config = config

  # load menu and locals
  I18n.load_path += Dir[File.join(config.locales_dir, '/**/*.{rb,yml,yaml}')] if config.locales_dir

  # add the full directory tree
  base_page.scan_directory_tree do |page, asset_dir|
    add_page(page) if page
    @dir_list << asset_dir if asset_dir
  end
  @page_paths += @pages_by_path.keys

  # recursively add sub-sites
  config.children.each do |sub_config|
    add_configuration(sub_config)
  end
end
add_page(page) click to toggle source

registers a page with the site, indexing the page path in our various hashes

# File lib/amber/site.rb, line 183
def add_page(page)
  @pages_by_name[page.name] ||= page
  @pages_by_path[page.path.join('/')] = page
  add_aliases(I18n.default_locale, page, @pages_by_path)
  page.locales.each do |locale|
    next if locale == I18n.default_locale
    add_aliases(locale, page, @pages_by_locale_path[locale])
  end
  @page_list << page
end
find_parent(path) click to toggle source
# File lib/amber/site.rb, line 208
def find_parent(path)
  so_far = []
  path.split('/').compact.each do |path_segment|
    so_far << path_segment
    if page = @pages_by_path[so_far.join('/')]
      return page
    end
  end
  return @root
end
pages_in_path_depth_order() click to toggle source

Returns an array like this:

[
  {:page => <page1>, :path => ['a', 'page1']},
  {:page => <page2>, :path => ['a','b', 'page2']},
]

This array is sorted by the depth of the path (shortest first) Pages will appear multiple times (once for each path, including aliases)

# File lib/amber/site.rb, line 280
def pages_in_path_depth_order
  paths = {}
  @page_list.each do |page|
    paths[page.path] ||= page
    locales = page.locales
    locales << I18n.default_locale unless locales.include? I18n.default_locale
    locales.each do |locale|
      page.aliases(locale).each do |alias_path|
        paths[alias_path] ||= page
      end
    end
  end
  paths.collect{|path, page| {page:page, path:path}}.sort{|a,b|
    a[:path].length <=> a[:path].length
  }
end
short_paths() click to toggle source

returns a hash containing all the automatically determined shortest paths for every page. the data structure looks like so:

{

"ddd" => <page 'bbb/ddd'>,
"ccc" => <page 'bbb/ccc'>,
"red" => <page 'autoalias/red'>,
"blue"=> <page 'autoalias/blue'>,
"red/blue" => <page 'autoalias/red/blue'>

}

short_paths does not include the normal paths or normal aliases, just the automatic short path aliases.

# File lib/amber/site.rb, line 245
def short_paths
  @short_paths ||= begin
    hash = {}
    pages_in_path_depth_order.each do |record|
      page = record[:page]
      path = record[:path]
      next if path.length == 1
      path_prefix = path.dup
      path.length.times do |depth|
        path_prefix.shift
        path_str = path_prefix.join('/')
        if @pages_by_path[path_str].nil? && hash[path_str].nil?
          hash[path_str] = page
        end
      end
    end
    # debug:
    #hash.each do |path, record|
    #  puts "#{record[:page].path.join('/')} => #{record[:path].join('/')}"
    #end
    hash
  end
end