<?xml version="1.0" encoding="UTF-8"?>
<wiki>
  <body>&lt;p&gt;I implemented RedCloth in this iteration, to give me &lt;strong&gt;Textile&lt;/strong&gt; markup for blog entires &amp;amp; comments.  RedCloth has the ability to escape &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; tags, which is extremely nice.  However, by &amp;#8220;escape&amp;#8221; it means &amp;#8220;remove&amp;#8221;.  Any tag not in the whitelist is completely removed from the page.  This is fairly annoying; by &amp;#8220;escape&amp;#8221;, I would imagine that I&amp;#8217;d get the tag displayed on the page as I typed it in.&lt;/p&gt;
&lt;p&gt;To test this I removed blockquote from the list of allowed tags.  Much to my surprise, &lt;em&gt;all&lt;/em&gt; blockquotes were removed, even those specified using the Textile code bq.!  &lt;strong&gt;&lt;em&gt;&lt;span class=&quot;caps&quot;&gt;WTF&lt;/span&gt;???&lt;/em&gt;&lt;/strong&gt;  Okay, so it turns out that when RedCloth &amp;#8220;escapes&amp;#8221; the &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;, it doesn&amp;#8217;t do so until &lt;em&gt;after&lt;/em&gt; the Textile transform has taken place.  Therefore, the whitelist goes towards tags input by the user &lt;em&gt;and&lt;/em&gt; tags determined by Textile codes.  This makes no sense.&lt;/p&gt;
&lt;p&gt;So given these two issues, I had some changes to make.  After familiarizing myself with the code, I tried my hardest to think of a fix obtained through monkey-patching or subclassing.  No such luck.  The methods just weren&amp;#8217;t written in an overriding-friendly way.  Rather than just modify the gem, which would have been very, very bad of me (punishment by torture), I unpacked the gem to /vendor and made the changes there.  This way, the changes aren&amp;#8217;t systemwide, and anyone will have them when downloading the project (punishment by slap on the wrist).  I hope the hardcore Rubyists out there can forgive me for this decision, and if you have a better way to implement these changes, please let me know.&lt;/p&gt;
&lt;p&gt;Without any further adieu, here is the before/after code of RedCloth.rb showing my changes.&lt;/p&gt;
&lt;p&gt;Change #1:&lt;/p&gt;
&lt;p&gt;The to_html method calls clean_html just before returning, if necessary.  This was the original code:&lt;/p&gt;
text.gsub!( /&amp;lt;\/?notextile&amp;gt;/, &amp;#8217;&amp;#8217; )
text.gsub!( /x%x%/, &amp;#8216;&amp;#38;&amp;#8217; )
text.strip!
clean_html text if filter_html
text
end
&lt;p&gt;Unfortunately, all Textile replacements have already been made, therefore that &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; is being cleaned too.  This is completely unnecessary, therefore we want clean_html to be called &lt;em&gt;before&lt;/em&gt; performing the Textile work, like so:&lt;/p&gt;
incoming_entities text
clean_white_space text
clean_html text if filter_html
@pre_list = []
rip_offtags text
no_textile text
hard_break text
unless @lite_mode
refs text
blocks text
end
inline text
smooth_offtags text
retrieve text
text.gsub!( /&amp;lt;\/?notextile&amp;gt;/, &amp;#8217;&amp;#8217; )
&amp;#8230;.
&lt;p&gt;Got it?&lt;/p&gt;
&lt;p&gt;The second fix allows me to type a disallowed &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; tag in the editor and display it to the user in its full taggy goodness.  This change was made to the clean_html method.  This method uses a regex to go through each tag; if it exists in the whitelist, then leave it alone, otherwise, replace it with an empty string.  Here is the original snippet from clean_html:&lt;/p&gt;
end
end if tags[tag]
&amp;#8220;&amp;lt;#{raw&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;}#{pcs.join &amp;quot; &amp;#8220;}&amp;gt;&amp;#8221;
else
&amp;quot; &amp;quot;
end
&lt;p&gt;and here is my change, allowing the tag to be displayed on the page, but still not rendered as &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;:&lt;/p&gt;
end
end if tags[tag]
&amp;#8220;&amp;lt;#{raw&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;}#{pcs.join &amp;quot; &amp;#8220;}&amp;gt;&amp;#8221;
else
&amp;#8220;&amp;lt;#{raw&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;}#{raw&lt;sup class=&quot;footnote&quot;&gt;&lt;a href=&quot;#fn2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;}&amp;gt;&amp;#8221;
end
&lt;p&gt;Not a huge deal, but now RedCloth and &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; escaping works like I would expect it to!  I&amp;#8217;m open for suggestions to better solutions for these problems.  But for now, that&amp;#8217;s how it will stay.&lt;/p&gt;</body>
  <created-at type="datetime">2008-05-01T01:09:32-07:00</created-at>
  <id type="integer">14799</id>
  <permalink>featured-code-snippet-2</permalink>
  <repository-id type="integer">6097</repository-id>
  <title>Featured Code Snippet #2</title>
  <updated-at type="datetime">2008-05-01T01:17:34-07:00</updated-at>
  <user-id type="integer">3648</user-id>
</wiki>
