Instantly share code, notes, and snippets.

Embed
What would you like to do?
Generate Swift constants for Xcode storyboards containing cell reuse identifiers, segue identifiers and storyboard identifier. More information: https://www.ralfebert.de/storyboard-constants/
#!/usr/bin/env ruby
require 'nokogiri'
def show_usage(msg = nil)
puts "#{msg}\n\n" if msg
puts "Usage:\n\t#{$PROGRAM_NAME} [storyboard_file]"
exit(0)
end
def swift_name(name)
name = name.gsub(/[^0-9A-Z_]/i, '')
name[0].downcase + name[1..-1]
end
def constant(name, value)
"var #{name}: String { return \"#{value}\" }"
end
def extension_for_class(cl)
ids = (cl.xpath(".//*[@reuseIdentifier]/@reuseIdentifier") + cl.xpath(".//*[@identifier]/@identifier"))
declarations = ids.map { |e| constant(swift_name(e.to_s), e) }
declarations.push "static " + constant("storyboardIdentifier", cl['storyboardIdentifier']) if cl['storyboardIdentifier']
return if declarations.empty?
<<-END
extension #{cl['customClass']} {
#{declarations.map {|line| "\t" + line }.join("\n")}
}
END
end
show_usage unless ARGV.count == 1
fname_storyboard = ARGV[0]
show_usage "Storyboard file not found: #{fname_storyboard}" unless File.exist?(fname_storyboard)
doc = File.open(fname_storyboard) { |f| Nokogiri::XML(f) }
show_usage "#{fname_storyboard} doesn't seem to be a storyboard" unless doc.root.name == "document"
extensions = doc.xpath(".//*[@customClass]").map { |cl| extension_for_class(cl) }
puts "// Generated with https://www.ralfebert.de/storyboard-constants/\n\n" + extensions.join.strip
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment