lib/squib/layout_parser.rb in squib-0.6.0 vs lib/squib/layout_parser.rb in squib-0.7.0

- old
+ new

@@ -1,89 +1,91 @@ -module Squib - # Internal class for handling layouts - #@api private - class LayoutParser - - # Load the layout file(s), if exists - # @api private - def self.load_layout(files) - layout = {} - Squib::logger.info { " using layout(s): #{files}" } - Array(files).each do |file| - thefile = file - thefile = builtin(file) unless File.exists?(file) - if File.exists? thefile - yml = layout.merge(YAML.load_file(thefile) || {}) #load_file returns false on empty file - yml.each do |key, value| - layout[key] = recurse_extends(yml, key, {}) - end - else - Squib::logger.error { "Layout file not found: #{file}. Skipping..." } - end - end - return layout - end - - # Determine the file path of the built-in layout file - def self.builtin(file) - "#{File.dirname(__FILE__)}/layouts/#{file}" - end - - # Process the extends recursively - # :nodoc: - # @api private - def self.recurse_extends(yml, key, visited ) - assert_not_visited(key, visited) - return yml[key] unless has_extends?(yml, key) - return yml[key] unless parents_exist?(yml, key) - visited[key] = key - parent_keys = [yml[key]['extends']].flatten - h = {} - parent_keys.each do |parent_key| - from_extends = yml[key].merge(recurse_extends(yml, parent_key, visited)) do |key, child_val, parent_val| - if child_val.to_s.strip.start_with?('+=') - parent_val + child_val.sub('+=','').strip.to_f - elsif child_val.to_s.strip.start_with?('-=') - parent_val - child_val.sub('-=','').strip.to_f - else - child_val #child overrides parent when merging, no += - end - end - h = h.merge(from_extends) do |key, older_sibling, younger_sibling| - younger_sibling #when two siblings have the same entry, the "younger" (lower one) overrides - end - end - return h - end - - # Does this layout entry have an extends field? - # i.e. is it a base-case or will it need recursion? - # :nodoc: - # @api private - def self.has_extends?(yml, key) - !!yml[key] && yml[key].key?('extends') - end - - # Checks if we have any absentee parents - # @api private - def self.parents_exist?(yml, key) - exists = true - Array(yml[key]['extends']).each do |parent| - unless yml.key?(parent) - exists = false unless - Squib.logger.error "Processing layout: '#{key}' attempts to extend a missing '#{yml[key]['extends']}'" - end - end - return exists - end - - # Safeguard against malformed circular extends - # :nodoc: - # @api private - def self.assert_not_visited(key, visited) - if visited.key? key - raise "Invalid layout: circular extends with '#{key}'" - end - end - - end -end \ No newline at end of file +require 'yaml' + +module Squib + # Internal class for handling layouts + #@api private + class LayoutParser + + # Load the layout file(s), if exists + # @api private + def self.load_layout(files) + layout = {} + Squib::logger.info { " using layout(s): #{files}" } + Array(files).each do |file| + thefile = file + thefile = builtin(file) unless File.exists?(file) + if File.exists? thefile + yml = layout.merge(YAML.load_file(thefile) || {}) #load_file returns false on empty file + yml.each do |key, value| + layout[key] = recurse_extends(yml, key, {}) + end + else + Squib::logger.error { "Layout file not found: #{file}. Skipping..." } + end + end + return layout + end + + # Determine the file path of the built-in layout file + def self.builtin(file) + "#{File.dirname(__FILE__)}/layouts/#{file}" + end + + # Process the extends recursively + # :nodoc: + # @api private + def self.recurse_extends(yml, key, visited ) + assert_not_visited(key, visited) + return yml[key] unless has_extends?(yml, key) + return yml[key] unless parents_exist?(yml, key) + visited[key] = key + parent_keys = [yml[key]['extends']].flatten + h = {} + parent_keys.each do |parent_key| + from_extends = yml[key].merge(recurse_extends(yml, parent_key, visited)) do |key, child_val, parent_val| + if child_val.to_s.strip.start_with?('+=') + parent_val + child_val.sub('+=','').strip.to_f + elsif child_val.to_s.strip.start_with?('-=') + parent_val - child_val.sub('-=','').strip.to_f + else + child_val #child overrides parent when merging, no += + end + end + h = h.merge(from_extends) do |key, older_sibling, younger_sibling| + younger_sibling #when two siblings have the same entry, the "younger" (lower one) overrides + end + end + return h + end + + # Does this layout entry have an extends field? + # i.e. is it a base-case or will it need recursion? + # :nodoc: + # @api private + def self.has_extends?(yml, key) + !!yml[key] && yml[key].key?('extends') + end + + # Checks if we have any absentee parents + # @api private + def self.parents_exist?(yml, key) + exists = true + Array(yml[key]['extends']).each do |parent| + unless yml.key?(parent) + exists = false unless + Squib.logger.error "Processing layout: '#{key}' attempts to extend a missing '#{yml[key]['extends']}'" + end + end + return exists + end + + # Safeguard against malformed circular extends + # :nodoc: + # @api private + def self.assert_not_visited(key, visited) + if visited.key? key + raise "Invalid layout: circular extends with '#{key}'" + end + end + + end +end