require 'support/class_options' class TextFilters define_option :default_processor, :liquid define_option :default_filter, :textile define_option :logger, nil @registered_filters = {} @registered_titles = {} attr_reader :name attr_reader :title def initialize(name, title) @name = name @title = title end # The default create_link method... # Override for your specific filter, if needed, in the #define block def create_link(title, url) %Q|#{title}| end # Process the text with using the specified context def process_text(text, context, processor=nil) case (processor || TextFilters.default_processor) when :erb then process_with_erb(text, context) when :liquid then process_with_liquid(text, context) else raise "Unknown Text Processor '#{processor.to_s}'" end end class << self private :new attr_reader :registered_filters attr_reader :registered_titles # Use this to create and register your TextFilters def define(name, title, &block) begin p = new(name, title) p.instance_eval(&block) if p.respond_to? :render_text registered_titles[title] = name registered_filters[name] = p else raise "#render_text isn't implemented in this class" end rescue LoadError TextFilters.logger.debug "Filter '#{name}' was not included: #{$!}" unless TextFilters.logger.nil? rescue TextFilters.logger.debug "Filter '#{name}' was not included: #{$!}" unless TextFilters.logger.nil? end end def get_filter(name) name = TextFilters.default_filter if name.nil? name = registered_titles[name] if name.is_a? String registered_filters[name] end def [](name) get_filter(name) end def all registered_filters end def all_titles registered_titles.keys end def render_text(text, name=nil) get_filter(name).render_text(text) end def process_text(text, context=nil, name=nil, processor=nil) get_filter(name).process_text(text, context, processor) end # Call def transform(text, context=nil, name=nil, processor=nil) render_text( process_text(text, context, name, processor), name ) end end private # This is an instance method so that it won't puke on requiring # a non-existant library until it's being registered -- the only # place I can really capture the LoadError def require(name) Kernel.require name end # Use ERB to process text... def process_with_erb(text, context) begin ERB.new( text ).result( context.get_binding ) rescue raise "ERB Error: #{$!}" end end # Use Liquid to process text... def process_with_liquid(text, context={}) begin context = context.stringify_keys if context.respond_to? :stringify_keys Liquid::Template.parse(text).render(context) rescue raise "Liquid Error: #{$!}" end end end class Hash # Having the method_missing catchall in conjunction with get_binding # allows us to use the hash as a Context for ERB def method_missing(meth, *arg) if self.has_key? meth.to_s self[meth.to_s] else super end end # Gets the binding object for use with ERB def get_binding binding end end Dir[File.join(File.dirname(__FILE__), 'text_filters', '*.rb')].each do |path| require "text_filters/#{File.basename(path)}" end