malvolio 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +184 -0
- data/LICENSE.txt +21 -0
- data/README.md +61 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/malvolio +6 -0
- data/bin/setup +8 -0
- data/lib/generators/malvolio/create_generator.rb +27 -0
- data/lib/generators/malvolio/create_with_inky_generator.rb +27 -0
- data/lib/generators/malvolio/templates/base/config.yaml +1 -0
- data/lib/generators/malvolio/templates/base/index.html +16 -0
- data/lib/generators/malvolio/templates/base/index.scss +0 -0
- data/lib/generators/malvolio/templates/base_with_inky/config.yaml +1 -0
- data/lib/generators/malvolio/templates/base_with_inky/index.html +22 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/_foundation_emails.scss +27 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/_global.scss +95 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_alignment.scss +88 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_button.scss +312 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_callout.scss +85 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_code.scss +0 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_media-query.scss +139 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_menu.scss +83 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_normalize.scss +86 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_outlook-first.scss +11 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_thumbnail.scss +49 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_typography.scss +404 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/components/_visibility.scss +66 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/grid/_block-grid.scss +32 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/grid/_grid.scss +180 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/settings/_settings.scss +148 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/util/_util.scss +22 -0
- data/lib/generators/malvolio/templates/base_with_inky/scss/index.scss +1 -0
- data/lib/malvolio.rb +7 -0
- data/lib/malvolio/cli.rb +50 -0
- data/lib/malvolio/compiler.rb +85 -0
- data/lib/malvolio/version.rb +3 -0
- data/malvolio.gemspec +46 -0
- metadata +228 -0
data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/grid/_block-grid.scss
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
// Foundation for Emails by ZURB
|
2
|
+
// zurb.com/ink/
|
3
|
+
// Licensed under MIT Open Source
|
4
|
+
|
5
|
+
////
|
6
|
+
/// @group block-grid
|
7
|
+
////
|
8
|
+
|
9
|
+
/// The highest number of `.x-up` classes available when using the block grid CSS.
|
10
|
+
/// @type Number
|
11
|
+
$block-grid-max: 8 !default;
|
12
|
+
|
13
|
+
/// Gutter between elements in a block grid.
|
14
|
+
/// @type Number
|
15
|
+
$block-grid-gutter: $global-gutter !default;
|
16
|
+
|
17
|
+
.block-grid {
|
18
|
+
width: 100%;
|
19
|
+
max-width: $global-width;
|
20
|
+
|
21
|
+
td {
|
22
|
+
display: inline-block;
|
23
|
+
padding: $block-grid-gutter / 2;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
// Sizing classes
|
28
|
+
@for $i from 2 through $block-grid-max {
|
29
|
+
.up-#{$i} td {
|
30
|
+
width: floor(($global-width - $i * $block-grid-gutter) / $i) !important;
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,180 @@
|
|
1
|
+
// Foundation for Emails by ZURB
|
2
|
+
// zurb.com/ink/
|
3
|
+
// Licensed under MIT Open Source
|
4
|
+
|
5
|
+
////
|
6
|
+
/// @group grid
|
7
|
+
////
|
8
|
+
|
9
|
+
/// Default number of columns for an email.
|
10
|
+
/// @type Number
|
11
|
+
$grid-column-count: 12 !default;
|
12
|
+
|
13
|
+
/// Default padding for the bottom of a column.
|
14
|
+
/// @type Number
|
15
|
+
$column-padding-bottom: $global-padding !default;
|
16
|
+
|
17
|
+
/// Default border radius for the container. Use a px value
|
18
|
+
/// @type Number
|
19
|
+
$container-radius: 0 !default;
|
20
|
+
|
21
|
+
//For viewing email in browser
|
22
|
+
@media only screen {
|
23
|
+
html {
|
24
|
+
min-height: 100%;
|
25
|
+
background: $body-background;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
table {
|
30
|
+
&.body {
|
31
|
+
background: $body-background;
|
32
|
+
height: 100%;
|
33
|
+
width: 100%;
|
34
|
+
}
|
35
|
+
|
36
|
+
&.container {
|
37
|
+
background: $container-background;
|
38
|
+
width: $global-width;
|
39
|
+
margin: 0 auto;
|
40
|
+
Margin: 0 auto;
|
41
|
+
text-align: inherit;
|
42
|
+
}
|
43
|
+
|
44
|
+
&.row {
|
45
|
+
padding: 0;
|
46
|
+
width: 100%;
|
47
|
+
position: relative;
|
48
|
+
}
|
49
|
+
|
50
|
+
&.spacer {
|
51
|
+
width: 100%;
|
52
|
+
td {
|
53
|
+
mso-line-height-rule: exactly;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
table.container table.row {
|
59
|
+
display: table;
|
60
|
+
}
|
61
|
+
|
62
|
+
td.columns,
|
63
|
+
td.column,
|
64
|
+
th.columns,
|
65
|
+
th.column {
|
66
|
+
margin: 0 auto;
|
67
|
+
Margin: 0 auto;
|
68
|
+
padding-left: $global-gutter;
|
69
|
+
padding-bottom: $column-padding-bottom;
|
70
|
+
|
71
|
+
// Prevents Nested columns from double the padding
|
72
|
+
.column,
|
73
|
+
.columns {
|
74
|
+
padding-left: 0 !important;
|
75
|
+
padding-right: 0 !important;
|
76
|
+
|
77
|
+
center {
|
78
|
+
min-width: none !important;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
td.columns.last,
|
84
|
+
td.column.last,
|
85
|
+
th.columns.last,
|
86
|
+
th.column.last {
|
87
|
+
padding-right: $global-gutter;
|
88
|
+
}
|
89
|
+
|
90
|
+
//makes sure nested tables are 100% width
|
91
|
+
td.columns,
|
92
|
+
td.column,
|
93
|
+
th.columns,
|
94
|
+
th.column {
|
95
|
+
table {
|
96
|
+
width: 100%;
|
97
|
+
|
98
|
+
&.button {
|
99
|
+
width:auto;
|
100
|
+
|
101
|
+
&.expanded{
|
102
|
+
width: 100%;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
@for $i from 1 through $grid-column-count {
|
109
|
+
td.large-#{$i},
|
110
|
+
th.large-#{$i} {
|
111
|
+
width: -zf-grid-calc-px($i, $grid-column-count, $global-width);
|
112
|
+
padding-left: $global-gutter / 2;
|
113
|
+
padding-right: $global-gutter / 2;
|
114
|
+
}
|
115
|
+
|
116
|
+
td.large-#{$i}.first,
|
117
|
+
th.large-#{$i}.first {
|
118
|
+
padding-left: $global-gutter;
|
119
|
+
}
|
120
|
+
|
121
|
+
td.large-#{$i}.last,
|
122
|
+
th.large-#{$i}.last {
|
123
|
+
padding-right: $global-gutter;
|
124
|
+
}
|
125
|
+
|
126
|
+
//Collapsed logic
|
127
|
+
.collapse {
|
128
|
+
> tbody > tr > td.large-#{$i},
|
129
|
+
> tbody > tr > th.large-#{$i} {
|
130
|
+
padding-right: 0;
|
131
|
+
padding-left: 0;
|
132
|
+
width: -zf-grid-calc-px($i, $grid-column-count, $global-width) + $global-gutter;
|
133
|
+
}
|
134
|
+
|
135
|
+
//Gotta give it that extra love for the first and last columns.
|
136
|
+
td.large-#{$i}.first,
|
137
|
+
th.large-#{$i}.first,
|
138
|
+
td.large-#{$i}.last,
|
139
|
+
th.large-#{$i}.last {
|
140
|
+
width: -zf-grid-calc-px($i, $grid-column-count, $global-width) + ($global-gutter * 1.5);
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
td.large-#{$i} center,
|
145
|
+
th.large-#{$i} center {
|
146
|
+
min-width: -zf-grid-calc-px($i, $grid-column-count, $global-width) - ($global-gutter * 2);
|
147
|
+
}
|
148
|
+
|
149
|
+
.body .columns td.large-#{$i},
|
150
|
+
.body .column td.large-#{$i},
|
151
|
+
.body .columns th.large-#{$i},
|
152
|
+
.body .column th.large-#{$i} {
|
153
|
+
width: -zf-grid-calc-pct($i, $grid-column-count);
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
@for $i from 1 through ($grid-column-count - 1) {
|
158
|
+
td.large-offset-#{$i},
|
159
|
+
td.large-offset-#{$i}.first,
|
160
|
+
td.large-offset-#{$i}.last,
|
161
|
+
th.large-offset-#{$i},
|
162
|
+
th.large-offset-#{$i}.first,
|
163
|
+
th.large-offset-#{$i}.last {
|
164
|
+
//1.5 takes in effect a whole empty cell.
|
165
|
+
padding-left: -zf-grid-calc-px($i, $grid-column-count, $global-width) + $global-gutter * 2;
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
td.expander,
|
170
|
+
th.expander {
|
171
|
+
visibility: hidden;
|
172
|
+
width: 0;
|
173
|
+
padding: 0 !important;
|
174
|
+
}
|
175
|
+
|
176
|
+
// adds radius to container
|
177
|
+
table.container.radius {
|
178
|
+
border-radius: $container-radius;
|
179
|
+
border-collapse: separate;
|
180
|
+
}
|
data/lib/generators/malvolio/templates/base_with_inky/scss/foundation_emails/settings/_settings.scss
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
// Foundation for Emails Settings
|
2
|
+
// ------------------------------
|
3
|
+
//
|
4
|
+
// Table of Contents:
|
5
|
+
//
|
6
|
+
// 1. Global
|
7
|
+
// 2. Grid
|
8
|
+
// 3. Block Grid
|
9
|
+
// 4. Typography
|
10
|
+
// 5. Button
|
11
|
+
// 6. Callout
|
12
|
+
// 7. Menu
|
13
|
+
// 8. Thumbnail
|
14
|
+
|
15
|
+
|
16
|
+
// 1. Global
|
17
|
+
// ---------
|
18
|
+
|
19
|
+
$primary-color: #2199e8;
|
20
|
+
$secondary-color: #777777;
|
21
|
+
$success-color: #3adb76;
|
22
|
+
$warning-color: #ffae00;
|
23
|
+
$alert-color: #ec5840;
|
24
|
+
$light-gray: #f3f3f3;
|
25
|
+
$medium-gray: #cacaca;
|
26
|
+
$dark-gray: #8a8a8a;
|
27
|
+
$black: #0a0a0a;
|
28
|
+
$white: #fefefe;
|
29
|
+
$pre-color: #ff6908;
|
30
|
+
$global-width: 580px;
|
31
|
+
$global-width-small: 95%;
|
32
|
+
$global-gutter: 16px;
|
33
|
+
$body-background: $light-gray;
|
34
|
+
$container-background: $white;
|
35
|
+
$global-padding: 16px;
|
36
|
+
$global-margin: 16px;
|
37
|
+
$global-radius: 3px;
|
38
|
+
$global-rounded: 500px;
|
39
|
+
$global-breakpoint: $global-width + $global-gutter;
|
40
|
+
|
41
|
+
// 2. Grid
|
42
|
+
// -------
|
43
|
+
|
44
|
+
$grid-column-count: 12;
|
45
|
+
$column-padding-bottom: $global-padding;
|
46
|
+
$container-radius: 0;
|
47
|
+
|
48
|
+
// 3. Block Grid
|
49
|
+
// -------------
|
50
|
+
|
51
|
+
$block-grid-max: 8;
|
52
|
+
$block-grid-gutter: $global-gutter;
|
53
|
+
|
54
|
+
// 4. Typography
|
55
|
+
// -------------
|
56
|
+
|
57
|
+
$global-font-color: $black;
|
58
|
+
$body-font-family: Helvetica, Arial, sans-serif;
|
59
|
+
$global-font-weight: normal;
|
60
|
+
$header-color: inherit;
|
61
|
+
$global-line-height: 130%;
|
62
|
+
$global-font-size: 16px;
|
63
|
+
$body-line-height: $global-line-height;
|
64
|
+
$header-font-family: $body-font-family;
|
65
|
+
$header-font-weight: $global-font-weight;
|
66
|
+
$h1-font-size: 34px;
|
67
|
+
$h2-font-size: 30px;
|
68
|
+
$h3-font-size: 28px;
|
69
|
+
$h4-font-size: 24px;
|
70
|
+
$h5-font-size: 20px;
|
71
|
+
$h6-font-size: 18px;
|
72
|
+
$header-margin-bottom: 10px;
|
73
|
+
$paragraph-margin-bottom: 10px;
|
74
|
+
$small-font-size: 80%;
|
75
|
+
$small-font-color: $medium-gray;
|
76
|
+
$lead-font-size: $global-font-size * 1.25;
|
77
|
+
$lead-line-height: 160%;
|
78
|
+
$text-padding: 10px;
|
79
|
+
$subheader-lineheight: 1.4;
|
80
|
+
$subheader-color: $dark-gray;
|
81
|
+
$subheader-font-weight: $global-font-weight;
|
82
|
+
$subheader-margin-top: 4px;
|
83
|
+
$subheader-margin-bottom: 8px;
|
84
|
+
$hr-width: $global-width;
|
85
|
+
$hr-border: 1px solid $black;
|
86
|
+
$hr-margin: 20px auto;
|
87
|
+
$anchor-text-decoration: none;
|
88
|
+
$anchor-color: $primary-color;
|
89
|
+
$anchor-color-visited: $anchor-color;
|
90
|
+
$anchor-color-hover: darken($primary-color, 10%);
|
91
|
+
$anchor-color-active: $anchor-color-hover;
|
92
|
+
$stat-font-size: 40px;
|
93
|
+
$remove-ios-blue: true;
|
94
|
+
|
95
|
+
// 5. Button
|
96
|
+
// ---------
|
97
|
+
|
98
|
+
$button-padding: (
|
99
|
+
tiny: 4px 8px 4px 8px,
|
100
|
+
small: 5px 10px 5px 10px,
|
101
|
+
default: 8px 16px 8px 16px,
|
102
|
+
large: 10px 20px 10px 20px,
|
103
|
+
);
|
104
|
+
$button-font-size: (
|
105
|
+
tiny: 10px,
|
106
|
+
small: 12px,
|
107
|
+
default: 16px,
|
108
|
+
large: 20px,
|
109
|
+
);
|
110
|
+
$button-color: $white;
|
111
|
+
$button-color-alt: $medium-gray;
|
112
|
+
$button-font-weight: bold;
|
113
|
+
$button-margin: 0 0 $global-margin 0;
|
114
|
+
$button-background: $primary-color;
|
115
|
+
$button-border: 2px solid $button-background;
|
116
|
+
$button-radius: $global-radius;
|
117
|
+
$button-rounded: $global-rounded;
|
118
|
+
|
119
|
+
// 6. Callout
|
120
|
+
// ----------
|
121
|
+
|
122
|
+
$callout-background: $white;
|
123
|
+
$callout-background-fade: 85%;
|
124
|
+
$callout-padding: 10px;
|
125
|
+
$callout-margin-bottom: $global-margin;
|
126
|
+
$callout-border: 1px solid darken($callout-background, 20%);
|
127
|
+
$callout-border-secondary: 1px solid darken($secondary-color, 20%);
|
128
|
+
$callout-border-success: 1px solid darken($success-color, 20%);
|
129
|
+
$callout-border-warning: 1px solid darken($warning-color, 20%);
|
130
|
+
$callout-border-alert: 1px solid darken($alert-color, 20%);
|
131
|
+
|
132
|
+
// 7. Menu
|
133
|
+
// -------
|
134
|
+
|
135
|
+
$menu-item-padding: 10px;
|
136
|
+
$menu-item-gutter: 10px;
|
137
|
+
$menu-item-color: $primary-color;
|
138
|
+
|
139
|
+
// 8. Thumbnail
|
140
|
+
// ------------
|
141
|
+
|
142
|
+
$thumbnail-border: solid 4px $white;
|
143
|
+
$thumbnail-margin-bottom: $global-margin;
|
144
|
+
$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2);
|
145
|
+
$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5);
|
146
|
+
$thumbnail-transition: box-shadow 200ms ease-out;
|
147
|
+
$thumbnail-radius: $global-radius;
|
148
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
// Foundation for Emails by ZURB
|
2
|
+
// foundation.zurb.com
|
3
|
+
// Licensed under MIT Open Source
|
4
|
+
|
5
|
+
/// Calculates a percentage value for a grid column width.
|
6
|
+
/// @access private
|
7
|
+
/// @param {number} $colNumber - Column count of the column.
|
8
|
+
/// @param {number} $totalColumns - Column count of the entire row.
|
9
|
+
/// @returns {number} A percentage width value.
|
10
|
+
@function -zf-grid-calc-pct($colNumber, $totalColumns) {
|
11
|
+
@return floor(percentage(($colNumber / $totalColumns)) * 1000000) / 1000000;
|
12
|
+
}
|
13
|
+
|
14
|
+
/// Calculates a pixel value for a grid column width.
|
15
|
+
/// @access private
|
16
|
+
/// @param {number} $columnNumber - Column count of the column.
|
17
|
+
/// @param {number} $totalColumns - Column count of the entire row.
|
18
|
+
/// @param {number} $containerWidth - Width of the surrounding container, in pixels.
|
19
|
+
/// @returns {number} A pixel width value.
|
20
|
+
@function -zf-grid-calc-px($columnNumber, $totalColumns, $containerWidth) {
|
21
|
+
@return ($containerWidth / $totalColumns * $columnNumber - $global-gutter);
|
22
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "foundation_emails/foundation_emails";
|
data/lib/malvolio.rb
ADDED
data/lib/malvolio/cli.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "rails/generators"
|
3
|
+
require "filewatcher"
|
4
|
+
|
5
|
+
module Malvolio
|
6
|
+
class CLI < Thor
|
7
|
+
option :inky, type: :boolean
|
8
|
+
desc "new NAME [--inky]", "creates a new email project"
|
9
|
+
def new(name)
|
10
|
+
if options[:inky]
|
11
|
+
::Rails::Generators.invoke("malvolio:create_with_inky", [name])
|
12
|
+
else
|
13
|
+
::Rails::Generators.invoke("malvolio:create", [name])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
option :no_warnings, type: :boolean
|
18
|
+
desc "build [PATH] [--no-warnings]", "compile the project to a finished HTML email"
|
19
|
+
def build(path = nil)
|
20
|
+
safely do
|
21
|
+
Malvolio::Compiler.new(path, options[:no_warnings]).run!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
option :no_warnings, type: :boolean
|
26
|
+
desc "watch [PATH] [--no-warnings]", "watch the project files and build and file changes"
|
27
|
+
def watch(path = nil)
|
28
|
+
path = File.expand_path(path || ".")
|
29
|
+
compiler = Malvolio::Compiler.new(path, options[:no_warnings])
|
30
|
+
html_files = Dir[File.join(path, "src", "**", "*.html")]
|
31
|
+
css_files = Dir[File.join(path, "src", "**", "*.css")]
|
32
|
+
sass_files = Dir[File.join(path, "src", "**", "*.scss")]
|
33
|
+
files = html_files + css_files + sass_files
|
34
|
+
puts "Now watching project for changes at #{path}"
|
35
|
+
Filewatcher.new(files).watch do
|
36
|
+
safely { compiler.run! }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def safely(&block)
|
43
|
+
begin
|
44
|
+
yield
|
45
|
+
rescue Malvolio::CompilationError => e
|
46
|
+
puts e
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|