antwort 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +21 -0
 - data/.rspec +2 -0
 - data/.rubocop.yml +19 -0
 - data/.ruby-version +1 -0
 - data/CHANGELOG.md +249 -0
 - data/Gemfile +3 -0
 - data/Guardfile +14 -0
 - data/README.md +108 -0
 - data/Rakefile +14 -0
 - data/antwort.gemspec +45 -0
 - data/bin/antwort +5 -0
 - data/lib/antwort.rb +13 -0
 - data/lib/antwort/builder.rb +8 -0
 - data/lib/antwort/builder/builder.rb +104 -0
 - data/lib/antwort/builder/email.rb +61 -0
 - data/lib/antwort/builder/flattener.rb +37 -0
 - data/lib/antwort/builder/helpers/logic.rb +82 -0
 - data/lib/antwort/builder/helpers/sanitizers.rb +29 -0
 - data/lib/antwort/builder/partial.rb +80 -0
 - data/lib/antwort/builder/style.rb +59 -0
 - data/lib/antwort/cli.rb +7 -0
 - data/lib/antwort/cli/cli.rb +275 -0
 - data/lib/antwort/cli/helpers.rb +44 -0
 - data/lib/antwort/cli/send.rb +79 -0
 - data/lib/antwort/cli/upload.rb +89 -0
 - data/lib/antwort/helpers.rb +19 -0
 - data/lib/antwort/server.rb +70 -0
 - data/lib/antwort/server/assets.rb +23 -0
 - data/lib/antwort/server/helpers.rb +67 -0
 - data/lib/antwort/server/markup.rb +39 -0
 - data/lib/antwort/version.rb +3 -0
 - data/spec/builder/builder_spec.rb +30 -0
 - data/spec/builder/email_spec.rb +21 -0
 - data/spec/builder/flattener_spec.rb +64 -0
 - data/spec/builder/helpers_logic_spec.rb +244 -0
 - data/spec/builder/partial_spec.rb +87 -0
 - data/spec/builder/style_spec.rb +66 -0
 - data/spec/cli/helpers_spec.rb +60 -0
 - data/spec/cli/upload_spec.rb +47 -0
 - data/spec/cli_spec.rb +46 -0
 - data/spec/fixtures/assets/images/1-demo/placeholder.png +0 -0
 - data/spec/fixtures/assets/images/newsletter/placeholder.png +0 -0
 - data/spec/fixtures/assets/images/shared/placeholder-grey.png +0 -0
 - data/spec/fixtures/assets/images/shared/placeholder-white.png +0 -0
 - data/spec/fixtures/build/demo-123456/build.html +7 -0
 - data/spec/fixtures/build/demo-123457/build.html +7 -0
 - data/spec/fixtures/build/demo-bar-123/build.html +7 -0
 - data/spec/fixtures/build/foo-1/build.html +7 -0
 - data/spec/fixtures/data/1-demo.yml +3 -0
 - data/spec/fixtures/emails/1-demo/index.html.erb +9 -0
 - data/spec/fixtures/emails/2-no-layout/index.html.erb +6 -0
 - data/spec/fixtures/emails/3-no-title/index.html.erb +1 -0
 - data/spec/fixtures/views/404.html.erb +1 -0
 - data/spec/fixtures/views/index.html.erb +14 -0
 - data/spec/fixtures/views/layout.erb +8 -0
 - data/spec/fixtures/views/server.erb +5 -0
 - data/spec/server_spec.rb +54 -0
 - data/spec/spec_helper.rb +38 -0
 - data/spec/support/capture.rb +17 -0
 - data/template/email/css/include.scss +5 -0
 - data/template/email/css/inline.scss +5 -0
 - data/template/email/email.html.erb +11 -0
 - data/template/email/images/.empty_directory +0 -0
 - data/template/project/.env.sample +21 -0
 - data/template/project/.gitignore.tt +17 -0
 - data/template/project/.ruby-version +1 -0
 - data/template/project/Gemfile.tt +9 -0
 - data/template/project/Guardfile +9 -0
 - data/template/project/assets/css/demo/include.scss +3 -0
 - data/template/project/assets/css/demo/inline.scss +33 -0
 - data/template/project/assets/css/server.scss +167 -0
 - data/template/project/assets/css/shared/_base.scss +64 -0
 - data/template/project/assets/css/shared/_mixins.scss +25 -0
 - data/template/project/assets/css/shared/_reset.scss +59 -0
 - data/template/project/assets/css/shared/_vars.scss +12 -0
 - data/template/project/assets/css/shared/include.scss +23 -0
 - data/template/project/assets/css/shared/inline.scss +9 -0
 - data/template/project/assets/images/.gitkeep +0 -0
 - data/template/project/assets/images/shared/placeholder.png +0 -0
 - data/template/project/build/.empty_directory +0 -0
 - data/template/project/data/.empty_directory +0 -0
 - data/template/project/data/config.yml +3 -0
 - data/template/project/data/demo.yml +4 -0
 - data/template/project/emails/demo/_partial.html.erb +9 -0
 - data/template/project/emails/demo/index.html.erb +54 -0
 - data/template/project/views/404.html.erb +8 -0
 - data/template/project/views/index.html.erb +18 -0
 - data/template/project/views/layout.erb +38 -0
 - data/template/project/views/markup/_button.html.erb +5 -0
 - data/template/project/views/markup/_image_tag.html.erb +10 -0
 - data/template/project/views/server.erb +32 -0
 - metadata +443 -0
 
| 
         @@ -0,0 +1,59 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Antwort
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Style
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :keys, :duplicate_keys, :flattened, :original
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(style = '')
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @style         = style
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @keys           = []
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @duplicate_keys = []
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @flattened      = []
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @original       = []
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  convert_to_hash
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  self
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                def original_str
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @style
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                def flattened_str
         
     | 
| 
      
 22 
     | 
    
         
            +
                  hash_to_str @flattened
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                def duplicates?
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @duplicate_keys.length > 0
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                private
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def convert_to_hash
         
     | 
| 
      
 32 
     | 
    
         
            +
                    str  = String.new(@style)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    h    = Hash.new
         
     | 
| 
      
 34 
     | 
    
         
            +
                    keys = Array.new
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    str.split(';').each do |s|
         
     | 
| 
      
 37 
     | 
    
         
            +
                      key = s.split(':').first.strip
         
     | 
| 
      
 38 
     | 
    
         
            +
                      val = s.split(':').last.strip
         
     | 
| 
      
 39 
     | 
    
         
            +
                      h[key] = val
         
     | 
| 
      
 40 
     | 
    
         
            +
                      @original << { key => val }
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                      if @keys.include? key
         
     | 
| 
      
 43 
     | 
    
         
            +
                        @duplicate_keys << key
         
     | 
| 
      
 44 
     | 
    
         
            +
                      else
         
     | 
| 
      
 45 
     | 
    
         
            +
                        @keys << key
         
     | 
| 
      
 46 
     | 
    
         
            +
                      end
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                    @flattened = h
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  # convert our flatted styles hash back into a string
         
     | 
| 
      
 52 
     | 
    
         
            +
                  def hash_to_str(hash)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    str = ''
         
     | 
| 
      
 54 
     | 
    
         
            +
                    hash.each { |k,v| str << "#{k}:#{v};" }
         
     | 
| 
      
 55 
     | 
    
         
            +
                    str.chop! if str[-1] == ';' # remove trailing ';'
         
     | 
| 
      
 56 
     | 
    
         
            +
                    str
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/antwort/cli.rb
    ADDED
    
    
| 
         @@ -0,0 +1,275 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Antwort
         
     | 
| 
      
 2 
     | 
    
         
            +
              class CLI < Thor
         
     | 
| 
      
 3 
     | 
    
         
            +
                include Thor::Actions
         
     | 
| 
      
 4 
     | 
    
         
            +
                include Antwort::CLIHelpers
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                class_option :version, type: :boolean
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                # set template source path for Thor
         
     | 
