thag_rs 0.2.0

A versatile cross-platform playground and REPL for Rust snippets, expressions and programs. Accepts a script file or dynamic options.
/*[toml]
[dependencies]
thag_common = { version = "0.2, thag-auto" }
warp = { version = "0.4", features = ["server"] }
*/

/// Quick markdown viewer checks your markdown for GitHub compatibility.
///
/// Script generated by GitHub Copilot.
///
/// Uses the GitHub REST API endpoint `/markdown` to convert Markdown to HTML and serves the HTML using the `warp` web framework. Make sure your Markdown file is less than 400 KB, as per the API's limitations.
///
/// ### Instructions:
///
/// 1. Set the `GITHUB_TOKEN` environment variable with your GitHub token (classic or fine-grained).
///
/// 2. Run the script:
///
///    ```bash
///    thag_markdown <path_to_markdown_file>
///    ```
///
/// 3. Open `http://localhost:8080` in your browser to view the rendered HTML.
//# Purpose: Useful tool and demo.
//# Categories: demo, tools
use reqwest::Client;
use std::env;
use std::fs;
use std::process;
use thag_common::{auto_help, help_system::check_help_and_exit};
use warp::Filter;

#[tokio::main]
async fn main() {
    // Check for help first - automatically extracts from source comments
    let help = auto_help!();
    check_help_and_exit(&help);

    // Get the Markdown file path from the command line arguments
    let args: Vec<String> = env::args().collect();
    if args.len() != 2 {
        eprintln!("Usage: {} <markdown_file_path>", args[0]);
        process::exit(1);
    }
    let markdown_file_path = &args[1];

    // Read the Markdown file
    let markdown_content = match fs::read_to_string(markdown_file_path) {
        Ok(content) => content,
        Err(err) => {
            eprintln!("Error reading file {markdown_file_path}: {err}");
            process::exit(1);
        }
    };

    // Get the GitHub token from the environment variable
    let github_token = env::var("GITHUB_TOKEN").unwrap_or_else(|_| {
        eprintln!("Error: GITHUB_TOKEN environment variable not set");
        process::exit(1);
    });

    // Use the GitHub REST API to convert Markdown to HTML
    let client = Client::new();
    let response = client
        .post("https://api.github.com/markdown")
        .header("Authorization", format!("Bearer {github_token}"))
        .header("Accept", "application/vnd.github+json")
        .header("User-Agent", "rust-markdown-to-html")
        .json(&serde_json::json!({
            "text": markdown_content,
            "mode": "markdown"
        }))
        .send()
        .await;

    let html_content = match response {
        Ok(resp) if resp.status().is_success() => resp.text().await.unwrap_or_else(|_| {
            eprintln!("Error reading response body");
            process::exit(1);
        }),
        Ok(resp) => {
            eprintln!("Error: GitHub API returned status {}", resp.status());
            process::exit(1);
        }
        Err(err) => {
            eprintln!("Error making request to GitHub API: {err}");
            process::exit(1);
        }
    };

    // Serve the HTML content on a local port
    let html_filter = warp::any().map(move || warp::reply::html(html_content.clone()));
    let port = 8080;
    println!("Serving HTML on http://localhost:{port}");
    warp::serve(html_filter).run(([127, 0, 0, 1], port)).await;
}