class BootstrapEmail::Compiler
Public Class Methods
new(mail)
click to toggle source
# File lib/bootstrap-email.rb, line 11 def initialize(mail) @mail = mail @source = mail.html_part || mail update_doc(@source.body.raw_source) end
Public Instance Methods
compile_html!()
click to toggle source
# File lib/bootstrap-email.rb, line 28 def compile_html! button badge alert card hr container grid align padding margin spacer table body end
inject_head!()
click to toggle source
# File lib/bootstrap-email.rb, line 51 def inject_head! @doc.at_css('head').add_child(bootstrap_email_head) end
inline_css!()
click to toggle source
# File lib/bootstrap-email.rb, line 44 def inline_css! @source.body = @doc.to_html @mail = Premailer::Rails::Hook.perform(@mail) @mail.header[:skip_premailer] = true update_doc(@mail.html_part.body.raw_source) end
perform_full_compile()
click to toggle source
# File lib/bootstrap-email.rb, line 21 def perform_full_compile compile_html! inline_css! inject_head! update_mailer! end
update_doc(source)
click to toggle source
# File lib/bootstrap-email.rb, line 17 def update_doc(source) @doc = Nokogiri::HTML(source) end
update_mailer!()
click to toggle source
# File lib/bootstrap-email.rb, line 55 def update_mailer! @mail.html_part.body = @doc.to_html @mail end
Private Instance Methods
alert()
click to toggle source
# File lib/bootstrap-email.rb, line 95 def alert each_node('.alert') do |node| # move all classes up and remove all classes from the element node.replace(template('table', classes: node['class'], contents: node.delete('class') && node.to_html)) end end
align()
click to toggle source
# File lib/bootstrap-email.rb, line 101 def align each_node('.float-left') do |node| align_helper(node, /float-left/, 'left') end each_node('.mx-auto') do |node| align_helper(node, /mx-auto/, 'center') end each_node('.float-right') do |node| align_helper(node, /float-right/, 'right') end end
align_helper(node, klass, template)
click to toggle source
# File lib/bootstrap-email.rb, line 113 def align_helper(node, klass, template) if node.name != 'table' # if it is already on a table, set the proprieties on the current table node['class'] = node['class'].sub(klass, '') node.replace(template("align-#{template}", contents: node.to_html)) else node['align'] = template end end
badge()
click to toggle source
# File lib/bootstrap-email.rb, line 89 def badge each_node('.badge') do |node| # move all classes up and remove all classes from the element node.replace(template('table-left', classes: node['class'], contents: node.delete('class') && node.to_html)) end end
body()
click to toggle source
# File lib/bootstrap-email.rb, line 208 def body @doc.css('body').each do |node| node.replace('<body>' + preview_text.to_s + template('body', classes: "#{node['class']} body", contents: node.inner_html.to_s) + '</body>') end end
bootstrap_email_head()
click to toggle source
# File lib/bootstrap-email.rb, line 62 def bootstrap_email_head engine = defined?(SassC::Engine).nil? ? Sass::Engine : SassC::Engine html_string = <<-HEREDOC <style type="text/css"> #{engine.new(File.open(File.expand_path('../core/head.scss', __dir__)).read, syntax: :scss, style: :compressed, cache: false, read_cache: false).render} </style> HEREDOC html_string end
card()
click to toggle source
# File lib/bootstrap-email.rb, line 122 def card each_node('.card') do |node| # move all classes up and remove all classes from element node.replace(template('table', classes: node['class'], contents: node.delete('class') && node.to_html)) end each_node('.card-body') do |node| # move all classes up and remove all classes from element node.replace(template('table', classes: node['class'], contents: node.delete('class') && node.to_html)) end end
container()
click to toggle source
# File lib/bootstrap-email.rb, line 137 def container each_node('.container') do |node| node.replace(template('container', classes: node['class'], contents: node.inner_html)) end each_node('.container-fluid') do |node| node.replace(template('table', classes: node['class'], contents: node.inner_html)) end end
each_node(css_lookup, &blk)
click to toggle source
# File lib/bootstrap-email.rb, line 78 def each_node(css_lookup, &blk) # sort by youngest child and traverse backwards up the tree @doc.css(css_lookup).sort_by { |n| n.ancestors.size }.reverse!.each(&blk) end
grid()
click to toggle source
# File lib/bootstrap-email.rb, line 146 def grid each_node('.row') do |node| node.replace(template('row', classes: node['class'], contents: node.inner_html)) end each_node('*[class*=col]') do |node| node.replace(template('col', classes: node['class'], contents: node.inner_html)) end end
hr()
click to toggle source
# File lib/bootstrap-email.rb, line 131 def hr each_node('hr') do |node| # drop hr in place of current node.replace(template('hr', classes: "hr #{node['class']}")) end end
margin()
click to toggle source
# File lib/bootstrap-email.rb, line 166 def margin each_node('*[class*=my-], *[class*=mt-], *[class*=mb-]') do |node| top_class = node['class'][/m[ty]{1}-(lg-)?(\d)/] bottom_class = node['class'][/m[by]{1}-(lg-)?(\d)/] node['class'] = node['class'].gsub(/(m[tby]{1}-(lg-)?\d)/, '') html = '' if top_class html += template('div', classes: "s-#{top_class.gsub(/m[ty]{1}-/, '')}", contents: nil) end html += node.to_html if bottom_class html += template('div', classes: "s-#{bottom_class.gsub(/m[by]{1}-/, '')}", contents: nil) end node.replace(html) end end
padding()
click to toggle source
# File lib/bootstrap-email.rb, line 155 def padding each_node('*[class*=p-], *[class*=pt-], *[class*=pr-], *[class*=pb-], *[class*=pl-], *[class*=px-], *[class*=py-]') do |node| next unless node.name != 'table' # if it is already on a table, set the padding on the table, else wrap the content in a table padding_regex = /(p[trblxy]?-\d)/ classes = node['class'].scan(padding_regex).join(' ') node['class'] = node['class'].gsub(padding_regex, '') node.replace(template('table', classes: classes, contents: node.to_html)) end end
preview_text()
click to toggle source
# File lib/bootstrap-email.rb, line 214 def preview_text preview_node = @doc.at_css('preview') return if preview_node.blank? # apply spacing after the text max of 100 characters so it doesn't show body text preview_node.content += ' ' * [(100 - preview_node.content.length.to_i), 0].max node = template('div', classes: 'preview', contents: preview_node.content) preview_node.remove node end
spacer()
click to toggle source
# File lib/bootstrap-email.rb, line 183 def spacer spacers = { '0' => 0, '1' => (16 * 0.25), '2' => (16 * 0.5), '3' => 16, '4' => (16 * 1.5), '5' => (16 * 3) } each_node('*[class*=s-]') do |node| temp = Nokogiri::HTML::DocumentFragment.parse(template('table', classes: node['class'] + ' w-100', contents: ' ')) temp.at_css('td')['height'] = spacers[node['class'].gsub(/s-/, '')].to_i node.replace(temp) end end
table()
click to toggle source
# File lib/bootstrap-email.rb, line 199 def table @doc.css('table').each do |node| # border="0" cellpadding="0" cellspacing="0" node['border'] = 0 node['cellpadding'] = 0 node['cellspacing'] = 0 end end
template(file, locals_hash = {})
click to toggle source
# File lib/bootstrap-email.rb, line 72 def template(file, locals_hash = {}) namespace = OpenStruct.new(locals_hash) template_html = File.open(File.expand_path("../core/templates/#{file}.html.erb", __dir__)).read ERB.new(template_html).result(namespace.instance_eval { binding }) end