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