1
0
mirror of https://github.com/gryf/ebook-converter.git synced 2026-03-04 15:55:52 +01:00

Added support for epub output format.

This commit is contained in:
2020-04-13 12:52:36 +02:00
parent fa3cf5c178
commit 32b86ab224
10 changed files with 62 additions and 95 deletions

View File

@@ -52,7 +52,7 @@ Currently, I've tested following input formats:
- Palm pdb - Palm pdb
- rtf - rtf
- mobi - mobi
- fb2
Note, that old Microsoft doc format is not supported, although old documents Note, that old Microsoft doc format is not supported, although old documents
can be fairly easy converted using text processors programs, lik Word or can be fairly easy converted using text processors programs, lik Word or
@@ -62,11 +62,10 @@ LibreOffice to supported formats.
Output formats Output formats
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
Currenlty, the only format which is supported is BBeB (lrf) mainly because it Currently, following formats are supported:
is the only one I care for now ;) I'm happy user of Sony PRS-505, and I have no
zero motivation to change that reader to something more fancy. Or plastic.
I'm going to enable others pretty soon. - lrf (for Sony readers)
- epub
Installation Installation

View File

@@ -9,7 +9,7 @@ import re, random, unicodedata, numbers
from collections import namedtuple from collections import namedtuple
from contextlib import contextmanager from contextlib import contextmanager
from math import ceil, sqrt, cos, sin, atan2 from math import ceil, sqrt, cos, sin, atan2
from polyglot.builtins import iteritems, itervalues, map, zip, string_or_bytes from ebook_converter.polyglot.builtins import iteritems, itervalues, map, zip, string_or_bytes
from itertools import chain from itertools import chain
from PyQt5.Qt import ( from PyQt5.Qt import (
@@ -18,14 +18,14 @@ from PyQt5.Qt import (
QPainterPath, QPen, QRectF, QTransform, QRadialGradient QPainterPath, QPen, QRectF, QTransform, QRadialGradient
) )
from calibre import force_unicode, fit_image from ebook_converter import force_unicode, fit_image
from calibre.constants import __appname__, __version__ from ebook_converter.constants import __appname__, __version__
from calibre.ebooks.metadata import fmt_sidx from ebook_converter.ebooks.metadata import fmt_sidx
from calibre.ebooks.metadata.book.base import Metadata from ebook_converter.ebooks.metadata.book.base import Metadata
from calibre.ebooks.metadata.book.formatter import SafeFormat from ebook_converter.ebooks.metadata.book.formatter import SafeFormat
from calibre.gui2 import ensure_app, config, load_builtin_fonts, pixmap_to_data from ebook_converter.gui2 import ensure_app, config, load_builtin_fonts, pixmap_to_data
from calibre.utils.cleantext import clean_ascii_chars, clean_xml_chars from ebook_converter.utils.cleantext import clean_ascii_chars, clean_xml_chars
from calibre.utils.config import JSONConfig from ebook_converter.utils.config import JSONConfig
# Default settings {{{ # Default settings {{{
cprefs = JSONConfig('cover_generation') cprefs = JSONConfig('cover_generation')
@@ -492,7 +492,7 @@ class Ornamental(Style):
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block): def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block):
if not self.PATH_CACHE: if not self.PATH_CACHE:
from calibre.utils.speedups import svg_path_to_painter_path from ebook_converter.utils.speedups import svg_path_to_painter_path
try: try:
self.__class__.PATH_CACHE['corner'] = svg_path_to_painter_path(self.CORNER_VECTOR) self.__class__.PATH_CACHE['corner'] = svg_path_to_painter_path(self.CORNER_VECTOR)
except Exception: except Exception:
@@ -728,7 +728,7 @@ def generate_masthead(title, output_path=None, width=600, height=60, as_qimage=F
def test(scale=0.25): def test(scale=0.25):
from PyQt5.Qt import QLabel, QPixmap, QMainWindow, QWidget, QScrollArea, QGridLayout from PyQt5.Qt import QLabel, QPixmap, QMainWindow, QWidget, QScrollArea, QGridLayout
from calibre.gui2 import Application from ebook_converter.gui2 import Application
app = Application([]) app = Application([])
mi = Metadata('Unknown', ['Kovid Goyal', 'John & Doe', 'Author']) mi = Metadata('Unknown', ['Kovid Goyal', 'John & Doe', 'Author'])
mi.series = 'A series & styles' mi.series = 'A series & styles'

View File

@@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
''' '''
Conversion to EPUB. Conversion to EPUB.
''' '''
from calibre.utils.zipfile import ZipFile, ZIP_STORED from ebook_converter.utils.zipfile import ZipFile, ZIP_STORED
def rules(stylesheets): def rules(stylesheets):

View File

@@ -9,15 +9,15 @@ from collections import defaultdict
from functools import partial from functools import partial
from css_parser.css import CSSRule, CSSStyleDeclaration from css_parser.css import CSSRule, CSSStyleDeclaration
from css_selectors import parse, SelectorSyntaxError from ebook_converter.css_selectors import parse, SelectorSyntaxError
from calibre import force_unicode from ebook_converter import force_unicode
from calibre.ebooks.oeb.base import OEB_STYLES, OEB_DOCS, XHTML, css_text from ebook_converter.ebooks.oeb.base import OEB_STYLES, OEB_DOCS, XHTML, css_text
from calibre.ebooks.oeb.normalize_css import normalize_filter_css, normalizers from ebook_converter.ebooks.oeb.normalize_css import normalize_filter_css, normalizers
from calibre.ebooks.oeb.polish.pretty import pretty_script_or_style, pretty_xml_tree, serialize from ebook_converter.ebooks.oeb.polish.pretty import pretty_script_or_style, pretty_xml_tree, serialize
from calibre.utils.icu import numeric_sort_key from ebook_converter.utils.icu import numeric_sort_key
from css_selectors import Select, SelectorError from ebook_converter.css_selectors import Select, SelectorError
from polyglot.builtins import iteritems, itervalues, unicode_type, filter from ebook_converter.polyglot.builtins import iteritems, itervalues, unicode_type, filter
def filter_used_rules(rules, log, select): def filter_used_rules(rules, log, select):

View File

@@ -7,16 +7,16 @@ __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import codecs, shutil, os, posixpath import codecs, shutil, os, posixpath
from polyglot.builtins import iteritems, itervalues, map from ebook_converter.polyglot.builtins import iteritems, itervalues, map
from functools import partial from functools import partial
from collections import Counter, defaultdict from collections import Counter, defaultdict
from calibre import sanitize_file_name from ebook_converter import sanitize_file_name
from calibre.ebooks.chardet import strip_encoding_declarations from ebook_converter.ebooks.chardet import strip_encoding_declarations
from calibre.ebooks.oeb.base import css_text from ebook_converter.ebooks.oeb.base import css_text
from calibre.ebooks.oeb.polish.css import iter_declarations, remove_property_value from ebook_converter.ebooks.oeb.polish.css import iter_declarations, remove_property_value
from calibre.ebooks.oeb.polish.utils import extract from ebook_converter.ebooks.oeb.polish.utils import extract
from polyglot.urllib import urlparse, urlunparse from ebook_converter.polyglot.urllib import urlparse, urlunparse
class LinkReplacer(object): class LinkReplacer(object):
@@ -151,7 +151,7 @@ def replace_ids(container, id_map):
def smarten_punctuation(container, report): def smarten_punctuation(container, report):
from calibre.ebooks.conversion.preprocess import smarten_punctuation from ebook_converter.ebooks.conversion.preprocess import smarten_punctuation
smartened = False smartened = False
for path in container.spine_items: for path in container.spine_items:
name = container.abspath_to_name(path) name = container.abspath_to_name(path)
@@ -230,9 +230,9 @@ def replace_file(container, name, path, basename, force_mt=None):
def mt_to_category(container, mt): def mt_to_category(container, mt):
from calibre.ebooks.oeb.polish.utils import guess_type from ebook_converter.ebooks.oeb.polish.utils import guess_type
from calibre.ebooks.oeb.polish.container import OEB_FONTS from ebook_converter.ebooks.oeb.polish.container import OEB_FONTS
from calibre.ebooks.oeb.base import OEB_DOCS, OEB_STYLES from ebook_converter.ebooks.oeb.base import OEB_DOCS, OEB_STYLES
if mt in OEB_DOCS: if mt in OEB_DOCS:
category = 'text' category = 'text'
elif mt in OEB_STYLES: elif mt in OEB_STYLES:
@@ -253,7 +253,7 @@ def get_recommended_folders(container, names):
recommendation is based on where the majority of files of the same type are recommendation is based on where the majority of files of the same type are
located in the container. If no files of a particular type are present, the located in the container. If no files of a particular type are present, the
recommended folder is assumed to be the folder containing the OPF file. ''' recommended folder is assumed to be the folder containing the OPF file. '''
from calibre.ebooks.oeb.polish.utils import guess_type from ebook_converter.ebooks.oeb.polish.utils import guess_type
counts = defaultdict(Counter) counts = defaultdict(Counter)
for name, mt in iteritems(container.mime_map): for name, mt in iteritems(container.mime_map):
folder = name.rpartition('/')[0] if '/' in name else '' folder = name.rpartition('/')[0] if '/' in name else ''
@@ -347,7 +347,7 @@ def remove_links_in_declaration(href_to_name, style, predicate):
def remove_links_to(container, predicate): def remove_links_to(container, predicate):
''' predicate must be a function that takes the arguments (name, href, ''' predicate must be a function that takes the arguments (name, href,
fragment=None) and returns True iff the link should be removed ''' fragment=None) and returns True iff the link should be removed '''
from calibre.ebooks.oeb.base import iterlinks, OEB_DOCS, OEB_STYLES, XPath, XHTML from ebook_converter.ebooks.oeb.base import iterlinks, OEB_DOCS, OEB_STYLES, XPath, XHTML
stylepath = XPath('//h:style') stylepath = XPath('//h:style')
styleattrpath = XPath('//*[@style]') styleattrpath = XPath('//*[@style]')
changed = set() changed = set()

View File

@@ -6,14 +6,14 @@ __license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
import copy, os, re import copy, os, re
from polyglot.builtins import map, string_or_bytes, range from ebook_converter.polyglot.builtins import map, string_or_bytes, range
from calibre.ebooks.oeb.base import barename, XPNSMAP, XPath, OPF, XHTML, OEB_DOCS from ebook_converter.ebooks.oeb.base import barename, XPNSMAP, XPath, OPF, XHTML, OEB_DOCS
from calibre.ebooks.oeb.polish.errors import MalformedMarkup from ebook_converter.ebooks.oeb.polish.errors import MalformedMarkup
from calibre.ebooks.oeb.polish.toc import node_from_loc from ebook_converter.ebooks.oeb.polish.toc import node_from_loc
from calibre.ebooks.oeb.polish.replace import LinkRebaser from ebook_converter.ebooks.oeb.polish.replace import LinkRebaser
from polyglot.builtins import iteritems, unicode_type from ebook_converter.polyglot.builtins import iteritems, unicode_type
from polyglot.urllib import urlparse from ebook_converter.polyglot.urllib import urlparse
class AbortError(ValueError): class AbortError(ValueError):

View File

@@ -8,11 +8,11 @@ __docformat__ = 'restructuredtext en'
import textwrap import textwrap
from calibre import guess_type from ebook_converter import guess_type
from calibre.utils.imghdr import identify from ebook_converter.utils.imghdr import identify
from calibre.utils.xml_parse import safe_xml_fromstring from ebook_converter.utils.xml_parse import safe_xml_fromstring
from polyglot.builtins import unicode_type from ebook_converter.polyglot.builtins import unicode_type
from polyglot.urllib import unquote from ebook_converter.polyglot.urllib import unquote
class CoverManager(object): class CoverManager(object):
@@ -84,39 +84,8 @@ class CoverManager(object):
self.log = log self.log = log
self.insert_cover() self.insert_cover()
def default_cover(self):
'''
Create a generic cover for books that dont have a cover
'''
if self.no_default_cover:
return None
self.log('Generating default cover')
m = self.oeb.metadata
title = unicode_type(m.title[0])
authors = [unicode_type(x) for x in m.creator if x.role == 'aut']
try:
from calibre.ebooks.covers import create_cover
series = series_index = None
if m.series:
try:
series, series_index = unicode_type(m.series[0]), m.series_index[0]
except IndexError:
pass
img_data = create_cover(title, authors, series, series_index)
id, href = self.oeb.manifest.generate('cover',
'cover_image.jpg')
item = self.oeb.manifest.add(id, href, guess_type('t.jpg')[0],
data=img_data)
m.clear('cover')
m.add('cover', item.id)
return item.href
except:
self.log.exception('Failed to generate default cover')
return None
def inspect_cover(self, href): def inspect_cover(self, href):
from calibre.ebooks.oeb.base import urlnormalize from ebook_converter.ebooks.oeb.base import urlnormalize
for x in self.oeb.manifest: for x in self.oeb.manifest:
if x.href == urlnormalize(href): if x.href == urlnormalize(href):
try: try:
@@ -127,14 +96,13 @@ class CoverManager(object):
return -1, -1 return -1, -1
def insert_cover(self): def insert_cover(self):
from calibre.ebooks.oeb.base import urldefrag from ebook_converter.ebooks.oeb.base import urldefrag
g, m = self.oeb.guide, self.oeb.manifest g, m = self.oeb.guide, self.oeb.manifest
item = None item = None
href = None
if 'titlepage' not in g: if 'titlepage' not in g:
if 'cover' in g: if 'cover' in g:
href = g['cover'].href href = g['cover'].href
else:
href = self.default_cover()
if href is None: if href is None:
return return
width, height = self.inspect_cover(href) width, height = self.inspect_cover(href)

View File

@@ -10,8 +10,8 @@ import posixpath
from lxml import etree from lxml import etree
from calibre.ebooks.oeb.base import rewrite_links, urlnormalize from ebook_converter.ebooks.oeb.base import rewrite_links, urlnormalize
from polyglot.urllib import urldefrag, urlparse from ebook_converter.polyglot.urllib import urldefrag, urlparse
class RenameFiles(object): # {{{ class RenameFiles(object): # {{{

View File

@@ -6,7 +6,7 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from calibre import fit_image from ebook_converter import fit_image
class RescaleImages(object): class RescaleImages(object):

View File

@@ -15,14 +15,14 @@ from collections import OrderedDict
from lxml.etree import XPath as _XPath from lxml.etree import XPath as _XPath
from lxml import etree from lxml import etree
from calibre import as_unicode, force_unicode from ebook_converter import as_unicode, force_unicode
from calibre.ebooks.epub import rules from ebook_converter.ebooks.epub import rules
from calibre.ebooks.oeb.base import (OEB_STYLES, XPNSMAP as NAMESPACES, from ebook_converter.ebooks.oeb.base import (OEB_STYLES, XPNSMAP as NAMESPACES,
urldefrag, rewrite_links, XHTML, urlnormalize) urldefrag, rewrite_links, XHTML, urlnormalize)
from calibre.ebooks.oeb.polish.split import do_split from ebook_converter.ebooks.oeb.polish.split import do_split
from polyglot.builtins import iteritems, range, map, unicode_type from ebook_converter.polyglot.builtins import iteritems, range, map, unicode_type
from polyglot.urllib import unquote from ebook_converter.polyglot.urllib import unquote
from css_selectors import Select, SelectorError from ebook_converter.css_selectors import Select, SelectorError
XPath = functools.partial(_XPath, namespaces=NAMESPACES) XPath = functools.partial(_XPath, namespaces=NAMESPACES)