Sync to trunk.

This commit is contained in:
John Schember 2009-11-29 20:31:01 -05:00
commit 0c8fdbd647
75 changed files with 8846 additions and 6901 deletions

View File

@ -352,7 +352,7 @@ License: other
Liberation Fonts
-----------------
calibre includes a copy of the liberation fonts, available from
https://calibre.kovidgoyal.net/downloads/liberation-fonts
https://calibre-ebook.com/downloads/liberation-fonts
BSD License (for all the BSD licensed code indicated above)
-----------------------------------------------------------

172
Changelog.yaml Normal file
View File

@ -0,0 +1,172 @@
# Each release can have new features and bug fixes. Each of which
# must have a title and can optionally have linked tickets and a description.
# In addition they can have a type field which defaults to minor, but should be major
# for important features/bug fixes.
# Also, each release can have new and improved recipes.
- version: 0.6.25
date: 2009-11-30
new features:
- title: Add option to swap title and author in the Bulk metadata dialog
tickets: [3885]
- title: Make the metadata download plugins customizable
- title: Various improvements to the conversion of PDB/PML books with an all new state machine based parser
- title: Driver for upgraded SONY PRS 500
- title: Full support for PocketBook 360 with SD card
- title: "ODT Input: Reflow positioned images"
tickets: [4060]
- title: Allow custom new recipes to reverse article order in feeds
tickets: [4095]
- title: "Conversion pipeline: Add option to control the inserted paragraph indent when using the remove blank line between paragraphs option"
- title: When reading metadata from PDf files, look for the ISBN in the file text.
tickets: [3013]
- title: Periodically check for updates to calibre instead of just at startup
tickets: [4040]
bug fixes:
- title: Reorganize Dutch language news sources into Belgium and Netherlands categories
tickets: [4098]
- title: Fix bad markup in some New York Times articles causing download to fail
tickets: [4032]
- title: Fix recipe for Glasgow Herald
- title: Fixed recipe for The Australian
- title: Add PDF to list of supported formats for the Kindle 2
new recipes:
- title: The Economist (no subscription required)
author: Kovid Goyal
- title: Sports Illustrated1
author: kwetal
- title: Levante
author: kwetal
- title: ncrnext
author: kwetal
improved recipes:
- The Philadelphia Inquirer
- Harpers
- Our Daily Bread
- Sydney Morning Herald
- version: 0.6.24
date: 2009-11-16
new features:
- title: Add option to swap title and author in the Bulk metadata dialog
tickets: [3885]
- title: Add option to download only social metadata
tickets: [4015]
- title: Update bundled odfpy library to 0.9.2 for improved conversion of ODT files.
- title: Output resolved conversion options in conversion log, for easier debugging.
- title: Add option to Bulk conversion dialog to not use per-book settings from a previous conversion
bug fixes:
- title: "Device drivers: Ignore files on the device when there is a file system/file name encoding error"
description: >
Sometimes, the presence of files on the e-book device that have special characters in the file name
would cause calibre to throw an error when scanning the device for books. Now, calibre will simply
ignore the files whose names it cannot decode.
- title: Fix various bugs in the downloading of social metadata in bulk
tickets: [4028, 4022]
- title: Do not URL encode paths to files in the XML output of calibredb list
description: Stanza on the iPhone could not handle URL encoded paths
- title: Fix rendering of stars in rating column in the library view
tickets: [3944]
- title: Fix PML parsing changes introduced in 0.6.22 as they break PDB eReader input badly.
- title: "Conversion pipeline: Respect UTF-8/32 BOM mark when decoding files in addition to UTF-16 BOM."
tickets: [4025]
- title: Restore all sections to Guardian newspaper download
- title: "Social metadata download: If the user specifies that they dont want social metadata, don't get tags from the basic metadata sources either"
new recipes:
- title: The Havard Business Review
author: Kovid Goyal
- title: Fokke en Sukke
author: kwetal
improved recipes:
- The Philadelphia Inquirer
- version: 0.6.22
date: 2009-11-13
new features:
- title: Support downloading of social metadata (ratings/tags/reviews etc.)
description: >
calibre is now able to download social metadata like tags/rating/reviews etc.,
in addition to normal metadata and covers. Currently it uses Amazon as the only
source for social metadata, but the download system supports plugins for the
addition of more sources in the future.
type: major
tickets: [2860]
- title: Convert metadata download system to plugins, with builtin plugins for isbndb.com, Google Books and Amazon
- title: PML metadata reader
- title: "PML Input: Fix handling of images and various other improvements"
bug fixes:
- title: Fix NYT Top stories, Barrons, New Scientist and Irish Times recipes
tickets: [4009, 3964, 3972, 3987]
- title: "FB2 Output: Handle large paragraphs"
tickets: [3941]
- title: "Bulk metadata download: Don't fail on downloading all remaining covers if there is an error downloading a single cover in the list"
- title: Populate site_customization for Input plugins
tickets: [3957]
- title: Fix news download scheduler raising an error for scheduled custom recipe that is subsequently deleted
tickets: [4010]
new recipes:
- title: NPR
author: onyxrev
- title: Welt Online
author: Oliver Niesner
- title: An Druma Mor
author: "David O'Callaghan"
improved recipes:
- Critica Digital
- Infobae
- Spiegel International

4
README
View File

