aaf-lipstick 4.2.0 → 4.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 51c40a77140713b3547d8b516df90c8330ee5b56
4
- data.tar.gz: 439534035d5c998f865b5f37dcd04cbac9f987a3
2
+ SHA256:
3
+ metadata.gz: e1169058e87d4e424cc8ce2591249b54dd0902d05eecfc17afc82999a138c953
4
+ data.tar.gz: df5e54e75c7bec1f17d373f4af40acf488f1827aec3212a0c6a7d98244aa082b
5
5
  SHA512:
6
- metadata.gz: 2a83ab4c24cdda9b10d0030ff42d2505608e41e936eec332331394a92248bd9bd74df8c15512c7b64af9f62badeda1efc48cdee5559aacb68dac4ca9ef32a242
7
- data.tar.gz: 5321a107c28a281c745774a5ffd1472afa4644da7b1efa1a322b0685eac09557b0c0c848e6fb4835c211a94c03f4331ec83f6d0720f724662f252787d27343d7
6
+ metadata.gz: f5be585896864525226c357e68a03d7e7068c2ad7794729c561d335a8cb0b7a11950d27d75424dfc4cc00ce125538bf5ec3fd2a32870ea008c27496a62835df0
7
+ data.tar.gz: 58e9d15f2b0b00990f16d07a08adffe71e5f205f5aff054542db5728bc16567e41327a0d0202616a314c8ba254dc7476cd835464493e30b914f0e586f29f1722
@@ -7,8 +7,8 @@ module Lipstick
7
7
  return if base.respond_to?(:validators)
8
8
 
9
9
  raise('Lipstick::AutoValidation requires a class which responds' \
10
- ' to the `validators` method. For example, as provided by' \
11
- ' ActiveModel::Validations')
10
+ ' to the `validators` method. For example, as provided by' \
11
+ ' ActiveModel::Validations')
12
12
  end
13
13
 
14
14
  def lipstick_auto_validators
@@ -10,6 +10,7 @@ module Lipstick
10
10
  attr_reader :attribute, :collation
11
11
 
12
12
  def initialize(attribute, collation)
13
+ super()
13
14
  @attribute = attribute
14
15
  @collation = collation
15
16
  end
@@ -27,20 +27,20 @@ class BootstrapFormBuilder < ActionView::Helpers::FormBuilder
27
27
  super
28
28
  end
29
29
 
30
- def check_box(*)
30
+ def check_box(*, &block)
31
31
  template.content_tag('div', class: 'checkbox') do
32
32
  template.content_tag('label') do
33
33
  template.concat(super)
34
- template.concat(template.capture { yield })
34
+ template.concat(template.capture(&block))
35
35
  end
36
36
  end
37
37
  end
38
38
 
39
- def radio_button(*)
39
+ def radio_button(*, &block)
40
40
  template.content_tag('div', class: 'radio') do
41
41
  template.content_tag('label') do
42
42
  template.concat(super)
43
- template.concat(template.capture { yield })
43
+ template.concat(template.capture(&block))
44
44
  end
45
45
  end
46
46
  end
@@ -5,34 +5,36 @@ module Lipstick
5
5
  module FormHelper
6
6
  include ActionView::Helpers::FormTagHelper
7
7
 
8
- def field_block(html_opts = {})
8
+ def field_block(html_opts = {}, &block)
9
9
  add_css_class(html_opts, 'form-group')
10
- content_tag('div', html_opts) { yield }
10
+ content_tag('div', html_opts, &block)
11
11
  end
12
12
 
13
- def radio_button_tag(name, value, checked = false, options = {})
13
+ # rubocop:disable Style/OptionalBooleanParameter
14
+ def radio_button_tag(name, value, checked = false, options = {}, &block)
14
15
  content_tag('div', class: 'radio') do
15
16
  content_tag('label') do
16
17
  concat(super)
17
- concat(capture { yield })
18
+ concat(capture(&block))
18
19
  end
19
20
  end
20
21
  end
22
+ # rubocop:enable Style/OptionalBooleanParameter
21
23
 
22
- def check_box_tag(*)
24
+ def check_box_tag(*, &block)
23
25
  content_tag('div', class: 'checkbox') do
24
26
  content_tag('label') do
25
27
  concat(super)
26
- concat(capture { yield })
28
+ concat(capture(&block))
27
29
  end
28
30
  end
29
31
  end
30
32
 
31
33
  alias orig_form_tag form_tag
32
34
 
33
- def inline_form_tag(url_for_options = {}, options = {})
35
+ def inline_form_tag(url_for_options = {}, options = {}, &block)
34
36
  add_css_class(options, 'form-inline')
35
- form_tag(url_for_options, options) { yield }
37
+ form_tag(url_for_options, options, &block)
36
38
  end
