Skip to content
This repository has been archived by the owner on May 1, 2022. It is now read-only.

Commit

Permalink
Add Sanitize to the mix. Refactor API to take an array of RedCloth op…
Browse files Browse the repository at this point in the history
…tions followed by a Santize config hash.

* Special options :skip_textile and :skip_sanitize allow one without the other
* Fixed tests for a combination of dasil003-sanitize 1.1.1 (gemcutter) and RedCloth 4.2.2.  These tests are brittle due to small changes in RedCloth over time.  I'm considering refactoring them to be much more basic and leave the RedCloth testing to the implementer.
  • Loading branch information
gtd committed Oct 15, 2009
1 parent 6049ebf commit 335eb59
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 30 deletions.
7 changes: 3 additions & 4 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ The reasoning behind this approach is simple. Filtering input before it is save

== Requirements

Sanitize 1.1.0
Nokogiri 1.3.3
RedCloth (for Textile support)
ActiveRecord (tested on 2.3.4)
* Sanitize >1.1.0 (prior versions had a whitespace issue)
* RedCloth (for Textile support)
* ActiveRecord (tested on 2.3.4)

== Changes from acts_as_textiled

Expand Down
20 changes: 17 additions & 3 deletions lib/acts_as_sanitiled.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require 'sanitize' unless defined? Sanitize

begin
require 'RedCloth' unless defined? RedCloth
rescue LoadError
Expand All @@ -17,10 +19,16 @@ def acts_as_textiled(*attributes)

@textiled_unicode = String.new.respond_to? :chars

sanitize_options = attributes.last.is_a?(Hash) ? attributes.pop : {}
options = attributes.last.is_a?(Hash) ? attributes.pop : {}
skip_textile = options.delete(:skip_textile)
skip_sanitize = options.delete(:skip_sanitize)

raise 'Both textile and sanitize were skipped' if skip_textile && skip_sanitize

sanitize_options = options.empty? ? Sanitize::Config::RELAXED : options
red_cloth_options = attributes.last && attributes.last.is_a?(Array) ? attributes.pop : []

raise 'You must specify some attributes textile/sanitize' if attributes.empty?
raise 'No attributes were specified to filter' if attributes.empty?

type_options = %w( plain source )

Expand All @@ -29,7 +37,13 @@ def acts_as_textiled(*attributes)
type = type.first

if type.nil? && self[attribute]
textiled[attribute.to_s] ||= RedCloth.new(self[attribute], red_cloth_options).to_html
if textiled[attribute.to_s].nil?
string = self[attribute]
string = RedCloth.new(string, red_cloth_options).to_html unless skip_textile
string = Sanitize.clean(string, sanitize_options) unless skip_sanitize
textiled[attribute.to_s] = string
end
textiled[attribute.to_s]
elsif type.nil? && self[attribute].nil?
nil
elsif type_options.include?(type.to_s)
Expand Down
2 changes: 1 addition & 1 deletion test/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def initialize(attributes = {})
end

def method_missing(name, *args)
if name.to_s[/=/]
if name.to_s[%r{=}]
@attributes[key = name.to_s.sub('=','')] = value = args.first
write_attribute key, value
else
Expand Down
44 changes: 22 additions & 22 deletions test/textiled_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,33 +40,33 @@

specify "should pick up changes to attributes" do
story = Story.find(2)

start_html = '<i>Beautify</i> your <strong>IRb</strong> prompt'
story.description.should.equal start_html
story.description.should.equal start_html

story.description = "**IRb** is simple"
changed_html = "<b>IRb</b> is simple"
story.description.should.equal changed_html

story.save

story.description.should.equal changed_html
story.description_plain.should.equal 'IRb is simple'
story.description.should.equal changed_html
story.description_plain.should.equal 'IRb is simple'
end

specify "should be able to toggle whether textile is active or not" do
story = Story.find(2)

desc_html = '<i>Beautify</i> your <strong>IRb</strong> prompt'
desc_textile = '__Beautify__ your *IRb* prompt'

story.description.should.equal desc_html
story.textiled = false
story.description.should.equal desc_textile
story.description.should.equal desc_textile

story.save

story.description.should.equal desc_textile
story.description.should.equal desc_textile
story.textiled = true
story.description.should.equal desc_html
end
Expand All @@ -78,9 +78,9 @@
blog_textile = '"ones zeros majors and minors":http://ozmm.org'
blog_plain = 'ones zeros majors and minors'

story.author.blog.should.equal blog_html
story.author.blog_source.should.equal blog_textile
story.author.blog_plain.should.equal blog_plain
story.author.blog.should.equal blog_html
story.author.blog_source.should.equal blog_textile
story.author.blog_plain.should.equal blog_plain
end

specify "should be able to toggle across associations" do
Expand All @@ -90,35 +90,35 @@
blog_textile = '"RedHanded":http://redhanded.hobix.com'
blog_plain = 'RedHanded'

