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,367 @@
1
+ """PDF 链接与签名注解提取,保持原生提取算法与资源语义。"""
2
+
3
+ from __future__ import annotations
4
+ import ctypes
5
+ import logging
6
+ import math
7
+ from typing import Any
8
+ import pypdfium2 as pdfium
9
+ import pypdfium2.raw as pdfium_c
10
+ from ...schema import BBox
11
+ from ...foundation.hyperlink import sanitize_hyperlink_target
12
+
13
+ from .native_contracts import PDFLinkAnnotation, _PDF_EXTERNAL_LINK_SCHEMES
14
+ from .native_coordinates import _drawing_page_size, _normalize_pdf_page_bbox, _transform_drawing_point
15
+
16
+ logger = logging.getLogger("docvortex.document.pdf.document")
17
+
18
+
19
+ def _validate_pdf_external_link_target(value: str) -> str | None:
20
+ """校验 PDF URI Action,只保留显式且可安全输出的外部链接。"""
21
+ return sanitize_hyperlink_target(value, allowed_schemes=_PDF_EXTERNAL_LINK_SCHEMES)
22
+
23
+
24
+ def _get_pdfium_uri_path(raw_doc: Any, raw_action: Any) -> str | None:
25
+ """按 PDFium 两阶段缓冲区协议读取 URI Action 的 UTF-8 目标。"""
26
+
27
+ try:
28
+ required = int(
29
+ pdfium_c.FPDFAction_GetURIPath(
30
+ raw_doc,
31
+ raw_action,
32
+ None,
33
+ 0,
34
+ )
35
+ )
36
+ except Exception:
37
+ return None
38
+ if required <= 1:
39
+ return None
40
+ try:
41
+ buffer = ctypes.create_string_buffer(required)
42
+ actual = int(
43
+ pdfium_c.FPDFAction_GetURIPath(
44
+ raw_doc,
45
+ raw_action,
46
+ buffer,
47
+ required,
48
+ )
49
+ )
50
+ except Exception:
51
+ return None
52
+ if actual <= 1 or actual > required:
53
+ return None
54
+ raw_value = bytes(buffer.raw[: actual - 1])
55
+ try:
56
+ return raw_value.decode("utf-8")
57
+ except UnicodeDecodeError:
58
+ return None
59
+
60
+
61
+ def _pdf_link_annotation_is_visible(page: pdfium.PdfPage, raw_link: Any) -> bool:
62
+ """读取 Link 注解可见性;损坏或显式隐藏的注解均不参与文本富化。"""
63
+
64
+ raw_annot = None
65
+ try:
66
+ raw_annot = pdfium_c.FPDFLink_GetAnnot(page.raw, raw_link)
67
+ if not raw_annot:
68
+ return False
69
+ flags = int(pdfium_c.FPDFAnnot_GetFlags(raw_annot))
70
+ except Exception:
71
+ return False
72
+ finally:
73
+ if raw_annot:
74
+ try:
75
+ pdfium_c.FPDFPage_CloseAnnot(raw_annot)
76
+ except Exception:
77
+ pass
78
+ hidden_flags = pdfium_c.FPDF_ANNOT_FLAG_INVISIBLE | pdfium_c.FPDF_ANNOT_FLAG_HIDDEN | pdfium_c.FPDF_ANNOT_FLAG_NOVIEW
79
+ return not bool(flags & hidden_flags)
80
+
81
+
82
+ def _visual_bbox_from_pdf_points(
83
+ points: list[tuple[float, float]],
84
+ page_bbox: BBox,
85
+ page_rotation: int,
86
+ ) -> BBox | None:
87
+ """把 PDF 底左坐标点集转换并裁剪为视觉页面左上坐标 bbox。"""
88
+
89
+ if not points or not all(math.isfinite(coordinate) for point in points for coordinate in point):
90
+ return None
91
+ visual_points = [_transform_drawing_point(point, page_bbox, page_rotation) for point in points]
92
+ page_width, page_height = _drawing_page_size(page_bbox, page_rotation)
93
+ visual_bbox = (
94
+ max(0.0, min(point[0] for point in visual_points)),
95
+ max(0.0, min(point[1] for point in visual_points)),
96
+ min(page_width, max(point[0] for point in visual_points)),
97
+ min(page_height, max(point[1] for point in visual_points)),
98
+ )
99
+ if visual_bbox[2] <= visual_bbox[0] or visual_bbox[3] <= visual_bbox[1]:
100
+ return None
101
+ return visual_bbox
102
+
103
+
104
+ def _pdf_link_region_bboxes(
105
+ raw_link: Any,
106
+ page_bbox: BBox,
107
+ page_rotation: int,
108
+ ) -> tuple[BBox, ...]:
109
+ """优先读取 Link QuadPoints,并在缺失时回退到注解矩形。"""
110
+
111
+ bboxes: list[BBox] = []
112
+ try:
113
+ quad_count = max(0, int(pdfium_c.FPDFLink_CountQuadPoints(raw_link)))
114
+ except Exception:
115
+ quad_count = 0
116
+ for quad_index in range(quad_count):
117
+ quad = pdfium_c.FS_QUADPOINTSF()
118
+ try:
119
+ ok = pdfium_c.FPDFLink_GetQuadPoints(
120
+ raw_link,
121
+ quad_index,
122
+ ctypes.byref(quad),
123
+ )
124
+ except Exception:
125
+ continue
126
+ if not ok:
127
+ continue
128
+ bbox = _visual_bbox_from_pdf_points(
129
+ [
130
+ (float(quad.x1), float(quad.y1)),
131
+ (float(quad.x2), float(quad.y2)),
132
+ (float(quad.x3), float(quad.y3)),
133
+ (float(quad.x4), float(quad.y4)),
134
+ ],
135
+ page_bbox,
136
+ page_rotation,
137
+ )
138
+ if bbox is not None and bbox not in bboxes:
139
+ bboxes.append(bbox)
140
+
141
+ if not bboxes:
142
+ rect = pdfium_c.FS_RECTF()
143
+ try:
144
+ ok = pdfium_c.FPDFLink_GetAnnotRect(raw_link, ctypes.byref(rect))
145
+ except Exception:
146
+ ok = False
147
+ if ok:
148
+ bbox = _visual_bbox_from_pdf_points(
149
+ [
150
+ (float(rect.left), float(rect.bottom)),
151
+ (float(rect.left), float(rect.top)),
152
+ (float(rect.right), float(rect.bottom)),
153
+ (float(rect.right), float(rect.top)),
154
+ ],
155
+ page_bbox,
156
+ page_rotation,
157
+ )
158
+ if bbox is not None:
159
+ bboxes.append(bbox)
160
+ return tuple(
161
+ sorted(
162
+ bboxes,
163
+ key=lambda bbox: (bbox[1], bbox[0], bbox[3], bbox[2]),
164
+ )
165
+ )
166
+
167
+
168
+ def _extract_page_link_annotations(
169
+ page: pdfium.PdfPage,
170
+ raw_doc: Any,
171
+ page_bbox: BBox,
172
+ page_rotation: int,
173
+ ) -> list[PDFLinkAnnotation]:
174
+ """枚举页面外部 URI Link;单条损坏数据不会中断同页其他链接。"""
175
+
176
+ annotations: list[PDFLinkAnnotation] = []
177
+ position = ctypes.c_int(0)
178
+ source_index = 0
179
+ while True:
180
+ raw_link = pdfium_c.FPDF_LINK()
181
+ previous_position = int(position.value)
182
+ try:
183
+ found = pdfium_c.FPDFLink_Enumerate(
184
+ page.raw,
185
+ ctypes.byref(position),
186
+ ctypes.byref(raw_link),
187
+ )
188
+ except Exception:
189
+ break
190
+ if not found:
191
+ break
192
+ current_source_index = source_index
193
+ source_index += 1
194
+ if int(position.value) <= previous_position:
195
+ break
196
+ try:
197
+ if not raw_link or not _pdf_link_annotation_is_visible(page, raw_link):
198
+ continue
199
+ raw_action = pdfium_c.FPDFLink_GetAction(raw_link)
200
+ if not raw_action or int(pdfium_c.FPDFAction_GetType(raw_action)) != pdfium_c.PDFACTION_URI:
201
+ continue
202
+ raw_target = _get_pdfium_uri_path(raw_doc, raw_action)
203
+ target = _validate_pdf_external_link_target(raw_target) if raw_target is not None else None
204
+ if target is None:
205
+ continue
206
+ bboxes = _pdf_link_region_bboxes(
207
+ raw_link,
208
+ page_bbox,
209
+ page_rotation,
210
+ )
211
+ if not bboxes:
212
+ continue
213
+ annotations.append(
214
+ PDFLinkAnnotation(
215
+ target=target,
216
+ bboxes=bboxes,
217
+ source_index=current_source_index,
218
+ )
219
+ )
220
+ except Exception:
221
+ continue
222
+ return annotations
223
+
224
+
225
+ def _get_annotation_string(raw_annot: Any, key: bytes) -> str | None:
226
+ """读取 PDFium 注释字典中的 UTF-16 字符串或名称,异常和空值统一返回 None。"""
227
+
228
+ try:
229
+ required = int(pdfium_c.FPDFAnnot_GetStringValue(raw_annot, key, None, 0))
230
+ except Exception:
231
+ return None
232
+ if required <= 2:
233
+ return None
234
+ try:
235
+ buffer = (ctypes.c_ushort * ((required + 1) // 2))()
236
+ actual = int(
237
+ pdfium_c.FPDFAnnot_GetStringValue(
238
+ raw_annot,
239
+ key,
240
+ buffer,
241
+ ctypes.sizeof(buffer),
242
+ )
243
+ )
244
+ except Exception:
245
+ return None
246
+ if actual <= 2 or actual > ctypes.sizeof(buffer):
247
+ return None
248
+ try:
249
+ return bytes(buffer)[: actual - 2].decode("utf-16-le")
250
+ except UnicodeDecodeError:
251
+ return None
252
+
253
+
254
+ def _signature_bbox_from_annotation(
255
+ raw_annot: Any,
256
+ page_bbox: BBox,
257
+ page_rotation: int,
258
+ form_handle: Any | None,
259
+ ) -> BBox | None:
260
+ """校验一个可见签名 Widget,并把注释矩形裁剪到视觉页面坐标。"""
261
+
262
+ try:
263
+ if int(pdfium_c.FPDFAnnot_GetSubtype(raw_annot)) != pdfium_c.FPDF_ANNOT_WIDGET:
264
+ return None
265
+ flags = int(pdfium_c.FPDFAnnot_GetFlags(raw_annot))
266
+ except Exception:
267
+ return None
268
+ hidden_flags = pdfium_c.FPDF_ANNOT_FLAG_INVISIBLE | pdfium_c.FPDF_ANNOT_FLAG_HIDDEN | pdfium_c.FPDF_ANNOT_FLAG_NOVIEW
269
+ if flags & hidden_flags:
270
+ return None
271
+ field_type: int | None = None
272
+ if form_handle is not None:
273
+ try:
274
+ field_type = int(pdfium_c.FPDFAnnot_GetFormFieldType(form_handle, raw_annot))
275
+ except Exception:
276
+ field_type = None
277
+ if field_type == pdfium_c.FPDF_FORMFIELD_SIGNATURE:
278
+ pass
279
+ elif field_type is None or field_type <= pdfium_c.FPDF_FORMFIELD_UNKNOWN:
280
+ if _get_annotation_string(raw_annot, b"FT") != "Sig":
281
+ return None
282
+ else:
283
+ return None
284
+
285
+ # 正常外观长度只有 UTF-16 终止符时等价于无 /AP /N,不能形成可见签名。
286
+ try:
287
+ appearance_length = int(
288
+ pdfium_c.FPDFAnnot_GetAP(
289
+ raw_annot,
290
+ pdfium_c.FPDF_ANNOT_APPEARANCEMODE_NORMAL,
291
+ None,
292
+ 0,
293
+ )
294
+ )
295
+ except Exception:
296
+ return None
297
+ if appearance_length <= 2:
298
+ return None
299
+
300
+ rect = pdfium_c.FS_RECTF()
301
+ try:
302
+ if not pdfium_c.FPDFAnnot_GetRect(raw_annot, ctypes.byref(rect)):
303
+ return None
304
+ except Exception:
305
+ return None
306
+ raw_bbox = _normalize_pdf_page_bbox((float(rect.left), float(rect.bottom), float(rect.right), float(rect.top)))
307
+ if not all(math.isfinite(value) for value in raw_bbox):
308
+ return None
309
+ page_points = [
310
+ _transform_drawing_point(point, page_bbox, page_rotation)
311
+ for point in (
312
+ (raw_bbox[0], raw_bbox[1]),
313
+ (raw_bbox[0], raw_bbox[3]),
314
+ (raw_bbox[2], raw_bbox[1]),
315
+ (raw_bbox[2], raw_bbox[3]),
316
+ )
317
+ ]
318
+ page_width, page_height = _drawing_page_size(page_bbox, page_rotation)
319
+ visual_bbox = (
320
+ max(0.0, min(point[0] for point in page_points)),
321
+ max(0.0, min(point[1] for point in page_points)),
322
+ min(page_width, max(point[0] for point in page_points)),
323
+ min(page_height, max(point[1] for point in page_points)),
324
+ )
325
+ if visual_bbox[2] <= visual_bbox[0] or visual_bbox[3] <= visual_bbox[1]:
326
+ return None
327
+ return visual_bbox
328
+
329
+
330
+ def _extract_page_signature_bboxes(
331
+ page: pdfium.PdfPage,
332
+ page_bbox: BBox,
333
+ page_rotation: int,
334
+ *,
335
+ form_handle: Any | None = None,
336
+ ) -> list[BBox]:
337
+ """遍历页面签名注释;逐个关闭句柄,并隔离损坏注释造成的异常。"""
338
+
339
+ try:
340
+ annot_count = max(0, int(pdfium_c.FPDFPage_GetAnnotCount(page.raw)))
341
+ except Exception:
342
+ return []
343
+ signature_bboxes: list[BBox] = []
344
+ for annot_index in range(annot_count):
345
+ raw_annot = None
346
+ try:
347
+ raw_annot = pdfium_c.FPDFPage_GetAnnot(page.raw, annot_index)
348
+ if not raw_annot:
349
+ continue
350
+ signature_bbox = _signature_bbox_from_annotation(
351
+ raw_annot,
352
+ page_bbox,
353
+ page_rotation,
354
+ form_handle,
355
+ )
356
+ if signature_bbox is not None:
357
+ signature_bboxes.append(signature_bbox)
358
+ except Exception:
359
+ # 单个损坏注释不能影响同页其他有效签名框。
360
+ continue
361
+ finally:
362
+ if raw_annot:
363
+ try:
364
+ pdfium_c.FPDFPage_CloseAnnot(raw_annot)
365
+ except Exception:
366
+ pass
367
+ return sorted(signature_bboxes, key=lambda bbox: (bbox[1], bbox[0], bbox[3], bbox[2]))
@@ -0,0 +1,169 @@
1
+ """PDF 原生页面快照、数据类型与固定常量,保持原生提取算法与资源语义。"""
2
+
3
+ from __future__ import annotations
4
+ import logging
5
+ from dataclasses import dataclass, field
6
+ from typing import Literal, TypeAlias
7
+ from .text.contracts import Char
8
+ from PIL import Image
9
+ from ...schema import BBox
10
+ from docvortex.foundation.type_identity import preserve_type_module
11
+
12
+
13
+ logger = logging.getLogger("docvortex.document.pdf.document")
14
+
15
+ POINTS_PER_INCH: int = 72
16
+
17
+
18
+ DEFAULT_RENDER_DPI: int = 200
19
+
20
+
21
+ DEFAULT_RENDER_SCALE: float = DEFAULT_RENDER_DPI / POINTS_PER_INCH
22
+
23
+
24
+ DEFAULT_RENDER_MAX_EDGE: int = 3500
25
+
26
+
27
+ NEAR_IDENTICAL_CHAR_BBOX_TOLERANCE = 1.0
28
+
29
+
30
+ OFFSET_DUPLICATE_CHAR_BBOX_TOLERANCE = 2.5
31
+
32
+
33
+ OFFSET_DUPLICATE_TRANSLATION_TOLERANCE = 0.1
34
+
35
+
36
+ OFFSET_DUPLICATE_MIN_BBOX_OVERLAP_RATIO = 0.45
37
+
38
+
39
+ DRAWING_FORM_MAX_DEPTH = 15
40
+
41
+
42
+ DRAWING_LINE_MERGE_TOLERANCE = 2.0
43
+
44
+
45
+ DRAWING_LINE_AXIS_ABSOLUTE_TOLERANCE = 1.0
46
+
47
+
48
+ DRAWING_LINE_AXIS_RATIO_TOLERANCE = 0.02
49
+
50
+
51
+ DRAWING_LINE_MIN_LENGTH = 1.0
52
+
53
+
54
+ DRAWING_THIN_RECT_MAX_THICKNESS = 2.0
55
+
56
+
57
+ DRAWING_THIN_RECT_MIN_ASPECT_RATIO = 4.0
58
+
59
+
60
+ PDF_IMAGE_FINGERPRINT_MAX_RAW_BYTES = 16 * 1024 * 1024
61
+
62
+
63
+ _PDF_EXTERNAL_LINK_SCHEMES = frozenset({"http", "https", "mailto", "tel"})
64
+
65
+
66
+ PDFMetadataKey: TypeAlias = Literal[
67
+ "Title",
68
+ "Author",
69
+ "Subject",
70
+ "Keywords",
71
+ "Creator",
72
+ "Producer",
73
+ "CreationDate",
74
+ "ModDate",
75
+ ]
76
+
77
+
78
+ class PDFPageImage:
79
+ """保存页面像素及其相对 PDF 点坐标的缩放比例。"""
80
+
81
+ def __init__(self, pil_image: Image.Image, scale: float) -> None:
82
+ """持有调用者提供的独立 Pillow 图片与缩放值。"""
83
+ self.pil_image = pil_image
84
+ self.scale = scale
85
+
86
+
87
+ @dataclass(frozen=True, slots=True)
88
+ class PDFPageTextGeometry:
89
+ """保存原始字符及 loose/tight/origin 三套视觉几何。"""
90
+
91
+ chars: list[Char]
92
+ tight_bboxes: dict[int, BBox]
93
+ origins: dict[int, tuple[float, float]]
94
+ loose_bboxes: dict[int, BBox] = field(default_factory=dict)
95
+
96
+
97
+ @dataclass(frozen=True)
98
+ class PDFDrawingLine:
99
+ """PDF 页面中可见的水平或竖直绘图线,坐标使用页面左上原点的 PDF point。"""
100
+
101
+ start: tuple[float, float]
102
+ end: tuple[float, float]
103
+ bbox: BBox
104
+ width: float
105
+ orientation: Literal["horizontal", "vertical"]
106
+
107
+
108
+ @dataclass(frozen=True)
109
+ class PDFLinkAnnotation:
110
+ """PDF 外部 URI Link 注解,区域坐标使用页面左上原点的 PDF point。"""
111
+
112
+ target: str
113
+ bboxes: tuple[BBox, ...]
114
+ source_index: int
115
+
116
+
117
+ @dataclass(frozen=True)
118
+ class PDFPathInfo:
119
+ """PDF Path 的可见几何和绘制特征,bbox 使用页面左上原点坐标。"""
120
+
121
+ bbox: BBox
122
+ segment_count: int
123
+ fill_visible: bool
124
+ stroke_visible: bool
125
+ form_depth: int
126
+ source_index: int
127
+ fill_rgba: tuple[int, int, int, int] | None = None
128
+
129
+
130
+ @dataclass(frozen=True)
131
+ class PDFImageInfo:
132
+ """PDF 点阵图的页面几何与稳定内容指纹,指纹读取失败时为 None。"""
133
+
134
+ bbox: BBox
135
+ fingerprint: str | None
136
+
137
+
138
+ @dataclass(frozen=True, slots=True)
139
+ class _PDFPageSnapshot:
140
+ """保存单次页面生命周期提取的纯 Python 数据,不持有 PDFium 子对象。"""
141
+
142
+ page_size: tuple[float, float]
143
+ rotation: Literal[0, 90, 180, 270]
144
+ text_geometry: PDFPageTextGeometry
145
+ drawing_lines: list[PDFDrawingLine]
146
+ path_infos: list[PDFPathInfo]
147
+ image_infos: list[PDFImageInfo]
148
+ form_bboxes: list[BBox]
149
+ signature_bboxes: list[BBox]
150
+ link_annotations: list[PDFLinkAnnotation]
151
+
152
+
153
+ @dataclass
154
+ class _PathSubpath:
155
+ """保存一个 PDF Path 子路径的点、直线段和闭合状态。"""
156
+
157
+ points: list[tuple[float, float]]
158
+ straight_segments: list[tuple[tuple[float, float], tuple[float, float]]]
159
+ closed: bool = False
160
+
161
+
162
+ preserve_type_module(PDFPageImage, "docvortex.document.pdf.document")
163
+ preserve_type_module(PDFPageTextGeometry, "docvortex.document.pdf.document")
164
+ preserve_type_module(PDFDrawingLine, "docvortex.document.pdf.document")
165
+ preserve_type_module(PDFLinkAnnotation, "docvortex.document.pdf.document")
166
+ preserve_type_module(PDFPathInfo, "docvortex.document.pdf.document")
167
+ preserve_type_module(PDFImageInfo, "docvortex.document.pdf.document")
168
+ preserve_type_module(_PDFPageSnapshot, "docvortex.document.pdf.document")
169
+ preserve_type_module(_PathSubpath, "docvortex.document.pdf.document")