inkcite 1.0.0

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.
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}