inkcite 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +110 -0
  4. data/Rakefile +8 -0
  5. data/assets/facebook-like.css +62 -0
  6. data/assets/facebook-like.js +59 -0
  7. data/assets/init/config.yml +97 -0
  8. data/assets/init/helpers.tsv +31 -0
  9. data/assets/init/source.html +60 -0
  10. data/assets/init/source.txt +6 -0
  11. data/bin/inkcite +6 -0
  12. data/inkcite.gemspec +42 -0
  13. data/lib/inkcite.rb +32 -0
  14. data/lib/inkcite/cli/base.rb +128 -0
  15. data/lib/inkcite/cli/build.rb +130 -0
  16. data/lib/inkcite/cli/init.rb +58 -0
  17. data/lib/inkcite/cli/preview.rb +30 -0
  18. data/lib/inkcite/cli/server.rb +123 -0
  19. data/lib/inkcite/cli/test.rb +61 -0
  20. data/lib/inkcite/email.rb +219 -0
  21. data/lib/inkcite/mailer.rb +140 -0
  22. data/lib/inkcite/minifier.rb +151 -0
  23. data/lib/inkcite/parser.rb +111 -0
  24. data/lib/inkcite/renderer.rb +177 -0
  25. data/lib/inkcite/renderer/base.rb +186 -0
  26. data/lib/inkcite/renderer/button.rb +168 -0
  27. data/lib/inkcite/renderer/div.rb +29 -0
  28. data/lib/inkcite/renderer/element.rb +82 -0
  29. data/lib/inkcite/renderer/footnote.rb +132 -0
  30. data/lib/inkcite/renderer/google_analytics.rb +35 -0
  31. data/lib/inkcite/renderer/image.rb +95 -0
  32. data/lib/inkcite/renderer/image_base.rb +82 -0
  33. data/lib/inkcite/renderer/in_browser.rb +38 -0
  34. data/lib/inkcite/renderer/like.rb +73 -0
  35. data/lib/inkcite/renderer/link.rb +243 -0
  36. data/lib/inkcite/renderer/litmus.rb +33 -0
  37. data/lib/inkcite/renderer/lorem.rb +39 -0
  38. data/lib/inkcite/renderer/mobile_image.rb +67 -0
  39. data/lib/inkcite/renderer/mobile_style.rb +40 -0
  40. data/lib/inkcite/renderer/mobile_toggle.rb +27 -0
  41. data/lib/inkcite/renderer/outlook_background.rb +48 -0
  42. data/lib/inkcite/renderer/partial.rb +31 -0
  43. data/lib/inkcite/renderer/preheader.rb +22 -0
  44. data/lib/inkcite/renderer/property.rb +39 -0
  45. data/lib/inkcite/renderer/responsive.rb +334 -0
  46. data/lib/inkcite/renderer/span.rb +21 -0
  47. data/lib/inkcite/renderer/table.rb +67 -0
  48. data/lib/inkcite/renderer/table_base.rb +149 -0
  49. data/lib/inkcite/renderer/td.rb +92 -0
  50. data/lib/inkcite/uploader.rb +173 -0
  51. data/lib/inkcite/util.rb +85 -0
  52. data/lib/inkcite/version.rb +3 -0
  53. data/lib/inkcite/view.rb +745 -0
  54. data/lib/inkcite/view/context.rb +38 -0
  55. data/lib/inkcite/view/media_query.rb +60 -0
  56. data/lib/inkcite/view/tag_stack.rb +38 -0
  57. data/test/email_spec.rb +16 -0
  58. data/test/parser_spec.rb +72 -0
  59. data/test/project/config.yml +98 -0
  60. data/test/project/helpers.tsv +56 -0
  61. data/test/project/images/inkcite.jpg +0 -0
  62. data/test/project/source.html +58 -0
  63. data/test/project/source.txt +6 -0
  64. data/test/renderer/button_spec.rb +45 -0
  65. data/test/renderer/div_spec.rb +101 -0
  66. data/test/renderer/element_spec.rb +31 -0
  67. data/test/renderer/footnote_spec.rb +57 -0
  68. data/test/renderer/image_spec.rb +82 -0
  69. data/test/renderer/link_spec.rb +84 -0
  70. data/test/renderer/mobile_image_spec.rb +27 -0
  71. data/test/renderer/mobile_style_spec.rb +37 -0
  72. data/test/renderer/td_spec.rb +126 -0
  73. data/test/renderer_spec.rb +28 -0
  74. data/test/view_spec.rb +15 -0
  75. metadata +333 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e3066d2404f84bcdf743a160b8c85cc838cd19c0
