GwR wip book jacket

This commit is contained in:
GRiker 2010-09-13 19:12:49 -06:00
parent a0f09b8fc1
commit ba67e47c92
4 changed files with 120 additions and 53 deletions

View File

@ -2342,8 +2342,10 @@ class ITUNES(DriverBase):
if isosx:
if DEBUG:
self.log.info(" deleting '%s' from iDevice" % cached_book['title'])
cached_book['dev_book'].delete()
try:
cached_book['dev_book'].delete()
except:
self.log.error(" error deleting '%s'" % cached_book['title'])
elif iswindows:
hit = self._find_device_book(cached_book)
if hit:

View File

@ -146,7 +146,6 @@ class CSSFlattener(object):
extra_css=css)
self.stylizers[item] = stylizer
def baseline_node(self, node, stylizer, sizes, csize):
csize = stylizer.style(node)['font-size']
if node.text:
@ -194,7 +193,7 @@ class CSSFlattener(object):
value = 0.0
cssdict[property] = "%0.5fem" % (value / fsize)
def flatten_node(self, node, stylizer, names, styles, psize, left=0):
def flatten_node(self, node, stylizer, names, styles, psize, item_id, left=0):
if not isinstance(node.tag, basestring) \
or namespace(node.tag) != XHTML_NS:
return
@ -286,15 +285,18 @@ class CSSFlattener(object):
if self.lineh and 'line-height' not in cssdict:
lineh = self.lineh / psize
cssdict['line-height'] = "%0.5fem" % lineh
if (self.context.remove_paragraph_spacing or
self.context.insert_blank_line) and tag in ('p', 'div'):
for prop in ('margin', 'padding', 'border'):
for edge in ('top', 'bottom'):
cssdict['%s-%s'%(prop, edge)] = '0pt'
if item_id != 'jacket' or self.context.output_profile.name == 'Kindle':
for prop in ('margin', 'padding', 'border'):
for edge in ('top', 'bottom'):
cssdict['%s-%s'%(prop, edge)] = '0pt'
if self.context.insert_blank_line:
cssdict['margin-top'] = cssdict['margin-bottom'] = '0.5em'
if self.context.remove_paragraph_spacing:
cssdict['text-indent'] = "%1.1fem" % self.context.remove_paragraph_spacing_indent_size
if cssdict:
items = cssdict.items()
items.sort()
@ -313,7 +315,7 @@ class CSSFlattener(object):
if 'style' in node.attrib:
del node.attrib['style']
for child in node:
self.flatten_node(child, stylizer, names, styles, psize, left)
self.flatten_node(child, stylizer, names, styles, psize, item_id, left)
def flatten_head(self, item, stylizer, href):
html = item.data
@ -360,7 +362,7 @@ class CSSFlattener(object):
stylizer = self.stylizers[item]
body = html.find(XHTML('body'))
fsize = self.context.dest.fbase
self.flatten_node(body, stylizer, names, styles, fsize)
self.flatten_node(body, stylizer, names, styles, fsize, item.id)
items = [(key, val) for (val, key) in styles.items()]
items.sort()
css = ''.join(".%s {\n%s;\n}\n\n" % (key, val) for key, val in items)

View File

