'),
(r'
.*?', lambda match : ''),
(r'.*?', lambda match : ''),
-
+
## This removes the "download image" of various sizes from the Image of the day.
(r'.*?
', lambda match : '
'),
diff --git a/resources/recipes/ncrnext.recipe b/resources/recipes/ncrnext.recipe
new file mode 100644
index 0000000000..d8a51e62c8
--- /dev/null
+++ b/resources/recipes/ncrnext.recipe
@@ -0,0 +1,114 @@
+from calibre.web.feeds.news import BasicNewsRecipe
+from calibre.ebooks.BeautifulSoup import BeautifulSoup
+
+class NrcNextRecipe(BasicNewsRecipe):
+ __license__ = 'GPL v3'
+ __author__ = 'kwetal'
+ version = 1
+ language = 'nl'
+ description = u'Dutch newsblog from the Dutch daily newspaper nrcnext.'
+ title = u'nrcnext'
+
+ no_stylesheets = True
+ template_css = ''
+
+ # I want to do some special processing on the articles. I could not solve it with the 'extra_css' property . So we do it the hard way.
+ keep_only_tags = [dict(name='div', attrs={'id' : 'main'})]
+ # If that's overkill for you comment out the previous line and uncomment the next. Then get rid of the preprocess_html() method.
+ #keep_only_tags = [dict(name='div', attrs={'class' : 'post'}), dict(name='div', attrs={'class' : 'vlag'}) ]
+
+ remove_tags = [dict(name = 'div', attrs = {'class' : 'meta'}),
+ dict(name = 'div', attrs = {'class' : 'datumlabel'}),
+ dict(name = 'ul', attrs = {'class' : 'cats single'}),
+ dict(name = 'ul', attrs = {'class' : 'cats onderwerpen'}),
+ dict(name = 'ul', attrs = {'class' : 'cats rubrieken'})]
+
+ use_embedded_content = False
+
+ def parse_index(self) :
+ # Use the wesbite as an index. Their RSS feeds can be out of date.
+ feeds = {}
+ feeds[u'columnisten'] = u'http://www.nrcnext.nl/columnisten/'
+ feeds[u'koken'] = u'http://www.nrcnext.nl/koken/'
+ feeds[u'geld & werk'] = u'http://www.nrcnext.nl/geld-en-werk/'
+ feeds[u'vandaag'] = u'http://www.nrcnext.nl'
+ feeds[u'city life in afrika'] = u'http://www.nrcnext.nl/city-life-in-afrika/'
+ answer = []
+ articles = {}
+ indices = []
+
+ for index, feed in feeds.items() :
+ soup = self.index_to_soup(feed)
+
+ for post in soup.findAll(True, attrs={'class' : 'post'}) :
+ # Find the links to the actual articles and rember the location they're pointing to and the title
+ a = post.find('a', attrs={'rel' : 'bookmark'})
+ href = a['href']
+ title = a.renderContents()
+
+ if index == 'columnisten' :
+ # In this feed/page articles can be written by more than one author. It is nice to see their names in the titles.
+ flag = post.find('h2', attrs = {'class' : 'vlag'})
+ author = flag.contents[0].renderContents()
+ completeTitle = u''.join([author, u': ', title])
+ else :
+ completeTitle = title
+
+ # Add the article to a temporary list
+ article = {'title' : completeTitle, 'date' : u'', 'url' : href, 'description' : '
'}
+ if not articles.has_key(index) :
+ articles[index] = []
+ articles[index].append(article)
+
+ # Add the index title to a temporary list
+ indices.append(index)
+
+ # Now, sort the temporary list of feeds in the order they appear on the website
+ indices = self.sort_index_by(indices, {u'columnisten' : 1, u'koken' : 3, u'geld & werk' : 2, u'vandaag' : 0, u'city life in afrika' : 4})
+ # Apply this sort order to the actual list of feeds and articles
+ answer = [(key, articles[key]) for key in indices if articles.has_key(key)]
+
+ return answer
+
+ def preprocess_html(self, soup) :
+ # This method is called for every page, be it cartoon or TOC. We need to process each in their own way
+ if soup.find('div', attrs = {'id' : 'main', 'class' : 'single'}) :
+ # It's an article, find the interesting part
+ tag = soup.find('div', attrs = {'class' : 'post'})
+ if tag :
+ # And replace any links with their text, so they don't show up underlined on my reader.
+ for link in tag.findAll('a') :
+ link.replaceWith(link.renderContents())
+
+ # Slows down my Sony reader; feel free to comment out
+ for movie in tag.findAll('span', attrs = {'class' : 'vvqbox vvqvimeo'}) :
+ movie.extract()
+ for movie in tag.findAll('span', attrs = {'class' : 'vvqbox vvqyoutube'}) :
+ movie.extract()
+
+ homeMadeSoup = BeautifulSoup('')
+ body = homeMadeSoup.find('body')
+ body.append(tag)
+
+ return homeMadeSoup
+ else :
+ # This should never happen and other famous last words...
+ return soup
+ else :
+ # It's a TOC, return the whole lot.
+ return soup
+
+ def postproces_html(self, soup) :
+ # Should not happen, but it does. Slows down my Sony eReader
+ for img in soup.findAll('img') :
+ if img['src'].startswith('http://') :
+ img.extract()
+
+ # Happens for some movies which we are not able to view anyway
+ for iframe in soup.findAll('iframe') :
+ if iframe['src'].startswith('http://') :
+ iframe.extract()
+
+
+
+
diff --git a/resources/recipes/nytimes.recipe b/resources/recipes/nytimes.recipe
index 89d5656741..26ecf895ef 100644
--- a/resources/recipes/nytimes.recipe
+++ b/resources/recipes/nytimes.recipe
@@ -14,7 +14,7 @@ class NYTimes(BasicNewsRecipe):
title = 'New York Times Top Stories'
__author__ = 'GRiker'
- language = _('English')
+ language = 'en'
description = 'Top Stories from the New York Times'
# List of sections typically included in Top Stories. Use a keyword from the
diff --git a/resources/recipes/nytimes_sub.recipe b/resources/recipes/nytimes_sub.recipe
index a2c805c299..a6e903f6dd 100644
--- a/resources/recipes/nytimes_sub.recipe
+++ b/resources/recipes/nytimes_sub.recipe
@@ -22,7 +22,10 @@ class NYTimes(BasicNewsRecipe):
remove_tags_before = dict(id='article')
remove_tags_after = dict(id='article')
remove_tags = [dict(attrs={'class':['articleTools', 'post-tools', 'side_tool', 'nextArticleLink clearfix']}),
- dict(id=['footer', 'toolsRight', 'articleInline', 'navigation', 'archive', 'side_search', 'blog_sidebar', 'side_tool', 'side_index']),
+ dict(id=['footer', 'toolsRight', 'articleInline',
+ 'navigation', 'archive', 'side_search', 'blog_sidebar',
+ 'side_tool', 'side_index',
+ 'relatedArticles', 'relatedTopics', 'adxSponLink']),
dict(name=['script', 'noscript', 'style'])]
encoding = 'cp1252'
no_stylesheets = True
diff --git a/resources/recipes/ourdailybread.recipe b/resources/recipes/ourdailybread.recipe
index 6987ab2325..0b37880377 100644
--- a/resources/recipes/ourdailybread.recipe
+++ b/resources/recipes/ourdailybread.recipe
@@ -21,8 +21,7 @@ class OurDailyBread(BasicNewsRecipe):
use_embedded_content = False
category = 'religion'
encoding = 'utf-8'
- extra_css = ' #devoTitle{font-size: x-large; font-weight: bold} '
-
+
conversion_options = {
'comments' : description
,'tags' : category
@@ -32,13 +31,13 @@ class OurDailyBread(BasicNewsRecipe):
keep_only_tags = [dict(name='div', attrs={'class':['altbg','text']})]
remove_tags = [dict(name='div', attrs={'id':['ctl00_cphPrimary_pnlBookCover']}),
- dict(name='div', attrs={'class':['devotionalLinks']})
]
extra_css = '''
.text{font-family:Arial,Helvetica,sans-serif;font-size:x-small;}
.devotionalTitle{font-family:Arial,Helvetica,sans-serif; font-size:large; font-weight: bold;}
.devotionalDate{font-family:Arial,Helvetica,sans-serif; font-size:xx-small;}
.devotionalVerse{font-family:Arial,Helvetica,sans-serif; font-size:xx-small; }
+ a{color:#000000;font-family:Arial,Helvetica,sans-serif; font-size:x-small;}
'''
feeds = [(u'Our Daily Bread', u'http://www.rbc.org/rss.ashx?id=50398')]
diff --git a/resources/recipes/sportsillustrated.recipe b/resources/recipes/sportsillustrated.recipe
new file mode 100644
index 0000000000..0dbae1ebc0
--- /dev/null
+++ b/resources/recipes/sportsillustrated.recipe
@@ -0,0 +1,99 @@
+from calibre.web.feeds.recipes import BasicNewsRecipe
+from calibre.ebooks.BeautifulSoup import BeautifulSoup
+#from random import randint
+from urllib import quote
+
+class SportsIllustratedRecipe(BasicNewsRecipe) :
+ __author__ = 'kwetal'
+ __copyright__ = 'kwetal'
+ __license__ = 'GPL v3'
+ language = 'en'
+ description = 'Sports Illustrated'
+ version = 1
+ title = u'Sports Illustrated'
+
+ no_stylesheets = True
+ remove_javascript = True
+ #template_css = ''
+ use_embedded_content = False
+
+ INDEX = 'http://sportsillustrated.cnn.com/'
+
+ def parse_index(self):
+ answer = []
+ soup = self.index_to_soup(self.INDEX)
+ # Find the link to the current issue on the front page.
+ cover = soup.find('img', attrs = {'alt' : 'Read All Articles', 'style' : 'vertical-align:bottom;'})
+ if cover:
+ currentIssue = cover.parent['href']
+ if currentIssue:
+ # Open the index of current issue
+ index = self.index_to_soup(currentIssue)
+
+ # Find all articles.
+ list = index.find('div', attrs = {'class' : 'siv_artList'})
+ if list:
+ articles = []
+ # Get all the artcles ready for calibre.
+ for headline in list.findAll('div', attrs = {'class' : 'headline'}):
+ title = self.tag_to_string(headline.a) + '\n' + self.tag_to_string(headline.findNextSibling('div', attrs = {'class' : 'info'}))
+ url = self.INDEX + headline.a['href']
+ description = self.tag_to_string(headline.findNextSibling('a').div)
+ article = {'title' : title, 'date' : u'', 'url' : url, 'description' : description}
+
+ articles.append(article)
+
+ # See if we can find a meaningfull title
+ feedTitle = 'Current Issue'
+ hasTitle = index.find('div', attrs = {'class' : 'siv_imageText_head'})
+ if hasTitle :
+ feedTitle = self.tag_to_string(hasTitle.h1)
+
+ answer.append([feedTitle, articles])
+
+ return answer
+
+
+ def print_version(self, url) :
+ # This is the url and the parameters that work to get the print version.
+ printUrl = 'http://si.printthis.clickability.com/pt/printThis?clickMap=printThis'
+ printUrl += '&fb=Y&partnerID=2356&url=' + quote(url)
+
+ return printUrl
+
+ # However the original javascript also uses the following parameters, but they can be left out:
+ # title : can be some random string
+ # random : some random number, but I think the number of digits is important
+ # expire : no idea what value to use
+ # All this comes from the Javascript function that redirects to the print version. It's called PT() and is defined in the file 48.js
+
+ def preprocess_html(self, soup):
+ header = soup.find('div', attrs = {'class' : 'siv_artheader'})
+ if header:
+ # It's an article, prepare a container for the content
+ homeMadeSoup = BeautifulSoup('')
+ body = homeMadeSoup.find('body')
+
+ # Find the date, title and byline
+ temp = header.find('td', attrs = {'class' : 'title'})
+ if temp :
+ date = temp.find('div', attrs = {'class' : 'date'})
+ if date:
+ body.append(date)
+ if temp.h1:
+ body.append(temp.h1)
+ if temp.h2 :
+ body.append(temp.h2)
+ byline = temp.find('div', attrs = {'class' : 'byline'})
+ if byline:
+ body.append(byline)
+
+ # Find the content
+ for para in soup.findAll('div', attrs = {'class' : 'siv_artpara'}) :
+ body.append(para)
+
+ return homeMadeSoup
+ else :
+ # It's a TOC, just return the whole lot
+ return soup
+
diff --git a/resources/recipes/sportsillustrated_columnists.recipe b/resources/recipes/sportsillustrated_columnists.recipe
new file mode 100644
index 0000000000..2f6b18c992
--- /dev/null
+++ b/resources/recipes/sportsillustrated_columnists.recipe
@@ -0,0 +1,60 @@
+from calibre.web.feeds.recipes import BasicNewsRecipe
+from calibre.ebooks.BeautifulSoup import BeautifulSoup
+#from random import randint
+from urllib import quote
+
+class SportsIllustratedColumnistsRecipe(BasicNewsRecipe) :
+ title = u'Sports Illustrated Columnists'
+ __author__ = u'kwetal'
+ __license__ = u'GPL v3'
+ language = 'en'
+ version = 2
+
+ oldest_article = 7
+ max_articles_per_feed = 100
+ no_stylesheets = True
+ remove_javascript = True
+
+ feeds = []
+ # RSS sources found at http://sportsillustrated.cnn.com/services/rss/
+ feeds.append((u'Jon Heyman', u'http://rss.cnn.com/rss/si_jon_heyman.rss'))
+ feeds.append((u'Austin Murphy', u'http://rss.cnn.com/rss/si_austin_murphy.rss'))
+ feeds.append((u'Lars Anderson', u'http://rss.cnn.com/rss/si_lars_anderson.rss'))
+ feeds.append((u'Melissa Segura', u'http://rss.cnn.com/rss/si_melissa_segura.rss'))
+ feeds.append((u'Peter King', u'http://rss.cnn.com/rss/si_peter_king.rss'))
+ feeds.append((u'Scott Wraight', u'http://rss.cnn.com/rss/si_scott_wraight.rss'))
+
+ def print_version(self, url) :
+ # This is the url and the parameters that work to get the print version.
+ printUrl = 'http://si.printthis.clickability.com/pt/printThis?clickMap=printThis'
+ printUrl += '&fb=Y&partnerID=2356&url=' + quote(url)
+
+ return printUrl
+
+ # However the original javascript also uses the following parameters, but they can be left out:
+ # title : can be some random string
+ # random : some random number, but I think the number of digits is important
+ # expire : no idea what value to use
+ # All this comes from the Javascript function that redirects to the print version. It's called PT() and is defined in the file 48.js
+
+ def preprocess_html(self, soup) :
+ temp = soup.find('div', attrs = {'class' : 'cnnstoryheadline'})
+ if temp :
+ # It's an article, make a valid content container
+ homeMadeSoup = BeautifulSoup('')
+ body = homeMadeSoup.find('body')
+
+ headline = temp.find('h1')
+ if headline :
+ body.append(headline)
+
+ for td in soup.findAll('td', attrs = {'class' : 'cnnstorycontentarea'}) :
+ for p in td.findAll('p') :
+ body.append(p)
+
+ return homeMadeSoup
+ else :
+ # It's a TOC, just return the whole lot
+ return soup
+
+
diff --git a/resources/recipes/the_oz.recipe b/resources/recipes/the_oz.recipe
index b2c0a412fc..a55f31e63e 100644
--- a/resources/recipes/the_oz.recipe
+++ b/resources/recipes/the_oz.recipe
@@ -27,14 +27,19 @@ class DailyTelegraph(BasicNewsRecipe):
, '--publisher' , title
]
- keep_only_tags = [
- dict(name='h1', attrs={'class':'section-heading'})
- ,dict(name='div', attrs={'id':'article'})
- ]
+ keep_only_tags = [dict(name='div', attrs={'id': 'story'})]
- remove_tags = [dict(name=['object','link'])]
+ #remove_tags = [dict(name=['object','link'])]
+ remove_tags = [dict(name ='div', attrs = {'class': 'story-info'}),
+ dict(name ='div', attrs = {'class': 'story-header-tools'}),
+ dict(name ='div', attrs = {'class': 'story-sidebar'}),
+ dict(name ='div', attrs = {'class': 'story-footer'}),
+ dict(name ='div', attrs = {'id': 'comments'}),
+ dict(name ='div', attrs = {'class': 'story-extras story-extras-2'}),
+ dict(name ='div', attrs = {'class': 'group item-count-1 story-related'})
+ ]
- extra_css = '''
+ extra_css = '''
h1{font-family :Georgia,"Times New Roman",Times,serif; font-size:large; }
#article{font-family :Georgia,"Times New Roman",Times,serif; font-size: x-small;}
.module-subheader{font-family :Tahoma,Geneva,Arial,Helvetica,sans-serif; color:#666666; font-size: xx-small;}
@@ -43,34 +48,40 @@ class DailyTelegraph(BasicNewsRecipe):
.caption{font-family:Trebuchet MS,Trebuchet,Helvetica,sans-serif; font-size: xx-small;}
'''
- feeds = [
- (u'News', u'http://feeds.news.com.au/public/rss/2.0/aus_news_807.xml'),
- (u'World News', u'http://feeds.news.com.au/public/rss/2.0/aus_world_808.xml'),
- (u'Opinion', u'http://feeds.news.com.au/public/rss/2.0/aus_opinion_58.xml'),
- (u'Business', u'http://feeds.news.com.au/public/rss/2.0/aus_business_811.xml'),
- (u'Media', u'http://feeds.news.com.au/public/rss/2.0/aus_media_57.xml'),
- (u'Higher Education', u'http://feeds.news.com.au/public/rss/2.0/aus_higher_education_56.xml'),
- (u'The Arts', u'http://feeds.news.com.au/public/rss/2.0/aus_arts_51.xml'),
- (u'Commercial Property', u'http://feeds.news.com.au/public/rss/2.0/aus_business_commercial_property_708.xml'),
- (u'The Nation', u'http://feeds.news.com.au/public/rss/2.0/aus_the_nation_62.xml'),
- (u'Sport', u'http://feeds.news.com.au/public/rss/2.0/aus_sport_61.xml'),
- (u'Travel', u'http://feeds.news.com.au/public/rss/2.0/aus_travel_and_indulgence_63.xml'),
- (u'Defence', u'http://feeds.news.com.au/public/rss/2.0/aus_defence_54.xml'),
- (u'Aviation', u'http://feeds.news.com.au/public/rss/2.0/aus_business_aviation_706.xml'),
- (u'Mining', u'http://feeds.news.com.au/public/rss/2.0/aus_business_mining_704.xml'),
- (u'Climate', u'http://feeds.news.com.au/public/rss/2.0/aus_climate_809.xml'),
- (u'Property', u'http://feeds.news.com.au/public/rss/2.0/aus_property_59.xml'),
- (u'US Election', u'http://feeds.news.com.au/public/rss/2.0/aus_uselection_687.xml')
- ]
+ feeds = [(u'News', u'http://feeds.news.com.au/public/rss/2.0/aus_news_807.xml'),
+ (u'Opinion', u'http://feeds.news.com.au/public/rss/2.0/aus_opinion_58.xml'),
+ (u'Business', u'http://feeds.news.com.au/public/rss/2.0/aus_business_811.xml'),
+ (u'Media', u'http://feeds.news.com.au/public/rss/2.0/aus_media_57.xml'),
+ (u'Higher Education', u'http://feeds.news.com.au/public/rss/2.0/aus_higher_education_56.xml'),
+ (u'The Arts', u'http://feeds.news.com.au/public/rss/2.0/aus_arts_51.xml'),
+ (u'Commercial Property', u'http://feeds.news.com.au/public/rss/2.0/aus_business_commercial_property_708.xml'),
+ (u'The Nation', u'http://feeds.news.com.au/public/rss/2.0/aus_the_nation_62.xml'),
+ (u'Sport', u'http://feeds.news.com.au/public/rss/2.0/aus_sport_61.xml'),
+ (u'Travel', u'http://feeds.news.com.au/public/rss/2.0/aus_travel_and_indulgence_63.xml'),
+ (u'Defence', u'http://feeds.news.com.au/public/rss/2.0/aus_defence_54.xml'),
+ (u'Aviation', u'http://feeds.news.com.au/public/rss/2.0/aus_business_aviation_706.xml'),
+ (u'Mining', u'http://feeds.news.com.au/public/rss/2.0/aus_business_mining_704.xml'),
+ (u'Climate', u'http://feeds.news.com.au/public/rss/2.0/aus_climate_809.xml'),
+ (u'Property', u'http://feeds.news.com.au/public/rss/2.0/aus_property_59.xml'),
+ (u'US Election', u'http://feeds.news.com.au/public/rss/2.0/aus_uselection_687.xml')]
+
+ def get_article_url(self, article):
+ return article.id
+
+ #br = self.get_browser()
+ #br.open(article.link).read()
+ #print br.geturl()
+
+ #return br.geturl()
def get_cover_url(self):
-
- href = 'http://www.theaustralian.news.com.au/'
-
+
+ href = 'http://www.theaustralian.news.com.au/'
+
soup = self.index_to_soup(href)
- img = soup.find('img',alt ="Digital editions of The Australian")
+ img = soup.find('img',alt ="AUS HP promo digital2")
print img
if img :
cover_url = img['src']
-
+
return cover_url
diff --git a/resources/recipes/time_magazine.recipe b/resources/recipes/time_magazine.recipe
index c6aeb59a45..7605a0bd59 100644
--- a/resources/recipes/time_magazine.recipe
+++ b/resources/recipes/time_magazine.recipe
@@ -16,6 +16,7 @@ class Time(BasicNewsRecipe):
encoding = 'utf-8'
no_stylesheets = True
language = 'en'
+ remove_javascript = True
extra_css = ''' h1 {font-family:Arial,Sans-serif;}
h2 {font-family:Arial,Sans-serif;}
@@ -31,14 +32,8 @@ class Time(BasicNewsRecipe):
.credit{font-family:georgia,serif; font-size:x-small;color:#999999;}
a:link{color:#CC0000;}
'''
-
- # remove_tags_before = dict(id="artHd")
- # remove_tags_after = {'class':"ltCol"}
- # remove_tags = [
- # {'class':['articleTools', 'enlarge', 'search','socialtools','blogtools','moretools','page','nextUp','next','subnav','RSS','line2','first','ybuzz','articlePagination','chiclets','imgcont','createListLink','rlinks','tabsWrap','pagination']},
- # {'id':['quigoArticle', 'contentTools', 'articleSideBar', 'header', 'navTop','articleTools','feedmodule','feedmodule3','promos','footer','linksFooter','timeArchive','belt','relatedStories','packages','Features']},
- # {'target':'_blank'},
- # ]
+
+
keep_only_tags = [ dict(name ="div",attrs = {"id" :["article",]}) ,
dict(name ="div",attrs = {"class" :["artHd","artTxt","photoBkt","vertPhoto","image","copy"]}) ,]
@@ -50,6 +45,8 @@ class Time(BasicNewsRecipe):
recursions = 1
match_regexps = [r'/[0-9,]+-(2|3|4|5|6|7|8|9)(,\d+){0,1}.html']
+ preprocess_regexps = [(re.compile(
+ r''), lambda m:'')]
def parse_index(self):
soup = self.index_to_soup('http://www.time.com/time/magazine')
@@ -75,13 +72,19 @@ class Time(BasicNewsRecipe):
return feeds
def find_articles(self, seched):
- for a in seched.findNextSiblings('a', href=True, attrs={'class':'toc_hed'}):
- yield {
- 'title' : self.tag_to_string(a),
- 'url' : 'http://www.time.com'+a['href'],
- 'date' : '',
- 'description' : self.article_description(a)
- }
+ articles = []
+ for a in seched.findNextSiblings( attrs={'class':['toc_hed','rule2']}):
+ if a.name in "div":
+ break
+ else:
+ yield {
+ 'title' : self.tag_to_string(a),
+ 'url' : 'http://www.time.com'+a['href'],
+ 'date' : '',
+ 'description' : self.article_description(a)
+ }
+
+
def article_description(self, a):
ans = []
diff --git a/setup/check.py b/setup/check.py
index 86df693b68..fa7ab9d111 100644
--- a/setup/check.py
+++ b/setup/check.py
@@ -75,7 +75,13 @@ class Check(Command):
raise SystemExit(1)
cache[f] = mtime
cPickle.dump(cache, open(self.CACHE, 'wb'), -1)
-
+ wn_path = os.path.expanduser('~/work/servers/src/calibre_servers/main')
+ if os.path.exists(wn_path):
+ sys.path.insert(0, wn_path)
+ self.info('\tChecking Changelog...')
+ import whats_new
+ whats_new.test()
+ sys.path.remove(wn_path)
def report_errors(self, errors):
for err in errors:
diff --git a/setup/commands.py b/setup/commands.py
index 650d88b5cd..d5687bb1d5 100644
--- a/setup/commands.py
+++ b/setup/commands.py
@@ -14,7 +14,7 @@ __all__ = [
'resources',
'check',
'sdist',
- 'manual', 'tag_release', 'upload_rss',
+ 'manual', 'tag_release',
'pypi_register', 'pypi_upload', 'upload_to_server',
'upload_user_manual', 'upload_to_mobileread', 'upload_demo',
'upload_to_sourceforge', 'upload_to_google_code',
@@ -49,11 +49,10 @@ check = Check()
from setup.resources import Resources
resources = Resources()
-from setup.publish import Manual, TagRelease, UploadRss, Stage1, Stage2, \
+from setup.publish import Manual, TagRelease, Stage1, Stage2, \
Stage3, Stage4, Publish
manual = Manual()
tag_release = TagRelease()
-upload_rss = UploadRss()
stage1 = Stage1()
stage2 = Stage2()
stage3 = Stage3()
diff --git a/setup/installer/osx/app/main.py b/setup/installer/osx/app/main.py
index d023dbcf00..e1819c9bfc 100644
--- a/setup/installer/osx/app/main.py
+++ b/setup/installer/osx/app/main.py
@@ -336,7 +336,7 @@ class Py2App(object):
NSAppleScriptEnabled=False,
NSHumanReadableCopyright='Copyright 2008, Kovid Goyal',
CFBundleGetInfoString=('calibre, an E-book management '
- 'application. Visit http://calibre.kovidgoyal.net for details.'),
+ 'application. Visit http://calibre-ebook.com for details.'),
CFBundleIconFile='library.icns',
LSMultipleInstancesProhibited=True,
LSEnvironment=env
diff --git a/setup/installer/osx/freeze.py b/setup/installer/osx/freeze.py
index c62d9f7154..89e2945fc7 100644
--- a/setup/installer/osx/freeze.py
+++ b/setup/installer/osx/freeze.py
@@ -404,7 +404,7 @@ def main():
'packages' : ['PIL', 'Authorization', 'lxml', 'dns'],
'excludes' : ['IPython', 'PyQt4.uic.port_v3.proxy_base'],
'plist' : { 'CFBundleGetInfoString' : '''calibre, an E-book management application.'''
- ''' Visit http://calibre.kovidgoyal.net for details.''',
+ ''' Visit http://calibre-ebook.com for details.''',
'CFBundleIdentifier':'net.kovidgoyal.calibre',
'CFBundleShortVersionString':VERSION,
'CFBundleVersion':APPNAME + ' ' + VERSION,
diff --git a/setup/installer/windows/wix-template.xml b/setup/installer/windows/wix-template.xml
index 1fa59ca07c..26394fe5b9 100644
--- a/setup/installer/windows/wix-template.xml
+++ b/setup/installer/windows/wix-template.xml
@@ -61,10 +61,10 @@
WorkingDirectory="APPLICATIONROOTDIRECTORY" />
+ Target="http://calibre-ebook.com/user_manual"/>
+ Target="http://calibre-ebook.com/get-involved"/>
diff --git a/setup/publish.py b/setup/publish.py
index bc42b07346..599c881be3 100644
--- a/setup/publish.py
+++ b/setup/publish.py
@@ -6,8 +6,7 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal '
__docformat__ = 'restructuredtext en'
-import sys, os, shutil, subprocess, re, time, glob
-from datetime import datetime
+import os, shutil, subprocess, glob
from setup import Command, __appname__, __version__
@@ -43,7 +42,7 @@ class Stage2(Command):
class Stage3(Command):
description = 'Stage 3 of the publish process'
- sub_commands = ['upload_rss', 'upload_user_manual', 'upload_demo', 'sdist',
+ sub_commands = ['upload_user_manual', 'upload_demo', 'sdist',
'upload_to_google_code', 'tag_release', 'upload_to_server',
'upload_to_sourceforge', 'upload_to_mobileread',
]
@@ -99,76 +98,4 @@ class TagRelease(Command):
subprocess.check_call(('bzr tag '+__version__).split())
subprocess.check_call('bzr commit --unchanged -m'.split() + ['IGN:Tag release'])
-try:
- class UploadRss(Command):
- description = 'Generate and upload a RSS feed of calibre releases'
-
- from bzrlib import log as blog
-
- class ChangelogFormatter(blog.LogFormatter):
- supports_tags = True
- supports_merge_revisions = False
- _show_advice = False
-
- def __init__(self, num_of_versions=20):
- sys.path.insert(0, os.path.join(Command.SRC, 'calibre', 'utils'))
- from rss_gen import RSS2
- self.num_of_versions = num_of_versions
- self.rss = RSS2(
- title = 'calibre releases',
- link = 'http://calibre.kovidgoyal.net/wiki/Changelog',
- description = 'Latest release of calibre',
- lastBuildDate = datetime.utcnow()
- )
- self.current_entry = None
-
- def log_revision(self, r):
- from rss_gen import RSSItem, Guid
- if len(self.rss.items) > self.num_of_versions-1:
- return
- msg = r.rev.message
- match = re.match(r'version\s+(\d+\.\d+.\d+)', msg)
-
- if match:
- if self.current_entry is not None:
- mkup = ''
- self.current_entry.description = mkup%(''.join(
- self.current_entry.description))
- if match.group(1) == '0.5.14':
- self.current_entry.description = \
- ''''''
- self.rss.items.append(self.current_entry)
- timestamp = r.rev.timezone + r.rev.timestamp
- self.current_entry = RSSItem(
- title = 'calibre %s released'%match.group(1),
- link = 'http://calibre.kovidgoyal.net/download',
- guid = Guid(match.group(), False),
- pubDate = datetime(*time.gmtime(timestamp)[:6]),
- description = []
- )
- elif self.current_entry is not None:
- if re.search(r'[a-zA-Z]', msg) and len(msg.strip()) > 5:
- if 'translation' not in msg and not msg.startswith('IGN'):
- msg = msg.replace('<', '<').replace('>', '>')
- msg = re.sub('#(\d+)', r'#\1',
- msg)
-
- self.current_entry.description.append(
- '%s'%msg.strip())
-
-
- def run(self, opts):
- from bzrlib import log, branch
- bzr_path = os.path.expanduser('~/work/calibre')
- b = branch.Branch.open(bzr_path)
- lf = UploadRss.ChangelogFormatter()
- self.info('\tGenerating bzr log...')
- log.show_log(b, lf)
- lf.rss.write_xml(open('/tmp/releases.xml', 'wb'))
- self.info('\tUploading RSS to server...')
- subprocess.check_call('scp /tmp/releases.xml divok:/var/www/calibre.kovidgoyal.net/htdocs/downloads'.split())
-except ImportError:
- class UploadRss(Command):
- description = 'You need bzr installed to use this command'
diff --git a/setup/pypi.py b/setup/pypi.py
index 7c5d1a54d5..d7d8d038ef 100644
--- a/setup/pypi.py
+++ b/setup/pypi.py
@@ -18,7 +18,7 @@ class Metadata(object):
version = __version__
author = 'Kovid Goyal'
author_email = 'kovid@kovidgoyal.net'
- url = 'http://calibre.kovidgoyal.net'
+ url = 'http://calibre-ebook.com'
description = 'E-book management application.'
long_description = open('README', 'rb').read()
license = 'GPL'
diff --git a/setup/upload.py b/setup/upload.py
index 03ed9a9f5c..b380dfdb1f 100644
--- a/setup/upload.py
+++ b/setup/upload.py
@@ -12,10 +12,9 @@ from tempfile import NamedTemporaryFile
from setup import Command, __version__, installer_name, __appname__
-PREFIX = "/var/www/calibre.kovidgoyal.net"
+PREFIX = "/var/www/calibre-ebook.com"
DOWNLOADS = PREFIX+"/htdocs/downloads"
BETAS = DOWNLOADS +'/betas'
-DOCS = PREFIX+"/htdocs/apidocs"
USER_MANUAL = PREFIX+'/htdocs/user_manual'
HTML2LRF = "calibre/ebooks/lrf/html/demo"
TXT2LRF = "src/calibre/ebooks/lrf/txt/demo"
@@ -116,6 +115,9 @@ class UploadToGoogleCode(Command):
def delete_old_files(self):
self.info('Deleting old files from Google Code...')
for fname in self.old_files:
+ ext = fname.rpartition('.')[-1]
+ if ext in ('flv', 'mp4', 'ogg', 'avi'):
+ continue
self.info('\tDeleting', fname)
self.br.open('http://code.google.com/p/calibre-ebook/downloads/delete?name=%s'%fname)
self.br.select_form(predicate=lambda x: 'delete.do' in x.action)
@@ -328,8 +330,6 @@ class UploadToServer(Command):
shell=True)
check_call('scp dist/calibre-*.tar.gz.asc divok:%s/signatures/'%DOWNLOADS,
shell=True)
- check_call('ssh divok bzr update /var/www/calibre.kovidgoyal.net/calibre/',
- shell=True)
check_call('ssh divok bzr update /usr/local/calibre',
shell=True)
check_call('''ssh divok echo %s \\> %s/latest_version'''\
diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py
index 45a9bd29d1..02bc0b621f 100644
--- a/src/calibre/customize/builtins.py
+++ b/src/calibre/customize/builtins.py
@@ -433,9 +433,9 @@ plugins += [
KINDLE,
KINDLE2,
KINDLE_DX,
- PRS500,
PRS505,
PRS700,
+ PRS500,
ANDROID,
CYBOOK_OPUS,
COOL_ER,
diff --git a/src/calibre/devices/android/driver.py b/src/calibre/devices/android/driver.py
index bb925c4103..2fc78bbc18 100644
--- a/src/calibre/devices/android/driver.py
+++ b/src/calibre/devices/android/driver.py
@@ -20,7 +20,7 @@ class ANDROID(USBMS):
VENDOR_ID = [
0x0bb4,
]
- PRODUCT_ID = [0x0c02]
+ PRODUCT_ID = [0x0c02, 0x0c01]
BCD = [0x100]
EBOOK_DIR_MAIN = 'wordplayer/calibretransfer'
diff --git a/src/calibre/devices/eb600/driver.py b/src/calibre/devices/eb600/driver.py
index 68d3243c12..9f6b3299d5 100644
--- a/src/calibre/devices/eb600/driver.py
+++ b/src/calibre/devices/eb600/driver.py
@@ -92,6 +92,7 @@ class POCKETBOOK360(EB600):
VENDOR_NAME = 'PHILIPS'
WINDOWS_MAIN_MEM = 'MASS_STORGE'
+ WINDOWS_CARD_A_MEM = 'MASS_STORAGE'
OSX_MAIN_MEM = 'Philips Mass Storge Media'
OSX_CARD_A_MEM = 'Philips Mass Storge Media'
diff --git a/src/calibre/devices/kindle/driver.py b/src/calibre/devices/kindle/driver.py
index 83f8d064fe..054e0b4c76 100644
--- a/src/calibre/devices/kindle/driver.py
+++ b/src/calibre/devices/kindle/driver.py
@@ -64,21 +64,17 @@ class KINDLE2(KINDLE):
name = 'Kindle 2 Device Interface'
description = _('Communicate with the Kindle 2 eBook reader.')
- author = _('John Schember')
- supported_platforms = ['windows', 'osx', 'linux']
+ FORMATS = KINDLE.FORMATS + ['pdf']
PRODUCT_ID = [0x0002]
BCD = [0x0100]
-class KINDLE_DX(KINDLE):
+class KINDLE_DX(KINDLE2):
name = 'Kindle DX Device Interface'
- description = _('Communicate with the Kindle 2 eBook reader.')
- author = _('John Schember')
- supported_platforms = ['windows', 'osx', 'linux']
+ description = _('Communicate with the Kindle DX eBook reader.')
- FORMATS = ['azw', 'mobi', 'prc', 'azw1', 'tpz', 'pdf', 'txt']
PRODUCT_ID = [0x0003]
BCD = [0x0100]
diff --git a/src/calibre/devices/prs505/driver.py b/src/calibre/devices/prs505/driver.py
index 58ad12c078..55a3f31d46 100644
--- a/src/calibre/devices/prs505/driver.py
+++ b/src/calibre/devices/prs505/driver.py
@@ -23,24 +23,24 @@ class PRS505(CLI, Device):
name = 'PRS-300/505 Device Interface'
gui_name = 'SONY Pocket Edition'
- description = _('Communicate with the Sony PRS-300/505 eBook reader.')
+ description = _('Communicate with the Sony PRS-300/505/500 eBook reader.')
author = _('Kovid Goyal and John Schember')
supported_platforms = ['windows', 'osx', 'linux']
FORMATS = ['epub', 'lrf', 'lrx', 'rtf', 'pdf', 'txt']
VENDOR_ID = [0x054c] #: SONY Vendor Id
- PRODUCT_ID = [0x031e] #: Product Id for the PRS 300 and 505
- BCD = [0x229, 0x1000]
+ PRODUCT_ID = [0x031e] #: Product Id for the PRS 300/505/new 500
+ BCD = [0x229, 0x1000, 0x22a]
VENDOR_NAME = 'SONY'
- WINDOWS_MAIN_MEM = re.compile('PRS-(505|300)')
- WINDOWS_CARD_A_MEM = re.compile(r'PRS-505/\S+:MS')
- WINDOWS_CARD_B_MEM = re.compile(r'PRS-505/\S+:SD')
+ WINDOWS_MAIN_MEM = re.compile('PRS-(505|300|500)')
+ WINDOWS_CARD_A_MEM = re.compile(r'PRS-(505|500)/\S+:MS')
+ WINDOWS_CARD_B_MEM = re.compile(r'PRS-(505|500)/\S+:SD')
- OSX_MAIN_MEM = re.compile(r'Sony PRS-(((505|300)/[^:]+)|(300)) Media')
- OSX_CARD_A_MEM = re.compile(r'Sony PRS-505/[^:]+:MS Media')
- OSX_CARD_B_MEM = re.compile(r'Sony PRS-505/[^:]+:SD Media')
+ OSX_MAIN_MEM = re.compile(r'Sony PRS-(((505|300|500)/[^:]+)|(300)) Media')
+ OSX_CARD_A_MEM = re.compile(r'Sony PRS-(505|500)/[^:]+:MS Media')
+ OSX_CARD_B_MEM = re.compile(r'Sony PRS-(505|500)/[^:]+:SD Media')
MAIN_MEMORY_VOLUME_LABEL = 'Sony Reader Main Memory'
STORAGE_CARD_VOLUME_LABEL = 'Sony Reader Storage Card'
@@ -198,3 +198,5 @@ class PRS505(CLI, Device):
write_card_prefix(self._card_b_prefix, 2)
self.report_progress(1.0, _('Sending metadata to device...'))
+
+
diff --git a/src/calibre/ebooks/conversion/cli.py b/src/calibre/ebooks/conversion/cli.py
index 178561fcb5..e319104562 100644
--- a/src/calibre/ebooks/conversion/cli.py
+++ b/src/calibre/ebooks/conversion/cli.py
@@ -40,7 +40,7 @@ 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
-''') + 'http://calibre.kovidgoyal.net/user_manual/conversion.html'
+''') + 'http://calibre-ebook.com/user_manual/conversion.html'
def print_help(parser, log):
help = parser.format_help().encode(preferred_encoding, 'replace')
diff --git a/src/calibre/ebooks/lrf/html/demo/demo.html b/src/calibre/ebooks/lrf/html/demo/demo.html
index 8a43b50708..7d2f783ccc 100644
--- a/src/calibre/ebooks/lrf/html/demo/demo.html
+++ b/src/calibre/ebooks/lrf/html/demo/demo.html
@@ -11,7 +11,7 @@
Demo of html2lrf
- This document contains a demonstration of the capabilities of html2lrf, the HTML to LRF converter from calibre. To obtain calibre visit
http://calibre.kovidgoyal.net
+ This document contains a demonstration of the capabilities of html2lrf, the HTML to LRF converter from calibre. To obtain calibre visit
http://calibre-ebook.com
Table of Contents
diff --git a/src/calibre/ebooks/odt/input.py b/src/calibre/ebooks/odt/input.py
index f83cd34760..1184148e80 100644
--- a/src/calibre/ebooks/odt/input.py
+++ b/src/calibre/ebooks/odt/input.py
@@ -74,10 +74,18 @@ class ODTInput(InputFormatPlugin):
# about them
from calibre.ebooks.oeb.base import XPath, XHTML
path = XPath('//h:p/h:div')
+ path2 = XPath('//h:div[@style]/h:img[@style]')
for item in oeb.spine:
root = item.data
if not hasattr(root, 'xpath'): continue
for div in path(root):
div.getparent().tag = XHTML('div')
+ # This construct doesn't render well in HTML
+ for img in path2(root):
+ div = img.getparent()
+ if 'position:relative' in div.attrib['style'] and len(div) == 1 \
+ and 'img' in div[0].tag:
+ del div.attrib['style']
+
diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py
index 77cef0d22c..05d4cbb256 100644
--- a/src/calibre/ebooks/oeb/base.py
+++ b/src/calibre/ebooks/oeb/base.py
@@ -849,7 +849,8 @@ class Manifest(object):
try:
data = etree.fromstring(data)
except:
- data=data.replace(':=', '=').replace(':>', '>')
+ data = data.replace(':=', '=').replace(':>', '>')
+ data = data.replace('', '')
try:
data = etree.fromstring(data)
except etree.XMLSyntaxError:
diff --git a/src/calibre/ebooks/pml/pmlconverter.py b/src/calibre/ebooks/pml/pmlconverter.py
index cd5bafa260..e495c24042 100644
--- a/src/calibre/ebooks/pml/pmlconverter.py
+++ b/src/calibre/ebooks/pml/pmlconverter.py
@@ -143,7 +143,7 @@ class PML_HTMLizer(object):
pml = re.sub(r'(?mus)^[ ]*(?=.)', '', pml)
pml = re.sub(r'(?mus)(?<=.)[ ]*$', '', pml)
pml = re.sub(r'(?mus)^[ ]*$', '', pml)
-
+
# Footnotes and Sidebars
pml = re.sub(r'(?mus).+?)">\s*(?P.*?)\s*', lambda match: '\\FN="fns-%s"%s\\FN' % (match.group('target'), match.group('text')) if match.group('text') else '', pml)
pml = re.sub(r'(?mus).+?)">\s*(?P.*?)\s*', lambda match: '\\SB="fns-%s"%s\\SB' % (match.group('target'), match.group('text')) if match.group('text') else '', pml)
@@ -230,13 +230,13 @@ class PML_HTMLizer(object):
elif code in self.BLOCK_STATES:
text = self.process_code_block(code, stream, pre)
else:
- text = self.process_code_simple(code)
+ text = self.process_code_simple(code, stream)
self.state[code][0] = not self.state[code][0]
return text
- def process_code_simple(self, code):
+ def process_code_simple(self, code, stream):
text = u''
if self.state[code][0]:
diff --git a/src/calibre/gui2/convert/font_key.ui b/src/calibre/gui2/convert/font_key.ui
index 13daeb360d..41d355b9c6 100644
--- a/src/calibre/gui2/convert/font_key.ui
+++ b/src/calibre/gui2/convert/font_key.ui
@@ -33,7 +33,7 @@
<p>This wizard will help you choose an appropriate font size key for your needs. Just enter the base font size of the input document and then enter an input font size. The wizard will display what font size it will be mapped to, by the font rescaling algorithm. You can adjust the algorithm by adjusting the output base font size and font key below. When you find values suitable for you, click OK.</p>
<p>By default, if the output base font size is zero and/or no font size key is specified, calibre will use the values from the current Output Profile. </p>
-<p>See the <a href="http://calibre.kovidgoyal.net/user_manual/conversion.html#font-size-rescaling">User Manual</a> for a discussion of how font size rescaling works.</p>
+<p>See the <a href="http://calibre-ebook.com/user_manual/conversion.html#font-size-rescaling">User Manual</a> for a discussion of how font size rescaling works.</p>
true
diff --git a/src/calibre/gui2/convert/xpath_wizard.ui b/src/calibre/gui2/convert/xpath_wizard.ui
index 6f67312c47..52985653fe 100644
--- a/src/calibre/gui2/convert/xpath_wizard.ui
+++ b/src/calibre/gui2/convert/xpath_wizard.ui
@@ -127,7 +127,7 @@
-
- <p>For example, to match all h2 tags that have class="chapter", set tag to <i>h2</i>, attribute to <i>class</i> and value to <i>chapter</i>.</p><p>Leaving attribute blank will match any attribute and leaving value blank will match any value. Setting tag to * will match any tag.</p><p>To learn more advanced usage of XPath see the <a href="http://calibre.kovidgoyal.net/user_manual/xpath.html">XPath Tutorial</a>.
+ <p>For example, to match all h2 tags that have class="chapter", set tag to <i>h2</i>, attribute to <i>class</i> and value to <i>chapter</i>.</p><p>Leaving attribute blank will match any attribute and leaving value blank will match any value. Setting tag to * will match any tag.</p><p>To learn more advanced usage of XPath see the <a href="http://calibre-ebook.com/user_manual/xpath.html">XPath Tutorial</a>.
true
diff --git a/src/calibre/gui2/dialogs/search.ui b/src/calibre/gui2/dialogs/search.ui
index 5c28807bac..bbd7411583 100644
--- a/src/calibre/gui2/dialogs/search.ui
+++ b/src/calibre/gui2/dialogs/search.ui
@@ -112,7 +112,7 @@
- See the <a href="http://calibre.kovidgoyal.net/user_manual/gui.html#the-search-interface">User Manual</a> for more help
+ See the <a href="http://calibre-ebook.com/user_manual/gui.html#the-search-interface">User Manual</a> for more help
true
diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py
index 9068fdb6bd..a95572083e 100644
--- a/src/calibre/gui2/main.py
+++ b/src/calibre/gui2/main.py
@@ -214,7 +214,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
####################### Vanity ########################
self.vanity_template = _('
For help see the: User Manual'
- '
')%'http://calibre.kovidgoyal.net/user_manual'
+ '
')%'http://calibre-ebook.com/user_manual'
self.vanity_template += _('%s: %s by Kovid Goyal '
'%%(version)s
%%(device)s
')%(__appname__, __version__)
self.latest_version = ' '
@@ -1721,12 +1721,13 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
Donate to support calibre
-
+
Calibre %s
%s