mirror of
https://github.com/gryf/ebook-converter.git
synced 2026-01-03 09:14:11 +01:00
123 lines
4.8 KiB
Python
123 lines
4.8 KiB
Python
import os
|
|
import re
|
|
|
|
from lxml import etree
|
|
|
|
from ebook_converter.customize.conversion import (OutputFormatPlugin,
|
|
OptionRecommendation)
|
|
from ebook_converter import CurrentDir
|
|
from ebook_converter.polyglot.urllib import unquote
|
|
from ebook_converter.ebooks.oeb.base import OPF_MIME, NCX_MIME, PAGE_MAP_MIME, OEB_STYLES
|
|
from ebook_converter.ebooks.oeb.normalize_css import condense_sheet
|
|
|
|
|
|
__license__ = 'GPL 3'
|
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
|
__docformat__ = 'restructuredtext en'
|
|
|
|
|
|
class OEBOutput(OutputFormatPlugin):
|
|
|
|
name = 'OEB Output'
|
|
author = 'Kovid Goyal'
|
|
file_type = 'oeb'
|
|
commit_name = 'oeb_output'
|
|
|
|
recommendations = {('pretty_print', True, OptionRecommendation.HIGH)}
|
|
|
|
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
|
|
|
self.log, self.opts = log, opts
|
|
if not os.path.exists(output_path):
|
|
os.makedirs(output_path)
|
|
with CurrentDir(output_path):
|
|
results = oeb_book.to_opf2(page_map=True)
|
|
for key in (OPF_MIME, NCX_MIME, PAGE_MAP_MIME):
|
|
href, root = results.pop(key, [None, None])
|
|
if root is not None:
|
|
if key == OPF_MIME:
|
|
try:
|
|
self.workaround_nook_cover_bug(root)
|
|
except:
|
|
self.log.exception('Something went wrong while trying to'
|
|
' workaround Nook cover bug, ignoring')
|
|
try:
|
|
self.workaround_pocketbook_cover_bug(root)
|
|
except:
|
|
self.log.exception('Something went wrong while trying to'
|
|
' workaround Pocketbook cover bug, ignoring')
|
|
self.migrate_lang_code(root)
|
|
raw = etree.tostring(root, pretty_print=True,
|
|
encoding='utf-8', xml_declaration=True)
|
|
if key == OPF_MIME:
|
|
# Needed as I can't get lxml to output opf:role and
|
|
# not output <opf:metadata> as well
|
|
raw = re.sub(br'(<[/]{0,1})opf:', br'\1', raw)
|
|
with lopen(href, 'wb') as f:
|
|
f.write(raw)
|
|
|
|
for item in oeb_book.manifest:
|
|
if (
|
|
not self.opts.expand_css and item.media_type in OEB_STYLES and hasattr(
|
|
item.data, 'cssText') and 'nook' not in self.opts.output_profile.short_name):
|
|
condense_sheet(item.data)
|
|
path = os.path.abspath(unquote(item.href))
|
|
dir = os.path.dirname(path)
|
|
if not os.path.exists(dir):
|
|
os.makedirs(dir)
|
|
with lopen(path, 'wb') as f:
|
|
f.write(item.bytes_representation)
|
|
item.unload_data_from_memory(memory=path)
|
|
|
|
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 ebook_converter.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_pocketbook_cover_bug(self, root): # {{{
|
|
m = root.xpath('//*[local-name() = "manifest"]/*[local-name() = "item" '
|
|
' and @id="cover"]')
|
|
if len(m) == 1:
|
|
m = m[0]
|
|
p = m.getparent()
|
|
p.remove(m)
|
|
p.insert(0, m)
|
|
# }}}
|
|
|
|
def migrate_lang_code(self, root): # {{{
|
|
from ebook_converter.utils.localization import lang_as_iso639_1
|
|
for lang in root.xpath('//*[local-name() = "language"]'):
|
|
clc = lang_as_iso639_1(lang.text)
|
|
if clc:
|
|
lang.text = clc
|
|
# }}}
|