#!/bin/bash # Usage: ./md2data_safe.sh FILE [--css CSS_FILE] [--size LIMIT] # Converts HTML or Markdown to Base64 Data URL # Default size limit is 30000 characters # ----------------- Functions ----------------- show_help() { echo "Usage: $0 FILE [--css CSS_FILE] [--size LIMIT]" echo echo "Parameters:" echo " FILE HTML or Markdown file to convert" echo " --css FILE Optional single CSS file to inject" echo " --size LIMIT Optional maximum size for Data URL (default: 30000)" exit 0 } check_file_exists() { local file="$1" if [ ! -f "$file" ]; then echo "Error: file '$file' not found." >&2 exit 1 fi } convert_md_to_html() { local file="$1" if ! command -v pandoc >/dev/null 2>&1; then echo "Error: pandoc is not installed." >&2 exit 1 fi pandoc "$file" -f markdown -t html -s } minify_css() { local css_file="$1" tr -d '\n' < "$css_file" | sed -E 's/[[:space:]]+/ /g;s/ *{ */{/g;s/ *} */}/g;s/ *; */;/g' } escape_css_for_sed() { local css="$1" css=${css//\\/\\\\} # Escape backslash css=${css//\//\\/} # Escape slashes css=${css//&/\\&} # Escape & echo "$css" } inject_css() { local html_file="$1" local css="$2" local escaped_css escaped_css=$(escape_css_for_sed "$css") if grep -q "" "$html_file"; then sed "/<\/head>/i " "$html_file" else echo "" cat "$html_file" fi } generate_data_url() { if base64 --help 2>&1 | grep -q -- '-w'; then base64 -w 0 else base64 fi } check_size() { local size="$1" local limit="$2" echo "Data URL size: $size characters" if [ "$size" -gt "$limit" ]; then echo "WARNING: Data URL exceeds recommended limit of $limit characters." else echo "Data URL is within a safe size for most browsers." fi } # ----------------- Argument Parsing ----------------- CSS_FILE="" LIMIT=30000 FILE="" while [[ $# -gt 0 ]]; do case "$1" in --help|-h) show_help ;; --css) CSS_FILE="$2" shift 2 ;; --size) LIMIT="$2" shift 2 ;; -*) echo "Unknown option: $1" >&2 exit 1 ;; *) FILE="$1" shift ;; esac done if [[ -z "$FILE" ]]; then show_help fi check_file_exists "$FILE" EXT="${FILE##*.}" # ----------------- Main Processing ----------------- # Temporary HTML file for streaming TMP_HTML=$(mktemp) trap 'rm -f "$TMP_HTML"' EXIT # Convert Markdown or copy HTML if [[ "$EXT" == "md" ]]; then convert_md_to_html "$FILE" > "$TMP_HTML" else cp "$FILE" "$TMP_HTML" fi # Minify and inject CSS if provided if [[ -n "$CSS_FILE" ]]; then check_file_exists "$CSS_FILE" MIN_CSS=$(minify_css "$CSS_FILE") TMP_HTML_INJECTED=$(mktemp) inject_css "$TMP_HTML" "$MIN_CSS" > "$TMP_HTML_INJECTED" mv "$TMP_HTML_INJECTED" "$TMP_HTML" echo "Injected CSS size: ${#MIN_CSS} characters" fi # Generate Base64 Data URL DATA_URL="data:text/html;charset=utf-8;base64,$(generate_data_url < "$TMP_HTML")" # Check size SIZE=${#DATA_URL} check_size "$SIZE" "$LIMIT" # Display clickable HTML link echo echo "Clickable HTML link:" echo "Open $FILE"