2013-06-10 15:33:37 -04:00
|
|
|
#
|
|
|
|
# HTML emails don't support CSS, so we can use nokogiri to inline attributes based on
|
|
|
|
# matchers.
|
|
|
|
#
|
|
|
|
module Email
|
|
|
|
class Styles
|
|
|
|
|
|
|
|
def initialize(html)
|
|
|
|
@html = html
|
2013-06-13 12:15:05 -04:00
|
|
|
@fragment = Nokogiri::HTML.fragment(@html)
|
2013-06-10 15:33:37 -04:00
|
|
|
end
|
|
|
|
|
2013-06-13 12:15:05 -04:00
|
|
|
def format_basic
|
|
|
|
@fragment.css('img').each do |img|
|
2013-06-10 15:33:37 -04:00
|
|
|
|
2013-11-28 17:20:56 -05:00
|
|
|
next if img['class'] == 'site-logo'
|
|
|
|
|
|
|
|
if img['class'] == "emoji" || img['src'] =~ /plugins\/emoji/
|
2013-07-26 03:27:46 -04:00
|
|
|
img['width'] = 20
|
|
|
|
img['height'] = 20
|
2013-06-13 12:15:05 -04:00
|
|
|
else
|
|
|
|
img['style'] = "max-width: 694px;"
|
|
|
|
end
|
|
|
|
|
2013-08-26 18:08:38 -04:00
|
|
|
# ensure all urls are absolute
|
2013-08-14 11:32:17 -04:00
|
|
|
if img['src'] =~ /^\/[^\/]/
|
2013-06-13 12:15:05 -04:00
|
|
|
img['src'] = "#{Discourse.base_url}#{img['src']}"
|
|
|
|
end
|
2013-08-26 18:08:38 -04:00
|
|
|
|
|
|
|
# ensure no schemaless urls
|
2013-12-03 10:10:53 -05:00
|
|
|
if img['src'] && img['src'].starts_with?("//")
|
2013-08-26 18:08:38 -04:00
|
|
|
img['src'] = "http:" + img['src']
|
|
|
|
end
|
2013-07-22 15:06:37 -04:00
|
|
|
end
|
2013-07-26 03:27:46 -04:00
|
|
|
end
|
2013-07-22 15:06:37 -04:00
|
|
|
|
2013-07-26 03:27:46 -04:00
|
|
|
def format_notification
|
|
|
|
style('.previous-discussion', 'font-size: 17px; color: #444;')
|
|
|
|
style('.date', "text-align:right;color:#999999;padding-right:5px;font-family:'lucida grande',tahoma,verdana,arial,sans-serif;font-size:11px")
|
|
|
|
style('.username', "font-size:13px;font-family:'lucida grande',tahoma,verdana,arial,sans-serif;color:#3b5998;text-decoration:none;font-weight:bold")
|
|
|
|
style('.post-wrapper', "margin-bottom:25px;max-width:761px")
|
|
|
|
style('.user-avatar', 'vertical-align:top;width:55px;')
|
|
|
|
style('.user-avatar img', nil, width: '45', height: '45')
|
|
|
|
style('hr', 'background-color: #ddd; height: 1px; border: 1px;')
|
|
|
|
# we can do this but it does not look right
|
|
|
|
# style('#main', 'font-family:"Helvetica Neue", Helvetica, Arial, sans-serif')
|
2013-07-26 18:08:58 -04:00
|
|
|
style('td.body', 'padding-top:5px;', colspan: "2")
|
|
|
|
correct_first_body_margin
|
2013-07-26 03:27:46 -04:00
|
|
|
correct_footer_style
|
|
|
|
reset_tables
|
2013-06-13 12:15:05 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def format_html
|
2013-07-26 03:27:46 -04:00
|
|
|
style('h3', 'margin: 15px 0 20px 0; border-bottom: 1px solid #ddd;')
|
|
|
|
style('hr', 'background-color: #ddd; height: 1px; border: 1px;')
|
2013-08-15 19:52:10 -04:00
|
|
|
style('a',' text-decoration: none; font-weight: bold; color: #006699;')
|
2013-07-26 03:27:46 -04:00
|
|
|
style('ul', 'margin: 0 0 0 10px; padding: 0 0 0 20px;')
|
|
|
|
style('li', 'padding-bottom: 10px')
|
|
|
|
style('div.digest-post', 'margin-left: 15px; margin-top: 20px; max-width: 694px;')
|
2013-08-09 14:43:02 -04:00
|
|
|
style('div.digest-post h1', 'font-size: 20px;')
|
2013-08-16 12:18:58 -04:00
|
|
|
style('span.footer-notice', 'color:#666; font-size:80%')
|
2013-11-29 12:21:21 -05:00
|
|
|
|
2013-11-29 13:00:10 -05:00
|
|
|
style('span.post-count', 'margin: 0 5px; color: #777;')
|
2013-11-29 12:21:21 -05:00
|
|
|
style('pre', 'white-space: pre-wrap')
|
2013-12-02 10:04:18 -05:00
|
|
|
style('code', 'background-color: #f1f1ff; padding: 2px 5px;')
|
|
|
|
style('pre code', 'display: block; background-color: #f1f1ff; padding: 5px')
|
2013-07-26 03:27:46 -04:00
|
|
|
end
|
2013-06-10 15:33:37 -04:00
|
|
|
|
2013-07-26 03:27:46 -04:00
|
|
|
def to_html
|
|
|
|
strip_classes_and_ids
|
|
|
|
@fragment.to_html.tap do |result|
|
|
|
|
result.gsub!(/\[email-indent\]/, "<div style='margin-left: 15px'>")
|
|
|
|
result.gsub!(/\[\/email-indent\]/, "</div>")
|
2013-06-10 15:33:37 -04:00
|
|
|
end
|
2013-07-26 03:27:46 -04:00
|
|
|
end
|
2013-06-10 15:33:37 -04:00
|
|
|
|
2013-07-26 03:27:46 -04:00
|
|
|
private
|
2013-06-10 15:33:37 -04:00
|
|
|
|
2013-07-26 18:08:58 -04:00
|
|
|
def correct_first_body_margin
|
|
|
|
@fragment.css('.body p').each do |element|
|
|
|
|
element['style'] = "margin-top:0;"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-07-26 03:27:46 -04:00
|
|
|
def correct_footer_style
|
|
|
|
@fragment.css('.footer').each do |element|
|
2013-07-29 02:00:02 -04:00
|
|
|
element['style'] = "color:#666;"
|
2013-07-26 03:27:46 -04:00
|
|
|
element.css('a').each do |inner|
|
2013-07-26 18:08:58 -04:00
|
|
|
inner['style'] = "color:#666;"
|
2013-07-26 03:27:46 -04:00
|
|
|
end
|
2013-06-10 15:33:37 -04:00
|
|
|
end
|
2013-07-26 03:27:46 -04:00
|
|
|
end
|
2013-06-10 15:33:37 -04:00
|
|
|
|
2013-07-26 03:27:46 -04:00
|
|
|
def strip_classes_and_ids
|
|
|
|
@fragment.css('*').each do |element|
|
|
|
|
element.delete('class')
|
|
|
|
element.delete('id')
|
2013-06-11 12:27:11 -04:00
|
|
|
end
|
2013-06-13 12:15:05 -04:00
|
|
|
end
|
2013-06-11 12:27:11 -04:00
|
|
|
|
2013-07-26 03:27:46 -04:00
|
|
|
def reset_tables
|
|
|
|
style('table',nil, cellspacing: '0', cellpadding: '0', border: '0')
|
2013-06-10 15:33:37 -04:00
|
|
|
end
|
|
|
|
|
2013-07-26 03:27:46 -04:00
|
|
|
def style(selector, style, attribs = {})
|
|
|
|
@fragment.css(selector).each do |element|
|
|
|
|
element['style'] = style if style
|
|
|
|
attribs.each do |k,v|
|
|
|
|
element[k] = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2013-06-10 15:33:37 -04:00
|
|
|
end
|
2013-07-26 03:27:46 -04:00
|
|
|
end
|