mirror of
https://github.com/gryf/ebook-converter.git
synced 2026-01-02 08:32:26 +01:00
Cleanup get_path usage in favor of pkg_resources.
This commit is contained in:
149
ebook_converter/data/jacket/stylesheet.css
Normal file
149
ebook_converter/data/jacket/stylesheet.css
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
** Book Jacket generation
|
||||
**
|
||||
** The template for Book Jackets is template.xhtml
|
||||
** This CSS is inserted into the generated HTML at conversion time
|
||||
**
|
||||
** Users can control parts of the presentation of a generated book jacket by
|
||||
** editing this file and template.xhtml
|
||||
**
|
||||
** The general form of a generated Book Jacket:
|
||||
**
|
||||
** Title
|
||||
** Series: series [series_index]
|
||||
** Published: year_of_publication
|
||||
** Rating: #_of_stars
|
||||
** Tags: tag1, tag2, tag3 ...
|
||||
**
|
||||
** Comments
|
||||
**
|
||||
** If a book does not have Series information, a date of publication, a rating or tags
|
||||
** the corresponding row is automatically removed from the generated book jacket.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Banner
|
||||
** Only affects EPUB, kindle ignores this type of formatting
|
||||
*/
|
||||
.cbj_banner {
|
||||
background: #eee;
|
||||
color: black;
|
||||
border: thin solid black;
|
||||
margin: 1em;
|
||||
padding: 1em;
|
||||
border-radius:8px;
|
||||
}
|
||||
|
||||
/*
|
||||
** Title
|
||||
*/
|
||||
table.cbj_header td.cbj_title {
|
||||
font-size: 1.5em;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*
|
||||
** Series
|
||||
*/
|
||||
table.cbj_header td.cbj_series {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*
|
||||
** Author
|
||||
*/
|
||||
table.cbj_header td.cbj_author {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*
|
||||
** Publisher/published
|
||||
*/
|
||||
table.cbj_header td.cbj_pubdata {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*
|
||||
** Table containing Rating and Tags
|
||||
*/
|
||||
table.cbj_header {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/*
|
||||
** General formatting for banner labels
|
||||
*/
|
||||
table.cbj_header td.cbj_label {
|
||||
font-family: sans-serif;
|
||||
text-align: right;
|
||||
width: 33%;
|
||||
}
|
||||
|
||||
/*
|
||||
** General formatting for banner content
|
||||
*/
|
||||
table.cbj_header td.cbj_content {
|
||||
font-family: sans-serif;
|
||||
text-align: left;
|
||||
width:67%;
|
||||
}
|
||||
|
||||
/*
|
||||
** Metadata divider
|
||||
*/
|
||||
hr.metadata_divider {
|
||||
width:90%;
|
||||
margin-left:5%;
|
||||
border-top: solid white 0px;
|
||||
border-right: solid white 0px;
|
||||
border-bottom: solid black 1px;
|
||||
border-left: solid white 0px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** To skip a banner item (Series|Published|Rating|Tags),
|
||||
** edit the appropriate CSS rule below.
|
||||
*/
|
||||
table.cbj_header tr.cbj_series {
|
||||
/* Uncomment the next line to remove 'Series' from banner section */
|
||||
/* display:none; */
|
||||
}
|
||||
|
||||
table.cbj_header tr.cbj_pubdata {
|
||||
/* Uncomment the next line to remove 'Published (year of publication)' from banner section */
|
||||
/* display:none; */
|
||||
}
|
||||
|
||||
table.cbj_header tr.cbj_rating {
|
||||
/* Uncomment the next line to remove 'Rating' from banner section */
|
||||
/* display:none; */
|
||||
}
|
||||
|
||||
table.cbj_header tr.cbj_tags {
|
||||
/* Uncomment the next line to remove 'Tags' from banner section */
|
||||
/* display:none; */
|
||||
}
|
||||
|
||||
hr {
|
||||
/* This rule controls formatting for any hr elements contained in the jacket */
|
||||
border-top: 0px solid white;
|
||||
border-right: 0px solid white;
|
||||
border-bottom: 2px solid black;
|
||||
border-left: 0px solid white;
|
||||
margin-left: 10%;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.cbj_footer {
|
||||
font-family: sans-serif;
|
||||
font-size: 0.8em;
|
||||
margin-top: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cbj_comments {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
58
ebook_converter/data/jacket/template.xhtml
Normal file
58
ebook_converter/data/jacket/template.xhtml
Normal file
@@ -0,0 +1,58 @@
|
||||
<html xmlns="{xmlns}">
|
||||
<head>
|
||||
<title>{title_str}</title>
|
||||
<meta name="calibre-content" content="jacket"/>
|
||||
<style type="text/css">{css}</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="cbj_banner">
|
||||
<table class="cbj_header">
|
||||
<tr>
|
||||
<td class="cbj_title" colspan="2">{title}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- If you do not want the series number to be formatted using roman numerals
|
||||
change {series.roman} to {series}. You can also access the raw series name and number
|
||||
using {series.name}, {series.number} or {series.roman_number} -->
|
||||
<td class="cbj_series" colspan="2">{series.roman}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cbj_author" colspan="2">{author}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="cbj_pubdata" colspan="2">{publisher} ({pubdate})</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="cbj_author" colspan="2"><hr class="metadata_divider" /></td>
|
||||
</tr>
|
||||
|
||||
<tr class="cbj_rating">
|
||||
<td class="cbj_label">{rating_label}:</td>
|
||||
<td class="cbj_content">{rating}</td>
|
||||
</tr>
|
||||
<tr class="cbj_tags">
|
||||
<td class="cbj_label">{tags_label}:</td>
|
||||
<!-- If you want the tags to be alphabetical, change {tags} to
|
||||
{tags.alphabetical} -->
|
||||
<td class="cbj_content">{tags}</td>
|
||||
</tr>
|
||||
<tr data-calibre-jacket-searchable-tags="1" style="color:white; display:none"><td colspan="2">{searchable_tags}</td></tr>
|
||||
</table>
|
||||
<div class="cbj_footer">{footer}</div>
|
||||
</div>
|
||||
<hr class="cbj_kindle_banner_hr" />
|
||||
<!--
|
||||
In addition you can add code to show the values of custom columns here.
|
||||
The value is available as _column_name and the title as
|
||||
_column_name_label. For example, if you have a custom column with
|
||||
label #genre, you can add it to this template with _genre_label and
|
||||
_genre. Note that the # is replaced by an underscore. For example
|
||||
|
||||
<div><b>{_genre_label}:</b> {_genre}</div>
|
||||
-->
|
||||
|
||||
<div class="cbj_comments">{comments}</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
210
ebook_converter/data/lrf.xsl
Normal file
210
ebook_converter/data/lrf.xsl
Normal file
@@ -0,0 +1,210 @@
|
||||
<?xml version="1.0"?>
|
||||
<xsl:stylesheet
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:c="calibre"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:opf="http://www.idpf.org/2007/opf"
|
||||
xmlns:calibre="http://calibre.kovidgoyal.net/2009/metadata"
|
||||
extension-element-prefixes="c"
|
||||
xsl:version = "1.1"
|
||||
>
|
||||
<xsl:output method="xml" indent="yes"/>
|
||||
|
||||
<xsl:template match="/">
|
||||
<package version="2.0">
|
||||
<metadata>
|
||||
<xsl:call-template name="make-metadata"/>
|
||||
</metadata>
|
||||
<manifest>
|
||||
<xsl:call-template name="make-manifest"/>
|
||||
</manifest>
|
||||
<spine toc="ncx">
|
||||
<xsl:call-template name="make-spine"/>
|
||||
</spine>
|
||||
</package>
|
||||
<xsl:call-template name="make-ncx"/>
|
||||
<xsl:call-template name="make-css"/>
|
||||
<xsl:for-each select="//Page">
|
||||
<xsl:call-template name="make-page"/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="make-css">
|
||||
<xsl:for-each select="//TextStyle|//BlockStyle">
|
||||
<c:styles/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="make-page">
|
||||
<xsl:variable name="pid" select="@objid"/>
|
||||
<xsl:document href="{$pid}.xhtml" method="xml" indent="yes">
|
||||
<html>
|
||||
<head>
|
||||
<title><xsl:value-of select="//Title"/></title>
|
||||
<link rel="stylesheet" type="text/css" href="styles.css"/>
|
||||
</head>
|
||||
<body class="body">
|
||||
<xsl:apply-templates />
|
||||
</body>
|
||||
</html>
|
||||
</xsl:document>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="RuledLine">
|
||||
<c:ruled-line/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="TextBlock">
|
||||
<c:text-block/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="ImageBlock">
|
||||
<c:image-block/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="Canvas">
|
||||
<c:canvas/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="make-metadata">
|
||||
<xsl:for-each select='//BookInformation/Info/BookInfo'>
|
||||
<xsl:apply-templates select="Title"/>
|
||||
<xsl:apply-templates select="Author"/>
|
||||
<xsl:apply-templates select="Publisher"/>
|
||||
<xsl:apply-templates select="Category|Classification"/>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select='//BookInformation/Info/DocInfo'>
|
||||
<xsl:apply-templates select="Language"/>
|
||||
<xsl:apply-templates select="Producer"/>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="Title">
|
||||
<xsl:element name="dc:title">
|
||||
<xsl:if test="@reading and @reading != ''">
|
||||
<xsl:attribute name="opf:file-as"><xsl:value-of select="@reading"/></xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="Author">
|
||||
<xsl:element name="dc:creator">
|
||||
<xsl:attribute name="opf:role">aut</xsl:attribute>
|
||||
<xsl:if test="@reading and @reading != ''">
|
||||
<xsl:attribute name="opf:file-as"><xsl:value-of select="@reading"/></xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="Publisher">
|
||||
<xsl:element name="dc:publisher">
|
||||
<xsl:if test="@reading and @reading != ''">
|
||||
<xsl:attribute name="opf:file-as"><xsl:value-of select="@reading"/></xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="Producer">
|
||||
<xsl:element name="dc:creator">
|
||||
<xsl:attribute name="opf:role">bkp</xsl:attribute>
|
||||
<xsl:if test="@reading and @reading != ''">
|
||||
<xsl:attribute name="opf:file-as"><xsl:value-of select="@reading"/></xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="Language">
|
||||
<xsl:element name="dc:language">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="Category|Classification">
|
||||
<xsl:if test=".!=''">
|
||||
<xsl:element name="dc:subject">
|
||||
<xsl:value-of select="."/>
|
||||
</xsl:element>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="make-manifest">
|
||||
<xsl:for-each select='//Page'>
|
||||
<xsl:element name="item">
|
||||
<xsl:attribute name="id"><xsl:value-of select="@objid"/></xsl:attribute>
|
||||
<xsl:attribute name="media-type"><xsl:text>application/xhtml+xml</xsl:text></xsl:attribute>
|
||||
<xsl:attribute name="href"><xsl:value-of select="@objid"/><xsl:text>.xhtml</xsl:text></xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="//ImageStream">
|
||||
<xsl:element name="item">
|
||||
<xsl:attribute name="id"><xsl:value-of select="@objid"/></xsl:attribute>
|
||||
<xsl:attribute name="media-type"><c:media-type/></xsl:attribute>
|
||||
<xsl:attribute name="href"><xsl:value-of select="@file"/></xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
<xsl:for-each select="//RegistFont">
|
||||
<xsl:element name="item">
|
||||
<xsl:attribute name="id"><xsl:value-of select="@objid"/></xsl:attribute>
|
||||
<xsl:attribute name="media-type"><c:media-type/></xsl:attribute>
|
||||
<xsl:attribute name="href"><xsl:value-of select="@file"/></xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" />
|
||||
<item id="styles" href="styles.css" media-type="text/css" />
|
||||
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="make-spine">
|
||||
<xsl:for-each select='//Page'>
|
||||
<xsl:element name="itemref">
|
||||
<xsl:attribute name="idref"><xsl:value-of select="@objid"/></xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="*">
|
||||
<xsl:message>
|
||||
<xsl:text>no match for element: "</xsl:text>
|
||||
<xsl:value-of select="name(.)"/>
|
||||
<xsl:text>" 
</xsl:text>
|
||||
</xsl:message>
|
||||
<xsl:apply-templates/>
|
||||
</xsl:template>
|
||||
|
||||
|
||||
<xsl:template name="make-ncx">
|
||||
<xsl:document href="toc.ncx" method="xml" indent="yes">
|
||||
<ncx version="2005-1"
|
||||
xmlns="http://www.daisy.org/z3986/2005/ncx/"
|
||||
xmlns:calibre="http://calibre.kovidgoyal.net/2009/metadata"
|
||||
>
|
||||
<head>
|
||||
<meta name="dtb:uid" content="uid"/>
|
||||
<meta name="dtb:depth" content="1"/>
|
||||
<meta name="dtb:generator" content="calibre"/>
|
||||
<meta name="dtb:totalPageCount" content="0"/>
|
||||
<meta name="dtb:maxPageNumber" content="0"/>
|
||||
</head>
|
||||
<docTitle><text>Table of Contents</text></docTitle>
|
||||
<navMap>
|
||||
<xsl:for-each select="//TOC/TocLabel">
|
||||
<xsl:element name="navPoint">
|
||||
<xsl:attribute name="id"><xsl:value-of select="count(preceding-sibling::*)"/></xsl:attribute>
|
||||
<xsl:attribute name="playOrder"><xsl:value-of select="count(preceding-sibling::*)+1"/></xsl:attribute>
|
||||
<navLabel><text><xsl:value-of select="."/></text></navLabel>
|
||||
<xsl:element name="content">
|
||||
<xsl:attribute name="src">
|
||||
<xsl:value-of select="@refpage"/>.xhtml#<xsl:value-of select="@refobj"/>
|
||||
</xsl:attribute>
|
||||
</xsl:element>
|
||||
</xsl:element>
|
||||
</xsl:for-each>
|
||||
</navMap>
|
||||
</ncx>
|
||||
</xsl:document>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
9
ebook_converter/data/new_nav.html
Normal file
9
ebook_converter/data/new_nav.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
|
||||
<head>
|
||||
<title>Navigation</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -6,6 +6,7 @@ __copyright__ = '2008, Anatoly Shipitsin <norguhtar at gmail.com>'
|
||||
Convert .fb2 files to .lrf
|
||||
"""
|
||||
import os, re
|
||||
import pkg_resources
|
||||
|
||||
from ebook_converter.customize.conversion import InputFormatPlugin, OptionRecommendation
|
||||
from ebook_converter import guess_type
|
||||
@@ -86,8 +87,9 @@ class FB2Input(InputFormatPlugin):
|
||||
css = re.sub(r'name\s*=\s*', 'class=', css)
|
||||
self.extract_embedded_content(doc)
|
||||
log.debug('Converting XML to HTML...')
|
||||
with open(P('templates/fb2.xsl'), 'rb') as f:
|
||||
ss = f.read().decode('utf-8')
|
||||
with open(pkg_resources.resource_filename('ebook_converter',
|
||||
'data/fb2.xsl')) as f:
|
||||
ss = f.read().decode()
|
||||
ss = ss.replace("__FB_NS__", fb_ns)
|
||||
if options.no_inline_fb2_toc:
|
||||
log('Disabling generation of inline FB2 TOC')
|
||||
|
||||
@@ -6,6 +6,7 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
import os, re, shutil
|
||||
from os.path import dirname, abspath, relpath as _relpath, exists, basename
|
||||
import pkg_resources
|
||||
|
||||
from ebook_converter.customize.conversion import OutputFormatPlugin, OptionRecommendation
|
||||
from ebook_converter import CurrentDir
|
||||
@@ -95,19 +96,31 @@ class HTMLOutput(OutputFormatPlugin):
|
||||
with open(opts.template_html_index, 'rb') as f:
|
||||
template_html_index_data = f.read()
|
||||
else:
|
||||
template_html_index_data = P('templates/html_export_default_index.tmpl', data=True)
|
||||
with open(pkg_resources.
|
||||
resource_filename('ebook_converter',
|
||||
'data/html_export_default_index.tmpl')
|
||||
) as fobj:
|
||||
template_html_index_data = fobj.read().decode()
|
||||
|
||||
if opts.template_html is not None:
|
||||
with open(opts.template_html, 'rb') as f:
|
||||
template_html_data = f.read()
|
||||
else:
|
||||
template_html_data = P('templates/html_export_default.tmpl', data=True)
|
||||
with open(pkg_resources.
|
||||
resource_filename('ebook_converter',
|
||||
'data/html_export_default.tmpl')
|
||||
) as fobj:
|
||||
template_html_data = fobj.read().decode()
|
||||
|
||||
if opts.template_css is not None:
|
||||
with open(opts.template_css, 'rb') as f:
|
||||
template_css_data = f.read()
|
||||
else:
|
||||
template_css_data = P('templates/html_export_default.css', data=True)
|
||||
with open(pkg_resources.
|
||||
resource_filename('ebook_converter',
|
||||
'data/html_export_default.css')
|
||||
) as fobj:
|
||||
template_css_data = fobj.read().decode()
|
||||
|
||||
template_html_index_data = template_html_index_data.decode('utf-8')
|
||||
template_html_data = template_html_data.decode('utf-8')
|
||||
|
||||
@@ -7,6 +7,8 @@ __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os, sys
|
||||
import pkg_resources
|
||||
|
||||
from ebook_converter.customize.conversion import InputFormatPlugin
|
||||
|
||||
|
||||
@@ -54,7 +56,12 @@ class LRFInput(InputFormatPlugin):
|
||||
plot_map[ro] = imgstr[0].get('file')
|
||||
|
||||
self.log('Converting XML to HTML...')
|
||||
styledoc = safe_xml_fromstring(P('templates/lrf.xsl', data=True))
|
||||
|
||||
with open(pkg_resources.
|
||||
resource_filename('ebook_converter',
|
||||
'data/lrf.xsl')) as fobj:
|
||||
# TODO(gryf): change this nonsense to etree.parse() instead.
|
||||
styledoc = safe_xml_fromstring(fobj.read())
|
||||
media_type = MediaType()
|
||||
styles = Styles()
|
||||
text_block = TextBlock(styles, char_button_map, plot_map, log)
|
||||
|
||||
@@ -5,29 +5,40 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
from PIL import ImageFont
|
||||
|
||||
from ebook_converter.utils.fonts.scanner import font_scanner
|
||||
|
||||
'''
|
||||
Default fonts used in the PRS500
|
||||
'''
|
||||
|
||||
|
||||
LIBERATION_FONT_MAP = {
|
||||
'Swis721 BT Roman' : 'LiberationSans-Regular',
|
||||
'Dutch801 Rm BT Roman' : 'LiberationSerif-Regular',
|
||||
'Courier10 BT Roman' : 'LiberationMono-Regular',
|
||||
}
|
||||
|
||||
LIBERATION_FONT_MAP = {'Swis721 BT Roman': 'Liberation Sans Regular',
|
||||
'Dutch801 Rm BT Roman': 'Liberation Serif Regular',
|
||||
'Courier10 BT Roman': 'Liberation Mono Regular'}
|
||||
_LIB_CACHE = {}
|
||||
FONT_FILE_MAP = {}
|
||||
|
||||
|
||||
def get_font(name, size, encoding='unic'):
|
||||
'''
|
||||
"""
|
||||
Get an ImageFont object by name.
|
||||
@param size: Font height in pixels. To convert from pts:
|
||||
sz in pixels = (dpi/72) * size in pts
|
||||
@param encoding: Font encoding to use. E.g. 'unic', 'symbol', 'ADOB', 'ADBE', 'aprm'
|
||||
@param manager: A dict that will store the PersistentTemporary
|
||||
'''
|
||||
@param encoding: Font encoding to use. E.g. 'unic', 'symbol', 'ADOB',
|
||||
'ADBE', 'aprm'
|
||||
"""
|
||||
if name in LIBERATION_FONT_MAP:
|
||||
return ImageFont.truetype(P('fonts/liberation/%s.ttf' % LIBERATION_FONT_MAP[name]), size, encoding=encoding)
|
||||
if not _LIB_CACHE:
|
||||
for key in font_scanner.cache['fonts']:
|
||||
record = font_scanner.cache['fonts'][key]
|
||||
_LIB_CACHE[record['family_name'] + ' ' +
|
||||
record['subfamily_name']] = record['path']
|
||||
|
||||
fpath = _LIB_CACHE.get(LIBERATION_FONT_MAP[name])
|
||||
if not fpath:
|
||||
raise ValueError('There is no liberation font existing in the '
|
||||
'system. Please install them before converter '
|
||||
'use.')
|
||||
return ImageFont.truetype(fpath, size, encoding=encoding)
|
||||
elif name in FONT_FILE_MAP:
|
||||
return ImageFont.truetype(FONT_FILE_MAP[name], size, encoding=encoding)
|
||||
|
||||
@@ -10,6 +10,7 @@ import re
|
||||
from collections import Counter, OrderedDict
|
||||
from functools import partial
|
||||
from operator import itemgetter
|
||||
import pkg_resources
|
||||
|
||||
from lxml import etree
|
||||
from lxml.builder import ElementMaker
|
||||
@@ -690,7 +691,10 @@ def commit_nav_toc(container, toc, lang=None, landmarks=None, previous_nav=None)
|
||||
if previous_nav is not None:
|
||||
root = previous_nav[1]
|
||||
else:
|
||||
root = container.parse_xhtml(P('templates/new_nav.html', data=True).decode('utf-8'))
|
||||
with open(pkg_resources.
|
||||
resource_filename('ebook_converter',
|
||||
'data/new_nav.html')) as fobj:
|
||||
root = container.parse_xhtml(fobj.read())
|
||||
container.replace(tocname, root)
|
||||
else:
|
||||
root = container.parsed(tocname)
|
||||
|
||||
@@ -9,13 +9,13 @@ __docformat__ = 'restructuredtext en'
|
||||
import sys, os, re
|
||||
from xml.sax.saxutils import escape
|
||||
from string import Formatter
|
||||
import pkg_resources
|
||||
|
||||
from ebook_converter import guess_type, strftime
|
||||
from ebook_converter.constants import iswindows
|
||||
from ebook_converter.ebooks.oeb.base import XPath, XHTML_NS, XHTML, xml2text, urldefrag, urlnormalize
|
||||
from ebook_converter.library.comments import comments_to_html, markdown
|
||||
from ebook_converter.utils.date import is_date_undefined, as_local_time
|
||||
from ebook_converter.utils.icu import sort_key
|
||||
from ebook_converter.ebooks.chardet import strip_encoding_declarations
|
||||
from ebook_converter.ebooks.metadata import fmt_sidx, rating_to_stars
|
||||
from ebook_converter.polyglot.builtins import unicode_type, map
|
||||
@@ -196,7 +196,7 @@ class Tags(unicode_type):
|
||||
def __new__(self, tags, output_profile):
|
||||
tags = [escape(x) for x in tags or ()]
|
||||
t = unicode_type.__new__(self, ', '.join(tags))
|
||||
t.alphabetical = ', '.join(sorted(tags, key=sort_key))
|
||||
t.alphabetical = ', '.join(sorted(tags))
|
||||
t.tags_list = tags
|
||||
return t
|
||||
|
||||
@@ -232,8 +232,14 @@ def postprocess_jacket(root, output_profile, has_data):
|
||||
def render_jacket(mi, output_profile,
|
||||
alt_title=_('Unknown'), alt_tags=[], alt_comments='',
|
||||
alt_publisher='', rescale_fonts=False, alt_authors=None):
|
||||
css = P('jacket/stylesheet.css', data=True).decode('utf-8')
|
||||
template = P('jacket/template.xhtml', data=True).decode('utf-8')
|
||||
with open(pkg_resources.resource_filename('ebook_converter',
|
||||
'data/jacket/stylesheet.css'),
|
||||
'rb') as fobj:
|
||||
css = fobj.read().decode()
|
||||
with open(pkg_resources.resource_filename('ebook_converter',
|
||||
'data/jacket/template.xhtml'),
|
||||
'rb') as fobj:
|
||||
template = fobj.read().decode()
|
||||
|
||||
template = re.sub(r'<!--.*?-->', '', template, flags=re.DOTALL)
|
||||
css = re.sub(r'/\*.*?\*/', '', css, flags=re.DOTALL)
|
||||
|
||||
@@ -6,6 +6,8 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
from collections import namedtuple
|
||||
import json
|
||||
import pkg_resources
|
||||
|
||||
from ebook_converter.utils.localization import canonicalize_lang
|
||||
|
||||
@@ -17,9 +19,31 @@ ccodes, ccodemap, country_names = None, None, None
|
||||
def get_codes():
|
||||
global ccodes, ccodemap, country_names
|
||||
if ccodes is None:
|
||||
from ebook_converter.utils.serialize import msgpack_loads
|
||||
data = msgpack_loads(P('localization/iso3166.calibre_msgpack', allow_user_override=False, data=True))
|
||||
ccodes, ccodemap, country_names = data['codes'], data['three_map'], data['names']
|
||||
src = pkg_resources.resource_filename('ebook_converter',
|
||||
'data/iso_3166-1.json')
|
||||
with open(src, 'rb') as f:
|
||||
db = json.load(f)
|
||||
codes = set()
|
||||
three_map = {}
|
||||
name_map = {}
|
||||
unicode_type = type(u'')
|
||||
for x in db['3166-1']:
|
||||
two = x.get('alpha_2')
|
||||
if two:
|
||||
two = unicode_type(two)
|
||||
codes.add(two)
|
||||
name_map[two] = x.get('name')
|
||||
if name_map[two]:
|
||||
name_map[two] = unicode_type(name_map[two])
|
||||
three = x.get('alpha_3')
|
||||
if three:
|
||||
three_map[unicode_type(three)] = two
|
||||
data = {'names': name_map,
|
||||
'codes': frozenset(codes),
|
||||
'three_map': three_map}
|
||||
|
||||
ccodes, ccodemap, country_names = (data['codes'], data['three_map'],
|
||||
data['names'])
|
||||
return ccodes, ccodemap
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import os, re, traceback, numbers
|
||||
from functools import partial
|
||||
from collections import defaultdict
|
||||
from copy import deepcopy
|
||||
import pkg_resources
|
||||
|
||||
from ebook_converter.utils.lock import ExclusiveFile
|
||||
from ebook_converter.constants import config_dir, CONFIG_DIR_MODE, ispy3, preferred_encoding, filesystem_encoding, iswindows
|
||||
@@ -634,7 +635,9 @@ def read_custom_tweaks():
|
||||
|
||||
|
||||
def default_tweaks_raw():
|
||||
return P('default_tweaks.py', data=True, allow_user_override=False)
|
||||
with open(pkg_resources.resource_filename('ebook_converter',
|
||||
'data/default_tweaks.py')) as f:
|
||||
return f.read().encode()
|
||||
|
||||
|
||||
def read_tweaks():
|
||||
|
||||
@@ -195,8 +195,7 @@ class FontScanner(Thread):
|
||||
|
||||
def __init__(self, folders=[], allowed_extensions={'ttf', 'otf'}):
|
||||
Thread.__init__(self)
|
||||
self.folders = folders + font_dirs() + [os.path.join(config_dir, 'fonts'),
|
||||
P('fonts/liberation')]
|
||||
self.folders = folders + font_dirs()
|
||||
self.folders = [os.path.normcase(os.path.abspath(font)) for font in
|
||||
self.folders]
|
||||
self.font_families = ()
|
||||
|
||||
@@ -451,6 +451,7 @@ def get_font_for_text(text, candidate_font_data=None):
|
||||
|
||||
def test_glyph_ids():
|
||||
from ebook_converter.utils.fonts.free_type import FreeType
|
||||
# TODO(gryf): move this test to test files
|
||||
data = P('fonts/liberation/LiberationSerif-Regular.ttf', data=True)
|
||||
ft = FreeType()
|
||||
font = ft.load_font(data)
|
||||
@@ -462,6 +463,7 @@ def test_glyph_ids():
|
||||
|
||||
|
||||
def test_supports_text():
|
||||
# TODO(gryf): move this test to test files
|
||||
data = P('fonts/calibreSymbols.otf', data=True)
|
||||
if not supports_text(data, '.★½'):
|
||||
raise RuntimeError('Incorrectly returning that text is not supported')
|
||||
@@ -470,6 +472,7 @@ def test_supports_text():
|
||||
|
||||
|
||||
def test_find_font():
|
||||
# TODO(gryf): move this test to test files
|
||||
from ebook_converter.utils.fonts.scanner import font_scanner
|
||||
abcd = '诶比西迪'
|
||||
family = font_scanner.find_font_for_text(abcd)[0]
|
||||
|
||||
@@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os, locale, re, io, sys
|
||||
import re, io, sys
|
||||
import json
|
||||
from gettext import GNUTranslations, NullTranslations
|
||||
import pkg_resources
|
||||
@@ -12,64 +12,6 @@ from ebook_converter.polyglot.builtins import is_py3, iteritems, unicode_type
|
||||
_available_translations = None
|
||||
|
||||
|
||||
def available_translations():
|
||||
global _available_translations
|
||||
if _available_translations is None:
|
||||
stats = P('localization/stats.calibre_msgpack', allow_user_override=False)
|
||||
if os.path.exists(stats):
|
||||
from ebook_converter.utils.serialize import msgpack_loads
|
||||
with open(stats, 'rb') as f:
|
||||
stats = msgpack_loads(f.read())
|
||||
else:
|
||||
stats = {}
|
||||
_available_translations = [x for x in stats if stats[x] > 0.1]
|
||||
return _available_translations
|
||||
|
||||
|
||||
def get_system_locale():
|
||||
from ebook_converter.constants import iswindows, isosx, plugins
|
||||
lang = None
|
||||
if iswindows:
|
||||
try:
|
||||
from ebook_converter.constants import get_windows_user_locale_name
|
||||
lang = get_windows_user_locale_name()
|
||||
lang = lang.strip()
|
||||
if not lang:
|
||||
lang = None
|
||||
except:
|
||||
pass # Windows XP does not have the GetUserDefaultLocaleName fn
|
||||
elif isosx:
|
||||
try:
|
||||
lang = plugins['usbobserver'][0].user_locale() or None
|
||||
except:
|
||||
# Fallback to environment vars if something bad happened
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
if lang is None:
|
||||
try:
|
||||
envvars = ['LANGUAGE', 'LC_ALL', 'LC_CTYPE', 'LC_MESSAGES', 'LANG']
|
||||
lang = locale.getdefaultlocale(envvars)[0]
|
||||
|
||||
# lang is None in two cases: either the environment variable is not
|
||||
# set or it's "C". Stop looking for a language in the latter case.
|
||||
if lang is None:
|
||||
for var in envvars:
|
||||
if os.environ.get(var) == 'C':
|
||||
lang = 'en_US'
|
||||
break
|
||||
except:
|
||||
pass # This happens on Ubuntu apparently
|
||||
if lang is None and 'LANG' in os.environ: # Needed for OS X
|
||||
try:
|
||||
lang = os.environ['LANG']
|
||||
except:
|
||||
pass
|
||||
if lang:
|
||||
lang = lang.replace('-', '_')
|
||||
lang = '_'.join(lang.split('_')[:2])
|
||||
return lang
|
||||
|
||||
|
||||
def sanitize_lang(lang):
|
||||
if lang:
|
||||
match = re.match('[a-z]{2,3}(_[A-Z]{2}){0,1}', lang)
|
||||
@@ -83,101 +25,16 @@ def sanitize_lang(lang):
|
||||
|
||||
|
||||
def get_lang():
|
||||
'Try to figure out what language to display the interface in'
|
||||
from ebook_converter.utils.config_base import prefs
|
||||
lang = prefs['language']
|
||||
lang = os.environ.get('CALIBRE_OVERRIDE_LANG', lang)
|
||||
if lang:
|
||||
return lang
|
||||
try:
|
||||
lang = get_system_locale()
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
lang = None
|
||||
return sanitize_lang(lang)
|
||||
return 'en_US'
|
||||
|
||||
|
||||
def is_rtl():
|
||||
return get_lang()[:2].lower() in {'he', 'ar'}
|
||||
|
||||
|
||||
def get_lc_messages_path(lang):
|
||||
hlang = None
|
||||
if zf_exists():
|
||||
if lang in available_translations():
|
||||
hlang = lang
|
||||
else:
|
||||
xlang = lang.split('_')[0].lower()
|
||||
if xlang in available_translations():
|
||||
hlang = xlang
|
||||
return hlang
|
||||
|
||||
|
||||
def zf_exists():
|
||||
return os.path.exists(P('localization/locales.zip',
|
||||
allow_user_override=False))
|
||||
|
||||
|
||||
_lang_trans = None
|
||||
|
||||
|
||||
def get_all_translators():
|
||||
from zipfile import ZipFile
|
||||
with ZipFile(P('localization/locales.zip', allow_user_override=False), 'r') as zf:
|
||||
for lang in available_translations():
|
||||
mpath = get_lc_messages_path(lang)
|
||||
if mpath is not None:
|
||||
buf = io.BytesIO(zf.read(mpath + '/messages.mo'))
|
||||
yield lang, GNUTranslations(buf)
|
||||
|
||||
|
||||
def get_single_translator(mpath, which='messages'):
|
||||
from zipfile import ZipFile
|
||||
with ZipFile(P('localization/locales.zip', allow_user_override=False), 'r') as zf:
|
||||
path = '{}/{}.mo'.format(mpath, which)
|
||||
data = zf.read(path)
|
||||
buf = io.BytesIO(data)
|
||||
try:
|
||||
return GNUTranslations(buf)
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
import hashlib
|
||||
sig = hashlib.sha1(data).hexdigest()
|
||||
raise ValueError('Failed to load translations for: {} (size: {} and signature: {}) with error: {}'.format(
|
||||
path, len(data), sig, e))
|
||||
|
||||
|
||||
def get_iso639_translator(lang):
|
||||
lang = sanitize_lang(lang)
|
||||
mpath = get_lc_messages_path(lang) if lang else None
|
||||
return get_single_translator(mpath, 'iso639') if mpath else None
|
||||
|
||||
|
||||
def get_translator(bcp_47_code):
|
||||
parts = bcp_47_code.replace('-', '_').split('_')[:2]
|
||||
parts[0] = lang_as_iso639_1(parts[0].lower()) or 'en'
|
||||
if len(parts) > 1:
|
||||
parts[1] = parts[1].upper()
|
||||
lang = '_'.join(parts)
|
||||
lang = {'pt':'pt_BR', 'zh':'zh_CN'}.get(lang, lang)
|
||||
available = available_translations()
|
||||
found = True
|
||||
if lang == 'en' or lang.startswith('en_'):
|
||||
return found, lang, NullTranslations()
|
||||
if lang not in available:
|
||||
lang = {'pt':'pt_BR', 'zh':'zh_CN'}.get(parts[0], parts[0])
|
||||
if lang not in available:
|
||||
lang = get_lang()
|
||||
if lang not in available:
|
||||
lang = 'en'
|
||||
found = False
|
||||
if lang == 'en':
|
||||
return True, lang, NullTranslations()
|
||||
return found, lang, get_single_translator(lang)
|
||||
|
||||
|
||||
lcdata = {
|
||||
'abday': ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'),
|
||||
'abmon': ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'),
|
||||
@@ -208,62 +65,9 @@ def load_po(path):
|
||||
|
||||
|
||||
def set_translators():
|
||||
global _lang_trans, lcdata
|
||||
# To test different translations invoke as
|
||||
# CALIBRE_OVERRIDE_LANG=de_DE.utf8 program
|
||||
lang = get_lang()
|
||||
t = buf = iso639 = None
|
||||
|
||||
if 'CALIBRE_TEST_TRANSLATION' in os.environ:
|
||||
buf = load_po(os.path.expanduser(os.environ['CALIBRE_TEST_TRANSLATION']))
|
||||
|
||||
if lang:
|
||||
mpath = get_lc_messages_path(lang)
|
||||
if buf is None and mpath and os.access(mpath + '.po', os.R_OK):
|
||||
buf = load_po(mpath + '.po')
|
||||
|
||||
if mpath is not None:
|
||||
from zipfile import ZipFile
|
||||
with ZipFile(P('localization/locales.zip',
|
||||
allow_user_override=False), 'r') as zf:
|
||||
if buf is None:
|
||||
buf = io.BytesIO(zf.read(mpath + '/messages.mo'))
|
||||
if mpath == 'nds':
|
||||
mpath = 'de'
|
||||
isof = mpath + '/iso639.mo'
|
||||
try:
|
||||
iso639 = io.BytesIO(zf.read(isof))
|
||||
except:
|
||||
pass # No iso639 translations for this lang
|
||||
if buf is not None:
|
||||
from ebook_converter.utils.serialize import msgpack_loads
|
||||
try:
|
||||
lcdata = msgpack_loads(zf.read(mpath + '/lcdata.calibre_msgpack'))
|
||||
except:
|
||||
pass # No lcdata
|
||||
|
||||
if buf is not None:
|
||||
t = GNUTranslations(buf)
|
||||
if iso639 is not None:
|
||||
iso639 = _lang_trans = GNUTranslations(iso639)
|
||||
t.add_fallback(iso639)
|
||||
|
||||
if t is None:
|
||||
t = NullTranslations()
|
||||
|
||||
try:
|
||||
set_translators.lang = t.info().get('language')
|
||||
except Exception:
|
||||
pass
|
||||
if is_py3:
|
||||
t.install(names=('ngettext',))
|
||||
else:
|
||||
t.install(unicode=True, names=('ngettext',))
|
||||
# Now that we have installed a translator, we have to retranslate the help
|
||||
# for the global prefs object as it was instantiated in get_lang(), before
|
||||
# the translator was installed.
|
||||
from ebook_converter.utils.config_base import prefs
|
||||
prefs.retranslate_help()
|
||||
t = NullTranslations()
|
||||
set_translators.lang = t.info().get('language')
|
||||
t.install(names=('ngettext',))
|
||||
|
||||
|
||||
set_translators.lang = None
|
||||
@@ -535,53 +339,5 @@ def get_udc():
|
||||
return _udc
|
||||
|
||||
|
||||
def user_manual_stats():
|
||||
stats = getattr(user_manual_stats, 'stats', None)
|
||||
if stats is None:
|
||||
import json
|
||||
try:
|
||||
stats = json.loads(P('user-manual-translation-stats.json', allow_user_override=False, data=True))
|
||||
except EnvironmentError:
|
||||
stats = {}
|
||||
user_manual_stats.stats = stats
|
||||
return stats
|
||||
|
||||
|
||||
def localize_user_manual_link(url):
|
||||
#lc = lang_as_iso639_1(get_lang())
|
||||
# if lc == 'en':
|
||||
return url
|
||||
# stats = user_manual_stats()
|
||||
# if stats.get(lc, 0) < 0.3:
|
||||
# return url
|
||||
# from polyglot.urllib import urlparse, urlunparse
|
||||
# parts = urlparse(url)
|
||||
# path = re.sub(r'/generated/[a-z]+/', '/generated/%s/' % lc, parts.path or '')
|
||||
# path = '/%s%s' % (lc, path)
|
||||
# parts = list(parts)
|
||||
# parts[2] = path
|
||||
# return urlunparse(parts)
|
||||
|
||||
|
||||
def website_languages():
|
||||
stats = getattr(website_languages, 'stats', None)
|
||||
if stats is None:
|
||||
try:
|
||||
stats = frozenset(P('localization/website-languages.txt', allow_user_override=False, data=True).split())
|
||||
except EnvironmentError:
|
||||
stats = frozenset()
|
||||
website_languages.stats = stats
|
||||
return stats
|
||||
|
||||
|
||||
def localize_website_link(url):
|
||||
lc = lang_as_iso639_1(get_lang())
|
||||
langs = website_languages()
|
||||
if lc == 'en' or lc not in langs:
|
||||
return url
|
||||
from ebook_converter.polyglot.urllib import urlparse, urlunparse
|
||||
parts = urlparse(url)
|
||||
path = '/{}{}'.format(lc, parts.path)
|
||||
parts = list(parts)
|
||||
parts[2] = path
|
||||
return urlunparse(parts)
|
||||
|
||||
Reference in New Issue
Block a user