Skip to content

Instantly share code, notes, and snippets.

@drumnkyle
Last active November 15, 2016 02:18
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save drumnkyle/bf3f3b5acbb1199c7b6c0f00f396977b to your computer and use it in GitHub Desktop.
A helper that will take a XIB as a string and make it more human readable
var outletRegex = /<outlet property=\"(.*)\" destination=\"(.*)\" id=\".*\"\/>/g;
var xcodeIDRegex = /id=\"(.*)\".*userLabel=\"(.*)\"/g;
var customClass = /id=\"(.*)\".*customClass=\"(.*)\"/g;
var allDiffs = [].slice.call(document.getElementsByClassName("sidebyside"));
for (i = 0; i < allDiffs.length; i++) {
if (allDiffs[i].getElementsByClassName("filename-row")[0].textContent.includes(".xib")) {
var xibString = allDiffs[i].innerText;
var matches, output = [];
while (matches = outletRegex.exec(xibString)) {
output.push({ id: matches[2], name: matches[1] });
}
console.log(output);
while (matches = xcodeIDRegex.exec(xibString)) {
output.push({ id: matches[1], name: matches[2] });
}
console.log(output);
while (matches = customClass.exec(xibString)) {
output.push({ id: matches[1], name: matches[2] });
}
console.log(output);
for (j = 0; j < output.length; j++) {
var id = output[j]["id"];
var replacing = new RegExp(id, "g");
var name = output[j]["name"];
allDiffs[i].innerHTML = allDiffs[i].innerHTML.replace(replacing, name);
}
}
}
/**
// This is the bookmarklet code:
javascript:(function()%7Bvar%20outletRegex%20%3D%20%2F%3Coutlet%20property%3D%5C%22(.*)%5C%22%20destination%3D%5C%22(.*)%5C%22%20id%3D%5C%22.*%5C%22%5C%2F%3E%2Fg%3Bvar%20xcodeIDRegex%20%3D%20%2Fid%3D%5C%22(.*)%5C%22.*userLabel%3D%5C%22(.*)%5C%22%2Fg%3Bvar%20customClass%20%3D%20%2Fid%3D%5C%22(.*)%5C%22.*customClass%3D%5C%22(.*)%5C%22%2Fg%3Bvar%20allDiffs%20%3D%20%5B%5D.slice.call(document.getElementsByClassName(%22sidebyside%22))%3Bfor%20(i%20%3D%200%3B%20i%20%3C%20allDiffs.length%3B%20i%2B%2B)%20%7Bif%20(allDiffs%5Bi%5D.getElementsByClassName(%22filename-row%22)%5B0%5D.textContent.includes(%22.xib%22))%20%7Bvar%20xibString%20%3D%20allDiffs%5Bi%5D.innerText%3Bvar%20matches%2C%20output%20%3D%20%5B%5D%3Bwhile%20(matches%20%3D%20outletRegex.exec(xibString))%20%7Boutput.push(%7B%20id%3A%20matches%5B2%5D%2C%20name%3A%20matches%5B1%5D%20%7D)%3B%7Dconsole.log(output)%3Bwhile%20(matches%20%3D%20xcodeIDRegex.exec(xibString))%20%7Boutput.push(%7B%20id%3A%20matches%5B1%5D%2C%20name%3A%20matches%5B2%5D%20%7D)%3B%7Dconsole.log(output)%3Bwhile%20(matches%20%3D%20customClass.exec(xibString))%20%7Boutput.push(%7B%20id%3A%20matches%5B1%5D%2C%20name%3A%20matches%5B2%5D%20%7D)%3B%7Dconsole.log(output)%3Bfor%20(j%20%3D%200%3B%20j%20%3C%20output.length%3B%20j%2B%2B)%20%7Bvar%20id%20%3D%20output%5Bj%5D%5B%22id%22%5D%3Bvar%20replacing%20%3D%20new%20RegExp(id%2C%20%22g%22)%3Bvar%20name%20%3D%20output%5Bj%5D%5B%22name%22%5D%3BallDiffs%5Bi%5D.innerHTML%20%3D%20allDiffs%5Bi%5D.innerHTML.replace(replacing%2C%20name)%3B%7D%7D%7D%7D)()
*/
<script>
// This is my attempt at trying to make a Safari extension, but it doesn't seem to do anything. Any help appreciated.
// This is the global.html file
safari.application.addEventListener("command", performCommand, false);
// Function to perform when event is received
function performCommand(event) {
// Make sure event comes from the button
if (event.command == "github") {
// This is where we finally respond to the click
var table = document.getElementsByClassName('blob-wrapper data type-xml');
var xibString = table[0].innerText;
var outletRegex = /<outlet property=\"(.*)\" destination=\"(.*)\" id=\".*\"\/>/g;
var matches, output = [];
while (matches = outletRegex.exec(xibString)) {
output.push({ id: matches[2], name: matches[1] });
}
for (i = 0; i < output.length; i++) {
var id = output[i]["id"];
var replacing = new RegExp(id, "g");
var name = output[i]["name"];
table[0].innerHTML = table[0].innerHTML.replace(replacing, name);
}
}
}
</script>
public struct ReadableXIB {
public enum ReplacementType {
case outlet
case xcodeIdentifier
case customClass
// TODO: Haven't gotten the Regex right
// case accessibilityIdentifier
var regex: NSRegularExpression {
switch self {
case .outlet:
return try! NSRegularExpression(pattern: "<outlet property=\"(.*)\" destination=\"(.*)\" id=\".*\"/>", options: .caseInsensitive)
case .xcodeIdentifier:
return try! NSRegularExpression(pattern: "id=\"(.*)\".*userLabel=\"(.*)\"", options: .caseInsensitive)
case .customClass:
return try! NSRegularExpression(pattern: "id=\"(.*)\".*customClass=\"(.*)\"", options: .caseInsensitive)
}
}
var isIDFirst: Bool {
switch self {
case .outlet:
return false
case .xcodeIdentifier:
return true
case .customClass:
return true
}
}
static let all: [ReplacementType] = [.outlet, .xcodeIdentifier, .customClass]
}
public let xibString: String
public let replacementTypes: [ReplacementType]
public init(xibString: String, withReplacements replacementTypes: [ReplacementType] = ReplacementType.all) {
self.xibString = xibString
self.replacementTypes = replacementTypes
}
public func generateReadableXIB() throws -> String {
return try convertingXIb(xibString, using: replacementTypes)
}
private func replacementPairs(forRegex regex: NSRegularExpression, in xibString: String, isIDFirst: Bool) throws -> [String: String] {
var idsToReplace: [String: String] = [:]
regex.enumerateMatches(in: xibString, options: [], range: NSRange(0..<xibString.characters.count)) { (result, flags, stop) in
let xibNSString = xibString as NSString
guard let result = result else {
stop.pointee = true
return
}
let newName = xibNSString.substring(with: result.rangeAt(isIDFirst ? 2 : 1))
let id = xibNSString.substring(with: result.rangeAt(isIDFirst ? 1 : 2))
idsToReplace[id] = newName
}
return idsToReplace
}
private func convertingXIb(_ xibString: String, using replacements: [ReplacementType]) throws -> String {
let replacementPairArray = try replacements.map {
try replacementPairs(forRegex: $0.regex, in: xibString, isIDFirst: $0.isIDFirst)
}
var replacements = replacementPairArray.flatMap { $0 }
// Remove File's Owner
if let filesOwnerIndex = replacements.index(where: { $0.key == "File\'s Owner" }) {
replacements.remove(at: filesOwnerIndex)
}
return replacements.reduce(xibString) { string, pair in
return string.replacingOccurrences(of: pair.key, with: pair.value)
}
}
}
@drumnkyle
Copy link
Author

I would like to make a Javascript version of this so that I can make a Safari and Chrome extension so that this can be used in the browser for code reviews. That is what would make this most useful. That way when you are looking at a diff, you hit a button and see a more readable version.

However, I don't know Javascript and I have never made a browser extension. So any help would be appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment