Last active
April 29, 2026 19:23
-
-
Save yolabingo/13fefaade768ab04167d012f74bbab7a to your computer and use it in GitHub Desktop.
bash markdown preview tool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # save to ~/bin/mdview: | |
| # gh gist view 13fefaade768ab04167d012f74bbab7a --raw > ~/bin/mdview && chmod +x ~/bin/mdview | |
| # mdview - Preview markdown files with gh markdown-preview --dark-mode | |
| # Usage: mdview [OPTIONS] [file|directory] | |
| # Options: | |
| # -h, --help Show this help message | |
| # -r, --recurse-dirs Recursively search for markdown files in subdirectories | |
| # | |
| # Dependencies (brew install <name> if missing): | |
| # - gh GitHub CLI (brew install gh) | |
| # - gh extension: yusukebe/gh-markdown-preview (gh extension install yusukebe/gh-markdown-preview) | |
| # - fzf Fuzzy finder for multi-file selection (brew install fzf) | |
| # | |
| # gh must be authenticated: gh auth login | |
| set -euo pipefail | |
| show_help() { | |
| cat <<EOF | |
| Usage: mdview [OPTIONS] [file|directory] | |
| Preview markdown files using GitHub's markdown-preview extension. | |
| OPTIONS: | |
| -h, --help Show this help message | |
| -r, --recurse-dirs Recursively search for markdown files in subdirectories | |
| EXAMPLES: | |
| mdview file.md # Preview a specific file | |
| mdview # Preview markdown files in current directory | |
| mdview ~/projects # Preview markdown files in a directory | |
| mdview -r ~/projects # Recursively search for markdown files | |
| EOF | |
| } | |
| check_deps() { | |
| local missing=() | |
| if ! command -v gh &>/dev/null; then | |
| missing+=("gh") | |
| fi | |
| if ! command -v fzf &>/dev/null; then | |
| missing+=("fzf") | |
| fi | |
| if [[ ${#missing[@]} -gt 0 ]]; then | |
| echo "Missing dependencies. Install:" | |
| for dep in "${missing[@]}"; do | |
| echo " brew install $dep" | |
| done | |
| exit 1 | |
| fi | |
| if ! gh auth status &>/dev/null; then | |
| echo "gh CLI not authenticated. Run: gh auth login" | |
| exit 1 | |
| fi | |
| if ! gh extension list | grep -q "markdown-preview"; then | |
| echo "Missing gh extension. Install:" | |
| echo " gh extension install yusukebe/gh-markdown-preview" | |
| exit 1 | |
| fi | |
| } | |
| open_preview() { | |
| local file="$1" | |
| local full_path | |
| full_path=$(cd "$(dirname "$file")" && pwd)/$(basename "$file") | |
| echo "✓ Opening: $full_path" | |
| echo | |
| gh markdown-preview --dark-mode "$file" | |
| } | |
| target="." | |
| recurse=false | |
| # Parse arguments | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| -h | --help) | |
| show_help | |
| exit 0 | |
| ;; | |
| -r | --recurse-dirs) | |
| recurse=true | |
| shift | |
| ;; | |
| *) | |
| target="$1" | |
| shift | |
| ;; | |
| esac | |
| done | |
| check_deps | |
| # If target is a file, preview it directly | |
| if [[ -f "$target" ]]; then | |
| open_preview "$target" | |
| exit 0 | |
| fi | |
| # If target is a directory, use fzf to select a markdown file | |
| if [[ -d "$target" ]]; then | |
| markdown_files=() | |
| if [[ "$recurse" == true ]]; then | |
| while IFS= read -r f; do markdown_files+=("$f"); done < <(find "$target" -name "*.md" -type f | sort) | |
| else | |
| while IFS= read -r f; do markdown_files+=("$f"); done < <(find "$target" -maxdepth 1 -name "*.md" -type f | sort) | |
| fi | |
| if [[ ${#markdown_files[@]} -eq 0 ]]; then | |
| echo "No markdown files found in '$target'" | |
| exit 1 | |
| fi | |
| # If only one file found, open it directly | |
| if [[ ${#markdown_files[@]} -eq 1 ]]; then | |
| open_preview "${markdown_files[0]}" | |
| exit 0 | |
| fi | |
| # Multiple files: use fzf to select | |
| selected=$(printf '%s\n' "${markdown_files[@]}" | fzf --prompt "Select markdown file: ") | |
| if [[ -n "$selected" ]]; then | |
| open_preview "$selected" | |
| else | |
| echo "No markdown file selected" | |
| exit 1 | |
| fi | |
| exit 0 | |
| fi | |
| echo "Error: '$target' is neither a file nor a directory" | |
| exit 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment