antwort 0.0.12 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +12 -0
  4. data/.ruby-version +1 -1
  5. data/CHANGELOG.md +28 -1
  6. data/README.md +1 -1
  7. data/antwort.gemspec +2 -2
  8. data/lib/antwort.rb +5 -4
  9. data/lib/antwort/builder/builder.rb +15 -24
  10. data/lib/antwort/builder/email.rb +47 -22
  11. data/lib/antwort/builder/flattener.rb +8 -9
  12. data/lib/antwort/builder/partial.rb +12 -11
  13. data/lib/antwort/builder/style.rb +26 -27
  14. data/lib/antwort/{builder.rb → builders.rb} +3 -3
  15. data/lib/antwort/cli.rb +0 -1
  16. data/lib/antwort/cli/cli.rb +42 -48
  17. data/lib/antwort/cli/send.rb +11 -14
  18. data/lib/antwort/cli/upload.rb +29 -28
  19. data/lib/antwort/core.rb +4 -0
  20. data/lib/antwort/email/build.rb +41 -0
  21. data/lib/antwort/email/collection.rb +41 -0
  22. data/lib/antwort/email/data.rb +27 -0
  23. data/lib/antwort/email/template.rb +88 -0
  24. data/lib/antwort/helpers/file_helper.rb +27 -0
  25. data/lib/antwort/{helpers.rb → helpers/helper.rb} +2 -2
  26. data/lib/antwort/helpers/logic_helper.rb +81 -0
  27. data/lib/antwort/helpers/markup_helper.rb +37 -0
  28. data/lib/antwort/{builder/helpers/sanitizers.rb → helpers/sanitizers_helper.rb} +2 -4
  29. data/lib/antwort/helpers/server_helper.rb +32 -0
  30. data/lib/antwort/{server.rb → server/server.rb} +26 -23
  31. data/{template/project → lib/antwort/server}/views/404.html.erb +1 -1
  32. data/{template/project → lib/antwort/server}/views/index.html.erb +4 -6
  33. data/{template/project → lib/antwort/server}/views/layout.erb +5 -5
  34. data/{template/project/views/markup/_button.html.erb → lib/antwort/server/views/markup/button.html.erb} +0 -0
  35. data/{template/project/views/markup/_image_tag.html.erb → lib/antwort/server/views/markup/image_tag.html.erb} +0 -0
  36. data/{template/project → lib/antwort/server}/views/server.erb +0 -0
  37. data/lib/antwort/version.rb +1 -1
  38. data/spec/builder/builder_spec.rb +17 -22
  39. data/spec/builder/email_spec.rb +11 -12
  40. data/spec/builder/flattener_spec.rb +20 -21
  41. data/spec/builder/helpers_logic_spec.rb +69 -73
  42. data/spec/builder/partial_spec.rb +42 -51
  43. data/spec/builder/style_spec.rb +25 -34
  44. data/spec/{cli_spec.rb → cli/cli_spec.rb} +8 -9
  45. data/spec/cli/send_spec.rb +80 -0
  46. data/spec/cli/upload_spec.rb +17 -9
  47. data/spec/email/build_spec.rb +13 -0
  48. data/spec/email/collection_spec.rb +56 -0
  49. data/spec/email/data_spec.rb +40 -0
  50. data/spec/email/template_spec.rb +116 -0
  51. data/spec/fixtures/assets/css/demo/include.scss +3 -0
  52. data/spec/fixtures/assets/css/demo/inline.scss +33 -0
  53. data/spec/fixtures/assets/css/no-images/include.scss +1 -0
  54. data/spec/fixtures/assets/css/no-images/inline.scss +2 -0
  55. data/spec/fixtures/assets/css/shared/_base.scss +64 -0
  56. data/spec/fixtures/assets/css/shared/_mixins.scss +25 -0
  57. data/spec/fixtures/assets/css/shared/_reset.scss +59 -0
  58. data/spec/fixtures/assets/css/shared/_vars.scss +12 -0
  59. data/spec/fixtures/assets/css/shared/include.scss +23 -0
  60. data/spec/fixtures/assets/css/shared/inline.scss +9 -0
  61. data/spec/fixtures/build/demo-20160101/demo.html +177 -0
  62. data/spec/fixtures/build/demo-20160101/source/demo.html +118 -0
  63. data/spec/fixtures/build/demo-20160101/source/include.css +58 -0
  64. data/spec/fixtures/build/demo-20160101/source/inline.css +83 -0
  65. data/spec/fixtures/build/demo-20160102/demo.html +177 -0
  66. data/spec/fixtures/build/demo-20160102/source/demo.html +118 -0
  67. data/spec/fixtures/build/demo-20160102/source/include.css +58 -0
  68. data/spec/fixtures/build/demo-20160102/source/inline.css +83 -0
  69. data/{template/project/data/.empty_directory → spec/fixtures/emails/1-demo/_bar.erb} +0 -0
  70. data/spec/fixtures/emails/1-demo/_foo.erb +0 -0
  71. data/spec/fixtures/emails/1-demo/index.html.erb +2 -2
  72. data/spec/fixtures/emails/4-custom-layout/index.html.erb +6 -0
  73. data/spec/fixtures/emails/4-custom-layout/layout.erb +5 -0
  74. data/spec/fixtures/emails/demo/index.html.erb +4 -0
  75. data/spec/fixtures/emails/no-images/index.html.erb +4 -0
  76. data/spec/fixtures/emails/shared/_foo.erb +0 -0
  77. data/spec/fixtures/{views → emails/shared}/layout.erb +0 -0
  78. data/spec/helpers/file_helper_spec.rb +30 -0
  79. data/spec/server/server_spec.rb +57 -0
  80. data/spec/spec_helper.rb +18 -7
  81. data/template/project/Gemfile.tt +1 -7
  82. metadata +92 -42
  83. data/lib/antwort/builder/helpers/logic.rb +0 -82
  84. data/lib/antwort/cli/helpers.rb +0 -44
  85. data/lib/antwort/server/helpers.rb +0 -67
  86. data/lib/antwort/server/markup.rb +0 -39
  87. data/spec/cli/helpers_spec.rb +0 -60
  88. data/spec/fixtures/build/demo-123456/build.html +0 -7
  89. data/spec/fixtures/build/demo-123457/build.html +0 -7
  90. data/spec/fixtures/build/demo-bar-123/build.html +0 -7
  91. data/spec/fixtures/views/404.html.erb +0 -1
  92. data/spec/fixtures/views/index.html.erb +0 -14
  93. data/spec/fixtures/views/server.erb +0 -5
  94. data/spec/server_spec.rb +0 -54
  95. data/template/project/.ruby-version +0 -1
  96. data/template/project/data/config.yml +0 -3
