From 262e86c6255d78055c400723d2880f7e38c5fdf5 Mon Sep 17 00:00:00 2001 From: Alex Cabal Date: Sun, 11 Oct 2020 13:39:32 -0500 Subject: [PATCH] Enable reading from the ToC and single-page reading --- README.md | 2 +- config/apache/standardebooks.org.conf | 26 +++++++++--- config/apache/standardebooks.test.conf | 26 +++++++++--- lib/Ebook.php | 37 +++++++++------- scripts/deploy-ebook-to-www | 35 ++++++++++++++-- templates/OpdsAcquisitionEntry.php | 4 +- .../a-basic-standard-ebooks-source-folder.php | 3 -- www/css/core.css | 8 ++++ www/css/web.css | 42 +++++++++++++++++++ www/ebooks/ebook.php | 14 ++++++- www/images/list.svg | 32 ++++++++++++++ www/images/page.svg | 32 ++++++++++++++ 12 files changed, 226 insertions(+), 35 deletions(-) create mode 100644 www/css/web.css create mode 100644 www/images/list.svg create mode 100644 www/images/page.svg diff --git a/README.md b/README.md index 325ff70c..af12fee5 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ If everything went well, `https://standardebooks.test/ebooks/` will show the one /standardebooks.org/web/www/ebooks/maurice-leblanc/813/alexander-teixeira-de-mattos/ ```` - These directories contain the full ebook source, as if it was pulled from Git. (But they are not actual Git repositories.) Additionally each one contains a `./dist/` folder containing built ebook files for distribution. + These directories contain the full ebook source, as if it was pulled from Git. (But they are not actual Git repositories.) Additionally each one contains a `./downloads/` folder containing built ebook files for distribution. The website pulls all ebook information from what is contained in `/standardebooks.org/web/www/ebooks/`. It does not inspect `/standardebooks.org/ebooks/`. Therefore it is possible for one or the other to hold different catalogs if they become out of sync. diff --git a/config/apache/standardebooks.org.conf b/config/apache/standardebooks.org.conf index 61aa8120..d384779b 100644 --- a/config/apache/standardebooks.org.conf +++ b/config/apache/standardebooks.org.conf @@ -92,10 +92,10 @@ Define domain standardebooks.org AddType application/epub+zip .epub AddType application/x-mobi8-ebook .azw3 - + # Serve distributables using the "download" dialog instead of opening in-browser # Note: the trailing e in the Header directive is required - SetEnvIf Request_URI ^/ebooks/.+?/dist/(.+)$ FILENAME=$1 + SetEnvIf Request_URI ^/ebooks/.+?/downloads/(.+)$ FILENAME=$1 Header set "Content-Disposition" "attachment; filename=%{FILENAME}e" @@ -115,6 +115,11 @@ Define domain standardebooks.org Header set Access-Control-Allow-Origin "*" + # We use a different CSP policy for single-page files because our default one doesn't allow inline images or CSS + + Header set Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';" + + # Remove www from requests RewriteCond %{HTTP_HOST} ^www\.(.+) [NC] RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L] @@ -159,6 +164,17 @@ Define domain standardebooks.org # Remove trailing slashes RewriteRule ^/(.+?)/$ /$1 [R=301,L] + # Redirect ToC of XHTML representation of books + RewriteRule ^/ebooks/(.+?)/text$ /ebooks/$1/src/epub/toc.xhtml [L] + + # Redirect XHTML representation of books + # This has to appear before the next check, so that we can exclude .xhtml endings + RewriteRule ^/ebooks/(.+?)/(text|css|images|fonts)(.*) /ebooks/$1/src/epub/$2$3 + + # Received: /filename and /filename.xhtml exists in filesystem; Result: rewrite to /filename.xhtml + RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xhtml -f + RewriteRule (.*) $1.xhtml + # Redirect index pages RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.php -f @@ -188,8 +204,8 @@ Define domain standardebooks.org RewriteRule ^/alices-adventures-in-wonderland.+$ /ebooks/lewis-carroll/alices-adventures-in-wonderland/$1 [R=301,L] RewriteRule ^/ebooks/philip-k-dick/short-stories(.+)$ /ebooks/philip-k-dick/short-fiction$1 [R=301,L] RewriteRule ^/ebooks/benjamin-disraeli/sibyl(.+)$ /ebooks/benjamin-disraeli/sybil$1 [R=301,L] - RewriteRule ^/ebooks/lewis-carroll/alices-adventures-in-wonderland/dist/(.+)$ /ebooks/lewis-carroll/alices-adventures-in-wonderland/john-tenniel/dist/$1 [R=301,L] - RewriteRule ^/ebooks/lewis-carroll/through-the-looking-glass/dist/(.+)$ /ebooks/lewis-carroll/through-the-looking-glass/john-tenniel/dist/$1 [R=301,L] + RewriteRule ^/ebooks/lewis-carroll/alices-adventures-in-wonderland/downloads/(.+)$ /ebooks/lewis-carroll/alices-adventures-in-wonderland/john-tenniel/downloads/$1 [R=301,L] + RewriteRule ^/ebooks/lewis-carroll/through-the-looking-glass/downloads/(.+)$ /ebooks/lewis-carroll/through-the-looking-glass/john-tenniel/downloads/$1 [R=301,L] RewriteRule ^/ebooks/nikolai-gogol/short-fiction/claud-field_isabel-f-hapgood_vizetelly-and-company$ /ebooks/nikolai-gogol/short-fiction/claud-field_isabel-f-hapgood_vizetelly-and-company_george-tolstoy [R=301,L] RewriteRule ^/ebooks/nikolai-gogol/short-fiction/claud-field_isabel-f-hapgood_vizetelly-and-company/(.+?)$ /ebooks/nikolai-gogol/short-fiction/claud-field_isabel-f-hapgood_vizetelly-and-company_george-tolstoy/$1 [R=301,L] RewriteRule ^/ebooks/h-g-wells/tales-of-space-and-time(.+)$ /ebooks/h-g-wells/short-fiction$1 [R=301,L] @@ -211,7 +227,7 @@ Define domain standardebooks.org RewriteRule ^/collections/([^\./]+?)$ /ebooks/index.php?collection=$1 [QSA] # Prevent this rule from firing if we're getting a distribution file - RewriteCond %{REQUEST_FILENAME} !^/ebooks/.+?/dist/.+$ + RewriteCond %{REQUEST_FILENAME} !^/ebooks/.+?/downloads/.+$ RewriteCond %{REQUEST_FILENAME} !^/ebooks/.+?/src/.+$ RewriteRule ^/ebooks/([^\.]+?)$ /ebooks/ebook.php?url-path=$1 diff --git a/config/apache/standardebooks.test.conf b/config/apache/standardebooks.test.conf index 7addc3ba..6dbd2692 100644 --- a/config/apache/standardebooks.test.conf +++ b/config/apache/standardebooks.test.conf @@ -91,10 +91,10 @@ Define domain standardebooks.test AddType application/epub+zip .epub AddType application/x-mobi8-ebook .azw3 - + # Serve distributables using the "download" dialog instead of opening in-browser # Note: the trailing e in the Header directive is required - SetEnvIf Request_URI ^/ebooks/.+?/dist/(.+)$ FILENAME=$1 + SetEnvIf Request_URI ^/ebooks/.+?/downloads/(.+)$ FILENAME=$1 Header set "Content-Disposition" "attachment; filename=%{FILENAME}e" @@ -114,6 +114,11 @@ Define domain standardebooks.test Header set Access-Control-Allow-Origin "*" + # We use a different CSP policy for single-page files because our default one doesn't allow inline images or CSS + + Header set Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';" + + # Remove www from requests RewriteCond %{HTTP_HOST} ^www\.(.+) [NC] RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L] @@ -158,6 +163,17 @@ Define domain standardebooks.test # Remove trailing slashes RewriteRule ^/(.+?)/$ /$1 [R=301,L] + # Redirect ToC of XHTML representation of books + RewriteRule ^/ebooks/(.+?)/text$ /ebooks/$1/src/epub/toc.xhtml [L] + + # Redirect XHTML representation of books + # This has to appear before the next check, so that we can exclude .xhtml endings + RewriteRule ^/ebooks/(.+?)/(text|css|images|fonts)(.*) /ebooks/$1/src/epub/$2$3 + + # Received: /filename and /filename.xhtml exists in filesystem; Result: rewrite to /filename.xhtml + RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xhtml -f + RewriteRule (.*) $1.xhtml + # Redirect index pages RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.php -f @@ -187,8 +203,8 @@ Define domain standardebooks.test RewriteRule ^/alices-adventures-in-wonderland.+$ /ebooks/lewis-carroll/alices-adventures-in-wonderland/$1 [R=301,L] RewriteRule ^/ebooks/philip-k-dick/short-stories(.+)$ /ebooks/philip-k-dick/short-fiction$1 [R=301,L] RewriteRule ^/ebooks/benjamin-disraeli/sibyl(.+)$ /ebooks/benjamin-disraeli/sybil$1 [R=301,L] - RewriteRule ^/ebooks/lewis-carroll/alices-adventures-in-wonderland/dist/(.+)$ /ebooks/lewis-carroll/alices-adventures-in-wonderland/john-tenniel/dist/$1 [R=301,L] - RewriteRule ^/ebooks/lewis-carroll/through-the-looking-glass/dist/(.+)$ /ebooks/lewis-carroll/through-the-looking-glass/john-tenniel/dist/$1 [R=301,L] + RewriteRule ^/ebooks/lewis-carroll/alices-adventures-in-wonderland/downloads/(.+)$ /ebooks/lewis-carroll/alices-adventures-in-wonderland/john-tenniel/downloads/$1 [R=301,L] + RewriteRule ^/ebooks/lewis-carroll/through-the-looking-glass/downloads/(.+)$ /ebooks/lewis-carroll/through-the-looking-glass/john-tenniel/downloads/$1 [R=301,L] RewriteRule ^/ebooks/nikolai-gogol/short-fiction/claud-field_isabel-f-hapgood_vizetelly-and-company$ /ebooks/nikolai-gogol/short-fiction/claud-field_isabel-f-hapgood_vizetelly-and-company_george-tolstoy [R=301,L] RewriteRule ^/ebooks/nikolai-gogol/short-fiction/claud-field_isabel-f-hapgood_vizetelly-and-company/(.+?)$ /ebooks/nikolai-gogol/short-fiction/claud-field_isabel-f-hapgood_vizetelly-and-company_george-tolstoy/$1 [R=301,L] RewriteRule ^/ebooks/h-g-wells/tales-of-space-and-time(.+)$ /ebooks/h-g-wells/short-fiction$1 [R=301,L] @@ -210,7 +226,7 @@ Define domain standardebooks.test RewriteRule ^/collections/([^\./]+?)$ /ebooks/index.php?collection=$1 [QSA] # Prevent this rule from firing if we're getting a distribution file - RewriteCond %{REQUEST_FILENAME} !^/ebooks/.+?/dist/.+$ + RewriteCond %{REQUEST_FILENAME} !^/ebooks/.+?/downloads/.+$ RewriteCond %{REQUEST_FILENAME} !^/ebooks/.+?/src/.+$ RewriteRule ^/ebooks/([^\.]+?)$ /ebooks/ebook.php?url-path=$1 diff --git a/lib/Ebook.php b/lib/Ebook.php index 79bb3d4a..fde517e8 100644 --- a/lib/Ebook.php +++ b/lib/Ebook.php @@ -55,6 +55,8 @@ class Ebook{ public $TitleWithCreditsHtml = ''; public $Timestamp; public $ModifiedTimestamp; + public $TextUrl; + public $TextSinglePageUrl; public function __construct(string $wwwFilesystemPath){ // First, construct a source repo path from our WWW filesystem path. @@ -91,41 +93,48 @@ class Ebook{ $this->UrlSafeIdentifier = str_replace(['url:https://standardebooks.org/ebooks/', '/'], ['', '_'], $this->Identifier); - // Generate the Kindle cover URL. - $tempPath = glob($this->WwwFilesystemPath . '/dist/*_EBOK_portrait.jpg'); + $this->TextUrl = $this->Url . '/text'; + + $tempPath = glob($this->WwwFilesystemPath . '/src/epub/text/single-page.xhtml'); if(sizeof($tempPath) > 0){ - $this->KindleCoverUrl = $this->Url . '/dist/' . basename($tempPath[0]); + $this->TextSinglePageUrl = $this->Url . '/text/single-page'; + } + + // Generate the Kindle cover URL. + $tempPath = glob($this->WwwFilesystemPath . '/downloads/*_EBOK_portrait.jpg'); + if(sizeof($tempPath) > 0){ + $this->KindleCoverUrl = $this->Url . '/downloads/' . basename($tempPath[0]); } // Generate the compatible epub URL. - $tempPath = glob($this->WwwFilesystemPath . '/dist/*.epub'); + $tempPath = glob($this->WwwFilesystemPath . '/downloads/*.epub'); if(sizeof($tempPath) > 0){ - $this->EpubUrl = $this->Url . '/dist/' . basename($tempPath[0]); + $this->EpubUrl = $this->Url . '/downloads/' . basename($tempPath[0]); } // Generate the epub URL - $tempPath = glob($this->WwwFilesystemPath . '/dist/*_advanced.epub'); + $tempPath = glob($this->WwwFilesystemPath . '/downloads/*_advanced.epub'); if(sizeof($tempPath) > 0){ - $this->AdvancedEpubUrl = $this->Url . '/dist/' . basename($tempPath[0]); + $this->AdvancedEpubUrl = $this->Url . '/downloads/' . basename($tempPath[0]); } // Generate the Kepub URL - $tempPath = glob($this->WwwFilesystemPath . '/dist/*.kepub.epub'); + $tempPath = glob($this->WwwFilesystemPath . '/downloads/*.kepub.epub'); if(sizeof($tempPath) > 0){ - $this->KepubUrl = $this->Url . '/dist/' . basename($tempPath[0]); + $this->KepubUrl = $this->Url . '/downloads/' . basename($tempPath[0]); } // Generate the azw3 URL. - $tempPath = glob($this->WwwFilesystemPath . '/dist/*.azw3'); + $tempPath = glob($this->WwwFilesystemPath . '/downloads/*.azw3'); if(sizeof($tempPath) > 0){ - $this->Azw3Url = $this->Url . '/dist/' . basename($tempPath[0]); + $this->Azw3Url = $this->Url . '/downloads/' . basename($tempPath[0]); } $this->HasDownloads = $this->EpubUrl || $this->AdvancedEpubUrl || $this->KepubUrl || $this->Azw3Url; - $tempPath = glob($this->WwwFilesystemPath . '/dist/cover.jpg'); + $tempPath = glob($this->WwwFilesystemPath . '/downloads/cover.jpg'); if(sizeof($tempPath) > 0){ - $this->DistCoverUrl = $this->Url . '/dist/' . basename($tempPath[0]); + $this->DistCoverUrl = $this->Url . '/downloads/' . basename($tempPath[0]); } // Fill in the short history of this repo. @@ -455,7 +464,7 @@ class Ebook{ $output->name = $this->Title; $output->image = SITE_URL . $this->DistCoverUrl; - $output->thumbnailUrl = SITE_URL . $this->Url . '/dist/cover-thumbnail.jpg'; + $output->thumbnailUrl = SITE_URL . $this->Url . '/downloads/cover-thumbnail.jpg'; $output->url = SITE_URL . $this->Url; $output->{'@id'} = SITE_URL . $this->Url; $output->description = $this->Description; diff --git a/scripts/deploy-ebook-to-www b/scripts/deploy-ebook-to-www index 03cf17b4..a676ae94 100755 --- a/scripts/deploy-ebook-to-www +++ b/scripts/deploy-ebook-to-www @@ -225,16 +225,16 @@ do git clone --quiet "${repoDir}" "${workDir}" - mkdir "${workDir}/dist" + mkdir -p "${workDir}/downloads" # Build the ebook if [ "${epubcheck}" = "true" ]; then - if ! se build --output-dir="${workDir}/dist" --check --kindle --kobo --covers "${workDir}"; then + if ! se build --output-dir="${workDir}"/downloads/ --check --kindle --kobo --covers "${workDir}"; then rm --preserve-root --recursive --force "${workDir}" die "Error building ebook, stopping deployment." fi else - if ! se build --output-dir="${workDir}/dist" --kindle --kobo --covers "${workDir}"; then + if ! se build --output-dir="${workDir}"/downloads/ --kindle --kobo --covers "${workDir}"; then rm --preserve-root --recursive --force "${workDir}" die "Error building ebook, stopping deployment." fi @@ -255,6 +255,35 @@ do # Re-create the webdir mkdir -p "${webDir}" + # Recompose the epub into a single file, but put it outside of the epub src for now so we don't stomp on it with the following sections. + # We do this first because the tweaks below shouldn't apply to the single-page file + cp "${webRoot}/www/css/web.css" "${workDir}"/src/epub/css/ + se recompose-epub --xhtml --output "${workDir}"/single-page.xhtml "${workDir}" + rm "${workDir}"/src/epub/css/web.css + + # Make some compatibilty adjustments for the individual XHTML files + + # Remove instances of the .xhtml filename extension in the source text + find "${workDir}"/src/epub \( -type d -name .git -prune \) -o -type f -name "*.xhtml" -print0 | xargs -0 sed --in-place 's/\.xhtml//g' + + # Add our web stylesheet to XHTML files + find "${workDir}"/src/epub \( -type d -name .git -prune \) -o -type f -name "*.xhtml" -print0 | xargs -0 sed --in-place --regexp-extended 's||\n\t\t|' + + # Remove -epub-* CSS properties from CSS files as they're invalid in a web context + sed --in-place --regexp-extended "s|\s*\-epub\-[^;]+?;||g" "${workDir}"/src/epub/css/*.css + + # Add lang attributes + find "${workDir}"/src/epub \( -type d -name .git -prune \) -o -type f -name "*.xhtml" -print0 | xargs -0 sed --in-place --regexp-extended 's/xml:lang="([^"]+?)"/xml:lang="\1" lang="\1"/g' + + # Add the work title to tags in the source text + workTitle=$(grep --only-matching --extended-regexp "<dc:title id=\"title\">(.+?)</dc:title>" "${workDir}"/src/epub/content.opf | sed --regexp-extended "s/<[^>]+?>//g") + find "${workDir}"/src/epub \( -type d -name .git -prune \) -o -type f -name "*.xhtml" -print0 | xargs -0 sed --in-place --regexp-extended "s|<title>|<title>${workTitle} - |g" + + # Done adding compatibility! + + # Move the single-page file back into the /src/epub/text/ folder + mv "${workDir}"/single-page.xhtml "${workDir}"/src/epub/text/single-page.xhtml + # Move contents of the work dir over mv "${workDir}"/* "${webDir}/" fi diff --git a/templates/OpdsAcquisitionEntry.php b/templates/OpdsAcquisitionEntry.php index fd0fe0aa..0005e39c 100644 --- a/templates/OpdsAcquisitionEntry.php +++ b/templates/OpdsAcquisitionEntry.php @@ -22,8 +22,8 @@ <? foreach($ebook->LocTags as $subject){ ?> <category scheme="http://purl.org/dc/terms/LCSH" term="<?= htmlspecialchars($subject, ENT_QUOTES|ENT_XML1, 'utf-8') ?>"/> <? } ?> - <link href="<?= $ebook->Url ?>/dist/cover.jpg" rel="http://opds-spec.org/image" type="image/jpeg"/> - <link href="<?= $ebook->Url ?>/dist/cover-thumbnail.jpg" rel="http://opds-spec.org/image/thumbnail" type="image/jpeg"/> + <link href="<?= $ebook->Url ?>/downloads/cover.jpg" rel="http://opds-spec.org/image" type="image/jpeg"/> + <link href="<?= $ebook->Url ?>/downloads/cover-thumbnail.jpg" rel="http://opds-spec.org/image/thumbnail" type="image/jpeg"/> <link href="<?= $ebook->Url ?>" rel="related" type="text/html" title="This ebook’s page at Standard Ebooks"/> <link href="<?= $ebook->EpubUrl ?>" rel="http://opds-spec.org/acquisition/open-access" type="application/epub+zip" title="Recommended compatible epub"/> <link href="<?= $ebook->AdvancedEpubUrl ?>" rel="http://opds-spec.org/acquisition/open-access" type="application/epub+zip" title="epub"/> diff --git a/www/contribute/a-basic-standard-ebooks-source-folder.php b/www/contribute/a-basic-standard-ebooks-source-folder.php index 063e58c8..74f5a55e 100644 --- a/www/contribute/a-basic-standard-ebooks-source-folder.php +++ b/www/contribute/a-basic-standard-ebooks-source-folder.php @@ -10,9 +10,6 @@ require_once('Core.php'); <img alt="A tree view of a new Standard Ebooks draft folder" src="/images/epub-draft-tree.png"/> </figure> <ul> - <li> - <p><code class="path">dist/</code> is where our <code class="program">build</code> script will put the finished ebook files. Right now it’s empty.</p> - </li> <li> <p><code class="path">images/</code> contains the raw image files used in an ebook. For ebooks without illustrations, you’ll have the following three files:</p> <ul> diff --git a/www/css/core.css b/www/css/core.css index 54e2192c..989d9655 100644 --- a/www/css/core.css +++ b/www/css/core.css @@ -889,6 +889,14 @@ time{ background-image: url("/images/distributed-proofreaders.svg"); } +.list::before{ + background-image: url("/images/list.svg"); +} + +.page::before{ + background-image: url("/images/page.svg"); +} + article.ebook h1{ border: none; margin: 0; diff --git a/www/css/web.css b/www/css/web.css new file mode 100644 index 00000000..f5a4dcb0 --- /dev/null +++ b/www/css/web.css @@ -0,0 +1,42 @@ +@namespace epub "http://www.idpf.org/2007/ops"; + +body{ + padding: 0 3em; + margin: 3em auto; + max-width: 60ch; +} + +section + section, +section + article, +article + section, +article + article{ + margin-top: 6em; +} + +nav[epub|type~="toc"] ol{ + list-style: none; +} + +@media(prefers-color-scheme: dark){ + body{ + background: #222222; + color: #ffffff; + } + + /* These three link colors provide WCAG AAA compliance at 16px */ + a:link{ + color: #6bb9f0; + } + + a:active{ + color: #e6cc22; + } + + a:visited{ + color: #dda0dd; + } + + img[epub|type~="se:color-depth.black-on-transparent"]{ + filter: invert(1); + } +} diff --git a/www/ebooks/ebook.php b/www/ebooks/ebook.php index 4543f233..6d736848 100644 --- a/www/ebooks/ebook.php +++ b/www/ebooks/ebook.php @@ -46,7 +46,7 @@ try{ $targetCarouselSize = 5; if(sizeof($ebooks) < $targetCarouselSize){ - $targetCarouselSize = sizeof($ebooks); + $targetCarouselSize = sizeof($ebooks) - 1; } $i = 0; @@ -110,10 +110,11 @@ catch(\Exception $ex){ <? if($ebook->HasDownloads){ ?> <section id="download"> - <h2>Free download</h2> + <h2>Read free</h2> <div class="us-pd-warning"> <p>This ebook is only thought to be free of copyright restrictions in the United States. It may still be under copyright in other countries. If you’re not located in the United States, you must check your local laws to verify that the contents of this ebook are free of copyright restrictions in the country you’re located in before downloading or using this ebook.</p> </div> + <h3>Download for ereaders</h3> <ul> <? if($ebook->EpubUrl !== null){ ?> <li><p><span><a href="<?= $ebook->EpubUrl ?>" class="epub">Compatible epub</a> </span><span>—</span> <span>All devices and apps except Amazon Kindle and Kobo.</span></p> @@ -138,6 +139,13 @@ catch(\Exception $ex){ <aside> <p>Read about <a href="/help/how-to-use-our-ebooks#which-file-to-download">which file to download</a> and <a href="/help/how-to-use-our-ebooks#transferring-to-your-ereader">how to transfer them to your ereader</a>.</p> </aside> + <h3>Read online</h3> + <ul> + <li><p><span><a href="<?= $ebook->TextUrl ?>" class="list">Start from the table of contents</a></span></p></li> + <? if($ebook->TextSinglePageUrl !== null){ ?> + <li><p><span><a href="<?= $ebook->TextSinglePageUrl ?>" class="page">Read on one page</a></span></p></li> + <? } ?> + </ul> </section> <? } ?> @@ -194,6 +202,7 @@ catch(\Exception $ex){ <? if($ebook->GitHubUrl !== null){ ?><p>If you’re comfortable with technology and want to contribute directly, check out <a href="<?= Formatter::ToPlainText($ebook->GitHubUrl) ?>">this ebook’s GitHub repository</a> and our <a href="/contribute">contributors section</a>.</p><? } ?> </section> + <? if(sizeof($carousel) > 0){ ?> <aside id="more-ebooks"> <h2>More free ebooks</h2> <ul> @@ -210,6 +219,7 @@ catch(\Exception $ex){ <? } ?> </ul> </aside> + <? } ?> </article> </main> <?= Template::Footer() ?> diff --git a/www/images/list.svg b/www/images/list.svg new file mode 100644 index 00000000..6b8cec09 --- /dev/null +++ b/www/images/list.svg @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + height="10" + width="10" + id="svg4" + version="1.1" + viewBox="0 0 10 10"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <!-- Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --> + <path + style="stroke-width:0.01953125" + id="path2" + d="M 0.9375,0.9375 A 0.9375,0.9375 0 1 0 1.875,1.875 0.9375,0.9375 0 0 0 0.9375,0.9375 Z m 0,3.125 A 0.9375,0.9375 0 1 0 1.875,5 0.9375,0.9375 0 0 0 0.9375,4.0625 Z m 0,3.125 A 0.9375,0.9375 0 1 0 1.875,8.125 0.9375,0.9375 0 0 0 0.9375,7.1875 Z M 9.6875,7.5 h -6.25 A 0.3125,0.3125 0 0 0 3.125,7.8125 v 0.625 A 0.3125,0.3125 0 0 0 3.4375,8.75 h 6.25 A 0.3125,0.3125 0 0 0 10,8.4375 V 7.8125 A 0.3125,0.3125 0 0 0 9.6875,7.5 Z m 0,-6.25 h -6.25 A 0.3125,0.3125 0 0 0 3.125,1.5625 v 0.625 A 0.3125,0.3125 0 0 0 3.4375,2.5 h 6.25 A 0.3125,0.3125 0 0 0 10,2.1875 V 1.5625 A 0.3125,0.3125 0 0 0 9.6875,1.25 Z m 0,3.125 h -6.25 A 0.3125,0.3125 0 0 0 3.125,4.6875 v 0.625 A 0.3125,0.3125 0 0 0 3.4375,5.625 h 6.25 A 0.3125,0.3125 0 0 0 10,5.3125 V 4.6875 A 0.3125,0.3125 0 0 0 9.6875,4.375 Z" /> +</svg> diff --git a/www/images/page.svg b/www/images/page.svg new file mode 100644 index 00000000..a58c6099 --- /dev/null +++ b/www/images/page.svg @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + height="10" + width="10" + id="svg4" + version="1.1" + viewBox="0 0 10 10"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <!-- Font Awesome Free 5.15.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --> + <path + style="stroke-width:0.01953125" + id="path2" + d="M 6.875,4.84375 V 5.390625 C 6.875,5.5195312 6.7695312,5.625 6.640625,5.625 H 3.359375 C 3.2304687,5.625 3.125,5.5195312 3.125,5.390625 V 4.84375 c 0,-0.1289063 0.1054687,-0.234375 0.234375,-0.234375 h 3.28125 C 6.7695312,4.609375 6.875,4.7148437 6.875,4.84375 Z M 6.640625,6.25 H 3.359375 C 3.2304687,6.25 3.125,6.3554687 3.125,6.484375 V 7.03125 c 0,0.1289062 0.1054687,0.234375 0.234375,0.234375 h 3.28125 C 6.7695312,7.265625 6.875,7.1601562 6.875,7.03125 V 6.484375 C 6.875,6.3554687 6.7695312,6.25 6.640625,6.25 Z M 8.75,2.5761719 V 9.0625 C 8.75,9.5800781 8.3300781,10 7.8125,10 H 2.1875 C 1.6699219,10 1.25,9.5800781 1.25,9.0625 V 0.9375 C 1.25,0.41992188 1.6699219,0 2.1875,0 H 6.1738281 C 6.421875,0 6.6601562,0.09960937 6.8359375,0.27539063 L 8.4746094,1.9140625 C 8.6503906,2.0878906 8.75,2.328125 8.75,2.5761719 Z m -2.5,-1.5625 V 2.5 H 7.7363281 Z M 7.8125,9.0625 V 3.4375 H 5.78125 C 5.5214844,3.4375 5.3125,3.2285156 5.3125,2.96875 V 0.9375 h -3.125 v 8.125 z" /> +</svg>