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]*)('|"|"|"|')?\\/([\\/]?)>, '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]*)('|"|"|"|')?\\/([\\/]?)>, 'i')
+ # CSS_MUNGABLE_RE= Regexp.new(%Q<(href|data|src)([\s]*)=([\s]*)('|"|"|"|')?\\/([\\/]?)>, '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