X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=zk.zsh;h=9b65aecc25db5e0c1709f2717b8651bd94a46d5c;hb=HEAD;hp=56e071f8af79e60139d3b569ec5870fb79b9b74f;hpb=39fd53ab88fb9464da14a29b5e1009589ac72fba;p=zk.zsh.git diff --git a/zk.zsh b/zk.zsh index 56e071f..9b65aec 100755 --- a/zk.zsh +++ b/zk.zsh @@ -1,14 +1,17 @@ #!/usr/bin/env zsh +# zk.zsh -- zettelkästen/wiki/static website helper/generator +# Copyright (C) 2022-2024 Sergey Matveev set -e +ZK_VERSION=ZKZSH1 usage() { - cat >&2 <&2 <&2 + exit 1 + } + zstat -A mtime -F "%F %T" +mtime $p + zstat -A size +size $p + pages[$p]=${mtime[1]} + sizes[$p]=${size[1]} +} +typeset -A cats +for p (**(/)) cats[$p]=1 -# Determine the links between them +zmodload zsh/mapfile +zmodload -F zsh/files b:zf_mkdir typeset -A links typeset -A backs +typeset -A cached +typeset -aU ws for p (${(k)pages}) { - for w (`cat $p`) { - [[ $w =~ "^\(.*\)$" ]] && w=${MATCH[2,-2]} - [[ ${pages[$w]} ]] || continue - links[$p]="$w ${links[$p]}" + [[ $ZK_CACHE ]] && { + zstat -A inode +inode $p + zstat -A ctime +ctime $p + cache=(${(f)mapfile[$ZK_CACHE/$p]}) + if [[ ( ${cache[1]} = $ZK_VERSION ) && + ( ${cache[2]} = ${inode[1]} ) && + ( ${cache[3]} = ${ctime[1]} ) ]]; then + ws=(${cache[4,-1]}) + [[ $ws ]] && links[$p]=${(j: :)ws} + cached[$p]=1 + continue + fi } -} - -# Deduplicate all references -typeset -A ws -for p (${(k)links}) { ws=() - for w (${=${links[$p]}}) { - ws[$w]=1 - backs[$w]="$p ${backs[$w]}" + for w (${=mapfile[$p]}) { + [[ $w =~ "\[([^] ]+)\]" ]] || continue + w=${match[1]} + [[ ( $w =~ "/$" ) && ( ${cats[$w[1,-2]]} ) ]] && { + ws=($ws $w) + continue + } + [[ ${pages[$w]} ]] || { + [[ $ZK_SHOW_MISSING ]] && print "missing $w" + continue + } + ws=($ws $w) + } + [[ $ZK_CACHE ]] && { + zf_mkdir -p $ZK_CACHE/$p:h + ws=($ZK_VERSION ${inode[1]} ${ctime[1]} $ws) + print -l $ws > $ZK_CACHE/$p + ws=(${ws[4,-1]}) } - links[$p]=${(k)ws} + [[ $ws ]] && links[$p]=${(j: :)ws} } -for p (${(k)backs}) { - ws=() - for w (${=${backs[$p]}}) ws[$w]=1 - backs[$p]=${(k)ws} +unset cache ws +for p ws (${(kv)links}) { + for w (${=ws}) backs[$w]="$p ${backs[$w]}" } +for p ws (${(kv)backs}) backs[$p]=${(j: :)${(u)=ws}} -autoload -U relative getrel() { - local tgt=$2:a - cd $1:h - relative $tgt + # nearly the copy-paste of Functions/Misc/relative + local dst=$2:a + local src=$1:h:a + local -a cur abs + cur=(${(s:/:)src}) + abs=(${(s:/:)dst:h} $dst:t) + integer i=1 + while [[ i -le $#abs && $abs[i] == $cur[i] ]] ; do + ((++i > $#cur)) && { + REPLY=${(j:/:)abs[i,-1]} + return + } + done + src=${(j:/:)cur[i,-1]/*/..} + dst=${(j:/:)abs[i,-1]} + REPLY=$src${dst:+/$dst} } -genhtml() { +genHTML() { local page=$1 - local data - [[ $# -eq 1 ]] && data="`cat $page`" || data=$2 - local tgt - data="${data//&/&}" - data="${data///>}" - for p (${(k)pages}) { - [[ $p = ALL ]] && continue - [[ $p = index ]] && continue - tgt=`getrel $page $p` - data="${data//${p}/$p}" + local data p + [[ $# -eq 1 ]] && data=${mapfile[$page]} || data=$2 + local _links=(${(oi)=links[$page]}) + if [[ ( ${cached[$page]} ) && ( -s $ZK_CACHE/${page}.html ) ]]; then + < $ZK_CACHE/${page}.html + else + data=${data//&/&} + data=${data///>} + for p ($_links) { + getrel $page $p + [[ -d $p ]] && REPLY=$REPLY/index + data="${data//\[${p}\]/[$p]}" + } + data=" + +$page (${pages[$page]}) + +
+$data
" + if [[ $ZK_CACHE ]]; then + print -r "$data" > $ZK_CACHE/${page}.html + < $ZK_CACHE/${page}.html + else + print -r "$data" + fi + fi + if [[ $_links ]]; then + print "
Links:
    " + for p ($_links) { + getrel $page $p + print "
  • $p ${pages[$p]}
  • " + } + print "
