# blog -- blogging aliases and functions
# ============================================================================
# BIN WRAPPERS
# ============================================================================
alias bnew='blog-new'
alias bstats='blog-stats'
alias blinks='blog-links'
alias blinkrot='blog-linkrot'
alias bback='blog-backlinks'
alias bfront='blog-frontmatter'
alias bbuild='blog-build-check'
alias brss='blog-rss-check'
alias bfdates='blog-future-dates'
alias bshot='blog-screenshot'
alias btitle='blog-title'
alias barch='blog-archive-url'
alias bai='blog-ai-review'
alias bdrafts='blog-draft-index'
# ============================================================================
# CONTENT SEARCH
# ============================================================================
alias bposts='find . \( -path "*/.git" -o -path "*/node_modules" -o -path "*/.next" -o -path "*/_site" -o -path "*/public" \) -prune -o \( -name "*.md" -o -name "*.mdx" -o -name "*.org" \) -print'
alias btodos='rg -n --glob "*.md" --glob "*.mdx" --glob "*.org" "TK|TODO|FIXME|XXX|REVIEW|SOURCE\\?"'
alias btypos='rg -n --glob "*.md" --glob "*.mdx" "\\b(teh|recieve|seperate|occured|wich|whcih|buitl|direcotry)\\b"'
alias bdates='rg -n --glob "*.md" --glob "*.mdx" "^(date|created|updated|modified|start_date):"'
alias btitles='rg -n --glob "*.md" --glob "*.mdx" "^(title:|# )"'
alias btags='rg -n --glob "*.md" --glob "*.mdx" "^(tags|topics|category|categories):"'
alias boutlinks='blog-links | sort -u'
alias boutdomains='blog-links | awk -F/ "/^https?:/{print \$3}" | sort | uniq -c | sort -nr'
# ============================================================================
# GIT INTEGRATION
# ============================================================================
alias bchanged='git diff --name-only -- "*.md" "*.mdx" "*.org"'
alias bstaged='git diff --cached --name-only -- "*.md" "*.mdx" "*.org"'
alias bworddiff='git diff --word-diff=color -- "*.md" "*.mdx" "*.org"'
# ============================================================================
# UTILITIES
# ============================================================================
alias bserve='python3 -m http.server 8000'
alias bfeed='find . -name "*.xml" -o -name "*.atom" -o -name "feed*" | sort'
alias bimages='find . \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" -o -name "*.webp" -o -name "*.gif" -o -name "*.svg" \) -print'
alias bbig='find . -type f -size +5M -not -path "*/.git/*" -print'
alias bempty='find . -type f \( -name "*.md" -o -name "*.mdx" -o -name "*.org" \) -size 0 -print'
alias bdups='find . -type f \( -name "*.md" -o -name "*.mdx" \) -print0 | xargs -0 awk "{print FILENAME \":\" FNR \":\" \$0}" | rg -n "\\b([[:alpha:]]+)\\s+\\1\\b"'
alias bsentences='perl -0777 -ne "while(/[A-Z][^.!?]{180,}[.!?]/g){print \"$ARGV:$.: $&\\n\"}"'
# ============================================================================
# PANDOC
# ============================================================================
alias bmd2html='pandoc --from=gfm --to=html5 --standalone'
alias bmd2docx='pandoc --from=gfm --to=docx'
alias bmd2epub='pandoc --from=gfm --to=epub3'
# ============================================================================
# URL EXTRACTION
# ============================================================================
alias bhtmltitles='rg -n "<title>|<h1"'
alias burls='rg -o "https?://[^\\]\\[()<>\"'"'"'[:space:]]+"'
alias burls-md='rg -o "\\[[^]]+\\]\\(https?://[^)]+\\)"'
# ============================================================================
# ARCHIVING
# ============================================================================
alias barchivequeue='blog-links | sort -u > archive-queue.txt'
alias barchivefeed='while read -r url; do blog-archive-url "$url"; done < archive-queue.txt'
# ============================================================================
# LLM REVIEW
# ============================================================================
alias bllm-summary='llm -s "Summarize this draft in 5 bullet points. Flag weak claims and missing sources."'
alias bllm-title='llm -s "Suggest 20 concise titles. Avoid clickbait. Return one per line."'
alias bllm-outline='llm -s "Turn this draft into a tight outline. Preserve the argument order."'
alias bllm-counter='llm -s "Act as a skeptical editor. List the strongest objections and missing evidence."'
alias bprompt='files-to-prompt . -e md -e mdx --ignore node_modules --ignore .git --ignore .next --markdown'
# ============================================================================
# FUNCTIONS
# ============================================================================
blog_root() {
git rev-parse --show-toplevel 2>/dev/null || pwd
}
blog_post_dirs() {
root=$(blog_root)
for d in content posts post blog notes garden essays articles src/content src/pages _posts pages; do
[ -d "$root/$d" ] && printf '%s\n' "$root/$d"
done
}
blog_posts() {
if [ "$#" -gt 0 ]; then
printf '%s\n' "$@"
return
fi
dirs=$(blog_post_dirs)
if [ -n "$dirs" ]; then
printf '%s\n' "$dirs" | while IFS= read -r d; do
find "$d" -type f \( -name '*.md' -o -name '*.mdx' -o -name '*.org' \)
done
else
find . \( -path '*/.git' -o -path '*/node_modules' -o -path '*/.next' -o -path '*/_site' \) -prune -o -type f \( -name '*.md' -o -name '*.mdx' -o -name '*.org' \) -print
fi
}
blog_slug() {
printf '%s' "$*" |
tr '[:upper:]' '[:lower:]' |
sed -e 's/[^a-z0-9]/-/g' -e 's/-\{2,\}/-/g' -e 's/^-//' -e 's/-$//'
}
blog_words() {
blog_posts "$@" | while IFS= read -r f; do
[ -f "$f" ] || continue
words=$(sed -e '/^---$/,/^---$/d' "$f" | wc -w | tr -d ' ')
printf '%7s %s\n' "$words" "$f"
done | sort -nr
}
blog_recent() {
blog_posts "$@" | xargs -r ls -lt | sed -n '1,40p'
}
blog_find() {
if [ "$#" -eq 0 ]; then
printf 'usage: blog_find PATTERN\n' >&2
return 2
fi
blog_posts | xargs -r rg -n -- "$@"
}
blog_titles() {
blog_posts "$@" | while IFS= read -r f; do
title=$(sed -n -e 's/^title:[[:space:]]*//p' -e 's/^# //p' "$f" | sed -n '1p')
[ -n "$title" ] || title="(untitled)"
printf '%s\t%s\n' "$title" "$f"
done
}
blog_extract_links() {
blog-links "$@"
}
blog_archive_queue() {
out="${1:-archive-queue.txt}"
shift 2>/dev/null || true
blog-links "$@" | sort -u > "$out"
printf '%s\n' "$out"
}
blog_archive_all() {
queue="${1:-archive-queue.txt}"
[ -f "$queue" ] || blog_archive_queue "$queue" >/dev/null
while IFS= read -r url; do
[ -n "$url" ] && blog-archive-url "$url"
done < "$queue"
}
blog_changed_posts() {
git diff --name-only -- '*.md' '*.mdx' '*.org'
}
blog_staged_posts() {
git diff --cached --name-only -- '*.md' '*.mdx' '*.org'
}
blog_review_changed() {
files=$(blog_changed_posts)
[ -n "$files" ] || return 0
printf '%s\n' "$files" | while IFS= read -r f; do
blog-ai-review "$f"
done
}
blog_reading_time() {
blog_posts "$@" | while IFS= read -r f; do
[ -f "$f" ] || continue
words=$(wc -w < "$f" | tr -d ' ')
mins=$(( (words + 224) / 225 ))
printf '%3s min %7s words %s\n' "$mins" "$words" "$f"
done | sort -n
}
blog_tk_context() {
blog_posts "$@" | xargs -r rg -n -C 2 'TK|TODO|FIXME|XXX|SOURCE\?|CITE\?'
}
blog_domain_counts() {
blog-links "$@" | awk -F/ '/^https?:/{print $3}' | sed 's/^www\.//' | sort | uniq -c | sort -nr
}