| 
      
 9 
     | 
    
         
            +
                def self.source_root
         
     | 
| 
      
 10 
     | 
    
         
            +
                  File.expand_path('../../../template', File.dirname(__FILE__))
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                #-- init
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                desc 'init [project_name]', 'Initializes a new Antwort Email project'
         
     | 
| 
      
 16 
     | 
    
         
            +
                method_option :user,
         
     | 
| 
      
 17 
     | 
    
         
            +
                              type: :string,
         
     | 
| 
      
 18 
     | 
    
         
            +
                              desc: 'Your username to antwort gem server'
         
     | 
| 
      
 19 
     | 
    
         
            +
                method_option :key,
         
     | 
| 
      
 20 
     | 
    
         
            +
                              type: :string,
         
     | 
| 
      
 21 
     | 
    
         
            +
                              desc: 'Your password to antwort gem server'
         
     | 
| 
      
 22 
     | 
    
         
            +
                method_option :git,
         
     | 
| 
      
 23 
     | 
    
         
            +
                              type: :boolean,
         
     | 
| 
      
 24 
     | 
    
         
            +
                              default: true,
         
     | 
| 
      
 25 
     | 
    
         
            +
                              desc: 'Initializes git repo if set to true'
         
     | 
| 
      
 26 
     | 
    
         
            +
                method_option :bundle,
         
     | 
| 
      
 27 
     | 
    
         
            +
                              type: :boolean,
         
     | 
| 
      
 28 
     | 
    
         
            +
                              default: true,
         
     | 
| 
      
 29 
     | 
    
         
            +
                              desc: 'Runs bundle command in new repo'
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                def init(project_name)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @project_name = project_name
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @user         = options[:user] if options[:user]
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @key          = options[:key] if options[:key]
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  copy_project
         
     | 
| 
      
 37 
     | 
    
         
            +
                  initialize_git_repo if options[:git]
         
     | 
| 
      
 38 
     | 
    
         
            +
                  run_bundler if options[:bundle]
         
     | 
| 
      
 39 
     | 
    
         
            +
                  say "New project initialized in: ./#{project_directory}/", :green
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                #-- new
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                desc 'new [email_id]', 'Creates a new email template'
         
     | 
| 
      
 45 
     | 
    
         
            +
                method_option aliases: 'n'
         
     | 
| 
      
 46 
     | 
    
         
            +
                def new(email_id)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @email_id = email_id
         
     | 
| 
      
 48 
     | 
    
         
            +
                  copy_email
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                #-- list
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                desc 'list', 'Lists all emails in the ./emails directory by id'
         
     | 
| 
      
 54 
     | 
    
         
            +
                method_option aliases: 'l'
         
     | 
| 
      
 55 
     | 
    
         
            +
                def list
         
     | 
| 
      
 56 
     | 
    
         
            +
                  list_folders('./emails').each { |e| puts "- #{e}" }
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                #-- upload
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                desc 'upload', 'Uploads email assets to AWS S3'
         
     | 
| 
      
 62 
     | 
    
         
            +
                method_option :force,
         
     | 
| 
      
 63 
     | 
    
         
            +
                              type: :boolean,
         
     | 
| 
      
 64 
     | 
    
         
            +
                              default: false,
         
     | 
| 
      
 65 
     | 
    
         
            +
                              aliases: '-f',
         
     | 
| 
      
 66 
     | 
    
         
            +
                              desc: 'Overwrites existing files on the server'
         
     | 
| 
      
 67 
     | 
    
         
            +
                method_option aliases: 'u'
         
     | 
| 
      
 68 
     | 
    
         
            +
                def upload(email_id)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  Upload.new(email_id, options[:force]).upload
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                #-- send
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                desc 'send [email_id]', 'Sends built email via SMTP'
         
     | 
| 
      
 75 
     | 
    
         
            +
                method_option :from,
         
     | 
| 
      
 76 
     | 
    
         
            +
                              type: :string,
         
     | 
