Skip to content

Save the best possible img from custom layout to standard (BL-16086)#7806

Open
JohnThomson wants to merge 2 commits intomasterfrom
saveBestCustomImgToStandard
Open

Save the best possible img from custom layout to standard (BL-16086)#7806
JohnThomson wants to merge 2 commits intomasterfrom
saveBestCustomImgToStandard

Conversation

@JohnThomson
Copy link
Copy Markdown
Contributor

@JohnThomson JohnThomson commented Apr 2, 2026


Open with Devin

This change is Reviewable

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment on lines +5231 to +5236
coverImgElt = GetCoverImageElt(outsideFrontCover);
if (coverImgElt == null)
return null;

return GetImagePath(coverImgElt);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Behavioral change: candidate selection no longer checks file existence on disk

The old GetCoverImagePathAndElt used GetImagePath() for candidate selection, which resolved paths against StoragePageFolder and checked RobustFile.Exists(). The new GetCoverImageElt uses GetImageSourceForCoverSelection() (Book.cs:5304-5311) which only reads DOM attributes. This means if the designated cover image has a valid-looking src but the file doesn't exist on disk, GetCoverImageElt will select that element, and then GetImagePath at Book.cs:5235 returns null — whereas the old code would have skipped it and tried the next candidate in the foreach loop. This affects all callers: CollectionApi.cs:710, BookMetadataApi.cs:56, BookCompressor.cs:48, PublishApi.cs:289, BookThumbNailer.cs:237, and Book.cs:5360. The scenario (designated image source is non-empty/non-placeholder but file missing, AND another valid candidate exists on the page) is very unlikely in practice, and DOM-based selection is more appropriate for the new BookData use case. Still, worth noting as a semantic change.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate

cubic-dev-ai[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor Author

@JohnThomson JohnThomson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JohnThomson made 2 comments and resolved 1 discussion.
Reviewable status: 0 of 3 files reviewed, 1 unresolved discussion.

Comment on lines +5231 to +5236
coverImgElt = GetCoverImageElt(outsideFrontCover);
if (coverImgElt == null)
return null;

return GetImagePath(coverImgElt);
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicate

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 5 additional findings in Devin Review.

Open in Devin Review

Comment on lines +5231 to +5235
coverImgElt = GetCoverImageElt(outsideFrontCover, StoragePageFolder);
if (coverImgElt == null)
return null;

return GetImagePath(coverImgElt);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 GetCoverImagePathAndElt sets coverImgElt to non-null out value even when return path is null

The refactored GetCoverImagePathAndElt sets the coverImgElt out parameter from GetCoverImageElt before calling GetImagePath. When GetCoverImageElt returns bestNonExistingNonPlaceholderElt (an element whose image file doesn't exist on disk), GetImagePath returns null but coverImgElt remains set to that element. This breaks the invariant from the old code where coverImgElt and the return path were always both null or both non-null.

This also changes observable behavior: when the designated cover image references a non-existent file and a placeholder element is also present on the cover page, the old code would return the placeholder path (via bestPlaceholderPath), but the new code returns null (because bestNonExistingNonPlaceholderElt ?? bestPlaceholderElt prefers the non-existing element, and then GetImagePath fails to find the file). Callers like BookThumbNailer.cs:237-252 that specifically handle placeholder paths to generate a thumbnail from a substitute placeholder file will now get null and skip thumbnail generation entirely.

Prompt for agents
In GetCoverImagePathAndElt (Book.cs around line 5231), the coverImgElt out parameter is set from GetCoverImageElt before GetImagePath is called. If GetImagePath returns null (file doesn't exist on disk), coverImgElt is still non-null, breaking the invariant that both are null or both non-null.

Additionally, GetCoverImageElt returns bestNonExistingNonPlaceholderElt in preference to bestPlaceholderElt at line 5319. When called from GetCoverImagePathAndElt with a bookFolderPath, this means a non-existing image element is preferred over a placeholder element. Then GetImagePath returns null for the non-existing file, losing the placeholder path that the old code would have returned.

To fix: either (a) check the return of GetImagePath and reset coverImgElt to null if the path is null, or (b) adjust the fallback in GetCoverImageElt so that when bookFolderPath is provided, bestPlaceholderElt is preferred over bestNonExistingNonPlaceholderElt (or at least equal). The bestNonExistingNonPlaceholderElt preference makes sense for the AddFallbackCoverImageFromCustomOutsideFrontCover use case (where bookFolderPath is null), but not for GetCoverImagePathAndElt.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant