module Longbow

Constants

VERSION

Public Class Methods

assets_file_path(directory) click to toggle source
# File lib/longbow/images.rb, line 366
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) click to toggle source
# File lib/longbow/colors.rb, line 16
def self.blue(text)
  colorize(text, 36)
end
check_for_newer_version() click to toggle source
# 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) click to toggle source

Main Colorize Functions

# 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, lsimages) click to toggle source

Images

# File lib/longbow/images.rb, line 13
def self.create_images directory, t, obj, lsimages
  # 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

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

  if lsimages 
    # Resize Launch Images
    resize_launch_images directory, t

    # Write JSON for Launch Assets
    write_json_for_launch_images directory, t
  end

end
create_plist_from_old_plist(old_plist, info_hash, global_hash) click to toggle source

Create Plist from Original Plist Content

# 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) click to toggle source
# File lib/longbow/targets.rb, line 82
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) click to toggle source
# File lib/longbow/colors.rb, line 12
def self.green(text)
  colorize(text, 32)
end
json_object_from_directory(directory) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source

Asset Directory Methods

# File lib/longbow/images.rb, line 359
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) click to toggle source

Download Image from URL

# File lib/longbow/images.rb, line 379
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
  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) click to toggle source
# File lib/longbow/colors.rb, line 20
def self.purple(text)
  colorize(text, 35)
end
recursive_plist_value_for_value(value) click to toggle source

Recursively create Plist Values for a given object

# 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) click to toggle source

Specific Colors

# File lib/longbow/colors.rb, line 8
def self.red(text)
  colorize(text, 31)
end
resize_icons(directory, t, iPhone, iPad) click to toggle source

Create & Resize Icons

# File lib/longbow/images.rb, line 41
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 = ['1024x1024']
  image_sizes += ['180x180', '120x120', '114x114', '87x87', '80x80', '58x58', '60x60', '57x57', '40x40', '29x29'] if iPhone
  image_sizes += ['167x167', '152x152', '144x144', '100x100', '80x80', '76x76', '72x72', '58x58', '50x50', '40x40', '29x29', '20x20'] 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) click to toggle source

Resize Image to Directory

# File lib/longbow/images.rb, line 114
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) click to toggle source

Create & Resize Launch Images

# File lib/longbow/images.rb, line 72
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) click to toggle source

Strip Non-Alphanumerics

# 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) click to toggle source
# 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_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
    main_settings.each_key do |key|
      settings[key] = main_settings[key]
    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'] = '${inherited}'
    #end
  end

  # Save The Project
  proj.save
end
write_json_for_icons(directory, t, iPhone, iPad) click to toggle source

Create JSON

# File lib/longbow/images.rb, line 124
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( '{ "idiom" : "iphone", "size" : "20x20", "scale" : "2x", "filename" : "icon40x40.png" }, { "size" : "20x20", "idiom" : "iphone", "filename" : "icon60x60.png", "scale" : "3x" }, { "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" : "20x20", "scale" : "1x", "filename" : "icon20x20.png" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x", "filename" : "icon40x40.png" }, { "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(',  { "idiom" : "ios-marketing", "size" : "1024x1024", "scale" : "1x", "filename" : "icon1024x1024.png" } ], "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) click to toggle source

JSON for Launch Images

# File lib/longbow/images.rb, line 153
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