kreuzberg 4.0.8 → 4.1.0

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.
Files changed (308) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -2
  3. data/README.md +1 -1
  4. data/ext/kreuzberg_rb/native/Cargo.lock +94 -98
  5. data/ext/kreuzberg_rb/native/Cargo.toml +4 -2
  6. data/ext/kreuzberg_rb/native/src/batch.rs +139 -0
  7. data/ext/kreuzberg_rb/native/src/config/mod.rs +10 -0
  8. data/ext/kreuzberg_rb/native/src/config/types.rs +1058 -0
  9. data/ext/kreuzberg_rb/native/src/error_handling.rs +125 -0
  10. data/ext/kreuzberg_rb/native/src/extraction.rs +79 -0
  11. data/ext/kreuzberg_rb/native/src/gc_guarded_value.rs +35 -0
  12. data/ext/kreuzberg_rb/native/src/helpers.rs +176 -0
  13. data/ext/kreuzberg_rb/native/src/lib.rs +342 -3622
  14. data/ext/kreuzberg_rb/native/src/metadata.rs +34 -0
  15. data/ext/kreuzberg_rb/native/src/plugins/mod.rs +92 -0
  16. data/ext/kreuzberg_rb/native/src/plugins/ocr_backend.rs +159 -0
  17. data/ext/kreuzberg_rb/native/src/plugins/post_processor.rs +126 -0
  18. data/ext/kreuzberg_rb/native/src/plugins/validator.rs +99 -0
  19. data/ext/kreuzberg_rb/native/src/result.rs +326 -0
  20. data/ext/kreuzberg_rb/native/src/validation.rs +4 -0
  21. data/lib/kreuzberg/config.rb +66 -0
  22. data/lib/kreuzberg/result.rb +107 -2
  23. data/lib/kreuzberg/types.rb +104 -0
  24. data/lib/kreuzberg/version.rb +1 -1
  25. data/lib/kreuzberg.rb +0 -4
  26. data/sig/kreuzberg.rbs +105 -1
  27. data/vendor/Cargo.toml +3 -3
  28. data/vendor/kreuzberg/Cargo.toml +4 -3
  29. data/vendor/kreuzberg/README.md +1 -1
  30. data/vendor/kreuzberg/src/api/config.rs +69 -0
  31. data/vendor/kreuzberg/src/api/handlers.rs +99 -2
  32. data/vendor/kreuzberg/src/api/mod.rs +14 -7
  33. data/vendor/kreuzberg/src/api/router.rs +214 -0
  34. data/vendor/kreuzberg/src/api/startup.rs +243 -0
  35. data/vendor/kreuzberg/src/api/types.rs +78 -0
  36. data/vendor/kreuzberg/src/cache/cleanup.rs +277 -0
  37. data/vendor/kreuzberg/src/cache/core.rs +428 -0
  38. data/vendor/kreuzberg/src/cache/mod.rs +21 -843
  39. data/vendor/kreuzberg/src/cache/utilities.rs +156 -0
  40. data/vendor/kreuzberg/src/chunking/boundaries.rs +301 -0
  41. data/vendor/kreuzberg/src/chunking/builder.rs +294 -0
  42. data/vendor/kreuzberg/src/chunking/config.rs +52 -0
  43. data/vendor/kreuzberg/src/chunking/core.rs +1017 -0
  44. data/vendor/kreuzberg/src/chunking/mod.rs +14 -2211
  45. data/vendor/kreuzberg/src/chunking/processor.rs +10 -0
  46. data/vendor/kreuzberg/src/chunking/validation.rs +686 -0
  47. data/vendor/kreuzberg/src/core/config/extraction/core.rs +169 -0
  48. data/vendor/kreuzberg/src/core/config/extraction/env.rs +179 -0
  49. data/vendor/kreuzberg/src/core/config/extraction/loaders.rs +204 -0
  50. data/vendor/kreuzberg/src/core/config/extraction/mod.rs +42 -0
  51. data/vendor/kreuzberg/src/core/config/extraction/types.rs +93 -0
  52. data/vendor/kreuzberg/src/core/config/formats.rs +135 -0
  53. data/vendor/kreuzberg/src/core/config/mod.rs +20 -0
  54. data/vendor/kreuzberg/src/core/config/ocr.rs +73 -0
  55. data/vendor/kreuzberg/src/core/config/page.rs +57 -0
  56. data/vendor/kreuzberg/src/core/config/pdf.rs +111 -0
  57. data/vendor/kreuzberg/src/core/config/processing.rs +312 -0
  58. data/vendor/kreuzberg/src/core/config_validation/dependencies.rs +187 -0
  59. data/vendor/kreuzberg/src/core/config_validation/mod.rs +386 -0
  60. data/vendor/kreuzberg/src/core/config_validation/sections.rs +401 -0
  61. data/vendor/kreuzberg/src/core/extractor/batch.rs +246 -0
  62. data/vendor/kreuzberg/src/core/extractor/bytes.rs +116 -0
  63. data/vendor/kreuzberg/src/core/extractor/file.rs +240 -0
  64. data/vendor/kreuzberg/src/core/extractor/helpers.rs +71 -0
  65. data/vendor/kreuzberg/src/core/extractor/legacy.rs +62 -0
  66. data/vendor/kreuzberg/src/core/extractor/mod.rs +490 -0
  67. data/vendor/kreuzberg/src/core/extractor/sync.rs +208 -0
  68. data/vendor/kreuzberg/src/core/mod.rs +4 -1
  69. data/vendor/kreuzberg/src/core/pipeline/cache.rs +60 -0
  70. data/vendor/kreuzberg/src/core/pipeline/execution.rs +89 -0
  71. data/vendor/kreuzberg/src/core/pipeline/features.rs +108 -0
  72. data/vendor/kreuzberg/src/core/pipeline/format.rs +392 -0
  73. data/vendor/kreuzberg/src/core/pipeline/initialization.rs +67 -0
  74. data/vendor/kreuzberg/src/core/pipeline/mod.rs +135 -0
  75. data/vendor/kreuzberg/src/core/pipeline/tests.rs +975 -0
  76. data/vendor/kreuzberg/src/core/server_config/env.rs +90 -0
  77. data/vendor/kreuzberg/src/core/server_config/loader.rs +202 -0
  78. data/vendor/kreuzberg/src/core/server_config/mod.rs +380 -0
  79. data/vendor/kreuzberg/src/core/server_config/tests/basic_tests.rs +124 -0
  80. data/vendor/kreuzberg/src/core/server_config/tests/env_tests.rs +216 -0
  81. data/vendor/kreuzberg/src/core/server_config/tests/file_loading_tests.rs +341 -0
  82. data/vendor/kreuzberg/src/core/server_config/tests/mod.rs +5 -0
  83. data/vendor/kreuzberg/src/core/server_config/validation.rs +17 -0
  84. data/vendor/kreuzberg/src/embeddings.rs +136 -13
  85. data/vendor/kreuzberg/src/extraction/{archive.rs → archive/mod.rs} +45 -239
  86. data/vendor/kreuzberg/src/extraction/archive/sevenz.rs +98 -0
  87. data/vendor/kreuzberg/src/extraction/archive/tar.rs +118 -0
  88. data/vendor/kreuzberg/src/extraction/archive/zip.rs +101 -0
  89. data/vendor/kreuzberg/src/extraction/html/converter.rs +592 -0
  90. data/vendor/kreuzberg/src/extraction/html/image_handling.rs +95 -0
  91. data/vendor/kreuzberg/src/extraction/html/mod.rs +53 -0
  92. data/vendor/kreuzberg/src/extraction/html/processor.rs +659 -0
  93. data/vendor/kreuzberg/src/extraction/html/stack_management.rs +103 -0
  94. data/vendor/kreuzberg/src/extraction/html/types.rs +28 -0
  95. data/vendor/kreuzberg/src/extraction/mod.rs +6 -2
  96. data/vendor/kreuzberg/src/extraction/pptx/container.rs +159 -0
  97. data/vendor/kreuzberg/src/extraction/pptx/content_builder.rs +168 -0
  98. data/vendor/kreuzberg/src/extraction/pptx/elements.rs +132 -0
  99. data/vendor/kreuzberg/src/extraction/pptx/image_handling.rs +57 -0
  100. data/vendor/kreuzberg/src/extraction/pptx/metadata.rs +160 -0
  101. data/vendor/kreuzberg/src/extraction/pptx/mod.rs +558 -0
  102. data/vendor/kreuzberg/src/extraction/pptx/parser.rs +379 -0
  103. data/vendor/kreuzberg/src/extraction/transform/content.rs +205 -0
  104. data/vendor/kreuzberg/src/extraction/transform/elements.rs +211 -0
  105. data/vendor/kreuzberg/src/extraction/transform/mod.rs +480 -0
  106. data/vendor/kreuzberg/src/extraction/transform/types.rs +27 -0
  107. data/vendor/kreuzberg/src/extractors/archive.rs +2 -0
  108. data/vendor/kreuzberg/src/extractors/bibtex.rs +2 -0
  109. data/vendor/kreuzberg/src/extractors/djot_format/attributes.rs +134 -0
  110. data/vendor/kreuzberg/src/extractors/djot_format/conversion.rs +223 -0
  111. data/vendor/kreuzberg/src/extractors/djot_format/extractor.rs +172 -0
  112. data/vendor/kreuzberg/src/extractors/djot_format/mod.rs +24 -0
  113. data/vendor/kreuzberg/src/extractors/djot_format/parsing/block_handlers.rs +271 -0
  114. data/vendor/kreuzberg/src/extractors/djot_format/parsing/content_extraction.rs +257 -0
  115. data/vendor/kreuzberg/src/extractors/djot_format/parsing/event_handlers.rs +101 -0
  116. data/vendor/kreuzberg/src/extractors/djot_format/parsing/inline_handlers.rs +201 -0
  117. data/vendor/kreuzberg/src/extractors/djot_format/parsing/mod.rs +16 -0
  118. data/vendor/kreuzberg/src/extractors/djot_format/parsing/state.rs +78 -0
  119. data/vendor/kreuzberg/src/extractors/djot_format/parsing/table_extraction.rs +68 -0
  120. data/vendor/kreuzberg/src/extractors/djot_format/parsing/text_extraction.rs +61 -0
  121. data/vendor/kreuzberg/src/extractors/djot_format/rendering.rs +452 -0
  122. data/vendor/kreuzberg/src/extractors/docbook.rs +2 -0
  123. data/vendor/kreuzberg/src/extractors/docx.rs +12 -1
  124. data/vendor/kreuzberg/src/extractors/email.rs +2 -0
  125. data/vendor/kreuzberg/src/extractors/epub/content.rs +333 -0
  126. data/vendor/kreuzberg/src/extractors/epub/metadata.rs +137 -0
  127. data/vendor/kreuzberg/src/extractors/epub/mod.rs +186 -0
  128. data/vendor/kreuzberg/src/extractors/epub/parsing.rs +86 -0
  129. data/vendor/kreuzberg/src/extractors/excel.rs +4 -0
  130. data/vendor/kreuzberg/src/extractors/fictionbook.rs +2 -0
  131. data/vendor/kreuzberg/src/extractors/frontmatter_utils.rs +466 -0
  132. data/vendor/kreuzberg/src/extractors/html.rs +80 -8
  133. data/vendor/kreuzberg/src/extractors/image.rs +8 -1
  134. data/vendor/kreuzberg/src/extractors/jats/elements.rs +350 -0
  135. data/vendor/kreuzberg/src/extractors/jats/metadata.rs +21 -0
  136. data/vendor/kreuzberg/src/extractors/{jats.rs → jats/mod.rs} +10 -412
  137. data/vendor/kreuzberg/src/extractors/jats/parser.rs +52 -0
  138. data/vendor/kreuzberg/src/extractors/jupyter.rs +2 -0
  139. data/vendor/kreuzberg/src/extractors/latex/commands.rs +93 -0
  140. data/vendor/kreuzberg/src/extractors/latex/environments.rs +157 -0
  141. data/vendor/kreuzberg/src/extractors/latex/metadata.rs +27 -0
  142. data/vendor/kreuzberg/src/extractors/latex/mod.rs +146 -0
  143. data/vendor/kreuzberg/src/extractors/latex/parser.rs +231 -0
  144. data/vendor/kreuzberg/src/extractors/latex/utilities.rs +126 -0
  145. data/vendor/kreuzberg/src/extractors/markdown.rs +39 -162
  146. data/vendor/kreuzberg/src/extractors/mod.rs +9 -1
  147. data/vendor/kreuzberg/src/extractors/odt.rs +2 -0
  148. data/vendor/kreuzberg/src/extractors/opml/core.rs +165 -0
  149. data/vendor/kreuzberg/src/extractors/opml/mod.rs +31 -0
  150. data/vendor/kreuzberg/src/extractors/opml/parser.rs +479 -0
  151. data/vendor/kreuzberg/src/extractors/orgmode.rs +2 -0
  152. data/vendor/kreuzberg/src/extractors/pdf/extraction.rs +106 -0
  153. data/vendor/kreuzberg/src/extractors/{pdf.rs → pdf/mod.rs} +25 -324
  154. data/vendor/kreuzberg/src/extractors/pdf/ocr.rs +214 -0
  155. data/vendor/kreuzberg/src/extractors/pdf/pages.rs +51 -0
  156. data/vendor/kreuzberg/src/extractors/pptx.rs +9 -2
  157. data/vendor/kreuzberg/src/extractors/rst.rs +2 -0
  158. data/vendor/kreuzberg/src/extractors/rtf/encoding.rs +116 -0
  159. data/vendor/kreuzberg/src/extractors/rtf/formatting.rs +24 -0
  160. data/vendor/kreuzberg/src/extractors/rtf/images.rs +72 -0
  161. data/vendor/kreuzberg/src/extractors/rtf/metadata.rs +216 -0
  162. data/vendor/kreuzberg/src/extractors/rtf/mod.rs +142 -0
  163. data/vendor/kreuzberg/src/extractors/rtf/parser.rs +259 -0
  164. data/vendor/kreuzberg/src/extractors/rtf/tables.rs +83 -0
  165. data/vendor/kreuzberg/src/extractors/structured.rs +2 -0
  166. data/vendor/kreuzberg/src/extractors/text.rs +4 -0
  167. data/vendor/kreuzberg/src/extractors/typst.rs +2 -0
  168. data/vendor/kreuzberg/src/extractors/xml.rs +2 -0
  169. data/vendor/kreuzberg/src/keywords/processor.rs +14 -0
  170. data/vendor/kreuzberg/src/language_detection/processor.rs +10 -0
  171. data/vendor/kreuzberg/src/lib.rs +2 -2
  172. data/vendor/kreuzberg/src/mcp/errors.rs +312 -0
  173. data/vendor/kreuzberg/src/mcp/format.rs +211 -0
  174. data/vendor/kreuzberg/src/mcp/mod.rs +9 -3
  175. data/vendor/kreuzberg/src/mcp/params.rs +196 -0
  176. data/vendor/kreuzberg/src/mcp/server.rs +39 -1438
  177. data/vendor/kreuzberg/src/mcp/tools/cache.rs +179 -0
  178. data/vendor/kreuzberg/src/mcp/tools/extraction.rs +403 -0
  179. data/vendor/kreuzberg/src/mcp/tools/mime.rs +150 -0
  180. data/vendor/kreuzberg/src/mcp/tools/mod.rs +11 -0
  181. data/vendor/kreuzberg/src/ocr/backends/easyocr.rs +96 -0
  182. data/vendor/kreuzberg/src/ocr/backends/mod.rs +7 -0
  183. data/vendor/kreuzberg/src/ocr/backends/paddleocr.rs +27 -0
  184. data/vendor/kreuzberg/src/ocr/backends/tesseract.rs +134 -0
  185. data/vendor/kreuzberg/src/ocr/hocr.rs +60 -16
  186. data/vendor/kreuzberg/src/ocr/language_registry.rs +11 -235
  187. data/vendor/kreuzberg/src/ocr/mod.rs +1 -0
  188. data/vendor/kreuzberg/src/ocr/processor/config.rs +203 -0
  189. data/vendor/kreuzberg/src/ocr/processor/execution.rs +494 -0
  190. data/vendor/kreuzberg/src/ocr/processor/mod.rs +265 -0
  191. data/vendor/kreuzberg/src/ocr/processor/validation.rs +145 -0
  192. data/vendor/kreuzberg/src/ocr/tesseract_backend.rs +41 -24
  193. data/vendor/kreuzberg/src/pdf/bindings.rs +21 -8
  194. data/vendor/kreuzberg/src/pdf/hierarchy/bounding_box.rs +289 -0
  195. data/vendor/kreuzberg/src/pdf/hierarchy/clustering.rs +199 -0
  196. data/vendor/kreuzberg/src/pdf/{hierarchy.rs → hierarchy/extraction.rs} +6 -346
  197. data/vendor/kreuzberg/src/pdf/hierarchy/mod.rs +18 -0
  198. data/vendor/kreuzberg/src/plugins/extractor/mod.rs +319 -0
  199. data/vendor/kreuzberg/src/plugins/extractor/registry.rs +434 -0
  200. data/vendor/kreuzberg/src/plugins/extractor/trait.rs +391 -0
  201. data/vendor/kreuzberg/src/plugins/mod.rs +13 -0
  202. data/vendor/kreuzberg/src/plugins/ocr.rs +11 -0
  203. data/vendor/kreuzberg/src/plugins/processor/mod.rs +365 -0
  204. data/vendor/kreuzberg/src/plugins/processor/registry.rs +37 -0
  205. data/vendor/kreuzberg/src/plugins/processor/trait.rs +284 -0
  206. data/vendor/kreuzberg/src/plugins/registry/extractor.rs +416 -0
  207. data/vendor/kreuzberg/src/plugins/registry/mod.rs +116 -0
  208. data/vendor/kreuzberg/src/plugins/registry/ocr.rs +293 -0
  209. data/vendor/kreuzberg/src/plugins/registry/processor.rs +304 -0
  210. data/vendor/kreuzberg/src/plugins/registry/validator.rs +238 -0
  211. data/vendor/kreuzberg/src/plugins/validator/mod.rs +424 -0
  212. data/vendor/kreuzberg/src/plugins/validator/registry.rs +355 -0
  213. data/vendor/kreuzberg/src/plugins/validator/trait.rs +276 -0
  214. data/vendor/kreuzberg/src/stopwords/languages/asian.rs +40 -0
  215. data/vendor/kreuzberg/src/stopwords/languages/germanic.rs +36 -0
  216. data/vendor/kreuzberg/src/stopwords/languages/mod.rs +10 -0
  217. data/vendor/kreuzberg/src/stopwords/languages/other.rs +44 -0
  218. data/vendor/kreuzberg/src/stopwords/languages/romance.rs +36 -0
  219. data/vendor/kreuzberg/src/stopwords/languages/slavic.rs +36 -0
  220. data/vendor/kreuzberg/src/stopwords/mod.rs +7 -33
  221. data/vendor/kreuzberg/src/text/quality.rs +1 -1
  222. data/vendor/kreuzberg/src/text/quality_processor.rs +10 -0
  223. data/vendor/kreuzberg/src/text/token_reduction/core/analysis.rs +238 -0
  224. data/vendor/kreuzberg/src/text/token_reduction/core/mod.rs +8 -0
  225. data/vendor/kreuzberg/src/text/token_reduction/core/punctuation.rs +54 -0
  226. data/vendor/kreuzberg/src/text/token_reduction/core/reducer.rs +384 -0
  227. data/vendor/kreuzberg/src/text/token_reduction/core/sentence_selection.rs +68 -0
  228. data/vendor/kreuzberg/src/text/token_reduction/core/word_filtering.rs +156 -0
  229. data/vendor/kreuzberg/src/text/token_reduction/filters/general.rs +377 -0
  230. data/vendor/kreuzberg/src/text/token_reduction/filters/html.rs +51 -0
  231. data/vendor/kreuzberg/src/text/token_reduction/filters/markdown.rs +285 -0
  232. data/vendor/kreuzberg/src/text/token_reduction/filters.rs +131 -246
  233. data/vendor/kreuzberg/src/types/djot.rs +209 -0
  234. data/vendor/kreuzberg/src/types/extraction.rs +301 -0
  235. data/vendor/kreuzberg/src/types/formats.rs +443 -0
  236. data/vendor/kreuzberg/src/types/metadata.rs +560 -0
  237. data/vendor/kreuzberg/src/types/mod.rs +281 -0
  238. data/vendor/kreuzberg/src/types/page.rs +182 -0
  239. data/vendor/kreuzberg/src/types/serde_helpers.rs +132 -0
  240. data/vendor/kreuzberg/src/types/tables.rs +39 -0
  241. data/vendor/kreuzberg/src/utils/quality/heuristics.rs +58 -0
  242. data/vendor/kreuzberg/src/utils/{quality.rs → quality/mod.rs} +168 -489
  243. data/vendor/kreuzberg/src/utils/quality/patterns.rs +117 -0
  244. data/vendor/kreuzberg/src/utils/quality/scoring.rs +178 -0
  245. data/vendor/kreuzberg/src/utils/string_pool/buffer_pool.rs +325 -0
  246. data/vendor/kreuzberg/src/utils/string_pool/interned.rs +102 -0
  247. data/vendor/kreuzberg/src/utils/string_pool/language_pool.rs +119 -0
  248. data/vendor/kreuzberg/src/utils/string_pool/mime_pool.rs +235 -0
  249. data/vendor/kreuzberg/src/utils/string_pool/mod.rs +41 -0
  250. data/vendor/kreuzberg/tests/api_chunk.rs +313 -0
  251. data/vendor/kreuzberg/tests/api_embed.rs +6 -9
  252. data/vendor/kreuzberg/tests/batch_orchestration.rs +1 -0
  253. data/vendor/kreuzberg/tests/concurrency_stress.rs +7 -0
  254. data/vendor/kreuzberg/tests/core_integration.rs +1 -0
  255. data/vendor/kreuzberg/tests/docx_metadata_extraction_test.rs +130 -0
  256. data/vendor/kreuzberg/tests/epub_native_extractor_tests.rs +5 -14
  257. data/vendor/kreuzberg/tests/format_integration.rs +2 -0
  258. data/vendor/kreuzberg/tests/helpers/mod.rs +1 -0
  259. data/vendor/kreuzberg/tests/html_table_test.rs +11 -11
  260. data/vendor/kreuzberg/tests/ocr_configuration.rs +16 -0
  261. data/vendor/kreuzberg/tests/ocr_errors.rs +18 -0
  262. data/vendor/kreuzberg/tests/ocr_quality.rs +9 -0
  263. data/vendor/kreuzberg/tests/ocr_stress.rs +1 -0
  264. data/vendor/kreuzberg/tests/pipeline_integration.rs +50 -0
  265. data/vendor/kreuzberg/tests/plugin_ocr_backend_test.rs +13 -0
  266. data/vendor/kreuzberg/tests/plugin_system.rs +12 -0
  267. data/vendor/kreuzberg/tests/registry_integration_tests.rs +2 -0
  268. data/vendor/kreuzberg-ffi/Cargo.toml +2 -1
  269. data/vendor/kreuzberg-ffi/benches/result_view_benchmark.rs +2 -0
  270. data/vendor/kreuzberg-ffi/kreuzberg.h +347 -178
  271. data/vendor/kreuzberg-ffi/src/config/html.rs +318 -0
  272. data/vendor/kreuzberg-ffi/src/config/loader.rs +154 -0
  273. data/vendor/kreuzberg-ffi/src/config/merge.rs +104 -0
  274. data/vendor/kreuzberg-ffi/src/config/mod.rs +385 -0
  275. data/vendor/kreuzberg-ffi/src/config/parse.rs +91 -0
  276. data/vendor/kreuzberg-ffi/src/config/serialize.rs +118 -0
  277. data/vendor/kreuzberg-ffi/src/config_builder.rs +598 -0
  278. data/vendor/kreuzberg-ffi/src/error.rs +46 -14
  279. data/vendor/kreuzberg-ffi/src/helpers.rs +10 -0
  280. data/vendor/kreuzberg-ffi/src/html_options.rs +421 -0
  281. data/vendor/kreuzberg-ffi/src/lib.rs +16 -0
  282. data/vendor/kreuzberg-ffi/src/panic_shield.rs +11 -0
  283. data/vendor/kreuzberg-ffi/src/plugins/ocr_backend.rs +2 -0
  284. data/vendor/kreuzberg-ffi/src/result.rs +148 -122
  285. data/vendor/kreuzberg-ffi/src/result_view.rs +4 -0
  286. data/vendor/kreuzberg-tesseract/Cargo.toml +2 -2
  287. metadata +200 -28
  288. data/vendor/kreuzberg/src/api/server.rs +0 -518
  289. data/vendor/kreuzberg/src/core/config.rs +0 -1914
  290. data/vendor/kreuzberg/src/core/config_validation.rs +0 -949
  291. data/vendor/kreuzberg/src/core/extractor.rs +0 -1200
  292. data/vendor/kreuzberg/src/core/pipeline.rs +0 -1223
  293. data/vendor/kreuzberg/src/core/server_config.rs +0 -1220
  294. data/vendor/kreuzberg/src/extraction/html.rs +0 -1830
  295. data/vendor/kreuzberg/src/extraction/pptx.rs +0 -3102
  296. data/vendor/kreuzberg/src/extractors/epub.rs +0 -696
  297. data/vendor/kreuzberg/src/extractors/latex.rs +0 -653
  298. data/vendor/kreuzberg/src/extractors/opml.rs +0 -635
  299. data/vendor/kreuzberg/src/extractors/rtf.rs +0 -809
  300. data/vendor/kreuzberg/src/ocr/processor.rs +0 -858
  301. data/vendor/kreuzberg/src/plugins/extractor.rs +0 -1042
  302. data/vendor/kreuzberg/src/plugins/processor.rs +0 -650
  303. data/vendor/kreuzberg/src/plugins/registry.rs +0 -1339
  304. data/vendor/kreuzberg/src/plugins/validator.rs +0 -967
  305. data/vendor/kreuzberg/src/text/token_reduction/core.rs +0 -832
  306. data/vendor/kreuzberg/src/types.rs +0 -1713
  307. data/vendor/kreuzberg/src/utils/string_pool.rs +0 -762
  308. data/vendor/kreuzberg-ffi/src/config.rs +0 -1341