| 
      
 77 
     | 
    
         
            +
                              default: ENV['SEND_FROM'],
         
     | 
| 
      
 78 
     | 
    
         
            +
                              aliases: '-f',
         
     | 
| 
      
 79 
     | 
    
         
            +
                              desc: 'Email address of sender'
         
     | 
| 
      
 80 
     | 
    
         
            +
                method_option :recipient,
         
     | 
| 
      
 81 
     | 
    
         
            +
                              type: :string,
         
     | 
| 
      
 82 
     | 
    
         
            +
                              default: ENV['SEND_TO'],
         
     | 
| 
      
 83 
     | 
    
         
            +
                              aliases: '-r',
         
     | 
| 
      
 84 
     | 
    
         
            +
                              desc: 'Email address of receipient'
         
     | 
| 
      
 85 
     | 
    
         
            +
                method_option :subject,
         
     | 
| 
      
 86 
     | 
    
         
            +
                              type: :string,
         
     | 
| 
      
 87 
     | 
    
         
            +
                              aliases: '-s',
         
     | 
| 
      
 88 
     | 
    
         
            +
                              desc: 'Email Subject. Defaults to <title> value if blank.'
         
     | 
| 
      
 89 
     | 
    
         
            +
                def send(email_id)
         
     | 
| 
      
 90 
     | 
    
         
            +
                  build = last_build_by_id(email_id)
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                  if build.nil?
         
     | 
| 
      
 93 
     | 
    
         
            +
                    say "   warning  ", :yellow
         
     | 
| 
      
 94 
     | 
    
         
            +
                    say "No build found for '#{email_id}'. Building now..."
         
     | 
| 
      
 95 
     | 
    
         
            +
                    build(email_id)
         
     | 
| 
      
 96 
     | 
    
         
            +
                    build = last_build_by_id(email_id)
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  Send.new(build, options).send
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                #-- server
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                desc 'server', 'Starts http://localhost:9292 server for coding and previewing emails'
         
     | 
| 
      
 105 
     | 
    
         
            +
                method_option :port,
         
     | 
| 
      
 106 
     | 
    
         
            +
                              type: :string,
         
     | 
| 
      
 107 
     | 
    
         
            +
                              default: 9292,
         
     | 
| 
      
 108 
     | 
    
         
            +
                              aliases: '-p',
         
     | 
| 
      
 109 
     | 
    
         
            +
                              desc: 'Port number of server'
         
     | 
| 
      
 110 
     | 
    
         
            +
                def server
         
     | 
| 
      
 111 
     | 
    
         
            +
                  require 'antwort'
         
     | 
| 
      
 112 
     | 
    
         
            +
                  Antwort::Server.run!(port: options[:port])
         
     | 
| 
      
 113 
     | 
    
         
            +
                end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                #-- build
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                desc 'build [email_id]', 'Builds email markup and inlines CSS from source'
         
     | 
| 
      
 118 
     | 
    
         
            +
                method_option aliases: 'b'
         
     | 
| 
      
 119 
     | 
    
         
            +
                method_option :all,
         
     | 
| 
      
 120 
     | 
    
         
            +
                              type: :boolean,
         
     | 
| 
      
 121 
     | 
    
         
            +
                              default: false,
         
     | 
| 
      
 122 
     | 
    
         
            +
                              aliases: '-a',
         
     | 
| 
      
 123 
     | 
    
         
            +
                              desc: 'Build all templates'
         
     | 
| 
      
 124 
     | 
    
         
            +
                method_option :partials,
         
     | 
| 
      
 125 
     | 
    
         
            +
                              type: :boolean,
         
     | 
| 
      
 126 
     | 
    
         
            +
                              default: false,
         
     | 
| 
      
 127 
     | 
    
         
            +
                              aliases: '-p',
         
     | 
| 
      
 128 
     | 
    
         
            +
                              desc: 'Build partials'
         
     | 
| 
      
 129 
     | 
    
         
            +
                method_option :'css-style',
         
     | 
