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,354 @@
1
+ """把 Excel 97–2003 BIFF 工作簿转换为 DocVortex 分页 model-list。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ import collections
6
+ import re
7
+ from typing import Any, BinaryIO
8
+
9
+ from loguru import logger
10
+ from openpyxl import Workbook # type: ignore[reportMissingModuleSource]
11
+ from openpyxl.cell.rich_text import CellRichText, TextBlock # type: ignore[reportMissingModuleSource]
12
+ from openpyxl.cell.text import InlineFont # type: ignore[reportMissingModuleSource]
13
+ from openpyxl.worksheet.worksheet import Worksheet # type: ignore[reportMissingModuleSource]
14
+
15
+ from ..errors import LegacyOfficeEncryptedError, LegacyOfficeResourceLimitError
16
+ from ..limits import MAX_GRID_SLOTS
17
+ from ..equation.mtef import decode_equation_native
18
+ from ..legacy.ole import BoundedOleReader
19
+ from ..spreadsheet.html import render_spreadsheet_table
20
+ from ..spreadsheet.models import AnchoredBlock, ExcelTable, FormulaMap, SheetImage
21
+ from ..spreadsheet.projector import SpreadsheetProjector
22
+ from ..streams import read_stream_bytes_from_start
23
+ from .....schema import BlockType
24
+
25
+ from .models import XlsChart, XlsChartSheet, XlsRichText, XlsSheet, XlsWorkbook
26
+ from .parser import parse_xls_workbook
27
+
28
+ _XLS_EQUATION_STREAM_RE = re.compile(
29
+ r"^(MBD[0-9A-F]{8})/Equation Native$",
30
+ re.IGNORECASE,
31
+ )
32
+
33
+
34
+ def _read_embedded_equations(ole: BoundedOleReader) -> dict[str, str]:
35
+ """读取 XLS embedding storages 中可安全解码的 Equation Native。"""
36
+
37
+ equations: dict[str, str] = {}
38
+ for stream_name in ole.stream_names(prefix="MBD"):
39
+ match = _XLS_EQUATION_STREAM_RE.match(stream_name)
40
+ if match is None:
41
+ continue
42
+ storage = match.group(1)
43
+ latex = decode_equation_native(ole.read_stream(stream_name))
44
+ if latex is None:
45
+ logger.warning(
46
+ "XLS_MTEF_FALLBACK: storage={!r} has an invalid or unsupported Equation Native stream",
47
+ storage,
48
+ )
49
+ continue
50
+ equations.setdefault(storage, latex)
51
+ return equations
52
+
53
+
54
+ def _inline_font(rich_text: XlsRichText, start: int) -> InlineFont | None:
55
+ """返回覆盖指定字符位置的 openpyxl 行内字体。"""
56
+
57
+ for run in rich_text.runs:
58
+ if run.start <= start < run.end:
59
+ style = run.style
60
+ return InlineFont(
61
+ b=style.bold,
62
+ i=style.italic,
63
+ u="single" if style.underline else None,
64
+ strike=style.strike,
65
+ vertAlign=("superscript" if style.superscript else "subscript" if style.subscript else None),
66
+ )
67
+ return None
68
+
69
+
70
+ def _rich_text_boundaries(value: XlsRichText) -> list[int]:
71
+ """收集富文本的起止边界并裁剪到有效字符范围。"""
72
+
73
+ boundaries = {0, len(value.text)}
74
+ for run in value.runs:
75
+ boundaries.add(max(0, min(run.start, len(value.text))))
76
+ boundaries.add(max(0, min(run.end, len(value.text))))
77
+ return sorted(boundaries)
78
+
79
+
80
+ def _to_openpyxl_rich_text(value: XlsRichText) -> str | CellRichText:
81
+ """把内部富文本转换为 XlsxConverter 已支持的 CellRichText。"""
82
+
83
+ if not value.runs:
84
+ return value.text
85
+ parts: list[str | TextBlock] = []
86
+ boundaries = _rich_text_boundaries(value)
87
+ for start, end in zip(boundaries, boundaries[1:]):
88
+ if start >= end:
89
+ continue
90
+ text = value.text[start:end]
91
+ font = _inline_font(value, start)
92
+ parts.append(TextBlock(font, text) if font is not None else text)
93
+ return CellRichText(parts)
94
+
95
+
96
+ class _XlsPageBuilder(SpreadsheetProjector):
97
+ """用轻量 openpyxl worksheet 适配器复用现有网格与 HTML 投影。"""
98
+
99
+ def __init__(self, workbook_model: XlsWorkbook) -> None:
100
+ """初始化解析结果映射和全工作簿网格预算。"""
101
+
102
+ super().__init__(include_hidden_sheets=False)
103
+ self.workbook_model = workbook_model
104
+ self._sheet_by_title: dict[str, XlsSheet] = {}
105
+ self._active_xls_sheet: XlsSheet | None = None
106
+ self._used_cells: set[tuple[int, int]] = set()
107
+ self._grid_slots = 0
108
+
109
+ def _build_openpyxl_workbook(self) -> Workbook:
110
+ """把 BIFF 语义模型投影成不落盘的 worksheet 对象。"""
111
+
112
+ workbook = Workbook()
113
+ merge_grid_slots = 0
114
+ default_sheet = workbook.active
115
+ if default_sheet is not None:
116
+ workbook.remove(default_sheet)
117
+ for sheet_model in self.workbook_model.sheets:
118
+ worksheet = workbook.create_sheet(sheet_model.name)
119
+ self._sheet_by_title[worksheet.title] = sheet_model
120
+ if not sheet_model.visible:
121
+ worksheet.sheet_state = Worksheet.SHEETSTATE_HIDDEN
122
+ for cell_model in sheet_model.cells.values():
123
+ cell = worksheet.cell(row=cell_model.row + 1, column=cell_model.col + 1)
124
+ cell.value = _to_openpyxl_rich_text(cell_model.value)
125
+ if cell_model.hyperlink:
126
+ cell.hyperlink = cell_model.hyperlink
127
+ for row_first, col_first, row_last, col_last in sheet_model.merges:
128
+ merge_slots = (row_last - row_first + 1) * (col_last - col_first + 1)
129
+ if merge_slots > MAX_GRID_SLOTS - merge_grid_slots:
130
+ raise LegacyOfficeResourceLimitError(f"workbook extent exceeds max_grid_slots={MAX_GRID_SLOTS}")
131
+ merge_grid_slots += merge_slots
132
+ worksheet.merge_cells(
133
+ start_row=row_first + 1,
134
+ start_column=col_first + 1,
135
+ end_row=row_last + 1,
136
+ end_column=col_last + 1,
137
+ )
138
+ return workbook
139
+
140
+ def _ensure_workbook(self) -> Workbook:
141
+ """惰性构造一次 openpyxl 适配工作簿。"""
142
+
143
+ workbook = getattr(self, "workbook", None)
144
+ if workbook is None:
145
+ workbook = self._build_openpyxl_workbook()
146
+ self.workbook = workbook
147
+ return workbook
148
+
149
+ def render_chart_selection(
150
+ self,
151
+ sheet_name: str,
152
+ rows: tuple[int, ...] | list[int],
153
+ cols: tuple[int, ...] | list[int],
154
+ ) -> str | None:
155
+ """把指定 worksheet 行列选择渲染为共享 chart HTML。"""
156
+
157
+ if not rows or not cols:
158
+ return None
159
+ grid_slots = len(rows) * len(cols)
160
+ self._grid_slots += grid_slots
161
+ if self._grid_slots > MAX_GRID_SLOTS:
162
+ raise LegacyOfficeResourceLimitError(f"workbook extent exceeds max_grid_slots={MAX_GRID_SLOTS}")
163
+ workbook = self._ensure_workbook()
164
+ if sheet_name not in workbook.sheetnames:
165
+ return None
166
+ sheet = workbook[sheet_name]
167
+ table = self._build_synthetic_table_from_sheet_selection(
168
+ sheet,
169
+ list(rows),
170
+ list(cols),
171
+ )
172
+ return render_spreadsheet_table(table)
173
+
174
+ def _chart_sheet_page(self, chart_sheet: XlsChartSheet) -> list[dict[str, Any]]:
175
+ """把独立 chart sheet 投影为仅含 chart block 的逻辑页。"""
176
+
177
+ if chart_sheet.source_sheet_name is None:
178
+ return []
179
+ content = self.render_chart_selection(
180
+ chart_sheet.source_sheet_name,
181
+ chart_sheet.source_rows,
182
+ chart_sheet.source_cols,
183
+ )
184
+ return [{"type": BlockType.CHART, "content": content}] if content else []
185
+
186
+ def build_pages(self) -> list[list[dict[str, Any]]]:
187
+ """按原目录顺序生成可见 worksheet/chart sheet 页面。"""
188
+
189
+ self.workbook = self._build_openpyxl_workbook()
190
+ pages_by_name: dict[str, list[dict[str, Any]]] = {}
191
+ for worksheet in self._iter_sheets_to_convert():
192
+ self._active_xls_sheet = self._sheet_by_title.get(worksheet.title)
193
+ self.cur_page = []
194
+ self._convert_sheet(worksheet)
195
+ pages_by_name[worksheet.title] = self.cur_page
196
+
197
+ ordered_pages: list[tuple[int, int, str, list[dict[str, Any]]]] = []
198
+ for index, sheet in enumerate(self.workbook_model.sheets):
199
+ if not sheet.visible:
200
+ continue
201
+ order = sheet.order if sheet.order >= 0 else index
202
+ ordered_pages.append((order, 0, sheet.name, pages_by_name.get(sheet.name, [])))
203
+ for index, chart_sheet in enumerate(self.workbook_model.chart_sheets):
204
+ if not chart_sheet.visible:
205
+ continue
206
+ order = chart_sheet.order if chart_sheet.order >= 0 else len(ordered_pages) + index
207
+ ordered_pages.append((order, 1, chart_sheet.name, self._chart_sheet_page(chart_sheet)))
208
+ ordered_pages.sort(key=lambda item: (item[0], item[1]))
209
+ sheet_pages = [(name, page) for _order, _kind, name, page in ordered_pages]
210
+ if self._should_emit_sheet_titles([page for _, page in sheet_pages]):
211
+ self._prepend_sheet_titles(sheet_pages)
212
+ return [page for _, page in sheet_pages]
213
+
214
+ def _collect_sheet_images(self, sheet: Worksheet) -> list[SheetImage]:
215
+ """返回解析器已经绑定到当前 sheet 的图片。"""
216
+
217
+ sheet_model = self._sheet_by_title.get(sheet.title)
218
+ if sheet_model is None:
219
+ return []
220
+ return [
221
+ SheetImage(
222
+ anchor=(image.row, image.col),
223
+ image_base64=image.image_base64,
224
+ )
225
+ for image in sheet_model.images
226
+ ]
227
+
228
+ def _map_math_formulas_to_cells(self, sheet: Worksheet) -> FormulaMap:
229
+ """把 legacy Equation Editor 公式映射到表格 cell anchor。"""
230
+
231
+ math_map: dict[tuple[int, int], list[str]] = collections.defaultdict(list)
232
+ sheet_model = self._sheet_by_title.get(sheet.title)
233
+ if sheet_model is None:
234
+ return math_map
235
+ for equation in sheet_model.equations:
236
+ math_map[(equation.row, equation.col)].append(equation.latex)
237
+ return math_map
238
+
239
+ def _find_tables_in_sheet(
240
+ self,
241
+ sheet: Worksheet,
242
+ ) -> tuple[set[tuple[int, int]], list[tuple[tuple[int, int], int, dict]]]:
243
+ """记录表格已吸收坐标,供独立公式去重。"""
244
+
245
+ used_cells, artifacts = super()._find_tables_in_sheet(sheet)
246
+ self._used_cells = used_cells
247
+ return used_cells, artifacts
248
+
249
+ def _find_data_tables(self, sheet: Worksheet) -> list[ExcelTable]:
250
+ """复用 XLSX 区域发现并累计限制实际物化网格。"""
251
+
252
+ tables = super()._find_data_tables(sheet)
253
+ self._grid_slots += sum(table.num_rows * table.num_cols for table in tables)
254
+ if self._grid_slots > MAX_GRID_SLOTS:
255
+ raise LegacyOfficeResourceLimitError(f"workbook extent exceeds max_grid_slots={MAX_GRID_SLOTS}")
256
+ return tables
257
+
258
+ def _chart_block(self, sheet: Worksheet, chart: XlsChart) -> dict[str, Any] | None:
259
+ """把简单 chart 引用转换成数据表,并保留可用预览图片。"""
260
+
261
+ if chart.source_rows and chart.source_cols:
262
+ content = self.render_chart_selection(
263
+ sheet.title,
264
+ chart.source_rows,
265
+ chart.source_cols,
266
+ )
267
+ if content is None:
268
+ return None
269
+ block = {
270
+ "type": BlockType.CHART,
271
+ "content": content,
272
+ }
273
+ if chart.image_base64:
274
+ block["image_base64"] = chart.image_base64
275
+ return block
276
+ if chart.image_base64:
277
+ return {
278
+ "type": BlockType.CHART,
279
+ "content": "",
280
+ "image_base64": chart.image_base64,
281
+ }
282
+ return None
283
+
284
+ def _find_charts_in_sheet(
285
+ self,
286
+ sheet: Worksheet,
287
+ ) -> list[AnchoredBlock]:
288
+ """按 cell anchor 输出当前工作表的 legacy chart blocks。"""
289
+
290
+ sheet_model = self._sheet_by_title.get(sheet.title)
291
+ if sheet_model is None:
292
+ return []
293
+ artifacts = []
294
+ for order, chart in enumerate(sheet_model.charts):
295
+ block = self._chart_block(sheet, chart)
296
+ if block is None:
297
+ continue
298
+ artifacts.append(((chart.row, chart.col), 10_000 + order, block))
299
+ for order, equation in enumerate(sheet_model.equations):
300
+ anchor = (equation.row, equation.col)
301
+ if anchor in self._used_cells:
302
+ continue
303
+ artifacts.append(
304
+ (
305
+ anchor,
306
+ 20_000 + order,
307
+ {"type": BlockType.EQUATION, "content": equation.latex},
308
+ )
309
+ )
310
+ return artifacts
311
+
312
+
313
+ def render_xls_chart_html(
314
+ workbook: XlsWorkbook,
315
+ sheet_name: str,
316
+ rows: tuple[int, ...] | list[int],
317
+ cols: tuple[int, ...] | list[int],
318
+ ) -> str | None:
319
+ """为 DOC/PPT 嵌入式 chart 复用 XLS 的稳定 HTML 投影。"""
320
+
321
+ return _XlsPageBuilder(workbook).render_chart_selection(
322
+ sheet_name,
323
+ rows,
324
+ cols,
325
+ )
326
+
327
+
328
+ class XlsConverter:
329
+ """将 Excel 97–2003 OLE/BIFF 二进制流转换为 model-list。"""
330
+
331
+ def __init__(self) -> None:
332
+ """初始化空分页输出。"""
333
+
334
+ self.pages: list[list[dict[str, Any]]] = []
335
+
336
+ def convert(self, file_binary: BinaryIO) -> None:
337
+ """读取 Workbook/Book stream,解析 BIFF 并生成可见 sheet 页面。"""
338
+
339
+ file_bytes = read_stream_bytes_from_start(file_binary)
340
+ with BoundedOleReader(file_bytes) as ole:
341
+ if ole.has_stream("EncryptionInfo") or ole.has_stream("EncryptedPackage"):
342
+ raise LegacyOfficeEncryptedError("password-protected XLS is not supported")
343
+ if ole.has_stream("Workbook"):
344
+ workbook_stream = ole.read_stream("Workbook")
345
+ else:
346
+ workbook_stream = ole.read_stream("Book")
347
+ native_equations = _read_embedded_equations(ole)
348
+ workbook = parse_xls_workbook(
349
+ workbook_stream,
350
+ native_equations=native_equations,
351
+ )
352
+ builder = _XlsPageBuilder(workbook)
353
+ self.pages = builder.build_pages()
354
+ logger.debug("XLS parsing produced {} visible sheet pages", len(self.pages))
@@ -0,0 +1,3 @@
1
+ """Flash XLSX 转换实现。"""
2
+
3
+ __all__: list[str] = []
@@ -0,0 +1,20 @@
1
+ from typing import Any, BinaryIO
2
+
3
+ from ... import XlsxModel
4
+
5
+
6
+ def convert_path(file_path: str) -> list[list[dict[str, Any]]]:
7
+ """从 XLSX 文件路径调用统一模型入口。"""
8
+
9
+ with open(file_path, "rb") as fh:
10
+ return convert_binary(fh)
11
+
12
+
13
+ def convert_binary(file_binary: BinaryIO) -> list[list[dict[str, Any]]]:
14
+ """兼容旧二进制转换函数,并转发给 XlsxModel。"""
15
+
16
+ return XlsxModel().predict(file_binary)
17
+
18
+
19
+ if __name__ == "__main__":
20
+ print(convert_path("test_xlsx/xlsx_01.xlsx"))