mirror of
https://github.com/gryf/ebook-converter.git
synced 2026-04-26 16:41:29 +02:00
Removed gettext related functions
This commit is contained in:
@@ -14,7 +14,7 @@ from ebook_converter import patheq
|
||||
from ebook_converter.utils.localization import localize_user_manual_link
|
||||
|
||||
|
||||
USAGE = '%prog ' + _('''\
|
||||
USAGE = '%prog ' + '''\
|
||||
input_file output_file [options]
|
||||
|
||||
Convert an e-book from one format to another.
|
||||
@@ -38,7 +38,8 @@ To get help on them specify the input and output file and then use the -h \
|
||||
option.
|
||||
|
||||
For full documentation of the conversion system see
|
||||
''') + localize_user_manual_link('https://manual.calibre-ebook.com/conversion.html')
|
||||
https://manual.calibre-ebook.com/conversion.html
|
||||
'''
|
||||
|
||||
HEURISTIC_OPTIONS = ['markup_chapter_headings',
|
||||
'italicize_common_cases', 'fix_indents',
|
||||
@@ -98,21 +99,20 @@ def option_recommendation_to_cli_option(add_option, rec):
|
||||
if opt.name == 'read_metadata_from_opf':
|
||||
switches.append('--from-opf')
|
||||
if opt.name == 'transform_css_rules':
|
||||
attrs['help'] = _(
|
||||
'Path to a file containing rules to transform the CSS styles'
|
||||
' in this book. The easiest way to create such a file is to'
|
||||
' use the wizard for creating rules in the calibre GUI. Access'
|
||||
' it in the "Look & feel->Transform styles" section of the conversion'
|
||||
' dialog. Once you create the rules, you can use the "Export" button'
|
||||
' to save them to a file.'
|
||||
)
|
||||
attrs['help'] = ('Path to a file containing rules to transform the '
|
||||
'CSS styles in this book. The easiest way to create '
|
||||
'such a file is to use the wizard for creating rules '
|
||||
'in the calibre GUI. Access it in the "Look & '
|
||||
'feel->Transform styles" section of the conversion '
|
||||
'dialog. Once you create the rules, you can use the '
|
||||
'"Export" button to save them to a file.')
|
||||
if opt.name in DEFAULT_TRUE_OPTIONS and rec.recommended_value is True:
|
||||
switches = ['--disable-'+opt.long_switch]
|
||||
add_option(optparse.Option(*switches, **attrs))
|
||||
|
||||
|
||||
def group_titles():
|
||||
return _('INPUT OPTIONS'), _('OUTPUT OPTIONS')
|
||||
return 'INPUT OPTIONS', 'OUTPUT OPTIONS'
|
||||
|
||||
|
||||
def recipe_test(option, opt_str, value, parser):
|
||||
@@ -160,15 +160,17 @@ def add_input_output_options(parser, plumber):
|
||||
|
||||
if input_options:
|
||||
title = group_titles()[0]
|
||||
io = optparse.OptionGroup(parser, title, _('Options to control the processing'
|
||||
' of the input %s file')%plumber.input_fmt)
|
||||
io = optparse.OptionGroup(parser, title, 'Options to control the '
|
||||
'processing of the input %s file' %
|
||||
plumber.input_fmt)
|
||||
add_options(io.add_option, input_options)
|
||||
parser.add_option_group(io)
|
||||
|
||||
if output_options:
|
||||
title = group_titles()[1]
|
||||
oo = optparse.OptionGroup(parser, title, _('Options to control the processing'
|
||||
' of the output %s')%plumber.output_fmt)
|
||||
oo = optparse.OptionGroup(parser, title, 'Options to control the '
|
||||
'processing of the output %s' %
|
||||
plumber.output_fmt)
|
||||
add_options(oo.add_option, output_options)
|
||||
parser.add_option_group(oo)
|
||||
|
||||
@@ -181,8 +183,8 @@ def add_pipeline_options(parser, plumber):
|
||||
'output_profile',
|
||||
]
|
||||
)),
|
||||
(_('LOOK AND FEEL') , (
|
||||
_('Options to control the look and feel of the output'),
|
||||
('LOOK AND FEEL' , (
|
||||
'Options to control the look and feel of the output',
|
||||
[
|
||||
'base_font_size', 'disable_font_rescaling',
|
||||
'font_size_mapping', 'embed_font_family',
|
||||
@@ -200,26 +202,23 @@ def add_pipeline_options(parser, plumber):
|
||||
]
|
||||
)),
|
||||
|
||||
(_('HEURISTIC PROCESSING') , (
|
||||
_('Modify the document text and structure using common'
|
||||
' patterns. Disabled by default. Use %(en)s to enable. '
|
||||
' Individual actions can be disabled with the %(dis)s options.')
|
||||
% dict(en='--enable-heuristics', dis='--disable-*'),
|
||||
('HEURISTIC PROCESSING' ,
|
||||
('Modify the document text and structure using common '
|
||||
'patterns. Disabled by default. Use %(en)s to enable. '
|
||||
'Individual actions can be disabled with the %(dis)s '
|
||||
'options.' % dict(en='--enable-heuristics', dis='--disable-*'),
|
||||
['enable_heuristics'] + HEURISTIC_OPTIONS
|
||||
)),
|
||||
|
||||
(_('SEARCH AND REPLACE') , (
|
||||
_('Modify the document text and structure using user defined patterns.'),
|
||||
[
|
||||
'sr1_search', 'sr1_replace',
|
||||
'sr2_search', 'sr2_replace',
|
||||
'sr3_search', 'sr3_replace',
|
||||
'search_replace',
|
||||
]
|
||||
('SEARCH AND REPLACE' ,
|
||||
('Modify the document text and structure using user defined '
|
||||
'patterns.',
|
||||
['sr1_search', 'sr1_replace', 'sr2_search', 'sr2_replace',
|
||||
'sr3_search', 'sr3_replace', 'search_replace']
|
||||
)),
|
||||
|
||||
(_('STRUCTURE DETECTION') , (
|
||||
_('Control auto-detection of document structure.'),
|
||||
('STRUCTURE DETECTION' , (
|
||||
'Control auto-detection of document structure.',
|
||||
[
|
||||
'chapter', 'chapter_mark',
|
||||
'prefer_metadata_cover', 'remove_first_image',
|
||||
@@ -228,21 +227,20 @@ def add_pipeline_options(parser, plumber):
|
||||
]
|
||||
)),
|
||||
|
||||
(_('TABLE OF CONTENTS') , (
|
||||
_('Control the automatic generation of a Table of Contents. By '
|
||||
'default, if the source file has a Table of Contents, it will '
|
||||
'be used in preference to the automatically generated one.'),
|
||||
[
|
||||
'level1_toc', 'level2_toc', 'level3_toc',
|
||||
'toc_threshold', 'max_toc_links', 'no_chapters_in_toc',
|
||||
'use_auto_toc', 'toc_filter', 'duplicate_links_in_toc',
|
||||
]
|
||||
)),
|
||||
('TABLE OF CONTENTS' ,
|
||||
('Control the automatic generation of a Table of Contents. By '
|
||||
'default, if the source file has a Table of Contents, it will '
|
||||
'be used in preference to the automatically generated one.',
|
||||
['level1_toc', 'level2_toc', 'level3_toc', 'toc_threshold',
|
||||
'max_toc_links', 'no_chapters_in_toc', 'use_auto_toc',
|
||||
'toc_filter', 'duplicate_links_in_toc']
|
||||
)
|
||||
),
|
||||
|
||||
(_('METADATA') , (_('Options to set metadata in the output'),
|
||||
('METADATA' , ('Options to set metadata in the output',
|
||||
plumber.metadata_option_names + ['read_metadata_from_opf'],
|
||||
)),
|
||||
(_('DEBUG'), (_('Options to help with debugging the conversion'),
|
||||
('DEBUG', ('Options to help with debugging the conversion',
|
||||
[
|
||||
'verbose',
|
||||
'debug_pipeline',
|
||||
@@ -265,9 +263,9 @@ def add_pipeline_options(parser, plumber):
|
||||
def option_parser():
|
||||
parser = OptionParser(usage=USAGE)
|
||||
parser.add_option('--list-recipes', default=False, action='store_true',
|
||||
help=_('List builtin recipe names. You can create an e-book from '
|
||||
'a builtin recipe like this: ebook-convert "Recipe Name.recipe" '
|
||||
'output.epub'))
|
||||
help='List builtin recipe names. You can create an e-book from '
|
||||
'a builtin recipe like this: ebook-convert "Recipe '
|
||||
'Name.recipe" output.epub')
|
||||
return parser
|
||||
|
||||
|
||||
@@ -393,20 +391,20 @@ def main(args=sys.argv):
|
||||
|
||||
plumber.run()
|
||||
|
||||
log(_('Output saved to'), ' ', plumber.output)
|
||||
log('Output saved to', ' ', plumber.output)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def manual_index_strings():
|
||||
return _('''\
|
||||
return '''\
|
||||
The options and default values for the options change depending on both the
|
||||
input and output formats, so you should always check with::
|
||||
|
||||
%s
|
||||
|
||||
Below are the options that are common to all conversion, followed by the
|
||||
options specific to every input and output format.''')
|
||||
options specific to every input and output format.'''
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -191,7 +191,7 @@ class CHMInput(InputFormatPlugin):
|
||||
title = param.attrib['value']
|
||||
elif match_string(param.attrib['name'], 'local'):
|
||||
href = param.attrib['value']
|
||||
child = toc.add(title or _('Unknown'), href)
|
||||
child = toc.add(title or 'Unknown', href)
|
||||
ancestor_map[node] = child
|
||||
|
||||
def _process_nodes(self, root):
|
||||
|
||||
@@ -25,51 +25,54 @@ class ComicInput(InputFormatPlugin):
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='colors', recommended_value=0,
|
||||
help=_('Reduce the number of colors used in the image. This works only'
|
||||
' if you choose the PNG output format. It is useful to reduce file sizes.'
|
||||
' Set to zero to turn off. Maximum value is 256. It is off by default.')),
|
||||
help='Reduce the number of colors used in the image. This works '
|
||||
'only if you choose the PNG output format. It is useful to '
|
||||
'reduce file sizes. Set to zero to turn off. Maximum value '
|
||||
'is 256. It is off by default.'),
|
||||
OptionRecommendation(name='dont_normalize', recommended_value=False,
|
||||
help=_('Disable normalize (improve contrast) color range '
|
||||
'for pictures. Default: False')),
|
||||
help='Disable normalize (improve contrast) color range '
|
||||
'for pictures. Default: False'),
|
||||
OptionRecommendation(name='keep_aspect_ratio', recommended_value=False,
|
||||
help=_('Maintain picture aspect ratio. Default is to fill the screen.')),
|
||||
help='Maintain picture aspect ratio. Default is to fill the '
|
||||
'screen.'),
|
||||
OptionRecommendation(name='dont_sharpen', recommended_value=False,
|
||||
help=_('Disable sharpening.')),
|
||||
help='Disable sharpening.'),
|
||||
OptionRecommendation(name='disable_trim', recommended_value=False,
|
||||
help=_('Disable trimming of comic pages. For some comics, '
|
||||
'trimming might remove content as well as borders.')),
|
||||
help='Disable trimming of comic pages. For some comics, trimming '
|
||||
'might remove content as well as borders.'),
|
||||
OptionRecommendation(name='landscape', recommended_value=False,
|
||||
help=_("Don't split landscape images into two portrait images")),
|
||||
help="Don't split landscape images into two portrait images"),
|
||||
OptionRecommendation(name='wide', recommended_value=False,
|
||||
help=_("Keep aspect ratio and scale image using screen height as "
|
||||
"image width for viewing in landscape mode.")),
|
||||
help="Keep aspect ratio and scale image using screen height as "
|
||||
"image width for viewing in landscape mode."),
|
||||
OptionRecommendation(name='right2left', recommended_value=False,
|
||||
help=_('Used for right-to-left publications like manga. '
|
||||
'Causes landscape pages to be split into portrait pages '
|
||||
'from right to left.')),
|
||||
help='Used for right-to-left publications like manga. '
|
||||
'Causes landscape pages to be split into portrait pages '
|
||||
'from right to left.'),
|
||||
OptionRecommendation(name='despeckle', recommended_value=False,
|
||||
help=_('Enable Despeckle. Reduces speckle noise. '
|
||||
'May greatly increase processing time.')),
|
||||
help='Enable Despeckle. Reduces speckle noise. May greatly '
|
||||
'increase processing time.'),
|
||||
OptionRecommendation(name='no_sort', recommended_value=False,
|
||||
help=_("Don't sort the files found in the comic "
|
||||
"alphabetically by name. Instead use the order they were "
|
||||
"added to the comic.")),
|
||||
help="Don't sort the files found in the comic "
|
||||
"alphabetically by name. Instead use the order they were "
|
||||
"added to the comic."),
|
||||
OptionRecommendation(name='output_format', choices=['png', 'jpg'],
|
||||
recommended_value='png', help=_('The format that images in the created e-book '
|
||||
'are converted to. You can experiment to see which format gives '
|
||||
'you optimal size and look on your device.')),
|
||||
recommended_value='png',
|
||||
help='The format that images in the created e-book are '
|
||||
'converted to. You can experiment to see which format '
|
||||
'gives you optimal size and look on your device.'),
|
||||
OptionRecommendation(name='no_process', recommended_value=False,
|
||||
help=_("Apply no processing to the image")),
|
||||
help="Apply no processing to the image"),
|
||||
OptionRecommendation(name='dont_grayscale', recommended_value=False,
|
||||
help=_('Do not convert the image to grayscale (black and white)')),
|
||||
help='Do not convert the image to grayscale (black and white)'),
|
||||
OptionRecommendation(name='comic_image_size', recommended_value=None,
|
||||
help=_('Specify the image size as widthxheight pixels. Normally,'
|
||||
' an image size is automatically calculated from the output '
|
||||
'profile, this option overrides it.')),
|
||||
help='Specify the image size as widthxheight pixels. Normally,'
|
||||
' an image size is automatically calculated from the output '
|
||||
'profile, this option overrides it.'),
|
||||
OptionRecommendation(name='dont_add_comic_pages_to_toc', recommended_value=False,
|
||||
help=_('When converting a CBC do not add links to each page to'
|
||||
' the TOC. Note this only applies if the TOC has more than one'
|
||||
' section')),
|
||||
help='When converting a CBC do not add links to each page to'
|
||||
' the TOC. Note this only applies if the TOC has more than '
|
||||
'one section'),
|
||||
}
|
||||
|
||||
recommendations = {
|
||||
@@ -192,7 +195,7 @@ class ComicInput(InputFormatPlugin):
|
||||
raise ValueError('No comic pages found in %s'%stream.name)
|
||||
|
||||
mi = MetaInformation(os.path.basename(stream.name).rpartition('.')[0],
|
||||
[_('Unknown')])
|
||||
['Unknown'])
|
||||
opf = OPFCreator(os.getcwd(), mi)
|
||||
entries = []
|
||||
|
||||
@@ -222,7 +225,7 @@ class ComicInput(InputFormatPlugin):
|
||||
if len(comics) == 1:
|
||||
wrappers = comics[0][2]
|
||||
for i, x in enumerate(wrappers):
|
||||
toc.add_item(href(x), None, _('Page')+' %d'%(i+1),
|
||||
toc.add_item(href(x), None, 'Page %d' % (i+1),
|
||||
play_order=i)
|
||||
else:
|
||||
po = 0
|
||||
@@ -234,7 +237,7 @@ class ComicInput(InputFormatPlugin):
|
||||
if not opts.dont_add_comic_pages_to_toc:
|
||||
for i, x in enumerate(wrappers):
|
||||
stoc.add_item(href(x), None,
|
||||
_('Page')+' %d'%(i+1), play_order=po)
|
||||
'Page %d' % (i+1), play_order=po)
|
||||
po += 1
|
||||
opf.set_toc(toc)
|
||||
with open('metadata.opf', 'wb') as m, open('toc.ncx', 'wb') as n:
|
||||
|
||||
@@ -8,19 +8,21 @@ __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
class DOCXInput(InputFormatPlugin):
|
||||
name = 'DOCX Input'
|
||||
author = 'Kovid Goyal'
|
||||
description = _('Convert DOCX files (.docx and .docm) to HTML')
|
||||
description = 'Convert DOCX files (.docx and .docm) to HTML'
|
||||
file_types = {'docx', 'docm'}
|
||||
commit_name = 'docx_input'
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='docx_no_cover', recommended_value=False,
|
||||
help=_('Normally, if a large image is present at the start of the document that looks like a cover, '
|
||||
'it will be removed from the document and used as the cover for created e-book. This option '
|
||||
'turns off that behavior.')),
|
||||
help='Normally, if a large image is present at the start of the '
|
||||
'document that looks like a cover, it will be removed from '
|
||||
'the document and used as the cover for created e-book. This '
|
||||
'option turns off that behavior.'),
|
||||
OptionRecommendation(name='docx_no_pagebreaks_between_notes', recommended_value=False,
|
||||
help=_('Do not insert a page break after every endnote.')),
|
||||
help='Do not insert a page break after every endnote.'),
|
||||
OptionRecommendation(name='docx_inline_subsup', recommended_value=False,
|
||||
help=_('Render superscripts and subscripts so that they do not affect the line height.')),
|
||||
help='Render superscripts and subscripts so that they do not '
|
||||
'affect the line height.'),
|
||||
}
|
||||
|
||||
recommendations = {('page_breaks_before', '/', OptionRecommendation.MED)}
|
||||
|
||||
@@ -19,52 +19,52 @@ class DOCXOutput(OutputFormatPlugin):
|
||||
options = {
|
||||
OptionRecommendation(name='docx_page_size', recommended_value='letter',
|
||||
level=OptionRecommendation.LOW, choices=PAGE_SIZES,
|
||||
help=_('The size of the page. Default is letter. Choices '
|
||||
'are %s') % PAGE_SIZES),
|
||||
help='The size of the page. Default is letter. Choices '
|
||||
'are %s' % PAGE_SIZES),
|
||||
|
||||
OptionRecommendation(name='docx_custom_page_size', recommended_value=None,
|
||||
help=_('Custom size of the document. Use the form widthxheight '
|
||||
help='Custom size of the document. Use the form widthxheight '
|
||||
'EG. `123x321` to specify the width and height (in pts). '
|
||||
'This overrides any specified page-size.')),
|
||||
'This overrides any specified page-size.'),
|
||||
|
||||
OptionRecommendation(name='docx_no_cover', recommended_value=False,
|
||||
help=_('Do not insert the book cover as an image at the start of the document.'
|
||||
' If you use this option, the book cover will be discarded.')),
|
||||
help='Do not insert the book cover as an image at the start of the document.'
|
||||
' If you use this option, the book cover will be discarded.'),
|
||||
|
||||
OptionRecommendation(name='preserve_cover_aspect_ratio', recommended_value=False,
|
||||
help=_('Preserve the aspect ratio of the cover image instead of stretching'
|
||||
' it out to cover the entire page.')),
|
||||
help='Preserve the aspect ratio of the cover image instead of stretching'
|
||||
' it out to cover the entire page.'),
|
||||
|
||||
OptionRecommendation(name='docx_no_toc', recommended_value=False,
|
||||
help=_('Do not insert the table of contents as a page at the start of the document.')),
|
||||
help='Do not insert the table of contents as a page at the start of the document.'),
|
||||
|
||||
OptionRecommendation(name='extract_to',
|
||||
help=_('Extract the contents of the generated %s file to the '
|
||||
help='Extract the contents of the generated %s file to the '
|
||||
'specified directory. The contents of the directory are first '
|
||||
'deleted, so be careful.') % 'DOCX'),
|
||||
'deleted, so be careful.' % 'DOCX'),
|
||||
|
||||
OptionRecommendation(name='docx_page_margin_left', recommended_value=72.0,
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The size of the left page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common left page margin setting.')
|
||||
help='The size of the left page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common left page margin setting.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='docx_page_margin_top', recommended_value=72.0,
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The size of the top page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common top page margin setting, unless set to zero.')
|
||||
help='The size of the top page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common top page margin setting, unless set to zero.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='docx_page_margin_right', recommended_value=72.0,
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The size of the right page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common right page margin setting, unless set to zero.')
|
||||
help='The size of the right page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common right page margin setting, unless set to zero.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='docx_page_margin_bottom', recommended_value=72.0,
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The size of the bottom page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common bottom page margin setting, unless set to zero.')
|
||||
help='The size of the bottom page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common bottom page margin setting, unless set to zero.'
|
||||
),
|
||||
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@ import re
|
||||
import shutil
|
||||
import urllib.parse
|
||||
|
||||
from ebook_converter.customize.conversion import (OutputFormatPlugin,
|
||||
OptionRecommendation)
|
||||
from ebook_converter.customize.conversion import OutputFormatPlugin
|
||||
from ebook_converter.customize.conversion import OptionRecommendation
|
||||
|
||||
from ebook_converter.ptempfile import TemporaryDirectory
|
||||
from ebook_converter import CurrentDir
|
||||
from ebook_converter.polyglot.builtins import as_bytes
|
||||
@@ -53,78 +54,79 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='extract_to',
|
||||
help=_('Extract the contents of the generated %s file to the '
|
||||
'specified directory. The contents of the directory are first '
|
||||
'deleted, so be careful.') % 'EPUB'),
|
||||
help='Extract the contents of the generated %s file to the '
|
||||
'specified directory. The contents of the directory are '
|
||||
'first deleted, so be careful.' % 'EPUB'),
|
||||
|
||||
OptionRecommendation(name='dont_split_on_page_breaks',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Turn off splitting at page breaks. Normally, input '
|
||||
'files are automatically split at every page break into '
|
||||
'two files. This gives an output e-book that can be '
|
||||
'parsed faster and with less resources. However, '
|
||||
'splitting is slow and if your source file contains a '
|
||||
'very large number of page breaks, you should turn off '
|
||||
'splitting on page breaks.'
|
||||
)
|
||||
help='Turn off splitting at page breaks. Normally, input '
|
||||
'files are automatically split at every page break into '
|
||||
'two files. This gives an output e-book that can be '
|
||||
'parsed faster and with less resources. However, '
|
||||
'splitting is slow and if your source file contains a '
|
||||
'very large number of page breaks, you should turn off '
|
||||
'splitting on page breaks.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='flow_size', recommended_value=260,
|
||||
help=_('Split all HTML files larger than this size (in KB). '
|
||||
'This is necessary as most EPUB readers cannot handle large '
|
||||
'file sizes. The default of %defaultKB is the size required '
|
||||
'for Adobe Digital Editions. Set to 0 to disable size based splitting.')
|
||||
help='Split all HTML files larger than this size (in KB). '
|
||||
'This is necessary as most EPUB readers cannot handle large '
|
||||
'file sizes. The default of %defaultKB is the size required '
|
||||
'for Adobe Digital Editions. Set to 0 to disable size based '
|
||||
'splitting.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='no_default_epub_cover', recommended_value=False,
|
||||
help=_('Normally, if the input file has no cover and you don\'t'
|
||||
help='Normally, if the input file has no cover and you don\'t'
|
||||
' specify one, a default cover is generated with the title, '
|
||||
'authors, etc. This option disables the generation of this cover.')
|
||||
'authors, etc. This option disables the generation of this cover.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='no_svg_cover', recommended_value=False,
|
||||
help=_('Do not use SVG for the book cover. Use this option if '
|
||||
help='Do not use SVG for the book cover. Use this option if '
|
||||
'your EPUB is going to be used on a device that does not '
|
||||
'support SVG, like the iPhone or the JetBook Lite. '
|
||||
'Without this option, such devices will display the cover '
|
||||
'as a blank page.')
|
||||
'as a blank page.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='preserve_cover_aspect_ratio',
|
||||
recommended_value=False, help=_(
|
||||
'When using an SVG cover, this option will cause the cover to scale '
|
||||
'to cover the available screen area, but still preserve its aspect ratio '
|
||||
'(ratio of width to height). That means there may be white borders '
|
||||
'at the sides or top and bottom of the image, but the image will '
|
||||
'never be distorted. Without this option the image may be slightly '
|
||||
'distorted, but there will be no borders.'
|
||||
)
|
||||
recommended_value=False,
|
||||
help='When using an SVG cover, this option will cause the cover '
|
||||
'to scale to cover the available screen area, but still '
|
||||
'preserve its aspect ratio (ratio of width to height). That '
|
||||
'means there may be white borders at the sides or top and '
|
||||
'bottom of the image, but the image will never be distorted. '
|
||||
'Without this option the image may be slightly distorted, '
|
||||
'but there will be no borders.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='epub_flatten', recommended_value=False,
|
||||
help=_('This option is needed only if you intend to use the EPUB'
|
||||
' with FBReaderJ. It will flatten the file system inside the'
|
||||
' EPUB, putting all files into the top level.')
|
||||
help='This option is needed only if you intend to use the EPUB'
|
||||
' with FBReaderJ. It will flatten the file system inside the'
|
||||
' EPUB, putting all files into the top level.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='epub_inline_toc', recommended_value=False,
|
||||
help=_('Insert an inline Table of Contents that will appear as part of the main book content.')
|
||||
help='Insert an inline Table of Contents that will appear as part '
|
||||
'of the main book content.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='epub_toc_at_end', recommended_value=False,
|
||||
help=_('Put the inserted inline Table of Contents at the end of the book instead of the start.')
|
||||
help='Put the inserted inline Table of Contents at the end of '
|
||||
'the book instead of the start.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='toc_title', recommended_value=None,
|
||||
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=ui_data['versions'],
|
||||
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.')
|
||||
),
|
||||
|
||||
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 = {('pretty_print', True, OptionRecommendation.HIGH)}
|
||||
@@ -219,7 +221,7 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
self.log.warn('This EPUB file has no Table of Contents. '
|
||||
'Creating a default TOC')
|
||||
first = next(iter(self.oeb.spine))
|
||||
self.oeb.toc.add(_('Start'), first.href)
|
||||
self.oeb.toc.add('Start', first.href)
|
||||
|
||||
from ebook_converter.ebooks.oeb.base import OPF
|
||||
identifiers = oeb.metadata['identifier']
|
||||
|
||||
@@ -32,8 +32,7 @@ class FB2Input(InputFormatPlugin):
|
||||
options = {
|
||||
OptionRecommendation(name='no_inline_fb2_toc',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Do not insert a Table of Contents at the beginning of the book.'
|
||||
)
|
||||
help='Do not insert a Table of Contents at the beginning of the book.'
|
||||
)}
|
||||
|
||||
def convert(self, stream, options, file_ext, log,
|
||||
@@ -129,9 +128,9 @@ class FB2Input(InputFormatPlugin):
|
||||
stream.seek(0)
|
||||
mi = get_metadata(stream, 'fb2')
|
||||
if not mi.title:
|
||||
mi.title = _('Unknown')
|
||||
mi.title = 'Unknown'
|
||||
if not mi.authors:
|
||||
mi.authors = [_('Unknown')]
|
||||
mi.authors = ['Unknown']
|
||||
cpath = None
|
||||
if mi.cover_data and mi.cover_data[1]:
|
||||
with open('fb2_cover_calibre_mi.jpg', 'wb') as f:
|
||||
|
||||
@@ -141,31 +141,31 @@ class FB2Output(OutputFormatPlugin):
|
||||
'home_sex', # Erotica & sex
|
||||
'home', # Other
|
||||
]
|
||||
ui_data = {
|
||||
'sectionize': {
|
||||
'toc': _('Section per entry in the ToC'),
|
||||
'files': _('Section per file'),
|
||||
'nothing': _('A single section')
|
||||
},
|
||||
'genres': FB2_GENRES,
|
||||
}
|
||||
ui_data = {'sectionize': {'toc': 'Section per entry in the ToC',
|
||||
'files': 'Section per file',
|
||||
'nothing': 'A single section'},
|
||||
'genres': FB2_GENRES}
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='sectionize',
|
||||
recommended_value='files', level=OptionRecommendation.LOW,
|
||||
choices=list(ui_data['sectionize']),
|
||||
help=_('Specify how sections are created:\n'
|
||||
' * nothing: {nothing}\n'
|
||||
' * files: {files}\n'
|
||||
' * toc: {toc}\n'
|
||||
'If ToC based generation fails, adjust the "Structure detection" and/or "Table of Contents" settings '
|
||||
'(turn on "Force use of auto-generated Table of Contents").').format(**ui_data['sectionize'])
|
||||
help='Specify how sections are created:\n'
|
||||
' * nothing: {nothing}\n'
|
||||
' * files: {files}\n'
|
||||
' * toc: {toc}\n'
|
||||
'If ToC based generation fails, adjust the "Structure '
|
||||
'detection" and/or "Table of Contents" settings (turn on '
|
||||
'"Force use of auto-generated Table of Contents")'
|
||||
'.'.format(**ui_data['sectionize'])
|
||||
),
|
||||
OptionRecommendation(name='fb2_genre',
|
||||
recommended_value='antique', level=OptionRecommendation.LOW,
|
||||
choices=FB2_GENRES,
|
||||
help=(_('Genre for the book. Choices: %s\n\n See: ') % ', '.join(FB2_GENRES)
|
||||
) + 'http://www.fictionbook.org/index.php/Eng:FictionBook_2.1_genres ' + _('for a complete list with descriptions.')),
|
||||
help='Genre for the book. Choices: %s\n\n See: http://www.'
|
||||
'fictionbook.org/index.php/Eng:FictionBook_2.1_genres for a '
|
||||
'complete list with descriptions.' % ', '.join(FB2_GENRES)),
|
||||
|
||||
}
|
||||
|
||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||
|
||||
@@ -35,27 +35,24 @@ class HTMLInput(InputFormatPlugin):
|
||||
options = {
|
||||
OptionRecommendation(name='breadth_first',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Traverse links in HTML files breadth first. Normally, '
|
||||
help='Traverse links in HTML files breadth first. Normally, '
|
||||
'they are traversed depth first.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='max_levels',
|
||||
recommended_value=5, level=OptionRecommendation.LOW,
|
||||
help=_('Maximum levels of recursion when following links in '
|
||||
help='Maximum levels of recursion when following links in '
|
||||
'HTML files. Must be non-negative. 0 implies that no '
|
||||
'links in the root HTML file are followed. Default is '
|
||||
'%default.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='dont_package',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Normally this input plugin re-arranges all the input '
|
||||
help='Normally this input plugin re-arranges all the input '
|
||||
'files into a standard folder hierarchy. Only use this option '
|
||||
'if you know what you are doing as it can result in various '
|
||||
'nasty side effects in the rest of the conversion pipeline.'
|
||||
)
|
||||
),
|
||||
|
||||
}
|
||||
@@ -129,12 +126,12 @@ class HTMLInput(InputFormatPlugin):
|
||||
a = string_to_authors(a)
|
||||
if not a:
|
||||
oeb.logger.warn('Creator not specified')
|
||||
a = [self.oeb.translate(__('Unknown'))]
|
||||
a = [self.oeb.translate('Unknown')]
|
||||
for aut in a:
|
||||
metadata.add('creator', aut)
|
||||
if not metadata.title:
|
||||
oeb.logger.warn('Title not specified')
|
||||
metadata.add('title', self.oeb.translate(__('Unknown')))
|
||||
metadata.add('title', self.oeb.translate('Unknown'))
|
||||
bookid = str(uuid.uuid4())
|
||||
metadata.add('identifier', bookid, id='uuid_id', scheme='uuid')
|
||||
for ident in metadata.identifier:
|
||||
|
||||
@@ -30,18 +30,18 @@ class HTMLOutput(OutputFormatPlugin):
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='template_css',
|
||||
help=_('CSS file used for the output instead of the default file')),
|
||||
help='CSS file used for the output instead of the default file'),
|
||||
|
||||
OptionRecommendation(name='template_html_index',
|
||||
help=_('Template used for generation of the HTML index file instead of the default file')),
|
||||
help='Template used for generation of the HTML index file instead of the default file'),
|
||||
|
||||
OptionRecommendation(name='template_html',
|
||||
help=_('Template used for the generation of the HTML contents of the book instead of the default file')),
|
||||
help='Template used for the generation of the HTML contents of the book instead of the default file'),
|
||||
|
||||
OptionRecommendation(name='extract_to',
|
||||
help=_('Extract the contents of the generated ZIP file to the '
|
||||
help='Extract the contents of the generated ZIP file to the '
|
||||
'specified directory. WARNING: The contents of the directory '
|
||||
'will be deleted.')
|
||||
'will be deleted.'
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
@@ -59,16 +59,17 @@ class HTMLZInput(InputFormatPlugin):
|
||||
# HTMLZ archive probably won't turn out as the user expects. With
|
||||
# Multiple HTML files ZIP input should be used in place of HTMLZ.
|
||||
if multiple_html:
|
||||
log.warn(_('Multiple HTML files found in the archive. Only %s will be used.') % index)
|
||||
log.warn('Multiple HTML files found in the archive. Only %s will '
|
||||
'be used.' % index)
|
||||
|
||||
if index:
|
||||
with open(index, 'rb') as tf:
|
||||
html = tf.read()
|
||||
else:
|
||||
raise Exception(_('No top level HTML file found.'))
|
||||
raise Exception('No top level HTML file found.')
|
||||
|
||||
if not html:
|
||||
raise Exception(_('Top level HTML file %s is empty') % index)
|
||||
raise Exception('Top level HTML file %s is empty' % index)
|
||||
|
||||
# Encoding
|
||||
if options.input_encoding:
|
||||
|
||||
@@ -17,40 +17,33 @@ class HTMLZOutput(OutputFormatPlugin):
|
||||
author = 'John Schember'
|
||||
file_type = 'htmlz'
|
||||
commit_name = 'htmlz_output'
|
||||
ui_data = {
|
||||
'css_choices': {
|
||||
'class': _('Use CSS classes'),
|
||||
'inline': _('Use the style attribute'),
|
||||
'tag': _('Use HTML tags wherever possible')
|
||||
},
|
||||
'sheet_choices': {
|
||||
'external': _('Use an external CSS file'),
|
||||
'inline': _('Use a <style> tag in the HTML file')
|
||||
}
|
||||
}
|
||||
ui_data = {'css_choices': {'class': 'Use CSS classes',
|
||||
'inline': 'Use the style attribute',
|
||||
'tag': 'Use HTML tags wherever possible'},
|
||||
'sheet_choices': {'external': 'Use an external CSS file',
|
||||
'inline': 'Use a <style> tag in the HTML '
|
||||
'file'}}
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='htmlz_css_type', recommended_value='class',
|
||||
level=OptionRecommendation.LOW,
|
||||
choices=list(ui_data['css_choices']),
|
||||
help=_('Specify the handling of CSS. Default is class.\n'
|
||||
'class: {class}\n'
|
||||
'inline: {inline}\n'
|
||||
'tag: {tag}'
|
||||
).format(**ui_data['css_choices'])),
|
||||
help='Specify the handling of CSS. Default is class.\n'
|
||||
'class: {class}\n'
|
||||
'inline: {inline}\n'
|
||||
'tag: {tag}'.format(**ui_data['css_choices'])),
|
||||
OptionRecommendation(name='htmlz_class_style', recommended_value='external',
|
||||
level=OptionRecommendation.LOW,
|
||||
choices=list(ui_data['sheet_choices']),
|
||||
help=_('How to handle the CSS when using css-type = \'class\'.\n'
|
||||
'Default is external.\n'
|
||||
'external: {external}\n'
|
||||
'inline: {inline}'
|
||||
).format(**ui_data['sheet_choices'])),
|
||||
help='How to handle the CSS when using css-type = \'class\'.\n'
|
||||
'Default is external.\n'
|
||||
'external: {external}\n'
|
||||
'inline: {inline}'.format(**ui_data['sheet_choices'])),
|
||||
OptionRecommendation(name='htmlz_title_filename',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('If set this option causes the file name of the HTML file'
|
||||
' inside the HTMLZ archive to be based on the book title.')
|
||||
),
|
||||
help='If set this option causes the file name of the HTML file '
|
||||
'inside the HTMLZ archive to be based on the book title.'
|
||||
)
|
||||
}
|
||||
|
||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||
|
||||
@@ -24,7 +24,7 @@ class LRFOptions(object):
|
||||
if val < 0:
|
||||
setattr(opts, attr, 0)
|
||||
self.title = None
|
||||
self.author = self.publisher = _('Unknown')
|
||||
self.author = self.publisher = 'Unknown'
|
||||
self.title_sort = self.author_sort = ''
|
||||
for x in m.creator:
|
||||
if x.role == 'aut':
|
||||
@@ -91,43 +91,44 @@ class LRFOutput(OutputFormatPlugin):
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='enable_autorotation', recommended_value=False,
|
||||
help=_('Enable auto-rotation of images that are wider than the screen width.')
|
||||
help='Enable auto-rotation of images that are wider than the '
|
||||
'screen width.'
|
||||
),
|
||||
OptionRecommendation(name='wordspace',
|
||||
recommended_value=2.5, level=OptionRecommendation.LOW,
|
||||
help=_('Set the space between words in pts. Default is %default')
|
||||
help='Set the space between words in pts. Default is %default'
|
||||
),
|
||||
OptionRecommendation(name='header', recommended_value=False,
|
||||
help=_('Add a header to all the pages with title and author.')
|
||||
help='Add a header to all the pages with title and author.'
|
||||
),
|
||||
OptionRecommendation(name='header_format', recommended_value="%t by %a",
|
||||
help=_('Set the format of the header. %a is replaced by the author '
|
||||
'and %t by the title. Default is %default')
|
||||
help='Set the format of the header. %a is replaced by the author '
|
||||
'and %t by the title. Default is %default'
|
||||
),
|
||||
OptionRecommendation(name='header_separation', recommended_value=0,
|
||||
help=_('Add extra spacing below the header. Default is %default pt.')
|
||||
help='Add extra spacing below the header. Default is %default pt.'
|
||||
),
|
||||
OptionRecommendation(name='minimum_indent', recommended_value=0,
|
||||
help=_('Minimum paragraph indent (the indent of the first line '
|
||||
'of a paragraph) in pts. Default: %default')
|
||||
help='Minimum paragraph indent (the indent of the first line '
|
||||
'of a paragraph) in pts. Default: %default'
|
||||
),
|
||||
OptionRecommendation(name='render_tables_as_images',
|
||||
recommended_value=False,
|
||||
help=_('This option has no effect')
|
||||
help='This option has no effect'
|
||||
),
|
||||
OptionRecommendation(name='text_size_multiplier_for_rendered_tables',
|
||||
recommended_value=1.0,
|
||||
help=_('Multiply the size of text in rendered tables by this '
|
||||
'factor. Default is %default')
|
||||
help='Multiply the size of text in rendered tables by this '
|
||||
'factor. Default is %default'
|
||||
),
|
||||
OptionRecommendation(name='serif_family', recommended_value=None,
|
||||
help=_('The serif family of fonts to embed')
|
||||
help='The serif family of fonts to embed'
|
||||
),
|
||||
OptionRecommendation(name='sans_family', recommended_value=None,
|
||||
help=_('The sans-serif family of fonts to embed')
|
||||
help='The sans-serif family of fonts to embed'
|
||||
),
|
||||
OptionRecommendation(name='mono_family', recommended_value=None,
|
||||
help=_('The monospace family of fonts to embed')
|
||||
help='The monospace family of fonts to embed'
|
||||
),
|
||||
|
||||
}
|
||||
@@ -151,7 +152,7 @@ class LRFOutput(OutputFormatPlugin):
|
||||
book = Book(title=opts.title, author=opts.author,
|
||||
bookid=uuid4().hex,
|
||||
publisher='%s %s'%(__appname__, __version__),
|
||||
category=_('Comic'), pagestyledefault=ps,
|
||||
category='Comic', pagestyledefault=ps,
|
||||
booksetting=BookSetting(screenwidth=width, screenheight=height))
|
||||
for page in pages:
|
||||
imageStream = ImageStream(page)
|
||||
|
||||
@@ -44,64 +44,64 @@ class MOBIOutput(OutputFormatPlugin):
|
||||
options = {
|
||||
OptionRecommendation(name='prefer_author_sort',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('When present, use author sort field as author.')
|
||||
help='When present, use author sort field as author.'
|
||||
),
|
||||
OptionRecommendation(name='no_inline_toc',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Don\'t add Table of Contents to the book. Useful if '
|
||||
'the book has its own table of contents.')),
|
||||
help='Don\'t add Table of Contents to the book. Useful if '
|
||||
'the book has its own table of contents.'),
|
||||
OptionRecommendation(name='toc_title', recommended_value=None,
|
||||
help=_('Title for any generated in-line table of contents.')
|
||||
help='Title for any generated in-line table of contents.'
|
||||
),
|
||||
OptionRecommendation(name='dont_compress',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Disable compression of the file contents.')
|
||||
help='Disable compression of the file contents.'
|
||||
),
|
||||
OptionRecommendation(name='personal_doc', recommended_value='[PDOC]',
|
||||
help=_('Tag for MOBI files to be marked as personal documents.'
|
||||
help='Tag for MOBI files to be marked as personal documents.'
|
||||
' This option has no effect on the conversion. It is used'
|
||||
' only when sending MOBI files to a device. If the file'
|
||||
' being sent has the specified tag, it will be marked as'
|
||||
' a personal document when sent to the Kindle.')
|
||||
' a personal document when sent to the Kindle.'
|
||||
),
|
||||
OptionRecommendation(name='mobi_ignore_margins',
|
||||
recommended_value=False,
|
||||
help=_('Ignore margins in the input document. If False, then '
|
||||
help='Ignore margins in the input document. If False, then '
|
||||
'the MOBI output plugin will try to convert margins specified'
|
||||
' in the input document, otherwise it will ignore them.')
|
||||
' in the input document, otherwise it will ignore them.'
|
||||
),
|
||||
OptionRecommendation(name='mobi_toc_at_start',
|
||||
recommended_value=False,
|
||||
help=_('When adding the Table of Contents to the book, add it at the start of the '
|
||||
'book instead of the end. Not recommended.')
|
||||
help='When adding the Table of Contents to the book, add it at the start of the '
|
||||
'book instead of the end. Not recommended.'
|
||||
),
|
||||
OptionRecommendation(name='extract_to',
|
||||
help=_('Extract the contents of the generated %s file to the '
|
||||
help='Extract the contents of the generated %s file to the '
|
||||
'specified directory. The contents of the directory are first '
|
||||
'deleted, so be careful.') % 'MOBI'
|
||||
'deleted, so be careful.' % 'MOBI'
|
||||
),
|
||||
OptionRecommendation(name='share_not_sync', recommended_value=False,
|
||||
help=_('Enable sharing of book content via Facebook etc. '
|
||||
help='Enable sharing of book content via Facebook etc. '
|
||||
' on the Kindle. WARNING: Using this feature means that '
|
||||
' the book will not auto sync its last read position '
|
||||
' on multiple devices. Complain to Amazon.')
|
||||
' on multiple devices. Complain to Amazon.'
|
||||
),
|
||||
OptionRecommendation(name='mobi_keep_original_images',
|
||||
recommended_value=False,
|
||||
help=_('By default calibre converts all images to JPEG format '
|
||||
help='By default calibre converts all images to JPEG format '
|
||||
'in the output MOBI file. This is for maximum compatibility '
|
||||
'as some older MOBI viewers have problems with other image '
|
||||
'formats. This option tells calibre not to do this. '
|
||||
'Useful if your document contains lots of GIF/PNG images that '
|
||||
'become very large when converted to JPEG.')),
|
||||
'become very large when converted to JPEG.'),
|
||||
OptionRecommendation(name='mobi_file_type', choices=ui_data['file_types'], recommended_value='old',
|
||||
help=_('By default calibre generates MOBI files that contain the '
|
||||
help='By default calibre generates MOBI files that contain the '
|
||||
'old MOBI 6 format. This format is compatible with all '
|
||||
'devices. However, by changing this setting, you can tell '
|
||||
'calibre to generate MOBI files that contain both MOBI 6 and '
|
||||
'the new KF8 format, or only the new KF8 format. KF8 has '
|
||||
'more features than MOBI 6, but only works with newer Kindles. '
|
||||
'Allowed values: {}').format('old, both, new')),
|
||||
'Allowed values: {}'.format('old, both, new'))
|
||||
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ class MOBIOutput(OutputFormatPlugin):
|
||||
# single section periodical
|
||||
self.oeb.manifest.remove(one)
|
||||
self.oeb.manifest.remove(two)
|
||||
sections = [TOC(klass='section', title=_('All articles'),
|
||||
sections = [TOC(klass='section', title='All articles',
|
||||
href=self.oeb.spine[0].href)]
|
||||
for x in toc:
|
||||
sections[0].nodes.append(x)
|
||||
@@ -274,34 +274,34 @@ class AZW3Output(OutputFormatPlugin):
|
||||
options = {
|
||||
OptionRecommendation(name='prefer_author_sort',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('When present, use author sort field as author.')
|
||||
help='When present, use author sort field as author.'
|
||||
),
|
||||
OptionRecommendation(name='no_inline_toc',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Don\'t add Table of Contents to the book. Useful if '
|
||||
'the book has its own table of contents.')),
|
||||
help='Don\'t add Table of Contents to the book. Useful if '
|
||||
'the book has its own table of contents.'),
|
||||
OptionRecommendation(name='toc_title', recommended_value=None,
|
||||
help=_('Title for any generated in-line table of contents.')
|
||||
help='Title for any generated in-line table of contents.'
|
||||
),
|
||||
OptionRecommendation(name='dont_compress',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Disable compression of the file contents.')
|
||||
help='Disable compression of the file contents.'
|
||||
),
|
||||
OptionRecommendation(name='mobi_toc_at_start',
|
||||
recommended_value=False,
|
||||
help=_('When adding the Table of Contents to the book, add it at the start of the '
|
||||
'book instead of the end. Not recommended.')
|
||||
help='When adding the Table of Contents to the book, add it at the start of the '
|
||||
'book instead of the end. Not recommended.'
|
||||
),
|
||||
OptionRecommendation(name='extract_to',
|
||||
help=_('Extract the contents of the generated %s file to the '
|
||||
help='Extract the contents of the generated %s file to the '
|
||||
'specified directory. The contents of the directory are first '
|
||||
'deleted, so be careful.') % 'AZW3'),
|
||||
'deleted, so be careful.' % 'AZW3'),
|
||||
OptionRecommendation(name='share_not_sync', recommended_value=False,
|
||||
help=_('Enable sharing of book content via Facebook etc. '
|
||||
help='Enable sharing of book content via Facebook etc. '
|
||||
' on the Kindle. WARNING: Using this feature means that '
|
||||
' the book will not auto sync its last read position '
|
||||
' on multiple devices. Complain to Amazon.')
|
||||
),
|
||||
' on multiple devices. Complain to Amazon.'
|
||||
)
|
||||
}
|
||||
|
||||
def convert(self, oeb, output_path, input_plugin, opts, log):
|
||||
|
||||
@@ -25,8 +25,10 @@ class PDBInput(InputFormatPlugin):
|
||||
Reader = get_reader(header.ident)
|
||||
|
||||
if Reader is None:
|
||||
raise PDBError('No reader available for format within container.\n Identity is %s. Book type is %s' %
|
||||
(header.ident, IDENTITY_TO_NAME.get(header.ident, _('Unknown'))))
|
||||
raise PDBError('No reader available for format within container.'
|
||||
'\n Identity is %s. Book type is %s' %
|
||||
(header.ident,
|
||||
IDENTITY_TO_NAME.get(header.ident, 'Unknown')))
|
||||
|
||||
log.debug('Detected ebook format as: %s with identity: %s' % (IDENTITY_TO_NAME[header.ident], header.ident))
|
||||
|
||||
|
||||
@@ -22,15 +22,16 @@ class PDBOutput(OutputFormatPlugin):
|
||||
OptionRecommendation(name='format', recommended_value='doc',
|
||||
level=OptionRecommendation.LOW,
|
||||
short_switch='f', choices=list(ALL_FORMAT_WRITERS),
|
||||
help=(_('Format to use inside the pdb container. Choices are:') + ' %s' % sorted(ALL_FORMAT_WRITERS))),
|
||||
help='Format to use inside the pdb container. Choices are: %s' %
|
||||
sorted(ALL_FORMAT_WRITERS)),
|
||||
OptionRecommendation(name='pdb_output_encoding', recommended_value='cp1252',
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('Specify the character encoding of the output document. '
|
||||
'The default is cp1252. Note: This option is not honored by all '
|
||||
'formats.')),
|
||||
help='Specify the character encoding of the output document. '
|
||||
'The default is cp1252. Note: This option is not honored by '
|
||||
'all formats.'),
|
||||
OptionRecommendation(name='inline_toc',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Add Table of Contents to beginning of the book.')),
|
||||
help='Add Table of Contents to beginning of the book.'),
|
||||
}
|
||||
|
||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||
|
||||
@@ -19,13 +19,13 @@ class PDFInput(InputFormatPlugin):
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='no_images', recommended_value=False,
|
||||
help=_('Do not extract images from the document')),
|
||||
help='Do not extract images from the document'),
|
||||
OptionRecommendation(name='unwrap_factor', recommended_value=0.45,
|
||||
help=_('Scale used to determine the length at which a line should '
|
||||
help='Scale used to determine the length at which a line should '
|
||||
'be unwrapped. Valid values are a decimal between 0 and 1. The '
|
||||
'default is 0.45, just below the median line length.')),
|
||||
'default is 0.45, just below the median line length.'),
|
||||
OptionRecommendation(name='new_pdf_engine', recommended_value=False,
|
||||
help=_('Use the new PDF conversion engine. Currently not operational.'))
|
||||
help='Use the new PDF conversion engine. Currently not operational.')
|
||||
}
|
||||
|
||||
def convert_new(self, stream, accelerators):
|
||||
|
||||
@@ -29,114 +29,111 @@ class PDFOutput(OutputFormatPlugin):
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='use_profile_size', recommended_value=False,
|
||||
help=_('Instead of using the paper size specified in the PDF Output options,'
|
||||
help='Instead of using the paper size specified in the PDF Output options,'
|
||||
' use a paper size corresponding to the current output profile.'
|
||||
' Useful if you want to generate a PDF for viewing on a specific device.')),
|
||||
' Useful if you want to generate a PDF for viewing on a specific device.'),
|
||||
OptionRecommendation(name='unit', recommended_value='inch',
|
||||
level=OptionRecommendation.LOW, short_switch='u', choices=UNITS,
|
||||
help=_('The unit of measure for page sizes. Default is inch. Choices '
|
||||
help='The unit of measure for page sizes. Default is inch. Choices '
|
||||
'are {} '
|
||||
'Note: This does not override the unit for margins!').format(', '.join(UNITS))),
|
||||
'Note: This does not override the unit for margins!'.format(', '.join(UNITS))),
|
||||
OptionRecommendation(name='paper_size', recommended_value='letter',
|
||||
level=OptionRecommendation.LOW, choices=PAPER_SIZES,
|
||||
help=_('The size of the paper. This size will be overridden when a '
|
||||
help='The size of the paper. This size will be overridden when a '
|
||||
'non default output profile is used. Default is letter. Choices '
|
||||
'are {}').format(', '.join(PAPER_SIZES))),
|
||||
'are {}'.format(', '.join(PAPER_SIZES))),
|
||||
OptionRecommendation(name='custom_size', recommended_value=None,
|
||||
help=_('Custom size of the document. Use the form widthxheight '
|
||||
help='Custom size of the document. Use the form widthxheight '
|
||||
'e.g. `123x321` to specify the width and height. '
|
||||
'This overrides any specified paper-size.')),
|
||||
'This overrides any specified paper-size.'),
|
||||
OptionRecommendation(name='preserve_cover_aspect_ratio',
|
||||
recommended_value=False,
|
||||
help=_('Preserve the aspect ratio of the cover, instead'
|
||||
help='Preserve the aspect ratio of the cover, instead'
|
||||
' of stretching it to fill the full first page of the'
|
||||
' generated pdf.')),
|
||||
' generated pdf.'),
|
||||
OptionRecommendation(name='pdf_serif_family',
|
||||
recommended_value='Times', help=_(
|
||||
'The font family used to render serif fonts. Will work only if the font is available system-wide.')),
|
||||
recommended_value='Times', help=
|
||||
'The font family used to render serif fonts. Will work only if the font is available system-wide.'),
|
||||
OptionRecommendation(name='pdf_sans_family',
|
||||
recommended_value='Helvetica', help=_(
|
||||
'The font family used to render sans-serif fonts. Will work only if the font is available system-wide.')),
|
||||
recommended_value='Helvetica', help=
|
||||
'The font family used to render sans-serif fonts. Will work only if the font is available system-wide.'),
|
||||
OptionRecommendation(name='pdf_mono_family',
|
||||
recommended_value='Courier', help=_(
|
||||
'The font family used to render monospace fonts. Will work only if the font is available system-wide.')),
|
||||
recommended_value='Courier', help=
|
||||
'The font family used to render monospace fonts. Will work only if the font is available system-wide.'),
|
||||
OptionRecommendation(name='pdf_standard_font', choices=ui_data['font_types'],
|
||||
recommended_value='serif', help=_(
|
||||
'The font family used to render monospace fonts')),
|
||||
recommended_value='serif', help=
|
||||
'The font family used to render monospace fonts'),
|
||||
OptionRecommendation(name='pdf_default_font_size',
|
||||
recommended_value=20, help=_(
|
||||
'The default font size')),
|
||||
OptionRecommendation(name='pdf_mono_font_size',
|
||||
recommended_value=16, help=_(
|
||||
'The default font size for monospaced text')),
|
||||
recommended_value=20, help='The default font size'),
|
||||
OptionRecommendation(name='pdf_mono_font_size', recommended_value=16,
|
||||
help='The default font size for monospaced text'),
|
||||
OptionRecommendation(name='pdf_hyphenate', recommended_value=False,
|
||||
help=_('Break long words at the end of lines. This can give the text at the right margin a more even appearance.')),
|
||||
help='Break long words at the end of lines. This can give the text at the right margin a more even appearance.'),
|
||||
OptionRecommendation(name='pdf_mark_links', recommended_value=False,
|
||||
help=_('Surround all links with a red box, useful for debugging.')),
|
||||
help='Surround all links with a red box, useful for debugging.'),
|
||||
OptionRecommendation(name='pdf_page_numbers', recommended_value=False,
|
||||
help=_('Add page numbers to the bottom of every page in the generated PDF file. If you '
|
||||
help='Add page numbers to the bottom of every page in the generated PDF file. If you '
|
||||
'specify a footer template, it will take precedence '
|
||||
'over this option.')),
|
||||
'over this option.'),
|
||||
OptionRecommendation(name='pdf_footer_template', recommended_value=None,
|
||||
help=_('An HTML template used to generate %s on every page.'
|
||||
' The strings _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_ will be replaced by their current values.')%_('footers')),
|
||||
help='An HTML template used to generate %s on every page.'
|
||||
' The strings _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_ will be replaced by their current values.' % 'footers'),
|
||||
OptionRecommendation(name='pdf_header_template', recommended_value=None,
|
||||
help=_('An HTML template used to generate %s on every page.'
|
||||
' The strings _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_ will be replaced by their current values.')%_('headers')),
|
||||
help='An HTML template used to generate %s on every page.'
|
||||
' The strings _PAGENUM_, _TITLE_, _AUTHOR_ and _SECTION_ will be replaced by their current values.' % 'headers'),
|
||||
OptionRecommendation(name='pdf_add_toc', recommended_value=False,
|
||||
help=_('Add a Table of Contents at the end of the PDF that lists page numbers. '
|
||||
'Useful if you want to print out the PDF. If this PDF is intended for electronic use, use the PDF Outline instead.')),
|
||||
help='Add a Table of Contents at the end of the PDF that lists page numbers. '
|
||||
'Useful if you want to print out the PDF. If this PDF is intended for electronic use, use the PDF Outline instead.'),
|
||||
OptionRecommendation(name='toc_title', recommended_value=None,
|
||||
help=_('Title for generated table of contents.')
|
||||
help='Title for generated table of contents.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='pdf_page_margin_left', recommended_value=72.0,
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The size of the left page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common left page margin setting.')
|
||||
help='The size of the left page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common left page margin setting.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='pdf_page_margin_top', recommended_value=72.0,
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The size of the top page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common top page margin setting, unless set to zero.')
|
||||
help='The size of the top page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common top page margin setting, unless set to zero.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='pdf_page_margin_right', recommended_value=72.0,
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The size of the right page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common right page margin setting, unless set to zero.')
|
||||
help='The size of the right page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common right page margin setting, unless set to zero.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='pdf_page_margin_bottom', recommended_value=72.0,
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('The size of the bottom page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common bottom page margin setting, unless set to zero.')
|
||||
help='The size of the bottom page margin, in pts. Default is 72pt.'
|
||||
' Overrides the common bottom page margin setting, unless set to zero.'
|
||||
),
|
||||
OptionRecommendation(name='pdf_use_document_margins', recommended_value=False,
|
||||
help=_('Use the page margins specified in the input document via @page CSS rules.'
|
||||
help='Use the page margins specified in the input document via @page CSS rules.'
|
||||
' This will cause the margins specified in the conversion settings to be ignored.'
|
||||
' If the document does not specify page margins, the conversion settings will be used as a fallback.')
|
||||
' If the document does not specify page margins, the conversion settings will be used as a fallback.'
|
||||
),
|
||||
OptionRecommendation(name='pdf_page_number_map', recommended_value=None,
|
||||
help=_('Adjust page numbers, as needed. Syntax is a JavaScript expression for the page number.'
|
||||
' For example, "if (n < 3) 0; else n - 3;", where n is current page number.')
|
||||
help='Adjust page numbers, as needed. Syntax is a JavaScript expression for the page number.'
|
||||
' For example, "if (n < 3) 0; else n - 3;", where n is current page number.'
|
||||
),
|
||||
OptionRecommendation(name='uncompressed_pdf',
|
||||
recommended_value=False, help=_(
|
||||
'Generate an uncompressed PDF, useful for debugging.')
|
||||
recommended_value=False, help=
|
||||
'Generate an uncompressed PDF, useful for debugging.'
|
||||
),
|
||||
OptionRecommendation(name='pdf_odd_even_offset', recommended_value=0.0,
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_(
|
||||
help=
|
||||
'Shift the text horizontally by the specified offset (in pts).'
|
||||
' On odd numbered pages, it is shifted to the right and on even'
|
||||
' numbered pages to the left. Use negative numbers for the opposite'
|
||||
' effect. Note that this setting is ignored on pages where the margins'
|
||||
' are smaller than the specified offset. Shifting is done by setting'
|
||||
' the PDF CropBox, not all software respects the CropBox.'
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -20,17 +20,17 @@ class PMLOutput(OutputFormatPlugin):
|
||||
options = {
|
||||
OptionRecommendation(name='pml_output_encoding', recommended_value='cp1252',
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('Specify the character encoding of the output document. '
|
||||
'The default is cp1252.')),
|
||||
help='Specify the character encoding of the output document. '
|
||||
'The default is cp1252.'),
|
||||
OptionRecommendation(name='inline_toc',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Add Table of Contents to beginning of the book.')),
|
||||
help='Add Table of Contents to beginning of the book.'),
|
||||
OptionRecommendation(name='full_image_depth',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Do not reduce the size or bit depth of images. Images '
|
||||
help='Do not reduce the size or bit depth of images. Images '
|
||||
'have their size and depth reduced by default to accommodate '
|
||||
'applications that can not convert images on their '
|
||||
'own such as Dropbook.')),
|
||||
'own such as Dropbook.'),
|
||||
}
|
||||
|
||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||
|
||||
@@ -18,7 +18,7 @@ class RBOutput(OutputFormatPlugin):
|
||||
options = {
|
||||
OptionRecommendation(name='inline_toc',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Add Table of Contents to beginning of the book.'))}
|
||||
help='Add Table of Contents to beginning of the book.')}
|
||||
|
||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||
from ebook_converter.ebooks.rb.writer import RBWriter
|
||||
|
||||
@@ -18,7 +18,7 @@ class RecipeInput(InputFormatPlugin):
|
||||
|
||||
name = 'Recipe Input'
|
||||
author = 'Kovid Goyal'
|
||||
description = _('Download periodical content from the internet')
|
||||
description = 'Download periodical content from the internet'
|
||||
file_types = {'recipe', 'downloaded_recipe'}
|
||||
commit_name = 'recipe_input'
|
||||
|
||||
@@ -34,20 +34,19 @@ class RecipeInput(InputFormatPlugin):
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='test', recommended_value=False,
|
||||
help=_(
|
||||
'Useful for recipe development. Forces'
|
||||
' max_articles_per_feed to 2 and downloads at most 2 feeds.'
|
||||
' You can change the number of feeds and articles by supplying optional arguments.'
|
||||
' For example: --test 3 1 will download at most 3 feeds and only 1 article per feed.')),
|
||||
help='Useful for recipe development. Forces max_articles_per_feed '
|
||||
'to 2 and downloads at most 2 feeds. You can change the '
|
||||
'number of feeds and articles by supplying optional '
|
||||
'arguments. For example: --test 3 1 will download at most 3 '
|
||||
'feeds and only 1 article per feed.'),
|
||||
OptionRecommendation(name='username', recommended_value=None,
|
||||
help=_('Username for sites that require a login to access '
|
||||
'content.')),
|
||||
help='Username for sites that require a login to access content.'),
|
||||
OptionRecommendation(name='password', recommended_value=None,
|
||||
help=_('Password for sites that require a login to access '
|
||||
'content.')),
|
||||
help='Password for sites that require a login to access content.'),
|
||||
OptionRecommendation(name='dont_download_recipe',
|
||||
recommended_value=False,
|
||||
help=_('Do not download latest version of builtin recipes from the calibre server')),
|
||||
help='Do not download latest version of builtin recipes from the '
|
||||
'calibre server'),
|
||||
OptionRecommendation(name='lrf', recommended_value=False,
|
||||
help='Optimize fetching for subsequent conversion to LRF.'),
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ class RTFInput(InputFormatPlugin):
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='ignore_wmf', recommended_value=False,
|
||||
help=_('Ignore WMF images instead of replacing them with a placeholder image.')),
|
||||
help='Ignore WMF images instead of replacing them with a '
|
||||
'placeholder image.'),
|
||||
}
|
||||
|
||||
def generate_xml(self, stream):
|
||||
@@ -259,8 +260,9 @@ class RTFInput(InputFormatPlugin):
|
||||
xml = self.generate_xml(stream.name)
|
||||
except RtfInvalidCodeException as e:
|
||||
self.log.exception('Unable to parse RTF')
|
||||
raise ValueError(_('This RTF file has a feature calibre does not '
|
||||
'support. Convert it to HTML first and then try it.\n%s')%e)
|
||||
raise ValueError('This RTF file has a feature calibre does not '
|
||||
'support. Convert it to HTML first and then try '
|
||||
'it.\n%s' % e)
|
||||
|
||||
d = glob.glob(os.path.join('*_rtf_pict_dir', 'picts.rtf'))
|
||||
if d:
|
||||
@@ -303,9 +305,9 @@ class RTFInput(InputFormatPlugin):
|
||||
stream.seek(0)
|
||||
mi = get_metadata(stream, 'rtf')
|
||||
if not mi.title:
|
||||
mi.title = _('Unknown')
|
||||
mi.title = 'Unknown'
|
||||
if not mi.authors:
|
||||
mi.authors = [_('Unknown')]
|
||||
mi.authors = ['Unknown']
|
||||
opf = OPFCreator(os.getcwd(), mi)
|
||||
opf.create_manifest([(u'index.xhtml', None)])
|
||||
opf.create_spine([u'index.xhtml'])
|
||||
|
||||
@@ -20,30 +20,30 @@ class SNBOutput(OutputFormatPlugin):
|
||||
options = {
|
||||
OptionRecommendation(name='snb_output_encoding', recommended_value='utf-8',
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('Specify the character encoding of the output document. '
|
||||
'The default is utf-8.')),
|
||||
help='Specify the character encoding of the output document. '
|
||||
'The default is utf-8.'),
|
||||
OptionRecommendation(name='snb_max_line_length',
|
||||
recommended_value=0, level=OptionRecommendation.LOW,
|
||||
help=_('The maximum number of characters per line. This splits on '
|
||||
'the first space before the specified value. If no space is found '
|
||||
'the line will be broken at the space after and will exceed the '
|
||||
'specified value. Also, there is a minimum of 25 characters. '
|
||||
'Use 0 to disable line splitting.')),
|
||||
help='The maximum number of characters per line. This splits on '
|
||||
'the first space before the specified value. If no space is '
|
||||
'found the line will be broken at the space after and will '
|
||||
'exceed the specified value. Also, there is a minimum of 25 '
|
||||
'characters. Use 0 to disable line splitting.'),
|
||||
OptionRecommendation(name='snb_insert_empty_line',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Specify whether or not to insert an empty line between '
|
||||
'two paragraphs.')),
|
||||
help='Specify whether or not to insert an empty line between two '
|
||||
'paragraphs.'),
|
||||
OptionRecommendation(name='snb_dont_indent_first_line',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Specify whether or not to insert two space characters '
|
||||
'to indent the first line of each paragraph.')),
|
||||
help='Specify whether or not to insert two space characters to '
|
||||
'indent the first line of each paragraph.'),
|
||||
OptionRecommendation(name='snb_hide_chapter_name',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Specify whether or not to hide the chapter title for each '
|
||||
'chapter. Useful for image-only output (eg. comics).')),
|
||||
help='Specify whether or not to hide the chapter title for each '
|
||||
'chapter. Useful for image-only output (eg. comics).'),
|
||||
OptionRecommendation(name='snb_full_screen',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Resize all the images for full screen view. ')),
|
||||
help='Resize all the images for full screen view. '),
|
||||
}
|
||||
|
||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||
@@ -123,7 +123,7 @@ class SNBOutput(OutputFormatPlugin):
|
||||
log.warn('This SNB file has no Table of Contents. '
|
||||
'Creating a default TOC')
|
||||
first = next(iter(oeb_book.spine))
|
||||
oeb_book.toc.add(_('Start page'), first.href)
|
||||
oeb_book.toc.add('Start page', first.href)
|
||||
else:
|
||||
first = next(iter(oeb_book.spine))
|
||||
if oeb_book.toc[0].href != first.href:
|
||||
@@ -133,9 +133,9 @@ class SNBOutput(OutputFormatPlugin):
|
||||
# the tocInfoTree directly instead of modifying the toc
|
||||
ch = etree.SubElement(tocBody, "chapter")
|
||||
ch.set("src", ProcessFileName(first.href) + ".snbc")
|
||||
ch.text = _('Cover pages')
|
||||
ch.text = 'Cover pages'
|
||||
outputFiles[first.href] = []
|
||||
outputFiles[first.href].append(("", _("Cover pages")))
|
||||
outputFiles[first.href].append(("", "Cover pages"))
|
||||
|
||||
for tocitem in oeb_book.toc:
|
||||
if tocitem.href.find('#') != -1:
|
||||
@@ -148,10 +148,12 @@ class SNBOutput(OutputFormatPlugin):
|
||||
else:
|
||||
outputFiles[item[0]] = []
|
||||
if "" not in outputFiles[item[0]]:
|
||||
outputFiles[item[0]].append(("", tocitem.title + _(" (Preface)")))
|
||||
outputFiles[item[0]].append(("",
|
||||
tocitem.title +
|
||||
" (Preface)"))
|
||||
ch = etree.SubElement(tocBody, "chapter")
|
||||
ch.set("src", ProcessFileName(item[0]) + ".snbc")
|
||||
ch.text = tocitem.title + _(" (Preface)")
|
||||
ch.text = tocitem.title + " (Preface)"
|
||||
outputFiles[item[0]].append((item[1], tocitem.title))
|
||||
else:
|
||||
if tocitem.href in outputFiles:
|
||||
@@ -200,7 +202,8 @@ class SNBOutput(OutputFormatPlugin):
|
||||
f.write(etree.tostring(oldTree, pretty_print=True, encoding='utf-8'))
|
||||
else:
|
||||
log.debug('Merge %s with last TOC item...' % item.href)
|
||||
snbwriter.merge_content(oldTree, oeb_book, item, [('', _("Start"))], opts)
|
||||
snbwriter.merge_content(oldTree, oeb_book, item,
|
||||
[('', "Start")], opts)
|
||||
|
||||
# Output the last one if needed
|
||||
log.debug('Output the last modified chapter again: %s' % lastName)
|
||||
|
||||
@@ -19,8 +19,8 @@ class TCROutput(OutputFormatPlugin):
|
||||
options = {
|
||||
OptionRecommendation(name='tcr_output_encoding', recommended_value='utf-8',
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('Specify the character encoding of the output document. '
|
||||
'The default is utf-8.'))}
|
||||
help='Specify the character encoding of the output document. '
|
||||
'The default is utf-8.')}
|
||||
|
||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||
from ebook_converter.ebooks.txt.txtml import TXTMLizer
|
||||
|
||||
@@ -9,23 +9,23 @@ __copyright__ = '2009, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
MD_EXTENSIONS = {
|
||||
'abbr': _('Abbreviations'),
|
||||
'admonition': _('Support admonitions'),
|
||||
'attr_list': _('Add attribute to HTML tags'),
|
||||
'codehilite': _('Add code highlighting via Pygments'),
|
||||
'def_list': _('Definition lists'),
|
||||
'extra': _('Enables various common extensions'),
|
||||
'fenced_code': _('Alternative code block syntax'),
|
||||
'footnotes': _('Footnotes'),
|
||||
'legacy_attrs': _('Use legacy element attributes'),
|
||||
'legacy_em': _('Use legacy underscore handling for connected words'),
|
||||
'meta': _('Metadata in the document'),
|
||||
'nl2br': _('Treat newlines as hard breaks'),
|
||||
'sane_lists': _('Do not allow mixing list types'),
|
||||
'smarty': _('Use markdown\'s internal smartypants parser'),
|
||||
'tables': _('Support tables'),
|
||||
'toc': _('Generate a table of contents'),
|
||||
'wikilinks': _('Wiki style links'),
|
||||
'abbr': 'Abbreviations',
|
||||
'admonition': 'Support admonitions',
|
||||
'attr_list': 'Add attribute to HTML tags',
|
||||
'codehilite': 'Add code highlighting via Pygments',
|
||||
'def_list': 'Definition lists',
|
||||
'extra': 'Enables various common extensions',
|
||||
'fenced_code': 'Alternative code block syntax',
|
||||
'footnotes': 'Footnotes',
|
||||
'legacy_attrs': 'Use legacy element attributes',
|
||||
'legacy_em': 'Use legacy underscore handling for connected words',
|
||||
'meta': 'Metadata in the document',
|
||||
'nl2br': 'Treat newlines as hard breaks',
|
||||
'sane_lists': 'Do not allow mixing list types',
|
||||
'smarty': 'Use markdown\'s internal smartypants parser',
|
||||
'tables': 'Support tables',
|
||||
'toc': 'Generate a table of contents',
|
||||
'wikilinks': 'Wiki style links',
|
||||
}
|
||||
|
||||
|
||||
@@ -39,57 +39,67 @@ class TXTInput(InputFormatPlugin):
|
||||
ui_data = {
|
||||
'md_extensions': MD_EXTENSIONS,
|
||||
'paragraph_types': {
|
||||
'auto': _('Try to auto detect paragraph type'),
|
||||
'block': _('Treat a blank line as a paragraph break'),
|
||||
'single': _('Assume every line is a paragraph'),
|
||||
'print': _('Assume every line starting with 2+ spaces or a tab starts a paragraph'),
|
||||
'unformatted': _('Most lines have hard line breaks, few/no blank lines or indents'),
|
||||
'off': _('Don\'t modify the paragraph structure'),
|
||||
'auto': 'Try to auto detect paragraph type',
|
||||
'block': 'Treat a blank line as a paragraph break',
|
||||
'single': 'Assume every line is a paragraph',
|
||||
'print': 'Assume every line starting with 2+ spaces or a tab '
|
||||
'starts a paragraph',
|
||||
'unformatted': 'Most lines have hard line breaks, few/no blank '
|
||||
'lines or indents',
|
||||
'off': 'Don\'t modify the paragraph structure',
|
||||
},
|
||||
'formatting_types': {
|
||||
'auto': _('Automatically decide which formatting processor to use'),
|
||||
'plain': _('No formatting'),
|
||||
'heuristic': _('Use heuristics to determine chapter headings, italics, etc.'),
|
||||
'textile': _('Use the TexTile markup language'),
|
||||
'markdown': _('Use the Markdown markup language')
|
||||
'auto': 'Automatically decide which formatting processor to use',
|
||||
'plain': 'No formatting',
|
||||
'heuristic': 'Use heuristics to determine chapter headings, '
|
||||
'italics, etc.',
|
||||
'textile': 'Use the TexTile markup language',
|
||||
'markdown': 'Use the Markdown markup language'
|
||||
},
|
||||
}
|
||||
|
||||
options = {
|
||||
OptionRecommendation(name='formatting_type', recommended_value='auto',
|
||||
choices=list(ui_data['formatting_types']),
|
||||
help=_('Formatting used within the document.\n'
|
||||
'* auto: {auto}\n'
|
||||
'* plain: {plain}\n'
|
||||
'* heuristic: {heuristic}\n'
|
||||
'* textile: {textile}\n'
|
||||
'* markdown: {markdown}\n'
|
||||
'To learn more about markdown see {url}').format(
|
||||
url='https://daringfireball.net/projects/markdown/', **ui_data['formatting_types'])
|
||||
help='Formatting used within the document.\n'
|
||||
'* auto: {auto}\n'
|
||||
'* plain: {plain}\n'
|
||||
'* heuristic: {heuristic}\n'
|
||||
'* textile: {textile}\n'
|
||||
'* markdown: {markdown}\n'
|
||||
'To learn more about markdown see '
|
||||
'{url}'.format(url='https://daringfireball.net/projects/'
|
||||
'markdown/',
|
||||
**ui_data['formatting_types'])
|
||||
),
|
||||
OptionRecommendation(name='paragraph_type', recommended_value='auto',
|
||||
choices=list(ui_data['paragraph_types']),
|
||||
help=_('Paragraph structure to assume. The value of "off" is useful for formatted documents such as Markdown or Textile. '
|
||||
'Choices are:\n'
|
||||
'* auto: {auto}\n'
|
||||
'* block: {block}\n'
|
||||
'* single: {single}\n'
|
||||
'* print: {print}\n'
|
||||
'* unformatted: {unformatted}\n'
|
||||
'* off: {off}').format(**ui_data['paragraph_types'])
|
||||
help='Paragraph structure to assume. The value of "off" is useful '
|
||||
'for formatted documents such as Markdown or Textile. '
|
||||
'Choices are:\n'
|
||||
'* auto: {auto}\n'
|
||||
'* block: {block}\n'
|
||||
'* single: {single}\n'
|
||||
'* print: {print}\n'
|
||||
'* unformatted: {unformatted}\n'
|
||||
'* off: {off}'.format(**ui_data['paragraph_types'])
|
||||
),
|
||||
OptionRecommendation(name='preserve_spaces', recommended_value=False,
|
||||
help=_('Normally extra spaces are condensed into a single space. '
|
||||
'With this option all spaces will be displayed.')),
|
||||
help='Normally extra spaces are condensed into a single space. '
|
||||
'With this option all spaces will be displayed.'),
|
||||
OptionRecommendation(name='txt_in_remove_indents', recommended_value=False,
|
||||
help=_('Normally extra space at the beginning of lines is retained. '
|
||||
'With this option they will be removed.')),
|
||||
OptionRecommendation(name="markdown_extensions", recommended_value='footnotes, tables, toc',
|
||||
help=_('Enable extensions to markdown syntax. Extensions are formatting that is not part '
|
||||
'of the standard markdown format. The extensions enabled by default: %default.\n'
|
||||
'To learn more about markdown extensions, see {}\n'
|
||||
'This should be a comma separated list of extensions to enable:\n'
|
||||
).format('https://python-markdown.github.io/extensions/') + '\n'.join('* %s: %s' % (k, MD_EXTENSIONS[k]) for k in sorted(MD_EXTENSIONS))),
|
||||
help='Normally extra space at the beginning of lines is retained. '
|
||||
'With this option they will be removed.'),
|
||||
OptionRecommendation(name="markdown_extensions",
|
||||
recommended_value='footnotes, tables, toc',
|
||||
help='Enable extensions to markdown syntax. Extensions are '
|
||||
'formatting that is not part of the standard markdown '
|
||||
'format. The extensions enabled by default: %default.\nTo '
|
||||
'learn more about markdown extensions, see {}\nThis should '
|
||||
'be a comma separated list of extensions to enable:'
|
||||
'\n'.format('https://python-markdown.github.io/extensions/') +
|
||||
'\n'.join('* %s: %s' % (k, MD_EXTENSIONS[k])
|
||||
for k in sorted(MD_EXTENSIONS))),
|
||||
}
|
||||
|
||||
def shift_file(self, fname, data):
|
||||
@@ -301,5 +311,5 @@ class TXTInput(InputFormatPlugin):
|
||||
for item in oeb.spine:
|
||||
if hasattr(item.data, 'xpath'):
|
||||
for title in item.data.xpath('//*[local-name()="title"]'):
|
||||
if title.text == _('Unknown'):
|
||||
if title.text == 'Unknown':
|
||||
title.text = self.html_postprocess_title
|
||||
|
||||
@@ -22,9 +22,9 @@ class TXTOutput(OutputFormatPlugin):
|
||||
ui_data = {
|
||||
'newline_types': NEWLINE_TYPES,
|
||||
'formatting_types': {
|
||||
'plain': _('Plain text'),
|
||||
'markdown': _('Markdown formatted text'),
|
||||
'textile': _('TexTile formatted text')
|
||||
'plain': 'Plain text',
|
||||
'markdown': 'Markdown formatted text',
|
||||
'textile': 'TexTile formatted text'
|
||||
},
|
||||
}
|
||||
|
||||
@@ -32,52 +32,57 @@ class TXTOutput(OutputFormatPlugin):
|
||||
OptionRecommendation(name='newline', recommended_value='system',
|
||||
level=OptionRecommendation.LOW,
|
||||
short_switch='n', choices=NEWLINE_TYPES,
|
||||
help=_('Type of newline to use. Options are %s. Default is \'system\'. '
|
||||
help='Type of newline to use. Options are %s. Default is \'system\'. '
|
||||
'Use \'old_mac\' for compatibility with Mac OS 9 and earlier. '
|
||||
'For macOS use \'unix\'. \'system\' will default to the newline '
|
||||
'type used by this OS.') % sorted(NEWLINE_TYPES)),
|
||||
'type used by this OS.' % sorted(NEWLINE_TYPES)),
|
||||
OptionRecommendation(name='txt_output_encoding', recommended_value='utf-8',
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('Specify the character encoding of the output document. '
|
||||
'The default is utf-8.')),
|
||||
help='Specify the character encoding of the output document. '
|
||||
'The default is utf-8.'),
|
||||
OptionRecommendation(name='inline_toc',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Add Table of Contents to beginning of the book.')),
|
||||
help='Add Table of Contents to beginning of the book.'),
|
||||
OptionRecommendation(name='max_line_length',
|
||||
recommended_value=0, level=OptionRecommendation.LOW,
|
||||
help=_('The maximum number of characters per line. This splits on '
|
||||
'the first space before the specified value. If no space is found '
|
||||
'the line will be broken at the space after and will exceed the '
|
||||
'specified value. Also, there is a minimum of 25 characters. '
|
||||
'Use 0 to disable line splitting.')),
|
||||
help='The maximum number of characters per line. This splits on '
|
||||
'the first space before the specified value. If no space is '
|
||||
'found the line will be broken at the space after and will '
|
||||
'exceed the specified value. Also, there is a minimum of 25 '
|
||||
'characters. Use 0 to disable line splitting.'),
|
||||
OptionRecommendation(name='force_max_line_length',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Force splitting on the max-line-length value when no space '
|
||||
'is present. Also allows max-line-length to be below the minimum')),
|
||||
help='Force splitting on the max-line-length value when no space '
|
||||
'is present. Also allows max-line-length to be below the '
|
||||
'minimum'),
|
||||
OptionRecommendation(name='txt_output_formatting',
|
||||
recommended_value='plain',
|
||||
choices=list(ui_data['formatting_types']),
|
||||
help=_('Formatting used within the document.\n'
|
||||
'* plain: {plain}\n'
|
||||
'* markdown: {markdown}\n'
|
||||
'* textile: {textile}').format(**ui_data['formatting_types'])),
|
||||
help='Formatting used within the document.\n'
|
||||
'* plain: {plain}\n'
|
||||
'* markdown: {markdown}\n'
|
||||
'* textile: {textile}'
|
||||
''.format(**ui_data['formatting_types'])),
|
||||
OptionRecommendation(name='keep_links',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Do not remove links within the document. This is only '
|
||||
'useful when paired with a txt-output-formatting option that '
|
||||
'is not none because links are always removed with plain text output.')),
|
||||
help='Do not remove links within the document. This is only '
|
||||
'useful when paired with a txt-output-formatting option that '
|
||||
'is not none because links are always removed with plain '
|
||||
'text output.'),
|
||||
OptionRecommendation(name='keep_image_references',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Do not remove image references within the document. This is only '
|
||||
'useful when paired with a txt-output-formatting option that '
|
||||
'is not none because links are always removed with plain text output.')),
|
||||
help='Do not remove image references within the document. This is '
|
||||
'only useful when paired with a txt-output-formatting option '
|
||||
'that is not none because links are always removed with '
|
||||
'plain text output.'),
|
||||
OptionRecommendation(name='keep_color',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Do not remove font color from output. This is only useful when '
|
||||
'txt-output-formatting is set to textile. Textile is the only '
|
||||
'formatting that supports setting font color. If this option is '
|
||||
'not specified font color will not be set and default to the '
|
||||
'color displayed by the reader (generally this is black).')),
|
||||
help='Do not remove font color from output. This is only useful '
|
||||
'when txt-output-formatting is set to textile. Textile is '
|
||||
'the only formatting that supports setting font color. If '
|
||||
'this option is not specified font color will not be set and '
|
||||
'default to the color displayed by the reader (generally '
|
||||
'this is black).')
|
||||
}
|
||||
|
||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||
|
||||
@@ -110,74 +110,70 @@ class Plumber(object):
|
||||
OptionRecommendation(name='verbose',
|
||||
recommended_value=0, level=OptionRecommendation.LOW,
|
||||
short_switch='v',
|
||||
help=_('Level of verbosity. Specify multiple times for greater '
|
||||
'verbosity. Specifying it twice will result in full '
|
||||
'verbosity, once medium verbosity and zero times least verbosity.')
|
||||
help='Level of verbosity. Specify multiple times for greater '
|
||||
'verbosity. Specifying it twice will result in full '
|
||||
'verbosity, once medium verbosity and zero times least verbosity.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='debug_pipeline',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
short_switch='d',
|
||||
help=_('Save the output from different stages of the conversion '
|
||||
'pipeline to the specified '
|
||||
'directory. Useful if you are unsure at which stage '
|
||||
'of the conversion process a bug is occurring.')
|
||||
help='Save the output from different stages of the conversion '
|
||||
'pipeline to the specified '
|
||||
'directory. Useful if you are unsure at which stage '
|
||||
'of the conversion process a bug is occurring.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='input_profile',
|
||||
recommended_value='default', level=OptionRecommendation.LOW,
|
||||
choices=[x.short_name for x in input_profiles()],
|
||||
help=_('Specify the input profile. The input profile gives the '
|
||||
'conversion system information on how to interpret '
|
||||
'various information in the input document. For '
|
||||
'example resolution dependent lengths (i.e. lengths in '
|
||||
'pixels). Choices are:')+ ', '.join([
|
||||
help='Specify the input profile. The input profile gives the '
|
||||
'conversion system information on how to interpret '
|
||||
'various information in the input document. For '
|
||||
'example resolution dependent lengths (i.e. lengths in '
|
||||
'pixels). Choices are:'+ ', '.join([
|
||||
x.short_name for x in input_profiles()])
|
||||
),
|
||||
|
||||
OptionRecommendation(name='output_profile',
|
||||
recommended_value='default', level=OptionRecommendation.LOW,
|
||||
choices=[x.short_name for x in output_profiles()],
|
||||
help=_('Specify the output profile. The output profile '
|
||||
'tells the conversion system how to optimize the '
|
||||
'created document for the specified device (such as by resizing images for the device screen size). In some cases, '
|
||||
'an output profile can be used to optimize the output for a particular device, but this is rarely necessary. '
|
||||
'Choices are:') + ', '.join([
|
||||
help='Specify the output profile. The output profile '
|
||||
'tells the conversion system how to optimize the '
|
||||
'created document for the specified device (such as by resizing images for the device screen size). In some cases, '
|
||||
'an output profile can be used to optimize the output for a particular device, but this is rarely necessary. '
|
||||
'Choices are:' + ', '.join([
|
||||
x.short_name for x in output_profiles()])
|
||||
),
|
||||
|
||||
OptionRecommendation(name='base_font_size',
|
||||
recommended_value=0, level=OptionRecommendation.LOW,
|
||||
help=_('The base font size in pts. All font sizes in the produced book '
|
||||
help='The base font size in pts. All font sizes in the produced book '
|
||||
'will be rescaled based on this size. By choosing a larger '
|
||||
'size you can make the fonts in the output bigger and vice '
|
||||
'versa. By default, when the value is zero, the base font size is chosen based on '
|
||||
'the output profile you chose.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='font_size_mapping',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Mapping from CSS font names to font sizes in pts. '
|
||||
help='Mapping from CSS font names to font sizes in pts. '
|
||||
'An example setting is 12,12,14,16,18,20,22,24. '
|
||||
'These are the mappings for the sizes xx-small to xx-large, '
|
||||
'with the final size being for huge fonts. The font '
|
||||
'rescaling algorithm uses these sizes to intelligently '
|
||||
'rescale fonts. The default is to use a mapping based on '
|
||||
'the output profile you chose.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='disable_font_rescaling',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Disable all rescaling of font sizes.'
|
||||
)
|
||||
help='Disable all rescaling of font sizes.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='minimum_line_height',
|
||||
recommended_value=120.0, level=OptionRecommendation.LOW,
|
||||
help=_(
|
||||
'The minimum line height, as a percentage of the element\'s '
|
||||
help='The minimum line height, as a percentage of the element\'s '
|
||||
'calculated font size. calibre will ensure that every element '
|
||||
'has a line height of at least this setting, irrespective of '
|
||||
'what the input document specifies. Set to zero to disable. '
|
||||
@@ -185,134 +181,119 @@ OptionRecommendation(name='minimum_line_height',
|
||||
'the direct line height specification, unless you know what '
|
||||
'you are doing. For example, you can achieve "double spaced" '
|
||||
'text by setting this to 240.'
|
||||
)
|
||||
),
|
||||
|
||||
|
||||
OptionRecommendation(name='line_height',
|
||||
recommended_value=0, level=OptionRecommendation.LOW,
|
||||
help=_(
|
||||
'The line height in pts. Controls spacing between consecutive '
|
||||
help='The line height in pts. Controls spacing between consecutive '
|
||||
'lines of text. Only applies to elements that do not define '
|
||||
'their own line height. In most cases, the minimum line height '
|
||||
'option is more useful. '
|
||||
'By default no line height manipulation is performed.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='embed_font_family',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_(
|
||||
'Embed the specified font family into the book. This specifies '
|
||||
help='Embed the specified font family into the book. This specifies '
|
||||
'the "base" font used for the book. If the input document '
|
||||
'specifies its own fonts, they may override this base font. '
|
||||
'You can use the filter style information option to remove fonts from the '
|
||||
'input document. Note that font embedding only works '
|
||||
'with some output formats, principally EPUB, AZW3 and DOCX.')
|
||||
'with some output formats, principally EPUB, AZW3 and DOCX.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='embed_all_fonts',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_(
|
||||
'Embed every font that is referenced in the input document '
|
||||
help='Embed every font that is referenced in the input document '
|
||||
'but not already embedded. This will search your system for the '
|
||||
'fonts, and if found, they will be embedded. Embedding will only work '
|
||||
'if the format you are converting to supports embedded fonts, such as '
|
||||
'EPUB, AZW3, DOCX or PDF. Please ensure that you have the proper license for embedding '
|
||||
'the fonts used in this document.'
|
||||
)),
|
||||
),
|
||||
|
||||
OptionRecommendation(name='subset_embedded_fonts',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_(
|
||||
'Subset all embedded fonts. Every embedded font is reduced '
|
||||
help='Subset all embedded fonts. Every embedded font is reduced '
|
||||
'to contain only the glyphs used in this document. This decreases '
|
||||
'the size of the font files. Useful if you are embedding a '
|
||||
'particularly large font with lots of unused glyphs.')
|
||||
'particularly large font with lots of unused glyphs.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='linearize_tables',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Some badly designed documents use tables to control the '
|
||||
help='Some badly designed documents use tables to control the '
|
||||
'layout of text on the page. When converted these documents '
|
||||
'often have text that runs off the page and other artifacts. '
|
||||
'This option will extract the content from the tables and '
|
||||
'present it in a linear fashion.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='level1_toc',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('XPath expression that specifies all tags that '
|
||||
help='XPath expression that specifies all tags that '
|
||||
'should be added to the Table of Contents at level one. If '
|
||||
'this is specified, it takes precedence over other forms '
|
||||
'of auto-detection.'
|
||||
' See the XPath Tutorial in the calibre User Manual for examples.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='level2_toc',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('XPath expression that specifies all tags that should be '
|
||||
help='XPath expression that specifies all tags that should be '
|
||||
'added to the Table of Contents at level two. Each entry is added '
|
||||
'under the previous level one entry.'
|
||||
' See the XPath Tutorial in the calibre User Manual for examples.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='level3_toc',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('XPath expression that specifies all tags that should be '
|
||||
help='XPath expression that specifies all tags that should be '
|
||||
'added to the Table of Contents at level three. Each entry '
|
||||
'is added under the previous level two entry.'
|
||||
' See the XPath Tutorial in the calibre User Manual for examples.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='use_auto_toc',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Normally, if the source file already has a Table of '
|
||||
help='Normally, if the source file already has a Table of '
|
||||
'Contents, it is used in preference to the auto-generated one. '
|
||||
'With this option, the auto-generated one is always used.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='no_chapters_in_toc',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_("Don't add auto-detected chapters to the Table of "
|
||||
help="Don't add auto-detected chapters to the Table of "
|
||||
'Contents.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='toc_threshold',
|
||||
recommended_value=6, level=OptionRecommendation.LOW,
|
||||
help=_(
|
||||
'If fewer than this number of chapters is detected, then links '
|
||||
'are added to the Table of Contents. Default: %default')
|
||||
help='If fewer than this number of chapters is detected, then links '
|
||||
'are added to the Table of Contents. Default: %default'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='max_toc_links',
|
||||
recommended_value=50, level=OptionRecommendation.LOW,
|
||||
help=_('Maximum number of links to insert into the TOC. Set to 0 '
|
||||
help='Maximum number of links to insert into the TOC. Set to 0 '
|
||||
'to disable. Default is: %default. Links are only added to the '
|
||||
'TOC if less than the threshold number of chapters were detected.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='toc_filter',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Remove entries from the Table of Contents whose titles '
|
||||
help='Remove entries from the Table of Contents whose titles '
|
||||
'match the specified regular expression. Matching entries and all '
|
||||
'their children are removed.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='duplicate_links_in_toc',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('When creating a TOC from links in the input document, '
|
||||
help='When creating a TOC from links in the input document, '
|
||||
'allow duplicate entries, i.e. allow more than one entry '
|
||||
'with the same text, provided that they point to a '
|
||||
'different location.')
|
||||
'different location.'
|
||||
),
|
||||
|
||||
|
||||
@@ -320,7 +301,7 @@ OptionRecommendation(name='chapter',
|
||||
recommended_value="//*[((name()='h1' or name()='h2') and "
|
||||
r"re:test(., '\s*((chapter|book|section|part)\s+)|((prolog|prologue|epilogue)(\s+|$))', 'i')) or @class "
|
||||
"= 'chapter']", level=OptionRecommendation.LOW,
|
||||
help=_('An XPath expression to detect chapter titles. The default '
|
||||
help='An XPath expression to detect chapter titles. The default '
|
||||
'is to consider <h1> or <h2> tags that contain the words '
|
||||
'"chapter", "book", "section", "prologue", "epilogue" or "part" as chapter titles as '
|
||||
'well as any tags that have class="chapter". The expression '
|
||||
@@ -328,390 +309,380 @@ OptionRecommendation(name='chapter',
|
||||
'detection, use the expression "/". See the XPath Tutorial '
|
||||
'in the calibre User Manual for further help on using this '
|
||||
'feature.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='chapter_mark',
|
||||
recommended_value='pagebreak', level=OptionRecommendation.LOW,
|
||||
choices=['pagebreak', 'rule', 'both', 'none'],
|
||||
help=_('Specify how to mark detected chapters. A value of '
|
||||
help='Specify how to mark detected chapters. A value of '
|
||||
'"pagebreak" will insert page breaks before chapters. '
|
||||
'A value of "rule" will insert a line before chapters. '
|
||||
'A value of "none" will disable chapter marking and a '
|
||||
'value of "both" will use both page breaks and lines '
|
||||
'to mark chapters.')
|
||||
'to mark chapters.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='start_reading_at',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('An XPath expression to detect the location in the document'
|
||||
help='An XPath expression to detect the location in the document'
|
||||
' at which to start reading. Some e-book reading programs'
|
||||
' (most prominently the Kindle) use this location as the'
|
||||
' position at which to open the book. See the XPath tutorial'
|
||||
' in the calibre User Manual for further help using this'
|
||||
' feature.')
|
||||
' feature.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='extra_css',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Either the path to a CSS stylesheet or raw CSS. '
|
||||
help='Either the path to a CSS stylesheet or raw CSS. '
|
||||
'This CSS will be appended to the style rules from '
|
||||
'the source file, so it can be used to override those '
|
||||
'rules.')
|
||||
'rules.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='transform_css_rules',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Rules for transforming the styles in this book. These'
|
||||
' rules are applied after all other CSS processing is done.')
|
||||
help='Rules for transforming the styles in this book. These'
|
||||
' rules are applied after all other CSS processing is done.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='filter_css',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('A comma separated list of CSS properties that '
|
||||
help='A comma separated list of CSS properties that '
|
||||
'will be removed from all CSS style rules. This is useful '
|
||||
'if the presence of some style information prevents it '
|
||||
'from being overridden on your device. '
|
||||
'For example: '
|
||||
'font-family,color,margin-left,margin-right')
|
||||
'font-family,color,margin-left,margin-right'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='expand_css',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_(
|
||||
'By default, calibre will use the shorthand form for various'
|
||||
help='By default, calibre will use the shorthand form for various'
|
||||
' CSS properties such as margin, padding, border, etc. This'
|
||||
' option will cause it to use the full expanded form instead.'
|
||||
' Note that CSS is always expanded when generating EPUB files'
|
||||
' with the output profile set to one of the Nook profiles'
|
||||
' as the Nook cannot handle shorthand CSS.')
|
||||
' as the Nook cannot handle shorthand CSS.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='page_breaks_before',
|
||||
recommended_value="//*[name()='h1' or name()='h2']",
|
||||
level=OptionRecommendation.LOW,
|
||||
help=_('An XPath expression. Page breaks are inserted '
|
||||
'before the specified elements. To disable use the expression: /')
|
||||
help='An XPath expression. Page breaks are inserted '
|
||||
'before the specified elements. To disable use the expression: /'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='remove_fake_margins',
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Some documents specify page margins by '
|
||||
help='Some documents specify page margins by '
|
||||
'specifying a left and right margin on each individual '
|
||||
'paragraph. calibre will try to detect and remove these '
|
||||
'margins. Sometimes, this can cause the removal of '
|
||||
'margins that should not have been removed. In this '
|
||||
'case you can disable the removal.')
|
||||
'case you can disable the removal.'
|
||||
),
|
||||
|
||||
|
||||
OptionRecommendation(name='margin_top',
|
||||
recommended_value=5.0, level=OptionRecommendation.LOW,
|
||||
help=_('Set the top margin in pts. Default is %default. '
|
||||
help='Set the top margin in pts. Default is %default. '
|
||||
'Setting this to less than zero will cause no margin to be set '
|
||||
'(the margin setting in the original document will be preserved). '
|
||||
'Note: Page oriented formats such as PDF and DOCX have their own'
|
||||
' margin settings that take precedence.')),
|
||||
' margin settings that take precedence.'),
|
||||
|
||||
OptionRecommendation(name='margin_bottom',
|
||||
recommended_value=5.0, level=OptionRecommendation.LOW,
|
||||
help=_('Set the bottom margin in pts. Default is %default. '
|
||||
help='Set the bottom margin in pts. Default is %default. '
|
||||
'Setting this to less than zero will cause no margin to be set '
|
||||
'(the margin setting in the original document will be preserved). '
|
||||
'Note: Page oriented formats such as PDF and DOCX have their own'
|
||||
' margin settings that take precedence.')),
|
||||
' margin settings that take precedence.'),
|
||||
|
||||
OptionRecommendation(name='margin_left',
|
||||
recommended_value=5.0, level=OptionRecommendation.LOW,
|
||||
help=_('Set the left margin in pts. Default is %default. '
|
||||
help='Set the left margin in pts. Default is %default. '
|
||||
'Setting this to less than zero will cause no margin to be set '
|
||||
'(the margin setting in the original document will be preserved). '
|
||||
'Note: Page oriented formats such as PDF and DOCX have their own'
|
||||
' margin settings that take precedence.')),
|
||||
' margin settings that take precedence.'),
|
||||
|
||||
OptionRecommendation(name='margin_right',
|
||||
recommended_value=5.0, level=OptionRecommendation.LOW,
|
||||
help=_('Set the right margin in pts. Default is %default. '
|
||||
help='Set the right margin in pts. Default is %default. '
|
||||
'Setting this to less than zero will cause no margin to be set '
|
||||
'(the margin setting in the original document will be preserved). '
|
||||
'Note: Page oriented formats such as PDF and DOCX have their own'
|
||||
' margin settings that take precedence.')),
|
||||
' margin settings that take precedence.'),
|
||||
|
||||
OptionRecommendation(name='change_justification',
|
||||
recommended_value='original', level=OptionRecommendation.LOW,
|
||||
choices=['left','justify','original'],
|
||||
help=_('Change text justification. A value of "left" converts all'
|
||||
help='Change text justification. A value of "left" converts all'
|
||||
' justified text in the source to left aligned (i.e. '
|
||||
'unjustified) text. A value of "justify" converts all '
|
||||
'unjustified text to justified. A value of "original" '
|
||||
'(the default) does not change justification in the '
|
||||
'source file. Note that only some output formats support '
|
||||
'justification.')),
|
||||
'justification.'),
|
||||
|
||||
OptionRecommendation(name='remove_paragraph_spacing',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Remove spacing between paragraphs. Also sets an indent on '
|
||||
help='Remove spacing between paragraphs. Also sets an indent on '
|
||||
'paragraphs of 1.5em. Spacing removal will not work '
|
||||
'if the source file does not use paragraphs (<p> or <div> tags).')
|
||||
'if the source file does not use paragraphs (<p> or <div> tags).'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='remove_paragraph_spacing_indent_size',
|
||||
recommended_value=1.5, level=OptionRecommendation.LOW,
|
||||
help=_('When calibre removes blank lines between paragraphs, it automatically '
|
||||
help='When calibre removes blank lines between paragraphs, it automatically '
|
||||
'sets a paragraph indent, to ensure that paragraphs can be easily '
|
||||
'distinguished. This option controls the width of that indent (in em). '
|
||||
'If you set this value negative, then the indent specified in the input '
|
||||
'document is used, that is, calibre does not change the indentation.')
|
||||
'document is used, that is, calibre does not change the indentation.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='prefer_metadata_cover',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Use the cover detected from the source file in preference '
|
||||
'to the specified cover.')
|
||||
help='Use the cover detected from the source file in preference '
|
||||
'to the specified cover.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='insert_blank_line',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Insert a blank line between paragraphs. Will not work '
|
||||
help='Insert a blank line between paragraphs. Will not work '
|
||||
'if the source file does not use paragraphs (<p> or <div> tags).'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='insert_blank_line_size',
|
||||
recommended_value=0.5, level=OptionRecommendation.LOW,
|
||||
help=_('Set the height of the inserted blank lines (in em).'
|
||||
help='Set the height of the inserted blank lines (in em).'
|
||||
' The height of the lines between paragraphs will be twice the value'
|
||||
' set here.')
|
||||
' set here.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='remove_first_image',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Remove the first image from the input e-book. Useful if the '
|
||||
help='Remove the first image from the input e-book. Useful if the '
|
||||
'input document has a cover image that is not identified as a cover. '
|
||||
'In this case, if you set a cover in calibre, the output document will '
|
||||
'end up with two cover images if you do not specify this option.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='insert_metadata',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Insert the book metadata at the start of '
|
||||
help='Insert the book metadata at the start of '
|
||||
'the book. This is useful if your e-book reader does not support '
|
||||
'displaying/searching metadata directly.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='smarten_punctuation',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Convert plain quotes, dashes and ellipsis to their '
|
||||
help='Convert plain quotes, dashes and ellipsis to their '
|
||||
'typographically correct equivalents. For details, see '
|
||||
'https://daringfireball.net/projects/smartypants'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='unsmarten_punctuation',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Convert fancy quotes, dashes and ellipsis to their '
|
||||
help='Convert fancy quotes, dashes and ellipsis to their '
|
||||
'plain equivalents.'
|
||||
)
|
||||
),
|
||||
|
||||
OptionRecommendation(name='read_metadata_from_opf',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
short_switch='m',
|
||||
help=_('Read metadata from the specified OPF file. Metadata read '
|
||||
help='Read metadata from the specified OPF file. Metadata read '
|
||||
'from this file will override any metadata in the source '
|
||||
'file.')
|
||||
'file.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='asciiize',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=(_('Transliterate unicode characters to an ASCII '
|
||||
'representation. Use with care because this will replace '
|
||||
'unicode characters with ASCII. For instance it will replace "%s" '
|
||||
'with "Mikhail Gorbachiov". Also, note that in '
|
||||
'cases where there are multiple representations of a character '
|
||||
'(characters shared by Chinese and Japanese for instance) the '
|
||||
'representation based on the current calibre interface language will be '
|
||||
'used.')%
|
||||
'\u041c\u0438\u0445\u0430\u0438\u043b '
|
||||
'\u0413\u043e\u0440\u0431\u0430\u0447\u0451\u0432'
|
||||
)
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help='Transliterate unicode characters to an ASCII '
|
||||
'representation. Use with care because this will replace '
|
||||
'unicode characters with ASCII. For instance it will replace "%s" '
|
||||
'with "Mikhail Gorbachiov". Also, note that in '
|
||||
'cases where there are multiple representations of a character '
|
||||
'(characters shared by Chinese and Japanese for instance) the '
|
||||
'representation based on the current calibre interface language will be '
|
||||
'used.' %
|
||||
'\u041c\u0438\u0445\u0430\u0438\u043b '
|
||||
'\u0413\u043e\u0440\u0431\u0430\u0447\u0451\u0432'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='keep_ligatures',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Preserve ligatures present in the input document. '
|
||||
help='Preserve ligatures present in the input document. '
|
||||
'A ligature is a special rendering of a pair of '
|
||||
'characters like ff, fi, fl et cetera. '
|
||||
'Most readers do not have support for '
|
||||
'ligatures in their default fonts, so they are '
|
||||
'unlikely to render correctly. By default, calibre '
|
||||
'will turn a ligature into the corresponding pair of normal '
|
||||
'characters. This option will preserve them instead.')
|
||||
'characters. This option will preserve them instead.'
|
||||
),
|
||||
|
||||
OptionRecommendation(name='title',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the title.')),
|
||||
help='Set the title.'),
|
||||
|
||||
OptionRecommendation(name='authors',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the authors. Multiple authors should be separated by '
|
||||
'ampersands.')),
|
||||
help='Set the authors. Multiple authors should be separated by '
|
||||
'ampersands.'),
|
||||
|
||||
OptionRecommendation(name='title_sort',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('The version of the title to be used for sorting. ')),
|
||||
help='The version of the title to be used for sorting. '),
|
||||
|
||||
OptionRecommendation(name='author_sort',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('String to be used when sorting by author. ')),
|
||||
help='String to be used when sorting by author. '),
|
||||
|
||||
OptionRecommendation(name='cover',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the cover to the specified file or URL')),
|
||||
help='Set the cover to the specified file or URL'),
|
||||
|
||||
OptionRecommendation(name='comments',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the e-book description.')),
|
||||
help='Set the e-book description.'),
|
||||
|
||||
OptionRecommendation(name='publisher',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the e-book publisher.')),
|
||||
help='Set the e-book publisher.'),
|
||||
|
||||
OptionRecommendation(name='series',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the series this e-book belongs to.')),
|
||||
help='Set the series this e-book belongs to.'),
|
||||
|
||||
OptionRecommendation(name='series_index',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the index of the book in this series.')),
|
||||
help='Set the index of the book in this series.'),
|
||||
|
||||
OptionRecommendation(name='rating',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the rating. Should be a number between 1 and 5.')),
|
||||
help='Set the rating. Should be a number between 1 and 5.'),
|
||||
|
||||
OptionRecommendation(name='isbn',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the ISBN of the book.')),
|
||||
help='Set the ISBN of the book.'),
|
||||
|
||||
OptionRecommendation(name='tags',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the tags for the book. Should be a comma separated list.')),
|
||||
help='Set the tags for the book. Should be a comma separated list.'),
|
||||
|
||||
OptionRecommendation(name='book_producer',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the book producer.')),
|
||||
help='Set the book producer.'),
|
||||
|
||||
OptionRecommendation(name='language',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the language.')),
|
||||
help='Set the language.'),
|
||||
|
||||
OptionRecommendation(name='pubdate',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the publication date (assumed to be in the local timezone, unless the timezone is explicitly specified)')),
|
||||
help='Set the publication date (assumed to be in the local timezone, unless the timezone is explicitly specified)'),
|
||||
|
||||
OptionRecommendation(name='timestamp',
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help=_('Set the book timestamp (no longer used anywhere)')),
|
||||
help='Set the book timestamp (no longer used anywhere)'),
|
||||
|
||||
OptionRecommendation(name='enable_heuristics',
|
||||
recommended_value=False, level=OptionRecommendation.LOW,
|
||||
help=_('Enable heuristic processing. This option must be set for any '
|
||||
'heuristic processing to take place.')),
|
||||
help='Enable heuristic processing. This option must be set for any '
|
||||
'heuristic processing to take place.'),
|
||||
|
||||
OptionRecommendation(name='markup_chapter_headings',
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Detect unformatted chapter headings and sub headings. Change '
|
||||
'them to h2 and h3 tags. This setting will not create a TOC, '
|
||||
'but can be used in conjunction with structure detection to create '
|
||||
'one.')),
|
||||
help='Detect unformatted chapter headings and sub headings. Change '
|
||||
'them to h2 and h3 tags. This setting will not create a TOC, '
|
||||
'but can be used in conjunction with structure detection to create '
|
||||
'one.'),
|
||||
|
||||
OptionRecommendation(name='italicize_common_cases',
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Look for common words and patterns that denote '
|
||||
'italics and italicize them.')),
|
||||
help='Look for common words and patterns that denote '
|
||||
'italics and italicize them.'),
|
||||
|
||||
OptionRecommendation(name='fix_indents',
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Turn indentation created from multiple non-breaking space entities '
|
||||
'into CSS indents.')),
|
||||
help='Turn indentation created from multiple non-breaking space entities '
|
||||
'into CSS indents.'),
|
||||
|
||||
OptionRecommendation(name='html_unwrap_factor',
|
||||
recommended_value=0.40, level=OptionRecommendation.LOW,
|
||||
help=_('Scale used to determine the length at which a line should '
|
||||
'be unwrapped. Valid values are a decimal between 0 and 1. The '
|
||||
'default is 0.4, just below the median line length. If only a '
|
||||
'few lines in the document require unwrapping this value should '
|
||||
'be reduced')),
|
||||
help='Scale used to determine the length at which a line should '
|
||||
'be unwrapped. Valid values are a decimal between 0 and 1. The '
|
||||
'default is 0.4, just below the median line length. If only a '
|
||||
'few lines in the document require unwrapping this value should '
|
||||
'be reduced'),
|
||||
|
||||
OptionRecommendation(name='unwrap_lines',
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Unwrap lines using punctuation and other formatting clues.')),
|
||||
help='Unwrap lines using punctuation and other formatting clues.'),
|
||||
|
||||
OptionRecommendation(name='delete_blank_paragraphs',
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Remove empty paragraphs from the document when they exist between '
|
||||
'every other paragraph')),
|
||||
help='Remove empty paragraphs from the document when they exist between '
|
||||
'every other paragraph'),
|
||||
|
||||
OptionRecommendation(name='format_scene_breaks',
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Left aligned scene break markers are center aligned. '
|
||||
'Replace soft scene breaks that use multiple blank lines with '
|
||||
'horizontal rules.')),
|
||||
help='Left aligned scene break markers are center aligned. Replace soft '
|
||||
'scene breaks that use multiple blank lines with horizontal rules.'),
|
||||
|
||||
OptionRecommendation(name='replace_scene_breaks',
|
||||
recommended_value='', level=OptionRecommendation.LOW,
|
||||
help=_('Replace scene breaks with the specified text. By default, the '
|
||||
'text from the input document is used.')),
|
||||
help='Replace scene breaks with the specified text. By default, the text '
|
||||
'from the input document is used.'),
|
||||
|
||||
OptionRecommendation(name='dehyphenate',
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Analyze hyphenated words throughout the document. The '
|
||||
'document itself is used as a dictionary to determine whether hyphens '
|
||||
'should be retained or removed.')),
|
||||
help='Analyze hyphenated words throughout the document. The document '
|
||||
'itself is used as a dictionary to determine whether hyphens should '
|
||||
'be retained or removed.'),
|
||||
|
||||
OptionRecommendation(name='renumber_headings',
|
||||
recommended_value=True, level=OptionRecommendation.LOW,
|
||||
help=_('Looks for occurrences of sequential <h1> or <h2> tags. '
|
||||
'The tags are renumbered to prevent splitting in the middle '
|
||||
'of chapter headings.')),
|
||||
help='Looks for occurrences of sequential <h1> or <h2> tags. The tags are '
|
||||
'renumbered to prevent splitting in the middle of chapter headings.'),
|
||||
|
||||
OptionRecommendation(name='sr1_search',
|
||||
recommended_value='', level=OptionRecommendation.LOW,
|
||||
help=_('Search pattern (regular expression) to be replaced with '
|
||||
'sr1-replace.')),
|
||||
help='Search pattern (regular expression) to be replaced with '
|
||||
'sr1-replace.'),
|
||||
|
||||
OptionRecommendation(name='sr1_replace',
|
||||
recommended_value='', level=OptionRecommendation.LOW,
|
||||
help=_('Replacement to replace the text found with sr1-search.')),
|
||||
help='Replacement to replace the text found with sr1-search.'),
|
||||
|
||||
OptionRecommendation(name='sr2_search',
|
||||
recommended_value='', level=OptionRecommendation.LOW,
|
||||
help=_('Search pattern (regular expression) to be replaced with '
|
||||
'sr2-replace.')),
|
||||
help='Search pattern (regular expression) to be replaced with '
|
||||
'sr2-replace.'),
|
||||
|
||||
OptionRecommendation(name='sr2_replace',
|
||||
recommended_value='', level=OptionRecommendation.LOW,
|
||||
help=_('Replacement to replace the text found with sr2-search.')),
|
||||
help='Replacement to replace the text found with sr2-search.'),
|
||||
|
||||
OptionRecommendation(name='sr3_search',
|
||||
recommended_value='', level=OptionRecommendation.LOW,
|
||||
help=_('Search pattern (regular expression) to be replaced with '
|
||||
'sr3-replace.')),
|
||||
help='Search pattern (regular expression) to be replaced with '
|
||||
'sr3-replace.'),
|
||||
|
||||
OptionRecommendation(name='sr3_replace',
|
||||
recommended_value='', level=OptionRecommendation.LOW,
|
||||
help=_('Replacement to replace the text found with sr3-search.')),
|
||||
help='Replacement to replace the text found with sr3-search.'),
|
||||
|
||||
OptionRecommendation(name='search_replace',
|
||||
recommended_value=None, level=OptionRecommendation.LOW, help=_(
|
||||
'Path to a file containing search and replace regular expressions. '
|
||||
'The file must contain alternating lines of regular expression '
|
||||
'followed by replacement pattern (which can be an empty line). '
|
||||
'The regular expression must be in the Python regex syntax and '
|
||||
'the file must be UTF-8 encoded.')),
|
||||
recommended_value=None, level=OptionRecommendation.LOW,
|
||||
help='Path to a file containing search and replace regular expressions. '
|
||||
'The file must contain alternating lines of regular expression '
|
||||
'followed by replacement pattern (which can be an empty line). '
|
||||
'The regular expression must be in the Python regex syntax and '
|
||||
'the file must be UTF-8 encoded.'),
|
||||
]
|
||||
# }}}
|
||||
|
||||
@@ -818,7 +789,7 @@ OptionRecommendation(name='search_replace',
|
||||
html_pat = re.compile(r'\.(x){0,1}htm(l){0,1}$', re.IGNORECASE)
|
||||
html_files = [f for f in files if html_pat.search(f) is not None]
|
||||
if not html_files:
|
||||
raise ValueError(_('Could not find an e-book inside the archive'))
|
||||
raise ValueError('Could not find an e-book inside the archive')
|
||||
html_files = [(f, os.stat(f).st_size) for f in html_files]
|
||||
html_files.sort(key=lambda x: x[1])
|
||||
html_files = [f[0] for f in html_files]
|
||||
@@ -908,14 +879,14 @@ OptionRecommendation(name='search_replace',
|
||||
try:
|
||||
val = float(val)
|
||||
except ValueError:
|
||||
self.log.warn(_('Values of series index and rating must'
|
||||
' be numbers. Ignoring'), val)
|
||||
self.log.warn('Values of series index and rating must'
|
||||
' be numbers. Ignoring', val)
|
||||
continue
|
||||
elif x in ('timestamp', 'pubdate'):
|
||||
try:
|
||||
val = parse_date(val, assume_utc=x=='timestamp')
|
||||
except:
|
||||
self.log.exception(_('Failed to parse date/time') + ' ' + str(val))
|
||||
self.log.exception('Failed to parse date/time %s', val)
|
||||
continue
|
||||
setattr(mi, x, val)
|
||||
|
||||
@@ -1095,7 +1066,7 @@ OptionRecommendation(name='search_replace',
|
||||
self.flush()
|
||||
return
|
||||
|
||||
self.ui_reporter(0.01, _('Converting input to HTML...'))
|
||||
self.ui_reporter(0.01, 'Converting input to HTML...')
|
||||
ir = CompositeProgressReporter(0.01, 0.34, self.ui_reporter)
|
||||
self.input_plugin.report_progress = ir
|
||||
if self.for_regex_wizard:
|
||||
@@ -1129,7 +1100,7 @@ OptionRecommendation(name='search_replace',
|
||||
self.input_plugin.specialize(self.oeb, self.opts, self.log,
|
||||
self.output_fmt)
|
||||
|
||||
pr(0., _('Running transforms on e-book...'))
|
||||
pr(0., 'Running transforms on e-book...')
|
||||
|
||||
self.oeb.plumber_output_format = self.output_fmt or ''
|
||||
|
||||
@@ -1266,7 +1237,7 @@ OptionRecommendation(name='search_replace',
|
||||
self.log.info('Creating %s...'%self.output_plugin.name)
|
||||
our = CompositeProgressReporter(0.67, 1., self.ui_reporter)
|
||||
self.output_plugin.report_progress = our
|
||||
our(0., _('Running %s plugin')%self.output_plugin.name)
|
||||
our(0., 'Running %s plugin' % self.output_plugin.name)
|
||||
with self.output_plugin:
|
||||
self.output_plugin.convert(self.oeb, self.output, self.input_plugin,
|
||||
self.opts, self.log)
|
||||
|
||||
@@ -261,9 +261,8 @@ def format_fields(mi, prefs):
|
||||
f = formatter()
|
||||
|
||||
def safe_format(field):
|
||||
return f.safe_format(
|
||||
getattr(prefs, field), mi, _('Template error'), mi, template_cache=_template_cache
|
||||
)
|
||||
return f.safe_format(getattr(prefs, field), mi, 'Template error', mi,
|
||||
template_cache=_template_cache)
|
||||
return map(safe_format, ('title_template', 'subtitle_template', 'footer_template'))
|
||||
|
||||
|
||||
@@ -285,7 +284,7 @@ def preserve_fields(obj, fields):
|
||||
|
||||
def format_text(mi, prefs):
|
||||
with preserve_fields(mi, 'authors formatted_series_index'):
|
||||
mi.authors = [a for a in mi.authors if a != _('Unknown')]
|
||||
mi.authors = [a for a in mi.authors if a != 'Unknown']
|
||||
mi.formatted_series_index = fmt_sidx(mi.series_index or 0, use_roman=get_use_roman())
|
||||
return tuple(format_fields(mi, prefs))
|
||||
# }}}
|
||||
@@ -358,7 +357,6 @@ class Style(object):
|
||||
class Cross(Style):
|
||||
|
||||
NAME = 'The Cross'
|
||||
GUI_NAME = _('The Cross')
|
||||
|
||||
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block):
|
||||
painter.fillRect(rect, self.color1)
|
||||
@@ -379,7 +377,6 @@ class Cross(Style):
|
||||
class Half(Style):
|
||||
|
||||
NAME = 'Half and Half'
|
||||
GUI_NAME = _('Half and half')
|
||||
|
||||
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block):
|
||||
g = QLinearGradient(QPointF(0, 0), QPointF(0, rect.height()))
|
||||
@@ -404,7 +401,6 @@ def draw_curved_line(painter_path, dx, dy, c1_frac, c1_amp, c2_frac, c2_amp):
|
||||
class Banner(Style):
|
||||
|
||||
NAME = 'Banner'
|
||||
GUI_NAME = _('Banner')
|
||||
GRADE = 0.07
|
||||
|
||||
def calculate_margins(self, prefs):
|
||||
@@ -474,7 +470,6 @@ class Banner(Style):
|
||||
class Ornamental(Style):
|
||||
|
||||
NAME = 'Ornamental'
|
||||
GUI_NAME = _('Ornamental')
|
||||
|
||||
# SVG vectors {{{
|
||||
CORNER_VECTOR = "m 67.791903,64.260958 c -4.308097,-2.07925 -4.086719,-8.29575 0.334943,-9.40552 4.119758,-1.03399 8.732363,5.05239 5.393055,7.1162 -0.55,0.33992 -1,1.04147 -1,1.55902 0,1.59332 2.597425,1.04548 5.365141,-1.1316 1.999416,-1.57274 2.634859,-2.96609 2.634859,-5.7775 0,-9.55787 -9.827495,-13.42961 -24.43221,-9.62556 -3.218823,0.83839 -5.905663,1.40089 -5.970755,1.25 -0.06509,-0.1509 -0.887601,-1.19493 -1.827799,-2.32007 -1.672708,-2.00174 -1.636693,-2.03722 1.675668,-1.65052 1.861815,0.21736 6.685863,-0.35719 10.720107,-1.27678 12.280767,-2.79934 20.195487,-0.0248 22.846932,8.0092 3.187273,9.65753 -6.423297,17.7497 -15.739941,13.25313 z m 49.881417,-20.53932 c -3.19204,-2.701 -3.72967,-6.67376 -1.24009,-9.16334 2.48236,-2.48236 5.35141,-2.67905 7.51523,-0.51523 1.85966,1.85966 2.07045,6.52954 0.37143,8.22857 -2.04025,2.04024 3.28436,1.44595 6.92316,-0.77272 9.66959,-5.89579 0.88581,-18.22422 -13.0777,-18.35516 -5.28594,-0.0496 -10.31098,1.88721 -14.26764,5.4991 -1.98835,1.81509 -2.16454,1.82692 -2.7936,0.18763 -0.40973,-1.06774 0.12141,-2.82197 1.3628,-4.50104 2.46349,-3.33205 1.67564,-4.01299 -2.891784,-2.49938 -2.85998,0.94777 -3.81038,2.05378 -5.59837,6.51495 -1.184469,2.95536 -3.346819,6.86882 -4.805219,8.69657 -1.4584,1.82776 -2.65164,4.02223 -2.65164,4.87662 0,3.24694 -4.442667,0.59094 -5.872557,-3.51085 -1.361274,-3.90495 0.408198,-8.63869 4.404043,-11.78183 5.155844,-4.05558 1.612374,-3.42079 -9.235926,1.65457 -12.882907,6.02725 -16.864953,7.18038 -24.795556,7.18038 -8.471637,0 -13.38802,-1.64157 -17.634617,-5.88816 -2.832233,-2.83224 -3.849773,-4.81378 -4.418121,-8.6038 -1.946289,-12.9787795 8.03227,-20.91713135 19.767685,-15.7259993 5.547225,2.4538018 6.993631,6.1265383 3.999564,10.1557393 -5.468513,7.35914 -15.917883,-0.19431 -10.657807,-7.7041155 1.486298,-2.1219878 1.441784,-2.2225068 -0.984223,-2.2225068 -1.397511,0 -4.010527,1.3130878 -5.806704,2.9179718 -2.773359,2.4779995 -3.265777,3.5977995 -3.265777,7.4266705 0,5.10943 2.254112,8.84197 7.492986,12.40748 8.921325,6.07175 19.286666,5.61396 37.12088,-1.63946 15.35037,-6.24321 21.294999,-7.42408 34.886123,-6.92999 11.77046,0.4279 19.35803,3.05537 24.34054,8.42878 4.97758,5.3681 2.53939,13.58271 -4.86733,16.39873 -4.17361,1.58681 -11.00702,1.19681 -13.31978,-0.76018 z m 26.50156,-0.0787 c -2.26347,-2.50111 -2.07852,-7.36311 0.39995,-10.51398 2.68134,-3.40877 10.49035,-5.69409 18.87656,-5.52426 l 6.5685,0.13301 -7.84029,0.82767 c -8.47925,0.89511 -12.76997,2.82233 -16.03465,7.20213 -1.92294,2.57976 -1.96722,3.00481 -0.57298,5.5 1.00296,1.79495 2.50427,2.81821 4.46514,3.04333 2.92852,0.33623 2.93789,0.32121 1.08045,-1.73124 -1.53602,-1.69728 -1.64654,-2.34411 -0.61324,-3.58916 2.84565,-3.4288 7.14497,-0.49759 5.03976,3.43603 -1.86726,3.48903 -8.65528,4.21532 -11.3692,1.21647 z m -4.17462,-14.20302 c -0.38836,-0.62838 -0.23556,-1.61305 0.33954,-2.18816 1.3439,-1.34389 4.47714,-0.17168 3.93038,1.47045 -0.5566,1.67168 -3.38637,2.14732 -4.26992,0.71771 z m -8.48037,-9.1829 c -12.462,-4.1101 -12.53952,-4.12156 -25.49998,-3.7694 -24.020921,0.65269 -32.338219,0.31756 -37.082166,-1.49417 -5.113999,-1.95305 -8.192504,-6.3647405 -6.485463,-9.2940713 0.566827,-0.972691 1.020091,-1.181447 1.037211,-0.477701 0.01685,0.692606 1.268676,1.2499998 2.807321,1.2499998 1.685814,0 4.868609,1.571672 8.10041,4.0000015 4.221481,3.171961 6.182506,3.999221 9.473089,3.996261 l 4.149585,-0.004 -3.249996,-1.98156 c -3.056252,-1.863441 -4.051566,-3.8760635 -2.623216,-5.3044145 0.794,-0.794 6.188222,1.901516 9.064482,4.5295635 1.858669,1.698271 3.461409,1.980521 10.559493,1.859621 11.30984,-0.19266 20.89052,1.29095 31.97905,4.95208 7.63881,2.52213 11.51931,3.16471 22.05074,3.65141 7.02931,0.32486 13.01836,0.97543 13.30902,1.44571 0.29065,0.47029 -5.2356,0.83436 -12.28056,0.80906 -12.25942,-0.044 -13.34537,-0.2229 -25.30902,-4.16865 z" # noqa
|
||||
@@ -541,7 +536,6 @@ class Ornamental(Style):
|
||||
class Blocks(Style):
|
||||
|
||||
NAME = 'Blocks'
|
||||
GUI_NAME = _('Blocks')
|
||||
FOOTER_ALIGN = Qt.AlignRight | Qt.AlignTop
|
||||
|
||||
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block):
|
||||
|
||||
@@ -222,7 +222,7 @@ class DOCX(object):
|
||||
|
||||
@property
|
||||
def metadata(self):
|
||||
mi = Metadata(_('Unknown'))
|
||||
mi = Metadata('Unknown')
|
||||
dp_name, ap_name = self.get_document_properties_names()
|
||||
if dp_name:
|
||||
try:
|
||||
|
||||
@@ -61,7 +61,7 @@ class Convert(object):
|
||||
self.ws_pat = re.compile(r'[\n\r\t]')
|
||||
self.log = self.docx.log
|
||||
self.detect_cover = detect_cover
|
||||
self.notes_text = notes_text or _('Notes')
|
||||
self.notes_text = notes_text or 'Notes'
|
||||
self.notes_nopb = notes_nopb
|
||||
self.nosupsub = nosupsub
|
||||
self.dest_dir = dest_dir or os.getcwd()
|
||||
@@ -77,7 +77,7 @@ class Convert(object):
|
||||
self.html = HTML(
|
||||
HEAD(
|
||||
META(charset='utf-8'),
|
||||
TITLE(self.mi.title or _('Unknown')),
|
||||
TITLE(self.mi.title or 'Unknown'),
|
||||
LINK(rel='stylesheet', type='text/css', href='docx.css'),
|
||||
),
|
||||
self.body
|
||||
@@ -390,8 +390,9 @@ class Convert(object):
|
||||
|
||||
def process_guide(E, guide):
|
||||
if self.toc_anchor is not None:
|
||||
guide.append(E.reference(
|
||||
href='index.html#' + self.toc_anchor, title=_('Table of Contents'), type='toc'))
|
||||
guide.append(E.reference(href='index.html#' + self.toc_anchor,
|
||||
title='Table of Contents',
|
||||
type='toc'))
|
||||
toc_file = os.path.join(self.dest_dir, 'toc.ncx')
|
||||
with open(os.path.join(self.dest_dir, 'metadata.opf'), 'wb') as of, open(toc_file, 'wb') as ncx:
|
||||
opf.render(of, ncx, 'toc.ncx', process_guide=process_guide)
|
||||
|
||||
@@ -202,7 +202,8 @@ class ImagesManager(object):
|
||||
makeelement(parent, 'wp:extent', cx=str(width), cy=str(height))
|
||||
makeelement(parent, 'wp:effectExtent', l='0', r='0', t='0', b='0')
|
||||
makeelement(parent, 'wp:wrapTopAndBottom')
|
||||
self.create_docx_image_markup(parent, 'cover.jpg', _('Cover'), img.rid, width, height)
|
||||
self.create_docx_image_markup(parent, 'cover.jpg', 'Cover', img.rid,
|
||||
width, height)
|
||||
return ans
|
||||
|
||||
def write_cover_block(self, body, cover_image):
|
||||
|
||||
@@ -161,7 +161,7 @@ class LinksManager(object):
|
||||
pbb.set('{%s}val' % self.namespace.namespaces['w'], 'on')
|
||||
for block in reversed(self.toc):
|
||||
block.serialize(body, self.namespace.makeelement)
|
||||
title = __('Table of Contents')
|
||||
title = 'Table of Contents'
|
||||
makeelement = self.namespace.makeelement
|
||||
p = makeelement(body, 'w:p', append=False)
|
||||
ppr = makeelement(p, 'w:pPr')
|
||||
|
||||
@@ -12,11 +12,11 @@ __docformat__ = 'restructuredtext en'
|
||||
class HTML2ZIP(FileTypePlugin):
|
||||
name = 'HTML to ZIP'
|
||||
author = 'Kovid Goyal'
|
||||
description = textwrap.dedent(_('''\
|
||||
Follow all local links in an HTML file and create a ZIP \
|
||||
file containing all linked files. This plugin is run \
|
||||
every time you add an HTML file to the library.\
|
||||
'''))
|
||||
description = textwrap.dedent('''\
|
||||
Follow all local links in an HTML file and create a ZIP \
|
||||
file containing all linked files. This plugin is run \
|
||||
every time you add an HTML file to the library.\
|
||||
''')
|
||||
version = numeric_version
|
||||
file_types = {'html', 'htm', 'xhtml', 'xhtm', 'shtm', 'shtml'}
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
@@ -60,8 +60,8 @@ every time you add an HTML file to the library.\
|
||||
return of.name
|
||||
|
||||
def customization_help(self, gui=False):
|
||||
return _('Character encoding for the input HTML files. Common choices '
|
||||
'include: cp1252, cp1251, latin1 and utf-8.')
|
||||
return 'Character encoding for the input HTML files. Common choices '
|
||||
'include: cp1252, cp1251, latin1 and utf-8.'
|
||||
|
||||
def do_user_config(self, parent=None):
|
||||
'''
|
||||
@@ -81,7 +81,7 @@ every time you add an HTML file to the library.\
|
||||
|
||||
button_box.accepted.connect(config_dialog.accept)
|
||||
button_box.rejected.connect(config_dialog.reject)
|
||||
config_dialog.setWindowTitle(_('Customize') + ' ' + self.name)
|
||||
config_dialog.setWindowTitle('Customize' + ' ' + self.name)
|
||||
from ebook_converter.customize.ui import (plugin_customization,
|
||||
customize_plugin)
|
||||
help_text = self.customization_help(gui=True)
|
||||
@@ -90,11 +90,12 @@ every time you add an HTML file to the library.\
|
||||
help_text.setTextInteractionFlags(Qt.LinksAccessibleByMouse | Qt.LinksAccessibleByKeyboard)
|
||||
help_text.setOpenExternalLinks(True)
|
||||
v.addWidget(help_text)
|
||||
bf = QCheckBox(_('Add linked files in breadth first order'))
|
||||
bf.setToolTip(_('Normally, when following links in HTML files'
|
||||
' calibre does it depth first, i.e. if file A links to B and '
|
||||
' C, but B links to D, the files are added in the order A, B, D, C. '
|
||||
' With this option, they will instead be added as A, B, C, D'))
|
||||
bf = QCheckBox('Add linked files in breadth first order')
|
||||
bf.setToolTip('Normally, when following links in HTML files calibre '
|
||||
'does it depth first, i.e. if file A links to B and C, '
|
||||
'but B links to D, the files are added in the order A, '
|
||||
'B, D, C. With this option, they will instead be added '
|
||||
'as A, B, C, D')
|
||||
sc = plugin_customization(self)
|
||||
if not sc:
|
||||
sc = ''
|
||||
|
||||
@@ -45,7 +45,7 @@ class OEB2HTML(object):
|
||||
try:
|
||||
self.book_title = str(oeb_book.metadata.title[0])
|
||||
except Exception:
|
||||
self.book_title = _('Unknown')
|
||||
self.book_title = 'Unknown'
|
||||
self.links = {}
|
||||
self.images = {}
|
||||
self.base_hrefs = [item.href for item in oeb_book.spine]
|
||||
|
||||
@@ -322,9 +322,9 @@ class HTMLConverter(object):
|
||||
|
||||
if not self.book_designer and self.is_book_designer(raw):
|
||||
self.book_designer = True
|
||||
self.log.info(_('\tBook Designer file detected.'))
|
||||
self.log.info('\tBook Designer file detected.')
|
||||
|
||||
self.log.info(_('\tParsing HTML...'))
|
||||
self.log.info('\tParsing HTML...')
|
||||
|
||||
if self.baen:
|
||||
nmassage.extend(HTMLConverter.BAEN)
|
||||
@@ -340,7 +340,7 @@ class HTMLConverter(object):
|
||||
soup = html5_parser(raw)
|
||||
if not self.baen and self.is_baen(soup):
|
||||
self.baen = True
|
||||
self.log.info(_('\tBaen file detected. Re-parsing...'))
|
||||
self.log.info('\tBaen file detected. Re-parsing...')
|
||||
return self.preprocess(raw)
|
||||
if self.book_designer:
|
||||
t = soup.find(id='BookTitle')
|
||||
@@ -356,7 +356,7 @@ class HTMLConverter(object):
|
||||
try:
|
||||
with open(os.path.join(tdir, 'html2lrf-verbose.html'), 'wb') as f:
|
||||
f.write(str(soup).encode('utf-8'))
|
||||
self.log.info(_('Written preprocessed HTML to ')+f.name)
|
||||
self.log.info('Written preprocessed HTML to '+f.name)
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -372,7 +372,8 @@ class HTMLConverter(object):
|
||||
self.css[selector] = self.override_css[selector]
|
||||
|
||||
self.file_name = os.path.basename(path)
|
||||
self.log.info(_('Processing %s')%(path if self.verbose else self.file_name))
|
||||
self.log.info('Processing %s' % (path if self.verbose else
|
||||
self.file_name))
|
||||
|
||||
if not os.path.exists(path):
|
||||
path = path.replace('&', '%26') # convertlit replaces & with %26 in file names
|
||||
@@ -385,7 +386,7 @@ class HTMLConverter(object):
|
||||
else:
|
||||
raw = xml_to_unicode(raw, self.verbose)[0]
|
||||
soup = self.preprocess(raw)
|
||||
self.log.info(_('\tConverting to BBeB...'))
|
||||
self.log.info('\tConverting to BBeB...')
|
||||
self.current_style = {}
|
||||
self.page_break_found = False
|
||||
if not isinstance(path, str):
|
||||
@@ -533,12 +534,13 @@ class HTMLConverter(object):
|
||||
for c in self.current_page.contents:
|
||||
if isinstance(c, (TextBlock, ImageBlock)):
|
||||
return c
|
||||
raise ConversionError(_('Could not parse file: %s')%self.file_name)
|
||||
raise ConversionError('Could not parse file: %s' %
|
||||
self.file_name)
|
||||
else:
|
||||
try:
|
||||
index = self.book.pages().index(opage)
|
||||
except ValueError:
|
||||
self.log.warning(_('%s is an empty file')%self.file_name)
|
||||
self.log.warning('%s is an empty file' % self.file_name)
|
||||
tb = self.book.create_text_block()
|
||||
self.current_page.append(tb)
|
||||
return tb
|
||||
@@ -546,7 +548,8 @@ class HTMLConverter(object):
|
||||
for c in page.contents:
|
||||
if isinstance(c, (TextBlock, ImageBlock, Canvas)):
|
||||
return c
|
||||
raise ConversionError(_('Could not parse file: %s')%self.file_name)
|
||||
raise ConversionError('Could not parse file: %s' %
|
||||
self.file_name)
|
||||
|
||||
return top
|
||||
|
||||
@@ -557,9 +560,8 @@ class HTMLConverter(object):
|
||||
para = children[i]
|
||||
break
|
||||
if para is None:
|
||||
raise ConversionError(
|
||||
_('Failed to parse link %(tag)s %(children)s')%dict(
|
||||
tag=tag, children=children))
|
||||
raise ConversionError('Failed to parse link %(tag)s %(children)s' %
|
||||
dict(tag=tag, children=children))
|
||||
text = self.get_text(tag, 1000)
|
||||
if not text:
|
||||
text = 'Link'
|
||||
@@ -941,9 +943,8 @@ class HTMLConverter(object):
|
||||
self.scaled_images[path] = pt
|
||||
return pt.name
|
||||
except (IOError, SystemError) as err: # PIL chokes on interlaced PNG images as well a some GIF images
|
||||
self.log.warning(
|
||||
_('Unable to process image %(path)s. Error: %(err)s')%dict(
|
||||
path=path, err=err))
|
||||
self.log.warning('Unable to process image %(path)s. Error: '
|
||||
'%(err)s' % dict(path=path, err=err))
|
||||
|
||||
if width is None or height is None:
|
||||
width, height = im.size
|
||||
@@ -988,7 +989,8 @@ class HTMLConverter(object):
|
||||
self.rotated_images[path] = pt
|
||||
width, height = im.size
|
||||
except IOError: # PIL chokes on interlaced PNG files and since auto-rotation is not critical we ignore the error
|
||||
self.log.debug(_('Unable to process interlaced PNG %s')% original_path)
|
||||
self.log.debug('Unable to process interlaced PNG %s' %
|
||||
original_path)
|
||||
finally:
|
||||
pt.close()
|
||||
|
||||
@@ -1725,9 +1727,11 @@ class HTMLConverter(object):
|
||||
try:
|
||||
self.process_table(tag, tag_css)
|
||||
except Exception as err:
|
||||
self.log.warning(_('An error occurred while processing a table: %s. Ignoring table markup.')%repr(err))
|
||||
self.log.warning('An error occurred while processing a '
|
||||
'table: %s. Ignoring table markup.' %
|
||||
repr(err))
|
||||
self.log.exception('')
|
||||
self.log.debug(_('Bad table:\n%s')%str(tag)[:300])
|
||||
self.log.debug('Bad table:\n%s' % str(tag)[:300])
|
||||
self.in_table = False
|
||||
self.process_children(tag, tag_css, tag_pseudo_css)
|
||||
finally:
|
||||
@@ -1749,7 +1753,7 @@ class HTMLConverter(object):
|
||||
for block, xpos, ypos, delta, targets in table.blocks(int(ps['textwidth']), int(ps['textheight'])):
|
||||
if not block:
|
||||
if ypos > int(ps['textheight']):
|
||||
raise Exception(_('Table has cell that is too large'))
|
||||
raise Exception('Table has cell that is too large')
|
||||
canvases.append(Canvas(int(self.current_page.pageStyle.attrs['textwidth']), ypos+rowpad,
|
||||
blockrule='block-fixed'))
|
||||
for name in targets:
|
||||
@@ -1813,10 +1817,10 @@ def process_file(path, options, logger):
|
||||
tim.save(tf.name)
|
||||
tpath = tf.name
|
||||
except IOError as err: # PIL sometimes fails, for example on interlaced PNG files
|
||||
logger.warn(_('Could not read cover image: %s'), err)
|
||||
logger.warn('Could not read cover image: %s', err)
|
||||
options.cover = None
|
||||
else:
|
||||
raise ConversionError(_('Cannot read from: %s')% (options.cover,))
|
||||
raise ConversionError('Cannot read from: %s'% (options.cover,))
|
||||
|
||||
if not options.title:
|
||||
options.title = default_title
|
||||
@@ -1844,9 +1848,9 @@ def process_file(path, options, logger):
|
||||
header = Paragraph()
|
||||
fheader = options.headerformat
|
||||
if not options.title:
|
||||
options.title = _('Unknown')
|
||||
options.title = 'Unknown'
|
||||
if not options.author:
|
||||
options.author = _('Unknown')
|
||||
options.author = 'Unknown'
|
||||
if not fheader:
|
||||
fheader = "%t by %a"
|
||||
fheader = re.sub(r'(?<!%)%t', options.title, fheader)
|
||||
@@ -1946,4 +1950,4 @@ def try_opf(path, options, logger):
|
||||
if not getattr(options, 'toc', None):
|
||||
options.toc = opf.toc
|
||||
except Exception:
|
||||
logger.exception(_('Failed to process OPF file'))
|
||||
logger.exception('Failed to process OPF file')
|
||||
|
||||
@@ -344,9 +344,9 @@ class ResourceCollection(object):
|
||||
res.set_basedir(path)
|
||||
|
||||
|
||||
def MetaInformation(title, authors=(_('Unknown'),)):
|
||||
def MetaInformation(title, authors=('Unknown',)):
|
||||
''' Convenient encapsulation of book metadata, needed for compatibility
|
||||
@param title: title or ``_('Unknown')`` or a MetaInformation object
|
||||
@param title: title or ``'Unknown'`` or a MetaInformation object
|
||||
@param authors: List of strings or []
|
||||
'''
|
||||
from ebook_converter.ebooks.metadata.book.base import Metadata
|
||||
|
||||
@@ -40,8 +40,9 @@ class KPFExtract(FileTypePlugin):
|
||||
|
||||
name = 'KPF Extract'
|
||||
author = 'Kovid Goyal'
|
||||
description = _('Extract the source DOCX file from Amazon Kindle Create KPF files.'
|
||||
' Note this will not contain any edits made in the Kindle Create program itself.')
|
||||
description = ('Extract the source DOCX file from Amazon Kindle Create '
|
||||
'KPF files. Note this will not contain any edits made in '
|
||||
'the Kindle Create program itself.')
|
||||
file_types = {'kpf'}
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
on_import = True
|
||||
@@ -62,9 +63,9 @@ class KPFExtract(FileTypePlugin):
|
||||
class ArchiveExtract(FileTypePlugin):
|
||||
name = 'Archive Extract'
|
||||
author = 'Kovid Goyal'
|
||||
description = _('Extract common e-book formats from archive files '
|
||||
'(ZIP/RAR). Also try to autodetect if they are actually '
|
||||
'CBZ/CBR files.')
|
||||
description = ('Extract common e-book formats from archive files (ZIP/'
|
||||
'RAR). Also try to autodetect if they are actually CBZ/CBR '
|
||||
'files.')
|
||||
file_types = {'zip', 'rar'}
|
||||
supported_platforms = ['windows', 'osx', 'linux']
|
||||
on_import = True
|
||||
|
||||
@@ -21,11 +21,11 @@ TOP_LEVEL_IDENTIFIERS = frozenset((
|
||||
))
|
||||
|
||||
PUBLICATION_METADATA_FIELDS = frozenset((
|
||||
'title', # title must never be None. Should be _('Unknown')
|
||||
'title', # title must never be None. Should be 'Unknown'
|
||||
# Pseudo field that can be set, but if not set is auto generated
|
||||
# from title and languages
|
||||
'title_sort',
|
||||
'authors', # Ordered list. Must never be None, can be [_('Unknown')]
|
||||
'authors', # Ordered list. Must never be None, can be ['Unknown']
|
||||
'author_sort_map', # Map of sort strings for each author
|
||||
# Pseudo field that can be set, but if not set is auto generated
|
||||
# from authors and languages
|
||||
|
||||
@@ -24,21 +24,19 @@ def human_readable(size, precision=2):
|
||||
return ('%.'+str(precision)+'f'+ 'MB') % (size/(1024*1024),)
|
||||
|
||||
|
||||
NULL_VALUES = {
|
||||
'user_metadata': {},
|
||||
'cover_data' : (None, None),
|
||||
'tags' : [],
|
||||
'identifiers' : {},
|
||||
'languages' : [],
|
||||
'device_collections': [],
|
||||
'author_sort_map': {},
|
||||
'authors' : [_('Unknown')],
|
||||
'author_sort' : _('Unknown'),
|
||||
'title' : _('Unknown'),
|
||||
'user_categories' : {},
|
||||
'author_link_map' : {},
|
||||
'language' : 'und'
|
||||
}
|
||||
NULL_VALUES = {'user_metadata': {},
|
||||
'cover_data': (None, None),
|
||||
'tags': [],
|
||||
'identifiers': {},
|
||||
'languages': [],
|
||||
'device_collections': [],
|
||||
'author_sort_map': {},
|
||||
'authors': ['Unknown'],
|
||||
'author_sort': 'Unknown',
|
||||
'title': 'Unknown',
|
||||
'user_categories': {},
|
||||
'author_link_map': {},
|
||||
'language': 'und'}
|
||||
|
||||
field_metadata = FieldMetadata()
|
||||
|
||||
@@ -74,10 +72,10 @@ class Metadata(object):
|
||||
'''
|
||||
__calibre_serializable__ = True
|
||||
|
||||
def __init__(self, title, authors=(_('Unknown'),), other=None, template_cache=None,
|
||||
formatter=None):
|
||||
def __init__(self, title, authors=('Unknown',), other=None,
|
||||
template_cache=None, formatter=None):
|
||||
'''
|
||||
@param title: title or ``_('Unknown')``
|
||||
@param title: title or ``'Unknown'``
|
||||
@param authors: List of strings or []
|
||||
@param other: None or a metadata object
|
||||
'''
|
||||
@@ -101,7 +99,7 @@ class Metadata(object):
|
||||
'''
|
||||
Return True if the value of field is null in this object.
|
||||
'null' means it is unknown or evaluates to False. So a title of
|
||||
_('Unknown') is null or a language of 'und' is null.
|
||||
'Unknown' is null or a language of 'und' is null.
|
||||
|
||||
Be careful with numeric fields since this will return True for zero as
|
||||
well as None.
|
||||
@@ -142,11 +140,9 @@ class Metadata(object):
|
||||
if val is None:
|
||||
d['#value#'] = 'RECURSIVE_COMPOSITE FIELD (Metadata) ' + field
|
||||
val = d['#value#'] = self.formatter.safe_format(
|
||||
d['display']['composite_template'],
|
||||
self,
|
||||
_('TEMPLATE ERROR'),
|
||||
self, column_name=field,
|
||||
template_cache=self.template_cache).strip()
|
||||
d['display']['composite_template'], self, 'TEMPLATE ERROR',
|
||||
self, column_name=field,
|
||||
template_cache=self.template_cache).strip()
|
||||
return val
|
||||
if field.startswith('#') and field.endswith('_index'):
|
||||
try:
|
||||
@@ -474,7 +470,7 @@ class Metadata(object):
|
||||
if v not in (None, NULL_VALUES.get(attr, None)):
|
||||
setattr(dest, attr, copy.deepcopy(v))
|
||||
|
||||
unknown = _('Unknown')
|
||||
unknown = 'Unknown'
|
||||
if other.title and other.title != unknown:
|
||||
self.title = other.title
|
||||
if hasattr(other, 'title_sort'):
|
||||
@@ -658,7 +654,7 @@ class Metadata(object):
|
||||
elif datatype == 'datetime':
|
||||
res = format_date(res, cmeta['display'].get('date_format','dd MMM yyyy'))
|
||||
elif datatype == 'bool':
|
||||
res = _('Yes') if res else _('No')
|
||||
res = 'Yes' if res else 'No'
|
||||
elif datatype == 'rating':
|
||||
res = '%.2g'%(res/2)
|
||||
elif datatype in ['int', 'float']:
|
||||
@@ -725,7 +721,7 @@ class Metadata(object):
|
||||
if self.authors:
|
||||
fmt('Author(s)', authors_to_string(self.authors) +
|
||||
((' [' + self.author_sort + ']')
|
||||
if self.author_sort and self.author_sort != _('Unknown') else ''))
|
||||
if self.author_sort and self.author_sort != 'Unknown' else ''))
|
||||
if self.publisher:
|
||||
fmt('Publisher', self.publisher)
|
||||
if getattr(self, 'book_producer', False):
|
||||
@@ -764,22 +760,26 @@ class Metadata(object):
|
||||
'''
|
||||
from ebook_converter.ebooks.metadata import authors_to_string
|
||||
from ebook_converter.utils.date import isoformat
|
||||
ans = [(_('Title'), str(self.title))]
|
||||
ans += [(_('Author(s)'), (authors_to_string(self.authors) if self.authors else _('Unknown')))]
|
||||
ans += [(_('Publisher'), str(self.publisher))]
|
||||
ans += [(_('Producer'), str(self.book_producer))]
|
||||
ans += [(_('Comments'), str(self.comments))]
|
||||
ans = [('Title', str(self.title))]
|
||||
ans += [('Author(s)', (authors_to_string(self.authors)
|
||||
if self.authors else 'Unknown'))]
|
||||
ans += [('Publisher', str(self.publisher))]
|
||||
ans += [('Producer', str(self.book_producer))]
|
||||
ans += [('Comments', str(self.comments))]
|
||||
ans += [('ISBN', str(self.isbn))]
|
||||
ans += [(_('Tags'), ', '.join([str(t) for t in self.tags]))]
|
||||
ans += [('Tags', ', '.join([str(t) for t in self.tags]))]
|
||||
if self.series:
|
||||
ans += [(_('Series'), str(self.series) + ' #%s'%self.format_series_index())]
|
||||
ans += [(_('Languages'), ', '.join(self.languages))]
|
||||
ans += [('Series', str(self.series) +
|
||||
' #%s' % self.format_series_index())]
|
||||
ans += [('Languages', ', '.join(self.languages))]
|
||||
if self.timestamp is not None:
|
||||
ans += [(_('Timestamp'), str(isoformat(self.timestamp, as_utc=False, sep=' ')))]
|
||||
ans += [('Timestamp', str(isoformat(self.timestamp, as_utc=False,
|
||||
sep=' ')))]
|
||||
if self.pubdate is not None:
|
||||
ans += [(_('Published'), str(isoformat(self.pubdate, as_utc=False, sep=' ')))]
|
||||
ans += [('Published', str(isoformat(self.pubdate, as_utc=False,
|
||||
sep=' ')))]
|
||||
if self.rights is not None:
|
||||
ans += [(_('Rights'), str(self.rights))]
|
||||
ans += [('Rights', str(self.rights))]
|
||||
for key in self.custom_field_keys():
|
||||
val = self.get(key, None)
|
||||
if val:
|
||||
|
||||
@@ -25,7 +25,7 @@ class SafeFormat(TemplateFormatter):
|
||||
if hasattr(self.book, orig_key):
|
||||
key = orig_key
|
||||
else:
|
||||
raise ValueError(_('Value: unknown field ') + orig_key)
|
||||
raise ValueError('Value: unknown field ' + orig_key)
|
||||
try:
|
||||
b = self.book.get_user_metadata(key, False)
|
||||
except:
|
||||
|
||||
@@ -110,7 +110,7 @@ def get_metadata(stream):
|
||||
root = _get_fbroot(get_fb2_data(stream)[0])
|
||||
ctx = Context(root)
|
||||
book_title = _parse_book_title(root, ctx)
|
||||
authors = _parse_authors(root, ctx) or [_('Unknown')]
|
||||
authors = _parse_authors(root, ctx) or ['Unknown']
|
||||
|
||||
# fallback for book_title
|
||||
if book_title:
|
||||
@@ -118,7 +118,7 @@ def get_metadata(stream):
|
||||
else:
|
||||
book_title = force_unicode(os.path.splitext(
|
||||
os.path.basename(getattr(stream, 'name',
|
||||
_('Unknown'))))[0])
|
||||
'Unknown')))[0])
|
||||
mi = MetaInformation(book_title, authors)
|
||||
|
||||
try:
|
||||
@@ -173,7 +173,7 @@ def _parse_authors(root, ctx):
|
||||
|
||||
# if no author so far
|
||||
if not authors:
|
||||
authors.append(_('Unknown'))
|
||||
authors.append('Unknown')
|
||||
|
||||
return authors
|
||||
|
||||
|
||||
@@ -151,10 +151,10 @@ def get_metadata_(src, encoding=None):
|
||||
return ans
|
||||
|
||||
# Title
|
||||
title = get('title') or title_tag.strip() or _('Unknown')
|
||||
title = get('title') or title_tag.strip() or 'Unknown'
|
||||
|
||||
# Author
|
||||
authors = authors_to_string(get_all('authors')) or _('Unknown')
|
||||
authors = authors_to_string(get_all('authors')) or 'Unknown'
|
||||
|
||||
# Create MetaInformation with Title and Author
|
||||
mi = Metadata(title, string_to_authors(authors))
|
||||
@@ -340,7 +340,7 @@ class MetadataHtmlTest(unittest.TestCase):
|
||||
|
||||
def test_input_title(self):
|
||||
stream_meta = get_metadata(self.get_stream('title'))
|
||||
canon_meta = Metadata('A Title Tag & Title Ⓒ', [_('Unknown')])
|
||||
canon_meta = Metadata('A Title Tag & Title Ⓒ', ['Unknown'])
|
||||
self.compare_metadata(stream_meta, canon_meta)
|
||||
|
||||
def test_input_meta_single(self):
|
||||
|
||||
@@ -33,7 +33,7 @@ def metadata_from_formats(formats, force_read_metadata=False, pattern=None):
|
||||
except:
|
||||
mi = metadata_from_filename(list(iter(formats))[0], pat=pattern)
|
||||
if not mi.authors:
|
||||
mi.authors = [_('Unknown')]
|
||||
mi.authors = ['Unknown']
|
||||
return mi
|
||||
|
||||
|
||||
@@ -61,9 +61,9 @@ def _metadata_from_formats(formats, force_read_metadata=False, pattern=None):
|
||||
return mi
|
||||
|
||||
if not mi.title:
|
||||
mi.title = _('Unknown')
|
||||
mi.title = 'Unknown'
|
||||
if not mi.authors:
|
||||
mi.authors = [_('Unknown')]
|
||||
mi.authors = ['Unknown']
|
||||
|
||||
return mi
|
||||
|
||||
@@ -106,9 +106,9 @@ def _get_metadata(stream, stream_type, use_libprs_metadata,
|
||||
base = metadata_from_filename(name, pat=pattern, fallback_pat=re.compile(
|
||||
r'^(?P<title>.+) - (?P<author>[^-]+)$'))
|
||||
if not base.authors:
|
||||
base.authors = [_('Unknown')]
|
||||
base.authors = ['Unknown']
|
||||
if not base.title:
|
||||
base.title = _('Unknown')
|
||||
base.title = 'Unknown'
|
||||
mi = MetaInformation(None, None)
|
||||
if force_read_metadata or prefs['read_file_metadata']:
|
||||
mi = get_file_type_metadata(stream, stream_type)
|
||||
|
||||
@@ -1360,7 +1360,7 @@ class OPFCreator(Metadata):
|
||||
if not isinstance(self.toc, TOC):
|
||||
self.toc = None
|
||||
if not self.authors:
|
||||
self.authors = [_('Unknown')]
|
||||
self.authors = ['Unknown']
|
||||
if self.guide is None:
|
||||
self.guide = Guide()
|
||||
if self.cover:
|
||||
@@ -1470,7 +1470,7 @@ class OPFCreator(Metadata):
|
||||
metadata = M.metadata()
|
||||
a = metadata.append
|
||||
role = {}
|
||||
a(DC_ELEM('title', self.title if self.title else _('Unknown'),
|
||||
a(DC_ELEM('title', self.title if self.title else 'Unknown',
|
||||
opf_attrs=role))
|
||||
for i, author in enumerate(self.authors):
|
||||
fa = {'role':'aut'}
|
||||
@@ -1679,7 +1679,7 @@ def metadata_to_opf(mi, as_string=True, default_lang=None):
|
||||
mi.cover = mi.cover.decode(filesystem_encoding)
|
||||
guide.text = '\n'+(' '*8)
|
||||
r = guide.makeelement(OPF('reference'),
|
||||
attrib={'type':'cover', 'title':_('Cover'), 'href':mi.cover})
|
||||
attrib={'type': 'cover', 'title': 'Cover', 'href': mi.cover})
|
||||
r.tail = '\n' +(' '*4)
|
||||
guide.append(r)
|
||||
if pretty_print_opf:
|
||||
|
||||
@@ -960,7 +960,7 @@ def set_last_modified_in_opf(root):
|
||||
|
||||
|
||||
def read_metadata(root, ver=None, return_extra_data=False):
|
||||
ans = Metadata(_('Unknown'), [_('Unknown')])
|
||||
ans = Metadata('Unknown', ['Unknown'])
|
||||
prefixes, refines = read_prefixes(root), read_refines(root)
|
||||
identifiers = read_identifiers(root, prefixes, refines)
|
||||
ids = {}
|
||||
|
||||
@@ -122,10 +122,10 @@ def get_metadata(stream, cover=True):
|
||||
with open(covpath, 'rb') as f:
|
||||
cdata = f.read()
|
||||
|
||||
title = info.get('Title', None) or _('Unknown')
|
||||
title = info.get('Title', None) or 'Unknown'
|
||||
au = info.get('Author', None)
|
||||
if au is None:
|
||||
au = [_('Unknown')]
|
||||
au = ['Unknown']
|
||||
else:
|
||||
au = string_to_authors(au)
|
||||
mi = MetaInformation(title, au)
|
||||
|
||||
@@ -110,10 +110,10 @@ def get_metadata(stream):
|
||||
"""
|
||||
stream.seek(0)
|
||||
if stream.read(5) != br'{\rtf':
|
||||
return MetaInformation(_('Unknown'))
|
||||
return MetaInformation('Unknown')
|
||||
block = get_document_info(stream)[0]
|
||||
if not block:
|
||||
return MetaInformation(_('Unknown'))
|
||||
return MetaInformation('Unknown')
|
||||
|
||||
stream.seek(0)
|
||||
cpg = detect_codepage(stream)
|
||||
@@ -123,7 +123,7 @@ def get_metadata(stream):
|
||||
if title_match is not None:
|
||||
title = decode(title_match.group(1).strip(), cpg)
|
||||
else:
|
||||
title = _('Unknown')
|
||||
title = 'Unknown'
|
||||
author_match = author_pat.search(block)
|
||||
if author_match is not None:
|
||||
author = decode(author_match.group(1).strip(), cpg)
|
||||
|
||||
@@ -17,7 +17,7 @@ def get_metadata(stream, extract_cover=True):
|
||||
name = getattr(stream, 'name', '').rpartition('.')[0]
|
||||
if name:
|
||||
name = os.path.basename(name)
|
||||
mi = MetaInformation(name or _('Unknown'), [_('Unknown')])
|
||||
mi = MetaInformation(name or 'Unknown', ['Unknown'])
|
||||
stream.seek(0)
|
||||
|
||||
mdata = ''
|
||||
|
||||
@@ -235,7 +235,7 @@ def more_recent(one, two):
|
||||
|
||||
def metadata_from_xmp_packet(raw_bytes):
|
||||
root = parse_xmp_packet(raw_bytes)
|
||||
mi = Metadata(_('Unknown'))
|
||||
mi = Metadata('Unknown')
|
||||
title = first_alt('//dc:title', root)
|
||||
if title:
|
||||
if title.startswith(r'\376\377'):
|
||||
@@ -346,7 +346,9 @@ def consolidate_metadata(info_mi, info):
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return info_mi
|
||||
info_title, info_authors, info_tags = info_mi.title or _('Unknown'), list(info_mi.authors or ()), list(info_mi.tags or ())
|
||||
info_title = info_mi.title or 'Unknown'
|
||||
info_authors = list(info_mi.authors or ())
|
||||
info_tags = list(info_mi.tags or ())
|
||||
info_mi.smart_update(xmp_mi, replace_metadata=True)
|
||||
prefer_info = False
|
||||
if 'ModDate' in info and hasattr(xmp_mi, 'metadata_date'):
|
||||
|
||||
@@ -32,7 +32,7 @@ class EXTHHeader(object): # {{{
|
||||
self.length, self.num_items = struct.unpack('>LL', raw[4:12])
|
||||
raw = raw[12:]
|
||||
pos = 0
|
||||
self.mi = MetaInformation(_('Unknown'), [_('Unknown')])
|
||||
self.mi = MetaInformation('Unknown', ['Unknown'])
|
||||
self.has_fake_cover = True
|
||||
self.start_offset = None
|
||||
left = self.num_items
|
||||
@@ -67,7 +67,7 @@ class EXTHHeader(object): # {{{
|
||||
if content == b'EBSP':
|
||||
if not self.mi.tags:
|
||||
self.mi.tags = []
|
||||
self.mi.tags.append(_('Sample Book'))
|
||||
self.mi.tags.append('Sample Book')
|
||||
elif idx == 502:
|
||||
# last update time
|
||||
pass
|
||||
@@ -127,7 +127,7 @@ class EXTHHeader(object): # {{{
|
||||
self.mi.authors.append(au)
|
||||
elif idx == 101:
|
||||
self.mi.publisher = clean_xml_chars(self.decode(content).strip())
|
||||
if self.mi.publisher in {'Unknown', _('Unknown')}:
|
||||
if self.mi.publisher in {'Unknown', 'Unknown'}:
|
||||
self.mi.publisher = None
|
||||
elif idx == 103:
|
||||
self.mi.comments = clean_xml_chars(self.decode(content).strip())
|
||||
@@ -194,7 +194,7 @@ class BookHeader(object):
|
||||
if len(raw) <= 16:
|
||||
self.codec = 'cp1252'
|
||||
self.extra_flags = 0
|
||||
self.title = _('Unknown')
|
||||
self.title = 'Unknown'
|
||||
self.language = 'ENGLISH'
|
||||
self.sublanguage = 'NEUTRAL'
|
||||
self.exth_flag, self.exth = 0, None
|
||||
@@ -233,7 +233,7 @@ class BookHeader(object):
|
||||
|
||||
toff, tlen = struct.unpack('>II', raw[0x54:0x5c])
|
||||
tend = toff + tlen
|
||||
self.title = raw[toff:tend] if tend < len(raw) else _('Unknown')
|
||||
self.title = raw[toff:tend] if tend < len(raw) else 'Unknown'
|
||||
langcode = struct.unpack('!L', raw[0x5C:0x60])[0]
|
||||
langid = langcode & 0xFF
|
||||
sublangid = (langcode >> 10) & 0xFF
|
||||
|
||||
@@ -30,10 +30,10 @@ class TopazError(ValueError):
|
||||
class KFXError(ValueError):
|
||||
|
||||
def __init__(self):
|
||||
ValueError.__init__(self, _(
|
||||
'This is an Amazon KFX book. It cannot be processed.'
|
||||
' See {} for information on how to handle KFX books.'
|
||||
).format('https://www.mobileread.com/forums/showthread.php?t=283371'))
|
||||
ValueError.__init__(self, 'This is an Amazon KFX book. It cannot be '
|
||||
'processed. See https://www.mobileread.com/forums/'
|
||||
'showthread.php?t=283371 for information on how '
|
||||
'to handle KFX books.')
|
||||
|
||||
|
||||
class MobiReader(object):
|
||||
@@ -77,7 +77,8 @@ class MobiReader(object):
|
||||
|
||||
raw = stream.read()
|
||||
if raw.startswith(b'TPZ'):
|
||||
raise TopazError(_('This is an Amazon Topaz book. It cannot be processed.'))
|
||||
raise TopazError('This is an Amazon Topaz book. It cannot be '
|
||||
'processed.')
|
||||
if raw.startswith(b'\xeaDRMION\xee'):
|
||||
raise KFXError()
|
||||
|
||||
@@ -642,7 +643,7 @@ class MobiReader(object):
|
||||
def create_opf(self, htmlfile, guide=None, root=None):
|
||||
mi = getattr(self.book_header.exth, 'mi', self.embedded_mi)
|
||||
if mi is None:
|
||||
mi = MetaInformation(self.book_header.title, [_('Unknown')])
|
||||
mi = MetaInformation(self.book_header.title, ['Unknown'])
|
||||
opf = OPFCreator(os.path.dirname(htmlfile), mi)
|
||||
if hasattr(self.book_header.exth, 'cover_offset'):
|
||||
opf.cover = 'images/%05d.jpg' % (self.book_header.exth.cover_offset + 1)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import os, glob
|
||||
import glob
|
||||
import os
|
||||
|
||||
from ebook_converter import CurrentDir
|
||||
from ebook_converter.ebooks.mobi import MobiError
|
||||
@@ -8,8 +9,8 @@ from ebook_converter.utils.logging import default_log
|
||||
from ebook_converter.ebooks import DRMError
|
||||
from ebook_converter.ebooks.mobi.reader.mobi8 import Mobi8Reader
|
||||
from ebook_converter.ebooks.conversion.plumber import Plumber, create_oebbook
|
||||
from ebook_converter.customize.ui import (plugin_for_input_format,
|
||||
plugin_for_output_format)
|
||||
from ebook_converter.customize.ui import plugin_for_input_format
|
||||
from ebook_converter.customize.ui import plugin_for_output_format
|
||||
from ebook_converter.utils.ipc.simple_worker import fork_job
|
||||
|
||||
|
||||
@@ -31,44 +32,46 @@ def do_explode(path, dest):
|
||||
opf = os.path.abspath(mr())
|
||||
try:
|
||||
os.remove('debug-raw.html')
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return opf
|
||||
|
||||
|
||||
def explode(path, dest, question=lambda x:True):
|
||||
def explode(path, dest, question=lambda x: True):
|
||||
with open(path, 'rb') as stream:
|
||||
raw = stream.read(3)
|
||||
stream.seek(0)
|
||||
if raw == b'TPZ':
|
||||
raise BadFormat(_('This is not a MOBI file. It is a Topaz file.'))
|
||||
raise BadFormat('This is not a MOBI file. It is a Topaz file.')
|
||||
|
||||
try:
|
||||
header = MetadataHeader(stream, default_log)
|
||||
except MobiError:
|
||||
raise BadFormat(_('This is not a MOBI file.'))
|
||||
raise BadFormat('This is not a MOBI file.')
|
||||
|
||||
if header.encryption_type != 0:
|
||||
raise DRMError(_('This file is locked with DRM. It cannot be tweaked.'))
|
||||
raise DRMError('This file is locked with DRM. It cannot be '
|
||||
'tweaked.')
|
||||
|
||||
kf8_type = header.kf8_type
|
||||
|
||||
if kf8_type is None:
|
||||
raise BadFormat(_('This MOBI file does not contain a KF8 format '
|
||||
'book. KF8 is the new format from Amazon. calibre can '
|
||||
'only tweak MOBI files that contain KF8 books. Older '
|
||||
'MOBI files without KF8 are not tweakable.'))
|
||||
raise BadFormat('This MOBI file does not contain a KF8 format '
|
||||
'book. KF8 is the new format from Amazon. calibre '
|
||||
'can only tweak MOBI files that contain KF8 '
|
||||
'books. Older MOBI files without KF8 are not '
|
||||
'tweakable.')
|
||||
|
||||
if kf8_type == 'joint':
|
||||
if not question(_('This MOBI file contains both KF8 and '
|
||||
'older Mobi6 data. Tweaking it will remove the Mobi6 data, which '
|
||||
'means the file will not be usable on older Kindles. Are you '
|
||||
'sure?')):
|
||||
if not question('This MOBI file contains both KF8 and older Mobi6 '
|
||||
'data. Tweaking it will remove the Mobi6 data, '
|
||||
'which means the file will not be usable on older '
|
||||
'Kindles. Are you sure?'):
|
||||
return None
|
||||
|
||||
return fork_job('ebook_converter.ebooks.mobi.tweak', 'do_explode', args=(path,
|
||||
dest), no_output=True)['result']
|
||||
return fork_job('ebook_converter.ebooks.mobi.tweak', 'do_explode',
|
||||
args=(path, dest), no_output=True)['result']
|
||||
|
||||
|
||||
def set_cover(oeb):
|
||||
@@ -96,11 +99,10 @@ def do_rebuild(opf, dest_path):
|
||||
def rebuild(src_dir, dest_path):
|
||||
opf = glob.glob(os.path.join(src_dir, '*.opf'))
|
||||
if not opf:
|
||||
raise ValueError('No OPF file found in %s'%src_dir)
|
||||
raise ValueError('No OPF file found in %s' % src_dir)
|
||||
opf = opf[0]
|
||||
# For debugging, uncomment the following two lines
|
||||
# def fork_job(a, b, args=None, no_output=True):
|
||||
# do_rebuild(*args)
|
||||
fork_job('ebook_converter.ebooks.mobi.tweak', 'do_rebuild', args=(opf, dest_path),
|
||||
no_output=True)
|
||||
|
||||
fork_job('ebook_converter.ebooks.mobi.tweak', 'do_rebuild',
|
||||
args=(opf, dest_path), no_output=True)
|
||||
|
||||
@@ -336,7 +336,7 @@ def utf8_text(text):
|
||||
text = text.decode('utf-8', 'replace')
|
||||
text = normalize(text).encode('utf-8')
|
||||
else:
|
||||
text = _('Unknown').encode('utf-8')
|
||||
text = 'Unknown'.encode('utf-8')
|
||||
return text
|
||||
|
||||
|
||||
|
||||
@@ -461,9 +461,9 @@ class Indexer(object): # {{{
|
||||
if node.klass == 'article':
|
||||
aut, desc = node.author, node.description
|
||||
if not aut:
|
||||
aut = _('Unknown')
|
||||
aut = 'Unknown'
|
||||
if not desc:
|
||||
desc = _('No details available')
|
||||
desc = 'No details available'
|
||||
node.author, node.description = aut, desc
|
||||
|
||||
self.cncx = CNCX(oeb.toc, self.is_periodical)
|
||||
|
||||
@@ -276,9 +276,9 @@ class Extract(ODF2XHTML):
|
||||
stream.seek(0)
|
||||
mi = get_metadata(stream, 'odt')
|
||||
if not mi.title:
|
||||
mi.title = _('Unknown')
|
||||
mi.title = 'Unknown'
|
||||
if not mi.authors:
|
||||
mi.authors = [_('Unknown')]
|
||||
mi.authors = ['Unknown']
|
||||
self.filter_load(stream, mi, log)
|
||||
|
||||
# NOTE(gryf): Here is a workaround for ODF2XHTML.xhtml() method,
|
||||
|
||||
@@ -967,7 +967,7 @@ class Manifest(object):
|
||||
if title:
|
||||
title = str(title[0])
|
||||
else:
|
||||
title = _('Unknown')
|
||||
title = 'Unknown'
|
||||
|
||||
return self._parse_xhtml(convert_markdown(data, title=title))
|
||||
|
||||
@@ -1368,23 +1368,23 @@ class Guide(object):
|
||||
:attr:`href`: Book-internal URL of the referenced section. May include
|
||||
a fragment identifier.
|
||||
"""
|
||||
_TYPES_TITLES = [('cover', __('Cover')),
|
||||
('title-page', __('Title page')),
|
||||
('toc', __('Table of Contents')),
|
||||
('index', __('Index')),
|
||||
('glossary', __('Glossary')),
|
||||
('acknowledgements', __('Acknowledgements')),
|
||||
('bibliography', __('Bibliography')),
|
||||
('colophon', __('Colophon')),
|
||||
('copyright-page', __('Copyright')),
|
||||
('dedication', __('Dedication')),
|
||||
('epigraph', __('Epigraph')),
|
||||
('foreword', __('Foreword')),
|
||||
('loi', __('List of illustrations')),
|
||||
('lot', __('List of tables')),
|
||||
('notes', __('Notes')),
|
||||
('preface', __('Preface')),
|
||||
('text', __('Main text'))]
|
||||
_TYPES_TITLES = [('cover', 'Cover'),
|
||||
('title-page', 'Title page'),
|
||||
('toc', 'Table of Contents'),
|
||||
('index', 'Index'),
|
||||
('glossary', 'Glossary'),
|
||||
('acknowledgements', 'Acknowledgements'),
|
||||
('bibliography', 'Bibliography'),
|
||||
('colophon', 'Colophon'),
|
||||
('copyright-page', 'Copyright'),
|
||||
('dedication', 'Dedication'),
|
||||
('epigraph', 'Epigraph'),
|
||||
('foreword', 'Foreword'),
|
||||
('loi', 'List of illustrations'),
|
||||
('lot', 'List of tables'),
|
||||
('notes', 'Notes'),
|
||||
('preface', 'Preface'),
|
||||
('text', 'Main text')]
|
||||
TITLES = dict(_TYPES_TITLES)
|
||||
TYPES = frozenset(TITLES)
|
||||
ORDER = {t: i for i, (t, _) in enumerate(_TYPES_TITLES)}
|
||||
|
||||
@@ -312,14 +312,14 @@ def parse_html(data, log=None, decoder=None, preprocessor=None,
|
||||
head = etree.Element(XHTML('head'))
|
||||
data.insert(0, head)
|
||||
title = etree.SubElement(head, XHTML('title'))
|
||||
title.text = _('Unknown')
|
||||
title.text = 'Unknown'
|
||||
elif not xpath(data, '/h:html/h:head/h:title'):
|
||||
title = etree.SubElement(head, XHTML('title'))
|
||||
title.text = _('Unknown')
|
||||
title.text = 'Unknown'
|
||||
# Ensure <title> is not empty
|
||||
title = xpath(data, '/h:html/h:head/h:title')[0]
|
||||
if not title.text or not title.text.strip():
|
||||
title.text = _('Unknown')
|
||||
title.text = 'Unknown'
|
||||
# Remove any encoding-specifying <meta/> elements
|
||||
for meta in META_XP(data):
|
||||
meta.getparent().remove(meta)
|
||||
|
||||
@@ -1458,12 +1458,13 @@ class AZW3Container(Container):
|
||||
with open(pathtoazw3, 'rb') as stream:
|
||||
raw = stream.read(3)
|
||||
if raw == b'TPZ':
|
||||
raise InvalidMobi(_('This is not a MOBI file. It is a Topaz file.'))
|
||||
raise InvalidMobi('This is not a MOBI file. It is a Topaz '
|
||||
'file.')
|
||||
|
||||
try:
|
||||
header = MetadataHeader(stream, default_log)
|
||||
except MobiError:
|
||||
raise InvalidMobi(_('This is not a MOBI file.'))
|
||||
raise InvalidMobi('This is not a MOBI file.')
|
||||
|
||||
if header.encryption_type != 0:
|
||||
raise DRMError()
|
||||
@@ -1471,15 +1472,16 @@ class AZW3Container(Container):
|
||||
kf8_type = header.kf8_type
|
||||
|
||||
if kf8_type is None:
|
||||
raise InvalidMobi(_('This MOBI file does not contain a KF8 format '
|
||||
'book. KF8 is the new format from Amazon. calibre can '
|
||||
'only edit MOBI files that contain KF8 books. Older '
|
||||
'MOBI files without KF8 are not editable.'))
|
||||
raise InvalidMobi('This MOBI file does not contain a KF8 '
|
||||
'format book. KF8 is the new format from '
|
||||
'Amazon. calibre can only edit MOBI files '
|
||||
'that contain KF8 books. Older MOBI files '
|
||||
'without KF8 are not editable.')
|
||||
|
||||
if kf8_type == 'joint':
|
||||
raise InvalidMobi(_('This MOBI file contains both KF8 and '
|
||||
'older Mobi6 data. calibre can only edit MOBI files '
|
||||
'that contain only KF8 data.'))
|
||||
raise InvalidMobi('This MOBI file contains both KF8 and older '
|
||||
'Mobi6 data. calibre can only edit MOBI '
|
||||
'files that contain only KF8 data.')
|
||||
|
||||
try:
|
||||
opf_path, obfuscated_fonts = fork_job(
|
||||
|
||||
@@ -167,20 +167,19 @@ def remove_unused_css(container, report=None, remove_unused_classes=False, merge
|
||||
num_changes = num_of_removed_rules + num_merged + num_of_removed_classes
|
||||
if num_changes > 0:
|
||||
if num_of_removed_rules > 0:
|
||||
report(ngettext('Removed one unused CSS style rule', 'Removed {} unused CSS style rules',
|
||||
num_of_removed_rules).format(num_of_removed_rules))
|
||||
report('Removed {} unused CSS style '
|
||||
'rules'.format(num_of_removed_rules))
|
||||
if num_of_removed_classes > 0:
|
||||
report(ngettext('Removed one unused class from the HTML', 'Removed {} unused classes from the HTML',
|
||||
num_of_removed_classes).format(num_of_removed_classes))
|
||||
report('Removed {} unused classes from the HTML'
|
||||
.format(num_of_removed_classes))
|
||||
if num_merged > 0:
|
||||
report(ngettext('Merged one CSS style rule', 'Merged {} CSS style rules',
|
||||
num_merged).format(num_merged))
|
||||
report('Merged {} CSS style rules'.format(num_merged))
|
||||
if num_of_removed_rules == 0:
|
||||
report(_('No unused CSS style rules found'))
|
||||
report('No unused CSS style rules found')
|
||||
if remove_unused_classes and num_of_removed_classes == 0:
|
||||
report(_('No unused class attributes found'))
|
||||
report('No unused class attributes found')
|
||||
if merge_rules and num_merged == 0:
|
||||
report(_('No style rules that could be merged found'))
|
||||
report('No style rules that could be merged found')
|
||||
return num_changes > 0
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@ class InvalidBook(ValueError):
|
||||
class DRMError(_DRMError):
|
||||
|
||||
def __init__(self):
|
||||
super(DRMError, self).__init__(_('This file is locked with DRM. It cannot be edited.'))
|
||||
super(DRMError, self).__init__('This file is locked with DRM. It '
|
||||
'cannot be edited.')
|
||||
|
||||
|
||||
class MalformedMarkup(ValueError):
|
||||
|
||||
@@ -157,7 +157,7 @@ def smarten_punctuation(container, report):
|
||||
newhtml = smarten_punctuation(html, container.log)
|
||||
if newhtml != html:
|
||||
changed = True
|
||||
report(_('Smartened punctuation in: %s')%name)
|
||||
report('Smartened punctuation in: %s' % name)
|
||||
newhtml = strip_encoding_declarations(newhtml)
|
||||
f.seek(0)
|
||||
f.truncate()
|
||||
@@ -171,7 +171,7 @@ def smarten_punctuation(container, report):
|
||||
container.dirty(name)
|
||||
smartened = True
|
||||
if not smartened:
|
||||
report(_('No punctuation that could be smartened found'))
|
||||
report('No punctuation that could be smartened found')
|
||||
return smartened
|
||||
|
||||
|
||||
|
||||
@@ -194,8 +194,9 @@ def split(container, name, loc_or_xpath, before=True, totals=None):
|
||||
try:
|
||||
split_point = node_from_loc(root, loc_or_xpath, totals=totals)
|
||||
except MalformedMarkup:
|
||||
raise MalformedMarkup(_('The file %s has malformed markup. Try running the Fix HTML tool'
|
||||
' before splitting') % name)
|
||||
raise MalformedMarkup('The file %s has malformed markup. Try '
|
||||
'running the Fix HTML tool before '
|
||||
'splitting' % name)
|
||||
container.replace(name, root)
|
||||
if in_table(split_point):
|
||||
raise AbortError('Cannot split inside tables')
|
||||
@@ -269,7 +270,7 @@ def multisplit(container, name, xpath, before=True):
|
||||
root = container.parsed(name)
|
||||
nodes = root.xpath(xpath, namespaces=XPNSMAP)
|
||||
if not nodes:
|
||||
raise AbortError(_('The expression %s did not match any nodes') % xpath)
|
||||
raise AbortError('The expression %s did not match any nodes' % xpath)
|
||||
for split_point in nodes:
|
||||
if in_table(split_point):
|
||||
raise AbortError('Cannot split inside tables')
|
||||
|
||||
@@ -240,17 +240,17 @@ def verify_toc_destinations(container, toc):
|
||||
name = item.dest
|
||||
if not name:
|
||||
item.dest_exists = False
|
||||
item.dest_error = _('No file named %s exists')%name
|
||||
item.dest_error = 'No file named %s exists' % name
|
||||
continue
|
||||
try:
|
||||
root = container.parsed(name)
|
||||
except KeyError:
|
||||
item.dest_exists = False
|
||||
item.dest_error = _('No file named %s exists')%name
|
||||
item.dest_error = 'No file named %s exists' % name
|
||||
continue
|
||||
if not hasattr(root, 'xpath'):
|
||||
item.dest_exists = False
|
||||
item.dest_error = _('No HTML file named %s exists')%name
|
||||
item.dest_error = 'No HTML file named %s exists' % name
|
||||
continue
|
||||
if not item.frag:
|
||||
item.dest_exists = True
|
||||
@@ -259,9 +259,8 @@ def verify_toc_destinations(container, toc):
|
||||
anchor_map[name] = frozenset(anchor_xpath(root))
|
||||
item.dest_exists = item.frag in anchor_map[name]
|
||||
if not item.dest_exists:
|
||||
item.dest_error = _(
|
||||
'The anchor %(a)s does not exist in file %(f)s')%dict(
|
||||
a=item.frag, f=name)
|
||||
item.dest_error = ('The anchor %(a)s does not exist in file '
|
||||
'%(f)s' % dict(a=item.frag, f=name))
|
||||
|
||||
|
||||
def find_existing_ncx_toc(container):
|
||||
@@ -370,7 +369,7 @@ def elem_to_toc_text(elem):
|
||||
text = re.sub(r'\s+', ' ', text.strip())
|
||||
text = text[:1000].strip()
|
||||
if not text:
|
||||
text = _('(Untitled)')
|
||||
text = '(Untitled)'
|
||||
return text
|
||||
|
||||
|
||||
@@ -533,8 +532,9 @@ def from_files(container):
|
||||
text = find_text(body[0])
|
||||
if not text:
|
||||
text = name.rpartition('/')[-1]
|
||||
if i == 0 and text.rpartition('.')[0].lower() in {'titlepage', 'cover'}:
|
||||
text = _('Cover')
|
||||
if i == 0 and text.rpartition('.')[0].lower() in {'titlepage',
|
||||
'cover'}:
|
||||
text = 'Cover'
|
||||
toc.add(text, name)
|
||||
return toc
|
||||
|
||||
@@ -563,8 +563,9 @@ def add_id(container, name, loc, totals=None):
|
||||
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)
|
||||
raise MalformedMarkup('The file %s has malformed markup. Try '
|
||||
'running the Fix HTML tool before '
|
||||
'editing.' % name)
|
||||
container.replace(name, root)
|
||||
|
||||
if not node.get('id'):
|
||||
@@ -641,7 +642,7 @@ def commit_ncx_toc(container, toc, lang=None, uid=None):
|
||||
if m:
|
||||
uid = xml2text(m[0])
|
||||
|
||||
title = _('Table of Contents')
|
||||
title = 'Table of Contents'
|
||||
m = container.opf_xpath('//dc:title')
|
||||
if m:
|
||||
x = xml2text(m[0]).strip()
|
||||
|
||||
@@ -146,14 +146,14 @@ class OEBReader(object):
|
||||
m.add('identifier', str(uuid.uuid4()), id='uuid_id', scheme='uuid')
|
||||
self.oeb.uid = self.oeb.metadata.identifier[-1]
|
||||
if not m.title:
|
||||
m.add('title', self.oeb.translate(__('Unknown')))
|
||||
m.add('title', self.oeb.translate('Unknown'))
|
||||
has_aut = False
|
||||
for x in m.creator:
|
||||
if getattr(x, 'role', '').lower() in ('', 'aut'):
|
||||
has_aut = True
|
||||
break
|
||||
if not has_aut:
|
||||
m.add('creator', self.oeb.translate(__('Unknown')), role='aut')
|
||||
m.add('creator', self.oeb.translate('Unknown'), role='aut')
|
||||
|
||||
def _manifest_prune_invalid(self):
|
||||
'''
|
||||
|
||||
@@ -10,7 +10,7 @@ __all__ = ['HTMLTOCAdder']
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
|
||||
|
||||
DEFAULT_TITLE = __('Table of Contents')
|
||||
DEFAULT_TITLE = 'Table of Contents'
|
||||
|
||||
STYLE_CSS = {
|
||||
'nested': """
|
||||
@@ -52,9 +52,9 @@ class HTMLTOCAdder(object):
|
||||
|
||||
@classmethod
|
||||
def config(cls, cfg):
|
||||
group = cfg.add_group('htmltoc', _('HTML TOC generation options.'))
|
||||
group = cfg.add_group('htmltoc', 'HTML TOC generation options.')
|
||||
group('toc_title', ['--toc-title'], default=None,
|
||||
help=_('Title for any generated in-line table of contents.'))
|
||||
help='Title for any generated in-line table of contents.')
|
||||
return cfg
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -110,12 +110,12 @@ class Jacket(Base):
|
||||
try:
|
||||
title = str(self.oeb.metadata.title[0])
|
||||
except:
|
||||
title = _('Unknown')
|
||||
title = 'Unknown'
|
||||
|
||||
try:
|
||||
authors = list(map(str, self.oeb.metadata.creator))
|
||||
except:
|
||||
authors = [_('Unknown')]
|
||||
authors = ['Unknown']
|
||||
|
||||
root = render_jacket(mi, self.opts.output_profile,
|
||||
alt_title=title, alt_tags=tags, alt_authors=authors,
|
||||
@@ -174,10 +174,11 @@ class Series(str):
|
||||
|
||||
def __new__(self, series, series_index):
|
||||
if series and series_index is not None:
|
||||
roman = _('{1} of <em>{0}</em>').format(
|
||||
roman = '{1} of <em>{0}</em>'.format(
|
||||
escape(series), escape(fmt_sidx(series_index, use_roman=True)))
|
||||
combined = _('{1} of <em>{0}</em>').format(
|
||||
escape(series), escape(fmt_sidx(series_index, use_roman=False)))
|
||||
combined = '{1} of <em>{0}</em>'.format(
|
||||
escape(series), escape(fmt_sidx(series_index,
|
||||
use_roman=False)))
|
||||
else:
|
||||
combined = roman = escape(series or u'')
|
||||
s = str.__new__(self, combined)
|
||||
@@ -227,7 +228,7 @@ def postprocess_jacket(root, output_profile, has_data):
|
||||
|
||||
|
||||
def render_jacket(mi, output_profile,
|
||||
alt_title=_('Unknown'), alt_tags=[], alt_comments='',
|
||||
alt_title='Unknown', alt_tags=[], alt_comments='',
|
||||
alt_publisher='', rescale_fonts=False, alt_authors=None):
|
||||
with open(pkg_resources.resource_filename('ebook_converter',
|
||||
'data/jacket/stylesheet.css'),
|
||||
@@ -244,7 +245,7 @@ def render_jacket(mi, output_profile,
|
||||
try:
|
||||
title_str = alt_title if mi.is_null('title') else mi.title
|
||||
except:
|
||||
title_str = _('Unknown')
|
||||
title_str = 'Unknown'
|
||||
title_str = escape(title_str)
|
||||
title = '<span class="title">%s</span>' % title_str
|
||||
|
||||
@@ -275,7 +276,7 @@ def render_jacket(mi, output_profile,
|
||||
|
||||
orig = mi.authors
|
||||
if mi.is_null('authors'):
|
||||
mi.authors = list(alt_authors or (_('Unknown'),))
|
||||
mi.authors = list(alt_authors or ('Unknown',))
|
||||
try:
|
||||
author = mi.format_authors()
|
||||
except:
|
||||
@@ -285,20 +286,25 @@ def render_jacket(mi, output_profile,
|
||||
has_data = {}
|
||||
|
||||
def generate_html(comments):
|
||||
args = dict(xmlns=XHTML_NS,
|
||||
title_str=title_str,
|
||||
css=css,
|
||||
title=title,
|
||||
author=author,
|
||||
publisher=publisher,
|
||||
pubdate_label=_('Published'), pubdate=pubdate,
|
||||
series_label=_('Series'), series=series,
|
||||
rating_label=_('Rating'), rating=rating,
|
||||
tags_label=_('Tags'), tags=tags,
|
||||
comments=comments,
|
||||
footer='',
|
||||
searchable_tags=' '.join(escape(t)+'ttt' for t in tags.tags_list),
|
||||
)
|
||||
args = {'author': author,
|
||||
'comments': comments,
|
||||
'css': css,
|
||||
'footer': '',
|
||||
'pubdate': pubdate,
|
||||
'pubdate_label': 'Published',
|
||||
'publisher': publisher,
|
||||
'rating': rating,
|
||||
'rating_label': 'Rating',
|
||||
'searchable_tags': ' '.join(escape(t) + 'ttt'
|
||||
for t in tags.tags_list),
|
||||
'series': series,
|
||||
'series_label': 'Series',
|
||||
'tags': tags,
|
||||
'tags_label': 'Tags',
|
||||
'title': title,
|
||||
'title_str': title_str,
|
||||
'xmlns': XHTML_NS}
|
||||
|
||||
for key in mi.custom_field_keys():
|
||||
m = mi.get_user_metadata(key, False) or {}
|
||||
try:
|
||||
|
||||
@@ -35,10 +35,9 @@ class SplitError(ValueError):
|
||||
|
||||
def __init__(self, path, root):
|
||||
size = len(tostring(root))/1024.
|
||||
ValueError.__init__(self,
|
||||
_('Could not find reasonable point at which to split: '
|
||||
'%(path)s Sub-tree size: %(size)d KB')%dict(
|
||||
path=path, size=size))
|
||||
ValueError.__init__(self, 'Could not find reasonable point at which '
|
||||
'to split: %(path)s Sub-tree size: %(size)d KB' %
|
||||
{'path': path, 'size': size})
|
||||
|
||||
|
||||
class Split(object):
|
||||
|
||||
@@ -100,7 +100,7 @@ class DetectStructure(object):
|
||||
|
||||
for node in self.oeb.toc.iter():
|
||||
if not node.title or not node.title.strip():
|
||||
node.title = _('Unnamed')
|
||||
node.title = 'Unnamed'
|
||||
|
||||
if self.opts.start_reading_at:
|
||||
self.detect_start_reading()
|
||||
@@ -279,7 +279,7 @@ class DetectStructure(object):
|
||||
node = self.oeb.toc.add(text, _href,
|
||||
play_order=self.oeb.toc.next_play_order())
|
||||
added[elem] = node
|
||||
# node.add(_('Top'), _href)
|
||||
# node.add('Top', _href)
|
||||
|
||||
if self.opts.level2_toc is not None and added:
|
||||
level2_toc, level2_title = self.get_toc_parts_for_xpath(self.opts.level2_toc)
|
||||
|
||||
@@ -29,13 +29,13 @@ class OEBWriter(object):
|
||||
"""Add any book-writing options to the :class:`Config` object
|
||||
:param:`cfg`.
|
||||
"""
|
||||
oeb = cfg.add_group('oeb', _('OPF/NCX/etc. generation options.'))
|
||||
oeb = cfg.add_group('oeb', 'OPF/NCX/etc. generation options.')
|
||||
versions = ['1.2', '2.0']
|
||||
oeb('opf_version', ['--opf-version'], default='2.0', choices=versions,
|
||||
help=_('OPF version to generate. Default is %default.'))
|
||||
help='OPF version to generate. Default is %default.')
|
||||
oeb('adobe_page_map', ['--adobe-page-map'], default=False,
|
||||
help=_('Generate an Adobe "page-map" file if pagination '
|
||||
'information is available.'))
|
||||
help='Generate an Adobe "page-map" file if pagination '
|
||||
'information is available.')
|
||||
return cfg
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -124,7 +124,7 @@ class Reader132(FormatReader):
|
||||
toc = hizer.get_toc()
|
||||
|
||||
if self.header_record.footnote_count > 0:
|
||||
html += '<br /><h1>%s</h1>' % _('Footnotes')
|
||||
html += '<br /><h1>%s</h1>' % 'Footnotes'
|
||||
footnoteids = re.findall(
|
||||
'\\w+(?=\x00)', self.section_data(self.header_record.footnote_offset).decode('cp1252' if self.encoding is None else self.encoding))
|
||||
for fid, i in enumerate(range(self.header_record.footnote_offset + 1, self.header_record.footnote_offset + self.header_record.footnote_count)):
|
||||
@@ -136,7 +136,7 @@ class Reader132(FormatReader):
|
||||
html += footnote_to_html(fid, self.decompress_text(i))
|
||||
|
||||
if self.header_record.sidebar_count > 0:
|
||||
html += '<br /><h1>%s</h1>' % _('Sidebar')
|
||||
html += '<br /><h1>%s</h1>' % 'Sidebar'
|
||||
sidebarids = re.findall(
|
||||
'\\w+(?=\x00)', self.section_data(self.header_record.sidebar_offset).decode('cp1252' if self.encoding is None else self.encoding))
|
||||
for sid, i in enumerate(range(self.header_record.sidebar_offset + 1, self.header_record.sidebar_offset + self.header_record.sidebar_count)):
|
||||
|
||||
@@ -70,8 +70,8 @@ def pdftohtml(output_dir, pdf_path, no_images, as_xml=False):
|
||||
stdin=subprocess.PIPE)
|
||||
except OSError as err:
|
||||
if err.errno == errno.ENOENT:
|
||||
raise ConversionError(
|
||||
_('Could not find pdftohtml, check it is in your PATH'))
|
||||
raise ConversionError('Could not find pdftohtml, check it is '
|
||||
'in your PATH')
|
||||
else:
|
||||
raise
|
||||
ret = eintr_retry_call(p.wait)
|
||||
|
||||
@@ -142,7 +142,7 @@ def convert_markdown_with_metadata(txt, title='', extensions=DEFAULT_MD_EXTENSIO
|
||||
extensions.append('meta')
|
||||
md = create_markdown_object(extensions)
|
||||
html = md.convert(txt)
|
||||
mi = Metadata(title or _('Unknown'))
|
||||
mi = Metadata(title or 'Unknown')
|
||||
m = md.Meta
|
||||
for k, v in {'date':'pubdate', 'summary':'comments'}.items():
|
||||
if v not in m and k in m:
|
||||
|
||||
@@ -96,7 +96,7 @@ class TXTMLizer(object):
|
||||
toc = ['']
|
||||
if getattr(self.opts, 'inline_toc', None):
|
||||
self.log.debug('Generating table of contents...')
|
||||
toc.append('%s\n\n' % _('Table of Contents:'))
|
||||
toc.append('%s\n\n' % 'Table of Contents:')
|
||||
for item in self.toc_titles:
|
||||
toc.append('* %s\n\n' % item)
|
||||
return ''.join(toc)
|
||||
|
||||
Reference in New Issue
Block a user