crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

commit e5bdc671f85244ebe9094c5edf52765573e53f75
parent 28968fea513baec6bad506f7101e36a00a601ee6
Author: Michael Camilleri <[email protected]>
Date:   Fri, 26 Jun 2026 09:39:41 +0900

Preserve puzzle titles from external providers

This commit keeps the title supplied by an external puzzle's JSON when
one is present. Untitled puzzles still derive the existing '<Weekday>
Crossword'-style title from their publication date, and the converter
coverage now exercises both paths through the same fixture.

Co-Authored-By: Codex GPT 5.5 <[email protected]>

Diffstat:
MCrossmate/Services/NYTToXDConverter.swift | 9++++++++-
MTests/Unit/NYTToXDConverterTests.swift | 20+++++++++++++++++++-
2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/Crossmate/Services/NYTToXDConverter.swift b/Crossmate/Services/NYTToXDConverter.swift @@ -52,6 +52,13 @@ enum NYTToXDConverter { // -- Metadata -- let publicationDate = root["publicationDate"] as? String ?? "" + let nytTitle = (root["title"] as? String)? + .trimmingCharacters(in: .whitespacesAndNewlines) + let title = if let nytTitle, !nytTitle.isEmpty { + nytTitle + } else { + title(forPublicationDate: publicationDate) + } let constructors = root["constructors"] as? [String] ?? [] let editor = root["editor"] as? String let copyright = root["copyright"] as? String @@ -263,7 +270,7 @@ enum NYTToXDConverter { // Metadata section var metadata: [String] = [] - metadata.append("Title: \(title(forPublicationDate: publicationDate))") + metadata.append("Title: \(title)") metadata.append("CmVer: \(XD.currentCmVersion)") metadata.append("Publisher: New York Times") if !publicationDate.isEmpty { diff --git a/Tests/Unit/NYTToXDConverterTests.swift b/Tests/Unit/NYTToXDConverterTests.swift @@ -15,6 +15,7 @@ struct NYTToXDConverterTests { /// entirely. private func puzzleJSON( relatives: [[Int]?], + title: String? = nil, formattedClueIndices: Set<Int> = [], formattedOverrides: [Int: String] = [:], clueTexts: [Int: String] = [:], @@ -62,7 +63,7 @@ struct NYTToXDConverterTests { } return cell } - let root: [String: Any] = [ + var root: [String: Any] = [ "publicationDate": "2025-01-01", "constructors": ["Tester"], "body": [[ @@ -71,6 +72,9 @@ struct NYTToXDConverterTests { "clues": clueDicts ]] ] + if let title { + root["title"] = title + } return try JSONSerialization.data(withJSONObject: root) } @@ -134,6 +138,20 @@ struct NYTToXDConverterTests { #expect(puzzle.publisher == "New York Times") } + @Test("NYT metadata preserves supplied puzzle title") + func nytMetadataPreservesSuppliedPuzzleTitle() throws { + let data = try puzzleJSON( + relatives: [nil, nil, nil, nil, nil, nil], + title: "Big Draw" + ) + let xd = try NYTToXDConverter.convert(jsonData: data) + #expect(header("Title", in: xd) == "Big Draw") + + let parsed = try XD.parse(xd) + let puzzle = Puzzle(xd: parsed) + #expect(puzzle.title == "Big Draw") + } + @Test("NYT moreAnswers.valid emits XD Accept metadata and round-trips") func moreAnswersEmitAcceptMetadata() throws { let data = try puzzleJSON(