mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Merge remote-tracking branch 'kovid/master'
This commit is contained in:
commit
6748b97ea0
@ -400,6 +400,17 @@ If you use this tool multiple times, each invocation will cause the previously
|
||||
created inline Table of Contents to be replaced. The tool can be accessed via
|
||||
:guilabel:`Tools->Table of Contents->Insert inline Table of Contents`.
|
||||
|
||||
Filter style information
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This tool can be used to easily remove specified CSS style properties from the
|
||||
entire book. You can tell it what properties you want removed, for example,
|
||||
``color, background-color, line-height`` and it will remove them from
|
||||
everywhere they occur --- stylesheets, ``<style>`` tags and inline ``style``
|
||||
attributes. After removing the style information, a summary of all the changes
|
||||
made is displayed so you can see exactly what was changed. The tool can be
|
||||
accessed via :guilabel:`Tools->Filter style information`.
|
||||
|
||||
.. _checkpoints:
|
||||
|
||||
Checkpoints
|
||||
|
@ -250,6 +250,11 @@ The following functions are available in addition to those described in single-f
|
||||
* ``divide(x, y)`` -- returns x / y. Throws an exception if either x or y are not numbers.
|
||||
* ``eval(string)`` -- evaluates the string as a program, passing the local variables (those ``assign`` ed to). This permits using the template processor to construct complex results from local variables. Because the `{` and `}` characters are special, you must use `[[` for the `{` character and `]]` for the '}' character; they are converted automatically. Note also that prefixes and suffixes (the `|prefix|suffix` syntax) cannot be used in the argument to this function when using template program mode.
|
||||
* ``field(name)`` -- returns the metadata field named by ``name``.
|
||||
* ``first_matching_cmp(val, cmp1, result1, cmp2, r2, ..., else_result)`` -- compares "val < cmpN" in sequence, returning resultN for the first comparison that succeeds. Returns else_result if no comparison succeeds. Example::
|
||||
|
||||
``first_matching_cmp(10,5,"small",10,"middle",15,"large","giant")``
|
||||
|
||||
returns "middle". The same example with a first value of 16 returns "giant".
|
||||
* ``first_non_empty(value, value, ...)`` -- returns the first value that is not empty. If all values are empty, then the empty value is returned. You can have as many values as you want.
|
||||
* ``format_date(x, date_format)`` -- format_date(val, format_string) -- format the value, which must be a date field, using the format_string, returning a string. The formatting codes are::
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
http://ameblo.jp/
|
||||
'''
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
class SakuraBlog(BasicNewsRecipe):
|
||||
title = u'chou chou blog'
|
||||
__author__ = 'Hiroshi Miura'
|
||||
oldest_article = 4
|
||||
publication_type = 'blog'
|
||||
max_articles_per_feed = 20
|
||||
description = 'Japanese popular dog blog'
|
||||
publisher = ''
|
||||
category = 'dog, pet, japan'
|
||||
language = 'ja'
|
||||
encoding = 'utf-8'
|
||||
use_embedded_content = True
|
||||
|
||||
feeds = [(u'blog', u'http://feedblog.ameba.jp/rss/ameblo/chouchou1218/rss20.xml')]
|
||||
|
||||
def parse_feeds(self):
|
||||
feeds = BasicNewsRecipe.parse_feeds(self)
|
||||
for curfeed in feeds:
|
||||
delList = []
|
||||
for a,curarticle in enumerate(curfeed.articles):
|
||||
if re.search(r'rssad.jp', curarticle.url):
|
||||
delList.append(curarticle)
|
||||
if len(delList)>0:
|
||||
for d in delList:
|
||||
index = curfeed.articles.index(d)
|
||||
curfeed.articles[index:index+1] = []
|
||||
return feeds
|
||||
|
@ -1,5 +1,5 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
__copyright__ = '2010,2014, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
japan.engadget.com
|
||||
'''
|
||||
@ -20,19 +20,20 @@ class EndgadgetJapan(BasicNewsRecipe):
|
||||
index = 'http://japanese.engadget.com/'
|
||||
remove_javascript = True
|
||||
|
||||
remove_tags_before = dict(name="h1", attrs={'class':"post_title"})
|
||||
remove_tags_after = dict(name='div', attrs={'class':'post_body'})
|
||||
remove_tags_before = dict(name="header", attrs={'class':"header"})
|
||||
remove_tags_after = dict(name='div', attrs={'class':'post-meta'})
|
||||
|
||||
def parse_index(self):
|
||||
feeds = []
|
||||
newsarticles = []
|
||||
soup = self.index_to_soup(self.index)
|
||||
for topstories in soup.findAll('div',attrs={'class':'post_content'}):
|
||||
itt = topstories.find('h4')
|
||||
for topstories in soup.findAll('header',attrs={'class':'post-header'}):
|
||||
itt = topstories.find('h2')
|
||||
itema = itt.find('a',href=True)
|
||||
itemtime = topstories.find('span',attrs={'class':'time'})
|
||||
newsarticles.append({
|
||||
'title' :itema.string
|
||||
,'date' :''
|
||||
,'date' :itemtime.string
|
||||
,'url' :itema['href']
|
||||
,'description':''
|
||||
})
|
||||
|
@ -1,5 +1,5 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
__copyright__ = '2010,2014, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
www.kahoku.co.jp
|
||||
'''
|
||||
@ -21,11 +21,5 @@ class KahokuShinpoNews(BasicNewsRecipe):
|
||||
|
||||
feeds = [(u'news', u'http://www.kahoku.co.jp/rss/index_thk.xml')]
|
||||
|
||||
keep_only_tags = [ dict(id="page_title"),
|
||||
dict(id="news_detail"),
|
||||
dict(id="bt_title"),
|
||||
{'class':"photoLeft"},
|
||||
dict(id="bt_body")
|
||||
]
|
||||
remove_tags = [ {'class':"button"}]
|
||||
keep_only_tags = [ {'class':"category"},{'class':"ttl"},{'class':'photoimg'},{'class':"txt"},{'class':"data"}]
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
__copyright__ = '2010,2014, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
sankei.jp.msn.com
|
||||
'''
|
||||
@ -20,5 +20,4 @@ class MSNSankeiNewsProduct(BasicNewsRecipe):
|
||||
|
||||
feeds = [(u'\u65b0\u5546\u54c1', u'http://sankei.jp.msn.com/rss/news/release.xml')]
|
||||
|
||||
remove_tags_before = dict(id="NewsTitle")
|
||||
remove_tags_after = dict(id="RelatedTitle")
|
||||
keep_only_tags = [dict(id=['MainContent'])]
|
||||
|
@ -15,16 +15,10 @@ class NationalGeographicNews(BasicNewsRecipe):
|
||||
remove_javascript = True
|
||||
no_stylesheets = True
|
||||
use_embedded_content = False
|
||||
auto_cleanup = True
|
||||
|
||||
feeds = [(u'news', u'http://feeds.nationalgeographic.com/ng/News/News_Main')]
|
||||
|
||||
remove_tags_before = dict(id='page_head')
|
||||
remove_tags_after = [dict(id='social_buttons'),{'class':'aside'}]
|
||||
remove_tags = [
|
||||
{'class':'hidden'}
|
||||
|
||||
]
|
||||
|
||||
def parse_feeds(self):
|
||||
feeds = BasicNewsRecipe.parse_feeds(self)
|
||||
for curfeed in feeds:
|
||||
|
@ -1,110 +0,0 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
www.nikkei.com
|
||||
'''
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
import mechanize
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
|
||||
class NikkeiNet_sub_economy(BasicNewsRecipe):
|
||||
title = u'\u65e5\u7d4c\u65b0\u805e\u96fb\u5b50\u7248(\u7d4c\u6e08)'
|
||||
__author__ = 'Hiroshi Miura'
|
||||
description = 'News and current market affairs from Japan'
|
||||
cover_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
masthead_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
needs_subscription = True
|
||||
oldest_article = 2
|
||||
max_articles_per_feed = 20
|
||||
language = 'ja'
|
||||
remove_javascript = False
|
||||
temp_files = []
|
||||
|
||||
remove_tags_before = {'class':"cmn-section cmn-indent"}
|
||||
remove_tags = [
|
||||
{'class':"JSID_basePageMove JSID_baseAsyncSubmit cmn-form_area JSID_optForm_utoken"},
|
||||
{'class':"cmn-article_keyword cmn-clearfix"},
|
||||
{'class':"cmn-print_headline cmn-clearfix"},
|
||||
{'class':"cmn-article_list"},
|
||||
dict(id="ABOUT-NIKKEI"),
|
||||
{'class':"cmn-sub_market"},
|
||||
]
|
||||
remove_tags_after = {'class':"cmn-pr_list"}
|
||||
|
||||
feeds = [ (u'\u653f\u6cbb', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=seiji'),
|
||||
(u'\u8ca1\u52d9', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=zaimu'),
|
||||
(u'\u7d4c\u6e08', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=keizai'),
|
||||
(u'\u30de\u30fc\u30b1\u30c3\u30c8', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=market'),
|
||||
(u'\u96c7\u7528', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=koyou'),
|
||||
(u'\u6559\u80b2', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=kyouiku'),
|
||||
(u'\u304a\u304f\u3084\u307f', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=okuyami'),
|
||||
(u'\u4eba\u4e8b', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=zinzi'),
|
||||
]
|
||||
|
||||
def get_browser(self):
|
||||
br = BasicNewsRecipe.get_browser(self)
|
||||
|
||||
cj = mechanize.LWPCookieJar()
|
||||
br.set_cookiejar(cj)
|
||||
|
||||
#br.set_debug_http(True)
|
||||
#br.set_debug_redirects(True)
|
||||
#br.set_debug_responses(True)
|
||||
|
||||
if self.username is not None and self.password is not None:
|
||||
#print "----------------------------get login form--------------------------------------------"
|
||||
# open login form
|
||||
br.open('https://id.nikkei.com/lounge/nl/base/LA0010.seam')
|
||||
response = br.response()
|
||||
#print "----------------------------get login form---------------------------------------------"
|
||||
#print "----------------------------set login form---------------------------------------------"
|
||||
# remove disabled input which brings error on mechanize
|
||||
response.set_data(response.get_data().replace("<input id=\"j_id48\"", "<!-- "))
|
||||
response.set_data(response.get_data().replace("gm_home_on.gif\" />", " -->"))
|
||||
br.set_response(response)
|
||||
br.select_form(name='LA0010Form01')
|
||||
br['LA0010Form01:LA0010Email'] = self.username
|
||||
br['LA0010Form01:LA0010Password'] = self.password
|
||||
br.form.find_control(id='LA0010Form01:LA0010AutoLoginOn',type="checkbox").get(nr=0).selected = True
|
||||
br.submit()
|
||||
br.response()
|
||||
#print "----------------------------send login form---------------------------------------------"
|
||||
#print "----------------------------open news main page-----------------------------------------"
|
||||
# open news site
|
||||
br.open('http://www.nikkei.com/')
|
||||
br.response()
|
||||
#print "----------------------------www.nikkei.com BODY --------------------------------------"
|
||||
#print response2.get_data()
|
||||
#print "-------------------------^^-got auto redirect form----^^--------------------------------"
|
||||
# forced redirect in default
|
||||
br.select_form(nr=0)
|
||||
br.submit()
|
||||
response3 = br.response()
|
||||
# return some cookie which should be set by Javascript
|
||||
#print response3.geturl()
|
||||
raw = response3.get_data()
|
||||
#print "---------------------------response to form --------------------------------------------"
|
||||
# grab cookie from JS and set it
|
||||
redirectflag = re.search(r"var checkValue = '(\d+)';", raw, re.M).group(1)
|
||||
br.select_form(nr=0)
|
||||
|
||||
self.temp_files.append(PersistentTemporaryFile('_fa.html'))
|
||||
self.temp_files[-1].write("#LWP-Cookies-2.0\n")
|
||||
|
||||
self.temp_files[-1].write("Set-Cookie3: Cookie-dummy=Cookie-value; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].write("Set-Cookie3: redirectFlag="+redirectflag+"; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].close()
|
||||
cj.load(self.temp_files[-1].name)
|
||||
|
||||
br.submit()
|
||||
|
||||
#br.set_debug_http(False)
|
||||
#br.set_debug_redirects(False)
|
||||
#br.set_debug_responses(False)
|
||||
return br
|
||||
|
||||
|
||||
|
||||
|
@ -1,107 +0,0 @@
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
www.nikkei.com
|
||||
'''
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
import mechanize
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
|
||||
|
||||
class NikkeiNet_sub_industory(BasicNewsRecipe):
|
||||
title = u'\u65e5\u7d4c\u65b0\u805e\u96fb\u5b50\u7248(\u7523\u696d)'
|
||||
__author__ = 'Hiroshi Miura'
|
||||
description = 'News and current market affairs from Japan'
|
||||
cover_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
masthead_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
needs_subscription = True
|
||||
oldest_article = 2
|
||||
max_articles_per_feed = 20
|
||||
language = 'ja'
|
||||
remove_javascript = False
|
||||
temp_files = []
|
||||
|
||||
remove_tags_before = {'class':"cmn-section cmn-indent"}
|
||||
remove_tags = [
|
||||
{'class':"JSID_basePageMove JSID_baseAsyncSubmit cmn-form_area JSID_optForm_utoken"},
|
||||
{'class':"cmn-article_keyword cmn-clearfix"},
|
||||
{'class':"cmn-print_headline cmn-clearfix"},
|
||||
]
|
||||
remove_tags_after = {'class':"cmn-pr_list"}
|
||||
|
||||
feeds = [ (u'\u65e5\u7d4c\u4f01\u696d', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=sangyo'),
|
||||
(u'\u65e5\u7d4c\u88fd\u54c1', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=newpro'),
|
||||
(u'internet', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=internet'),
|
||||
(u'\u56fd\u969b', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=kaigai'),
|
||||
(u'\u79d1\u5b66', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=kagaku'),
|
||||
|
||||
]
|
||||
|
||||
def get_browser(self):
|
||||
br = BasicNewsRecipe.get_browser(self)
|
||||
|
||||
cj = mechanize.LWPCookieJar()
|
||||
br.set_cookiejar(cj)
|
||||
|
||||
#br.set_debug_http(True)
|
||||
#br.set_debug_redirects(True)
|
||||
#br.set_debug_responses(True)
|
||||
|
||||
if self.username is not None and self.password is not None:
|
||||
#print "----------------------------get login form--------------------------------------------"
|
||||
# open login form
|
||||
br.open('https://id.nikkei.com/lounge/nl/base/LA0010.seam')
|
||||
response = br.response()
|
||||
#print "----------------------------get login form---------------------------------------------"
|
||||
#print "----------------------------set login form---------------------------------------------"
|
||||
# remove disabled input which brings error on mechanize
|
||||
response.set_data(response.get_data().replace("<input id=\"j_id48\"", "<!-- "))
|
||||
response.set_data(response.get_data().replace("gm_home_on.gif\" />", " -->"))
|
||||
br.set_response(response)
|
||||
br.select_form(name='LA0010Form01')
|
||||
br['LA0010Form01:LA0010Email'] = self.username
|
||||
br['LA0010Form01:LA0010Password'] = self.password
|
||||
br.form.find_control(id='LA0010Form01:LA0010AutoLoginOn',type="checkbox").get(nr=0).selected = True
|
||||
br.submit()
|
||||
br.response()
|
||||
#print "----------------------------send login form---------------------------------------------"
|
||||
#print "----------------------------open news main page-----------------------------------------"
|
||||
# open news site
|
||||
br.open('http://www.nikkei.com/')
|
||||
br.response()
|
||||
#print "----------------------------www.nikkei.com BODY --------------------------------------"
|
||||
#print response2.get_data()
|
||||
#print "-------------------------^^-got auto redirect form----^^--------------------------------"
|
||||
# forced redirect in default
|
||||
br.select_form(nr=0)
|
||||
br.submit()
|
||||
response3 = br.response()
|
||||
# return some cookie which should be set by Javascript
|
||||
#print response3.geturl()
|
||||
raw = response3.get_data()
|
||||
#print "---------------------------response to form --------------------------------------------"
|
||||
# grab cookie from JS and set it
|
||||
redirectflag = re.search(r"var checkValue = '(\d+)';", raw, re.M).group(1)
|
||||
br.select_form(nr=0)
|
||||
|
||||
self.temp_files.append(PersistentTemporaryFile('_fa.html'))
|
||||
self.temp_files[-1].write("#LWP-Cookies-2.0\n")
|
||||
|
||||
self.temp_files[-1].write("Set-Cookie3: Cookie-dummy=Cookie-value; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].write("Set-Cookie3: redirectFlag="+redirectflag+"; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].close()
|
||||
cj.load(self.temp_files[-1].name)
|
||||
|
||||
br.submit()
|
||||
|
||||
#br.set_debug_http(False)
|
||||
#br.set_debug_redirects(False)
|
||||
#br.set_debug_responses(False)
|
||||
return br
|
||||
|
||||
|
||||
|
||||
|
@ -1,104 +0,0 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
www.nikkei.com
|
||||
'''
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
import mechanize
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
|
||||
|
||||
class NikkeiNet_sub_life(BasicNewsRecipe):
|
||||
title = u'\u65e5\u7d4c\u65b0\u805e\u96fb\u5b50\u7248(\u751f\u6d3b)'
|
||||
__author__ = 'Hiroshi Miura'
|
||||
description = 'News and current market affairs from Japan'
|
||||
cover_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
masthead_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
needs_subscription = True
|
||||
oldest_article = 2
|
||||
max_articles_per_feed = 20
|
||||
language = 'ja'
|
||||
remove_javascript = False
|
||||
temp_files = []
|
||||
|
||||
remove_tags_before = {'class':"cmn-section cmn-indent"}
|
||||
remove_tags = [
|
||||
{'class':"JSID_basePageMove JSID_baseAsyncSubmit cmn-form_area JSID_optForm_utoken"},
|
||||
{'class':"cmn-article_keyword cmn-clearfix"},
|
||||
{'class':"cmn-print_headline cmn-clearfix"},
|
||||
]
|
||||
remove_tags_after = {'class':"cmn-pr_list"}
|
||||
|
||||
feeds = [ (u'\u304f\u3089\u3057', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=kurashi'),
|
||||
(u'\u30a8\u30b3', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=eco'),
|
||||
(u'\u5065\u5eb7', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=kenkou'),
|
||||
(u'\u7279\u96c6', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=special')
|
||||
]
|
||||
|
||||
def get_browser(self):
|
||||
br = BasicNewsRecipe.get_browser(self)
|
||||
|
||||
cj = mechanize.LWPCookieJar()
|
||||
br.set_cookiejar(cj)
|
||||
|
||||
#br.set_debug_http(True)
|
||||
#br.set_debug_redirects(True)
|
||||
#br.set_debug_responses(True)
|
||||
|
||||
if self.username is not None and self.password is not None:
|
||||
#print "----------------------------get login form--------------------------------------------"
|
||||
# open login form
|
||||
br.open('https://id.nikkei.com/lounge/nl/base/LA0010.seam')
|
||||
response = br.response()
|
||||
#print "----------------------------get login form---------------------------------------------"
|
||||
#print "----------------------------set login form---------------------------------------------"
|
||||
# remove disabled input which brings error on mechanize
|
||||
response.set_data(response.get_data().replace("<input id=\"j_id48\"", "<!-- "))
|
||||
response.set_data(response.get_data().replace("gm_home_on.gif\" />", " -->"))
|
||||
br.set_response(response)
|
||||
br.select_form(name='LA0010Form01')
|
||||
br['LA0010Form01:LA0010Email'] = self.username
|
||||
br['LA0010Form01:LA0010Password'] = self.password
|
||||
br.form.find_control(id='LA0010Form01:LA0010AutoLoginOn',type="checkbox").get(nr=0).selected = True
|
||||
br.submit()
|
||||
br.response()
|
||||
#print "----------------------------send login form---------------------------------------------"
|
||||
#print "----------------------------open news main page-----------------------------------------"
|
||||
# open news site
|
||||
br.open('http://www.nikkei.com/')
|
||||
br.response()
|
||||
#print "----------------------------www.nikkei.com BODY --------------------------------------"
|
||||
#print response2.get_data()
|
||||
#print "-------------------------^^-got auto redirect form----^^--------------------------------"
|
||||
# forced redirect in default
|
||||
br.select_form(nr=0)
|
||||
br.submit()
|
||||
response3 = br.response()
|
||||
# return some cookie which should be set by Javascript
|
||||
#print response3.geturl()
|
||||
raw = response3.get_data()
|
||||
#print "---------------------------response to form --------------------------------------------"
|
||||
# grab cookie from JS and set it
|
||||
redirectflag = re.search(r"var checkValue = '(\d+)';", raw, re.M).group(1)
|
||||
br.select_form(nr=0)
|
||||
|
||||
self.temp_files.append(PersistentTemporaryFile('_fa.html'))
|
||||
self.temp_files[-1].write("#LWP-Cookies-2.0\n")
|
||||
|
||||
self.temp_files[-1].write("Set-Cookie3: Cookie-dummy=Cookie-value; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].write("Set-Cookie3: redirectFlag="+redirectflag+"; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].close()
|
||||
cj.load(self.temp_files[-1].name)
|
||||
|
||||
br.submit()
|
||||
|
||||
#br.set_debug_http(False)
|
||||
#br.set_debug_redirects(False)
|
||||
#br.set_debug_responses(False)
|
||||
return br
|
||||
|
||||
|
||||
|
||||
|
@ -1,103 +0,0 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
www.nikkei.com
|
||||
'''
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
import mechanize
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
|
||||
|
||||
class NikkeiNet_sub_main(BasicNewsRecipe):
|
||||
title = u'\u65e5\u7d4c\u65b0\u805e\u96fb\u5b50\u7248(\u7dcf\u5408)'
|
||||
__author__ = 'Hiroshi Miura'
|
||||
description = 'News and current market affairs from Japan'
|
||||
cover_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
masthead_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
needs_subscription = True
|
||||
oldest_article = 2
|
||||
max_articles_per_feed = 20
|
||||
language = 'ja'
|
||||
remove_javascript = False
|
||||
temp_files = []
|
||||
|
||||
remove_tags_before = {'class':"cmn-section cmn-indent"}
|
||||
remove_tags = [
|
||||
{'class':"JSID_basePageMove JSID_baseAsyncSubmit cmn-form_area JSID_optForm_utoken"},
|
||||
{'class':"cmn-article_keyword cmn-clearfix"},
|
||||
{'class':"cmn-print_headline cmn-clearfix"},
|
||||
{'class':"cmn-article_list"},
|
||||
{'class':"cmn-dashedline"},
|
||||
{'class':"cmn-hide"},
|
||||
]
|
||||
remove_tags_after = {'class':"cmn-pr_list"}
|
||||
|
||||
feeds = [ (u'NIKKEI', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=main')]
|
||||
|
||||
def get_browser(self):
|
||||
br = BasicNewsRecipe.get_browser(self)
|
||||
|
||||
cj = mechanize.LWPCookieJar()
|
||||
br.set_cookiejar(cj)
|
||||
|
||||
#br.set_debug_http(True)
|
||||
#br.set_debug_redirects(True)
|
||||
#br.set_debug_responses(True)
|
||||
|
||||
if self.username is not None and self.password is not None:
|
||||
#print "----------------------------get login form--------------------------------------------"
|
||||
# open login form
|
||||
br.open('https://id.nikkei.com/lounge/nl/base/LA0010.seam')
|
||||
response = br.response()
|
||||
#print "----------------------------get login form---------------------------------------------"
|
||||
#print "----------------------------set login form---------------------------------------------"
|
||||
# remove disabled input which brings error on mechanize
|
||||
response.set_data(response.get_data().replace("<input id=\"j_id48\"", "<!-- "))
|
||||
response.set_data(response.get_data().replace("gm_home_on.gif\" />", " -->"))
|
||||
br.set_response(response)
|
||||
br.select_form(name='LA0010Form01')
|
||||
br['LA0010Form01:LA0010Email'] = self.username
|
||||
br['LA0010Form01:LA0010Password'] = self.password
|
||||
br.form.find_control(id='LA0010Form01:LA0010AutoLoginOn',type="checkbox").get(nr=0).selected = True
|
||||
br.submit()
|
||||
br.response()
|
||||
#print "----------------------------send login form---------------------------------------------"
|
||||
#print "----------------------------open news main page-----------------------------------------"
|
||||
# open news site
|
||||
br.open('http://www.nikkei.com/')
|
||||
br.response()
|
||||
#print "----------------------------www.nikkei.com BODY --------------------------------------"
|
||||
#print response2.get_data()
|
||||
#print "-------------------------^^-got auto redirect form----^^--------------------------------"
|
||||
# forced redirect in default
|
||||
br.select_form(nr=0)
|
||||
br.submit()
|
||||
response3 = br.response()
|
||||
# return some cookie which should be set by Javascript
|
||||
#print response3.geturl()
|
||||
raw = response3.get_data()
|
||||
#print "---------------------------response to form --------------------------------------------"
|
||||
# grab cookie from JS and set it
|
||||
redirectflag = re.search(r"var checkValue = '(\d+)';", raw, re.M).group(1)
|
||||
br.select_form(nr=0)
|
||||
|
||||
self.temp_files.append(PersistentTemporaryFile('_fa.html'))
|
||||
self.temp_files[-1].write("#LWP-Cookies-2.0\n")
|
||||
|
||||
self.temp_files[-1].write("Set-Cookie3: Cookie-dummy=Cookie-value; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].write("Set-Cookie3: redirectFlag="+redirectflag+"; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].close()
|
||||
cj.load(self.temp_files[-1].name)
|
||||
|
||||
br.submit()
|
||||
|
||||
#br.set_debug_http(False)
|
||||
#br.set_debug_redirects(False)
|
||||
#br.set_debug_responses(False)
|
||||
return br
|
||||
|
||||
|
||||
|
||||
|
@ -1,102 +0,0 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
www.nikkei.com
|
||||
'''
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
import mechanize
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
|
||||
|
||||
class NikkeiNet_sub_shakai(BasicNewsRecipe):
|
||||
title = u'\u65e5\u7d4c\u65b0\u805e\u96fb\u5b50\u7248(Social)'
|
||||
__author__ = 'Hiroshi Miura'
|
||||
description = 'News and current market affairs from Japan'
|
||||
cover_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
masthead_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
needs_subscription = True
|
||||
oldest_article = 2
|
||||
max_articles_per_feed = 20
|
||||
language = 'ja'
|
||||
remove_javascript = False
|
||||
temp_files = []
|
||||
|
||||
remove_tags_before = {'class':"cmn-section cmn-indent"}
|
||||
remove_tags = [
|
||||
{'class':"JSID_basePageMove JSID_baseAsyncSubmit cmn-form_area JSID_optForm_utoken"},
|
||||
{'class':"cmn-article_keyword cmn-clearfix"},
|
||||
{'class':"cmn-print_headline cmn-clearfix"},
|
||||
]
|
||||
remove_tags_after = {'class':"cmn-pr_list"}
|
||||
|
||||
feeds = [
|
||||
(u'\u793e\u4f1a', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=shakai')
|
||||
]
|
||||
|
||||
def get_browser(self):
|
||||
br = BasicNewsRecipe.get_browser(self)
|
||||
|
||||
cj = mechanize.LWPCookieJar()
|
||||
br.set_cookiejar(cj)
|
||||
|
||||
#br.set_debug_http(True)
|
||||
#br.set_debug_redirects(True)
|
||||
#br.set_debug_responses(True)
|
||||
|
||||
if self.username is not None and self.password is not None:
|
||||
#print "----------------------------get login form--------------------------------------------"
|
||||
# open login form
|
||||
br.open('https://id.nikkei.com/lounge/nl/base/LA0010.seam')
|
||||
response = br.response()
|
||||
#print "----------------------------get login form---------------------------------------------"
|
||||
#print "----------------------------set login form---------------------------------------------"
|
||||
# remove disabled input which brings error on mechanize
|
||||
response.set_data(response.get_data().replace("<input id=\"j_id48\"", "<!-- "))
|
||||
response.set_data(response.get_data().replace("gm_home_on.gif\" />", " -->"))
|
||||
br.set_response(response)
|
||||
br.select_form(name='LA0010Form01')
|
||||
br['LA0010Form01:LA0010Email'] = self.username
|
||||
br['LA0010Form01:LA0010Password'] = self.password
|
||||
br.form.find_control(id='LA0010Form01:LA0010AutoLoginOn',type="checkbox").get(nr=0).selected = True
|
||||
br.submit()
|
||||
br.response()
|
||||
#print "----------------------------send login form---------------------------------------------"
|
||||
#print "----------------------------open news main page-----------------------------------------"
|
||||
# open news site
|
||||
br.open('http://www.nikkei.com/')
|
||||
br.response()
|
||||
#print "----------------------------www.nikkei.com BODY --------------------------------------"
|
||||
#print response2.get_data()
|
||||
#print "-------------------------^^-got auto redirect form----^^--------------------------------"
|
||||
# forced redirect in default
|
||||
br.select_form(nr=0)
|
||||
br.submit()
|
||||
response3 = br.response()
|
||||
# return some cookie which should be set by Javascript
|
||||
#print response3.geturl()
|
||||
raw = response3.get_data()
|
||||
#print "---------------------------response to form --------------------------------------------"
|
||||
# grab cookie from JS and set it
|
||||
redirectflag = re.search(r"var checkValue = '(\d+)';", raw, re.M).group(1)
|
||||
br.select_form(nr=0)
|
||||
|
||||
self.temp_files.append(PersistentTemporaryFile('_fa.html'))
|
||||
self.temp_files[-1].write("#LWP-Cookies-2.0\n")
|
||||
|
||||
self.temp_files[-1].write("Set-Cookie3: Cookie-dummy=Cookie-value; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].write("Set-Cookie3: redirectFlag="+redirectflag+"; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].close()
|
||||
cj.load(self.temp_files[-1].name)
|
||||
|
||||
br.submit()
|
||||
|
||||
#br.set_debug_http(False)
|
||||
#br.set_debug_redirects(False)
|
||||
#br.set_debug_responses(False)
|
||||
return br
|
||||
|
||||
|
||||
|
||||
|
@ -1,108 +0,0 @@
|
||||
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
www.nikkei.com
|
||||
'''
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.recipes import BasicNewsRecipe
|
||||
import mechanize
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
|
||||
|
||||
class NikkeiNet_sub_sports(BasicNewsRecipe):
|
||||
title = u'\u65e5\u7d4c\u65b0\u805e\u96fb\u5b50\u7248(\u30b9\u30dd\u30fc\u30c4)'
|
||||
__author__ = 'Hiroshi Miura'
|
||||
description = 'News and current market affairs from Japan'
|
||||
cover_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
masthead_url = 'http://parts.nikkei.com/parts/ds/images/common/logo_r1.svg'
|
||||
needs_subscription = True
|
||||
oldest_article = 2
|
||||
max_articles_per_feed = 20
|
||||
language = 'ja'
|
||||
remove_javascript = False
|
||||
temp_files = []
|
||||
|
||||
remove_tags_before = {'class':"cmn-section cmn-indent"}
|
||||
remove_tags = [
|
||||
{'class':"JSID_basePageMove JSID_baseAsyncSubmit cmn-form_area JSID_optForm_utoken"},
|
||||
{'class':"cmn-article_keyword cmn-clearfix"},
|
||||
{'class':"cmn-print_headline cmn-clearfix"},
|
||||
]
|
||||
remove_tags_after = {'class':"cmn-pr_list"}
|
||||
|
||||
feeds = [
|
||||
(u'\u30b9\u30dd\u30fc\u30c4\uff1a\u30d7\u30ed\u91ce\u7403', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=baseball'),
|
||||
(u'\u30b9\u30dd\u30fc\u30c4\uff1a\u5927\u30ea\u30fc\u30b0', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=mlb'),
|
||||
(u'\u30b9\u30dd\u30fc\u30c4\uff1a\u30b5\u30c3\u30ab\u30fc', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=soccer'),
|
||||
(u'\u30b9\u30dd\u30fc\u30c4\uff1a\u30b4\u30eb\u30d5', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=golf'),
|
||||
(u'\u30b9\u30dd\u30fc\u30c4\uff1a\u76f8\u64b2', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=sumou'),
|
||||
(u'\u30b9\u30dd\u30fc\u30c4\uff1a\u7af6\u99ac', u'http://www.zou3.net/php/rss/nikkei2rss.php?head=keiba')
|
||||
]
|
||||
|
||||
def get_browser(self):
|
||||
br = BasicNewsRecipe.get_browser(self)
|
||||
|
||||
cj = mechanize.LWPCookieJar()
|
||||
br.set_cookiejar(cj)
|
||||
|
||||
#br.set_debug_http(True)
|
||||
#br.set_debug_redirects(True)
|
||||
#br.set_debug_responses(True)
|
||||
|
||||
if self.username is not None and self.password is not None:
|
||||
#print "----------------------------get login form--------------------------------------------"
|
||||
# open login form
|
||||
br.open('https://id.nikkei.com/lounge/nl/base/LA0010.seam')
|
||||
response = br.response()
|
||||
#print "----------------------------get login form---------------------------------------------"
|
||||
#print "----------------------------set login form---------------------------------------------"
|
||||
# remove disabled input which brings error on mechanize
|
||||
response.set_data(response.get_data().replace("<input id=\"j_id48\"", "<!-- "))
|
||||
response.set_data(response.get_data().replace("gm_home_on.gif\" />", " -->"))
|
||||
br.set_response(response)
|
||||
br.select_form(name='LA0010Form01')
|
||||
br['LA0010Form01:LA0010Email'] = self.username
|
||||
br['LA0010Form01:LA0010Password'] = self.password
|
||||
br.form.find_control(id='LA0010Form01:LA0010AutoLoginOn',type="checkbox").get(nr=0).selected = True
|
||||
br.submit()
|
||||
br.response()
|
||||
#print "----------------------------send login form---------------------------------------------"
|
||||
#print "----------------------------open news main page-----------------------------------------"
|
||||
# open news site
|
||||
br.open('http://www.nikkei.com/')
|
||||
br.response()
|
||||
#print "----------------------------www.nikkei.com BODY --------------------------------------"
|
||||
#print response2.get_data()
|
||||
#print "-------------------------^^-got auto redirect form----^^--------------------------------"
|
||||
# forced redirect in default
|
||||
br.select_form(nr=0)
|
||||
br.submit()
|
||||
response3 = br.response()
|
||||
# return some cookie which should be set by Javascript
|
||||
#print response3.geturl()
|
||||
raw = response3.get_data()
|
||||
#print "---------------------------response to form --------------------------------------------"
|
||||
# grab cookie from JS and set it
|
||||
redirectflag = re.search(r"var checkValue = '(\d+)';", raw, re.M).group(1)
|
||||
br.select_form(nr=0)
|
||||
|
||||
self.temp_files.append(PersistentTemporaryFile('_fa.html'))
|
||||
self.temp_files[-1].write("#LWP-Cookies-2.0\n")
|
||||
|
||||
self.temp_files[-1].write("Set-Cookie3: Cookie-dummy=Cookie-value; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].write("Set-Cookie3: redirectFlag="+redirectflag+"; domain=\".nikkei.com\"; path=\"/\"; path_spec; secure; expires=\"2029-12-21 05:07:59Z\"; version=0\n")
|
||||
self.temp_files[-1].close()
|
||||
cj.load(self.temp_files[-1].name)
|
||||
|
||||
br.submit()
|
||||
|
||||
#br.set_debug_http(False)
|
||||
#br.set_debug_redirects(False)
|
||||
#br.set_debug_responses(False)
|
||||
return br
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
__copyright__ = '2010,2014, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
http://ameblo.jp/sauta19/
|
||||
'''
|
||||
@ -18,7 +18,7 @@ class UniNoHimituKichiBlog(BasicNewsRecipe):
|
||||
category = 'cat, pet, japan'
|
||||
language = 'ja'
|
||||
encoding = 'utf-8'
|
||||
|
||||
keep_only_tags = [{'class':'entry_head'},{'class':'subContentsInner'}]
|
||||
feeds = [(u'blog', u'http://feedblog.ameba.jp/rss/ameblo/sauta19/rss20.xml')]
|
||||
|
||||
def parse_feeds(self):
|
||||
|
@ -1,5 +1,5 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
__copyright__ = '2010,2014, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
www.yomiuri.co.jp
|
||||
'''
|
||||
@ -16,16 +16,13 @@ class YOLNews(BasicNewsRecipe):
|
||||
publisher = 'Yomiuri Online News'
|
||||
category = 'news, japan'
|
||||
language = 'ja'
|
||||
encoding = 'Shift_JIS'
|
||||
encoding = 'UTF-8'
|
||||
index = 'http://www.yomiuri.co.jp/latestnews/'
|
||||
remove_javascript = True
|
||||
masthead_title = u'YOMIURI ONLINE'
|
||||
|
||||
keep_only_tags = [{'class':"article-def"}]
|
||||
remove_tags = [{'class':"RelatedArticle"},
|
||||
{'class':"sbtns"}
|
||||
]
|
||||
remove_tags_after = {'class':"date-def"}
|
||||
|
||||
keep_only_tags = [{'class':"article text-resizeable"}]
|
||||
|
||||
def parse_feeds(self):
|
||||
feeds = BasicNewsRecipe.parse_feeds(self)
|
||||
@ -42,22 +39,22 @@ class YOLNews(BasicNewsRecipe):
|
||||
|
||||
def parse_index(self):
|
||||
feeds = []
|
||||
soup = self.index_to_soup(self.index)
|
||||
topstories = soup.find('ul',attrs={'class':'list-def'})
|
||||
if topstories:
|
||||
newsarticles = []
|
||||
for itt in topstories.findAll('li'):
|
||||
soup = self.index_to_soup(self.index)
|
||||
listlatest = soup.find('ul', attrs={'class':'list-common list-common-latest'})
|
||||
if listlatest:
|
||||
for itt in listlatest.findAll('li'):
|
||||
itema = itt.find('a',href=True)
|
||||
if itema:
|
||||
itd1 = itema.findNextSibling(text = True)
|
||||
itd2 = itd1.findNextSibling(text = True)
|
||||
itd3 = itd2.findNextSibling(text = True)
|
||||
item_headline = itema.find('span',attrs={'class':'headline'})
|
||||
item_date = item_headline.find('span',attrs={'class':'update'})
|
||||
newsarticles.append({
|
||||
'title' :itema.string
|
||||
,'date' :''.join([itd1, itd2, itd3])
|
||||
,'url' :'http://www.yomiuri.co.jp' + itema['href']
|
||||
'title' :item_headline.contents[0]
|
||||
,'date' :item_date
|
||||
,'url' :itema['href']
|
||||
,'description':''
|
||||
})
|
||||
feeds.append(('latest', newsarticles))
|
||||
return feeds
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
|
||||
__copyright__ = '2010,2014, Hiroshi Miura <miurahr@linux.com>'
|
||||
'''
|
||||
www.yomiuri.co.jp
|
||||
'''
|
||||
@ -16,16 +16,12 @@ class YOLNews(BasicNewsRecipe):
|
||||
publisher = 'Yomiuri Online News'
|
||||
category = 'news, japan'
|
||||
language = 'ja'
|
||||
encoding = 'Shift_JIS'
|
||||
encoding = 'UTF-8'
|
||||
index = 'http://www.yomiuri.co.jp/world/'
|
||||
remove_javascript = True
|
||||
masthead_title = u"YOMIURI ONLINE"
|
||||
|
||||
keep_only_tags = [{'class':"article-def"}]
|
||||
remove_tags = [{'class':"RelatedArticle"},
|
||||
{'class':"sbtns"}
|
||||
]
|
||||
remove_tags_after = {'class':"date-def"}
|
||||
keep_only_tags = [{'class':"article text-resizeable"}]
|
||||
|
||||
def parse_feeds(self):
|
||||
feeds = BasicNewsRecipe.parse_feeds(self)
|
||||
@ -42,18 +38,34 @@ class YOLNews(BasicNewsRecipe):
|
||||
|
||||
def parse_index(self):
|
||||
feeds = []
|
||||
soup = self.index_to_soup(self.index)
|
||||
topstories = soup.find('ul',attrs={'class':'list-def'})
|
||||
if topstories:
|
||||
newsarticles = []
|
||||
soup = self.index_to_soup(self.index)
|
||||
mainspan = soup.find('div', attrs={'class':'pbNested span-main-inr'})
|
||||
if mainspan:
|
||||
topstories = mainspan.find('ul',attrs={'class':'list-top'})
|
||||
if topstories:
|
||||
for itt in topstories.findAll('li'):
|
||||
itema = itt.find('a',href=True)
|
||||
if itema:
|
||||
itd1 = itema.findNextSibling(text = True)
|
||||
item_headline = itema.find('span',attrs={'class':'headline'})
|
||||
item_date = item_headline.find('span',attrs={'class':'update'})
|
||||
newsarticles.append({
|
||||
'title' :itema.string
|
||||
,'date' :''.join([itd1])
|
||||
,'url' :'http://www.yomiuri.co.jp' + itema['href']
|
||||
'title' :item_headline.contents[0]
|
||||
,'date' :item_date
|
||||
,'url' :itema['href']
|
||||
,'description':''
|
||||
})
|
||||
secondstories = mainspan.find('ul', attrs={'class':'list-common'})
|
||||
if secondstories:
|
||||
for itt in secondstories.findAll('li'):
|
||||
itema = itt.find('a',href=True)
|
||||
if itema:
|
||||
item_headline = itema.find('span',attrs={'class':'headline'})
|
||||
item_date = item_headline.find('span',attrs={'class':'update'})
|
||||
newsarticles.append({
|
||||
'title' :item_headline.contents[0]
|
||||
,'date' :item_date
|
||||
,'url' :itema['href']
|
||||
,'description':''
|
||||
})
|
||||
feeds.append(('World', newsarticles))
|
||||
|
@ -1382,3 +1382,4 @@ application/vnd.ms-opentype otf
|
||||
application/font-woff woff
|
||||
application/x-font-truetype ttf
|
||||
text/xml plist
|
||||
application/x-ibooks+zip ibook
|
||||
|
@ -41,10 +41,10 @@ Cygwin
|
||||
This is needed for automation of the build process, and the ease of use of the
|
||||
unix shell (bash).
|
||||
|
||||
Install, vim, rsync, openssh, unzip, wget, make at a minimum.
|
||||
Install vim, dos2unix, rsync, openssh, unzip, wget, make, zsh, bash-completion, curl at a minimum.
|
||||
|
||||
After installing python run::
|
||||
python setup/vcvars.py && echo 'source ~/.vcvars' >> ~/.bash_profile
|
||||
python setup/vcvars.py && echo 'source ~/.vcvars' >> ~/.zshrc
|
||||
|
||||
To allow you to use the visual studio tools in the cygwin shell.
|
||||
|
||||
@ -147,39 +147,334 @@ Put sqlite3*.h from the sqlite windows amalgamation in ~/sw/include
|
||||
APSW
|
||||
-----
|
||||
|
||||
Download source from http://code.google.com/p/apsw/downloads/list and run in visual studio prompt
|
||||
Download source from http://code.google.com/p/apsw/downloads/list and run
|
||||
|
||||
python setup.py fetch --all --missing-checksum-ok build --enable-all-extensions install test
|
||||
|
||||
Build requirements
|
||||
-------------------
|
||||
|
||||
Install perl and ruby (needed to build openssl and qt):
|
||||
Perl: http://www.activestate.com/activeperl
|
||||
Ruby: http://rubyinstaller.org/
|
||||
|
||||
Put both perl.exe and ruby.exe in the PATH
|
||||
|
||||
Get nasm.exe from (needed for openssl and libjpeg-turbo)
|
||||
http://www.nasm.us/pub/nasm/releasebuilds/2.11/win32/nasm-2.11-win32.zip
|
||||
and put it in ~/sw/bin (which must be in PATH)
|
||||
|
||||
OpenSSL
|
||||
--------
|
||||
|
||||
First install ActiveState Perl if you dont already have perl in windows
|
||||
|
||||
Then, get nasm.exe from
|
||||
http://www.nasm.us/pub/nasm/releasebuilds/2.05/nasm-2.05-win32.zip and put it
|
||||
somewhere on your PATH (I chose ~/sw/bin)
|
||||
|
||||
Download and untar the openssl tarball, follow the instructions in INSTALL.(W32|W64)
|
||||
to install use prefix q:\openssl
|
||||
Download and untar the openssl tarball.
|
||||
To install use a private prefix: --prefix=C:/cygwin64/home/kovid/sw/private/openssl
|
||||
|
||||
The following *MUST BE RUN* in a Visual Studio Command prompt and not in a cygwin
|
||||
environment.
|
||||
|
||||
For 32-bit::
|
||||
perl Configure VC-WIN32 no-asm enable-static-engine --prefix=Q:/openssl
|
||||
perl Configure VC-WIN32 no-asm enable-static-engine --prefix=C:/cygwin64/home/kovid/sw/private/openssl
|
||||
ms\do_ms.bat
|
||||
nmake -f ms\ntdll.mak
|
||||
nmake -f ms\ntdll.mak test
|
||||
nmake -f ms\ntdll.mak install
|
||||
|
||||
For 64-bit::
|
||||
perl Configure VC-WIN64A no-asm enable-static-engine --prefix=C:/cygwin/home/kovid/sw/private/openssl
|
||||
perl Configure VC-WIN64A no-asm enable-static-engine --prefix=C:/cygwin64/home/kovid/sw/private/openssl
|
||||
ms\do_win64a.bat
|
||||
nmake -f ms\ntdll.mak
|
||||
nmake -f ms\ntdll.mak test
|
||||
nmake -f ms\ntdll.mak install
|
||||
|
||||
ICU
|
||||
-------
|
||||
|
||||
Download the win32 *source* .zip from http://www.icu-project.org/download
|
||||
|
||||
Extract to C:\cygwin64\home\kovid\sw\private\icu
|
||||
|
||||
The following must be run in the VS Command Prompt, not the cygwin ssh shell
|
||||
|
||||
cd to <ICU>\source::
|
||||
|
||||
set PATH=%PATH%;C:\cygwin64\bin
|
||||
dos2unix runConfigureICU
|
||||
bash ./runConfigureICU Cygwin/MSVC
|
||||
make
|
||||
|
||||
zlib
|
||||
------
|
||||
|
||||
http://www.zlib.net/
|
||||
|
||||
Build with::
|
||||
nmake -f win32/Makefile.msc
|
||||
nmake -f win32/Makefile.msc test
|
||||
cp zlib1.dll* ~/sw/bin && cp zlib.lib zdll.* ~/sw/lib/ && cp zconf.h zlib.h ~/sw/include/
|
||||
|
||||
jpeg-8
|
||||
-------
|
||||
|
||||
Get the source code from: http://sourceforge.net/projects/libjpeg-turbo/files/
|
||||
|
||||
Run::
|
||||
chmod +x cmakescripts/* && mkdir -p build && cd build
|
||||
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DWITH_JPEG8=1 ..
|
||||
nmake
|
||||
cp sharedlib/jpeg8.dll* ~/sw/bin/ && cp sharedlib/jpeg.lib ~/sw/lib/ && cp jconfig.h ../jerror.h ../jpeglib.h ../jmorecfg.h ~/sw/include
|
||||
|
||||
libpng
|
||||
---------
|
||||
|
||||
Download the libpng .zip source file from:
|
||||
http://www.libpng.org/pub/png/libpng.html
|
||||
|
||||
Run::
|
||||
mkdir -p build && cd build
|
||||
cmake -G "NMake Makefiles" -DPNG_SHARED=1 -DCMAKE_BUILD_TYPE=Release -DZLIB_INCLUDE_DIR=C:/cygwin64/home/kovid/sw/include -DZLIB_LIBRARY=C:/cygwin64/home/kovid/sw/lib/zdll.lib ..
|
||||
nmake
|
||||
cp libpng*.dll ~/sw/bin/ && cp libpng*.lib ~/sw/lib/ && cp pnglibconf.h ../png.h ../pngconf.h ~/sw/include/
|
||||
|
||||
freetype
|
||||
-----------
|
||||
|
||||
Get the .zip source from: http://download.savannah.gnu.org/releases/freetype/
|
||||
|
||||
Edit *all copies* of the file ftoption.h and add to generate a .lib
|
||||
and a correct dll
|
||||
|
||||
#define FT_EXPORT(return_type) __declspec(dllexport) return_type
|
||||
#define FT_EXPORT_DEF(return_type) __declspec(dllexport) return_type
|
||||
|
||||
VS 2008 .sln file is present, open it
|
||||
|
||||
* If you are doing x64 build, click the Win32 dropdown, select
|
||||
Configuration manager->Active solution platform -> New -> x64
|
||||
|
||||
* Change active build type to release multithreaded
|
||||
|
||||
* Project->Properties->Configuration Properties change configuration type
|
||||
to dll and build solution
|
||||
|
||||
cp "`find . -name freetype.dll`" ~/sw/bin/ && cp "`find . -name freetype.lib`" ~/sw/lib/
|
||||
|
||||
Now change configuration back to static for .lib and build solution
|
||||
|
||||
cp "`find . -name 'freetype*MT.lib'`" ~/sw/lib/
|
||||
cp -rf include ~/sw/include/freetype2 && rm -rf ~/sw/include/freetype2/internal
|
||||
|
||||
TODO: Test if this bloody thing actually works on 64 bit (apparently freetype
|
||||
assumes sizeof(long) == sizeof(ptr) which is not true in Win64. See for
|
||||
example: http://forum.openscenegraph.org/viewtopic.php?t=2880
|
||||
|
||||
expat
|
||||
--------
|
||||
|
||||
Get from: http://sourceforge.net/projects/expat/files/expat/
|
||||
|
||||
Apparently expat requires stdint.h which VS 2008 does not have. So we get our
|
||||
own.
|
||||
|
||||
Run::
|
||||
cd lib && wget http://msinttypes.googlecode.com/svn/trunk/stdint.h && cd ..
|
||||
mkdir -p build && cd build
|
||||
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release ..
|
||||
nmake
|
||||
cp expat.dll ~/sw/bin/ && cp expat.lib ~/sw/lib/
|
||||
cp ../lib/expat.h ../lib/expat_external.h ~/sw/include
|
||||
|
||||
libiconv
|
||||
----------
|
||||
|
||||
Run::
|
||||
mkdir vs2008 && cd vs2008
|
||||
|
||||
Then follow these instructions:
|
||||
http://www.codeproject.com/Articles/302012/How-to-Build-libiconv-with-Microsoft-Visual-Studio
|
||||
|
||||
NOTE: Built as MT rather than MD so no manifest
|
||||
|
||||
Change the type to Release and config to x64 or Win32 and Build solution and
|
||||
then::
|
||||
cp "`find . -name '*.dll'`" ~/sw/bin/
|
||||
cp "`find . -name '*.lib'`" ~/sw/lib/iconv.lib
|
||||
cp "`find . -name iconv.h`" ~/sw/include/
|
||||
|
||||
Information for using a static version of libiconv is at the link above.
|
||||
|
||||
libxml2
|
||||
-------------
|
||||
|
||||
Get it from: ftp://xmlsoft.org/libxml2/
|
||||
|
||||
Run::
|
||||
cd win32
|
||||
cscript.exe configure.js include=C:/cygwin64/home/kovid/sw/include lib=C:/cygwin64/home/kovid/sw/lib prefix=C:/cygwin64/home/kovid/sw zlib=yes iconv=yes
|
||||
nmake /f Makefile.msvc
|
||||
cd ..
|
||||
mkdir -p ~/sw/include/libxml2/libxml && cp include/libxml/*.h ~/sw/include/libxml2/libxml/
|
||||
find . -type f \( -name "*.dll" -o -name "*.dll.manifest" \) -exec cp "{}" ~/sw/bin/ \;
|
||||
find . -name libxml2.lib -exec cp "{}" ~/sw/lib/ \;
|
||||
|
||||
libxslt
|
||||
---------
|
||||
|
||||
Get it from: ftp://xmlsoft.org/libxml2/
|
||||
|
||||
Run::
|
||||
cd win32
|
||||
cscript.exe configure.js include=C:/cygwin64/home/kovid/sw/include include=C:/cygwin64/home/kovid/sw/include/libxml2 lib=C:/cygwin64/home/kovid/sw/lib prefix=C:/cygwin64/home/kovid/sw zlib=yes iconv=yes
|
||||
nmake /f Makefile.msvc
|
||||
mkdir -p ~/sw/include/libxslt ~/sw/include/libexslt
|
||||
cd ..
|
||||
cp libxslt/*.h ~/sw/include/libxslt/
|
||||
cp libexslt/*.h ~/sw/include/libexslt/
|
||||
find . -type f \( -name "*.dll" -o -name "*.dll.manifest" \) -exec cp "{}" ~/sw/bin/ \;
|
||||
find . -name 'lib*xslt.lib' -exec cp "{}" ~/sw/lib/ \;
|
||||
|
||||
lxml
|
||||
------
|
||||
|
||||
Get the source from: http://pypi.python.org/pypi/lxml
|
||||
|
||||
Change the include dirs and lib dirs by editing setupinfo.py and changing the
|
||||
library_dirs() function to return::
|
||||
|
||||
return ['C:/cygwin64/home/kovid/sw/lib']
|
||||
|
||||
and the include_dirs() function to return
|
||||
|
||||
return ['C:/cygwin64/home/kovid/sw/include/libxml2', 'C:/cygwin64/home/kovid/sw/include']
|
||||
|
||||
Run::
|
||||
python setup.py install
|
||||
|
||||
|
||||
Python Imaging Library
|
||||
------------------------
|
||||
|
||||
Download from http://pypi.python.org/pypi/Pillow/
|
||||
Edit setup.py setting the ROOT values, like this::
|
||||
|
||||
SW = r'C:\cygwin64\home\kovid\sw'
|
||||
JPEG_ROOT = ZLIB_ROOT = FREETYPE_ROOT = (SW+r'\lib', SW+r'\include')
|
||||
|
||||
Set zip_safe=False
|
||||
|
||||
Build and install with::
|
||||
python setup.py install
|
||||
|
||||
poppler
|
||||
-------------
|
||||
|
||||
mkdir build
|
||||
|
||||
Run the cmake GUI which will find the various dependencies automatically.
|
||||
On 64 bit cmake might not let you choose Visual Studio 2008, in whcih case
|
||||
leave the source field blank, click configure choose Visual Studio 2008 and
|
||||
then enter the source field.
|
||||
|
||||
In cmake: disable GTK, Qt, openjpeg, cpp, lcms, gtk_tests, qt_tests. Enable
|
||||
jpeg, png and zlib::
|
||||
|
||||
cp build/utils/Release/*.exe ~/sw/bin
|
||||
|
||||
podofo
|
||||
----------
|
||||
|
||||
Download from http://podofo.sourceforge.net/download.html
|
||||
|
||||
mkdir build
|
||||
|
||||
Add the following three lines near the top of CMakeLists.txt
|
||||
SET(WANT_LIB64 FALSE)
|
||||
SET(PODOFO_BUILD_SHARED TRUE)
|
||||
SET(PODOFO_BUILD_STATIC FALSE)
|
||||
|
||||
PoDoFo's CMakeLists.txt is pretty bad. Run the cmake-gui and fill in values for
|
||||
freetype2 and open ssl (choose any one .lib for the libcrypto variable, you
|
||||
will have to fix it manually in Visual Studio later anyway). Then generate the
|
||||
VisualStudio solution. In the solution. In the Solution got to
|
||||
Project->Properties->Linker->Input and add the second ssl library. And in
|
||||
C++->General add the openssl include dir.
|
||||
|
||||
Now build only the project podofo_shared (release mode)
|
||||
|
||||
Run::
|
||||
cp "`find . -name '*.dll'`" ~/sw/bin/
|
||||
cp "`find . -name '*.lib'`" ~/sw/lib/
|
||||
mkdir ~/sw/include/podofo
|
||||
cp build/podofo_config.h ~/sw/include/podofo
|
||||
cp -r src/* ~/sw/include/podofo/
|
||||
|
||||
|
||||
ImageMagick
|
||||
--------------
|
||||
|
||||
Get the source from: http://www.imagemagick.org/download/windows/ImageMagick-windows.zip
|
||||
Unzip it and then run::
|
||||
chmod +x `find . -name '*.exe'`
|
||||
|
||||
Edit VisualMagick/configure/configure.cpp to set
|
||||
|
||||
int projectType = MULTITHREADEDDLL;
|
||||
|
||||
Open configure.sln and build it to create configure.exe
|
||||
|
||||
Run configure.exe set 32/64 bit disable X11 and OpenMPI and click the Edit
|
||||
magick-baseconfig.h button
|
||||
|
||||
Undefine ProvideDllMain
|
||||
|
||||
Now open VisualMagick/VisualDynamicMT.sln set to Release
|
||||
|
||||
Remove the UTIL_IMdisplay and CORE_Magick++ projects.
|
||||
|
||||
F7 for build solution.
|
||||
|
||||
netifaces
|
||||
------------
|
||||
|
||||
Download the source tarball from http://alastairs-place.net/projects/netifaces/
|
||||
|
||||
Rename netifaces.c to netifaces.cpp and make the same change in setup.py
|
||||
|
||||
Run::
|
||||
python setup.py build
|
||||
cp `find build/ -name *.pyd` /cygdrive/c/Python27/Lib/site-packages/
|
||||
|
||||
|
||||
psutil
|
||||
--------
|
||||
|
||||
Download the source tarball
|
||||
|
||||
Run
|
||||
|
||||
Python setup.py build
|
||||
cp -r build/lib.win32-*/* /cygdrive/c/Python27/Lib/site-packages/
|
||||
|
||||
easylzma
|
||||
----------
|
||||
|
||||
This is only needed to build the portable installer.
|
||||
|
||||
Get it from http://lloyd.github.com/easylzma/ (use the trunk version)
|
||||
|
||||
Run cmake and build the Visual Studio solution (generates CLI tools and dll and
|
||||
static lib automatically)
|
||||
|
||||
chmlib
|
||||
-------
|
||||
|
||||
Download the zip source code from: http://www.jedrea.com/chmlib/
|
||||
Run::
|
||||
cd src && unzip ./ChmLib-ds6.zip
|
||||
Then open ChmLib.dsw in Visual Studio, change the configuration to Release
|
||||
(Win32|x64) and build solution, this will generate a static library in
|
||||
Release/ChmLib.lib
|
||||
|
||||
Qt
|
||||
--------
|
||||
Download Qt sourcecode (.zip) from: http://download.qt-project.org/official_releases/qt/
|
||||
@ -225,328 +520,6 @@ Compiling instructions::
|
||||
nmake
|
||||
nmake install
|
||||
|
||||
ICU
|
||||
-------
|
||||
|
||||
Download the win32 source .zip from http://www.icu-project.org/download
|
||||
|
||||
Extract to q:\icu
|
||||
|
||||
Add Q:\icu\bin to PATH and reboot
|
||||
|
||||
In a Visual Studio Command Prompt
|
||||
cd to <ICU>\source
|
||||
Run set PATH=%PATH%;c:\cygwin\bin
|
||||
Run dos2unix on configure and runConfigureICU
|
||||
|
||||
Run bash ./runConfigureICU Cygwin/MSVC
|
||||
|
||||
Run make (note that you must have GNU make installed in cygwin)
|
||||
|
||||
Optionally run make check
|
||||
|
||||
zlib
|
||||
------
|
||||
|
||||
Build with::
|
||||
nmake -f win32/Makefile.msc
|
||||
nmake -f win32/Makefile.msc test
|
||||
|
||||
cp zlib1.dll* ../../bin
|
||||
cp zlib.lib zdll.* ../../lib
|
||||
cp zconf.h zlib.h ../../include
|
||||
|
||||
jpeg-8
|
||||
-------
|
||||
|
||||
Get the source code from: http://sourceforge.net/projects/libjpeg-turbo/files/
|
||||
|
||||
Run::
|
||||
chmod +x cmakescripts/* && cd build
|
||||
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DWITH_JPEG8=1 ..
|
||||
nmake
|
||||
cp sharedlib/jpeg8.dll* ~/sw/bin/
|
||||
cp sharedlib/jpeg.lib ~/sw/lib/
|
||||
cp jconfig.h ../jerror.h ../jpeglib.h ../jmorecfg.h ~/sw/include
|
||||
|
||||
libpng
|
||||
---------
|
||||
|
||||
Download the libpng .zip source file from:
|
||||
http://www.libpng.org/pub/png/libpng.html
|
||||
|
||||
Run::
|
||||
mkdir build && cd build
|
||||
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DZLIB_INCLUDE_DIR=C:/cygwin/home/kovid/sw/include -DZLIB_LIBRARY=C:/cygwin/home/kovid/sw/lib/zdll.lib ..
|
||||
nmake
|
||||
cp libpng*.dll ~/sw/bin/
|
||||
cp libpng*.lib ~/sw/lib/
|
||||
cp pnglibconf.h ../png.h ../pngconf.h ~/sw/include/
|
||||
|
||||
freetype
|
||||
-----------
|
||||
|
||||
Get the .zip source from: http://download.savannah.gnu.org/releases/freetype/
|
||||
|
||||
Edit *all copies* of the file ftoption.h and add to generate a .lib
|
||||
and a correct dll
|
||||
|
||||
#define FT_EXPORT(return_type) __declspec(dllexport) return_type
|
||||
#define FT_EXPORT_DEF(return_type) __declspec(dllexport) return_type
|
||||
|
||||
|
||||
VS 2008 .sln file is present, open it
|
||||
|
||||
* If you are doing x64 build, click the Win32 dropdown, select
|
||||
Configuration manager->Active solution platform -> New -> x64
|
||||
|
||||
* Change active build type to release mutithreaded
|
||||
|
||||
* Project->Properties->Configuration Properties change configuration type
|
||||
to dll and build solution
|
||||
|
||||
cp "`find . -name *.dll`" ~/sw/bin/
|
||||
cp "`find . -name freetype.lib`" ~/sw/lib/
|
||||
|
||||
Now change configuration back to static for .lib and build solution
|
||||
cp "`find . -name freetype*MT.lib`" ~/sw/lib/
|
||||
|
||||
cp build/freetype-2.3.9/objs/win32/vc2008/freetype239MT.lib lib/
|
||||
cp -rf include/* ~/sw/include/
|
||||
|
||||
TODO: Test if this bloody thing actually works on 64 bit (apparently freetype
|
||||
assumes sizeof(long) == sizeof(ptr) which is not true in Win64. See for
|
||||
example: http://forum.openscenegraph.org/viewtopic.php?t=2880
|
||||
|
||||
expat
|
||||
--------
|
||||
|
||||
Get from: http://sourceforge.net/projects/expat/files/expat/
|
||||
|
||||
Apparently expat requires stdint.h which VS 2008 does not have. So we get our
|
||||
own.
|
||||
|
||||
Run::
|
||||
cd lib
|
||||
wget http://msinttypes.googlecode.com/svn/trunk/stdint.h
|
||||
mkdir build && cd build
|
||||
cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release ..
|
||||
nmake
|
||||
cp expat.dll ~/sw/bin/ && cp expat.lib ~/sw/lib/
|
||||
cp ../lib/expat.h ../lib/expat_external.h ~/sw/include
|
||||
|
||||
libiconv
|
||||
----------
|
||||
|
||||
Run::
|
||||
mkdir vs2008 && cd vs2008
|
||||
|
||||
Then follow these instructions:
|
||||
http://www.codeproject.com/Articles/302012/How-to-Build-libiconv-with-Microsoft-Visual-Studio
|
||||
|
||||
Change the type to Release and config to x64 or Win32 and Build solution and
|
||||
then::
|
||||
cp "`find . -name *.dll`" ~/sw/bin/
|
||||
cp "`find . -name *.dll.manifest`" ~/sw/bin/
|
||||
cp "`find . -name *.lib`" ~/sw/lib/iconv.lib
|
||||
cp "`find . -name iconv.h`" ~/sw/include/
|
||||
|
||||
Information for using a static version of libiconv is at the link above.
|
||||
|
||||
libxml2
|
||||
-------------
|
||||
|
||||
Get it from: ftp://xmlsoft.org/libxml2/
|
||||
|
||||
Run::
|
||||
cd win32
|
||||
cscript.exe configure.js include=C:/cygwin/home/kovid/sw/include lib=C:/cygwin/home/kovid/sw/lib prefix=C:/cygwin/home/kovid/sw zlib=yes iconv=yes
|
||||
nmake /f Makefile.msvc
|
||||
mkdir -p ~/sw/include/libxml2/libxml
|
||||
cp include/libxml/*.h ~/sw/include/libxml2/libxml/
|
||||
find . -type f \( -name "*.dll" -o -name "*.dll.manifest" \) -exec cp "{}" ~/sw/bin/ \;
|
||||
find . -name libxml2.lib -exec cp "{}" ~/sw/lib/ \;
|
||||
|
||||
libxslt
|
||||
---------
|
||||
|
||||
Get it from: ftp://xmlsoft.org/libxml2/
|
||||
|
||||
Run::
|
||||
cd win32
|
||||
cscript.exe configure.js include=C:/cygwin/home/kovid/sw/include include=C:/cygwin/home/kovid/sw/include/libxml2 lib=C:/cygwin/home/kovid/sw/lib prefix=C:/cygwin/home/kovid/sw zlib=yes iconv=yes
|
||||
nmake /f Makefile.msvc
|
||||
mkdir -p ~/sw/include/libxslt ~/sw/include/libexslt
|
||||
cp libxslt/*.h ~/sw/include/libxslt/
|
||||
cp libexslt/*.h ~/sw/include/libexslt/
|
||||
find . -type f \( -name "*.dll" -o -name "*.dll.manifest" \) -exec cp "{}" ~/sw/bin/ \;
|
||||
find . -name lib*xslt.lib -exec cp "{}" ~/sw/lib/ \;
|
||||
|
||||
lxml
|
||||
------
|
||||
|
||||
Get the source from: http://pypi.python.org/pypi/lxml
|
||||
|
||||
Change the include dirs and lib dirs by editing setupinfo.py and changing the
|
||||
library_dirs() function to return::
|
||||
|
||||
return ['C:/cygwin/home/kovid/sw/lib']
|
||||
|
||||
and the include_dirs() function to return
|
||||
|
||||
return ['C:/cygwin/home/kovid/sw/include/libxml2', 'C:/cygwin/home/kovid/sw/include']
|
||||
|
||||
Run::
|
||||
python setup.py install
|
||||
|
||||
Python Imaging Library
|
||||
------------------------
|
||||
|
||||
For 32-bit:
|
||||
Install as normal using installer at http://www.lfd.uci.edu/~gohlke/pythonlibs/
|
||||
|
||||
For 64-bit:
|
||||
Download from http://pypi.python.org/pypi/Pillow/
|
||||
Edit setup.py setting the ROOT values, like this::
|
||||
|
||||
SW = r'C:\cygwin\home\kovid\sw'
|
||||
JPEG_ROOT = ZLIB_ROOT = FREETYPE_ROOT = (SW+r'\lib', SW+r'\include')
|
||||
|
||||
Build and install with::
|
||||
python setup.py build
|
||||
python setup.py install
|
||||
|
||||
Note that the lcms module will not be built. PIL requires lcms-1.x but only
|
||||
lcms-2.x can be compiled as a 64 bit library.
|
||||
|
||||
Pillow >= 2.2 installs itself as a .egg file. calibre needs it to be a PIL
|
||||
directory. Extract the PIL directory as follows:
|
||||
cd /cygdrive/c/Python27/Lib/site-packages
|
||||
mkdir p && cd p
|
||||
unzip ../Pillow-*.egg
|
||||
cd .. && rm Pillow-*.egg && mv p/PIL . && chmod +x PIL/*.pyd
|
||||
|
||||
Test it on the target system with
|
||||
|
||||
calibre-debug -c "from PIL import Image; import _imaging, _imagingmath, _imagingft"
|
||||
|
||||
kdewin32-msvc
|
||||
----------------
|
||||
|
||||
I dont think this is needed any more, I've left it here just in case I'm wrong.
|
||||
|
||||
Get it from http://www.winkde.org/pub/kde/ports/win32/repository/kdesupport/
|
||||
mkdir build
|
||||
Run cmake
|
||||
|
||||
Set build type to release and configuration to dll
|
||||
|
||||
Build
|
||||
|
||||
cp build/kdewin32-msvc-0.3.9/build/include/* include/
|
||||
cp build/kdewin32-msvc-0.3.9/build/bin/Release/*.dll bin/
|
||||
cp build/kdewin32-msvc-0.3.9/build/bin/Release/*.lib lib/
|
||||
cp build/kdewin32-msvc-0.3.9/build/bin/Release/*.exp lib/
|
||||
cp -r build/kdewin32-msvc-0.3.9/include/msvc/ include/
|
||||
cp build/kdewin32-msvc-0.3.9/include/*.h include/
|
||||
|
||||
poppler
|
||||
-------------
|
||||
|
||||
mkdir build
|
||||
|
||||
Run the cmake GUI which will find the various dependencies automatically.
|
||||
On 64 bit cmake might not let you choose Visual Studio 2008, in whcih case
|
||||
leave the source field blank, click configure choose Visual Studio 2008 and
|
||||
then enter the source field.
|
||||
|
||||
In Cmake: disable GTK, Qt, OPenjpeg, cpp, lcms, gtk_tests, qt_tests. Enable
|
||||
jpeg, png and zlib::
|
||||
|
||||
cp build/utils/Release/*.exe ../../bin/
|
||||
|
||||
podofo
|
||||
----------
|
||||
|
||||
Download from http://podofo.sourceforge.net/download.html
|
||||
|
||||
Add the following three lines near the top of CMakeLists.txt
|
||||
SET(WANT_LIB64 FALSE)
|
||||
SET(PODOFO_BUILD_SHARED TRUE)
|
||||
SET(PODOFO_BUILD_STATIC FALSE)
|
||||
|
||||
Run::
|
||||
cp "`find . -name *.dll`" ~/sw/bin/
|
||||
cp "`find . -name *.lib`" ~/sw/lib/
|
||||
mkdir ~/sw/include/podofo
|
||||
cp build/podofo_config.h ~/sw/include/podofo
|
||||
cp -r src/* ~/sw/include/podofo/
|
||||
|
||||
|
||||
ImageMagick
|
||||
--------------
|
||||
|
||||
Get the source from: http://www.imagemagick.org/download/windows/ImageMagick-windows.zip
|
||||
|
||||
Edit VisualMagick/configure/configure.cpp to set
|
||||
|
||||
int projectType = MULTITHREADEDDLL;
|
||||
|
||||
Run configure.bat in a visual studio command prompt
|
||||
|
||||
Run configure.exe generated by configure.bat
|
||||
|
||||
Edit magick/magick-config.h
|
||||
|
||||
Undefine ProvideDllMain and MAGICKCORE_X11_DELEGATE
|
||||
|
||||
Now open VisualMagick/VisualDynamicMT.sln set to Release
|
||||
Remove the CORE_xlib, UTIL_Imdisplay and CORE_Magick++ projects.
|
||||
|
||||
F7 for build solution, you will get one error due to the removal of xlib, ignore
|
||||
it.
|
||||
|
||||
netifaces
|
||||
------------
|
||||
|
||||
Download the source tarball from http://alastairs-place.net/projects/netifaces/
|
||||
|
||||
Rename netifaces.c to netifaces.cpp and make the same change in setup.py
|
||||
|
||||
Run::
|
||||
python setup.py build
|
||||
cp `find build/ -name *.pyd` /cygdrive/c/Python27/Lib/site-packages/
|
||||
|
||||
|
||||
psutil
|
||||
--------
|
||||
|
||||
Download the source tarball
|
||||
|
||||
Run
|
||||
|
||||
Python setup.py build
|
||||
cp -r build/lib.win32-*/* /cygdrive/c/Python27/Lib/site-packages/
|
||||
|
||||
easylzma
|
||||
----------
|
||||
|
||||
This is only needed to build the portable installer.
|
||||
|
||||
Get it from http://lloyd.github.com/easylzma/ (use the trunk version)
|
||||
|
||||
Run cmake and build the Visual Studio solution (generates CLI tools and dll and
|
||||
static lib automatically)
|
||||
|
||||
chmlib
|
||||
-------
|
||||
|
||||
Download the zip source code from: http://www.jedrea.com/chmlib/
|
||||
Run::
|
||||
cd src && unzip ./ChmLib-ds6.zip
|
||||
Then open ChmLib.dsw in Visual Studio, change the configuration to Release
|
||||
(Win32|x64) and build solution, this will generate a static library in
|
||||
Release/ChmLib.lib
|
||||
|
||||
libimobiledevice
|
||||
------------------
|
||||
|
@ -225,7 +225,6 @@ class Plugin(object): # {{{
|
||||
ans[candidate] = zf.read(candidate)
|
||||
return ans
|
||||
|
||||
|
||||
def customization_help(self, gui=False):
|
||||
'''
|
||||
Return a string giving help on how to customize this plugin.
|
||||
@ -284,7 +283,6 @@ class Plugin(object): # {{{
|
||||
sys.path.insert(0, self.sys_insertion_path)
|
||||
zf.close()
|
||||
|
||||
|
||||
def __exit__(self, *args):
|
||||
ip, it = getattr(self, 'sys_insertion_path', None), getattr(self,
|
||||
'_sys_insertion_tdir', None)
|
||||
@ -516,8 +514,7 @@ class CatalogPlugin(Plugin): # {{{
|
||||
from calibre.customize.ui import config
|
||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
||||
|
||||
if not type(self) in builtin_plugins and \
|
||||
not self.name in config['disabled_plugins']:
|
||||
if not type(self) in builtin_plugins and self.name not in config['disabled_plugins']:
|
||||
files_to_copy = ["%s.%s" % (self.name.lower(),ext) for ext in ["ui","py"]]
|
||||
resources = zipfile.ZipFile(self.plugin_path,'r')
|
||||
|
||||
@ -733,6 +730,7 @@ class ViewerPlugin(Plugin): # {{{
|
||||
example, you can modify the toolbars via ui.tool_bar and ui.tool_bar2.
|
||||
'''
|
||||
pass
|
||||
|
||||
def customize_context_menu(self, menu, event, hit_test_result):
|
||||
'''
|
||||
This method is called every time the context (right-click) menu is
|
||||
@ -743,4 +741,3 @@ class ViewerPlugin(Plugin): # {{{
|
||||
pass
|
||||
|
||||
# }}}
|
||||
|
||||
|
@ -14,6 +14,7 @@ from cssselect.xpath import XPathExpr, is_safe_name
|
||||
|
||||
from calibre import force_unicode
|
||||
from calibre.ebooks.oeb.base import OEB_STYLES, OEB_DOCS, XPNSMAP, XHTML_NS
|
||||
from calibre.ebooks.oeb.normalize_css import normalize_filter_css, normalizers
|
||||
from calibre.ebooks.oeb.stylizer import MIN_SPACE_RE, is_non_whitespace, xpath_lower_case, fix_namespace
|
||||
from calibre.ebooks.oeb.polish.pretty import pretty_script_or_style
|
||||
|
||||
@ -167,3 +168,80 @@ def remove_unused_css(container, report):
|
||||
else:
|
||||
report(_('No unused CSS style rules found'))
|
||||
return num_of_removed_rules > 0
|
||||
|
||||
def filter_declaration(style, properties):
|
||||
changed = False
|
||||
for prop in properties:
|
||||
if style.removeProperty(prop) != '':
|
||||
changed = True
|
||||
all_props = set(style.keys())
|
||||
for prop in style.getProperties():
|
||||
n = normalizers.get(prop.name, None)
|
||||
if n is not None:
|
||||
normalized = n(prop.name, prop.propertyValue)
|
||||
removed = properties.intersection(set(normalized))
|
||||
if removed:
|
||||
changed = True
|
||||
style.removeProperty(prop.name)
|
||||
for prop in set(normalized) - removed - all_props:
|
||||
style.setProperty(prop, normalized[prop])
|
||||
return changed
|
||||
|
||||
def filter_sheet(sheet, properties):
|
||||
from cssutils.css import CSSRule
|
||||
changed = False
|
||||
remove = []
|
||||
for rule in sheet.cssRules.rulesOfType(CSSRule.STYLE_RULE):
|
||||
if filter_declaration(rule.style, properties):
|
||||
changed = True
|
||||
if rule.style.length == 0:
|
||||
remove.append(rule)
|
||||
for rule in remove:
|
||||
sheet.cssRules.remove(rule)
|
||||
return changed
|
||||
|
||||
|
||||
def filter_css(container, properties, names=()):
|
||||
if not names:
|
||||
types = OEB_STYLES | OEB_DOCS
|
||||
names = []
|
||||
for name, mt in container.mime_map.iteritems():
|
||||
if mt in types:
|
||||
names.append(name)
|
||||
properties = normalize_filter_css(properties)
|
||||
doc_changed = False
|
||||
|
||||
for name in names:
|
||||
mt = container.mime_map[name]
|
||||
if mt in OEB_STYLES:
|
||||
sheet = container.parsed(name)
|
||||
filtered = filter_sheet(sheet, properties)
|
||||
if filtered:
|
||||
container.dirty(name)
|
||||
doc_changed = True
|
||||
elif mt in OEB_DOCS:
|
||||
root = container.parsed(name)
|
||||
changed = False
|
||||
for style in root.xpath('//*[local-name()="style"]'):
|
||||
if style.text and style.get('type', 'text/css') in {None, '', 'text/css'}:
|
||||
sheet = container.parse_css(style.text)
|
||||
if filter_sheet(sheet, properties):
|
||||
changed = True
|
||||
style.text = force_unicode(sheet.cssText, 'utf-8')
|
||||
pretty_script_or_style(container, style)
|
||||
for elem in root.xpath('//*[@style]'):
|
||||
text = elem.get('style', None)
|
||||
if text:
|
||||
style = container.parse_css(text, is_declaration=True)
|
||||
if filter_declaration(style, properties):
|
||||
changed = True
|
||||
if style.length == 0:
|
||||
del elem.attrib['style']
|
||||
else:
|
||||
elem.set('style', force_unicode(style.getCssText(separator=' '), 'utf-8'))
|
||||
if changed:
|
||||
container.dirty(name)
|
||||
doc_changed = True
|
||||
|
||||
return doc_changed
|
||||
|
||||
|
@ -128,11 +128,17 @@ def read_words_from_html_tag(tag, words, file_name, parent_locale, locale):
|
||||
|
||||
def locale_from_tag(tag):
|
||||
if 'lang' in tag.attrib:
|
||||
try:
|
||||
loc = parse_lang_code(tag.get('lang'))
|
||||
except ValueError:
|
||||
loc = None
|
||||
if loc is not None:
|
||||
return loc
|
||||
if '{http://www.w3.org/XML/1998/namespace}lang' in tag.attrib:
|
||||
try:
|
||||
loc = parse_lang_code(tag.get('{http://www.w3.org/XML/1998/namespace}lang'))
|
||||
except ValueError:
|
||||
loc = None
|
||||
if loc is not None:
|
||||
return loc
|
||||
|
||||
|
@ -253,6 +253,10 @@ class StatsCollector(object):
|
||||
src = rule.get('src', None)
|
||||
if not src:
|
||||
continue
|
||||
if src.startswith('url(') and src.endswith(')') and src[4] not in {'"', "'"}:
|
||||
# Quote the url otherwise cssutils fails to parse it if it has
|
||||
# ' or " in it
|
||||
src = "url('" + src[4:-1].replace("'", "\\'") + "')"
|
||||
style = self.parser.parseStyle('background-image:%s'%src, validate=False)
|
||||
src = style.getProperty('background-image').propertyValue[0].uri
|
||||
name = self.href_to_name(src, '@font-face rule')
|
||||
|
@ -432,7 +432,20 @@ class PolishAction(InterfaceAction):
|
||||
return None
|
||||
db = self.gui.library_view.model().db
|
||||
ans = (db.id(r) for r in rows)
|
||||
return self.get_supported_books(ans)
|
||||
ans = self.get_supported_books(ans)
|
||||
for fmts in ans.itervalues():
|
||||
for x in fmts:
|
||||
if x.startswith('ORIGINAL_'):
|
||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||
if not confirm(_(
|
||||
'One of the books you are polishing has an {0} format.'
|
||||
' Polishing will use this as the source and overwrite'
|
||||
' any existing {1} format. Are you sure you want to proceed?').format(
|
||||
x, x[len('ORIGINAL_'):]), 'confirm_original_polish', title=_('Are you sure?'),
|
||||
confirm_msg=_('Ask for this confirmation again')):
|
||||
return {}
|
||||
break
|
||||
return ans
|
||||
|
||||
def get_supported_books(self, book_ids):
|
||||
from calibre.ebooks.oeb.polish.main import SUPPORTED
|
||||
|
@ -18,8 +18,9 @@ from calibre import prints, isbytestring
|
||||
from calibre.ptempfile import PersistentTemporaryDirectory, TemporaryDirectory
|
||||
from calibre.ebooks.oeb.base import urlnormalize
|
||||
from calibre.ebooks.oeb.polish.main import SUPPORTED, tweak_polish
|
||||
from calibre.ebooks.oeb.polish.container import get_container as _gc, clone_container, guess_type, OEB_FONTS
|
||||
from calibre.ebooks.oeb.polish.container import get_container as _gc, clone_container, guess_type, OEB_FONTS, OEB_DOCS, OEB_STYLES
|
||||
from calibre.ebooks.oeb.polish.cover import mark_as_cover, mark_as_titlepage
|
||||
from calibre.ebooks.oeb.polish.css import filter_css
|
||||
from calibre.ebooks.oeb.polish.pretty import fix_all_html, pretty_all
|
||||
from calibre.ebooks.oeb.polish.replace import rename_files, replace_file, get_recommended_folders, rationalize_folders
|
||||
from calibre.ebooks.oeb.polish.split import split, merge, AbortError, multisplit
|
||||
@ -41,7 +42,7 @@ from calibre.gui2.tweak_book.search import validate_search_request, run_search
|
||||
from calibre.gui2.tweak_book.spell import find_next as find_next_word
|
||||
from calibre.gui2.tweak_book.widgets import (
|
||||
RationalizeFolders, MultiSplit, ImportForeign, QuickOpen, InsertLink,
|
||||
InsertSemantics, BusyCursor, InsertTag)
|
||||
InsertSemantics, BusyCursor, InsertTag, FilterCSS)
|
||||
|
||||
_diff_dialogs = []
|
||||
|
||||
@ -674,6 +675,31 @@ class Boss(QObject):
|
||||
d.apply_changes(current_container())
|
||||
self.apply_container_update_to_gui()
|
||||
|
||||
def filter_css(self):
|
||||
self.commit_all_editors_to_container()
|
||||
c = current_container()
|
||||
ed = self.gui.central.current_editor
|
||||
for name, q in editors.iteritems():
|
||||
if ed is q:
|
||||
current_name = name
|
||||
break
|
||||
else:
|
||||
current_name = None
|
||||
if current_name and c.mime_map[current_name] not in OEB_DOCS | OEB_STYLES:
|
||||
current_name = None
|
||||
d = FilterCSS(current_name=current_name, parent=self.gui)
|
||||
if d.exec_() == d.Accepted and d.filtered_properties:
|
||||
self.add_savepoint(_('Before: Filter style information'))
|
||||
with BusyCursor():
|
||||
changed = filter_css(current_container(), d.filtered_properties, names=d.filter_names)
|
||||
if changed:
|
||||
self.apply_container_update_to_gui()
|
||||
self.show_current_diff()
|
||||
else:
|
||||
self.rewind_savepoint()
|
||||
return info_dialog(self.gui, _('No matches'), _(
|
||||
'No matching style rules were found'), show=True)
|
||||
|
||||
def show_find(self):
|
||||
self.gui.central.show_find()
|
||||
ed = self.gui.central.current_editor
|
||||
|
@ -9,7 +9,7 @@ __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
import sys
|
||||
|
||||
from PyQt4.Qt import (
|
||||
QIcon, Qt, QSplitter, QListWidget, QTextBrowser, QPalette,
|
||||
QIcon, Qt, QSplitter, QListWidget, QTextBrowser, QPalette, QMenu,
|
||||
QListWidgetItem, pyqtSignal, QApplication, QStyledItemDelegate)
|
||||
|
||||
from calibre.ebooks.oeb.polish.check.base import WARN, INFO, DEBUG, ERROR, CRITICAL
|
||||
@ -28,6 +28,19 @@ def icon_for_level(level):
|
||||
icon = None
|
||||
return QIcon(I(icon)) if icon else QIcon()
|
||||
|
||||
def prefix_for_level(level):
|
||||
if level > WARN:
|
||||
text = _('ERROR')
|
||||
elif level == WARN:
|
||||
text = _('WARNING')
|
||||
elif level == INFO:
|
||||
text = _('INFO')
|
||||
else:
|
||||
text = ''
|
||||
if text:
|
||||
text += ': '
|
||||
return text
|
||||
|
||||
class Delegate(QStyledItemDelegate):
|
||||
|
||||
def initStyleOption(self, option, index):
|
||||
@ -47,6 +60,8 @@ class Check(QSplitter):
|
||||
self.setChildrenCollapsible(False)
|
||||
|
||||
self.items = i = QListWidget(self)
|
||||
i.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||
i.customContextMenuRequested.connect(self.context_menu)
|
||||
self.items.setSpacing(3)
|
||||
self.items.itemDoubleClicked.connect(self.current_item_activated)
|
||||
self.items.currentItemChanged.connect(self.current_item_changed)
|
||||
@ -66,6 +81,22 @@ class Check(QSplitter):
|
||||
if state is not None:
|
||||
self.restoreState(state)
|
||||
|
||||
def context_menu(self, pos):
|
||||
m = QMenu()
|
||||
if self.items.count() > 0:
|
||||
m.addAction(QIcon(I('edit-copy.png')), _('Copy list of errors to clipboard'), self.copy_to_clipboard)
|
||||
if list(m.actions()):
|
||||
m.exec_(self.mapToGlobal(pos))
|
||||
|
||||
def copy_to_clipboard(self):
|
||||
items = []
|
||||
for item in (self.items.item(i) for i in xrange(self.items.count())):
|
||||
msg = unicode(item.text())
|
||||
msg = prefix_for_level(item.data(Qt.UserRole).toPyObject().level) + msg
|
||||
items.append(msg)
|
||||
if items:
|
||||
QApplication.clipboard().setText('\n'.join(items))
|
||||
|
||||
def save_state(self):
|
||||
tprefs.set('check-book-splitter-state', bytearray(self.saveState()))
|
||||
|
||||
|
@ -349,6 +349,8 @@ class Main(MainWindow):
|
||||
_('Arrange into folders'))
|
||||
self.action_set_semantics = reg('tags.png', _('Set &Semantics'), self.boss.set_semantics, 'set-semantics', (),
|
||||
_('Set Semantics'))
|
||||
self.action_filter_css = reg('filter.png', _('&Filter style information'), self.boss.filter_css, 'filter-css', (),
|
||||
_('Filter style information'))
|
||||
|
||||
# Polish actions
|
||||
group = _('Polish Book')
|
||||
@ -482,6 +484,7 @@ class Main(MainWindow):
|
||||
e.addAction(self.action_pretty_all)
|
||||
e.addAction(self.action_rationalize_folders)
|
||||
e.addAction(self.action_set_semantics)
|
||||
e.addAction(self.action_filter_css)
|
||||
e.addAction(self.action_spell_check_book)
|
||||
e.addAction(self.action_check_book)
|
||||
|
||||
|
@ -15,7 +15,7 @@ from PyQt4.Qt import (
|
||||
QFormLayout, QHBoxLayout, QToolButton, QIcon, QApplication, Qt, QWidget,
|
||||
QPoint, QSizePolicy, QPainter, QStaticText, pyqtSignal, QTextOption,
|
||||
QAbstractListModel, QModelIndex, QVariant, QStyledItemDelegate, QStyle,
|
||||
QListView, QTextDocument, QSize, QComboBox, QFrame, QCursor)
|
||||
QListView, QTextDocument, QSize, QComboBox, QFrame, QCursor, QCheckBox)
|
||||
|
||||
from calibre import prepare_string_for_xml
|
||||
from calibre.ebooks.oeb.polish.utils import lead_text
|
||||
@ -689,7 +689,7 @@ class InsertLink(Dialog):
|
||||
frag = item.get('id', None) or item.get('name')
|
||||
text = lead_text(item, num_words=4)
|
||||
ac.append((text, frag))
|
||||
ac.sort(key=lambda (text, frag): primary_sort_key(text))
|
||||
ac.sort(key=lambda text_frag: primary_sort_key(text_frag[0]))
|
||||
self.anchor_names.model().set_names(self.anchor_cache[name])
|
||||
self.update_target()
|
||||
|
||||
@ -924,6 +924,75 @@ class InsertSemantics(Dialog):
|
||||
|
||||
# }}}
|
||||
|
||||
class FilterCSS(Dialog): # {{{
|
||||
|
||||
def __init__(self, current_name=None, parent=None):
|
||||
self.current_name = current_name
|
||||
Dialog.__init__(self, _('Filter Style Information'), 'filter-css', parent=parent)
|
||||
|
||||
def setup_ui(self):
|
||||
from calibre.gui2.convert.look_and_feel_ui import Ui_Form
|
||||
f, w = Ui_Form(), QWidget()
|
||||
f.setupUi(w)
|
||||
self.l = l = QFormLayout(self)
|
||||
self.setLayout(l)
|
||||
|
||||
l.addRow(QLabel(_('Select what style information you want completely removed:')))
|
||||
self.h = h = QHBoxLayout()
|
||||
|
||||
for name, text in {
|
||||
'fonts':_('&Fonts'), 'margins':_('&Margins'), 'padding':_('&Padding'), 'floats':_('Flo&ats'), 'colors':_('&Colors')}.iteritems():
|
||||
c = QCheckBox(text)
|
||||
setattr(self, 'opt_' + name, c)
|
||||
h.addWidget(c)
|
||||
c.setToolTip(getattr(f, 'filter_css_' + name).toolTip())
|
||||
l.addRow(h)
|
||||
|
||||
self.others = o = QLineEdit(self)
|
||||
l.addRow(_('&Other CSS properties:'), o)
|
||||
o.setToolTip(f.filter_css_others.toolTip())
|
||||
|
||||
if self.current_name is not None:
|
||||
self.filter_current = c = QCheckBox(_('Only filter CSS in the current file (%s)') % self.current_name)
|
||||
l.addRow(c)
|
||||
|
||||
l.addRow(self.bb)
|
||||
|
||||
@property
|
||||
def filter_names(self):
|
||||
if self.current_name is not None and self.filter_current.isChecked():
|
||||
return (self.current_name,)
|
||||
return ()
|
||||
|
||||
@property
|
||||
def filtered_properties(self):
|
||||
ans = set()
|
||||
a = ans.add
|
||||
if self.opt_fonts.isChecked():
|
||||
a('font-family')
|
||||
if self.opt_margins.isChecked():
|
||||
a('margin')
|
||||
if self.opt_padding.isChecked():
|
||||
a('padding')
|
||||
if self.opt_floats.isChecked():
|
||||
a('float'), a('clear')
|
||||
if self.opt_colors.isChecked():
|
||||
a('color'), a('background-color')
|
||||
for x in unicode(self.others.text()).split(','):
|
||||
x = x.strip()
|
||||
if x:
|
||||
a(x)
|
||||
return ans
|
||||
|
||||
@classmethod
|
||||
def test(cls):
|
||||
d = cls()
|
||||
if d.exec_() == d.Accepted:
|
||||
print (d.filtered_properties)
|
||||
|
||||
# }}}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication([])
|
||||
InsertLink.test()
|
||||
FilterCSS.test()
|
||||
|
@ -178,6 +178,27 @@ class BuiltinCmp(BuiltinFormatterFunction):
|
||||
return eq
|
||||
return gt
|
||||
|
||||
class BuiltinFirstMatchingCmp(BuiltinFormatterFunction):
|
||||
name = 'first_matching_cmp'
|
||||
category = 'Relational'
|
||||
arg_count = -1
|
||||
__doc__ = doc = _('first_matching_cmp(val, cmp1, result1, cmp2, r2, ..., else_result) -- '
|
||||
'compares "val < cmpN" in sequence, returning resultN for '
|
||||
'the first comparison that succeeds. Returns else_result '
|
||||
'if no comparison succeeds. Example: '
|
||||
'first_matching_cmp(10,5,"small",10,"middle",15,"large","giant") '
|
||||
'returns "middle". The same example with a first value of 16 returns "giant".')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, *args):
|
||||
if (len(args) % 2) != 0:
|
||||
raise ValueError(_('first_matching_cmp requires an even number of arguments'))
|
||||
val = float(args[0] if args[0] and args[0] != 'None' else 0)
|
||||
for i in range(1, len(args) - 1, 2):
|
||||
c = float(args[i] if args[i] and args[i] != 'None' else 0)
|
||||
if val < c:
|
||||
return args[i+1]
|
||||
return args[len(args)-1]
|
||||
|
||||
class BuiltinStrcat(BuiltinFormatterFunction):
|
||||
name = 'strcat'
|
||||
arg_count = -1
|
||||
@ -1310,9 +1331,9 @@ _formatter_builtins = [
|
||||
BuiltinCapitalize(), BuiltinCmp(), BuiltinContains(), BuiltinCount(),
|
||||
BuiltinCurrentLibraryName(), BuiltinCurrentLibraryPath(),
|
||||
BuiltinDaysBetween(), BuiltinDivide(), BuiltinEval(), BuiltinFirstNonEmpty(),
|
||||
BuiltinField(), BuiltinFinishFormatting(), BuiltinFormatDate(),
|
||||
BuiltinFormatNumber(), BuiltinFormatsModtimes(), BuiltinFormatsPaths(),
|
||||
BuiltinFormatsSizes(),
|
||||
BuiltinField(), BuiltinFinishFormatting(), BuiltinFirstMatchingCmp(),
|
||||
BuiltinFormatDate(), BuiltinFormatNumber(), BuiltinFormatsModtimes(),
|
||||
BuiltinFormatsPaths(), BuiltinFormatsSizes(),
|
||||
BuiltinHasCover(), BuiltinHumanReadable(), BuiltinIdentifierInList(),
|
||||
BuiltinIfempty(), BuiltinLanguageCodes(), BuiltinLanguageStrings(),
|
||||
BuiltinInList(), BuiltinListDifference(), BuiltinListEquals(),
|
||||
|
@ -140,6 +140,7 @@ class TestICU(unittest.TestCase):
|
||||
|
||||
def test_contractions(self):
|
||||
' Test contractions '
|
||||
self.skipTest('Skipping as this depends too much on ICU version')
|
||||
c = icu._icu.Collator('cs')
|
||||
self.ae(icu.contractions(c), frozenset({u'Z\u030c', u'z\u030c', u'Ch',
|
||||
u'C\u030c', u'ch', u'cH', u'c\u030c', u's\u030c', u'r\u030c', u'CH',
|
||||
|
Loading…
x
Reference in New Issue
Block a user