add options for empty frontmatter

This commit is contained in:
JMARyA 2024-03-08 11:49:36 +01:00
parent b2ae45131d
commit 6d33cf285e
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
4 changed files with 270 additions and 285 deletions

493
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
[package]
name = "mdlint"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
[profile.release]

View file

@ -5,6 +5,8 @@ pub fn get_args() -> ArgMatches {
.about("Lint markdown frontmatter using JSON Schema")
.arg(arg!([schema] "Schema file used for validation").required(true))
.arg(arg!([file] "File to validate").required(true))
.arg(arg!(--greedy "Require all properties to be present even if they are not strictly required in schema").required(false))
.arg(arg!(-g --greedy "Require all properties to be present even if they are not strictly required in schema").required(false))
.arg(clap::Arg::new("empty-frontmatter").short('e').long("empty-frontmatter").conflicts_with("ignore-missing-frontmatter").required(false).num_args(0).help("Treat missing frontmatter as empty frontmatter"))
.arg(clap::Arg::new("ignore-missing-frontmatter").short('i').long("ignore-missing-frontmatter").conflicts_with("empty-frontmatter").required(false).num_args(0).help("Dont print an error when no frontmatter has been found"))
.get_matches()
}

View file

@ -9,13 +9,17 @@ trait ErrorExit {
fn quit_on_error(self, msg: &str) -> Self::T;
}
impl<T, E> ErrorExit for Result<T, E> {
impl<T, E: std::fmt::Debug> ErrorExit for Result<T, E> {
type T = T;
fn quit_on_error(self, msg: &str) -> T {
self.map_or_else(
|_| {
eprintln!("{} {msg}", Style::new().red().apply_to("Error:"));
|e| {
if msg.is_empty() {
eprintln!("{} {e:?}", Style::new().red().apply_to("Error:"));
} else {
eprintln!("{} {msg}", Style::new().red().apply_to("Error:"));
}
std::process::exit(1);
},
|res| res,
@ -66,6 +70,34 @@ fn require_everything(schema: &mut serde_json::Value) {
}
}
fn get_frontmatter_from_file(file: &str, args: &clap::ArgMatches) -> serde_yaml::Value {
let frontmatter_str = get_frontmatter(&std::fs::read_to_string(file).quit_on_error(&format!(
"Could not read markdown file '{}'",
Style::new().blue().apply_to(file)
)));
let frontmatter_str = frontmatter_str.map_or_else(
|| {
if args.get_flag("ignore-missing-frontmatter") {
std::process::exit(0);
}
if !args.get_flag("empty-frontmatter") {
Result::<(), ()>::Err(()).quit_on_error(&format!(
"Could not parse frontmatter '{}'",
Style::new().blue().apply_to(file)
));
}
"{}".to_string()
},
|s| s,
);
serde_yaml::from_str(&frontmatter_str).quit_on_error(&format!(
"Frontmatter is no valid yaml '{}'",
Style::new().blue().apply_to(file)
))
}
fn main() {
let args = args::get_args();
@ -86,21 +118,9 @@ fn main() {
.compile(&schema)
.quit_on_error("Schema is not valid");
let frontmatter = serde_yaml::from_str(
&get_frontmatter(&std::fs::read_to_string(file).quit_on_error(&format!(
"Could not read markdown file '{}'",
Style::new().blue().apply_to(file)
)))
.ok_or(0)
.quit_on_error(&format!(
"Could not parse frontmatter '{}'",
Style::new().blue().apply_to(file)
)),
)
.quit_on_error(&format!(
"Frontmatter is no valid yaml '{}'",
Style::new().blue().apply_to(file)
));
let frontmatter = get_frontmatter_from_file(file, &args);
let frontmatter: serde_json::Value =
serde_json::from_str(&serde_json::to_string(&frontmatter).unwrap()).unwrap();
let result = comp_schema.validate(&frontmatter);