A simple CSS to Swift Model Parser.
extension String {
/// Returns the substring that contains the characters after first occurrence of the provided token.
///
/// - Parameter token: The token
/// - Returns: The substring that contains the characters after first occurrence of the provided token.
func removeLeading(startWith token: String) -> String {
if let token = range(of: token) {
var newString = self
newString.removeSubrange(startIndex..<token.upperBound)
return newString
}
return self
}
/// Returns the substring that contains the characters before first occurrence of the provided token.
///
/// - Parameter token: The token
/// - Returns: The substring that contains the characters before first occurrence of the provided token.
func removeTrailing(startWith token: String) -> String {
if let token = range(of: token) {
var newString = self
newString.removeSubrange(token.lowerBound..<endIndex)
return newString
}
return self
}
/// Replaces the occurrences of the strings provided.
///
/// - Parameter strings: Strings to remove.
/// - Returns: Updated string with the strings removed.
func replacingOccurrences(strings: [String]) -> String {
var updatedString = self
for string in strings {
updatedString = updatedString.replacingOccurrences(of: string, with: "")
}
return updatedString
}
}
struct CssStyle {
/// Name of the style.
let name: String
/// Properties of the style.
let properties: [String: String]
}
final class CssParser {
/// Parses the CSS file string into an array of CSS styles.
///
/// - Parameter fileContent: CSS file content.
/// - Returns: Array of CSS styles.
static func parse(fileContent: String) -> [CssStyle] {
var styles = [CssStyle]()
var pendingStyleName = ""
var pendingStyleProperties = [String: String]()
var pendingLine = ""
for character in fileContent {
pendingLine.append(character)
if character == "{" {
pendingStyleName = pendingLine.replacingOccurrences(strings: [" ", "\n", "{"])
pendingLine = ""
} else if character == ";" {
let propertyLine = pendingLine.replacingOccurrences(strings: [";", "\n"])
let key = propertyLine.removeTrailing(startWith: ":").replacingOccurrences(strings: [" "])
let value = propertyLine.removeLeading(startWith: ":").removeLeading(startWith: " ")
pendingStyleProperties[key] = value
pendingLine = ""
} else if character == "}" {
styles.append(CssStyle(name: pendingStyleName, properties: pendingStyleProperties))
pendingStyleProperties.removeAll()
pendingStyleName = ""
pendingLine = ""
}
}
return styles
}
}