@@ -1,82 +0,0 @@
1
- module Antwort
2
- module LogicHelpers
3
-
4
- def preserve_nbsps(html = '')
5
- html.gsub(/ /, '%nbspace%')
6
- end
7
-
8
- def restore_nbsps(html = '')
9
- html.gsub(/%nbspace%/, ' ')
10
- end
11
-
12
- def preserve_logic(html = '')
13
- html = preserve_comments(html)
14
- html = preserve_conditionals(html) # conditionals before loops, in case we have them inside loops
15
- html = preserve_loops(html)
16
- html = preserve_variables(html)
17
- html = preserve_assignments(html)
18
- html = convert_partials_to_includes(html)
19
- html = convert_helper_wrappers(html)
20
- html = preserve_leftover_statements(html) # must be last
21
- html
22
- end
23
-
24
- def preserve_conditionals(html = '')
25
- html.gsub(%r{<%\s*if (.*?)%>}, '{% if \1 %}') # if
26
- .gsub(%r{<%\s*unless (.*?)%>}, '{% if !( \1) %}') # unless
27
- .gsub(%r{<%\s*elsif(.*?)%>}, '{% elseif\1%}') # elsif
28
- .gsub(%r{<%\s*else\s*%>}, '{% else %}') # else
29
- .gsub(%r{<%\s*end\s*%>}, '{% end %}') # end
30
- .gsub(/[ \t]{2,}%}/, ' %}') # remove extra white space, e.g. {% else %}
31
- end
32
-
33
- def preserve_loops(html = '')
34
- html.gsub(%r{<%\s+(.*)(\.each\s+do\s+\|)\s*(\S+)\s*(\|\s+)%>}, '{% for \3 in \1 %}')
35
- .gsub(%r{<%\s+(.*)(\.each_with_index\s+do\s+\|)\s*(\S+)\s*,\s*(\S+)\s*(\|\s+)%>}, '{% for \3 in \1 with: {@index: \4} %}')
36
- .gsub(%r{<%\s*end\s*%>}, '{% end %}')
37
- end
38
-
39
- def preserve_comments(html = '')
40
- html.gsub(%r{<%[ \t]*#(.*)%>},'{#\1#}')
41
- .gsub(/{#([^=\s])/, '{# \1') # {#foo #} ->{# foo #}
42
- end
43
-
44
- def preserve_variables(html = '')
45
- html.gsub(/\[:(.*?)\]/, '.\1') # a[:b][:c] -> a.b.c
46
- .gsub(/\['(.*?)'\]/, '.\1') # a['b'] -> a.b
47
- .gsub(/\["(.*?)"\]/, '.\1') # a["b"] -> a.b
48
- .gsub(%r{<%=(.*?)%>}, '{{\1}}') # assume leftover erb output are variables
49
- end
50
-
51
- def preserve_assignments(html = '')
52
- html.gsub(%r{<%\s+([A-Za-z0-9_]+)\s*(\|\|=)\s*(.*)\s+%>}, '{% set \1 = \1 || \3 %}')
53
- .gsub(%r{<%\s+([A-Za-z0-9_]+)\s*(=)\s*(.*)\s+%>}, '{% set \1 = \3 %}')
54
- end
55
-
56
- def preserve_leftover_statements(html = '')
57
- html.gsub(%r{<%\s*(.*?)?%>}, '{% \1%}') # no trailing space because group captures it
58
- end
59
-
60
- def restore_variables_in_links(html = '')
61
- html.gsub('%7B%7B%20','{{ ')
62
- .gsub('%20%7D%7D',' }}')
63
- end
64
-
65
- def convert_partials_to_includes(html = '')
66
- html.gsub(%r{{{ partial :(.+?) }}}, '{% include \1 %}')
67
- .gsub(%r{{% include (.+),\s+locals:(.+?)%}}, '{% include \1 with:\2%}')
68
- .gsub(%r{(<%=\s+?partial\s+?:)(.+?),(.+?)(locals:)((.|\n)+?)(%>)}, '{% include \2 with:\5%}') # multiline partials not caught in presumably leftover variable
69
- end
70
-
71
- def convert_helper_wrappers(html = '')
72
- html.gsub(%r{{{ button(.+?)}}}, '{% button\1%}')
73
- .gsub(%r{{{ image_tag(.+?)}}}, '{% image_tag\1%}')
74
- end
75
-
76
- def cleanup_logic(html = '')
77
- html.gsub(%r{({%|{{)(.*?)(&lt;)(.*?)(}}|%})}, '\1\2<\4\5') # <
78
- .gsub(%r{({%|{{)(.*?)(&gt;)(.*?)(}}|%})}, '\1\2>\4\5') # >
79
- .gsub(/&amp;&amp;/, '&&')
80
- end
81
- end
82
- end
@@ -1,44 +0,0 @@
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
@@ -1,67 +0,0 @@
1
- module Antwort
2
- module ApplicationHelpers
3
-
4
- def sanitize_param(string)
5
- string.nil? ? '' : string.gsub(/([^A-Za-z0-9_\/-]+)|(--)/, '_')
6
- end
7
-
8
- def get_template_file(template_name)
9
- # Dir.entries("your/folder").select {|f| !File.directory? f}
10
- "#{settings.views}/emails/#{template_name}/index.html.erb"
11
- end
12
-
13
- def get_page_title(template_name)
14
- get_metadata(template_name)[:title] || 'Untitled'
15
- end
16
-
17
- def get_metadata(template_name)
18
- read_template(template_name)[:metadata]
19
- end
20
-
21
- def read_template(template_name)
22
- file = get_template_file(template_name)
23
-
24
- data = File.read(file)
25
- md = data.match(/^(?<metadata>---\s*\n.*?\n?)^(---\s*$\n?)/m)
26
- {
27
- body: (md.nil?) ? data : md.post_match,
28
- metadata: (md.nil?) ? {} : symbolize_keys!(YAML.load(md[:metadata]))
29
- }
30
- end
31
-
32
- def fetch_data_yaml(template_name)
33
- data = {}
34
- data_file = settings.root + '/data/' + template_name + '.yml'
35
- if File.file? data_file
36
- data = YAML.load_file(data_file)
37
- data = symbolize_keys! data if data
38
- end
39
- data
40
- end
41
-
42
- def template_exists?(template_name)
43
- File.file? settings.templates_dir + '/' + template_name + '/index.html.erb'
44
- end
45
-
46
- def template_from_path
47
- request.path_info.gsub(%r{/template/}i, '')
48
- end
49
-
50
- def hash_to_instance_vars(data)
51
- data.each { |k, v| instance_variable_set("@#{k}", v) } if data
52
- end
53
-
54
- def image_url_from_path(path)
55
- p = path.split(':')[0]
56
- if (p == 'http' || p == 'https')
57
- url = path
58
- else
59
- a = [path]
60
- a.unshift(template_from_path) unless path[0] == '/'
61
- a.unshift('/assets')
62
- url = File.join(a)
63
- end
64
- url
65
- end
66
- end
67
- end
@@ -1,39 +0,0 @@
1
- module Antwort
2
- module MarkupHelpers
3
- def image_tag(path, options = {})
4
- options[:source] = image_url_from_path(path)
5
- options[:alt] ||= ''
6
- partial('views/markup/image_tag', locals: options)
7
- .gsub(/\n/, '')
8
- end
9
-
10
- def button(text, url, args = {})
11
- options = {
12
- text: text,
13
- url: url
14
- }.merge(args)
15
- partial('views/markup/button', locals: options)
16
- end
17
-
18
- def wrapper_table(args = {}, &block)
19
- options = {
20
- width: '100%',
21
- cell_align: 'center',
22
- cell_valign: 'top',
23
- content: capture_html(&block)
24
- }.merge(args)
25
-
26
- concat_content partial('views/markup/table_wrapper', locals: options)
27
- end
28
-
29
- def counter_classes(index)
30
- # 0 index based
31
- klass = ''
32
- klass += index.even? ? ' is-2n' : ''
33
- klass += (index % 3 == 0) ? ' is-3n' : ''
34
- klass += (index % 4 == 0) ? ' is-4n' : ''
35
- klass += (index % 6 == 0) ? ' is-6n' : ''
36
- klass
37
- end
38
- end
39
- end
@@ -1,60 +0,0 @@
1
- require 'spec_helper'
2
-
3
- class Dummy
4
- end
5
-
6
- describe Antwort::CLIHelpers do
7
-
8
- before :each do
9
- @helper = Dummy.new
10
- @helper.extend(Antwort::CLIHelpers)
11
- end
12
-
13
- before :all do
14
- Dir.chdir(fixtures_root)
15
- end
16
-
17
- describe 'CLI Helpers' do
18
-
19
- it '#built_emails' do
20
- b = @helper.built_emails
21
- expect(b).to include('demo-123456')
22
- expect(b).not_to include('2-no-layout')
23
- end
24
-
25
- it '#available_emails - lists all available emails' do
26
- a = @helper.available_emails
27
- expect(a).to include('1-demo')
28
- expect(a).to include('2-no-layout')
29
- expect(a).to include('3-no-title')
30
- end
31
-
32
- it '#images_dir - returns images asset path by EMAIL_ID' do
33
- expect(@helper.images_dir('foo')).to eq './assets/images/foo'
34
- end
35
-
36
- it '#count_files' do
37
- expect(@helper.count_files './assets/images/shared').to be(2)
38
- expect(@helper.count_files './assets/images/1-demo').to be(1)
39
- end
40
-
41
- it '#last_build_by_id' do
42
- expect(@helper.last_build_by_id 'foo').to eq('foo-1')
43
- expect(@helper.last_build_by_id 'demo').to eq('demo-123457')
44
- expect(@helper.last_build_by_id 'demo').not_to eq('demo-123456')
45
- expect(@helper.last_build_by_id 'demo').not_to eq('demo-bar-123')
46
- end
47
-
48
- it '#list_folders' do
49
- a = @helper.list_folders '.'
50
- expect(a).to include('assets')
51
- expect(a).to include('build')
52
- expect(a).to include('data')
53
- expect(a).to include('emails')
54
- expect(a).to include('views')
55
- expect(a).not_to include('support')
56
- expect(a).not_to include('lib')
57
- end
58
-
59
- end
60
- end
@@ -1,7 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head></head>
4
- <body>
5
- <h1>Build</h1>
6
- </body>
7
- </html>
@@ -1,7 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head></head>
4
- <body>
5
- <h1>Build</h1>
6
- </body>
7
- </html>
@@ -1,7 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head></head>
4
- <body>
5
- <h1>Build</h1>
6
- </body>
7
- </html>
@@ -1 +0,0 @@
1
- 404 error, template not found
@@ -1,14 +0,0 @@
1
-
2
- <% if @pages.length == 0 %>
3
- No emails found
4
- <% else %>
5
- <ul>
6
- <% @pages.each do |page| %>
7
- <li>
8
- <a href="template/<%= page[:path] %>">
9
- <%= page[:title] %>
10
- </a>
11
- </li>
12
- <% end %>
13
- </ul>
14
- <% end %>
@@ -1,5 +0,0 @@
1
- <html>
2
- <body>
3
- <%= yield %>
4
- </body>
5
- </html>
data/spec/server_spec.rb DELETED
@@ -1,54 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Antwort Server' do
4
-
5
- def app
6
- Antwort::Server
7
- end
8
-
9
- describe "Index page" do
10
- it "is valid" do
11
- get '/'
12
- expect(last_response.status).to eq(200)
13
- end
14
-
15
- it "lists available templates by title, includes link" do
16
- get '/'
17
- expect(last_response.body).to include('Email One')
18
- expect(last_response.body).to include('Email Two')
19
- expect(last_response.body).to include('<a href="template/1-demo">')
20
- expect(last_response.body).to include('<a href="template/2-no-layout">')
21
- end
22
- end
23
-
24
- describe "Template show action" do
25
-
26
- it "shows email preview" do
27
- get '/template/1-demo'
28
- expect(last_response.body).to include('<h1>Hello One</h1>')
29
- expect(last_response.body).to include('<title>Email One</title>')
30
- end
31
-
32
- it "loads corresponding data yaml file" do
33
- get '/template/1-demo'
34
- expect(last_response.body).to include('foo')
35
- expect(last_response.body).to include('bar')
36
- end
37
-
38
- it "respects layout:false metadata attribute" do
39
- get '/template/2-no-layout'
40
- expect(last_response.body).not_to include('<body>')
41
- end
42
-
43
- it "has default title if none found" do
44
- get 'template/3-no-title'
45
- expect(last_response.body).to include('Untitled')
46
- end
47
-
48
- it "shows 404 error if template not found" do
49
- get '/template/does-not-exist'
50
- expect(last_response.status).to eq(404)
51
- end
52
- end
53
-
54
- end
@@ -1 +0,0 @@
1
- 2.2.2
@@ -1,3 +0,0 @@
1
- styles:
2
- background_color: '#ffffff'
3
-