diff --git a/recipes/edge_conversations.recipe b/recipes/edge_conversations.recipe new file mode 100644 index 0000000000..4d5ae5dbc3 --- /dev/null +++ b/recipes/edge_conversations.recipe @@ -0,0 +1,50 @@ +__license__ = 'GPL v3' +__copyright__ = '2012 Levien van Zon ' + +''' +Fetch Edge.org conversations +''' +from calibre.web.feeds.news import BasicNewsRecipe + +class EdgeConversationRSS(BasicNewsRecipe): + title = u'Edge.org Conversations' + __author__ = 'levien' + language = 'en' + description = '''Edge.org offers "open-minded, free ranging, intellectually + playful ... an unadorned pleasure in curiosity, a collective expression of + wonder at the living and inanimate world ... an ongoing and thrilling + colloquium.''' + oldest_article = 60 + max_articles_per_feed = 100 + no_stylesheets = True + + keep_only_tags = [dict(name='div', attrs={'class':'HomeLeftPannel IMGCTRL'}) ] + remove_tags = [ + dict(name='div',attrs={'class':'Logo'}) + ] + + feeds = [(u'Edge RSS', u'http://edge.org/feeds/')] + + def print_version(self, url): + return url.replace('conversation/', 'conversation.php?cid=') + + def parse_feeds(self): + + # Call parent's method. + feeds = BasicNewsRecipe.parse_feeds(self) + + # Loop through all feeds. + for feed in feeds: + + # Loop through all articles in feed. + for article in feed.articles[:]: + + # Remove anything that is not a conversation, and remove PDF files as well... + + if not ('CONVERSATION' in article.title): + feed.articles.remove(article) + elif 'pdf' in article.url: + feed.articles.remove(article) + + return feeds + diff --git a/recipes/novilist_novine_hr.recipe b/recipes/novilist_novine_hr.recipe index b0ff97711a..4cd3e8277a 100644 --- a/recipes/novilist_novine_hr.recipe +++ b/recipes/novilist_novine_hr.recipe @@ -22,13 +22,16 @@ class NoviList_hr(BasicNewsRecipe): language = 'hr' remove_empty_feeds = True publication_type = 'newspaper' - needs_subscription = 'required' + needs_subscription = True masthead_url = 'http://novine.novilist.hr/images/system/novilist-logo.jpg' + index = 'http://novine.novilist.hr/' extra_css = """ - body{font-family: Geneva,Arial,Helvetica,Swiss,sans-serif } + @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)} + body{font-family: Geneva,Arial,Helvetica,Swiss,sans1,sans-serif } img{display:block; margin-bottom: 0.4em; margin-top: 0.4em} - .nadnaslov,.podnaslov{font-size: small; text-align: center} - .naslov{font-size: x-large; color: maroon; font-weight: bold} + .nadnaslov,.podnaslov{font-size: small; display: block; margin-bottom: 1em} + .naslov{font-size: x-large; color: maroon; font-weight: bold; display: block; margin-bottom: 1em;} + p{display: block} """ preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')] @@ -47,12 +50,12 @@ class NoviList_hr(BasicNewsRecipe): ] remove_tags = [dict(name=['meta', 'link', 'iframe', 'embed', 'object'])] - remove_attributes=['border', 'lang'] + remove_attributes=['border', 'lang', 'size', 'face', 'bgcolor'] def get_browser(self): br = BasicNewsRecipe.get_browser() if self.username is not None and self.password is not None: - br.open('http://novine.novilist.hr/loginnow.asp') + br.open(self.index + 'loginnow.asp') br.select_form(nr=0) br['username'] = self.username br['password'] = self.password @@ -62,11 +65,11 @@ class NoviList_hr(BasicNewsRecipe): def parse_index(self): articles = [] count = 0 - soup = self.index_to_soup('http://novine.novilist.hr/') + soup = self.index_to_soup(self.index) #cover url for alink in soup.findAll('a'): if alink['href'].startswith('images/clanci/DOC_'): - self.cover_url = 'http://novine.novilist.hr/' + alink['href'] + self.cover_url = self.index + alink['href'] #feeds for item in soup.findAll('td',attrs={'class':'tocrubrika'}): count = count +1 @@ -74,28 +77,24 @@ class NoviList_hr(BasicNewsRecipe): return articles aitem = item.a section = self.tag_to_string(aitem) - feedlink = 'http://novine.novilist.hr/' + aitem['href'] + feedlink = self.index + aitem['href'] feedpage = self.index_to_soup(feedlink) self.report_progress(0, _('Fetching feed')+' %s...'%(section)) inarts = [] for alink in feedpage.findAll('a',attrs={'class':'naslovlinkdesno'}): - url = 'http://novine.novilist.hr/' + alink['href'] - title = self.tag_to_string(alink) - date = strftime(self.timefmt) - description = '' + url = self.index + alink['href'] inarts.append({ - 'title' :title - ,'date' :date + 'title' :self.tag_to_string(alink) + ,'date' :strftime(self.timefmt) ,'url' :url - ,'description':description + ,'description':'' }) - articles.append((section,inarts)) + if self.remove_empty_feeds: + if inarts: + articles.append((section,inarts)) + else: + articles.append((section,inarts)) return articles def print_version(self, url): return url.replace('?WCI=Rubrike&','?WCI=Pretrazivac&') - - def preprocess_html(self, soup): - for item in soup.findAll(style=True): - del item['style'] - return soup diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index f17b909ea7..82c2519e29 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -10,7 +10,10 @@ from math import floor from functools import partial warnings.simplefilter('ignore', DeprecationWarning) - +try: + os.getcwdu() +except: + os.chdir(os.path.expanduser('~')) from calibre.constants import (iswindows, isosx, islinux, isfrozen, isbsd, preferred_encoding, __appname__, __version__, __author__, diff --git a/src/calibre/devices/eb600/driver.py b/src/calibre/devices/eb600/driver.py index 49a648f3ac..e733d8d8d2 100644 --- a/src/calibre/devices/eb600/driver.py +++ b/src/calibre/devices/eb600/driver.py @@ -97,7 +97,7 @@ class POCKETBOOK360(EB600): VENDOR_NAME = ['PHILIPS', '__POCKET', 'POCKETBO'] WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['MASS_STORGE', 'BOOK_USB_STORAGE', - 'POCKET_611_61'] + 'OK_POCKET_611_61'] OSX_MAIN_MEM = OSX_CARD_A_MEM = 'Philips Mass Storge Media' OSX_MAIN_MEM_VOL_PAT = re.compile(r'/Pocket') diff --git a/src/calibre/devices/iriver/driver.py b/src/calibre/devices/iriver/driver.py index 21b188e031..7479c10866 100644 --- a/src/calibre/devices/iriver/driver.py +++ b/src/calibre/devices/iriver/driver.py @@ -6,6 +6,8 @@ __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' +import re + from calibre.devices.usbms.driver import USBMS class IRIVER_STORY(USBMS): @@ -25,7 +27,9 @@ class IRIVER_STORY(USBMS): VENDOR_NAME = 'IRIVER' WINDOWS_MAIN_MEM = ['STORY', 'STORY_EB05', 'STORY_WI-FI', 'STORY_EB07'] + WINDOWS_MAIN_MEM = re.compile(r'(%s)&'%('|'.join(WINDOWS_MAIN_MEM))) WINDOWS_CARD_A_MEM = ['STORY', 'STORY_SD'] + WINDOWS_CARD_A_MEM = re.compile(r'(%s)&'%('|'.join(WINDOWS_CARD_A_MEM))) #OSX_MAIN_MEM = 'Kindle Internal Storage Media' #OSX_CARD_A_MEM = 'Kindle Card Storage Media' diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py index 096f041ca6..bc01cc13cd 100644 --- a/src/calibre/ebooks/oeb/base.py +++ b/src/calibre/ebooks/oeb/base.py @@ -942,12 +942,12 @@ class Manifest(object): if isinstance(data, etree._Element): ans = xml2str(data, pretty_print=self.oeb.pretty_print) if self.media_type in OEB_DOCS: - # Convert self closing div|span|a tags to normally closed - # ones, as they are interpreted incorrectly by some browser - # based renderers + # Convert self closing div|span|a|video|audio|iframe tags + # to normally closed ones, as they are interpreted + # incorrectly by some browser based renderers ans = re.sub( # tag name followed by either a space or a / - r'<(?Pdiv|a|span)(?=[\s/])(?P[^>]*)/>', + r'<(?Pdiv|a|span|video|audio|iframe)(?=[\s/])(?P[^>]*)/>', r'<\g\g>>', ans) return ans if isinstance(data, unicode): diff --git a/src/calibre/ebooks/oeb/display/cfi.coffee b/src/calibre/ebooks/oeb/display/cfi.coffee index ef8401deb8..5f27446ffe 100644 --- a/src/calibre/ebooks/oeb/display/cfi.coffee +++ b/src/calibre/ebooks/oeb/display/cfi.coffee @@ -398,8 +398,8 @@ class CanonicalFragmentIdentifier break rect = target.getBoundingClientRect() - x = x - rect.x - y = y - rect.y + x -= rect.left + y -= rect.top cdoc = cd cwin = cdoc.defaultView diff --git a/src/calibre/ebooks/oeb/display/test-cfi/cfi-test.coffee b/src/calibre/ebooks/oeb/display/test-cfi/cfi-test.coffee index b259636722..3479c95511 100644 --- a/src/calibre/ebooks/oeb/display/test-cfi/cfi-test.coffee +++ b/src/calibre/ebooks/oeb/display/test-cfi/cfi-test.coffee @@ -32,10 +32,12 @@ window_ypos = (pos=null) -> mark_and_reload = (evt) -> # Remove image in case the click was on the image itself, we want the cfi to # be on the underlying element + x = evt.clientX + y = evt.clientY if evt.button == 2 return # Right mouse click, generated only in firefox reset = document.getElementById('reset') - if document.elementFromPoint(evt.clientX, evt.clientY) == reset + if document.elementFromPoint(x, y) == reset return ms = document.getElementById("marker") if ms @@ -43,7 +45,7 @@ mark_and_reload = (evt) -> fn = () -> try - window.current_cfi = window.cfi.at(evt.clientX, evt.clientY) + window.current_cfi = window.cfi.at(x, y) catch err alert("Failed to calculate cfi: #{ err }") return @@ -57,6 +59,28 @@ mark_and_reload = (evt) -> setTimeout(fn, 1) null +window_scroll_pos = (win) -> + if typeof(win.pageXOffset) == 'number' + x = win.pageXOffset + y = win.pageYOffset + else # IE < 9 + if document.body and ( document.body.scrollLeft or document.body.scrollTop ) + x = document.body.scrollLeft + y = document.body.scrollTop + else if document.documentElement and ( document.documentElement.scrollLeft or document.documentElement.scrollTop) + y = document.documentElement.scrollTop + x = document.documentElement.scrollLeft + return [x, y] + +frame_clicked = (evt) -> + iframe = evt.target.ownerDocument.defaultView.frameElement + # We know that the offset parent of the iframe is body + # So we can easily calculate the event co-ords w.r.t. the browser window + [winx, winy] = window_scroll_pos(window) + x = evt.clientX + iframe.offsetLeft - winx + y = evt.clientY + iframe.offsetTop - winy + mark_and_reload({'clientX':x, 'clientY':y, 'button':evt.button}) + window.onload = -> try window.cfi.is_compatible() @@ -64,6 +88,9 @@ window.onload = -> alert(error) return document.onclick = mark_and_reload + for iframe in document.getElementsByTagName("iframe") + iframe.contentWindow.document.onclick = frame_clicked + r = location.hash.match(/#(\d*)epubcfi\((.+)\)$/) if r window.current_cfi = r[2] diff --git a/src/calibre/ebooks/oeb/display/test-cfi/iframe.html b/src/calibre/ebooks/oeb/display/test-cfi/iframe.html new file mode 100644 index 0000000000..fb2f0f969c --- /dev/null +++ b/src/calibre/ebooks/oeb/display/test-cfi/iframe.html @@ -0,0 +1,30 @@ + + + + Testing EPUB CFI + + +

