Module: Longbow

Defined in:
lib/longbow/json.rb,
lib/longbow/plist.rb,
lib/longbow/colors.rb,
lib/longbow/images.rb,
lib/longbow/targets.rb,
lib/longbow/version.rb,
lib/longbow/utilities.rb

Constant Summary collapse

VERSION =
'0.1.0'

Class Method Summary collapse

Class Method Details

.assets_file_path(directory) ⇒ Object



364
365
366
367
368
369
370
371
372
373
# File 'lib/longbow/images.rb', line 364

def self.assets_file_path directory
  asset_path = ''
  Dir.glob(directory + '/**/*/').each do |d|
    searching = 'Images.xcassets/'
    asset_path = d if d.slice(d.length - searching.length, searching.length) == searching
    break if asset_path.length > 0
  end

  return asset_path
end

.blue(text) ⇒ Object



16
17
18
# File 'lib/longbow/colors.rb', line 16

def self.blue(text)
  colorize(text, 36)
end

.check_for_newer_versionObject



7
8
9
10
11
# File 'lib/longbow/version.rb', line 7

def self.check_for_newer_version
  unless Gem.latest_version_for('longbow').to_s == VERSION
    Longbow::purple "\n  A newer version of longbow is available. Run '[sudo] gem update longbow'."
  end
end

.colorize(text, color_code) ⇒ Object

Main Colorize Functions



3
4
5
# File 'lib/longbow/colors.rb', line 3

def self.colorize(text, color_code)
  puts "\e[#{color_code}m#{text}\e[0m"
end

.create_images(directory, t, obj) ⇒ Object

Images



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/longbow/images.rb', line 13

def self.create_images directory, t, obj
  # Bad Params
  if !directory || !t || !obj
    return false
  end

  # Get Device Information
  iPhone = obj['devices'].include? 'iPhone'
  iPad = obj['devices'].include? 'iPad'

  # Resize Icons
  resize_icons directory, t, iPhone, iPad

  # Resize Launch Images
  resize_launch_images directory, t

  # Write JSON for Icon Assets
  write_json_for_icons directory, t, iPhone, iPad

  # Write JSON for Launch Assets
  write_json_for_launch_images directory, t

end

.create_plist_from_old_plist(old_plist, info_hash, global_hash) ⇒ Object

Create Plist from Original Plist Content



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/longbow/plist.rb', line 4

def self.create_plist_from_old_plist old_plist, info_hash, global_hash
  return '' unless old_plist
  return old_plist unless (info_hash || global_hash)
  plist_text = old_plist
  [global_hash,info_hash].each do |hash|
    next unless hash
    hash.each_key do |k|
      value = hash[k]
      matches = plist_text.match /<key>#{k}<\/key>\s*<(.*?)>.*<\/(.*?)>/
      if matches
        plist_text = plist_text.sub(matches[0], "<key>" + k + "</key>\n" + recursive_plist_value_for_value(value) + "\n")
      else
        plist_text = plist_text.sub(/<\/dict>\s*<\/plist>/, "<key>" + k + "</key>\n" + recursive_plist_value_for_value(value) + "\n</dict></plist>")
      end
    end
  end

  return plist_text
end

.create_target(project, target) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/longbow/targets.rb', line 84

def self.create_target project, target
  main_target = project.targets.first
  deployment_target = main_target.deployment_target

  # Create New Target
  new_target = Xcodeproj::Project::ProjectHelper.new_target project, :application, target, :ios, deployment_target, project.products_group, 'en'
  if new_target
    # Add Build Phases
    main_target.build_phases.objects.each do |b|
      if b.isa == 'PBXSourcesBuildPhase'
        b.files_references.each do |f|
          new_target.source_build_phase.add_file_reference f
        end
      elsif b.isa == 'PBXFrameworksBuildPhase'
        b.files_references.each do |f|
          new_target.frameworks_build_phase.add_file_reference f
        end
      elsif b.isa == 'PBXResourcesBuildPhase'
        b.files_references.each do |f|
          new_target.resources_build_phase.add_file_reference f
        end
      elsif b.isa == 'PBXShellScriptBuildPhase'
        phase = new_target.new_shell_script_build_phase(name = b.display_name)
        phase.shell_script = b.shell_script
      end
    end

    Longbow::blue '  ' + target + ' created.' unless $nolog
  else
    puts
    Longbow::red '  Target Creation failed for target named: ' + target
    puts
  end

  return new_target
end

.green(text) ⇒ Object



12
13
14
# File 'lib/longbow/colors.rb', line 12

