mirror of https://github.com/dyne/webnomad.git
added directory index feature
This commit is contained in:
parent
4e277ed539
commit
c861598763
25
README.txt
25
README.txt
|
|
@ -64,9 +64,9 @@
|
|||
|
||||
** IMAGE SLIDESHOW
|
||||
|
||||
To create an image slideshow simply create a page with file extension
|
||||
.gal inside the views/ directory, for example one can call it
|
||||
views/vacation_in_Italy.gal
|
||||
To create an image slideshow simply create a page with file
|
||||
extension .gal or .gallery inside the views/ directory, for example
|
||||
one can call it views/vacation_in_Italy.gal
|
||||
|
||||
To add images into it one should create a -files directory inside
|
||||
views/ better if named after the gallery page, something like:
|
||||
|
|
@ -90,6 +90,25 @@
|
|||
At last run webnomad/render and the slideshow will be ready at the
|
||||
page in pub/ which in our case is pub/vacation_in_Italy.
|
||||
|
||||
## DIRECTORY INDEXES
|
||||
|
||||
Using webnomad One can also create static web pages indexing all
|
||||
files into any filesystem directories recursively, making thumbnail
|
||||
previews of images and linking to the originals.
|
||||
|
||||
In order to do so create a file in views with extension .idx or
|
||||
.index, then fill it in with the needed configurations, for
|
||||
instance a file `my_pictures_folder.index` can contain
|
||||
|
||||
```
|
||||
index /home/jaromil/pics
|
||||
```
|
||||
|
||||
This will produce a `pub/my_pictures_folder.html` file which will
|
||||
list all files inside that directory with previews and further
|
||||
links to subfolders that are indexed the same way.
|
||||
|
||||
|
||||
* DEVELOPERS
|
||||
|
||||
Bleeding edge is on GitHub. see https://github.com/dyne/webnomad
|
||||
|
|
|
|||
|
|
@ -0,0 +1,309 @@
|
|||
#!/usr/bin/env zsh
|
||||
#
|
||||
# ZShelf, file directory indexing for the web
|
||||
#
|
||||
# Copyright (C) 2014 Denis Roio <jaromil@dyne.org>
|
||||
#
|
||||
# This source code is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This source code is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# Please refer to the GNU Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Public License along with
|
||||
# this source code; if not, write to:
|
||||
# Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
VERSION=0.1
|
||||
|
||||
QUIET=0
|
||||
RECURSIVE=0
|
||||
PARAM=()
|
||||
LINK_PREFIX=""
|
||||
|
||||
autoload colors; colors
|
||||
|
||||
# standard output message routines
|
||||
# it's always useful to wrap them, in case we change behaviour later
|
||||
notice() { if [[ $QUIET == 0 ]]; then print "$fg_bold[green][*]$fg_no_bold[default] $1" >&2; fi }
|
||||
error() { if [[ $QUIET == 0 ]]; then print "$fg[red][!]$fg[default] $1" >&2; fi }
|
||||
func() { if [[ $DEBUG == 1 ]]; then print "$fg[blue][D]$fg[default] $1" >&2; fi }
|
||||
act() {
|
||||
if [[ $QUIET == 0 ]]; then
|
||||
if [ "$1" = "-n" ]; then
|
||||
print -n "$fg_bold[white] . $fg_no_bold[default] $2" >&2;
|
||||
else
|
||||
print "$fg_bold[white] . $fg_no_bold[default] $1" >&2;
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# quick bold
|
||||
B="$fg_bold[white]"
|
||||
r="$reset_color"
|
||||
|
||||
# honor quiet and debug flags as early as possible
|
||||
if [[ ${@} == *-q* ]]; then QUIET=1; fi
|
||||
if [[ ${@} == *-D* ]]; then DEBUG=1; fi
|
||||
|
||||
# what operating system are we in? use os_detect()
|
||||
# simplifying modes of operation: GNU or MAC
|
||||
case $(uname) in
|
||||
Linux) OS=GNU
|
||||
notice "ZShelf v$VERSION running on GNU/Linux" ;;
|
||||
|
||||
Darwin) OS=MAC
|
||||
notice "ZShelf v$VERSION running on Mac/OSX" ;;
|
||||
|
||||
*) OS=GNU # default
|
||||
error "Running on an unknown operating system, assuming GNU" ;;
|
||||
esac
|
||||
|
||||
if [[ ${@} == *-r* ]]; then RECURSIVE=1; fi
|
||||
|
||||
# file list map for current dir
|
||||
# format: filename;size;date
|
||||
typeset -alU files
|
||||
|
||||
# TODO
|
||||
usage() { act "no help ATM sry" }
|
||||
index_dir() {
|
||||
{ test -d "$1" } || { error "cannot index: not a directory '$1'"; return 1 }
|
||||
files=()
|
||||
ttmp=`ls -l --time-style=long-iso "$1" | awk '
|
||||
/^total/ { next }
|
||||
/^$/ { next }
|
||||
{ printf "files+=(\"%s;%s;%s\")", $8, $5, $6 }
|
||||
'`
|
||||
{ test $? = 0 } || {
|
||||
error "Error parsing directory: $1"
|
||||
return 1 }
|
||||
|
||||
eval "$ttmp"
|
||||
act "${#files} files parsed in dir $1"
|
||||
|
||||
cat <<EOF
|
||||
<table class="table table-hover table-condensed">
|
||||
<thead><tr><th>Filename</th><th>Size</th><th>Date</th><th><!-- preview --></th></tr></thead>
|
||||
EOF
|
||||
for f in ${files}; do
|
||||
name="${f[(ws:;:)1]}"
|
||||
size="${f[(ws:;:)2]}"
|
||||
date="${f[(ws:;:)3]}"
|
||||
|
||||
ext="${name##*.}" # file extension
|
||||
file="${1}/${name}" # file path
|
||||
|
||||
func "$name \t $size \t $date"
|
||||
|
||||
preview=`preview_file "$file"`
|
||||
|
||||
link="$name"
|
||||
# link ${file}.html if its existing, else link file directly
|
||||
{ test -r "${name%%.*}.html" } && { link="${name%%.*}.html" }
|
||||
|
||||
{ test "$preview" = "" } || {
|
||||
func "file preview produced"
|
||||
|
||||
case $ext:l in
|
||||
jpg|jpeg|png|gif|pdf)
|
||||
func "preview is a thumbnail"
|
||||
preview="<img src=\"$preview\" alt=\"$name\" title=\"$name\">" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
cat <<EOF
|
||||
<tr>
|
||||
<td><a href="${LINK_PREFIX}${link}">${name}</a></td>
|
||||
<td>$size</td><td>$date</td>
|
||||
<td><a href="${LINK_PREFIX}${link}">$preview</a></td></tr>
|
||||
EOF
|
||||
done
|
||||
print "</table>"
|
||||
}
|
||||
|
||||
preview_file() {
|
||||
{ test "$1" = "" } && { error "no file to preview."; return 1 }
|
||||
# get the file extension using zsh builtins
|
||||
# %% is for deleting prefix and ## is for deleting suffix
|
||||
for f in ${1}; do
|
||||
filename="${f##*/}"
|
||||
name="${filename%%.*}"
|
||||
ext="${f##*.}"
|
||||
|
||||
# lowercase
|
||||
case $ext:l in
|
||||
md) # markdown
|
||||
notice "$f: rendering markdown using maruku"
|
||||
output="$name".html
|
||||
maruku --html --html-frag $f -o "$output"
|
||||
print "$output"
|
||||
;;
|
||||
jpg|jpeg|png|gif)
|
||||
output="${name}-thumb.${ext}"
|
||||
{ test -r "$output" } && {
|
||||
act "$f: thumbnail found, skip rendering"
|
||||
print "$output"
|
||||
continue }
|
||||
notice "$f: rendering thumbnail using ImageMagick"
|
||||
convert $f -resize 100 $output
|
||||
print "$output"
|
||||
;;
|
||||
pdf)
|
||||
output="${name}-thumb.jpg"
|
||||
{ test -r "$output" } && {
|
||||
act "$f: thumbnail found, skip rendering"
|
||||
print "$output"
|
||||
continue }
|
||||
notice "$f: rendering thumbnail using ImageMagick"
|
||||
convert "${f}[0]" -resize 100 $output
|
||||
print "$output"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
return 0
|
||||
}
|
||||
autostart() {
|
||||
if [ -d "$1" ]; then
|
||||
index_dir "$1"
|
||||
elif [ -f "$1" ]; then
|
||||
preview_file "$1"
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
return $?
|
||||
}
|
||||
|
||||
typeset -A subcommands_opts
|
||||
|
||||
### Options configuration
|
||||
#Hi, dear developer! Are you trying to add a new subcommand, or to add some options?
|
||||
#Well, keep in mind that:
|
||||
# 1. An option CAN'T have differente meanings/behaviour in different subcommands.
|
||||
# For example, "-s" means "size" and accept an argument. If you are tempted to add
|
||||
# an option "-s" (that means, for example "silent", and doesn't accept an argument)
|
||||
# DON'T DO IT!
|
||||
# There are two reasons for that:
|
||||
# I. usability; user expect that "-s" is "size
|
||||
# II. Option parsing WILL EXPLODE if you do this kind of bad things
|
||||
# (it will say "option defined more than once, and he's right)
|
||||
|
||||
|
||||
|
||||
# recursive, quiet, Debug, help, verbose, n=dryrun
|
||||
main_opts=(r q D h v n)
|
||||
|
||||
# p: prefix (string arg) = <a href> link prefix
|
||||
subcommands_opts[index]="p: "
|
||||
subcommands_opts[preview]=""
|
||||
|
||||
option_is_set() {
|
||||
#First argument, the option (something like "-s")
|
||||
#Second (optional) argument: if it's "out", command will print it out 'set'/'unset'
|
||||
# This is useful for if conditions
|
||||
#Return 0 if is set, 1 otherwise
|
||||
[[ -n ${(k)opts[$1]} ]];
|
||||
r=$?
|
||||
if [[ $2 == out ]]; then
|
||||
if [[ $r == 0 ]]; then print 'set'
|
||||
else print 'unset'; fi
|
||||
fi
|
||||
return $r;
|
||||
}
|
||||
option_value() { #First argument, the option (something like "-s")
|
||||
<<< ${opts[$1]}
|
||||
}
|
||||
|
||||
### Detect subcommand
|
||||
local -aU every_opts #every_opts behave like a set; that is, an array with unique elements
|
||||
for optspec in $subcommands_opts$main_opts; do
|
||||
for opt in ${=optspec}; do
|
||||
every_opts+=${opt}
|
||||
done
|
||||
done
|
||||
local -a oldstar
|
||||
oldstar=($argv)
|
||||
zparseopts -M -E -D -Adiscardme ${every_opts}
|
||||
unset discardme
|
||||
subcommand=$1
|
||||
{ test "$subcommand" = "" } && { subcommand="__default" }
|
||||
|
||||
argv=(${oldstar})
|
||||
unset oldstar
|
||||
|
||||
### Parsing global + command-specific options
|
||||
# zsh magic: ${=string} will split to multiple arguments when spaces occur
|
||||
set -A cmd_opts ${main_opts} ${=subcommands_opts[$subcommand]}
|
||||
if [[ -n $cmd_opts ]]; then #if there is no option, we don't need parsing
|
||||
zparseopts -M -E -D -Aopts ${cmd_opts}
|
||||
if [[ $? != 0 ]]; then
|
||||
error "Some error occurred during option processing."
|
||||
exitcode=1
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
#build PARAM (array of arguments) and check if there are unrecognized options
|
||||
local ok=0
|
||||
for arg in $*; do
|
||||
if [[ $arg == '--' || $arg == '-' ]]; then
|
||||
ok=1
|
||||
continue #it shouldnt be appended to PARAM
|
||||
elif [[ $arg[1] == '-' ]]; then
|
||||
if [[ $ok == 0 ]]; then
|
||||
error "unrecognized option $arg"
|
||||
exitcode=1
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
PARAM+=$arg
|
||||
done
|
||||
|
||||
# if 1st parameter is a known subcommand omit it from params
|
||||
{ test "$subcommand" = "__default" } || { PARAM[1]=(); shift }
|
||||
|
||||
### End parsing command-specific options
|
||||
|
||||
{ option_is_set -v } && {
|
||||
cat $ZSHELFEXEC | awk '/^#/ {print $0 } !/^#/ {exit}'
|
||||
echo }
|
||||
{ option_is_set -h } && { usage; return 0 }
|
||||
{ option_is_set -v } && { CLEANEXIT=0
|
||||
cat $JAROMAILEXEC | awk 'BEGIN { v=1 } !/^#/ { exit }'
|
||||
return 0 }
|
||||
{ option_is_set -q } && { QUIET=1 }
|
||||
{ option_is_set -D } && { DEBUG=1; QUIET=0; func "All debug messages ON" }
|
||||
{ option_is_set -n } && { DRYRUN=1; act "Dry run, show operations without executing them." }
|
||||
{ option_is_set -r } && { RECURSIVE=1 }
|
||||
{ option_is_set -p } && { LINK_PREFIX="`option_value -p`" }
|
||||
|
||||
# we take a file or directory as the only one parameter
|
||||
ARG=${PARAM[1]}
|
||||
case "$subcommand" in
|
||||
index)
|
||||
index_dir "$ARG"
|
||||
{ test -r "${ARG}/README.md" } && {
|
||||
res=`preview_file "${ARG}/README.md"`
|
||||
print "<hr>"
|
||||
cat "$res"
|
||||
}
|
||||
;;
|
||||
preview) preview_file ${PARAM} ;;
|
||||
help) usage ;;
|
||||
'source') return 0 ;;
|
||||
*) # unknown command, pass it to autostart
|
||||
func "unknown command, using autostart"
|
||||
autostart ${=PARAM}
|
||||
exitcode=$?
|
||||
{ test $exitcode = 0 } || {
|
||||
error "command \"$subcommand\" not recognized"
|
||||
act "try -h for help"
|
||||
}
|
||||
;;
|
||||
esac
|
||||
exitcode=$?
|
||||
return $exitcode
|
||||
6
init
6
init
|
|
@ -21,10 +21,7 @@ SYS=`dirname $0`
|
|||
source $SYS/utils
|
||||
|
||||
|
||||
|
||||
|
||||
act "Initializing $B $DIR $r"
|
||||
pushd $DIR
|
||||
act "Initializing Webnomad"
|
||||
|
||||
act "Below is the log of files copied into this directory."
|
||||
act "Init does not rewrite any existing file"
|
||||
|
|
@ -87,4 +84,3 @@ act "Look in your new WebNomad project: $B $DIR $r"
|
|||
act "Customize $B config.zsh $r and then files in the $B tmpl/ $r folder"
|
||||
act "Create new HTML pages in $B views/ $r"
|
||||
|
||||
{ test "$DIR" = "." } || { sleep 10 }
|
||||
|
|
|
|||
32
render
32
render
|
|
@ -200,7 +200,7 @@ EOF
|
|||
pics=`grep -v '^#'`
|
||||
for p in ${(f)pics}; do
|
||||
file=${p[(ws: :)1]}
|
||||
desc=`echo $p | awk '{ for(c=2;c<=NF;c++) printf("%s ",$c) }'`
|
||||
desc=`pecho $p | awk '{ for(c=2;c<=NF;c++) printf("%s ",$c) }'`
|
||||
cat << EOF >> pub/$dst_js
|
||||
slides.push({
|
||||
href: '${file}',
|
||||
|
|
@ -260,6 +260,23 @@ EOF
|
|||
|
||||
}
|
||||
|
||||
index() {
|
||||
# render_header "<link rel=\"stylesheet\" href=\"css/blueimp-gallery.min.css\" />"
|
||||
{ test -d "$1" } || { error "cannot index directory not found: $1"; return 1 }
|
||||
source $SYS/index source
|
||||
dirs=`find "$1" -type d`
|
||||
base=`dirname "$1"`
|
||||
for d in ${(f)dirs}; do
|
||||
dir="${d##*${base}}"
|
||||
mkdir -p "pub/$dir"
|
||||
render_header > "pub/$dir/index.html"
|
||||
pushd "pub/$dir"
|
||||
index_dir "$d" >> index.html
|
||||
popd
|
||||
render_footer >> "pub/$dir/index.html"
|
||||
done
|
||||
}
|
||||
|
||||
read_meta() {
|
||||
tmp=`head -n 3 | awk '
|
||||
!/^#/ { next }
|
||||
|
|
@ -345,6 +362,7 @@ done
|
|||
|
||||
# render all image galleries
|
||||
gals=(`find views -type f -name '*.gal'`)
|
||||
gals+=(`find views -type f -name '*.gallery'`)
|
||||
for src in $gals; do
|
||||
cat ${src} | read_meta
|
||||
dst="pub/`basename ${src%.*}`"
|
||||
|
|
@ -353,6 +371,16 @@ for src in $gals; do
|
|||
print "done"
|
||||
done
|
||||
|
||||
|
||||
# render all directory indexes
|
||||
idxs=(`find views -type f -name '*.idx'`)
|
||||
idxs+=(`find views -type f -name '*.index'`)
|
||||
for idx in $idxs; do
|
||||
notice "Directory index rendering: $idx"
|
||||
source ${idx}
|
||||
done
|
||||
|
||||
|
||||
for m in `find views -mindepth 1 -type d `; do
|
||||
act -n "publishing $B $m $r ... "
|
||||
rsync -r $m pub/
|
||||
|
|
@ -373,4 +401,4 @@ done
|
|||
|
||||
notice "Website refreshed."
|
||||
|
||||
{ test "$DIR" = "." } || { sleep 10 }
|
||||
# { test "$DIR" = "." } || { sleep 10 }
|
||||
|
|
|
|||
Loading…
Reference in New Issue