diff --git a/napi/Cargo.lock b/napi/Cargo.lock index 8a11ccd..8aa8837 100644 --- a/napi/Cargo.lock +++ b/napi/Cargo.lock @@ -129,12 +129,6 @@ version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" -[[package]] -name = "bytecount" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" - [[package]] name = "cbc" version = "0.1.2" @@ -679,7 +673,7 @@ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "lopdf" version = "0.40.0" -source = "git+https://github.com/J-F-Liu/lopdf?rev=052674053814a9f4897af94f0b8e46a545c9b329#052674053814a9f4897af94f0b8e46a545c9b329" +source = "git+https://github.com/J-F-Liu/lopdf?rev=7a05512d831415b1f2b1ce522391d6beab8a1284#7a05512d831415b1f2b1ce522391d6beab8a1284" dependencies = [ "aes", "bitflags", @@ -695,7 +689,6 @@ dependencies = [ "log", "md-5", "nom", - "nom_locate", "rand", "rangemap", "rayon", @@ -807,17 +800,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "nom_locate" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b577e2d69827c4740cba2b52efaad1c4cc7c73042860b199710b3575c68438d" -dependencies = [ - "bytecount", - "memchr", - "nom", -] - [[package]] name = "num-conv" version = "0.2.1" diff --git a/napi/package.json b/napi/package.json index 52bd043..5bbc4df 100644 --- a/napi/package.json +++ b/napi/package.json @@ -1,6 +1,6 @@ { "name": "firecrawl-pdf-inspector", - "version": "0.3.3", + "version": "0.3.4", "description": "Fast PDF classification and text extraction. Detect text-based vs scanned PDFs, extract text by region with quality checks. Native Rust performance via napi-rs.", "main": "index.js", "types": "index.d.ts", diff --git a/src/lib.rs b/src/lib.rs index 588e492..194e0f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -525,9 +525,6 @@ fn collect_text_in_region_with_options( adaptive_threshold: f32, ) -> String { let bounds = region_bounds(rx1, ry1, rx2, ry2, page_height, coord_space); - let Some(page) = items.first().map(|item| item.page) else { - return String::new(); - }; let matched: Vec = items .iter() .filter(|item| region_overlaps_item(item, bounds)) @@ -536,11 +533,39 @@ fn collect_text_in_region_with_options( if matched.is_empty() { return String::new(); } - let mut thresholds = HashMap::new(); - if adaptive_threshold > 0.10 { - thresholds.insert(page, adaptive_threshold); + + // Simple extraction: the caller (fire-pdf) already handles reading order + // and column splitting via the layout model. We just need to sort items + // top-to-bottom, left-to-right and group into lines. + let mut sorted = matched; + sorted.sort_by(|a, b| b.y.total_cmp(&a.y).then(a.x.total_cmp(&b.x))); + + let y_tolerance = 3.0; + let mut lines: Vec = Vec::new(); + + for item in sorted { + let should_merge = lines.last().is_some_and(|last_line: &extractor::TextLine| { + last_line.page == item.page && (last_line.y - item.y).abs() < y_tolerance + }); + if should_merge { + lines.last_mut().unwrap().items.push(item); + } else { + let y = item.y; + let page = item.page; + lines.push(extractor::TextLine { + items: vec![item], + y, + page, + adaptive_threshold, + }); + } } - let lines = extractor::group_into_lines_with_thresholds(matched, &thresholds, &HashSet::new()); + + // Sort items within each line by X position + for line in &mut lines { + text_utils::sort_line_items(&mut line.items); + } + lines .into_iter() .map(|line| line.text())