#!/bin/sh
- # Copyright 2016 - 2018 Paul Hänsch
+ # Copyright 2016 - 2019 Paul Hänsch
#
# This file is part of cgilite.
#
# Parse the allowable date formats from Section 3.3.1 of
# https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
HEADER If-Modified-Since \
- | sed -r 's;^[^ ]+, ([0-9]{2}) (...) ([0-9]{4}) (..:..:..) GMT$;\3-\2-\1 \4;;
+ | sed -E 's;^[^ ]+, ([0-9]{2}) (...) ([0-9]{4}) (..:..:..) GMT$;\3-\2-\1 \4;;
s;^[^ ]+, ([0-9]{2})-(...)-([789][0-9]) (..:..:..) GMT$;19\3-\2-\1 \4;;
s;^[^ ]+, ([0-9]{2})-(...)-([0-6][0-9]) (..:..:..) GMT$;20\3-\2-\1 \4;;
s;^[^ ]+ (...) ([0-9]{2}) (..:..:..) ([0-9]{4})$;\4-\1-\2 \3;;
| xargs -r0 date +%s -ud 2>&-
)"
- range="$(HEADER Range |sed -nr 's;^bytes=([0-9]+-[0-9]*|-[0-9]+)$;\1;p;q;')"
+ range="$(HEADER Range |sed -nE 's;^bytes=([0-9]+-[0-9]*|-[0-9]+)$;\1;p;q;')"
case "$range" in
*-) range="${range}$((file_size - 1))";;
-*) [ ${range#-} -le $file_size ] \
checkid(){ grep -m 1 -xE '[0-9a-zA-Z:=]{16}'; }
+ transid(){
+ # transaction ID to modify a given file
+ local file="$1"
+ { stat -c %F%i%n%N%s%Y "$file" 2>&-
+ printf %s "$SESSION_ID"
+ server_key
+ } | sha256sum | cut -d\ -f1
+ }
+
update_session(){
local session sid time sig serverkey checksig
checksig="${checksig%% *}"
d=$(date +%s)
- if [ "$checksig" != "$sig" \
- -o "$time" -lt "$d" \
- -o ! "$(printf %s "$sid" |checkid)" ] 2>&-
+ if ! [ "$checksig" = "$sig" \
+ -a "$time" -ge "$d" \
+ -a "$(printf %s "$sid" |checkid)" ] 2>&-
then
debug Setting up new session
sid="$(randomid)"
#!/bin/sh
- # Copyright 2018 Paul Hänsch
+ # Copyright 2018, 2019 Paul Hänsch
#
# This is a file format helper, part of CGIlite.
#
STRING(){
{ [ $# -eq 0 ] && cat || printf %s "$*"; } \
- | sed -r ':X; $!{N;bX;}'"$STRING"
+ | sed -E ':X; $!{N;bX;}'"$STRING"
}
UNSTRING='
'
UNSTRING(){
{ [ $# -eq 0 ] && cat || printf %s "$*"; } \
- | sed -r "$UNSTRING"
+ | sed -E "$UNSTRING"
}
+ /* === 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;
body {
font-family: sans-serif;
padding: 2em 1em 6em 1em;
- background-color: #555;
+ #background-color: #555;
text-align: center;
overflow-x: hidden;
}
position: fixed;
bottom: 0; left: 0;
width: 100%;
- background-color: #EEE;
height: 1.25em;
content: ' ';
+ #background: #EEE repeating-linear-gradient(#EEE, #DDD 8px);
}
a.previous, a.next ,a.toplevel {
font-size: .75em;
padding: .5em 4em .5em 12em;
text-align: center;
- color: #888;
+ #color: #888;
z-index: 4;
+ /* footer must not have background, so slide number is not covered */
}
- footer:before {
+ footer:before { /* fake background in case footer spans multiple lines */
content: ' ';
position: absolute;
top: 0; left: 0;
bottom: 1.5em;
width: 100%;
- background-color: #EEE;
+ #background: #EEE repeating-linear-gradient(#EEE, #DDD 8px);
z-index: -1;
}
width: 2ex; overflow: hidden;
font-size: .875em;
padding-bottom: .25em;
- color: #EEE;
+ color: transparent;
z-index: 5;
}
body a.toplevel:before {
- color: #888;
+ #color: #888;
content: '\2196';
}
bottom: 0; left: 6.25em;
font-size: .875em;
padding-bottom: .125em;
- color: #888;
+ #color: #888;
z-index: 5;
}
text-align: left;
content: attr(count);
padding-left: .125em;
- color: #DDD;
+ #color: #DDD;
}
div.slide + a { display: none; }
position: relative;
vertical-align: top;
width: 48em; line-height: 30em;
- color: rgba(0, 0, 0, 0);
+ color: transparent;
z-index: 2;
}
#div.slide:nth-of-type(1) { margin-right: .5em; }
/* ==== Slide Appearance ==== */
div.slide {
- background: #FFF no-repeat center;
+ #background: #FFF no-repeat center;
text-align: center;
line-height: 1.5em;
}
div.slide h1, div.slide h2 {
display: block;
- background-color: #EEE;
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,
margin: .25em auto;
}
+ div.slide pre, div.slide code {
+ #background-color: rgba(224,224,224,128);
+ font-family: monospace;
+ }
div.slide pre {
- background-color: rgba(192,192,192,128);
padding: 1ex;
text-align: left;
- font-family: monospace;
overflow: hidden;
}
+ div.slide code {
+ padding: 0 .5em;
+ }
/* ==== Slide Display ==== */
text-align: left;
content: attr(count) " /";
padding-left: 4em;
- background-color: #EEE;
- color: #888;
+ #color: #888;
+ #background: #EEE repeating-linear-gradient(#EEE, #DDD 8px);
}
/* back and forth link buttons */
display: block;
font-size: inherit;
line-height: 1em;
- color: #888;
+ #color: #888;
}
:target + a:before, :target + a + a:before {
display: block;
position: fixed;
bottom: 0;
- color: #888;
+ #color: #888;
padding: 0 1em .25em 1em;
z-index: 4;
}
prev='' next='' idoff=0
depth=0 ucdepth=-1
- base64() {
- uuencode -m - <"$1" \
- | sed '1d; :X;$!{N;bX;}; s;\n;;g; s;=\+;;g;'
+ _base64() {
+ # busybox does not ship base64, only uuencode. Other platforms might need base64 instead
+ if which uuencode; then
+ uuencode -m - <"$1" \
+ | sed '1d; :X;$!{N;bX;}; s;\n;;g; s;=\+;;g;'
+ else
+ base64 <"$1" \
+ | sed ':X;$!{N;bX;}; s;\n;;g; s;=\+;;g;'
+ fi
}
{ "${0%/*}"/cgilite/html-sh.sed || cat; } \
file="${file#\"}" file="${file%\"}"
echo Inlining Background Image "$file" >&2
if [ -r "$file" ]; then
- tag="${pre}url('data:image/${file##*.};base64,$(base64 "$file")')${post}"
+ tag="${pre}url('data:image/${file##*.};base64,$(_base64 "$file")')${post}"
fi
done >/dev/null
file="${tag#${pre}src=\"}" file="${file%\"$post}"
echo Inlining Image "$file" >&2
if [ -r "$file" ]; then
- tag="${pre}src=\"data:image/${file##*.};base64,$(base64 "${file}")\"${post}"
+ tag="${pre}src=\"data:image/${file##*.};base64,$(_base64 "${file}")\"${post}"
fi
done >/dev/null
--- /dev/null
+ demo.html: demo.short
+ ../clickslide.sh <$< >$@
--- /dev/null
+ [html [head
+ [title ClickSlide Demo]
+ ] [body
+ [footer Clickslide Demo]
+
+ [slide [h1 Clickslide]
+ a Compiler for Browser based Slideshows
+ ]
+
+ [slide
+ [ul
+ [li Why would I write another Slideshow system]
+ [li What's wrong with JavaScript?]
+ [li How do you simplify HTML?]
+ ]
+ ]
+
+ [slide [h2 Why Write another Slideshow System?]
+ [ul .uncover
+ [li WYSIWYG Slideshow applications are annoying [ul
+ [li too much fiddling, not straight to point]
+ ]]
+ [li [em LaTeX] is not exactly casual]
+ [li Existing browser slideshows are [ul
+ [li based on JavaScript]
+ [li Either verbous HTML, or unflexible markup]
+ ]]
+ ]
+ ]
+
+ [slide [h2 Why avoid JavaScript]
+ [ul .uncover
+ [li Nothing wrong with JS as a programming language, [strong but...]]
+ [li Freedom to [em Use], [em Study], [em Share], and [em Improve] can in practice not be applied to code served from another computer (regardless of the license this code is under)]
+ [li Impossible to get browser security straight for Turing complete programs [ul
+ [li → Massive security problems, which are fundamentally unresolvable]
+ [li HTML and CSS are not Turing complete (CSS is a [em regular] language)]
+ ]]
+ [li Performance killer in practice]
+ ]
+ ]
+
+ [slide [h1 Usage and Features]]
+
+ [slide [h2 Simplifying HTML]
+ Maintain the flexibility of plain HTML. Decrease verbosity of the code. [br]
+ [pre style="display: inline-block; width: 46%; background-image: linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,.5)), url(exb0.jpg);"
+ \<html\>
+ \<head\>
+ \<title\>Demo\</title\>
+ \</head\>
+ \<body id="frontpage"\>
+ \<h1 class="top"\>Headline\</h1\>
+ \</body\>
+ \</html\>
+ ]
+ [pre style="display: inline-block; width: 46%; background-image: linear-gradient(rgba(255,255,255,.75), rgba(255,255,255,.5)), url(exb3.jpg);"
+ \[html
+ \[head
+ \[title Demo\]
+ \]
+ \[body \#frontpage
+ \[h1 .top Headline\]
+ \]
+ \]
+ ]
+ ]
+
+ [slide [h2 Example Slide Show]
+ [pre
+ \[html \[head
+ \[title Example Slideshow\]
+ \]\[body
+ \[footer Title | Author | Date and Place\]
+ \[slide \[h1 Title\]\]
+ \[slide \[h2 A Slide\]
+ \[ul .uncover
+ \[li This list\]
+ \[li gets uncovered\]
+ \[li item by item\]
+ \]\]\]\]
+ ]
+ ]
+
+ [slide [h2 Syntax]
+ [ul
+ [li Clickslide uses [a "//plutz.net/software/shorthand.html" Shorthand] syntax]
+ [li it introduces the [code slide]-tag to make up a single slide]
+ [li lists belonging to the [code \.uncover]-class will be uncovered item by item when the list is clicked]
+ [li You can view the source code of this presentation: [a "demo.short" click here]]
+ ]
+ ]
+
+ [slide [h2 Features]
+ [ul
+ [li Whole slideshow is contained in one document]
+ [li Images get embedded into the document via base64-coding]
+ [li Slideshow can be put on a website, emailed, or passed around on a thumbdrive]
+ [li Slideshow can be viewed on virtually all desktop and mobile devices]
+ [li Source files can be easily tracked via version control]
+ ]
+ ]
+
+ [slide [h1 Thank you for listening!]]
+ ]