Last active
August 29, 2015 14:22
-
-
Save Goos/92b7cbc7328ff538a550 to your computer and use it in GitHub Desktop.
A hacky script that takes .xcassets directories and produces a Swift file defining an enum with a case for each image in the asset directories, as well as an UIImage convenience initializer that takes said enum as an argument instead of a string. This enables compiler-checked UIImage initialization returning non-optional images. Inspired by the …
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "pathname" | |
class XCAsset | |
def initialize(path, is_root) | |
@path = path | |
@is_root = is_root | |
name = @path.split.last | |
@is_container = !(name.to_s =~ /\.imageset$/) | |
if @is_container | |
@name = name.to_s.sub(".xcassets", "") | |
@children = @path.children.select { |child| | |
!(child.to_s =~ /\.appiconset$/) and child.directory? | |
}.map { |child| | |
XCAsset.new(child, false) | |
}.sort_by { |asset| asset.container? ? 0 : 1 } | |
else | |
@name = name.to_s.sub(".imageset", "") | |
end | |
end | |
def name | |
@name | |
end | |
def children | |
@children | |
end | |
def container? | |
@is_container | |
end | |
def root? | |
@is_root | |
end | |
end | |
class StringRenderer | |
def render(assets) | |
@tablevel = 0 | |
str = "import UIKit\n\n" | |
str += "extension UIImage {" | |
@tablevel += 1 | |
str += "\n#{tabstring}enum AssetIdentifier: String {\n" | |
assets.each { |child| | |
if child.container? | |
str += render_container(child) | |
else | |
str += render_identifier(child) | |
end | |
str += "\n" | |
} | |
str += "#{tabstring}}" | |
str += render_initializers() | |
str += "\n}" | |
end | |
def tabstring | |
(0...@tablevel).reduce("") { |x,y| x += " " } | |
end | |
def render_container(container) | |
@tablevel += 1 | |
str = "#{tabstring}" | |
if container.root? | |
str += "/* #{container.name} */" | |
else | |
str += "// #{container.name}" | |
end | |
container.children.each { |child| | |
str += "\n" | |
if child.container? | |
str += render_container(child) if child.children.count > 0 | |
else | |
str += render_identifier(child) | |
end | |
} | |
@tablevel -= 1 | |
str += "\n" | |
str | |
end | |
def render_identifier(asset) | |
name_without_spaces = asset.name.sub(" ", "") | |
"#{tabstring}case #{name_without_spaces} = \"#{asset.name}\"" | |
end | |
def render_initializers | |
str = "\n\n#{tabstring}convenience init!(assetIdentifier: AssetIdentifier) {" | |
@tablevel += 1 | |
str += "\n#{tabstring}self.init(named: assetIdentifier.rawValue)" | |
@tablevel -= 1 | |
str += "\n#{tabstring}}" | |
str | |
end | |
end | |
renderer = StringRenderer.new() | |
srcroot = nil | |
input_files = [] | |
output_file = nil | |
ENV.each do |arg| | |
key = arg.first | |
val = arg.last | |
if key =~ /^SCRIPT_INPUT_FILE(?!_COUNT)/ && val =~ /.xcassets$/ | |
input_files.push val | |
elsif key =~ /^SCRIPT_OUTPUT_FILE/ | |
output_file = val | |
elsif key =~ /^SRCROOT/ | |
srcroot = val | |
end | |
end | |
if input_files.empty? | |
puts "Error: None or improper input files specified." | |
exit | |
end | |
if output_file == nil | |
puts "Error: No output file specified." | |
exit | |
end | |
asset_folders = input_files.map { |path| | |
p = Pathname.new(path) | |
XCAsset.new(p, true) | |
} | |
content = renderer.render(asset_folders) | |
File.open(output_file, 'w+') { |f| f.write(content) } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment