def upgrade_to_epub3(self, tdir, opf): self.log.info('Upgrading to EPUB 3...') from calibre.ebooks.epub import simple_container_xml from calibre.ebooks.oeb.polish.cover import fix_conversion_titlepage_links_in_nav try: os.mkdir(os.path.join(tdir, 'META-INF')) except EnvironmentError: pass with open(os.path.join(tdir, 'META-INF', 'container.xml'), 'wb') as f: f.write( simple_container_xml(os.path.basename(opf)).encode('utf-8')) from calibre.ebooks.oeb.polish.container import EpubContainer container = EpubContainer(tdir, self.log) from calibre.ebooks.oeb.polish.upgrade import epub_2_to_3 existing_nav = getattr(self.opts, 'epub3_nav_parsed', None) nav_href = getattr(self.opts, 'epub3_nav_href', None) previous_nav = (nav_href, existing_nav) if existing_nav and nav_href else None epub_2_to_3(container, self.log.info, previous_nav=previous_nav) fix_conversion_titlepage_links_in_nav(container) container.commit() os.remove(f.name) try: os.rmdir(os.path.join(tdir, 'META-INF')) except EnvironmentError: pass
def upgrade_to_epub3(self, tdir, opf): self.log.info('Upgrading to EPUB 3...') from calibre.ebooks.epub import simple_container_xml try: os.mkdir(os.path.join(tdir, 'META-INF')) except EnvironmentError: pass with open(os.path.join(tdir, 'META-INF', 'container.xml'), 'wb') as f: f.write( simple_container_xml(os.path.basename(opf)).encode('utf-8')) from calibre.ebooks.oeb.polish.container import EpubContainer container = EpubContainer(tdir, self.log) from calibre.ebooks.oeb.polish.upgrade import epub_2_to_3 epub_2_to_3(container, self.log.info) container.commit() os.remove(f.name) try: os.rmdir(os.path.join(tdir, 'META-INF')) except EnvironmentError: pass
def upgrade_to_epub3(self, tdir, opf): self.log.info('Upgrading to EPUB 3...') from calibre.ebooks.epub import simple_container_xml from calibre.ebooks.oeb.polish.cover import fix_conversion_titlepage_links_in_nav try: os.mkdir(os.path.join(tdir, 'META-INF')) except EnvironmentError: pass with open(os.path.join(tdir, 'META-INF', 'container.xml'), 'wb') as f: f.write(simple_container_xml(os.path.basename(opf)).encode('utf-8')) from calibre.ebooks.oeb.polish.container import EpubContainer container = EpubContainer(tdir, self.log) from calibre.ebooks.oeb.polish.upgrade import epub_2_to_3 existing_nav = getattr(self.opts, 'epub3_nav_parsed', None) nav_href = getattr(self.opts, 'epub3_nav_href', None) previous_nav = (existing_nav, nav_href) if existing_nav and nav_href else None epub_2_to_3(container, self.log.info, previous_nav=previous_nav) fix_conversion_titlepage_links_in_nav(container) container.commit() os.remove(f.name) try: os.rmdir(os.path.join(tdir, 'META-INF')) except EnvironmentError: pass
def modify_epub(container, filename, metadata=None, opts={}): print(str(opts)) # Search for the ePub cover found_cover = False opf = container.opf cover_meta_node = opf.xpath('./opf:metadata/opf:meta[@name="cover"]', namespaces=OPF_NAMESPACES) if len(cover_meta_node) > 0: cover_meta_node = cover_meta_node[0] cover_id = cover_meta_node.attrib[ "content"] if "content" in cover_meta_node.attrib else None if cover_id is not None: print( "KoboTouchExtended:common:modify_epub:Found cover image ID '{0}'" .format(cover_id)) cover_node = opf.xpath( './opf:manifest/opf:item[@id="{0}"]'.format(cover_id), namespaces=OPF_NAMESPACES) if len(cover_node) > 0: cover_node = cover_node[0] if "properties" not in cover_node.attrib or cover_node.attrib[ "properties"] != "cover-image": print( "KoboTouchExtended:common:modify_epub:Setting cover-image property" ) cover_node.set("properties", "cover-image") container.dirty(container.opf_name) found_cover = True # It's possible that the cover image can't be detected this way. Try looking for the cover image ID in the OPF manifest. if not found_cover: print( "KoboTouchExtended:common:modify_epub:Looking for cover image in OPF manifest" ) node_list = opf.xpath( './opf:manifest/opf:item[(@id="cover" or starts-with(@id, "cover")) and starts-with(@media-type, "image")]', namespaces=OPF_NAMESPACES) if len(node_list) > 0: node = node_list[0] if "properties" not in node.attrib or node.attrib[ "properties"] != 'cover-image': print( "KoboTouchExtended:common:modify_epub:Setting cover-image") node.set("properties", "cover-image") container.dirty(container.opf_name) found_cover = True # Because of the changes made to the markup here, cleanup needs to be done before any other content file processing container.forced_cleanup() if 'clean_markup' in opts and opts['clean_markup'] is True: container.clean_markup() # Hyphenate files? if 'hyphenate' in opts and opts['hyphenate'] is True: if ('replace_lang' not in opts or opts['replace_lang'] is not True) or (metadata is not None and metadata.language == NULL_VALUES['language']): print( "KoboTouchExtended:common:modify_epub:WARNING - Hyphenation is enabled but not overriding content file language. Hyphenation may use the wrong dictionary." ) hyphenation_css = PersistentTemporaryFile(suffix='_hyphenate', prefix='kepub_') hyphenation_css.write(get_resources('css/hyphenation.css')) hyphenation_css.close() css_path = os.path.basename( container.copy_file_to_container(hyphenation_css.name, name='kte-css/hyphenation.css')) container.add_content_file_reference("kte-css/{0}".format(css_path)) # Override content file language if 'replace_lang' in opts and opts['replace_lang'] is True and ( metadata is not None and metadata.language != NULL_VALUES["language"]): # First override for the OPF file lang_node = container.opf_xpath('//opf:metadata/dc:language') if len(lang_node) > 0: print( "KoboTouchExtended:common:modify_epub:Overriding OPF language") lang_node = lang_node[0] lang_node.text = metadata.language else: print("KoboTouchExtended:common:modify_epub:Setting OPF language") metadata_node = container.opf_xpath('//opf:metadata')[0] lang_node = metadata_node.makeelement("{%s}language" % OPF_NAMESPACES['dc']) lang_node.text = metadata.language container.insert_into_xml(metadata_node, lang_node) container.dirty(container.opf_name) # Now override for content files for name in container.get_html_names(): print( "KoboTouchExtended:common:modify_epub:Overriding content file language :: {0}" .format(name)) root = container.parsed(name) root.attrib["{%s}lang" % XML_NAMESPACE] = metadata.language root.attrib["lang"] = metadata.language # Now smarten punctuation if 'smarten_punctuation' in opts and opts['smarten_punctuation'] is True: container.smarten_punctuation() if 'extended_kepub_features' in opts and opts[ 'extended_kepub_features'] is True: if metadata is not None: print( "KoboTouchExtended:common:modify_epub:Adding extended Kobo features to {0} by {1}" .format(metadata.title, ' and '.join(metadata.authors))) # Add the Kobo span tags container.add_kobo_spans() skip_js = False # Check to see if there's already a kobo*.js in the ePub for name in container.name_path_map: if kobo_js_re.match(name): skip_js = True break if not skip_js: if os.path.isfile(reference_kepub): reference_container = EpubContainer(reference_kepub, default_log) for name in reference_container.name_path_map: if kobo_js_re.match(name): jsname = container.copy_file_to_container( os.path.join(reference_container.root, name), name='kobo.js') container.add_content_file_reference(jsname) break os.unlink(filename) container.commit(filename)
def modify_epub( container, # type: EpubContainer filename, # type: str metadata=None, # type: Optional[Metadata] opts={}, # type: Dict[str, Union[str, bool]] ): # type: (...) -> None """Modify the ePub file to make it KePub-compliant.""" _modify_start = time.time() # Search for the ePub cover # TODO: Refactor out cover detection logic so it can be directly used in # metadata/writer.py found_cover = False # type: bool opf = container.opf # type: _Element cover_meta_node_list = opf.xpath( './opf:metadata/opf:meta[@name="cover"]', namespaces=OPF_NAMESPACES) # List[_Element] if len(cover_meta_node_list) > 0: cover_meta_node = cover_meta_node_list[0] # type: _Element cover_id = cover_meta_node.attrib.get("content", None) log.debug("Found meta node with name=cover") if cover_id: log.info("Found cover image ID '{0}'".format(cover_id)) cover_node_list = opf.xpath( './opf:manifest/opf:item[@id="{0}"]'.format(cover_id), namespaces=OPF_NAMESPACES, ) # type: List[_Element] if len(cover_node_list) > 0: cover_node = cover_node_list[0] # type: _Element log.debug("Found an item node with cover ID") if cover_node.attrib.get("properties", "") != "cover-image": log.info("Setting cover-image property") cover_node.set("properties", "cover-image") container.dirty(container.opf_name) else: log.warning("Item node is already set as cover-image") found_cover = True # It's possible that the cover image can't be detected this way. Try # looking for the cover image ID in the OPF manifest. if not found_cover: log.debug("Looking for cover image in OPF manifest") node_list = opf.xpath( "./opf:manifest/opf:item[(translate(@id, " + "'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')" + '="cover" or starts-with(translate(@id, ' + "'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')" + ', "cover")) and starts-with(@media-type, "image")]', namespaces=OPF_NAMESPACES, ) # type: List[_Element] if len(node_list) > 0: log.info("Found {0:d} nodes, assuming the first is the " "right node".format(len(node_list))) node = node_list[0] # type: _Element if node.attrib.get("properties", "") != "cover-image": log.info("Setting cover-image property") node.set("properties", "cover-image") container.dirty(container.opf_name) else: log.warning("Item node is already set as cover-image") found_cover = True # Hyphenate files? if opts.get("no-hyphens", False): nohyphen_css = PersistentTemporaryFile( suffix="_nohyphen", prefix="kepub_") # type: PersistentTemporaryFile nohyphen_css.write(get_resources("css/no-hyphens.css")) # noqa: F821 nohyphen_css.close() css_path = os.path.basename( container.copy_file_to_container( nohyphen_css.name, name="kte-css/no-hyphens.css")) # type: str container.add_content_file_reference("kte-css/{0}".format(css_path)) os.unlink(nohyphen_css.name) elif opts.get("hyphenate", False) and opts.get("hyphen_min_chars", 6) > 0: if metadata and metadata.language == NULL_VALUES["language"]: log.warning( "Hyphenation is enabled but not overriding content file " "language. Hyphenation may use the wrong dictionary.") hyphen_css = PersistentTemporaryFile( suffix="_hyphenate", prefix="kepub_") # type: PersistentTemporaryFile css_template = get_resources( "css/hyphenation.css.tmpl").decode() # noqa: F821 hyphen_limit_lines = opts.get("hyphen_limit_lines", 2) if hyphen_limit_lines == 0: hyphen_limit_lines = "no-limit" hyphen_css.write( css_template.format( hyphen_min_chars=opts.get("hyphen_min_chars"), hyphen_min_chars_before=opts.get("hyphen_min_chars_before", 3), hyphen_min_chars_after=opts.get("hyphen_min_chars_after", 3), hyphen_limit_lines=hyphen_limit_lines, ).encode()) hyphen_css.close() css_path = os.path.basename( container.copy_file_to_container( hyphen_css.name, name="kte-css/hyphenation.css")) # type: str container.add_content_file_reference("kte-css/{0}".format(css_path)) os.unlink(hyphen_css.name) # Now smarten punctuation if opts.get("smarten_punctuation", False): container.smarten_punctuation() if opts.get("extended_kepub_features", True): if metadata is not None: log.info("Adding extended Kobo features to {0} by {1}".format( metadata.title, " and ".join(metadata.authors))) # Add the Kobo span and div tags container.convert() # Check to see if there's already a kobo*.js in the ePub skip_js = False # type: str for name in container.name_path_map: if KOBO_JS_RE.match(name): skip_js = True break if not skip_js: if os.path.isfile(REFERENCE_KEPUB): reference_container = EpubContainer(REFERENCE_KEPUB, log) for name in reference_container.name_path_map: if KOBO_JS_RE.match(name): jsname = container.copy_file_to_container( os.path.join(reference_container.root, name), name="kobo.js") container.add_content_file_reference(jsname) break # Add the Kobo style hacks stylehacks_css = PersistentTemporaryFile(suffix="_stylehacks", prefix="kepub_") stylehacks_css.write( get_resources("css/style-hacks.css")) # noqa: F821 stylehacks_css.close() css_path = os.path.basename( container.copy_file_to_container(stylehacks_css.name, name="kte-css/stylehacks.css")) container.add_content_file_reference("kte-css/{0}".format(css_path)) os.unlink(filename) container.commit(filename) _modify_time = time.time() - _modify_start log.info("modify_epub took {0:f} seconds".format(_modify_time))