docvortex 0.2.1__py3-none-any.whl

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 (364) hide show
  1. docvortex/__init__.py +21 -0
  2. docvortex/analyzers/__init__.py +3 -0
  3. docvortex/analyzers/native/__init__.py +37 -0
  4. docvortex/analyzers/native/_shared/__init__.py +3 -0
  5. docvortex/analyzers/native/_shared/hyperlink.py +16 -0
  6. docvortex/analyzers/native/_shared/image.py +8 -0
  7. docvortex/analyzers/native/_shared/markup/__init__.py +47 -0
  8. docvortex/analyzers/native/_shared/markup/anchors.py +30 -0
  9. docvortex/analyzers/native/_shared/markup/formula.py +37 -0
  10. docvortex/analyzers/native/_shared/markup/projector.py +57 -0
  11. docvortex/analyzers/native/_shared/markup/styles.py +19 -0
  12. docvortex/analyzers/native/_shared/mathml.py +17 -0
  13. docvortex/analyzers/native/_shared/names.py +7 -0
  14. docvortex/analyzers/native/_shared/xycut.py +414 -0
  15. docvortex/analyzers/native/contracts.py +44 -0
  16. docvortex/analyzers/native/csv.py +351 -0
  17. docvortex/analyzers/native/epub/__init__.py +18 -0
  18. docvortex/analyzers/native/epub/constants.py +45 -0
  19. docvortex/analyzers/native/epub/converter.py +80 -0
  20. docvortex/analyzers/native/epub/errors.py +20 -0
  21. docvortex/analyzers/native/epub/metadata.py +31 -0
  22. docvortex/analyzers/native/epub/package.py +649 -0
  23. docvortex/analyzers/native/epub/xhtml.py +306 -0
  24. docvortex/analyzers/native/html/__init__.py +6 -0
  25. docvortex/analyzers/native/html/anchors.py +271 -0
  26. docvortex/analyzers/native/html/constants.py +25 -0
  27. docvortex/analyzers/native/html/contracts.py +7 -0
  28. docvortex/analyzers/native/html/converter.py +117 -0
  29. docvortex/analyzers/native/html/document.py +389 -0
  30. docvortex/analyzers/native/html/errors.py +12 -0
  31. docvortex/analyzers/native/html/resources.py +365 -0
  32. docvortex/analyzers/native/html/selector.py +421 -0
  33. docvortex/analyzers/native/models.py +209 -0
  34. docvortex/analyzers/native/ofd/__init__.py +14 -0
  35. docvortex/analyzers/native/ofd/constants.py +59 -0
  36. docvortex/analyzers/native/ofd/converter.py +31 -0
  37. docvortex/analyzers/native/ofd/errors.py +16 -0
  38. docvortex/analyzers/native/ofd/geometry.py +215 -0
  39. docvortex/analyzers/native/ofd/images.py +124 -0
  40. docvortex/analyzers/native/ofd/metadata.py +53 -0
  41. docvortex/analyzers/native/ofd/models.py +170 -0
  42. docvortex/analyzers/native/ofd/package.py +346 -0
  43. docvortex/analyzers/native/ofd/path.py +201 -0
  44. docvortex/analyzers/native/ofd/reading_order.py +293 -0
  45. docvortex/analyzers/native/ofd/resources.py +122 -0
  46. docvortex/analyzers/native/ofd/scene.py +347 -0
  47. docvortex/analyzers/native/ofd/table.py +240 -0
  48. docvortex/analyzers/native/ofd/text.py +521 -0
  49. docvortex/analyzers/native/office/__init__.py +3 -0
  50. docvortex/analyzers/native/office/doc/__init__.py +3 -0
  51. docvortex/analyzers/native/office/doc/bookmarks.py +81 -0
  52. docvortex/analyzers/native/office/doc/doc_converter.py +573 -0
  53. docvortex/analyzers/native/office/doc/fib.py +261 -0
  54. docvortex/analyzers/native/office/doc/fields.py +101 -0
  55. docvortex/analyzers/native/office/doc/formatting.py +171 -0
  56. docvortex/analyzers/native/office/doc/images.py +162 -0
  57. docvortex/analyzers/native/office/doc/lists.py +356 -0
  58. docvortex/analyzers/native/office/doc/models.py +164 -0
  59. docvortex/analyzers/native/office/doc/parser.py +851 -0
  60. docvortex/analyzers/native/office/doc/pieces.py +256 -0
  61. docvortex/analyzers/native/office/doc/records.py +40 -0
  62. docvortex/analyzers/native/office/doc/sprm.py +269 -0
  63. docvortex/analyzers/native/office/doc/styles.py +215 -0
  64. docvortex/analyzers/native/office/docx/__init__.py +3 -0
  65. docvortex/analyzers/native/office/docx/context.py +71 -0
  66. docvortex/analyzers/native/office/docx/docx_converter.py +614 -0
  67. docvortex/analyzers/native/office/docx/equationxml.py +119 -0
  68. docvortex/analyzers/native/office/docx/fields.py +816 -0
  69. docvortex/analyzers/native/office/docx/formatting_types.py +23 -0
  70. docvortex/analyzers/native/office/docx/main.py +50 -0
  71. docvortex/analyzers/native/office/docx/numbering.py +491 -0
  72. docvortex/analyzers/native/office/docx/office_xml.py +57 -0
  73. docvortex/analyzers/native/office/docx/package_normalizer.py +248 -0
  74. docvortex/analyzers/native/office/docx/resources.py +526 -0
  75. docvortex/analyzers/native/office/docx/styles.py +693 -0
  76. docvortex/analyzers/native/office/docx/tables.py +515 -0
  77. docvortex/analyzers/native/office/equation/__init__.py +3 -0
  78. docvortex/analyzers/native/office/equation/image.py +470 -0
  79. docvortex/analyzers/native/office/equation/latex_dict.py +324 -0
  80. docvortex/analyzers/native/office/equation/mtef.py +885 -0
  81. docvortex/analyzers/native/office/equation/mtef_v5.py +941 -0
  82. docvortex/analyzers/native/office/equation/omml.py +561 -0
  83. docvortex/analyzers/native/office/equation/ooxml.py +62 -0
  84. docvortex/analyzers/native/office/errors.py +33 -0
  85. docvortex/analyzers/native/office/image.py +307 -0
  86. docvortex/analyzers/native/office/legacy/__init__.py +3 -0
  87. docvortex/analyzers/native/office/legacy/binary.py +43 -0
  88. docvortex/analyzers/native/office/legacy/officeart.py +362 -0
  89. docvortex/analyzers/native/office/legacy/ole.py +110 -0
  90. docvortex/analyzers/native/office/limits.py +12 -0
  91. docvortex/analyzers/native/office/odf/__init__.py +3 -0
  92. docvortex/analyzers/native/office/odf/chart.py +76 -0
  93. docvortex/analyzers/native/office/odf/constants.py +70 -0
  94. docvortex/analyzers/native/office/odf/converters.py +403 -0
  95. docvortex/analyzers/native/office/odf/errors.py +18 -0
  96. docvortex/analyzers/native/office/odf/metadata.py +91 -0
  97. docvortex/analyzers/native/office/odf/models.py +176 -0
  98. docvortex/analyzers/native/office/odf/package.py +270 -0
  99. docvortex/analyzers/native/office/odf/styles.py +329 -0
  100. docvortex/analyzers/native/office/odf/table.py +469 -0
  101. docvortex/analyzers/native/office/odf/text.py +1002 -0
  102. docvortex/analyzers/native/office/ooxml_chart.py +1016 -0
  103. docvortex/analyzers/native/office/opc.py +38 -0
  104. docvortex/analyzers/native/office/ppt/__init__.py +3 -0
  105. docvortex/analyzers/native/office/ppt/models.py +118 -0
  106. docvortex/analyzers/native/office/ppt/parser.py +1895 -0
  107. docvortex/analyzers/native/office/ppt/ppt_converter.py +292 -0
  108. docvortex/analyzers/native/office/ppt/records.py +131 -0
  109. docvortex/analyzers/native/office/ppt/style_text.py +247 -0
  110. docvortex/analyzers/native/office/pptx/__init__.py +3 -0
  111. docvortex/analyzers/native/office/pptx/context.py +113 -0
  112. docvortex/analyzers/native/office/pptx/lists.py +558 -0
  113. docvortex/analyzers/native/office/pptx/main.py +20 -0
  114. docvortex/analyzers/native/office/pptx/package_normalizer.py +321 -0
  115. docvortex/analyzers/native/office/pptx/pptx_converter.py +323 -0
  116. docvortex/analyzers/native/office/pptx/resources.py +329 -0
  117. docvortex/analyzers/native/office/pptx/shapes.py +393 -0
  118. docvortex/analyzers/native/office/pptx/text_styles.py +625 -0
  119. docvortex/analyzers/native/office/pptx/titles.py +178 -0
  120. docvortex/analyzers/native/office/rich_text.py +420 -0
  121. docvortex/analyzers/native/office/rtf/__init__.py +3 -0
  122. docvortex/analyzers/native/office/rtf/converter.py +708 -0
  123. docvortex/analyzers/native/office/rtf/lexer.py +213 -0
  124. docvortex/analyzers/native/office/rtf/math.py +339 -0
  125. docvortex/analyzers/native/office/rtf/models.py +185 -0
  126. docvortex/analyzers/native/office/rtf/parser.py +1553 -0
  127. docvortex/analyzers/native/office/spreadsheet/__init__.py +3 -0
  128. docvortex/analyzers/native/office/spreadsheet/html.py +81 -0
  129. docvortex/analyzers/native/office/spreadsheet/models.py +79 -0
  130. docvortex/analyzers/native/office/spreadsheet/projector.py +928 -0
  131. docvortex/analyzers/native/office/streams.py +18 -0
  132. docvortex/analyzers/native/office/xls/__init__.py +3 -0
  133. docvortex/analyzers/native/office/xls/chart.py +132 -0
  134. docvortex/analyzers/native/office/xls/embedded_chart.py +299 -0
  135. docvortex/analyzers/native/office/xls/models.py +109 -0
  136. docvortex/analyzers/native/office/xls/number_format.py +521 -0
  137. docvortex/analyzers/native/office/xls/parser.py +1145 -0
  138. docvortex/analyzers/native/office/xls/records.py +201 -0
  139. docvortex/analyzers/native/office/xls/strings.py +205 -0
  140. docvortex/analyzers/native/office/xls/xls_converter.py +354 -0
  141. docvortex/analyzers/native/office/xlsx/__init__.py +3 -0
  142. docvortex/analyzers/native/office/xlsx/main.py +20 -0
  143. docvortex/analyzers/native/office/xlsx/ooxml_ole.py +522 -0
  144. docvortex/analyzers/native/office/xlsx/package_normalizer.py +310 -0
  145. docvortex/analyzers/native/office/xlsx/xlsx_converter.py +716 -0
  146. docvortex/analyzers/native/pdf/__init__.py +3 -0
  147. docvortex/analyzers/native/pdf/auxiliary_text.py +1671 -0
  148. docvortex/analyzers/native/pdf/char_geometry.py +1662 -0
  149. docvortex/analyzers/native/pdf/code_blocks.py +535 -0
  150. docvortex/analyzers/native/pdf/formulas.py +1985 -0
  151. docvortex/analyzers/native/pdf/geometry.py +281 -0
  152. docvortex/analyzers/native/pdf/graphics.py +1501 -0
  153. docvortex/analyzers/native/pdf/index_blocks.py +268 -0
  154. docvortex/analyzers/native/pdf/inline/__init__.py +3 -0
  155. docvortex/analyzers/native/pdf/inline/common.py +112 -0
  156. docvortex/analyzers/native/pdf/inline/detection.py +590 -0
  157. docvortex/analyzers/native/pdf/inline/matching.py +1185 -0
  158. docvortex/analyzers/native/pdf/inline/materialize.py +457 -0
  159. docvortex/analyzers/native/pdf/inline/scripts.py +975 -0
  160. docvortex/analyzers/native/pdf/inline/types.py +385 -0
  161. docvortex/analyzers/native/pdf/line_layout.py +1106 -0
  162. docvortex/analyzers/native/pdf/line_merging.py +1223 -0
  163. docvortex/analyzers/native/pdf/models.py +246 -0
  164. docvortex/analyzers/native/pdf/native_text.py +1004 -0
  165. docvortex/analyzers/native/pdf/pipeline.py +1390 -0
  166. docvortex/analyzers/native/pdf/script_geometry.py +636 -0
  167. docvortex/analyzers/native/pdf/shared.py +30 -0
  168. docvortex/analyzers/native/pdf/spatial_text.py +383 -0
  169. docvortex/analyzers/native/pdf/table_annotations.py +446 -0
  170. docvortex/analyzers/native/pdf/table_constants.py +48 -0
  171. docvortex/analyzers/native/pdf/table_detection.py +227 -0
  172. docvortex/analyzers/native/pdf/table_filled_grid.py +218 -0
  173. docvortex/analyzers/native/pdf/table_geometry.py +40 -0
  174. docvortex/analyzers/native/pdf/table_materialization.py +444 -0
  175. docvortex/analyzers/native/pdf/table_recovery/__init__.py +15 -0
  176. docvortex/analyzers/native/pdf/table_recovery/candidate.py +356 -0
  177. docvortex/analyzers/native/pdf/table_recovery/contracts.py +154 -0
  178. docvortex/analyzers/native/pdf/table_recovery/engine.py +609 -0
  179. docvortex/analyzers/native/pdf/table_recovery/geometry.py +164 -0
  180. docvortex/analyzers/native/pdf/table_recovery/sparse_common.py +85 -0
  181. docvortex/analyzers/native/pdf/table_recovery/sparse_hybrid.py +804 -0
  182. docvortex/analyzers/native/pdf/table_recovery/sparse_multiline.py +1122 -0
  183. docvortex/analyzers/native/pdf/table_recovery/text.py +414 -0
  184. docvortex/analyzers/native/pdf/table_recovery/text_grid.py +618 -0
  185. docvortex/analyzers/native/pdf/table_recovery/vector.py +1931 -0
  186. docvortex/analyzers/native/pdf/table_rows.py +34 -0
  187. docvortex/analyzers/native/pdf/table_rules.py +1129 -0
  188. docvortex/analyzers/native/pdf/table_text_styles.py +283 -0
  189. docvortex/analyzers/native/pdf/tables.py +147 -0
  190. docvortex/analyzers/native/pdf/text_assembly/__init__.py +3 -0
  191. docvortex/analyzers/native/pdf/text_assembly/annotations.py +581 -0
  192. docvortex/analyzers/native/pdf/text_assembly/assembly.py +292 -0
  193. docvortex/analyzers/native/pdf/text_assembly/common.py +477 -0
  194. docvortex/analyzers/native/pdf/text_assembly/footnotes.py +394 -0
  195. docvortex/analyzers/native/pdf/text_assembly/merging.py +1274 -0
  196. docvortex/analyzers/native/pdf/text_assembly/rows.py +692 -0
  197. docvortex/analyzers/native/pdf/text_blocks.py +82 -0
  198. docvortex/analyzers/native/pdf/text_styles.py +55 -0
  199. docvortex/analyzers/native/pdf/title_analysis/__init__.py +3 -0
  200. docvortex/analyzers/native/pdf/title_analysis/body_profile.py +215 -0
  201. docvortex/analyzers/native/pdf/title_analysis/common.py +117 -0
  202. docvortex/analyzers/native/pdf/title_analysis/document_profile.py +164 -0
  203. docvortex/analyzers/native/pdf/title_analysis/lane_titles.py +758 -0
  204. docvortex/analyzers/native/pdf/title_analysis/page_titles.py +1024 -0
  205. docvortex/analyzers/native/pdf/title_analysis/prototype.py +194 -0
  206. docvortex/analyzers/native/pdf/title_analysis/structural.py +1081 -0
  207. docvortex/analyzers/native/pdf/titles.py +75 -0
  208. docvortex/analyzers/native/pdf/typography.py +19 -0
  209. docvortex/analyzers/native/pdf/visual_annotations.py +1262 -0
  210. docvortex/api.py +180 -0
  211. docvortex/assets/__init__.py +5 -0
  212. docvortex/assets/store.py +51 -0
  213. docvortex/cli.py +54 -0
  214. docvortex/codecs/__init__.py +3 -0
  215. docvortex/codecs/html/__init__.py +22 -0
  216. docvortex/codecs/html/contracts.py +236 -0
  217. docvortex/codecs/html/materializer.py +331 -0
  218. docvortex/codecs/html/parser.py +763 -0
  219. docvortex/codecs/html/resources.py +34 -0
  220. docvortex/codecs/json.py +17 -0
  221. docvortex/content/__init__.py +5 -0
  222. docvortex/content/inline.py +248 -0
  223. docvortex/content/markup/__init__.py +44 -0
  224. docvortex/content/markup/anchors.py +188 -0
  225. docvortex/content/markup/formula.py +280 -0
  226. docvortex/content/markup/projector.py +1237 -0
  227. docvortex/content/markup/styles.py +327 -0
  228. docvortex/content/mathml.py +167 -0
  229. docvortex/content/normalization.py +188 -0
  230. docvortex/content/spans.py +183 -0
  231. docvortex/content/table/__init__.py +18 -0
  232. docvortex/content/table/blocks.py +152 -0
  233. docvortex/content/table/content.py +425 -0
  234. docvortex/content/table/document.py +104 -0
  235. docvortex/content/table/html.py +399 -0
  236. docvortex/content/table/models.py +76 -0
  237. docvortex/content/table/rules.py +42 -0
  238. docvortex/content/table/structure.py +221 -0
  239. docvortex/content/tree.py +5 -0
  240. docvortex/document/__init__.py +3 -0
  241. docvortex/document/contracts.py +22 -0
  242. docvortex/document/detection.py +389 -0
  243. docvortex/document/filetypes.py +175 -0
  244. docvortex/document/page_range.py +167 -0
  245. docvortex/document/pdf/__init__.py +19 -0
  246. docvortex/document/pdf/classify.py +1138 -0
  247. docvortex/document/pdf/constants.py +132 -0
  248. docvortex/document/pdf/diagnostics.py +350 -0
  249. docvortex/document/pdf/document.py +582 -0
  250. docvortex/document/pdf/font_runtime.py +335 -0
  251. docvortex/document/pdf/geometry.py +31 -0
  252. docvortex/document/pdf/images.py +654 -0
  253. docvortex/document/pdf/native_annotations.py +367 -0
  254. docvortex/document/pdf/native_contracts.py +169 -0
  255. docvortex/document/pdf/native_coordinates.py +216 -0
  256. docvortex/document/pdf/native_lifecycle.py +16 -0
  257. docvortex/document/pdf/native_objects.py +902 -0
  258. docvortex/document/pdf/native_text_geometry.py +315 -0
  259. docvortex/document/pdf/pdfium.py +325 -0
  260. docvortex/document/pdf/raster.py +46 -0
  261. docvortex/document/pdf/text/__init__.py +62 -0
  262. docvortex/document/pdf/text/contracts.py +211 -0
  263. docvortex/document/pdf/text/extract.py +165 -0
  264. docvortex/document/pdf/text/geometry.py +16 -0
  265. docvortex/document/pdf/text/groups.py +162 -0
  266. docvortex/document/pdf/visual_geometry.py +201 -0
  267. docvortex/document/pdf/visuals.py +343 -0
  268. docvortex/document/source.py +92 -0
  269. docvortex/errors.py +21 -0
  270. docvortex/export/__init__.py +3 -0
  271. docvortex/export/bundle.py +98 -0
  272. docvortex/export/files.py +66 -0
  273. docvortex/export/middle.py +208 -0
  274. docvortex/foundation/__init__.py +3 -0
  275. docvortex/foundation/geometry.py +125 -0
  276. docvortex/foundation/hyperlink.py +65 -0
  277. docvortex/foundation/image.py +48 -0
  278. docvortex/foundation/image_encoding.py +30 -0
  279. docvortex/foundation/image_payload.py +280 -0
  280. docvortex/foundation/language.py +92 -0
  281. docvortex/foundation/platform.py +38 -0
  282. docvortex/foundation/text.py +153 -0
  283. docvortex/foundation/type_identity.py +20 -0
  284. docvortex/foundation/xml_names.py +20 -0
  285. docvortex/options.py +30 -0
  286. docvortex/postprocess/__init__.py +3 -0
  287. docvortex/postprocess/content.py +53 -0
  288. docvortex/postprocess/document.py +19 -0
  289. docvortex/postprocess/lists.py +236 -0
  290. docvortex/postprocess/page_blocks.py +214 -0
  291. docvortex/postprocess/pages.py +95 -0
  292. docvortex/postprocess/paragraphs.py +580 -0
  293. docvortex/postprocess/visual.py +715 -0
  294. docvortex/render/__init__.py +48 -0
  295. docvortex/render/_internal/__init__.py +3 -0
  296. docvortex/render/_internal/common/__init__.py +3 -0
  297. docvortex/render/_internal/common/context.py +43 -0
  298. docvortex/render/_internal/common/html_table.py +178 -0
  299. docvortex/render/_internal/common/index.py +33 -0
  300. docvortex/render/_internal/common/list_items.py +158 -0
  301. docvortex/render/_internal/common/planner.py +140 -0
  302. docvortex/render/_internal/docx/__init__.py +3 -0
  303. docvortex/render/_internal/docx/assets.py +202 -0
  304. docvortex/render/_internal/docx/inline.py +434 -0
  305. docvortex/render/_internal/docx/math.py +220 -0
  306. docvortex/render/_internal/docx/renderer.py +905 -0
  307. docvortex/render/_internal/docx/styles.py +195 -0
  308. docvortex/render/_internal/docx/table.py +442 -0
  309. docvortex/render/_internal/epub/__init__.py +5 -0
  310. docvortex/render/_internal/epub/assets.py +173 -0
  311. docvortex/render/_internal/epub/package.py +249 -0
  312. docvortex/render/_internal/epub/renderer.py +1156 -0
  313. docvortex/render/_internal/html/__init__.py +3 -0
  314. docvortex/render/_internal/html/inline.py +346 -0
  315. docvortex/render/_internal/html/renderer.py +1041 -0
  316. docvortex/render/_internal/html/sanitizer.py +478 -0
  317. docvortex/render/_internal/html/table.py +121 -0
  318. docvortex/render/_internal/latex/__init__.py +1 -0
  319. docvortex/render/_internal/latex/assets.py +85 -0
  320. docvortex/render/_internal/latex/inline.py +145 -0
  321. docvortex/render/_internal/latex/renderer.py +506 -0
  322. docvortex/render/_internal/latex/table.py +347 -0
  323. docvortex/render/_internal/markdown/__init__.py +3 -0
  324. docvortex/render/_internal/markdown/assets.py +78 -0
  325. docvortex/render/_internal/markdown/blocks.py +635 -0
  326. docvortex/render/_internal/markdown/escaping.py +51 -0
  327. docvortex/render/_internal/markdown/inline.py +260 -0
  328. docvortex/render/_internal/markdown/renderer.py +93 -0
  329. docvortex/render/_internal/markdown/table.py +281 -0
  330. docvortex/render/_internal/pdf/__init__.py +3 -0
  331. docvortex/render/_internal/pdf/assets.py +197 -0
  332. docvortex/render/_internal/pdf/formula.py +417 -0
  333. docvortex/render/_internal/pdf/inline.py +343 -0
  334. docvortex/render/_internal/pdf/renderer.py +734 -0
  335. docvortex/render/_internal/pdf/styles.py +206 -0
  336. docvortex/render/_internal/pdf/table.py +272 -0
  337. docvortex/render/_internal/structured_content/__init__.py +3 -0
  338. docvortex/render/_internal/structured_content/renderer.py +193 -0
  339. docvortex/render/api.py +199 -0
  340. docvortex/render/contracts.py +205 -0
  341. docvortex/render/docx.py +38 -0
  342. docvortex/render/epub.py +35 -0
  343. docvortex/render/fragments.py +70 -0
  344. docvortex/render/html.py +29 -0
  345. docvortex/render/latex.py +24 -0
  346. docvortex/render/markdown.py +50 -0
  347. docvortex/render/pdf.py +25 -0
  348. docvortex/render/structured_content.py +23 -0
  349. docvortex/resources/epub/docvortex.css +91 -0
  350. docvortex/resources/fasttext-langdetect/lid.176.ftz +0 -0
  351. docvortex/resources/fonts/DroidSansFallbackFull.ttf +0 -0
  352. docvortex/resources/fonts/NOTICE +190 -0
  353. docvortex/resources/fonts/manifest.json +9 -0
  354. docvortex/resources/html/docvortex.css +601 -0
  355. docvortex/resources/html/docvortex.min.css +1 -0
  356. docvortex/result.py +91 -0
  357. docvortex/schema.py +1141 -0
  358. docvortex/version.py +3 -0
  359. docvortex-0.2.1.dist-info/METADATA +193 -0
  360. docvortex-0.2.1.dist-info/RECORD +364 -0
  361. docvortex-0.2.1.dist-info/WHEEL +5 -0
  362. docvortex-0.2.1.dist-info/entry_points.txt +2 -0
  363. docvortex-0.2.1.dist-info/licenses/LICENSE.md +21 -0
  364. docvortex-0.2.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,227 @@
