maglove-engine 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 825f4967e1ffdad50b807c795c277b4f0861a1b5
4
+ data.tar.gz: c2be11d3033dc57a57780b13d4ef569abeac0e7d
5
+ SHA512:
6
+ metadata.gz: 6e8b680e4b5f1f66ed16bb808cb1360b5b3c1cccb37454c00fa7c491a46322e5d7d17585986003481cad66b41862e7ade925381e867251aee234dfe51326d638
7
+ data.tar.gz: 288b0f1c11d2cabef09fdb06c575a20b694ded9c11b16c1d2253e083ecf4715d285eb135cf90c6baf14d4e8ff3f8f6fc1b136f41226235bdf029a44adcfbaca9
@@ -0,0 +1,9 @@
1
+ module Maglove
2
+ module Engine
3
+ class Configuration
4
+ include Singleton
5
+ attr_accessor :asset_uri
6
+ attr_accessor :block_path
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ module Maglove
2
+ module Engine
3
+ class Registry
4
+ include Singleton
5
+ attr_reader :widgets
6
+
7
+ def initialize
8
+ @widgets = {}
9
+ end
10
+
11
+ def register_widget(identifier, klass)
12
+ widgets[identifier] = klass
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,99 @@
1
+ module Maglove
2
+ module Engine
3
+ class Scope
4
+ def initialize(engine, variables = {})
5
+ @engine = engine
6
+ @variables = variables
7
+ end
8
+
9
+ def theme
10
+ @variables[:theme]
11
+ end
12
+
13
+ def asset_uri
14
+ var(:asset_uri, Maglove::Engine.config.asset_uri)
15
+ end
16
+
17
+ def block_path
18
+ var(:block_path, Maglove::Engine.config.block_path)
19
+ end
20
+
21
+ def asset(url)
22
+ "#{asset_uri}/themes/#{theme}/#{url}"
23
+ end
24
+
25
+ def root_asset(url)
26
+ "#{asset_uri}/#{url}"
27
+ end
28
+
29
+ def widget(identifier, options = {}, &block)
30
+ unless Maglove::Engine::Registry.instance.widgets.keys.include?(identifier.to_sym)
31
+ raise "Widget not found: #{identifier}"
32
+ end
33
+ widget = Maglove::Engine.widget(identifier, options, self)
34
+ widget.render(&block)
35
+ end
36
+
37
+ def block(identifier, variables = {})
38
+ path = File.join(block_path, "#{identifier}.haml")
39
+ haml = File.read(path)
40
+ Maglove::Engine.render(haml, @variables.merge(variables))
41
+ end
42
+
43
+ def var(key, default = nil)
44
+ @variables[key.to_sym] || default
45
+ end
46
+
47
+ def variable(key, default = nil)
48
+ var(key, default)
49
+ end
50
+
51
+ def style_string(options, *args, &block)
52
+ StyleBuilder.new(options, args).process(&block)
53
+ end
54
+
55
+ def method_missing(name, *args, &block)
56
+ if name.to_s.end_with?("_widget") and args.length <= 1
57
+ identifier = "legacy_#{name[0..-8]}".to_sym
58
+ widget(identifier, args.first || {}, &block)
59
+ elsif args.length == 0 and @variables.key?(name.to_sym)
60
+ @variables[name.to_sym]
61
+ else
62
+ super
63
+ end
64
+ end
65
+
66
+ def respond_to_missing?(name, include_private = false)
67
+ name.to_s.end_with?("_widget") || super
68
+ end
69
+
70
+ def drop_container
71
+ haml_tag :div, class: '_typeloft_widget_drop_container'
72
+ end
73
+
74
+ def style(*args, &block)
75
+ style = nil
76
+ if args[-1].class.name == 'Hash'
77
+ style_options = args.pop
78
+ style = style_string(style_options, *style_options.keys)
79
+ end
80
+ classes = args.map { |a| "__#{a}" }
81
+ haml_tag :span, class: classes.join(' '), style: style do
82
+ yield if block_given?
83
+ end
84
+ end
85
+
86
+ def link(href, target: nil, &block)
87
+ haml_tag :a, href: href, target: target do
88
+ yield if block_given?
89
+ end
90
+ end
91
+
92
+ def font(font_face, &block)
93
+ haml_tag :font, face: font_face do
94
+ yield if block_given?
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,67 @@
1
+ module Maglove
2
+ module Engine
3
+ class StyleBuilder
4
+ attr_accessor :options
5
+ attr_accessor :styles
6
+
7
+ def initialize(options, styles = [])
8
+ @options = {}
9
+ @styles = {}
10
+
11
+ # expand margins
12
+ if styles.include?(:margin)
13
+ styles |= [:margin_top, :margin_right, :margin_bottom, :margin_left]
14
+ styles.reject! { |_style| styles == :margin }
15
+ end
16
+
17
+ # expand paddings
18
+ if styles.include?(:padding)
19
+ styles |= [:padding_top, :padding_right, :padding_bottom, :padding_left]
20
+ styles.reject! { |_style| styles == :padding }
21
+ end
22
+
23
+ # build sanitized options
24
+ options.each do |k, v|
25
+ @options[sanitize_style(k)] = v
26
+ end
27
+
28
+ # add initial styles
29
+ add_multi(styles)
30
+ end
31
+
32
+ def process(&block)
33
+ yield self if block_given?
34
+ result = @styles.map { |k, v| "#{k}: #{v};" }.join(' ')
35
+ result.empty? ? nil : result
36
+ end
37
+
38
+ def add_multi(styles)
39
+ styles.each do |style|
40
+ add(style)
41
+ end
42
+ end
43
+
44
+ def add(style, value = nil, template = nil)
45
+ style = sanitize_style(style)
46
+
47
+ # handle empty value field
48
+ if (!value || value.empty?) && !(!(@options[style]) || @options[style].empty?)
49
+ value = @options[style]
50
+ end
51
+
52
+ # apply template
53
+ if value && !value.empty? && template && !template.empty?
54
+ value = ERB.new(template).result(binding)
55
+ end
56
+
57
+ @styles[style] = value if value && !value.empty?
58
+ end
59
+
60
+ def sanitize_style(value)
61
+ value.to_s.gsub(/([A-Z]+)([A-Z][a-z])/, '\1-\2')
62
+ .gsub(/([a-z\d])([A-Z])/, '\1-\2')
63
+ .tr('_', '-').downcase
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,5 @@
1
+ module Maglove
2
+ module Engine
3
+ VERSION = "2.0.5"
4
+ end
5
+ end
@@ -0,0 +1,58 @@
1
+ require 'singleton'
2
+ require 'haml'
3
+ require 'erb'
4
+ require 'nokogiri'
5
+ require 'active_support/inflector'
6
+ require 'maglove/widget'
7
+ require 'maglove/engine/registry'
8
+ require 'maglove/engine/configuration'
9
+ require 'maglove/engine/scope'
10
+ require 'maglove/engine/style_builder'
11
+
12
+ module Maglove
13
+ module Engine
14
+ def self.config
15
+ Configuration.instance
16
+ end
17
+
18
+ def self.configure(&block)
19
+ yield Configuration.instance if block_given?
20
+ Configuration.instance
21
+ end
22
+
23
+ def self.widget(identifier, options = {}, scope)
24
+ Maglove::Engine::Registry.instance.widgets[identifier].new(scope, options)
25
+ end
26
+
27
+ def self.render(haml, variables = {})
28
+ engine = Haml::Engine.new(haml, remove_whitespace: true)
29
+ scope = Scope.new(engine, variables)
30
+ engine.render(scope)
31
+ rescue StandardError => e
32
+ raise RenderError.new(e.message, e)
33
+ end
34
+
35
+ def self.register_widget(identifier, klass)
36
+ Registry.instance.register_widget(identifier, klass)
37
+ end
38
+
39
+ def self.register_widgets
40
+ path = File.join(File.dirname(__FILE__), "/widget/*.rb")
41
+ Dir[path].each do |file|
42
+ require file
43
+ identifier = File.basename(file).split(".").first
44
+ klass_name = identifier.camelcase
45
+ Maglove::Engine.register_widget(identifier.to_sym, "Maglove::Widget::#{klass_name}".constantize)
46
+ Maglove::Engine.register_widget("legacy_#{identifier}".to_sym, "Maglove::Widget::Legacy#{klass_name}".constantize)
47
+ end
48
+ end
49
+
50
+ class RenderError < StandardError
51
+ attr_reader :original_error
52
+ def initialize(message = "Error", original_error = nil)
53
+ super(message)
54
+ @original_error = original_error
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,65 @@
1
+ module Maglove
2
+ module Widget
3
+ class Button < V2
4
+ def identifier
5
+ "button"
6
+ end
7
+
8
+ def defaults
9
+ {
10
+ background_color: "#e6e6e6",
11
+ border_radius: "4px",
12
+ border_width: "1px",
13
+ border_style: "solid",
14
+ media: false,
15
+ size: "btn-lg",
16
+ style: "primary",
17
+ type: "btn-fit"
18
+ }
19
+ end
20
+ end
21
+
22
+ class LegacyButton < V1
23
+ def identifier
24
+ "button"
25
+ end
26
+
27
+ def defaults
28
+ {
29
+ background_color: "#e6e6e6",
30
+ border_radius: "4px",
31
+ border_width: "1px",
32
+ border_style: "solid",
33
+ media: false,
34
+ size: "btn-lg",
35
+ style: "primary",
36
+ type: "btn-fit"
37
+ }
38
+ end
39
+
40
+ def button_attributes
41
+ {
42
+ "class" => "_typeloft_editable btn btn-#{options[:style]} #{options[:size]} #{options[:type]} #{options[:media] ? 'btn-media' : ''}",
43
+ "href" => (options[:href] or "#"),
44
+ "style" => style_string(options, :border_radius, :border_width, :border_style, :border_color, :background_color) do |sb|
45
+ sb.add(:border_style, "solid")
46
+ end,
47
+ "data-media" => options[:media]
48
+ }
49
+ end
50
+
51
+ def render(&block)
52
+ super do
53
+ haml_tag :a, button_attributes do
54
+ if options[:media] and !options[:media].blank?
55
+ haml_tag :video do
56
+ haml_tag :source, { src: options[:media], type: "video/mp4" }
57
+ end
58
+ end
59
+ yield self if block_given?
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,80 @@
1
+ module Maglove
2
+ module Widget
3
+ class Columns < V2
4
+ def identifier
5
+ "columns"
6
+ end
7
+
8
+ def defaults
9
+ {
10
+ layout: "6x6",
11
+ collapse_options: "sm"
12
+ }
13
+ end
14
+
15
+ def column(&block)
16
+ yield self if block_given?
17
+ end
18
+ end
19
+
20
+ class LegacyColumns < V1
21
+ attr_reader :columns
22
+ attr_reader :column_count
23
+ attr_reader :total_columns
24
+
25
+ def initialize(scope, options = {})
26
+ super
27
+ @column_count = 0
28
+ column_array = @options[:columns].to_s.split("x").map(&:to_i)
29
+ if column_array.length == 1
30
+ @total_columns = column_array[0]
31
+ @columns = Array.new(@total_columns) { 12 / @total_columns }
32
+ else
33
+ @total_columns = column_array.length
34
+ @columns = column_array
35
+ end
36
+ end
37
+
38
+ def identifier
39
+ "columns"
40
+ end
41
+
42
+ def defaults
43
+ {
44
+ columns: "2",
45
+ style: "default",
46
+ margin_bottom: "",
47
+ collapse_options: "sm"
48
+ }
49
+ end
50
+
51
+ def render(&block)
52
+ super do
53
+ haml_tag :div, row_options do
54
+ yield self if block_given?
55
+ end
56
+ end
57
+ end
58
+
59
+ def column(&block)
60
+ span = columns[column_count]
61
+ raise "ERROR: Row does not allow column at position #{column_count}" unless span
62
+ @column_count += 1
63
+ phone_cols = (options[:collapse_options] == "xs") ? span : "12"
64
+ haml_tag :div, class: "column col-#{phone_cols} col-tablet-#{span} col-#{options[:collapse_options]}-#{span}" do
65
+ yield self if block_given?
66
+ drop_container
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def row_options
73
+ {
74
+ class: "row row-#{options[:style]}",
75
+ style: style_string(options, :margin_bottom)
76
+ }
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,123 @@
1
+ module Maglove
2
+ module Widget
3
+ class Container < V2
4
+ def identifier
5
+ "container"
6
+ end
7
+
8
+ def defaults
9
+ {
10
+ animate: "none",
11
+ parallax_effect: "none",
12
+ border_radius: nil,
13
+ border_width: nil,
14
+ border_style: nil,
15
+ border_color: "transparent",
16
+ min_height: nil,
17
+ max_height: nil,
18
+ overflow_y: nil
19
+ }
20
+ end
21
+ end
22
+
23
+ class LegacyContainer < V1
24
+ def identifier
25
+ "container"
26
+ end
27
+
28
+ def defaults
29
+ {
30
+ animate: "none",
31
+ image_source: false,
32
+ image_position: "center_center",
33
+ image_size: "cover",
34
+ parallax_effect: "none",
35
+ parallax_speed: 0.6,
36
+ background_color: nil,
37
+ bg_color: nil,
38
+ opacity: nil,
39
+ border_radius: nil,
40
+ border_width: nil,
41
+ border_color: "#111111",
42
+ border_style: nil,
43
+ style: "default",
44
+ padding_top: nil,
45
+ padding_right: nil,
46
+ padding_bottom: nil,
47
+ padding_left: nil,
48
+ alignment: "center",
49
+ min_height: nil,
50
+ max_height: nil,
51
+ max_width: nil,
52
+ margin_top: nil,
53
+ margin_right: nil,
54
+ margin_bottom: nil,
55
+ margin_left: nil,
56
+ overflow_y: nil
57
+ }
58
+ end
59
+
60
+ def render(&block)
61
+ super do
62
+ haml_tag :section, container_options do
63
+ haml_tag :div, image_options do
64
+ yield self if block_given?
65
+ drop_container
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ private
72
+
73
+ def container_options
74
+ result = { class: container_classes, style: container_styles }
75
+ if !options[:parallax_effect].empty? and options[:parallax_effect] != "none"
76
+ result["data-parallax-style"] = options[:parallax_effect]
77
+ result["data-parallax-speed"] = options[:parallax_speed]
78
+ end
79
+ result
80
+ end
81
+
82
+ def image_options
83
+ { class: "one-container-image", style: image_styles }
84
+ end
85
+
86
+ def container_classes
87
+ classes = ["one-container"]
88
+ classes.push("animate #{options[:animate]}") if options[:animate] != "none"
89
+ classes.push("container-#{options[:style]}") unless options[:style].empty?
90
+ classes.push("container-image-#{options[:image_size]}") unless options[:image_size].empty?
91
+ classes.push("container-parallax") if !options[:parallax_effect].empty? and options[:parallax_effect] != "none"
92
+ classes.join(" ")
93
+ end
94
+
95
+ def container_styles
96
+ style_string options, :opacity, :border, :opacity, :border_radius, :border_width, :border_color, :border_style, :margin do |sb|
97
+ sb.add(:background_color, (options[:background_color] == "custom") ? options[:bg_color] : nil)
98
+ if options[:background_color] == "overlay"
99
+ sb.add(:background_image, options[:image_source], "linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url(<%= value %>)")
100
+ else
101
+ sb.add(:background_image, options[:image_source], "url(<%= value %>)")
102
+ end
103
+ sb.add(:background_position, options[:image_position], "<%= value.split('_').join(' ') %>")
104
+ end
105
+ end
106
+
107
+ def image_styles
108
+ if options[:alignment] == "left"
109
+ options[:margin_left] = "0"
110
+ options[:margin_right] = "auto"
111
+ elsif options[:alignment] == "right"
112
+ options[:margin_left] = "auto"
113
+ options[:margin_right] = "0"
114
+ else
115
+ options[:margin_left] = "auto"
116
+ options[:margin_right] = "auto"
117
+ end
118
+
119
+ style_string options, :min_height, :max_height, :max_width, :padding, :overflow_y, :margin_left, :margin_right
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,45 @@
1
+ module Maglove
2
+ module Widget
3
+ class Heading < V2
4
+ def identifier
5
+ "heading"
6
+ end
7
+
8
+ def defaults
9
+ {
10
+ type: "h1",
11
+ align: "left",
12
+ line_height: "1.3",
13
+ padding: [0, 0, 8, 0]
14
+ }
15
+ end
16
+ end
17
+
18
+ class LegacyHeading < V1
19
+ def identifier
20
+ "heading"
21
+ end
22
+
23
+ def defaults
24
+ {
25
+ type: "h1",
26
+ style: "default",
27
+ align: "left",
28
+ margin_bottom: "1em",
29
+ line_height: nil,
30
+ letter_spacing: nil
31
+ }
32
+ end
33
+
34
+ def render(&block)
35
+ super do
36
+ haml_tag :header, class: "#{options[:style]} align-#{options[:align]}", style: style_string(options, :margin, :padding) do
37
+ haml_tag options[:type], class: "_typeloft_editable _typeloft_widget_autoselect", style: style_string(options, :line_height, :letter_spacing) do
38
+ yield self if block_given?
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,36 @@
1
+ module Maglove
2
+ module Widget
3
+ class HorizontalRule < V2
4
+ def identifier
5
+ "horizontal_rule"
6
+ end
7
+
8
+ def defaults
9
+ {
10
+ style: 'solid',
11
+ color: 'dark'
12
+ }
13
+ end
14
+ end
15
+
16
+ class LegacyHorizontalRule < V1
17
+ def identifier
18
+ "horizontal_rule"
19
+ end
20
+
21
+ def defaults
22
+ {
23
+ style: 'solid',
24
+ color: 'dark',
25
+ max_height: 'inherit'
26
+ }
27
+ end
28
+
29
+ def render(&block)
30
+ super do
31
+ haml_tag :hr, style: "max-height: #{options[:max_height]}", class: "#{options[:style]} #{options[:color]}"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,76 @@
1
+ module Maglove
2
+ module Widget
3
+ class Image < V2
4
+ def identifier
5
+ "image"
6
+ end
7
+
8
+ def defaults
9
+ {
10
+ style: "img-responsive",
11
+ align: "center",
12
+ source: false,
13
+ magnify: false,
14
+ tooltip_icon: "bullhorn",
15
+ tooltip_text_alignment: "justify",
16
+ tooltip_text_size: "medium",
17
+ tooltip_position: "top-right",
18
+ tooltip_text: nil
19
+ }
20
+ end
21
+ end
22
+
23
+ class LegacyImage < V1
24
+ def identifier
25
+ "image"
26
+ end
27
+
28
+ def defaults
29
+ {
30
+ style: "img-responsive",
31
+ align: "center",
32
+ title: nil,
33
+ source: false,
34
+ magnify: false,
35
+ margin_bottom: "0",
36
+ max_width: "100%",
37
+ min_width: "0",
38
+ tooltip_icon: "bullhorn",
39
+ tooltip_text_alignment: "justify",
40
+ tooltip_text_size: "medium",
41
+ tooltip_position: "top-right",
42
+ tooltip_text: nil
43
+ }
44
+ end
45
+
46
+ def render(&block)
47
+ super do
48
+ image_class = "image-widget align-#{options[:align]}"
49
+ image_class += " popup-position-#{options[:tooltip_position]}" unless options[:tooltip_text].nil?
50
+ haml_tag :div, class: image_class, style: "min-width: #{options[:min_width]}; max-width: #{options[:max_width]}; #{style_string(options, :margin, :padding)}" do
51
+ wrap_image_link do
52
+ unless options[:tooltip_text].nil?
53
+ haml_tag :i, class: "popup fa fa-lg fa-#{options[:tooltip_icon]}"
54
+ haml_tag :div, class: "popup-box", style: "font-size: #{options[:tooltip_text_size]}, text-align: #{options[:tooltip_text_alignment]};" do
55
+ haml_concat(options[:tooltip_text])
56
+ end
57
+ end
58
+ haml_tag :img, class: "image #{options[:style]} #{options[:magnify] ? 'magnific-image' : ''}", src: options[:source], title: options[:title]
59
+ haml_tag :div, class: "image-drop-target"
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def wrap_image_link(&block)
68
+ if options[:href].nil?
69
+ yield
70
+ else
71
+ link(options[:href], &block)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end