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,457 @@
1
+ """把已对齐的链接、样式及上下标区间物化为 InlineSpan。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from typing import Any, Sequence
7
+
8
+ from .....schema import BBox
9
+ from .....content.spans import (
10
+ append_equation_span,
11
+ append_hyperlink_span,
12
+ append_text_span,
13
+ extend_inline_spans,
14
+ normalize_span_dicts,
15
+ )
16
+ from .common import _canonical_styles
17
+ from .matching import (
18
+ _assign_lines_to_blocks,
19
+ _assign_script_lines_to_blocks,
20
+ _block_bbox_to_page_bbox,
21
+ _filter_line_styles_for_block,
22
+ _match_link_ranges,
23
+ _match_script_line_ranges,
24
+ _match_style_ranges,
25
+ _merge_raw_link_intervals,
26
+ _merge_style_ranges,
27
+ _project_content_chars,
28
+ _raw_link_intervals,
29
+ )
30
+ from .types import (
31
+ _NATIVE_SCRIPT_TAG_RE,
32
+ _PDF_INLINE_SPAN_BLOCK_TYPES,
33
+ _PDF_LINK_INTERVALS_KEY,
34
+ _PDF_STYLE_INTERVALS_KEY,
35
+ PDF_NATIVE_SCRIPT_MARKUP_KEY,
36
+ PDFTextLinkLine,
37
+ PDFTextScriptLine,
38
+ PDFTextScriptRange,
39
+ PDFTextStyle,
40
+ PDFTextStyleLine,
41
+ PDFTextStyleRange,
42
+ _NativeScriptMarkup,
43
+ _ProjectedChar,
44
+ _RawStyleInterval,
45
+ )
46
+
47
+
48
+ def apply_pdf_text_links(
49
+ blocks: list[dict[str, Any]],
50
+ lines: Sequence[PDFTextLinkLine],
51
+ page_size: tuple[float, float],
52
+ ) -> None:
53
+ """把页面 Link 几何证据写入自然语言 block,歧义时保持原文。"""
54
+
55
+ assignments = _assign_lines_to_blocks(blocks, lines, page_size)
56
+ for block_index, block_lines in assignments.items():
57
+ content = blocks[block_index].get("content")
58
+ if not isinstance(content, str) or not content:
59
+ continue
60
+ projected = _project_content_chars(content)
61
+ link_ranges = _match_link_ranges(projected, block_lines)
62
+ if not link_ranges:
63
+ continue
64
+ intervals = _raw_link_intervals(content, projected, link_ranges)
65
+ if intervals:
66
+ intervals = _merge_raw_link_intervals(content, intervals)
67
+ blocks[block_index][_PDF_LINK_INTERVALS_KEY] = intervals
68
+
69
+
70
+ def _append_raw_style_interval(
71
+ intervals: list[_RawStyleInterval],
72
+ start: int | None,
73
+ end: int,
74
+ styles: tuple[PDFTextStyle, ...],
75
+ ) -> None:
76
+ """向结果追加一个合法原字符串样式区间。"""
77
+
78
+ if start is not None and start < end and styles:
79
+ intervals.append(_RawStyleInterval(start, end, styles))
80
+
81
+
82
+ def _merge_raw_style_intervals(
83
+ content: str,
84
+ intervals: Sequence[_RawStyleInterval],
85
+ ) -> list[_RawStyleInterval]:
86
+ """合并原字符串中相邻且样式一致、仅由普通空白隔开的区间。"""
87
+
88
+ merged: list[_RawStyleInterval] = []
89
+ for interval in sorted(intervals, key=lambda item: (item.start, item.end, item.styles)):
90
+ if interval.start >= interval.end or not interval.styles:
91
+ continue
92
+ if (
93
+ merged
94
+ and merged[-1].styles == interval.styles
95
+ and (interval.start <= merged[-1].end or content[merged[-1].end : interval.start].isspace())
96
+ ):
97
+ merged[-1] = _RawStyleInterval(
98
+ merged[-1].start,
99
+ max(merged[-1].end, interval.end),
100
+ merged[-1].styles,
101
+ )
102
+ else:
103
+ merged.append(interval)
104
+ return merged
105
+
106
+
107
+ def _raw_style_intervals(
108
+ content: str,
109
+ projected: Sequence[_ProjectedChar],
110
+ ranges: Sequence[PDFTextStyleRange],
111
+ ) -> list[_RawStyleInterval]:
112
+ """把样式区间转换为不跨公式或已有行内标签的原字符串区间。"""
113
+
114
+ intervals: list[_RawStyleInterval] = []
115
+ for style_range in ranges:
116
+ current_start: int | None = None
117
+ current_end = 0
118
+ current_styles: tuple[PDFTextStyle, ...] = ()
119
+ for token in projected[style_range.start : style_range.end]:
120
+ # Link 注解已提供语义,链接范围内的几何下划线不重复输出为文本样式。
121
+ missing_styles = _canonical_styles(
122
+ style
123
+ for style in style_range.styles
124
+ if style not in token.existing_styles and not (style == "underline" and token.inside_hyperlink)
125
+ )
126
+ if not missing_styles:
127
+ _append_raw_style_interval(
128
+ intervals,
129
+ current_start,
130
+ current_end,
131
+ current_styles,
132
+ )
133
+ current_start = None
134
+ current_styles = ()
135
+ continue
136
+ if current_start is None:
137
+ current_start = token.raw_start
138
+ current_end = token.raw_end
139
+ current_styles = missing_styles
140
+ continue
141
+ gap = content[current_end : token.raw_start]
142
+ if missing_styles == current_styles and (token.raw_start <= current_end or not gap or gap.isspace()):
143
+ current_end = max(current_end, token.raw_end)
144
+ else:
145
+ _append_raw_style_interval(
146
+ intervals,
147
+ current_start,
148
+ current_end,
149
+ current_styles,
150
+ )
151
+ current_start = token.raw_start
152
+ current_end = token.raw_end
153
+ current_styles = missing_styles
154
+ _append_raw_style_interval(
155
+ intervals,
156
+ current_start,
157
+ current_end,
158
+ current_styles,
159
+ )
160
+ return _merge_raw_style_intervals(content, intervals)
161
+
162
+
163
+ def apply_pdf_text_styles(
164
+ blocks: list[dict[str, Any]],
165
+ lines: Sequence[PDFTextStyleLine],
166
+ page_size: tuple[float, float],
167
+ ) -> None:
168
+ """把页面字体和装饰线证据写入自然语言 block,歧义时保持原文。"""
169
+
170
+ assignments = _assign_lines_to_blocks(blocks, lines, page_size)
171
+ for block_index, block_lines in assignments.items():
172
+ block = blocks[block_index]
173
+ block_lines = _filter_line_styles_for_block(
174
+ block_lines,
175
+ block.get("type"),
176
+ )
177
+ content = block.get("content")
178
+ if not isinstance(content, str) or not content or not any(line.style_ranges for line in block_lines):
179
+ continue
180
+ projected = _project_content_chars(content)
181
+ style_ranges = _match_style_ranges(projected, block_lines)
182
+ if not style_ranges:
183
+ continue
184
+ intervals = _raw_style_intervals(content, projected, style_ranges)
185
+ if intervals:
186
+ existing = block.get(_PDF_STYLE_INTERVALS_KEY, [])
187
+ block[_PDF_STYLE_INTERVALS_KEY] = _merge_raw_style_intervals(
188
+ content,
189
+ [
190
+ *(interval for interval in existing if isinstance(interval, _RawStyleInterval)),
191
+ *intervals,
192
+ ],
193
+ )
194
+
195
+
196
+ def _script_range_hits_late_formula_region(
197
+ script_range: PDFTextScriptRange,
198
+ regions: list[BBox],
199
+ ) -> bool:
200
+ """判断非公式候选是否落入后续文本块恢复出的行内数学区域。"""
201
+ if script_range.formula_region:
202
+ return False
203
+ center_x = (script_range.bbox[0] + script_range.bbox[2]) / 2
204
+ center_y = (script_range.bbox[1] + script_range.bbox[3]) / 2
205
+ return any(region[0] <= center_x <= region[2] and region[1] <= center_y <= region[3] for region in regions)
206
+
207
+
208
+ def _record_materialized_script_ranges(
209
+ content: str,
210
+ projected: Sequence[_ProjectedChar],
211
+ combined_ranges: Sequence[PDFTextStyleRange],
212
+ block_index: int,
213
+ line: PDFTextScriptLine,
214
+ script_ranges: Sequence[PDFTextScriptRange],
215
+ output: list[dict[str, Any]],
216
+ ) -> None:
217
+ """记录真正通过文本投影的私有上下标区间,供审阅产物精确回溯。"""
218
+ for script_range in script_ranges:
219
+ evidence_line = PDFTextStyleLine(
220
+ bbox=line.bbox,
221
+ text=line.text,
222
+ style_ranges=(
223
+ PDFTextStyleRange(
224
+ script_range.start,
225
+ script_range.end,
226
+ (script_range.style,),
227
+ ),
228
+ ),
229
+ source_index=line.source_index,
230
+ )
231
+ matched = _match_script_line_ranges(projected, evidence_line)
232
+ if len(matched) != 1:
233
+ continue
234
+ mapped = matched[0]
235
+ if not any(
236
+ mapped.start >= combined.start and mapped.end <= combined.end and script_range.style in combined.styles
237
+ for combined in combined_ranges
238
+ ):
239
+ continue
240
+ raw_intervals = _raw_style_intervals(content, projected, [mapped])
241
+ if len(raw_intervals) != 1:
242
+ continue
243
+ raw_interval = raw_intervals[0]
244
+ output.append(
245
+ {
246
+ "block_index": block_index,
247
+ "raw_start": raw_interval.start,
248
+ "raw_end": raw_interval.end,
249
+ "source_index": line.source_index,
250
+ "range_start": script_range.start,
251
+ "range_end": script_range.end,
252
+ "role": script_range.style,
253
+ "text": line.text[script_range.start : script_range.end],
254
+ "bbox": script_range.bbox,
255
+ "angle": line.angle,
256
+ "formula_region": script_range.formula_region,
257
+ "stable_body_count": script_range.stable_body_count,
258
+ }
259
+ )
260
+
261
+
262
+ def apply_pdf_text_scripts(
263
+ blocks: list[dict[str, Any]],
264
+ lines: list[PDFTextScriptLine],
265
+ page_size: tuple[float, float],
266
+ *,
267
+ materialized_diagnostics: list[dict[str, Any]] | None = None,
268
+ ) -> None:
269
+ """把 Flash 上下标 sidecar 投影到最终自然语言 block,并清理公式私有区域。"""
270
+ assignments = _assign_script_lines_to_blocks(blocks, lines, page_size)
271
+ for block_index, block_lines in assignments.items():
272
+ block = blocks[block_index]
273
+ regions = [
274
+ region
275
+ for value in block.get("_inline_math_regions", [])
276
+ if (region := _block_bbox_to_page_bbox(value, page_size)) is not None
277
+ ]
278
+ projected_lines = []
279
+ eligible_ranges: dict[int, tuple[PDFTextScriptRange, ...]] = {}
280
+ for line in block_lines:
281
+ retained = tuple(
282
+ script_range
283
+ for script_range in line.script_ranges
284
+ if not _script_range_hits_late_formula_region(script_range, regions)
285
+ )
286
+ eligible_ranges[id(line)] = retained
287
+ ranges = tuple(
288
+ PDFTextStyleRange(
289
+ script_range.start,
290
+ script_range.end,
291
+ (script_range.style,),
292
+ )
293
+ for script_range in retained
294
+ )
295
+ projected_lines.append(
296
+ PDFTextStyleLine(
297
+ bbox=line.bbox,
298
+ text=line.text,
299
+ style_ranges=ranges,
300
+ source_index=line.source_index,
301
+ )
302
+ )
303
+ projected_lines = _filter_line_styles_for_block(projected_lines, block.get("type"))
304
+ content = block.get("content")
305
+ if not isinstance(content, str) or not content:
306
+ continue
307
+ projected = _project_content_chars(content)
308
+ combined_ranges = _merge_style_ranges(
309
+ [
310
+ *_match_style_ranges(projected, projected_lines),
311
+ *(
312
+ matched_range
313
+ for projected_line in projected_lines
314
+ for matched_range in _match_script_line_ranges(projected, projected_line)
315
+ ),
316
+ ]
317
+ )
318
+ if materialized_diagnostics is not None:
319
+ for line in block_lines:
320
+ _record_materialized_script_ranges(
321
+ content,
322
+ projected,
323
+ combined_ranges,
324
+ block_index,
325
+ line,
326
+ eligible_ranges.get(id(line), ()),
327
+ materialized_diagnostics,
328
+ )
329
+ intervals = _raw_style_intervals(content, projected, combined_ranges)
330
+ if intervals:
331
+ existing = block.get(_PDF_STYLE_INTERVALS_KEY, [])
332
+ block[_PDF_STYLE_INTERVALS_KEY] = _merge_raw_style_intervals(
333
+ content,
334
+ [
335
+ *(interval for interval in existing if isinstance(interval, _RawStyleInterval)),
336
+ *intervals,
337
+ ],
338
+ )
339
+ for block in blocks:
340
+ block.pop("_inline_math_regions", None)
341
+
342
+
343
+ def _parse_native_script_markup(content: str) -> _NativeScriptMarkup | None:
344
+ """严格解析 detector-owned 平坦 sup/sub 标签;畸形或嵌套结构返回 None。"""
345
+ marker_ranges: list[tuple[int, int]] = []
346
+ style_intervals: list[tuple[int, int, str]] = []
347
+ active: tuple[str, int] | None = None
348
+ for match in _NATIVE_SCRIPT_TAG_RE.finditer(content):
349
+ marker_ranges.append((match.start(), match.end()))
350
+ style = "superscript" if match.group("tag") == "sup" else "subscript"
351
+ if match.group("closing") is None:
352
+ if active is not None:
353
+ return None
354
+ active = (style, match.end())
355
+ continue
356
+ if active is None or active[0] != style:
357
+ return None
358
+ if active[1] < match.start():
359
+ style_intervals.append((active[1], match.start(), style))
360
+ active = None
361
+ if active is not None or not marker_ranges:
362
+ return None
363
+ return _NativeScriptMarkup(
364
+ marker_ranges=tuple(marker_ranges),
365
+ style_intervals=tuple(style_intervals),
366
+ )
367
+
368
+
369
+ def materialize_pdf_inline_spans(blocks: list[dict[str, Any]]) -> None:
370
+ """把 PDF 原文、样式区间、链接区间和行内公式一次性物化为 Span。"""
371
+ formula_pattern = re.compile(r"\\\((?P<latex>.*?)\\\)", re.DOTALL)
372
+ for block in blocks:
373
+ owns_native_script_markup = block.pop(PDF_NATIVE_SCRIPT_MARKUP_KEY, False) is True
374
+ if block.get("type") not in _PDF_INLINE_SPAN_BLOCK_TYPES:
375
+ continue
376
+ content = block.get("content")
377
+ link_intervals = block.pop(_PDF_LINK_INTERVALS_KEY, [])
378
+ style_intervals = block.pop(_PDF_STYLE_INTERVALS_KEY, [])
379
+ if not isinstance(content, str):
380
+ continue
381
+ native_scripts = _parse_native_script_markup(content) if owns_native_script_markup else None
382
+ marker_ranges = native_scripts.marker_ranges if native_scripts is not None else ()
383
+ script_intervals = native_scripts.style_intervals if native_scripts is not None else ()
384
+ formulas = list(formula_pattern.finditer(content))
385
+ boundaries = {0, len(content)}
386
+ for interval in [*link_intervals, *style_intervals]:
387
+ boundaries.update((interval.start, interval.end))
388
+ for start, end in marker_ranges:
389
+ boundaries.update((start, end))
390
+ for start, end, _style in script_intervals:
391
+ boundaries.update((start, end))
392
+ for formula in formulas:
393
+ boundaries.update((formula.start(), formula.end()))
394
+ ordered = sorted(value for value in boundaries if 0 <= value <= len(content))
395
+ spans: list[dict[str, Any]] = []
396
+ for start, end in zip(ordered, ordered[1:]):
397
+ if start >= end:
398
+ continue
399
+ if any(marker_start <= start and end <= marker_end for marker_start, marker_end in marker_ranges):
400
+ continue
401
+ formula = next((item for item in formulas if item.start() == start and item.end() == end), None)
402
+ if formula is not None:
403
+ append_equation_span(spans, formula.group("latex"))
404
+ continue
405
+ text = content[start:end]
406
+ if not text:
407
+ continue
408
+ styles = _canonical_styles(
409
+ style
410
+ for interval in style_intervals
411
+ if interval.start <= start and end <= interval.end
412
+ for style in interval.styles
413
+ )
414
+ script_styles = tuple(
415
+ style
416
+ for interval_start, interval_end, style in script_intervals
417
+ if interval_start <= start and end <= interval_end
418
+ )
419
+ combined_styles = tuple(dict.fromkeys((*styles, *script_styles)))
420
+ link = next(
421
+ (interval for interval in link_intervals if interval.start <= start and end <= interval.end),
422
+ None,
423
+ )
424
+ if link is None:
425
+ if combined_styles and text.strip():
426
+ leading_length = len(text) - len(text.lstrip())
427
+ trailing_length = len(text) - len(text.rstrip())
428
+ core_end = len(text) - trailing_length if trailing_length else len(text)
429
+ append_text_span(spans, text[:leading_length])
430
+ append_text_span(spans, text[leading_length:core_end], combined_styles)
431
+ append_text_span(spans, text[core_end:])
432
+ else:
433
+ append_text_span(spans, text, combined_styles)
434
+ continue
435
+ children: list[dict[str, Any]] = []
436
+ append_text_span(children, text, (style for style in combined_styles if style != "underline"))
437
+ if spans and spans[-1].get("type") == "hyperlink" and spans[-1].get("url") == link.target:
438
+ existing = spans[-1].get("content")
439
+ if isinstance(existing, list):
440
+ extend_inline_spans(existing, children)
441
+ continue
442
+ append_hyperlink_span(spans, children, link.target)
443
+ block["content"] = normalize_span_dicts(spans)
444
+
445
+
446
+ __all__ = [
447
+ "apply_pdf_text_links",
448
+ "_append_raw_style_interval",
449
+ "_merge_raw_style_intervals",
450
+ "_raw_style_intervals",
451
+ "apply_pdf_text_styles",
452
+ "_script_range_hits_late_formula_region",
453
+ "_record_materialized_script_ranges",
454
+ "apply_pdf_text_scripts",
455
+ "_parse_native_script_markup",
456
+ "materialize_pdf_inline_spans",
457
+ ]