@ -13,6 +13,9 @@ from itertools import repeat
from lxml import etree
from calibre import guess_type, strftime
from calibre.constants import __appname__, __version__
from calibre.utils.date import now
from calibre.ebooks.BeautifulSoup import BeautifulSoup
from calibre.ebooks.oeb.base import XPath, XPNSMAP
from calibre.library.comments import comments_to_html
class Jacket(object):
@ -29,13 +32,30 @@ class Jacket(object):
<style type="text/css" media="screen">%(css)s</style>
</head>
<body>
<div class="banner">
<div class="meta_div">%(title)s</div>
<div class="meta_div">%(series)s</div>
<div class="meta_div">%(rating)s</div>
<div class="meta_div">%(tags)s</div>
<div class="cbj_banner">
<div class="cbj_title">%(title)s</div>
<table class="cbj_header">
<tr class="cbj_series">
<td class="cbj_label">Series:</td>
<td class="cbj_content">%(series)s</td>
</tr>
<tr class="cbj_pubdate">
<td class="cbj_label">Published:</td>
<td class="cbj_content">%(pubdate)s</td>
</tr>
<tr class="cbj_rating">
<td class="cbj_label">Rating:</td>
<td class="cbj_content">%(rating)s</td>
</tr>
<tr class="cbj_tags">
<td class="cbj_label">Tags:</td>
<td class="cbj_content">%(tags)s</td>
</tr>
</table>
<div class="cbj_footer">%(footer)s</div>
</div>
<div class="comments">%(comments)s</div>
<hr class="cbj_kindle_banner_hr" />
<div class="cbj_comments">%(comments)s</div>
</body>
</html>
''')
@ -56,7 +76,7 @@ class Jacket(object):
def get_rating(self, rating):
ans = ''
if rating is None:
return
return ans
try:
num = float(rating)/2
except:
@ -65,19 +85,54 @@ class Jacket(object):
num = min(num, 5)
if num < 1:
return ans
id, href = self.oeb.manifest.generate('star', 'star.png')
self.oeb.manifest.add(id, href, 'image/png', data=I('star.png', data=True))
ans = '<span class="rating">Rating: </span> ' + ''.join(repeat('<img style="vertical-align:text-top" alt="star" src="%s" />'%href, num))
if self.opts.output_profile.name == 'Kindle':
ans = '%s' % ''.join(repeat('&#9733;', num))
else:
id, href = self.oeb.manifest.generate('star', 'star.png')
self.oeb.manifest.add(id, href, 'image/png', data=I('star.png', data=True))
ans = '%s' % ''.join(repeat('<img style="vertical-align:text-bottom" alt="star" src="%s" />'%href, num))
return ans
def insert_metadata(self, mi):
self.log('Inserting metadata into book...')
jacket_resources = P("jacket")
if os.path.isdir(jacket_resources):
stylesheet = os.path.join(jacket_resources, 'stylesheet.css')
with open(stylesheet) as f:
css_data = f.read()
css_data = ''
stylesheet = os.path.join(jacket_resources, 'stylesheet.css')
with open(stylesheet) as f:
css = f.read()
try:
title_str = mi.title if mi.title else unicode(self.oeb.metadata.title[0])
except:
title_str = _('Unknown')
title = '<span class="title">%s</span>' % (escape(title_str))
series = escape(mi.series if mi.series else '')
if mi.series and mi.series_index is not None:
series += escape(' [%s]'%mi.format_series_index())
if not mi.series:
series = ''
try:
pubdate = strftime(u'%Y', mi.pubdate.timetuple())
except:
#pubdate = strftime(u'%Y', now())
pubdate = ''
rating = self.get_rating(mi.rating)
tags = mi.tags
if not tags:
try:
tags = map(unicode, self.oeb.metadata.subject)
except:
tags = []
if tags:
#tags = self.opts.dest.tags_to_string(tags)
tags = ', '.join(tags)
else:
tags = ''
comments = mi.comments
if not comments:
@ -91,46 +146,50 @@ class Jacket(object):
if comments:
comments = comments_to_html(comments)
series = '<span class="meta_label">Series: </span><span class="series">%s</span>' % escape(mi.series if mi.series else '')
if mi.series and mi.series_index is not None:
series += '<span class="series">%s</span>' % escape(' [%s]'%mi.format_series_index())
if not mi.series:
series = ''
tags = mi.tags
if not tags:
try:
tags = map(unicode, self.oeb.metadata.subject)
except:
tags = []
if tags:
tags = '<span class="meta_label">Tags:</span><span class="tags">%s</span>' % self.opts.dest.tags_to_string(tags)
else:
tags = ''
try:
title_str = mi.title if mi.title else unicode(self.oeb.metadata.title[0])
except:
title_str = _('Unknown')
title = '<span class="title">%s</span><span class="pubdate"> (%s)</span>' % (escape(title_str), strftime(u'%Y', mi.pubdate.timetuple()))
footer = 'B<span class="cbj_smallcaps">OOK JACKET GENERATED BY %s %s</span>' % (__appname__.upper(),__version__)
def generate_html(comments):
return self.JACKET_TEMPLATE%dict(xmlns=XPNSMAP['h'],
title=title, comments=comments,
series=series,
tags=tags, rating=self.get_rating(mi.rating),
css=css_data, title_str=title_str)
args = dict(xmlns=XPNSMAP['h'],
title_str=title_str,
css=css,
title=title,
pubdate=pubdate,
series=series,
rating=rating,
tags=tags,
comments=comments,
footer = footer)
# Post-process the generated html to strip out empty header items
generated_html = self.JACKET_TEMPLATE % args
soup = BeautifulSoup(generated_html)
if not series:
series_tag = soup.find('tr', attrs={'class':'cbj_series'})
series_tag.extract()
if not rating:
rating_tag = soup.find('tr', attrs={'class':'cbj_rating'})
rating_tag.extract()
if not tags:
tags_tag = soup.find('tr', attrs={'class':'cbj_tags'})
tags_tag.extract()
if not pubdate:
pubdate_tag = soup.find('tr', attrs={'class':'cbj_pubdate'})
pubdate_tag.extract()
if self.opts.output_profile.name != 'Kindle':
hr_tag = soup.find('hr', attrs={'class':'cbj_kindle_banner_hr'})
hr_tag.extract()
return soup.renderContents()
id, href = self.oeb.manifest.generate('jacket', 'jacket.xhtml')
from calibre.ebooks.oeb.base import RECOVER_PARSER, XPath
try:
root = etree.fromstring(generate_html(comments), parser=RECOVER_PARSER)
# print "root: %s" % etree.tostring(root, encoding='utf-8',
# xml_declaration=True, pretty_print=True)
except:
root = etree.fromstring(generate_html(escape(orig_comments)),
parser=RECOVER_PARSER)
jacket = XPath('//h:meta[@name="calibre-content" and @content="jacket"]')
found = None
for item in list(self.oeb.spine)[:4]:

View File

@ -2523,6 +2523,10 @@ class EPUB_MOBI(CatalogPlugin):
# Fetch the database as a dictionary
self.booksBySeries = self.plugin.search_sort_db(self.db, self.opts)
if not self.booksBySeries:
self.opts.generate_series = False
self.opts.log(" no series found in selected books, cancelling series generation")
return
friendly_name = "Series"