fastlane-plugin-framer 0.2.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -4
- data/lib/fastlane/plugin/framer/actions/framer_action.rb +102 -33
- data/lib/fastlane/plugin/framer/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c4b531a62b518edcbfb5ef5d6696cd3a109511b
|
4
|
+
data.tar.gz: b85e2d2e122b8f4c32497f4b5274729793b44a64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75f7533dbabe59ff64b89e884440da4bbe438101dd851f600a79ad2434ccc2e5a63ead9709df95a7c45622a1b7941ba864470198df7054ecdece69d6eb9422dd
|
7
|
+
data.tar.gz: 8af5b26a8ffd8881c3b945173ce4b1bad502f5bf24b7007abaff2cfb96cbf6818877f33354eb520f7279312c1979d61336c5ba1e3f36ea5ba29e2165743ec7db
|
data/README.md
CHANGED
@@ -24,11 +24,11 @@ You can specify the position and the size of the screen in the template and (opt
|
|
24
24
|
|
25
25
|
## Example
|
26
26
|
|
27
|
-
Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin.
|
27
|
+
Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin.
|
28
28
|
|
29
29
|
There are 2 lanes, one for a simple flow (`demo-1`) and another with more languages and screens (`demo-2`).
|
30
30
|
|
31
|
-
Try them by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane demo_1` or `bundle exec fastlane demo_2`.
|
31
|
+
Try them by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane demo_1` or `bundle exec fastlane demo_2`.
|
32
32
|
|
33
33
|
## Configuration
|
34
34
|
|
@@ -42,7 +42,7 @@ The **framer** action support 4 optional parameters (default values are used).
|
|
42
42
|
|
43
43
|
| Option | Description | Default |
|
44
44
|
| ----------------- | -------- | ------------ |
|
45
|
-
| `source_folder` | path to the folder that contains raw screenshots and `text.json` file | `./fastlane/framer/screens` |
|
45
|
+
| `source_folder` | path to the folder that contains raw screenshots and `text.json` file | `./fastlane/framer/screens` |
|
46
46
|
| `template_folder` | path to the folder that contains the templates images and configuration | `./fastlane/framer/templates` |
|
47
47
|
| `output_folder` | path to the folder that will contains the final images, framed. Used then by `deliver` | `./fastlane/screenshots` (default one for `deliver`) |
|
48
48
|
| `output_suffix` | filenam suffix for the framed images | `-framed` |
|
@@ -101,6 +101,26 @@ If you want some text in the final framed images, you need to create a `text.jso
|
|
101
101
|
`text.json` is a simple map where *key* is the part of the screenshot filename (I suggest the same string you use with the `snapshot()` command on your UI tests.
|
102
102
|
The *value* can be any strings.
|
103
103
|
|
104
|
+
### Colors
|
105
|
+
|
106
|
+
You can customize the color of the text and the background color applyed below the template (if you have transparencies on the template, you can fill them with the background color).
|
107
|
+
|
108
|
+
`colors.json` is a simple map where *key* is the part of the screenshot filename. The *value* is a map with 2 optional keys, *text* and *background*.
|
109
|
+
|
110
|
+
```
|
111
|
+
{
|
112
|
+
"default": {
|
113
|
+
"background": "#00FFFF",
|
114
|
+
"text": "#FFFFFF"
|
115
|
+
},
|
116
|
+
"demo": {
|
117
|
+
"background": "#FF00FF",
|
118
|
+
}
|
119
|
+
}
|
120
|
+
```
|
121
|
+
|
122
|
+
Default values can be defined inside the *default* map.
|
123
|
+
|
104
124
|
## Run tests for this plugin
|
105
125
|
|
106
126
|
To run both the tests, and code style validation, run
|
@@ -108,7 +128,7 @@ To run both the tests, and code style validation, run
|
|
108
128
|
rake
|
109
129
|
```
|
110
130
|
|
111
|
-
To automatically fix many of the styling issues, use
|
131
|
+
To automatically fix many of the styling issues, use
|
112
132
|
```
|
113
133
|
rubocop -a
|
114
134
|
```
|
@@ -3,13 +3,31 @@ require 'json'
|
|
3
3
|
|
4
4
|
module Fastlane
|
5
5
|
module Actions
|
6
|
+
|
6
7
|
class Template
|
7
8
|
attr_accessor :name
|
8
|
-
attr_accessor :
|
9
|
+
attr_accessor :width, :height
|
9
10
|
|
10
11
|
attr_accessor :file
|
11
12
|
attr_accessor :imageOffset, :imageWidth, :imageBelow
|
12
|
-
attr_accessor :textOffsetX, :textOffsetY, :textWidth, :textHeight, :textPadding, :textSize, :textFont
|
13
|
+
attr_accessor :textOffsetX, :textOffsetY, :textWidth, :textHeight, :textPadding, :textSize, :textFont
|
14
|
+
end
|
15
|
+
|
16
|
+
class Colors
|
17
|
+
attr_accessor :text, :background
|
18
|
+
|
19
|
+
def merge(other)
|
20
|
+
unless other.text.nil? || other.text.empty?
|
21
|
+
self.text = other.text
|
22
|
+
end
|
23
|
+
unless other.background.nil? || other.background.empty?
|
24
|
+
self.background = other.background
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
"{ text: #{self.text}, background: #{self.background} }"
|
30
|
+
end
|
13
31
|
end
|
14
32
|
|
15
33
|
class FramerAction < Action
|
@@ -29,20 +47,23 @@ module Fastlane
|
|
29
47
|
UI.message "Processing #{file}"
|
30
48
|
|
31
49
|
template = self.find_template(templates, file)
|
32
|
-
text = self.find_text(source_folder, file)
|
33
|
-
output = self.find_output(source_folder, file, output_folder, params[:output_suffix])
|
34
|
-
|
35
50
|
if template.nil?
|
36
51
|
UI.error "Unable to find template for screenshot #{file}"
|
37
52
|
next
|
38
53
|
end
|
54
|
+
UI.message "Using template: #{template.name} (#{template.width}x#{template.height})"
|
39
55
|
|
40
|
-
|
41
|
-
UI.
|
42
|
-
|
56
|
+
text = self.find_text(source_folder, file)
|
57
|
+
UI.message "Using text: #{text}"
|
58
|
+
|
59
|
+
colors = self.find_colors(source_folder, file)
|
60
|
+
UI.message "Using colors: #{colors}"
|
61
|
+
|
62
|
+
output = self.find_output(source_folder, file, output_folder, params[:output_suffix])
|
63
|
+
UI.message "Saving to: #{output}"
|
43
64
|
|
44
65
|
# Do the magic
|
45
|
-
self.combine(file, template, text, output)
|
66
|
+
self.combine(file, template, colors, text, output)
|
46
67
|
|
47
68
|
UI.verbose "Framed screenshot #{output}"
|
48
69
|
end
|
@@ -76,7 +97,8 @@ module Fastlane
|
|
76
97
|
|
77
98
|
# Read template image size
|
78
99
|
img = MiniMagick::Image.open(file)
|
79
|
-
template.
|
100
|
+
template.width = img.width
|
101
|
+
template.height = img.height
|
80
102
|
img.destroy!
|
81
103
|
|
82
104
|
# Get template config
|
@@ -92,7 +114,6 @@ module Fastlane
|
|
92
114
|
template.imageWidth = (config_custom['image'] && config_custom['image']['width']) || (config_default['image'] && config_default['image']['width'])
|
93
115
|
template.imageBelow = (config_custom['image'] && config_custom['image']['add_below']) || (config_default['image'] && config_default['image']['add_below']) || false
|
94
116
|
|
95
|
-
template.textColor = (config_custom['text'] && config_custom['text']['color']) || (config_default['text'] && config_default['text']['color'])
|
96
117
|
template.textFont = (config_custom['text'] && config_custom['text']['font']) || (config_default['text'] && config_default['text']['font'])
|
97
118
|
template.textSize = (config_custom['text'] && config_custom['text']['size']) || (config_default['text'] && config_default['text']['size'])
|
98
119
|
template.textWidth = (config_custom['text'] && config_custom['text']['width']) || (config_default['text'] && config_default['text']['width'])
|
@@ -108,22 +129,20 @@ module Fastlane
|
|
108
129
|
end
|
109
130
|
|
110
131
|
def self.find_template(templates, screenshot_file)
|
111
|
-
# Read
|
112
|
-
|
113
|
-
|
114
|
-
img.destroy!
|
132
|
+
# Read device name from file
|
133
|
+
filename = File.basename(screenshot_file)
|
134
|
+
device = filename.slice(0, filename.rindex('-'))
|
115
135
|
|
116
136
|
# Search template that matches that size
|
117
|
-
return templates.find { |template| template.
|
137
|
+
return templates.find { |template| template.name == device }
|
118
138
|
end
|
119
139
|
|
120
140
|
def self.find_text(source_dir, screenshot_file)
|
121
141
|
directory = File.dirname(screenshot_file)
|
122
142
|
strings_path = File.join(directory, "text.json")
|
123
143
|
|
124
|
-
while !File.exist?(strings_path) do
|
144
|
+
while directory.start_with?(source_dir) && !File.exist?(strings_path) do
|
125
145
|
directory = File.dirname(directory)
|
126
|
-
break if directory == source_dir
|
127
146
|
strings_path = File.join(directory, "text.json")
|
128
147
|
end
|
129
148
|
|
@@ -135,6 +154,46 @@ module Fastlane
|
|
135
154
|
return result.last if result
|
136
155
|
end
|
137
156
|
|
157
|
+
def self.find_colors(source_dir, screenshot_file)
|
158
|
+
|
159
|
+
# Default values
|
160
|
+
colors = Colors.new
|
161
|
+
colors.text = "#000000"
|
162
|
+
colors.background = nil
|
163
|
+
|
164
|
+
# Read values from file
|
165
|
+
directory = File.dirname(screenshot_file)
|
166
|
+
colors_path = File.join(directory, "colors.json")
|
167
|
+
|
168
|
+
while directory.start_with?(source_dir) && !File.exist?(colors_path) do
|
169
|
+
directory = File.dirname(directory)
|
170
|
+
colors_path = File.join(directory, "colors.json")
|
171
|
+
end
|
172
|
+
|
173
|
+
if File.exist?(colors_path)
|
174
|
+
config = JSON.parse(File.read(colors_path))
|
175
|
+
|
176
|
+
# Read default values
|
177
|
+
default = Colors.new
|
178
|
+
default.text = config['default']['text']
|
179
|
+
default.background = config['default']['background']
|
180
|
+
colors.merge(default)
|
181
|
+
|
182
|
+
# Read and apply override, if any
|
183
|
+
override = config.select { |k, v| File.basename(screenshot_file).upcase.include? k.upcase }.values.map { |value|
|
184
|
+
c = Colors.new
|
185
|
+
c.text = value['text']
|
186
|
+
c.background = value['background']
|
187
|
+
c
|
188
|
+
}
|
189
|
+
unless override.empty?
|
190
|
+
colors.merge(override.first)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
return colors
|
195
|
+
end
|
196
|
+
|
138
197
|
def self.find_output(source_folder, screenshot_file, output_folder, output_suffix)
|
139
198
|
# Prepare file name
|
140
199
|
if output_suffix.empty?
|
@@ -158,7 +217,19 @@ module Fastlane
|
|
158
217
|
return file_path
|
159
218
|
end
|
160
219
|
|
161
|
-
def self.combine(screenshot_file, template, text, output_file)
|
220
|
+
def self.combine(screenshot_file, template, colors, text, output_file)
|
221
|
+
|
222
|
+
# Prepare base image
|
223
|
+
result_img = MiniMagick::Image.open("#{Framer::ROOT}/assets/background.png")
|
224
|
+
result_img.resize "#{template.width}x#{template.height}!" # `!` says it should ignore the ratio
|
225
|
+
|
226
|
+
# Apply background color, if any
|
227
|
+
unless colors.background.nil?
|
228
|
+
result_img.combine_options do |c|
|
229
|
+
c.fill "#{colors.background}"
|
230
|
+
c.draw "rectangle 0,0,#{template.width},#{template.height}"
|
231
|
+
end
|
232
|
+
end
|
162
233
|
|
163
234
|
# Get template image
|
164
235
|
template_img = MiniMagick::Image.open(template.file)
|
@@ -171,29 +242,27 @@ module Fastlane
|
|
171
242
|
|
172
243
|
# Put screenshot over template
|
173
244
|
if template.imageBelow
|
174
|
-
|
175
|
-
# Create a blank image
|
176
|
-
base_1_img = MiniMagick::Image.open("#{Framer::ROOT}/assets/background.png")
|
177
|
-
base_1_img.resize "#{template.size}!" # `!` says it should ignore the ratio
|
178
245
|
|
179
246
|
# Screenshot first
|
180
|
-
|
247
|
+
result_img = result_img.composite(screenshot_img) do |c|
|
181
248
|
c.compose "Over"
|
182
249
|
c.geometry template.imageOffset.to_s
|
183
250
|
end
|
184
|
-
|
251
|
+
|
185
252
|
# Template second
|
186
|
-
result_img =
|
253
|
+
result_img = result_img.composite(template_img) do |c|
|
187
254
|
c.compose "Over"
|
188
255
|
end
|
189
256
|
|
190
|
-
base_1_img.destroy!
|
191
|
-
base_2_img.destroy!
|
192
|
-
|
193
257
|
else
|
194
258
|
|
195
|
-
#
|
196
|
-
result_img =
|
259
|
+
# Template first
|
260
|
+
result_img = result_img.composite(template_img) do |c|
|
261
|
+
c.compose "Over"
|
262
|
+
end
|
263
|
+
|
264
|
+
# Screenshot second
|
265
|
+
result_img = result_img.composite(screenshot_img) do |c|
|
197
266
|
c.compose "Over"
|
198
267
|
c.geometry template.imageOffset.to_s
|
199
268
|
end
|
@@ -217,7 +286,7 @@ module Fastlane
|
|
217
286
|
c.pointsize template.textSize.to_s
|
218
287
|
c.gravity "Center"
|
219
288
|
c.draw "text 0,0 '#{text}'"
|
220
|
-
c.fill
|
289
|
+
c.fill colors.text.to_s
|
221
290
|
end
|
222
291
|
text_img.trim # remove white space
|
223
292
|
|
@@ -255,7 +324,7 @@ module Fastlane
|
|
255
324
|
result_img.destroy!
|
256
325
|
screenshot_img.destroy!
|
257
326
|
template_img.destroy!
|
258
|
-
|
327
|
+
|
259
328
|
end
|
260
329
|
|
261
330
|
def self.create_dir_if_not_exists(path)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-framer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- DrAL3X
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mini_magick
|