mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Conversion EPUB Output: Add an option to output EPUB 3 files.
This commit is contained in:
parent
94058dd07b
commit
10ab8bfa26
@ -117,6 +117,12 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
help=_('Title for any generated in-line table of contents.')
|
help=_('Title for any generated in-line table of contents.')
|
||||||
),
|
),
|
||||||
|
|
||||||
|
OptionRecommendation(name='epub_version', recommended_value='2', choices=('2', '3'),
|
||||||
|
help=_('The version of the EPUB file to generate. EPUB 2 is the'
|
||||||
|
' most widely compatible, only use EPUB 3 if you know you'
|
||||||
|
' actually need it.')
|
||||||
|
),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
recommendations = set([('pretty_print', True, OptionRecommendation.HIGH)])
|
recommendations = set([('pretty_print', True, OptionRecommendation.HIGH)])
|
||||||
@ -168,6 +174,7 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
seen_names.add(name)
|
seen_names.add(name)
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
def convert(self, oeb, output_path, input_plugin, opts, log):
|
def convert(self, oeb, output_path, input_plugin, opts, log):
|
||||||
self.log, self.opts, self.oeb = log, opts, oeb
|
self.log, self.opts, self.oeb = log, opts, oeb
|
||||||
|
|
||||||
@ -249,6 +256,8 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
opf = [x for x in os.listdir(tdir) if x.endswith('.opf')][0]
|
opf = [x for x in os.listdir(tdir) if x.endswith('.opf')][0]
|
||||||
self.condense_ncx([os.path.join(tdir, x) for x in os.listdir(tdir)
|
self.condense_ncx([os.path.join(tdir, x) for x in os.listdir(tdir)
|
||||||
if x.endswith('.ncx')][0])
|
if x.endswith('.ncx')][0])
|
||||||
|
if self.opts.epub_version == '3':
|
||||||
|
self.upgrade_to_epub3(tdir, opf)
|
||||||
encryption = None
|
encryption = None
|
||||||
if encrypted_fonts:
|
if encrypted_fonts:
|
||||||
encryption = self.encrypt_fonts(encrypted_fonts, tdir, uuid)
|
encryption = self.encrypt_fonts(encrypted_fonts, tdir, uuid)
|
||||||
@ -274,6 +283,26 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
zf.extractall(path=opts.extract_to)
|
zf.extractall(path=opts.extract_to)
|
||||||
self.log.info('EPUB extracted to', opts.extract_to)
|
self.log.info('EPUB extracted to', opts.extract_to)
|
||||||
|
|
||||||
|
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 encrypt_fonts(self, uris, tdir, uuid): # {{{
|
def encrypt_fonts(self, uris, tdir, uuid): # {{{
|
||||||
from binascii import unhexlify
|
from binascii import unhexlify
|
||||||
|
|
||||||
@ -324,7 +353,7 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
return ans
|
return ans
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
def condense_ncx(self, ncx_path):
|
def condense_ncx(self, ncx_path): # {{{
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
if not self.opts.pretty_print:
|
if not self.opts.pretty_print:
|
||||||
tree = etree.parse(ncx_path)
|
tree = etree.parse(ncx_path)
|
||||||
@ -335,6 +364,7 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
tag.tail = tag.tail.strip()
|
tag.tail = tag.tail.strip()
|
||||||
compressed = etree.tostring(tree.getroot(), encoding='utf-8')
|
compressed = etree.tostring(tree.getroot(), encoding='utf-8')
|
||||||
open(ncx_path, 'wb').write(compressed)
|
open(ncx_path, 'wb').write(compressed)
|
||||||
|
# }}}
|
||||||
|
|
||||||
def workaround_ade_quirks(self): # {{{
|
def workaround_ade_quirks(self): # {{{
|
||||||
'''
|
'''
|
||||||
@ -420,8 +450,7 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
if not tag.text:
|
if not tag.text:
|
||||||
tag.getparent().remove(tag)
|
tag.getparent().remove(tag)
|
||||||
for tag in XPath('//h:script')(root):
|
for tag in XPath('//h:script')(root):
|
||||||
if (not tag.text and not tag.get('src', False) and
|
if (not tag.text and not tag.get('src', False) and tag.get('type', None) != 'text/x-mathjax-config'):
|
||||||
tag.get('type', None) != 'text/x-mathjax-config'):
|
|
||||||
tag.getparent().remove(tag)
|
tag.getparent().remove(tag)
|
||||||
for tag in XPath('//h:body/descendant::h:script')(root):
|
for tag in XPath('//h:body/descendant::h:script')(root):
|
||||||
tag.getparent().remove(tag)
|
tag.getparent().remove(tag)
|
||||||
|
@ -17,6 +17,18 @@ def rules(stylesheets):
|
|||||||
yield r
|
yield r
|
||||||
|
|
||||||
|
|
||||||
|
def simple_container_xml(opf_path, extra_entries=''):
|
||||||
|
return u'''\
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
|
||||||
|
<rootfiles>
|
||||||
|
<rootfile full-path="{0}" media-type="application/oebps-package+xml"/>
|
||||||
|
{extra_entries}
|
||||||
|
</rootfiles>
|
||||||
|
</container>
|
||||||
|
'''.format(opf_path, extra_entries=extra_entries)
|
||||||
|
|
||||||
|
|
||||||
def initialize_container(path_to_container, opf_name='metadata.opf',
|
def initialize_container(path_to_container, opf_name='metadata.opf',
|
||||||
extra_entries=[]):
|
extra_entries=[]):
|
||||||
'''
|
'''
|
||||||
@ -26,15 +38,7 @@ def initialize_container(path_to_container, opf_name='metadata.opf',
|
|||||||
for path, mimetype, _ in extra_entries:
|
for path, mimetype, _ in extra_entries:
|
||||||
rootfiles += u'<rootfile full-path="{0}" media-type="{1}"/>'.format(
|
rootfiles += u'<rootfile full-path="{0}" media-type="{1}"/>'.format(
|
||||||
path, mimetype)
|
path, mimetype)
|
||||||
CONTAINER = u'''\
|
CONTAINER = simple_container_xml(opf_name, rootfiles).encode('utf-8')
|
||||||
<?xml version="1.0"?>
|
|
||||||
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
|
|
||||||
<rootfiles>
|
|
||||||
<rootfile full-path="{0}" media-type="application/oebps-package+xml"/>
|
|
||||||
{extra_entries}
|
|
||||||
</rootfiles>
|
|
||||||
</container>
|
|
||||||
'''.format(opf_name, extra_entries=rootfiles).encode('utf-8')
|
|
||||||
zf = ZipFile(path_to_container, 'w')
|
zf = ZipFile(path_to_container, 'w')
|
||||||
zf.writestr('mimetype', 'application/epub+zip', compression=ZIP_STORED)
|
zf.writestr('mimetype', 'application/epub+zip', compression=ZIP_STORED)
|
||||||
zf.writestr('META-INF/', '', 0755)
|
zf.writestr('META-INF/', '', 0755)
|
||||||
@ -42,5 +46,3 @@ def initialize_container(path_to_container, opf_name='metadata.opf',
|
|||||||
for path, _, data in extra_entries:
|
for path, _, data in extra_entries:
|
||||||
zf.writestr(path, data)
|
zf.writestr(path, data)
|
||||||
return zf
|
return zf
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,9 +23,11 @@ class PluginWidget(Widget, Ui_Form):
|
|||||||
['dont_split_on_page_breaks', 'flow_size',
|
['dont_split_on_page_breaks', 'flow_size',
|
||||||
'no_default_epub_cover', 'no_svg_cover',
|
'no_default_epub_cover', 'no_svg_cover',
|
||||||
'epub_inline_toc', 'epub_toc_at_end', 'toc_title',
|
'epub_inline_toc', 'epub_toc_at_end', 'toc_title',
|
||||||
'preserve_cover_aspect_ratio', 'epub_flatten']
|
'preserve_cover_aspect_ratio', 'epub_flatten', 'epub_version']
|
||||||
)
|
)
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
self.opt_no_svg_cover.toggle()
|
self.opt_no_svg_cover.toggle()
|
||||||
|
ev = get_option('epub_version')
|
||||||
|
self.opt_epub_version.addItems(list(ev.option.choices))
|
||||||
self.db, self.book_id = db, book_id
|
self.db, self.book_id = db, book_id
|
||||||
self.initialize_options(get_option, get_help, db, book_id)
|
self.initialize_options(get_option, get_help, db, book_id)
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="7" column="0">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -118,6 +118,19 @@
|
|||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QLineEdit" name="opt_toc_title"/>
|
<widget class="QLineEdit" name="opt_toc_title"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>EP&UB version:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>opt_epub_version</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QComboBox" name="opt_epub_version"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user