module MasterView # Mixin services for directive implementation classes. # # Subclasses of MasterView::DirectiveBase inherit this mixin. # module DirectiveHelpers CRLF = "\r\n" # start of ERB which is evaluated but does not contribute content to the document ERB_EVAL_START = '<% ' # end of ERB which is evaluated but does not contribute content to the document ERB_EVAL_END = ' -%>' # start of ERB whose evaluation results in content in the document ERB_CONTENT_START = '<%= ' # end of ERB whose evaluation results in content in the document ERB_CONTENT_END = ' %>' ####OBSOLETE: SWEEP AND REMOVE ERB_START = ERB_EVAL_START #:nodoc: #WAS: '<% ' ERB_EVAL = ERB_CONTENT_START #:nodoc: #WAS: '<%= ' ERB_END = ERB_CONTENT_END #:nodoc: #WAS: ' %>' #convenience constants defined to allow priority to directives #higher priority (lower value) will be executed first in chain module DirectivePriorities Highest = 0 UltraHigh = 0x3FFFFFFF/16 VeryHigh = 0x3FFFFFFF/8 High = 0x3FFFFFFF/4 MediumHigh = 0x3FFFFFFF/3 Medium = 0x3FFFFFFF/2 MediumLow = (0x3FFFFFFF/3)*2 Low = (0x3FFFFFFF/4)*3 VeryLow = (0x3FFFFFFF/8)*7 UltraLow = (0x3FFFFFFF/16)*15 Lowest = 0x3FFFFFFF end # convert render_partial_name to file_name, ex foo/bar to foo/_bar.rhtml def render_partial_name_to_file_name(render_partial_name, default_extension) pathname = Pathname.for_path(render_partial_name) dir_pathname = pathname.dirname base = pathname.basename(pathname.extname).to_s filename = '_'+base filename += default_extension if default_extension path = (dir_pathname+filename).to_s end # find the last string that fully matches exactly the # parent tags content string array # It looks for something that has been output as a unit in # the array not a substring # returns the ref to the string which you can operate on # using replace def find_last_in_parent(tag, full_string) ret = nil parent = tag.parent unless parent.nil? parent.content.reverse.each do |str| if str == full_string ret = str break end end end ret end # set the last occurence to empty string # returns true if found and set to empty string def delete_last_in_parent(tag, full_string) str = find_last_in_parent(tag, full_string) found = !str.nil? str.replace('') if found found end # find a hash value from inside a simple str containing a hash # non-evaling, looks for a :key => 'foo/bar' returning foo/bar string def find_string_val_in_string_hash(str, key_or_sym) key = key_or_sym.to_s m = str.match( Regexp.new( Regexp.escape(key)+"\s*=>\s*'([^']*)'" ) ) #try single quote m = str.match( Regexp.new( Regexp.escape(key)+"\s*=>\s*\"([^\"]*)\"" ) ) if m.nil? #try double quote return nil if m.nil? m[1] end #returns an array of args by parsing and evaling the str value passed in #uses evaling, so can't have any variables only simple strings, numbers, booleans def parse_eval_into_array(value) return [] if value.nil? || value.empty? val = value.strip args = [] until val.empty? if val =~ /^[:'"%\[{&*]/ #starts with quote or ruby lang char v = nil val = '{'+val+'}' if val =~ /^:/ #starts with colon, assume hash so wrap with brackets eval 'v = '+ val #rest is all evaled if v.is_a? Array args += v else args << v end break else unquoted_string = val.slice!( /^[^,]+/ ) #pull off everything up to a comma unquoted_string.strip! args.push unquoted_string val.slice!( /^,/ ) #strip off comma if exists val.strip! end end args end #returns a hash, for values that are not already part of hash it adds them using default_key #uses evaling so it cannot have any variables or non-simple types def parse_eval_into_hash(value, default_key) h = {} a = parse_eval_into_array(value) a.each do |v| if v.is_a?(Hash) h.merge!(v) else #it adds any additional non-hash args using default key, if key,val exists, it changes to array and appends prev = h[default_key] if prev.nil? #nil just add it h[default_key] = v elsif prev.is_a?(Array) #was array, concat h[default_key] = prev+v else #anything else, make it into array h[default_key] = [prev, v] end end end h end #parse into array of strings, containing the various arguments without evaling #looks for %q{}, %q[], hash, array, function call using (), values deliminated by commas, def parse(str) AttrStringParser.parse(str) end #remove any strings that were prepended to the hashes, typically these are overridden by other values, so # we need to strip them off leaving only the hashes, returns a string with only hashes def remove_prepended_strings(full_string) return full_string if full_string.nil? || full_string.strip.empty? hashes = full_string.scan( /(\{?)\s*(\S+\s*=>.*)/ ).flatten hashes.join.strip end #merge hash_to_merge values into the hash contained in the full_string, hash_arg is zero based index of which #hash this needes to be merged to if there are multiple ones. def merge_into_embedded_hash(full_string, hash_arg, hash_to_merge) return full_string if hash_to_merge.empty? full_string ||= "" sorted_hash_to_merge = hash_to_merge.sort { |a,b| a.to_s <=> b.to_s } #sort, remember the keys might be symbols so use to_s str_to_merge = sorted_hash_to_merge.collect{ |h,v| "#{h.inspect} => #{v.inspect}" }.join(', ') hashes = full_string.scan( /(\{?[^{}]+=>[^{}]+\}?)\s*,?\s*/ ).flatten hash_str = hashes[hash_arg] #be careful to use methods to update string in place or else put back in hash if hash_str.nil? hashes.each do |v| #make sure each prior hash has brackets, since we are adding a hash unless v.index '}' v.insert(0, '{') v.insert(-1, '}') end end hashes[hash_arg] = hash_str = "" end closing_brack = hash_str.index '}' if closing_brack hash_str.insert(closing_brack, ', '+str_to_merge) else hash_str << ', ' unless hash_str.empty? hash_str << str_to_merge end hashes.join(', ') end #return attributes with lowercase keys def lowercase_attribute_keys(attributes) lcattrs = {} attributes.each { |k,v| lcattrs[k.downcase] = v } lcattrs end #return attributes with lowercase keys and values def lowercase_attribute_keys_and_values(attributes) lcattrs = {} attributes.each { |k,v| lcattrs[k.downcase] = v.downcase } lcattrs end # using hash, symbolize keys, sort keys, serialize to string def symbolize_sort_and_serialize_hash_to_str(hash) symbolized = {} hash.each{ |k,v| symbolized[k.to_sym] = v } #symbolize sorted = symbolized.sort{ |a,b| a[0].to_s <=> b[0].to_s } # sort the keys sorted_strings = sorted.collect{ |k,v| "#{k.inspect} => '#{v}'"} # create strings sorted_strings.join(', ') # finally combine them end end end