Created
September 23, 2014 17:20
-
-
Save seoh/7673fbcd19ab792f02b5 to your computer and use it in GitHub Desktop.
Swift Comparison and String Literal
This file contains 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
// http://nshipster.com/swift-comparison-protocols/ | |
import Foundation | |
struct CSSSelector { | |
let selector: String | |
struct Specificity { | |
let id: Int | |
let `class`: Int | |
let element: Int | |
init(_ components: [String]) { | |
var (id, `class`, element) = (0, 0, 0) | |
for token in components { | |
if token.hasPrefix("#") { | |
id++ | |
} else if token.hasPrefix(".") { | |
`class`++ | |
} else { | |
element++ | |
} | |
} | |
self.id = id | |
self.`class` = `class` | |
self.element = element | |
} | |
} | |
let specificity: Specificity | |
init(_ string: String) { | |
self.selector = string | |
// Naïve tokenization, ignoring operators, pseudo-selectors, and `style=`. | |
let components: [String] = self.selector.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceCharacterSet()) | |
self.specificity = Specificity(components) | |
} | |
} | |
extension CSSSelector: StringLiteralConvertible { | |
typealias ExtendedGraphemeClusterLiteralType = StringLiteralType | |
typealias UnicodeScalarLiteralType = StringLiteralType | |
static func convertFromStringLiteral(value: StringLiteralType) -> CSSSelector { | |
return self(value) | |
} | |
static func convertFromExtendedGraphemeClusterLiteral(value: ExtendedGraphemeClusterLiteralType) -> CSSSelector { | |
return self(value) | |
} | |
static func convertFromUnicodeScalarLiteral(value: UnicodeScalarLiteralType) -> CSSSelector { | |
return self(value) | |
} | |
} | |
extension CSSSelector: Equatable {} | |
// MARK: Equatable | |
func ==(lhs: CSSSelector, rhs: CSSSelector) -> Bool { | |
// Naïve equality that uses string comparison rather than resolving equivalent selectors | |
return lhs.selector == rhs.selector | |
} | |
extension CSSSelector.Specificity: Comparable {} | |
// MARK: Comparable | |
func <(lhs: CSSSelector.Specificity, rhs: CSSSelector.Specificity) -> Bool { | |
return lhs.id < rhs.id || | |
lhs.`class` < rhs.`class` || | |
lhs.element < rhs.element | |
} | |
// MARK: Equatable | |
func ==(lhs: CSSSelector.Specificity, rhs: CSSSelector.Specificity) -> Bool { | |
return lhs.id == rhs.id && | |
lhs.`class` == rhs.`class` && | |
lhs.element == rhs.element | |
} | |
let a: CSSSelector = "#logo" | |
let b: CSSSelector = "html body #logo" | |
let c: CSSSelector = "body div #logo" | |
let d: CSSSelector = ".container #logo" | |
println(b == c) // false | |
println(b.specificity == c.specificity) // true | |
println(c.specificity < a.specificity) // false | |
println(d.specificity > c.specificity) // true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment