Skip to content

Commit

Permalink
fix: Correct metadata type promotion for Date, Double, and Int (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jbmorley authored May 7, 2024
1 parent 3fe8d63 commit 5b2842e
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 24 deletions.
14 changes: 0 additions & 14 deletions Sources/InContextCore/Extensions/Dictionary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,6 @@ import Foundation

extension Dictionary {

func promotingStringDates() -> Dictionary<Key, Any> {
return map { (key, value) -> (Key, Any) in
if let string = value as? String,
let date = DateParser.default.date(from: string) {
return (key, date)
} else {
return (key, value)
}
}
.reduce(into: [Key: Any]()) { partialResult, element in
partialResult[element.0] = element.1
}
}

func value<T>(for key: Key, default defaultValue: T) throws -> T {
guard let value = self[key] else {
return defaultValue
Expand Down
14 changes: 9 additions & 5 deletions Sources/InContextCore/Extensions/KeyedDecodingContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,15 @@ extension KeyedDecodingContainer {
if let boolValue = try? decode(Bool.self, forKey: key) {
dictionary[key.stringValue] = boolValue
} else if let stringValue = try? decode(String.self, forKey: key) {
dictionary[key.stringValue] = stringValue
} else if let intValue = try? decode(Int.self, forKey: key) {
dictionary[key.stringValue] = intValue
} else if let doubleValue = try? decode(Double.self, forKey: key) {
dictionary[key.stringValue] = doubleValue
if let intValue = Int(stringValue) {
dictionary[key.stringValue] = intValue
} else if let doubleValue = Double(stringValue) {
dictionary[key.stringValue] = doubleValue
} else if let dateValue = DateParser.default.date(from: stringValue) {
dictionary[key.stringValue] = dateValue
} else {
dictionary[key.stringValue] = stringValue
}
} else if let nestedDictionary = try? decode(Dictionary<String, Any>.self, forKey: key) {
dictionary[key.stringValue] = nestedDictionary
} else if let nestedArray = try? decode(Array<Any>.self, forKey: key) {
Expand Down
14 changes: 10 additions & 4 deletions Sources/InContextCore/Extensions/UnkeyedDecodingContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ extension UnkeyedDecodingContainer {
while isAtEnd == false {
if let value = try? decode(Bool.self) {
array.append(value)
} else if let value = try? decode(Double.self) {
array.append(value)
} else if let value = try? decode(String.self) {
array.append(value)
} else if let string = try? decode(String.self) {
if let int = Int(string) {
array.append(int)
} else if let double = Double(string) {
array.append(double)
} else if let date = DateParser.default.date(from: string) {
array.append(date)
} else {
array.append(string)
}
} else if let nestedDictionary = try? decode(Dictionary<String, Any>.self) {
array.append(nestedDictionary)
} else if let nestedArray = try? decode(Array<Any>.self) {
Expand Down
1 change: 0 additions & 1 deletion Sources/InContextCore/Utilities/DictionaryWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ struct DictionaryWrapper: Decodable {
let container = try decoder.container(keyedBy: UnknownCodingKeys.self)
self.dictionary = try container
.decode(Dictionary<String, Any>.self)
.promotingStringDates()
}

}
71 changes: 71 additions & 0 deletions Tests/InContextTests/Tests/FrontmatterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,75 @@ title: おはよう
XCTAssertEqual(document.title, "おはよう")
}

func testInt() throws {
let document = try FrontmatterDocument(contents: """
---
random: 12
---
""")
XCTAssertEqual(document.metadata["random"] as? Int, 12)
}

func testDouble() throws {
let document = try FrontmatterDocument(contents: """
---
random: 12.5
---
""")
XCTAssertEqual(document.metadata["random"] as? Double, 12.5)
}

func testQueryDefinition() throws {
let document = try FrontmatterDocument(contents: """
---
template: posts.html
item_template: post_content.html
category: pages
queries:
posts:
include:
- general
sort: descending
limit: 3
---
""")

guard let queries = document.metadata["queries"] as? [AnyHashable: Any],
let postsQuery = queries["posts"] as? [AnyHashable: Any] else {
XCTFail("Unexpected metadata query structure")
return
}

XCTAssertEqual(postsQuery["include"] as? [String], ["general"])
XCTAssertEqual(postsQuery["sort"] as? String, "descending")
XCTAssertEqual(postsQuery["limit"] as? Int, 3)
}

func testCommentsWithDates() throws {
let document = try FrontmatterDocument(contents: """
---
category: Computing
comments:
- author: Daniel
author_email: ''
author_url: ''
content: I debate the validity of 'Cambridgidian' as an English word. Try Cantabrigian
instead ;)
date: 2005-06-01 19:24:30 +0000
date: 2005-05-30 22:17:44 +0000
template: post
title: Oh The Shame...
---
""")

XCTAssertEqual(document.metadata["date"] as? Date, Date(2005, 05, 30, 22, 17, 44))

guard let comments = document.metadata["comments"] as? [[AnyHashable: Any]],
let comment = comments.first else {
XCTFail("Unexpected metadata comment structure")
return
}
XCTAssertEqual(comment["date"] as? Date, Date(2005, 06, 01, 19, 24, 30))
}

}

0 comments on commit 5b2842e

Please sign in to comment.