kreuzberg 4.0.0.pre.rc.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.rubocop.yaml +1 -0
- data/.rubocop.yml +538 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +157 -0
- data/README.md +426 -0
- data/Rakefile +25 -0
- data/Steepfile +47 -0
- data/examples/async_patterns.rb +341 -0
- data/ext/kreuzberg_rb/extconf.rb +45 -0
- data/ext/kreuzberg_rb/native/Cargo.lock +6535 -0
- data/ext/kreuzberg_rb/native/Cargo.toml +44 -0
- data/ext/kreuzberg_rb/native/README.md +425 -0
- data/ext/kreuzberg_rb/native/build.rs +15 -0
- data/ext/kreuzberg_rb/native/include/ieeefp.h +11 -0
- data/ext/kreuzberg_rb/native/include/msvc_compat/strings.h +14 -0
- data/ext/kreuzberg_rb/native/include/strings.h +20 -0
- data/ext/kreuzberg_rb/native/include/unistd.h +47 -0
- data/ext/kreuzberg_rb/native/src/lib.rs +2998 -0
- data/extconf.rb +28 -0
- data/kreuzberg.gemspec +148 -0
- data/lib/kreuzberg/api_proxy.rb +142 -0
- data/lib/kreuzberg/cache_api.rb +46 -0
- data/lib/kreuzberg/cli.rb +55 -0
- data/lib/kreuzberg/cli_proxy.rb +127 -0
- data/lib/kreuzberg/config.rb +691 -0
- data/lib/kreuzberg/error_context.rb +32 -0
- data/lib/kreuzberg/errors.rb +118 -0
- data/lib/kreuzberg/extraction_api.rb +85 -0
- data/lib/kreuzberg/mcp_proxy.rb +186 -0
- data/lib/kreuzberg/ocr_backend_protocol.rb +113 -0
- data/lib/kreuzberg/post_processor_protocol.rb +86 -0
- data/lib/kreuzberg/result.rb +216 -0
- data/lib/kreuzberg/setup_lib_path.rb +80 -0
- data/lib/kreuzberg/validator_protocol.rb +89 -0
- data/lib/kreuzberg/version.rb +5 -0
- data/lib/kreuzberg.rb +103 -0
- data/sig/kreuzberg/internal.rbs +184 -0
- data/sig/kreuzberg.rbs +520 -0
- data/spec/binding/cache_spec.rb +227 -0
- data/spec/binding/cli_proxy_spec.rb +85 -0
- data/spec/binding/cli_spec.rb +55 -0
- data/spec/binding/config_spec.rb +345 -0
- data/spec/binding/config_validation_spec.rb +283 -0
- data/spec/binding/error_handling_spec.rb +213 -0
- data/spec/binding/errors_spec.rb +66 -0
- data/spec/binding/plugins/ocr_backend_spec.rb +307 -0
- data/spec/binding/plugins/postprocessor_spec.rb +269 -0
- data/spec/binding/plugins/validator_spec.rb +274 -0
- data/spec/fixtures/config.toml +39 -0
- data/spec/fixtures/config.yaml +41 -0
- data/spec/fixtures/invalid_config.toml +4 -0
- data/spec/smoke/package_spec.rb +178 -0
- data/spec/spec_helper.rb +42 -0
- data/vendor/kreuzberg/Cargo.toml +204 -0
- data/vendor/kreuzberg/README.md +175 -0
- data/vendor/kreuzberg/benches/otel_overhead.rs +48 -0
- data/vendor/kreuzberg/build.rs +474 -0
- data/vendor/kreuzberg/src/api/error.rs +81 -0
- data/vendor/kreuzberg/src/api/handlers.rs +199 -0
- data/vendor/kreuzberg/src/api/mod.rs +79 -0
- data/vendor/kreuzberg/src/api/server.rs +353 -0
- data/vendor/kreuzberg/src/api/types.rs +170 -0
- data/vendor/kreuzberg/src/cache/mod.rs +1167 -0
- data/vendor/kreuzberg/src/chunking/mod.rs +677 -0
- data/vendor/kreuzberg/src/core/batch_mode.rs +95 -0
- data/vendor/kreuzberg/src/core/config.rs +1032 -0
- data/vendor/kreuzberg/src/core/extractor.rs +1024 -0
- data/vendor/kreuzberg/src/core/io.rs +329 -0
- data/vendor/kreuzberg/src/core/mime.rs +605 -0
- data/vendor/kreuzberg/src/core/mod.rs +45 -0
- data/vendor/kreuzberg/src/core/pipeline.rs +984 -0
- data/vendor/kreuzberg/src/embeddings.rs +432 -0
- data/vendor/kreuzberg/src/error.rs +431 -0
- data/vendor/kreuzberg/src/extraction/archive.rs +954 -0
- data/vendor/kreuzberg/src/extraction/docx.rs +40 -0
- data/vendor/kreuzberg/src/extraction/email.rs +854 -0
- data/vendor/kreuzberg/src/extraction/excel.rs +688 -0
- data/vendor/kreuzberg/src/extraction/html.rs +553 -0
- data/vendor/kreuzberg/src/extraction/image.rs +368 -0
- data/vendor/kreuzberg/src/extraction/libreoffice.rs +563 -0
- data/vendor/kreuzberg/src/extraction/markdown.rs +213 -0
- data/vendor/kreuzberg/src/extraction/mod.rs +81 -0
- data/vendor/kreuzberg/src/extraction/office_metadata/app_properties.rs +398 -0
- data/vendor/kreuzberg/src/extraction/office_metadata/core_properties.rs +247 -0
- data/vendor/kreuzberg/src/extraction/office_metadata/custom_properties.rs +240 -0
- data/vendor/kreuzberg/src/extraction/office_metadata/mod.rs +130 -0
- data/vendor/kreuzberg/src/extraction/office_metadata/odt_properties.rs +287 -0
- data/vendor/kreuzberg/src/extraction/pptx.rs +3000 -0
- data/vendor/kreuzberg/src/extraction/structured.rs +490 -0
- data/vendor/kreuzberg/src/extraction/table.rs +328 -0
- data/vendor/kreuzberg/src/extraction/text.rs +269 -0
- data/vendor/kreuzberg/src/extraction/xml.rs +333 -0
- data/vendor/kreuzberg/src/extractors/archive.rs +446 -0
- data/vendor/kreuzberg/src/extractors/bibtex.rs +469 -0
- data/vendor/kreuzberg/src/extractors/docbook.rs +502 -0
- data/vendor/kreuzberg/src/extractors/docx.rs +367 -0
- data/vendor/kreuzberg/src/extractors/email.rs +143 -0
- data/vendor/kreuzberg/src/extractors/epub.rs +707 -0
- data/vendor/kreuzberg/src/extractors/excel.rs +343 -0
- data/vendor/kreuzberg/src/extractors/fictionbook.rs +491 -0
- data/vendor/kreuzberg/src/extractors/fictionbook.rs.backup2 +738 -0
- data/vendor/kreuzberg/src/extractors/html.rs +393 -0
- data/vendor/kreuzberg/src/extractors/image.rs +198 -0
- data/vendor/kreuzberg/src/extractors/jats.rs +1051 -0
- data/vendor/kreuzberg/src/extractors/jupyter.rs +367 -0
- data/vendor/kreuzberg/src/extractors/latex.rs +652 -0
- data/vendor/kreuzberg/src/extractors/markdown.rs +700 -0
- data/vendor/kreuzberg/src/extractors/mod.rs +365 -0
- data/vendor/kreuzberg/src/extractors/odt.rs +628 -0
- data/vendor/kreuzberg/src/extractors/opml.rs +634 -0
- data/vendor/kreuzberg/src/extractors/orgmode.rs +528 -0
- data/vendor/kreuzberg/src/extractors/pdf.rs +493 -0
- data/vendor/kreuzberg/src/extractors/pptx.rs +248 -0
- data/vendor/kreuzberg/src/extractors/rst.rs +576 -0
- data/vendor/kreuzberg/src/extractors/rtf.rs +810 -0
- data/vendor/kreuzberg/src/extractors/security.rs +484 -0
- data/vendor/kreuzberg/src/extractors/security_tests.rs +367 -0
- data/vendor/kreuzberg/src/extractors/structured.rs +140 -0
- data/vendor/kreuzberg/src/extractors/text.rs +260 -0
- data/vendor/kreuzberg/src/extractors/typst.rs +650 -0
- data/vendor/kreuzberg/src/extractors/xml.rs +135 -0
- data/vendor/kreuzberg/src/image/dpi.rs +164 -0
- data/vendor/kreuzberg/src/image/mod.rs +6 -0
- data/vendor/kreuzberg/src/image/preprocessing.rs +417 -0
- data/vendor/kreuzberg/src/image/resize.rs +89 -0
- data/vendor/kreuzberg/src/keywords/config.rs +154 -0
- data/vendor/kreuzberg/src/keywords/mod.rs +237 -0
- data/vendor/kreuzberg/src/keywords/processor.rs +267 -0
- data/vendor/kreuzberg/src/keywords/rake.rs +293 -0
- data/vendor/kreuzberg/src/keywords/types.rs +68 -0
- data/vendor/kreuzberg/src/keywords/yake.rs +163 -0
- data/vendor/kreuzberg/src/language_detection/mod.rs +942 -0
- data/vendor/kreuzberg/src/lib.rs +105 -0
- data/vendor/kreuzberg/src/mcp/mod.rs +32 -0
- data/vendor/kreuzberg/src/mcp/server.rs +1968 -0
- data/vendor/kreuzberg/src/ocr/cache.rs +469 -0
- data/vendor/kreuzberg/src/ocr/error.rs +37 -0
- data/vendor/kreuzberg/src/ocr/hocr.rs +216 -0
- data/vendor/kreuzberg/src/ocr/mod.rs +58 -0
- data/vendor/kreuzberg/src/ocr/processor.rs +863 -0
- data/vendor/kreuzberg/src/ocr/table/mod.rs +4 -0
- data/vendor/kreuzberg/src/ocr/table/tsv_parser.rs +144 -0
- data/vendor/kreuzberg/src/ocr/tesseract_backend.rs +450 -0
- data/vendor/kreuzberg/src/ocr/types.rs +393 -0
- data/vendor/kreuzberg/src/ocr/utils.rs +47 -0
- data/vendor/kreuzberg/src/ocr/validation.rs +206 -0
- data/vendor/kreuzberg/src/panic_context.rs +154 -0
- data/vendor/kreuzberg/src/pdf/error.rs +122 -0
- data/vendor/kreuzberg/src/pdf/images.rs +139 -0
- data/vendor/kreuzberg/src/pdf/metadata.rs +346 -0
- data/vendor/kreuzberg/src/pdf/mod.rs +50 -0
- data/vendor/kreuzberg/src/pdf/rendering.rs +369 -0
- data/vendor/kreuzberg/src/pdf/table.rs +393 -0
- data/vendor/kreuzberg/src/pdf/text.rs +158 -0
- data/vendor/kreuzberg/src/plugins/extractor.rs +1013 -0
- data/vendor/kreuzberg/src/plugins/mod.rs +209 -0
- data/vendor/kreuzberg/src/plugins/ocr.rs +620 -0
- data/vendor/kreuzberg/src/plugins/processor.rs +642 -0
- data/vendor/kreuzberg/src/plugins/registry.rs +1337 -0
- data/vendor/kreuzberg/src/plugins/traits.rs +258 -0
- data/vendor/kreuzberg/src/plugins/validator.rs +956 -0
- data/vendor/kreuzberg/src/stopwords/mod.rs +1470 -0
- data/vendor/kreuzberg/src/text/mod.rs +19 -0
- data/vendor/kreuzberg/src/text/quality.rs +697 -0
- data/vendor/kreuzberg/src/text/string_utils.rs +217 -0
- data/vendor/kreuzberg/src/text/token_reduction/cjk_utils.rs +164 -0
- data/vendor/kreuzberg/src/text/token_reduction/config.rs +100 -0
- data/vendor/kreuzberg/src/text/token_reduction/core.rs +796 -0
- data/vendor/kreuzberg/src/text/token_reduction/filters.rs +902 -0
- data/vendor/kreuzberg/src/text/token_reduction/mod.rs +160 -0
- data/vendor/kreuzberg/src/text/token_reduction/semantic.rs +619 -0
- data/vendor/kreuzberg/src/text/token_reduction/simd_text.rs +147 -0
- data/vendor/kreuzberg/src/types.rs +903 -0
- data/vendor/kreuzberg/src/utils/mod.rs +17 -0
- data/vendor/kreuzberg/src/utils/quality.rs +959 -0
- data/vendor/kreuzberg/src/utils/string_utils.rs +381 -0
- data/vendor/kreuzberg/stopwords/af_stopwords.json +53 -0
- data/vendor/kreuzberg/stopwords/ar_stopwords.json +482 -0
- data/vendor/kreuzberg/stopwords/bg_stopwords.json +261 -0
- data/vendor/kreuzberg/stopwords/bn_stopwords.json +400 -0
- data/vendor/kreuzberg/stopwords/br_stopwords.json +1205 -0
- data/vendor/kreuzberg/stopwords/ca_stopwords.json +280 -0
- data/vendor/kreuzberg/stopwords/cs_stopwords.json +425 -0
- data/vendor/kreuzberg/stopwords/da_stopwords.json +172 -0
- data/vendor/kreuzberg/stopwords/de_stopwords.json +622 -0
- data/vendor/kreuzberg/stopwords/el_stopwords.json +849 -0
- data/vendor/kreuzberg/stopwords/en_stopwords.json +1300 -0
- data/vendor/kreuzberg/stopwords/eo_stopwords.json +175 -0
- data/vendor/kreuzberg/stopwords/es_stopwords.json +734 -0
- data/vendor/kreuzberg/stopwords/et_stopwords.json +37 -0
- data/vendor/kreuzberg/stopwords/eu_stopwords.json +100 -0
- data/vendor/kreuzberg/stopwords/fa_stopwords.json +801 -0
- data/vendor/kreuzberg/stopwords/fi_stopwords.json +849 -0
- data/vendor/kreuzberg/stopwords/fr_stopwords.json +693 -0
- data/vendor/kreuzberg/stopwords/ga_stopwords.json +111 -0
- data/vendor/kreuzberg/stopwords/gl_stopwords.json +162 -0
- data/vendor/kreuzberg/stopwords/gu_stopwords.json +226 -0
- data/vendor/kreuzberg/stopwords/ha_stopwords.json +41 -0
- data/vendor/kreuzberg/stopwords/he_stopwords.json +196 -0
- data/vendor/kreuzberg/stopwords/hi_stopwords.json +227 -0
- data/vendor/kreuzberg/stopwords/hr_stopwords.json +181 -0
- data/vendor/kreuzberg/stopwords/hu_stopwords.json +791 -0
- data/vendor/kreuzberg/stopwords/hy_stopwords.json +47 -0
- data/vendor/kreuzberg/stopwords/id_stopwords.json +760 -0
- data/vendor/kreuzberg/stopwords/it_stopwords.json +634 -0
- data/vendor/kreuzberg/stopwords/ja_stopwords.json +136 -0
- data/vendor/kreuzberg/stopwords/kn_stopwords.json +84 -0
- data/vendor/kreuzberg/stopwords/ko_stopwords.json +681 -0
- data/vendor/kreuzberg/stopwords/ku_stopwords.json +64 -0
- data/vendor/kreuzberg/stopwords/la_stopwords.json +51 -0
- data/vendor/kreuzberg/stopwords/lt_stopwords.json +476 -0
- data/vendor/kreuzberg/stopwords/lv_stopwords.json +163 -0
- data/vendor/kreuzberg/stopwords/ml_stopwords.json +1 -0
- data/vendor/kreuzberg/stopwords/mr_stopwords.json +101 -0
- data/vendor/kreuzberg/stopwords/ms_stopwords.json +477 -0
- data/vendor/kreuzberg/stopwords/ne_stopwords.json +490 -0
- data/vendor/kreuzberg/stopwords/nl_stopwords.json +415 -0
- data/vendor/kreuzberg/stopwords/no_stopwords.json +223 -0
- data/vendor/kreuzberg/stopwords/pl_stopwords.json +331 -0
- data/vendor/kreuzberg/stopwords/pt_stopwords.json +562 -0
- data/vendor/kreuzberg/stopwords/ro_stopwords.json +436 -0
- data/vendor/kreuzberg/stopwords/ru_stopwords.json +561 -0
- data/vendor/kreuzberg/stopwords/si_stopwords.json +193 -0
- data/vendor/kreuzberg/stopwords/sk_stopwords.json +420 -0
- data/vendor/kreuzberg/stopwords/sl_stopwords.json +448 -0
- data/vendor/kreuzberg/stopwords/so_stopwords.json +32 -0
- data/vendor/kreuzberg/stopwords/st_stopwords.json +33 -0
- data/vendor/kreuzberg/stopwords/sv_stopwords.json +420 -0
- data/vendor/kreuzberg/stopwords/sw_stopwords.json +76 -0
- data/vendor/kreuzberg/stopwords/ta_stopwords.json +129 -0
- data/vendor/kreuzberg/stopwords/te_stopwords.json +54 -0
- data/vendor/kreuzberg/stopwords/th_stopwords.json +118 -0
- data/vendor/kreuzberg/stopwords/tl_stopwords.json +149 -0
- data/vendor/kreuzberg/stopwords/tr_stopwords.json +506 -0
- data/vendor/kreuzberg/stopwords/uk_stopwords.json +75 -0
- data/vendor/kreuzberg/stopwords/ur_stopwords.json +519 -0
- data/vendor/kreuzberg/stopwords/vi_stopwords.json +647 -0
- data/vendor/kreuzberg/stopwords/yo_stopwords.json +62 -0
- data/vendor/kreuzberg/stopwords/zh_stopwords.json +796 -0
- data/vendor/kreuzberg/stopwords/zu_stopwords.json +31 -0
- data/vendor/kreuzberg/tests/api_extract_multipart.rs +52 -0
- data/vendor/kreuzberg/tests/api_tests.rs +966 -0
- data/vendor/kreuzberg/tests/archive_integration.rs +543 -0
- data/vendor/kreuzberg/tests/batch_orchestration.rs +556 -0
- data/vendor/kreuzberg/tests/batch_processing.rs +316 -0
- data/vendor/kreuzberg/tests/bibtex_parity_test.rs +421 -0
- data/vendor/kreuzberg/tests/concurrency_stress.rs +525 -0
- data/vendor/kreuzberg/tests/config_features.rs +598 -0
- data/vendor/kreuzberg/tests/config_loading_tests.rs +415 -0
- data/vendor/kreuzberg/tests/core_integration.rs +510 -0
- data/vendor/kreuzberg/tests/csv_integration.rs +414 -0
- data/vendor/kreuzberg/tests/docbook_extractor_tests.rs +498 -0
- data/vendor/kreuzberg/tests/docx_metadata_extraction_test.rs +122 -0
- data/vendor/kreuzberg/tests/docx_vs_pandoc_comparison.rs +370 -0
- data/vendor/kreuzberg/tests/email_integration.rs +325 -0
- data/vendor/kreuzberg/tests/epub_native_extractor_tests.rs +275 -0
- data/vendor/kreuzberg/tests/error_handling.rs +393 -0
- data/vendor/kreuzberg/tests/fictionbook_extractor_tests.rs +228 -0
- data/vendor/kreuzberg/tests/format_integration.rs +159 -0
- data/vendor/kreuzberg/tests/helpers/mod.rs +142 -0
- data/vendor/kreuzberg/tests/html_table_test.rs +551 -0
- data/vendor/kreuzberg/tests/image_integration.rs +253 -0
- data/vendor/kreuzberg/tests/instrumentation_test.rs +139 -0
- data/vendor/kreuzberg/tests/jats_extractor_tests.rs +639 -0
- data/vendor/kreuzberg/tests/jupyter_extractor_tests.rs +704 -0
- data/vendor/kreuzberg/tests/keywords_integration.rs +479 -0
- data/vendor/kreuzberg/tests/keywords_quality.rs +509 -0
- data/vendor/kreuzberg/tests/latex_extractor_tests.rs +496 -0
- data/vendor/kreuzberg/tests/markdown_extractor_tests.rs +490 -0
- data/vendor/kreuzberg/tests/mime_detection.rs +428 -0
- data/vendor/kreuzberg/tests/ocr_configuration.rs +510 -0
- data/vendor/kreuzberg/tests/ocr_errors.rs +676 -0
- data/vendor/kreuzberg/tests/ocr_quality.rs +627 -0
- data/vendor/kreuzberg/tests/ocr_stress.rs +469 -0
- data/vendor/kreuzberg/tests/odt_extractor_tests.rs +695 -0
- data/vendor/kreuzberg/tests/opml_extractor_tests.rs +616 -0
- data/vendor/kreuzberg/tests/orgmode_extractor_tests.rs +822 -0
- data/vendor/kreuzberg/tests/pdf_integration.rs +43 -0
- data/vendor/kreuzberg/tests/pipeline_integration.rs +1411 -0
- data/vendor/kreuzberg/tests/plugin_ocr_backend_test.rs +771 -0
- data/vendor/kreuzberg/tests/plugin_postprocessor_test.rs +560 -0
- data/vendor/kreuzberg/tests/plugin_system.rs +921 -0
- data/vendor/kreuzberg/tests/plugin_validator_test.rs +783 -0
- data/vendor/kreuzberg/tests/registry_integration_tests.rs +586 -0
- data/vendor/kreuzberg/tests/rst_extractor_tests.rs +692 -0
- data/vendor/kreuzberg/tests/rtf_extractor_tests.rs +776 -0
- data/vendor/kreuzberg/tests/security_validation.rs +415 -0
- data/vendor/kreuzberg/tests/stopwords_integration_test.rs +888 -0
- data/vendor/kreuzberg/tests/test_fastembed.rs +609 -0
- data/vendor/kreuzberg/tests/typst_behavioral_tests.rs +1259 -0
- data/vendor/kreuzberg/tests/typst_extractor_tests.rs +647 -0
- data/vendor/kreuzberg/tests/xlsx_metadata_extraction_test.rs +87 -0
- data/vendor/rb-sys/.cargo-ok +1 -0
- data/vendor/rb-sys/.cargo_vcs_info.json +6 -0
- data/vendor/rb-sys/Cargo.lock +393 -0
- data/vendor/rb-sys/Cargo.toml +70 -0
- data/vendor/rb-sys/Cargo.toml.orig +57 -0
- data/vendor/rb-sys/LICENSE-APACHE +190 -0
- data/vendor/rb-sys/LICENSE-MIT +21 -0
- data/vendor/rb-sys/bin/release.sh +21 -0
- data/vendor/rb-sys/build/features.rs +108 -0
- data/vendor/rb-sys/build/main.rs +246 -0
- data/vendor/rb-sys/build/stable_api_config.rs +153 -0
- data/vendor/rb-sys/build/version.rs +48 -0
- data/vendor/rb-sys/readme.md +36 -0
- data/vendor/rb-sys/src/bindings.rs +21 -0
- data/vendor/rb-sys/src/hidden.rs +11 -0
- data/vendor/rb-sys/src/lib.rs +34 -0
- data/vendor/rb-sys/src/macros.rs +371 -0
- data/vendor/rb-sys/src/memory.rs +53 -0
- data/vendor/rb-sys/src/ruby_abi_version.rs +38 -0
- data/vendor/rb-sys/src/special_consts.rs +31 -0
- data/vendor/rb-sys/src/stable_api/compiled.c +179 -0
- data/vendor/rb-sys/src/stable_api/compiled.rs +257 -0
- data/vendor/rb-sys/src/stable_api/ruby_2_6.rs +316 -0
- data/vendor/rb-sys/src/stable_api/ruby_2_7.rs +316 -0
- data/vendor/rb-sys/src/stable_api/ruby_3_0.rs +324 -0
- data/vendor/rb-sys/src/stable_api/ruby_3_1.rs +317 -0
- data/vendor/rb-sys/src/stable_api/ruby_3_2.rs +315 -0
- data/vendor/rb-sys/src/stable_api/ruby_3_3.rs +326 -0
- data/vendor/rb-sys/src/stable_api/ruby_3_4.rs +327 -0
- data/vendor/rb-sys/src/stable_api.rs +261 -0
- data/vendor/rb-sys/src/symbol.rs +31 -0
- data/vendor/rb-sys/src/tracking_allocator.rs +332 -0
- data/vendor/rb-sys/src/utils.rs +89 -0
- data/vendor/rb-sys/src/value_type.rs +7 -0
- metadata +536 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#![cfg(feature = "office")]
|
|
2
|
+
|
|
3
|
+
use kreuzberg::core::config::ExtractionConfig;
|
|
4
|
+
use kreuzberg::plugins::DocumentExtractor;
|
|
5
|
+
use std::path::PathBuf;
|
|
6
|
+
|
|
7
|
+
/// Helper to get absolute path to test documents
|
|
8
|
+
fn test_file_path(filename: &str) -> PathBuf {
|
|
9
|
+
let manifest_dir = env!("CARGO_MANIFEST_DIR");
|
|
10
|
+
PathBuf::from(manifest_dir)
|
|
11
|
+
.parent()
|
|
12
|
+
.unwrap()
|
|
13
|
+
.parent()
|
|
14
|
+
.unwrap()
|
|
15
|
+
.join("test_documents")
|
|
16
|
+
.join("fictionbook")
|
|
17
|
+
.join(filename)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#[tokio::test]
|
|
21
|
+
async fn test_fictionbook_extract_metadata_title() {
|
|
22
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
23
|
+
let path = test_file_path("meta.fb2");
|
|
24
|
+
|
|
25
|
+
let result = extractor
|
|
26
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
27
|
+
.await
|
|
28
|
+
.expect("Failed to extract FB2 file");
|
|
29
|
+
|
|
30
|
+
assert!(
|
|
31
|
+
result.content.contains("Book title"),
|
|
32
|
+
"Book title should be extracted from FB2 content"
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
#[tokio::test]
|
|
37
|
+
async fn test_fictionbook_extract_metadata_genre() {
|
|
38
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
39
|
+
let path = test_file_path("meta.fb2");
|
|
40
|
+
|
|
41
|
+
let result = extractor
|
|
42
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
43
|
+
.await
|
|
44
|
+
.expect("Failed to extract FB2 file");
|
|
45
|
+
|
|
46
|
+
assert!(result.metadata.subject.is_none());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#[tokio::test]
|
|
50
|
+
async fn test_fictionbook_extract_content_sections() {
|
|
51
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
52
|
+
let path = test_file_path("titles.fb2");
|
|
53
|
+
|
|
54
|
+
let result = extractor
|
|
55
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
56
|
+
.await
|
|
57
|
+
.expect("Failed to extract FB2 file");
|
|
58
|
+
|
|
59
|
+
assert!(
|
|
60
|
+
result.content.contains("Simple title"),
|
|
61
|
+
"Section titles should be extracted"
|
|
62
|
+
);
|
|
63
|
+
assert!(
|
|
64
|
+
result.content.contains("Emphasized"),
|
|
65
|
+
"Section with emphasis should be extracted"
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#[tokio::test]
|
|
70
|
+
async fn test_fictionbook_extract_section_hierarchy() {
|
|
71
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
72
|
+
let path = test_file_path("basic.fb2");
|
|
73
|
+
|
|
74
|
+
let result = extractor
|
|
75
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
76
|
+
.await
|
|
77
|
+
.expect("Failed to extract FB2 file");
|
|
78
|
+
|
|
79
|
+
assert!(
|
|
80
|
+
result.content.contains("Top-level title"),
|
|
81
|
+
"Top-level section should be extracted"
|
|
82
|
+
);
|
|
83
|
+
assert!(result.content.contains("Section"), "Nested section should be extracted");
|
|
84
|
+
assert!(
|
|
85
|
+
result.content.contains("Subsection"),
|
|
86
|
+
"Nested subsection should be extracted"
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#[tokio::test]
|
|
91
|
+
async fn test_fictionbook_extract_inline_markup() {
|
|
92
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
93
|
+
let path = test_file_path("emphasis.fb2");
|
|
94
|
+
|
|
95
|
+
let result = extractor
|
|
96
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
97
|
+
.await
|
|
98
|
+
.expect("Failed to extract FB2 file");
|
|
99
|
+
|
|
100
|
+
let content = result.content.to_lowercase();
|
|
101
|
+
assert!(content.contains("plain"), "Plain text should be extracted");
|
|
102
|
+
assert!(content.contains("strong"), "Strong emphasis should be extracted");
|
|
103
|
+
assert!(content.contains("emphasis"), "Emphasis should be extracted");
|
|
104
|
+
assert!(content.contains("strikethrough"), "Strikethrough should be extracted");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
#[tokio::test]
|
|
108
|
+
async fn test_fictionbook_extract_emphasis() {
|
|
109
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
110
|
+
let path = test_file_path("basic.fb2");
|
|
111
|
+
|
|
112
|
+
let result = extractor
|
|
113
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
114
|
+
.await
|
|
115
|
+
.expect("Failed to extract FB2 file");
|
|
116
|
+
|
|
117
|
+
assert!(
|
|
118
|
+
result.content.contains("emphasized"),
|
|
119
|
+
"Emphasized text should be extracted"
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
#[tokio::test]
|
|
124
|
+
async fn test_fictionbook_extract_strong() {
|
|
125
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
126
|
+
let path = test_file_path("basic.fb2");
|
|
127
|
+
|
|
128
|
+
let result = extractor
|
|
129
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
130
|
+
.await
|
|
131
|
+
.expect("Failed to extract FB2 file");
|
|
132
|
+
|
|
133
|
+
assert!(result.content.contains("strong"), "Strong text should be extracted");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
#[tokio::test]
|
|
137
|
+
async fn test_fictionbook_extract_code() {
|
|
138
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
139
|
+
let path = test_file_path("basic.fb2");
|
|
140
|
+
|
|
141
|
+
let result = extractor
|
|
142
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
143
|
+
.await
|
|
144
|
+
.expect("Failed to extract FB2 file");
|
|
145
|
+
|
|
146
|
+
assert!(result.content.contains("verbatim"), "Code content should be extracted");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
#[tokio::test]
|
|
150
|
+
async fn test_fictionbook_extract_blockquote() {
|
|
151
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
152
|
+
let path = test_file_path("basic.fb2");
|
|
153
|
+
|
|
154
|
+
let result = extractor
|
|
155
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
156
|
+
.await
|
|
157
|
+
.expect("Failed to extract FB2 file");
|
|
158
|
+
|
|
159
|
+
assert!(result.content.contains("Blockquote"), "Blockquote should be extracted");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
#[tokio::test]
|
|
163
|
+
async fn test_fictionbook_extract_tables() {
|
|
164
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
165
|
+
let path = test_file_path("tables.fb2");
|
|
166
|
+
|
|
167
|
+
let result = extractor
|
|
168
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
169
|
+
.await
|
|
170
|
+
.expect("Failed to extract FB2 file");
|
|
171
|
+
|
|
172
|
+
assert!(
|
|
173
|
+
!result.content.is_empty(),
|
|
174
|
+
"Content should be extracted from file with tables"
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
#[tokio::test]
|
|
179
|
+
async fn test_fictionbook_markdown_formatting_preservation() {
|
|
180
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
181
|
+
let path = test_file_path("emphasis.fb2");
|
|
182
|
+
|
|
183
|
+
let result = extractor
|
|
184
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
185
|
+
.await
|
|
186
|
+
.expect("Failed to extract FB2 file");
|
|
187
|
+
|
|
188
|
+
assert!(
|
|
189
|
+
result.content.contains("**strong**"),
|
|
190
|
+
"Strong text should be formatted as **bold** in markdown"
|
|
191
|
+
);
|
|
192
|
+
assert!(
|
|
193
|
+
result.content.contains("*emphasis*"),
|
|
194
|
+
"Emphasis text should be formatted as *italic* in markdown"
|
|
195
|
+
);
|
|
196
|
+
assert!(
|
|
197
|
+
result.content.contains("~~deleted~~"),
|
|
198
|
+
"Strikethrough text should be formatted as ~~strikethrough~~ in markdown"
|
|
199
|
+
);
|
|
200
|
+
assert!(
|
|
201
|
+
result.content.contains("`code`"),
|
|
202
|
+
"Code text should be wrapped in backticks in markdown"
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
#[tokio::test]
|
|
207
|
+
async fn test_fictionbook_formatting_in_body_paragraphs() {
|
|
208
|
+
let extractor = kreuzberg::extractors::FictionBookExtractor::new();
|
|
209
|
+
let path = test_file_path("basic.fb2");
|
|
210
|
+
|
|
211
|
+
let result = extractor
|
|
212
|
+
.extract_file(&path, "application/x-fictionbook+xml", &ExtractionConfig::default())
|
|
213
|
+
.await
|
|
214
|
+
.expect("Failed to extract FB2 file");
|
|
215
|
+
|
|
216
|
+
assert!(
|
|
217
|
+
result.content.contains("*emphasized*"),
|
|
218
|
+
"Emphasis formatting should be preserved in body content"
|
|
219
|
+
);
|
|
220
|
+
assert!(
|
|
221
|
+
result.content.contains("**strong**"),
|
|
222
|
+
"Strong formatting should be preserved in body content"
|
|
223
|
+
);
|
|
224
|
+
assert!(
|
|
225
|
+
result.content.contains("`verbatim`"),
|
|
226
|
+
"Code formatting should be preserved in body content"
|
|
227
|
+
);
|
|
228
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
//! Binding-specific format integration tests.
|
|
2
|
+
//!
|
|
3
|
+
//! Positive-path scenarios are now covered by the shared fixture-based E2E
|
|
4
|
+
//! suites. The tests here focus on behaviour that is specific to the Rust
|
|
5
|
+
//! asynchronous APIs or to graceful handling when optional system
|
|
6
|
+
//! dependencies are missing.
|
|
7
|
+
|
|
8
|
+
mod helpers;
|
|
9
|
+
|
|
10
|
+
use helpers::{assert_mime_type, assert_non_empty_content, get_test_file_path, test_documents_available};
|
|
11
|
+
use kreuzberg::core::config::ExtractionConfig;
|
|
12
|
+
use kreuzberg::core::extractor::extract_file;
|
|
13
|
+
|
|
14
|
+
#[cfg(feature = "ocr")]
|
|
15
|
+
use kreuzberg::core::config::OcrConfig;
|
|
16
|
+
|
|
17
|
+
#[cfg(feature = "pdf")]
|
|
18
|
+
#[tokio::test]
|
|
19
|
+
async fn test_pdf_password_protected_async() {
|
|
20
|
+
if !test_documents_available() {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let path = get_test_file_path("pdfs/copy_protected.pdf");
|
|
25
|
+
if !path.exists() {
|
|
26
|
+
tracing::debug!("Skipping test: protected PDF not available");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let result = extract_file(&path, None, &ExtractionConfig::default()).await;
|
|
31
|
+
|
|
32
|
+
match result {
|
|
33
|
+
Err(err) => {
|
|
34
|
+
tracing::debug!("Password protection detected (expected): {}", err);
|
|
35
|
+
}
|
|
36
|
+
Ok(res) => {
|
|
37
|
+
tracing::debug!("Protected PDF extracted; some files allow fallback");
|
|
38
|
+
assert_mime_type(&res, "application/pdf");
|
|
39
|
+
assert!(res.chunks.is_none(), "Chunks should be None without chunking config");
|
|
40
|
+
assert!(res.detected_languages.is_none(), "Language detection not enabled");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
#[cfg(feature = "office")]
|
|
46
|
+
#[tokio::test]
|
|
47
|
+
async fn test_legacy_doc_extraction_async() {
|
|
48
|
+
if !test_documents_available() {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let path = get_test_file_path("legacy_office/simple.doc");
|
|
53
|
+
if !path.exists() {
|
|
54
|
+
tracing::debug!("Skipping test: legacy .doc file not available");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let result = extract_file(&path, None, &ExtractionConfig::default()).await;
|
|
59
|
+
|
|
60
|
+
match result {
|
|
61
|
+
Ok(extracted) => {
|
|
62
|
+
assert_mime_type(&extracted, "application/msword");
|
|
63
|
+
assert_non_empty_content(&extracted);
|
|
64
|
+
assert!(
|
|
65
|
+
extracted.chunks.is_none(),
|
|
66
|
+
"Chunks should be None without chunking config"
|
|
67
|
+
);
|
|
68
|
+
assert!(extracted.detected_languages.is_none(), "Language detection not enabled");
|
|
69
|
+
}
|
|
70
|
+
Err(err) => {
|
|
71
|
+
tracing::debug!(
|
|
72
|
+
"Legacy Office extraction failed (LibreOffice may not be installed): {}",
|
|
73
|
+
err
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#[cfg(feature = "ocr")]
|
|
80
|
+
#[tokio::test]
|
|
81
|
+
async fn test_ocr_simple_english_image_async() {
|
|
82
|
+
if !test_documents_available() {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let path = get_test_file_path("images/test_hello_world.png");
|
|
87
|
+
if !path.exists() {
|
|
88
|
+
tracing::debug!("Skipping test: OCR sample image not available");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let config = ExtractionConfig {
|
|
93
|
+
ocr: Some(OcrConfig {
|
|
94
|
+
backend: "tesseract".to_string(),
|
|
95
|
+
language: "eng".to_string(),
|
|
96
|
+
tesseract_config: None,
|
|
97
|
+
}),
|
|
98
|
+
force_ocr: true,
|
|
99
|
+
..Default::default()
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
let result = extract_file(&path, None, &config).await;
|
|
103
|
+
|
|
104
|
+
match result {
|
|
105
|
+
Ok(res) => {
|
|
106
|
+
assert_mime_type(&res, "image/png");
|
|
107
|
+
assert_non_empty_content(&res);
|
|
108
|
+
let content_lower = res.content.to_lowercase();
|
|
109
|
+
assert!(
|
|
110
|
+
content_lower.contains("hello") || content_lower.contains("world"),
|
|
111
|
+
"OCR output {:?} should contain HELLO or WORLD",
|
|
112
|
+
res.content
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
Err(err) => {
|
|
116
|
+
tracing::debug!("OCR test failed (Tesseract may not be installed): {}", err);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#[cfg(feature = "ocr")]
|
|
122
|
+
#[tokio::test]
|
|
123
|
+
async fn test_ocr_image_without_text_async() {
|
|
124
|
+
if !test_documents_available() {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let path = get_test_file_path("images/flower_no_text.jpg");
|
|
129
|
+
if !path.exists() {
|
|
130
|
+
tracing::debug!("Skipping test: OCR flower image not available");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let config = ExtractionConfig {
|
|
135
|
+
ocr: Some(OcrConfig {
|
|
136
|
+
backend: "tesseract".to_string(),
|
|
137
|
+
language: "eng".to_string(),
|
|
138
|
+
tesseract_config: None,
|
|
139
|
+
}),
|
|
140
|
+
force_ocr: true,
|
|
141
|
+
..Default::default()
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
let result = extract_file(&path, None, &config).await;
|
|
145
|
+
|
|
146
|
+
match result {
|
|
147
|
+
Ok(res) => {
|
|
148
|
+
assert_mime_type(&res, "image/jpeg");
|
|
149
|
+
assert!(
|
|
150
|
+
res.content.len() < 200,
|
|
151
|
+
"Expected minimal OCR output, got {} bytes",
|
|
152
|
+
res.content.len()
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
Err(err) => {
|
|
156
|
+
tracing::debug!("OCR fallback test failed (Tesseract may not be installed): {}", err);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
//! Shared test helpers for integration tests.
|
|
2
|
+
//!
|
|
3
|
+
//! This module provides common utilities for loading test files,
|
|
4
|
+
//! making assertions, and setting up test environments.
|
|
5
|
+
|
|
6
|
+
#![allow(dead_code)]
|
|
7
|
+
|
|
8
|
+
use kreuzberg::types::ExtractionResult;
|
|
9
|
+
use std::path::PathBuf;
|
|
10
|
+
|
|
11
|
+
/// Get the test_documents directory path.
|
|
12
|
+
///
|
|
13
|
+
/// This assumes the test is running from the workspace root.
|
|
14
|
+
pub fn get_test_documents_dir() -> PathBuf {
|
|
15
|
+
let workspace_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
16
|
+
.parent()
|
|
17
|
+
.unwrap()
|
|
18
|
+
.parent()
|
|
19
|
+
.unwrap()
|
|
20
|
+
.to_path_buf();
|
|
21
|
+
|
|
22
|
+
workspace_root.join("test_documents")
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// Get the full path to a test file.
|
|
26
|
+
///
|
|
27
|
+
/// # Arguments
|
|
28
|
+
///
|
|
29
|
+
/// * `relative_path` - Path relative to test_documents/
|
|
30
|
+
pub fn get_test_file_path(relative_path: &str) -> PathBuf {
|
|
31
|
+
get_test_documents_dir().join(relative_path)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// Assert that extraction result contains non-empty content.
|
|
35
|
+
///
|
|
36
|
+
/// This is a common assertion for most extraction tests - we want
|
|
37
|
+
/// to verify that *something* was extracted, even if we don't know
|
|
38
|
+
/// the exact content.
|
|
39
|
+
pub fn assert_non_empty_content(result: &ExtractionResult) {
|
|
40
|
+
assert!(
|
|
41
|
+
!result.content.trim().is_empty(),
|
|
42
|
+
"Extraction result should have non-empty content, got: '{}'",
|
|
43
|
+
result.content
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Assert that extraction result has expected MIME type.
|
|
48
|
+
pub fn assert_mime_type(result: &ExtractionResult, expected: &str) {
|
|
49
|
+
assert_eq!(
|
|
50
|
+
result.mime_type, expected,
|
|
51
|
+
"Expected MIME type '{}', got '{}'",
|
|
52
|
+
expected, result.mime_type
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// Skip test if file doesn't exist (for optional test files).
|
|
57
|
+
///
|
|
58
|
+
/// Returns true if test should be skipped.
|
|
59
|
+
pub fn skip_if_missing(relative_path: &str) -> bool {
|
|
60
|
+
let path = get_test_file_path(relative_path);
|
|
61
|
+
if !path.exists() {
|
|
62
|
+
tracing::debug!("Skipping test: file not found at {}", path.display());
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
false
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// Check if test documents directory exists and has files.
|
|
69
|
+
///
|
|
70
|
+
/// This is useful for CI environments where test_documents might
|
|
71
|
+
/// be a git submodule that hasn't been initialized.
|
|
72
|
+
pub fn test_documents_available() -> bool {
|
|
73
|
+
let dir = get_test_documents_dir();
|
|
74
|
+
dir.exists() && dir.read_dir().map(|mut d| d.next().is_some()).unwrap_or(false)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/// Assert that content length is above a minimum threshold.
|
|
78
|
+
///
|
|
79
|
+
/// This is useful for smoke testing - ensuring substantial content
|
|
80
|
+
/// was extracted without needing to verify exact text.
|
|
81
|
+
pub fn assert_min_content_length(result: &ExtractionResult, min_length: usize) {
|
|
82
|
+
assert!(
|
|
83
|
+
result.content.len() >= min_length,
|
|
84
|
+
"Expected content length >= {}, got {}. Content preview: '{}'",
|
|
85
|
+
min_length,
|
|
86
|
+
result.content.len(),
|
|
87
|
+
result.content.chars().take(200).collect::<String>()
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/// Assert that content contains at least one of the given substrings.
|
|
92
|
+
pub fn assert_content_contains_any(result: &ExtractionResult, substrings: &[&str]) {
|
|
93
|
+
let found = substrings.iter().any(|s| result.content.contains(s));
|
|
94
|
+
assert!(
|
|
95
|
+
found,
|
|
96
|
+
"Expected content to contain at least one of {:?}, but found none",
|
|
97
|
+
substrings
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/// Assert that extraction result has at least one table.
|
|
102
|
+
pub fn assert_has_tables(result: &ExtractionResult) {
|
|
103
|
+
assert!(
|
|
104
|
+
!result.tables.is_empty(),
|
|
105
|
+
"Expected result to have tables, but found none"
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Create a test configuration with OCR enabled.
|
|
110
|
+
pub fn test_config_with_ocr() -> kreuzberg::core::config::ExtractionConfig {
|
|
111
|
+
use kreuzberg::core::config::{ExtractionConfig, OcrConfig};
|
|
112
|
+
|
|
113
|
+
ExtractionConfig {
|
|
114
|
+
ocr: Some(OcrConfig {
|
|
115
|
+
backend: "tesseract".to_string(),
|
|
116
|
+
language: "eng".to_string(),
|
|
117
|
+
tesseract_config: None,
|
|
118
|
+
}),
|
|
119
|
+
force_ocr: false,
|
|
120
|
+
..Default::default()
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
#[cfg(test)]
|
|
125
|
+
mod tests {
|
|
126
|
+
use super::*;
|
|
127
|
+
|
|
128
|
+
#[test]
|
|
129
|
+
fn test_get_test_documents_dir() {
|
|
130
|
+
let dir = get_test_documents_dir();
|
|
131
|
+
assert!(dir.to_string_lossy().ends_with("test_documents"));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
#[test]
|
|
135
|
+
fn test_test_documents_available() {
|
|
136
|
+
let available = test_documents_available();
|
|
137
|
+
if !available {
|
|
138
|
+
tracing::debug!("Warning: test_documents directory not available");
|
|
139
|
+
tracing::debug!("This is expected in CI without git submodules initialized");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|