use pagesift_api::types::Document;
pub const CONTENT_RISK: &[&str] = &[
"empty_content",
"thin_content",
"partial_content",
"replies_omitted",
"pages_missing",
"content_missing",
"fonts_missing",
"max_pages",
"output_truncated",
"cells_truncated",
"CSV truncated at the cell limit",
"sheet truncated at the cell limit",
"response body exceeded the size limit",
"scanned PDF",
"columns_dropped",
"epub_item_missing",
"decode",
"body_truncated",
"scanned_pages_without_ocr",
"ocr_failed",
"ocr_incomplete",
"http_error_status",
"http_redirect_status",
"not_modified",
"render_unavailable",
"render_incomplete",
"render_skipped_",
];
pub fn is_content_risk(warning: &str) -> bool {
CONTENT_RISK.iter().any(|kind| warning.starts_with(kind))
}
pub fn fill_warning(doc: &mut Document) {
let Some(p) = doc.metadata.pagesift.as_ref() else {
return;
};
let risks: Vec<&str> = p
.warnings
.iter()
.map(String::as_str)
.filter(|w| is_content_risk(w))
.collect();
if risks.is_empty() {
return;
}
let joined = risks.join("; ");
doc.warning = Some(match doc.warning.take() {
Some(existing) if !existing.is_empty() => format!("{existing}; {joined}"),
_ => joined,
});
}
#[cfg(test)]
mod tests {
use super::*;
use pagesift_api::types::{Metadata, PagesiftMeta};
fn doc(warnings: &[&str]) -> Document {
Document {
metadata: Metadata {
pagesift: Some(PagesiftMeta {
warnings: warnings.iter().map(|w| w.to_string()).collect(),
..Default::default()
}),
..Default::default()
},
..Default::default()
}
}
#[test]
fn data_loss_warnings_reach_the_firecrawl_field() {
let mut d = doc(&[
"pdf_repaired: the cross-reference table was unusable",
"content_missing: 2 of 15 pages lost their content streams (pages 1, 4)",
"fonts_missing: 1 of 15 pages lost font definitions (pages 2)",
]);
fill_warning(&mut d);
assert_eq!(
d.warning.as_deref(),
Some(
"content_missing: 2 of 15 pages lost their content streams (pages 1, 4); \
fonts_missing: 1 of 15 pages lost font definitions (pages 2)"
)
);
}
#[test]
fn informational_warnings_stay_in_metadata_only() {
let mut d = doc(&[
"pdf_repaired: recovered",
"comments_omitted: 300 characters",
]);
fill_warning(&mut d);
assert_eq!(d.warning, None);
}
#[test]
fn audit_snapshots_cover_only_content_risks() {
for kind in crate::audit::SUSPICIOUS_WARNINGS {
assert!(is_content_risk(kind), "{kind}");
}
}
}