From c64588bee4e007ae36fb535d636a03696f1351bd Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 22 Feb 2025 09:51:39 +0530 Subject: [PATCH] kepubify: Generate a default cover image if input document has no cover image --- src/calibre/ebooks/oeb/polish/kepubify.py | 21 ++++++++++++++----- .../ebooks/oeb/polish/tests/kepubify.py | 17 +++++++++++---- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/calibre/ebooks/oeb/polish/kepubify.py b/src/calibre/ebooks/oeb/polish/kepubify.py index c56c4fbf75..8b9d1636d3 100644 --- a/src/calibre/ebooks/oeb/polish/kepubify.py +++ b/src/calibre/ebooks/oeb/polish/kepubify.py @@ -39,6 +39,7 @@ OUTER_DIV_ID = 'book-columns' INNER_DIV_ID = 'book-inner' KOBO_SPAN_CLASS = 'koboSpan' DUMMY_TITLE_PAGE_NAME = 'kobo-title-page-generated-by-calibre' +DUMMY_COVER_IMAGE_NAME = 'kobo-cover-image-generated-by-calibre' SKIPPED_TAGS = frozenset(( '', 'script', 'style', 'atom', 'pre', 'audio', 'video', 'svg', 'math' )) @@ -294,7 +295,7 @@ def is_probably_a_title_page(root): return (num_images + num_svgs == 1 and textlen <= 10) or (textlen <= 50 and (num_images + num_svgs) < 1) -def add_dummy_title_page(container: Container, cover_image_name: str) -> None: +def add_dummy_title_page(container: Container, cover_image_name: str, mi) -> None: html = f'''\ @@ -320,7 +321,6 @@ def add_dummy_title_page(container: Container, cover_image_name: str) -> None: cover_href = container.name_to_href(cover_image_name, titlepage_name) html = html.replace('__CONTENT__', f'cover') else: - mi = container.mi aus = authors_to_string(mi.authors) html = html.replace('__CONTENT__', f'''

{mi.title}

@@ -340,6 +340,12 @@ def remove_dummy_title_page(container: Container) -> None: break +def remove_dummy_cover_image(container: Container) -> None: + for name in tuple(container.mime_map): + if DUMMY_COVER_IMAGE_NAME in name: + container.remove_item(name) + + def first_spine_item_is_probably_title_page(container: Container) -> bool: for name, is_linear in container.spine_names: fname = name.split('/')[-1] @@ -371,12 +377,17 @@ def process_path(path: str, metadata_lang: str, opts: Options, media_type: str) def kepubify_container(container: Container, opts: Options, max_workers: int = 0) -> None: remove_dummy_title_page(container) + remove_dummy_cover_image(container) metadata_lang = container.mi.language cover_image_name = find_cover_image(container) or find_cover_image3(container) - if cover_image_name: - container.apply_unique_properties(cover_image_name, 'cover-image') + mi = container.mi + if not cover_image_name: + from calibre.ebooks.covers import generate_cover + cdata = generate_cover(mi) + cover_image_name = container.add_file(f'{DUMMY_COVER_IMAGE_NAME}.jpeg', cdata, modify_name_if_needed=True) + container.apply_unique_properties(cover_image_name, 'cover-image') if not find_cover_page(container) and not first_spine_item_is_probably_title_page(container): - add_dummy_title_page(container, cover_image_name) + add_dummy_title_page(container, cover_image_name, mi) names_that_need_work = tuple(name for name, mt in container.mime_map.items() if mt in OEB_DOCS or mt in OEB_STYLES) num_workers = calculate_number_of_workers(names_that_need_work, container, max_workers) paths = tuple(map(container.name_to_abspath, names_that_need_work)) diff --git a/src/calibre/ebooks/oeb/polish/tests/kepubify.py b/src/calibre/ebooks/oeb/polish/tests/kepubify.py index 89dfbe4fe6..f56f87be6c 100644 --- a/src/calibre/ebooks/oeb/polish/tests/kepubify.py +++ b/src/calibre/ebooks/oeb/polish/tests/kepubify.py @@ -3,7 +3,15 @@ from calibre.ebooks.oeb.polish.container import get_container -from calibre.ebooks.oeb.polish.kepubify import DUMMY_TITLE_PAGE_NAME, Options, kepubify_html_data, kepubify_path, remove_kobo_markup_from_html, serialize_html +from calibre.ebooks.oeb.polish.kepubify import ( + DUMMY_COVER_IMAGE_NAME, + DUMMY_TITLE_PAGE_NAME, + Options, + kepubify_html_data, + kepubify_path, + remove_kobo_markup_from_html, + serialize_html, +) from calibre.ebooks.oeb.polish.parsing import parse from calibre.ebooks.oeb.polish.tests.base import BaseTest, get_book_for_kepubify @@ -24,10 +32,11 @@ class KepubifyTests(BaseTest): ps = c.open('page_styles.css', 'r').read() for q in ('@page', 'widows', 'orphans'): self.assertNotIn(q, ps) - cimage = ('cover.png',) if has_cover else () + cimage = ('cover.png',) if has_cover else (f'{DUMMY_COVER_IMAGE_NAME}.jpeg',) self.assertEqual(cimage, tuple(c.manifest_items_with_property('cover-image'))) - b() - b(has_cover=False) + for has_cover in (True, False): + for epub_version in '23': + b(has_cover, epub_version) def test_kepubify_html(self): prefix = '''