diff --git a/Sources/Compass.swift b/Sources/Compass.swift index 88d421a..2fa1126 100644 --- a/Sources/Compass.swift +++ b/Sources/Compass.swift @@ -95,8 +95,12 @@ public struct Compass { extension Compass { + public static func compassURL(urn: String, scheme: String = Compass.scheme) -> URL? { + return URL(string: "\(scheme)\(urn.compass_encoded())") + } + public static func navigate(to urn: String, scheme: String = Compass.scheme) { - guard let url = URL(string: "\(scheme)\(urn)") else { return } + guard let url = compassURL(urn: urn, scheme: scheme) else { return } open(url: url) } } diff --git a/Sources/Location.swift b/Sources/Location.swift index 28dce93..c4aee77 100644 --- a/Sources/Location.swift +++ b/Sources/Location.swift @@ -10,7 +10,13 @@ public struct Location { public init(path: String, arguments: [String: String] = [:], payload: Any? = nil) { self.path = path - self.arguments = arguments self.payload = payload + + var decodedArguments = [String: String]() + arguments.forEach { (key, value) in + decodedArguments[key] = value.compass_decoded() + } + + self.arguments = decodedArguments } } diff --git a/Sources/String+Extensions.swift b/Sources/String+Extensions.swift index 726e51c..5249f69 100644 --- a/Sources/String+Extensions.swift +++ b/Sources/String+Extensions.swift @@ -24,4 +24,12 @@ extension String { return parameters } + + func compass_encoded() -> String { + return addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? self + } + + func compass_decoded() -> String { + return removingPercentEncoding ?? self + } } diff --git a/Tests/Compass/CompassTests.swift b/Tests/Compass/CompassTests.swift index 38a127c..86cd277 100644 --- a/Tests/Compass/CompassTests.swift +++ b/Tests/Compass/CompassTests.swift @@ -11,6 +11,7 @@ class CompassTests: XCTestCase { "profile:admin", "login", "callback", + "organization:{name}:{type}", "user:list:{userId}:{kind}", "user:list", "{appId}:user:list:{userId}:{kind}" @@ -23,7 +24,7 @@ class CompassTests: XCTestCase { func testRoutes() { XCTAssert(!Compass.routes.isEmpty) - XCTAssert(Compass.routes.count == 7) + XCTAssert(Compass.routes.count == 8) } func testParseArguments() { @@ -263,4 +264,19 @@ class CompassTests: XCTestCase { XCTAssertEqual(location.arguments["expires_in"], "3600") XCTAssertEqual(location.arguments["token_type"], "Bearer") } + + func testEncodedURN() { + let urn = "organization:hyper oslo:simply awesome" + let url = Compass.compassURL(urn: urn) + + XCTAssertNotNil(url) + + guard let location = Compass.parse(url: url!) else { + XCTFail("Compass parsing failed") + return + } + + XCTAssertEqual(location.arguments["name"], "hyper oslo") + XCTAssertEqual(location.arguments["type"], "simply awesome") + } }