| 
      
 130 
     | 
    
         
            +
                              type: :string,
         
     | 
| 
      
 131 
     | 
    
         
            +
                              default: 'expanded',
         
     | 
| 
      
 132 
     | 
    
         
            +
                              aliases: '-c',
         
     | 
| 
      
 133 
     | 
    
         
            +
                              desc: 'CSS output style'
         
     | 
| 
      
 134 
     | 
    
         
            +
                def build(email_id='')
         
     | 
| 
      
 135 
     | 
    
         
            +
                  require 'antwort'
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                  emails = options[:all] ? available_emails : Array.new.push(email_id)
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                  emails.each do |email_id|
         
     | 
| 
      
 140 
     | 
    
         
            +
                    attrs = { email: email_id, id: create_id_from_timestamp }.merge(options)
         
     | 
| 
      
 141 
     | 
    
         
            +
                    email = Antwort::EmailBuilder.new(attrs)
         
     | 
| 
      
 142 
     | 
    
         
            +
                    until email.build
         
     | 
| 
      
 143 
     | 
    
         
            +
                      sleep 1
         
     | 
| 
      
 144 
     | 
    
         
            +
                    end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                    if build_partials?
         
     | 
| 
      
 147 
     | 
    
         
            +
                      partials = Antwort::PartialBuilder.new(attrs)
         
     | 
| 
      
 148 
     | 
    
         
            +
                      sleep 1 until partials.build
         
     | 
| 
      
 149 
     | 
    
         
            +
                    end
         
     | 
| 
      
 150 
     | 
    
         
            +
                  end
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                  show_accuracy_warning if build_partials?
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                  return true
         
     | 
| 
      
 155 
     | 
    
         
            +
                end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                #-- prune
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                desc 'prune', 'Removes all files in the ./build directory'
         
     | 
| 
      
 160 
     | 
    
         
            +
                method_option :force,
         
     | 
| 
      
 161 
     | 
    
         
            +
                          type: :boolean,
         
     | 
| 
      
 162 
     | 
    
         
            +
                          default: false,
         
     | 
| 
      
 163 
     | 
    
         
            +
                          aliases: '-f',
         
     | 
| 
      
 164 
     | 
    
         
            +
                          desc: 'Removes all files in the ./build directory'
         
     | 
| 
      
 165 
     | 
    
         
            +
                def prune
         
     | 
| 
      
 166 
     | 
    
         
            +
                  if confirms_prune?
         
     | 
| 
      
 167 
     | 
    
         
            +
                    build_dir = File.expand_path('./build')
         
     | 
| 
      
 168 
     | 
    
         
            +
                    Dir.foreach(build_dir) do |f|
         
     | 
| 
      
 169 
     | 
    
         
            +
                      next if f.to_s[0] == '.'
         
     | 
| 
      
 170 
     | 
    
         
            +
                      say "   delete ", :red
         
     | 
| 
      
 171 
     | 
    
         
            +
                      say "./build/#{f}/"
         
     | 
| 
      
 172 
     | 
    
         
            +
                      FileUtils.rm_rf(File.expand_path("./build/#{f}"))
         
     | 
| 
      
 173 
     | 
    
         
            +
                    end
         
     | 
| 
      
 174 
     | 
    
         
            +
                  else
         
     | 
| 
      
 175 
     | 
    
         
            +
                    say "prune aborted."
         
     | 
| 
      
 176 
     | 
    
         
            +
                  end
         
     | 
| 
      
 177 
     | 
    
         
            +
                end
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
                #-- remove
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                desc 'remove [email_id]', 'Removes an email, incl. its assets, styles and data'
         
     | 
| 
      
 182 
     | 
    
         
            +
                method_option :force,
         
     | 
| 
      
 183 
     | 
    
         
            +
                          type: :boolean,
         
     | 
| 
      
 184 
     | 
    
         
            +
                          default: false,
         
     | 
| 
      
 185 
     | 
    
         
            +
                          aliases: '-f',
         
     | 