But I must explain to you how all this mistaken + idea of denouncing pleasure and praising pain was born and I will + give you a complete account of the system, and expound the actual + teachings of the great explorer of the truth, the master-builder of + human happiness. No one rejects, dislikes, or avoids pleasure + itself, because it is pleasure, but because those who do not know + how to pursue pleasure rationally encounter consequences that are + extremely painful. Nor again is there anyone who loves or + pursues or desires to obtain pain of itself, because it is + pain, but because occasionally circumstances occur in which toil + and pain can procure him some great pleasure. To take a trivial + example, which of us ever undertakes laborious physical exercise, + except to obtain some advantage from it? But who has any right to + find fault with a man who chooses to enjoy a pleasure that has no + annoying consequences, or one who avoids a pain that produces no + resultant pleasure? On the other hand, we denounce with righteous + indignation and dislike men who are so beguiled and demoralized by + the charms of pleasure of the moment, so blinded by desire, that + they cannot foresee

+ + + + + diff --git a/src/calibre/ebooks/oeb/display/test-cfi/index.html b/src/calibre/ebooks/oeb/display/test-cfi/index.html index 53d84de0c7..9ece7940a7 100644 --- a/src/calibre/ebooks/oeb/display/test-cfi/index.html +++ b/src/calibre/ebooks/oeb/display/test-cfi/index.html @@ -118,6 +118,10 @@ Test Image +

