website

My personal website
git clone https://codeberg.org/emmett1/website
Log | Files | Refs | README | LICENSE

index.sh (7629B)


      1 #!/bin/sh
      2 # index.sh - generate index.html for current directory
      3 
      4 humansize() {
      5   size=$1
      6   if [ "$size" -lt 1024 ]; then
      7     echo "${size} B"
      8   elif [ "$size" -lt $((1024*1024)) ]; then
      9     awk "BEGIN { printf \"%.1f KB\", $size/1024 }"
     10   elif [ "$size" -lt $((1024*1024*1024)) ]; then
     11     awk "BEGIN { printf \"%.1f MB\", $size/1024/1024 }"
     12   else
     13     awk "BEGIN { printf \"%.1f GB\", $size/1024/1024/1024 }"
     14   fi
     15 }
     16 
     17 genhtml() {
     18   OUTPUT="index.html"
     19   
     20   title=$([ "$subdir" ] && echo /home/${PWD##*/} || echo /home)
     21 
     22   {
     23   echo "<!DOCTYPE html>"
     24   echo "<html lang=\"en\">"
     25   echo "<head>"
     26   echo "  <meta charset=\"UTF-8\">"
     27   echo "  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
     28   echo "  <title>${title##*/} | emmett1.my</title>"
     29   echo "  <link rel=\"icon\" href=\"/assets/pixelfox.png\" type=\"image/png\">"
     30   echo "  <style>
     31   body { font-family: monospace; background: #1e1e1e; color: #e0e0e0; margin: 0; padding: 1em; max-width: 60em; margin-left: auto; margin-right: auto; font-size: 14px; }
     32   table { width: 100%; border-collapse: collapse; }
     33   th { padding: 0.4em 0.6em; border-bottom: 1px solid #393939; font-size: 0.9em; text-align: left; }
     34   td { padding: 0.4em 0.6em; border-bottom: 1px solid #2a2a2a; }
     35   th.name, td.name { text-align: left; }
     36   th.meta, td.meta { text-align: right; white-space: nowrap; }
     37   td.meta .date { display: inline-block; min-width: 150px; margin-right: 12px; text-align: right; }
     38   td.meta .size { display: inline-block; width: 80px; text-align: right; }
     39   a { color: #4ea1ff; text-decoration: none; }
     40   a:hover { text-decoration: underline; }
     41   pre.readme { margin-top: 2em; padding: 1em; background: #2a2a2a; border-radius: 4px; white-space: pre-wrap; }
     42   footer { margin-top: 2em; text-align: center; font-size: 0.9em; color: #888; }
     43   code { background: #333; color: #ffcc66; padding: 0.1em 0.3em; border-radius: 3px; font-family: monospace; }
     44   pre code { background: none; color: inherit; padding: 0; border-radius: 0; }
     45   @media (max-width: 600px) {
     46     thead { display: none; }
     47     tbody tr { display: block; padding: 0.6em 0; border-bottom: 1px solid #2a2a2a; }
     48     td { display: block; border: none; padding: 0.2em 0; }
     49     td.name { font-weight: 600; }
     50     td.meta { display: flex; justify-content: space-between; font-size: 0.9em; color: #bbb; }
     51     td.meta .date, td.meta .size { min-width: 0; margin: 0; width: auto; text-align: left; }
     52   }
     53   </style>"
     54   echo "</head>"
     55   echo "<body>"
     56   echo "<h1>index of $title</h1>"
     57   echo "<table>"
     58   echo "<thead><tr><th class=\"name\">name</th><th class=\"meta\">last modified & size</th></tr></thead>"
     59   echo "<tbody>"
     60   
     61   if [ "$subdir" ]; then
     62     echo "<tr><td class=\"name\"><a href=\"../\">../</a></td><td class=\"meta\"><span class=\"date\">-</span><span class=\"size\">-</span></td></tr>"
     63   fi
     64 
     65   # List files
     66   for f in *; do
     67     case $f in
     68       *.html) continue;;
     69     esac
     70     [ "$f" = "." ] && continue
     71     [ "$f" = ".." ] && continue
     72     [ "$f" = "README" ] && continue
     73     [ "$f" = "LICENSE" ] && continue
     74     [ "$f" = "index.sh" ] && continue
     75     [ "$f" = "assets" ] && continue
     76     [ "$f" = "images" ] && continue
     77 
     78     if [ -e "$f" ]; then
     79       mod=$(date -r "$f" +"%Y-%m-%d %H:%M")
     80       if [ -d "$f" ]; then
     81         size="-"
     82       else
     83         bytes=$(stat -c%s "$f")
     84         size=$(humansize "$bytes")
     85       fi
     86 
     87       if [ -f "$f" ] && echo "$f" | grep -qE '\.txt$'; then
     88         txt_html="${f}.html"
     89         {
     90           echo "<!DOCTYPE html>"
     91           echo "<html lang=\"en\">"
     92           echo "<head>"
     93           echo "  <meta charset=\"UTF-8\">"
     94           echo "  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
     95           echo "  <title>$f | emmett1.my</title>"
     96           echo "  <link rel=\"icon\" href=\"/assets/pixelfox.png\" type=\"image/png\">"
     97           cat <<'EOF'
     98 <style>
     99   body { font-family: monospace; background: #1e1e1e; color: #e0e0e0; margin: 0; padding: 1em; max-width: 60em; margin-left: auto; margin-right: auto; font-size: 14px; }
    100   a { color: #4ea1ff; text-decoration: none; }
    101   a:hover { text-decoration: underline; }
    102   pre { padding: 1em; background: #2a2a2a; border-radius: 4px; white-space: pre-wrap; }
    103   footer { margin-top: 2em; text-align: center; font-size: 0.9em; color: #888; }
    104   blockquote { margin: 0.5em 0; padding-left: 1em; border-left: 3px solid #4ea1ff; color: #ccc; }
    105   img { max-width: 100%; margin: 0.5em 0; display: block; }
    106   code { background: #333; color: #ffcc66; padding: 0.1em 0.3em; border-radius: 3px; font-family: monospace; }
    107   pre code { background: none; color: inherit; padding: 0; border-radius: 0; }
    108 </style>
    109 EOF
    110           echo "</head>"
    111           echo "<body>"
    112           echo "<h1>$f</h1>"
    113           in_code=0
    114           while IFS= read -r line || [ -n "$line" ]; do
    115             if [ "$line" = '```' ]; then
    116               if [ $in_code -eq 0 ]; then
    117                 printf '<pre><code>'
    118                 in_code=1
    119               else
    120                 echo '</code></pre>'
    121                 in_code=0
    122               fi
    123               continue
    124             fi
    125 
    126             if [ $in_code -eq 1 ]; then
    127               printf '%s\n' "$line" | sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g'
    128               continue
    129             fi
    130 
    131             # Images
    132             if printf '%s\n' "$line" | grep -q '!\['; then
    133               line=$(printf '%s' "$line" | sed -E 's/!\[([^]]*)\]\(([^)]*)\)/<img src="\2" alt="\1">/g')
    134             fi
    135 
    136             # Blockquotes
    137             if printf '%s\n' "$line" | grep -q '^>'; then
    138               safe=$(printf '%s' "$line" | sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g')
    139               line="<blockquote>${safe#&gt; }</blockquote>"
    140             fi
    141 
    142             # Plain text (escape, inline code, URLs, bold, links)
    143             if ! echo "$line" | grep -qE '<(img|blockquote)'; then
    144               # Escape text
    145               line=$(printf '%s' "$line" | sed -e 's/&/\&amp;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g')
    146 
    147               # Inline code
    148               line=$(printf '%s' "$line" | sed -E 's/`([^`]+)`/<code>\1<\/code>/g')
    149 
    150               # Bold (**bold**)
    151               line=$(printf '%s' "$line" | sed -E 's/\*\*([^*]+)\*\*/<b>\1<\/b>/g')
    152 
    153               # Auto-link raw URLs
    154               line=$(printf '%s' "$line" | sed -E 's#(https?://[^ ]+)#<a href="\1">\1</a>#g')
    155               
    156               # Markdown links [text](url) (no https://)
    157               line=$(printf '%s' "$line" | sed -E 's/\[([^]]+)\]\(([^)]+)\)/<a href="\2">\1<\/a>/g')
    158             fi
    159 
    160             # Preserve empty lines
    161             if [ -z "$line" ]; then
    162               echo "<br>"
    163             else
    164               echo "$line<br>"
    165             fi
    166           done < "$f"
    167 
    168           echo "<footer><a href=\"index.html\">back to index</a> — generated by index.sh on $(date)</footer>"
    169           echo "</body>"
    170           echo "</html>"
    171         } > "$txt_html"
    172 
    173         echo "<tr><td class=\"name\"><a href=\"$txt_html\">$f</a></td><td class=\"meta\"><span class=\"date\">$mod</span><span class=\"size\">$size</span></td></tr>"
    174       else
    175         echo "<tr><td class=\"name\"><a href=\"$f\">$f$([ -d $f ] && echo /)</a></td><td class=\"meta\"><span class=\"date\">$mod</span><span class=\"size\">$size</span></td></tr>"
    176       fi
    177     fi
    178   done
    179 
    180   echo "</tbody>"
    181   echo "</table>"
    182 
    183   if [ -f README ]; then
    184     echo "<pre class=\"readme\">"
    185     cat README
    186     echo "</pre>"
    187   fi
    188 
    189   echo "<footer>generated by index.sh on $(date)</footer>"
    190   echo "</body>"
    191   echo "</html>"
    192   } > "$OUTPUT"
    193 }
    194 
    195 genhtml
    196 
    197 subdir=1
    198 for d in *; do
    199   [ -d "$d" ] || continue
    200   (
    201     cd "$d"
    202     genhtml
    203   )
    204 done