techkaczynski.dev / code

summaryrefslogtreecommitdiff
path: root/mdview.sh
diff options
context:
space:
mode:
authortech kaczynski <tk@techkaczynski.dev>2026-09-24 21:50:26 +1000
committertech kaczynski <tk@techkaczynski.dev>2026-09-24 21:50:26 +1000
commite2914e36b269eb292ce56e2cf7baa71d11280acf (patch)
tree2d46c2c3dbf31372f6f1938929d2a7ca9eaf3033 /mdview.sh
initial commit.main
Diffstat (limited to 'mdview.sh')
-rwxr-xr-xmdview.sh166
1 files changed, 166 insertions, 0 deletions
diff --git a/mdview.sh b/mdview.sh
new file mode 100755
index 0000000..1f95105
--- /dev/null
+++ b/mdview.sh
@@ -0,0 +1,166 @@
+#!/bin/sh
+
+# mdview - simple markdown viewer
+# Usage: mdview [--light|--dark|--auto] [--live] <file.md>
+
+theme="auto"
+live_mode=0
+filename=""
+# lang="en" - maybe support language tags later
+
+for arg in "$@"; do
+ case "$arg" in
+ --light) theme="light" ;;
+ --dark) theme="dark" ;;
+ --auto) theme="auto" ;;
+ --live|-w) live_mode=1 ;;
+ --help|-h)
+ echo "Usage: mdview [--light|--dark|--auto] [--live] <file.md>"
+ echo " --light Light theme"
+ echo " --dark Dark theme"
+ echo " --auto Follow system (default)"
+ echo " --live Watch file for changes"
+ exit 0
+ ;;
+ *) filename="$arg" ;;
+ esac
+done
+
+if [ -z "$filename" ]; then
+ echo "Usage: mdview [--light|--dark|--auto] [--live] <file.md>" >&2
+ exit 1
+fi
+
+# Resolve the base directory for relative paths
+if [ "$filename" = "-" ]; then
+ base_dir="file://$(pwd)/"
+else
+ base_dir="file://$(cd "$(dirname "$filename")" && pwd)/"
+fi
+
+case "$theme" in
+ light)
+ css_file="$HOME/.config/mdview/github-markdown-light.css"
+ page_background="#ffffff"
+ page_scheme="light"
+ ;;
+ dark)
+ css_file="$HOME/.config/mdview/github-markdown-dark.css"
+ page_background="#0d1117"
+ page_scheme="dark"
+ ;;
+ auto)
+ css_file="$HOME/.config/mdview/github-markdown.css"
+ page_background="Canvas"
+ page_scheme="light dark"
+ ;;
+esac
+
+html() {
+ if [ "$filename" = "-" ]; then
+ body=$(cat | cmark-gfm --width 80 --unsafe)
+ else
+ body=$(cmark-gfm --width 80 --unsafe "$filename")
+ fi
+
+ cat <<EOF
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <base href="$base_dir">
+ <style>
+ :root {
+ color-scheme: $page_scheme;
+ }
+
+ html,
+ body {
+ min-height: 100%;
+ }
+
+ body {
+ margin: 0;
+ background-color: $page_background;
+ }
+
+ .markdown-body {
+ box-sizing: border-box;
+ min-width: 200px;
+ max-width: 980px;
+ min-height: 100vh;
+ margin: 0 auto;
+ padding: 45px;
+ }
+
+ @media (max-width: 767px) {
+ .markdown-body {
+ padding: 15px;
+ }
+ }
+ </style>
+</head>
+<body>
+ <article class="markdown-body">
+$body
+ </article>
+</body>
+</html>
+EOF
+}
+
+if [ "$live_mode" -eq 1 ]; then
+ if [ "$filename" = "-" ]; then
+ echo "mdview: --live cannot be used with standard input" >&2
+ exit 1
+ fi
+
+ tmp=$(mktemp /tmp/mdview_live_XXXXXX.html)
+ surf_pid=""
+
+ cleanup() {
+ [ -n "$surf_pid" ] && kill "$surf_pid" 2>/dev/null
+ rm -f "$tmp"
+ }
+
+ render() {
+ html > "$tmp" || return 1
+
+ if [ -n "$surf_pid" ]; then
+ kill -HUP "$surf_pid" 2>/dev/null || return 1
+ fi
+ }
+
+ trap cleanup EXIT INT TERM
+
+ render || exit 1
+
+ echo "Live preview: $filename (theme: $theme)"
+ echo "Press Ctrl+C to stop"
+
+ # -d disables surf's disk cache.
+ surf -d -C "$css_file" "$tmp" &
+ surf_pid=$!
+
+ old_sum=$(cksum < "$filename") || exit 1
+
+ while kill -0 "$surf_pid" 2>/dev/null; do
+ sleep 1
+
+ new_sum=$(cksum < "$filename") || continue
+ [ "$new_sum" = "$old_sum" ] && continue
+
+ old_sum=$new_sum
+
+ if render; then
+ echo "Updated: $filename"
+ fi
+ done
+else
+ tmp=$(mktemp /tmp/mdview_XXXXXX.html)
+ html > "$tmp"
+ surf -C "$css_file" "$tmp"
+ rm -f "$tmp"
+fi
+