1
+ """PDF 表格检测编排与续表标题;保留原有认领顺序与判定规则。"""
2
+
3
+ from __future__ import annotations
4
+ from ....schema import BBox
5
+ from .models import _PageSource, _TableAnnotation, _TableCandidate
6
+ from .geometry import (
7
+ _bbox_area,
8
+ _bbox_axis_overlap_ratio,
9
+ _bbox_overlap_in_smaller,
10
+ _bbox_union,
11
+ _expand_bbox,
12
+ _rotate_bbox_from_upright,
13
+ _rotate_bbox_to_upright,
14
+ _transform_axis_lines,
15
+ )
16
+
17
+ from .table_constants import _TABLE_CONTINUATION_RE
18
+ from .table_filled_grid import _detect_filled_grid_table_candidates
19
+ from .table_rules import (
20
+ _build_closed_rule_grid_candidates,
21
+ _build_fragments,
22
+ _build_rule_table_candidates,
23
+ _cluster_fragment_rows,
24
+ _connected_rule_grid_bboxes,
25
+ _median_fragment_height,
26
+ _merge_table_candidates,
27
+ )
28
+
29
+
30
+ def _detect_table_candidates(
31
+ source: _PageSource,
32
+ excluded_bboxes: list[BBox] | None = None,
33
+ ) -> list[_TableCandidate]:
34
+ """按文本方向融合横线区间、规则文本和填充行带,生成表格候选。"""
35
+
36
+ excluded_bboxes = excluded_bboxes or []
37
+ filled_grid_candidates = _detect_filled_grid_table_candidates(
38
+ source.path_infos,
39
+ source.page_size,
40
+ excluded_bboxes,
41
+ )
42
+ filled_grid_bboxes = [candidate.bbox for candidate in filled_grid_candidates]
43
+ rule_candidates: list[_TableCandidate] = []
44
+ angles = sorted({line.angle for line in source.lines})
45
+ for angle in angles:
46
+ angle_lines = [line for line in source.lines if line.angle == angle]
47
+ if not angle_lines:
48
+ continue
49
+ fragments = _build_fragments(angle_lines, source.page_size)
50
+ if not fragments:
51
+ continue
52
+ median_height = _median_fragment_height(fragments)
53
+ rows = _cluster_fragment_rows(fragments, median_height)
54
+ local_axis_lines = _transform_axis_lines(
55
+ source.drawing_lines,
56
+ source.page_size,
57
+ angle,
58
+ )
59
+ local_excluded_bboxes = [
60
+ _expand_bbox(
61
+ _rotate_bbox_to_upright(bbox, source.page_size, angle),
62
+ 2.5 * median_height,
63
+ )
64
+ for bbox in [*excluded_bboxes, *filled_grid_bboxes]
65
+ ]
66
+ local_closed_grid_excluded_bboxes = [
67
+ *local_excluded_bboxes,
68
+ *[_rotate_bbox_to_upright(bbox, source.page_size, angle) for bbox in source.form_bboxes],
69
+ ]
70
+ rule_candidates.extend(
71
+ _build_rule_table_candidates(
72
+ rows,
73
+ angle_lines,
74
+ source.page_size,
75
+ angle,
76
+ median_height,
77
+ local_axis_lines,
78
+ path_infos=source.path_infos,
79
+ excluded_bboxes=local_excluded_bboxes,
80
+ )
81
+ )
82
+ rule_candidates.extend(
83
+ _build_closed_rule_grid_candidates(
84
+ rows,
85
+ angle_lines,
86
+ source.page_size,
87
+ angle,
88
+ median_height,
89
+ local_axis_lines,
90
+ local_closed_grid_excluded_bboxes,
91
+ )
92
+ )
93
+ merged_rule_candidates = [
94
+ candidate
95
+ for candidate in _merge_table_candidates(rule_candidates)
96
+ if not any(_bbox_overlap_in_smaller(candidate.bbox, filled_bbox) >= 0.2 for filled_bbox in filled_grid_bboxes)
97
+ ]
98
+ candidates = [*filled_grid_candidates, *merged_rule_candidates]
99
+ _externalize_table_continuation_captions(
100
+ source,
101
+ candidates,
102
+ )
103
+ return sorted(
104
+ candidates,
105
+ key=lambda candidate: (candidate.bbox[1], candidate.bbox[0]),
106
+ )
107
+
108
+
109
+ def _externalize_table_continuation_captions(
110
+ source: _PageSource,
111
+ candidates: list[_TableCandidate],
112
+ ) -> None:
113
+ """以连通物理网格收紧表体,并把其上方续表标记外置为 caption。"""
114
+
115
+ for candidate in candidates:
116
+ angle_lines = [line for line in source.lines if line.angle == candidate.angle]
117
+ if not angle_lines:
118
+ continue
119
+ fragments = _build_fragments(
120
+ angle_lines,
121
+ source.page_size,
122
+ )
123
+ if not fragments:
124
+ continue
125
+ median_height = _median_fragment_height(fragments)
126
+ local_axis_lines = _transform_axis_lines(
127
+ source.drawing_lines,
128
+ source.page_size,
129
+ candidate.angle,
130
+ )
131
+ grid_matches = [
132
+ grid_bbox
133
+ for grid_bbox in _connected_rule_grid_bboxes(
134
+ local_axis_lines,
135
+ median_height,
136
+ )
137
+ if _bbox_axis_overlap_ratio(
138
+ grid_bbox,
139
+ candidate.local_bbox,
140
+ axis="x",
141
+ )
142
+ >= 0.9
143
+ and _bbox_overlap_in_smaller(
144
+ grid_bbox,
145
+ candidate.local_bbox,
146
+ )
147
+ >= 0.9
148
+ ]
149
+ if not grid_matches:
150
+ continue
151
+ grid_bbox = max(
152
+ grid_matches,
153
+ key=lambda bbox: _bbox_area(bbox),
154
+ )
155
+ continuation_lines = []
156
+ for line in angle_lines:
157
+ if (
158
+ _TABLE_CONTINUATION_RE.fullmatch(
159
+ line.text.strip(),
160
+ )
161
+ is None
162
+ ):
163
+ continue
164
+ local_bbox = _rotate_bbox_to_upright(
165
+ line.bbox,
166
+ source.page_size,
167
+ candidate.angle,
168
+ )
169
+ gap = grid_bbox[1] - local_bbox[3]
170
+ if (
171
+ local_bbox[3] <= grid_bbox[1] + 0.25 * median_height
172
+ and -0.25 * median_height <= gap <= 3.0 * median_height
173
+ and _bbox_axis_overlap_ratio(
174
+ local_bbox,
175
+ grid_bbox,
176
+ axis="x",
177
+ )
178
+ >= 0.8
179
+ ):
180
+ continuation_lines.append(
181
+ (line, local_bbox),
182
+ )
183
+ if len(continuation_lines) != 1:
184
+ continue
185
+ continuation_line, continuation_local_bbox = continuation_lines[0]
186
+ continuation_bbox = continuation_line.bbox
187
+ existing_caption = next(
188
+ (annotation for annotation in candidate.annotations if annotation.kind == "caption"),
189
+ None,
190
+ )
191
+ if existing_caption is None:
192
+ candidate.annotations.append(
193
+ _TableAnnotation(
194
+ kind="caption",
195
+ bbox=continuation_bbox,
196
+ line_indices={continuation_line.source_index},
197
+ line_bboxes={
198
+ continuation_line.source_index: continuation_bbox,
199
+ },
200
+ )
201
+ )
202
+ else:
203
+ existing_caption.bbox = _bbox_union(
204
+ existing_caption.bbox,
205
+ continuation_bbox,
206
+ )
207
+ existing_caption.line_indices.add(
208
+ continuation_line.source_index,
209
+ )
210
+ existing_caption.line_bboxes[continuation_line.source_index] = continuation_bbox
211
+ candidate.line_indices.discard(
212
+ continuation_line.source_index,
213
+ )
214
+ core_bbox = _rotate_bbox_from_upright(
215
+ grid_bbox,
216
+ source.page_size,
217
+ candidate.angle,
218
+ )
219
+ candidate.core_bbox = core_bbox
220
+ candidate.local_bbox = _bbox_union(
221
+ grid_bbox,
222
+ continuation_local_bbox,
223
+ )
224
+ candidate.bbox = _bbox_union(
225
+ core_bbox,
226
+ continuation_bbox,
227
+ )
@@ -0,0 +1,218 @@
1
+ """PDF 填充单元格候选;保留原有认领顺序与判定规则。"""
2
+
3
+ from __future__ import annotations
4
+ from ....schema import BBox
5
+ from ....document.pdf.document import PDFPathInfo
6
+ from .models import _TableCandidate
7
+ from .geometry import (
8
+ _bbox_area,
9
+ _bbox_overlap_in_smaller,
10
+ )
11
+
12
+ from .table_constants import (
13
+ _FILLED_GRID_MAX_PAGE_AREA_RATIO,
14
+ _FILLED_GRID_MIN_PAGE_AREA_RATIO,
15
+ _FILLED_GRID_MIN_PAGE_HEIGHT_RATIO,
16
+ _FILLED_GRID_MIN_PAGE_WIDTH_RATIO,
17
+ )
18
+
19
+
20
+ def _detect_filled_grid_table_candidates(
21
+ path_infos: list[PDFPathInfo],
22
+ page_size: tuple[float, float],
23
+ excluded_bboxes: list[BBox] | None = None,
24
+ ) -> list[_TableCandidate]:
25
+ """仅按根层填充矩形的嵌套行带识别精确表格外框。"""
26
+
27
+ page_width, page_height = page_size
28
+ page_area = page_width * page_height
29
+ if page_area <= 0:
30
+ return []
31
+ excluded_bboxes = excluded_bboxes or []
32
+ rectangles = [
33
+ path_info.bbox
34
+ for path_info in path_infos
35
+ if path_info.form_depth == 0
36
+ and path_info.fill_visible
37
+ and path_info.segment_count == 5
38
+ and _bbox_area(path_info.bbox) > 0
39
+ ]
40
+ evidence: list[tuple[_TableCandidate, int, float, float]] = []
41
+ for outer_bbox in rectangles:
42
+ outer_width = outer_bbox[2] - outer_bbox[0]
43
+ outer_height = outer_bbox[3] - outer_bbox[1]
44
+ outer_area = _bbox_area(outer_bbox)
45
+ if not (
46
+ _FILLED_GRID_MIN_PAGE_AREA_RATIO <= outer_area / page_area <= _FILLED_GRID_MAX_PAGE_AREA_RATIO
47
+ and outer_width >= _FILLED_GRID_MIN_PAGE_WIDTH_RATIO * page_width
48
+ and outer_height >= _FILLED_GRID_MIN_PAGE_HEIGHT_RATIO * page_height
49
+ ):
50
+ continue
51
+ if any(_bbox_overlap_in_smaller(outer_bbox, excluded_bbox) >= 0.5 for excluded_bbox in excluded_bboxes):
52
+ continue
53
+
54
+ cells = _select_maximal_filled_grid_cells(rectangles, outer_bbox)
55
+ bands = _group_filled_grid_cells_into_bands(cells, outer_bbox)
56
+ accepted_bands = [band for band in bands if _filled_grid_band_covers_outer_width(band, outer_bbox)]
57
+ if len(accepted_bands) < 4:
58
+ continue
59
+ accepted_bands.sort(
60
+ key=lambda band: (
61
+ min(cell[1] for cell in band),
62
+ min(cell[0] for cell in band),
63
+ )
64
+ )
65
+ covered_height = sum(max(cell[3] for cell in band) - min(cell[1] for cell in band) for band in accepted_bands)
66
+ vertical_coverage = covered_height / outer_height
67
+ if vertical_coverage < 0.75:
68
+ continue
69
+ if any(
70
+ min(cell[1] for cell in next_band) - max(cell[3] for cell in current_band) > 0.05 * outer_height
71
+ for current_band, next_band in zip(
72
+ accepted_bands,
73
+ accepted_bands[1:],
74
+ )
75
+ ):
76
+ continue
77
+ candidate = _TableCandidate(
78
+ bbox=outer_bbox,
79
+ local_bbox=outer_bbox,
80
+ angle=0,
81
+ score=float(100.0 + len(accepted_bands) + vertical_coverage),
82
+ core_bbox=outer_bbox,
83
+ line_indices=set(),
84
+ )
85
+ evidence.append(
86
+ (
87
+ candidate,
88
+ len(accepted_bands),
89
+ vertical_coverage,
90
+ outer_area,
91
+ )
92
+ )
93
+
94
+ output: list[_TableCandidate] = []
95
+ for candidate, _band_count, _coverage, _outer_area in sorted(
96
+ evidence,
97
+ key=lambda item: (item[1], item[2], item[3]),
98
+ reverse=True,
99
+ ):
100
+ if any(_bbox_overlap_in_smaller(candidate.bbox, accepted.bbox) >= 0.9 for accepted in output):
101
+ continue
102
+ output.append(candidate)
103
+ return sorted(output, key=lambda candidate: (candidate.bbox[1], candidate.bbox[0]))
104
+
105
+
106
+ def _select_maximal_filled_grid_cells(
107
+ rectangles: list[BBox],
108
+ outer_bbox: BBox,
109
+ ) -> list[BBox]:
110
+ """移除边缘细条、重复 Path 和同跨度半行底纹,保留最大单元格。"""
111
+
112
+ outer_width = outer_bbox[2] - outer_bbox[0]
113
+ outer_height = outer_bbox[3] - outer_bbox[1]
114
+ outer_area = _bbox_area(outer_bbox)
115
+ x_tolerance = 0.01 * outer_width
116
+ y_tolerance = 0.02 * outer_height
117
+ nested_rectangles = [
118
+ rectangle
119
+ for rectangle in rectangles
120
+ if rectangle != outer_bbox
121
+ and _bbox_is_contained_with_tolerance(
122
+ rectangle,
123
+ outer_bbox,
124
+ x_tolerance,
125
+ y_tolerance,
126
+ )
127
+ and _bbox_area(rectangle) <= 0.8 * outer_area
128
+ and rectangle[2] - rectangle[0] >= 0.1 * outer_width
129
+ and rectangle[3] - rectangle[1] >= 0.06 * outer_height
130
+ ]
131
+ output: list[BBox] = []
132
+ for rectangle in sorted(
133
+ nested_rectangles,
134
+ key=lambda bbox: (-_bbox_area(bbox), bbox[1], bbox[0]),
135
+ ):
136
+ if any(
137
+ rectangle != other
138
+ and _bbox_is_contained_with_tolerance(
139
+ rectangle,
140
+ other,
141
+ x_tolerance,
142
+ y_tolerance,
143
+ )
144
+ and _bbox_area(other) >= 1.08 * _bbox_area(rectangle)
145
+ and _bbox_area(other) <= 0.8 * outer_area
146
+ and abs((rectangle[2] - rectangle[0]) - (other[2] - other[0])) <= 0.01 * outer_width
147
+ for other in nested_rectangles
148
+ ):
149
+ continue
150
+ if any(_bbox_overlap_in_smaller(rectangle, accepted) >= 0.95 for accepted in output):
151
+ continue
152
+ output.append(rectangle)
153
+ return sorted(output, key=lambda bbox: (bbox[1], bbox[0], bbox[3], bbox[2]))
154
+
155
+
156
+ def _bbox_is_contained_with_tolerance(
157
+ inner_bbox: BBox,
158
+ outer_bbox: BBox,
159
+ x_tolerance: float,
160
+ y_tolerance: float,
161
+ ) -> bool:
162
+ """按横纵独立容差判断一个矩形是否完整位于另一个矩形内。"""
163
+
164
+ return (
165
+ inner_bbox[0] >= outer_bbox[0] - x_tolerance
166
+ and inner_bbox[1] >= outer_bbox[1] - y_tolerance
167
+ and inner_bbox[2] <= outer_bbox[2] + x_tolerance
168
+ and inner_bbox[3] <= outer_bbox[3] + y_tolerance
169
+ )
170
+
171
+
172
+ def _group_filled_grid_cells_into_bands(
173
+ cells: list[BBox],
174
+ outer_bbox: BBox,
175
+ ) -> list[list[BBox]]:
176
+ """按相近上下边界把最大填充单元格聚成水平行带。"""
177
+
178
+ y_tolerance = 0.02 * (outer_bbox[3] - outer_bbox[1])
179
+ bands: list[list[BBox]] = []
180
+ for cell in sorted(cells, key=lambda bbox: (bbox[1], bbox[0], bbox[3])):
181
+ target = next(
182
+ (band for band in bands if abs(cell[1] - band[0][1]) <= y_tolerance and abs(cell[3] - band[0][3]) <= y_tolerance),
183
+ None,
184
+ )
185
+ if target is None:
186
+ bands.append([cell])
187
+ else:
188
+ target.append(cell)
189
+ return bands
190
+
191
+
192
+ def _filled_grid_band_covers_outer_width(
193
+ band: list[BBox],
194
+ outer_bbox: BBox,
195
+ ) -> bool:
196
+ """校验单个填充行带的单元格数量、横向覆盖、间隙和端点。"""
197
+
198
+ if len(band) < 2:
199
+ return False
200
+ outer_width = outer_bbox[2] - outer_bbox[0]
201
+ segments = sorted((cell[0], cell[2]) for cell in band)
202
+ current_left, current_right = segments[0]
203
+ covered_width = 0.0
204
+ maximum_gap = 0.0
205
+ for left, right in segments[1:]:
206
+ if left <= current_right:
207
+ current_right = max(current_right, right)
208
+ continue
209
+ covered_width += current_right - current_left
210
+ maximum_gap = max(maximum_gap, left - current_right)
211
+ current_left, current_right = left, right
212
+ covered_width += current_right - current_left
213
+ return (
214
+ covered_width >= 0.9 * outer_width
215
+ and maximum_gap <= 0.01 * outer_width
216
+ and abs(min(cell[0] for cell in band) - outer_bbox[0]) <= 0.02 * outer_width
217
+ and abs(max(cell[2] for cell in band) - outer_bbox[2]) <= 0.02 * outer_width
218
+ )
@@ -0,0 +1,40 @@
1
+ """提供表格恢复与文本投影共享的局部几何,不改变各业务层校验策略。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from ....schema import BBox
6
+
7
+
8
+ def normalize_bbox(value: object) -> BBox | None:
9
+ """把任意四元组规范为有效浮点 bbox,异常或退化框返回空。"""
10
+
11
+ try:
12
+ x0, y0, x1, y1 = [float(item) for item in value] # type: ignore[arg-type]
13
+ except (TypeError, ValueError):
14
+ return None
15
+ left, right = sorted((x0, x1))
16
+ top, bottom = sorted((y0, y1))
17
+ if right <= left or bottom <= top:
18
+ return None
19
+ return left, top, right, bottom
20
+
21
+
22
+ def rotate_local_bbox(
23
+ bbox: BBox,
24
+ width: float,
25
+ height: float,
26
+ angle: int,
27
+ ) -> BBox:
28
+ """把表格裁剪框内 bbox 转换到正向表格局部坐标。"""
29
+
30
+ x0, y0, x1, y1 = bbox
31
+ if angle == 270:
32
+ return height - y1, x0, height - y0, x1
33
+ if angle == 90:
34
+ return y0, width - x1, y1, width - x0
35
+ if angle == 180:
36
+ return width - x1, height - y1, width - x0, height - y0
37
+ return bbox
38
+
39
+
40
+ __all__ = ["normalize_bbox", "rotate_local_bbox"]