" + fi + local bs=(${(oi)=${backs[$page]}}) + if [[ $bs ]]; then + print "
Backlinks:
    " + for p ($bs) { + getrel $page $p + print "
  • $p ${pages[$p]}
  • " + } + print "
" + fi + print "" +} + +zmodload -F zsh/datetime b:strftime +strftime -s now "%F %T" + +genIndex() { + local p + local entries=() + local _links=() + typeset -aU _cats=() + local curdepth=${#${(s:/:)1}} + (( curdepth = curdepth + 1 )) + for p (${(k)pages[(I)$1*]}) { + case ${#${(As:/:)p}} in + ($curdepth) _links=($p $_links) ;; + ( $(( $curdepth + 1 )) ) _cats=(${1}${${p#$1}%%/*} $_cats) ;; + (*) continue ;; + esac } - print "<\!DOCTYPE html> -$page
-$data
-

    " - for p (${(oi)=${backs[$page]}}) { - [[ $p = ALL ]] && continue - tgt=`getrel $page $p` - print "
  • $p
  • " + local page=${1}index + print " + + +$page ($now) +
      " + for p (${(oi)_links}) { + getrel $page $p + print "
    • $p ${pages[$p]} (${sizes[$p]} bytes)
    • " } - print "
    " + print "
" + if [[ $_cats ]]; then + print "
Subdirectories:
    " + for p (${(oi)_cats}) { + getrel $page $p/index + print "
  • $p
  • " + } + print "
" + fi + local bs=(${(oi)=${backs[$1]}}) + if [[ $bs ]]; then + print "
Backlinks:
    " + for p ($bs) { + getrel $page $p + print "
  • $p ${pages[$p]}
  • " + } + print "
" + fi + print "" } case $1 in (links) for w (${(oi)=${links[$2]}}) print $w ;; (backs) for w (${(oi)=${backs[$2]}}) print $w ;; -(html) genhtml $2 ;; +(html) genHTML $2 ;; +(html-index) genIndex $2 ;; (htmls) for p (${(k)pages}) { - local subdir=$p:h - mkdir -p $2/$subdir - genhtml $p > $2/$p.html + zf_mkdir -p $2/$p:h + genHTML $p > $2/$p.html + touch -r $p $2/$p.html } - local all="" - for p (${(oi)${(k)pages}}) all="$p\n$all" - genhtml ALL $all > $2/ALL.html + for p (${(k)cats}) genIndex $p/ > $2/$p/index.html + genIndex "" > $2/index.html + for p ("" ${(k)cats}) touch -d ${now/ /T} $2/$p/index.html ;; (*) usage ;; esac