<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>ruby on rails legacy html bbcode on random thoughts</title><link>https://awesomeprogrammer.com/categories/ruby-on-rails-legacy-html-bbcode/</link><description>Recent content in ruby on rails legacy html bbcode on random thoughts</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Wed, 08 Aug 2012 00:00:00 +0000</lastBuildDate><atom:link href="https://awesomeprogrammer.com/categories/ruby-on-rails-legacy-html-bbcode/index.xml" rel="self" type="application/rss+xml"/><item><title>Rails legacy database migration, Part 2</title><link>https://awesomeprogrammer.com/blog/2012/08/08/rails-legacy-database-migration-part-2/</link><pubDate>Wed, 08 Aug 2012 00:00:00 +0000</pubDate><guid>https://awesomeprogrammer.com/blog/2012/08/08/rails-legacy-database-migration-part-2/</guid><description><![CDATA[<p><a href="/blog/2012/07/28/rails-legacy-database-migration/">(Link to Part 1)</a> Now let&rsquo;s look at some tools that can help you migrating messy html into some more easy to maintain format. Obvious choice for many would be <a href="http://daringfireball.net/projects/markdown/">markdown</a>, but as markdown is quite geeky I decided to go with well known by average user - and hated by many programmers - <a href="http://en.wikipedia.org/wiki/BBCode">BBCode</a>. BBCode would also allow me to implement some custom tags that I needed anyway - so from now we will stick with it.</p>
<h3 id="how-to-parse--html-to-bbcode-in-ruby--rails">How to parse  HTML to BBCode in Ruby / Rails?</h3>
<p>After some unsuccessful tries with regular expressions that aren&rsquo;t really solutions to the problem. Here are my weapons of choice:</p>
<ul>
<li><a href="https://github.com/flavorjones/loofah">Loofah</a> - powered with <a href="http://nokogiri.org">Nokogiri</a> and libxml2 is a excellent choice</li>
<li><a href="https://github.com/asceth/bbcoder">BBCoder</a> - easy to configure and clean BBCode to HTML parser</li>
<li><a href="https://github.com/carld/tidy">Tidy</a> - Ruby interface for TidyHTML (if you have really messy content as I do you can tidy-it-up a little bit before processing)</li>
</ul>
<p>Loofah allows to define custom scrubbers that we will later apply to our dirty, dirty html. I won&rsquo;t repeat here the documentation and/or manual, because you can easily read it yourself - and I&rsquo;m really recommending getting to know how nokogiri works and why it&rsquo;s so awesome. Let&rsquo;s just cut straight to the problem.</p>
<p>Here code for my Loofah&rsquo;s scrubber that converts HTML to BBCode:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HTMLBBCoder</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">Loofah</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Scrubber</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">initialize</span>
</span></span><span style="display:flex;"><span>    @direction <span style="color:#f92672">=</span> <span style="color:#e6db74">:bottom_up</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">scrub</span>(node)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">CONTINUE</span> <span style="color:#66d9ef">if</span> node<span style="color:#f92672">.</span>text?
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">case</span> node<span style="color:#f92672">.</span>name
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;i&#34;</span>, <span style="color:#e6db74">&#34;em&#34;</span>
</span></span><span style="display:flex;"><span>        node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[i]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/i]&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;br&#34;</span>
</span></span><span style="display:flex;"><span>        node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;strong&#34;</span>
</span></span><span style="display:flex;"><span>        node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[b]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/b]&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;a&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;href&#39;</span><span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> node<span style="color:#f92672">.</span>inner_html
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[url=</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;href&#39;</span><span style="color:#f92672">]</span><span style="color:#e6db74">}</span><span style="color:#e6db74">]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/url]&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">.</span>remove <span style="color:#75715e"># remove urls without href or title</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;img&#34;</span>
</span></span><span style="display:flex;"><span>        node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[img]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;src&#39;</span><span style="color:#f92672">]</span><span style="color:#e6db74">}</span><span style="color:#e6db74">[/img]&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;table&#34;</span>, <span style="color:#e6db74">&#34;td&#34;</span> ,<span style="color:#e6db74">&#34;tr&#34;</span>, <span style="color:#e6db74">&#34;li&#34;</span>, <span style="color:#e6db74">&#34;b&#34;</span>, <span style="color:#e6db74">&#34;ol&#34;</span>, <span style="color:#e6db74">&#34;ul&#34;</span>, <span style="color:#e6db74">&#34;u&#34;</span>
</span></span><span style="display:flex;"><span>        node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>name<span style="color:#e6db74">}</span><span style="color:#e6db74">]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>name<span style="color:#e6db74">}</span><span style="color:#e6db74">]&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;span&#34;</span>, <span style="color:#e6db74">&#34;div&#34;</span>, <span style="color:#e6db74">&#34;p&#34;</span> <span style="color:#75715e"># handle text aligment, font-weight etc.</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> node<span style="color:#f92672">.</span>attributes<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;style&#39;</span><span style="color:#f92672">]</span> 
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">if</span> node<span style="color:#f92672">.</span>attributes<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;style&#39;</span><span style="color:#f92672">].</span>to_s<span style="color:#f92672">.</span>match(<span style="color:#e6db74">/bold/</span>)
</span></span><span style="display:flex;"><span>             node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[b]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/b]&#34;</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">elsif</span> node<span style="color:#f92672">.</span>attributes<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;style&#39;</span><span style="color:#f92672">].</span>to_s<span style="color:#f92672">.</span>match(<span style="color:#e6db74">/italic/</span>)
</span></span><span style="display:flex;"><span>            node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[i]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/i]&#34;</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">elsif</span> node<span style="color:#f92672">.</span>attributes<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;style&#39;</span><span style="color:#f92672">].</span>to_s<span style="color:#f92672">.</span>match(<span style="color:#e6db74">/underline/</span>)
</span></span><span style="display:flex;"><span>            node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[u]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/u]&#34;</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">elsif</span> node<span style="color:#f92672">.</span>attributes<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;style&#39;</span><span style="color:#f92672">].</span>to_s<span style="color:#f92672">.</span>match(<span style="color:#e6db74">/center/</span>) <span style="color:#f92672">||</span> (node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;align&#39;</span><span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;align&#39;</span><span style="color:#f92672">].</span>match(<span style="color:#e6db74">/center/</span>))
</span></span><span style="display:flex;"><span>             node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[center]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/center]&#34;</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>            node<span style="color:#f92672">.</span>replace(node<span style="color:#f92672">.</span>inner_html)  
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">.</span>replace(node<span style="color:#f92672">.</span>inner_html)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;font&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;color&#39;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[color=</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;color&#39;</span><span style="color:#f92672">]</span><span style="color:#e6db74">}</span><span style="color:#e6db74">]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/color]&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">.</span>inner_html<span style="color:#f92672">.</span>empty? ? node<span style="color:#f92672">.</span>remove : node<span style="color:#f92672">.</span>replace(node<span style="color:#f92672">.</span>inner_html)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">STOP</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">end</span> <span style="color:#75715e"># case</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span> <span style="color:#75715e"># scrub</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span> <span style="color:#75715e"># class</span>
</span></span></code></pre></div><p>It goes from bottom, rewrites the html tags into BBCode tags and on the way fixes some common problems I have encountered. You will probably need to tweak it for your needs, but at least now you have a base. It&rsquo;s not pretties thing in the world, but it gets the job done.</p>
<p>Now let&rsquo;s use some Tidy help before calling the scrubber. You can tweak settings after <a href="http://tidy.sourceforge.net/docs/tidy_man.html">reading the manual</a>. I decided to go with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>tidy <span style="color:#f92672">=</span> <span style="color:#66d9ef">Tidy</span><span style="color:#f92672">.</span>open({<span style="color:#e6db74">:show_warnings</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">:wrap</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;char-encoding&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;utf8&#39;</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;output-bom&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;show-body-only&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;word2000&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;merge-spans&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;merge-divs&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;drop-empty-paras&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;tidy-mark&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;drop-proprietary-attributes&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;quote-ampersand&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;force-output&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">true</span>}) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>tidy<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  clean <span style="color:#f92672">=</span> tidy<span style="color:#f92672">.</span>clean(text)
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># maybe here you&#39;ll want to check for errors/warnings</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>After tidy&rsquo;ing it up you probably will have to force encoding like that:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Loofah</span><span style="color:#f92672">.</span>fragment(clean<span style="color:#f92672">.</span>force_encoding(<span style="color:#e6db74">&#39;UTF-8&#39;</span>))<span style="color:#f92672">.</span>scrub!(bbcoder)<span style="color:#f92672">.</span>to_s
</span></span></code></pre></div><p>Also - depending of your chunks of html you may need to wrap your text inside some proper html tags like <em>&lt;p&gt;</em> or <em>&lt;div&gt;</em></p>]]></description><content:encoded><![CDATA[<p><a href="/blog/2012/07/28/rails-legacy-database-migration/">(Link to Part 1)</a> Now let&rsquo;s look at some tools that can help you migrating messy html into some more easy to maintain format. Obvious choice for many would be <a href="http://daringfireball.net/projects/markdown/">markdown</a>, but as markdown is quite geeky I decided to go with well known by average user - and hated by many programmers - <a href="http://en.wikipedia.org/wiki/BBCode">BBCode</a>. BBCode would also allow me to implement some custom tags that I needed anyway - so from now we will stick with it.</p>
<h3 id="how-to-parse--html-to-bbcode-in-ruby--rails">How to parse  HTML to BBCode in Ruby / Rails?</h3>
<p>After some unsuccessful tries with regular expressions that aren&rsquo;t really solutions to the problem. Here are my weapons of choice:</p>
<ul>
<li><a href="https://github.com/flavorjones/loofah">Loofah</a> - powered with <a href="http://nokogiri.org">Nokogiri</a> and libxml2 is a excellent choice</li>
<li><a href="https://github.com/asceth/bbcoder">BBCoder</a> - easy to configure and clean BBCode to HTML parser</li>
<li><a href="https://github.com/carld/tidy">Tidy</a> - Ruby interface for TidyHTML (if you have really messy content as I do you can tidy-it-up a little bit before processing)</li>
</ul>
<p>Loofah allows to define custom scrubbers that we will later apply to our dirty, dirty html. I won&rsquo;t repeat here the documentation and/or manual, because you can easily read it yourself - and I&rsquo;m really recommending getting to know how nokogiri works and why it&rsquo;s so awesome. Let&rsquo;s just cut straight to the problem.</p>
<p>Here code for my Loofah&rsquo;s scrubber that converts HTML to BBCode:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">HTMLBBCoder</span> <span style="color:#f92672">&lt;</span> <span style="color:#66d9ef">Loofah</span><span style="color:#f92672">::</span><span style="color:#66d9ef">Scrubber</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">initialize</span>
</span></span><span style="display:flex;"><span>    @direction <span style="color:#f92672">=</span> <span style="color:#e6db74">:bottom_up</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">scrub</span>(node)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">CONTINUE</span> <span style="color:#66d9ef">if</span> node<span style="color:#f92672">.</span>text?
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">case</span> node<span style="color:#f92672">.</span>name
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;i&#34;</span>, <span style="color:#e6db74">&#34;em&#34;</span>
</span></span><span style="display:flex;"><span>        node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[i]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/i]&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;br&#34;</span>
</span></span><span style="display:flex;"><span>        node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;strong&#34;</span>
</span></span><span style="display:flex;"><span>        node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[b]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/b]&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;a&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;href&#39;</span><span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> node<span style="color:#f92672">.</span>inner_html
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[url=</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;href&#39;</span><span style="color:#f92672">]</span><span style="color:#e6db74">}</span><span style="color:#e6db74">]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/url]&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">.</span>remove <span style="color:#75715e"># remove urls without href or title</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;img&#34;</span>
</span></span><span style="display:flex;"><span>        node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[img]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;src&#39;</span><span style="color:#f92672">]</span><span style="color:#e6db74">}</span><span style="color:#e6db74">[/img]&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;table&#34;</span>, <span style="color:#e6db74">&#34;td&#34;</span> ,<span style="color:#e6db74">&#34;tr&#34;</span>, <span style="color:#e6db74">&#34;li&#34;</span>, <span style="color:#e6db74">&#34;b&#34;</span>, <span style="color:#e6db74">&#34;ol&#34;</span>, <span style="color:#e6db74">&#34;ul&#34;</span>, <span style="color:#e6db74">&#34;u&#34;</span>
</span></span><span style="display:flex;"><span>        node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>name<span style="color:#e6db74">}</span><span style="color:#e6db74">]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>name<span style="color:#e6db74">}</span><span style="color:#e6db74">]&#34;</span>)
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;span&#34;</span>, <span style="color:#e6db74">&#34;div&#34;</span>, <span style="color:#e6db74">&#34;p&#34;</span> <span style="color:#75715e"># handle text aligment, font-weight etc.</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> node<span style="color:#f92672">.</span>attributes<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;style&#39;</span><span style="color:#f92672">]</span> 
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">if</span> node<span style="color:#f92672">.</span>attributes<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;style&#39;</span><span style="color:#f92672">].</span>to_s<span style="color:#f92672">.</span>match(<span style="color:#e6db74">/bold/</span>)
</span></span><span style="display:flex;"><span>             node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[b]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/b]&#34;</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">elsif</span> node<span style="color:#f92672">.</span>attributes<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;style&#39;</span><span style="color:#f92672">].</span>to_s<span style="color:#f92672">.</span>match(<span style="color:#e6db74">/italic/</span>)
</span></span><span style="display:flex;"><span>            node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[i]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/i]&#34;</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">elsif</span> node<span style="color:#f92672">.</span>attributes<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;style&#39;</span><span style="color:#f92672">].</span>to_s<span style="color:#f92672">.</span>match(<span style="color:#e6db74">/underline/</span>)
</span></span><span style="display:flex;"><span>            node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[u]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/u]&#34;</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">elsif</span> node<span style="color:#f92672">.</span>attributes<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;style&#39;</span><span style="color:#f92672">].</span>to_s<span style="color:#f92672">.</span>match(<span style="color:#e6db74">/center/</span>) <span style="color:#f92672">||</span> (node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;align&#39;</span><span style="color:#f92672">]</span> <span style="color:#f92672">&amp;&amp;</span> node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;align&#39;</span><span style="color:#f92672">].</span>match(<span style="color:#e6db74">/center/</span>))
</span></span><span style="display:flex;"><span>             node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[center]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/center]&#34;</span>)
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>            node<span style="color:#f92672">.</span>replace(node<span style="color:#f92672">.</span>inner_html)  
</span></span><span style="display:flex;"><span>          <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">.</span>replace(node<span style="color:#f92672">.</span>inner_html)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">when</span> <span style="color:#e6db74">&#34;font&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;color&#39;</span><span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">.</span>replace(<span style="color:#e6db74">&#34;[color=</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">[</span><span style="color:#e6db74">&#39;color&#39;</span><span style="color:#f92672">]</span><span style="color:#e6db74">}</span><span style="color:#e6db74">]</span><span style="color:#e6db74">#{</span>node<span style="color:#f92672">.</span>inner_html<span style="color:#e6db74">}</span><span style="color:#e6db74">[/color]&#34;</span>)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>          node<span style="color:#f92672">.</span>inner_html<span style="color:#f92672">.</span>empty? ? node<span style="color:#f92672">.</span>remove : node<span style="color:#f92672">.</span>replace(node<span style="color:#f92672">.</span>inner_html)
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">end</span>
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">STOP</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">end</span> <span style="color:#75715e"># case</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">end</span> <span style="color:#75715e"># scrub</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span> <span style="color:#75715e"># class</span>
</span></span></code></pre></div><p>It goes from bottom, rewrites the html tags into BBCode tags and on the way fixes some common problems I have encountered. You will probably need to tweak it for your needs, but at least now you have a base. It&rsquo;s not pretties thing in the world, but it gets the job done.</p>
<p>Now let&rsquo;s use some Tidy help before calling the scrubber. You can tweak settings after <a href="http://tidy.sourceforge.net/docs/tidy_man.html">reading the manual</a>. I decided to go with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span>tidy <span style="color:#f92672">=</span> <span style="color:#66d9ef">Tidy</span><span style="color:#f92672">.</span>open({<span style="color:#e6db74">:show_warnings</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">:wrap</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;char-encoding&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#e6db74">&#39;utf8&#39;</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;output-bom&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;show-body-only&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;word2000&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;merge-spans&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;merge-divs&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#ae81ff">1</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;drop-empty-paras&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;tidy-mark&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;drop-proprietary-attributes&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;quote-ampersand&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">false</span>,
</span></span><span style="display:flex;"><span>                  <span style="color:#e6db74">&#39;force-output&#39;</span> <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">true</span>}) <span style="color:#66d9ef">do</span> <span style="color:#f92672">|</span>tidy<span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>  clean <span style="color:#f92672">=</span> tidy<span style="color:#f92672">.</span>clean(text)
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># maybe here you&#39;ll want to check for errors/warnings</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">end</span>
</span></span></code></pre></div><p>After tidy&rsquo;ing it up you probably will have to force encoding like that:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ruby" data-lang="ruby"><span style="display:flex;"><span><span style="color:#66d9ef">Loofah</span><span style="color:#f92672">.</span>fragment(clean<span style="color:#f92672">.</span>force_encoding(<span style="color:#e6db74">&#39;UTF-8&#39;</span>))<span style="color:#f92672">.</span>scrub!(bbcoder)<span style="color:#f92672">.</span>to_s
</span></span></code></pre></div><p>Also - depending of your chunks of html you may need to wrap your text inside some proper html tags like <em>&lt;p&gt;</em> or <em>&lt;div&gt;</em></p>]]></content:encoded></item></channel></rss>