lib/masterview/analyzer.rb in masterview-0.2.5 vs lib/masterview/analyzer.rb in masterview-0.3.0

- old
+ new

@@ -1,35 +1,42 @@ module MasterView + + # The Analyzer module provides parsing and analysis services for the + # TemplateSpec class to determine the parts of a template document + # and their up-to-date status + # module Analyzer ExpandAlwaysElements = %w{ script textarea } module Common + def calc_hash(data) #MasterView::Log.warn { 'hash= '+data.hash.to_s+' data='+data } data.gsub( /\s+/, ' ' ).hash #collapse whitespace end def src_hash(data_orig) - data = data_orig.gsub MasterView::NamespacePrefix+'import_render', MasterView::NamespacePrefix+'gen_partial' - data = data.gsub MasterView::NamespacePrefix+'import', MasterView::NamespacePrefix+'generate' + mv_ns = DirectiveRegistry.current.mv_namespace_prefix + data = data_orig.gsub mv_ns+'import_render', mv_ns+'gen_partial' + data = data.gsub mv_ns+'import', mv_ns+'generate' calc_hash(data) end end class ContentEntry include Common attr_accessor :hash, :data - + def initialize(data) @data = data @hash = src_hash(data) end end - + class StackEntry attr_accessor :name, :buffer, :depth, :import, :parts def initialize(name, depth, import) @name = name @@ -58,11 +65,11 @@ end end # builder class facilitates the hash_check and building process by monitoring if all parts of a # file have been requested, if not when a higher index part is requested all the other previous - # parts will be sent along as well, this is necessary for cases where a file doesn't have as many + # parts will be sent along as well, this is necessary for cases where a file doesn't have as many # internal parts or none at all. This way the hash and all the parts of the file will still be there # if layout has two parts and only last part -1 is requested, this builder will give back part 0 and part 1 # if layout would have had three parts then it would have given back all three. # if a part does not exist then it will come back as empty string, same for an index out of bounds class Builder @@ -83,11 +90,11 @@ next_index_to_use = (nind = @builder_hash[name]) ? nind : 0 next_index_to_use = 0 if (-1 == index) && (next_index_to_use+1 > content_parts_length) # allow -1 to rerequest part as needed (singlefile) return '' if content_parts.nil? || (next_index_to_use+1 > content_parts_length) highest_index = content_parts.length - 1 requested_index = (index == -1) ? highest_index : index - content = content_parts[next_index_to_use..requested_index].collect do |ce| + content = content_parts[next_index_to_use..requested_index].collect do |ce| (ce.data.gsub( /\s/, '' ).empty?) ? '' : ce.data # if only white space then get rid of it end.join @builder_hash[name] = requested_index + 1 # store next index to use content end @@ -108,10 +115,23 @@ @only_check_hash = options[:only_check_hash] || false @builder = Builder.new(@content) @default_extname = options[:default_extname] || ::MasterView::IOMgr.erb.default_extension @keyword_expander = KeywordExpander.new @keyword_expander.set_template_pathname( options[:template_pathname], @default_extname ) if options[:template_pathname] + mv_ns = DirectiveRegistry.current.mv_namespace_prefix + @mv_processing_directives = { + # attribute_qname => directive_type_flags + mv_ns+'generate' => { :partial => false, :import => false }, + mv_ns+'gen_partial' => { :partial => true, :import => false }, + mv_ns+'import' => { :partial => false, :import => true }, + mv_ns+'import_render' => { :partial => true, :import => true }, + } + @mv_import_directive_mappings = { + # mv:import and mv:import_render get mapped to generate directives during analysis + mv_ns+'import_render' => mv_ns+'gen_partial', + mv_ns+'import' => mv_ns+'generate', + } Log.debug { "only_check_hash => true" } if @only_check_hash end def only_check_hash? @only_check_hash @@ -123,60 +143,54 @@ def start_document #todo end - def doctype(name, pub, sys, long_name, uri) + def doctype(name, pub_sys, long_name, uri) #todo end def start_element(uri, localname, qname, attributes) unescape_attributes!(attributes) @depth += 1 + # expand the target specification to the actual path for import/generate directives in case of rebuilding + path = nil import = false - if attributes[::MasterView::NamespacePrefix+'generate'] - path = @keyword_expander.expand_keywords(attributes[::MasterView::NamespacePrefix+'generate']) - attributes[::MasterView::NamespacePrefix+'generate'] = path # put back expanded version in case of rebuilding - elsif attributes[::MasterView::NamespacePrefix+'gen_partial'] - expanded_partial_attr = @keyword_expander.expand_keywords(attributes[::MasterView::NamespacePrefix+'gen_partial']) - attributes[::MasterView::NamespacePrefix+'gen_partial'] = expanded_partial_attr # put back expanded version in case of rebuilding - partial = find_string_val_in_string_hash( expanded_partial_attr, :partial) - path = render_partial_name_to_file_name(partial, @default_extname) - elsif attributes[::MasterView::NamespacePrefix+'import'] - path = @keyword_expander.expand_keywords(attributes[::MasterView::NamespacePrefix+'import']) - attributes[::MasterView::NamespacePrefix+'import'] = path # put back expanded version in case of rebuilding - import = true - elsif attributes[::MasterView::NamespacePrefix+'import_render'] - expanded_partial_attr = @keyword_expander.expand_keywords(attributes[::MasterView::NamespacePrefix+'import_render']) - attributes[::MasterView::NamespacePrefix+'import_render'] = expanded_partial_attr # put back expanded version in case of rebuilding - partial = find_string_val_in_string_hash( expanded_partial_attr, :partial) - path = render_partial_name_to_file_name(partial, @default_extname) - import = true - end + @mv_processing_directives.each_pair { | mv_attr_name, directive_type_flags | + if attributes.has_key?( mv_attr_name ) + expanded_attr_value = @keyword_expander.expand_keywords(attributes[mv_attr_name]) + attributes[mv_attr_name] = expanded_attr_value + if directive_type_flags[:partial] + partial = find_string_val_in_string_hash( expanded_attr_value, :partial ) + path = render_partial_name_to_file_name(partial, @default_extname) + else + path = expanded_attr_value + end + import = directive_type_flags[:import] + break + end + } if path store_last_buffer false @stack << StackEntry.new(path, @depth, import) end unless @stack.empty? - @stack.last.buffer << "<#{qname}" + @stack.last.buffer << "<#{qname}" sorted_attributes = attributes.sort do |a,b| # sort import and import_render like generate and gen_partial so hashs work a_working = a[0] b_working = b[0] working_cmp = [a_working, b_working].collect do |working| - if working == ::MasterView::NamespacePrefix+'import_render' - working = ::MasterView::NamespacePrefix+'gen_partial' - elsif working == ::MasterView::NamespacePrefix+'import' - working = ::MasterView::NamespacePrefix+'generate' - end + # mv:import and mv:import_render to generate directives + working = @mv_import_directive_mappings.fetch(working, working) working end working_cmp[0] <=> working_cmp[1] end - sorted_attributes.each do |name, value| + sorted_attributes.each do |name, value| @stack.last.buffer << " #{name}=\"#{value}\"" end @stack.last.buffer << '>' #must output as separate string so simplify_empty_elements can find it end end @@ -200,10 +214,10 @@ @stack.last.buffer << '/>' else @stack.last.buffer << '</' << "#{qname}>" #must output </ as separate string so simplify_empty_elements can find it end end - + if @stack.last && @depth == @stack.last.depth store_last_buffer true @stack.pop end @depth -= 1