mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
28730f61a7
@ -4,6 +4,70 @@
|
|||||||
# for important features/bug fixes.
|
# for important features/bug fixes.
|
||||||
# Also, each release can have new and improved recipes.
|
# Also, each release can have new and improved recipes.
|
||||||
|
|
||||||
|
- version: 0.6.54
|
||||||
|
date: 2010-05-21
|
||||||
|
|
||||||
|
new features:
|
||||||
|
- title: "EPUB Output: Add option to toggle preserving the aspect ratio of the cover."
|
||||||
|
type: major
|
||||||
|
description: >
|
||||||
|
"By default calibre creates an SVG based cover that scales with the screen size of the reader used to view it. Previosuly this scaling
|
||||||
|
was limited to preserve the aspect ratio of the image. This would often result in white borders at the sides or top and bottom of the image.
|
||||||
|
No, by default, calibre will setup the cover to not preserve aspect ratio, doing away with the white borders. The downside is that if the
|
||||||
|
aspect ratio of the cover is very different from the reader, it will look distorted. The old behavior can be restored via
|
||||||
|
Preferences->Conversion->EPUB Output."
|
||||||
|
|
||||||
|
- title: "Conversion pipeline: calibre will now automatically replace all ligatures in the input document."
|
||||||
|
type: major
|
||||||
|
description: >
|
||||||
|
"Conversion pipeline: calibre will now automatically replace all ligatures in the input document with the normal character
|
||||||
|
sequence they are meant to represent. This is because most readers lack the font support to display ligatures.
|
||||||
|
This can be turned off via an option under Look & Feel, in the Conversion settings."
|
||||||
|
|
||||||
|
- title: "Support for the iPapyrus and Newsmy readers and the Sony Ericsson XPERIA X10"
|
||||||
|
|
||||||
|
- title: "PDF Output: Set the first page to the cover."
|
||||||
|
tickets: [5581]
|
||||||
|
|
||||||
|
bug fixes:
|
||||||
|
- title: "Conversion pipeline: Handle input documents with no text. Allows conversion of MOBI files tha are only a sequence of images."
|
||||||
|
tickets: [5554]
|
||||||
|
|
||||||
|
- title: "Fix text justification control not working with translated version of calibre"
|
||||||
|
tickets: [5551]
|
||||||
|
|
||||||
|
- title: "HTML Input: Encoding detection fixed for <meta> tags that have newlines in their content attributes"
|
||||||
|
tickets: [5567]
|
||||||
|
|
||||||
|
- title: "EPUB Input: Handle malformed UUID in EPUB with obfuscated fonts."
|
||||||
|
tickets: [5552]
|
||||||
|
|
||||||
|
- title: "Don't resort when editing columns in the main GUI"
|
||||||
|
|
||||||
|
- title: "Fix regression in Kobo driver that caused it to only detect books in the root directory of the device"
|
||||||
|
|
||||||
|
new recipes:
|
||||||
|
- title: La Stampa and Libero
|
||||||
|
author: Gabriele Marini
|
||||||
|
|
||||||
|
- title: Der Tagesspiegel
|
||||||
|
author: ipaschke
|
||||||
|
|
||||||
|
- title: EMG and Agro Gerilla
|
||||||
|
author: Darko Miletic
|
||||||
|
|
||||||
|
- title: American Prospect, FactCheck and PolitiFact
|
||||||
|
author: Michael Heinz
|
||||||
|
|
||||||
|
improved recipes:
|
||||||
|
- Times Online
|
||||||
|
- The Atlantic
|
||||||
|
- Il Messagero
|
||||||
|
- Leggo
|
||||||
|
- Instapaper
|
||||||
|
- New York Review of Books
|
||||||
|
- NIN Online
|
||||||
|
|
||||||
- version: 0.6.53
|
- version: 0.6.53
|
||||||
date: 2010-05-15
|
date: 2010-05-15
|
||||||
|
|
||||||
@ -157,7 +221,7 @@
|
|||||||
new features:
|
new features:
|
||||||
- title: "Add merge book feature"
|
- title: "Add merge book feature"
|
||||||
type: major
|
type: major
|
||||||
desc: >
|
description: >
|
||||||
"You can now merge multiple books into a single book, by clicking the arrow next to the edit meta information button.
|
"You can now merge multiple books into a single book, by clicking the arrow next to the edit meta information button.
|
||||||
Meta information from the books will be merged as well as individual book files in different formats"
|
Meta information from the books will be merged as well as individual book files in different formats"
|
||||||
|
|
||||||
|
BIN
resources/images/news/american_thinker.png
Normal file
BIN
resources/images/news/american_thinker.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 705 B |
BIN
resources/images/news/emg_en.png
Normal file
BIN
resources/images/news/emg_en.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 682 B |
BIN
resources/images/news/emg_rs.recipe
Normal file
BIN
resources/images/news/emg_rs.recipe
Normal file
Binary file not shown.
After Width: | Height: | Size: 682 B |
40
resources/recipes/agrogerila.recipe
Normal file
40
resources/recipes/agrogerila.recipe
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
boljevac.blogspot.com
|
||||||
|
'''
|
||||||
|
|
||||||
|
import re
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class AgroGerila(BasicNewsRecipe):
|
||||||
|
title = 'Agro Gerila'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'Politicki nekorektan blog.'
|
||||||
|
oldest_article = 45
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
language = 'sr'
|
||||||
|
encoding = 'utf-8'
|
||||||
|
no_stylesheets = True
|
||||||
|
use_embedded_content = True
|
||||||
|
publication_type = 'blog'
|
||||||
|
extra_css = ' @font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)} body{font-family: "Trebuchet MS",Trebuchet,Verdana,sans1,sans-serif} .article_description{font-family: sans1, sans-serif} img{margin-bottom: 0.8em; border: 1px solid #333333; padding: 4px } '
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : 'film, blog, srbija'
|
||||||
|
, 'publisher': 'Dry-Na-Nord'
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')]
|
||||||
|
|
||||||
|
feeds = [(u'Posts', u'http://boljevac.blogspot.com/feeds/posts/default')]
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return self.adeify_images(soup)
|
||||||
|
|
||||||
|
|
43
resources/recipes/american_thinker.recipe
Normal file
43
resources/recipes/american_thinker.recipe
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Walt Anthony <workshop.northpole at gmail.com>'
|
||||||
|
'''
|
||||||
|
www.americanthinker.com
|
||||||
|
'''
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class AmericanThinker(BasicNewsRecipe):
|
||||||
|
title = u'American Thinker'
|
||||||
|
description = "American Thinker is a daily internet publication devoted to the thoughtful exploration of issues of importance to Americans."
|
||||||
|
__author__ = 'Walt Anthony'
|
||||||
|
publisher = 'Thomas Lifson'
|
||||||
|
category = 'news, politics, USA'
|
||||||
|
oldest_article = 7 #days
|
||||||
|
max_articles_per_feed = 50
|
||||||
|
summary_length = 150
|
||||||
|
language = 'en'
|
||||||
|
|
||||||
|
remove_javascript = True
|
||||||
|
no_stylesheets = True
|
||||||
|
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
, 'linearize_tables' : True
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(name=['table', 'iframe', 'embed', 'object'])
|
||||||
|
]
|
||||||
|
|
||||||
|
remove_tags_after = dict(name='div', attrs={'class':'article_body'})
|
||||||
|
|
||||||
|
|
||||||
|
feeds = [(u'http://feeds.feedburner.com/americanthinker'),
|
||||||
|
(u'http://feeds.feedburner.com/AmericanThinkerBlog')
|
||||||
|
]
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
return 'http://www.americanthinker.com/printpage/?url=' + url
|
26
resources/recipes/aprospect.recipe
Executable file
26
resources/recipes/aprospect.recipe
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
import re
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class AmericanProspect(BasicNewsRecipe):
|
||||||
|
title = u'American Prospect'
|
||||||
|
__author__ = u'Michael Heinz'
|
||||||
|
oldest_article = 30
|
||||||
|
language = 'en'
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
recursions = 0
|
||||||
|
no_stylesheets = True
|
||||||
|
remove_javascript = True
|
||||||
|
|
||||||
|
preprocess_regexps = [
|
||||||
|
(re.compile(r'<body.*?<div class="pad_10L10R">', re.DOTALL|re.IGNORECASE), lambda match: '<body><div>'),
|
||||||
|
(re.compile(r'</div>.*</body>', re.DOTALL|re.IGNORECASE), lambda match: '</div></body>'),
|
||||||
|
(re.compile('\r'),lambda match: ''),
|
||||||
|
(re.compile(r'<!-- .+? -->', re.DOTALL|re.IGNORECASE), lambda match: ''),
|
||||||
|
(re.compile(r'<link .+?>', re.DOTALL|re.IGNORECASE), lambda match: ''),
|
||||||
|
(re.compile(r'<script.*?</script>', re.DOTALL|re.IGNORECASE), lambda match: ''),
|
||||||
|
(re.compile(r'<noscript.*?</noscript>', re.DOTALL|re.IGNORECASE), lambda match: ''),
|
||||||
|
(re.compile(r'<meta .*?/>', re.DOTALL|re.IGNORECASE), lambda match: ''),
|
||||||
|
]
|
||||||
|
|
||||||
|
feeds = [(u'Articles', u'feed://www.prospect.org/articles_rss.jsp')]
|
||||||
|
|
@ -5,7 +5,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
'''
|
'''
|
||||||
theatlantic.com
|
theatlantic.com
|
||||||
'''
|
'''
|
||||||
import string
|
import string, re
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
from calibre.ebooks.BeautifulSoup import Tag, NavigableString
|
from calibre.ebooks.BeautifulSoup import Tag, NavigableString
|
||||||
@ -23,6 +23,8 @@ class TheAtlantic(BasicNewsRecipe):
|
|||||||
remove_tags = [dict(id=['header', 'printAds', 'pageControls'])]
|
remove_tags = [dict(id=['header', 'printAds', 'pageControls'])]
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
|
|
||||||
|
preprocess_regexps = [(re.compile(r'<!--.*?-->', re.DOTALL), lambda m: '')]
|
||||||
|
|
||||||
|
|
||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
return url.replace('/archive/', '/print/')
|
return url.replace('/archive/', '/print/')
|
||||||
|
@ -9,6 +9,7 @@ class BillOReilly(BasicNewsRecipe):
|
|||||||
title = u"Bill O'Reilly"
|
title = u"Bill O'Reilly"
|
||||||
__author__ = 'Rob Lammert - rob.lammert[at]gmail.com'
|
__author__ = 'Rob Lammert - rob.lammert[at]gmail.com'
|
||||||
description = u"Articles from Bill O'Reilly's website and his Fox New's website"
|
description = u"Articles from Bill O'Reilly's website and his Fox New's website"
|
||||||
|
language = 'en'
|
||||||
oldest_article = 7.0
|
oldest_article = 7.0
|
||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
recursions = 0
|
recursions = 0
|
||||||
|
@ -31,7 +31,7 @@ class DigitalSpyUK(BasicNewsRecipe):
|
|||||||
|
|
||||||
remove_tags = [dict(name=['link'])]
|
remove_tags = [dict(name=['link'])]
|
||||||
remove_attributes = ['height','width']
|
remove_attributes = ['height','width']
|
||||||
keep_only_tags = [dict(name='div',attrs={'id':'article'})]
|
keep_only_tags = [dict(name='div',attrs={'id':'content'})]
|
||||||
|
|
||||||
feeds = [
|
feeds = [
|
||||||
(u'News' , u'http://www.digitalspy.co.uk/rss/zones/gb/all.xml' )
|
(u'News' , u'http://www.digitalspy.co.uk/rss/zones/gb/all.xml' )
|
||||||
|
@ -22,7 +22,7 @@ class Economist(BasicNewsRecipe):
|
|||||||
' Needs a subscription from ')+INDEX
|
' Needs a subscription from ')+INDEX
|
||||||
|
|
||||||
oldest_article = 7.0
|
oldest_article = 7.0
|
||||||
cover_url = 'http://www.economist.com/images/covers/currentcovereu_large.jpg'
|
cover_url = 'http://www.economist.com/images/covers/currentcoverus_large.jpg'
|
||||||
remove_tags = [dict(name=['script', 'noscript', 'title', 'iframe', 'cf_floatingcontent']),
|
remove_tags = [dict(name=['script', 'noscript', 'title', 'iframe', 'cf_floatingcontent']),
|
||||||
dict(attrs={'class':['dblClkTrk']})]
|
dict(attrs={'class':['dblClkTrk']})]
|
||||||
remove_tags_before = dict(name=lambda tag: tag.name=='title' and tag.parent.name=='body')
|
remove_tags_before = dict(name=lambda tag: tag.name=='title' and tag.parent.name=='body')
|
||||||
|
@ -15,7 +15,7 @@ class Economist(BasicNewsRecipe):
|
|||||||
' Much slower than the subscription based version.')
|
' Much slower than the subscription based version.')
|
||||||
|
|
||||||
oldest_article = 7.0
|
oldest_article = 7.0
|
||||||
cover_url = 'http://www.economist.com/images/covers/currentcovereu_large.jpg'
|
cover_url = 'http://www.economist.com/images/covers/currentcoverus_large.jpg'
|
||||||
remove_tags = [dict(name=['script', 'noscript', 'title', 'iframe', 'cf_floatingcontent']),
|
remove_tags = [dict(name=['script', 'noscript', 'title', 'iframe', 'cf_floatingcontent']),
|
||||||
dict(attrs={'class':['dblClkTrk']})]
|
dict(attrs={'class':['dblClkTrk']})]
|
||||||
remove_tags_before = dict(name=lambda tag: tag.name=='title' and tag.parent.name=='body')
|
remove_tags_before = dict(name=lambda tag: tag.name=='title' and tag.parent.name=='body')
|
||||||
|
45
resources/recipes/emg_en.recipe
Normal file
45
resources/recipes/emg_en.recipe
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
emg.rs/en/news
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class emportal_en(BasicNewsRecipe):
|
||||||
|
title = 'Ekonom:east News'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'Daily business news from Serbia.'
|
||||||
|
publisher = 'Ekonom:east Media Group'
|
||||||
|
category = 'Business, SEE, Serbia, Belgrade, news, Ekonomist, EMportal'
|
||||||
|
oldest_article = 2
|
||||||
|
max_articles_per_feed = 200
|
||||||
|
no_stylesheets = True
|
||||||
|
encoding = 'utf8'
|
||||||
|
use_embedded_content = False
|
||||||
|
language = 'en'
|
||||||
|
remove_empty_feeds = True
|
||||||
|
masthead_url = 'http://www.emg.rs/img/emportal-rss.png'
|
||||||
|
extra_css = ' body{font-family: Arial,Helvetica,sans-serif } '
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_tags = [dict(attrs={'class':['text-share']})]
|
||||||
|
keep_only_tags = [dict(attrs={'class':'text'})]
|
||||||
|
remove_tags_after = dict(attrs={'class':'text-share'})
|
||||||
|
remove_attributes = ['width','height']
|
||||||
|
|
||||||
|
feeds = [(u'Serbia' , u'http://www.emg.rs/en/news/serbia/rss.xml')]
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
return url.replace('.html','.print.html')
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return soup
|
51
resources/recipes/emg_rs.recipe
Normal file
51
resources/recipes/emg_rs.recipe
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
'''
|
||||||
|
emg.rs/vesti
|
||||||
|
'''
|
||||||
|
|
||||||
|
import re
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class emportal_rs(BasicNewsRecipe):
|
||||||
|
title = 'Ekonom:east Vesti'
|
||||||
|
__author__ = 'Darko Miletic'
|
||||||
|
description = 'Vasa dnevna doza poslovnih informacija iz Srbije, regiona i sveta. Vesti, Berze, Dogadaji, Casopisi.'
|
||||||
|
publisher = 'Ekonom:east Media Group'
|
||||||
|
category = 'Ekonom:east Media Group, Ekonomist, Budelar, Bankar, EMportal, Preduzeca, Moja Posla, EU praktikum, ekonomija, Srbija, Beograd, investicije, finansije, energetika, berza'
|
||||||
|
oldest_article = 2
|
||||||
|
max_articles_per_feed = 200
|
||||||
|
no_stylesheets = True
|
||||||
|
encoding = 'utf8'
|
||||||
|
use_embedded_content = False
|
||||||
|
language = 'sr'
|
||||||
|
remove_empty_feeds = True
|
||||||
|
masthead_url = 'http://www.emg.rs/img/emportal-rss.png'
|
||||||
|
extra_css = ' @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)} body{font-family: Arial,Helvetica,sans1,sans-serif } .article_description{font-family: sans1, sans-serif} '
|
||||||
|
|
||||||
|
conversion_options = {
|
||||||
|
'comment' : description
|
||||||
|
, 'tags' : category
|
||||||
|
, 'publisher' : publisher
|
||||||
|
, 'language' : language
|
||||||
|
}
|
||||||
|
|
||||||
|
preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')]
|
||||||
|
remove_tags = [dict(attrs={'class':['text-share']})]
|
||||||
|
keep_only_tags = [dict(attrs={'class':'text'})]
|
||||||
|
remove_tags_after = dict(attrs={'class':'text-share'})
|
||||||
|
remove_attributes = ['width','height']
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Srbija' , u'http://www.emg.rs/vesti/srbija/rss.xml')
|
||||||
|
,(u'Region' , u'http://www.emg.rs/vesti/region/rss.xml')
|
||||||
|
,(u'Svet' , u'http://www.emg.rs/vesti/svet/rss.xml' )
|
||||||
|
]
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
return url.replace('.html','.print.html')
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
return soup
|
19
resources/recipes/factcheck.recipe
Normal file
19
resources/recipes/factcheck.recipe
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class FactCheckOrg(BasicNewsRecipe):
|
||||||
|
title = u'Factcheck'
|
||||||
|
__author__ = u'Michael Heinz'
|
||||||
|
language = 'en'
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
recursion = 0
|
||||||
|
|
||||||
|
publication_type = 'magazine'
|
||||||
|
masthead_url = 'http://factcheck.org/wp-content/themes/Streamline/images/headernew.jpg'
|
||||||
|
cover_url = 'http://factcheck.org/wp-content/themes/Streamline/images/headernew.jpg'
|
||||||
|
|
||||||
|
remove_tags = [ dict({'id':['footer','footerabout','sidebar']}) ]
|
||||||
|
|
||||||
|
|
||||||
|
feeds = [(u'Factcheck', u'feed://www.factcheck.org/feed/')]
|
||||||
|
|
@ -9,14 +9,20 @@ class Freakonomics(BasicNewsRecipe):
|
|||||||
|
|
||||||
title = 'Freakonomics Blog'
|
title = 'Freakonomics Blog'
|
||||||
description = 'The Hidden side of everything'
|
description = 'The Hidden side of everything'
|
||||||
__author__ = 'Kovid Goyal'
|
__author__ = 'Starson17'
|
||||||
language = 'en'
|
language = 'en'
|
||||||
|
cover_url = 'http://ilkerugur.files.wordpress.com/2009/04/freakonomics.jpg'
|
||||||
|
|
||||||
|
feeds = [('Blog', 'http://feeds.feedburner.com/freakonomicsblog')]
|
||||||
|
|
||||||
feeds = [('Blog', 'http://freakonomics.blogs.nytimes.com/feed/atom/')]
|
keep_only_tags = [dict(name='div', attrs={'id':'header'}),
|
||||||
|
dict(name='h1'),
|
||||||
def get_article_url(self, article):
|
dict(name='h2'),
|
||||||
return article.get('feedburner_origlink', None)
|
dict(name='div', attrs={'class':'entry-content'}),
|
||||||
|
]
|
||||||
def print_version(self, url):
|
extra_css = '''
|
||||||
return url + '?pagemode=print'
|
h1{font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:large;}
|
||||||
|
h2{font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:small;}
|
||||||
|
p{font-family:Arial,Helvetica,sans-serif;font-size:small;}
|
||||||
|
body{font-family:Helvetica,Arial,sans-serif;font-size:small;}
|
||||||
|
'''
|
||||||
|
@ -7,14 +7,14 @@ description = 'Italian daily newspaper - v1.01 (04, January 2010)'
|
|||||||
'''
|
'''
|
||||||
http://www.messaggero.it/
|
http://www.messaggero.it/
|
||||||
'''
|
'''
|
||||||
|
import time
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class IlMessaggero(BasicNewsRecipe):
|
class IlMessaggero(BasicNewsRecipe):
|
||||||
__author__ = 'Gabriele Marini'
|
__author__ = 'Gabriele Marini'
|
||||||
description = 'Italian News'
|
description = 'Italian News'
|
||||||
|
|
||||||
cover_url = 'http://www.ilmessaggero.it/img_tst/logomsgr.gif'
|
# cover_url = 'http://www.ilmessaggero.it/img_tst/logomsgr.gif'
|
||||||
title = u'Il Messaggero'
|
title = u'Il Messaggero'
|
||||||
publisher = 'Caltagirone Editore'
|
publisher = 'Caltagirone Editore'
|
||||||
category = 'News, politics, culture, economy, general interest'
|
category = 'News, politics, culture, economy, general interest'
|
||||||
@ -34,6 +34,21 @@ class IlMessaggero(BasicNewsRecipe):
|
|||||||
dict(name='h2', attrs={'class':'sottotitLettura'}),
|
dict(name='h2', attrs={'class':'sottotitLettura'}),
|
||||||
dict(name='span', attrs={'class':'testoArticoloG'})
|
dict(name='span', attrs={'class':'testoArticoloG'})
|
||||||
]
|
]
|
||||||
|
def get_cover_url(self):
|
||||||
|
cover = None
|
||||||
|
st = time.localtime()
|
||||||
|
year = str(st.tm_year)
|
||||||
|
month = "%.2d" % st.tm_mon
|
||||||
|
day = "%.2d" % st.tm_mday
|
||||||
|
cover='http://carta.ilmessaggero.it/' + year + month + day + '/jpeg/MSGR_20_CITTA_1.jpg'
|
||||||
|
br = BasicNewsRecipe.get_browser()
|
||||||
|
try:
|
||||||
|
br.open(cover)
|
||||||
|
except:
|
||||||
|
self.log("\nCover unavailable")
|
||||||
|
cover = 'http://www.ilmessaggero.it/img_tst/logomsgr.gif'
|
||||||
|
|
||||||
|
return cover
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
57
resources/recipes/infomotori.recipe
Normal file
57
resources/recipes/infomotori.recipe
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__author__ = 'Gabriele Marini, based on Darko Miletic'
|
||||||
|
__copyright__ = '2009-2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
description = 'On Line Motor News - 01-05-2010'
|
||||||
|
|
||||||
|
'''
|
||||||
|
http://www.infomotori.it/
|
||||||
|
'''
|
||||||
|
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class infomotori(BasicNewsRecipe):
|
||||||
|
author = 'Gabriele Marini'
|
||||||
|
title = u'Infomotori'
|
||||||
|
cover = 'http://www.infomotori.com/content/files/anniversario_01.gif'
|
||||||
|
oldest_article = 31
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
recursion = 100
|
||||||
|
use_embedded_content = False
|
||||||
|
|
||||||
|
language = 'it'
|
||||||
|
use_embedded_content = False
|
||||||
|
remove_javascript = True
|
||||||
|
no_stylesheets = True
|
||||||
|
language = 'it'
|
||||||
|
timefmt = '[%a, %d %b, %Y]'
|
||||||
|
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
raw = self.browser.open(url).read()
|
||||||
|
soup = BeautifulSoup(raw.decode('utf8', 'replace'))
|
||||||
|
print_link = soup.find('a', {'class':'printarticle'})
|
||||||
|
|
||||||
|
'''if print_link is None:
|
||||||
|
|
||||||
|
keep_only_tags = [ dict(name='div', attrs={'class':['article main-column-article photogallery-column','category-header','article-body']})
|
||||||
|
]
|
||||||
|
remove_tags = [ dict(name='div', attrs={'class':['thumbnails-article','infoflash-footer','imushortarticle']}),
|
||||||
|
dict(name='div', attrs={'id':['linkinviastampa','linkspazioblu','altriarticoli','articoliconcorrenti','articolicorrelati','boxbrand']}),
|
||||||
|
dict(name='table', attrs={'class':'article-page'})
|
||||||
|
]
|
||||||
|
|
||||||
|
remove_tags_after = [ dict(name='div', attrs={'id':'articlebody'})
|
||||||
|
]
|
||||||
|
return url
|
||||||
|
'''
|
||||||
|
return print_link['href']
|
||||||
|
|
||||||
|
feeds = [(u'Ultime Novit\xe0', u'http://feeds.infomotori.com/ultimenovita'),
|
||||||
|
(u'Auto: Ultime Novit\xe0 ', u'http://feeds.infomotori.com/autonovita'),
|
||||||
|
(u'Moto: Ultime Novit\xe0 Moto', u'http://feeds.infomotori.com/motonovita'),
|
||||||
|
(u'Notizie Flash', u'http://feeds.infomotori.com/infoflashmotori'),
|
||||||
|
(u'Veicoli Ecologici e Mobilit\xe0 Sostenibile', u'http://feeds.infomotori.com/ecomotori'),
|
||||||
|
(u'4x4 Fuoristrada, Crossover e Suv', u'http://feeds.infomotori.com/fuoristrada'),
|
||||||
|
(u'Shopping Motori', u'http://feeds.infomotori.com/shoppingmotori')
|
||||||
|
]
|
@ -1,11 +1,10 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
__copyright__ = '2009-2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
'''
|
'''
|
||||||
www.instapaper.com
|
www.instapaper.com
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import urllib
|
||||||
from calibre import strftime
|
from calibre import strftime
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
@ -22,18 +21,15 @@ class Instapaper(BasicNewsRecipe):
|
|||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
use_embedded_content = False
|
use_embedded_content = False
|
||||||
remove_javascript = True
|
|
||||||
needs_subscription = True
|
needs_subscription = True
|
||||||
INDEX = u'http://www.instapaper.com'
|
INDEX = u'http://www.instapaper.com'
|
||||||
LOGIN = INDEX + u'/user/login'
|
LOGIN = INDEX + u'/user/login'
|
||||||
|
|
||||||
html2lrf_options = [
|
conversion_options = {
|
||||||
'--comment', description
|
'comment' : description
|
||||||
, '--category', category
|
, 'tags' : category
|
||||||
, '--publisher', publisher
|
, 'publisher' : publisher
|
||||||
]
|
}
|
||||||
|
|
||||||
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}"'
|
|
||||||
|
|
||||||
feeds = [
|
feeds = [
|
||||||
(u'Unread articles' , INDEX + u'/u' )
|
(u'Unread articles' , INDEX + u'/u' )
|
||||||
@ -63,7 +59,7 @@ class Instapaper(BasicNewsRecipe):
|
|||||||
description = self.tag_to_string(item.div)
|
description = self.tag_to_string(item.div)
|
||||||
atag = item.a
|
atag = item.a
|
||||||
if atag and atag.has_key('href'):
|
if atag and atag.has_key('href'):
|
||||||
url = self.INDEX + atag['href'] + '/text'
|
url = atag['href']
|
||||||
title = self.tag_to_string(atag)
|
title = self.tag_to_string(atag)
|
||||||
date = strftime(self.timefmt)
|
date = strftime(self.timefmt)
|
||||||
articles.append({
|
articles.append({
|
||||||
@ -75,3 +71,6 @@ class Instapaper(BasicNewsRecipe):
|
|||||||
totalfeeds.append((feedtitle, articles))
|
totalfeeds.append((feedtitle, articles))
|
||||||
return totalfeeds
|
return totalfeeds
|
||||||
|
|
||||||
|
def print_version(self, url):
|
||||||
|
return self.INDEX + '/text?u=' + urllib.quote(url)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__author__ = 'Lorenzo Vigentini'
|
__author__ = 'Lorenzo Vigentini, Gabriele Marini'
|
||||||
__copyright__ = '2009, Lorenzo Vigentini <l.vigentini at gmail.com>'
|
__copyright__ = '2009, Lorenzo Vigentini <l.vigentini at gmail.com>'
|
||||||
__version__ = 'v1.02'
|
__version__ = 'v1.02'
|
||||||
__date__ = '10, January 2010'
|
__date__ = '10, January 2010'
|
||||||
@ -10,17 +10,17 @@ __description__ = 'Italian weekly magazine'
|
|||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class laGazzetta(BasicNewsRecipe):
|
class Espresso(BasicNewsRecipe):
|
||||||
__author__ = 'Lorenzo Vigentini'
|
__author__ = 'Lorenzo Vigentini, Gabriele Marini'
|
||||||
description = 'Italian weekly magazine'
|
description = 'Italian weekly magazine'
|
||||||
|
|
||||||
cover_url = 'http://espresso.repubblica.it/images/logo_espresso.gif'
|
cover_url = 'http://espresso.repubblica.it/images/logo_espresso.gif'
|
||||||
title = 'l Espresso '
|
title = 'L\'Espresso '
|
||||||
publisher = 'Gruppo editoriale lEspresso'
|
publisher = 'Gruppo editoriale L\'Espresso'
|
||||||
category = 'News, politics, culture, economy, general interest'
|
category = 'News, politics, culture, economy, general interest'
|
||||||
|
|
||||||
language = 'it'
|
language = 'it'
|
||||||
encoding = 'cp1252'
|
# encoding = 'cp1252'
|
||||||
timefmt = '[%a, %d %b, %Y]'
|
timefmt = '[%a, %d %b, %Y]'
|
||||||
|
|
||||||
oldest_article = 16
|
oldest_article = 16
|
||||||
@ -33,35 +33,45 @@ class laGazzetta(BasicNewsRecipe):
|
|||||||
|
|
||||||
|
|
||||||
feeds = [
|
feeds = [
|
||||||
(u'Espresso Homepage', u'http://kpm.data.kataweb.it/kpm3eolx/rss/home'),
|
(u'Homepage', u'http://kpm.data.kataweb.it/kpm3eolx/rss/home'),
|
||||||
(u'Espresso Local', u'http://kpm.data.kataweb.it/kpm3eolx/rss/local'),
|
(u'Local', u'http://kpm.data.kataweb.it/kpm3eolx/rss/local'),
|
||||||
(u'Espresso Style & Design', u'http://kpm.data.kataweb.it/kpm3eolx/rss/style_design'),
|
(u'Style & Design', u'http://kpm.data.kataweb.it/kpm3eolx/rss/style_design'),
|
||||||
(u'Espresso Opinioni', u'http://kpm.data.kataweb.it/kpm3eolx/rss/opinioni'),
|
(u'Opinioni', u'http://kpm.data.kataweb.it/kpm3eolx/rss/opinioni'),
|
||||||
(u'Espresso Rubriche', u'http://kpm.data.kataweb.it/kpm3eolx/rss/rubriche'),
|
(u'Rubriche', u'http://kpm.data.kataweb.it/kpm3eolx/rss/rubriche'),
|
||||||
(u'Espresso Limes', u'http://temi.repubblica.it/limes/feed/')
|
(u'Limes', u'http://temi.repubblica.it/limes/feed/'),
|
||||||
|
(u'Chiesa: HomePage', u'http://data.kataweb.it/rss/chiesa/homepage/it'),
|
||||||
|
(u'Chiesa: Speciali e Focus', u'http://data.kataweb.it/rss/chiesa/speciali_e_focus/it')
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def print_version(self,url):
|
def print_version(self,url):
|
||||||
|
print url[7:25]
|
||||||
|
if url[7:25] == 'temi.repubblica.it':
|
||||||
|
return url + '/?printpage=undefined'
|
||||||
|
elif url[7:25] == 'www.chiesa.espress':
|
||||||
|
return url
|
||||||
return url + '/&print=true'
|
return url + '/&print=true'
|
||||||
|
|
||||||
|
|
||||||
keep_only_tags = [
|
keep_only_tags = [
|
||||||
dict(name='div', attrs={'class':['testo','copertina','occhiello','firma','didascalia','content-second-right','detail-articles','titolo-local','generic-articles']}),
|
dict(name='div', attrs={'class':['testo','copertina','occhiello','firma','didascalia','content-second-right','detail-articles','titolo-local','generic-articles']}),
|
||||||
dict(name='div', attrs={'class':['generic-articles','summary','detail-articles']}),
|
dict(name='div', attrs={'class':['generic-articles','summary','detail-articles']}),
|
||||||
dict(name='div', attrs={'id':'content-second-right'})
|
dict(name='div', attrs={'id':['content-second-right','content2']})
|
||||||
]
|
]
|
||||||
|
|
||||||
remove_tags = [
|
remove_tags = [
|
||||||
dict(name='div',attrs={'class':['servizi','aggiungi','label-web','bottom-mobile','box-abbonamenti','box-cerca','big','little','stampaweb']}),
|
dict(name='div',attrs={'class':['servizi','aggiungi','label-web','bottom-mobile','box-abbonamenti','box-cerca','big','little','stampaweb']}),
|
||||||
dict(name='div',attrs={'id':['topheader','header','navigation-new','navigation','content-second-left']}),
|
dict(name='div',attrs={'id':['topheader','header','navigation-new','navigation','content-second-left','menutext']}),
|
||||||
|
dict(name='ul',attrs={'id':'user-utility'}),
|
||||||
dict(name=['script','noscript','iframe'])
|
dict(name=['script','noscript','iframe'])
|
||||||
]
|
]
|
||||||
extra_css = '''
|
# extra_css = '''
|
||||||
h1 {font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:20px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:18px;}
|
# h1 {font-family:Times New Roman,"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:24px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:18px;}
|
||||||
h2 {font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:18px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:16px; }
|
# h2 {font-family:Times New Roman, "Trebuchet MS",Arial,Helvetica,sans-serif; font-size:18px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:16px; }
|
||||||
h3 {color:#333333;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:16px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:14px;}
|
# h3 {color:#333333;font-family:Times New Roman, "Trebuchet MS",Arial,Helvetica,sans-serif; font-size:16px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:14px;}
|
||||||
h4 {color:#333333; font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:16px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:14px; }
|
# h4 {color:#333333; font-family:Times New Roman, "Trebuchet MS",Arial,Helvetica,sans-serif;font-size:16px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:14px; }
|
||||||
h5 {color:#333333; font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:12px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:14px; text-transform:uppercase;}
|
# h5 {color:#333333; font-family:Times New Roman, "Trebuchet MS",Arial,Helvetica,sans-serif; font-size:12px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:14px; text-transform:uppercase;}
|
||||||
.firma {color:#333333;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:12px; font-size-adjust:none; font-stretch:normal; font-style:italic; font-variant:normal; font-weight:bold; line-height:15px; text-decoration:none;}
|
# .firma {color:#333333;font-family:Times New Roman, "Trebuchet MS",Arial,Helvetica,sans-serif;font-size:12px; font-size-adjust:none; font-stretch:normal; font-style:italic; font-variant:normal; font-weight:bold; line-height:15px; text-decoration:none;}
|
||||||
.testo {font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:10px;}
|
# .testo {font-family:Times New Roman, "Trebuchet MS",Arial,Helvetica,sans-serif; font-size:10px;}
|
||||||
'''
|
# '''
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__author__ = 'Lorenzo Vigentini, based on Darko Miletic'
|
__author__ = 'Lorenzo Vigentini, based on Darko Miletic, Gabriele Marini'
|
||||||
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>, Lorenzo Vigentini <l.vigentini at gmail.com>'
|
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>, Lorenzo Vigentini <l.vigentini at gmail.com>'
|
||||||
description = 'Italian daily newspaper - v1.01 (04, January 2010)'
|
description = 'Italian daily newspaper - v1.01 (04, January 2010); 16.05.2010 new version'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
http://www.repubblica.it/
|
http://www.repubblica.it/
|
||||||
@ -11,7 +11,7 @@ http://www.repubblica.it/
|
|||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class LaRepubblica(BasicNewsRecipe):
|
class LaRepubblica(BasicNewsRecipe):
|
||||||
author = 'Lorenzo Vigentini, based on Darko Miletic'
|
__author__ = 'Lorenzo Vigentini, Gabriele Marini'
|
||||||
description = 'Italian daily newspaper'
|
description = 'Italian daily newspaper'
|
||||||
|
|
||||||
cover_url = 'http://www.repubblica.it/images/homepage/la_repubblica_logo.gif'
|
cover_url = 'http://www.repubblica.it/images/homepage/la_repubblica_logo.gif'
|
||||||
@ -36,7 +36,8 @@ class LaRepubblica(BasicNewsRecipe):
|
|||||||
|
|
||||||
keep_only_tags = [dict(name='div', attrs={'class':'articolo'}),
|
keep_only_tags = [dict(name='div', attrs={'class':'articolo'}),
|
||||||
dict(name='div', attrs={'class':'body-text'}),
|
dict(name='div', attrs={'class':'body-text'}),
|
||||||
dict(name='div', attrs={'class':'page-content'}),
|
# dict(name='div', attrs={'class':'page-content'}),
|
||||||
|
dict(name='p', attrs={'class':'disclaimer clearfix'}),
|
||||||
dict(name='div', attrs={'id':'contA'})
|
dict(name='div', attrs={'id':'contA'})
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -47,11 +48,9 @@ class LaRepubblica(BasicNewsRecipe):
|
|||||||
dict(name='div', attrs={'class':'bottom-mobile'}),
|
dict(name='div', attrs={'class':'bottom-mobile'}),
|
||||||
dict(name='div', attrs={'id':['rssdiv','blocco']}),
|
dict(name='div', attrs={'id':['rssdiv','blocco']}),
|
||||||
dict(name='div', attrs={'class':'utility'}),
|
dict(name='div', attrs={'class':'utility'}),
|
||||||
dict(name='div', attrs={'class':'generalbox'})
|
dict(name='div', attrs={'class':'generalbox'}),
|
||||||
|
dict(name='ul', attrs={'id':'hystory'})
|
||||||
]
|
]
|
||||||
remove_tags_after = [
|
|
||||||
dict(name='div',attrs={'id':'ugc_linkUpload'})
|
|
||||||
]
|
|
||||||
|
|
||||||
feeds = [
|
feeds = [
|
||||||
(u'Rilievo', u'http://www.repubblica.it/rss/homepage/rss2.0.xml'),
|
(u'Rilievo', u'http://www.repubblica.it/rss/homepage/rss2.0.xml'),
|
||||||
|
67
resources/recipes/la_stampa.recipe
Normal file
67
resources/recipes/la_stampa.recipe
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__author__ = 'Gabriele Marini, based on Darko Miletic'
|
||||||
|
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
__description__ = 'La Stampa 05/05/2010'
|
||||||
|
|
||||||
|
'''
|
||||||
|
http://www.lastampa.it/
|
||||||
|
'''
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class LaStampa(BasicNewsRecipe):
|
||||||
|
|
||||||
|
title = u'La Stampa'
|
||||||
|
language = 'it'
|
||||||
|
__author__ = 'Gabriele Marini'
|
||||||
|
oldest_article = 15
|
||||||
|
max_articles_per_feed = 50
|
||||||
|
recursion = 100
|
||||||
|
cover_url = 'http://www.lastampa.it/edicola/PDF/1.pdf'
|
||||||
|
use_embedded_content = False
|
||||||
|
remove_javascript = True
|
||||||
|
no_stylesheets = True
|
||||||
|
|
||||||
|
conversion_options = {'linearize_tables':True}
|
||||||
|
remove_attributes = ['colspan']
|
||||||
|
|
||||||
|
extra_css = ' .boxocchiello2{font-size: small} .catenaccio{font-style: italic} .titoloRub{font-size: xx-large; font-weight: bold } .titologir{font-size: xx-large; font-weight: bold } .sezione{font-weight: bold} '
|
||||||
|
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
link = article.get('links')
|
||||||
|
if link:
|
||||||
|
return link[0]['href']
|
||||||
|
|
||||||
|
keep_only_tags = [dict(attrs={'class':['boxocchiello2','titoloRub','titologir','catenaccio','sezione','articologirata']}),
|
||||||
|
dict(name='div', attrs={'id':'corpoarticolo'})
|
||||||
|
]
|
||||||
|
|
||||||
|
remove_tags = [dict(name='div', attrs={'id':'menutop'}),
|
||||||
|
dict(name='div', attrs={'id':'fwnetblocco'}),
|
||||||
|
dict(name='table', attrs={'id':'strumenti'}),
|
||||||
|
dict(name='table', attrs={'id':'imgesterna'}),
|
||||||
|
dict(name='a', attrs={'class':'linkblu'}),
|
||||||
|
dict(name='a', attrs={'class':'link'}),
|
||||||
|
dict(name='span', attrs={'class':['boxocchiello','boxocchiello2','sezione']})
|
||||||
|
]
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Home', u'http://www.lastampa.it/redazione/rss_home.xml'),
|
||||||
|
(u'Editoriali', u'http://www.lastampa.it/cmstp/rubriche/oggetti/rss.asp?ID_blog=25'),
|
||||||
|
(u'Politica', u'http://www.lastampa.it/redazione/cmssezioni/politica/rss_politica.xml'),
|
||||||
|
(u'ArciItaliana', u'http://www.lastampa.it/cmstp/rubriche/oggetti/rss.asp?ID_blog=14'),
|
||||||
|
(u'Cronache', u'http://www.lastampa.it/redazione/cmssezioni/cronache/rss_cronache.xml'),
|
||||||
|
(u'Esteri', u'http://www.lastampa.it/redazione/cmssezioni/esteri/rss_esteri.xml'),
|
||||||
|
(u'Danni Collaterali', u'http://www.lastampa.it/cmstp/rubriche/oggetti/rss.asp?ID_blog=90'),
|
||||||
|
(u'Economia', u'http://www.lastampa.it/redazione/cmssezioni/economia/rss_economia.xml'),
|
||||||
|
(u'Tecnologia ', u'http://www.lastampa.it/cmstp/rubriche/oggetti/rss.asp?ID_blog=30'),
|
||||||
|
(u'Spettacoli', u'http://www.lastampa.it/redazione/cmssezioni/spettacoli/rss_spettacoli.xml'),
|
||||||
|
(u'Sport', u'http://www.lastampa.it/sport/rss_home.xml'),
|
||||||
|
(u'Torino', u'http://rss.feedsportal.com/c/32418/f/466938/index.rss'),
|
||||||
|
(u'Motori', u'http://www.lastampa.it/cmstp/rubriche/oggetti/rss.asp?ID_blog=57'),
|
||||||
|
(u'Scienza', u'http://www.lastampa.it/cmstp/rubriche/oggetti/rss.asp?ID_blog=38'),
|
||||||
|
(u'Fotografia', u'http://rss.feedsportal.com/c/32418/f/478449/index.rss'),
|
||||||
|
(u'Scuola', u'http://www.lastampa.it/cmstp/rubriche/oggetti/rss.asp?ID_blog=60'),
|
||||||
|
(u'Tempo Libero', u'http://www.lastampa.it/tempolibero/rss_home.xml')
|
||||||
|
]
|
@ -7,14 +7,14 @@ description = 'Italian daily newspaper - v1.00 05-05-2010'
|
|||||||
'''
|
'''
|
||||||
http://www.leggo.it
|
http://www.leggo.it
|
||||||
'''
|
'''
|
||||||
|
import time
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class LeggoIT(BasicNewsRecipe):
|
class LeggoIT(BasicNewsRecipe):
|
||||||
__author__ = 'Gabriele Marini'
|
__author__ = 'Gabriele Marini'
|
||||||
description = 'Italian Free daily newspaper'
|
description = 'Italian Free daily newspaper'
|
||||||
|
|
||||||
cover_url = 'http://www.leggo.it/img/logo-leggo2.gif'
|
# cover_url = 'http://www.leggo.it/img/logo-leggo2.gif'
|
||||||
title = u'Leggo.it'
|
title = u'Leggo.it'
|
||||||
publisher = 'Ced Caltagirone Editore S.p.A.'
|
publisher = 'Ced Caltagirone Editore S.p.A.'
|
||||||
category = 'News, politics, culture, economy, general interest'
|
category = 'News, politics, culture, economy, general interest'
|
||||||
@ -33,8 +33,8 @@ class LeggoIT(BasicNewsRecipe):
|
|||||||
|
|
||||||
keep_only_tags = [
|
keep_only_tags = [
|
||||||
dict(name='h1',attrs={'class':'nero22'}),
|
dict(name='h1',attrs={'class':'nero22'}),
|
||||||
dict(name='div',attrs={'id':'testodim'})
|
dict(name='div',attrs={'id':'testodim'})
|
||||||
]
|
]
|
||||||
feeds = [
|
feeds = [
|
||||||
(u'Home Page', u'http://www.leggo.it/rss/home.xml'),
|
(u'Home Page', u'http://www.leggo.it/rss/home.xml'),
|
||||||
(u'Italia', u'http://www.leggo.it/rss/italia.xml'),
|
(u'Italia', u'http://www.leggo.it/rss/italia.xml'),
|
||||||
@ -45,5 +45,21 @@ class LeggoIT(BasicNewsRecipe):
|
|||||||
(u'Spettacoli', u'http://www.leggo.it/rss/spettacoli.xml'),
|
(u'Spettacoli', u'http://www.leggo.it/rss/spettacoli.xml'),
|
||||||
(u'Salute', u'http://www.leggo.it/rss/salute.xml'),
|
(u'Salute', u'http://www.leggo.it/rss/salute.xml'),
|
||||||
(u'Scienza', u'http://www.leggo.it/rss/scienza.xml')
|
(u'Scienza', u'http://www.leggo.it/rss/scienza.xml')
|
||||||
]
|
]
|
||||||
|
def get_cover_url(self):
|
||||||
|
cover = None
|
||||||
|
st = time.localtime()
|
||||||
|
year = str(st.tm_year)
|
||||||
|
month = "%.2d" % st.tm_mon
|
||||||
|
day = "%.2d" % st.tm_mday
|
||||||
|
cover='http://www.leggo.it/'+ year + month + day + '/jpeg/LEGGO_ROMA_1.jpg'
|
||||||
|
br = BasicNewsRecipe.get_browser()
|
||||||
|
try:
|
||||||
|
br.open(cover)
|
||||||
|
except:
|
||||||
|
self.log("\nCover unavailable")
|
||||||
|
cover = 'http://www.leggo.it/img/logo-leggo2.gif'
|
||||||
|
|
||||||
|
return cover
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ __author__ = 'Lorenzo Vigentini'
|
|||||||
__copyright__ = '2009, Lorenzo Vigentini <l.vigentini at gmail.com>'
|
__copyright__ = '2009, Lorenzo Vigentini <l.vigentini at gmail.com>'
|
||||||
__version__ = 'v1.01'
|
__version__ = 'v1.01'
|
||||||
__date__ = '10, January 2010'
|
__date__ = '10, January 2010'
|
||||||
__description__ = 'Monthly Italian edition of Scientific American'
|
__description__ = 'Monthly Italian edition of Scientific American, 16.05.2010 new version'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
http://lescienze.espresso.repubblica.it/
|
http://lescienze.espresso.repubblica.it/
|
||||||
@ -13,22 +13,22 @@ http://lescienze.espresso.repubblica.it/
|
|||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
class leScienze(BasicNewsRecipe):
|
class leScienze(BasicNewsRecipe):
|
||||||
author = 'Lorenzo Vigentini'
|
__author__ = 'Lorenzo Vigentini, Gabriele Marini'
|
||||||
description = 'Monthly Italian edition of Scientific American'
|
description = 'Monthly Italian edition of Scientific American'
|
||||||
|
|
||||||
cover_url = 'http://lescienze.espresso.repubblica.it/images/logo_lescienze.gif'
|
cover_url = 'http://lescienze.espresso.repubblica.it/images/logo_lescienze.gif'
|
||||||
title = 'le Scienze'
|
title = 'le Scienze'
|
||||||
publisher = 'Gruppo editoriale lEspresso'
|
publisher = 'Gruppo editoriale L\'Espresso'
|
||||||
category = 'Science, general interest'
|
category = 'Science, general interest'
|
||||||
|
|
||||||
language = 'it'
|
language = 'it'
|
||||||
encoding = 'cp1252'
|
# encoding = 'cp1252'
|
||||||
timefmt = '[%a, %d %b, %Y]'
|
timefmt = '[%a, %d %b, %Y]'
|
||||||
|
|
||||||
oldest_article = 31
|
oldest_article = 100
|
||||||
max_articles_per_feed = 20
|
max_articles_per_feed = 100
|
||||||
use_embedded_content = False
|
use_embedded_content = False
|
||||||
recursion = 10
|
recursion = 20
|
||||||
|
|
||||||
remove_javascript = True
|
remove_javascript = True
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
@ -46,6 +46,8 @@ class leScienze(BasicNewsRecipe):
|
|||||||
remove_tags_after = [dict(name='div',attrs={'class':'box-commenti'})]
|
remove_tags_after = [dict(name='div',attrs={'class':'box-commenti'})]
|
||||||
|
|
||||||
feeds = [
|
feeds = [
|
||||||
|
|
||||||
|
(u'Home', u'http://data.kataweb.it/rss/scienze'),
|
||||||
(u'Antropologia', u'http://data.kataweb.it/rss/scienze/antropologia'),
|
(u'Antropologia', u'http://data.kataweb.it/rss/scienze/antropologia'),
|
||||||
(u'Archeologia', u'http://data.kataweb.it/rss/scienze/archeologia'),
|
(u'Archeologia', u'http://data.kataweb.it/rss/scienze/archeologia'),
|
||||||
(u'Arte e Musica', u'http://data.kataweb.it/rss/scienze/arte_e_musica'),
|
(u'Arte e Musica', u'http://data.kataweb.it/rss/scienze/arte_e_musica'),
|
||||||
@ -72,18 +74,3 @@ class leScienze(BasicNewsRecipe):
|
|||||||
(u'Storia della scienza', u'http://data.kataweb.it/rss/scienze/storia_della_scienza')
|
(u'Storia della scienza', u'http://data.kataweb.it/rss/scienze/storia_della_scienza')
|
||||||
]
|
]
|
||||||
|
|
||||||
extra_css = '''
|
|
||||||
h1 {font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:20px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:18px;}
|
|
||||||
h2 {font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:18px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:16px; }
|
|
||||||
h3 {color:#333333;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:16px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:14px;}
|
|
||||||
h4 {color:#333333; font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:16px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:14px; }
|
|
||||||
h5 {color:#333333; font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:12px; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:bold; line-height:14px; text-transform:uppercase;}
|
|
||||||
.occhiello {color:#666666;display:block;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:13px;font-size-adjust:none;font-stretch:normal;font-style:normal;font-variant:normal;font-weight:bold;line-height:15px;}
|
|
||||||
.titolo {font-weight:bold;}
|
|
||||||
.label {font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:12px;font-size-adjust:none;font-stretch:normal;font-style:normal;font-variant:normal;font-weight:bold;height:15px;line-height:15px;text-transform:uppercase;}
|
|
||||||
.firma {color:#333333;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:12px; font-size-adjust:none; font-stretch:normal; font-style:italic; font-variant:normal; font-weight:bold; line-height:15px; text-decoration:none;}
|
|
||||||
.testo {font-family:"Trebuchet MS",Arial,Helvetica,sans-serif; font-size:10px;}
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
56
resources/recipes/libero.recipe
Normal file
56
resources/recipes/libero.recipe
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__author__ = 'Gabriele Marini, based on Darko Miletic'
|
||||||
|
__copyright__ = '2009-2010, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
|
description = 'Italian daily newspaper - 13-05-2010'
|
||||||
|
|
||||||
|
'''
|
||||||
|
http://www.libero-news.it/
|
||||||
|
'''
|
||||||
|
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class LiberoNews(BasicNewsRecipe):
|
||||||
|
__author__ = 'Marini Gabriele'
|
||||||
|
description = 'Italian daily newspaper'
|
||||||
|
|
||||||
|
cover_url = 'http://www.ilgiornale.it/img_v1/logo.gif'
|
||||||
|
title = u'Libero'
|
||||||
|
publisher = 'EDITORIALE LIBERO s.r.l 2006'
|
||||||
|
category = 'News, politics, culture, economy, general interest'
|
||||||
|
|
||||||
|
language = 'it'
|
||||||
|
timefmt = '[%a, %d %b, %Y]'
|
||||||
|
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 50
|
||||||
|
use_embedded_content = False
|
||||||
|
recursion = 100
|
||||||
|
|
||||||
|
no_stylesheets = True
|
||||||
|
conversion_options = {'linearize_tables':True}
|
||||||
|
remove_javascript = True
|
||||||
|
|
||||||
|
keep_only_tags = [
|
||||||
|
dict(name='div', attrs={'class':'Articolo'})
|
||||||
|
]
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='div', attrs={'class':['CommentaFoto','Priva2']}),
|
||||||
|
dict(name='div', attrs={'id':['commentigenerale']})
|
||||||
|
]
|
||||||
|
feeds = [
|
||||||
|
(u'Politica', u'http://www.libero-news.it/rss.jsp?sezione=14'),
|
||||||
|
(u'Italia', u'http://www.libero-news.it/rss.jsp?sezione=15'),
|
||||||
|
(u'Esteri', u'http://www.libero-news.it/rss.jsp?sezione=16'),
|
||||||
|
(u'Economia', u'http://www.libero-news.it/rss.jsp?sezione=17'),
|
||||||
|
(u'Cultura', u'http://www.libero-news.it/rss.jsp?sezione=18'),
|
||||||
|
(u'Scienze', u'http://www.libero-news.it/rss.jsp?sezione=19'),
|
||||||
|
(u'Tecnologia', u'http://www.libero-news.it/rss.jsp?sezione=20'),
|
||||||
|
(u'LifeStyle', u'http://www.libero-news.it/rss.jsp?sezione=22'),
|
||||||
|
(u'Sport', u'http://www.libero-news.it/rss.jsp?sezione=23'),
|
||||||
|
(u'Costume e Societ\xc3\xa0', u' http://www.libero-news.it/rss.jsp?sezione=24'),
|
||||||
|
(u'Milano', u'http://www.libero-news.it/rss.jsp?sezione=26'),
|
||||||
|
(u'Roma', u'http://www.libero-news.it/rss.jsp?sezione=27'),
|
||||||
|
(u'Alimentazione', u'http://www.libero-news.it/rss.jsp?sezione=29')
|
||||||
|
]
|
||||||
|
|
@ -23,7 +23,7 @@ class NewYorkReviewOfBooks(BasicNewsRecipe):
|
|||||||
no_javascript = True
|
no_javascript = True
|
||||||
needs_subscription = True
|
needs_subscription = True
|
||||||
|
|
||||||
keep_only_tags = [dict(id='article-body')]
|
keep_only_tags = [dict(id=['article-body','page-title'])]
|
||||||
remove_tags = [dict(attrs={'class':['article-tools', 'article-links',
|
remove_tags = [dict(attrs={'class':['article-tools', 'article-links',
|
||||||
'center advertisement']})]
|
'center advertisement']})]
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ class NewYorkReviewOfBooks(BasicNewsRecipe):
|
|||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
no_javascript = True
|
no_javascript = True
|
||||||
|
|
||||||
keep_only_tags = [dict(id='article-body')]
|
keep_only_tags = [dict(id=['article-body', 'page-title'])]
|
||||||
remove_tags = [dict(attrs={'class':['article-tools', 'article-links',
|
remove_tags = [dict(attrs={'class':['article-tools', 'article-links',
|
||||||
'center advertisement']})]
|
'center advertisement']})]
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ class Newsweek(BasicNewsRecipe):
|
|||||||
'articlecontent','photoBox', 'article columnist first']}, ]
|
'articlecontent','photoBox', 'article columnist first']}, ]
|
||||||
recursions = 1
|
recursions = 1
|
||||||
match_regexps = [r'http://www.newsweek.com/id/\S+/page/\d+']
|
match_regexps = [r'http://www.newsweek.com/id/\S+/page/\d+']
|
||||||
|
preprocess_regexps = [(re.compile(r'<!--.*?-->', re.DOTALL), lambda m: '')]
|
||||||
|
|
||||||
def find_title(self, section):
|
def find_title(self, section):
|
||||||
d = {'scope':'Scope', 'thetake':'The Take', 'features':'Features',
|
d = {'scope':'Scope', 'thetake':'The Take', 'features':'Features',
|
||||||
|
@ -5,7 +5,7 @@ __copyright__ = '2008-2010, Darko Miletic <darko.miletic at gmail.com>'
|
|||||||
www.nin.co.rs
|
www.nin.co.rs
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import re, urllib
|
import re
|
||||||
from calibre import strftime
|
from calibre import strftime
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
@ -16,13 +16,13 @@ class Nin(BasicNewsRecipe):
|
|||||||
publisher = 'NIN d.o.o.'
|
publisher = 'NIN d.o.o.'
|
||||||
category = 'news, politics, Serbia'
|
category = 'news, politics, Serbia'
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
|
delay = 1
|
||||||
oldest_article = 15
|
oldest_article = 15
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
needs_subscription = True
|
needs_subscription = True
|
||||||
remove_empty_feeds = True
|
remove_empty_feeds = True
|
||||||
PREFIX = 'http://www.nin.co.rs'
|
PREFIX = 'http://www.nin.co.rs'
|
||||||
INDEX = PREFIX + '/?change_lang=ls'
|
INDEX = PREFIX + '/?change_lang=ls'
|
||||||
LOGIN = PREFIX + '/?logout=true'
|
|
||||||
use_embedded_content = False
|
use_embedded_content = False
|
||||||
language = 'sr'
|
language = 'sr'
|
||||||
publication_type = 'magazine'
|
publication_type = 'magazine'
|
||||||
@ -41,14 +41,12 @@ class Nin(BasicNewsRecipe):
|
|||||||
|
|
||||||
def get_browser(self):
|
def get_browser(self):
|
||||||
br = BasicNewsRecipe.get_browser()
|
br = BasicNewsRecipe.get_browser()
|
||||||
br.open(self.INDEX)
|
|
||||||
if self.username is not None and self.password is not None:
|
if self.username is not None and self.password is not None:
|
||||||
data = urllib.urlencode({ 'login_name':self.username
|
br.open(self.INDEX)
|
||||||
,'login_password':self.password
|
br.select_form(name='form1')
|
||||||
,'imageField.x':'32'
|
br['login_name' ] = self.username
|
||||||
,'imageField.y':'15'
|
br['login_password'] = self.password
|
||||||
})
|
br.submit()
|
||||||
br.open(self.LOGIN,data)
|
|
||||||
return br
|
return br
|
||||||
|
|
||||||
keep_only_tags =[dict(name='td', attrs={'width':'520'})]
|
keep_only_tags =[dict(name='td', attrs={'width':'520'})]
|
||||||
|
148
resources/recipes/observer_gb.recipe
Normal file
148
resources/recipes/observer_gb.recipe
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
'''
|
||||||
|
http://www.guardian.co.uk/theobserver
|
||||||
|
'''
|
||||||
|
from calibre import strftime
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class Guardian(BasicNewsRecipe):
|
||||||
|
|
||||||
|
title = u'The Observer'
|
||||||
|
__author__ = 'jbambridge'
|
||||||
|
language = 'en_GB'
|
||||||
|
simultaneous_downloads = 5
|
||||||
|
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
remove_javascript = True
|
||||||
|
|
||||||
|
timefmt = ' [%a, %d %b %Y]'
|
||||||
|
|
||||||
|
filter_regexps = [r'r\.kelkoo\.com']
|
||||||
|
|
||||||
|
keep_only_tags = [
|
||||||
|
dict(name='div', attrs={'id':["content","article_header","main-article-info",]}),
|
||||||
|
]
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='div', attrs={'class':["video-content","videos-third-column"]}),
|
||||||
|
dict(name='div', attrs={'id':["article-toolbox","subscribe-feeds",]}),
|
||||||
|
dict(name='div', attrs={'class':["promo-component bookshop-books-promo bookshop-books"]}),
|
||||||
|
dict(name='ul', attrs={'class':["pagination"]}),
|
||||||
|
dict(name='ul', attrs={'id':["content-actions"]}),
|
||||||
|
dict(name='li', attrs={'id':["product-image"]}),
|
||||||
|
]
|
||||||
|
use_embedded_content = False
|
||||||
|
|
||||||
|
no_stylesheets = True
|
||||||
|
extra_css = '''
|
||||||
|
.article-attributes{font-size: x-small; font-family:Arial,Helvetica,sans-serif;}
|
||||||
|
.h1{font-size: large ;font-family:georgia,serif; font-weight:bold;}
|
||||||
|
.stand-first-alone{color:#666666; font-size:small; font-family:Arial,Helvetica,sans-serif;}
|
||||||
|
.caption{color:#666666; font-size:x-small; font-family:Arial,Helvetica,sans-serif;}
|
||||||
|
#article-wrapper{font-size:small; font-family:Arial,Helvetica,sans-serif;font-weight:normal;}
|
||||||
|
.main-article-info{font-family:Arial,Helvetica,sans-serif;}
|
||||||
|
#full-contents{font-size:small; font-family:Arial,Helvetica,sans-serif;font-weight:normal;}
|
||||||
|
#match-stats-summary{font-size:small; font-family:Arial,Helvetica,sans-serif;font-weight:normal;}
|
||||||
|
'''
|
||||||
|
|
||||||
|
feeds = [
|
||||||
|
(u'Main Section', u'feed://www.guardian.co.uk/theobserver/news/uknews/rss'),
|
||||||
|
(u'News', u'feed://www.guardian.co.uk/theobserver/news/rss'),
|
||||||
|
(u'World News', u'feed://www.guardian.co.uk/theobserver/news/worldnews/rss'),
|
||||||
|
(u'In Focus', u'feed://www.guardian.co.uk/theobserver/news/focus/rss'),
|
||||||
|
(u'7 Days', u'feed://www.guardian.co.uk/theobserver/news/7days/rss'),
|
||||||
|
(u'Seven Days', u'feed://www.guardian.co.uk/theobserver/news/seven-days/rss'),
|
||||||
|
(u'Media', u'feed://www.guardian.co.uk/theobserver/news/media/rss'),
|
||||||
|
(u'Business', u'feed://www.guardian.co.uk/theobserver/businessandmedia/rss'),
|
||||||
|
(u'Cash', u'feed://www.guardian.co.uk/theobserver/news/cash/rss'),
|
||||||
|
(u'Money', u'feed://feeds.guardian.co.uk/theguardian/money/rss'),
|
||||||
|
(u'Comment', u'feed://www.guardian.co.uk/theobserver/news/comment/rss'),
|
||||||
|
(u'Travel', u'feed://www.guardian.co.uk/theobserver/escape/rss'),
|
||||||
|
(u'Culture', u'feed://www.guardian.co.uk/theobserver/review/rss'),
|
||||||
|
(u'Money', u'feed://feeds.guardian.co.uk/theguardian/money/rss'),
|
||||||
|
(u'TV & Radio', u'feed://www.guardian.co.uk/tv-and-radio/rss'),
|
||||||
|
(u'New Review', u'feed://www.guardian.co.uk/theobserver/new-review/rss'),
|
||||||
|
(u'Agenda', u'feed://www.guardian.co.uk/theobserver/new-review/agenda/rss'),
|
||||||
|
(u'Critics', u'feed://www.guardian.co.uk/theobserver/new-review/critics/rss'),
|
||||||
|
(u'Features', u'feed://www.guardian.co.uk/theobserver/new-review/features/rss'),
|
||||||
|
(u'Discover', u'feed://www.guardian.co.uk/theobserver/new-review/discover/rss'),
|
||||||
|
(u'Books', u'feed://www.guardian.co.uk/theobserver/new-review/books/rss'),
|
||||||
|
(u'Magazine', u'feed://www.guardian.co.uk/theobserver/magazine/rss'),
|
||||||
|
(u'Regulars', u'feed://www.guardian.co.uk/theobserver/magazine/regulars/rss'),
|
||||||
|
(u'Life & Style', u'feed://www.guardian.co.uk/theobserver/magazine/life-and-style/rss'),
|
||||||
|
(u'Mag Features', u'feed://www.guardian.co.uk/theobserver/magazine/features2/rss'),
|
||||||
|
(u'Sport', u'feed://www.guardian.co.uk/theobserver/sport/rss')
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_article_url(self, article):
|
||||||
|
url = article.get('guid', None)
|
||||||
|
if '/video/' in url or '/flyer/' in url or '/quiz/' in url or \
|
||||||
|
'/gallery/' in url or 'ivebeenthere' in url or \
|
||||||
|
'pickthescore' in url or 'audioslideshow' in url :
|
||||||
|
url = None
|
||||||
|
return url
|
||||||
|
|
||||||
|
def preprocess_html(self, soup):
|
||||||
|
|
||||||
|
for item in soup.findAll(style=True):
|
||||||
|
del item['style']
|
||||||
|
|
||||||
|
for item in soup.findAll(face=True):
|
||||||
|
del item['face']
|
||||||
|
for tag in soup.findAll(name=['ul','li']):
|
||||||
|
tag.name = 'div'
|
||||||
|
|
||||||
|
return soup
|
||||||
|
|
||||||
|
def find_sections(self):
|
||||||
|
soup = self.index_to_soup('http://www.guardian.co.uk/theobserver')
|
||||||
|
# find cover pic
|
||||||
|
img = soup.find( 'img',attrs ={'alt':'Guardian digital edition'})
|
||||||
|
if img is not None:
|
||||||
|
self.cover_url = img['src']
|
||||||
|
# end find cover pic
|
||||||
|
|
||||||
|
idx = soup.find('div', id='book-index')
|
||||||
|
for s in idx.findAll('strong', attrs={'class':'book'}):
|
||||||
|
a = s.find('a', href=True)
|
||||||
|
yield (self.tag_to_string(a), a['href'])
|
||||||
|
|
||||||
|
def find_articles(self, url):
|
||||||
|
soup = self.index_to_soup(url)
|
||||||
|
div = soup.find('div', attrs={'class':'book-index'})
|
||||||
|
for ul in div.findAll('ul', attrs={'class':'trailblock'}):
|
||||||
|
for li in ul.findAll('li'):
|
||||||
|
a = li.find(href=True)
|
||||||
|
if not a:
|
||||||
|
continue
|
||||||
|
title = self.tag_to_string(a)
|
||||||
|
url = a['href']
|
||||||
|
if not title or not url:
|
||||||
|
continue
|
||||||
|
tt = li.find('div', attrs={'class':'trailtext'})
|
||||||
|
if tt is not None:
|
||||||
|
for da in tt.findAll('a'): da.extract()
|
||||||
|
desc = self.tag_to_string(tt).strip()
|
||||||
|
yield {
|
||||||
|
'title': title, 'url':url, 'description':desc,
|
||||||
|
'date' : strftime('%a, %d %b'),
|
||||||
|
}
|
||||||
|
|
||||||
|
def parse_index(self):
|
||||||
|
try:
|
||||||
|
feeds = []
|
||||||
|
for title, href in self.find_sections():
|
||||||
|
feeds.append((title, list(self.find_articles(href))))
|
||||||
|
return feeds
|
||||||
|
except:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
def postprocess_html(self,soup,first):
|
||||||
|
return soup.findAll('html')[0]
|
||||||
|
|
||||||
|
|
30
resources/recipes/politifact.recipe
Normal file
30
resources/recipes/politifact.recipe
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class PolitiFactCom(BasicNewsRecipe):
|
||||||
|
title = u'Politifact'
|
||||||
|
__author__ = u'Michael Heinz'
|
||||||
|
oldest_article = 21
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
recursion = 0
|
||||||
|
language = 'en'
|
||||||
|
|
||||||
|
no_stylesheets = True
|
||||||
|
|
||||||
|
publication_type = 'magazine'
|
||||||
|
masthead_url = 'http://static.politifact.com.s3.amazonaws.com/images/politifactdotcom-flag-fff_01.png'
|
||||||
|
cover_url = 'http://static.politifact.com.s3.amazonaws.com/images/politifactdotcom-flag-fff_01.png'
|
||||||
|
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='div', attrs={'class':'pfstoryarchive'}),
|
||||||
|
dict(name='div', attrs={'class':'pfhead'}),
|
||||||
|
dict(name='div', attrs={'class':'boxmid'}),
|
||||||
|
]
|
||||||
|
|
||||||
|
keep_only_tags = [dict(name='div', attrs={'class':'pfcontentleft'})]
|
||||||
|
feeds = [
|
||||||
|
(u'Articles', u'http://www.politifact.com/feeds/articles/truth-o-meter/'),
|
||||||
|
(u'Obamameter', u'http://politifact.com/feeds/updates/'),
|
||||||
|
(u'Statements', u'http://www.politifact.com/feeds/statements/truth-o-meter/')
|
||||||
|
]
|
||||||
|
|
||||||
|
|
@ -8,6 +8,7 @@ class SeanHannity(BasicNewsRecipe):
|
|||||||
__author__ = 'Rob Lammert - rob.lammert[at]gmail.com'
|
__author__ = 'Rob Lammert - rob.lammert[at]gmail.com'
|
||||||
description = u"Articles from Sean Hannity's website, www.hannity.com"
|
description = u"Articles from Sean Hannity's website, www.hannity.com"
|
||||||
oldest_article = 7.0
|
oldest_article = 7.0
|
||||||
|
language = 'en'
|
||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
recursions = 0
|
recursions = 0
|
||||||
encoding = 'utf8'
|
encoding = 'utf8'
|
||||||
|
86
resources/recipes/tagesspiegel.recipe
Normal file
86
resources/recipes/tagesspiegel.recipe
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010 Ingo Paschke <ipaschke@gmail.com>'
|
||||||
|
|
||||||
|
'''
|
||||||
|
Fetch Tagesspiegel.
|
||||||
|
'''
|
||||||
|
import string, re
|
||||||
|
from calibre import strftime
|
||||||
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
|
|
||||||
|
class TagesspiegelRSS(BasicNewsRecipe):
|
||||||
|
title = u'Der Tagesspiegel'
|
||||||
|
__author__ = 'ipaschke'
|
||||||
|
language = 'de'
|
||||||
|
oldest_article = 7
|
||||||
|
max_articles_per_feed = 100
|
||||||
|
|
||||||
|
extra_css = '''
|
||||||
|
.hcf-overline{color:#990000; font-family:Arial,Helvetica,sans-serif;font-size:xx-small;display:block}
|
||||||
|
.hcf-teaser{font-family:Verdana,Arial,Helvetica;font-size:x-small;margin-top:0}
|
||||||
|
h1{font-family:Arial,Helvetica,sans-serif;font-size:large;clear:right;}
|
||||||
|
.hcf-caption{color:#666666; font-family:Arial,Helvetica,sans-serif;font-size:xx-small;}
|
||||||
|
.hcf-copyright{color:#666666; font-family:Arial,Helvetica,sans-serif;font-size:xx-small;}
|
||||||
|
.hcf-article{font-family:Arial,Helvetica;font-size:x-small}
|
||||||
|
.quote{font-family:Georgia,Palatino,Palatino Linotype,FreeSerif,serif;font-size:x-small}
|
||||||
|
.quote .cite{font-family:Georgia,Palatino,Palatino Linotype,FreeSerif,serif;font-size:xx-small}
|
||||||
|
.hcf-inline-left{float:left;margin-right:15px;position:relative;}
|
||||||
|
.hcf-inline-right{float:right;margin-right:15px;position:relative;}
|
||||||
|
.hcf-smart-box{font-family: Arial, Helvetica, sans-serif; font-size: xx-small; margin: 0px 15px 8px 0px; width: 300px;}
|
||||||
|
'''
|
||||||
|
|
||||||
|
no_stylesheets = True
|
||||||
|
no_javascript = True
|
||||||
|
remove_empty_feeds = True
|
||||||
|
encoding = 'utf-8'
|
||||||
|
|
||||||
|
keep_only_tags = dict(name='div', attrs={'class':["hcf-article"]})
|
||||||
|
remove_tags = [
|
||||||
|
dict(name='link'), dict(name='iframe'),dict(name='style'),dict(name='meta'),dict(name='button'),
|
||||||
|
dict(name='div', attrs={'class':["hcf-jump-to-comments","hcf-clear","hcf-magnify hcf-media-control"] }),
|
||||||
|
dict(name='span', attrs={'class':["hcf-mainsearch",] }),
|
||||||
|
dict(name='ul', attrs={'class':["hcf-tools"] }),
|
||||||
|
]
|
||||||
|
|
||||||
|
def parse_index(self):
|
||||||
|
soup = self.index_to_soup('http://www.tagesspiegel.de/zeitung/')
|
||||||
|
|
||||||
|
def feed_title(div):
|
||||||
|
return ''.join(div.findAll(text=True, recursive=False)).strip()
|
||||||
|
|
||||||
|
articles = {}
|
||||||
|
key = None
|
||||||
|
ans = []
|
||||||
|
|
||||||
|
for div in soup.findAll(True, attrs={'class':['hcf-teaser', 'hcf-header', 'story headline']}):
|
||||||
|
|
||||||
|
if div['class'] == 'hcf-header':
|
||||||
|
key = string.capwords(feed_title(div.em.a))
|
||||||
|
articles[key] = []
|
||||||
|
ans.append(key)
|
||||||
|
|
||||||
|
elif div['class'] == 'hcf-teaser' and getattr(div.contents[0],'name','') == 'h2':
|
||||||
|
a = div.find('a', href=True)
|
||||||
|
if not a:
|
||||||
|
continue
|
||||||
|
url = 'http://www.tagesspiegel.de' + a['href']
|
||||||
|
title = self.tag_to_string(a, use_alt=True).strip()
|
||||||
|
description = ''
|
||||||
|
pubdate = strftime('%a, %d %b')
|
||||||
|
summary = div.find('p', attrs={'class':'hcf-teaser'})
|
||||||
|
if summary:
|
||||||
|
description = self.tag_to_string(summary, use_alt=False)
|
||||||
|
|
||||||
|
feed = key if key is not None else 'Uncategorized'
|
||||||
|
if not articles.has_key(feed):
|
||||||
|
articles[feed] = []
|
||||||
|
if not 'podcasts' in url:
|
||||||
|
articles[feed].append(
|
||||||
|
dict(title=title, url=url, date=pubdate,
|
||||||
|
description=re.sub('mehr$', '', description),
|
||||||
|
content=''))
|
||||||
|
|
||||||
|
ans = [(key, articles[key]) for key in ans if articles.has_key(key)]
|
||||||
|
|
||||||
|
return ans
|
||||||
|
|
@ -5,6 +5,7 @@ __copyright__ = '2008-2009, Darko Miletic <darko.miletic at gmail.com>'
|
|||||||
'''
|
'''
|
||||||
timesonline.co.uk
|
timesonline.co.uk
|
||||||
'''
|
'''
|
||||||
|
import re
|
||||||
|
|
||||||
from calibre.web.feeds.news import BasicNewsRecipe
|
from calibre.web.feeds.news import BasicNewsRecipe
|
||||||
from calibre.ebooks.BeautifulSoup import Tag
|
from calibre.ebooks.BeautifulSoup import Tag
|
||||||
@ -26,6 +27,8 @@ class Timesonline(BasicNewsRecipe):
|
|||||||
recursions = 9
|
recursions = 9
|
||||||
match_regexps = [r'http://www.timesonline.co.uk/.*page=[2-9]']
|
match_regexps = [r'http://www.timesonline.co.uk/.*page=[2-9]']
|
||||||
|
|
||||||
|
preprocess_regexps = [(re.compile(r'<!--.*?-->', re.DOTALL), lambda m: '')]
|
||||||
|
|
||||||
keep_only_tags = [
|
keep_only_tags = [
|
||||||
dict(name='div', attrs= {'id':['region-column1and2-layout2']}),
|
dict(name='div', attrs= {'id':['region-column1and2-layout2']}),
|
||||||
{'class' : ['subheading']},
|
{'class' : ['subheading']},
|
||||||
@ -76,8 +79,7 @@ class Timesonline(BasicNewsRecipe):
|
|||||||
soup = self.index_to_soup(index)
|
soup = self.index_to_soup(index)
|
||||||
link_item = soup.find(name = 'div',attrs ={'class': "float-left margin-right-15"})
|
link_item = soup.find(name = 'div',attrs ={'class': "float-left margin-right-15"})
|
||||||
if link_item:
|
if link_item:
|
||||||
cover_url = 'http://www.timesonline.co.uk' + link_item.img['src']
|
cover_url = link_item.img['src']
|
||||||
print cover_url
|
|
||||||
return cover_url
|
return cover_url
|
||||||
|
|
||||||
def get_article_url(self, article):
|
def get_article_url(self, article):
|
||||||
@ -85,9 +87,9 @@ class Timesonline(BasicNewsRecipe):
|
|||||||
|
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
def preprocess_html(self, soup):
|
||||||
soup.html['xml:lang'] = self.lang
|
soup.html['xml:lang'] = self.language
|
||||||
soup.html['lang'] = self.lang
|
soup.html['lang'] = self.language
|
||||||
mlang = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.lang)])
|
mlang = Tag(soup,'meta',[("http-equiv","Content-Language"),("content",self.language)])
|
||||||
mcharset = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset=ISO-8859-1")])
|
mcharset = Tag(soup,'meta',[("http-equiv","Content-Type"),("content","text/html; charset=ISO-8859-1")])
|
||||||
soup.head.insert(0,mlang)
|
soup.head.insert(0,mlang)
|
||||||
soup.head.insert(1,mcharset)
|
soup.head.insert(1,mcharset)
|
||||||
|
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
__appname__ = 'calibre'
|
__appname__ = 'calibre'
|
||||||
__version__ = '0.6.53'
|
__version__ = '0.6.54'
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
@ -450,9 +450,9 @@ from calibre.devices.eslick.driver import ESLICK
|
|||||||
from calibre.devices.nuut2.driver import NUUT2
|
from calibre.devices.nuut2.driver import NUUT2
|
||||||
from calibre.devices.iriver.driver import IRIVER_STORY
|
from calibre.devices.iriver.driver import IRIVER_STORY
|
||||||
from calibre.devices.binatone.driver import README
|
from calibre.devices.binatone.driver import README
|
||||||
from calibre.devices.hanvon.driver import N516, EB511, ALEX, AZBOOKA
|
from calibre.devices.hanvon.driver import N516, EB511, ALEX, AZBOOKA, THEBOOK
|
||||||
from calibre.devices.edge.driver import EDGE
|
from calibre.devices.edge.driver import EDGE
|
||||||
from calibre.devices.teclast.driver import TECLAST_K3
|
from calibre.devices.teclast.driver import TECLAST_K3, NEWSMY, IPAPYRUS
|
||||||
from calibre.devices.sne.driver import SNE
|
from calibre.devices.sne.driver import SNE
|
||||||
from calibre.devices.misc import PALMPRE, KOBO, AVANT
|
from calibre.devices.misc import PALMPRE, KOBO, AVANT
|
||||||
|
|
||||||
@ -530,9 +530,12 @@ plugins += [
|
|||||||
EB600,
|
EB600,
|
||||||
README,
|
README,
|
||||||
N516,
|
N516,
|
||||||
|
THEBOOK,
|
||||||
EB511,
|
EB511,
|
||||||
ELONEX,
|
ELONEX,
|
||||||
TECLAST_K3,
|
TECLAST_K3,
|
||||||
|
NEWSMY,
|
||||||
|
IPAPYRUS,
|
||||||
EDGE,
|
EDGE,
|
||||||
SNE,
|
SNE,
|
||||||
ALEX,
|
ALEX,
|
||||||
|
@ -245,6 +245,8 @@ class iPadOutput(OutputProfile):
|
|||||||
|
|
||||||
name = 'iPad'
|
name = 'iPad'
|
||||||
short_name = 'ipad'
|
short_name = 'ipad'
|
||||||
|
description = _('Intended for the iPad and similar devices with a '
|
||||||
|
'resolution of 768x1024')
|
||||||
screen_size = (768, 1024)
|
screen_size = (768, 1024)
|
||||||
comic_screen_size = (768, 1024)
|
comic_screen_size = (768, 1024)
|
||||||
dpi = 132.0
|
dpi = 132.0
|
||||||
|
@ -24,6 +24,9 @@ class ANDROID(USBMS):
|
|||||||
# Motorola
|
# Motorola
|
||||||
0x22b8 : { 0x41d9 : [0x216], 0x2d67 : [0x100], 0x41db : [0x216]},
|
0x22b8 : { 0x41d9 : [0x216], 0x2d67 : [0x100], 0x41db : [0x216]},
|
||||||
|
|
||||||
|
# Sony Ericsson
|
||||||
|
0xfce : { 0xd12e : [0x0100]},
|
||||||
|
|
||||||
0x18d1 : { 0x4e11 : [0x0100, 0x226], 0x4e12: [0x0100, 0x226]},
|
0x18d1 : { 0x4e11 : [0x0100, 0x226], 0x4e12: [0x0100, 0x226]},
|
||||||
|
|
||||||
# Samsung
|
# Samsung
|
||||||
|
@ -24,7 +24,7 @@ class N516(USBMS):
|
|||||||
|
|
||||||
VENDOR_ID = [0x0525]
|
VENDOR_ID = [0x0525]
|
||||||
PRODUCT_ID = [0xa4a5]
|
PRODUCT_ID = [0xa4a5]
|
||||||
BCD = [0x323, 0x326, 0x399]
|
BCD = [0x323, 0x326]
|
||||||
|
|
||||||
VENDOR_NAME = 'INGENIC'
|
VENDOR_NAME = 'INGENIC'
|
||||||
WINDOWS_MAIN_MEM = '_FILE-STOR_GADGE'
|
WINDOWS_MAIN_MEM = '_FILE-STOR_GADGE'
|
||||||
@ -34,6 +34,16 @@ class N516(USBMS):
|
|||||||
EBOOK_DIR_MAIN = 'e_book'
|
EBOOK_DIR_MAIN = 'e_book'
|
||||||
SUPPORTS_SUB_DIRS = True
|
SUPPORTS_SUB_DIRS = True
|
||||||
|
|
||||||
|
class THEBOOK(N516):
|
||||||
|
name = 'The Book driver'
|
||||||
|
gui_name = 'The Book'
|
||||||
|
description = _('Communicate with The Book reader.')
|
||||||
|
author = 'Kovid Goyal'
|
||||||
|
|
||||||
|
BCD = [0x399]
|
||||||
|
MAIN_MEMORY_VOLUME_LABEL = 'The Book Main Memory'
|
||||||
|
EBOOK_DIR_MAIN = 'My books'
|
||||||
|
|
||||||
class ALEX(N516):
|
class ALEX(N516):
|
||||||
|
|
||||||
name = 'Alex driver'
|
name = 'Alex driver'
|
||||||
|
@ -34,6 +34,6 @@ class Worker(threading.Thread):
|
|||||||
def run(self):
|
def run(self):
|
||||||
'''Thread loops taking jobs from the queue as they become available'''
|
'''Thread loops taking jobs from the queue as they become available'''
|
||||||
while True:
|
while True:
|
||||||
job = self.jobs.get(True, None)
|
self.jobs.get(True, None)
|
||||||
# Do job
|
# Do job
|
||||||
self.jobs.task_done()
|
self.jobs.task_done()
|
@ -17,10 +17,10 @@ class PALMPRE(USBMS):
|
|||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
|
|
||||||
# Ordered list of supported formats
|
# Ordered list of supported formats
|
||||||
FORMATS = ['mobi', 'prc', 'pdb', 'txt']
|
FORMATS = ['epub', 'mobi', 'prc', 'pdb', 'txt']
|
||||||
|
|
||||||
VENDOR_ID = [0x0830]
|
VENDOR_ID = [0x0830]
|
||||||
PRODUCT_ID = [0x8004, 0x8002]
|
PRODUCT_ID = [0x8004, 0x8002, 0x0101]
|
||||||
BCD = [0x0316]
|
BCD = [0x0316]
|
||||||
|
|
||||||
VENDOR_NAME = 'PALM'
|
VENDOR_NAME = 'PALM'
|
||||||
@ -48,6 +48,7 @@ class KOBO(USBMS):
|
|||||||
WINDOWS_MAIN_MEM = '.KOBOEREADER'
|
WINDOWS_MAIN_MEM = '.KOBOEREADER'
|
||||||
|
|
||||||
EBOOK_DIR_MAIN = ''
|
EBOOK_DIR_MAIN = ''
|
||||||
|
SUPPORTS_SUB_DIRS = True
|
||||||
|
|
||||||
class AVANT(USBMS):
|
class AVANT(USBMS):
|
||||||
name = 'Booq Avant Device Interface'
|
name = 'Booq Avant Device Interface'
|
||||||
|
@ -39,4 +39,28 @@ class TECLAST_K3(USBMS):
|
|||||||
|
|
||||||
return drives
|
return drives
|
||||||
|
|
||||||
|
class NEWSMY(TECLAST_K3):
|
||||||
|
name = 'Newsmy device interface'
|
||||||
|
gui_name = 'Newsmy'
|
||||||
|
description = _('Communicate with the Newsmy reader.')
|
||||||
|
|
||||||
|
FORMATS = ['epub', 'fb2', 'pdb', 'html', 'pdf', 'txt', 'skt']
|
||||||
|
|
||||||
|
VENDOR_NAME = ''
|
||||||
|
WINDOWS_MAIN_MEM = 'NEWSMY'
|
||||||
|
WINDOWS_CARD_A_MEM = 'USBDISK____SD'
|
||||||
|
|
||||||
|
def windows_sort_drives(self, drives):
|
||||||
|
return drives
|
||||||
|
|
||||||
|
class IPAPYRUS(TECLAST_K3):
|
||||||
|
|
||||||
|
name = 'iPapyrus device interface'
|
||||||
|
gui_name = 'iPapyrus'
|
||||||
|
description = _('Communicate with the iPapyrus reader.')
|
||||||
|
|
||||||
|
FORMATS = ['epub', 'pdf', 'txt']
|
||||||
|
|
||||||
|
VENDOR_NAME = 'E_READER'
|
||||||
|
WINDOWS_MAIN_MEM = ''
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ def detect(aBuf):
|
|||||||
ENCODING_PATS = [
|
ENCODING_PATS = [
|
||||||
re.compile(r'<\?[^<>]+encoding=[\'"](.*?)[\'"][^<>]*>',
|
re.compile(r'<\?[^<>]+encoding=[\'"](.*?)[\'"][^<>]*>',
|
||||||
re.IGNORECASE),
|
re.IGNORECASE),
|
||||||
re.compile(r'<meta.*?content=[\'"].*?charset=([^\s\'"]+).*?[\'"].*?>',
|
re.compile(r'''<meta\s+?[^<>]+?content=['"][^'"]*?charset=([-a-z0-9]+)[^'"]*?['"][^<>]*>''',
|
||||||
re.IGNORECASE)
|
re.IGNORECASE)
|
||||||
]
|
]
|
||||||
ENTITY_PATTERN = re.compile(r'&(\S+?);')
|
ENTITY_PATTERN = re.compile(r'&(\S+?);')
|
||||||
|
@ -15,6 +15,7 @@ from calibre.ptempfile import PersistentTemporaryDirectory
|
|||||||
from calibre.utils.date import parse_date
|
from calibre.utils.date import parse_date
|
||||||
from calibre.utils.zipfile import ZipFile
|
from calibre.utils.zipfile import ZipFile
|
||||||
from calibre import extract, walk
|
from calibre import extract, walk
|
||||||
|
from calibre.constants import __version__
|
||||||
|
|
||||||
DEBUG_README=u'''
|
DEBUG_README=u'''
|
||||||
This debug directory contains snapshots of the e-book as it passes through the
|
This debug directory contains snapshots of the e-book as it passes through the
|
||||||
@ -410,6 +411,18 @@ OptionRecommendation(name='asciiize',
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
OptionRecommendation(name='keep_ligatures',
|
||||||
|
recommended_value=False, level=OptionRecommendation.LOW,
|
||||||
|
help=_('Preserve ligatures present in the input document. '
|
||||||
|
'A ligature is a special rendering of a pair of '
|
||||||
|
'characters like ff, fi, fl et cetera. '
|
||||||
|
'Most readers do not have support for '
|
||||||
|
'ligatures in their default fonts, so they are '
|
||||||
|
'unlikely to render correctly. By default, calibre '
|
||||||
|
'will turn a ligature into the corresponding pair of normal '
|
||||||
|
'characters. This option will preserve them instead.')
|
||||||
|
),
|
||||||
|
|
||||||
OptionRecommendation(name='title',
|
OptionRecommendation(name='title',
|
||||||
recommended_value=None, level=OptionRecommendation.LOW,
|
recommended_value=None, level=OptionRecommendation.LOW,
|
||||||
help=_('Set the title.')),
|
help=_('Set the title.')),
|
||||||
@ -711,6 +724,7 @@ OptionRecommendation(name='timestamp',
|
|||||||
if self.opts.verbose > 1:
|
if self.opts.verbose > 1:
|
||||||
self.log.debug('Resolved conversion options')
|
self.log.debug('Resolved conversion options')
|
||||||
try:
|
try:
|
||||||
|
self.log.debug('calibre version:', __version__)
|
||||||
self.log.debug(pprint.pformat(self.opts.__dict__))
|
self.log.debug(pprint.pformat(self.opts.__dict__))
|
||||||
except:
|
except:
|
||||||
self.log.exception('Failed to get resolved conversion options')
|
self.log.exception('Failed to get resolved conversion options')
|
||||||
|
@ -18,6 +18,24 @@ convert_entities = functools.partial(entity_to_unicode, exceptions=['quot',
|
|||||||
'apos', 'lt', 'gt', 'amp', '#60', '#62'])
|
'apos', 'lt', 'gt', 'amp', '#60', '#62'])
|
||||||
_span_pat = re.compile('<span.*?</span>', re.DOTALL|re.IGNORECASE)
|
_span_pat = re.compile('<span.*?</span>', re.DOTALL|re.IGNORECASE)
|
||||||
|
|
||||||
|
LIGATURES = {
|
||||||
|
u'\u00c6': u'AE',
|
||||||
|
u'\u00e6': u'ae',
|
||||||
|
u'\u0152': u'OE',
|
||||||
|
u'\u0153': u'oe',
|
||||||
|
u'\u0132': u'IJ',
|
||||||
|
u'\u0133': u'ij',
|
||||||
|
u'\u1D6B': u'ue',
|
||||||
|
u'\uFB00': u'ff',
|
||||||
|
u'\uFB01': u'fi',
|
||||||
|
u'\uFB02': u'fl',
|
||||||
|
u'\uFB03': u'ffi',
|
||||||
|
u'\uFB04': u'ffl',
|
||||||
|
u'\uFB05': u'ft',
|
||||||
|
u'\uFB06': u'st',
|
||||||
|
}
|
||||||
|
|
||||||
|
_ligpat = re.compile(u'|'.join(LIGATURES))
|
||||||
|
|
||||||
def sanitize_head(match):
|
def sanitize_head(match):
|
||||||
x = match.group(1)
|
x = match.group(1)
|
||||||
@ -228,6 +246,9 @@ class HTMLPreProcessor(object):
|
|||||||
else:
|
else:
|
||||||
rules = []
|
rules = []
|
||||||
|
|
||||||
|
if not self.extra_opts.keep_ligatures:
|
||||||
|
html = _ligpat.sub(lambda m:LIGATURES[m.group()], html)
|
||||||
|
|
||||||
end_rules = []
|
end_rules = []
|
||||||
if getattr(self.extra_opts, 'remove_header', None):
|
if getattr(self.extra_opts, 'remove_header', None):
|
||||||
try:
|
try:
|
||||||
|
@ -37,8 +37,13 @@ class EPUBInput(InputFormatPlugin):
|
|||||||
scheme = item.get(xkey)
|
scheme = item.get(xkey)
|
||||||
if (scheme and scheme.lower() == 'uuid') or \
|
if (scheme and scheme.lower() == 'uuid') or \
|
||||||
(item.text and item.text.startswith('urn:uuid:')):
|
(item.text and item.text.startswith('urn:uuid:')):
|
||||||
key = str(item.text).rpartition(':')[-1]
|
try:
|
||||||
key = list(map(ord, uuid.UUID(key).bytes))
|
key = str(item.text).rpartition(':')[-1]
|
||||||
|
key = list(map(ord, uuid.UUID(key).bytes))
|
||||||
|
except:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
key = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
root = etree.parse(encfile)
|
root = etree.parse(encfile)
|
||||||
@ -49,7 +54,7 @@ class EPUBInput(InputFormatPlugin):
|
|||||||
cr = em.getparent().xpath('descendant::*[contains(name(), "CipherReference")]')[0]
|
cr = em.getparent().xpath('descendant::*[contains(name(), "CipherReference")]')[0]
|
||||||
uri = cr.get('URI')
|
uri = cr.get('URI')
|
||||||
path = os.path.abspath(os.path.join(os.path.dirname(encfile), '..', *uri.split('/')))
|
path = os.path.abspath(os.path.join(os.path.dirname(encfile), '..', *uri.split('/')))
|
||||||
if os.path.exists(path):
|
if key is not None and os.path.exists(path):
|
||||||
self._encrypted_font_uris.append(uri)
|
self._encrypted_font_uris.append(uri)
|
||||||
self.decrypt_font(key, path)
|
self.decrypt_font(key, path)
|
||||||
return True
|
return True
|
||||||
|
@ -7,12 +7,10 @@ __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os, shutil, re
|
import os, shutil, re
|
||||||
from urllib import unquote
|
|
||||||
|
|
||||||
from calibre.customize.conversion import OutputFormatPlugin
|
from calibre.customize.conversion import OutputFormatPlugin
|
||||||
from calibre.ptempfile import TemporaryDirectory
|
from calibre.ptempfile import TemporaryDirectory
|
||||||
from calibre.constants import __appname__, __version__
|
from calibre import CurrentDir
|
||||||
from calibre import guess_type, CurrentDir
|
|
||||||
from calibre.customize.conversion import OptionRecommendation
|
from calibre.customize.conversion import OptionRecommendation
|
||||||
from calibre.constants import filesystem_encoding
|
from calibre.constants import filesystem_encoding
|
||||||
|
|
||||||
@ -92,51 +90,21 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
'as a blank page.')
|
'as a blank page.')
|
||||||
),
|
),
|
||||||
|
|
||||||
|
OptionRecommendation(name='preserve_cover_aspect_ratio',
|
||||||
|
recommended_value=False, help=_(
|
||||||
|
'When using an SVG cover, this option will cause the cover to scale '
|
||||||
|
'to cover the available screen area, but still preserve its aspect ratio '
|
||||||
|
'(ratio of width to height). That means there may be white borders '
|
||||||
|
'at the sides or top and bottom of the image, but the image will '
|
||||||
|
'never be distorted. Without this option the image may be slightly '
|
||||||
|
'distorted, but there will be no borders.'
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
recommendations = set([('pretty_print', True, OptionRecommendation.HIGH)])
|
recommendations = set([('pretty_print', True, OptionRecommendation.HIGH)])
|
||||||
|
|
||||||
NONSVG_TITLEPAGE_COVER = '''\
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<meta name="calibre:cover" content="true" />
|
|
||||||
<title>Cover</title>
|
|
||||||
<style type="text/css" title="override_css">
|
|
||||||
@page {padding: 0pt; margin:0pt}
|
|
||||||
body { text-align: center; padding:0pt; margin: 0pt; }
|
|
||||||
div { padding:0pt; margin: 0pt; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div>
|
|
||||||
<img src="%s" alt="cover" style="height: 100%%" />
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
'''
|
|
||||||
|
|
||||||
TITLEPAGE_COVER = '''\
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<meta name="calibre:cover" content="true" />
|
|
||||||
<title>Cover</title>
|
|
||||||
<style type="text/css" title="override_css">
|
|
||||||
@page {padding: 0pt; margin:0pt}
|
|
||||||
body { text-align: center; padding:0pt; margin: 0pt; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
width="100%%" height="100%%" viewBox="0 0 600 800"
|
|
||||||
preserveAspectRatio="xMidYMid meet">
|
|
||||||
<image width="600" height="800" xlink:href="%s"/>
|
|
||||||
</svg>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
'''
|
|
||||||
|
|
||||||
def workaround_webkit_quirks(self):
|
def workaround_webkit_quirks(self):
|
||||||
from calibre.ebooks.oeb.base import XPath
|
from calibre.ebooks.oeb.base import XPath
|
||||||
@ -167,7 +135,12 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
)
|
)
|
||||||
split(self.oeb, self.opts)
|
split(self.oeb, self.opts)
|
||||||
|
|
||||||
self.insert_cover()
|
from calibre.ebooks.oeb.transforms.cover import CoverManager
|
||||||
|
cm = CoverManager(
|
||||||
|
no_default_cover=self.opts.no_default_epub_cover,
|
||||||
|
no_svg_cover=self.opts.no_svg_cover,
|
||||||
|
preserve_aspect_ratio=self.opts.preserve_cover_aspect_ratio)
|
||||||
|
cm(self.oeb, self.opts, self.log)
|
||||||
|
|
||||||
self.workaround_sony_quirks()
|
self.workaround_sony_quirks()
|
||||||
|
|
||||||
@ -259,97 +232,6 @@ class EPUBOutput(OutputFormatPlugin):
|
|||||||
ans += '\n</encryption>'
|
ans += '\n</encryption>'
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def default_cover(self):
|
|
||||||
'''
|
|
||||||
Create a generic cover for books that dont have a cover
|
|
||||||
'''
|
|
||||||
from calibre.utils.pil_draw import draw_centered_text
|
|
||||||
from calibre.ebooks.metadata import authors_to_string
|
|
||||||
if self.opts.no_default_epub_cover:
|
|
||||||
return None
|
|
||||||
self.log('Generating default cover')
|
|
||||||
m = self.oeb.metadata
|
|
||||||
title = unicode(m.title[0])
|
|
||||||
authors = [unicode(x) for x in m.creator if x.role == 'aut']
|
|
||||||
|
|
||||||
import cStringIO
|
|
||||||
cover_file = cStringIO.StringIO()
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
|
||||||
Image, ImageDraw, ImageFont
|
|
||||||
except ImportError:
|
|
||||||
import Image, ImageDraw, ImageFont
|
|
||||||
font_path = P('fonts/liberation/LiberationSerif-Bold.ttf')
|
|
||||||
app = '['+__appname__ +' '+__version__+']'
|
|
||||||
|
|
||||||
COVER_WIDTH, COVER_HEIGHT = 590, 750
|
|
||||||
img = Image.new('RGB', (COVER_WIDTH, COVER_HEIGHT), 'white')
|
|
||||||
draw = ImageDraw.Draw(img)
|
|
||||||
# Title
|
|
||||||
font = ImageFont.truetype(font_path, 44)
|
|
||||||
bottom = draw_centered_text(img, draw, font, title, 15, ysep=9)
|
|
||||||
# Authors
|
|
||||||
bottom += 14
|
|
||||||
font = ImageFont.truetype(font_path, 32)
|
|
||||||
authors = authors_to_string(authors)
|
|
||||||
bottom = draw_centered_text(img, draw, font, authors, bottom, ysep=7)
|
|
||||||
# Vanity
|
|
||||||
font = ImageFont.truetype(font_path, 28)
|
|
||||||
width, height = draw.textsize(app, font=font)
|
|
||||||
left = max(int((COVER_WIDTH - width)/2.), 0)
|
|
||||||
top = COVER_HEIGHT - height - 15
|
|
||||||
draw.text((left, top), app, fill=(0,0,0), font=font)
|
|
||||||
# Logo
|
|
||||||
logo = Image.open(I('library.png'), 'r')
|
|
||||||
width, height = logo.size
|
|
||||||
left = max(int((COVER_WIDTH - width)/2.), 0)
|
|
||||||
top = max(int((COVER_HEIGHT - height)/2.), 0)
|
|
||||||
img.paste(logo, (left, max(bottom, top)))
|
|
||||||
img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE)
|
|
||||||
|
|
||||||
img.convert('RGB').save(cover_file, 'JPEG')
|
|
||||||
cover_file.flush()
|
|
||||||
id, href = self.oeb.manifest.generate('cover_image', 'cover_image.jpg')
|
|
||||||
item = self.oeb.manifest.add(id, href, guess_type('t.jpg')[0],
|
|
||||||
data=cover_file.getvalue())
|
|
||||||
m.clear('cover')
|
|
||||||
m.add('cover', item.id)
|
|
||||||
|
|
||||||
return item.href
|
|
||||||
except:
|
|
||||||
self.log.exception('Failed to generate default cover')
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def insert_cover(self):
|
|
||||||
from calibre.ebooks.oeb.base import urldefrag
|
|
||||||
from calibre import guess_type
|
|
||||||
g, m = self.oeb.guide, self.oeb.manifest
|
|
||||||
item = None
|
|
||||||
if 'titlepage' not in g:
|
|
||||||
if 'cover' in g:
|
|
||||||
href = g['cover'].href
|
|
||||||
else:
|
|
||||||
href = self.default_cover()
|
|
||||||
if href is not None:
|
|
||||||
templ = self.NONSVG_TITLEPAGE_COVER if self.opts.no_svg_cover \
|
|
||||||
else self.TITLEPAGE_COVER
|
|
||||||
tp = templ%unquote(href)
|
|
||||||
id, href = m.generate('titlepage', 'titlepage.xhtml')
|
|
||||||
item = m.add(id, href, guess_type('t.xhtml')[0],
|
|
||||||
data=etree.fromstring(tp))
|
|
||||||
else:
|
|
||||||
item = self.oeb.manifest.hrefs[
|
|
||||||
urldefrag(self.oeb.guide['titlepage'].href)[0]]
|
|
||||||
if item is not None:
|
|
||||||
self.oeb.spine.insert(0, item, True)
|
|
||||||
if 'cover' not in self.oeb.guide.refs:
|
|
||||||
self.oeb.guide.add('cover', 'Title Page', 'a')
|
|
||||||
self.oeb.guide.refs['cover'].href = item.href
|
|
||||||
if 'titlepage' in self.oeb.guide.refs:
|
|
||||||
self.oeb.guide.refs['titlepage'].href = item.href
|
|
||||||
|
|
||||||
def condense_ncx(self, ncx_path):
|
def condense_ncx(self, ncx_path):
|
||||||
if not self.opts.pretty_print:
|
if not self.opts.pretty_print:
|
||||||
tree = etree.parse(ncx_path)
|
tree = etree.parse(ncx_path)
|
||||||
|
@ -669,10 +669,19 @@ class OPF(object):
|
|||||||
remove = list(self.authors_path(self.metadata))
|
remove = list(self.authors_path(self.metadata))
|
||||||
for elem in remove:
|
for elem in remove:
|
||||||
elem.getparent().remove(elem)
|
elem.getparent().remove(elem)
|
||||||
|
elems = []
|
||||||
for author in val:
|
for author in val:
|
||||||
attrib = {'{%s}role'%self.NAMESPACES['opf']: 'aut'}
|
attrib = {'{%s}role'%self.NAMESPACES['opf']: 'aut'}
|
||||||
elem = self.create_metadata_element('creator', attrib=attrib)
|
elem = self.create_metadata_element('creator', attrib=attrib)
|
||||||
self.set_text(elem, author.strip())
|
self.set_text(elem, author.strip())
|
||||||
|
# Ensure new author element is at the top of the list
|
||||||
|
# for broken implementations that always use the first
|
||||||
|
# <dc:creator> element with no attention to the role
|
||||||
|
elems.append(elem)
|
||||||
|
for elem in reversed(elems):
|
||||||
|
parent = elem.getparent()
|
||||||
|
parent.remove(elem)
|
||||||
|
parent.insert(0, elem)
|
||||||
|
|
||||||
return property(fget=fget, fset=fset)
|
return property(fget=fget, fset=fset)
|
||||||
|
|
||||||
|
@ -18,10 +18,10 @@ from calibre.ebooks.chardet import xml_to_unicode
|
|||||||
from calibre.utils.zipfile import safe_replace, ZipFile
|
from calibre.utils.zipfile import safe_replace, ZipFile
|
||||||
from calibre.utils.config import DynamicConfig
|
from calibre.utils.config import DynamicConfig
|
||||||
from calibre.utils.logging import Log
|
from calibre.utils.logging import Log
|
||||||
from calibre.ebooks.epub.output import EPUBOutput
|
|
||||||
from calibre import guess_type, prints
|
from calibre import guess_type, prints
|
||||||
|
from calibre.ebooks.oeb.transforms.cover import CoverManager
|
||||||
|
|
||||||
TITLEPAGE = EPUBOutput.TITLEPAGE_COVER.decode('utf-8')
|
TITLEPAGE = CoverManager.SVG_TEMPLATE.decode('utf-8').replace('__ar__', 'none')
|
||||||
|
|
||||||
def character_count(html):
|
def character_count(html):
|
||||||
'''
|
'''
|
||||||
|
173
src/calibre/ebooks/oeb/transforms/cover.py
Normal file
173
src/calibre/ebooks/oeb/transforms/cover.py
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
import textwrap
|
||||||
|
from urllib import unquote
|
||||||
|
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
|
from calibre import __appname__, __version__, guess_type
|
||||||
|
|
||||||
|
class CoverManager(object):
|
||||||
|
|
||||||
|
SVG_TEMPLATE = textwrap.dedent('''\
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="calibre:cover" content="true" />
|
||||||
|
<title>Cover</title>
|
||||||
|
<style type="text/css" title="override_css">
|
||||||
|
@page {padding: 0pt; margin:0pt}
|
||||||
|
body { text-align: center; padding:0pt; margin: 0pt; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
width="100%%" height="100%%" viewBox="0 0 600 800"
|
||||||
|
preserveAspectRatio="__ar__">
|
||||||
|
<image width="600" height="800" xlink:href="%s"/>
|
||||||
|
</svg>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
''')
|
||||||
|
|
||||||
|
NONSVG_TEMPLATE = textwrap.dedent('''\
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="calibre:cover" content="true" />
|
||||||
|
<title>Cover</title>
|
||||||
|
<style type="text/css" title="override_css">
|
||||||
|
@page {padding: 0pt; margin:0pt}
|
||||||
|
body { text-align: center; padding:0pt; margin: 0pt }
|
||||||
|
div { padding:0pt; margin: 0pt }
|
||||||
|
img { padding:0pt; margin: 0pt }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<img src="%s" alt="cover" __style__ />
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
''')
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, no_default_cover=False, no_svg_cover=False,
|
||||||
|
preserve_aspect_ratio=False, fixed_size=None):
|
||||||
|
self.no_default_cover = no_default_cover
|
||||||
|
self.no_svg_cover = no_svg_cover
|
||||||
|
self.preserve_aspect_ratio = preserve_aspect_ratio
|
||||||
|
|
||||||
|
ar = 'xMidYMid meet' if preserve_aspect_ratio else 'none'
|
||||||
|
self.svg_template = self.SVG_TEMPLATE.replace('__ar__', ar)
|
||||||
|
|
||||||
|
if fixed_size is None:
|
||||||
|
style = 'style="height: 100%%"'
|
||||||
|
else:
|
||||||
|
width, height = fixed_size
|
||||||
|
style = 'style="height: %s; width: %s"'%(width, height)
|
||||||
|
self.non_svg_template = self.NONSVG_TEMPLATE.replace('__style__',
|
||||||
|
style)
|
||||||
|
|
||||||
|
def __call__(self, oeb, opts, log):
|
||||||
|
self.oeb = oeb
|
||||||
|
self.log = log
|
||||||
|
self.insert_cover()
|
||||||
|
|
||||||
|
def default_cover(self):
|
||||||
|
'''
|
||||||
|
Create a generic cover for books that dont have a cover
|
||||||
|
'''
|
||||||
|
from calibre.utils.pil_draw import draw_centered_text
|
||||||
|
from calibre.ebooks.metadata import authors_to_string
|
||||||
|
if self.no_default_cover:
|
||||||
|
return None
|
||||||
|
self.log('Generating default cover')
|
||||||
|
m = self.oeb.metadata
|
||||||
|
title = unicode(m.title[0])
|
||||||
|
authors = [unicode(x) for x in m.creator if x.role == 'aut']
|
||||||
|
|
||||||
|
import cStringIO
|
||||||
|
cover_file = cStringIO.StringIO()
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
Image, ImageDraw, ImageFont
|
||||||
|
except ImportError:
|
||||||
|
import Image, ImageDraw, ImageFont
|
||||||
|
font_path = P('fonts/liberation/LiberationSerif-Bold.ttf')
|
||||||
|
app = '['+__appname__ +' '+__version__+']'
|
||||||
|
|
||||||
|
COVER_WIDTH, COVER_HEIGHT = 590, 750
|
||||||
|
img = Image.new('RGB', (COVER_WIDTH, COVER_HEIGHT), 'white')
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
# Title
|
||||||
|
font = ImageFont.truetype(font_path, 44)
|
||||||
|
bottom = draw_centered_text(img, draw, font, title, 15, ysep=9)
|
||||||
|
# Authors
|
||||||
|
bottom += 14
|
||||||
|
font = ImageFont.truetype(font_path, 32)
|
||||||
|
authors = authors_to_string(authors)
|
||||||
|
bottom = draw_centered_text(img, draw, font, authors, bottom, ysep=7)
|
||||||
|
# Vanity
|
||||||
|
font = ImageFont.truetype(font_path, 28)
|
||||||
|
width, height = draw.textsize(app, font=font)
|
||||||
|
left = max(int((COVER_WIDTH - width)/2.), 0)
|
||||||
|
top = COVER_HEIGHT - height - 15
|
||||||
|
draw.text((left, top), app, fill=(0,0,0), font=font)
|
||||||
|
# Logo
|
||||||
|
logo = Image.open(I('library.png'), 'r')
|
||||||
|
width, height = logo.size
|
||||||
|
left = max(int((COVER_WIDTH - width)/2.), 0)
|
||||||
|
top = max(int((COVER_HEIGHT - height)/2.), 0)
|
||||||
|
img.paste(logo, (left, max(bottom, top)))
|
||||||
|
img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE)
|
||||||
|
|
||||||
|
img.convert('RGB').save(cover_file, 'JPEG')
|
||||||
|
cover_file.flush()
|
||||||
|
id, href = self.oeb.manifest.generate('cover_image', 'cover_image.jpg')
|
||||||
|
item = self.oeb.manifest.add(id, href, guess_type('t.jpg')[0],
|
||||||
|
data=cover_file.getvalue())
|
||||||
|
m.clear('cover')
|
||||||
|
m.add('cover', item.id)
|
||||||
|
|
||||||
|
return item.href
|
||||||
|
except:
|
||||||
|
self.log.exception('Failed to generate default cover')
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def insert_cover(self):
|
||||||
|
from calibre.ebooks.oeb.base import urldefrag
|
||||||
|
g, m = self.oeb.guide, self.oeb.manifest
|
||||||
|
item = None
|
||||||
|
if 'titlepage' not in g:
|
||||||
|
if 'cover' in g:
|
||||||
|
href = g['cover'].href
|
||||||
|
else:
|
||||||
|
href = self.default_cover()
|
||||||
|
if href is not None:
|
||||||
|
templ = self.non_svg_template if self.no_svg_cover \
|
||||||
|
else self.svg_template
|
||||||
|
tp = templ%unquote(href)
|
||||||
|
id, href = m.generate('titlepage', 'titlepage.xhtml')
|
||||||
|
item = m.add(id, href, guess_type('t.xhtml')[0],
|
||||||
|
data=etree.fromstring(tp))
|
||||||
|
else:
|
||||||
|
item = self.oeb.manifest.hrefs[
|
||||||
|
urldefrag(self.oeb.guide['titlepage'].href)[0]]
|
||||||
|
if item is not None:
|
||||||
|
self.oeb.spine.insert(0, item, True)
|
||||||
|
if 'cover' not in self.oeb.guide.refs:
|
||||||
|
self.oeb.guide.add('cover', 'Title Page', 'a')
|
||||||
|
self.oeb.guide.refs['cover'].href = item.href
|
||||||
|
if 'titlepage' in self.oeb.guide.refs:
|
||||||
|
self.oeb.guide.refs['titlepage'].href = item.href
|
||||||
|
|
||||||
|
|
@ -164,7 +164,10 @@ class CSSFlattener(object):
|
|||||||
body = html.find(XHTML('body'))
|
body = html.find(XHTML('body'))
|
||||||
fsize = self.context.source.fbase
|
fsize = self.context.source.fbase
|
||||||
self.baseline_node(body, stylizer, sizes, fsize)
|
self.baseline_node(body, stylizer, sizes, fsize)
|
||||||
sbase = max(sizes.items(), key=operator.itemgetter(1))[0]
|
try:
|
||||||
|
sbase = max(sizes.items(), key=operator.itemgetter(1))[0]
|
||||||
|
except:
|
||||||
|
sbase = 12.0
|
||||||
self.oeb.logger.info(
|
self.oeb.logger.info(
|
||||||
"Source base font size is %0.05fpt" % sbase)
|
"Source base font size is %0.05fpt" % sbase)
|
||||||
return sbase
|
return sbase
|
||||||
|
@ -22,7 +22,7 @@ from calibre.ebooks.pdf.pageoptions import UNITS, PAPER_SIZES, \
|
|||||||
class PDFOutput(OutputFormatPlugin):
|
class PDFOutput(OutputFormatPlugin):
|
||||||
|
|
||||||
name = 'PDF Output'
|
name = 'PDF Output'
|
||||||
author = 'John Schember'
|
author = 'John Schember and Kovid Goyal'
|
||||||
file_type = 'pdf'
|
file_type = 'pdf'
|
||||||
|
|
||||||
options = set([
|
options = set([
|
||||||
@ -44,12 +44,20 @@ class PDFOutput(OutputFormatPlugin):
|
|||||||
level=OptionRecommendation.LOW, choices=ORIENTATIONS.keys(),
|
level=OptionRecommendation.LOW, choices=ORIENTATIONS.keys(),
|
||||||
help=_('The orientation of the page. Default is portrait. Choices '
|
help=_('The orientation of the page. Default is portrait. Choices '
|
||||||
'are %s') % ORIENTATIONS.keys()),
|
'are %s') % ORIENTATIONS.keys()),
|
||||||
|
OptionRecommendation(name='preserve_cover_aspect_ratio',
|
||||||
|
recommended_value=False,
|
||||||
|
help=_('Preserve the aspect ratio of the cover, instead'
|
||||||
|
' of stretching it to fill the ull first page of the'
|
||||||
|
' generated pdf.')
|
||||||
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
def convert(self, oeb_book, output_path, input_plugin, opts, log):
|
||||||
|
self.oeb = oeb_book
|
||||||
self.input_plugin, self.opts, self.log = input_plugin, opts, log
|
self.input_plugin, self.opts, self.log = input_plugin, opts, log
|
||||||
self.output_path = output_path
|
self.output_path = output_path
|
||||||
self.metadata = oeb_book.metadata
|
self.metadata = oeb_book.metadata
|
||||||
|
self.cover_data = None
|
||||||
|
|
||||||
if input_plugin.is_image_collection:
|
if input_plugin.is_image_collection:
|
||||||
log.debug('Converting input as an image collection...')
|
log.debug('Converting input as an image collection...')
|
||||||
@ -61,8 +69,20 @@ class PDFOutput(OutputFormatPlugin):
|
|||||||
def convert_images(self, images):
|
def convert_images(self, images):
|
||||||
self.write(ImagePDFWriter, images)
|
self.write(ImagePDFWriter, images)
|
||||||
|
|
||||||
|
def get_cover_data(self):
|
||||||
|
g, m = self.oeb.guide, self.oeb.manifest
|
||||||
|
if 'titlepage' not in g:
|
||||||
|
if 'cover' in g:
|
||||||
|
href = g['cover'].href
|
||||||
|
from calibre.ebooks.oeb.base import urlnormalize
|
||||||
|
for item in m:
|
||||||
|
if item.href == urlnormalize(href):
|
||||||
|
self.cover_data = item.data
|
||||||
|
|
||||||
def convert_text(self, oeb_book):
|
def convert_text(self, oeb_book):
|
||||||
self.log.debug('Serializing oeb input to disk for processing...')
|
self.log.debug('Serializing oeb input to disk for processing...')
|
||||||
|
self.get_cover_data()
|
||||||
|
|
||||||
with TemporaryDirectory('_pdf_out') as oeb_dir:
|
with TemporaryDirectory('_pdf_out') as oeb_dir:
|
||||||
from calibre.customize.ui import plugin_for_output_format
|
from calibre.customize.ui import plugin_for_output_format
|
||||||
oeb_output = plugin_for_output_format('oeb')
|
oeb_output = plugin_for_output_format('oeb')
|
||||||
@ -74,7 +94,7 @@ class PDFOutput(OutputFormatPlugin):
|
|||||||
self.write(PDFWriter, [s.path for s in opf.spine])
|
self.write(PDFWriter, [s.path for s in opf.spine])
|
||||||
|
|
||||||
def write(self, Writer, items):
|
def write(self, Writer, items):
|
||||||
writer = Writer(self.opts, self.log)
|
writer = Writer(self.opts, self.log, cover_data=self.cover_data)
|
||||||
|
|
||||||
close = False
|
close = False
|
||||||
if not hasattr(self.output_path, 'write'):
|
if not hasattr(self.output_path, 'write'):
|
||||||
|
@ -15,14 +15,83 @@ from calibre.ptempfile import PersistentTemporaryDirectory
|
|||||||
from calibre.ebooks.pdf.pageoptions import unit, paper_size, \
|
from calibre.ebooks.pdf.pageoptions import unit, paper_size, \
|
||||||
orientation
|
orientation
|
||||||
from calibre.ebooks.metadata import authors_to_string
|
from calibre.ebooks.metadata import authors_to_string
|
||||||
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
|
from calibre import __appname__, __version__, fit_image
|
||||||
|
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
from PyQt4.Qt import QUrl, QEventLoop, SIGNAL, QObject, \
|
from PyQt4.Qt import QUrl, QEventLoop, QObject, \
|
||||||
QPrinter, QMetaObject, QSizeF, Qt
|
QPrinter, QMetaObject, QSizeF, Qt, QPainter, QPixmap
|
||||||
from PyQt4.QtWebKit import QWebView
|
from PyQt4.QtWebKit import QWebView
|
||||||
|
|
||||||
from pyPdf import PdfFileWriter, PdfFileReader
|
from pyPdf import PdfFileWriter, PdfFileReader
|
||||||
|
|
||||||
|
def get_pdf_printer():
|
||||||
|
return QPrinter(QPrinter.HighResolution)
|
||||||
|
|
||||||
|
|
||||||
|
def get_custom_size(opts):
|
||||||
|
custom_size = None
|
||||||
|
if opts.custom_size != None:
|
||||||
|
width, sep, height = opts.custom_size.partition('x')
|
||||||
|
if height != '':
|
||||||
|
try:
|
||||||
|
width = int(width)
|
||||||
|
height = int(height)
|
||||||
|
custom_size = (width, height)
|
||||||
|
except:
|
||||||
|
custom_size = None
|
||||||
|
return custom_size
|
||||||
|
|
||||||
|
def setup_printer(opts, for_comic=False):
|
||||||
|
from calibre.gui2 import is_ok_to_use_qt
|
||||||
|
if not is_ok_to_use_qt():
|
||||||
|
raise Exception('Not OK to use Qt')
|
||||||
|
|
||||||
|
printer = get_pdf_printer()
|
||||||
|
custom_size = get_custom_size(opts)
|
||||||
|
|
||||||
|
if opts.output_profile.short_name == 'default':
|
||||||
|
if custom_size is None:
|
||||||
|
printer.setPaperSize(paper_size(opts.paper_size))
|
||||||
|
else:
|
||||||
|
printer.setPaperSize(QSizeF(custom_size[0], custom_size[1]), unit(opts.unit))
|
||||||
|
else:
|
||||||
|
w = opts.output_profile.comic_screen_size[0] if for_comic else \
|
||||||
|
opts.output_profile.width
|
||||||
|
h = opts.output_profile.comic_screen_size[1] if for_comic else \
|
||||||
|
opts.output_profile.height
|
||||||
|
dpi = opts.output_profile.dpi
|
||||||
|
printer.setPaperSize(QSizeF(float(w) / dpi, float(h)/dpi), QPrinter.Inch)
|
||||||
|
|
||||||
|
printer.setPageMargins(0, 0, 0, 0, QPrinter.Point)
|
||||||
|
printer.setOrientation(orientation(opts.orientation))
|
||||||
|
printer.setOutputFormat(QPrinter.PdfFormat)
|
||||||
|
return printer
|
||||||
|
|
||||||
|
def get_printer_page_size(opts, for_comic=False):
|
||||||
|
printer = setup_printer(opts, for_comic=for_comic)
|
||||||
|
size = printer.paperSize(QPrinter.Millimeter)
|
||||||
|
return size.width() / 10., size.height() / 10.
|
||||||
|
|
||||||
|
def draw_image_page(printer, painter, p, preserve_aspect_ratio=True):
|
||||||
|
page_rect = printer.pageRect()
|
||||||
|
if preserve_aspect_ratio:
|
||||||
|
aspect_ratio = float(p.width())/p.height()
|
||||||
|
nw, nh = page_rect.width(), page_rect.height()
|
||||||
|
if aspect_ratio > 1:
|
||||||
|
nh = int(page_rect.width()/aspect_ratio)
|
||||||
|
else: # Width is smaller than height
|
||||||
|
nw = page_rect.height()*aspect_ratio
|
||||||
|
__, nnw, nnh = fit_image(nw, nh, page_rect.width(),
|
||||||
|
page_rect.height())
|
||||||
|
dx = int((page_rect.width() - nnw)/2.)
|
||||||
|
dy = int((page_rect.height() - nnh)/2.)
|
||||||
|
page_rect.moveTo(dx, dy)
|
||||||
|
page_rect.setHeight(nnh)
|
||||||
|
page_rect.setWidth(nnw)
|
||||||
|
painter.drawPixmap(page_rect, p, p.rect())
|
||||||
|
|
||||||
|
|
||||||
class PDFMetadata(object):
|
class PDFMetadata(object):
|
||||||
def __init__(self, oeb_metadata=None):
|
def __init__(self, oeb_metadata=None):
|
||||||
self.title = _('Unknown')
|
self.title = _('Unknown')
|
||||||
@ -35,8 +104,9 @@ class PDFMetadata(object):
|
|||||||
self.author = authors_to_string([x.value for x in oeb_metadata.creator])
|
self.author = authors_to_string([x.value for x in oeb_metadata.creator])
|
||||||
|
|
||||||
|
|
||||||
class PDFWriter(QObject):
|
class PDFWriter(QObject): # {{{
|
||||||
def __init__(self, opts, log):
|
|
||||||
|
def __init__(self, opts, log, cover_data=None):
|
||||||
from calibre.gui2 import is_ok_to_use_qt
|
from calibre.gui2 import is_ok_to_use_qt
|
||||||
if not is_ok_to_use_qt():
|
if not is_ok_to_use_qt():
|
||||||
raise Exception('Not OK to use Qt')
|
raise Exception('Not OK to use Qt')
|
||||||
@ -46,25 +116,16 @@ class PDFWriter(QObject):
|
|||||||
|
|
||||||
self.loop = QEventLoop()
|
self.loop = QEventLoop()
|
||||||
self.view = QWebView()
|
self.view = QWebView()
|
||||||
self.connect(self.view, SIGNAL('loadFinished(bool)'), self._render_html)
|
self.view.setRenderHints(QPainter.Antialiasing|QPainter.TextAntialiasing|QPainter.SmoothPixmapTransform)
|
||||||
|
self.view.loadFinished.connect(self._render_html,
|
||||||
|
type=Qt.QueuedConnection)
|
||||||
self.render_queue = []
|
self.render_queue = []
|
||||||
self.combine_queue = []
|
self.combine_queue = []
|
||||||
self.tmp_path = PersistentTemporaryDirectory('_pdf_output_parts')
|
self.tmp_path = PersistentTemporaryDirectory('_pdf_output_parts')
|
||||||
|
|
||||||
self.custom_size = None
|
|
||||||
if opts.custom_size != None:
|
|
||||||
width, sep, height = opts.custom_size.partition('x')
|
|
||||||
if height != '':
|
|
||||||
try:
|
|
||||||
width = int(width)
|
|
||||||
height = int(height)
|
|
||||||
self.custom_size = (width, height)
|
|
||||||
except:
|
|
||||||
self.custom_size = None
|
|
||||||
|
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
|
self.size = get_printer_page_size(opts)
|
||||||
self.size = self._size()
|
self.cover_data = cover_data
|
||||||
|
|
||||||
def dump(self, items, out_stream, pdf_metadata):
|
def dump(self, items, out_stream, pdf_metadata):
|
||||||
self.metadata = pdf_metadata
|
self.metadata = pdf_metadata
|
||||||
@ -77,27 +138,6 @@ class PDFWriter(QObject):
|
|||||||
QMetaObject.invokeMethod(self, "_render_book", Qt.QueuedConnection)
|
QMetaObject.invokeMethod(self, "_render_book", Qt.QueuedConnection)
|
||||||
self.loop.exec_()
|
self.loop.exec_()
|
||||||
|
|
||||||
def _size(self):
|
|
||||||
'''
|
|
||||||
The size of a pdf page in cm.
|
|
||||||
'''
|
|
||||||
printer = QPrinter(QPrinter.HighResolution)
|
|
||||||
|
|
||||||
if self.opts.output_profile.short_name == 'default':
|
|
||||||
if self.custom_size == None:
|
|
||||||
printer.setPaperSize(paper_size(self.opts.paper_size))
|
|
||||||
else:
|
|
||||||
printer.setPaperSize(QSizeF(self.custom_size[0], self.custom_size[1]), unit(self.opts.unit))
|
|
||||||
else:
|
|
||||||
printer.setPaperSize(QSizeF(self.opts.output_profile.width / self.opts.output_profile.dpi, self.opts.output_profile.height / self.opts.output_profile.dpi), QPrinter.Inch)
|
|
||||||
|
|
||||||
printer.setPageMargins(0, 0, 0, 0, QPrinter.Point)
|
|
||||||
printer.setOrientation(orientation(self.opts.orientation))
|
|
||||||
printer.setOutputFormat(QPrinter.PdfFormat)
|
|
||||||
|
|
||||||
size = printer.paperSize(QPrinter.Millimeter)
|
|
||||||
|
|
||||||
return size.width() / 10, size.height() / 10
|
|
||||||
|
|
||||||
@QtCore.pyqtSignature('_render_book()')
|
@QtCore.pyqtSignature('_render_book()')
|
||||||
def _render_book(self):
|
def _render_book(self):
|
||||||
@ -114,17 +154,20 @@ class PDFWriter(QObject):
|
|||||||
|
|
||||||
self.view.load(QUrl.fromLocalFile(item))
|
self.view.load(QUrl.fromLocalFile(item))
|
||||||
|
|
||||||
|
def get_printer(self):
|
||||||
|
printer = get_pdf_printer()
|
||||||
|
printer.setPaperSize(QSizeF(self.size[0] * 10, self.size[1] * 10), QPrinter.Millimeter)
|
||||||
|
printer.setPageMargins(0, 0, 0, 0, QPrinter.Point)
|
||||||
|
printer.setOrientation(orientation(self.opts.orientation))
|
||||||
|
printer.setOutputFormat(QPrinter.PdfFormat)
|
||||||
|
printer.setFullPage(True)
|
||||||
|
return printer
|
||||||
|
|
||||||
def _render_html(self, ok):
|
def _render_html(self, ok):
|
||||||
if ok:
|
if ok:
|
||||||
item_path = os.path.join(self.tmp_path, '%i.pdf' % len(self.combine_queue))
|
item_path = os.path.join(self.tmp_path, '%i.pdf' % len(self.combine_queue))
|
||||||
|
|
||||||
self.logger.debug('\tRendering item %s as %i' % (os.path.basename(str(self.view.url().toLocalFile())), len(self.combine_queue)))
|
self.logger.debug('\tRendering item %s as %i' % (os.path.basename(str(self.view.url().toLocalFile())), len(self.combine_queue)))
|
||||||
|
printer = self.get_printer()
|
||||||
printer = QPrinter(QPrinter.HighResolution)
|
|
||||||
printer.setPaperSize(QSizeF(self.size[0] * 10, self.size[1] * 10), QPrinter.Millimeter)
|
|
||||||
printer.setPageMargins(0, 0, 0, 0, QPrinter.Point)
|
|
||||||
printer.setOrientation(orientation(self.opts.orientation))
|
|
||||||
printer.setOutputFormat(QPrinter.PdfFormat)
|
|
||||||
printer.setOutputFileName(item_path)
|
printer.setOutputFileName(item_path)
|
||||||
self.view.print_(printer)
|
self.view.print_(printer)
|
||||||
self._render_book()
|
self._render_book()
|
||||||
@ -134,9 +177,27 @@ class PDFWriter(QObject):
|
|||||||
shutil.rmtree(self.tmp_path, True)
|
shutil.rmtree(self.tmp_path, True)
|
||||||
self.tmp_path = PersistentTemporaryDirectory('_pdf_output_parts')
|
self.tmp_path = PersistentTemporaryDirectory('_pdf_output_parts')
|
||||||
|
|
||||||
|
def insert_cover(self):
|
||||||
|
if self.cover_data is None:
|
||||||
|
return
|
||||||
|
item_path = os.path.join(self.tmp_path, 'cover.pdf')
|
||||||
|
printer = self.get_printer()
|
||||||
|
printer.setOutputFileName(item_path)
|
||||||
|
self.combine_queue.insert(0, item_path)
|
||||||
|
p = QPixmap()
|
||||||
|
p.loadFromData(self.cover_data)
|
||||||
|
if not p.isNull():
|
||||||
|
painter = QPainter(printer)
|
||||||
|
draw_image_page(printer, painter, p,
|
||||||
|
preserve_aspect_ratio=self.opts.preserve_cover_aspect_ratio)
|
||||||
|
painter.end()
|
||||||
|
|
||||||
|
|
||||||
def _write(self):
|
def _write(self):
|
||||||
self.logger.debug('Combining individual PDF parts...')
|
self.logger.debug('Combining individual PDF parts...')
|
||||||
|
|
||||||
|
self.insert_cover()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
outPDF = PdfFileWriter(title=self.metadata.title, author=self.metadata.author)
|
outPDF = PdfFileWriter(title=self.metadata.title, author=self.metadata.author)
|
||||||
for item in self.combine_queue:
|
for item in self.combine_queue:
|
||||||
@ -148,37 +209,50 @@ class PDFWriter(QObject):
|
|||||||
self._delete_tmpdir()
|
self._delete_tmpdir()
|
||||||
self.loop.exit(0)
|
self.loop.exit(0)
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
class ImagePDFWriter(PDFWriter):
|
class ImagePDFWriter(object):
|
||||||
|
|
||||||
def _render_next(self):
|
def __init__(self, opts, log, cover_data=None):
|
||||||
item = str(self.render_queue.pop(0))
|
self.opts = opts
|
||||||
self.combine_queue.append(os.path.join(self.tmp_path, '%i.pdf' % (len(self.combine_queue) + 1)))
|
self.log = log
|
||||||
|
self.size = get_printer_page_size(opts, for_comic=True)
|
||||||
|
|
||||||
self.logger.debug('Processing %s...' % item)
|
def dump(self, items, out_stream, pdf_metadata):
|
||||||
|
f = PersistentTemporaryFile('_comic2pdf.pdf')
|
||||||
|
f.close()
|
||||||
|
try:
|
||||||
|
self.render_images(f.name, pdf_metadata, items)
|
||||||
|
with open(f.name, 'rb') as x:
|
||||||
|
shutil.copyfileobj(x, out_stream)
|
||||||
|
finally:
|
||||||
|
os.remove(f.name)
|
||||||
|
|
||||||
height = 'height: %fcm;' % (self.size[1] * 1.3)
|
def render_images(self, outpath, mi, items):
|
||||||
|
printer = get_pdf_printer()
|
||||||
|
printer.setPaperSize(QSizeF(self.size[0] * 10, self.size[1] * 10), QPrinter.Millimeter)
|
||||||
|
printer.setPageMargins(0, 0, 0, 0, QPrinter.Point)
|
||||||
|
printer.setOrientation(orientation(self.opts.orientation))
|
||||||
|
printer.setOutputFormat(QPrinter.PdfFormat)
|
||||||
|
printer.setOutputFileName(outpath)
|
||||||
|
printer.setDocName(mi.title)
|
||||||
|
printer.setCreator(u'%s [%s]'%(__appname__, __version__))
|
||||||
|
# Seems to be no way to set author
|
||||||
|
printer.setFullPage(True)
|
||||||
|
|
||||||
html = '<html><body style="margin: 0;"><img src="%s" style="%s display: block; margin-left: auto; margin-right: auto; padding: 0px;" /></body></html>' % (item, height)
|
painter = QPainter(printer)
|
||||||
|
painter.setRenderHints(QPainter.Antialiasing|QPainter.SmoothPixmapTransform)
|
||||||
|
|
||||||
self.view.setHtml(html)
|
for i, imgpath in enumerate(items):
|
||||||
|
self.log('Rendering image:', i)
|
||||||
def _size(self):
|
p = QPixmap()
|
||||||
printer = QPrinter(QPrinter.HighResolution)
|
p.load(imgpath)
|
||||||
|
if not p.isNull():
|
||||||
if self.opts.output_profile.short_name == 'default':
|
if i > 0:
|
||||||
if self.custom_size == None:
|
printer.newPage()
|
||||||
printer.setPaperSize(paper_size(self.opts.paper_size))
|
draw_image_page(printer, painter, p)
|
||||||
else:
|
|
||||||
printer.setPaperSize(QSizeF(self.custom_size[0], self.custom_size[1]), unit(self.opts.unit))
|
|
||||||
else:
|
else:
|
||||||
printer.setPaperSize(QSizeF(self.opts.output_profile.comic_screen_size[0] / self.opts.output_profile.dpi, self.opts.output_profile.comic_screen_size[1] / self.opts.output_profile.dpi), QPrinter.Inch)
|
self.log.warn('Failed to load image', i)
|
||||||
|
painter.end()
|
||||||
|
|
||||||
printer.setPageMargins(0, 0, 0, 0, QPrinter.Point)
|
|
||||||
printer.setOrientation(orientation(self.opts.orientation))
|
|
||||||
printer.setOutputFormat(QPrinter.PdfFormat)
|
|
||||||
|
|
||||||
size = printer.paperSize(QPrinter.Millimeter)
|
|
||||||
|
|
||||||
return size.width() / 10, size.height() / 10
|
|
||||||
|
|
||||||
|
@ -354,7 +354,6 @@ if another paragraph_def is found, the state changes to collect_tokens.
|
|||||||
def __tab_stop_func(self, line):
|
def __tab_stop_func(self, line):
|
||||||
"""
|
"""
|
||||||
"""
|
"""
|
||||||
type = 'tabs-%s' % self.__tab_type
|
|
||||||
self.__att_val_dict['tabs'] += '%s:' % self.__tab_type
|
self.__att_val_dict['tabs'] += '%s:' % self.__tab_type
|
||||||
self.__att_val_dict['tabs'] += '%s;' % line[20:-1]
|
self.__att_val_dict['tabs'] += '%s;' % line[20:-1]
|
||||||
self.__tab_type = 'left'
|
self.__tab_type = 'left'
|
||||||
@ -373,7 +372,6 @@ if another paragraph_def is found, the state changes to collect_tokens.
|
|||||||
"""
|
"""
|
||||||
leader = self.__tab_type_dict.get(self.__token_info)
|
leader = self.__tab_type_dict.get(self.__token_info)
|
||||||
if leader != None:
|
if leader != None:
|
||||||
type = 'tabs-%s' % self.__tab_type
|
|
||||||
self.__att_val_dict['tabs'] += '%s^' % leader
|
self.__att_val_dict['tabs'] += '%s^' % leader
|
||||||
else:
|
else:
|
||||||
if self.__run_level > 3:
|
if self.__run_level > 3:
|
||||||
|
@ -318,7 +318,6 @@ class Styles:
|
|||||||
Try to add the number to dictionary entry tabs-left, or tabs-right, etc.
|
Try to add the number to dictionary entry tabs-left, or tabs-right, etc.
|
||||||
If the dictionary entry doesn't exist, create one.
|
If the dictionary entry doesn't exist, create one.
|
||||||
"""
|
"""
|
||||||
type = 'tabs-%s' % self.__tab_type
|
|
||||||
try:
|
try:
|
||||||
if self.__leader_found:
|
if self.__leader_found:
|
||||||
self.__styles_dict['par'][self.__styles_num]['tabs']\
|
self.__styles_dict['par'][self.__styles_num]['tabs']\
|
||||||
@ -362,7 +361,6 @@ class Styles:
|
|||||||
leader = self.__tab_type_dict.get(self.__token_info)
|
leader = self.__tab_type_dict.get(self.__token_info)
|
||||||
if leader != None:
|
if leader != None:
|
||||||
leader += '^'
|
leader += '^'
|
||||||
type = 'tabs-%s' % self.__tab_type
|
|
||||||
try:
|
try:
|
||||||
self.__styles_dict['par'][self.__styles_num]['tabs'] += ':%s;' % leader
|
self.__styles_dict['par'][self.__styles_num]['tabs'] += ':%s;' % leader
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -18,8 +18,11 @@ class PluginWidget(Widget, Ui_Form):
|
|||||||
def __init__(self, parent, get_option, get_help, db=None, book_id=None):
|
def __init__(self, parent, get_option, get_help, db=None, book_id=None):
|
||||||
Widget.__init__(self, parent, 'epub_output',
|
Widget.__init__(self, parent, 'epub_output',
|
||||||
['dont_split_on_page_breaks', 'flow_size',
|
['dont_split_on_page_breaks', 'flow_size',
|
||||||
'no_default_epub_cover', 'no_svg_cover']
|
'no_default_epub_cover', 'no_svg_cover',
|
||||||
|
'preserve_cover_aspect_ratio',]
|
||||||
)
|
)
|
||||||
|
for i in range(2):
|
||||||
|
self.opt_no_svg_cover.toggle()
|
||||||
self.db, self.book_id = db, book_id
|
self.db, self.book_id = db, book_id
|
||||||
self.initialize_options(get_option, get_help, db, book_id)
|
self.initialize_options(get_option, get_help, db, book_id)
|
||||||
|
|
||||||
|
@ -14,13 +14,34 @@
|
|||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="0" column="0">
|
||||||
<widget class="QCheckBox" name="opt_dont_split_on_page_breaks">
|
<widget class="QCheckBox" name="opt_dont_split_on_page_breaks">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Do not &split on page breaks</string>
|
<string>Do not &split on page breaks</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="opt_no_default_epub_cover">
|
||||||
|
<property name="text">
|
||||||
|
<string>No default &cover</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="opt_no_svg_cover">
|
||||||
|
<property name="text">
|
||||||
|
<string>No &SVG cover</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QCheckBox" name="opt_preserve_cover_aspect_ratio">
|
||||||
|
<property name="text">
|
||||||
|
<string>Preserve cover &aspect ratio</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -60,22 +81,25 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QCheckBox" name="opt_no_default_epub_cover">
|
|
||||||
<property name="text">
|
|
||||||
<string>No default &cover</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QCheckBox" name="opt_no_svg_cover">
|
|
||||||
<property name="text">
|
|
||||||
<string>No &SVG cover</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>opt_no_svg_cover</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>opt_preserve_cover_aspect_ratio</receiver>
|
||||||
|
<slot>setDisabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>81</x>
|
||||||
|
<y>73</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>237</x>
|
||||||
|
<y>68</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -6,7 +6,7 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
from PyQt4.Qt import SIGNAL
|
from PyQt4.Qt import SIGNAL, QVariant
|
||||||
|
|
||||||
from calibre.gui2.convert.look_and_feel_ui import Ui_Form
|
from calibre.gui2.convert.look_and_feel_ui import Ui_Form
|
||||||
from calibre.gui2.convert import Widget
|
from calibre.gui2.convert import Widget
|
||||||
@ -24,8 +24,14 @@ class LookAndFeelWidget(Widget, Ui_Form):
|
|||||||
'linearize_tables',
|
'linearize_tables',
|
||||||
'disable_font_rescaling', 'insert_blank_line',
|
'disable_font_rescaling', 'insert_blank_line',
|
||||||
'remove_paragraph_spacing', 'remove_paragraph_spacing_indent_size','input_encoding',
|
'remove_paragraph_spacing', 'remove_paragraph_spacing_indent_size','input_encoding',
|
||||||
'asciiize']
|
'asciiize', 'keep_ligatures']
|
||||||
)
|
)
|
||||||
|
for val, text in [
|
||||||
|
('original', _('Original')),
|
||||||
|
('left', _('Left align')),
|
||||||
|
('justify', _('Justify text'))
|
||||||
|
]:
|
||||||
|
self.opt_change_justification.addItem(text, QVariant(val))
|
||||||
self.db, self.book_id = db, book_id
|
self.db, self.book_id = db, book_id
|
||||||
self.initialize_options(get_option, get_help, db, book_id)
|
self.initialize_options(get_option, get_help, db, book_id)
|
||||||
self.opt_disable_font_rescaling.toggle()
|
self.opt_disable_font_rescaling.toggle()
|
||||||
@ -35,6 +41,21 @@ class LookAndFeelWidget(Widget, Ui_Form):
|
|||||||
self.opt_remove_paragraph_spacing.toggle()
|
self.opt_remove_paragraph_spacing.toggle()
|
||||||
self.opt_remove_paragraph_spacing.toggle()
|
self.opt_remove_paragraph_spacing.toggle()
|
||||||
|
|
||||||
|
def get_value_handler(self, g):
|
||||||
|
if g is self.opt_change_justification:
|
||||||
|
ans = unicode(g.itemData(g.currentIndex()).toString())
|
||||||
|
return ans
|
||||||
|
return Widget.get_value_handler(self, g)
|
||||||
|
|
||||||
|
def set_value_handler(self, g, val):
|
||||||
|
if g is self.opt_change_justification:
|
||||||
|
for i in range(g.count()):
|
||||||
|
c = unicode(g.itemData(i).toString())
|
||||||
|
if val == c:
|
||||||
|
g.setCurrentIndex(i)
|
||||||
|
break
|
||||||
|
return True
|
||||||
|
|
||||||
def font_key_wizard(self):
|
def font_key_wizard(self):
|
||||||
from calibre.gui2.convert.font_key import FontKeyChooser
|
from calibre.gui2.convert.font_key import FontKeyChooser
|
||||||
d = FontKeyChooser(self, self.opt_base_font_size.value(),
|
d = FontKeyChooser(self, self.opt_base_font_size.value(),
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2">
|
<item row="1" column="1" colspan="2">
|
||||||
<widget class="QDoubleSpinBox" name="opt_base_font_size">
|
<widget class="QDoubleSpinBox" name="opt_base_font_size">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> pt</string>
|
<string> pt</string>
|
||||||
@ -63,7 +63,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1" colspan="2">
|
<item row="2" column="1" colspan="3">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="opt_font_size_mapping">
|
<widget class="QLineEdit" name="opt_font_size_mapping">
|
||||||
@ -84,7 +84,7 @@
|
|||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset>
|
<iconset resource="../../../../resources/images.qrc">
|
||||||
<normaloff>:/images/wizard.svg</normaloff>:/images/wizard.svg</iconset>
|
<normaloff>:/images/wizard.svg</normaloff>:/images/wizard.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="iconSize">
|
<property name="iconSize">
|
||||||
@ -107,7 +107,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2">
|
<item row="3" column="1" colspan="2">
|
||||||
<widget class="QDoubleSpinBox" name="opt_line_height">
|
<widget class="QDoubleSpinBox" name="opt_line_height">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> pt</string>
|
<string> pt</string>
|
||||||
@ -127,60 +127,50 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1" colspan="2">
|
<item row="4" column="1" colspan="3">
|
||||||
<widget class="QLineEdit" name="opt_input_encoding"/>
|
<widget class="QLineEdit" name="opt_input_encoding"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0" colspan="3">
|
<item row="5" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<widget class="QCheckBox" name="opt_remove_paragraph_spacing">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove &spacing between paragraphs</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="2" colspan="2">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="opt_remove_paragraph_spacing">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Remove &spacing between paragraphs</string>
|
<string>Indent size:</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer">
|
<widget class="QDoubleSpinBox" name="opt_remove_paragraph_spacing_indent_size">
|
||||||
<property name="orientation">
|
<property name="toolTip">
|
||||||
<enum>Qt::Horizontal</enum>
|
<string><p>When calibre removes inter paragraph spacing, it automatically sets a paragraph indent, to ensure that paragraphs can be easily distinguished. This option controls the width of that indent.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="suffix">
|
||||||
<size>
|
<string> em</string>
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
<property name="decimals">
|
||||||
</item>
|
<number>1</number>
|
||||||
<item>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
</widget>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Indent size:</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDoubleSpinBox" name="opt_remove_paragraph_spacing_indent_size">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><p>When calibre removes inter paragraph spacing, it automatically sets a paragraph indent, to ensure that paragraphs can be easily distinguished. This option controls the width of that indent.</string>
|
|
||||||
</property>
|
|
||||||
<property name="suffix">
|
|
||||||
<string> em</string>
|
|
||||||
</property>
|
|
||||||
<property name="decimals">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Text justification:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="7" column="0">
|
||||||
<widget class="QCheckBox" name="opt_linearize_tables">
|
<widget class="QCheckBox" name="opt_linearize_tables">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -188,14 +178,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="9" column="0">
|
<item row="9" column="0" colspan="4">
|
||||||
<widget class="QCheckBox" name="opt_asciiize">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Transliterate unicode characters to ASCII.</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="10" column="0" colspan="3">
|
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Extra &CSS</string>
|
<string>Extra &CSS</string>
|
||||||
@ -207,6 +190,16 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="6" column="2" colspan="2">
|
||||||
|
<widget class="QComboBox" name="opt_change_justification"/>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1" colspan="3">
|
||||||
|
<widget class="QCheckBox" name="opt_asciiize">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Transliterate unicode characters to ASCII</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="8" column="0">
|
<item row="8" column="0">
|
||||||
<widget class="QCheckBox" name="opt_insert_blank_line">
|
<widget class="QCheckBox" name="opt_insert_blank_line">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -214,35 +207,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="8" column="1" colspan="2">
|
||||||
<widget class="QLabel" name="label_5">
|
<widget class="QCheckBox" name="opt_keep_ligatures">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Text justification:</string>
|
<string>Keep &ligatures</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="2">
|
|
||||||
<widget class="QComboBox" name="opt_change_justification">
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>justify</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>left</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>original</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
|
@ -18,7 +18,8 @@ class PluginWidget(Widget, Ui_Form):
|
|||||||
HELP = _('Options specific to')+' PDF '+_('output')
|
HELP = _('Options specific to')+' PDF '+_('output')
|
||||||
|
|
||||||
def __init__(self, parent, get_option, get_help, db=None, book_id=None):
|
def __init__(self, parent, get_option, get_help, db=None, book_id=None):
|
||||||
Widget.__init__(self, parent, 'pdf_output', ['paper_size', 'orientation'])
|
Widget.__init__(self, parent, 'pdf_output', ['paper_size',
|
||||||
|
'orientation', 'preserve_cover_aspect_ratio'])
|
||||||
self.db, self.book_id = db, book_id
|
self.db, self.book_id = db, book_id
|
||||||
self.initialize_options(get_option, get_help, db, book_id)
|
self.initialize_options(get_option, get_help, db, book_id)
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<widget class="QComboBox" name="opt_orientation"/>
|
<widget class="QComboBox" name="opt_orientation"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="3" column="0">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -53,6 +53,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="opt_preserve_cover_aspect_ratio">
|
||||||
|
<property name="text">
|
||||||
|
<string>Preserve &aspect ratio of cover</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -695,8 +695,8 @@ class BooksModel(QAbstractTableModel):
|
|||||||
self.db.set(row, column, val)
|
self.db.set(row, column, val)
|
||||||
self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), \
|
self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), \
|
||||||
index, index)
|
index, index)
|
||||||
if column == self.sorted_on[0]:
|
#if column == self.sorted_on[0]:
|
||||||
self.resort()
|
# self.resort()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -601,7 +601,7 @@
|
|||||||
<normaloff>:/images/merge_books.svg</normaloff>:/images/merge_books.svg</iconset>
|
<normaloff>:/images/merge_books.svg</normaloff>:/images/merge_books.svg</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Merge books</string>
|
<string>Merge book records</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string>M</string>
|
<string>M</string>
|
||||||
|
@ -106,6 +106,13 @@ class Booq(Device):
|
|||||||
output_format = 'EPUB'
|
output_format = 'EPUB'
|
||||||
id = 'booq'
|
id = 'booq'
|
||||||
|
|
||||||
|
class TheBook(Device):
|
||||||
|
name = 'The Book'
|
||||||
|
manufacturer = 'Augen'
|
||||||
|
output_profile = 'prs505'
|
||||||
|
output_format = 'EPUB'
|
||||||
|
id = 'thebook'
|
||||||
|
|
||||||
class Avant(Booq):
|
class Avant(Booq):
|
||||||
name = 'Booq Avant'
|
name = 'Booq Avant'
|
||||||
|
|
||||||
|
@ -491,9 +491,9 @@ TXT input supports a number of options to differentiate how paragraphs are detec
|
|||||||
:guilabel:`Process using markdown`
|
:guilabel:`Process using markdown`
|
||||||
|app| also supports running TXT input though a transformation preprocessor known as markdown. Markdown
|
|app| also supports running TXT input though a transformation preprocessor known as markdown. Markdown
|
||||||
allows for basic formatting to be added to TXT documents, such as bold, italics, section headings, tables,
|
allows for basic formatting to be added to TXT documents, such as bold, italics, section headings, tables,
|
||||||
loists, a Table of Contents, etc. Marking chapter headings with a leading # and setting the chapter XPath detection
|
lists, a Table of Contents, etc. Marking chapter headings with a leading # and setting the chapter XPath detection
|
||||||
expression to "//h:h1" is the easiest way to have a proper table of contents generated from a TXT document.
|
expression to "//h:h1" is the easiest way to have a proper table of contents generated from a TXT document.
|
||||||
You can learn more about the markdown syntax at http://daringfireball.net/projects/markdown/syntax.
|
You can learn more about the markdown syntax `here <http://daringfireball.net/projects/markdown/syntax>`_.
|
||||||
|
|
||||||
|
|
||||||
Convert PDF documents
|
Convert PDF documents
|
||||||
|
@ -145,7 +145,7 @@ First perform the following steps in |app|
|
|||||||
|
|
||||||
For an iPad:
|
For an iPad:
|
||||||
|
|
||||||
Install the ReadMe app on your iPad using iTunes. Open Safari and browse to::
|
Install the ReadMe app on your iPad using iTunes. Open the Readme builtin browser and browse to::
|
||||||
|
|
||||||
http://192.168.1.2:8080/
|
http://192.168.1.2:8080/
|
||||||
|
|
||||||
|
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
@ -4,9 +4,9 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: calibre 0.6.53\n"
|
"Project-Id-Version: calibre 0.6.54\n"
|
||||||
"POT-Creation-Date: 2010-05-15 21:26+MDT\n"
|
"POT-Creation-Date: 2010-05-21 15:44+MDT\n"
|
||||||
"PO-Revision-Date: 2010-05-15 21:26+MDT\n"
|
"PO-Revision-Date: 2010-05-21 15:44+MDT\n"
|
||||||
"Last-Translator: Automatically generated\n"
|
"Last-Translator: Automatically generated\n"
|
||||||
"Language-Team: LANGUAGE\n"
|
"Language-Team: LANGUAGE\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -95,8 +95,8 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/rotate.py:63
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/rotate.py:63
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:81
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:81
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:82
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:82
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/writer.py:28
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/writer.py:87
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/writer.py:29
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/writer.py:88
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:233
|
#: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:233
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:235
|
#: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:235
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:279
|
#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:279
|
||||||
@ -135,7 +135,7 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:671
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:671
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:747
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:747
|
||||||
#: /home/kovid/work/calibre/src/calibre/library/server.py:794
|
#: /home/kovid/work/calibre/src/calibre/library/server.py:794
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:113
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:114
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:45
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:63
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
#: /home/kovid/work/calibre/src/calibre/utils/podofo/__init__.py:77
|
||||||
@ -247,7 +247,7 @@ msgid "This profile tries to provide sane defaults and is useful if you know not
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:57
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:57
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:256
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:258
|
||||||
msgid "This profile is intended for the SONY PRS line. The 500/505/600/700 etc."
|
msgid "This profile is intended for the SONY PRS line. The 500/505/600/700 etc."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -256,62 +256,62 @@ msgid "This profile is intended for the SONY PRS 300."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:78
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:78
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:290
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:292
|
||||||
msgid "This profile is intended for the SONY PRS-900."
|
msgid "This profile is intended for the SONY PRS-900."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:86
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:86
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:320
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:322
|
||||||
msgid "This profile is intended for the Microsoft Reader."
|
msgid "This profile is intended for the Microsoft Reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:97
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:97
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:331
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:333
|
||||||
msgid "This profile is intended for the Mobipocket books."
|
msgid "This profile is intended for the Mobipocket books."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:110
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:110
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:344
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:346
|
||||||
msgid "This profile is intended for the Hanlin V3 and its clones."
|
msgid "This profile is intended for the Hanlin V3 and its clones."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:122
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:122
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:356
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:358
|
||||||
msgid "This profile is intended for the Hanlin V5 and its clones."
|
msgid "This profile is intended for the Hanlin V5 and its clones."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:132
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:132
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:364
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:366
|
||||||
msgid "This profile is intended for the Cybook G3."
|
msgid "This profile is intended for the Cybook G3."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:145
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:145
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:377
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:379
|
||||||
msgid "This profile is intended for the Cybook Opus."
|
msgid "This profile is intended for the Cybook Opus."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:157
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:157
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:388
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:390
|
||||||
msgid "This profile is intended for the Amazon Kindle."
|
msgid "This profile is intended for the Amazon Kindle."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:169
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:169
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:423
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:425
|
||||||
msgid "This profile is intended for the Irex Illiad."
|
msgid "This profile is intended for the Irex Illiad."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:181
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:181
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:436
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:438
|
||||||
msgid "This profile is intended for the IRex Digital Reader 1000."
|
msgid "This profile is intended for the IRex Digital Reader 1000."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:194
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:194
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:450
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:452
|
||||||
msgid "This profile is intended for the IRex Digital Reader 800."
|
msgid "This profile is intended for the IRex Digital Reader 800."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:206
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:206
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:464
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:466
|
||||||
msgid "This profile is intended for the B&N Nook."
|
msgid "This profile is intended for the B&N Nook."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -323,23 +323,27 @@ msgstr ""
|
|||||||
msgid "This profile tries to provide sane defaults and is useful if you want to produce a document intended to be read at a computer or on a range of devices."
|
msgid "This profile tries to provide sane defaults and is useful if you want to produce a document intended to be read at a computer or on a range of devices."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:269
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:248
|
||||||
|
msgid "Intended for the iPad and similar devices with a resolution of 768x1024"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:271
|
||||||
msgid "This profile is intended for the Kobo Reader."
|
msgid "This profile is intended for the Kobo Reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:281
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:283
|
||||||
msgid "This profile is intended for the SONY PRS-300."
|
msgid "This profile is intended for the SONY PRS-300."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:299
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:301
|
||||||
msgid "This profile is intended for the 5-inch JetBook."
|
msgid "This profile is intended for the 5-inch JetBook."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:308
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:310
|
||||||
msgid "This profile is intended for the SONY PRS line. The 500/505/700 etc, in landscape mode. Mainly useful for comics."
|
msgid "This profile is intended for the SONY PRS line. The 500/505/700 etc, in landscape mode. Mainly useful for comics."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:406
|
#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:408
|
||||||
msgid "This profile is intended for the Amazon Kindle DX."
|
msgid "This profile is intended for the Amazon Kindle DX."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -403,11 +407,11 @@ msgstr ""
|
|||||||
msgid "Communicate with Android phones."
|
msgid "Communicate with Android phones."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:36
|
#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:39
|
||||||
msgid "Comma separated list of directories to send e-books to on the device. The first one that exists will be used"
|
msgid "Comma separated list of directories to send e-books to on the device. The first one that exists will be used"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:64
|
#: /home/kovid/work/calibre/src/calibre/devices/android/driver.py:67
|
||||||
msgid "Communicate with S60 phones."
|
msgid "Communicate with S60 phones."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -523,7 +527,7 @@ msgstr ""
|
|||||||
msgid "Communicate with the Kobo Reader"
|
msgid "Communicate with the Kobo Reader"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/misc.py:55
|
#: /home/kovid/work/calibre/src/calibre/devices/misc.py:56
|
||||||
msgid "Communicate with the Booq Avant"
|
msgid "Communicate with the Booq Avant"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -604,6 +608,14 @@ msgstr ""
|
|||||||
msgid "Communicate with the Teclast K3 reader."
|
msgid "Communicate with the Teclast K3 reader."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/devices/teclast/driver.py:45
|
||||||
|
msgid "Communicate with the Newsmy reader."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/devices/teclast/driver.py:60
|
||||||
|
msgid "Communicate with the iPapyrus reader."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:252
|
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:252
|
||||||
msgid "Unable to detect the %s disk drive. Try rebooting."
|
msgid "Unable to detect the %s disk drive. Try rebooting."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -916,280 +928,288 @@ msgstr ""
|
|||||||
msgid "Output saved to"
|
msgid "Output saved to"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:94
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:95
|
||||||
msgid "Level of verbosity. Specify multiple times for greater verbosity."
|
msgid "Level of verbosity. Specify multiple times for greater verbosity."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:101
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:102
|
||||||
msgid "Save the output from different stages of the conversion pipeline to the specified directory. Useful if you are unsure at which stage of the conversion process a bug is occurring."
|
msgid "Save the output from different stages of the conversion pipeline to the specified directory. Useful if you are unsure at which stage of the conversion process a bug is occurring."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:110
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:111
|
||||||
msgid "Specify the input profile. The input profile gives the conversion system information on how to interpret various information in the input document. For example resolution dependent lengths (i.e. lengths in pixels). Choices are:"
|
msgid "Specify the input profile. The input profile gives the conversion system information on how to interpret various information in the input document. For example resolution dependent lengths (i.e. lengths in pixels). Choices are:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:121
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:122
|
||||||
msgid "Specify the output profile. The output profile tells the conversion system how to optimize the created document for the specified device. In some cases, an output profile is required to produce documents that will work on a device. For example EPUB on the SONY reader. Choices are:"
|
msgid "Specify the output profile. The output profile tells the conversion system how to optimize the created document for the specified device. In some cases, an output profile is required to produce documents that will work on a device. For example EPUB on the SONY reader. Choices are:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:132
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:133
|
||||||
msgid "The base font size in pts. All font sizes in the produced book will be rescaled based on this size. By choosing a larger size you can make the fonts in the output bigger and vice versa. By default, the base font size is chosen based on the output profile you chose."
|
msgid "The base font size in pts. All font sizes in the produced book will be rescaled based on this size. By choosing a larger size you can make the fonts in the output bigger and vice versa. By default, the base font size is chosen based on the output profile you chose."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:142
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:143
|
||||||
msgid "Mapping from CSS font names to font sizes in pts. An example setting is 12,12,14,16,18,20,22,24. These are the mappings for the sizes xx-small to xx-large, with the final size being for huge fonts. The font rescaling algorithm uses these sizes to intelligently rescale fonts. The default is to use a mapping based on the output profile you chose."
|
msgid "Mapping from CSS font names to font sizes in pts. An example setting is 12,12,14,16,18,20,22,24. These are the mappings for the sizes xx-small to xx-large, with the final size being for huge fonts. The font rescaling algorithm uses these sizes to intelligently rescale fonts. The default is to use a mapping based on the output profile you chose."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:154
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:155
|
||||||
msgid "Disable all rescaling of font sizes."
|
msgid "Disable all rescaling of font sizes."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:161
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:162
|
||||||
msgid "The line height in pts. Controls spacing between consecutive lines of text. By default no line height manipulation is performed."
|
msgid "The line height in pts. Controls spacing between consecutive lines of text. By default no line height manipulation is performed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:169
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:170
|
||||||
msgid "Some badly designed documents use tables to control the layout of text on the page. When converted these documents often have text that runs off the page and other artifacts. This option will extract the content from the tables and present it in a linear fashion."
|
msgid "Some badly designed documents use tables to control the layout of text on the page. When converted these documents often have text that runs off the page and other artifacts. This option will extract the content from the tables and present it in a linear fashion."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:179
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:180
|
||||||
msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level one. If this is specified, it takes precedence over other forms of auto-detection."
|
msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level one. If this is specified, it takes precedence over other forms of auto-detection."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:188
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:189
|
||||||
msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level two. Each entry is added under the previous level one entry."
|
msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level two. Each entry is added under the previous level one entry."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:196
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:197
|
||||||
msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level three. Each entry is added under the previous level two entry."
|
msgid "XPath expression that specifies all tags that should be added to the Table of Contents at level three. Each entry is added under the previous level two entry."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:204
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:205
|
||||||
msgid "Normally, if the source file already has a Table of Contents, it is used in preference to the auto-generated one. With this option, the auto-generated one is always used."
|
msgid "Normally, if the source file already has a Table of Contents, it is used in preference to the auto-generated one. With this option, the auto-generated one is always used."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:212
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:213
|
||||||
msgid "Don't add auto-detected chapters to the Table of Contents."
|
msgid "Don't add auto-detected chapters to the Table of Contents."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:219
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:220
|
||||||
msgid "If fewer than this number of chapters is detected, then links are added to the Table of Contents. Default: %default"
|
msgid "If fewer than this number of chapters is detected, then links are added to the Table of Contents. Default: %default"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:226
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:227
|
||||||
msgid "Maximum number of links to insert into the TOC. Set to 0 to disable. Default is: %default. Links are only added to the TOC if less than the threshold number of chapters were detected."
|
msgid "Maximum number of links to insert into the TOC. Set to 0 to disable. Default is: %default. Links are only added to the TOC if less than the threshold number of chapters were detected."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:234
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:235
|
||||||
msgid "Remove entries from the Table of Contents whose titles match the specified regular expression. Matching entries and all their children are removed."
|
msgid "Remove entries from the Table of Contents whose titles match the specified regular expression. Matching entries and all their children are removed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:245
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:246
|
||||||
msgid "An XPath expression to detect chapter titles. The default is to consider <h1> or <h2> tags that contain the words \"chapter\",\"book\",\"section\" or \"part\" as chapter titles as well as any tags that have class=\"chapter\". The expression used must evaluate to a list of elements. To disable chapter detection, use the expression \"/\". See the XPath Tutorial in the calibre User Manual for further help on using this feature."
|
msgid "An XPath expression to detect chapter titles. The default is to consider <h1> or <h2> tags that contain the words \"chapter\",\"book\",\"section\" or \"part\" as chapter titles as well as any tags that have class=\"chapter\". The expression used must evaluate to a list of elements. To disable chapter detection, use the expression \"/\". See the XPath Tutorial in the calibre User Manual for further help on using this feature."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:259
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:260
|
||||||
msgid "Specify how to mark detected chapters. A value of \"pagebreak\" will insert page breaks before chapters. A value of \"rule\" will insert a line before chapters. A value of \"none\" will disable chapter marking and a value of \"both\" will use both page breaks and lines to mark chapters."
|
msgid "Specify how to mark detected chapters. A value of \"pagebreak\" will insert page breaks before chapters. A value of \"rule\" will insert a line before chapters. A value of \"none\" will disable chapter marking and a value of \"both\" will use both page breaks and lines to mark chapters."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:269
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:270
|
||||||
msgid "Either the path to a CSS stylesheet or raw CSS. This CSS will be appended to the style rules from the source file, so it can be used to override those rules."
|
msgid "Either the path to a CSS stylesheet or raw CSS. This CSS will be appended to the style rules from the source file, so it can be used to override those rules."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:278
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:279
|
||||||
msgid "An XPath expression. Page breaks are inserted before the specified elements."
|
msgid "An XPath expression. Page breaks are inserted before the specified elements."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:284
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:285
|
||||||
msgid "Set the top margin in pts. Default is %default. Note: 72 pts equals 1 inch"
|
msgid "Set the top margin in pts. Default is %default. Note: 72 pts equals 1 inch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:289
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:290
|
||||||
msgid "Set the bottom margin in pts. Default is %default. Note: 72 pts equals 1 inch"
|
msgid "Set the bottom margin in pts. Default is %default. Note: 72 pts equals 1 inch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:294
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:295
|
||||||
msgid "Set the left margin in pts. Default is %default. Note: 72 pts equals 1 inch"
|
msgid "Set the left margin in pts. Default is %default. Note: 72 pts equals 1 inch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:299
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:300
|
||||||
msgid "Set the right margin in pts. Default is %default. Note: 72 pts equals 1 inch"
|
msgid "Set the right margin in pts. Default is %default. Note: 72 pts equals 1 inch"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:305
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:306
|
||||||
msgid "Change text justification. A value of \"left\" converts all justified text in the source to left aligned (i.e. unjustified) text. A value of \"justify\" converts all unjustified text to justified. A value of \"original\" (the default) does not change justification in the source file. Note that only some output formats support justification."
|
msgid "Change text justification. A value of \"left\" converts all justified text in the source to left aligned (i.e. unjustified) text. A value of \"justify\" converts all unjustified text to justified. A value of \"original\" (the default) does not change justification in the source file. Note that only some output formats support justification."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:315
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:316
|
||||||
msgid "Remove spacing between paragraphs. Also sets an indent on paragraphs of 1.5em. Spacing removal will not work if the source file does not use paragraphs (<p> or <div> tags)."
|
msgid "Remove spacing between paragraphs. Also sets an indent on paragraphs of 1.5em. Spacing removal will not work if the source file does not use paragraphs (<p> or <div> tags)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:322
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:323
|
||||||
msgid "When calibre removes inter paragraph spacing, it automatically sets a paragraph indent, to ensure that paragraphs can be easily distinguished. This option controls the width of that indent."
|
msgid "When calibre removes inter paragraph spacing, it automatically sets a paragraph indent, to ensure that paragraphs can be easily distinguished. This option controls the width of that indent."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:329
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:330
|
||||||
msgid "Use the cover detected from the source file in preference to the specified cover."
|
msgid "Use the cover detected from the source file in preference to the specified cover."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:335
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:336
|
||||||
msgid "Insert a blank line between paragraphs. Will not work if the source file does not use paragraphs (<p> or <div> tags)."
|
msgid "Insert a blank line between paragraphs. Will not work if the source file does not use paragraphs (<p> or <div> tags)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:342
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:343
|
||||||
msgid "Remove the first image from the input ebook. Useful if the first image in the source file is a cover and you are specifying an external cover."
|
msgid "Remove the first image from the input ebook. Useful if the first image in the source file is a cover and you are specifying an external cover."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:350
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:351
|
||||||
msgid "Insert the book metadata at the start of the book. This is useful if your ebook reader does not support displaying/searching metadata directly."
|
msgid "Insert the book metadata at the start of the book. This is useful if your ebook reader does not support displaying/searching metadata directly."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:358
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:359
|
||||||
msgid "Attempt to detect and correct hard line breaks and other problems in the source file. This may make things worse, so use with care."
|
msgid "Attempt to detect and correct hard line breaks and other problems in the source file. This may make things worse, so use with care."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:366
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:367
|
||||||
msgid "Use a regular expression to try and remove the header."
|
msgid "Use a regular expression to try and remove the header."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:373
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:374
|
||||||
msgid "The regular expression to use to remove the header."
|
msgid "The regular expression to use to remove the header."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:379
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:380
|
||||||
msgid "Use a regular expression to try and remove the footer."
|
msgid "Use a regular expression to try and remove the footer."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:386
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:387
|
||||||
msgid "The regular expression to use to remove the footer."
|
msgid "The regular expression to use to remove the footer."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:393
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:394
|
||||||
msgid "Read metadata from the specified OPF file. Metadata read from this file will override any metadata in the source file."
|
msgid "Read metadata from the specified OPF file. Metadata read from this file will override any metadata in the source file."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:400
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:401
|
||||||
msgid "Transliterate unicode characters to an ASCII representation. Use with care because this will replace unicode characters with ASCII. For instance it will replace \"%s\" with \"Mikhail Gorbachiov\". Also, note that in cases where there are multiple representations of a character (characters shared by Chinese and Japanese for instance) the representation used by the largest number of people will be used (Chinese in the previous example)."
|
msgid "Transliterate unicode characters to an ASCII representation. Use with care because this will replace unicode characters with ASCII. For instance it will replace \"%s\" with \"Mikhail Gorbachiov\". Also, note that in cases where there are multiple representations of a character (characters shared by Chinese and Japanese for instance) the representation used by the largest number of people will be used (Chinese in the previous example)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:415
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:416
|
||||||
|
msgid "Preserve ligatures present in the input document. A ligature is a special rendering of a pair of characters like ff, fi, fl et cetera. Most readers do not have support for ligatures in their default fonts, so they are unlikely to render correctly. By default, calibre will turn a ligature into the corresponding pair of normal characters. This option will preserve them instead."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:428
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:38
|
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:38
|
||||||
msgid "Set the title."
|
msgid "Set the title."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:419
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:432
|
||||||
msgid "Set the authors. Multiple authors should be separated by ampersands."
|
msgid "Set the authors. Multiple authors should be separated by ampersands."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:424
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:437
|
||||||
msgid "The version of the title to be used for sorting. "
|
msgid "The version of the title to be used for sorting. "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:428
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:441
|
||||||
msgid "String to be used when sorting by author. "
|
msgid "String to be used when sorting by author. "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:432
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:445
|
||||||
msgid "Set the cover to the specified file or URL"
|
msgid "Set the cover to the specified file or URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:436
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:449
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:54
|
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:54
|
||||||
msgid "Set the ebook description."
|
msgid "Set the ebook description."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:440
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:453
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:56
|
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:56
|
||||||
msgid "Set the ebook publisher."
|
msgid "Set the ebook publisher."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:444
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:457
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:60
|
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:60
|
||||||
msgid "Set the series this ebook belongs to."
|
msgid "Set the series this ebook belongs to."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:448
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:461
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:62
|
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:62
|
||||||
msgid "Set the index of the book in this series."
|
msgid "Set the index of the book in this series."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:452
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:465
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:64
|
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:64
|
||||||
msgid "Set the rating. Should be a number between 1 and 5."
|
msgid "Set the rating. Should be a number between 1 and 5."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:456
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:469
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:66
|
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:66
|
||||||
msgid "Set the ISBN of the book."
|
msgid "Set the ISBN of the book."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:460
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:473
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:68
|
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:68
|
||||||
msgid "Set the tags for the book. Should be a comma separated list."
|
msgid "Set the tags for the book. Should be a comma separated list."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:464
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:477
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:70
|
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:70
|
||||||
msgid "Set the book producer."
|
msgid "Set the book producer."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:468
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:481
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:72
|
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/cli.py:72
|
||||||
msgid "Set the language."
|
msgid "Set the language."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:472
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:485
|
||||||
msgid "Set the publication date."
|
msgid "Set the publication date."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:476
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:489
|
||||||
msgid "Set the book timestamp (used by the date column in calibre)."
|
msgid "Set the book timestamp (used by the date column in calibre)."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:576
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:589
|
||||||
msgid "Could not find an ebook inside the archive"
|
msgid "Could not find an ebook inside the archive"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:634
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:647
|
||||||
msgid "Values of series index and rating must be numbers. Ignoring"
|
msgid "Values of series index and rating must be numbers. Ignoring"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:641
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:654
|
||||||
msgid "Failed to parse date/time"
|
msgid "Failed to parse date/time"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:788
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:802
|
||||||
msgid "Converting input to HTML..."
|
msgid "Converting input to HTML..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:815
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:829
|
||||||
msgid "Running transforms on ebook..."
|
msgid "Running transforms on ebook..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:902
|
#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/plumber.py:916
|
||||||
msgid "Creating"
|
msgid "Creating"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:58
|
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:205
|
||||||
msgid "Extract the contents of the generated EPUB file to the specified directory. The contents of the directory are first deleted, so be careful."
|
msgid "Extract the contents of the generated EPUB file to the specified directory. The contents of the directory are first deleted, so be careful."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:64
|
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:211
|
||||||
msgid "Turn off splitting at page breaks. Normally, input files are automatically split at every page break into two files. This gives an output ebook that can be parsed faster and with less resources. However, splitting is slow and if your source file contains a very large number of page breaks, you should turn off splitting on page breaks."
|
msgid "Turn off splitting at page breaks. Normally, input files are automatically split at every page break into two files. This gives an output ebook that can be parsed faster and with less resources. However, splitting is slow and if your source file contains a very large number of page breaks, you should turn off splitting on page breaks."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:75
|
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:222
|
||||||
msgid "Split all HTML files larger than this size (in KB). This is necessary as most EPUB readers cannot handle large file sizes. The default of %defaultKB is the size required for Adobe Digital Editions."
|
msgid "Split all HTML files larger than this size (in KB). This is necessary as most EPUB readers cannot handle large file sizes. The default of %defaultKB is the size required for Adobe Digital Editions."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:82
|
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:229
|
||||||
msgid "Normally, if the input file has no cover and you don't specify one, a default cover is generated with the title, authors, etc. This option disables the generation of this cover."
|
msgid "Normally, if the input file has no cover and you don't specify one, a default cover is generated with the title, authors, etc. This option disables the generation of this cover."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:88
|
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:235
|
||||||
msgid "Do not use SVG for the book cover. Use this option if your EPUB is going to be used ona device that does not support SVG, like the iPhone or the JetBook Lite. Without this option, such devices will display the cover as a blank page."
|
msgid "Do not use SVG for the book cover. Use this option if your EPUB is going to be used ona device that does not support SVG, like the iPhone or the JetBook Lite. Without this option, such devices will display the cover as a blank page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/ebooks/epub/output.py:243
|
||||||
|
msgid "When using an SVG cover, this option will cause the cover to scale to cover the available screen area, but still preserve its aspect ratio (ratio of width to height). That means there may be white borders at the sides or top and bottom of the image, but the image will never be distorted. Without this option the image may be slightly distorted, but there will be no borders."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/fb2ml.py:144
|
#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/fb2ml.py:144
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/rb/rbml.py:102
|
#: /home/kovid/work/calibre/src/calibre/ebooks/rb/rbml.py:102
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/txtml.py:77
|
#: /home/kovid/work/calibre/src/calibre/ebooks/txt/txtml.py:77
|
||||||
@ -2026,19 +2046,19 @@ msgstr ""
|
|||||||
msgid "Split Options:"
|
msgid "Split Options:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:31
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:59
|
||||||
msgid "The unit of measure. Default is inch. Choices are %s Note: This does not override the unit for margins!"
|
msgid "The unit of measure. Default is inch. Choices are %s Note: This does not override the unit for margins!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:36
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:64
|
||||||
msgid "The size of the paper. This size will be overridden when an output profile is used. Default is letter. Choices are %s"
|
msgid "The size of the paper. This size will be overridden when an output profile is used. Default is letter. Choices are %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:40
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:68
|
||||||
msgid "Custom size of the document. Use the form widthxheight EG. `123x321` to specify the width and height. This overrides any specified paper-size."
|
msgid "Custom size of the document. Use the form widthxheight EG. `123x321` to specify the width and height. This overrides any specified paper-size."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:45
|
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/output.py:73
|
||||||
msgid "The orientation of the page. Default is portrait. Choices are %s"
|
msgid "The orientation of the page. Default is portrait. Choices are %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -2307,10 +2327,10 @@ msgstr ""
|
|||||||
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_tab_template_ui.py:27
|
#: /home/kovid/work/calibre/src/calibre/gui2/catalog/catalog_tab_template_ui.py:27
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:88
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:88
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:49
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:49
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:44
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:48
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input_ui.py:28
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input_ui.py:28
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output_ui.py:28
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output_ui.py:28
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:125
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:119
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:115
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:115
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:166
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:166
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:66
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:66
|
||||||
@ -2512,7 +2532,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:52
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:52
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:53
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/debug_ui.py:53
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:131
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:125
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:171
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:171
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/xexp_edit_ui.py:52
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/xexp_edit_ui.py:52
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:76
|
#: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:76
|
||||||
@ -2558,26 +2578,30 @@ msgstr ""
|
|||||||
msgid "EPUB Output"
|
msgid "EPUB Output"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:45
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:49
|
||||||
msgid "Do not &split on page breaks"
|
msgid "Do not &split on page breaks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:46
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:50
|
||||||
msgid "Split files &larger than:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:47
|
|
||||||
msgid " KB"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:48
|
|
||||||
msgid "No default &cover"
|
msgid "No default &cover"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:49
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:51
|
||||||
msgid "No &SVG cover"
|
msgid "No &SVG cover"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:52
|
||||||
|
msgid "Preserve cover &aspect ratio"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:53
|
||||||
|
msgid "Split files &larger than:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:54
|
||||||
|
msgid " KB"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:12
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:12
|
||||||
msgid "FB2 Input"
|
msgid "FB2 Input"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2618,15 +2642,15 @@ msgid "&Base font size:"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:105
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:105
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:129
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:123
|
||||||
msgid "Font size &key:"
|
msgid "Font size &key:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:106
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:106
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:110
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:110
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:112
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/font_key_ui.py:112
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:128
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:122
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:133
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:127
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:118
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:118
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:120
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:120
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:125
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:125
|
||||||
@ -2665,72 +2689,76 @@ msgstr ""
|
|||||||
msgid "Control the look and feel of the output"
|
msgid "Control the look and feel of the output"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:126
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel.py:30
|
||||||
|
msgid "Original"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel.py:31
|
||||||
|
msgid "Left align"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel.py:32
|
||||||
|
msgid "Justify text"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:120
|
||||||
msgid "&Disable font size rescaling"
|
msgid "&Disable font size rescaling"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:127
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:121
|
||||||
msgid "Base &font size:"
|
msgid "Base &font size:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:130
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:124
|
||||||
msgid "Wizard to help you choose an appropriate font size key"
|
msgid "Wizard to help you choose an appropriate font size key"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:132
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:126
|
||||||
msgid "Line &height:"
|
msgid "Line &height:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:134
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:128
|
||||||
msgid "Input character &encoding:"
|
msgid "Input character &encoding:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:135
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:129
|
||||||
msgid "Remove &spacing between paragraphs"
|
msgid "Remove &spacing between paragraphs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:136
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:130
|
||||||
msgid "Indent size:"
|
msgid "Indent size:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:137
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:131
|
||||||
msgid "<p>When calibre removes inter paragraph spacing, it automatically sets a paragraph indent, to ensure that paragraphs can be easily distinguished. This option controls the width of that indent."
|
msgid "<p>When calibre removes inter paragraph spacing, it automatically sets a paragraph indent, to ensure that paragraphs can be easily distinguished. This option controls the width of that indent."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:138
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:132
|
||||||
msgid " em"
|
msgid " em"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:139
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:133
|
||||||
msgid "&Linearize tables"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:140
|
|
||||||
msgid "&Transliterate unicode characters to ASCII."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:141
|
|
||||||
msgid "Extra &CSS"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:142
|
|
||||||
msgid "Insert &blank line"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:143
|
|
||||||
msgid "Text justification:"
|
msgid "Text justification:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:144
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:134
|
||||||
msgid "justify"
|
msgid "&Linearize tables"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:145
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:135
|
||||||
msgid "left"
|
msgid "Extra &CSS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:146
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:136
|
||||||
msgid "original"
|
msgid "&Transliterate unicode characters to ASCII"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:137
|
||||||
|
msgid "Insert &blank line"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:138
|
||||||
|
msgid "Keep &ligatures"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:19
|
#: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:19
|
||||||
@ -7833,18 +7861,22 @@ msgid "English (Ireland)"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:109
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:109
|
||||||
msgid "Spanish (Paraguay)"
|
msgid "English (China)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:110
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:110
|
||||||
msgid "German (AT)"
|
msgid "Spanish (Paraguay)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:111
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:111
|
||||||
msgid "Dutch (NL)"
|
msgid "German (AT)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:112
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:112
|
||||||
|
msgid "Dutch (NL)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: /home/kovid/work/calibre/src/calibre/utils/localization.py:113
|
||||||
msgid "Dutch (BE)"
|
msgid "Dutch (BE)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -7868,13 +7900,13 @@ msgstr ""
|
|||||||
msgid "Control email delivery"
|
msgid "Control email delivery"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/__init__.py:102
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/__init__.py:113
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/__init__.py:124
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/__init__.py:135
|
||||||
msgid "Unknown feed"
|
msgid "Unknown feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/__init__.py:142
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/__init__.py:153
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/__init__.py:165
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/__init__.py:178
|
||||||
msgid "Untitled article"
|
msgid "Untitled article"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -7970,23 +8002,23 @@ msgstr ""
|
|||||||
msgid "Untitled Article"
|
msgid "Untitled Article"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1228
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1230
|
||||||
msgid "Article downloaded: %s"
|
msgid "Article downloaded: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1239
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1241
|
||||||
msgid "Article download failed: %s"
|
msgid "Article download failed: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1256
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1258
|
||||||
msgid "Fetching feed"
|
msgid "Fetching feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1403
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1405
|
||||||
msgid "Failed to log in, check your username and password for the calibre Periodicals service."
|
msgid "Failed to log in, check your username and password for the calibre Periodicals service."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1419
|
#: /home/kovid/work/calibre/src/calibre/web/feeds/news.py:1421
|
||||||
msgid "You do not have permission to download this issue. Either your subscription has expired or you have exceeded the maximum allowed downloads for today."
|
msgid "You do not have permission to download this issue. Either your subscription has expired or you have exceeded the maximum allowed downloads for today."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
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
8663
src/calibre/translations/en_AU.po
Normal file
8663
src/calibre/translations/en_AU.po
Normal file
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
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
8663
src/calibre/translations/th.po
Normal file
8663
src/calibre/translations/th.po
Normal file
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
@ -106,6 +106,7 @@ _extra_lang_codes = {
|
|||||||
'en_SG' : _('English (Singapore)'),
|
'en_SG' : _('English (Singapore)'),
|
||||||
'en_YE' : _('English (Yemen)'),
|
'en_YE' : _('English (Yemen)'),
|
||||||
'en_IE' : _('English (Ireland)'),
|
'en_IE' : _('English (Ireland)'),
|
||||||
|
'en_CN' : _('English (China)'),
|
||||||
'es_PY' : _('Spanish (Paraguay)'),
|
'es_PY' : _('Spanish (Paraguay)'),
|
||||||
'de_AT' : _('German (AT)'),
|
'de_AT' : _('German (AT)'),
|
||||||
'nl' : _('Dutch (NL)'),
|
'nl' : _('Dutch (NL)'),
|
||||||
|
@ -49,6 +49,17 @@ class Article(object):
|
|||||||
self.date = published
|
self.date = published
|
||||||
self.utctime = dt_factory(self.date, assume_utc=True, as_utc=True)
|
self.utctime = dt_factory(self.date, assume_utc=True, as_utc=True)
|
||||||
self.localtime = self.utctime.astimezone(local_tz)
|
self.localtime = self.utctime.astimezone(local_tz)
|
||||||
|
self._formatted_date = None
|
||||||
|
|
||||||
|
@dynamic_property
|
||||||
|
def formatted_date(self):
|
||||||
|
def fget(self):
|
||||||
|
if self._formatted_date is None:
|
||||||
|
self._formatted_date = self.localtime.strftime(" [%a, %d %b %H:%M]")
|
||||||
|
return self._formatted_date
|
||||||
|
def fset(self, val):
|
||||||
|
self._formatted_date = val
|
||||||
|
return property(fget=fget, fset=fset)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def title(self):
|
def title(self):
|
||||||
@ -150,6 +161,8 @@ class Feed(object):
|
|||||||
self.articles.append(article)
|
self.articles.append(article)
|
||||||
else:
|
else:
|
||||||
self.logger.debug('Skipping article %s (%s) from feed %s as it is too old.'%(title, article.localtime.strftime('%a, %d %b, %Y %H:%M'), self.title))
|
self.logger.debug('Skipping article %s (%s) from feed %s as it is too old.'%(title, article.localtime.strftime('%a, %d %b, %Y %H:%M'), self.title))
|
||||||
|
d = item.get('date', '')
|
||||||
|
article.formatted_date = d
|
||||||
|
|
||||||
|
|
||||||
def parse_article(self, item):
|
def parse_article(self, item):
|
||||||
|
@ -1179,6 +1179,8 @@ class BasicNewsRecipe(Recipe):
|
|||||||
body.insert(len(body.contents), elem)
|
body.insert(len(body.contents), elem)
|
||||||
with open(last, 'wb') as fi:
|
with open(last, 'wb') as fi:
|
||||||
fi.write(unicode(soup).encode('utf-8'))
|
fi.write(unicode(soup).encode('utf-8'))
|
||||||
|
if len(feeds) == 0:
|
||||||
|
raise Exception('All feeds are empty, aborting.')
|
||||||
|
|
||||||
if len(feeds) > 1:
|
if len(feeds) > 1:
|
||||||
for i, f in enumerate(feeds):
|
for i, f in enumerate(feeds):
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user