commit
c4c329b600
622
BaseSearcher.py
622
BaseSearcher.py
File diff suppressed because it is too large
Load Diff
|
@ -80,7 +80,7 @@ class BibrecPage (Page.Page):
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
if os.format in ('html', 'mobile'):
|
if os.format == 'html':
|
||||||
cat = BaseSearcher.Cat ()
|
cat = BaseSearcher.Cat ()
|
||||||
cat.header = _('Similar Books')
|
cat.header = _('Similar Books')
|
||||||
cat.title = _('Readers also downloaded…')
|
cat.title = _('Readers also downloaded…')
|
||||||
|
@ -101,30 +101,9 @@ class BibrecPage (Page.Page):
|
||||||
cat.order = 33
|
cat.order = 33
|
||||||
os.entries.append (cat)
|
os.entries.append (cat)
|
||||||
|
|
||||||
if os.format in ('mobile', ):
|
|
||||||
for author in dc.authors:
|
|
||||||
cat = BaseSearcher.Cat ()
|
|
||||||
cat.title = _('By {author}').format (author = author.name_and_dates)
|
|
||||||
cat.rel = 'related'
|
|
||||||
cat.url = os.url ('author', id = author.id)
|
|
||||||
cat.class_ += 'navlink grayed'
|
|
||||||
cat.icon = 'author'
|
|
||||||
cat.order = 31
|
|
||||||
os.entries.append (cat)
|
|
||||||
|
|
||||||
for subject in dc.subjects:
|
|
||||||
cat = BaseSearcher.Cat ()
|
|
||||||
cat.title = _('On {subject}').format (subject = subject.subject)
|
|
||||||
cat.rel = 'related'
|
|
||||||
cat.url = os.url ('subject', id = subject.id)
|
|
||||||
cat.class_ += 'navlink grayed'
|
|
||||||
cat.icon = 'subject'
|
|
||||||
cat.order = 32
|
|
||||||
os.entries.append (cat)
|
|
||||||
|
|
||||||
os.total_results = 1
|
os.total_results = 1
|
||||||
|
|
||||||
os.template = 'results' if os.format == 'mobile' else 'bibrec'
|
os.template = 'bibrec'
|
||||||
os.page = 'bibrec'
|
os.page = 'bibrec'
|
||||||
os.og_type = 'book'
|
os.og_type = 'book'
|
||||||
os.finalize ()
|
os.finalize ()
|
||||||
|
|
|
@ -19,7 +19,6 @@ pgdatabase: 'gutenberg'
|
||||||
pguser: 'postgres'
|
pguser: 'postgres'
|
||||||
|
|
||||||
host: 'www.gutenberg.org'
|
host: 'www.gutenberg.org'
|
||||||
host_mobile: 'm.gutenberg.org'
|
|
||||||
host_https: 1
|
host_https: 1
|
||||||
file_host: 'www.gutenberg.org'
|
file_host: 'www.gutenberg.org'
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,6 @@ def main():
|
||||||
'daemonize': False,
|
'daemonize': False,
|
||||||
'pidfile': None,
|
'pidfile': None,
|
||||||
'host': 'localhost',
|
'host': 'localhost',
|
||||||
'host_mobile': 'localhost',
|
|
||||||
'file_host': 'localhost',
|
'file_host': 'localhost',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -165,7 +164,7 @@ def main():
|
||||||
cherrypy.config['js_mtime'] = t
|
cherrypy.config['js_mtime'] = t
|
||||||
|
|
||||||
cherrypy.config['all_hosts'] = (
|
cherrypy.config['all_hosts'] = (
|
||||||
cherrypy.config['host'], cherrypy.config['host_mobile'], cherrypy.config['file_host'])
|
cherrypy.config['host'], cherrypy.config['file_host'])
|
||||||
|
|
||||||
cherrypy.config.update({'error_page.404': error_page_404})
|
cherrypy.config.update({'error_page.404': error_page_404})
|
||||||
|
|
||||||
|
|
|
@ -13,19 +13,21 @@ Serve cover images of most popular and latest ebooks.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
import re
|
||||||
|
|
||||||
import cherrypy
|
import cherrypy
|
||||||
import six
|
import six
|
||||||
|
import textwrap
|
||||||
|
|
||||||
from libgutenberg import GutenbergGlobals as gg
|
from libgutenberg import GutenbergGlobals as gg
|
||||||
|
|
||||||
import BaseSearcher
|
import BaseSearcher
|
||||||
|
|
||||||
class CoverPages (object):
|
class CoverPages(object):
|
||||||
""" Output a gallery of cover pages. """
|
""" Output a gallery of cover pages. """
|
||||||
|
|
||||||
orders = { 'latest': 'release_date',
|
orders = {'latest': 'release_date',
|
||||||
'popular': 'downloads' }
|
'popular': 'downloads'}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def serve (rows, size):
|
def serve (rows, size):
|
||||||
|
@ -33,72 +35,65 @@ class CoverPages (object):
|
||||||
|
|
||||||
cherrypy.response.headers['Content-Type'] = 'text/html; charset=utf-8'
|
cherrypy.response.headers['Content-Type'] = 'text/html; charset=utf-8'
|
||||||
cherrypy.response.headers['Content-Language'] = 'en'
|
cherrypy.response.headers['Content-Language'] = 'en'
|
||||||
|
s = ''
|
||||||
s = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" xml:base="http://www.gutenberg.org">
|
|
||||||
<head>
|
|
||||||
<title>Cover Flow</title>
|
|
||||||
<!--<style>
|
|
||||||
.cover-thumb {
|
|
||||||
display: inline-block;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
|
||||||
.cover-thumb-small {
|
|
||||||
width: 76px;
|
|
||||||
height: 110px;
|
|
||||||
}
|
|
||||||
.cover-thumb-medium {
|
|
||||||
width: 210px;
|
|
||||||
height: 310px;
|
|
||||||
}
|
|
||||||
</style>-->
|
|
||||||
</head>
|
|
||||||
<body><div>"""
|
|
||||||
|
|
||||||
for row in rows:
|
for row in rows:
|
||||||
url = '/' + row.filename
|
url = '/' + row.filename
|
||||||
href = '/ebooks/%d' % row.pk
|
href = '/ebooks/%d' % row.pk
|
||||||
title = gg.xmlspecialchars (row.title)
|
if row.title:
|
||||||
title = title.replace ('"', '"')
|
title = gg.xmlspecialchars (row.title) # handles <,>,&
|
||||||
|
#Shortening long titles for latest covers
|
||||||
|
title = title.replace('"', '"')
|
||||||
|
title = title.replace("'", ''')
|
||||||
|
else:
|
||||||
|
title = '!! missing title !!'
|
||||||
|
short_title = title
|
||||||
|
title_len = len(title)
|
||||||
|
short_title = re.sub(r"\-+", " ", short_title)
|
||||||
|
short_title = short_title.splitlines()[0]
|
||||||
|
if(title_len > 80):
|
||||||
|
short_title = textwrap.wrap(short_title, 80)[0]
|
||||||
|
s += """
|
||||||
|
<a href="{href}" title="{title}" target="_top">
|
||||||
|
<div class="cover_image">
|
||||||
|
<div class="cover_img">
|
||||||
|
<img src="{url}" alt="{title}" title="{title}" draggable="false">
|
||||||
|
</div>
|
||||||
|
<div class="cover_title">
|
||||||
|
<h5>{short_title}</h5>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
""".format(url=url, href=href, title=title, short_title=short_title, size=size)
|
||||||
|
|
||||||
s += """<a href="{href}"
|
return s.encode('utf-8')
|
||||||
title="{title}"
|
|
||||||
class="cover-thumb cover-thumb-{size}" target="_top"
|
|
||||||
style="background-image: url({url})"> </a>\n""".format (
|
|
||||||
url = url, href = href, title = title, size = size)
|
|
||||||
|
|
||||||
|
|
||||||
return (s + '</div></body></html>\n').encode ('utf-8')
|
def index(self, count, size, order, **kwargs):
|
||||||
|
|
||||||
def index (self, count, size, order, **kwargs):
|
|
||||||
""" Internal help function. """
|
""" Internal help function. """
|
||||||
|
|
||||||
try:
|
try:
|
||||||
count = int (count)
|
count = int(count)
|
||||||
if count < 1:
|
if count < 1:
|
||||||
raise ValueError ('count < 0')
|
raise ValueError('count < 0')
|
||||||
if size not in ('small', 'medium'):
|
if size not in ('small', 'medium'):
|
||||||
raise ValueError ('bogus size')
|
raise ValueError('bogus size')
|
||||||
order = 'books.%s' % self.orders[order]
|
order = 'books.%s' % self.orders[order]
|
||||||
|
|
||||||
rows = BaseSearcher.SQLSearcher.execute (
|
rows = BaseSearcher.SQLSearcher.execute(
|
||||||
"""SELECT files.filename, books.pk, books.title FROM files, books
|
"""SELECT files.filename, books.pk, books.title FROM files, books
|
||||||
WHERE files.fk_books = books.pk
|
WHERE files.fk_books = books.pk
|
||||||
AND files.diskstatus = 0
|
AND files.diskstatus = 0
|
||||||
AND files.fk_filetypes = %%(size)s
|
AND files.fk_filetypes = %%(size)s
|
||||||
ORDER BY %s DESC
|
ORDER BY %s DESC
|
||||||
OFFSET 1 LIMIT %%(count)s -- %s""" % (order, cherrypy.request.remote.ip),
|
OFFSET 1 LIMIT %%(count)s -- %s""" % (order, cherrypy.request.remote.ip),
|
||||||
{ 'count': count,
|
{'count': count, 'size': 'cover.%s' % size,}
|
||||||
'size': 'cover.%s' % size,
|
)
|
||||||
})
|
|
||||||
|
|
||||||
if rows:
|
if rows:
|
||||||
return self.serve (rows, size)
|
return self.serve(rows, size)
|
||||||
|
|
||||||
except (ValueError, KeyError) as what:
|
except (ValueError, KeyError) as what:
|
||||||
raise cherrypy.HTTPError (400, 'Bad Request. %s' % six.text_type (what))
|
raise cherrypy.HTTPError (400, 'Bad Request. %s' % six.text_type(what))
|
||||||
except IOError:
|
except IOError:
|
||||||
pass
|
pass
|
||||||
raise cherrypy.HTTPError (500, 'Internal Server Error.')
|
raise cherrypy.HTTPError (500, 'Internal Server Error.')
|
||||||
|
|
|
@ -37,7 +37,6 @@ def format (format_, page, os_):
|
||||||
formatters = {}
|
formatters = {}
|
||||||
formatters['opds'] = OPDSFormatter.OPDSFormatter ()
|
formatters['opds'] = OPDSFormatter.OPDSFormatter ()
|
||||||
formatters['stanza'] = formatters['opds']
|
formatters['stanza'] = formatters['opds']
|
||||||
formatters['mobile'] = HTMLFormatter.MobileFormatter ()
|
|
||||||
formatters['html'] = HTMLFormatter.HTMLFormatter ()
|
formatters['html'] = HTMLFormatter.HTMLFormatter ()
|
||||||
formatters['json'] = JSONFormatter.JSONFormatter ()
|
formatters['json'] = JSONFormatter.JSONFormatter ()
|
||||||
# FIXME: only needed to load sitemap.xml templates
|
# FIXME: only needed to load sitemap.xml templates
|
||||||
|
|
|
@ -31,9 +31,6 @@ from i18n_tool import ugettext as _
|
||||||
# filetypes ignored on desktop site
|
# filetypes ignored on desktop site
|
||||||
NO_DESKTOP_FILETYPES = 'plucker qioo rdf rst rst.gen rst.master tei cover.medium cover.small'.split ()
|
NO_DESKTOP_FILETYPES = 'plucker qioo rdf rst rst.gen rst.master tei cover.medium cover.small'.split ()
|
||||||
|
|
||||||
# filetypes shown on mobile site
|
|
||||||
MOBILE_TYPES = (mt.epub, mt.mobi, mt.pdf, 'text/html', mt.html)
|
|
||||||
|
|
||||||
# filetypes which are usually handed over to a separate app on mobile devices
|
# filetypes which are usually handed over to a separate app on mobile devices
|
||||||
HANDOVER_TYPES = (mt.epub, mt.mobi, mt.pdf)
|
HANDOVER_TYPES = (mt.epub, mt.mobi, mt.pdf)
|
||||||
|
|
||||||
|
@ -187,44 +184,3 @@ class HTMLFormatter (XMLishFormatter):
|
||||||
if showncount == 0:
|
if showncount == 0:
|
||||||
for file_ in dc.files + dc.generated_files:
|
for file_ in dc.files + dc.generated_files:
|
||||||
file_.hidden = False
|
file_.hidden = False
|
||||||
|
|
||||||
|
|
||||||
class MobileFormatter (XMLishFormatter):
|
|
||||||
""" Produce HTML output suitable for mobile devices. """
|
|
||||||
|
|
||||||
CONTENT_TYPE = mt.xhtml + '; charset=UTF-8'
|
|
||||||
DOCTYPE = 'html5'
|
|
||||||
|
|
||||||
def __init__ (self):
|
|
||||||
super (MobileFormatter, self).__init__ ()
|
|
||||||
|
|
||||||
|
|
||||||
def get_serializer (self):
|
|
||||||
return genshi.output.HTMLSerializer (doctype = self.DOCTYPE, strip_whitespace = False)
|
|
||||||
|
|
||||||
|
|
||||||
def fix_dc (self, dc, os):
|
|
||||||
""" Add some info to dc for easier templating.
|
|
||||||
|
|
||||||
Also make sure that dc `walks like a cat´. """
|
|
||||||
|
|
||||||
super (MobileFormatter, self).fix_dc (dc, os)
|
|
||||||
|
|
||||||
for file_ in dc.files + dc.generated_files:
|
|
||||||
if len (file_.mediatypes) == 1:
|
|
||||||
type_ = six.text_type (file_.mediatypes[0])
|
|
||||||
m = type_.partition (';')[0]
|
|
||||||
if m in MOBILE_TYPES:
|
|
||||||
cat = BaseSearcher.Cat ()
|
|
||||||
cat.type = file_.mediatypes[0]
|
|
||||||
cat.header = _('Download')
|
|
||||||
cat.title = file_.hr_filetype
|
|
||||||
cat.extra = file_.hr_extent
|
|
||||||
|
|
||||||
cat.charset = file_.encoding
|
|
||||||
cat.url = '/' + file_.filename
|
|
||||||
cat.icon = dc.icon
|
|
||||||
cat.icon2 = 'download'
|
|
||||||
cat.class_ += 'filelink'
|
|
||||||
cat.order = 20
|
|
||||||
os.entries.append (cat)
|
|
||||||
|
|
|
@ -35,12 +35,7 @@ class BookSearchPage (SearchPage):
|
||||||
os.f_format_icon = os.format_icon_titles
|
os.f_format_icon = os.format_icon_titles
|
||||||
|
|
||||||
if os.sort_order == 'random':
|
if os.sort_order == 'random':
|
||||||
sql.where.append ("""
|
sql.where.append ("pk in (select pk from books order by random() limit 20)")
|
||||||
pk in (select floor (random () * maxbook)::integer
|
|
||||||
from generate_series (1, 30), (select max (pk) as maxbook
|
|
||||||
from books) xbks1)
|
|
||||||
""")
|
|
||||||
|
|
||||||
if len (os.query):
|
if len (os.query):
|
||||||
sql.fulltext ('books.tsvec', os.query)
|
sql.fulltext ('books.tsvec', os.query)
|
||||||
os.title = _("Books: {title}").format (title = os.query)
|
os.title = _("Books: {title}").format (title = os.query)
|
||||||
|
@ -270,7 +265,7 @@ class AuthorPage (SearchPage):
|
||||||
os.entries.insert (0, cat)
|
os.entries.insert (0, cat)
|
||||||
|
|
||||||
# author aliases
|
# author aliases
|
||||||
if os.format in ('html', 'mobile'):
|
if os.format == 'html':
|
||||||
rows = BaseSearcher.SQLSearcher.execute (
|
rows = BaseSearcher.SQLSearcher.execute (
|
||||||
"""SELECT alias AS title FROM aliases
|
"""SELECT alias AS title FROM aliases
|
||||||
WHERE fk_authors = %(fk_authors)s AND alias_heading = 1""",
|
WHERE fk_authors = %(fk_authors)s AND alias_heading = 1""",
|
||||||
|
|
|
@ -30,7 +30,6 @@ class Start (Page.Page):
|
||||||
|
|
||||||
os.search_terms = ''
|
os.search_terms = ''
|
||||||
os.title = {
|
os.title = {
|
||||||
'mobile': _('PG Mobile'),
|
|
||||||
'opds': _('Project Gutenberg'),
|
'opds': _('Project Gutenberg'),
|
||||||
'stanza': _('Project Gutenberg')
|
'stanza': _('Project Gutenberg')
|
||||||
}.get (os.format, _('Search Project Gutenberg'))
|
}.get (os.format, _('Search Project Gutenberg'))
|
||||||
|
|
|
@ -86,17 +86,27 @@ sudo systemctl status autocat3.service
|
||||||
# we are having problems with monit trying to restart. It might be necessary to also stop
|
# we are having problems with monit trying to restart. It might be necessary to also stop
|
||||||
# monit. Further diagnosis is forthcoming.
|
# monit. Further diagnosis is forthcoming.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
create a "feature" branch on on the git repo, using either master or development as base.
|
||||||
|
when your code is working, submit a pull request to master or development as appropriate.
|
||||||
|
|
||||||
## updates
|
## updates
|
||||||
|
# currently gutenberg1 is production deployment, gutenberg2 is dev deployment
|
||||||
|
# to do a new deployment, first pull from the master or dev as appropriate
|
||||||
|
# into gutenberg1 or gutenberg2.
|
||||||
|
# DONT edit files on the deployment servers, they should always be updated from the git remote.
|
||||||
|
|
||||||
su - autocat
|
su - autocat
|
||||||
# or sudo su - autocat if you can sudo
|
# or sudo su - autocat if you can sudo
|
||||||
|
|
||||||
cd autocat3
|
cd autocat3
|
||||||
git pull
|
|
||||||
git checkout remotes/origin/master
|
git fetch origin
|
||||||
|
|
||||||
|
#for gutenberg1
|
||||||
|
git checkout remotes/origin/gutenberg1
|
||||||
# for gutenberg2
|
# for gutenberg2
|
||||||
# git checkout remotes/origin/gutenberg2
|
git checkout remotes/origin/gutenberg2
|
||||||
|
|
||||||
pipenv install --ignore-pipfile
|
pipenv install --ignore-pipfile
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
DON'T USE THIS PAGE FOR SCRAPING.
|
DON'T USE THIS PAGE FOR SCRAPING.
|
||||||
|
|
||||||
Seriously. You'll only get your IP blocked.
|
Seriously. You'll only get your IP blocked.
|
||||||
|
|
||||||
Read http://www.gutenberg.org/feeds/ to learn how to download Project
|
Read http://www.gutenberg.org/feeds/ to learn how to download Project
|
||||||
Gutenberg metadata much faster than by scraping.
|
Gutenberg metadata much faster than by scraping.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
@ -55,7 +51,7 @@ Gutenberg metadata much faster than by scraping.
|
||||||
|
|
||||||
<head xmlns:og="http://opengraphprotocol.org/schema/">
|
<head xmlns:og="http://opengraphprotocol.org/schema/">
|
||||||
|
|
||||||
${site_head ()}
|
${site_head()}
|
||||||
|
|
||||||
<title>${os.title} - Free Ebook</title>
|
<title>${os.title} - Free Ebook</title>
|
||||||
|
|
||||||
|
@ -69,9 +65,10 @@ Gutenberg metadata much faster than by scraping.
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="mw-head-dummy" class="noprint" />
|
<div class="container">
|
||||||
|
${site_top()}
|
||||||
|
|
||||||
<div id="content" itemscope="itemscope" itemtype="http://schema.org/Book" i18n:comment="On the 'bibrec' page.">
|
<div class="page_content" id="content" itemscope="itemscope" itemtype="http://schema.org/Book" i18n:comment="On the 'bibrec' page.">
|
||||||
|
|
||||||
<div class="breadcrumbs noprint">
|
<div class="breadcrumbs noprint">
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -84,12 +81,10 @@ Gutenberg metadata much faster than by scraping.
|
||||||
</py:for>
|
</py:for>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="header">
|
|
||||||
<h1 itemprop="name">${os.title}</h1>
|
<h1 itemprop="name">${os.title}</h1>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="body">
|
|
||||||
|
<div class="page-body">
|
||||||
<div property="dcterms:publisher" itemprop="publisher" content="Project Gutenberg" />
|
<div property="dcterms:publisher" itemprop="publisher" content="Project Gutenberg" />
|
||||||
<div itemprop="bookFormat" content="EBook" />
|
<div itemprop="bookFormat" content="EBook" />
|
||||||
|
|
||||||
|
@ -110,34 +105,134 @@ Gutenberg metadata much faster than by scraping.
|
||||||
|
|
||||||
<div id="social" class="noprint">
|
<div id="social" class="noprint">
|
||||||
<ul>
|
<ul>
|
||||||
<!--! Broken. Dialog opens and closes immediately. Disabled for now.
|
|
||||||
<li>
|
<li>
|
||||||
${fb_share (os.canonical_url, os.title.encode ('utf-8'),
|
${tw_share(os.canonical_url, os.twit)}
|
||||||
os.description.encode ('utf-8'), os.cover_thumb_url)}
|
|
||||||
</li>
|
|
||||||
-->
|
|
||||||
<li>
|
|
||||||
${tw_share (os.canonical_url, os.twit)}
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a onclick="printpage ()" title="Print this page"><span class="icon icon_print" /></a>
|
${fb_share(os.canonical_url)}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a onclick="printpage()" title="Print this page"><span class="icon icon_print" /></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="qr">
|
<div id="qr">
|
||||||
<!--! qr code of mobile page for screen -->
|
|
||||||
<span class="qrcode qrcode-desktop" title="Scan QR Code for this page." />
|
<span class="qrcode qrcode-desktop" title="Scan QR Code for this page." />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="tabs-wrapper">
|
<div id="tabs-wrapper">
|
||||||
<div id="tabs">
|
<div id="tabs">
|
||||||
<ul class="noprint">
|
<div id="download" i18n:comment="On the 'Download' tab of the 'bibrec' page.">
|
||||||
<li><a href="#download">Download</a></li>
|
|
||||||
<li><a href="#bibrec">Bibrec</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
<py:for each="e in os.entries">
|
||||||
|
<py:if test="isinstance(e, bs.DC)">
|
||||||
|
<div about="[ebook:$e.project_gutenberg_id]" rel="dcterms:hasFormat" >
|
||||||
|
|
||||||
|
<h2>Download This eBook</h2>
|
||||||
|
|
||||||
|
<table class="files">
|
||||||
|
<colgroup>
|
||||||
|
<col class="narrow" />
|
||||||
|
<col />
|
||||||
|
<col />
|
||||||
|
<col />
|
||||||
|
<col class="narrow noprint" />
|
||||||
|
<col class="narrow noprint" />
|
||||||
|
<col class="narrow noprint" />
|
||||||
|
</colgroup>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th />
|
||||||
|
<th>Format <span>${help ('Format')}</span></th>
|
||||||
|
<th class="noscreen">Url</th>
|
||||||
|
<th i18n:comment="Size of a file." class="right">Size</th>
|
||||||
|
<th class="noprint"><span>${help ('Dropbox')}</span></th>
|
||||||
|
<th class="noprint"><span>${help ('Google Drive')}</span></th>
|
||||||
|
<th class="noprint"><span>${help ('OneDrive')}</span></th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr py:for="i, file_ in enumerate(e.files)"
|
||||||
|
py:if="not file_.hidden"
|
||||||
|
class="${i%2 and 'odd' or 'even'}"
|
||||||
|
about="${file_.url}" typeof="pgterms:file">
|
||||||
|
<td><span class="icon icon_${e.icon}" /></td>
|
||||||
|
<td property="dcterms:format" content="${file_.mediatypes[-1]}" datatype="dcterms:IMT"
|
||||||
|
class="unpadded icon_save"
|
||||||
|
><a href="/${file_.filename}" type="${file_.mediatypes[-1]}" class="link"
|
||||||
|
title="Download">${file_.hr_filetype}</a></td>
|
||||||
|
<td class="noscreen">${file_.url}</td>
|
||||||
|
<td class="right"
|
||||||
|
property="dcterms:extent" content="${file_.extent}">${file_.hr_extent}</td>
|
||||||
|
<td class="noprint">
|
||||||
|
<a py:if="file_.dropbox_url"
|
||||||
|
href="${file_.dropbox_url}"
|
||||||
|
title="Send to Dropbox." rel="nofollow"><span class="icon icon_dropbox" /></a>
|
||||||
|
</td>
|
||||||
|
<td class="noprint">
|
||||||
|
<a py:if="file_.gdrive_url"
|
||||||
|
href="${file_.gdrive_url}"
|
||||||
|
title="Send to Google Drive." rel="nofollow"><span class="icon icon_gdrive" /></a>
|
||||||
|
</td>
|
||||||
|
<td class="noprint">
|
||||||
|
<a py:if="file_.honeypot_url"
|
||||||
|
href="${file_.honeypot_url}"
|
||||||
|
title="Send to MegaUpload." rel="nofollow" />
|
||||||
|
<a py:if="file_.msdrive_url"
|
||||||
|
href="${file_.msdrive_url}"
|
||||||
|
title="Send to OneDrive." rel="nofollow"><span class="icon icon_msdrive" /></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<!--! more files ... -->
|
||||||
|
<tr py:if="e.base_dir"
|
||||||
|
class="${i%2 and 'odd' or 'even'}">
|
||||||
|
<td><span class="icon icon_folder" /></td>
|
||||||
|
<td class="unpadded icon_file"><a href="${e.base_dir}" class="link"
|
||||||
|
i18n:comment="Link to the directory containing all files.">More Files…</a></td>
|
||||||
|
<td class="noscreen">${os.qualify (e.base_dir)}</td>
|
||||||
|
<td/>
|
||||||
|
<td class="noprint"><!--! dropbox column --></td>
|
||||||
|
<td class="noprint"><!--! gdrive column --></td>
|
||||||
|
<td class="noprint"><!--! msdrive column --></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</py:if>
|
||||||
|
</py:for>
|
||||||
|
|
||||||
|
</div> <!-- download -->
|
||||||
|
|
||||||
|
<div id="more_stuff">
|
||||||
|
<py:for each="n, e in enumerate (os.entries)">
|
||||||
|
<py:if test="isinstance (e, bs.Cat) and e.rel not in ('start', )">
|
||||||
|
<py:if test="e.header and old_header != e.header">
|
||||||
|
<h2 class="header">${e.header}</h2>
|
||||||
|
</py:if>
|
||||||
|
<?python old_header = e.header ?>
|
||||||
|
|
||||||
|
<div class="${e.class_}">
|
||||||
|
<a rel="nofollow"
|
||||||
|
href="${e.url}"
|
||||||
|
type="${e.type}"
|
||||||
|
charset="${e.charset}"
|
||||||
|
accesskey="${str (n % 10)}">
|
||||||
|
<span class="cell leftcell">
|
||||||
|
<span class="icon icon_${e.icon}" />
|
||||||
|
</span>
|
||||||
|
<span class="cell content">
|
||||||
|
<span class="title">${e.title}</span>
|
||||||
|
<span py:if="e.subtitle" class="subtitle">${e.subtitle}</span>
|
||||||
|
<span py:if="e.extra" class="extra">${e.extra}</span>
|
||||||
|
</span>
|
||||||
|
<span class="hstrut" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</py:if>
|
||||||
|
</py:for>
|
||||||
|
</div> <!-- more stuff -->
|
||||||
<div id="bibrec" i18n:comment="On the 'bibrec' tab of the 'bibrec' page.">
|
<div id="bibrec" i18n:comment="On the 'bibrec' tab of the 'bibrec' page.">
|
||||||
<py:for each="e in os.entries">
|
<py:for each="e in os.entries">
|
||||||
<py:if test="isinstance (e, bs.DC)">
|
<py:if test="isinstance (e, bs.DC)">
|
||||||
|
@ -170,23 +265,23 @@ Gutenberg metadata much faster than by scraping.
|
||||||
</td>
|
</td>
|
||||||
<td py:when="marc.code[0]=='5'">
|
<td py:when="marc.code[0]=='5'">
|
||||||
<?python
|
<?python
|
||||||
text = gg.xmlspecialchars (marc.text)
|
text = gg.xmlspecialchars(marc.text)
|
||||||
text = re.sub (r'(//\S+)', r'<a href="\1">\1</a>', text)
|
text = re.sub(r'(//\S+)', r'<a href="\1">\1</a>', text)
|
||||||
text = re.sub (r'#(\d+)', r'<a href="/ebooks/\1">#\1</a>', text)
|
text = re.sub(r'#(\d+)', r'<a href="/ebooks/\1">#\1</a>', text)
|
||||||
?>
|
?>
|
||||||
${ Markup (gg.insert_breaks (text)) }
|
${ Markup (gg.insert_breaks (text)) }
|
||||||
</td>
|
</td>
|
||||||
<td py:when="marc.code=='245'" itemprop="headline">
|
<td py:when="marc.code=='245'" itemprop="headline">
|
||||||
${ Markup (gg.insert_breaks (gg.xmlspecialchars (marc.text))) }
|
${ Markup (gg.insert_breaks(gg.xmlspecialchars(marc.text))) }
|
||||||
</td>
|
</td>
|
||||||
<td py:when="marc.code=='240'" itemprop="alternativeHeadline">
|
<td py:when="marc.code=='240'" itemprop="alternativeHeadline">
|
||||||
${ Markup (gg.insert_breaks (gg.xmlspecialchars (marc.text))) }
|
${ Markup (gg.insert_breaks(gg.xmlspecialchars(marc.text))) }
|
||||||
</td>
|
</td>
|
||||||
<td py:when="marc.code=='246'" itemprop="alternativeHeadline">
|
<td py:when="marc.code=='246'" itemprop="alternativeHeadline">
|
||||||
${ Markup (gg.insert_breaks (gg.xmlspecialchars (marc.text))) }
|
${ Markup (gg.insert_breaks(gg.xmlspecialchars(marc.text))) }
|
||||||
</td>
|
</td>
|
||||||
<td py:otherwise="">
|
<td py:otherwise="">
|
||||||
${ Markup (gg.insert_breaks (gg.xmlspecialchars (marc.text))) }
|
${ Markup (gg.insert_breaks(gg.xmlspecialchars(marc.text))) }
|
||||||
</td>
|
</td>
|
||||||
</py:choose>
|
</py:choose>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -200,7 +295,7 @@ Gutenberg metadata much faster than by scraping.
|
||||||
|
|
||||||
<tr py:for="locc in e.loccs"
|
<tr py:for="locc in e.loccs"
|
||||||
property="dcterms:subject" datatype="dcterms:LCC" content="${locc.id}">
|
property="dcterms:subject" datatype="dcterms:LCC" content="${locc.id}">
|
||||||
<th>LoC Class</th>
|
<th>LoC Class</th>
|
||||||
<td>
|
<td>
|
||||||
<a href="/browse/loccs/${locc.id.lower ()}">${locc.id}: ${locc.locc}</a>
|
<a href="/browse/loccs/${locc.id.lower ()}">${locc.id}: ${locc.locc}</a>
|
||||||
</td>
|
</td>
|
||||||
|
@ -226,12 +321,12 @@ Gutenberg metadata much faster than by scraping.
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr property="dcterms:issued" datatype="xsd:date" content="${e.xsd_release_date_time}">
|
<tr property="dcterms:issued" datatype="xsd:date" content="${e.xsd_release_date_time}">
|
||||||
<th>Release Date</th>
|
<th>Release Date</th>
|
||||||
<td itemprop="datePublished">${e.hr_release_date}</td>
|
<td itemprop="datePublished">${e.hr_release_date}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Copyright Status</th>
|
<th>Copyright Status</th>
|
||||||
<td property="dcterms:rights">${e.rights}</td>
|
<td property="dcterms:rights">${e.rights}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -251,122 +346,13 @@ Gutenberg metadata much faster than by scraping.
|
||||||
</py:if>
|
</py:if>
|
||||||
</py:for>
|
</py:for>
|
||||||
|
|
||||||
<div id="more_stuff">
|
|
||||||
<py:for each="n, e in enumerate (os.entries)">
|
|
||||||
<py:if test="isinstance (e, bs.Cat) and e.rel not in ('start', )">
|
|
||||||
<py:if test="e.header and old_header != e.header">
|
|
||||||
<h2 class="header">${e.header}</h2>
|
|
||||||
</py:if>
|
|
||||||
<?python old_header = e.header ?>
|
|
||||||
|
|
||||||
<div class="${e.class_}">
|
|
||||||
<a rel="nofollow"
|
|
||||||
href="${e.url}"
|
|
||||||
type="${e.type}"
|
|
||||||
charset="${e.charset}"
|
|
||||||
accesskey="${str (n % 10)}">
|
|
||||||
<span class="cell leftcell">
|
|
||||||
<span class="icon icon_${e.icon}" />
|
|
||||||
</span>
|
|
||||||
<span class="cell content">
|
|
||||||
<span class="title">${e.title}</span>
|
|
||||||
<span py:if="e.subtitle" class="subtitle">${e.subtitle}</span>
|
|
||||||
<span py:if="e.extra" class="extra">${e.extra}</span>
|
|
||||||
</span>
|
|
||||||
<span class="hstrut" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</py:if>
|
|
||||||
</py:for>
|
|
||||||
</div> <!-- more stuff -->
|
|
||||||
|
|
||||||
</div> <!--! bibrec -->
|
</div> <!--! bibrec -->
|
||||||
|
|
||||||
<div id="download" i18n:comment="On the 'Download' tab of the 'bibrec' page.">
|
|
||||||
|
|
||||||
<py:for each="e in os.entries">
|
|
||||||
<py:if test="isinstance (e, bs.DC)">
|
|
||||||
<div about="[ebook:$e.project_gutenberg_id]" rel="dcterms:hasFormat" ><!--! rev="dcterms:isFormatOf" -->
|
|
||||||
|
|
||||||
<h2>Download This eBook</h2>
|
|
||||||
|
|
||||||
<table class="files">
|
|
||||||
<colgroup>
|
|
||||||
<col class="narrow" />
|
|
||||||
<col />
|
|
||||||
<col />
|
|
||||||
<col />
|
|
||||||
<col class="narrow noprint" />
|
|
||||||
<col class="narrow noprint" />
|
|
||||||
<col class="narrow noprint" />
|
|
||||||
</colgroup>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<th />
|
|
||||||
<th>Format <span>${help ('Format')}</span></th>
|
|
||||||
<th class="noscreen">Url</th>
|
|
||||||
<th i18n:comment="Size of a file." class="right">Size</th>
|
|
||||||
<th class="noprint"><span>${help ('Dropbox')}</span></th>
|
|
||||||
<th class="noprint"><span>${help ('Google Drive')}</span></th>
|
|
||||||
<th class="noprint"><span>${help ('OneDrive')}</span></th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr py:for="i, file_ in enumerate (e.files)"
|
|
||||||
py:if="not file_.hidden"
|
|
||||||
class="${i%2 and 'odd' or 'even'}"
|
|
||||||
about="${file_.url}" typeof="pgterms:file">
|
|
||||||
<td><span class="icon icon_${e.icon}" /></td>
|
|
||||||
<td property="dcterms:format" content="${file_.mediatypes[-1]}" datatype="dcterms:IMT"
|
|
||||||
class="unpadded icon_save"
|
|
||||||
><a href="/${file_.filename}" type="${file_.mediatypes[-1]}" class="link"
|
|
||||||
title="Download">${file_.hr_filetype}</a></td>
|
|
||||||
<td class="noscreen">${file_.url}</td>
|
|
||||||
<td class="right"
|
|
||||||
property="dcterms:extent" content="${file_.extent}">${file_.hr_extent}</td>
|
|
||||||
<td class="noprint">
|
|
||||||
<a py:if="file_.dropbox_url"
|
|
||||||
href="${file_.dropbox_url}"
|
|
||||||
title="Send to Dropbox." rel="nofollow"><span class="icon icon_dropbox" /></a>
|
|
||||||
</td>
|
|
||||||
<td class="noprint">
|
|
||||||
<a py:if="file_.gdrive_url"
|
|
||||||
href="${file_.gdrive_url}"
|
|
||||||
title="Send to Google Drive." rel="nofollow"><span class="icon icon_gdrive" /></a>
|
|
||||||
</td>
|
|
||||||
<td class="noprint">
|
|
||||||
<a py:if="file_.honeypot_url"
|
|
||||||
href="${file_.honeypot_url}"
|
|
||||||
title="Send to MegaUpload." rel="nofollow" />
|
|
||||||
<a py:if="file_.msdrive_url"
|
|
||||||
href="${file_.msdrive_url}"
|
|
||||||
title="Send to OneDrive." rel="nofollow"><span class="icon icon_msdrive" /></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!--! more files ... -->
|
|
||||||
<tr py:if="e.base_dir"
|
|
||||||
class="${i%2 and 'odd' or 'even'}">
|
|
||||||
<td><span class="icon icon_folder" /></td>
|
|
||||||
<td class="unpadded icon_file"><a href="${e.base_dir}" class="link"
|
|
||||||
i18n:comment="Link to the directory containing all files.">More Files…</a></td>
|
|
||||||
<td class="noscreen">${os.qualify (e.base_dir)}</td>
|
|
||||||
<td/>
|
|
||||||
<td class="noprint"><!--! dropbox column --></td>
|
|
||||||
<td class="noprint"><!--! gdrive column --></td>
|
|
||||||
<td class="noprint"><!--! msdrive column --></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</py:if>
|
|
||||||
</py:for>
|
|
||||||
|
|
||||||
</div> <!-- download -->
|
|
||||||
|
|
||||||
</div> <!--! tabs -->
|
</div> <!--! tabs -->
|
||||||
</div> <!--! tabs-wrapper -->
|
</div> <!--! tabs-wrapper -->
|
||||||
</div> <!--! body -->
|
</div> <!--! body -->
|
||||||
|
</div>
|
||||||
<div id="dialog" class="hidden">
|
<div id="dialog" class="hidden">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -380,7 +366,6 @@ Gutenberg metadata much faster than by scraping.
|
||||||
about=""
|
about=""
|
||||||
rel="dcterms:conformsTo"
|
rel="dcterms:conformsTo"
|
||||||
resource="http://www.w3.org/TR/rdfa-syntax" /></a>
|
resource="http://www.w3.org/TR/rdfa-syntax" /></a>
|
||||||
|
|
||||||
<a href="${os.url_carry ('bibrec', format='rdf')}"
|
<a href="${os.url_carry ('bibrec', format='rdf')}"
|
||||||
title="Download RDF/XML Metadata for this ebook."><img
|
title="Download RDF/XML Metadata for this ebook."><img
|
||||||
src="http://www.w3.org/RDF/icons/rdf_metadata_button.32"
|
src="http://www.w3.org/RDF/icons/rdf_metadata_button.32"
|
||||||
|
@ -389,11 +374,9 @@ Gutenberg metadata much faster than by scraping.
|
||||||
alt="RDF/XML Metadata" /></a>
|
alt="RDF/XML Metadata" /></a>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
${site_footer ()}
|
${site_footer()}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
${site_top ()}
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -7,16 +7,24 @@
|
||||||
xmlns:og="http://opengraphprotocol.org/schema/"
|
xmlns:og="http://opengraphprotocol.org/schema/"
|
||||||
xmlns:fb="http://www.facebook.com/2008/fbml"
|
xmlns:fb="http://www.facebook.com/2008/fbml"
|
||||||
py:strip="">
|
py:strip="">
|
||||||
|
<xi:include href="site-layout.html" />
|
||||||
|
<xi:include href="social-functions.html" />
|
||||||
|
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
.icon { background: transparent url(/pics/sprite.png?${cherrypy.config['css_mtime']}) 0 0 no-repeat; }
|
.icon { background: transparent url(/pics/sprite.png?${cherrypy.config['css_mtime']}) 0 0 no-repeat; }
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" type="text/css"
|
<link rel="stylesheet" type="text/css"
|
||||||
href="/css/pg-desktop-one.css?${cherrypy.config['css_mtime']}" />
|
href="/gutenberg/pg-desktop-one.css?${cherrypy.config['css_mtime']}" />
|
||||||
|
<link rel="stylesheet" type="text/css"
|
||||||
|
href="/gutenberg/new_nav.css?${cherrypy.config['css_mtime']}"/>
|
||||||
|
<link rel="stylesheet" type="text/css"
|
||||||
|
href="/gutenberg/style.css?${cherrypy.config['css_mtime']}"/>
|
||||||
|
|
||||||
<script type="text/javascript">//<![CDATA[
|
<script type="text/javascript">//<![CDATA[
|
||||||
//<![CDATA[
|
//<![CDATA[
|
||||||
var json_search = "/ebooks/suggest/";
|
var json_search = "/ebooks/suggest/";
|
||||||
var mobile_url = "//m.gutenberg.org/ebooks.mobile/";
|
|
||||||
var canonical_url = "https://www.gutenberg.org/ebooks/";
|
var canonical_url = "https://www.gutenberg.org/ebooks/";
|
||||||
var lang = "en";
|
var lang = "en";
|
||||||
var fb_lang = "en_US"; /* FB accepts only xx_XX */
|
var fb_lang = "en_US"; /* FB accepts only xx_XX */
|
||||||
|
@ -27,7 +35,7 @@
|
||||||
//]]></script>
|
//]]></script>
|
||||||
<script type="text/javascript"
|
<script type="text/javascript"
|
||||||
src="/js/pg-desktop-one.js?${cherrypy.config['js_mtime']}" />
|
src="/js/pg-desktop-one.js?${cherrypy.config['js_mtime']}" />
|
||||||
<link rel="shortcut icon" href="/pics/favicon" />
|
<link rel="shortcut icon" href="/gutenberg/favicon" />
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<meta http-equiv="Content-Style-Type" content="text/css" />
|
<meta http-equiv="Content-Style-Type" content="text/css" />
|
||||||
|
|
||||||
|
@ -36,99 +44,22 @@
|
||||||
<title>${os.message}</title>
|
<title>${os.message}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="mw-head-dummy" class="noprint" />
|
<div class="container">
|
||||||
|
${site_top()}
|
||||||
|
<div id="page_content" i18n:comment="error page." style="margin-top: 4em">
|
||||||
|
|
||||||
<div id="content" i18n:comment="On the page of results of a search.">
|
|
||||||
<div class="header">
|
|
||||||
<h1>${os.message}</h1>
|
<h1>${os.message}</h1>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="body">
|
|
||||||
|
<div class="page-body">
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="fb-root" />
|
|
||||||
|
|
||||||
<div id="print-head" class="noscreen">
|
|
||||||
<div class="center">Project Gutenberg offers thousands of free ebooks to download.</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="screen-head" class="noprint">
|
|
||||||
<table>
|
|
||||||
<tr i18n:comment="The logo, tagline and badges at the very top of every page.">
|
|
||||||
|
|
||||||
<td rowspan="2" id="logo" i18n:comment="The PG logo at the top left of every page.">
|
|
||||||
<a href="/wiki/Main_Page" title="Go to the Main Page.">
|
|
||||||
<span class="icon icon_logo" />
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td id="tagline-badges" colspan="2">
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td id="tagline">Project Gutenberg offers thousands of free ebooks to download.</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr id="menubar-search">
|
|
||||||
<td id="menubar" i18n:comment="The menu bar at the top of every page.">
|
|
||||||
<a id="menubar-first"
|
|
||||||
tabindex="11" accesskey="1"
|
|
||||||
title="Start a new search."
|
|
||||||
href="/ebooks/">Search</a>
|
|
||||||
|
|
||||||
<a tabindex="22"
|
|
||||||
title="Our latest releases."
|
|
||||||
href="/ebooks/search/?sort_order=release_date">Latest</a>
|
|
||||||
|
|
||||||
<a tabindex="31"
|
|
||||||
title="Read the Project Gutenberg terms of use."
|
|
||||||
href="/terms_of_use/">Terms of Use</a>
|
|
||||||
|
|
||||||
<a tabindex="32"
|
|
||||||
href="/wiki/Gutenberg:Project_Gutenberg_Needs_Your_Donation"
|
|
||||||
title="Learn why we need some money.">Donate?</a>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td id="search" i18n:comment="The search box at the top right of every page.">
|
|
||||||
<form method="get" action="/ebooks/search/"
|
|
||||||
enctype="multipart/form-data">
|
|
||||||
<table class="borderless">
|
|
||||||
<tr>
|
|
||||||
<td id="search-button-cell">
|
|
||||||
<button id="search-button" type="submit" title="Execute the search. <enter>">
|
|
||||||
<span class="icon icon_smsearch" />
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
<td id="search-input-cell">
|
|
||||||
<input id="search-input" name="query" type="text" title="Search Project Gutenberg. <s>"
|
|
||||||
accesskey="s" value="" />
|
|
||||||
</td>
|
|
||||||
<td id="help-button-cell">
|
|
||||||
<button id="help-button" type="button" title="Open the help menu. <h>"
|
|
||||||
accesskey="h">Help</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div id="helpbox" class="hide">
|
|
||||||
<xi:include href="help.html" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -66,7 +66,7 @@ which contains *all* Project Gutenberg metadata in one RDF/XML file.
|
||||||
<body>
|
<body>
|
||||||
<div id="mw-head-dummy" class="noprint" />
|
<div id="mw-head-dummy" class="noprint" />
|
||||||
|
|
||||||
<div id="content" i18n:comment="On the page of results of a search.">
|
<div id="content" class="page_content" i18n:comment="On the page of results of a search.">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1><span class="icon icon_${os.title_icon}" />${os.title}</h1>
|
<h1><span class="icon icon_${os.title_icon}" />${os.title}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,151 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
|
|
||||||
DON'T USE THIS PAGE FOR SCRAPING.
|
|
||||||
|
|
||||||
Seriously. You'll only get your IP blocked.
|
|
||||||
|
|
||||||
Download https://www.gutenberg.org/feeds/catalog.rdf.bz2 instead,
|
|
||||||
which contains *all* Project Gutenberg metadata in one RDF/XML file.
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
|
||||||
xmlns:py="http://genshi.edgewall.org/"
|
|
||||||
xmlns:i18n="http://genshi.edgewall.org/i18n"
|
|
||||||
xml:lang="${os.lang}">
|
|
||||||
|
|
||||||
<?python
|
|
||||||
import re
|
|
||||||
|
|
||||||
from libgutenberg import GutenbergGlobals as gg
|
|
||||||
old_header = ''
|
|
||||||
|
|
||||||
def help_page (s = ''):
|
|
||||||
s = s.replace (' ', '_')
|
|
||||||
return '%s#%s' % ('/wiki/Gutenberg:Help_on_Bibliographic_Record_Page', s)
|
|
||||||
?>
|
|
||||||
|
|
||||||
<xi:include href="site-layout.mobile" />
|
|
||||||
|
|
||||||
<head profile="http://a9.com/-/spec/opensearch/1.1/">
|
|
||||||
${site_head ()}
|
|
||||||
|
|
||||||
<title>${os.title}</title>
|
|
||||||
|
|
||||||
<meta name="totalResults" content="${os.total_results}" />
|
|
||||||
<meta name="startIndex" content="${os.start_index}" />
|
|
||||||
<meta name="itemsPerPage" content="${os.items_per_page}" />
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="content" i18n:comment="On the page of results of a search.">
|
|
||||||
<ol class="results">
|
|
||||||
|
|
||||||
${search_box ()}
|
|
||||||
|
|
||||||
<py:for each="n, e in enumerate (os.entries)">
|
|
||||||
<py:if test="e.header and old_header != e.header">
|
|
||||||
<li class="header">${e.header}</li>
|
|
||||||
</py:if>
|
|
||||||
<?python old_header = e.header ?>
|
|
||||||
|
|
||||||
<py:if test="isinstance (e, bs.DC)">
|
|
||||||
<li class="bibrec">
|
|
||||||
<div class="table">
|
|
||||||
<div class="row">
|
|
||||||
<div class="cell leftcell">
|
|
||||||
<div class="icon icon_${e.icon}" />
|
|
||||||
</div>
|
|
||||||
<div class="cell content">
|
|
||||||
<!--! get coverpage first, it floats to the right -->
|
|
||||||
<img py:if="e.cover_image" class="coverpage"
|
|
||||||
src="${e.cover_image.url}" alt="[Coverpage]" />
|
|
||||||
<p py:for="author in e.authors">${author.role}: ${author.name_and_dates}</p>
|
|
||||||
<py:for each="marc in e.marcs">
|
|
||||||
<py:choose test="">
|
|
||||||
<p py:when="marc.code[0]=='5'">
|
|
||||||
<?python
|
|
||||||
text = gg.xmlspecialchars (marc.text)
|
|
||||||
text = re.sub (r'(//\S+)', r'<a href="\1">\1</a>', text)
|
|
||||||
text = re.sub (r'#(\d+)',
|
|
||||||
r'<a href="/ebooks/\1.mobile">#\1</a>', text)
|
|
||||||
?>
|
|
||||||
${marc.caption}:
|
|
||||||
${ Markup (gg.insert_breaks (text)) }
|
|
||||||
</p>
|
|
||||||
<p py:otherwise="">
|
|
||||||
${marc.caption}:
|
|
||||||
${ Markup (gg.insert_breaks (gg.xmlspecialchars (marc.text))) }
|
|
||||||
</p>
|
|
||||||
</py:choose>
|
|
||||||
</py:for>
|
|
||||||
<p>Ebook No.: ${e.project_gutenberg_id}</p>
|
|
||||||
<p>Published: ${e.hr_release_date}</p>
|
|
||||||
<p>Downloads: ${e.downloads}</p>
|
|
||||||
<p py:for="language in e.languages">Language: ${language.language}</p>
|
|
||||||
<p py:for="subject in e.subjects">Subject: ${subject.subject}</p>
|
|
||||||
<p py:for="locc in e.loccs">LoCC: ${locc.locc}</p>
|
|
||||||
<p py:for="category in e.categories">Category: ${category}</p>
|
|
||||||
<p>Rights: ${e.rights}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</py:if>
|
|
||||||
|
|
||||||
<py:if test="isinstance (e, bs.Cat)">
|
|
||||||
<py:choose test="">
|
|
||||||
<py:when test="e.rel == '__statusline__'" />
|
|
||||||
|
|
||||||
<py:otherwise>
|
|
||||||
<li class="${e.class_}">
|
|
||||||
<a class="table link" href="${e.url}" accesskey="${str (n % 10)}">
|
|
||||||
<span class="row">
|
|
||||||
<span class="cell leftcell">
|
|
||||||
<span class="icon icon_${e.icon}" />
|
|
||||||
</span>
|
|
||||||
<span class="cell content">
|
|
||||||
<span py:if="e.title" class="title">${e.title}</span>
|
|
||||||
<span py:if="e.subtitle" class="subtitle">${e.subtitle}</span>
|
|
||||||
<span py:if="e.extra" class="extra">${e.extra}</span>
|
|
||||||
</span>
|
|
||||||
<span py:if="e.icon2" class="cell rightcell">
|
|
||||||
<span class="icon icon_${e.icon2}" />
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</py:otherwise>
|
|
||||||
</py:choose>
|
|
||||||
</py:if>
|
|
||||||
</py:for>
|
|
||||||
|
|
||||||
<py:if test="os.show_next_page_link">
|
|
||||||
<li class="navlink more grayed">
|
|
||||||
<a class="table link"
|
|
||||||
href="${os.url_carry (start_index = os.next_page_index)}">
|
|
||||||
<span class="row">
|
|
||||||
<span class="cell leftcell">
|
|
||||||
<span class="icon icon_more" />
|
|
||||||
</span>
|
|
||||||
<span class="cell content">
|
|
||||||
<span class="title"><span>Next Page</span>…</span>
|
|
||||||
</span>
|
|
||||||
<span class="cell rightcell">
|
|
||||||
<span class="icon spinner" />
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</py:if>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${site_footer ()}
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -16,12 +16,15 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css"
|
<link rel="stylesheet" type="text/css"
|
||||||
href="/css/pg-desktop-one.css?${cherrypy.config['css_mtime']}" />
|
href="/gutenberg/pg-desktop-one.css?${cherrypy.config['css_mtime']}" />
|
||||||
|
<link rel="stylesheet" type="text/css"
|
||||||
|
href="/gutenberg/new_nav.css?${cherrypy.config['css_mtime']}"/>
|
||||||
|
<link rel="stylesheet" type="text/css"
|
||||||
|
href="/gutenberg/style.css?${cherrypy.config['css_mtime']}"/>
|
||||||
|
|
||||||
<!--! IE8 does not recognize application/javascript -->
|
<!--! IE8 does not recognize application/javascript -->
|
||||||
<script>//<![CDATA[
|
<script>//<![CDATA[
|
||||||
var json_search = "${os.json_search}";
|
var json_search = "${os.json_search}";
|
||||||
var mobile_url = "${os.mobile_url}";
|
|
||||||
var canonical_url = "${os.canonical_url}";
|
var canonical_url = "${os.canonical_url}";
|
||||||
var lang = "${os.lang}";
|
var lang = "${os.lang}";
|
||||||
var fb_lang = "${os.fb_lang}"; /* FB accepts only xx_XX */
|
var fb_lang = "${os.fb_lang}"; /* FB accepts only xx_XX */
|
||||||
|
@ -34,7 +37,7 @@
|
||||||
<script
|
<script
|
||||||
src="/js/pg-desktop-one.js?${cherrypy.config['js_mtime']}" />
|
src="/js/pg-desktop-one.js?${cherrypy.config['js_mtime']}" />
|
||||||
|
|
||||||
<link rel="shortcut icon" href="/pics/favicon" />
|
<link rel="shortcut icon" href="/gutenberg/favicon" />
|
||||||
<link rel="canonical" href="${os.canonical_url}" />
|
<link rel="canonical" href="${os.canonical_url}" />
|
||||||
|
|
||||||
<link rel="search"
|
<link rel="search"
|
||||||
|
@ -110,99 +113,12 @@
|
||||||
|
|
||||||
<py:def function="copyright">
|
<py:def function="copyright">
|
||||||
<div class="copyright" i18n:comment="The copyright notice on the footer of every page.">
|
<div class="copyright" i18n:comment="The copyright notice on the footer of every page.">
|
||||||
© 2003–2019 Project Gutenberg Literary Archive Foundation — All Rights Reserved.
|
© 2020 Project Gutenberg Literary Archive Foundation — All Rights Reserved.
|
||||||
</div>
|
</div>
|
||||||
</py:def>
|
</py:def>
|
||||||
|
|
||||||
<py:def function="site_top">
|
<py:def function="site_top">
|
||||||
<div id="fb-root" />
|
<xi:include href="../../menu.html" />
|
||||||
|
|
||||||
<div id="print-head" class="noscreen">
|
|
||||||
<div class="center">${os.desktop_url}<br/><br/>${os.tagline}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="screen-head" class="noprint">
|
|
||||||
<table>
|
|
||||||
<tr i18n:comment="The logo, tagline and badges at the very top of every page.">
|
|
||||||
|
|
||||||
<td rowspan="2" id="logo" i18n:comment="The PG logo at the top left of every page.">
|
|
||||||
<a href="/wiki/Main_Page" title="Go to the Main Page.">
|
|
||||||
<span class="icon icon_logo" />
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td id="tagline-badges" colspan="2">
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td id="tagline">${os.tagline}</td>
|
|
||||||
<td id="paypal-badge" class="badge">${paypal ()}</td>
|
|
||||||
<td id="flattr-badge" class="badge">${flattr ()}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr id="menubar-search">
|
|
||||||
<td id="menubar" i18n:comment="The menu bar at the top of every page.">
|
|
||||||
<a py:if="os.page != 'start'"
|
|
||||||
id="menubar-first"
|
|
||||||
tabindex="11" accesskey="1"
|
|
||||||
title="Start a new search."
|
|
||||||
href="${os.url ('start')}">Search</a>
|
|
||||||
<span py:if="os.page == 'start'"
|
|
||||||
id="menubar-first" class="grayed">Search</span>
|
|
||||||
|
|
||||||
<a tabindex="22"
|
|
||||||
title="Our latest releases."
|
|
||||||
href="/ebooks/search/?sort_order=release_date">Latest</a>
|
|
||||||
|
|
||||||
<a tabindex="31"
|
|
||||||
title="Read the Project Gutenberg terms of use."
|
|
||||||
href="/terms_of_use/">Terms of Use</a>
|
|
||||||
|
|
||||||
<a tabindex="32"
|
|
||||||
href="/wiki/Gutenberg:Project_Gutenberg_Needs_Your_Donation"
|
|
||||||
title="Learn why we need some money.">Donate?</a>
|
|
||||||
|
|
||||||
<a tabindex="33" accesskey="m" href="${os.mobile_url}"
|
|
||||||
title="Go to our mobile site.">Mobile</a>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td id="search" i18n:comment="The search box at the top right of every page.">
|
|
||||||
<form method="get" action="${os.desktop_search}"
|
|
||||||
enctype="multipart/form-data">
|
|
||||||
<table class="borderless">
|
|
||||||
<tr>
|
|
||||||
<td id="search-button-cell">
|
|
||||||
<button id="search-button" type="submit" title="Execute the search. <enter>">
|
|
||||||
<span class="icon icon_smsearch" />
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
<td id="search-input-cell">
|
|
||||||
<input id="search-input" name="query" type="text" title="${os.placeholder} <s>"
|
|
||||||
accesskey="s" value="${os.search_terms}" />
|
|
||||||
</td>
|
|
||||||
<td id="help-button-cell">
|
|
||||||
<button id="help-button" type="button" title="Open the help menu. <h>"
|
|
||||||
accesskey="h">Help</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<div id="helpbox" class="hide">
|
|
||||||
<xi:include href="help.html" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</py:def>
|
</py:def>
|
||||||
|
|
||||||
<py:def function="site_footer">
|
<py:def function="site_footer">
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
|
||||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
|
||||||
xmlns:py="http://genshi.edgewall.org/"
|
|
||||||
xmlns:i18n="http://genshi.edgewall.org/i18n"
|
|
||||||
py:strip="">
|
|
||||||
<?python
|
|
||||||
from i18n_tool import ugettext as _
|
|
||||||
?>
|
|
||||||
|
|
||||||
<py:def function="site_head">
|
|
||||||
<style >
|
|
||||||
.icon { background: transparent url(/pics/sprite.png?${cherrypy.config['css_mtime']}) 0 0 no-repeat; }
|
|
||||||
</style>
|
|
||||||
<link rel="stylesheet" type="text/css"
|
|
||||||
href="/css/pg-mobile-one.css?${cherrypy.config['css_mtime']}" />
|
|
||||||
|
|
||||||
<script type="application/javascript"><![CDATA[
|
|
||||||
var mobile_search = "${os.add_amp (os.mobile_search)}query=";
|
|
||||||
var json_search = "${os.json_search}";
|
|
||||||
var msg_load_more = "${_('Load More Results…')}";
|
|
||||||
var do_animations = ${'true' if os.do_animations else 'false'};
|
|
||||||
]]>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="application/javascript"
|
|
||||||
src="/js/pg-mobile-one.js?${cherrypy.config['js_mtime']}" />
|
|
||||||
|
|
||||||
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
|
|
||||||
<meta http-equiv="Content-Style-Type" content="text/css" />
|
|
||||||
<meta http-equiv="Content-Language" content="${os.lang}" />
|
|
||||||
|
|
||||||
<meta name="description" content="The Project Gutenberg ebook catalog for mobile devices." />
|
|
||||||
<meta name="keywords" content="free ebooks, free books, free audio books" />
|
|
||||||
<meta name="classification" content="public" />
|
|
||||||
|
|
||||||
<link rel="icon" href="/pics/favicon" />
|
|
||||||
|
|
||||||
<link rel="canonical" href="${os.canonical_url}" />
|
|
||||||
|
|
||||||
<link rel="search"
|
|
||||||
type="application/opensearchdescription+xml"
|
|
||||||
title="Search Project Gutenberg"
|
|
||||||
href="${os.osd_url}" />
|
|
||||||
|
|
||||||
<link rel="alternate nofollow"
|
|
||||||
type="${os.type_opds}"
|
|
||||||
title="OPDS feed"
|
|
||||||
href="${os.url_carry (format = 'opds')}" />
|
|
||||||
|
|
||||||
<link py:if="os.touch_icon" rel="apple-touch-icon" href="${os.touch_icon}" />
|
|
||||||
<link py:if="os.touch_icon_precomposed" rel="apple-touch-icon-precomposed" href="${os.touch_icon_precomposed}" />
|
|
||||||
<meta py:if="os.viewport" name="viewport" content="${os.viewport}" />
|
|
||||||
</py:def>
|
|
||||||
|
|
||||||
<py:def function="search_box">
|
|
||||||
<li class="grayed" id="searchlist">
|
|
||||||
<div class="table link">
|
|
||||||
<div class="row">
|
|
||||||
<div class="cell leftcell">
|
|
||||||
<div class="icon icon_search" />
|
|
||||||
</div>
|
|
||||||
<div class="cell content">
|
|
||||||
<form id="search" method="get" action="${os.mobile_search}"
|
|
||||||
enctype="multipart/form-data">
|
|
||||||
<div id="query-clear-wrapper">
|
|
||||||
<div id="query-wrapper">
|
|
||||||
<input id="query" name="query"
|
|
||||||
type="text"
|
|
||||||
inputmode="latin"
|
|
||||||
value="${os.search_terms}"
|
|
||||||
title="${os.placeholder}" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<!--! <div class="cell cancelcell">
|
|
||||||
<button type="reset" id="clear" class="icon icon_cancel"
|
|
||||||
title="Clear" i18n:comment="Reset Form Button" />
|
|
||||||
</div> -->
|
|
||||||
<div class="cell rightcell">
|
|
||||||
<button type="button" id="help"
|
|
||||||
title="Help" onclick="toggle_help ()" i18n:comment="Help about search button">
|
|
||||||
<div class="icon icon_help" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li class="grayed" id="helpbox"
|
|
||||||
style="display: none" onclick="clear_help ()">
|
|
||||||
<div class="helpbox">
|
|
||||||
<xi:include href="help.html" />
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<py:if test="os.page != 'start' and os.start_index == 1">
|
|
||||||
<li class="navlink grayed">
|
|
||||||
<a class="table link" href="${os.url ('start')}" accesskey="h">
|
|
||||||
<span class="row">
|
|
||||||
<span class="cell leftcell">
|
|
||||||
<span class="icon icon_internal" />
|
|
||||||
</span>
|
|
||||||
<span class="cell content">
|
|
||||||
<span class="title">Search Start Page</span>
|
|
||||||
</span>
|
|
||||||
<span class="cell rightcell">
|
|
||||||
<span class="icon icon_next" />
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</py:if>
|
|
||||||
</py:def>
|
|
||||||
|
|
||||||
<py:def function="site_footer">
|
|
||||||
<div class="footer">
|
|
||||||
<div class="copyright">
|
|
||||||
© 2003–2012 Project Gutenberg Literary Archive Foundation — All Rights Reserved.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</py:def>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -10,48 +10,40 @@
|
||||||
<?python
|
<?python
|
||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
|
|
||||||
def p (params):
|
def p(params):
|
||||||
return urllib.parse.urlencode (params).replace ('+', '%20')
|
return urllib.parse.urlencode(params).replace('+', '%20')
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|
||||||
<py:def function="fb_share(url, title, description, picture)">
|
<py:def function="fb_share(url)">
|
||||||
<?python
|
<?python
|
||||||
params = {
|
params = {
|
||||||
'link': url,
|
'u': url,
|
||||||
'app_id': cherrypy.config['facebook_app_id'],
|
|
||||||
'name': title,
|
|
||||||
'description': description,
|
|
||||||
'redirect_uri': 'https://www.gutenberg.org/fb_redirect.html',
|
|
||||||
}
|
}
|
||||||
if picture is not None:
|
|
||||||
params['picture'] = picture
|
|
||||||
?>
|
?>
|
||||||
<div class="social-button fb-share-button" i18n:comment="Share on Facebook.">
|
<div class="social-button fb-share-button">
|
||||||
<a href="https://www.facebook.com/dialog/feed?${p (params)}"
|
<a href="https://www.facebook.com/sharer.php?${p(params)}"
|
||||||
title="Share on Facebook"
|
title="Share on Facebook"
|
||||||
onclick="open_share_popup(this.href, this.target, 1024, 560)" target="_fb_share_popup">
|
onclick="open_share_popup(this.href, this.target, 640, 320)"
|
||||||
|
target="_top">
|
||||||
<span class="icon icon_facebook" />
|
<span class="icon icon_facebook" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</py:def>
|
</py:def>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<py:def function="tw_share(url, text)">
|
<py:def function="tw_share(url, text)">
|
||||||
<!-- tweet without javascript -->
|
<!-- tweet without javascript -->
|
||||||
<?python
|
<?python
|
||||||
params = {
|
params = {
|
||||||
'url': url,
|
'url': url,
|
||||||
'text': text.encode ('utf-8'),
|
'text': text.encode('utf-8'),
|
||||||
'count': 'none',
|
'count': 'none',
|
||||||
'lang': os.twitter_lang,
|
'lang': os.twitter_lang,
|
||||||
'related': "gutenberg_new:Project Gutenberg New Books"
|
'related': "gutenberg_new:Project Gutenberg New Books"
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<div class="social-button twitter-share-button">
|
<div class="social-button twitter-share-button">
|
||||||
<!--! https://dev.twitter.com/docs/tweet-button -->
|
<a href="https://twitter.com/share?${p(params)}"
|
||||||
<a href="https://twitter.com/share?${p (params)}"
|
|
||||||
title="Share on Twitter"
|
title="Share on Twitter"
|
||||||
onclick="open_share_popup(this.href, this.target, 640, 320)"
|
onclick="open_share_popup(this.href, this.target, 640, 320)"
|
||||||
target="_top">
|
target="_top">
|
||||||
|
|
Loading…
Reference in New Issue