Skip to content

Commit dcf13f0

Browse files
committed
Update resolveFullClueAnswer interface (BREAKING CHANGE)
Also: improve tests, improve type checking in test files
1 parent 73942ea commit dcf13f0

File tree

6 files changed

+34
-46
lines changed

6 files changed

+34
-46
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4565,7 +4565,7 @@ The main `xd-crossword-tools` package provides comprehensive functionality for f
45654565
| `xdDiff` | Creates semantic diff between two XD files | `beforeXD: string`, `afterXD: string` | `DiffResults` | Line-by-line differences with metadata awareness |
45664566
| `runLinterForClue` | Runs linting checks on individual clues | `clue: Clue`, `ordinal: "across" \| "down"` | `Report[]` | Checks for common crossword construction issues |
45674567
| `validateClueAnswersMatchGrid` | Validates clue answers match grid tiles | `json: CrosswordJSON` | `Report[]` | Checks consistency between answers and grid |
4568-
| `resolveFullClueAnswer` | Resolves clue answer with rebus and splits | `rebusMap: Rebuses`, `clue: Clue`, `splitChar: string` | `string` | Handles rebus substitution and split characters |
4568+
| `resolveFullClueAnswer` | Resolves clue answer with rebus and splits | `clue: Clue`, `splitChar: string` | `string` | Handles rebus substitution and split characters |
45694569

45704570
### xd-crossword-tools-parser Utility Functions
45714571

packages/xd-crossword-tools/src/JSONtoXD.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Clue, CrosswordJSON, Tile } from "xd-crossword-tools-parser"
22