def self.green(text)
  colorize(text, 32)
end

.json_object_from_directory(directory) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/longbow/json.rb', line 8

def self.json_object_from_directory directory
  return nil unless directory

  # Check for longbow.json
  @json_path = directory + '/longbow.json'
  unless File.exists?(@json_path)
    Longbow::red "\n  Couldn't find longbow.json at #{@json_path}\n"
    puts "  Run this command to install the correct files:\n  longbow install\n"
    return nil
  end

  # Create hash from longbow.json
  json_contents = File.open(@json_path).read
  return json_object_from_string json_contents
end

.json_object_from_string(contents) ⇒ Object



33
34
35
36
37
38
39
40
41
# File 'lib/longbow/json.rb', line 33

def self.json_object_from_string contents
  begin
    !!JSON.parse(contents)
  rescue
    return nil
  end

  return JSON.parse(contents)
end

.json_object_from_url(url) ⇒ Object



25
26
27
28
29
30
# File 'lib/longbow/json.rb', line 25

def self.json_object_from_url url
  return nil unless url
  contents = ''
  open(url) {|io| contents = io.read}
  return json_object_from_string contents
end

.lint_json_object(obj) ⇒ Object



44
45
46
47
48
# File 'lib/longbow/json.rb', line 44

def self.lint_json_object obj
  return false unless obj
  return false unless obj['targets']
  return true
end

.make_asset_directory(directory, target, path_extension) ⇒ Object

Asset Directory Methods



357
358
359
360
361
362
# File 'lib/longbow/images.rb', line 357

def self.make_asset_directory directory, target, path_extension
  asset_path = assets_file_path directory
  full_path = asset_path + '/' + Longbow::stripped_text(target) + path_extension
  FileUtils::mkdir_p full_path
  return full_path
end

.path_for_downloaded_image_from_url(directory, filename, url, folder) ⇒ Object

Download Image from URL



377
378
379
380
381
382
383
384
385
386
387
# File 'lib/longbow/images.rb', line 377

def self.path_for_downloaded_image_from_url directory, filename, url, folder
  img_path = directory + '/resources/'+ folder + '/'
  img_file_name = filename + '.png'
  FileUtils::mkdir_p img_path
  puts img_path
  File.open(img_path + img_file_name, 'wb') do |f|
    f.write open(url).read
  end

  return img_path + img_file_name
end

.purple(text) ⇒ Object



20
21
22
# File 'lib/longbow/colors.rb', line 20

def self.purple(text)
  colorize(text, 35)
end

.recursive_plist_value_for_value(value) ⇒ Object

Recursively create Plist Values for a given object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/longbow/plist.rb', line 25

def self.recursive_plist_value_for_value value
  return '' unless value != nil

  # Check Number
  if value.kind_of?(Numeric)
    return '<real>' + value.to_s + '</real>'
  end

  # Check Boolean
  if !!value == value
    if value == true
      return '<true />'
    else
      return '<false />'
    end
  end

  # Check Array
  if value.kind_of?(Array)
    total_values = '<array>'
    value.each do |v|
      total_values += recursive_plist_value_for_value(v)
    end
    return total_values + '</array>'
  end

  # Check Hash
  if value.kind_of?(Hash)
    total_values = '<dict>'
    value.each_key do |key|
      total_values += '<key>' + key + '</key>'
      total_values += recursive_plist_value_for_value value[key]
    end
    return total_values + '</dict>'
  end

  return '<string>' + value.to_s + '</string>'
end

.red(text) ⇒ Object

Specific Colors



8
9
10
# File 'lib/longbow/colors.rb', line 8

def self.red(text)
  colorize(text, 31)
end

.resize_icons(directory, t, iPhone, iPad) ⇒ Object

Create & Resize Icons



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/longbow/images.rb', line 39

def self.resize_icons directory, t, iPhone, iPad
  # Set Up
  target = t['name']

  # Get Image Information
  img_path = ''
  if t['icon_url']
    img_path = self.path_for_downloaded_image_from_url directory, target, t['icon_url'], 'icons'
  elsif t['icon_path']
    img_path = directory + '/' + t['icon_path']
  end

  # Make directory
  img_dir = make_asset_directory directory, target, '.appiconset/'

  # Resize
  image_sizes = []
  image_sizes += ['180x180', '120x120', '114x114', '87x87', '80x80', '58x58', '57x57', '29x29'] if iPhone
  image_sizes += ['167x167', '152x152', '144x144', '100x100', '80x80', '76x76', '72x72', '58x58', '50x50', '40x40', '29x29'] if iPad
  image_sizes.uniq.each do |size|
    image = Image.read(img_path).first
    next unless image
    resize_image_to_directory img_dir, image, size, 'icon'
  end

  Longbow::green ('  - Created Icon images for ' + target) unless $nolog
  return true
