Files
bin/doc_rust_generate.sh
Sebastian Krüger e93c7d917e Fix doc_rust_generate.sh script execution and add theme-specific CSS selectors
Fixed critical bugs preventing script execution:
- Fixed verbose() function return code causing exit with set -e
- Fixed check_dependencies() missing return 0
- Removed spinner that was hanging with set -euo pipefail
- Added progress messages for cargo doc execution

Enhanced CSS theming:
- Wrapped CSS variables in :root[data-theme="dark"] selector
- Added :root[data-theme="light"] variant with inverted colors
- Higher specificity to override rustdoc default rules
- Light theme uses lighter backgrounds and darker text for proper contrast

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 03:43:41 +01:00

843 lines
26 KiB
Bash
Executable File

#!/usr/bin/env bash
##############################################################
# Rust Documentation Generator with Custom Themes
# Generates beautiful Rust documentation with custom color schemes
##############################################################
set -euo pipefail
# Color definitions using tput
RED="" GREEN="" YELLOW="" BLUE="" MAGENTA="" CYAN="" BOLD="" DIM="" RESET=""
if [[ -t 1 ]] && command -v tput >/dev/null 2>&1; then
COLORS=$(tput colors 2>/dev/null || echo 0)
if [[ ${COLORS:-0} -ge 8 ]]; then
RED=$(tput setaf 1 2>/dev/null || echo "")
GREEN=$(tput setaf 2 2>/dev/null || echo "")
YELLOW=$(tput setaf 3 2>/dev/null || echo "")
BLUE=$(tput setaf 4 2>/dev/null || echo "")
MAGENTA=$(tput setaf 5 2>/dev/null || echo "")
CYAN=$(tput setaf 6 2>/dev/null || echo "")
BOLD=$(tput bold 2>/dev/null || echo "")
DIM=$(tput dim 2>/dev/null || echo "")
RESET=$(tput sgr0 2>/dev/null || echo "")
fi
fi
# Script paths
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly ASSETS_DIR="${SCRIPT_DIR}/assets/doc_rust_generate"
readonly THEME_DIR="${ASSETS_DIR}/theme"
readonly TMP_DIR="${SCRIPT_DIR}/tmp"
# Default values
OUTPUT_DIR="${PWD}/output"
PRIMARY_COLOR="#ff69b4" # Default pink
STYLE="slate"
FONT_SANS="Inter"
FONT_MONO="JetBrains Mono"
INPUT_FILES=()
VERBOSE=false
DRY_RUN=false
SERVE=false
OPEN=false
SERVE_PORT=8000
# Style color mappings (neutral background colors)
declare -A STYLE_COLORS=(
["slate"]="#64748b"
["zinc"]="#71717a"
["neutral"]="#737373"
["stone"]="#78716c"
["gray"]="#6b7280"
)
##############################################################
# UI Functions
##############################################################
info() {
echo "${BLUE}${BOLD}==>${RESET} $*"
}
success() {
echo "${GREEN}${BOLD}[OK]${RESET} $*"
}
error() {
echo "${RED}${BOLD}[ERROR]${RESET} $*" >&2
}
warning() {
echo "${YELLOW}${BOLD}[WARN]${RESET} $*"
}
verbose() {
if [[ "$VERBOSE" == true ]]; then
echo "${DIM} -> $*${RESET}"
fi
return 0
}
# Spinner for long-running operations
spinner() {
local pid=$1
local message=$2
local delay=0.1
local spinstr='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
# Only show spinner if not verbose and output is a terminal
if [[ "$VERBOSE" == true ]] || [[ ! -t 1 ]]; then
wait "$pid"
return $?
fi
echo -n "${message} "
while kill -0 "$pid" 2>/dev/null; do
local temp=${spinstr#?}
printf "${CYAN}%c${RESET} " "$spinstr"
spinstr=$temp${spinstr%"$temp"}
sleep $delay
printf "\b\b\b"
done
wait "$pid"
local exit_code=$?
if [[ $exit_code -eq 0 ]]; then
printf "${GREEN}${RESET}\n"
else
printf "${RED}${RESET}\n"
fi
return $exit_code
}
##############################################################
# Help and Usage
##############################################################
show_help() {
cat << EOF
${BOLD}${MAGENTA}Rust Documentation Generator with Custom Themes${RESET}
${BOLD}USAGE:${RESET}
$(basename "$0") [OPTIONS] <inputs...>
${BOLD}DESCRIPTION:${RESET}
Generate beautiful Rust documentation with custom color schemes and styling.
Supports various input types including Rust projects, individual files, and more.
${BOLD}ARGUMENTS:${RESET}
<inputs> Input file(s) or pattern(s) to document:
- Rust project directories (containing Cargo.toml)
- Individual .rs files
- Markdown files (.md)
- JSON/TOML configuration files
- Glob patterns (e.g., src/**/*.rs)
${BOLD}OPTIONS:${RESET}
-o, --output DIR Output directory for generated docs
(default: \$PWD/output)
-c, --color COLOR Primary accent color (hex format)
(default: #ff69b4)
Examples: #3498db, #10b981, #8b5cf6
-s, --style STYLE Background style theme
Options: slate, zinc, neutral, stone, gray
(default: slate)
--font-sans FONT Google Font for body text (default: Inter)
--font-mono FONT Google Font for code blocks
(default: JetBrains Mono)
--serve Start HTTP server after generation
--open Open documentation in browser (implies --serve)
-p, --port PORT Port for HTTP server (default: 8000)
-v, --verbose Enable verbose output
-d, --dry-run Show what would be done without executing
-h, --help Show this help message
${BOLD}EXAMPLES:${RESET}
${DIM}# Generate docs for current Rust project${RESET}
$(basename "$0") .
${DIM}# Custom color scheme${RESET}
$(basename "$0") . -c "#3498db" -s zinc -o ./docs
${DIM}# Document specific files${RESET}
$(basename "$0") src/lib.rs src/main.rs -o ./api-docs
${DIM}# Use custom fonts${RESET}
$(basename "$0") . --font-sans "Roboto" --font-mono "Fira Code"
${DIM}# Generate and open in browser${RESET}
$(basename "$0") . --open
${BOLD}NOTES:${RESET}
- Requires: cargo, rustdoc, bc, yq, jq, python3 with jinja2
- Colors are automatically generated in light and dark variants
- Google Fonts are automatically imported
- Mermaid.js diagrams are automatically rendered
EOF
}
##############################################################
# Dependency Checks
##############################################################
check_dependencies() {
local missing=()
command -v cargo >/dev/null 2>&1 || missing+=("cargo")
command -v rustdoc >/dev/null 2>&1 || missing+=("rustdoc")
command -v bc >/dev/null 2>&1 || missing+=("bc")
command -v yq >/dev/null 2>&1 || missing+=("yq")
command -v jq >/dev/null 2>&1 || missing+=("jq")
command -v python3 >/dev/null 2>&1 || missing+=("python3")
if ! python3 -c "import jinja2" 2>/dev/null; then
missing+=("python3-jinja2")
fi
if [[ ${#missing[@]} -gt 0 ]]; then
error "Missing required dependencies: ${missing[*]}"
exit 1
fi
# Check for helper scripts
if [[ ! -x "${SCRIPT_DIR}/css_color_palette.sh" ]]; then
error "Helper script not found: ${SCRIPT_DIR}/css_color_palette.sh"
exit 1
fi
if [[ ! -x "${SCRIPT_DIR}/jinja_template_render.sh" ]]; then
error "Helper script not found: ${SCRIPT_DIR}/jinja_template_render.sh"
exit 1
fi
return 0
}
##############################################################
# Input Processing
##############################################################
validate_color() {
local color="$1"
# Remove leading # if present
color="${color#\#}"
if [[ ! "$color" =~ ^[0-9A-Fa-f]{3}$ ]] && [[ ! "$color" =~ ^[0-9A-Fa-f]{6}$ ]]; then
error "Invalid hex color: $1"
error "Expected format: #RGB or #RRGGBB"
exit 1
fi
# Ensure 6-digit format
if [[ ${#color} -eq 3 ]]; then
color="${color:0:1}${color:0:1}${color:1:1}${color:1:1}${color:2:1}${color:2:1}"
fi
echo "#${color}"
}
validate_style() {
local style="$1"
case "$style" in
slate|zinc|neutral|stone|gray)
echo "$style"
;;
*)
error "Invalid style: $style"
error "Valid options: slate, zinc, neutral, stone, gray"
exit 1
;;
esac
}
##############################################################
# Color Palette Generation
##############################################################
generate_color_palette() {
local primary_color="$1"
local style="$2"
local output_file="$3"
verbose "Primary color: $primary_color"
verbose "Style: $style"
# Generate primary color palette (monochromatic)
if [[ "$VERBOSE" == false ]]; then
info "Generating color palette..."
fi
if ! "${SCRIPT_DIR}/css_color_palette.sh" "$primary_color" \
-p monochromatic \
-o "${TMP_DIR}/primary_palette.yaml" \
-m dark \
-s all >/dev/null 2>&1; then
error "Failed to generate primary color palette"
return 1
fi
verbose "Generated primary palette: ${TMP_DIR}/primary_palette.yaml"
if [[ "$VERBOSE" == false ]]; then
success "Color palette generated"
fi
}
##############################################################
# CSS Variables Generation
##############################################################
generate_css_variables() {
local primary_color="$1"
local style="$2"
local output_file="$3"
info "Generating CSS variables..."
# Read the generated palette
local palette_file="${TMP_DIR}/primary_palette.yaml"
if [[ ! -f "$palette_file" ]]; then
error "Palette file not found: $palette_file"
return 1
fi
# Extract color values from the palette
local primary_50 primary_100 primary_200 primary_300 primary_400
local primary_500 primary_600 primary_700 primary_800 primary_900 primary_950
primary_50=$(yq -r '.colors.primary."50"' "$palette_file")
primary_100=$(yq -r '.colors.primary."100"' "$palette_file")
primary_200=$(yq -r '.colors.primary."200"' "$palette_file")
primary_300=$(yq -r '.colors.primary."300"' "$palette_file")
primary_400=$(yq -r '.colors.primary."400"' "$palette_file")
primary_500=$(yq -r '.colors.primary."500"' "$palette_file")
primary_600=$(yq -r '.colors.primary."600"' "$palette_file")
primary_700=$(yq -r '.colors.primary."700"' "$palette_file")
primary_800=$(yq -r '.colors.primary."800"' "$palette_file")
primary_900=$(yq -r '.colors.primary."900"' "$palette_file")
primary_950=$(yq -r '.colors.primary."950"' "$palette_file")
# Get style-specific colors (from existing theme.yaml)
local style_file="${THEME_DIR}/theme.yaml"
# Generate CSS custom properties
cat > "$output_file" << EOF
/* Generated CSS Variables for Rustdoc Theme */
/* Primary Color: ${primary_color} */
/* Style: ${style} */
/* Import Google Fonts */
@import url('https://fonts.googleapis.com/css2?family=${FONT_SANS// /+}:wght@300;400;500;600;700&family=${FONT_MONO// /+}:wght@400;500;600;700&display=swap');
/* Base variables for all themes */
:root {
/* Primary color palette */
--primary-50: ${primary_50};
--primary-100: ${primary_100};
--primary-200: ${primary_200};
--primary-300: ${primary_300};
--primary-400: ${primary_400};
--primary-500: ${primary_500};
--primary-600: ${primary_600};
--primary-700: ${primary_700};
--primary-800: ${primary_800};
--primary-900: ${primary_900};
--primary-950: ${primary_950};
/* Google Fonts */
--font-family: '${FONT_SANS}', 'Fira Sans', Arial, sans-serif;
--font-family-code: '${FONT_MONO}', 'Fira Mono', monospace;
}
/* Dark theme overrides */
:root[data-theme="dark"] {
EOF
# Now read the theme.yaml and replace color references with our palette
verbose "Processing theme variables..."
# Read theme.yaml and substitute colors
while IFS=': ' read -r key value; do
# Skip empty lines and comments
[[ -z "$key" || "$key" =~ ^# ]] && continue
# Remove quotes and leading/trailing whitespace
value="${value#\"}"
value="${value%\"}"
value="${value#\'}"
value="${value%\'}"
value="${value# }"
value="${value% }"
# Replace hardcoded colors with our palette where appropriate
# This is a simple substitution - for primary/accent colors use our palette
if [[ "$value" == "#ff69b4" || "$value" == "#ff1493" || "$value" == "#ec407a" ]]; then
value="${primary_500}"
elif [[ "$value" == "#f06292" ]]; then
value="${primary_400}"
fi
echo " --${key}: ${value};" >> "$output_file"
done < <(grep -E '^[a-zA-Z]' "$style_file" || true)
# Close the dark theme block
echo "}" >> "$output_file"
# Add light theme variant (with adjusted colors)
cat >> "$output_file" << EOF
/* Light theme overrides */
:root[data-theme="light"] {
EOF
# For light theme, read theme.yaml again but use lighter colors
while IFS=': ' read -r key value; do
# Skip empty lines and comments
[[ -z "$key" || "$key" =~ ^# ]] && continue
# Remove quotes and leading/trailing whitespace
value="${value#\"}"
value="${value%\"}"
value="${value#\'}"
value="${value%\'}"
value="${value# }"
value="${value% }"
# For light theme, invert dark backgrounds to light
case "$key" in
*background*|*-bg-*)
# Use lighter shades for backgrounds
if [[ "$value" == "#2f3542" ]]; then
value="#f8f9fa" # main background
elif [[ "$value" == "#1e272e" ]]; then
value="#ffffff" # secondary background
elif [[ "$value" == "#24272e" ]]; then
value="#f1f3f5" # hover background
fi
;;
*color*|*-fg-*)
# Use darker text for light backgrounds
if [[ "$value" == "#e8eaed" ]]; then
value="#2f3542" # main text color
elif [[ "$value" == "#ffffff" ]]; then
value="#000000" # white text -> black
fi
;;
*border*)
# Adjust borders for light theme
if [[ "$value" == "#57606f" ]]; then
value="#dee2e6"
fi
;;
esac
# Replace primary accent colors with our palette
if [[ "$value" == "#ff69b4" || "$value" == "#ff1493" || "$value" == "#ec407a" ]]; then
value="${primary_600}" # Slightly darker for light theme
elif [[ "$value" == "#f06292" ]]; then
value="${primary_500}"
fi
echo " --${key}: ${value};" >> "$output_file"
done < <(grep -E '^[a-zA-Z]' "$style_file" || true)
# Close the light theme block
echo "}" >> "$output_file"
verbose "Generated CSS variables: $output_file"
success "CSS variables generated"
}
##############################################################
# Render Header Template
##############################################################
render_header_template() {
local output_file="$1"
info "Rendering header template..."
# Process mermaid.yaml variables to match our theme
local mermaid_yaml="${TMP_DIR}/mermaid_processed.yaml"
# Copy and update mermaid colors
cp "${THEME_DIR}/mermaid.yaml" "$mermaid_yaml"
# Update with our primary color
yq -i ".primaryColor = \"${PRIMARY_COLOR}\"" "$mermaid_yaml"
yq -i ".lineColor = \"${PRIMARY_COLOR}\"" "$mermaid_yaml"
yq -i ".border1 = \"${PRIMARY_COLOR}\"" "$mermaid_yaml"
yq -i ".noteBorderColor = \"${PRIMARY_COLOR}\"" "$mermaid_yaml"
yq -i ".arrowheadColor = \"${PRIMARY_COLOR}\"" "$mermaid_yaml"
yq -i ".clusterBorder = \"${PRIMARY_COLOR}\"" "$mermaid_yaml"
yq -i ".defaultLinkColor = \"${PRIMARY_COLOR}\"" "$mermaid_yaml"
yq -i ".fontFamily = \"${FONT_SANS}, system-ui, -apple-system, sans-serif\"" "$mermaid_yaml"
verbose "Processed mermaid config: $mermaid_yaml"
# Render the Jinja2 template
if ! "${SCRIPT_DIR}/jinja_template_render.sh" \
-f "$mermaid_yaml" \
-o "${TMP_DIR}" \
"${THEME_DIR}/header.html.jinja"; then
error "Failed to render header template"
return 1
fi
# Move rendered file to expected location if different
if [[ "${TMP_DIR}/header.html" != "$output_file" ]]; then
mv "${TMP_DIR}/header.html" "$output_file"
fi
verbose "Rendered header: $output_file"
success "Header template rendered"
}
##############################################################
# Consolidate CSS
##############################################################
consolidate_css() {
local output_file="$1"
info "Consolidating CSS files..."
# Combine variables.css and theme.css
cat "${TMP_DIR}/variables.css" > "$output_file"
echo "" >> "$output_file"
cat "${THEME_DIR}/theme.css" >> "$output_file"
verbose "Consolidated CSS: $output_file"
success "CSS consolidated"
}
##############################################################
# Run Rustdoc
##############################################################
run_rustdoc() {
local inputs=("$@")
info "Running rustdoc..."
local header_file="${TMP_DIR}/header.html"
local css_file="${TMP_DIR}/theme-combined.css"
# Determine if we're documenting a cargo project or individual files
local is_cargo_project=false
for input in "${inputs[@]}"; do
if [[ -f "${input}/Cargo.toml" ]] || [[ -f "${input%/}/Cargo.toml" ]]; then
is_cargo_project=true
break
fi
done
if [[ "$is_cargo_project" == true ]]; then
info "Detected Cargo project, using 'cargo doc'..."
# Find the Cargo.toml directory
local cargo_dir=""
for input in "${inputs[@]}"; do
if [[ -f "${input}/Cargo.toml" ]]; then
cargo_dir="$input"
break
elif [[ -f "${input%/}/Cargo.toml" ]]; then
cargo_dir="${input%/}"
break
fi
done
# Build cargo doc command with custom theme
local cargo_args=(
"doc"
"--no-deps"
"--target-dir" "${OUTPUT_DIR}"
)
# Set RUSTDOCFLAGS environment variable for custom styling
export RUSTDOCFLAGS="--html-in-header ${header_file} --extend-css ${css_file}"
if [[ "$VERBOSE" == true ]]; then
cargo_args+=("-v")
fi
verbose "Running: cargo ${cargo_args[*]}"
verbose "RUSTDOCFLAGS: $RUSTDOCFLAGS"
if [[ "$DRY_RUN" == true ]]; then
warning "Dry run: would execute cargo ${cargo_args[*]}"
else
if [[ "$VERBOSE" == false ]]; then
info "Running cargo doc (this may take a while)..."
fi
# In non-verbose mode, show cargo progress messages
if [[ "$VERBOSE" == true ]]; then
# Verbose: show everything
if ! (cd "$cargo_dir" && cargo "${cargo_args[@]}"); then
error "cargo doc failed"
return 1
fi
else
# Non-verbose: filter output to show only important messages
if ! (cd "$cargo_dir" && cargo "${cargo_args[@]}" 2>&1 | grep -E '(Documenting|Compiling|Finished|error|warning)' || true); then
# Check if cargo actually failed
if ! (cd "$cargo_dir" && cargo "${cargo_args[@]}" >/dev/null 2>&1); then
error "cargo doc failed"
return 1
fi
fi
fi
success "Documentation generated successfully"
info "Output directory: ${OUTPUT_DIR}/doc"
fi
else
# Document individual files using rustdoc directly
warning "Individual file documentation not fully implemented yet"
warning "Please provide a Cargo project directory"
return 1
fi
}
##############################################################
# Serve and Open Documentation
##############################################################
serve_and_open_docs() {
local doc_dir="${OUTPUT_DIR}/doc"
local index_file="${doc_dir}/universal_lsp/index.html"
# Find the actual index.html file (might be in different location)
if [[ ! -f "$index_file" ]]; then
# Try to find any index.html in the doc directory
index_file=$(find "$doc_dir" -name "index.html" -type f | head -1)
if [[ -z "$index_file" ]]; then
warning "Could not find index.html in documentation"
index_file="${doc_dir}/index.html"
fi
fi
# Get the relative path from doc_dir to index_file for the URL
local rel_path="${index_file#$doc_dir/}"
local url="http://localhost:${SERVE_PORT}/${rel_path}"
info "Starting HTTP server on port ${SERVE_PORT}..."
echo ""
# Start Python HTTP server in the background
cd "$doc_dir" || {
error "Failed to change to documentation directory: $doc_dir"
return 1
}
# Kill any existing server on this port
if lsof -Pi ":${SERVE_PORT}" -sTCP:LISTEN -t >/dev/null 2>&1; then
warning "Port ${SERVE_PORT} is already in use. Trying to kill existing process..."
lsof -Pi ":${SERVE_PORT}" -sTCP:LISTEN -t | xargs kill -9 2>/dev/null || true
sleep 1
fi
# Start server
python3 -m http.server "$SERVE_PORT" >/dev/null 2>&1 &
local server_pid=$!
# Give the server a moment to start
sleep 1
# Check if server started successfully
if ! kill -0 "$server_pid" 2>/dev/null; then
error "Failed to start HTTP server"
return 1
fi
success "Server started (PID: $server_pid)"
info "Documentation available at: ${CYAN}${url}${RESET}"
# Open in browser if requested
if [[ "$OPEN" == true ]]; then
info "Opening documentation in browser..."
# Try different browser openers
if command -v xdg-open >/dev/null 2>&1; then
xdg-open "$url" >/dev/null 2>&1 &
elif command -v open >/dev/null 2>&1; then
open "$url" >/dev/null 2>&1 &
elif command -v sensible-browser >/dev/null 2>&1; then
sensible-browser "$url" >/dev/null 2>&1 &
else
warning "Could not detect browser opener (xdg-open, open, sensible-browser)"
info "Please open manually: $url"
fi
sleep 1
success "Browser opened"
fi
echo ""
echo "${BOLD}${GREEN}Server running!${RESET}"
echo "${DIM}Press Ctrl+C to stop the server${RESET}"
echo ""
# Wait for Ctrl+C
trap "echo ''; info 'Shutting down server...'; kill $server_pid 2>/dev/null; success 'Server stopped'; exit 0" INT TERM
# Keep the script running
wait "$server_pid"
}
##############################################################
# Cleanup
##############################################################
cleanup() {
if [[ "$VERBOSE" == true ]]; then
verbose "Temporary files preserved in: ${TMP_DIR}"
fi
}
trap cleanup EXIT
##############################################################
# Main Function
##############################################################
main() {
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-o|--output)
OUTPUT_DIR="$2"
shift 2
;;
-c|--color)
PRIMARY_COLOR=$(validate_color "$2")
shift 2
;;
-s|--style)
STYLE=$(validate_style "$2")
shift 2
;;
--font-sans)
FONT_SANS="$2"
shift 2
;;
--font-mono)
FONT_MONO="$2"
shift 2
;;
--serve)
SERVE=true
shift
;;
--open)
OPEN=true
SERVE=true # Opening implies serving
shift
;;
-p|--port)
SERVE_PORT="$2"
shift 2
;;
-v|--verbose)
VERBOSE=true
shift
;;
-d|--dry-run)
DRY_RUN=true
shift
;;
-h|--help)
show_help
exit 0
;;
-*)
error "Unknown option: $1"
echo "Use -h or --help for usage information"
exit 1
;;
*)
INPUT_FILES+=("$1")
shift
;;
esac
done
# Print banner
echo "${MAGENTA}${BOLD}"
echo "=============================================="
echo " Rust Documentation Generator"
echo "=============================================="
echo "${RESET}"
# Check dependencies
info "Checking dependencies..."
check_dependencies
success "All dependencies found"
# Validate inputs
if [[ ${#INPUT_FILES[@]} -eq 0 ]]; then
error "No input files specified"
echo "Use -h or --help for usage information"
exit 1
fi
# Create temporary directory
mkdir -p "$TMP_DIR"
verbose "Temporary directory: $TMP_DIR"
# Show configuration
echo ""
info "Configuration:"
echo " Primary Color: ${PRIMARY_COLOR}"
echo " Style: ${STYLE}"
echo " Font Sans: ${FONT_SANS}"
echo " Font Mono: ${FONT_MONO}"
echo " Output: ${OUTPUT_DIR}"
echo " Inputs: ${INPUT_FILES[*]}"
echo ""
# Generate color palette
generate_color_palette "$PRIMARY_COLOR" "$STYLE" "${TMP_DIR}/palette.yaml"
# Generate CSS variables
generate_css_variables "$PRIMARY_COLOR" "$STYLE" "${TMP_DIR}/variables.css"
# Render header template
render_header_template "${TMP_DIR}/header.html"
# Consolidate CSS
consolidate_css "${TMP_DIR}/theme-combined.css"
# Run rustdoc
run_rustdoc "${INPUT_FILES[@]}"
echo ""
success "Documentation generation complete!"
if [[ "$DRY_RUN" == false ]]; then
info "View your documentation:"
echo " ${CYAN}${OUTPUT_DIR}/doc/index.html${RESET}"
# Serve and/or open documentation if requested
if [[ "$SERVE" == true ]]; then
echo ""
serve_and_open_docs
fi
fi
echo ""
}
# Run main function
main "$@"