Merge pull request #57 from gutenbergtools/gutenberg1

Gutenberg1
gutenberg1
Eric Hellman 2020-09-04 13:44:38 -04:00 committed by GitHub
commit c4c329b600
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 497 additions and 1105 deletions

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -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 ('"', '&quot;') title = gg.xmlspecialchars (row.title) # handles <,>,&
#Shortening long titles for latest covers
title = title.replace('"', '&quot;')
title = title.replace("'", '&apos;')
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.')

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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="content" i18n:comment="On the page of results of a search."> <div id="page_content" i18n:comment="error page." style="margin-top: 4em">
<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. &lt;enter&gt;">
<span class="icon icon_smsearch" />
</button>
</td>
<td id="search-input-cell">
<input id="search-input" name="query" type="text" title="Search Project Gutenberg. &lt;s&gt;"
accesskey="s" value="" />
</td>
<td id="help-button-cell">
<button id="help-button" type="button" title="Open the help menu. &lt;h&gt;"
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>

View File

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

View File

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

View File

@ -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.">
© 20032019 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. &lt;enter&gt;">
<span class="icon icon_smsearch" />
</button>
</td>
<td id="search-input-cell">
<input id="search-input" name="query" type="text" title="${os.placeholder} &lt;s&gt;"
accesskey="s" value="${os.search_terms}" />
</td>
<td id="help-button-cell">
<button id="help-button" type="button" title="Open the help menu. &lt;h&gt;"
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">

View File

@ -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">
© 20032012 Project Gutenberg Literary Archive Foundation — All Rights Reserved.
</div>
</div>
</py:def>
</html>

View File

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