lib/gumdrop/renderer.rb in gumdrop-1.1.0 vs lib/gumdrop/renderer.rb in gumdrop-1.1.1

- old
+ new

@@ -2,42 +2,49 @@ class Renderer include Util::SiteAccess SPECIAL_OPTS= %w(layout force_partial) - MUNGABLE_RE= Regexp.new(%Q<(href|data|src)([\s]*)=([\s]*)('|"|&quot;|&#34;|&#39;)?\\/([\\/]?)>, 'i') - attr_reader :context, :cache + attr_reader :context, :cache, :ctx_pool def initialize site.active_renderer= self @context, @content, @opts= nil, nil, nil - @stack= [] + @ctx_pool= ContextPool.new self @cache= {} end def draw(content, opts={}) - event_block :render_item do |data| - data[:content]= content - log.debug " rendering: #{ content.source_filename } (#{ content.uri })" - if content.binary? or content.missing? - log.warn "Missing content body for: #{ content.uri }" - nil - else - opts[:calling_page]= @context unless opts.has_key? :calling_page - _in_context(content, opts) do - data[:context]= @context - data[:output]= _render_content! - @cache[content.source_path]= data[:output] if @context.cache - data[:output] - end + if @ctx_pool.size > 0 + _start_rendering(content, opts) + else + event_block :render_item do |data| + _start_rendering(content, opts, data) end end end private + def _start_rendering(content, opts, data={}) + data[:content]= content + log.debug " rendering: #{ content.source_filename } (#{ content.uri })" + if content.binary? or content.missing? + log.warn "Missing content body for: #{ content.uri }" + nil + else + opts[:calling_page]= @context unless opts.has_key? :calling_page + _in_new_context(content, opts) do + data[:context]= @context + data[:output]= _render_content! + @cache[content.source_path]= data[:output] if @context.cache + data[:output] + end + end + end + def _render_content! output= @content.body _render_pipeline(@content.source_filename) do |template_class| output= _render_text(output, template_class) end @@ -89,15 +96,18 @@ sub_layout= _sub_layout_for(sub_layout) end end end + HTML_MUNGABLE_RE= Regexp.new(%Q<(href|data|src)([\s]*)=([\s]*)('|"|&quot;|&#34;|&#39;)?\\/([\\/]?)>, 'i') + # CSS_MUNGABLE_RE= Regexp.new(%Q<(href|data|src)([\s]*)=([\s]*)('|"|&quot;|&#34;|&#39;)?\\/([\\/]?)>, 'i') + def _relativize_uris(text) return text unless _relativize? path_to_root= _path_to_root text.force_encoding("UTF-8") if text.respond_to? :force_encoding - text.gsub MUNGABLE_RE do |match| + text.gsub HTML_MUNGABLE_RE do |match| if $5 == '/' "#{ $1 }#{ $2 }=#{ $3 }#{ $4 }/" else "#{ $1 }#{ $2 }=#{ $3 }#{ $4 }#{ path_to_root }" end @@ -142,58 +152,50 @@ def _path_to_root '../' * @content.level end - def _in_context(content, opts) - _new_context(content, opts) - output= yield - _revert_context - output - end + def _in_new_context(content, opts) + @ctx_pool.sub_context do |ctx, prev_ctx| + ctx._setup content, opts + safe_opts= opts.reject { |o| SPECIAL_OPTS.include? o.to_s } + ctx.set safe_opts - def _new_context(content, opts) - @stack.push({ - content: @content, - context: @context, - opts: @opts - }.to_hash_object) - @context= RenderContext.new content, self, @context - safe_opts= opts.reject { |o| SPECIAL_OPTS.include? o.to_s } - @context.set safe_opts - @content= content - @opts= opts - if @stack.size == 1 - @context.set :layout, _default_layout - end - end + @context= ctx + @content= content + @opts= opts - def _revert_context - prev= @stack.pop - case @opts[:hoist] - when :all, true - _hoist_data(prev.context) - when Array - _hoist_data(prev.context, @opts[:hoist]) + if @ctx_pool.size == 1 + ctx.set :layout, _default_layout + end + + output= yield + + case opts[:hoist] + when :all, true + _hoist_data(prev_ctx) + when Array + _hoist_data(prev_ctx, opts[:hoist]) + end if opts.has_key? :hoist + + @context= prev_ctx + @content= prev_ctx.content || nil + @opts= prev_ctx.opts || nil + + ctx._setup nil, nil + output end - @context= prev.context - @content= prev.content - @opts= prev.opts end - + def _hoist_data(to_context, keys=nil) keys ||= @context.state.keys safe_keys= keys.reject {|k| SPECIAL_OPTS.include? k.to_s } safe_keys.each do |key| to_context.set key, @context.state[key] end end - def _previous - @stack.last - end - class << self # Returns the `Tilt::Template` for the given `ext` or nil def for(ext) Tilt[ext] @@ -202,23 +204,80 @@ end end end + class ContextPool + def initialize(renderer, size=3) + @_current= -1 + @renderer= renderer + @pool=[] + prev= nil + size.times do |i| + ctx= RenderContext.new nil, nil, renderer, prev + @pool << ctx + prev= ctx + end + end + + def sub_context + result= yield self.next, self.prev + self.pop + result + end + + def next + @_current += 1 + @pool << RenderContext.new( nil, nil, @renderer, prev ) if @_current == @pool.size + @pool[@_current] + end + + def current + @pool[@_current] + end + + def prev + @pool[@_current - 1] rescue nil + end + + def pop + @_current -= 1 + @pool[@_current] + end + + def root + @pool[0] + end + + def size + @_current + 1 + end + end + class RenderContext include Util::SiteAccess include Util::ViewHelpers - attr_reader :content, :state + attr_reader :content, :state, :opts - def initialize(content, renderer, parent=nil) + def initialize(content, opts, renderer, parent=nil) + # @content_page= nil @content= content @renderer= renderer @parent= parent + @opts= opts @state= {} end + def _setup(content, opts) + # @content_page= nil + @content= content + @opts= opts + # @state= {} + @state.clear() + end + def render(path=nil, opts={}) content= site.resolve path, opts raise StandardError, "Content or Partial cannot be found at: #{path} (#{opts})" if content.nil? opts[:force_partial]= true opts[:calling_page]= self @@ -245,16 +304,10 @@ @state[key.to_s.to_sym]= value end end def page - @content_page ||= begin - parent= self - while !parent.nil? and !parent.calling_page.nil? do - parent= parent.calling_page - end - parent - end + @renderer.ctx_pool.root end def content_for(key, &block) keyname= "_content_#{key}" if block_given? \ No newline at end of file