mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-27 11:37:59 -06:00
The app, crates, binaries, bundle id, packaging, icons, screenshots and docs are now PdfCraft / pdfcraft (repo storytold/pdfcraft). On first launch the desktop app moves the PrintCraft settings and crash-recovery folders to the new name, and both apps read settings saved under the old storage key, so upgrades keep recent files, preferences and unsaved work. The signing test fixtures keep their PrintCraft subject names (they are binary). Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
70 lines
3.1 KiB
Rust
70 lines
3.1 KiB
Rust
//! Project automation for PdfCraft, run via `cargo xtask <command>`.
|
|
|
|
use std::process::ExitCode;
|
|
|
|
mod assets;
|
|
mod demo_pdf;
|
|
mod fuzz;
|
|
mod gates;
|
|
mod layers;
|
|
mod parity;
|
|
mod screenshots;
|
|
mod version;
|
|
|
|
type Command = fn(&[String]) -> anyhow::Result<()>;
|
|
|
|
/// Every subcommand: name, one-line summary, entry point.
|
|
const COMMANDS: &[(&str, &str, Command)] = &[
|
|
("version", "Print the workspace version, or `version set X.Y.Z[-pre]` to change it and refresh Cargo.lock", version_cmd),
|
|
("layers", "Enforce the crate dependency layering (plan/architecture.md §3)", gates::layers),
|
|
("wasm", "cargo check --target wasm32-unknown-unknown for every crate below L8", gates::wasm),
|
|
("deny", "Dependency licences, bans, sources and advisories (deny.toml; needs cargo-deny)", gates::deny),
|
|
("ci", "fmt --check, clippy -D warnings, test, layers, wasm, assets, deny, parity (stops at first failure)", gates::ci),
|
|
("assets", "Enforce the asset policy (AGENTS.md §1) against ATTRIBUTION.toml; --write regenerates ATTRIBUTION.md", assets::run),
|
|
("corpus", "Fetch test corpora into corpus/ (git-ignored): pdf.js test PDFs", gates::corpus),
|
|
("check", "Robustness sweep over corpus/ with pdfcraft-cli; fails on crashes or regressions vs xtask/baselines", gates::check),
|
|
("fuzz", "Mutation fuzzing of open/render/edit/save in child processes; findings in fuzz-out/ (--time 300)", fuzz::run),
|
|
("parity", "Validate parity/acrobat-features.toml against the registry, tools and tests; report progress (--json, --partial)", parity::run),
|
|
("text-oracle", "Compare text extraction with pdftotext over corpus/ (word F1; target median ≥ 0.97)", gates::text_oracle),
|
|
("screenshots", "Regenerate the README screenshots in docs/images/ and their ATTRIBUTION entries", screenshots::run),
|
|
("models", "Fetch the OCR models (ATTRIBUTION.toml kind = \"model\") into assets/models/, verified by SHA-256", assets::models),
|
|
("demo-pdf", "Build dist/demo/pdfcraft-showcase.pdf (needs Google Chrome or Chromium)", demo_pdf::run),
|
|
];
|
|
|
|
fn version_cmd(args: &[String]) -> anyhow::Result<()> {
|
|
let args: Vec<&str> = args.iter().map(String::as_str).collect();
|
|
version::run(&gates::root(), &args).map_err(anyhow::Error::msg)
|
|
}
|
|
|
|
fn main() -> ExitCode {
|
|
let args: Vec<String> = std::env::args().skip(1).collect();
|
|
let Some(name) = args.first() else {
|
|
print_help();
|
|
return ExitCode::FAILURE;
|
|
};
|
|
if matches!(name.as_str(), "help" | "-h" | "--help") {
|
|
print_help();
|
|
return ExitCode::SUCCESS;
|
|
}
|
|
let Some((_, _, command)) = COMMANDS.iter().find(|(n, _, _)| n == name) else {
|
|
eprintln!("xtask: unknown command `{name}`\n");
|
|
print_help();
|
|
return ExitCode::FAILURE;
|
|
};
|
|
match command(&args[1..]) {
|
|
Ok(()) => ExitCode::SUCCESS,
|
|
Err(err) => {
|
|
eprintln!("xtask {name}: error: {err:#}");
|
|
ExitCode::FAILURE
|
|
}
|
|
}
|
|
}
|
|
|
|
fn print_help() {
|
|
eprintln!("Usage: cargo xtask <command> [args]\n\nCommands:");
|
|
for (name, about, _) in COMMANDS {
|
|
eprintln!(" {name:<12} {about}");
|
|
}
|
|
eprintln!(" {:<12} Show this list", "help");
|
|
}
|