@ -4,10 +4,10 @@ devices. It can go out to the internet and fetch metadata for your books. \
It can download newspapers and convert them into e-books for convenient \
reading. It is cross platform, running on Linux, Windows and OS X.
For screenshots: https://calibre.kovidgoyal.net/wiki/Screenshots
For screenshots: https://calibre-ebook.com/demo
For installation/usage instructions please see
http://calibre.kovidgoyal.net
http://calibre-ebook.com
For source code access:
bzr branch lp:calibre

View File

@ -7,11 +7,11 @@
<script type="text/javascript" src="/static/date.js" charset="utf-8"></script>
<script type="text/javascript" src="/static/jquery.js" charset="utf-8"></script>
<script type="text/javascript" src="/static/gui.js" charset="utf-8"></script>
<link rel="icon" href="http://calibre.kovidgoyal.net/chrome/site/favicon.ico" type="image/x-icon" />
<link rel="icon" href="http://calibre-ebook.com/favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="banner">
<a style="border: 0pt" href="http://calibre.kovidgoyal.net" alt="calibre" title="calibre"><img style="border:0pt" src="/static/calibre.png" alt="calibre" /></a>
<a style="border: 0pt" href="http://calibre-ebook.com" alt="calibre" title="calibre"><img style="border:0pt" src="/static/calibre.png" alt="calibre" /></a>
</div>
<div id="search_box">

View File

@ -9,22 +9,22 @@ from calibre.web.feeds.news import BasicNewsRecipe
class DeStandaard(BasicNewsRecipe):
title = u'De Standaard'
__author__ = u'Darko Miletic'
language = 'nl'
language = 'nl_BE'
description = u'News from Belgium'
description = u'News from Belgium'
oldest_article = 7
max_articles_per_feed = 100
no_stylesheets = True
use_embedded_content = False
encoding = 'utf-8'
keep_only_tags = [dict(name='div' , attrs={'id':['intro','continued']})]
feeds = [(u'De Standaard Online', u'http://feeds.feedburner.com/dso-front')]
def get_article_url(self, article):
return article.get('guid', None)
def print_version(self, url):
return url.replace('/Detail.aspx?','/PrintArtikel.aspx?')

View File

@ -19,7 +19,7 @@ class DeGentenaarOnline(BasicNewsRecipe):
no_stylesheets = True
use_embedded_content = False
encoding = 'utf-8'
language = 'nl'
language = 'nl_BE'
lang = 'nl-BE'
direction = 'ltr'

View File

@ -11,9 +11,9 @@ from calibre.web.feeds.news import BasicNewsRecipe
class DeMorganBe(BasicNewsRecipe):
title = u'De Morgen'
__author__ = u'Darko Miletic'
description = u'News from Belgium'
description = u'News from Belgium'
oldest_article = 7
language = 'nl'
language = 'nl_BE'
max_articles_per_feed = 100
no_stylesheets = True
@ -21,7 +21,7 @@ class DeMorganBe(BasicNewsRecipe):
keep_only_tags = [dict(name='div' , attrs={'class':'art_box2'})]
feeds = [
feeds = [
(u'Nieuws' , u'http://www.demorgen.be/nieuws/rss.xml' )
,(u'De Gedachte' , u'http://www.demorgen.be/degedachte/rss.xml' )
,(u'Financiele morgen' , u'http://www.demorgen.be/financielemorgen/rss.xml')
@ -29,5 +29,5 @@ class DeMorganBe(BasicNewsRecipe):
,(u'Sport' , u'http://www.demorgen.be/sport/rss.xml' )
,(u'Bis' , u'http://www.demorgen.be/bis/rss.xml' )
,(u'Magazine' , u'http://www.demorgen.be/magazine/rss.xml' )
,(u'De stand der dingen', u'http://www.demorgen.be/standderdingen/rss.xml' )
,(u'De stand der dingen', u'http://www.demorgen.be/standderdingen/rss.xml' )
]

View File

@ -0,0 +1,68 @@
from calibre.web.feeds.news import BasicNewsRecipe
import time
from datetime import datetime
from lxml import html
class Economist(BasicNewsRecipe):
title = 'The Economist (free)'
language = 'en'
__author__ = "Kovid Goyal"
description = ('Global news and current affairs from a European perspective.'
' Much slower than the subscription based version.')
oldest_article = 6.5
cover_url = 'http://www.economist.com/images/covers/currentcovereu_large.jpg'
remove_tags = [dict(name=['script', 'noscript', 'title'])]
remove_tags_before = dict(name=lambda tag: tag.name=='title' and tag.parent.name=='body')
def parse_index(self):
from calibre.web.feeds.feedparser import parse
raw = self.index_to_soup(
'http://feeds.feedburner.com/economist/full_print_edition',
raw=True)
entries = parse(raw).entries
feeds = {}
for i, item in enumerate(entries):
from calibre.web.feeds import Article
published = time.gmtime(item.get('timestamp', time.time()))
title = item.get('title', _('Untitled article'))
link = item.get('link', None)
description = item.get('description', '')
author = item.get('author', '')
try:
feedtitle, link = self.process_eco_feed_article(link)
self.log('Found print version for article:', title)
except:
self.log.exception('Failed to process article:', title)
continue
a = Article(i, title, link, author, description, published, '')
delta = datetime.utcnow() - a.utctime
if delta.days*24*3600 + delta.seconds > 24*3600*self.oldest_article:
self.log.debug('Skipping article %s (%s) from feed %s as it is too old.'%(title, a.localtime.strftime('%a, %d %b, %Y %H:%M'), title))
continue
article = dict(title=a.title, description=a.text_summary,
date=time.strftime(self.timefmt, a.date), author=a.author, url=a.url)
if feedtitle not in feeds:
feeds[feedtitle] = []
feeds[feedtitle].append(article)
return [(t, a) for t, a in feeds.items()]
def process_eco_feed_article(self, url):
ret = self.browser.open(url)
raw = ret.read()
url = self.browser.geturl().replace('displaystory', 'PrinterFriendly').strip()
root = html.fromstring(raw)
matches = root.xpath('//*[@class = "article-section"]')
feedtitle = 'Miscellaneous'
if matches:
feedtitle = html.tostring(matches[0], method='text',
encoding=unicode)
return feedtitle, url

View File

@ -1,4 +1,3 @@
import re
from calibre.web.feeds.news import BasicNewsRecipe
@ -9,27 +8,22 @@ class GlasgowHerald(BasicNewsRecipe):
no_stylesheets = True
language = 'en_GB'
__author__ = 'McCande'
preprocess_regexps = [ (re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
(r'<center><h3>', lambda match : '<h3>'),
(r'Click here to comment on this story...', lambda match : ''),
(r'<h3>Related links</h3>.*?</head>', lambda match : '</head>'),
]
]
__author__ = 'Kovid Goyal'
keep_only_tags = [dict(attrs={'class':'article'})]
remove_tags = [
dict(id=['pic-nav']),
dict(attrs={'class':['comments-top']})
]
feeds = [
(u'News', u'http://www.theherald.co.uk/news/news/rss.xml'),
(u'Politics', u'http://www.theherald.co.uk/politics/news/rss.xml'),
(u'Features', u'http://www.theherald.co.uk/features/features/rss.xml'),
(u'Business', u'http://www.theherald.co.uk/business/news/rss.xml')]
(u'News', u'http://www.heraldscotland.com/cmlink/1.758'),
(u'Sport', u'http://www.heraldscotland.com/cmlink/1.761'),
(u'Business', u'http://www.heraldscotland.com/cmlink/1.763'),
(u'Life & Style', u'http://www.heraldscotland.com/cmlink/1.770'),
(u'Arts & Entertainment',
u'http://www.heraldscotland.com/cmlink/1.768',),
(u'Columnists', u'http://www.heraldscotland.com/cmlink/1.658574')]
def print_version(self, url):
(beginning,end)=url.split(".var.")
num=end[0:7]
main="http://www.theherald.co.uk/misc/print.php?artid="+num
return main

