Skip to content

Commit

Permalink
Merge pull request #48 from hyperoslo/fix/docs
Browse files Browse the repository at this point in the history
Add documentations
  • Loading branch information
onmyway133 committed Jul 31, 2017
2 parents b9bacdb + ef38497 commit 9598ba8
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 1 deletion.
9 changes: 9 additions & 0 deletions Sources/Location.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
/// An encapsulated location request, used for navigate based on the registed routes.
/// You can either construct it or call Navigator.parse(url).
public struct Location {

/// The urn
public let path: String

/// The arguments if any
public let arguments: [String: String]

/// An optional payload if you want to send in app objects
public let payload: Any?

/// The application scheme
public var scheme: String {
return Navigator.scheme
}

/// Construct a Location
public init(path: String, arguments: [String: String] = [:], payload: Any? = nil) {
self.path = path
self.payload = payload
Expand Down
37 changes: 37 additions & 0 deletions Sources/Navigator.swift
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
import Foundation

/// The Navigator is used to parse Location from url, and navigate
public struct Navigator {

/// The Result used in the findMatch function
typealias Result = (
route: String,
arguments: [String: String],
concreteMatchCount: Int,
wildcardMatchCount: Int)

fileprivate static var internalScheme = ""

/// The delimiter used to split parts within url, default to :
public static var delimiter: String = ":"

/// The scheme used by Compass, usually it is your application scheme
public static var scheme: String {
set { Navigator.internalScheme = newValue }
get { return "\(Navigator.internalScheme)://" }
}

/// A list of route strings
public static var routes = [String]()

/// Parse Location from url
///
/// - Parameters:
/// - url: The url to be parsed
/// - payload: The optional payload if you want to send in app objects
/// - Returns: The Location that can be used
public static func parse(url: URL, payload: Any? = nil) -> Location? {
let path = url.absoluteString.substring(from: scheme.endIndex)

Expand All @@ -42,6 +54,13 @@ public struct Navigator {
return nil
}


/// Helper function to parse url if it has components and queryItems
///
/// - Parameters:
/// - url: The url to be parsed
/// - payload: The optional payload if you want to send in app objects
/// - Returns: The Location that can be used
static func parseComponents(url: URL, payload: Any? = nil) -> Location? {
guard let route = url.host else { return nil }

Expand All @@ -59,6 +78,12 @@ public struct Navigator {
return Location(path: route, arguments: arguments, payload: payload)
}

/// Find the best match registed route for a certain route string
///
/// - Parameters:
/// - routeString: The registered route string
/// - pathString: The path extracted from the requested url
/// - Returns: The Result on how this pathString matches
static func findMatch(routeString: String, pathString: String) -> Result? {
let routes = routeString.split(delimiter)
let paths = pathString.split(delimiter)
Expand Down Expand Up @@ -95,10 +120,22 @@ public struct Navigator {

extension Navigator {

/// Parse an urn to be Compass friendly URL
///
/// - Parameters:
/// - urn: The requested urn
/// - scheme: The application scheme
/// - Returns: The URL to be ready used by Compass
public static func compassURL(urn: String, scheme: String = Navigator.scheme) -> URL? {
return URL(string: "\(scheme)\(urn.compass_encoded())")
}


/// Navigate by telling the application to open a url
///
/// - Parameters:
/// - urn: The requested urn
/// - scheme: The application scheme
public static func navigate(to urn: String, scheme: String = Navigator.scheme) {
guard let url = compassURL(urn: urn, scheme: scheme) else { return }
open(url: url)
Expand Down
22 changes: 21 additions & 1 deletion Sources/Router.swift
Original file line number Diff line number Diff line change
@@ -1,26 +1,46 @@
/// Possible error enums
///
/// - notFound: The route can not be found
/// - invalidArguments: The argument is not valid
public enum RouteError: Error {
case notFound
case invalidArguments(Location)
case invalidPayload(Location)
}

/// Anything conforming to Routable knows how to navigate to a certain location. Used by Router
public protocol Routable {

/// Navigate to a location based on the current controller
///
/// - Parameters:
/// - location: The location to go to
/// - currentController: The current controller
/// - Throws: Throws RouteError if any
func navigate(to location: Location, from currentController: CurrentController) throws
}

/// Anything conforming to ErrorRoutable knows how to handle route error. Used by Router
public protocol ErrorRoutable {

func handle(routeError error: Error, from currentController: CurrentController)
}

/// A Router knows how to parse routing request and delegate handling to Routable
public struct Router: Routable {

/// A map of route string and Routable
public var routes = [String: Routable]()

/// The error handler
public var errorRoute: ErrorRoutable?

public init() {}

/// Navigate to a location based on the current controller
///
/// - Parameters:
/// - location: The requested location
/// - currentController: The current controller
public func navigate(to location: Location, from currentController: CurrentController) {
guard let route = routes[location.path] else {
errorRoute?.handle(routeError: RouteError.notFound, from: currentController)
Expand Down
14 changes: 14 additions & 0 deletions Sources/String+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ import Foundation

extension String {

/// Safely split components based on delimiter
///
/// - Parameter delimiter: The delimiter
/// - Returns: An array of parts
func split(_ delimiter: String) -> [String] {
let components = self.components(separatedBy: delimiter)
return components != [""] ? components : []
}

/// Get query parameters if any
///
/// - Returns: A map of query key and content
func queryParameters() -> [String: String] {
var parameters = [String: String]()

Expand All @@ -25,10 +32,17 @@ extension String {
return parameters
}

/// Route string must be percent encoded to be registered in Compass route list
///
/// - Returns: The percented encoded string
func compass_encoded() -> String {
return addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? self
}


/// Perform percent decoding to be in a user readable Location
///
/// - Returns: The percented decoded string
func compass_decoded() -> String {
return removingPercentEncoding ?? self
}
Expand Down
6 changes: 6 additions & 0 deletions Sources/TypeAlias.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@
#if os(OSX)
public typealias CurrentController = NSViewController

/// Tell the application to open the url
///
/// - Parameter url: The requested url
func open(url: URL) {
NSWorkspace.shared().open(url)
}
#else
public typealias CurrentController = UIViewController

/// Tell the application to open the url
///
/// - Parameter url: The requested url
func open(url: URL) {
UIApplication.shared.openURL(url)
}
Expand Down

0 comments on commit 9598ba8

Please sign in to comment.