3-
export function resolveFullClueAnswer(rebusMap: CrosswordJSON["rebuses"], clue: Clue, splitChar: string) {
3+
export function resolveFullClueAnswer(clue: Clue, splitChar: string) {
44
// For simple cases (no rebus, no splits, no internal splits), just return the answer directly
55
const hasRebus = clue.tiles.some((t) => t.type === "rebus")
66
const hasSplits = clue.splits && clue.splits.length > 0
@@ -112,7 +112,7 @@ export const JSONToXD = (json: CrosswordJSON): string => {
112112
const getCluesXD = (clues: Clue[], direction: "A" | "D") => {
113113
return clues
114114
.map((clue) => {
115-
const final = resolveFullClueAnswer(json.rebuses, clue, splitChar)
115+
const final = resolveFullClueAnswer(clue, splitChar)
116116
let line = `${direction}${clue.number}. ${clue.body} ~ ${final}`
117117
if (clue.metadata) {
118118
let printed = false

packages/xd-crossword-tools/tests/JSONtoXD.test.ts

Lines changed: 18 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ describe("resolveFullClueAnswer", () => {
1919
],
2020
metadata: undefined,
2121
} as Clue
22-
expect(resolveFullClueAnswer(rebuses, clue, "")).toEqual(clue.answer)
22+
expect(resolveFullClueAnswer(clue, "")).toEqual(clue.answer)
2323
})
2424

2525
it("Returns answer for rebus clue", () => {
@@ -35,7 +35,7 @@ describe("resolveFullClueAnswer", () => {
3535
],
3636
metadata: undefined,
3737
} as Clue
38-
expect(resolveFullClueAnswer(rebuses, clue, "")).toEqual(clue.answer)
38+
expect(resolveFullClueAnswer(clue, "")).toEqual(clue.answer)
3939
})
4040

4141
it("Returns answer for clue with pipes", () => {
@@ -54,7 +54,7 @@ describe("resolveFullClueAnswer", () => {
5454
metadata: undefined,
5555
splits: [1],
5656
} as Clue
57-
expect(resolveFullClueAnswer(rebuses, clue, "|")).toEqual("OK|GO")
57+
expect(resolveFullClueAnswer(clue, "|")).toEqual("OK|GO")
5858
})
5959

6060
it("Returns answer for rebus clue with pipes", () => {
@@ -78,7 +78,7 @@ describe("resolveFullClueAnswer", () => {
7878
metadata: undefined,
7979
splits: [5, 6, 7],
8080
} as Clue
81-
expect(resolveFullClueAnswer(rebuses, clue, "|")).toEqual("TWITCH|DOT|T|V")
81+
expect(resolveFullClueAnswer(clue, "|")).toEqual("TWITCH|DOT|T|V")
8282
})
8383

8484
it("Demonstrates correct pipe position handling with rebus squares", () => {
@@ -99,17 +99,19 @@ describe("resolveFullClueAnswer", () => {
9999
{ type: "letter", letter: "H" },
100100
],
101101
metadata: undefined,
102+
display: [["text", "Not too much!"]],
103+
direction: "across" as const,
102104
// Internal splits within the rebus at tile position 3
103105
rebusInternalSplits: { 3: [0, 1] }, // T|A|SK
104106
} as Clue
105107

106108
// Should produce JUST|A|SKOSH (perfect internal rebus splits)
107-
expect(resolveFullClueAnswer(rebuses, clue, "|")).toEqual("JUST|A|SKOSH")
109+
expect(resolveFullClueAnswer(clue, "|")).toEqual("JUST|A|SKOSH")
108110
})
109111

110112
it("Returns answer for clue with Schrödinger square", () => {
111113
const rebuses = {}
112-
const schrodingerTile: SchrodingerTile = { type: "schrodinger", validLetters: ["O", "A"] }
114+
const schrodingerTile: SchrodingerTile = { type: "schrodinger", validLetters: ["O", "A"], validRebuses: [] }
113115
const clue = {
114116
body: "Sugar ____",
115117
answer: "CONE",
@@ -120,7 +122,7 @@ describe("resolveFullClueAnswer", () => {
120122
display: [["text", "Sugar ____"]],
121123
metadata: { alt: "CANE" },
122124
} as Clue
123-
expect(resolveFullClueAnswer(rebuses, clue, "")).toEqual("CONE")
125+
expect(resolveFullClueAnswer(clue, "")).toEqual("CONE")
124126
})
125127
})
126128

@@ -404,6 +406,7 @@ D4. Former intimates ~ EXES`
404406
title: Pipe Bug Test
405407
author: Test
406408
date: 2025-01-01
409+
editor: Penelope Rudow
407410
rebus: ❶=TASK
408411
splitcharacter: |
409412
@@ -413,32 +416,13 @@ JUS❶OSH
413416
414417
## Clues
415418
416-
A1. Not too much! ~ JUST|A|SKOSH`
417-
418-
const expectedOutput = `## Metadata
419-
420-
title: Pipe Bug Test
421-
author: Test
422-
date: 2025-01-01
423-
editor: Not set
424-
rebus: ❶=TASK
425-
splitcharacter: |
426-
427-
## Grid
428-
429-
JUS❶OSH
430-
431-
## Clues
432-
433-
A1. Not too much! ~ JUST|A|SKOSH
434-
435-
`
419+
A1. Not too much! ~ JUST|A|SKOSH\n\n`
436420

437421
const json = xdToJSON(puzzle)
438422
const newXD = JSONToXD(json)
439423

440424
// Perfect round-trip: internal rebus splits are preserved
441-
expect(newXD).toEqual(expectedOutput)
425+
expect(newXD).toEqual(puzzle)
442426
})
443427

444428
it("Handles mixed regular and internal rebus splits", () => {
@@ -466,14 +450,13 @@ A1. Not too much! ~ JUST|A|SKOSH
466450
splits: [5, 6, 7], // Split after TWITCH, after rebus, and after T
467451
rebusInternalSplits: { 6: [0] }, // D|OT within rebus
468452
} as Clue
469-
453+
470454
// Should produce TWITCH|D|OT|T|V
471-
expect(resolveFullClueAnswer(rebuses, clue, "|")).toEqual("TWITCH|D|OT|T|V")
455+
expect(resolveFullClueAnswer(clue, "|")).toEqual("TWITCH|D|OT|T|V")
472456
})
473457

474458
it("Handles multiple internal splits in same rebus", () => {
475459
// Test case with multiple internal splits in the same rebus
476-
const rebuses = { "❶": "TASK" }
477460
const clue = {
478461
body: "All internal splits",
479462
answer: "JUSTASKOSH",
@@ -491,10 +474,10 @@ A1. Not too much! ~ JUST|A|SKOSH
491474
metadata: undefined,
492475
display: [["text", "All internal splits"]],
493476
direction: "across" as const,
494-
rebusInternalSplits: { 3: [0, 1, 2] }, // T|A|S|K
477+
rebusInternalSplits: { 3: [0, 1] },
495478
} as Clue
496-
497-
// Should produce JUST|A|S|KOSH
498-
expect(resolveFullClueAnswer(rebuses, clue, "|")).toEqual("JUST|A|S|KOSH")
479+
480+
// Should produce JUST|A|SKOSH
481+
expect(resolveFullClueAnswer(clue, "|")).toEqual("JUST|A|SKOSH")
499482
})
500483
})

packages/xd-crossword-tools/tests/amuseJSONToXD.test.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,16 @@ describeConditional("amuseJSONToXD", () => {
2424
expect(result.tiles[0][0].type).toBe("schrodinger")
2525

2626
expect(result.tiles[0][0]).toHaveProperty("validLetters")
27-
expect(result.tiles[0][0].validLetters).toEqual(["H", "J"])
27+
if (result.tiles[0][0].type === "schrodinger") {
28+
expect(result.tiles[0][0].validLetters).toEqual(["H", "J"])
29+
}
2830

2931
expect(result.clues.down[0]).toHaveProperty("answer")
3032
expect(result.clues.down[0].answer).toEqual("HELLO")
3133

3234
expect(result.clues.down[0]).toHaveProperty("metadata")
3335
expect(result.clues.down[0].metadata).toHaveProperty("alt")
34-
expect(result.clues.down[0].metadata.alt).toEqual("JELLO")
36+
expect(result.clues.down[0].metadata?.alt).toEqual("JELLO")
3537
})
3638

3739
it("handles rebus clues correctly", () => {
@@ -41,10 +43,14 @@ describeConditional("amuseJSONToXD", () => {
4143
expect(result.tiles[3][0].type).toBe("rebus")
4244

4345
expect(result.tiles[3][0]).toHaveProperty("word")
44-
expect(result.tiles[3][0].word).toBe("LD")
46+
if (result.tiles[3][0].type === "rebus") {
47+
expect(result.tiles[3][0].word).toBe("LD")
48+
}
4549

4650
expect(result.tiles[3][0]).toHaveProperty("symbol")
47-
expect(result.tiles[3][0].symbol).toBe("ⓐ")
51+
if (result.tiles[3][0].type === "rebus") {
52+
expect(result.tiles[3][0].symbol).toBe("ⓐ")
53+
}
4854

4955
expect(result.meta).toHaveProperty("rebus")
5056
expect(result.meta.rebus).toContain("ⓐ=LD")

packages/xd-crossword-tools/tests/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Careful of this resolving to the .js version!
22
import { puzToXD } from "../src/puzToXD"
3-
import { uclickXMLToXd } from "../src/uclickToXD"
3+
import { uclickXMLToXD } from "../src/uclickToXD"
44

55
import { xdToJSON } from "xd-crossword-tools-parser"
66

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
{
22
"extends": "../../tsconfig.base.json",
33
"compilerOptions": {
4-
"outDir": "./dist",
5-
"rootDir": "./src"
4+
"outDir": "./dist"
65
},
7-
"include": ["src/**/*"],
6+
"include": ["src/**/*", "tests/**/*"],
87
"exclude": ["node_modules", "dist"],
98
"types": ["vitest/globals"]
109
}

0 commit comments

Comments
 (0)