View File

@ -19,7 +19,7 @@ class GazetvanAntwerpen(BasicNewsRecipe):
no_stylesheets = True
use_embedded_content = False
encoding = 'utf-8'
language = 'nl'
language = 'nl_BE'
lang = 'nl-BE'
direction = 'ltr'

View File

@ -29,7 +29,13 @@ class Harpers(BasicNewsRecipe):
html2epub_options = 'publisher="' + publisher + '"\ncomments="' + description + '"\ntags="' + category + '"\noverride_css=" p {text-indent: 0em; margin-top: 0em; margin-bottom: 0.5em} img {margin-top: 0em; margin-bottom: 0.4em}"'
extra_css = '''
h1{ font-family:georgia ; color:#111111; font-size:large;}
.box-of-helpful{ font-family:arial ; font-size:x-small;}
p{font-family:georgia ;}
.caption{font-family:Verdana,sans-serif;font-size:x-small;color:#666666;}
'''
keep_only_tags = [ dict(name='div', attrs={'id':'cached'}) ]
remove_tags = [
dict(name='table', attrs={'class':['rcnt','rcnt topline']})
@ -38,6 +44,17 @@ class Harpers(BasicNewsRecipe):
feeds = [(u"Harper's Magazine", u'http://www.harpers.org/rss/frontpage-rss20.xml')]
def get_cover_url(self):
cover_url = None
index = 'http://harpers.org/'
soup = self.index_to_soup(index)
link_item = soup.find(name = 'img',attrs= {'class':"cover"})
print link_item
if link_item:
cover_url = 'http://harpers.org' + link_item['src']
print cover_url
return cover_url
def preprocess_html(self, soup):
mcharset = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset=utf-8")])
soup.head.insert(1,mcharset)
@ -47,3 +64,5 @@ class Harpers(BasicNewsRecipe):
del item['xmlns']
return soup

View File

@ -19,7 +19,7 @@ class HLN_be(BasicNewsRecipe):
no_stylesheets = True
use_embedded_content = False
encoding = 'utf-8'
language = 'nl'
language = 'nl_BE'
lang = 'nl-BE'
direction = 'ltr'
@ -39,7 +39,7 @@ class HLN_be(BasicNewsRecipe):
.gen_footnote3{font-size:80%; color: #666666;}
'''
keep_only_tags = [dict(name='div', attrs={'class':'art_box2'})]
remove_tags = [
dict(name=['embed','object'])

View File

@ -19,16 +19,16 @@ class HLN_be(BasicNewsRecipe):
use_embedded_content = False
no_stylesheets = True
encoding = 'utf-8'
language = 'nl'
language = 'nl_BE'
conversion_options = {
conversion_options = {
'comments' : description
,'tags' : category
,'language' : 'nl-NL'
,'publisher' : publisher
}
remove_tags = [dict(name=['form','object','embed'])]
keep_only_tags = [dict(name='div', attrs={'id':'art_box2'})]

View File

@ -1,6 +1,6 @@
__license__ = 'GPL v3'
__copyright__ = '2009 Neil Grogan'
#
#
# Irish Independent Recipe
#
@ -10,7 +10,7 @@ class IrishIndependent(BasicNewsRecipe):
title = u'Irish Independent'
description = 'Irish and World news from Irelands Bestselling Daily Broadsheet'
__author__ = 'Neil Grogan'
language = 'en_UK'
language = 'en_GB'
oldest_article = 7
max_articles_per_feed = 100
remove_tags_before = dict(id='article')
@ -37,7 +37,7 @@ class IrishIndependent(BasicNewsRecipe):
(u'Letters', u'http://www.independent.ie/opinion/letters/rss'),
(u'Weather', u'http://www.independent.ie/weather/rss')
]
# If text only articles are desired
#def print_version(self, url):
# return '%s?service=Print' % url

View File

@ -0,0 +1,68 @@
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import Tag
class LevanteRecipe(BasicNewsRecipe):
__license__ = 'GPL v3'
__author__ = 'kwetal'
version = 1
language = 'es'
description = u'El Mercantil Valenciano'
title = u'Levante'
oldest_article = 2
max_articles_per_feed = 100
encoding = 'latin1'
no_stylesheets = True
remove_javascript = True
# Feeds taken from http://www.levante-emv.com/servicios/rss/rss.jsp?pServicio=rss
# Feed titles are without accented characters for now. Hope to resolve this in the future.
feeds = []
feeds.append((u'Portada Valencia', u'http://www.levante-emv.com/elementosInt/rss/1'))
feeds.append((u'Portada Castello', u'http://www.levante-emv.com/elementosInt/rss/2'))
feeds.append((u'Portada Alacant', u'http://www.levante-emv.com/elementosInt/rss/3'))
feeds.append((u'Lo Mas Leido', u'http://www.levante-emv.com/elementosInt/rss/LoMas'))
feeds.append((u'Seccion al minuto', u'http://www.levante-emv.com/elementosInt/rss/AlMinuto'))
feeds.append((u'Comunidad Valenciana', u'http://www.levante-emv.com/elementosInt/rss/19'))
feeds.append((u'Valencia', u'http://www.levante-emv.com/elementosInt/rss/16'))
feeds.append((u'Castello', u'http://www.levante-emv.com/elementosInt/rss/4'))
feeds.append((u'Alacant', u'http://www.levante-emv.com/elementosInt/rss/17'))
feeds.append((u'Comarcas', u'http://www.levante-emv.com/elementosInt/rss/12'))
feeds.append((u'Espana', u'http://www.levante-emv.com/elementosInt/rss/6'))
feeds.append((u'Internacional', u'http://www.levante-emv.com/elementosInt/rss/7'))
feeds.append((u'Opinion', u'http://www.levante-emv.com/elementosInt/rss/5'))
feeds.append((u'Economia', u'http://www.levante-emv.com/elementosInt/rss/8'))
feeds.append((u'Sociedad', u'http://www.levante-emv.com/elementosInt/rss/9'))
feeds.append((u'Sucesos', u'http://www.levante-emv.com/elementosInt/rss/10'))
feeds.append((u'Deportes', u'http://www.levante-emv.com/elementosInt/rss/11'))
feeds.append((u'Motor', u'http://www.levante-emv.com/elementosInt/rss/31'))
feeds.append((u'Panorama', u'http://www.levante-emv.com/elementosInt/rss/18'))
feeds.append((u'Salud y Vida', u'http://www.levante-emv.com/elementosInt/rss/20'))
feeds.append((u'Ciencia y Salud', u'http://www.levante-emv.com/elementosInt/rss/44'))
feeds.append((u'Ciencia e Investigacion', u'http://www.levante-emv.com/elementosInt/rss/23'))
feeds.append((u'Ensenanza', u'http://www.levante-emv.com/elementosInt/rss/22'))
feeds.append((u'Fiestas y Tradiciones', u'http://www.levante-emv.com/elementosInt/rss/24'))
feeds.append((u'Club Diario', u'http://www.levante-emv.com/elementosInt/rss/26'))
feeds.append((u'Juntos', u'http://www.levante-emv.com/elementosInt/rss/33'))
feeds.append((u'Integrados', u'http://www.levante-emv.com/elementosInt/rss/35'))
feeds.append((u'Agenda', u'http://www.levante-emv.com/elementosInt/rss/36'))
feeds.append((u'Cultura', u'http://www.levante-emv.com/elementosInt/rss/39'))
feeds.append((u'Tecnologia', u'http://www.levante-emv.com/elementosInt/rss/40'))
feeds.append((u'Gente', u'http://www.levante-emv.com/elementosInt/rss/41'))
feeds.append((u'Television', u'http://www.levante-emv.com/elementosInt/rss/42'))
feeds.append((u'Participa', u'http://www.levante-emv.com/elementosInt/rss/45'))
keep_only_tags = [dict(name='div', attrs={'class' : 'noticia_titular'}),
dict(name='div', attrs={'class' : 'subtitulo'}),
dict(name='div', attrs={'id' : 'noticia_texto', 'class' : 'noticia_texto'})]
def preprocess_html(self, soup):
# Nuke some real crappy html
theirHead = soup.head
theirHead.extract()
myHead = Tag(soup, 'head')
soup.insert(0, myHead)
return soup

View File

@ -13,7 +13,6 @@
##
## Version 0.3-2008_2_28
## Based on WIRED.py by David Chen, 2007, and newsweek.py, bbc.py, nytimes.py by Kovid Goyal
## https://calibre.kovidgoyal.net/wiki/UserProfiles
##
## Usage:
## >web2lrf --user-profile nasa.py
@ -40,7 +39,7 @@ class NASA(BasicNewsRecipe):
## Don't grab articles more than 30 days old
oldest_article = 30
preprocess_regexps = [(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
preprocess_regexps = [(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[
## Fix the encoding to UTF-8
(r'<meta http-equiv="Content-Type" content="text/html; charset=(\S+)"', lambda match : match.group().replace(match.group(1), 'UTF-8')),
@ -53,12 +52,12 @@ class NASA(BasicNewsRecipe):
## Correctly embed in-line images by removing the surrounding javascript that will be ignored in the conversion
(r'<a.*?onclick.*?>.*?(<img .*?>)', lambda match: match.group(1),),
## This removes header and footer information from each print version.
(r'<!-- Top Header starts -->.*?<!-- Body starts -->', lambda match : '<New Stuff>'),
(r'<hr align="center" width="200"><p align="center">.*?<!-- Press Release standard text ends -->', lambda match : '<New Stuff>'),
(r'<!-- Top Header starts -->.*?<!---->', lambda match : '<New Stuff>'),
## This removes the "download image" of various sizes from the Image of the day.
(r'<div id="download_image_box_print">.*?<div id="caption_region_print">', lambda match : '<New Stuff>'),

View File

@ -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' : '<p>&nbsp;</p>'}
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('<html><head></head><body></body></html>')
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()

View File

@ -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

View File

@ -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

View File

@ -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')]

View File

@ -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('<html><head></head><body></body></html>')
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

View File

@ -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('<html><head></head><body></body></html>')
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

View File

@ -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

View File

@ -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'<meta .+/>'), 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 = []

View File

@ -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:

View File

@ -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()

View File

@ -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

View File

@ -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,

View File

@ -61,10 +61,10 @@
WorkingDirectory="APPLICATIONROOTDIRECTORY" />
<util:InternetShortcut Id="OnlineDocumentationShortcut"
Name="User Manual" Type="url"
Target="http://calibre.kovidgoyal.net/user_manual"/>
Target="http://calibre-ebook.com/user_manual"/>
<util:InternetShortcut Id="GetInvolvedS"
Name="Get Involved" Type="url"
Target="http://calibre.kovidgoyal.net/wiki/Development"/>
Target="http://calibre-ebook.com/get-involved"/>
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\Microsoft\{app}" Name="start_menu_shortcuts_installed" Type="integer" Value="1" KeyPath="yes"/>

View File

@ -6,8 +6,7 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__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 = '<div><ul>%s</ul></div>'
self.current_entry.description = mkup%(''.join(
self.current_entry.description))
if match.group(1) == '0.5.14':
self.current_entry.description = \
'''<div>See <a href="http://calibre.kovidgoyal.net/new_in_6">New in
6</a></div>'''
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('<', '&lt;').replace('>', '&gt;')
msg = re.sub('#(\d+)', r'<a href="http://calibre.kovidgoyal.net/ticket/\1">#\1</a>',
msg)
self.current_entry.description.append(
'<li>%s</li>'%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'

View File

@ -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'

View File

@ -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'''\

View File

@ -433,9 +433,9 @@ plugins += [
KINDLE,
KINDLE2,
KINDLE_DX,
PRS500,
PRS505,
PRS700,
PRS500,
ANDROID,
CYBOOK_OPUS,
COOL_ER,

View File

@ -20,7 +20,7 @@ class ANDROID(USBMS):
VENDOR_ID = [
0x0bb4,
]
PRODUCT_ID = [0x0c02]
PRODUCT_ID = [0x0c02, 0x0c01]
BCD = [0x100]
EBOOK_DIR_MAIN = 'wordplayer/calibretransfer'

View File

@ -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'

View File

@ -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]

View File

@ -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...'))

View File

@ -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')

View File

@ -11,7 +11,7 @@
</head>
<h1>Demo of <span style='font-family:monospace'>html2lrf</span></h1>
<p>
This document contains a demonstration of the capabilities of <span style='font-family:monospace'>html2lrf</span>, the HTML to LRF converter from <em>calibre.</em> To obtain calibre visit<br/><span style='font:sans-serif'>http://calibre.kovidgoyal.net</span>
This document contains a demonstration of the capabilities of <span style='font-family:monospace'>html2lrf</span>, the HTML to LRF converter from <em>calibre.</em> To obtain calibre visit<br/><span style='font:sans-serif'>http://calibre-ebook.com</span>
</p>
<br/>
<h2 id="toc">Table of Contents</h2>

View File

@ -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']

View File

@ -849,7 +849,8 @@ class Manifest(object):
try:
data = etree.fromstring(data)
except:
data=data.replace(':=', '=').replace(':>', '>')
data = data.replace(':=', '=').replace(':>', '>')
data = data.replace('<http:/>', '')
try:
data = etree.fromstring(data)
except etree.XMLSyntaxError:

View File

@ -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)<footnote\s+id="(?P<target>.+?)">\s*(?P<text>.*?)\s*</footnote>', lambda match: '\\FN="fns-%s"%s\\FN' % (match.group('target'), match.group('text')) if match.group('text') else '', pml)
pml = re.sub(r'(?mus)<sidebar\s+id="(?P<target>.+?)">\s*(?P<text>.*?)\s*</sidebar>', 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]:

View File

@ -33,7 +33,7 @@
<property name="text">
<string>&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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. &lt;/p&gt;
&lt;p&gt;See the &lt;a href=&quot;http://calibre.kovidgoyal.net/user_manual/conversion.html#font-size-rescaling&quot;&gt;User Manual&lt;/a&gt; for a discussion of how font size rescaling works.&lt;/p&gt;</string>
&lt;p&gt;See the &lt;a href=&quot;http://calibre-ebook.com/user_manual/conversion.html#font-size-rescaling&quot;&gt;User Manual&lt;/a&gt; for a discussion of how font size rescaling works.&lt;/p&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>

View File

@ -127,7 +127,7 @@
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>&lt;p&gt;For example, to match all h2 tags that have class=&quot;chapter&quot;, set tag to &lt;i&gt;h2&lt;/i&gt;, attribute to &lt;i&gt;class&lt;/i&gt; and value to &lt;i&gt;chapter&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;Leaving attribute blank will match any attribute and leaving value blank will match any value. Setting tag to * will match any tag.&lt;/p&gt;&lt;p&gt;To learn more advanced usage of XPath see the &lt;a href=&quot;http://calibre.kovidgoyal.net/user_manual/xpath.html&quot;&gt;XPath Tutorial&lt;/a&gt;.</string>
<string>&lt;p&gt;For example, to match all h2 tags that have class=&quot;chapter&quot;, set tag to &lt;i&gt;h2&lt;/i&gt;, attribute to &lt;i&gt;class&lt;/i&gt; and value to &lt;i&gt;chapter&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;Leaving attribute blank will match any attribute and leaving value blank will match any value. Setting tag to * will match any tag.&lt;/p&gt;&lt;p&gt;To learn more advanced usage of XPath see the &lt;a href=&quot;http://calibre-ebook.com/user_manual/xpath.html&quot;&gt;XPath Tutorial&lt;/a&gt;.</string>
</property>
<property name="wordWrap">
<bool>true</bool>

View File

@ -112,7 +112,7 @@
</size>
</property>
<property name="text" >
<string>See the &lt;a href="http://calibre.kovidgoyal.net/user_manual/gui.html#the-search-interface">User Manual&lt;/a> for more help</string>
<string>See the &lt;a href="http://calibre-ebook.com/user_manual/gui.html#the-search-interface">User Manual&lt;/a> for more help</string>
</property>
<property name="openExternalLinks" >
<bool>true</bool>

View File

@ -214,7 +214,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
####################### Vanity ########################
self.vanity_template = _('<p>For help see the: <a href="%s">User Manual</a>'
'<br>')%'http://calibre.kovidgoyal.net/user_manual'
'<br>')%'http://calibre-ebook.com/user_manual'
self.vanity_template += _('<b>%s</b>: %s by <b>Kovid Goyal '
'%%(version)s</b><br>%%(device)s</p>')%(__appname__, __version__)
self.latest_version = ' '
@ -1721,12 +1721,13 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
<title>Donate to support calibre</title>
</head>
<body style="background:white">
<div><a href="http://calibre.kovidgoyal.net"><img style="border:0px" src="http://calibre.kovidgoyal.net/chrome/site/calibre_banner.png" alt="calibre" /></a></div>
<div><a href="http://calibre-ebook.com"><img style="border:0px"
src="file://%s" alt="calibre" /></a></div>
<p>Calibre %s</p>
%s
</body>
</html>
'''%(MSG, BUTTON)
'''%(P('content_server/calibre_banner.png').replace(os.sep, '/'), MSG, BUTTON)
pt = PersistentTemporaryFile('_donate.htm')
pt.write(HTML.encode('utf-8'))
pt.close()
@ -1812,7 +1813,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
def update_found(self, version):
os = 'windows' if iswindows else 'osx' if isosx else 'linux'
url = 'http://%s.kovidgoyal.net/download_%s'%(__appname__, os)
url = 'http://calibre-ebook.com/download_%s'%os
self.latest_version = '<br>' + _('<span style="color:red; font-weight:bold">'
'Latest version: <a href="%s">%s</a></span>')%(url, version)
self.vanity.setText(self.vanity_template%\
@ -1823,10 +1824,10 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
dynamic.get('update to version %s'%version, True):
if question_dialog(self, _('Update available'),
_('%s has been updated to version %s. '
'See the <a href="http://calibre.kovidgoyal.net/wiki/'
'Changelog">new features</a>. Visit the download pa'
'See the <a href="http://calibre-ebook.com/whats-new'
'">new features</a>. Visit the download pa'
'ge?')%(__appname__, version)):
url = 'http://calibre.kovidgoyal.net/download_'+\
url = 'http://calibre-ebook.com/download_'+\
('windows' if iswindows else 'osx' if isosx else 'linux')
QDesktopServices.openUrl(QUrl(url))
dynamic.set('update to version %s'%version, False)

View File

@ -46,7 +46,7 @@
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;h2&gt;Demo videos&lt;/h2&gt;Videos demonstrating the various features of calibre are available &lt;a href=&quot;http://calibre.kovidgoyal.net/downloads/videos/&quot;&gt;online&lt;/a&gt;.</string>
<string>&lt;h2&gt;Demo videos&lt;/h2&gt;Videos demonstrating the various features of calibre are available &lt;a href=&quot;http://calibre-ebook.com/demo&quot;&gt;online&lt;/a&gt;.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -75,7 +75,7 @@
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>&lt;h2&gt;User Manual&lt;/h2&gt;A User Manual is also available &lt;a href=&quot;http://calibre.kovidgoyal.net/user_manual&quot;&gt;online&lt;/a&gt;.</string>
<string>&lt;h2&gt;User Manual&lt;/h2&gt;A User Manual is also available &lt;a href=&quot;http://calibre-ebook.com/user_manual&quot;&gt;online&lt;/a&gt;.</string>
</property>
<property name="wordWrap">
<bool>true</bool>

View File

@ -64,7 +64,7 @@ STANZA_TEMPLATE='''\
<title>calibre Library</title>
<author>
<name>calibre</name>
<uri>http://calibre.kovidgoyal.net</uri>
<uri>http://calibre-ebook.com</uri>
</author>
<id>$id</id>
<updated>${updated.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated>

View File

@ -176,7 +176,7 @@ class LibraryServer(object):
}
</style>
<link rel="icon" href="http://calibre.kovidgoyal.net/chrome/site/favicon.ico" type="image/x-icon" />
<link rel="icon" href="http://calibre-ebook.com/favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="logo">
@ -276,7 +276,7 @@ class LibraryServer(object):
${Markup(next_link)}
<author>
<name>calibre</name>
<uri>http://calibre.kovidgoyal.net</uri>
<uri>http://calibre-ebook.com</uri>
</author>
<subtitle>
${subtitle}
@ -296,7 +296,7 @@ class LibraryServer(object):
<link rel="search" title="Search" type="application/atom+xml" href="/stanza/?search={searchTerms}"/>
<author>
<name>calibre</name>
<uri>http://calibre.kovidgoyal.net</uri>
<uri>http://calibre-ebook.com</uri>
</author>
<subtitle>
${subtitle}

View File

@ -120,7 +120,7 @@ html_copy_source = False
# Output file base name for HTML help builder.
htmlhelp_basename = 'calibredoc'
html_use_opensearch = 'http://calibre.kovidgoyal.net/user_manual'
html_use_opensearch = 'http://calibre-ebook.com/user_manual'
html_show_sphinx = False

View File

@ -54,7 +54,7 @@ That's all. To add this code to |app| as a plugin, simply create a zip file with
zip plugin.zip my_plugin.py
You can download the Hello World plugin from
`helloworld_plugin.zip <http://calibre.kovidgoyal.net/downloads/helloworld_plugin.zip>`_.
`helloworld_plugin.zip <http://calibre-ebook.com/downloads/helloworld_plugin.zip>`_.
Now either use the configuration dialog in |app| GUI to add this zip file as a plugin, or
use the command::

View File

@ -65,7 +65,7 @@ this, make your changes, then run::
bzr send -o my-changes
This will create a :file:`my-changes` file in the current directory,
simply attach that to a ticket on the |app| `bug tracker <http://calibre.kovidgoyal.net/newticket>`_.
simply attach that to a ticket on the |app| `bug tracker <http://bugs.calibre-ebook.com/newticket>`_.
If you plan to do a lot of development on |app|, then the best method is to create a
`Launchpad <http://launchpad.net>`_ account. Once you have the account, you can use it to register

View File

@ -21,6 +21,7 @@ What formats does |app| support conversion to/from?
It can convert every input format in the following list, to every output format.
*Input Formats:* CBZ, CBR, CBC, EPUB, FB2, HTML, LIT, LRF, MOBI, ODT, PDF, PRC**, PDB, PML, RB, RTF, TCR, TXT
*Output Formats:* EPUB, FB2, OEB, LIT, LRF, MOBI, PDB, PML, RB, PDF, TCR, TXT
** PRC is a generic format, |app| supports PRC files with TextRead and MOBIBook headers
@ -68,8 +69,7 @@ There are two aspects to this problem:
How do I use some of the advanced features of the conversion tools?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can get help on any individual feature of the converters by mousing over it in the GUI or running ``ebook-convert dummy.html .epub -h`` at a terminal. A good place to start is to look at the following demo files that demonstrate some of the advanced features:
* `html-demo.zip <http://calibre.kovidgoyal.net/downloads/html-demo.zip>`_
* `txt-demo.zip <http://calibre.kovidgoyal.net/downloads/txt-demo.zip>`_
* `html-demo.zip <http://calibre-ebook.com/downloads/html-demo.zip>`_
Device Integration
@ -231,11 +231,11 @@ I want |app| to download news from my favorite news website.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you are reasonably proficient with computers, you can teach |app| to download news from any website of your choosing. To learn how to do this see :ref:`news`.
Otherwise, you can register a request for a particular news site by adding a comment `here <http://calibre.kovidgoyal.net/ticket/405>`_.
Otherwise, you can register a request for a particular news site by adding a comment `here <http://bugs.calibre-ebook.com/ticket/405>`_.
Can I use web2lrf to download an arbitrary website?
Can I use web2disk to download an arbitrary website?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``web2lrf --url http://mywebsite.com default``
``web2disk http://mywebsite.com``
Miscellaneous
--------------
@ -284,5 +284,5 @@ Most purchased EPUB books have `DRM <http://wiki.mobileread.com/wiki/DRM>`_. Thi
I want some feature added to |app|. What can I do?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You have two choices:
1. Create a patch by hacking on |app| and send it to me for review and inclusion. See `Development <http://calibre.kovidgoyal.net/wiki/Development>`_.
2. `Open a ticket <http://calibre.kovidgoyal.net/newticket>`_ (you have to register and login first) and hopefully I will find the time to implement your feature.
1. Create a patch by hacking on |app| and send it to me for review and inclusion. See `Development <http://calibre-ebook.com/get-involved>`_.
2. `Open a ticket <http://bugs.calibre-ebook.com/newticket>`_ (you have to register and login first) and hopefully I will find the time to implement your feature.

View File

@ -270,7 +270,9 @@ Once the download is complete, you can look at the downloaded :term:`HTML` by op
...
If you're satisfied with your recipe, consider attaching it to `the wiki <http://calibre.kovidgoyal.net/wiki/UserRecipes>`_, so that others can use it as well. If you feel there is enough demand to justify its inclusion into the set of built-in recipes, add a comment to the ticket http://calibre.kovidgoyal.net/ticket/405
If you're satisfied with your recipe, and you feel there is enough demand to justify its inclusion into the set of built-in recipes, add a comment to the ticket http://bugs.calibre-ebook.com/ticket/405
Alternatively, you could just post your recipe in the calibre forum at http://www.mobileread.com/forums/forumdisplay.php?f=166 to share it with other calibre users.
.. seealso::

View File

@ -1,7 +1,7 @@
{% extends "!layout.html" %}
{% block sidebarlogo %}
<p class="logo">
<a href="http://calibre.kovidgoyal.net"><img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/></a>
<a href="http://calibre-ebook.com"><img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/></a>
</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick" />

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,7 @@ def create_man_page(prog, parser):
lines += ['.SH SEE ALSO',
'The User Manual is available at '
'http://calibre.kovidgoyal.net/user_manual',
'http://calibre-ebook.com/user_manual',
'.PP', '.B Created by '+__author__]
lines = [x if isinstance(x, unicode) else unicode(x, 'utf-8', 'replace') for

View File

@ -0,0 +1,83 @@
#include <libwmf/api.h>
#include <libwmf/svg.h>
#define False 0
#define True 1
typedef int bool;
bool create_api(wmfAPI** API) {
wmfAPI_Options options;
wmf_error_t error;
unsigned long flags;
flags = WMF_OPT_FUNCTION;
flags |= WMF_OPT_IGNORE_NONFATAL;
options.function = wmf_svg_function;
error = wmf_api_create (API, flags, &options);
if (error != wmf_E_None) {
wmf_api_destroy (*API);
return False;
}
return True;
}
bool load_image(wmfAPI *API, const char *path) {
wmf_error_t error;
error = wmf_file_open(API, path);
if (error != wmf_E_None) {
wmf_api_destroy (API);
return False;
}
return True;
}
bool scan_image(wmfAPI *API, wmfD_Rect *bbox) {
wmf_error_t error;
error = wmf_scan (API, 0, bbox);
if (error != wmf_E_None) {
wmf_api_destroy (API);
return False;
}
return True;
}
void get_image_size(wmfD_Rect *bbox, float *width, float *height) {
*width = bbox->BR.x - bbox->TL.x;
*height = bbox->BR.y - bbox->TL.y;
}
int main(int argc, char **argv) {
wmfAPI *API = NULL;
wmfD_Rect bbox;
wmf_svg_t *ddata;
float width, height;
if (argc != 2) {
fprintf(stderr, "Usage: wmf file\n");
return 1;
}
if (!create_api(&API)) {
fprintf(stderr, "Failed to create WMF API\n");
return 1;
}
ddata = WMF_SVG_GetData(API);
if (!load_image(API, argv[1])) {
fprintf(stderr, "Failed to load image: %s\n", argv[1]);
return 1;
}
if (!scan_image(API, &bbox)) {
fprintf(stderr, "Failed to scan image: %s\n", argv[1]);
return 1;
}
wmf_file_close(API);
get_image_size(&bbox, &width, &height);
printf("Image size: %f x %f\n", width, height);
return 0;
}

View File

@ -100,6 +100,8 @@ _extra_lang_codes = {
'en_AU' : _('English (AU)'),
'en_CA' : _('English (CA)'),
'en_IN' : _('English (IND)'),
'nl' : _('Dutch (NL)'),
'nl_BE' : _('Dutch (BE)'),
'und' : _('Unknown')
}

View File

@ -122,6 +122,9 @@ class BasicNewsRecipe(Recipe):
#: websites that try to make it difficult to scrape content.
articles_are_obfuscated = False
#: Reverse the order of articles in each feed
reverse_article_order = False
#: Specify any extra :term:`CSS` that should be addded to downloaded :term:`HTML` files
#: It will be inserted into `<style>` tags, just before the closing
#: `</head>` tag thereby overriding all :term:`CSS` except that which is
@ -728,6 +731,10 @@ class BasicNewsRecipe(Recipe):
fi.write(html)
self.jobs = []
if self.reverse_article_order:
feeds = [list(reversed(feed)) for feed in feeds]
for f, feed in enumerate(feeds):
feed_dir = os.path.join(self.output_dir, 'feed_%d'%f)
if not os.path.isdir(feed_dir):