public
Rubygem
Description: a humane, eval-safe templating system using Hpricot
Clone URL: git://github.com/mattly/hpreserve.git
Click here to lend your support to: hpreserve and make a donation at www.pledgie.com !
commit  cf491d230e32b4a88b7075ca1a9b77a14ef36677
tree    ba5c07c2999915de41ae3adfe93d671bce3d2f9f
parent  8b4863a478a377bc02fd320c88e2a3a02a486078
hpreserve / lib / hpreserve / filters.rb
100644 74 lines (61 sloc) 2.364 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
module Hpreserve
  
  # todo: rewrite this
  
  # Acts as a sandbox to run filters in, most everything except the self.parse method
  # was stolen from Liquid's Strainer class. Almost all the standard class methods
  # (especially instance_eval) are undefined, and respond_to? is modified to only
  # return true on methods defined by the filter modules registered.
  class Filters
    
    @@filter_modules = []
    
    def self.register(filterset)
      [filterset].flatten.each do |mod|
        raise StandardError("passed filter is not a module") unless mod.is_a?(Module)
        @@filter_modules << mod
      end
    end
    
    def self.create
      filterset = Filters.new
      @@filter_modules.each { |m| filterset.extend m }
      filterset
    end
    
    # The filter parser expects a string formatted similar to an html element's "style"
    # attribute:
    #
    # * <tt>filter="date: %d %b; truncate_words: 15, ...; capitalize"</tt>
    #
    # (to provide an example of two currently filters you wouldn't use
    # together...) (todo: better examples fool!). Filters are separated by semicolons
    # and are executed in order given. If the filter needs arguments, those are given
    # after a colon and separated by commas.
    def self.parse(str='')
      str.split(';').inject([]) do |memo, rule|
        list = rule.split(':')
        filter = list.shift.strip
        set = [filter]
        unless list.empty?
          list = list.join(':') # get us back to our original string
          list = list.split(',') # becase we care about something else
          set += list.collect {|a| a.strip } # get rid of any pesky whitespace
        end
        memo << set
      end
    end
    
    @@required_methods = %w(__send__ __id__ debugger run inspect methods respond_to? extend)
    
    # :nodoc
    # keeping inspect around simply to make irb happy.
    def inspect; end
 
    def respond_to?(method)
      method_name = method.to_s
      return false if method_name =~ /^__/
      return false if @@required_methods.include?(method_name)
      super
    end
    
    def run(filter, node, *args)
      
      __send__(filter, node, *args) if respond_to?(filter)
    end
 
    instance_methods.each do |m|
      unless @@required_methods.include?(m)
        undef_method m
      end
    end
    
  end
end