diff --git a/resources/images/news/science_news_recent_issues.png b/resources/images/news/science_news_recent_issues.png
new file mode 100644
index 0000000000..355fb8c3a6
Binary files /dev/null and b/resources/images/news/science_news_recent_issues.png differ
diff --git a/resources/recipes/science_news_recent_issues.recipe b/resources/recipes/science_news_recent_issues.recipe
new file mode 100644
index 0000000000..7eb93e0d59
--- /dev/null
+++ b/resources/recipes/science_news_recent_issues.recipe
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+
+__license__ = 'GPL v3'
+'''
+sciencenews.org
+'''
+from calibre.web.feeds.news import BasicNewsRecipe
+
+class ScienceNewsIssue(BasicNewsRecipe):
+ title = u'Science News Recent Issues'
+ __author__ = u'Darko Miletic, Sujata Raman and Starson17'
+ description = u'''Science News is an award-winning weekly
+ newsmagazine covering the most important research in all fields of science.
+ Its 16 pages each week are packed with short, accurate articles that appeal
+ to both general readers and scientists. Published since 1922, the magazine
+ now reaches about 150,000 subscribers and more than 1 million readers.
+ These are the latest News Items from Science News. This recipe downloads
+ the last 30 days worth of articles.'''
+ category = u'Science, Technology, News'
+ publisher = u'Society for Science & the Public'
+ oldest_article = 30
+ language = 'en'
+ max_articles_per_feed = 100
+ no_stylesheets = True
+ use_embedded_content = False
+ timefmt = ' [%A, %d %B, %Y]'
+ recursions = 1
+ remove_attributes = ['style']
+
+ conversion_options = {'linearize_tables' : True
+ , 'comment' : description
+ , 'tags' : category
+ , 'publisher' : publisher
+ , 'language' : language
+ }
+
+ extra_css = '''
+ .content_description{font-family:georgia ;font-size:x-large; color:#646464 ; font-weight:bold;}
+ .content_summary{font-family:georgia ;font-size:small ;color:#585858 ; font-weight:bold;}
+ .content_authors{font-family:helvetica,arial ;font-size: xx-small ;color:#14487E ;}
+ .content_edition{font-family:helvetica,arial ;font-size: xx-small ;}
+ .exclusive{color:#FF0000 ;}
+ .anonymous{color:#14487E ;}
+ .content_content{font-family:helvetica,arial ;font-size: medium ; color:#000000;}
+ .description{color:#585858;font-family:helvetica,arial ;font-size: large ;}
+ .credit{color:#A6A6A6;font-family:helvetica,arial ;font-size: xx-small ;}
+ '''
+
+ keep_only_tags = [ dict(name='div', attrs={'id':'column_action'}) ]
+ remove_tags_after = dict(name='ul', attrs={'id':'content_functions_bottom'})
+ remove_tags = [
+ dict(name='ul', attrs={'id':'content_functions_bottom'})
+ ,dict(name='div', attrs={'id':['content_functions_top','breadcrumb_content']})
+ ,dict(name='img', attrs={'class':'icon'})
+ ,dict(name='div', attrs={'class': 'embiggen'})
+ ]
+
+ feeds = [(u"Science News Current Issues", u'http://www.sciencenews.org/view/feed/type/edition/name/issues.rss')]
+
+ match_regexps = [
+ r'www.sciencenews.org/view/feature/id/',
+ r'www.sciencenews.org/view/generic/id'
+ ]
+
+ def get_cover_url(self):
+ cover_url = None
+ index = 'http://www.sciencenews.org/view/home'
+ soup = self.index_to_soup(index)
+ link_item = soup.find(name = 'img',alt = "issue")
+ if link_item:
+ cover_url = 'http://www.sciencenews.org' + link_item['src'] + '.jpg'
+
+ return cover_url
+
+ def preprocess_html(self, soup):
+ for tag in soup.findAll(name=['span']):
+ tag.name = 'div'
+ return soup
diff --git a/src/calibre/customize/profiles.py b/src/calibre/customize/profiles.py
index 0310f09242..1d879f0c5d 100644
--- a/src/calibre/customize/profiles.py
+++ b/src/calibre/customize/profiles.py
@@ -255,6 +255,9 @@ class OutputProfile(Plugin):
#: Unsupported unicode characters to be replaced during preprocessing
unsupported_unicode_chars = []
+ #: Number of ems that the left margin of a blockquote is rendered as
+ mobi_ems_per_blockquote = 1.0
+
@classmethod
def tags_to_string(cls, tags):
return escape(', '.join(tags))
@@ -564,6 +567,7 @@ class KindleOutput(OutputProfile):
supports_mobi_indexing = True
periodical_date_in_title = False
ratings_char = u'\u2605'
+ mobi_ems_per_blockquote = 2.0
@classmethod
def tags_to_string(cls, tags):
@@ -582,6 +586,7 @@ class KindleDXOutput(OutputProfile):
comic_screen_size = (741, 1022)
supports_mobi_indexing = True
periodical_date_in_title = False
+ mobi_ems_per_blockquote = 2.0
@classmethod
def tags_to_string(cls, tags):
diff --git a/src/calibre/ebooks/epub/input.py b/src/calibre/ebooks/epub/input.py
index 214511ae14..cdd69ea50f 100644
--- a/src/calibre/ebooks/epub/input.py
+++ b/src/calibre/ebooks/epub/input.py
@@ -117,7 +117,8 @@ class EPUBInput(InputFormatPlugin):
encfile = os.path.abspath(os.path.join('META-INF', 'encryption.xml'))
opf = None
for f in walk(u'.'):
- if f.lower().endswith('.opf') and '__MACOSX' not in f:
+ if f.lower().endswith('.opf') and '__MACOSX' not in f and \
+ not os.path.basename(f).startswith('.'):
opf = os.path.abspath(f)
break
path = getattr(stream, 'name', 'stream')
diff --git a/src/calibre/ebooks/metadata/fb2.py b/src/calibre/ebooks/metadata/fb2.py
index 576fbaa6fc..6e0d56dfa0 100644
--- a/src/calibre/ebooks/metadata/fb2.py
+++ b/src/calibre/ebooks/metadata/fb2.py
@@ -33,7 +33,10 @@ def get_metadata(stream):
le = XPath('descendant::fb2:last-name')(au)
if le:
lname = tostring(le[0])
- author += ' '+lname
+ if author:
+ author += ' '+lname
+ else:
+ author = lname
if author:
authors.append(author)
if len(authors) == 1 and author is not None:
diff --git a/src/calibre/ebooks/mobi/mobiml.py b/src/calibre/ebooks/mobi/mobiml.py
index 231ad51eee..a822e66758 100644
--- a/src/calibre/ebooks/mobi/mobiml.py
+++ b/src/calibre/ebooks/mobi/mobiml.py
@@ -184,13 +184,14 @@ class MobiMLizer(object):
elif tag in NESTABLE_TAGS and istate.rendered:
para = wrapper = bstate.nested[-1]
elif left > 0 and indent >= 0:
+ ems = self.profile.mobi_ems_per_blockquote
para = wrapper = etree.SubElement(parent, XHTML('blockquote'))
para = wrapper
- emleft = int(round(left / self.profile.fbase)) - 1
+ emleft = int(round(left / self.profile.fbase)) - ems
emleft = min((emleft, 10))
while emleft > 0:
para = etree.SubElement(para, XHTML('blockquote'))
- emleft -= 1
+ emleft -= ems
else:
para = wrapper = etree.SubElement(parent, XHTML('p'))
bstate.inline = bstate.para = para
diff --git a/src/calibre/ebooks/mobi/output.py b/src/calibre/ebooks/mobi/output.py
index 49da18ea7b..d82704a0df 100644
--- a/src/calibre/ebooks/mobi/output.py
+++ b/src/calibre/ebooks/mobi/output.py
@@ -41,6 +41,24 @@ class MOBIOutput(OutputFormatPlugin):
),
])
+ def remove_image_transparencies(self):
+ from calibre.utils.magick.draw import save_cover_data_to
+ for item in self.oeb.manifest:
+ if item.media_type.startswith('image'):
+ raw = item.data
+ ext = item.media_type.split('/')[-1].lower()
+ if ext not in ('png', 'gif') or not raw:
+ continue
+ try:
+ data = save_cover_data_to(raw, 'img.'+ext, return_data=True)
+ except:
+ self.log.exception('Failed to remove transparency from',
+ item.href)
+ data = None
+ if data is not None:
+ item.data = data
+ item.unload_data_from_memory()
+
def check_for_periodical(self):
if self.oeb.metadata.publication_type and \
unicode(self.oeb.metadata.publication_type[0]).startswith('periodical:'):
@@ -160,6 +178,7 @@ class MOBIOutput(OutputFormatPlugin):
from calibre.ebooks.oeb.transforms.rasterize import SVGRasterizer, Unavailable
from calibre.ebooks.oeb.transforms.htmltoc import HTMLTOCAdder
from calibre.customize.ui import plugin_for_input_format
+ self.remove_image_transparencies()
imagemax = PALM_MAX_IMAGE_SIZE if opts.rescale_images else None
if not opts.no_inline_toc:
tocadder = HTMLTOCAdder(title=opts.toc_title)
diff --git a/src/calibre/ebooks/mobi/reader.py b/src/calibre/ebooks/mobi/reader.py
index 6a44c2aa77..dbe6854006 100644
--- a/src/calibre/ebooks/mobi/reader.py
+++ b/src/calibre/ebooks/mobi/reader.py
@@ -234,7 +234,7 @@ class MobiReader(object):
self.debug = debug
self.embedded_mi = None
self.base_css_rules = textwrap.dedent('''
- blockquote { margin: 0em 0em 0em 1.25em; text-align: justify }
+ blockquote { margin: 0em 0em 0em 2em; text-align: justify }
p { margin: 0em; text-align: justify }
diff --git a/src/calibre/ebooks/oeb/transforms/rescale.py b/src/calibre/ebooks/oeb/transforms/rescale.py
index c3b4d6d40c..79d4c76487 100644
--- a/src/calibre/ebooks/oeb/transforms/rescale.py
+++ b/src/calibre/ebooks/oeb/transforms/rescale.py
@@ -39,7 +39,7 @@ class RescaleImages(object):
if item.media_type.startswith('image'):
ext = item.media_type.split('/')[-1].upper()
if ext == 'JPG': ext = 'JPEG'
- if ext not in ('PNG', 'JPEG'):
+ if ext not in ('PNG', 'JPEG', 'GIF'):
ext = 'JPEG'
raw = item.data
diff --git a/src/calibre/gui2/dialogs/tweak_epub.ui b/src/calibre/gui2/dialogs/tweak_epub.ui
index 063460aaae..fc6f24675f 100644
--- a/src/calibre/gui2/dialogs/tweak_epub.ui
+++ b/src/calibre/gui2/dialogs/tweak_epub.ui
@@ -10,7 +10,7 @@
0
0
382
- 242
+ 265
diff --git a/src/calibre/gui2/preferences/plugboard.ui b/src/calibre/gui2/preferences/plugboard.ui
index 289518816f..b73c396481 100644
--- a/src/calibre/gui2/preferences/plugboard.ui
+++ b/src/calibre/gui2/preferences/plugboard.ui
@@ -19,7 +19,7 @@
Here you can change the metadata calibre uses to update a book when saving to disk or sending to device.
-Use this dialog to define a 'plugboard' for a format (or all formats) and a device (or all devices). The plugboard spefies what template is connected to what field. The template is used to compute a value, and that value is assigned to the connected field.
+Use this dialog to define a 'plugboard' for a format (or all formats) and a device (or all devices). The plugboard specifies what template is connected to what field. The template is used to compute a value, and that value is assigned to the connected field.
Often templates will contain simple references to composite columns, but this is not necessary. You can use any template in a source box that you can use elsewhere in calibre.