| 
      
 186 
     | 
    
         
            +
                          desc: 'Removes an email, incl. its assets, styles and data'
         
     | 
| 
      
 187 
     | 
    
         
            +
                def remove(email_id)
         
     | 
| 
      
 188 
     | 
    
         
            +
                  @email_id = email_id
         
     | 
| 
      
 189 
     | 
    
         
            +
                  if confirms_remove?
         
     | 
| 
      
 190 
     | 
    
         
            +
                    remove_email
         
     | 
| 
      
 191 
     | 
    
         
            +
                  else
         
     | 
| 
      
 192 
     | 
    
         
            +
                    say "Remove aborted."
         
     | 
| 
      
 193 
     | 
    
         
            +
                  end
         
     | 
| 
      
 194 
     | 
    
         
            +
                end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                #-- version
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                desc 'version','Ouputs version number'
         
     | 
| 
      
 199 
     | 
    
         
            +
                def version
         
     | 
| 
      
 200 
     | 
    
         
            +
                  puts "Version: #{Antwort::VERSION}" if options[:version]
         
     | 
| 
      
 201 
     | 
    
         
            +
                end
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                default_task :version
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
                attr_reader :project_name, :email_id
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                no_commands do
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                  def build_partials?
         
     | 
| 
      
 210 
     | 
    
         
            +
                    options[:partials]
         
     | 
| 
      
 211 
     | 
    
         
            +
                  end
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                  def confirms_prune?
         
     | 
| 
      
 214 
     | 
    
         
            +
                    options[:force] || yes?('Are you sure you want to delete all folders in the ./build directory? (y/n)')
         
     | 
| 
      
 215 
     | 
    
         
            +
                  end
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                  def confirms_remove?
         
     | 
| 
      
 218 
     | 
    
         
            +
                    options[:force] || yes?("Are you sure you want to delete '#{email_id}', including its css, images and data? (y/n)")
         
     | 
| 
      
 219 
     | 
    
         
            +
                  end
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
                  def copy_email
         
     | 
| 
      
 222 
     | 
    
         
            +
                    directory 'email/css',
         
     | 
| 
      
 223 
     | 
    
         
            +
                              File.join('assets', 'css', email_directory)
         
     | 
| 
      
 224 
     | 
    
         
            +
                    directory 'email/images',
         
     | 
| 
      
 225 
     | 
    
         
            +
                              File.join('assets', 'images', email_directory)
         
     | 
| 
      
 226 
     | 
    
         
            +
                    create_file File.join('data', "#{email_id}.yml")
         
     | 
| 
      
 227 
     | 
    
         
            +
                    copy_file 'email/email.html.erb',
         
     | 
| 
      
 228 
     | 
    
         
            +
                              File.join('emails', email_directory, 'index.html.erb')
         
     | 
| 
      
 229 
     | 
    
         
            +
                  end
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                  def remove_email
         
     | 
| 
      
 232 
     | 
    
         
            +
                    remove_file File.expand_path("./data/#{email_id}.yml")
         
     | 
| 
      
 233 
     | 
    
         
            +
                    remove_dir File.expand_path("./assets/css/#{email_id}/")
         
     | 
| 
      
 234 
     | 
    
         
            +
                    remove_dir File.expand_path("./assets/images/#{email_id}/")
         
     | 
| 
      
 235 
     | 
    
         
            +
                    remove_dir File.expand_path("./emails/#{email_id}/")
         
     | 
| 
      
 236 
     | 
    
         
            +
                  end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                  def copy_project
         
     | 
| 
      
 239 
     | 
    
         
            +
                    directory 'project', project_directory
         
     | 
| 
      
 240 
     | 
    
         
            +
                  end
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
                  def initialize_git_repo
         
     | 
| 
      
 243 
     | 
    
         
            +
                    inside(project_directory) do
         
     | 
| 
      
 244 
     | 
    
         
            +
                      run('git init .')
         
     | 
| 
      
 245 
     | 
    
         
            +
                    end
         
     | 
