def workaround_nook_cover_bug(self, root): # {{{ cov = root.xpath('//*[local-name() = "meta" and @name="cover" and' ' @content != "cover"]') def manifest_items_with_id(id_): return root.xpath( '//*[local-name() = "manifest"]/*[local-name() = "item" ' ' and @id="%s"]' % id_) if len(cov) == 1: cov = cov[0] covid = cov.get('content', '') if covid: manifest_item = manifest_items_with_id(covid) if len(manifest_item) == 1 and \ manifest_item[0].get('media-type', '').startswith('image/'): self.log.warn( 'The cover image has an id != "cover". Renaming' ' to work around bug in Nook Color') from calibre.ebooks.oeb.base import uuid_id newid = uuid_id() for item in manifest_items_with_id('cover'): item.set('id', newid) for x in root.xpath('//*[@idref="cover"]'): x.set('idref', newid) manifest_item = manifest_item[0] manifest_item.set('id', 'cover') cov.set('content', 'cover')
def workaround_nook_cover_bug(self, root): # {{{ cov = root.xpath('//*[local-name() = "meta" and @name="cover" and' ' @content != "cover"]') def manifest_items_with_id(id_): return root.xpath('//*[local-name() = "manifest"]/*[local-name() = "item" ' ' and @id="%s"]'%id_) if len(cov) == 1: cov = cov[0] covid = cov.get('content', '') if covid: manifest_item = manifest_items_with_id(covid) if len(manifest_item) == 1 and \ manifest_item[0].get('media-type', '').startswith('image/'): self.log.warn('The cover image has an id != "cover". Renaming' ' to work around bug in Nook Color') from calibre.ebooks.oeb.base import uuid_id newid = uuid_id() for item in manifest_items_with_id('cover'): item.set('id', newid) for x in root.xpath('//*[@idref="cover"]'): x.set('idref', newid) manifest_item = manifest_item[0] manifest_item.set('id', 'cover') cov.set('content', 'cover')
def commit_ncx_toc(container, toc, lang=None, uid=None): tocname = find_existing_ncx_toc(container) if tocname is None: item = container.generate_item('toc.ncx', id_prefix='toc') tocname = container.href_to_name(item.get('href'), base=container.opf_name) ncx_id = item.get('id') [s.set('toc', ncx_id) for s in container.opf_xpath('//opf:spine')] if not lang: lang = get_lang() for l in container.opf_xpath('//dc:language'): l = canonicalize_lang(xml2text(l).strip()) if l: lang = l lang = lang_as_iso639_1(l) or l break lang = lang_as_iso639_1(lang) or lang if not uid: uid = uuid_id() eid = container.opf.get('unique-identifier', None) if eid: m = container.opf_xpath('//*[@id="%s"]'%eid) if m: uid = xml2text(m[0]) title = _('Table of Contents') m = container.opf_xpath('//dc:title') if m: x = xml2text(m[0]).strip() title = x or title to_href = partial(container.name_to_href, base=tocname) root = create_ncx(toc, to_href, title, lang, uid) container.replace(tocname, root) container.pretty_print.add(tocname)
def commit_toc(container, toc, lang=None, uid=None): tocname = find_existing_toc(container) if tocname is None: item = container.generate_item("toc.ncx", id_prefix="toc") tocname = container.href_to_name(item.get("href"), base=container.opf_name) if not lang: lang = get_lang() for l in container.opf_xpath("//dc:language"): l = canonicalize_lang(xml2text(l).strip()) if l: lang = l lang = lang_as_iso639_1(l) or l break lang = lang_as_iso639_1(lang) or lang if not uid: uid = uuid_id() eid = container.opf.get("unique-identifier", None) if eid: m = container.opf_xpath('//*[@id="%s"]' % eid) if m: uid = xml2text(m[0]) title = _("Table of Contents") m = container.opf_xpath("//dc:title") if m: x = xml2text(m[0]).strip() title = x or title to_href = partial(container.name_to_href, base=tocname) root = create_ncx(toc, to_href, title, lang, uid) container.replace(tocname, root) container.pretty_print.add(tocname)
def commit_toc(container, toc, lang=None, uid=None): tocname = find_existing_toc(container) if tocname is None: item = container.generate_item('toc.ncx', id_prefix='toc') tocname = container.href_to_name(item.get('href'), base=container.opf_name) if not lang: lang = get_lang() for l in container.opf_xpath('//dc:language'): l = canonicalize_lang(xml2text(l).strip()) if l: lang = l lang = lang_as_iso639_1(l) or l break lang = lang_as_iso639_1(lang) or lang if not uid: uid = uuid_id() eid = container.opf.get('unique-identifier', None) if eid: m = container.opf_xpath('//*[@id="%s"]' % eid) if m: uid = xml2text(m[0]) title = _('Table of Contents') m = container.opf_xpath('//dc:title') if m: x = xml2text(m[0]).strip() title = x or title to_href = partial(container.name_to_href, base=tocname) root = create_ncx(toc, to_href, title, lang, uid) container.replace(tocname, root) container.pretty_print.add(tocname)
def create_epub_cover(container, cover_path): from calibre.ebooks.conversion.config import load_defaults from calibre.ebooks.oeb.transforms.cover import CoverManager ext = cover_path.rpartition('.')[-1].lower() raster_cover_item = container.generate_item('cover.'+ext, id_prefix='cover') raster_cover = container.href_to_name(raster_cover_item.get('href'), container.opf_name) with open(cover_path, 'rb') as src, container.open(raster_cover, 'wb') as dest: shutil.copyfileobj(src, dest) opts = load_defaults('epub_output') keep_aspect = opts.get('preserve_cover_aspect_ratio', False) no_svg = opts.get('no_svg_cover', False) if no_svg: style = 'style="height: 100%%"' templ = CoverManager.NONSVG_TEMPLATE.replace('__style__', style) else: width, height = 600, 800 try: width, height = identify(cover_path)[:2] except: container.log.exception("Failed to get width and height of cover") ar = 'xMidYMid meet' if keep_aspect else 'none' templ = CoverManager.SVG_TEMPLATE.replace('__ar__', ar) templ = templ.replace('__viewbox__', '0 0 %d %d'%(width, height)) templ = templ.replace('__width__', str(width)) templ = templ.replace('__height__', str(height)) titlepage_item = container.generate_item('titlepage.xhtml', id_prefix='titlepage') titlepage = container.href_to_name(titlepage_item.get('href'), container.opf_name) raw = templ%container.name_to_href(raster_cover).encode('utf-8') with container.open(titlepage, 'wb') as f: f.write(raw) # We have to make sure the raster cover item has id="cover" for the moron # that wrote the Nook firmware if raster_cover_item.get('id') != 'cover': from calibre.ebooks.oeb.base import uuid_id newid = uuid_id() for item in container.opf_xpath('//*[@id="cover"]'): item.set('id', newid) for item in container.opf_xpath('//*[@idref="cover"]'): item.set('idref', newid) raster_cover_item.set('id', 'cover') spine = container.opf_xpath('//opf:spine')[0] ref = spine.makeelement(OPF('itemref'), idref=titlepage_item.get('id')) container.insert_into_xml(spine, ref, index=0) guide = container.opf_get_or_create('guide') container.insert_into_xml(guide, guide.makeelement( OPF('reference'), type='cover', title=_('Cover'), href=container.name_to_href(titlepage, base=container.opf_name))) metadata = container.opf_get_or_create('metadata') meta = metadata.makeelement(OPF('meta'), name='cover') meta.set('content', raster_cover_item.get('id')) container.insert_into_xml(metadata, meta) return raster_cover, titlepage
def ensure_id(elem): if elem.tag == XHTML("a"): anchor = elem.get("name", None) if anchor: return False, anchor elem_id = elem.get("id", None) if elem_id: return False, elem_id elem.set("id", uuid_id()) return True, elem.get("id")
def ensure_id(elem): if elem.tag == XHTML('a'): anchor = elem.get('name', None) if anchor: return False, anchor elem_id = elem.get('id', None) if elem_id: return False, elem_id elem.set('id', uuid_id()) return True, elem.get('id')
def add_id(container, name, loc): root = container.parsed(name) body = root.xpath('//*[local-name()="body"]')[0] locs = deque(loc) node = body while locs: children = tuple(node.iterchildren(etree.Element)) node = children[locs[0]] locs.popleft() node.set('id', node.get('id', uuid_id())) container.commit_item(name, keep_parsed=True) return node.get('id')
def __call__(self, container): from calibre.ebooks.oeb.base import uuid_id from calibre.ebooks.oeb.polish.replace import replace_ids newid = uuid_id() changed = False elems = (e for e in container.parsed(self.name).xpath('//*[@id]') if e.get('id') == self.invalid_id) for e in elems: e.set('id', newid) changed = True container.dirty(self.name) if changed: replace_ids(container, {self.name:{self.invalid_id:newid}}) return changed
def __call__(self, container): from calibre.ebooks.oeb.base import uuid_id opf = container.opf uid = uuid_id() opf.set('unique-identifier', uid) m = container.opf_xpath('/opf:package/opf:metadata') if not m: m = [container.opf.makeelement(OPF('metadata'), nsmap={'dc':DC11_NS})] container.insert_into_xml(container.opf, m[0], 0) m = m[0] dc = m.makeelement(DC('identifier'), id=uid, nsmap={'opf':OPF2_NS}) dc.set(OPF('scheme'), 'uuid') dc.text = uid container.insert_into_xml(m, dc) container.dirty(container.opf_name) return True
def process_node(xml_parent, toc_parent): for child in toc_parent: play_order['c'] += 1 point = etree.SubElement(xml_parent, NCX('navPoint'), id=uuid_id(), playOrder=str(play_order['c'])) label = etree.SubElement(point, NCX('navLabel')) title = child.title if title: title = spat.sub(' ', title) etree.SubElement(label, NCX('text')).text = title if child.dest: href = to_href(child.dest) if child.frag: href += '#'+child.frag etree.SubElement(point, NCX('content'), src=href) process_node(point, child)
def add_id(container, name, loc, totals=None): root = container.parsed(name) try: node = node_from_loc(root, loc, totals=totals) except MalformedMarkup: # The webkit HTML parser and the container parser have yielded # different node counts, this can happen if the file is valid XML # but contains constructs like nested <p> tags. So force parse it # with the HTML 5 parser and try again. raw = container.raw_data(name) root = container.parse_xhtml(raw, fname=name, force_html5_parse=True) try: node = node_from_loc(root, loc, totals=totals) except MalformedMarkup: raise MalformedMarkup(_('The file %s has malformed markup. Try running the Fix HTML tool' ' before editing.') % name) container.replace(name, root) node.set('id', node.get('id', uuid_id())) container.commit_item(name, keep_parsed=True) return node.get('id')
def create_epub_cover(container, cover_path, existing_image, options=None): from calibre.ebooks.conversion.config import load_defaults from calibre.ebooks.oeb.transforms.cover import CoverManager try: ext = cover_path.rpartition(".")[-1].lower() except Exception: ext = "jpeg" cname, tname = "cover." + ext, "titlepage.xhtml" recommended_folders = get_recommended_folders(container, (cname, tname)) if existing_image: raster_cover = existing_image manifest_id = {v: k for k, v in container.manifest_id_map.iteritems()}[existing_image] raster_cover_item = container.opf_xpath('//opf:manifest/*[@id="%s"]' % manifest_id)[0] else: folder = recommended_folders[cname] if folder: cname = folder + "/" + cname raster_cover_item = container.generate_item(cname, id_prefix="cover") raster_cover = container.href_to_name(raster_cover_item.get("href"), container.opf_name) with container.open(raster_cover, "wb") as dest: if callable(cover_path): cover_path("write_image", dest) else: with lopen(cover_path, "rb") as src: shutil.copyfileobj(src, dest) if options is None: opts = load_defaults("epub_output") keep_aspect = opts.get("preserve_cover_aspect_ratio", False) no_svg = opts.get("no_svg_cover", False) else: keep_aspect = options.get("keep_aspect", False) no_svg = options.get("no_svg", False) if no_svg: style = 'style="height: 100%%"' templ = CoverManager.NONSVG_TEMPLATE.replace("__style__", style) else: if callable(cover_path): templ = (options or {}).get("template", CoverManager.SVG_TEMPLATE) else: width, height = 600, 800 try: if existing_image: width, height = identify(container.raw_data(existing_image, decode=False))[1:] else: with lopen(cover_path, "rb") as csrc: width, height = identify(csrc)[1:] except: container.log.exception("Failed to get width and height of cover") ar = "xMidYMid meet" if keep_aspect else "none" templ = CoverManager.SVG_TEMPLATE.replace("__ar__", ar) templ = templ.replace("__viewbox__", "0 0 %d %d" % (width, height)) templ = templ.replace("__width__", str(width)) templ = templ.replace("__height__", str(height)) folder = recommended_folders[tname] if folder: tname = folder + "/" + tname titlepage_item = container.generate_item(tname, id_prefix="titlepage") titlepage = container.href_to_name(titlepage_item.get("href"), container.opf_name) raw = templ % container.name_to_href(raster_cover, titlepage).encode("utf-8") with container.open(titlepage, "wb") as f: f.write(raw) # We have to make sure the raster cover item has id="cover" for the moron # that wrote the Nook firmware if raster_cover_item.get("id") != "cover": from calibre.ebooks.oeb.base import uuid_id newid = uuid_id() for item in container.opf_xpath('//*[@id="cover"]'): item.set("id", newid) for item in container.opf_xpath('//*[@idref="cover"]'): item.set("idref", newid) raster_cover_item.set("id", "cover") spine = container.opf_xpath("//opf:spine")[0] ref = spine.makeelement(OPF("itemref"), idref=titlepage_item.get("id")) container.insert_into_xml(spine, ref, index=0) guide = container.opf_get_or_create("guide") container.insert_into_xml( guide, guide.makeelement( OPF("reference"), type="cover", title=_("Cover"), href=container.name_to_href(titlepage, base=container.opf_name), ), ) metadata = container.opf_get_or_create("metadata") meta = metadata.makeelement(OPF("meta"), name="cover") meta.set("content", raster_cover_item.get("id")) container.insert_into_xml(metadata, meta) return raster_cover, titlepage
def create_epub_cover(container, cover_path, existing_image, options=None): from calibre.ebooks.conversion.config import load_defaults from calibre.ebooks.oeb.transforms.cover import CoverManager try: ext = cover_path.rpartition('.')[-1].lower() except Exception: ext = 'jpeg' cname, tname = 'cover.' + ext, 'titlepage.xhtml' recommended_folders = get_recommended_folders(container, (cname, tname)) if existing_image: raster_cover = existing_image manifest_id = {v:k for k, v in container.manifest_id_map.iteritems()}[existing_image] raster_cover_item = container.opf_xpath('//opf:manifest/*[@id="%s"]' % manifest_id)[0] else: folder = recommended_folders[cname] if folder: cname = folder + '/' + cname raster_cover_item = container.generate_item(cname, id_prefix='cover') raster_cover = container.href_to_name(raster_cover_item.get('href'), container.opf_name) with container.open(raster_cover, 'wb') as dest: if callable(cover_path): cover_path('write_image', dest) else: with lopen(cover_path, 'rb') as src: shutil.copyfileobj(src, dest) if options is None: opts = load_defaults('epub_output') keep_aspect = opts.get('preserve_cover_aspect_ratio', False) no_svg = opts.get('no_svg_cover', False) else: keep_aspect = options.get('keep_aspect', False) no_svg = options.get('no_svg', False) if no_svg: style = 'style="height: 100%%"' templ = CoverManager.NONSVG_TEMPLATE.replace('__style__', style) has_svg = False else: if callable(cover_path): templ = (options or {}).get('template', CoverManager.SVG_TEMPLATE) has_svg = 'xlink:href' in templ else: width, height = 600, 800 has_svg = True try: if existing_image: width, height = identify(container.raw_data(existing_image, decode=False))[1:] else: with lopen(cover_path, 'rb') as csrc: width, height = identify(csrc)[1:] except: container.log.exception("Failed to get width and height of cover") ar = 'xMidYMid meet' if keep_aspect else 'none' templ = CoverManager.SVG_TEMPLATE.replace('__ar__', ar) templ = templ.replace('__viewbox__', '0 0 %d %d'%(width, height)) templ = templ.replace('__width__', str(width)) templ = templ.replace('__height__', str(height)) folder = recommended_folders[tname] if folder: tname = folder + '/' + tname titlepage_item = container.generate_item(tname, id_prefix='titlepage') titlepage = container.href_to_name(titlepage_item.get('href'), container.opf_name) raw = templ%container.name_to_href(raster_cover, titlepage).encode('utf-8') with container.open(titlepage, 'wb') as f: f.write(raw) # We have to make sure the raster cover item has id="cover" for the moron # that wrote the Nook firmware if raster_cover_item.get('id') != 'cover': from calibre.ebooks.oeb.base import uuid_id newid = uuid_id() for item in container.opf_xpath('//*[@id="cover"]'): item.set('id', newid) for item in container.opf_xpath('//*[@idref="cover"]'): item.set('idref', newid) raster_cover_item.set('id', 'cover') spine = container.opf_xpath('//opf:spine')[0] ref = spine.makeelement(OPF('itemref'), idref=titlepage_item.get('id')) container.insert_into_xml(spine, ref, index=0) ver = container.opf_version_parsed if ver.major < 3: guide = container.opf_get_or_create('guide') container.insert_into_xml(guide, guide.makeelement( OPF('reference'), type='cover', title=_('Cover'), href=container.name_to_href(titlepage, base=container.opf_name))) metadata = container.opf_get_or_create('metadata') meta = metadata.makeelement(OPF('meta'), name='cover') meta.set('content', raster_cover_item.get('id')) container.insert_into_xml(metadata, meta) else: container.apply_unique_properties(raster_cover, 'cover-image') container.apply_unique_properties(titlepage, 'calibre:title-page') if has_svg: container.add_properties(titlepage, 'svg') return raster_cover, titlepage
def create_epub_cover(container, cover_path): from calibre.ebooks.conversion.config import load_defaults from calibre.ebooks.oeb.transforms.cover import CoverManager ext = cover_path.rpartition(".")[-1].lower() raster_cover_item = container.generate_item("cover." + ext, id_prefix="cover") raster_cover = container.href_to_name(raster_cover_item.get("href"), container.opf_name) with open(cover_path, "rb") as src, container.open(raster_cover, "wb") as dest: shutil.copyfileobj(src, dest) opts = load_defaults("epub_output") keep_aspect = opts.get("preserve_cover_aspect_ratio", False) no_svg = opts.get("no_svg_cover", False) if no_svg: style = 'style="height: 100%%"' templ = CoverManager.NONSVG_TEMPLATE.replace("__style__", style) else: width, height = 600, 800 try: width, height = identify(cover_path)[:2] except: container.log.exception("Failed to get width and height of cover") ar = "xMidYMid meet" if keep_aspect else "none" templ = CoverManager.SVG_TEMPLATE.replace("__ar__", ar) templ = templ.replace("__viewbox__", "0 0 %d %d" % (width, height)) templ = templ.replace("__width__", str(width)) templ = templ.replace("__height__", str(height)) titlepage_item = container.generate_item("titlepage.xhtml", id_prefix="titlepage") titlepage = container.href_to_name(titlepage_item.get("href"), container.opf_name) raw = templ % container.name_to_href(raster_cover).encode("utf-8") with container.open(titlepage, "wb") as f: f.write(raw) # We have to make sure the raster cover item has id="cover" for the moron # that wrote the Nook firmware if raster_cover_item.get("id") != "cover": from calibre.ebooks.oeb.base import uuid_id newid = uuid_id() for item in container.opf_xpath('//*[@id="cover"]'): item.set("id", newid) for item in container.opf_xpath('//*[@idref="cover"]'): item.set("idref", newid) raster_cover_item.set("id", "cover") spine = container.opf_xpath("//opf:spine")[0] ref = spine.makeelement(OPF("itemref"), idref=titlepage_item.get("id")) container.insert_into_xml(spine, ref, index=0) guide = container.opf_get_or_create("guide") container.insert_into_xml( guide, guide.makeelement( OPF("reference"), type="cover", title=_("Cover"), href=container.name_to_href(titlepage, base=container.opf_name), ), ) metadata = container.opf_get_or_create("metadata") meta = metadata.makeelement(OPF("meta"), name="cover") meta.set("content", raster_cover_item.get("id")) container.insert_into_xml(metadata, meta) return raster_cover, titlepage
def add_id(container, name, loc): root = container.parsed(name) node = node_from_loc(root, loc) node.set('id', node.get('id', uuid_id())) container.commit_item(name, keep_parsed=True) return node.get('id')
def create_epub_cover(container, cover_path, existing_image, options=None): from calibre.ebooks.conversion.config import load_defaults from calibre.ebooks.oeb.transforms.cover import CoverManager try: ext = cover_path.rpartition('.')[-1].lower() except Exception: ext = 'jpeg' cname, tname = 'cover.' + ext, 'titlepage.xhtml' recommended_folders = get_recommended_folders(container, (cname, tname)) if existing_image: raster_cover = existing_image manifest_id = {v: k for k, v in iteritems(container.manifest_id_map) }[existing_image] raster_cover_item = container.opf_xpath('//opf:manifest/*[@id="%s"]' % manifest_id)[0] else: folder = recommended_folders[cname] if folder: cname = folder + '/' + cname raster_cover_item = container.generate_item(cname, id_prefix='cover') raster_cover = container.href_to_name(raster_cover_item.get('href'), container.opf_name) with container.open(raster_cover, 'wb') as dest: if callable(cover_path): cover_path('write_image', dest) else: with lopen(cover_path, 'rb') as src: shutil.copyfileobj(src, dest) if options is None: opts = load_defaults('epub_output') keep_aspect = opts.get('preserve_cover_aspect_ratio', False) no_svg = opts.get('no_svg_cover', False) else: keep_aspect = options.get('keep_aspect', False) no_svg = options.get('no_svg', False) if no_svg: style = 'style="height: 100%%"' templ = CoverManager.NONSVG_TEMPLATE.replace('__style__', style) has_svg = False else: if callable(cover_path): templ = (options or {}).get('template', CoverManager.SVG_TEMPLATE) has_svg = 'xlink:href' in templ else: width, height = 600, 800 has_svg = True try: if existing_image: width, height = identify( container.raw_data(existing_image, decode=False))[1:] else: with lopen(cover_path, 'rb') as csrc: width, height = identify(csrc)[1:] except: container.log.exception( "Failed to get width and height of cover") ar = 'xMidYMid meet' if keep_aspect else 'none' templ = CoverManager.SVG_TEMPLATE.replace('__ar__', ar) templ = templ.replace('__viewbox__', '0 0 %d %d' % (width, height)) templ = templ.replace('__width__', str(width)) templ = templ.replace('__height__', str(height)) folder = recommended_folders[tname] if folder: tname = folder + '/' + tname titlepage_item = container.generate_item(tname, id_prefix='titlepage') titlepage = container.href_to_name(titlepage_item.get('href'), container.opf_name) raw = templ % container.name_to_href(raster_cover, titlepage).encode('utf-8') with container.open(titlepage, 'wb') as f: f.write(raw) # We have to make sure the raster cover item has id="cover" for the moron # that wrote the Nook firmware if raster_cover_item.get('id') != 'cover': from calibre.ebooks.oeb.base import uuid_id newid = uuid_id() for item in container.opf_xpath('//*[@id="cover"]'): item.set('id', newid) for item in container.opf_xpath('//*[@idref="cover"]'): item.set('idref', newid) raster_cover_item.set('id', 'cover') spine = container.opf_xpath('//opf:spine')[0] ref = spine.makeelement(OPF('itemref'), idref=titlepage_item.get('id')) container.insert_into_xml(spine, ref, index=0) ver = container.opf_version_parsed if ver.major < 3: guide = container.opf_get_or_create('guide') container.insert_into_xml( guide, guide.makeelement(OPF('reference'), type='cover', title=_('Cover'), href=container.name_to_href( titlepage, base=container.opf_name))) metadata = container.opf_get_or_create('metadata') meta = metadata.makeelement(OPF('meta'), name='cover') meta.set('content', raster_cover_item.get('id')) container.insert_into_xml(metadata, meta) else: container.apply_unique_properties(raster_cover, 'cover-image') container.apply_unique_properties(titlepage, 'calibre:title-page') if has_svg: container.add_properties(titlepage, 'svg') return raster_cover, titlepage