lib/acts_as_textiled/base.rb
module Err
module Acts #:nodoc: all
module Textiled
def self.included(klass)
klass.extend ClassMethods
end
module ClassMethods
def acts_as_textiled(*attributes)
@textiled_attributes = []
@textiled_unicode = String.new.respond_to? :chars
ruled = attributes.last.is_a?(Hash) ? attributes.pop : {}
attributes += ruled.keys
type_options = %w( plain source )
attributes.each do |attribute|
define_method(attribute) do |*type|
type = type.first
if type.nil? && self[attribute]
textiled[attribute.to_s] ||= RedCloth.new(self[attribute], Array(ruled[attribute])).to_html
elsif type.nil? && self[attribute].nil?
nil
elsif type_options.include?(type.to_s)
send("#{attribute}_#{type}")
else
raise "I don't understand the `#{type}' option. Try #{type_options.join(' or ')}."
end
end
define_method("#{attribute}_plain", proc { strip_redcloth_html(__send__(attribute)) if __send__(attribute) } )
define_method("#{attribute}_source", proc { __send__("#{attribute}_before_type_cast") } )
@textiled_attributes << attribute
end
include Err::Acts::Textiled::InstanceMethods
end
def textiled_attributes
Array(@textiled_attributes)
end
end
module InstanceMethods
def textiled
textiled? ? (@textiled ||= {}) : @attributes.dup
end
def textiled?
@is_textiled != false
end
def textiled=(bool)
@is_textiled = !!bool
end
def textilize
self.class.textiled_attributes.each { |attr| __send__(attr) }
end
def reload
textiled.clear
super
end
def write_attribute(attr_name, value)
textiled[attr_name.to_s] = nil
super
end
private
def strip_redcloth_html(html)
returning html.dup.gsub(html_regexp, '') do |h|
redcloth_glyphs.each do |(entity, char)|
sub = [ :gsub!, entity, char ]
@textiled_unicode ? h.chars.send(*sub) : h.send(*sub)
end
end
end
def redcloth_glyphs
[[ '’', "'" ],
[ '‘', "'" ],
[ '<', '<' ],
[ '>', '>' ],
[ '”', '"' ],
[ '“', '"' ],
[ '…', '...' ],
[ '\1—', '--' ],
[ ' → ', '->' ],
[ ' – ', '-' ],
[ '×', 'x' ],
[ '™', '(TM)' ],
[ '®', '(R)' ],
[ '©', '(C)' ]]
end
def html_regexp
%r{<(?:[^>"']+|"(?:\\.|[^\\"]+)*"|'(?:\\.|[^\\']+)*')*>}xm
end
end
end
end
end