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,310 @@
1
+ from io import BytesIO
2
+ import re
3
+ from zipfile import BadZipFile, ZipFile, ZipInfo
4
+ import xml.etree.ElementTree as ET
5
+
6
+ from ..opc import write_zip_package
7
+
8
+ SPREADSHEETML_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
9
+ SHARED_STRINGS_PATH = "xl/sharedStrings.xml"
10
+ STYLES_PATH = "xl/styles.xml"
11
+ WORKSHEET_PREFIX = "xl/worksheets/"
12
+ WORKSHEET_SUFFIX = ".xml"
13
+ UNDERLINE_TAG = f"{{{SPREADSHEETML_NS}}}u"
14
+ FILLS_TAG = f"{{{SPREADSHEETML_NS}}}fills"
15
+ FILL_TAG = f"{{{SPREADSHEETML_NS}}}fill"
16
+ PATTERN_FILL_TAG = f"{{{SPREADSHEETML_NS}}}patternFill"
17
+ AUTOFILTER_TAG = f"{{{SPREADSHEETML_NS}}}autoFilter"
18
+ DIMENSION_TAG = f"{{{SPREADSHEETML_NS}}}dimension"
19
+ SHEET_DATA_TAG = f"{{{SPREADSHEETML_NS}}}sheetData"
20
+ CELL_TAG = f"{{{SPREADSHEETML_NS}}}c"
21
+ UNDERLINE_VAL_ATTRS = ("val", f"{{{SPREADSHEETML_NS}}}val")
22
+ VALID_UNDERLINE_VALUES = {
23
+ "single",
24
+ "double",
25
+ "singleAccounting",
26
+ "doubleAccounting",
27
+ "none",
28
+ }
29
+ ROW_ONLY_RANGE_RE = re.compile(r"^\$?([1-9][0-9]*):\$?([1-9][0-9]*)$")
30
+ CELL_REF_RE = re.compile(r"^\$?([A-Za-z]{1,3})\$?[1-9][0-9]*$")
31
+ CELL_RANGE_RE = re.compile(r"^\$?([A-Za-z]{1,3})\$?[1-9][0-9]*:\$?([A-Za-z]{1,3})\$?[1-9][0-9]*$")
32
+ WHOLE_COLUMN_RANGE_RE = re.compile(r"^\$?([A-Za-z]{1,3}):\$?([A-Za-z]{1,3})$")
33
+ MAX_EXCEL_COLUMN = "XFD"
34
+
35
+
36
+ def normalize_xlsx_package(file_bytes: bytes) -> bytes:
37
+ """在进入 openpyxl 前修复常见 XLSX 包级兼容问题。"""
38
+ try:
39
+ with ZipFile(BytesIO(file_bytes)) as source:
40
+ rewritten_members: list[tuple[ZipInfo, bytes]] = []
41
+ changed = False
42
+
43
+ for info in source.infolist():
44
+ member_data = source.read(info.filename)
45
+ normalized_data = _normalize_xlsx_member(info.filename, member_data)
46
+ if normalized_data != member_data:
47
+ changed = True
48
+ member_data = normalized_data
49
+ rewritten_members.append((info, member_data))
50
+ except BadZipFile as exc:
51
+ raise ValueError("Invalid XLSX package: file is not a ZIP archive.") from exc
52
+
53
+ if not changed:
54
+ return file_bytes
55
+
56
+ return write_zip_package(rewritten_members)
57
+
58
+
59
+ def strip_xlsx_ole_objects_for_openpyxl(file_bytes: bytes) -> bytes:
60
+ """仅为 openpyxl 读取副本移除会被误判为列定义的 oleObjects。"""
61
+
62
+ try:
63
+ with ZipFile(BytesIO(file_bytes)) as source:
64
+ rewritten_members: list[tuple[ZipInfo, bytes]] = []
65
+ changed = False
66
+ for info in source.infolist():
67
+ member_data = source.read(info.filename)
68
+ if _is_worksheet_xml(info.filename):
69
+ normalized_data = _remove_worksheet_ole_objects(member_data)
70
+ changed = changed or normalized_data != member_data
71
+ member_data = normalized_data
72
+ rewritten_members.append((info, member_data))
73
+ except BadZipFile as exc:
74
+ raise ValueError("Invalid XLSX package: file is not a ZIP archive.") from exc
75
+ return write_zip_package(rewritten_members) if changed else file_bytes
76
+
77
+
78
+ def _remove_worksheet_ole_objects(xml_bytes: bytes) -> bytes:
79
+ """删除 worksheet 的 oleObjects 容器,原始 ZIP 仍由公式解析器持有。"""
80
+
81
+ try:
82
+ root = ET.fromstring(xml_bytes)
83
+ except ET.ParseError:
84
+ return xml_bytes
85
+ changed = False
86
+ for child in list(root):
87
+ if child.tag.rsplit("}", 1)[-1] != "oleObjects":
88
+ continue
89
+ root.remove(child)
90
+ changed = True
91
+ if not changed:
92
+ return xml_bytes
93
+ return ET.tostring(root, encoding="utf-8", xml_declaration=True)
94
+
95
+
96
+ def _normalize_xlsx_member(member_name: str, member_data: bytes) -> bytes:
97
+ """根据 XLSX 包内成员路径分发 XML 兼容性规范化逻辑。"""
98
+ if member_name == SHARED_STRINGS_PATH:
99
+ return _normalize_shared_strings_xml(member_data)
100
+ if member_name == STYLES_PATH:
101
+ return _normalize_styles_xml(member_data)
102
+ if _is_worksheet_xml(member_name):
103
+ return _normalize_worksheet_xml(member_data)
104
+ return member_data
105
+
106
+
107
+ def _normalize_shared_strings_xml(xml_bytes: bytes) -> bytes:
108
+ """规范化共享字符串 XML 中 openpyxl 无法接受的富文本属性。"""
109
+ try:
110
+ root = ET.fromstring(xml_bytes)
111
+ except ET.ParseError:
112
+ return xml_bytes
113
+
114
+ changed = False
115
+ for underline in root.findall(f".//{UNDERLINE_TAG}"):
116
+ if _drop_blank_underline_value(underline):
117
+ changed = True
118
+
119
+ if not changed:
120
+ return xml_bytes
121
+
122
+ return ET.tostring(root, encoding="utf-8", xml_declaration=True)
123
+
124
+
125
+ def _normalize_styles_xml(xml_bytes: bytes) -> bytes:
126
+ """规范化 styles.xml 中 openpyxl 无法接受的空 fill 节点。"""
127
+ try:
128
+ root = ET.fromstring(xml_bytes)
129
+ except ET.ParseError:
130
+ return xml_bytes
131
+
132
+ changed = False
133
+ fills = root.find(FILLS_TAG)
134
+ if fills is not None:
135
+ for fill in fills.findall(FILL_TAG):
136
+ if _ensure_fill_has_pattern(fill):
137
+ changed = True
138
+
139
+ if not changed:
140
+ return xml_bytes
141
+
142
+ return ET.tostring(root, encoding="utf-8", xml_declaration=True)
143
+
144
+
145
+ def _normalize_worksheet_xml(xml_bytes: bytes) -> bytes:
146
+ """规范化 worksheet XML 中会阻断 openpyxl 加载的行范围筛选器。"""
147
+ try:
148
+ root = ET.fromstring(xml_bytes)
149
+ except ET.ParseError:
150
+ return xml_bytes
151
+
152
+ changed = False
153
+ for auto_filter in root.findall(f".//{AUTOFILTER_TAG}"):
154
+ if _normalize_auto_filter_ref(root, auto_filter):
155
+ changed = True
156
+
157
+ if not changed:
158
+ return xml_bytes
159
+
160
+ return ET.tostring(root, encoding="utf-8", xml_declaration=True)
161
+
162
+
163
+ def _drop_blank_underline_value(underline: ET.Element) -> bool:
164
+ """删除空白 underline val,保留 <u/> 的默认单下划线语义。"""
165
+ for attr_name in UNDERLINE_VAL_ATTRS:
166
+ attr_value = underline.attrib.get(attr_name)
167
+ if attr_value is None:
168
+ continue
169
+ if attr_value.strip() == "":
170
+ del underline.attrib[attr_name]
171
+ return True
172
+ if attr_value not in VALID_UNDERLINE_VALUES:
173
+ return False
174
+ return False
175
+
176
+
177
+ def _ensure_fill_has_pattern(fill: ET.Element) -> bool:
178
+ """为空 fill 补一个空 patternFill,保留原 fillId 顺序和样式引用。"""
179
+ if len(fill):
180
+ return False
181
+
182
+ fill.append(ET.Element(PATTERN_FILL_TAG))
183
+ return True
184
+
185
+
186
+ def _normalize_auto_filter_ref(root: ET.Element, auto_filter: ET.Element) -> bool:
187
+ """将 autoFilter 的纯行范围 ref 扩展为 openpyxl 可接受的单元格范围。"""
188
+ ref = auto_filter.attrib.get("ref")
189
+ if not ref:
190
+ return False
191
+
192
+ rows = _parse_row_only_range(ref)
193
+ if rows is None:
194
+ return False
195
+
196
+ min_col, max_col = _resolve_worksheet_column_bounds(root)
197
+ auto_filter.set("ref", f"{min_col}{rows[0]}:{max_col}{rows[1]}")
198
+ return True
199
+
200
+
201
+ def _parse_row_only_range(ref: str) -> tuple[int, int] | None:
202
+ """解析 Excel 行范围写法,仅接受正整数且起止顺序有效的范围。"""
203
+ match = ROW_ONLY_RANGE_RE.match(ref)
204
+ if match is None:
205
+ return None
206
+
207
+ min_row, max_row = int(match.group(1)), int(match.group(2))
208
+ if min_row > max_row:
209
+ return None
210
+ return min_row, max_row
211
+
212
+
213
+ def _resolve_worksheet_column_bounds(root: ET.Element) -> tuple[str, str]:
214
+ """优先从 dimension 获取列边界,失败时退回扫描 sheetData。"""
215
+ dimension = root.find(DIMENSION_TAG)
216
+ if dimension is not None:
217
+ columns = _column_bounds_from_ref(dimension.attrib.get("ref", ""))
218
+ if columns is not None:
219
+ return columns
220
+
221
+ columns = _column_bounds_from_sheet_data(root)
222
+ if columns is not None:
223
+ return columns
224
+
225
+ return "A", MAX_EXCEL_COLUMN
226
+
227
+
228
+ def _column_bounds_from_ref(ref: str) -> tuple[str, str] | None:
229
+ """从 dimension/ref 这类范围字符串中解析起止列。"""
230
+ ref = ref.strip()
231
+ if not ref:
232
+ return None
233
+
234
+ range_match = CELL_RANGE_RE.match(ref)
235
+ if range_match is not None:
236
+ return (
237
+ range_match.group(1).upper(),
238
+ range_match.group(2).upper(),
239
+ )
240
+
241
+ cell_match = CELL_REF_RE.match(ref)
242
+ if cell_match is not None:
243
+ column = cell_match.group(1).upper()
244
+ return column, column
245
+
246
+ whole_column_match = WHOLE_COLUMN_RANGE_RE.match(ref)
247
+ if whole_column_match is not None:
248
+ return (
249
+ whole_column_match.group(1).upper(),
250
+ whole_column_match.group(2).upper(),
251
+ )
252
+
253
+ return None
254
+
255
+
256
+ def _column_bounds_from_sheet_data(root: ET.Element) -> tuple[str, str] | None:
257
+ """扫描 sheetData 里的单元格引用,推导工作表真实列范围。"""
258
+ sheet_data = root.find(SHEET_DATA_TAG)
259
+ if sheet_data is None:
260
+ return None
261
+
262
+ column_indexes = []
263
+ for cell in sheet_data.findall(f".//{CELL_TAG}"):
264
+ column = _column_from_cell_ref(cell.attrib.get("r", ""))
265
+ if column is not None:
266
+ column_indexes.append(_column_to_index(column))
267
+
268
+ if not column_indexes:
269
+ return None
270
+
271
+ return (
272
+ _index_to_column(min(column_indexes)),
273
+ _index_to_column(max(column_indexes)),
274
+ )
275
+
276
+
277
+ def _column_from_cell_ref(cell_ref: str) -> str | None:
278
+ """从 A1 形式的单元格引用中提取列名。"""
279
+ match = CELL_REF_RE.match(cell_ref)
280
+ if match is None:
281
+ return None
282
+ return match.group(1).upper()
283
+
284
+
285
+ def _column_to_index(column: str) -> int:
286
+ """将 Excel 列名转换为 1-based 数字索引。"""
287
+ index = 0
288
+ for char in column.upper():
289
+ if not "A" <= char <= "Z":
290
+ return 0
291
+ index = index * 26 + ord(char) - ord("A") + 1
292
+ return index
293
+
294
+
295
+ def _index_to_column(index: int) -> str:
296
+ """将 1-based 数字索引转换为 Excel 列名。"""
297
+ column = []
298
+ while index:
299
+ index, remainder = divmod(index - 1, 26)
300
+ column.append(chr(ord("A") + remainder))
301
+ return "".join(reversed(column))
302
+
303
+
304
+ def _is_worksheet_xml(member_name: str) -> bool:
305
+ """判断包内成员是否为普通 worksheet XML。"""
306
+ return (
307
+ member_name.startswith(WORKSHEET_PREFIX)
308
+ and member_name.endswith(WORKSHEET_SUFFIX)
309
+ and not member_name.startswith(f"{WORKSHEET_PREFIX}_rels/")
310
+ )