| 
      
 246 
     | 
    
         
            +
                  end
         
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
      
 248 
     | 
    
         
            +
                  def run_bundler
         
     | 
| 
      
 249 
     | 
    
         
            +
                    inside(project_directory) do
         
     | 
| 
      
 250 
     | 
    
         
            +
                      run('bundle')
         
     | 
| 
      
 251 
     | 
    
         
            +
                    end
         
     | 
| 
      
 252 
     | 
    
         
            +
                  end
         
     | 
| 
      
 253 
     | 
    
         
            +
             
     | 
| 
      
 254 
     | 
    
         
            +
                  def email_directory
         
     | 
| 
      
 255 
     | 
    
         
            +
                    email_id.downcase.gsub(/([^A-Za-z0-9_\/-]+)|(--)/, '')
         
     | 
| 
      
 256 
     | 
    
         
            +
                  end
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
                  def project_directory
         
     | 
| 
      
 259 
     | 
    
         
            +
                    project_name.downcase.gsub(/([^A-Za-z0-9_\/-]+)|(--)/, '')
         
     | 
| 
      
 260 
     | 
    
         
            +
                  end
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
                  def create_id_from_timestamp
         
     | 
| 
      
 263 
     | 
    
         
            +
                    stamp = Time.now.to_s
         
     | 
| 
      
 264 
     | 
    
         
            +
                    stamp.split(' ')[0..1].join.gsub(/(-|:)/, '')
         
     | 
| 
      
 265 
     | 
    
         
            +
                  end
         
     | 
| 
      
 266 
     | 
    
         
            +
             
     | 
| 
      
 267 
     | 
    
         
            +
                  def show_accuracy_warning
         
     | 
| 
      
 268 
     | 
    
         
            +
                    say ''
         
     | 
| 
      
 269 
     | 
    
         
            +
                    say '** NOTE: Accuracy of Inlinied Partials **', :yellow
         
     | 
| 
      
 270 
     | 
    
         
            +
                    say 'Partials do not have access to the full DOM tree. Therefore, nested CSS selectors, e.g. ".layout td",'
         
     | 
| 
      
 271 
     | 
    
         
            +
                    say 'may not be matched for inlining. Always double check your code before use in production!'
         
     | 
| 
      
 272 
     | 
    
         
            +
                  end
         
     | 
| 
      
 273 
     | 
    
         
            +
                end
         
     | 
| 
      
 274 
     | 
    
         
            +
              end
         
     | 
| 
      
 275 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Antwort
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CLIHelpers
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def built_emails
         
     | 
| 
      
 5 
     | 
    
         
            +
                  list_folders('./build')
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                def available_emails
         
     | 
| 
      
 9 
     | 
    
         
            +
                  list_folders('./emails')
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def images_dir(email_id)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  "./assets/images/#{email_id}"
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def count_files(dir)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  Dir[File.join(dir, '**', '*')].count { |f| File.file? f }
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def last_build_by_id(email_id)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  built_emails.select { |f| f.split('-')[0..-2].join('-') == email_id }.sort.last
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def list_folders(folder_name)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  path = File.expand_path(folder_name)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  Dir.entries(path).select { |f| !f.include? '.' }
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def list_partials(folder_name)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  path = File.expand_path(folder_name)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  Dir.entries(path).select { |f| f[0]== '_' && f[-4,4] == '.erb' }
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def folder_exists?(folder_name)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  if Dir.exists?(folder_name)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 37 
     | 
    
         
            +
                  else
         
     | 
| 
      
 38 
     | 
    
         
            +
                    say "Error: Folder #{folder_name} does not exist.", :red
         
     | 
| 
      
 39 
     | 
    
         
            +
                    return false
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,79 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'thor/shell'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'mail'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Antwort
         
     | 
| 
      
 5 
     | 
    
         
            +
              class CLI
         
     | 
| 
      
 6 
     | 
    
         
            +
                class Send
         
     | 
| 
      
 7 
     | 
    
         
            +
                  include Thor::Shell
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :build_id, :sender, :recipient, :subject
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  Mail.defaults do
         
     | 