Iframes

+

Try clicking anywhere in the iframe below:

+ +

Video

Try clicking on this video while it is playing. The page should reload with the video paused at the point it was at when you @@ -125,7 +129,7 @@ play (otherwise the click will cause a reload).

]+)/>', re.IGNORECASE) @@ -483,7 +481,8 @@ class DocumentView(QWebView): # {{{ self.initial_pos = 0.0 self.to_bottom = False self.document = Document(self.shortcuts, parent=self, - resize_callback=self.viewport_resized) + resize_callback=self.viewport_resized, + debug_javascript=debug_javascript) self.setPage(self.document) self.manager = None self._reference_mode = False diff --git a/src/calibre/gui2/viewer/javascript.py b/src/calibre/gui2/viewer/javascript.py index b8fdc154c3..ab8492dc6f 100644 --- a/src/calibre/gui2/viewer/javascript.py +++ b/src/calibre/gui2/viewer/javascript.py @@ -39,14 +39,14 @@ class JavaScriptLoader(object): self._cache = {} self._hp_cache = {} - def __getattr__(self, name): + def get(self, name): ans = self._cache.get(name, None) if ans is None: src = self.CS.get(name, None) if src is None: src = self.JS.get(name, None) if src is None: - raise AttributeError('No such resource: %s'%name) + raise KeyError('No such resource: %s'%name) ans = P(src, data=True, allow_user_override=False).decode('utf-8') else: @@ -70,7 +70,7 @@ class JavaScriptLoader(object): def __call__(self, evaljs, lang, default_lang): for x in self.ORDER: - src = getattr(self, x) + src = self.get(x) evaljs(src) def lang_name(l): diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 10fb6ca93a..2cf53824c4 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -175,6 +175,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer): def __init__(self, pathtoebook=None, debug_javascript=False, open_at=None): MainWindow.__init__(self, None) self.setupUi(self) + self.view.initialize_view(debug_javascript) self.view.magnification_changed.connect(self.magnification_changed) self.show_toc_on_open = False self.current_book_has_toc = False @@ -215,7 +216,6 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.search.setMinimumWidth(200) self.tool_bar2.insertWidget(self.action_find_next, self.search) self.view.set_manager(self) - self.view.document.debug_javascript = debug_javascript self.pi = ProgressIndicator(self) self.toc.setVisible(False) self.action_quit = QAction(self)