@@ -1,653 +0,0 @@
1
- //! Native Rust LaTeX text extractor.
2
- //!
3
- //! This extractor provides comprehensive LaTeX document parsing and text extraction.
4
- //!
5
- //! Features:
6
- //! - Metadata extraction: title, author, date from \title{}, \author{}, \date{}
7
- //! - Section hierarchy: \section{}, \subsection{}, \subsubsection{}, etc.
8
- //! - Inline formatting: \emph{}, \textbf{}, \textit{}, \texttt{}, \underline{}
9
- //! - Lists: itemize, enumerate, description environments
10
- //! - Tables: tabular environment parsing
11
- //! - Math: inline ($...$) and display (\[...\]) math preservation
12
- //! - Unicode support
13
- //!
14
- //! Requires the `office` feature.
15
-
16
- use crate::Result;
17
- use crate::core::config::ExtractionConfig;
18
- use crate::plugins::{DocumentExtractor, Plugin};
19
- use crate::types::{ExtractionResult, Metadata, Table};
20
- use async_trait::async_trait;
21
-
22
- /// LaTeX document extractor
23
- pub struct LatexExtractor;
24
-
25
- impl LatexExtractor {
26
- /// Create a new LaTeX extractor.
27
- pub fn new() -> Self {
28
- Self
29
- }
30
-
31
- /// Parse LaTeX content and extract text.
32
- fn extract_from_latex(content: &str) -> (String, Metadata, Vec<Table>) {
33
- let mut parser = LatexParser::new(content);
34
- parser.parse()
35
- }
36
- }
37
-
38
- impl Default for LatexExtractor {
39
- fn default() -> Self {
40
- Self::new()
41
- }
42
- }
43
-
44
- impl Plugin for LatexExtractor {
45
- fn name(&self) -> &str {
46
- "latex-extractor"
47
- }
48
-
49
- fn version(&self) -> String {
50
- env!("CARGO_PKG_VERSION").to_string()
51
- }
52
-
53
- fn initialize(&self) -> Result<()> {
54
- Ok(())
55
- }
56
-
57
- fn shutdown(&self) -> Result<()> {
58
- Ok(())
59
- }
60
-
61
- fn description(&self) -> &str {
62
- "Native Rust LaTeX document extractor with metadata and table support"
63
- }
64
-
65
- fn author(&self) -> &str {
66
- "Kreuzberg Team"
67
- }
68
- }
69
-
70
- #[async_trait]
71
- impl DocumentExtractor for LatexExtractor {
72
- #[cfg_attr(feature = "otel", tracing::instrument(
73
- skip(self, content, _config),
74
- fields(
75
- extractor.name = self.name(),
76
- content.size_bytes = content.len(),
77
- )
78
- ))]
79
- async fn extract_bytes(
80
- &self,
81
- content: &[u8],
82
- mime_type: &str,
83
- _config: &ExtractionConfig,
84
- ) -> Result<ExtractionResult> {
85
- let latex_str = String::from_utf8_lossy(content).to_string();
86
- let (text, metadata, tables) = Self::extract_from_latex(&latex_str);
87
-
88
- Ok(ExtractionResult {
89
- content: text,
90
- mime_type: mime_type.to_string(),
91
- metadata,
92
- tables,
93
- detected_languages: None,
94
- chunks: None,
95
- images: None,
96
- pages: None,
97
- })
98
- }
99
-
100
- fn supported_mime_types(&self) -> &[&str] {
101
- &["application/x-latex", "text/x-tex"]
102
- }
103
-
104
- fn priority(&self) -> i32 {
105
- 50
106
- }
107
- }
108
-
109
- /// LaTeX parser
110
- struct LatexParser<'a> {
111
- source: &'a str,
112
- metadata: Metadata,
113
- tables: Vec<Table>,
114
- output: String,
115
- }
116
-
117
- impl<'a> LatexParser<'a> {
118
- fn new(source: &'a str) -> Self {
119
- Self {
120
- source,
121
- metadata: Metadata::default(),
122
- tables: Vec::new(),
123
- output: String::new(),
124
- }
125
- }
126
-
127
- fn parse(&mut self) -> (String, Metadata, Vec<Table>) {
128
- let lines: Vec<&str> = self.source.lines().collect();
129
- let mut in_document = false;
130
- let mut skip_until_end = None::<String>;
131
- let mut i = 0;
132
-
133
- let is_plain_tex = self.source.contains("\\bye") && !self.source.contains("\\begin{document}");
134
- if is_plain_tex {
135
- in_document = true;
136
- }
137
-
138
- while i < lines.len() {
139
- let line = lines[i];
140
- let trimmed = line.trim();
141
-
142
- if let Some(ref env) = skip_until_end {
143
- if trimmed.contains(&format!("\\end{{{}}}", env)) {
144
- skip_until_end = None;
145
- }
146
- i += 1;
147
- continue;
148
- }
149
-
150
- if is_plain_tex && trimmed.contains("\\bye") {
151
- break;
152
- }
153
-
154
- if !in_document && !is_plain_tex {
155
- self.extract_metadata_from_line(trimmed);
156
- }
157
-
158
- if !is_plain_tex && trimmed.contains("\\begin{document}") {
159
- in_document = true;
160
-
161
- if trimmed.contains("\\end{document}") {
162
- let Some(begin_pos) = trimmed.find("\\begin{document}") else {
163
- break;
164
- };
165
- let Some(end_pos) = trimmed.find("\\end{document}") else {
166
- break;
167
- };
168
- let content_between = trimmed[begin_pos + 16..end_pos].trim();
169
- if !content_between.is_empty() {
170
- if content_between.starts_with("\\section{") {
171
- if let Some(title) = self.extract_braced(content_between, "section") {
172
- self.output.push_str(&format!("\n# {}\n\n", title));
173
- }
174
- } else {
175
- let processed = self.process_line(content_between);
176
- if !processed.is_empty() {
177
- self.output.push_str(&processed);
178
- self.output.push('\n');
179
- }
180
- }
181
- }
182
- break;
183
- }
184
-
185
- i += 1;
186
- continue;
187
- }
188
-
189
- if !is_plain_tex && trimmed.contains("\\end{document}") {
190
- break;
191
- }
192
-
193
- if in_document {
194
- if trimmed.contains("\\begin{") {
195
- let Some(env_name) = self.extract_env_name(trimmed) else {
196
- i += 1;
197
- continue;
198
- };
199
- match env_name.as_str() {
200
- "itemize" | "enumerate" | "description" => {
201
- let (env_content, new_i) = self.collect_environment(&lines, i, &env_name);
202
- self.process_list(&env_content, &env_name);
203
- i = new_i;
204
- continue;
205
- }
206
- "tabular" => {
207
- let (env_content, new_i) = self.collect_environment(&lines, i, "tabular");
208
- self.process_table(&env_content);
209
- i = new_i;
210
- continue;
211
- }
212
- "table" => {
213
- let (env_content, new_i) = self.collect_environment(&lines, i, "table");
214
- self.process_table_with_caption(&env_content);
215
- i = new_i;
216
- continue;
217
- }
218
- "equation" | "align" | "gather" | "multline" => {
219
- let (env_content, new_i) = self.collect_environment(&lines, i, &env_name);
220
- self.output.push_str("$$\\begin{");
221
- self.output.push_str(&env_name);
222
- self.output.push_str("}\n");
223
- self.output.push_str(&env_content);
224
- self.output.push_str("\\end{");
225
- self.output.push_str(&env_name);
226
- self.output.push_str("}$$\n\n");
227
- i = new_i;
228
- continue;
229
- }
230
- _ => {
231
- skip_until_end = Some(env_name);
232
- }
233
- }
234
- }
235
-
236
- if trimmed.starts_with("\\section{") {
237
- if let Some(title) = self.extract_braced(trimmed, "section") {
238
- self.output.push_str(&format!("\n# {}\n\n", title));
239
- }
240
- } else if trimmed.starts_with("\\subsection{") {
241
- if let Some(title) = self.extract_braced(trimmed, "subsection") {
242
- self.output.push_str(&format!("## {}\n\n", title));
243
- }
244
- } else if trimmed.starts_with("\\subsubsection{") {
245
- if let Some(title) = self.extract_braced(trimmed, "subsubsection") {
246
- self.output.push_str(&format!("### {}\n\n", title));
247
- }
248
- } else if trimmed.starts_with("\\[") {
249
- let mut math_content = trimmed.to_string();
250
- if !trimmed.contains("\\]") {
251
- i += 1;
252
- while i < lines.len() {
253
- let math_line = lines[i];
254
- math_content.push('\n');
255
- math_content.push_str(math_line);
256
- if math_line.trim().contains("\\]") {
257
- break;
258
- }
259
- i += 1;
260
- }
261
- }
262
- self.output.push_str(&math_content);
263
- self.output.push('\n');
264
- } else if !trimmed.is_empty() && !trimmed.starts_with("%") {
265
- let processed = self.process_line(trimmed);
266
- if !processed.is_empty() {
267
- self.output.push_str(&processed);
268
- self.output.push('\n');
269
- }
270
- }
271
- }
272
-
273
- i += 1;
274
- }
275
-
276
- let content = self.output.trim().to_string();
277
- (content, self.metadata.clone(), self.tables.clone())
278
- }
279
-
280
- fn extract_metadata_from_line(&mut self, line: &str) {
281
- if line.starts_with("\\title{") {
282
- let Some(title) = self.extract_braced(line, "title") else {
283
- return;
284
- };
285
- self.metadata.additional.insert("title".to_string(), title.into());
286
- } else if line.starts_with("\\author{") {
287
- let Some(author) = self.extract_braced(line, "author") else {
288
- return;
289
- };
290
- self.metadata.additional.insert("author".to_string(), author.into());
291
- } else if line.starts_with("\\date{") {
292
- let Some(date) = self.extract_braced(line, "date") else {
293
- return;
294
- };
295
- self.metadata.additional.insert("date".to_string(), date.into());
296
- }
297
- }
298
-
299
- fn extract_env_name(&self, line: &str) -> Option<String> {
300
- if let Some(start) = line.find("\\begin{") {
301
- let after = &line[start + 7..];
302
- if let Some(end) = after.find('}') {
303
- return Some(after[..end].to_string());
304
- }
305
- }
306
- None
307
- }
308
-
309
- fn collect_environment(&self, lines: &[&str], start_idx: usize, env_name: &str) -> (String, usize) {
310
- let mut content = String::new();
311
- let mut i = start_idx + 1;
312
- let end_marker = format!("\\end{{{}}}", env_name);
313
-
314
- while i < lines.len() {
315
- let line = lines[i];
316
- if line.trim().contains(&end_marker) {
317
- return (content, i + 1);
318
- }
319
- content.push_str(line);
320
- content.push('\n');
321
- i += 1;
322
- }
323
-
324
- (content, i)
325
- }
326
-
327
- fn process_list(&mut self, content: &str, list_type: &str) {
328
- let lines: Vec<&str> = content.lines().collect();
329
- let mut item_num = 1;
330
- let mut i = 0;
331
-
332
- while i < lines.len() {
333
- let line = lines[i];
334
- let trimmed = line.trim();
335
-
336
- if trimmed.contains("\\begin{") {
337
- let Some(env_name) = self.extract_env_name(trimmed) else {
338
- i += 1;
339
- continue;
340
- };
341
- if env_name == "itemize" || env_name == "enumerate" || env_name == "description" {
342
- let (nested_content, new_i) = self.collect_environment(&lines, i, &env_name);
343
- let current_output_len = self.output.len();
344
- self.process_list(&nested_content, &env_name);
345
- let nested_output = self.output[current_output_len..].to_string();
346
- self.output.truncate(current_output_len);
347
- for nested_line in nested_output.lines() {
348
- self.output.push_str(" ");
349
- self.output.push_str(nested_line);
350
- self.output.push('\n');
351
- }
352
- i = new_i;
353
- continue;
354
- }
355
- }
356
-
357
- if trimmed.starts_with("\\item") {
358
- let Some(pos) = trimmed.find("\\item") else {
359
- i += 1;
360
- continue;
361
- };
362
- let after = trimmed[pos + 5..].trim();
363
-
364
- if after.starts_with('[') {
365
- let Some(bracket_end) = after.find(']') else {
366
- i += 1;
367
- continue;
368
- };
369
- let label = after[1..bracket_end].to_string();
370
- let text = after[bracket_end + 1..].trim().to_string();
371
- if list_type == "description" {
372
- let processed_text = self.process_line(&text);
373
- self.output.push_str(&format!("{}: {}\n", label, processed_text));
374
- item_num += 1;
375
- i += 1;
376
- continue;
377
- }
378
- }
379
-
380
- let prefix = if list_type == "enumerate" {
381
- format!("{}. ", item_num)
382
- } else {
383
- "- ".to_string()
384
- };
385
- self.output.push_str(&prefix);
386
-
387
- let item_text = self.process_line(after);
388
- self.output.push_str(item_text.trim());
389
- self.output.push('\n');
390
- item_num += 1;
391
- }
392
-
393
- i += 1;
394
- }
395
- self.output.push('\n');
396
- }
397
-
398
- fn process_table(&mut self, content: &str) {
399
- let lines: Vec<&str> = content.lines().collect();
400
- let mut rows: Vec<Vec<String>> = Vec::new();
401
-
402
- for line in lines {
403
- let trimmed = line.trim();
404
- if trimmed.starts_with("\\hline") || trimmed.is_empty() || trimmed.contains("\\begin{tabular}") {
405
- continue;
406
- }
407
-
408
- let row_str = trimmed.replace("\\\\", "");
409
- let cells: Vec<String> = row_str
410
- .split('&')
411
- .map(|s| self.clean_text(s.trim()))
412
- .filter(|s| !s.is_empty())
413
- .collect();
414
-
415
- if !cells.is_empty() {
416
- rows.push(cells);
417
- }
418
- }
419
-
420
- if !rows.is_empty() {
421
- let mut markdown = String::new();
422
- for (i, row) in rows.iter().enumerate() {
423
- markdown.push('|');
424
- for cell in row {
425
- markdown.push_str(&format!(" {} |", cell));
426
- }
427
- markdown.push('\n');
428
-
429
- if i == 0 && rows.len() > 1 {
430
- markdown.push('|');
431
- for _ in row {
432
- markdown.push_str(" --- |");
433
- }
434
- markdown.push('\n');
435
- }
436
- }
437
-
438
- self.output.push_str(&markdown);
439
-
440
- let table = Table {
441
- cells: rows,
442
- markdown: markdown.clone(),
443
- page_number: 1,
444
- };
445
- self.tables.push(table);
446
- }
447
- }
448
-
449
- fn process_table_with_caption(&mut self, content: &str) {
450
- if content.contains("\\caption{") {
451
- let Some(caption) = self.extract_braced_from_content(content, "caption") else {
452
- return;
453
- };
454
- self.output.push_str(&caption);
455
- self.output.push('\n');
456
- }
457
-
458
- if content.contains("\\begin{tabular}") {
459
- let Some(start) = content.find("\\begin{tabular}") else {
460
- return;
461
- };
462
- let Some(end) = content.find("\\end{tabular}") else {
463
- return;
464
- };
465
- let tabular_content = &content[start..end + 13];
466
- self.process_table(tabular_content);
467
- }
468
- }
469
-
470
- fn process_line(&self, line: &str) -> String {
471
- let mut result = String::new();
472
- let mut chars = line.chars().peekable();
473
-
474
- while let Some(ch) = chars.next() {
475
- if ch == '\\' {
476
- let mut cmd = String::new();
477
- while let Some(&c) = chars.peek() {
478
- if c.is_alphabetic() {
479
- cmd.push(chars.next().unwrap());
480
- } else {
481
- break;
482
- }
483
- }
484
-
485
- match cmd.as_str() {
486
- "textbf" => {
487
- if let Some(content) = self.read_braced_from_chars(&mut chars) {
488
- let processed = self.process_line(&content);
489
- result.push_str(&processed);
490
- }
491
- }
492
- "textit" | "emph" => {
493
- if let Some(content) = self.read_braced_from_chars(&mut chars) {
494
- let processed = self.process_line(&content);
495
- result.push_str(&processed);
496
- }
497
- }
498
- "texttt" => {
499
- if let Some(content) = self.read_braced_from_chars(&mut chars) {
500
- result.push_str(&content);
501
- }
502
- }
503
- "underline" => {
504
- if let Some(content) = self.read_braced_from_chars(&mut chars) {
505
- let processed = self.process_line(&content);
506
- result.push_str(&processed);
507
- }
508
- }
509
- "font" => {
510
- while let Some(&c) = chars.peek() {
511
- if c == '\\' {
512
- break;
513
- }
514
- chars.next();
515
- }
516
- }
517
- "usepackage" => {
518
- self.read_braced_from_chars(&mut chars);
519
- }
520
- _ => {
521
- if let Some(content) = self.read_braced_from_chars(&mut chars) {
522
- let processed = self.process_line(&content);
523
- result.push_str(&processed);
524
- } else if cmd.len() == 1 {
525
- }
526
- }
527
- }
528
- } else if ch == '$' {
529
- result.push(ch);
530
- while let Some(&c) = chars.peek() {
531
- result.push(chars.next().unwrap());
532
- if c == '$' {
533
- break;
534
- }
535
- }
536
- } else {
537
- result.push(ch);
538
- }
539
- }
540
-
541
- result
542
- }
543
-
544
- fn read_braced_from_chars(&self, chars: &mut std::iter::Peekable<std::str::Chars>) -> Option<String> {
545
- while let Some(&c) = chars.peek() {
546
- if c.is_whitespace() {
547
- chars.next();
548
- } else {
549
- break;
550
- }
551
- }
552
-
553
- if chars.peek() != Some(&'{') {
554
- return None;
555
- }
556
- chars.next();
557
-
558
- let mut content = String::new();
559
- let mut depth = 1;
560
-
561
- for c in chars.by_ref() {
562
- match c {
563
- '{' => {
564
- depth += 1;
565
- content.push(c);
566
- }
567
- '}' => {
568
- depth -= 1;
569
- if depth == 0 {
570
- return Some(content);
571
- }
572
- content.push(c);
573
- }
574
- _ => content.push(c),
575
- }
576
- }
577
-
578
- Some(content)
579
- }
580
-
581
- fn extract_braced(&self, text: &str, command: &str) -> Option<String> {
582
- let pattern = format!("\\{}{{", command);
583
- if let Some(start) = text.find(&pattern) {
584
- let after = &text[start + pattern.len()..];
585
- let mut depth = 1;
586
- let mut content = String::new();
587
-
588
- for ch in after.chars() {
589
- match ch {
590
- '{' => {
591
- depth += 1;
592
- content.push(ch);
593
- }
594
- '}' => {
595
- depth -= 1;
596
- if depth == 0 {
597
- return Some(self.clean_text(&content));
598
- }
599
- content.push(ch);
600
- }
601
- _ => content.push(ch),
602
- }
603
- }
604
- }
605
- None
606
- }
607
-
608
- fn extract_braced_from_content(&self, text: &str, command: &str) -> Option<String> {
609
- self.extract_braced(text, command)
610
- }
611
-
612
- fn clean_text(&self, text: &str) -> String {
613
- text.to_string()
614
- .replace("\\\\", "\n")
615
- .replace("\\&", "&")
616
- .replace("\\#", "#")
617
- .replace("\\_", "_")
618
- .replace("\\{", "{")
619
- .replace("\\}", "}")
620
- .replace("\\%", "%")
621
- .trim()
622
- .to_string()
623
- }
624
- }
625
-
626
- #[cfg(test)]
627
- mod tests {
628
- use super::*;
629
-
630
- #[test]
631
- fn test_basic_title_extraction() {
632
- let latex = r#"\title{Hello World}"#;
633
- let (_, metadata, _) = LatexExtractor::extract_from_latex(latex);
634
- assert_eq!(
635
- metadata.additional.get("title").and_then(|v| v.as_str()),
636
- Some("Hello World")
637
- );
638
- }
639
-
640
- #[test]
641
- fn test_author_extraction() {
642
- let latex = r#"\author{John Doe}"#;
643
- let (_, metadata, _) = LatexExtractor::extract_from_latex(latex);
644
- assert!(metadata.additional.contains_key("author"));
645
- }
646
-
647
- #[test]
648
- fn test_section_extraction() {
649
- let latex = r#"\begin{document}\section{Introduction}\end{document}"#;
650
- let (content, _, _) = LatexExtractor::extract_from_latex(latex);
651
- assert!(content.contains("Introduction"));
652
- }
653
- }