| 
      
 11 
     | 
    
         
            +
                    delivery_method :smtp,
         
     | 
| 
      
 12 
     | 
    
         
            +
                                    address:   ENV['SMTP_SERVER'],
         
     | 
| 
      
 13 
     | 
    
         
            +
                                    port:      ENV['SMTP_PORT'],
         
     | 
| 
      
 14 
     | 
    
         
            +
                                    user_name: ENV['SMTP_USERNAME'],
         
     | 
| 
      
 15 
     | 
    
         
            +
                                    password:  ENV['SMTP_PASSWORD'],
         
     | 
| 
      
 16 
     | 
    
         
            +
                                    authentication: 'plain',
         
     | 
| 
      
 17 
     | 
    
         
            +
                                    enable_starttls_auto: false,
         
     | 
| 
      
 18 
     | 
    
         
            +
                                    return_response: true
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def initialize(build_id, options={})
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @build_id  = build_id
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @html_body = File.open("#{build_folder}/#{template_name}.html").read
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    @recipient = options[:recipient]
         
     | 
| 
      
 26 
     | 
    
         
            +
                    @sender    = options[:from] || ENV['SEND_FROM']
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @subject   = options[:subject] || "[Test] " << extract_title(@html_body)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def send
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # because scope changes inside mail DSL
         
     | 
| 
      
 32 
     | 
    
         
            +
                    mail_from    = @sender
         
     | 
| 
      
 33 
     | 
    
         
            +
                    mail_to      = @recipient
         
     | 
| 
      
 34 
     | 
    
         
            +
                    mail_subject = @subject
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    # setup email
         
     | 
| 
      
 37 
     | 
    
         
            +
                    mail = Mail.new do
         
     | 
| 
      
 38 
     | 
    
         
            +
                      from     mail_from
         
     | 
| 
      
 39 
     | 
    
         
            +
                      to       mail_to
         
     | 
| 
      
 40 
     | 
    
         
            +
                      subject  mail_subject
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                      text_part do
         
     | 
| 
      
 43 
     | 
    
         
            +
                        body 'This is plain text'
         
     | 
| 
      
 44 
     | 
    
         
            +
                      end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                      html_part do
         
     | 
| 
      
 47 
     | 
    
         
            +
                        content_type 'text/html; charset=UTF-8'
         
     | 
| 
      
 48 
     | 
    
         
            +
                        body @html_body
         
     | 
| 
      
 49 
     | 
    
         
            +
                      end
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    # send email
         
     | 
| 
      
 53 
     | 
    
         
            +
                    if mail.deliver!
         
     | 
| 
      
 54 
     | 
    
         
            +
                      say "Sent Email \"#{template_name}\" at #{Time.now.strftime('%d.%m.%Y %H:%M')}", :green
         
     | 
| 
      
 55 
     | 
    
         
            +
                      say "  to:      #{@recipient}"
         
     | 
| 
      
 56 
     | 
    
         
            +
                      say "  subject: #{@subject}"
         
     | 
| 
      
 57 
     | 
    
         
            +
                      say "  html:    #{build_id}/#{template_name}.html"
         
     | 
| 
      
 58 
     | 
    
         
            +
                    else
         
     | 
| 
      
 59 
     | 
    
         
            +
                      say "Error sending #{build_id}/#{template_name} at #{Time.now.strftime('%d.%m.%Y %H:%M')}", :red
         
     | 
| 
      
 60 
     | 
    
         
            +
                    end
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  private
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  def template_name
         
     | 
| 
      
 66 
     | 
    
         
            +
                    @build_id.split('-')[0...-1].join('-') # removes timestamp ID
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  def build_folder
         
     | 
| 
      
 70 
     | 
    
         
            +
                    "build/#{@build_id}"
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  def extract_title(body = '')
         
     | 
| 
      
 74 
     | 
    
         
            +
                    body.scan(%r{<title>(.*?)</title>}).first.first
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
            end
         
     |