Escape hashtags in emails

Custom Redcarpet renderer to escape hashtags (but not legitimate headers)
in emails before Markdown processing. Prevents hashtags from being rendered
as H1 headers. This also leaves open the possibility of parsing hashtags
into clickable links in the future.

fixes #3325
This commit is contained in:
Steven Hancock 2012-05-28 21:31:27 -07:00
parent f68f14aa5b
commit c2bc7272fb
6 changed files with 82 additions and 4 deletions

View file

@ -29,7 +29,7 @@ gem 'twitter', '2.0.2'
# mail # mail
gem 'markerb', '~> 1.0.0' gem 'markerb', :git => 'git://github.com/plataformatec/markerb.git'
gem 'messagebus_ruby_api', '1.0.3' gem 'messagebus_ruby_api', '1.0.3'
gem 'airbrake' gem 'airbrake'
gem 'newrelic_rpm' gem 'newrelic_rpm'

View file

@ -30,6 +30,13 @@ GIT
rspec (>= 1.3.1) rspec (>= 1.3.1)
selenium-webdriver (>= 0.1.3) selenium-webdriver (>= 0.1.3)
GIT
remote: git://github.com/plataformatec/markerb.git
revision: 93b1e8bea9b8fa89ef930f78ba562f596c022198
specs:
markerb (1.0.0)
redcarpet (>= 2.0)
GEM GEM
remote: http://rubygems.org/ remote: http://rubygems.org/
specs: specs:
@ -243,8 +250,6 @@ GEM
i18n (>= 0.4.0) i18n (>= 0.4.0)
mime-types (~> 1.16) mime-types (~> 1.16)
treetop (~> 1.4.8) treetop (~> 1.4.8)
markerb (1.0.0)
redcarpet (>= 2.0)
messagebus_ruby_api (1.0.3) messagebus_ruby_api (1.0.3)
mime-types (1.18) mime-types (1.18)
mini_magick (3.4) mini_magick (3.4)
@ -490,7 +495,7 @@ DEPENDENCIES
jquery-rails jquery-rails
json json
linecache (= 0.46) linecache (= 0.46)
markerb (~> 1.0.0) markerb!
messagebus_ruby_api (= 1.0.3) messagebus_ruby_api (= 1.0.3)
mini_magick (= 3.4) mini_magick (= 3.4)
mobile-fu mobile-fu

View file

@ -0,0 +1,3 @@
require Rails.root.join("lib", "diaspora", "markdownify_email")
Rails.application.config.markerb.renderer = Diaspora::Markdownify::Email

View file

@ -0,0 +1,25 @@
require Rails.root.join("app", "models", "acts_as_taggable_on", "tag")
module Diaspora
module Markdownify
class Email < Redcarpet::Render::HTML
TAG_REGEX = /(?:^|\s)#([#{ActsAsTaggableOn::Tag.tag_text_regexp}]+)/u
def preprocess(text)
process_tags(text)
end
private
def tags(text)
text.scan(TAG_REGEX).map { |match| match[0] }
end
def process_tags(text)
return text unless text.match(TAG_REGEX)
tags(text).each do |tag|
text.gsub!(/##{tag}/i, "\\##{tag}")
end
text
end
end
end
end

View file

@ -0,0 +1,36 @@
require 'spec_helper'
describe Diaspora::Markdownify::Email do
describe '#preprocess' do
before do
@html = Diaspora::Markdownify::Email.new
end
it 'should escape a hashtag' do
markdownified = @html.preprocess("#tag")
markdownified.should == "\\#tag"
end
it 'should escape multiple hashtags' do
markdownified = @html.preprocess("There are #two #tags")
markdownified.should == "There are \\#two \\#tags"
end
it 'should not escape headers' do
markdownified = @html.preprocess("# header")
markdownified.should == "# header"
end
end
describe "Markdown rendering" do
before do
@markdown = Redcarpet::Markdown.new(Diaspora::Markdownify::Email)
@sample_text = "# Header\n\n#messages containing #hashtags should render properly"
end
it 'should render the message' do
rendered = @markdown.render(@sample_text).strip
rendered.should == "<h1>Header</h1>\n\n<p>#messages containing #hashtags should render properly</p>"
end
end
end

View file

@ -325,4 +325,13 @@ describe Notifier do
end end
end end
end end
describe 'hashtags' do
it 'escapes hashtags' do
mails = Notifier.admin("#Welcome to bureaucracy!", [bob])
mails.length.should == 1
mail = mails.first
mail.body.encoded.should match /#Welcome to bureaucracy!/
end
end
end end