#![allow(deprecated)]
use anyhow::Result;
use xberg::ExtractionConfig;
#[cfg(feature = "analysis")]
pub use self::analysis::ReductionLevelArg;
pub use self::general::AccelerationArg;
pub use self::output::JupyterCellRenderingArg;
use crate::ContentOutputFormatArg;
mod analysis;
mod chunking;
mod general;
mod html;
mod layout;
mod llm;
mod ocr;
mod output;
mod pdf;
#[cfg(feature = "redaction")]
mod redaction;
#[cfg(test)]
mod tests;
use llm::{apply_llm_api_key, resolve_llm_api_key};
#[derive(Debug, Default, clap::Args)]
pub struct ExtractionOverrides {
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub ocr: Option<bool>,
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub ocr_backend: Option<String>,
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub ocr_language: Option<String>,
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub force_ocr: Option<bool>,
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub ocr_scanned_pages: bool,
#[cfg(feature = "ocr-surface")]
#[arg(long, requires = "ocr_scanned_pages")]
pub scanned_min_confidence: Option<f64>,
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub disable_ocr: Option<bool>,
#[arg(long)]
pub no_cache: Option<bool>,
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub ocr_auto_rotate: Option<bool>,
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub ocr_no_cache: Option<bool>,
#[cfg(feature = "ocr-surface")]
#[arg(long, value_name = "JSON")]
pub ocr_backend_options: Option<String>,
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub vlm_model: Option<String>,
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub vlm_api_key: Option<String>,
#[arg(long, value_name = "KEY")]
pub api_key: Option<String>,
#[cfg(feature = "ocr-surface")]
#[arg(long)]
pub vlm_prompt: Option<String>,
#[cfg(any(feature = "core-cli", feature = "analysis"))]
#[arg(long)]
pub chunk: Option<bool>,
#[cfg(any(feature = "core-cli", feature = "analysis"))]
#[arg(long)]
pub chunk_size: Option<usize>,
#[cfg(any(feature = "core-cli", feature = "analysis"))]
#[arg(long)]
pub chunk_overlap: Option<usize>,
#[cfg(any(feature = "core-cli", feature = "analysis"))]
#[arg(long)]
pub chunking_tokenizer: Option<String>,
#[arg(long, value_enum)]
pub content_format: Option<ContentOutputFormatArg>,
#[arg(long, value_enum, hide = true)]
pub output_format: Option<ContentOutputFormatArg>,
#[arg(long)]
pub include_structure: Option<bool>,
#[arg(long, value_enum)]
pub jupyter_cell_rendering: Option<JupyterCellRenderingArg>,
#[cfg(feature = "analysis")]
#[arg(long)]
pub quality: Option<bool>,
#[cfg(feature = "analysis")]
#[arg(long)]
pub detect_language: Option<bool>,
#[cfg(feature = "layout-detection")]
#[arg(long, default_missing_value = "true", num_args = 0..=1)]
pub layout: Option<bool>,
#[cfg(feature = "layout-detection")]
#[arg(long)]
pub layout_confidence: Option<f32>,
#[cfg(feature = "layout-detection")]
#[arg(
long,
help = "Layout page selection: always (default, every page) or auto (pre-screen pages)"
)]
pub layout_strategy: Option<String>,
#[cfg(feature = "layout-detection")]
#[arg(
long,
help = "Table structure model: tatr (default), slanet_wired, slanet_wireless, slanet_plus, slanet_auto, disabled"
)]
pub layout_table_model: Option<String>,
#[cfg(feature = "formula-recognition")]
#[arg(
long,
help = "Formula recognition model for layout-detected formula regions: latex_ocr"
)]
pub layout_formula_model: Option<String>,
#[cfg(feature = "layout-detection")]
#[arg(long)]
pub use_layout_for_markdown: bool,
#[arg(long, value_enum)]
pub acceleration: Option<AccelerationArg>,
#[arg(long, help = "Limit parallel extractions in batch mode")]
pub max_concurrent: Option<usize>,
#[arg(long, help = "Limit total threads for constrained environments")]
pub max_threads: Option<usize>,
#[arg(
long,
help = "Set concurrent OCR sessions directly, instead of following the thread budget"
)]
pub max_concurrent_ocr: Option<usize>,
#[arg(long)]
pub extract_pages: Option<bool>,
#[arg(long)]
pub page_markers: Option<bool>,
#[arg(long)]
pub extract_images: Option<bool>,
#[arg(long)]
pub target_dpi: Option<i32>,
#[cfg(feature = "pdf-surface")]
#[arg(long)]
pub pdf_password: Vec<String>,
#[cfg(feature = "pdf-surface")]
#[arg(long)]
pub pdf_extract_images: Option<bool>,
#[cfg(feature = "pdf-surface")]
#[arg(long)]
pub pdf_extract_tables: Option<bool>,
#[cfg(all(feature = "pdf-surface", feature = "ocr-surface"))]
#[arg(long)]
pub pdf_ocr_inline_images: Option<bool>,
#[cfg(feature = "pdf-surface")]
#[arg(long)]
pub pdf_extract_metadata: Option<bool>,
#[cfg(feature = "pdf-surface")]
#[arg(long, value_name = "BACKEND")]
pub pdf_backend: Option<String>,
#[cfg(feature = "analysis")]
#[arg(long, value_enum)]
pub token_reduction: Option<ReductionLevelArg>,
#[arg(long)]
pub msg_codepage: Option<u32>,
#[arg(long)]
pub cache_namespace: Option<String>,
#[arg(long)]
pub cache_ttl_secs: Option<u64>,
#[cfg(feature = "html")]
#[arg(long, value_name = "THEME")]
pub html_theme: Option<String>,
#[cfg(feature = "html")]
#[arg(long, value_name = "CSS")]
pub html_css: Option<String>,
#[cfg(feature = "html")]
#[arg(long, value_name = "PATH")]
pub html_css_file: Option<std::path::PathBuf>,
#[cfg(feature = "html")]
#[arg(long, value_name = "PREFIX")]
pub html_class_prefix: Option<String>,
#[cfg(feature = "html")]
#[arg(long)]
pub html_no_embed_css: bool,
#[arg(long, value_name = "CHAR")]
pub csv_delimiter: Option<String>,
#[arg(long, value_name = "PREFIX")]
pub csv_comment_prefix: Vec<String>,
#[cfg(feature = "redaction")]
#[arg(long, value_name = "PATH|-")]
pub redaction_findings: Option<std::path::PathBuf>,
#[cfg(feature = "redaction")]
#[arg(skip)]
pub(crate) redaction_findings_stdin: Option<Vec<xberg::core::config::redaction::ExternalRedactionFinding>>,
}
impl ExtractionOverrides {
pub fn validate(&self) -> Result<()> {
#[cfg(any(feature = "core-cli", feature = "analysis"))]
self.validate_chunking()?;
self.validate_target_dpi()?;
#[cfg(feature = "layout-detection")]
self.validate_layout()?;
#[cfg(feature = "ocr-surface")]
self.validate_ocr()?;
#[cfg(all(
any(feature = "core-cli", feature = "analysis"),
not(feature = "chunking-tokenizers")
))]
self.validate_chunking_tokenizer_feature()?;
self.validate_concurrency()?;
#[cfg(feature = "pdf-surface")]
self.validate_pdf_backend()?;
self.validate_csv()?;
Ok(())
}
pub fn apply(self, config: &mut ExtractionConfig) {
let resolved_api_key = resolve_llm_api_key(self.api_key.as_deref());
#[cfg(feature = "ocr-surface")]
self.apply_ocr(config);
#[cfg(feature = "ocr-surface")]
self.apply_vlm_ocr(config);
#[cfg(any(feature = "core-cli", feature = "analysis"))]
self.apply_chunking(config);
#[cfg(feature = "analysis")]
self.apply_quality_and_detection(config);
self.apply_output_format(config);
self.apply_include_structure(config);
self.apply_jupyter_cell_rendering(config);
self.apply_layout(config);
self.apply_acceleration(config);
self.apply_concurrency(config);
self.apply_pages(config);
self.apply_images(config);
#[cfg(feature = "pdf-surface")]
self.apply_pdf(config);
#[cfg(feature = "analysis")]
self.apply_token_reduction(config);
self.apply_email(config);
self.apply_cache(config);
self.apply_html_styled(config);
self.apply_csv(config);
#[cfg(feature = "redaction")]
self.apply_redaction(config);
if let Some(key) = resolved_api_key {
apply_llm_api_key(config, &key);
}
#[cfg(feature = "layout-detection")]
self.warn_layout_wastes_plain_output(config);
}
}