end

.resize_image_to_directory(directory, image, size, tag) ⇒ Object

Resize Image to Directory



112
113
114
115
116
117
118
# File 'lib/longbow/images.rb', line 112

def self.resize_image_to_directory directory, image, size, tag
  sizes = size.split('x')
  new_w = Integer(sizes[0])
  new_h = Integer(sizes[1])
  image.resize_to_fill! new_w, new_h
  image.write  directory + '/' + tag + size + '.png'
end

.resize_launch_images(directory, t) ⇒ Object

Create & Resize Launch Images



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/longbow/images.rb', line 70

def self.resize_launch_images directory, t
  # Set Up
  target = t['name']

  ['launch_phone_p', 'launch_phone_l', 'launch_tablet_p', 'launch_tablet_l'].each do |key|
    if t[key + '_url']
      img_path = self.path_for_downloaded_image_from_url directory, key + '_' + target, t[key + '_url'], 'launch'
    elsif t[key + '_path']
      img_path = directory + '/' + t[key + '_path']
    else
      next
    end

    # Make directory
    img_dir = make_asset_directory directory, target, '.launchimage/'

    # Make resize sizes
    sizes = []
    if key == 'launch_phone_p'
      sizes = ['640x1136','640x960','320x480']
    elsif key == 'launch_phone_l'
      sizes = ['1136x640','960x640','480x320']
    elsif key == 'launch_tablet_p'
      sizes = ['1536x2048','768x1024','1536x2008','768x1004']
    elsif key == 'launch_tablet_l'
      sizes = ['2048x1536','1024x768','2048x1496','1024x748']
    end

    # Resize Images
    sizes.each do |size|
      image = Image.read(img_path).first
      return false unless image
      resize_image_to_directory img_dir, image, size, key + '_'
    end
  end

  Longbow::green ('  - Created Launch images for ' + target) unless $nolog
  return true
end

.stripped_text(text) ⇒ Object

Strip Non-Alphanumerics



5
6
7
# File 'lib/longbow/utilities.rb', line 5

def self.stripped_text text
  return text.gsub(/[^0-9a-z ]/i, '')
end

.update_target(directory, target, global_keys, info_keys, icon, launch) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/longbow/targets.rb', line 8

def self.update_target directory, target, global_keys, info_keys, icon, launch
  unless directory && target
    Longbow::red '  Invalid parameters. Could not create/update target named: ' + target
    return false
  end

  # Find Project File
  project_paths = []
  Dir.foreach(directory) do |fname|
    project_paths << fname if fname.include? '.xcodeproj'
  end

  # Open The Project
  return false if project_paths.length == 0
  proj = Xcodeproj::Project.open(project_paths[0])

  # Get Main Target's Basic Info
  @target = nil
  proj.targets.each do |t|
    if t.to_s == target
      @target = t
      Longbow::blue '  ' + target + ' found.' unless $nolog
      break
    end
  end

  #puts proj.pretty_print

  # Create Target if Necessary
  main_target = proj.targets.first
  @target = create_target(proj, target) unless @target

  # Plist Creating/Adding
  main_plist = main_target.build_configurations[0].build_settings['INFOPLIST_FILE']

  main_plist.sub! '$(SRCROOT)/', ''
  main_plist_contents = File.read(directory + '/' + main_plist)
  target_plist_path = directory + '/' + main_plist.split('/')[0] + '/' + target + '-info.plist'
  plist_text = Longbow::create_plist_from_old_plist main_plist_contents, info_keys, global_keys
  File.open(target_plist_path, 'w') do |f|
    f.write(plist_text)
  end
  Longbow::green '  - ' + target + '-info.plist Updated.' unless $nolog
  
  # Add Build Settings
  @target.build_configurations.each do |b|
    # Main Settings
    main_settings = nil
    base_config = nil
    main_target.build_configurations.each do |bc|
      main_settings = bc.build_settings if bc.to_s == b.to_s
      base_config = bc.base_configuration_reference if bc.to_s == b.to_s
    end
    settings = b.build_settings

    if main_settings
      main_settings.each_key do |key|
        settings[key] = main_settings[key]
      end
    end
    # Plist & Icons
    settings['INFOPLIST_FILE'] = main_plist.split('/')[0] + '/' + target + '-info.plist'
    settings['ASSETCATALOG_COMPILER_APPICON_NAME'] = Longbow::stripped_text(target) if icon
    settings['ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME'] = Longbow::stripped_text(target) if launch
    settings['SKIP_INSTALL'] = 'NO'

    if File.exists? directory + '/Pods'
      b.base_configuration_reference = base_config
      settings['PODS_ROOT'] = '${SRCROOT}/Pods'
    end
  end

  # Save The Project
  proj.save
