xc_html_generator 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 25460904a9b2cb299009f1328895c4510cb5926e293e1cae9d47cbc569c9aa16
4
+ data.tar.gz: 25f2bc9ab1020212c535b02b7eb27d6e2c07fc9a1b4a4c0d4942169a346aadcd
5
+ SHA512:
6
+ metadata.gz: 10f784b665bd07a0e374ada0727b3798c11238cb2ba7449c9050ca76621e3010deae41ddd83f1480d535755b7f9aa76f091246335ebe99e9d2d58f8c05e9f767
7
+ data.tar.gz: 4572bc001b4da3654baf30f318467472f42ae97436e0f0966645654d8f19c859a1655677c84615f347ff7034de1ef0956062a51d4055b357e91fa2111910a6cc
@@ -0,0 +1,285 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>fastlane/snapshot</title>
5
+ <meta charset="UTF-8">
6
+ <style type="text/css">
7
+ * {
8
+ font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
9
+ font-weight: 300;
10
+ }
11
+ #sortMenu {
12
+ overflow: hidden;
13
+ border: 1px solid #ccc;
14
+ background-color: #f1f1f1;
15
+ display: none;
16
+ }
17
+ #sortMenu button {
18
+ background-color: inherit;
19
+ float: left;
20
+ border: none;
21
+ outline: none;
22
+ cursor: pointer;
23
+ padding: 14px 16px;
24
+ font-size: 17px;
25
+ }
26
+ #sortMenu button:hover {
27
+ background-color: #ddd;
28
+ }
29
+ #sortMenu button.active {
30
+ background-color: #ccc;
31
+ }
32
+ .deviceName {
33
+ display: block;
34
+ font-size: 30px;
35
+ padding-bottom: 24px;
36
+ padding-top: 45px;
37
+ }
38
+ .screenshot {
39
+ cursor: pointer;
40
+ border: 1px #EEE solid;
41
+ z-index: 0;
42
+ }
43
+ .caption {
44
+ font-size: 24px;
45
+ padding-bottom: 24px;
46
+ padding-top: 30px;
47
+ }
48
+ h1, h2 {
49
+ font-weight: bold;
50
+ }
51
+ th {
52
+ text-align: left;
53
+ }
54
+ td {
55
+ text-align: center;
56
+ min-width: 200px;
57
+ }
58
+ #overlay {
59
+ position:fixed;
60
+ top:0;
61
+ left:0;
62
+ background:rgba(0,0,0,0.8);
63
+ z-index:5;
64
+ width:100%;
65
+ height:100%;
66
+ display:none;
67
+ cursor: zoom-out;
68
+ text-align: center;
69
+ }
70
+ #imageDisplay {
71
+ height: auto;
72
+ width: auto;
73
+ z-index: 10;
74
+ cursor: pointer;
75
+ }
76
+ #imageInfo {
77
+ background: none repeat scroll 0 0 rgba(0, 0, 0, 0.2);
78
+ border-radius: 5px;
79
+ color: white;
80
+ margin: 20px;
81
+ padding: 10px;
82
+ position: absolute;
83
+ right: 0;
84
+ top: 0;
85
+ width: 250px;
86
+ z-index: -1;
87
+ }
88
+ #imageInfo:hover {
89
+ z-index: 20;
90
+ }
91
+ </style>
92
+ </head>
93
+ <body>
94
+ <div id="sortMenu">
95
+ <button id="defaultTab" class="tabLink" onclick="openTab(event, 'byLanguage')">By Language</button>
96
+ <button class="tabLink" onclick="openTab(event, 'byScreen')">By Screen</button>
97
+ </div>
98
+ <div id="byLanguage" class="tabContent"><h1 class="tabTitle">By Language:</h1><% image_counter = 0 %><% @data_by_language.each do |language, content| %>
99
+ <h2 id="<%= language %>"><%= language %></h2>
100
+ <hr>
101
+ <table><% content.each do |device_name, screens| %>
102
+ <tr>
103
+ <th colspan="<%= screens.count %>">
104
+ <a id="<%= language %>-<%= device_name %>" class="deviceName" href="#<%= language %>-<%= device_name %>"><%= device_name %></a>
105
+ </th>
106
+ </tr>
107
+ <tr><% screens.each do |screen_path| %><% next if screen_path.include?"_framed.png" %>
108
+ <td><% image_counter += 1 %>
109
+ <a href="<%= screen_path %>" target="_blank" class="screenshotLink">
110
+ <img class="screenshot" src="<%= screen_path %>" style="width: 100%;" alt="<%= language %> <%= device_name %>" data-tab="1" data-counter="<%= image_counter %>">
111
+ </a>
112
+ </td><% end %>
113
+ </tr><% end %>
114
+ </table><% end %>
115
+ </div>
116
+ <div id="byScreen" class="tabContent"><h1 class="tabTitle">By Screen:</h1><% image_counter = 0 %><% @data_by_screen.each do |screen, content| %>
117
+ <h2 id="<%= screen %>" class="screen"><%= screen %></h2>
118
+ <hr>
119
+ <table><% content.each do |device_name, screens| %>
120
+ <tr>
121
+ <th colspan="<%= screens.count %>">
122
+ <a id="<%= screen %>-<%= device_name %>" class="deviceName" href="#<%= screen %>-<%= device_name %>"><%= device_name %></a>
123
+ </th>
124
+ </tr>
125
+ <tr><% screens.each do |language, screen_path| %><% next if screen_path.include?"_framed.png" %>
126
+ <td><% image_counter += 1 %>
127
+ <a href="<%= screen_path %>" target="_blank" class="screenshotLink">
128
+ <img class="screenshot" src="<%= screen_path %>" style="width: 100%;" alt="<%= language %> <%= device_name %>" data-tab="2" data-counter="<%= image_counter %>">
129
+ </a>
130
+ <div class="caption"><%= language %></div>
131
+ </td><% end %>
132
+ </tr><% end %>
133
+ </table><% end %>
134
+ </div>
135
+ <div id="overlay">
136
+ <img id="imageDisplay" src="" alt="" />
137
+ <div id="imageInfo"></div>
138
+ </div>
139
+ <script type="text/javascript">
140
+ var overlay = document.getElementById('overlay');
141
+ var imageDisplay = document.getElementById('imageDisplay');
142
+ var imageInfo = document.getElementById('imageInfo');
143
+ var screenshotLink = document.getElementsByClassName('screenshotLink');
144
+
145
+ window.onload = setup();
146
+
147
+ function setup() {
148
+ var i, menu, tabTitles;
149
+
150
+ // Since JS is enabled, show sort menu and hide tab titles
151
+ menu = document.getElementById("sortMenu");
152
+ menu.style.display = "block";
153
+
154
+ tabTitles = document.getElementsByClassName("tabTitle");
155
+ for (i = 0; i < tabTitles.length; i++) {
156
+ tabTitles[i].style.display = "none";
157
+ }
158
+
159
+ doClick(document.getElementById("defaultTab"));
160
+ }
161
+
162
+ function getCurrentTab() {
163
+ var i, tabs;
164
+ tabs = document.getElementsByClassName("tabContent");
165
+ for (i = 0; i < tabs.length; i++) {
166
+ if (tabs[i].style.display != "none") {
167
+ return i + 1;
168
+ }
169
+ }
170
+ return 1; // fallback
171
+ }
172
+
173
+ function openTab(evt, tabName) {
174
+ var i, tabContent, tabLinks;
175
+ tabs = document.getElementsByClassName("tabContent");
176
+ for (i = 0; i < tabs.length; i++) {
177
+ tabs[i].style.display = "none";
178
+ }
179
+ tabLinks = document.getElementsByClassName("tabLink");
180
+ for (i = 0; i < tabLinks.length; i++) {
181
+ tabLinks[i].className = tabLinks[i].className.replace(" active", "");
182
+ }
183
+ document.getElementById(tabName).style.display = "block";
184
+ evt.currentTarget.className += " active";
185
+ }
186
+
187
+ function doClick(el) {
188
+ if (document.createEvent) {
189
+ var evObj = document.createEvent('MouseEvents', true);
190
+ evObj.initMouseEvent("click", false, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
191
+ el.dispatchEvent(evObj);
192
+ } else if (document.createEventObject) { //IE
193
+ var evObj = document.createEventObject();
194
+ el.fireEvent('onclick', evObj);
195
+ }
196
+ }
197
+
198
+ for (index = 0; index < screenshotLink.length; ++index) {
199
+ screenshotLink[index].addEventListener('click', function(e) {
200
+ e.preventDefault();
201
+
202
+ var img = e.target;
203
+ if (e.target.tagName == 'A') {
204
+ img = e.target.children[0];
205
+ }
206
+
207
+ // beautify
208
+ var tmpImg = new Image();
209
+ tmpImg.src = img.src;
210
+ imageDisplay.style.height = 'auto';
211
+ imageDisplay.style.width = 'auto';
212
+ imageDisplay.style.paddingTop = 0;
213
+ if (window.innerHeight < tmpImg.height) {
214
+ imageDisplay.style.height = document.documentElement.clientHeight+'px';
215
+ } else if (window.innerWidth < tmpImg.width) {
216
+ imageDisplay.style.width = document.documentElement.clientWidth;+'px';
217
+ } else {
218
+ imageDisplay.style.paddingTop = parseInt((window.innerHeight - tmpImg.height) / 2)+'px';
219
+ }
220
+
221
+ imageDisplay.src = img.src;
222
+ imageDisplay.alt = img.alt;
223
+ imageDisplay.dataset.counter = img.dataset.counter;
224
+
225
+ imageInfo.innerHTML = '<h3>'+img.alt+'</h3>';
226
+ imageInfo.innerHTML += decodeURI(img.src.split("/").pop());
227
+ imageInfo.innerHTML += '<br />'+tmpImg.height+'&times;'+tmpImg.width+'px';
228
+
229
+ overlay.style.display = "block";
230
+ });
231
+ }
232
+
233
+ imageDisplay.addEventListener('click', function(e) {
234
+ e.stopPropagation(); // !
235
+
236
+ overlay.style.display = "none";
237
+
238
+ img_tab = parseInt(getCurrentTab());
239
+ img_counter = parseInt(e.target.dataset.counter) + 1;
240
+ try {
241
+ link = document.body.querySelector('img[data-tab="'+img_tab+'"][data-counter="'+img_counter+'"]').parentNode;
242
+ } catch (e) {
243
+ try {
244
+ link = document.body.querySelector('img[data-tab="'+img_tab+'"][data-counter="0"]').parentNode;
245
+ } catch (e) {
246
+ return false;
247
+ }
248
+ }
249
+ doClick(link);
250
+ });
251
+
252
+ overlay.addEventListener('click', function(e) {
253
+ overlay.style.display = "none";
254
+ })
255
+
256
+ function keyPressed(e) {
257
+ e = e || window.event;
258
+ var charCode = e.keyCode || e.which;
259
+ switch(charCode) {
260
+ case 27: // Esc
261
+ overlay.style.display = "none";
262
+ break;
263
+ case 34: // Page Down
264
+ case 39: // Right arrow
265
+ case 54: // Keypad right
266
+ case 76: // l
267
+ case 102: // Keypad right
268
+ e.preventDefault();
269
+ doClick(imageDisplay);
270
+ break;
271
+ case 33: // Page up
272
+ case 37: // Left arrow
273
+ case 52: // Keypad left
274
+ case 72: // h
275
+ case 100: // Keypad left
276
+ e.preventDefault();
277
+ document.getElementById('imageDisplay').dataset.counter -= 2; // hacky
278
+ doClick(imageDisplay);
279
+ break;
280
+ }
281
+ };
282
+ document.body.addEventListener('keydown', keyPressed);
283
+ </script>
284
+ </body>
285
+ </html>
@@ -0,0 +1,125 @@
1
+
2
+
3
+ class HtmlGenerator
4
+ require 'erb'
5
+ require 'fastimage'
6
+ require 'xcresult'
7
+ require 'fastlane'
8
+
9
+ attr_accessor :screenshots_path
10
+
11
+ def initialize(params = {})
12
+ @screenshots_path = params.fetch(:screenshots_path, path)
13
+ end
14
+
15
+ def path
16
+ Dir.pwd
17
+ end
18
+
19
+ def html_path
20
+ File.join(path, "lib", "html", "page.html.erb")
21
+ end
22
+
23
+ def result_path
24
+ path
25
+ end
26
+ # Tweet
27
+ # @return [String]
28
+ def generate
29
+
30
+ screens_path = screenshots_path
31
+
32
+ @data_by_language = {}
33
+ @data_by_screen = {}
34
+ Dir[File.join(screens_path, "*")].sort.each do |device_name_folders|
35
+ device_name = File.basename(device_name_folders)
36
+ Dir[File.join(device_name_folders, "*")].sort.each do |language_folder|
37
+ language = File.basename(language_folder)
38
+ Dir[File.join(language_folder, '*.png')].sort.each do |screenshot|
39
+ file_name = File.basename(screenshot)
40
+ available_devices.each do |key_name, output_name|
41
+ next unless device_name.include?(key_name)
42
+ # This screenshot is from this device
43
+
44
+ @data_by_language[language] ||= {}
45
+ @data_by_language[language][output_name] ||= []
46
+
47
+ screen_name = file_name.sub(key_name + '-', '').sub('.png', '')
48
+ @data_by_screen[screen_name] ||= {}
49
+ @data_by_screen[screen_name][output_name] ||= {}
50
+
51
+ resulting_path = screenshot
52
+ @data_by_language[language][output_name] << resulting_path
53
+ @data_by_screen[screen_name][output_name][language] = resulting_path
54
+ break # to not include iPhone 6 and 6 Plus (name is contained in the other name)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ html = ERB.new(File.read(html_path)).result(binding) # https://web.archive.org/web/20160430190141/www.rrn.dk/rubys-erb-templating-system
60
+
61
+ export_path = "#{screens_path}/screenshots.html"
62
+
63
+ File.write(export_path, html)
64
+
65
+ export_path = File.expand_path(export_path)
66
+ p "Successfully created HTML file with an overview of all the screenshots: '#{export_path}'"
67
+ #system("open '#{export_path}'") unless Snapshot.config[:skip_open_summary]
68
+ end
69
+
70
+ def xcode_9_and_above_device_name_mappings
71
+ {
72
+ # snapshot in Xcode 9 saves screenshots with the SIMULATOR_DEVICE_NAME
73
+ # which includes spaces
74
+ 'iPhone 12 Pro Max' => "iPhone 12 Pro Max",
75
+ 'iPhone 12 Pro' => "iPhone 12 Pro",
76
+ 'iPhone 12 mini' => "iPhone 12 mini",
77
+ 'iPhone 12' => "iPhone 12",
78
+ 'iPhone 11 Pro Max' => "iPhone 11 Pro Max",
79
+ 'iPhone 11 Pro' => "iPhone 11 Pro",
80
+ 'iPhone 11' => "iPhone 11",
81
+ 'iPhone XS Max' => "iPhone XS Max",
82
+ 'iPhone XS' => "iPhone XS",
83
+ 'iPhone XR' => "iPhone XR",
84
+ 'iPhone 8 Plus' => "iPhone 8 Plus",
85
+ 'iPhone 8' => "iPhone 8",
86
+ 'iPhone X' => "iPhone X",
87
+ 'iPhone 7 Plus' => "iPhone 7 Plus (5.5-Inch)",
88
+ 'iPhone 7' => "iPhone 7 (4.7-Inch)",
89
+ 'iPhone 6s Plus' => "iPhone 6s Plus (5.5-Inch)",
90
+ 'iPhone 6 Plus' => "iPhone 6 Plus (5.5-Inch)",
91
+ 'iPhone 6s' => "iPhone 6s (4.7-Inch)",
92
+ 'iPhone 6' => "iPhone 6 (4.7-Inch)",
93
+ 'iPhone 5s' => "iPhone 5s (4-Inch)",
94
+ 'iPhone 5' => "iPhone 5 (4-Inch)",
95
+ 'iPhone SE' => "iPhone SE",
96
+ 'iPhone 4s' => "iPhone 4s (3.5-Inch)",
97
+ 'iPad 2' => 'iPad 2',
98
+ 'iPad Air (3rd generation)' => 'iPad Air (3rd generation)',
99
+ 'iPad Air 2' => 'iPad Air 2',
100
+ 'iPad Air' => 'iPad Air',
101
+ 'iPad (5th generation)' => 'iPad (5th generation)',
102
+ 'iPad (7th generation)' => 'iPad (7th generation)',
103
+ 'iPad Pro (9.7-inch)' => 'iPad Pro (9.7-inch)',
104
+ 'iPad Pro (9.7 inch)' => 'iPad Pro (9.7-inch)', # iOS 10.3.1 simulator
105
+ 'iPad Pro (10.5-inch)' => 'iPad Pro (10.5-inch)',
106
+ 'iPad Pro (11-inch) (2nd generation)' => 'iPad Pro (11-inch) (2nd generation)',
107
+ 'iPad Pro (11-inch)' => 'iPad Pro (11-inch)',
108
+ 'iPad Pro (12.9-inch) (4th generation)' => 'iPad Pro (12.9-inch) (4th generation)',
109
+ 'iPad Pro (12.9-inch) (3rd generation)' => 'iPad Pro (12.9-inch) (3rd generation)',
110
+ 'iPad Pro (12.9-inch) (2nd generation)' => 'iPad Pro (12.9-inch) (2nd generation)',
111
+ 'iPad Pro (12.9-inch)' => 'iPad Pro (12.9-inch)',
112
+ 'iPad Pro (12.9 inch)' => 'iPad Pro (12.9-inch)', # iOS 10.3.1 simulator
113
+ 'iPad Pro' => 'iPad Pro (12.9-inch)', # iOS 9.3 simulator
114
+ 'Apple TV 1080p' => 'Apple TV',
115
+ 'Apple TV 4K (at 1080p)' => 'Apple TV 4K (at 1080p)',
116
+ 'Apple TV 4K' => 'Apple TV 4K',
117
+ 'Apple TV' => 'Apple TV',
118
+ 'Mac' => 'Mac'
119
+ }
120
+ end
121
+
122
+ def available_devices
123
+ return xcode_9_and_above_device_name_mappings
124
+ end
125
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xc_html_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kostyantin Ishchenko
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-05-13 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple gem that genarate html from xcparse result
14
+ email: ko7tyantin@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/html/page.html.erb
20
+ - lib/xc_html_generator.rb
21
+ homepage: https://rubygems.org/gems/xc_html_generator
22
+ licenses:
23
+ - MIT
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubygems_version: 3.2.16
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Helper gem for xcparse
44
+ test_files: []