diff --git a/config/apache/standardebooks.org.conf b/config/apache/standardebooks.org.conf index d5e2cb1e..e0ee2d1a 100644 --- a/config/apache/standardebooks.org.conf +++ b/config/apache/standardebooks.org.conf @@ -138,6 +138,14 @@ Define domain standardebooks.org ProxySet connectiontimeout=5 timeout=240 + # In RewriteCond, RewriteRule gets evaluated BEFORE RewriteCond, so $1 refers to the first + # match in RewriteRule + # Rewrite POST /some/url -> POST /some/url/post.php + RewriteCond %{REQUEST_METHOD} ^POST$ + RewriteCond %{DOCUMENT_ROOT}/$1/ -d + RewriteCond %{DOCUMENT_ROOT}/$1/post.php -f + RewriteRule ^([^\.]+)$ $1/post.php [L] + # In case of 404, serve the 404 page specified by ErrorDocument, not the default FPM error page. # Note that we can't use `ProxyErrorOverride on` because that catches ALL 4xx and 5xx HTTP headers # and serves the default Apache page for them. diff --git a/config/apache/standardebooks.test.conf b/config/apache/standardebooks.test.conf index ff07bfd7..03d04e0f 100644 --- a/config/apache/standardebooks.test.conf +++ b/config/apache/standardebooks.test.conf @@ -137,6 +137,14 @@ Define domain standardebooks.test ProxySet connectiontimeout=5 timeout=240 + # In RewriteCond, RewriteRule gets evaluated BEFORE RewriteCond, so $1 refers to the first + # match in RewriteRule + # Rewrite POST /some/url -> POST /some/url/post.php + RewriteCond %{REQUEST_METHOD} ^POST$ + RewriteCond %{DOCUMENT_ROOT}/$1/ -d + RewriteCond %{DOCUMENT_ROOT}/$1/post.php -f + RewriteRule ^([^\.]+)$ $1/post.php [L] + # In case of 404, serve the 404 page specified by ErrorDocument, not the default FPM error page. # Note that we can't use `ProxyErrorOverride on` because that catches ALL 4xx and 5xx HTTP headers # and serves the default Apache page for them. diff --git a/templates/Footer.php b/templates/Footer.php index 4f91e9b8..8848d44e 100644 --- a/templates/Footer.php +++ b/templates/Footer.php @@ -12,6 +12,9 @@
  • Donate
  • +
  • + Settings +
  • GitHub
  • diff --git a/templates/Header.php b/templates/Header.php index 765b3fe1..9b6d52e8 100644 --- a/templates/Header.php +++ b/templates/Header.php @@ -16,6 +16,8 @@ if(!isset($manual)){ $manual = false; } +$colorScheme = $_COOKIE['color-scheme'] ?? 'auto'; + # We hash with crc32 because it's faster than md5 and "good enough" for this simple cache-busting use case header('content-type: application/xhtml+xml'); @@ -28,8 +30,10 @@ print("\n"); <? if($title != ''){ ?><?= Formatter::ToPlainText($title) ?> - <? } ?>Standard Ebooks: Free and liberated ebooks, carefully produced for the true book lover. - + + + diff --git a/www/css/core.css b/www/css/core.css index d2f4b68e..a80df2de 100644 --- a/www/css/core.css +++ b/www/css/core.css @@ -95,22 +95,85 @@ --link-highlight: var(--button); } -@media(prefers-color-scheme: dark){ - :root{ - --body-text: var(--dark-body-text); - --header: var(--dark-header); - --button: var(--dark-button); - --button-highlight: var(--dark-button-highlight); - --border: var(--dark-border); - --sub-text: var(--dark-sub-text); - --body-bg: var(--dark-body-bg); - --input-hover: var(--dark-input-hover); - --input-border: var(--dark-input-border); - --input-outline: var(--dark-input-outline); - --link-highlight: var(--button-highlight); /* lighter looks better in dark mode */ - } +/* Start CSS reset */ +/* Dont @import this, to prevent FOUC */ +html{ + margin: 0; + padding: 0; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; } +body{ + margin: 0; + padding: 0; +} + +a{ + outline: 0; +} + +blockquote{ + margin: 0; + quotes: none; +} + +p{ + margin: 0; +} + +ol{ + margin: 0; + padding: 0; +} + +ul{ + margin: 0; + padding: 0; +} + +h1{ + margin: 0; +} + +h2{ + margin: 0; +} + +h3{ + margin: 0; +} + +h4{ + margin: 0; +} + +h5{ + margin: 0; +} + +h6{ + margin: 0; +} + +figure{ + margin: 0; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +q{ + quotes: none; +} + +button::-moz-focus-inner{ + border: 0; +} +/* End reset */ + html{ color: var(--body-text); font-family: "Crimson Pro", Georgia, serif; @@ -539,6 +602,11 @@ form button{ hyphens: none; } +form button{ + line-height: 1; + margin-left: 1rem; +} + .ebooks nav li.highlighted a:focus, a.button:focus, input[type="search"]:focus, @@ -1480,6 +1548,10 @@ select[multiple] option:last-child{ margin-bottom: 1rem; /* needed for firefox */ } +form[action="/settings"]{ + margin: 0 1rem; +} + form[action="/ebooks"] label{ max-width: 100%; } @@ -1932,7 +2004,7 @@ article.ebook section aside.donation p::after{ display: inline; } - footer ul li:nth-child(3)::after{ + footer ul li:nth-child(4)::after{ content: "\A"; /* This is a line break */ white-space: pre; margin: 0; @@ -2051,6 +2123,24 @@ article.ebook section aside.donation p::after{ main.ebooks > ol{ grid-template-columns: repeat(2, 1fr); } + + footer ul li:nth-child(2)::after{ + content: "\A"; /* This is a line break */ + white-space: pre; + margin: 0; + } + + footer ul li:nth-child(4)::after{ + content: "\b7"; + white-space: normal; + margin: 0 10px; + } + + footer ul li:nth-child(5)::after{ + content: "\A"; /* This is a line break */ + white-space: pre; + margin: 0; + } } @media(max-width: 680px){ @@ -2242,10 +2332,16 @@ article.ebook section aside.donation p::after{ text-align: left; } - footer ul li:nth-child(5)::after{ - content: "\A"; /* This is a line break */ - white-space: pre; - margin: 0; + form[action="/settings"] button{ + display: block; + margin-top: 1rem; + margin-left: 0; + } + + form[action="/settings"] button, + form[action="/settings"] span, + form[action="/settings"] select{ + width: 100%; } } @@ -2259,16 +2355,6 @@ article.ebook section aside.donation p::after{ .masthead ol li img.contact{ height: .75rem; } -} - -@media(max-width: 380px){ - main.front-page h1{ - font-size: 2rem; - } - - h1,h2,h3,h4,h5,h6,code,.ebook h1 + p{ - hyphens: auto; - } body > footer{ padding-top: 0; @@ -2282,6 +2368,16 @@ article.ebook section aside.donation p::after{ footer ul li::after{ display: none; } +} + +@media(max-width: 380px){ + main.front-page h1{ + font-size: 2rem; + } + + h1,h2,h3,h4,h5,h6,code,.ebook h1 + p{ + hyphens: auto; + } main.ebooks > ol{ grid-template-columns: 1fr; @@ -2308,7 +2404,6 @@ article.ebook section aside.donation p::after{ grid-row: 6; } - body > header ul li:nth-child(2n)::after{ display: none; } @@ -2321,7 +2416,6 @@ article.ebook section aside.donation p::after{ display: none; } - body > header ul li:nth-child(2) ~ li, body > header ul li + li{ margin-top: 1rem; @@ -2341,73 +2435,3 @@ article.ebook section aside.donation p::after{ text-align: left; } } - -@media(prefers-color-scheme: dark){ - - - main.front-page > section > section figure img{ - box-shadow: 3px 3px 1px rgba(0, 0, 0, .5); - } - - body > header > a:focus{ - /* Since we use invert() to change the color of the SE logo, - we must specify the light outline (which is dark) - so that it inverts to white */ - outline: 1px dashed var(--light-input-outline); - } - - article.ebook section#read-online a::before, - article.ebook section#download ul li a[class]::before, - article.ebook section#details ul li a[class]::before, - footer p:last-child a::before, - main.front-page > section > section figure.oss img + img, - main.front-page > section > h2::before, - main.front-page > section > h2::after{ - filter: invert() grayscale(100%) brightness(120%) drop-shadow(3px 3px 1px rgba(0, 0, 0, .25)); /* grayscale and brightness makes it hit about #eeeeee */ - } - - .masthead img[src*="portrait.svg"], - .masthead img.contact{ - filter: invert(); - } - - .masthead img[src*="portrait.svg"]{ - border-color: var(--border-light); - } - - aside.donation, - article.ebook section aside.donation{ - background: rgba(0, 0, 0, .25); - } - - aside.donation, - article.ebook section aside.donation{ - box-shadow: none; - } - - select, - input[type="search"]{ - box-shadow: 1px 1px 0 rgba(0, 0, 0, .5) inset; - } - - input::placeholder{ - color: rgba(255, 255, 255, .75); - } - - main.ebooks > ol img:hover{ - box-shadow: 3px 3px 1px rgba(0, 0, 0, .5); - } - - article.ebook #more-ebooks img:hover{ - box-shadow: 3px 3px 1px rgba(0, 0, 0, .5); - } - - label.select > span + span::after, - label.search::before{ - text-shadow: 1px 1px 0 #000; - } - - h1,h2,h3,h4,h5,h6{ - text-shadow: 2px 2px 0 rgba(0, 0, 0, .75); - } -} diff --git a/www/css/dark.css b/www/css/dark.css new file mode 100644 index 00000000..8cfd425f --- /dev/null +++ b/www/css/dark.css @@ -0,0 +1,79 @@ +:root{ + --body-text: var(--dark-body-text); + --header: var(--dark-header); + --button: var(--dark-button); + --button-highlight: var(--dark-button-highlight); + --border: var(--dark-border); + --sub-text: var(--dark-sub-text); + --body-bg: var(--dark-body-bg); + --input-hover: var(--dark-input-hover); + --input-border: var(--dark-input-border); + --input-outline: var(--dark-input-outline); + --link-highlight: var(--button-highlight); /* lighter looks better in dark mode */ +} + +main.front-page > section > section figure img{ + box-shadow: 3px 3px 1px rgba(0, 0, 0, .5); +} + +body > header > a:focus{ + /* Since we use invert() to change the color of the SE logo, + we must specify the light outline (which is dark) + so that it inverts to white */ + outline: 1px dashed var(--light-input-outline); +} + +article.ebook section#read-online a::before, +article.ebook section#download ul li a[class]::before, +article.ebook section#details ul li a[class]::before, +footer p:last-child a::before, +main.front-page > section > section figure.oss img + img, +main.front-page > section > h2::before, +main.front-page > section > h2::after{ + filter: invert() grayscale(100%) brightness(120%) drop-shadow(3px 3px 1px rgba(0, 0, 0, .25)); /* grayscale and brightness makes it hit about #eeeeee */ +} + +.masthead img[src*="portrait.svg"], +.masthead img.contact{ + filter: invert(); +} + +.masthead img[src*="portrait.svg"]{ + border-color: var(--border-light); +} + +aside.donation, +article.ebook section aside.donation{ + background: rgba(0, 0, 0, .25); +} + +aside.donation, +article.ebook section aside.donation{ + box-shadow: none; +} + +select, +input[type="search"]{ + box-shadow: 1px 1px 0 rgba(0, 0, 0, .5) inset; +} + +input::placeholder{ + color: rgba(255, 255, 255, .75); +} + +main.ebooks > ol img:hover{ + box-shadow: 3px 3px 1px rgba(0, 0, 0, .5); +} + +article.ebook #more-ebooks img:hover{ + box-shadow: 3px 3px 1px rgba(0, 0, 0, .5); +} + +label.select > span + span::after, +label.search::before{ + text-shadow: 1px 1px 0 #000; +} + +h1,h2,h3,h4,h5,h6{ + text-shadow: 2px 2px 0 rgba(0, 0, 0, .75); +} diff --git a/www/css/reset.css b/www/css/reset.css deleted file mode 100644 index b692a4e1..00000000 --- a/www/css/reset.css +++ /dev/null @@ -1,94 +0,0 @@ -/* Dont @import this, to prevent FOUC */ -html{ - margin: 0; - padding: 0; - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; -} - -body{ - margin: 0; - padding: 0; -} - -a{ - outline: 0; -} - -blockquote{ - margin: 0; - quotes: none; -} - -p{ - margin: 0; -} - -ol{ - margin: 0; - padding: 0; -} - -ul{ - margin: 0; - padding: 0; -} - -h1{ - margin: 0; -} - -h2{ - margin: 0; -} - -h3{ - margin: 0; -} - -h4{ - margin: 0; -} - -h5{ - margin: 0; -} - -h6{ - margin: 0; -} - -table { - border-collapse: collapse; - border-spacing: 0; -} - -q{ - quotes: none; -} - -figure{ - margin: 0; -} - -button::-moz-focus-inner{ - border: 0; -} - -/* ie 11 compatibility */ -header{ - display: block; -} - -nav{ - display: block; -} - -main{ - display: block; -} - -footer{ - display: block; -} -/* end ie 11 compatibility */ diff --git a/www/settings/index.php b/www/settings/index.php new file mode 100644 index 00000000..55aefa76 --- /dev/null +++ b/www/settings/index.php @@ -0,0 +1,23 @@ + 'Website Settings', 'description' => 'Adjust your settings for viewing the Standard Ebooks website.']) ?> +
    +

    Website Settings

    +
    + + +
    +
    + diff --git a/www/settings/post.php b/www/settings/post.php new file mode 100644 index 00000000..9419ac01 --- /dev/null +++ b/www/settings/post.php @@ -0,0 +1,21 @@ + 0, 'path' => '/', 'secure' => true, 'httponly' => true]); +} +else{ + setcookie('color-scheme', $colorScheme, ['expires' => strtotime('+10 years'), 'path' => '/', 'secure' => true, 'httponly' => true]); +} + +// HTTP 303, See other +http_response_code(303); +header('Location: /settings'); +?>