story.author.blog.should.equal blog_html
story.author.blog.should.equal blog_html
story.author.textiled = false

story.author.blog.should.equal blog_textile
story.author.textiled = true

story.author.blog.should.equal blog_html
story.author.blog.should.equal blog_html
end

specify "should enhance text attributes" do
story = Story.find(3)

body_html = %[<p><em>Textile</em> is useful because it makes text <em>slightly</em> easier to <strong>read</strong>.</p>\n<p>If only it were so <strong>easy</strong> to use in every programming language. In Rails,<br />\nwith the help of <a href="http://google.com/search?q=acts_as_textiled">acts_as_textiled</a>,<br />\nit&#8217;s way easy. Thanks in no small part to <span style="color:red;">RedCloth</span>, of course.</p>]
body_html = %[<p><em>Textile</em> is useful because it makes text <em>slightly</em> easier to <strong>read</strong>.</p>\n<p>If only it were so <strong>easy</strong> to use in every programming language. In Rails,<br />\nwith the help of <a href="http://google.com/search?q=acts_as_textiled">acts_as_textiled</a>,<br />\nits way easy. Thanks in no small part to RedCloth, of course.</p>]
body_textile = %[_Textile_ is useful because it makes text _slightly_ easier to *read*.\n\nIf only it were so *easy* to use in every programming language. In Rails,\nwith the help of "acts_as_textiled":http://google.com/search?q=acts_as_textiled,\nit's way easy. Thanks in no small part to %{color:red}RedCloth%, of course.\n]
body_plain = %[Textile is useful because it makes text slightly easier to read.\nIf only it were so easy to use in every programming language. In Rails,\nwith the help of acts_as_textiled,\nit's way easy. Thanks in no small part to RedCloth, of course.]
body_plain = %[Textile is useful because it makes text slightly easier to read.\nIf only it were so easy to use in every programming language. In Rails,\nwith the help of acts_as_textiled,\nits way easy. Thanks in no small part to RedCloth, of course.]

story.body.should.equal body_html
story.body_source.should.equal body_textile
story.body.should.equal body_html
story.body_source.should.equal body_textile
story.body_plain.should.equal body_plain
end

specify "should handle character conversions" do
story = Story.find(4)

body_html = "<p>Is Textile&#8482; the wave of the future? What about acts_as_textiled&#169;? It&#8217;s<br />\ndoubtful. Why does Textile&#8482; smell like <em>Python</em>? Can we do anything to<br />\nfix that? No? Well, I guess there are worse smells &#8211; like Ruby. jk.</p>\n<p>But seriously, ice &gt; water and water &lt; rain. But&#8230;nevermind. 1 &#215; 1? 1.</p>\n<p>&#8220;You&#8217;re a good kid,&#8221; he said. &#8220;Keep it up.&#8221;</p>"
body_plain = %[Is Textile(TM) the wave of the future? What about acts_as_textiled(C)? It's\ndoubtful. Why does Textile(TM) smell like Python? Can we do anything to\nfix that? No? Well, I guess there are worse smells-like Ruby. jk.\nBut seriously, ice > water and water < rain. But...nevermind. 1 x 1? 1.\n"You're a good kid," he said. "Keep it up."]
body_html = "<p>Is Textile the wave of the future? What about acts_as_textiled©? Its<br />\ndoubtful. Why does Textile smell like <em>Python</em>? Can we do anything to<br />\nfix that? No? Well, I guess there are worse smells like Ruby. jk.</p>\n<p>But seriously, ice &gt; water and water &lt; rain. Butnevermind. 1 × 1? 1.</p>\n<p>Youre a good kid, he said. Keep it up.</p>"
body_plain = %[Is Textile the wave of the future? What about acts_as_textiled©? Its\ndoubtful. Why does Textile smell like Python? Can we do anything to\nfix that? No? Well, I guess there are worse smellslike Ruby. jk.\nBut seriously, ice > water and water < rain. Butnevermind. 1 × 1? 1.\nYoure a good kid, he said. Keep it up.]

story.body.should.equal body_html
story.body_plain.should.equal body_plain
story.body.should.equal body_html
story.body_plain.should.equal body_plain
end

specify "should be able to do on-demand textile caching" do
Expand All @@ -131,15 +131,15 @@
story.textilize

story.textiled.size.should.equal 2
story.description.should.equal desc_html
story.description.should.equal desc_html
end

specify "should work well with after_find callbacks" do
story = StoryWithAfterFind.find(2)

desc_html = '<i>Beautify</i> your <strong>IRb</strong> prompt'

story.textiled.size.should.equal 2
story.textiled.size.should.equal 2
story.description.should.equal desc_html
end
end

0 comments on commit 335eb59

Please sign in to comment.