end

.write_json_for_icons(directory, t, iPhone, iPad) ⇒ Object

Create JSON



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/longbow/images.rb', line 122

def self.write_json_for_icons directory, t, iPhone, iPad
  # Set Up
  target = t['name']

  # Make directory
  img_dir = make_asset_directory directory, target, '.appiconset/'

  # Write the JSON file
  File.open(img_dir + '/Contents.json', 'w') do |f|
    f.write('{ "images" : [ ')

    if iPhone
      f.write( '{ "size" : "29x29", "idiom" : "iphone", "filename" : "icon58x58.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "icon87x87.png", "scale" : "3x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "icon80x80.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "icon120x120.png", "scale" : "3x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "icon120x120.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "icon29x29.png", "scale" : "1x" }, { "size" : "57x57", "idiom" : "iphone", "filename" : "icon57x57.png", "scale" : "1x" }, { "size" : "57x57", "idiom" : "iphone", "filename" : "icon114x114.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "icon180x180.png", "scale" : "3x" }' + (iPad ? ',' : ''))
    end

    if iPad
      f.write( '{ "idiom" : "ipad", "size" : "29x29", "scale" : "1x", "filename" : "icon29x29.png" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x", "filename" : "icon58x58.png" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x", "filename" : "icon40x40.png" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x", "filename" : "icon80x80.png" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x", "filename" : "icon76x76.png" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x", "filename" : "icon152x152.png" }, { "idiom" : "ipad", "size" : "50x50", "scale" : "1x", "filename" : "icon50x50.png" }, { "idiom" : "ipad", "size" : "50x50", "scale" : "2x", "filename" : "icon100x100.png" }, { "idiom" : "ipad", "size" : "72x72", "scale" : "1x", "filename" : "icon72x72.png" }, { "idiom" : "ipad", "size" : "72x72", "scale" : "2x", "filename" : "icon144x144.png" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x", "filename" : "icon167x167.png" }')
    end

    f.write(' ], "info" : { "version" : 1, "author" : "xcode" }, "properties" : { "pre-rendered" : true } }')
  end

  # Return true
  Longbow::green ('  - Created Images.xcassets icon set for ' + target) unless $nolog
  return true
end

.write_json_for_launch_images(directory, t) ⇒ Object

JSON for Launch Images



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/longbow/images.rb', line 151

