emjay 0.1.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 (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +158 -0
  4. data/lib/emjay/body_component.rb +142 -0
  5. data/lib/emjay/component.rb +61 -0
  6. data/lib/emjay/components/body/mj_accordion.rb +99 -0
  7. data/lib/emjay/components/body/mj_accordion_element.rb +127 -0
  8. data/lib/emjay/components/body/mj_accordion_text.rb +123 -0
  9. data/lib/emjay/components/body/mj_accordion_title.rb +171 -0
  10. data/lib/emjay/components/body/mj_body.rb +70 -0
  11. data/lib/emjay/components/body/mj_button.rb +198 -0
  12. data/lib/emjay/components/body/mj_carousel.rb +410 -0
  13. data/lib/emjay/components/body/mj_carousel_image.rb +188 -0
  14. data/lib/emjay/components/body/mj_column.rb +287 -0
  15. data/lib/emjay/components/body/mj_divider.rb +120 -0
  16. data/lib/emjay/components/body/mj_group.rb +196 -0
  17. data/lib/emjay/components/body/mj_hero.rb +382 -0
  18. data/lib/emjay/components/body/mj_image.rb +188 -0
  19. data/lib/emjay/components/body/mj_navbar.rb +187 -0
  20. data/lib/emjay/components/body/mj_navbar_link.rb +129 -0
  21. data/lib/emjay/components/body/mj_raw.rb +34 -0
  22. data/lib/emjay/components/body/mj_section.rb +442 -0
  23. data/lib/emjay/components/body/mj_social.rb +174 -0
  24. data/lib/emjay/components/body/mj_social_element.rb +272 -0
  25. data/lib/emjay/components/body/mj_spacer.rb +57 -0
  26. data/lib/emjay/components/body/mj_table.rb +113 -0
  27. data/lib/emjay/components/body/mj_text.rb +100 -0
  28. data/lib/emjay/components/body/mj_wrapper.rb +56 -0
  29. data/lib/emjay/components/head/mj_attributes.rb +38 -0
  30. data/lib/emjay/components/head/mj_breakpoint.rb +28 -0
  31. data/lib/emjay/components/head/mj_font.rb +24 -0
  32. data/lib/emjay/components/head/mj_head.rb +20 -0
  33. data/lib/emjay/components/head/mj_html_attributes.rb +33 -0
  34. data/lib/emjay/components/head/mj_preview.rb +24 -0
  35. data/lib/emjay/components/head/mj_style.rb +34 -0
  36. data/lib/emjay/components/head/mj_title.rb +24 -0
  37. data/lib/emjay/global_data.rb +64 -0
  38. data/lib/emjay/head_component.rb +37 -0
  39. data/lib/emjay/helpers/conditional_tag.rb +24 -0
  40. data/lib/emjay/helpers/fonts.rb +34 -0
  41. data/lib/emjay/helpers/gen_random_hex_string.rb +9 -0
  42. data/lib/emjay/helpers/make_lower_breakpoint.rb +17 -0
  43. data/lib/emjay/helpers/media_queries.rb +47 -0
  44. data/lib/emjay/helpers/merge_outlook_conditionals.rb +11 -0
  45. data/lib/emjay/helpers/minify_outlook_conditionals.rb +18 -0
  46. data/lib/emjay/helpers/shorthand_parser.rb +33 -0
  47. data/lib/emjay/helpers/styles.rb +34 -0
  48. data/lib/emjay/helpers/suffix_css_classes.rb +12 -0
  49. data/lib/emjay/helpers/width_parser.rb +26 -0
  50. data/lib/emjay/rails/mail_interceptor.rb +37 -0
  51. data/lib/emjay/rails/template_handler.rb +16 -0
  52. data/lib/emjay/railtie.rb +21 -0
  53. data/lib/emjay/registry.rb +19 -0
  54. data/lib/emjay/renderer.rb +302 -0
  55. data/lib/emjay/skeleton.rb +80 -0
  56. data/lib/emjay/version.rb +5 -0
  57. data/lib/emjay.rb +66 -0
  58. data/llms.txt +130 -0
  59. metadata +129 -0
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../body_component"
4
+ require_relative "../../registry"
5
+ require_relative "../../helpers/conditional_tag"
6
+ require_relative "../../helpers/make_lower_breakpoint"
7
+ require_relative "../../helpers/gen_random_hex_string"
8
+
9
+ module Emjay
10
+ module Components
11
+ class MjNavbar < BodyComponent
12
+ def self.component_name
13
+ "mj-navbar"
14
+ end
15
+
16
+ def self.default_attributes
17
+ {
18
+ "align" => "center",
19
+ "base-url" => nil,
20
+ "hamburger" => nil,
21
+ "ico-align" => "center",
22
+ "ico-open" => "&#9776;",
23
+ "ico-close" => "&#8855;",
24
+ "ico-color" => "#000000",
25
+ "ico-font-size" => "30px",
26
+ "ico-font-family" => "Ubuntu, Helvetica, Arial, sans-serif",
27
+ "ico-text-transform" => "uppercase",
28
+ "ico-padding" => "10px",
29
+ "ico-text-decoration" => "none",
30
+ "ico-line-height" => "30px"
31
+ }
32
+ end
33
+
34
+ def self.allowed_attributes
35
+ {
36
+ "align" => "enum(left,center,right)",
37
+ "base-url" => "string",
38
+ "hamburger" => "string",
39
+ "ico-align" => "enum(left,center,right)",
40
+ "ico-open" => "string",
41
+ "ico-close" => "string",
42
+ "ico-color" => "color",
43
+ "ico-font-size" => "unit(px,%)",
44
+ "ico-font-family" => "string",
45
+ "ico-text-transform" => "string",
46
+ "ico-padding" => "unit(px,%){1,4}",
47
+ "ico-padding-left" => "unit(px,%)",
48
+ "ico-padding-top" => "unit(px,%)",
49
+ "ico-padding-right" => "unit(px,%)",
50
+ "ico-padding-bottom" => "unit(px,%)",
51
+ "padding" => "unit(px,%){1,4}",
52
+ "padding-left" => "unit(px,%)",
53
+ "padding-top" => "unit(px,%)",
54
+ "padding-right" => "unit(px,%)",
55
+ "padding-bottom" => "unit(px,%)",
56
+ "ico-text-decoration" => "string",
57
+ "ico-line-height" => "unit(px,%,)"
58
+ }
59
+ end
60
+
61
+ def head_style(breakpoint)
62
+ "\n noinput.mj-menu-checkbox { display:block!important; max-height:none!important; visibility:visible!important; }\n\n @media only screen and (max-width:#{MakeLowerBreakpoint.call(breakpoint)}) {\n .mj-menu-checkbox[type=\"checkbox\"] ~ .mj-inline-links { display:none!important; }\n .mj-menu-checkbox[type=\"checkbox\"]:checked ~ .mj-inline-links,\n .mj-menu-checkbox[type=\"checkbox\"] ~ .mj-menu-trigger { display:block!important; max-width:none!important; max-height:none!important; font-size:inherit!important; }\n .mj-menu-checkbox[type=\"checkbox\"] ~ .mj-inline-links > a { display:block!important; }\n .mj-menu-checkbox[type=\"checkbox\"]:checked ~ .mj-menu-trigger .mj-menu-icon-close { display:block!important; }\n .mj-menu-checkbox[type=\"checkbox\"]:checked ~ .mj-menu-trigger .mj-menu-icon-open { display:none!important; }\n }\n "
63
+ end
64
+
65
+ def get_styles
66
+ {
67
+ div: {},
68
+ label: {
69
+ "display" => "block",
70
+ "cursor" => "pointer",
71
+ "mso-hide" => "all",
72
+ "-moz-user-select" => "none",
73
+ "user-select" => "none",
74
+ "color" => get_attribute("ico-color"),
75
+ "font-size" => get_attribute("ico-font-size"),
76
+ "font-family" => get_attribute("ico-font-family"),
77
+ "text-transform" => get_attribute("ico-text-transform"),
78
+ "text-decoration" => get_attribute("ico-text-decoration"),
79
+ "line-height" => get_attribute("ico-line-height"),
80
+ "padding" => get_attribute("ico-padding"),
81
+ "padding-top" => get_attribute("ico-padding-top"),
82
+ "padding-right" => get_attribute("ico-padding-right"),
83
+ "padding-bottom" => get_attribute("ico-padding-bottom"),
84
+ "padding-left" => get_attribute("ico-padding-left")
85
+ },
86
+ trigger: {
87
+ "display" => "none",
88
+ "max-height" => "0px",
89
+ "max-width" => "0px",
90
+ "font-size" => "0px",
91
+ "overflow" => "hidden"
92
+ },
93
+ icoOpen: {
94
+ "mso-hide" => "all"
95
+ },
96
+ icoClose: {
97
+ "display" => "none",
98
+ "mso-hide" => "all"
99
+ }
100
+ }
101
+ end
102
+
103
+ def render
104
+ hamburger_html = (get_attribute("hamburger") == "hamburger") ? render_hamburger : ""
105
+
106
+ div_attrs = html_attributes(
107
+ class: "mj-inline-links",
108
+ style: :div
109
+ )
110
+
111
+ children = @props[:children] || []
112
+ children_html = render_children(children,
113
+ attributes: {"navbarBaseUrl" => get_attribute("base-url")})
114
+
115
+ align = get_attribute("align")
116
+
117
+ <<~HTML
118
+ #{hamburger_html}
119
+ <div
120
+ #{div_attrs}
121
+ >
122
+ #{ConditionalTag.conditional_tag("<table role=\"presentation\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" align=\"#{align}\"><tr>")}
123
+ #{children_html}
124
+ #{ConditionalTag.conditional_tag("</tr></table>")}
125
+ </div>
126
+ HTML
127
+ end
128
+
129
+ private
130
+
131
+ def render_hamburger
132
+ label_key = GenRandomHexString.call(16)
133
+
134
+ input_html = ConditionalTag.mso_conditional_tag(
135
+ "<input type=\"checkbox\" id=\"#{label_key}\" class=\"mj-menu-checkbox\" style=\"display:none !important; max-height:0; visibility:hidden;\" />",
136
+ negation: true
137
+ )
138
+
139
+ trigger_attrs = html_attributes(
140
+ class: "mj-menu-trigger",
141
+ style: :trigger
142
+ )
143
+
144
+ label_attrs = html_attributes(
145
+ for: label_key,
146
+ class: "mj-menu-label",
147
+ style: :label,
148
+ align: get_attribute("ico-align")
149
+ )
150
+
151
+ ico_open_attrs = html_attributes(
152
+ class: "mj-menu-icon-open",
153
+ style: :icoOpen
154
+ )
155
+
156
+ ico_close_attrs = html_attributes(
157
+ class: "mj-menu-icon-close",
158
+ style: :icoClose
159
+ )
160
+
161
+ <<~HTML
162
+ #{input_html}
163
+ <div
164
+ #{trigger_attrs}
165
+ >
166
+ <label
167
+ #{label_attrs}
168
+ >
169
+ <span
170
+ #{ico_open_attrs}
171
+ >
172
+ #{get_attribute("ico-open")}
173
+ </span>
174
+ <span
175
+ #{ico_close_attrs}
176
+ >
177
+ #{get_attribute("ico-close")}
178
+ </span>
179
+ </label>
180
+ </div>
181
+ HTML
182
+ end
183
+ end
184
+ end
185
+
186
+ Registry.register(Components::MjNavbar)
187
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../body_component"
4
+ require_relative "../../registry"
5
+ require_relative "../../helpers/conditional_tag"
6
+ require_relative "../../helpers/suffix_css_classes"
7
+
8
+ module Emjay
9
+ module Components
10
+ class MjNavbarLink < BodyComponent
11
+ def self.component_name
12
+ "mj-navbar-link"
13
+ end
14
+
15
+ def self.ending_tag?
16
+ true
17
+ end
18
+
19
+ def self.default_attributes
20
+ {
21
+ "color" => "#000000",
22
+ "font-family" => "Ubuntu, Helvetica, Arial, sans-serif",
23
+ "font-size" => "13px",
24
+ "font-weight" => "normal",
25
+ "line-height" => "22px",
26
+ "padding" => "15px 10px",
27
+ "target" => "_blank",
28
+ "text-decoration" => "none",
29
+ "text-transform" => "uppercase"
30
+ }
31
+ end
32
+
33
+ def self.allowed_attributes
34
+ {
35
+ "color" => "color",
36
+ "font-family" => "string",
37
+ "font-size" => "unit(px)",
38
+ "font-style" => "string",
39
+ "font-weight" => "string",
40
+ "href" => "string",
41
+ "name" => "string",
42
+ "target" => "string",
43
+ "rel" => "string",
44
+ "letter-spacing" => "unitWithNegative(px,em)",
45
+ "line-height" => "unit(px,%,)",
46
+ "padding-bottom" => "unit(px,%)",
47
+ "padding-left" => "unit(px,%)",
48
+ "padding-right" => "unit(px,%)",
49
+ "padding-top" => "unit(px,%)",
50
+ "padding" => "unit(px,%){1,4}",
51
+ "text-decoration" => "string",
52
+ "text-transform" => "string"
53
+ }
54
+ end
55
+
56
+ def get_styles
57
+ {
58
+ a: {
59
+ "display" => "inline-block",
60
+ "color" => get_attribute("color"),
61
+ "font-family" => get_attribute("font-family"),
62
+ "font-size" => get_attribute("font-size"),
63
+ "font-style" => get_attribute("font-style"),
64
+ "font-weight" => get_attribute("font-weight"),
65
+ "letter-spacing" => get_attribute("letter-spacing"),
66
+ "line-height" => get_attribute("line-height"),
67
+ "text-decoration" => get_attribute("text-decoration"),
68
+ "text-transform" => get_attribute("text-transform"),
69
+ "padding" => get_attribute("padding"),
70
+ "padding-top" => get_attribute("padding-top"),
71
+ "padding-left" => get_attribute("padding-left"),
72
+ "padding-right" => get_attribute("padding-right"),
73
+ "padding-bottom" => get_attribute("padding-bottom")
74
+ },
75
+ td: {
76
+ "padding" => get_attribute("padding"),
77
+ "padding-top" => get_attribute("padding-top"),
78
+ "padding-left" => get_attribute("padding-left"),
79
+ "padding-right" => get_attribute("padding-right"),
80
+ "padding-bottom" => get_attribute("padding-bottom")
81
+ }
82
+ }
83
+ end
84
+
85
+ def render
86
+ td_attrs = html_attributes(
87
+ style: :td,
88
+ class: SuffixCssClasses.call(get_attribute("css-class"), "outlook")
89
+ )
90
+
91
+ <<~HTML
92
+ #{ConditionalTag.conditional_tag("<td#{td_attrs}>")}
93
+ #{render_content}
94
+ #{ConditionalTag.conditional_tag("</td>")}
95
+ HTML
96
+ end
97
+
98
+ private
99
+
100
+ def render_content
101
+ href = get_attribute("href")
102
+ navbar_base_url = get_attribute("navbarBaseUrl")
103
+ link = navbar_base_url ? "#{navbar_base_url}#{href}" : href
104
+
105
+ css_class = get_attribute("css-class")
106
+ css_suffix = css_class ? " #{css_class}" : ""
107
+
108
+ a_attrs = html_attributes(
109
+ class: "mj-link#{css_suffix}",
110
+ href: link,
111
+ rel: get_attribute("rel"),
112
+ target: get_attribute("target"),
113
+ name: get_attribute("name"),
114
+ style: :a
115
+ )
116
+
117
+ <<~HTML
118
+ <a
119
+ #{a_attrs}
120
+ >
121
+ #{get_content}
122
+ </a>
123
+ HTML
124
+ end
125
+ end
126
+ end
127
+
128
+ Registry.register(Components::MjNavbarLink)
129
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../body_component"
4
+ require_relative "../../registry"
5
+
6
+ module Emjay
7
+ module Components
8
+ class MjRaw < BodyComponent
9
+ def self.component_name
10
+ "mj-raw"
11
+ end
12
+
13
+ def self.ending_tag?
14
+ true
15
+ end
16
+
17
+ def self.raw_element?
18
+ true
19
+ end
20
+
21
+ def self.allowed_attributes
22
+ {
23
+ "position" => "enum(file-start)"
24
+ }
25
+ end
26
+
27
+ def render
28
+ get_content
29
+ end
30
+ end
31
+ end
32
+
33
+ Registry.register(Components::MjRaw)
34
+ end