use crate::agent::CliError;
use std::path::PathBuf;
#[derive(clap::Args)]
pub(crate) struct Args {
#[command(subcommand)]
command: Command,
}
#[derive(clap::Subcommand)]
enum Command {
Auto(AutoArgs),
}
#[derive(Clone, Copy, clap::ValueEnum)]
enum Level {
Aa,
Aaa,
}
#[derive(clap::Args)]
struct AutoArgs {
input: PathBuf,
#[arg(long)]
out: PathBuf,
#[arg(long)]
config: Option<PathBuf>,
#[arg(long, value_enum, ignore_case = true, default_value = "AA")]
level: Level,
#[arg(long)]
px_per_pt: Option<f64>,
#[arg(long)]
model_cache: Option<PathBuf>,
#[arg(long)]
json: bool,
#[arg(long)]
junit: Option<PathBuf>,
}
pub(crate) fn run(args: Args) -> Result<u8, CliError> {
let Command::Auto(a) = args.command;
#[allow(unused_mut)]
let mut model_cache = a.model_cache.clone();
#[cfg(feature = "ocr")]
if model_cache.is_none() {
model_cache = Some(saccade_core::media::default_model_dir());
}
let options = saccade_a11y::Options {
config: a.config.clone(),
level: match a.level {
Level::Aa => saccade_a11y::auto::Level::AA,
Level::Aaa => saccade_a11y::auto::Level::AAA,
},
px_per_pt: a.px_per_pt.unwrap_or(96. / 72.),
scale_known: a.px_per_pt.is_some(),
model_cache: model_cache.clone(),
};
let report = saccade_a11y::run(&a.input, &a.out, &options)?;
if let Some(path) = a.junit.as_deref() {
let mut inputs = vec![a.input.as_path(), a.out.as_path()];
if let Some(c) = a.config.as_deref() {
inputs.push(c);
}
if let Some(c) = model_cache.as_deref() {
inputs.push(c);
}
report.junit(path, &inputs)?;
}
if a.json {
let value = summary_result(&serde_json::to_value(&report)?, &a.out)?;
crate::local_cmd::print(&value, true)?;
} else {
crate::emit(&report.text())?;
}
Ok(match report.verdict {
saccade_a11y::auto::Verdict::Pass | saccade_a11y::auto::Verdict::Warn => 0,
saccade_a11y::auto::Verdict::Fail => 1,
saccade_a11y::auto::Verdict::Unmeasurable => 4,
})
}
pub(crate) fn summary_result(
value: &serde_json::Value,
out: &std::path::Path,
) -> Result<serde_json::Value, CliError> {
let mut result = crate::local_cmd::analysis_result(value, out)?;
result["data"] = serde_json::json!({
"verdict": value["verdict"], "scope": value["scope"],
"images": value["images"].as_array().into_iter().flatten().map(|image| serde_json::json!({
"name": image["name"], "verdict": image["verdict"], "summary": image["summary"],
"scope": image["scope"], "limitations": image["limitations"],
})).collect::<Vec<_>>()
});
Ok(result)
}