def self.write_json_for_launch_images directory, t
  # Set Up
  target = t['name']
  phone_portrait = t['launch_phone_p_url'] || t['launch_phone_p_path']
  phone_landscape = t['launch_phone_l_url'] || t['launch_phone_l_path']
  tablet_portrait = t['launch_tablet_p_url'] || t['launch_tablet_p_path']
  tablet_landscape = t['launch_tablet_l_url'] || t['launch_tablet_l_path']
  return false unless phone_portrait || phone_landscape || tablet_landscape || tablet_portrait

  # Make Directory
  img_dir = make_asset_directory directory, target, '.launchimage/'

  File.open(img_dir + '/Contents.json', 'w') do |f|
    f.write('{"images" : [')

    if phone_portrait
      f.write('{
    "orientation" : "portrait",
    "idiom" : "iphone",
    "extent" : "full-screen",
    "minimum-system-version" : "7.0",
    "filename" : "launch_phone_p_640x960.png",
    "scale" : "2x"
  },
  {
    "extent" : "full-screen",
    "idiom" : "iphone",
    "subtype" : "retina4",
    "filename" : "launch_phone_p_640x1136.png",
    "minimum-system-version" : "7.0",
    "orientation" : "portrait",
    "scale" : "2x"
  },
  {
    "orientation" : "portrait",
    "idiom" : "iphone",
    "extent" : "full-screen",
    "filename" : "launch_phone_p_320x480.png",
    "scale" : "1x"
  },
  {
    "orientation" : "portrait",
    "idiom" : "iphone",
    "extent" : "full-screen",
    "filename" : "launch_phone_p_640x960.png",
    "scale" : "2x"
  },
  {
    "orientation" : "portrait",
    "idiom" : "iphone",
    "extent" : "full-screen",
    "subtype" : "retina4",
    "filename" : "launch_phone_p_640x1136.png",
    "scale" : "2x"
  }')
      f.write ',' if phone_landscape || tablet_portrait || tablet_landscape
    end

    if phone_landscape
      f.write('{
    "orientation" : "landscape",
    "idiom" : "iphone",
    "extent" : "full-screen",
    "minimum-system-version" : "7.0",
    "filename" : "launch_phone_l_960x640.png",
    "scale" : "2x"
  },
  {
    "extent" : "full-screen",
    "idiom" : "iphone",
    "subtype" : "retina4",
    "filename" : "launch_phone_l_1136x640.png",
    "minimum-system-version" : "7.0",
    "orientation" : "landscape",
    "scale" : "2x"
  },
  {
    "orientation" : "landscape",
    "idiom" : "iphone",
    "extent" : "full-screen",
    "filename" : "launch_phone_l_480x320.png",
    "scale" : "1x"
  },
  {
    "orientation" : "landscape",
    "idiom" : "iphone",
    "extent" : "full-screen",
    "filename" : "launch_phone_l_960x640.png",
    "scale" : "2x"
  },
  {
    "orientation" : "landscape",
    "idiom" : "iphone",
    "extent" : "full-screen",
    "subtype" : "retina4",
    "filename" : "launch_phone_l_1136x640.png",
    "scale" : "2x"
  }')
      f.write ',' if tablet_portrait || tablet_landscape
    end

    if tablet_portrait
      f.write('{
    "orientation" : "portrait",
    "idiom" : "ipad",
    "extent" : "full-screen",
    "filename" : "launch_tablet_p_768x1024.png",
    "minimum-system-version" : "7.0",
    "scale" : "1x"
  },
  {
    "orientation" : "portrait",
    "idiom" : "ipad",
    "extent" : "full-screen",
    "filename" : "launch_tablet_p_1536x2048.png",
    "minimum-system-version" : "7.0",
    "scale" : "2x"
  },
  {
    "orientation" : "portrait",
    "idiom" : "ipad",
    "extent" : "to-status-bar",
    "scale" : "1x",
    "filename" : "launch_tablet_p_768x1004.png"
  },
  {
    "orientation" : "portrait",
    "idiom" : "ipad",
    "extent" : "full-screen",
    "scale" : "1x",
    "filename" : "launch_tablet_p_768x1024.png"
  },
  {
    "orientation" : "portrait",
    "idiom" : "ipad",
    "extent" : "to-status-bar",
    "scale" : "2x",
    "filename" : "launch_tablet_p_1536x2008.png"
  },
  {
    "orientation" : "portrait",
    "idiom" : "ipad",
    "extent" : "full-screen",
    "scale" : "2x",
    "filename" : "launch_tablet_p_1536x2048.png"
  }')
      f.write ',' if tablet_landscape
    end

    if tablet_landscape
      f.write('{
    "orientation" : "landscape",
    "idiom" : "ipad",
    "extent" : "full-screen",
    "filename" : "launch_tablet_l_1024x768.png",
    "minimum-system-version" : "7.0",
    "scale" : "1x"
  },
  {
    "orientation" : "landscape",
    "idiom" : "ipad",
    "extent" : "full-screen",
    "filename" : "launch_tablet_l_2048x1536.png",
    "minimum-system-version" : "7.0",
    "scale" : "2x"
  },
  {
    "orientation" : "landscape",
    "idiom" : "ipad",
    "extent" : "to-status-bar",
    "scale" : "1x",
    "filename" : "launch_tablet_l_1024x748.png"
  },
  {
    "orientation" : "landscape",
    "idiom" : "ipad",
    "extent" : "full-screen",
    "scale" : "1x",
    "filename" : "launch_tablet_l_1024x768.png"
  },
  {
    "orientation" : "landscape",
    "idiom" : "ipad",
    "extent" : "to-status-bar",
    "scale" : "2x",
    "filename" : "launch_tablet_l_2048x1496.png"
  },
  {
    "orientation" : "landscape",
    "idiom" : "ipad",
    "extent" : "full-screen",
    "scale" : "2x",
    "filename" : "launch_tablet_l_2048x1536.png"
  }')
    end

    f.write('],"info" : {"version" : 1,"author" : "xcode"}}')
  end

  # Return true
  Longbow::green ('  - Created Images.xcassets launch image set for ' + target) unless $nolog
  return true
end