From: Paul Hänsch Date: Wed, 23 Sep 2026 15:29:29 +0000 (+0200) Subject: slideshow handler, using code from "clickslide" X-Git-Url: https://git.plutz.net/?a=commitdiff_plain;h=007137db90bfe67fb64703360f05c439ea7b6a45;p=shellwiki slideshow handler, using code from "clickslide" --- diff --git a/handlers/70_slideshow.sh b/handlers/70_slideshow.sh new file mode 100755 index 0000000..066aa88 --- /dev/null +++ b/handlers/70_slideshow.sh @@ -0,0 +1,148 @@ +#!/bin/sh + +# Copyright 2019 - 2026 Paul Hänsch +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +case $PATH_INFO in + */\[slideshow\]) : ;; + *) return 1 ;; +esac + +printf "%s\r\n" "Content-Type: text/html; charset=utf-8" "" + +cat <<-EOF + + + + $(HTML ${PAGE_TITLE}) + + overview + EOF + +page="${PATH_INFO%\[*\]}" +wiki "$page" | { + read -r line + prev='' next='' idoff=0 + depth=0 ucdepth=-1 + + while :; do + tag="${tag}${line%%>*}" + + if [ "$line" = "${line%%>*}" ]; then + # $line did not contain ">" and thus was added to $tag entirely + if ! read -r line; then + printf %s\\n "$tag" + break + fi + tag="${tag}${BR}" + else + # $line is shortened by segment added to $tag + line="${line#*>}" + tag="${tag}>" + fi + + case $tag in + *\*) # Count slide id, insert "next" button + prev="$next" + next="${tag#*
next
*) + prev="$next" + next="autoslide${idoff}" + idoff="$((idoff + 1))" + printf '%snext
*) # Count slide id, insert "next" button + prev="$next" + next="${tag#*
previous' \ + "${tag%next
*|*\*) + prev="$next" + next="autoslide${idoff}" + idoff="$((idoff + 1))" + if [ $depth -eq $sldepth ]; then + printf '%s
previous' \ + "${tag%next
*) # Insert "previous" button + if [ $depth -eq $sldepth ]; then + printf '%s
previous%s' \ + "${tag%
*}" "$prev" "${tag#*
}" + else + printf %s "${tag%*}" + fi + tag='' depth=$((depth - 1)) + ;; + # *\*) # Insert toplevel link + # printf '%soverview' "$tag" + # tag='' depth=$((depth + 1)) + # ;; + # *\*) # Insert total slide count + # printf '%i%s' "$idoff" "$tag" + # tag='' depth=$((depth - 1)) + # ;; + *\<*class=\"uncover\"*\>*) # Insert checkboxes in "uncover" lists + #printf '%s
  • ' "$tag" + printf '%s' "$tag" + tag='' depth=$((depth + 1)) + ucdepth=$((depth + 1)) + ;; + *\*) + printf %s "$tag" + tag='' depth=$((depth - 1)) + [ $depth -lt $ucdepth ] && ucdepth=-1 + ;; + *\<*\>*) + if [ $ucdepth = $depth ]; then + printf '%s<%s' "${tag%<*}" "${tag#*<}" + else + printf %s "$tag" + fi + [ "${tag}" = "${tag%/>}" ] && depth=$((depth + 1)) + tag='' + ;; + *) : + ;; + esac + done + printf '%i' "$idoff" +} + +printf '' + +return 0 diff --git a/themes/slideshow.css b/themes/slideshow.css new file mode 100644 index 0000000..2f5ca87 --- /dev/null +++ b/themes/slideshow.css @@ -0,0 +1,312 @@ +/* === Colors === */ + +footer, +body a.toplevel:before, +body span.count, +div.slide:target:after, +div.slide:target + a, div.slide:target + a + a, +:target + a:before, :target + a + a:before +{ color: #888; } + +body +{ background-color: #AAA; + background-image: repeating-linear-gradient( to bottom right, #AAA, #999 8px); +} + +div.slide +{ background-color: #FFF; + background-image: repeating-linear-gradient( #FFF, #EEE 4px); +} + +div.slide:target:after, +footer:before, body:after +{ background-color: #EEE; + background-image: repeating-linear-gradient(#EEE, #DDD 8px); +} + +div.slide h1, div.slide h2 +{ background-color: #EEE; + background-image: repeating-linear-gradient(#EEE, #DDD 8px); +} + +div.slide pre, div.slide code +{ background-color: #DDD; + background-image: repeating-linear-gradient(#CCC, #DDD 4px); +} + +div.slide:after /* slide number on overview screen */ +{ color: #AAA; } + +/* === Overall Layout === */ + +* { + box-sizing: border-box; + margin: 0; padding: 0; + background-position: center; + background-repeat: no-repeat; + background-size: cover; +} + +/* min-height: 240px */ body { font-size: 9px; } +@media(min-height: 320px) { body { font-size: 12px; } } +@media(min-height: 480px) { body { font-size: 19px; } } +@media(min-height: 720px) { body { font-size: 28px; } } +@media(min-height: 768px) { body { font-size: 30px; } } +@media(min-height: 800px) { body { font-size: 32px; } } +@media(min-height: 960px) { body { font-size: 38px; } } +@media(min-height: 1024px) { body { font-size: 41px; } } +@media(min-height: 1080px) { body { font-size: 43px; } } +@media(min-height: 2160px) { body { font-size: 86px; } } + +body { + font-family: sans-serif; + padding: 2em 1em 6em 1em; + #background-color: #555; + text-align: center; + overflow-x: hidden; +} +body * { + text-align: left; + font-size: inherit; +} + +body:after { + position: fixed; + bottom: 0; left: 0; + width: 100%; + height: 1.25em; + content: ' '; + #background: #EEE repeating-linear-gradient(#EEE, #DDD 8px); +} + +a.previous, a.next ,a.toplevel { + text-decoration: none; +} + +footer { + position: fixed; + bottom: 0; left: 0; + width: 100%; + font-size: .75em; + padding: .5em 4em .5em 12em; + text-align: center; + #color: #888; + z-index: 4; + /* footer must not have background, so slide number is not covered */ +} +footer:before { /* fake background in case footer spans multiple lines */ + content: ' '; + position: absolute; + top: 0; left: 0; + bottom: 1.5em; + width: 100%; + #background: #EEE repeating-linear-gradient(#EEE, #DDD 8px); + z-index: -1; +} + +body a.toplevel { + position: fixed; + bottom: 0; left: 8em; + width: 2ex; overflow: hidden; + font-size: .875em; + padding-bottom: .25em; + color: transparent; + z-index: 5; +} +body a.toplevel:before { + #color: #888; + content: '\2196'; +} + +body span.count { + position: fixed; + bottom: 0; left: 6.25em; + font-size: .875em; + padding-bottom: .125em; + #color: #888; + z-index: 5; +} + +/* ==== Overview Screen ==== */ + +div.slide, a.nextslide { + font-size: .15625em; +} + +div.slide { + position: relative; + display: inline-block; + overflow: hidden; + width: 48em; height: 30em; + margin-left: -48em; + border: 1px solid black; +} + +div.slide:after { /* slide number */ + position: absolute; + bottom: 0; left: 0; + font-size: 15em; + line-height: 1em; + text-align: left; + content: attr(count); + padding-left: .125em; + #color: #DDD; +} + +div.slide + a { display: none; } +a.nextslide { + display: inline-block; + position: relative; + vertical-align: top; + width: 48em; line-height: 30em; + color: transparent; + z-index: 2; +} +#div.slide:nth-of-type(1) { margin-right: .5em; } + +/* ==== Slide Appearance ==== */ + +div.slide { + #background: #FFF no-repeat center; + text-align: center; + line-height: 1.5em; +} + +div.slide > * { + margin-top: 1em; + max-width: 85%; + margin-left: auto; + margin-right: auto; +} + +div.slide > *:first-child:last-child, +div.slide > h2:first-child + :last-child { + margin-top: 20%; + transform: translate(0, -50%); +} + +div.slide h1, div.slide h2 { + display: block; + text-align: center; + font-size: 1.5em; + margin-top: 0; + margin-bottom: 1em; + width: 100%; max-width: 100%; + #background: #EEE repeating-linear-gradient(#EEE, #DDD 8px); +} + +div.slide h1, +div.slide > h1:first-child:last-child { + margin-top: 25%; + margin-bottom: 0; + padding: .5em 2em; +} + +div.slide h2 { + padding: .25em 1em; +} + +div.slide > table { + width: 85%; +} +div.slide * table { + width: 100%; +} + +div.slide ul li { + list-style-type: square; + margin-left: 2em; +} + +div.slide ul ul, div.slide ul ol, +div.slide ol ul, div.slide ol ol { + margin-left: -1em; +} + +div.slide > ul, +div.slide > ol { + width: fit-content; + margin: .25em auto; +} + +div.slide li pre { + margin-bottom: .25em; +} + +div.slide pre, div.slide code { + #background-color: rgba(224,224,224,128); + font-family: monospace; +} +div.slide pre { + padding: 1ex; + text-align: left; + overflow: hidden; +} +div.slide code { + padding: 0 .5em; +} + +/* ==== Slide Display ==== */ + +div.slide:target { + position: fixed; + z-index: 3; + top: 0; bottom: 0; left: 0; right: 0; + width: auto; height: 100%; + margin: 0; + border: none; + font-size: inherit; +} + +/* slide number, footer bar*/ +div.slide:target:after { + position: absolute; + bottom: 0; left: 0; + width: 100%; + font-size: .875em; + line-height: 1.5em; + text-align: left; + content: attr(count) " /"; + padding-left: 4em; + #color: #888; + #background: #EEE repeating-linear-gradient(#EEE, #DDD 8px); +} + +/* back and forth link buttons */ +div.slide:target + a, +div.slide:target + a + a { + position: static; + display: block; + font-size: inherit; + line-height: 1em; + #color: #888; +} +:target + a:before, :target + a + a:before { + display: block; + position: fixed; + bottom: 0; + #color: #888; + padding: 0 1em .25em 1em; + z-index: 4; +} +:target + a:before { left: 0; } +:target + a:before { content: '\22d8'; } +:target + a + a:before { right: 0; } +:target + a + a:before { content: '\22d9'; } + +.uncover[type="checkbox"] + * { opacity: .2; } +.uncover[type="checkbox"]:checked + * { opacity: 1; } + +.uncover[type="checkbox"] { + position: fixed; + top: 0; bottom: 0; left: 0; right: 0; + width: 100%; height: 100%; + opacity: 0; + z-index: 1; +} + +.uncover[type="checkbox"] + * + .uncover[type="checkbox"] { display: none; } +.uncover[type="checkbox"]:checked + * + .uncover[type="checkbox"] { display: inline; } +.uncover[type="checkbox"]:checked + * + .uncover[type="checkbox"]:checked, +.uncover[type="checkbox"]:checked { display: none; } +