use std::path::PathBuf;
use clap::{Parser, ValueEnum};
#[derive(Parser, Debug)]
#[command(name = "docspec")]
#[command(version = "0.1.0")]
#[command(
about = "Convert documents between formats using streaming event pipeline",
long_about = "Convert documents between formats using streaming event pipeline.\n\nSupports converting Markdown or HTML input to BlockNote JSON, HTML, or oxa.dev JSON output.\n\nNote: HTML input and output currently preserve only paragraph text. Other HTML input\nelements and non-paragraph output events (headings, lists, tables, formatting, etc.)\nare silently dropped. Use BlockNote JSON output for fuller feature coverage."
)]
pub struct Cli {
#[arg(long, value_name = "WHEN", default_value = "auto")]
pub color: ColorChoice,
#[arg(short, long)]
pub from: Option<CliInputFormat>,
#[arg(value_name = "FILE")]
pub input: Option<PathBuf>,
#[arg(short, long, value_name = "FILE")]
pub output: Option<PathBuf>,
#[arg(short, long)]
pub to: Option<CliOutputFormat>,
}
#[derive(Clone, Copy, Debug, ValueEnum)]
pub enum ColorChoice {
#[value(name = "always")]
Always,
#[value(name = "auto")]
Auto,
#[value(name = "never")]
Never,
}
#[derive(Clone, Copy, Debug, ValueEnum)]
pub enum CliInputFormat {
#[value(name = "html")]
Html,
#[value(name = "markdown")]
Markdown,
}
#[derive(Clone, Copy, Debug, ValueEnum)]
pub enum CliOutputFormat {
#[value(name = "blocknote")]
Blocknote,
#[value(name = "html")]
Html,
#[value(name = "oxa")]
Oxa,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn clap_rejects_blocknote_as_input() {
let result = Cli::try_parse_from(["docspec", "--from", "blocknote", "x.md"]);
assert!(
result.is_err(),
"blocknote should not be a valid input format"
);
}
#[test]
fn clap_rejects_markdown_as_output() {
let result = Cli::try_parse_from(["docspec", "--to", "markdown", "x.md"]);
assert!(
result.is_err(),
"markdown should not be a valid output format"
);
}
#[test]
fn clap_accepts_html_as_output_format() {
let result = Cli::try_parse_from(["docspec", "--to", "html", "x.md"]);
assert!(
result.is_ok(),
"html should be a valid output format, got error: {:?}",
result.as_ref().err()
);
let cli = result.unwrap_or_else(|_| std::process::abort());
assert!(
matches!(cli.to, Some(CliOutputFormat::Html)),
"expected CliOutputFormat::Html, got {:?}",
cli.to
);
}
#[test]
fn clap_accepts_oxa_as_output_format() {
let result = Cli::try_parse_from(["docspec", "--to", "oxa", "x.md"]);
assert!(
result.is_ok(),
"oxa should be a valid output format, got error: {:?}",
result.as_ref().err()
);
let cli = result.unwrap_or_else(|_| std::process::abort());
assert!(
matches!(cli.to, Some(CliOutputFormat::Oxa)),
"expected CliOutputFormat::Oxa, got {:?}",
cli.to
);
}
}