37
39
 
38
40
  def search_form_tag(filter, url: nil,
@@ -111,7 +113,7 @@ module Lipstick
111
113
  end
112
114
 
113
115
  def delete_button_tag(url, text: true, **opts)
114
- action = text&.is_a?(String) ? text : 'Delete'
116
+ action = text.is_a?(String) ? text : 'Delete'
115
117
 
116
118
  content_tag('div', class: 'btn-group') do
117
119
  concat(delete_dropdown_opener(text && action, opts))
@@ -135,7 +137,7 @@ module Lipstick
135
137
  # v.validate_field(:name, ...) # Validate the test_object[name] field
136
138
  # end
137
139
  # %>
138
- def validate_form(selector, sym = nil)
140
+ def validate_form(selector, sym = nil, &block)
139
141
  opts = {
140
142
  type: 'application/vnd.aaf.lipstick.validations+json',
141
143
  'data-target': selector,
@@ -143,7 +145,7 @@ module Lipstick
143
145
  }
144
146
 
145
147
  content_tag('script', opts) do
146
- validation_json(sym) { |v| yield v }.html_safe
148
+ validation_json(sym, &block).html_safe
147
149
  end
148
150
  end
149
151
 
@@ -42,9 +42,7 @@ module Lipstick
42
42
 
43
43
  return validate_with_param(target, validation, true) if opts.empty?
44
44
 
45
- if opts.keys == [:param]
46
- return validate_with_param(target, validation, opts[:param])
47
- end
45
+ return validate_with_param(target, validation, opts[:param]) if opts.keys == [:param]
48
46
 
49
47
  add_rule(target, validation, opts)
50
48
  end
@@ -10,11 +10,11 @@ module Lipstick
10
10
  end
11
11
  end
12
12
 
13
- def aaf_footer
13
+ def aaf_footer(&block)
14
14
  content_tag('footer') do
15
15
  content_tag('div', class: 'footer-content') do
16
16
  concat(aaf_logo)
17
- concat(capture { yield })
17
+ concat(capture(&block))
18
18
  end
19
19
  end
20
20
  end
@@ -3,8 +3,8 @@
3
3
  module Lipstick
4
4
  module Helpers
5
5
  module NavHelper
6
- def nav_bar
7
- content_tag('nav', class: 'navbar shrink') { yield }
6
+ def nav_bar(&block)
7
+ content_tag('nav', class: 'navbar shrink', &block)
8
8
  end
9
9
 
10
10
  def nav_first_item(text, url)
@@ -14,10 +14,10 @@ module Lipstick
14
14
  end
15
15
  end
16
16
 
17
- def nav_collapsing_items
17
+ def nav_collapsing_items(&block)
18
18
  attrs = { class: 'collapse navbar-collapse', id: 'aaf-nav-collapse' }
19
19
  content_tag('div', attrs) do
20
- content_tag('ul', class: 'nav navbar-nav') { yield }
20
+ content_tag('ul', class: 'nav navbar-nav', &block)
21
21
  end
22
22
  end
23
23
 
@@ -25,13 +25,13 @@ module Lipstick
25
25
  link_to request.query_parameters.merge(sort_by: param_name,
26
26
  direction: opposite_direction) do
27
27
  concat("#{name} ")
28
- concat(
29
- content_tag('div', class: 'glyphicon') do
30
- content_tag('div',
31
- class: "glyphicon-chevron-#{icon(direction)}") do
32
- end
33
- end
34
- )
28
+ concat(glyphicon(direction))
29
+ end
30
+ end
31
+
32
+ def glyphicon(direction)
33
+ content_tag('div', class: 'glyphicon') do
34
+ content_tag('div', nil, class: "glyphicon-chevron-#{icon(direction)}")
35
35
  end
36
36
  end
37
37
 
@@ -6,4 +6,5 @@ module Lipstick
6
6
  end
7
7
 
8
8
  require 'lipstick/images/email_banner'
9
+ require 'lipstick/images/logo_only_email_banner'
9
10
  require 'lipstick/images/processor'
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rmagick'
4
-
5
3
  module Lipstick
6
4
  module Images
7
5
  # Creates an AAF standard email banner, with three elements, positioned as
@@ -28,17 +26,24 @@ module Lipstick
28
26
  #
29
27
  # For image compositing, (x, y) is the position of the top-left corner.
30
28
  class EmailBanner
31
- def initialize(image:, title:, environment:)
29
+ def initialize(image:, title:, environment:,
30
+ background_color:, resize_to:)
31
+ require 'rmagick'
32
+
32
33
  @title = title
33
34
  @environment = environment
34
35
  @image = image
36
+ @background_color = background_color
37
+ @resize_to = resize_to
35
38
  end
36
39
 
37
40
  def to_png
41
+ bgcolor = @background_color
42
+
38
43
  canvas = Magick::ImageList.new
39
44
  canvas.new_image(WIDTH, HEIGHT) do |f|
40
45
  f.format = 'PNG'
41
- f.background_color = '#2A3685'
46
+ f.background_color = bgcolor
42
47
  end
43
48
 
44
49
  annotate_title(canvas)
@@ -90,7 +95,7 @@ module Lipstick
90
95
 
91
96
  def logo
92
97
  @logo ||= Magick::Image.read(@image.pathname.to_s).first
93
- .resize_to_fill(78, 78)
98
+ .resize_to_fill(@resize_to[0], @resize_to[1])
94
99
  end
95
100
 
96
101
  def gap
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lipstick
4
+ module Images
5
+ # Creates a logo-only email banner, with two elements.
6
+ #
7
+ # 1. Logo, centered vertically and horizontally within the image.
8
+ # 2. Environment string, stamped across the logo.
9
+ #
10
+ # The math here seemed like it would be a lot simpler than the EmailBanner
11
+ # class, but then I went and made it all confusing by bringing trigonometry
12
+ # into it. I promise there was a good reason for doing it.
13
+ class LogoOnlyEmailBanner
14
+ def initialize(image:, environment:, background_color:)
15
+ require 'rmagick'
16
+
17
+ @environment = environment.upcase
18
+ @image = image
19
+ @background_color = background_color
20
+ end
21
+
22
+ def to_png
23
+ bgcolor = @background_color
24
+
25
+ canvas = Magick::ImageList.new
26
+ canvas.new_image(WIDTH, HEIGHT) do |f|
27
+ f.format = 'PNG'
28
+ f.background_color = bgcolor
29
+ end
30
+
31
+ canvas.composite!(logo, logo_x, logo_y, Magick::SrcOverCompositeOp)
32
+
33
+ annotate_environment(canvas)
34
+
35
+ canvas.to_blob
36
+ end
37
+
38
+ private
39
+
40
+ WIDTH = 600
41
+ HEIGHT = 150
42
+ MID_Y = HEIGHT / 2
43
+ ANGLE_DEGREES = 10
44
+ ANGLE_RADIANS = Math::PI * ANGLE_DEGREES / 180
45
+ private_constant :WIDTH, :HEIGHT, :MID_Y, :ANGLE_DEGREES, :ANGLE_RADIANS
46
+
47
+ def environment_format
48
+ @environment_format ||= Magick::Draw.new do |title|
49
+ title.font_family = 'ArialB'
50
+ title.font_weight = 900
51
+ title.pointsize = 36
52
+ title.gravity = Magick::ForgetGravity
53
+ title.fill = '#bc2028'
54
+ title.rotation = -1 * ANGLE_DEGREES
55
+ end
56
+ end
57
+
58
+ def blank_environment?
59
+ !@environment&.present?
60
+ end
61
+
62
+ def annotate_environment(canvas)
63
+ return if blank_environment?
64
+
65
+ environment_format.annotate(canvas, 0, 0, env_x, env_y, @environment)
66
+ end
67
+
68
+ def logo
69
+ @logo ||= Magick::Image.read(@image.pathname.to_s).first
70
+ end
71
+
72
+ def gap
73
+ @gap ||= environment_format.get_type_metrics('AAF').width
74
+ end
75
+
76
+ def logo_w
77
+ logo.bounding_box.width
78
+ end
79
+
80
+ # x position to vertically center logo
81
+ def logo_x
82
+ ((WIDTH - logo.bounding_box.width) / 2).round
83
+ end
84
+
85
+ # y position to vertically center logo
86
+ def logo_y
87
+ ((HEIGHT - logo.bounding_box.height) / 2).round
88
+ end
89
+
90
+ def env_metrics
91
+ return OpenStruct.new(width: 0, height: 0) if blank_environment?
92
+
93
+ environment_format.get_type_metrics(@environment)
94
+ end
95
+
96
+ def env_x
97
+ m = env_metrics
98
+
99
+ # The horizontal width of the environment text is found by:
100
+ # w cos(0) + h sin(0)
101
+ #
102
+ # w = text width
103
+ # h = text ascent
104
+ # 0 = angle of text rotation
105
+ #
106
+ # Contrary to the description in `EmailBanner`, since we're upper
107
+ # casing the environment string here, we don't need to worry about text
108
+ # descent.
109
+ w = Math.cos(ANGLE_RADIANS) * m.width +
110
+ Math.sin(ANGLE_RADIANS) * m.ascent
111
+
112
+ # We center that the same as for `logo_x`
113
+ ((WIDTH - w) / 2).round
114
+ end
115
+
116
+ def env_y
117
+ m = env_metrics
118
+
119
+ # The horizontal width of the environment text is found by:
120
+ # w sin(0) + h cos(0)
121
+ h = Math.sin(ANGLE_RADIANS) * m.width +
122
+ Math.cos(ANGLE_RADIANS) * m.ascent
123
+
124
+ # We use addition here instead of the usual subtraction, as the text
125
+ # moves in the upward direction from the position we set.
126
+ ((HEIGHT + h) / 2).round
127
+ end
128
+ end
129
+ end
130
+ end
@@ -16,11 +16,28 @@ module Lipstick
16
16
  end
17
17
  # rubocop:enable Security/Eval
18
18
 
19
- def email_banner(image: 'logo.png', title:, environment:)
19
+ def email_banner(title:, environment:, image: 'logo.png', **kwargs)
20
20
  @context.depend_on_asset(image)
21
21
  asset = @context.environment.find_asset(image)
22
- EmailBanner.new(image: asset, title: title, environment: environment)
23
- .to_png
22
+
23
+ EmailBanner.new(
24
+ image: asset,
25
+ title: title,
26
+ environment: environment,
27
+ background_color: kwargs[:background_color] || '#2A3685',
28
+ resize_to: kwargs[:resize_to] || [78, 78]
29
+ ).to_png
30
+ end
31
+
32
+ def logo_only_email_banner(environment:, image: 'logo.png', **kwargs)
33
+ @context.depend_on_asset(image)
34
+ asset = @context.environment.find_asset(image)
35
+
36
+ LogoOnlyEmailBanner.new(
37
+ image: asset,
38
+ environment: environment,
39
+ background_color: kwargs[:background_color] || '#2A3685'
40
+ ).to_png
24
41
  end
25
42
  end
26
43
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lipstick
4
- VERSION = '4.2.0'
4
+ VERSION = '4.6.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aaf-lipstick
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.0
4
+ version: 4.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shaun Mangelsdorf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-21 00:00:00.000000000 Z
11
+ date: 2021-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erubis
@@ -26,20 +26,6 @@ dependencies:
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: kramdown
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.5'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.5'
41
- - !ruby/object:Gem::Dependency
42
- name: rails
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
31
  - - ">="
@@ -53,7 +39,7 @@ dependencies:
53
39
  - !ruby/object:Gem::Version
54
40
  version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
- name: rmagick
42
+ name: rails
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - ">="
@@ -220,6 +206,20 @@ dependencies:
220
206
  - - ">="
221
207
  - !ruby/object:Gem::Version
222
208
  version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: rmagick
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: rspec-rails
225
225
  requirement: !ruby/object:Gem::Requirement
@@ -252,22 +252,16 @@ dependencies:
252
252
  name: sqlite3
253
253
  requirement: !ruby/object:Gem::Requirement
254
254
  requirements:
255
- - - "~>"
256
- - !ruby/object:Gem::Version
257
- version: '1.3'
258
- - - "<"
255
+ - - ">="
259
256
  - !ruby/object:Gem::Version
260
- version: '1.4'
257
+ version: '0'
261
258
  type: :development
262
259
  prerelease: false
263
260
  version_requirements: !ruby/object:Gem::Requirement
264
261
  requirements:
265
- - - "~>"
266
- - !ruby/object:Gem::Version
267
- version: '1.3'
268
- - - "<"
262
+ - - ">="
269
263
  - !ruby/object:Gem::Version
270
- version: '1.4'
264
+ version: '0'
271
265
  - !ruby/object:Gem::Dependency
272
266
  name: tilt
273
267
  requirement: !ruby/object:Gem::Requirement
@@ -324,6 +318,7 @@ files:
324
318
  - lib/lipstick/helpers/sortable_helper.rb
325
319
  - lib/lipstick/images.rb
326
320
  - lib/lipstick/images/email_banner.rb
321
+ - lib/lipstick/images/logo_only_email_banner.rb
327
322
  - lib/lipstick/images/processor.rb
328
323
  - lib/lipstick/sortable.rb
329
324
  - lib/lipstick/version.rb
@@ -339,15 +334,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
339
334
  requirements:
340
335
  - - ">="
341
336
  - !ruby/object:Gem::Version
342
- version: '0'
337
+ version: '2.7'
343
338
  required_rubygems_version: !ruby/object:Gem::Requirement
344
339
  requirements:
345
340
  - - ">="
346
341
  - !ruby/object:Gem::Version
347
342
  version: '0'
348
343
  requirements: []
349
- rubyforge_project:
350
- rubygems_version: 2.5.2.3
344
+ rubygems_version: 3.1.2
351
345
  signing_key:
352
346
  specification_version: 4
353
347
  summary: A gem for applying AAF branding to our services