Skip to content

Commit 38d22e6

Browse files
gershamclaude
andcommitted
Render compose batch pages that have no id as one page each
Pages without an id get the default id page-N from the parser, but the batch's page lookup matched only explicit ids, so every page rendered the whole deck and the contact sheet then failed with "Invalid URL". The lookup now matches a page without an id by its position. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent a96c0e1 commit 38d22e6

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

‎src/compose/batch.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ function pageSource(input: unknown, pageId: string): unknown {
5555
if (!input || typeof input !== "object" || Array.isArray(input)) return input;
5656
const record = input as Record<string, unknown>;
5757
if (!Array.isArray(record.pages)) return input;
58-
const match = record.pages.find((item) => (
59-
item && typeof item === "object" && !Array.isArray(item) && (item as { id?: string }).id === pageId
58+
// A page without an id has the default id the parser gives it: page-N, by position.
59+
const match = record.pages.find((item, index) => (
60+
item && typeof item === "object" && !Array.isArray(item)
61+
&& ((item as { id?: unknown }).id == null ? pageId === `page-${index + 1}` : (item as { id?: string }).id === pageId)
6062
));
6163
if (!match || typeof match !== "object" || Array.isArray(match)) return input;
6264
const { pages: _pages, ...rails } = record;

‎src/compose/compose.test.ts‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,29 @@ test("compose batch contact-sheet and --only use the same engine", async () => {
441441
await rm(dir, { recursive: true, force: true });
442442
});
443443

444+
test("compose batch renders pages without ids one page each, with a contact sheet", async () => {
445+
const dir = await testTemp("compose-batch-noid-");
446+
const input = path.join(dir, "deck.json");
447+
await writeFile(input, JSON.stringify({
448+
width: 320,
449+
height: 180,
450+
background: "#111111",
451+
text: "#eeeeee",
452+
pages: [{ left: { title: "One" } }, { left: { title: "Two" } }],
453+
}));
454+
const output = path.join(dir, "rendered");
455+
const result = await composeBatch(input, output);
456+
assert.equal(result.rendered, 2);
457+
assert.equal(result.failed, 0);
458+
assert.deepEqual(result.pages.map((page) => page.id), ["page-1", "page-2"]);
459+
for (const id of ["page-1", "page-2"]) {
460+
assert.equal(existsSync(path.join(output, id, "manifest.json")), true);
461+
assert.equal(existsSync(path.join(output, id, "page-1")), false, "a page renders itself, not the whole deck");
462+
}
463+
assert.ok((await readFile(result.preview)).subarray(0, 8).equals(PNG_HEADER));
464+
await rm(dir, { recursive: true, force: true });
465+
});
466+
444467
test("compose batch continues after one page image fails", async () => {
445468
const dir = await testTemp("compose-batch-fail-");
446469
const input = path.join(dir, "deck.json");

0 commit comments

Comments
 (0)