Skip to content
This repository has been archived by the owner on Sep 6, 2018. It is now read-only.

Commit

Permalink
Add support for multiple color palettes
Browse files Browse the repository at this point in the history
  • Loading branch information
djbe committed May 30, 2017
1 parent b3444ac commit fb9dd25
Show file tree
Hide file tree
Showing 12 changed files with 68 additions and 47 deletions.
15 changes: 9 additions & 6 deletions Sources/Parsers/ColorsFileParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,21 @@ public enum ColorsParserError: Error, CustomStringConvertible {
}
}

struct Palette {
let name: String
let colors: [String: UInt32]
}

protocol ColorsFileTypeParser: class {
static var extensions: [String] { get }

init()
func parseFile(at path: Path) throws -> [String: UInt32]
func parseFile(at path: Path) throws -> Palette
}

public final class ColorsFileParser {
private var parsers = [String: ColorsFileTypeParser.Type]()
var colors = [String: UInt32]()
var palettes = [Palette]()

public init() throws {
try register(parser: ColorsCLRFileParser.self)
Expand All @@ -53,11 +58,9 @@ public final class ColorsFileParser {
}

let parser = parserType.init()
let colors = try parser.parseFile(at: path)
let palette = try parser.parseFile(at: path)

for (name, value) in colors {
self.colors[name] = value
}
palettes += [palette]
}

func register(parser: ColorsFileTypeParser.Type) throws {
Expand Down
5 changes: 3 additions & 2 deletions Sources/Parsers/ColorsFileParsers/ColorsCLRFileParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@ final class ColorsCLRFileParser: ColorsFileTypeParser {
static let userColors = "UserColors"
}

func parseFile(at path: Path) throws -> [String: UInt32] {
func parseFile(at path: Path) throws -> Palette {
if let colorsList = NSColorList(name: Keys.userColors, fromFile: path.string) {
var colors = [String: UInt32]()

for colorName in colorsList.allKeys {
colors[colorName] = colorsList.color(withKey: colorName)?.hexValue
}

return colors
let name = path.lastComponentWithoutExtension
return Palette(name: name, colors: colors)
} else {
throw ColorsParserError.invalidFile(path: path, reason: "Invalid color list")
}
Expand Down
5 changes: 3 additions & 2 deletions Sources/Parsers/ColorsFileParsers/ColorsJSONFileParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import PathKit
final class ColorsJSONFileParser: ColorsFileTypeParser {
static let extensions = ["json"]

func parseFile(at path: Path) throws -> [String: UInt32] {
func parseFile(at path: Path) throws -> Palette {
do {
let json = try JSONSerialization.jsonObject(with: try path.read(), options: [])
guard let dict = json as? [String: String] else {
Expand All @@ -23,7 +23,8 @@ final class ColorsJSONFileParser: ColorsFileTypeParser {
colors[key] = try parse(hex: value, key: key)
}

return colors
let name = path.lastComponentWithoutExtension
return Palette(name: name, colors: colors)
} catch let error as ColorsParserError {
throw error
} catch let error {
Expand Down
5 changes: 3 additions & 2 deletions Sources/Parsers/ColorsFileParsers/ColorsTXTFileParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ final class ColorsTextFileParser: ColorsFileTypeParser {
// - One line per entry
// - Each line composed by the color name, then ":", then the color hex representation
// - Extra spaces will be skipped
func parseFile(at path: Path) throws -> [String: UInt32] {
func parseFile(at path: Path) throws -> Palette {
do {
let dict = try keyValueDict(from: path, withSeperator: ":")
for key in dict.keys {
Expand All @@ -77,6 +77,7 @@ final class ColorsTextFileParser: ColorsFileTypeParser {
throw ColorsParserError.invalidFile(path: path, reason: error.localizedDescription)
}

return colors
let name = path.lastComponentWithoutExtension
return Palette(name: name, colors: colors)
}
}
5 changes: 3 additions & 2 deletions Sources/Parsers/ColorsFileParsers/ColorsXMLFileParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final class ColorsXMLFileParser: ColorsFileTypeParser {
static let nameAttribute = "name"
}

func parseFile(at path: Path) throws -> [String: UInt32] {
func parseFile(at path: Path) throws -> Palette {
guard let document = Kanna.XML(xml: try path.read(), encoding: .utf8) else {
throw ColorsParserError.invalidFile(path: path, reason: "Unknown XML parser error.")
}
Expand All @@ -34,6 +34,7 @@ final class ColorsXMLFileParser: ColorsFileTypeParser {
colors[name] = try parse(hex: value, key: name)
}

return colors
let name = path.lastComponentWithoutExtension
return Palette(name: name, colors: colors)
}
}
55 changes: 35 additions & 20 deletions Sources/Stencil/ColorsContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,47 @@
import Foundation

/*
- `colors`: `Array` of:
- `name` : `String` — name of each color
- `red` : `String` — hex value of the red component
- `green`: `String` — hex value of the green component
- `blue` : `String` — hex value of the blue component
- `alpha`: `String` — hex value of the alpha component
- `palettes`: `Array` of:
- `name`: `String` — name of the palette
- `colors`: `Array` of:
- `name` : `String` — name of each color
- `red` : `String` — hex value of the red component
- `green`: `String` — hex value of the green component
- `blue` : `String` — hex value of the blue component
- `alpha`: `String` — hex value of the alpha component
*/
extension ColorsFileParser {
public func stencilContext() -> [String: Any] {
let colorMap = colors.map({ (color: (name: String, value: UInt32)) -> [String:String] in
let name = color.name.trimmingCharacters(in: CharacterSet.whitespaces)
let hex = "00000000" + String(color.value, radix: 16)
let hexChars = Array(hex.characters.suffix(8))
let comps = (0..<4).map { idx in String(hexChars[idx*2...idx*2+1]) }
let palettes: [[String: Any]] = self.palettes
.sorted(by: { $0.name < $1.name })
.map { palette in
let colors = palette.colors
.sorted { $0.key < $1.key }
.map(map(color:value:))

return [
"name": name,
"red": comps[0],
"green": comps[1],
"blue": comps[2],
"alpha": comps[3]
]
}).sorted { $0["name"] ?? "" < $1["name"] ?? "" }
return [
"name": palette.name,
"colors": colors
]
}

return [
"colors": colorMap
"palettes": palettes
]
}

private func map(color name: String, value: UInt32) -> [String: String] {
let name = name.trimmingCharacters(in: .whitespaces)
let hex = "00000000" + String(value, radix: 16)
let hexChars = Array(hex.characters.suffix(8))
let comps = (0..<4).map { idx in String(hexChars[idx*2...idx*2+1]) }

return [
"name": name,
"red": comps[0],
"green": comps[1],
"blue": comps[2],
"alpha": comps[3]
]
}
}
2 changes: 1 addition & 1 deletion Tests/SwiftGenKitTests/ColorsCLRFileTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import PathKit
class ColorsCLRFileTests: XCTestCase {
func testFileWithDefaults() throws {
let parser = try ColorsFileParser()
parser.colors = try ColorsCLRFileParser().parseFile(at: Fixtures.path(for: "colors.clr", sub: .colors))
parser.palettes = [try ColorsCLRFileParser().parseFile(at: Fixtures.path(for: "colors.clr", sub: .colors))]

let result = parser.stencilContext()
XCTDiffContexts(result, expected: "defaults.plist", sub: .colors)
Expand Down
2 changes: 1 addition & 1 deletion Tests/SwiftGenKitTests/ColorsJSONFileTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import PathKit
class ColorsJSONFileTests: XCTestCase {
func testFileWithDefaults() throws {
let parser = try ColorsFileParser()
parser.colors = try ColorsJSONFileParser().parseFile(at: Fixtures.path(for: "colors.json", sub: .colors))
parser.palettes = [try ColorsJSONFileParser().parseFile(at: Fixtures.path(for: "colors.json", sub: .colors))]

let result = parser.stencilContext()
XCTDiffContexts(result, expected: "defaults.plist", sub: .colors)
Expand Down
15 changes: 7 additions & 8 deletions Tests/SwiftGenKitTests/ColorsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ import XCTest

final class TestFileParser1: ColorsFileTypeParser {
static let extensions = ["test1"]
func parseFile(at path: Path) throws -> [String: UInt32] {
return ["test1": 1]
func parseFile(at path: Path) throws -> Palette {
return Palette(name: "test1", colors: [:])
}
}

final class TestFileParser2: ColorsFileTypeParser {
static let extensions = ["test2"]
func parseFile(at path: Path) throws -> [String: UInt32] {
return ["test2": 1]
func parseFile(at path: Path) throws -> Palette {
return Palette(name: "test2", colors: [:])
}
}

final class TestFileParser3: ColorsFileTypeParser {
static let extensions = ["test1"]
func parseFile(at path: Path) throws -> [String: UInt32] {
return [:]
func parseFile(at path: Path) throws -> Palette {
return Palette(name: "test3", colors: [:])
}
}

Expand All @@ -45,8 +45,7 @@ class ColorParserTests: XCTestCase {
try parser.register(parser: TestFileParser2.self)

try parser.parseFile(at: "someFile.test1")
XCTAssertEqual(parser.colors["test1"], 1)
XCTAssertNil(parser.colors["test2"])
XCTAssertEqual(parser.palettes.first?.name, "test1")
}

func testDispatchUnknownExtension() throws {
Expand Down
2 changes: 1 addition & 1 deletion Tests/SwiftGenKitTests/ColorsTextFileTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import PathKit
class ColorsTextFileTests: XCTestCase {
func testFileWithDefaults() throws {
let parser = try ColorsFileParser()
parser.colors = try ColorsTextFileParser().parseFile(at: Fixtures.path(for: "colors.txt", sub: .colors))
parser.palettes = [try ColorsTextFileParser().parseFile(at: Fixtures.path(for: "colors.txt", sub: .colors))]

let result = parser.stencilContext()
XCTDiffContexts(result, expected: "text-defaults.plist", sub: .colors)
Expand Down
2 changes: 1 addition & 1 deletion Tests/SwiftGenKitTests/ColorsXMLFileTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import PathKit
class ColorsXMLFileTests: XCTestCase {
func testFileWithDefaults() throws {
let parser = try ColorsFileParser()
parser.colors = try ColorsXMLFileParser().parseFile(at: Fixtures.path(for: "colors.xml", sub: .colors))
parser.palettes = [try ColorsXMLFileParser().parseFile(at: Fixtures.path(for: "colors.xml", sub: .colors))]

let result = parser.stencilContext()
XCTDiffContexts(result, expected: "defaults.plist", sub: .colors)
Expand Down

0 comments on commit fb9dd25

Please sign in to comment.