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 "(.+?) " "${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||${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){ ?>
} ?>
-
-
+
+
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');
-
- dist/
is where our build
script will put the finished ebook files. Right now it’s empty.
-
images/
contains the raw image files used in an ebook. For ebooks without illustrations, you’ll have the following three files:
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){ ?>
- Free download
+ Read free
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.
+ Download for ereaders
} ?>
@@ -194,6 +202,7 @@ catch(\Exception $ex){
if($ebook->GitHubUrl !== null){ ?>If you’re comfortable with technology and want to contribute directly, check out this ebook’s GitHub repository and our contributors section .
} ?>
+ if(sizeof($carousel) > 0){ ?>
More free ebooks
@@ -210,6 +219,7 @@ catch(\Exception $ex){
} ?>
+ } ?>
= 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 @@
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+