require 'liquid' require 'pyrosoma/frame' require 'pyrosoma/database' class Pyrosoma module RenderLiquidTemplate class Find < Liquid::Block Syntax = /(\w+) as '(.*?)'(?: limit (\d+))?(?: offset (\d+))?(?: order '(.*?)')?/ def initialize(markup, tokens) super if markup =~ Syntax @variable = $1 @query = $2 @name = $1 + "-" + $2 @options = {} @options.update({:limit => Integer($3)}) if $3 @options.update({:offset => Integer($4)}) if $4 @options.update({:sort => $5}) if $5 else raise SyntaxError.new("Syntax Error in 'find block' - Valid syntax: find [item] as '[query]' [limit N] [offset N] [order S]?") end end def render(context) result = [] db = context.registers[:db] frame = context.registers[:frame] # ICK!! XXX @query.gsub!(/\$(\w+)\$/) { frame[$1.intern] } context.stack do db.search_each(@query, @options) { |match| context[@variable] = FrameDrop.new db[match] result << super } end result end end ::Liquid::Template.register_tag('find', Find) class FrameDrop < Liquid::Drop def initialize(frame) @frame = frame.add_inverse end def render(*a, &b) @frame.render(*a, &b) end def before_method(key) r = @frame[key.to_sym] if r.kind_of? Frame FrameDrop.new(r) elsif r.kind_of? Array r.map { |v| v.kind_of?(Frame) ? FrameDrop.new(v) : v } else r end end def to_hash @frame.inject({}) { |h, (k, v)| h[k.to_s] = invoke_drop k; h }. merge({'self' => self}) end end module FrameFilters def render(frame, template = :template) frame = [frame] unless frame.kind_of? Array frame.map { |f| f.render template.to_sym } end end module MarkupFilters require 'clothesline' def clothesline(text, clothesline = "BlueCloth RubyPants") ClothesLine.parse(clothesline).new(text).to_html end def to_time(string) Time.at string.to_i end end def render(template = :template) if self[template] liquid = Liquid::Template.parse self[template] liquid.render!(FrameDrop.new(self).to_hash, {:registers => {:db => db, :frame => self}, :filters => [FrameFilters, MarkupFilters]}) else super end end end class Frame include RenderLiquidTemplate end end