mmdflux 2.1.0

Render Mermaid diagrams as Unicode text, ASCII, SVG, and MMDS JSON.
Documentation
#!/usr/bin/env bash
# Usage: scripts/view [file.mmd] [-- extra cargo run args...]
#        cat file.mmd | scripts/view [-- extra cargo run args...]
#
# Defaults: -f svg --edge-preset step
# Override any default by passing it explicitly after --
#
# Examples:
#   scripts/view tests/fixtures/flowchart/simple.mmd
#   scripts/view tests/fixtures/flowchart/simple.mmd -- --edge-preset basis
#   cat file.mmd | scripts/view

set -euo pipefail

SCALE=2
BG="white"

# Query terminal background color via OSC 11 (works in Ghostty, Kitty, WezTerm, etc.)
# Returns perceived luminance 0-255, or 255 (light) on failure.
query_bg_lum() {
    [[ -t 1 ]] || { echo 255; return; }

    local old_stty response
    old_stty=$(stty -g 2>/dev/null) || { echo 255; return; }
    stty raw -echo min 0 time 0

    # OSC 11 query: ESC ] 11 ; ? ST
    printf '\033]11;?\033\\' >/dev/tty

    # Read response with short timeout; terminals terminate with BEL or ST
    response=""
    IFS= read -r -t 0.3 -d $'\a' response </dev/tty 2>/dev/null \
        || IFS= read -r -t 0.3 response </dev/tty 2>/dev/null \
        || true

    stty "$old_stty" 2>/dev/null

    # Parse rgb:RRRR/GGGG/BBBB (16-bit components; take upper byte)
    if [[ "$response" =~ rgb:([0-9a-fA-F]+)/([0-9a-fA-F]+)/([0-9a-fA-F]+) ]]; then
        local r g b
        r=$(( 16#${BASH_REMATCH[1]:0:2} ))
        g=$(( 16#${BASH_REMATCH[2]:0:2} ))
        b=$(( 16#${BASH_REMATCH[3]:0:2} ))
        echo $(( (r * 299 + g * 587 + b * 114) / 1000 ))
    else
        echo 255
    fi
}

lum=$(query_bg_lum)
if (( lum < 128 )); then
    BG="black"
fi

# Default mmdflux flags (can be overridden by passing them explicitly)
MMDFLUX_DEFAULTS=(-f svg --edge-preset step)

# Split args: optional file, then optional -- extra-flags
FILE=""
EXTRA_ARGS=()

if [[ $# -gt 0 && "$1" != "--" && -f "$1" ]]; then
    FILE="$1"
    shift
fi

if [[ $# -gt 0 && "$1" == "--" ]]; then
    shift
    EXTRA_ARGS=("$@")
fi

# Pick display command: kitten icat in Kitty (graphics protocol), chafa elsewhere
if [[ -n "${KITTY_WINDOW_ID:-}" ]]; then
    DISPLAY_CMD=(kitten icat)
else
    DISPLAY_CMD=(chafa)
fi

# Remove defaults that the user explicitly overrides
MERGED_ARGS=()
for (( i=0; i<${#MMDFLUX_DEFAULTS[@]}; i++ )); do
    flag="${MMDFLUX_DEFAULTS[i]}"
    # Check if this flag appears in EXTRA_ARGS (user override wins)
    override=false
    for extra in "${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}"; do
        if [[ "$extra" == "$flag" ]]; then
            override=true
            break
        fi
    done
    if $override; then
        # Skip this default flag and its value
        (( i++ )) || true
    else
        MERGED_ARGS+=("$flag")
        if (( i + 1 < ${#MMDFLUX_DEFAULTS[@]} )) && [[ "${MMDFLUX_DEFAULTS[i+1]}" != --* ]]; then
            (( i++ ))
            MERGED_ARGS+=("${MMDFLUX_DEFAULTS[i]}")
        fi
    fi
done

# Run the pipeline
if [[ -n "$FILE" ]]; then
    INPUT_CMD=(cat "$FILE")
else
    INPUT_CMD=(cat)
fi

"${INPUT_CMD[@]}" \
    | cargo run -q -- "${MERGED_ARGS[@]}" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"} \
    | rsvg-convert --background-color="$BG" -z "$SCALE" \
    | "${DISPLAY_CMD[@]}"