Class: MasterView::Renderer

Inherits:
Object
  • Object
show all
Includes:
DirectiveHelpers
Defined in:
lib/masterview/parser.rb

Constant Summary

Constants included from DirectiveHelpers

DirectiveHelpers::CRLF, DirectiveHelpers::ERB_END, DirectiveHelpers::ERB_EVAL, DirectiveHelpers::ERB_START

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DirectiveHelpers

#delete_last_in_parent, #find_last_in_parent, #find_string_val_in_string_hash, #lowercase_attribute_keys, #lowercase_attribute_keys_and_values, #merge_into_embedded_hash, #parse, #parse_eval_into_array, #parse_eval_into_hash, #remove_prepended_strings

Constructor Details

#initialize(options = {}) ⇒ Renderer

Returns a new instance of Renderer.



245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/masterview/parser.rb', line 245

def initialize( options = {} )
  @@last_renderer = self; #save last renderer for convenient access
  @default_render_handler = SimpleRenderHandler.new
  @render_levels = [
    RenderLevel.new( [RenderMode.new] )
  ]

  serializer = options[:serializer] || DefaultSerializer
  self.serializer = serializer.is_a?(Class) ? serializer.new : serializer #one can pass in Serializer class or an instance
  self.restrict_output_to_directory = options[:output_dir] || nil
  self.mv_ns = options[:namespace] || NamespacePrefix
  self.directive_load_paths = ( DefaultDirectiveLoadPaths << options[:additional_directive_paths] ).flatten
  self.template_path = options[:template_path] || ''
end

Instance Attribute Details

#default_render_handlerObject

Returns the value of attribute default_render_handler.



241
242
243
# File 'lib/masterview/parser.rb', line 241

def default_render_handler
  @default_render_handler
end

#directive_classesObject

Returns the value of attribute directive_classes.



241
242
243
# File 'lib/masterview/parser.rb', line 241

def directive_classes
  @directive_classes
end

#directive_load_pathsObject

Returns the value of attribute directive_load_paths.



240
241
242
# File 'lib/masterview/parser.rb', line 240

def directive_load_paths
  @directive_load_paths
end

#mv_nsObject

Returns the value of attribute mv_ns.



240
241
242
# File 'lib/masterview/parser.rb', line 240

def mv_ns
  @mv_ns
end

#render_levelsObject

Returns the value of attribute render_levels.



241
242
243
# File 'lib/masterview/parser.rb', line 241

def render_levels
  @render_levels
end

#restrict_output_to_directoryObject

Returns the value of attribute restrict_output_to_directory.



240
241
242
# File 'lib/masterview/parser.rb', line 240

def restrict_output_to_directory
  @restrict_output_to_directory
end

#serializerObject

Returns the value of attribute serializer.



241
242
243
# File 'lib/masterview/parser.rb', line 241

def serializer
  @serializer
end

#template_pathObject

Returns the value of attribute template_path.



241
242
243
# File 'lib/masterview/parser.rb', line 241

def template_path
  @template_path
end

Class Method Details

.last_rendererObject



243
# File 'lib/masterview/parser.rb', line 243

def self.last_renderer; @@last_renderer; end

Instance Method Details

#append_content(type, content) ⇒ Object



334
335
336
337
338
339
340
# File 'lib/masterview/parser.rb', line 334

def append_content(type, content)
  modes.each do |mode|
    if mode.tag
      mode.tag.content << mode.render_directives( type, mode.tag.create_context(:content_part => content) )
    end
  end
end

#append_raw(raw_output) ⇒ Object

does not call any directives, direct output



343
344
345
346
347
348
349
# File 'lib/masterview/parser.rb', line 343

def append_raw(raw_output) 
  modes.each do |mode|
    if mode.tag
      mode.tag.content << raw_output
    end
  end
end

#build_full_attribute_name(mv_ns, directive_class) ⇒ Object

this method is invoked to build the full attribute name (the attribute which will be watched for in html attibutes. It concatenates the namespace prefix to the class name after first removing any module prefixes and then downcasing the first letter



299
300
301
# File 'lib/masterview/parser.rb', line 299

def build_full_attribute_name(mv_ns, directive_class)
  mv_ns+directive_class.name.split(':').last.downcase_first_letter
end

#capitalize_first_letter(string) ⇒ Object



394
395
396
# File 'lib/masterview/parser.rb', line 394

def capitalize_first_letter(string)
  string[0,1].upcase + string[1..-1]
end

#enforce_sandbox!(path) ⇒ Object



313
314
315
316
317
318
319
320
321
# File 'lib/masterview/parser.rb', line 313

def enforce_sandbox!(path)
  unless @restrict_output_to_directory.nil?
    expanded_path = File.expand_path(path, @restrict_output_to_directory)
    unless expanded_path.starts_with? @restrict_output_to_directory
      raise InvalidPathException.new( "invalid path=#{path} resticted to path=#{@restrict_output_to_directory}")
    end
    path.replace expanded_path
  end
end

#modesObject



303
304
305
# File 'lib/masterview/parser.rb', line 303

def modes
  @render_levels.last.render_modes
end

#pop_levelObject



351
352
353
# File 'lib/masterview/parser.rb', line 351

def pop_level
  @render_levels.pop
end

#pop_tagObject



355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
# File 'lib/masterview/parser.rb', line 355

def pop_tag
  need_to_pop_level = false
  modes.each do |mode|
    mode.tag.etag << mode.render_directives(:etag)
    content = []
    content << mode.tag.stag << mode.tag.content << mode.tag.etag
    content = simplify_empty_elements content
    last_tag = mode.tags.pop
    if mode.tags.empty?
      unless mode.output.nil?
        @serializer.serialize(mode, last_tag)
        need_to_pop_level = true
      end
    else #add it to the parent
      mode.tag.content << content
    end
  end
  pop_level if need_to_pop_level
end

#push_level(render_level) ⇒ Object



306
307
308
309
310
311
# File 'lib/masterview/parser.rb', line 306

def push_level(render_level)
  render_level.render_modes.each do |mode|
    enforce_sandbox!(mode.output)
  end
  @render_levels.push render_level
end

#push_tag(tag_name, attributes) ⇒ Object



324
325
326
327
328
329
330
331
332
# File 'lib/masterview/parser.rb', line 324

def push_tag(tag_name, attributes)
  modes.each do |mode|
    attributes_copy = attributes.clone #these get changed in select_active_directives
    directives = select_active_directives(tag_name, attributes_copy, mode)
    parent = (mode.tags.empty?) ? nil : mode.tag
    mode.tags.push Tag.new(directives, tag_name, attributes_copy, mode.mode_type, parent)
    mode.tag.stag << mode.render_directives(:stag)
  end
end

#select_active_directives(tag_name, attributes, mode) ⇒ Object



398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
# File 'lib/masterview/parser.rb', line 398

def select_active_directives(tag_name, attributes, mode)
  selected = DirectiveSet.new
  directives_needed = []
  @auto_directives.each do |directive_class|
    directives_needed << directive_class.new(nil)
  end
  @directive_classes.each do |key,directive_class|
    directives_needed << directive_class.new(attributes.delete(key)) if attributes[key]
  end
  sorted_directives = directives_needed.sort do |x,y| 
    xval = (x.respond_to?(:priority)) ? x.priority : DirectivePriorities::Medium
    yval = (y.respond_to?(:priority)) ? y.priority : DirectivePriorities::Medium
    xval <=> yval
  end
  sorted_directives << @default_render_handler #insure this is last
  selected << sorted_directives
end

#simplify_empty_elements(content) ⇒ Object

relies on the fact that > and </ are individual strings and are back to back with nothing in between



375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/masterview/parser.rb', line 375

def simplify_empty_elements(content) #relies on the fact that > and </ are individual strings and are back to back with nothing in between
  ret = []
  next_to_last = nil
  last = nil
  content.flatten!
  content.each do |item|
    if next_to_last == '>' && last == '</'
      ret.pop #remove '>'
      ret.pop #remove '</'
      ret << '/>'
    else
      ret << item
    end
    next_to_last = last
    last = item
  end
  ret
end