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/&/\&/g' -e 's/</\</g' -e 's/>/\>/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/&/\&/g' -e 's/</\</g' -e 's/>/\>/g') 139 line="<blockquote>${safe#> }</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/&/\&/g' -e 's/</\</g' -e 's/>/\>/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