4
+ data.tar.gz: 73adb02dd0f48a81a2b9223a5f03d221c18fa908
5
+ SHA512:
6
+ metadata.gz: 39ff00165434c67e13ae7b72fa5cb90c4991530ab5005059d0c7f64c118c62a55b7be3cc60d147f44536bbf710934a4c7c455c248f205e75c7ca87730451fe41
7
+ data.tar.gz: aa990339b0f3ef6b949231ad2d5efd27eb5218f2e6ccd525a4413a8e421a84d480c3579a11a2bb5e89be862f6483e45130b396f3d66cdb71c1c99f075d695146
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Inkceptional
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # Inkcite
2
+
3
+ Inkcite is an opinionated workflow for building modern, responsive email.
4
+ Like [Middleman] is to static web sites, Inkcite makes it easy for email
5
+ developers to keep their code DRY (don’t repeat yourself) and integrate
6
+ versioning, testing and minification into their workflow.
7
+
8
+ * Easy, flexible templates, variables and helpers
9
+ * ERB for easy A/B testing and versioning
10
+ * Automatic link tagging and tracking
11
+ * [Litmus] integration for compatibility
12
+ * Preview distribution lists
13
+ * Content inclusion/exclusion rules
14
+
15
+ ## Installation
16
+
17
+ Inkcite is a Ruby gem. Ruby comes pre-installed on Mac OS X and Linux. If
18
+ you’re using Windows, try [RubyInstaller].
19
+
20
+ ```
21
+ gem install inkcite
22
+ ```
23
+
24
+ ## Getting Started
25
+
26
+ After Inkcite is installed, you will have access to the `inkcite` command.
27
+ Create a new Inkcite email at your terminal or command prompt:
28
+
29
+ ```
30
+ inkcite init MY_EMAIL
31
+ ```
32
+
33
+ This will create a new directory called `MY_EMAIL` and fill it with the source
34
+ files for your new email project. It includes a subdirectory called `images`
35
+ where you store all images for your email.
36
+
37
+ Change directories into your new project and start the preview server:
38
+
39
+ ```
40
+ cd MY_EMAIL
41
+ inkcite server
42
+ ```
43
+
44
+ Inkcite’s preview server gives you a live view of your email as you build it
45
+ by modifying the `source.html`, `helpers.tsv`, `source.txt` and `config.yml`
46
+ files. Open your browser to `http://localhost:4567` to see your email as you
47
+ build it. As you make changes, simply refresh your browser to see up-to-date
48
+ results.
49
+
50
+ The `config.yml` file has an extensive set of properties that influence the
51
+ HTML code that Inkcite produces plus how it sends preview emails.
52
+
53
+ During development, you can refer to your command prompt or terminal window to
54
+ see important warnings (such as missing images or links).
55
+
56
+ ## Email Previews
57
+
58
+ When you’re ready to see what your email looks like in an email client,
59
+ Inkcite will send previews on demand. Make sure you have configured the
60
+ `smtp` settings in the `config.yml` file so that Inkcite can send email via
61
+ your SMTP server. When you’re ready to send:
62
+
63
+ ``` inkcite preview ```
64
+
65
+ With no other parameters, this will send a preview version of your email to
66
+ the `from` email address you configured. You can also use the preview command
67
+ to send to your email to internal or client distribution lists for review.
68
+
69
+ ## Compatibility Testing
70
+
71
+ Testing your Inkcite-built emails with [Litmus] is easy. Make sure you have
72
+ configured the `litmus` section of the `config.yml` file.
73
+
74
+ ``` inkcite test ```
75
+
76
+ The will create a new email test using your default set of email clients and
77
+ send a preview version of the email to Litmus for testing. Subsequent runs of
78
+ the test command will update the same test. Log into your Litmus account to
79
+ review the results of the test.
80
+
81
+ ## Production Builds
82
+
83
+ After you’ve previewed and tested your email, you’re ready to create the
84
+ production-ready email files. From the project directory:
85
+
86
+ ``` inkcite build ```
87
+
88
+ By default, this will create the production version of your email. This
89
+ includes fully-qualified URLs for images, link tracking and tagging and a host
90
+ of other preflight features.
91
+
92
+ ## Bug Reports
93
+
94
+ Github Issues is used for managing bug reports and feature requests. If you
95
+ run into issues, please search the issues and submit new problems:
96
+ https://github.com/inkceptional/inkcite/issues
97
+
98
+ The best way to get quick responses to your issues and swift fixes to your
99
+ bugs is to submit detailed bug reports, include test cases and respond to
100
+ developer questions in a timely manner.
101
+
102
+ ## License
103
+
104
+ Copyright (c) 2014 Jeffrey D. Hoffman. MIT Licensed, see [LICENSE] for
105
+ details.
106
+
107
+ [Middleman]: http://middlemanapp.com
108
+ [Litmus]: http://litmus.com
109
+ [rubyinstaller]: http://rubyinstaller.org/
110
+ [LICENSE]: https://github.com/inkceptional/inkcite/blob/master/LICENSE
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs.push "lib"
6
+ t.test_files = FileList['test/*_spec.rb', 'test/renderer/*_spec.rb']
7
+ t.verbose = true
8
+ end
@@ -0,0 +1,62 @@
1
+ #dialog-wrap {
2
+ display: none;
3
+ position: absolute;
4
+ background-color: rgba(82, 82, 82, 0.7);
5
+ border-radius: 8px;
6
+ padding: 10px;
7
+ z-index: 10;
8
+ }
9
+
10
+ #dialog {
11
+ background-color: #fff;
12
+ border: 1px solid #555;
13
+ color: #333333;
14
+ font-family: "lucida grande",tahoma,verdana,arial,sans-serif;
15
+ font-size: 11px;
16
+ line-height: 1.28;
17
+ text-align: left;
18
+ }
19
+
20
+ #dialog h2 {
21
+ background-color: #6D84B4;
22
+ color: #FFFFFF;
23
+ font-size: 14px;
24
+ font-weight: bold;
25
+ margin: 0;
26
+ padding: 5px 10px;
27
+ }
28
+
29
+ #dialog-content {
30
+ padding: 15px;
31
+ width: 450px;
32
+ height: 100px;
33
+ }
34
+
35
+ #dialog-buttons {
36
+ background-color: #f2f2f2;
37
+ border-top: 1px solid #ccc;
38
+ padding: 8px 10px;
39
+ text-align: right;
40
+ }
41
+
42
+ #dialog-buttons a {
43
+ display: inline-block;
44
+ border: 1px solid #29447E;
45
+ border-bottom-color: #1A356E;
46
+ background-color: #5B74A8;
47
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
48
+ text-decoration: none;
49
+ color: #fff;
50
+ font-size: 13px;
51
+ font-weight: bold;
52
+ }
53
+
54
+ #dialog-buttons a span {
55
+ display: inline-block;
56
+ border-top: 1px solid #8A9CC2;
57
+ padding: 2px 6px 3px;
58
+ }
59
+
60
+ .loading {
61
+ background: url(spinner.gif) no-repeat center;
62
+ }
@@ -0,0 +1,59 @@
1
+ var loaded = false;
2
+
3
+ function closeLike() {
4
+ $('#dialog-wrap').fadeOut('slow');
5
+ return false;
6
+ }
7
+
8
+ function openLike() {
9
+
10
+ if (!loaded) {
11
+ loaded = true;
12
+
13
+ (function(d, s, id) {
14
+ var js, fjs = d.getElementsByTagName(s)[0];
15
+ if (d.getElementById(id)) return;
16
+ js = d.createElement(s); js.id = id;
17
+ js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
18
+ fjs.parentNode.insertBefore(js, fjs);
19
+ }(document, 'script', 'facebook-jssdk'));
20
+
21
+ var waitForFB;
22
+ waitForFB = function() {
23
+ var $dialog = $('#dialog-wrap');
24
+ var $iframe = $dialog.find('iframe');
25
+ if ($iframe.contents().length != 1) {
26
+ setTimeout(waitForFB, 100);
27
+ } else {
28
+ $dialog.find('#dialog-content').removeClass('loading');
29
+ }
30
+ }
31
+
32
+ waitForFB();
33
+ }
34
+
35
+ var $window = $(window);
36
+ var $dialog = $('#dialog-wrap');
37
+
38
+ var top = Math.round(($window.height() - $dialog.outerHeight()) / 2) + $window.scrollTop();
39
+ if (top < 0) {
40
+ top = 0;
41
+ }
42
+
43
+ var left = Math.round(($window.width() - $dialog.outerWidth()) / 2) + $window.scrollLeft();
44
+ if (left < 0) {
45
+ left = 0;
46
+ }
47
+
48
+ $dialog.css({ top: top, left: left });
49
+
50
+ $dialog.fadeIn('slow');
51
+
52
+ return false;
53
+ }
54
+
55
+ $(function() {
56
+ if (window.location.hash === '#like') {
57
+ openLike();
58
+ }
59
+ });
@@ -0,0 +1,97 @@
1
+ # When true (recommended), appends a cache-busting timestamp to the
2
+ # images referenced in the email. This ensures the client always
3
+ # retrieves the latest version of the image and helpful during client
4
+ # previews. Generally this should be disabled in production.
5
+ cache-bust: true
6
+
7
+ # When true copies image alt-text to the title property. Populating both
8
+ # presents a more consistent image tooltip experience.
9
+ copy-alt-to-title: false
10
+
11
+ # When true (recommended), minifies the HTML and CSS of the email. Should
12
+ # usually be disabled in development to make debugging easier.
13
+ minify: true
14
+
15
+ # When true (recommended), enables image optimization using ImageOptim.
16
+ # http://imageoptim.com
17
+ optimize-images: true
18
+
19
+ # When empty links are found in content, this is the URL that will be
20
+ # included instead - so that clients understand this link is missing
21
+ # and needs to be provided.
22
+ missing-link-url: 'https://github.com/404'
23
+
24
+ # Inkcite can generate multiple versions of an email from a single source
25
+ # file which is useful for targeted mailings and a/b testing. Specify a
26
+ # unique, single-word identifier for each version.
27
+ #versions:
28
+ # - past_customer
29
+ # - prospect
30
+
31
+ # SMTP settings for sending previews to the small list of internal and client
32
+ # addresses specified below. Most importantly, specify the address your test
33
+ # emails will be sent 'from:'
34
+ smtp:
35
+ host: 'smtp.gmail.com'
36
+ port: 587
37
+ domain: 'yourdomain.com'
38
+ username: ''
39
+ password: ''
40
+ from: 'Your Name <email@domain.com>'
41
+
42
+ # Specify the distribution lists for preview versions of your email.
43
+ recipients:
44
+ client:
45
+ - 'Awesome Client <awesome.client@domain.com>'
46
+ internal:
47
+ - 'Creative Director <creative.director@domain.com>'
48
+ - 'Proofreader <proof.reader@domain.com>'
49
+
50
+ # Easy Litmus integration for compatibility testing.
51
+ # http://litmusapp.com
52
+ litmus:
53
+ subdomain: ''
54
+ username: ''
55
+ password: ''
56
+
57
+ # Easy deployment of static assets to a CDN or publicly-accessible
58
+ # server - required when your email has images.
59
+ sftp:
60
+ host: ''
61
+ path: ''
62
+ username: ''
63
+ password: ''
64
+
65
+ # Link tagging ensures that every link in the email includes a
66
+ # name-value pair. This is useful if you harvest data from your
67
+ # website analytics. {id} will be replaced with the unique ID
68
+ # from the link if you're concerned about which link the
69
+ # recipient clicked to get to your website.
70
+ tag-links: "from_email=myemail|{id}"
71
+
72
+ # Optionally, if your email newsletter links to multiple websites
73
+ # and you only want to tag links to a specific domain, include
74
+ # that domain in this setting.
75
+ #tag-links-domain: 'clientdomain.com'
76
+
77
+
78
+ # Environment-specific overrides allow you to change any setting
79
+ # for each environment (e.g local development vs. client preview).
80
+
81
+ # These overrides apply to your local development environment when
82
+ # you are viewing the email in your browser via Inkcite's server.
83
+ development:
84
+ minify: false
85
+
86
+ # These overrides apply to previews both internally and to external
87
+ # clients and sent with Inkcite's preview function.
88
+ preview:
89
+ view-in-browser-url: 'http://preview.contenthost.com/path/{filename}'
90
+ image-host: 'http://preview.imagehost.com/emails/'
91
+
92
+ # These overrides apply to the final, ready-to-send files.
93
+ production:
94
+ cache-bust: false
95
+ image-host: "http://production.imagehost.com/emails/myemail"
96
+ view-in-browser-url: 'http://production.contenthost.com/path/{filename}'
97
+
@@ -0,0 +1,31 @@
1
+ // This file helps you keep your email code DRY (don't repeat yourself)
2
+ // by allowing you to easily define constants and custom tags.
3
+ //
4
+ // The keys and values in this file are tab-delimited.
5
+
6
+ // Palette
7
+ #background #ffffff
8
+ #text #000000
9
+ #link #0099cc
10
+
11
+ // Default font styles
12
+ font-family sans-serif
13
+ font-size 15
14
+ line-height 19
15
+
16
+ // This is an example of a custom tag. Tabs delimit the tag name, its open and
17
+ // close values. Inkcite will replace instances of {big} and {/big} with these
18
+ // values, respectively. Notice that it allows its color, which defaults to
19
+ // #444444, to be configured in your HTML as in {big color=#ff0000}.
20
+ big <div style="font-size: 18px; font-weight: bold; color: $color=#444444$"> </div>
21
+
22
+ // Bullet-proof buttons
23
+ button-border-radius 5
24
+ button-float center
25
+ button-padding 8
26
+ button-width 175
27
+
28
+ // Dimensions
29
+ width 500
30
+
31
+ wrap {table width=100% bgcolor={#background}}{td font-family="{font-family}" align=center} {/td}{/table}
@@ -0,0 +1,60 @@
1
+ {wrap}
2
+
3
+ {preheader}This preheader will only be visible in supporting clients.{/preheader}
4
+
5
+ {table padding=10 width={width} mobile="fill"}
6
+ {td font=default align=left}
7
+
8
+ {img src=logo.gif height=50 width=200 alt="Company Logo"}<br>
9
+
10
+ The &#123;img&#125; helper automatically uses placehold.it when the specified image is missing from the images/ folder. It also sets the <code>display</code>-style to block and will warn you when you've forgotten to set dimensions. &#123;img&#124; are responsive-ready - you can set this image to <code>hide</code>, <code>fill</code> or show a different image using the <code>mobile-src</code> property.
11
+
12
+ {img src=billboard.jpg height=180 width={width} mobile="fill"}<br>
13
+
14
+ {lorem sentences=10}<br><br>
15
+
16
+ {button id="call-to-action" href="http://inkceptional.com"}I'm a Responsive Button{/button}<br>
17
+
18
+ {/td}
19
+ {/table}
20
+
21
+ {table width={width} padding=10 float=center valign=top mobile="drop"}
22
+ {td width=50%}
23
+
24
+ {img src=kittens.jpg width=250 height=150 mobile="fill"}<br>
25
+
26
+ {big}{lorem type=headline}{/big}
27
+
28
+ {lorem sentences=8}<br><br>
29
+
30
+ {button id="call-to-action2" href="http://inkceptional.com"}Create &amp; Send{/button}
31
+
32
+ {/td}
33
+ {td width=50% bgcolor=#eeeeee font=default}
34
+
35
+ {big}{lorem type=headline}{/big}
36
+ {lorem sentences=3}<br><br>
37
+
38
+ {big}{lorem type=headline}{/big}
39
+ {lorem sentences=3}<br><br>
40
+
41
+ {big color=#990000}{lorem type=headline}{/big}
42
+ {lorem sentences=3}
43
+
44
+ {/td}
45
+ {/table}
46
+
47
+ {table padding=10 width={width} float=center mobile="fill"}
48
+ {td align=left font=small}
49
+
50
+ {img src=footer.jpg height=100 width={width} mobile="hide"}<br>
51
+
52
+ <% if email? %>
53
+ This email was sent to [email]. {a id="unsubscribe" href=#}Click here to unsubscribe{/a}.
54
+ Using ERB, this unsubscribe notice will only appear in the 'email' format of this project.
55
+ <% end %>
56
+
57
+ {/td}
58
+ {/table}
59
+
60
+ {/wrap}