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,356 @@
1
+ """解析 Word PlfLst/PlfLfo 并维护九级列表编号状态。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+
7
+ from ..legacy.binary import bounded_slice, get_u16, get_u32
8
+ from .models import DocListInfo
9
+ from .records import DocBudget
10
+
11
+ LEVELS = 9
12
+
13
+
14
+ @dataclass(frozen=True, slots=True)
15
+ class NumberToken:
16
+ """编号模板中的层级引用或普通文本。"""
17
+
18
+ level: int | None = None
19
+ text: str = ""
20
+
21
+
22
+ @dataclass(frozen=True, slots=True)
23
+ class LevelDefinition:
24
+ """一个 Word 列表层级的编号规则。"""
25
+
26
+ marker: str = "bullet"
27
+ start: int = 1
28
+ restart: int | None = None
29
+ tokens: tuple[NumberToken, ...] = ()
30
+
31
+
32
+ @dataclass(frozen=True, slots=True)
33
+ class ListDefinition:
34
+ """一个 LFO 解析后的完整列表定义。"""
35
+
36
+ lsid: int
37
+ levels: tuple[LevelDefinition, ...]
38
+ overrides: tuple[int | None, ...] = (None,) * LEVELS
39
+
40
+
41
+ @dataclass(slots=True)
42
+ class _ListCounter:
43
+ """同一 lsid 的多级编号运行状态。"""
44
+
45
+ values: list[int] = field(default_factory=lambda: [0] * LEVELS)
46
+ started: list[bool] = field(default_factory=lambda: [False] * LEVELS)
47
+
48
+
49
+ class ListTables:
50
+ """按 ilfo 查询列表定义并生成逐段落可见编号。"""
51
+
52
+ def __init__(self, definitions: dict[int, ListDefinition] | None = None) -> None:
53
+ """初始化列表定义及空计数器。"""
54
+
55
+ self._definitions = definitions or {}
56
+ self._counters: dict[int, _ListCounter] = {}
57
+ self._override_used: set[tuple[int, int]] = set()
58
+
59
+ def paragraph_info(self, ilfo: int, level: int) -> DocListInfo | None:
60
+ """推进指定列表层级并返回当前段落的标签。"""
61
+
62
+ if ilfo in {0, 0xF801}:
63
+ return None
64
+ definition = self._definitions.get(ilfo)
65
+ if definition is None:
66
+ fallback_levels = tuple(LevelDefinition() for _ in range(LEVELS))
67
+ definition = ListDefinition(lsid=(0xFFFF_FFFF ^ ilfo), levels=fallback_levels)
68
+ level = min(max(level, 0), LEVELS - 1)
69
+ level_def = definition.levels[level]
70
+ if level_def.marker == "none":
71
+ return None
72
+ if level_def.marker == "bullet":
73
+ return DocListInfo(
74
+ identity=definition.lsid,
75
+ level=level,
76
+ ordered=False,
77
+ )
78
+ counter = self._counters.setdefault(definition.lsid, _ListCounter())
79
+ first_for_override = (ilfo, level) not in self._override_used
80
+ self._override_used.add((ilfo, level))
81
+ override = definition.overrides[level]
82
+ if first_for_override and override is not None:
83
+ value = override
84
+ elif counter.started[level]:
85
+ value = counter.values[level] + 1
86
+ else:
87
+ value = level_def.start
88
+ counter.values[level] = value
89
+ counter.started[level] = True
90
+ for deeper in range(level + 1, LEVELS):
91
+ restart = definition.levels[deeper].restart
92
+ if restart is None or level < restart:
93
+ counter.started[deeper] = False
94
+ return DocListInfo(
95
+ identity=definition.lsid,
96
+ level=level,
97
+ ordered=True,
98
+ start=value,
99
+ label=_render_label(definition, counter, level),
100
+ )
101
+
102
+
103
+ def _roman(value: int) -> str:
104
+ """把正整数格式化为常用 Roman 编号。"""
105
+
106
+ if value <= 0:
107
+ return str(value)
108
+ pairs = (
109
+ (1000, "M"),
110
+ (900, "CM"),
111
+ (500, "D"),
112
+ (400, "CD"),
113
+ (100, "C"),
114
+ (90, "XC"),
115
+ (50, "L"),
116
+ (40, "XL"),
117
+ (10, "X"),
118
+ (9, "IX"),
119
+ (5, "V"),
120
+ (4, "IV"),
121
+ (1, "I"),
122
+ )
123
+ result: list[str] = []
124
+ remaining = value
125
+ for number, label in pairs:
126
+ while remaining >= number:
127
+ result.append(label)
128
+ remaining -= number
129
+ return "".join(result)
130
+
131
+
132
+ def _alpha(value: int) -> str:
133
+ """把正整数格式化为 Excel 风格字母序号。"""
134
+
135
+ if value <= 0:
136
+ return str(value)
137
+ result: list[str] = []
138
+ remaining = value
139
+ while remaining:
140
+ remaining, digit = divmod(remaining - 1, 26)
141
+ result.append(chr(ord("A") + digit))
142
+ return "".join(reversed(result))
143
+
144
+
145
+ def _format_marker(marker: str, value: int) -> str:
146
+ """按 Word nfc 对应的 marker 类型格式化整数。"""
147
+
148
+ if marker == "upper_roman":
149
+ return _roman(value)
150
+ if marker == "lower_roman":
151
+ return _roman(value).lower()
152
+ if marker == "upper_alpha":
153
+ return _alpha(value)
154
+ if marker == "lower_alpha":
155
+ return _alpha(value).lower()
156
+ return str(value)
157
+
158
+
159
+ def _render_label(definition: ListDefinition, counter: _ListCounter, level: int) -> str:
160
+ """用当前各层编号替换 LVL 模板中的占位符。"""
161
+
162
+ level_def = definition.levels[level]
163
+ if not level_def.tokens:
164
+ return f"{_format_marker(level_def.marker, counter.values[level])}."
165
+ parts: list[str] = []
166
+ for token in level_def.tokens:
167
+ if token.level is None:
168
+ parts.append(token.text)
169
+ continue
170
+ source_level = min(max(token.level, 0), LEVELS - 1)
171
+ source = definition.levels[source_level]
172
+ value = counter.values[source_level] if counter.started[source_level] else source.start
173
+ parts.append(_format_marker(source.marker, value))
174
+ return "".join(parts).strip()
175
+
176
+
177
+ def _marker_for_nfc(nfc: int) -> str:
178
+ """把常见 MS-OSHARED 编号格式映射为内部 marker。"""
179
+
180
+ return {
181
+ 0: "decimal",
182
+ 1: "upper_roman",
183
+ 2: "lower_roman",
184
+ 3: "upper_alpha",
185
+ 4: "lower_alpha",
186
+ 23: "bullet",
187
+ 0xFF: "none",
188
+ }.get(nfc, "decimal")
189
+
190
+
191
+ def _parse_level(data: bytes, offset: int) -> tuple[LevelDefinition, int] | None:
192
+ """解析一个 LVL 及其 PAPX/CHPX 后的编号文本。"""
193
+
194
+ header = bounded_slice(data, offset, 28)
195
+ if header is None:
196
+ return None
197
+ start = get_u32(header, 0)
198
+ if start is None:
199
+ return None
200
+ nfc = header[4]
201
+ flags = header[5]
202
+ placeholder_offsets = [value for value in header[6:15] if value]
203
+ chpx_size = header[24]
204
+ papx_size = header[25]
205
+ restart_limit = header[26]
206
+ cursor = offset + 28 + papx_size + chpx_size
207
+ char_count = get_u16(data, cursor)
208
+ if char_count is None:
209
+ return None
210
+ cursor += 2
211
+ text_bytes = bounded_slice(data, cursor, char_count * 2)
212
+ if text_bytes is None:
213
+ return None
214
+ units = [get_u16(text_bytes, index * 2) or 0 for index in range(char_count)]
215
+ tokens: list[NumberToken] = []
216
+ marker = _marker_for_nfc(nfc)
217
+ if marker not in {"bullet", "none"}:
218
+ for index, unit in enumerate(units):
219
+ if unit <= 8 and index + 1 in placeholder_offsets:
220
+ tokens.append(NumberToken(level=unit))
221
+ elif unit >= 0x20:
222
+ char = chr(unit)
223
+ if tokens and tokens[-1].level is None:
224
+ tokens[-1] = NumberToken(text=tokens[-1].text + char)
225
+ else:
226
+ tokens.append(NumberToken(text=char))
227
+ restart = restart_limit if flags & 0x08 else None
228
+ return (
229
+ LevelDefinition(
230
+ marker=marker,
231
+ start=max(int(start), 0),
232
+ restart=restart,
233
+ tokens=tuple(tokens),
234
+ ),
235
+ cursor + char_count * 2,
236
+ )
237
+
238
+
239
+ def _parse_list_definitions(
240
+ table_stream: bytes,
241
+ *,
242
+ offset: int,
243
+ size: int,
244
+ budget: DocBudget,
245
+ ) -> dict[int, tuple[LevelDefinition, ...]]:
246
+ """解析 PlfLst 的 LSTF 数组及后续 LVL。"""
247
+
248
+ data = table_stream[offset:] if 0 <= offset < len(table_stream) else b""
249
+ count = get_u16(data, 0)
250
+ if count is None or size < 2 + count * 28:
251
+ return {}
252
+ cursor = 2
253
+ descriptors: list[tuple[int, bool]] = []
254
+ for _ in range(count):
255
+ record = bounded_slice(data, cursor, 28)
256
+ if record is None:
257
+ return {}
258
+ lsid = get_u32(record, 0)
259
+ if lsid is None:
260
+ return {}
261
+ descriptors.append((lsid, bool(record[26] & 1)))
262
+ cursor += 28
263
+ budget.charge()
264
+ cursor = size
265
+ result: dict[int, tuple[LevelDefinition, ...]] = {}
266
+ for lsid, simple in descriptors:
267
+ count_levels = 1 if simple else LEVELS
268
+ levels: list[LevelDefinition] = []
269
+ for _ in range(count_levels):
270
+ parsed = _parse_level(data, cursor)
271
+ if parsed is None:
272
+ return result
273
+ level, cursor = parsed
274
+ levels.append(level)
275
+ budget.charge()
276
+ if simple:
277
+ levels = [levels[0]] * LEVELS
278
+ while len(levels) < LEVELS:
279
+ levels.append(LevelDefinition())
280
+ result[lsid] = tuple(levels)
281
+ return result
282
+
283
+
284
+ def parse_list_tables(
285
+ table_stream: bytes,
286
+ *,
287
+ list_offset: int,
288
+ list_size: int,
289
+ override_offset: int,
290
+ override_size: int,
291
+ budget: DocBudget,
292
+ ) -> ListTables:
293
+ """解析 PlfLst/PlfLfo 并建立一基 ilfo 查找表。"""
294
+
295
+ by_lsid = _parse_list_definitions(
296
+ table_stream,
297
+ offset=list_offset,
298
+ size=list_size,
299
+ budget=budget,
300
+ )
301
+ data = bounded_slice(table_stream, override_offset, override_size)
302
+ if data is None or len(data) < 4:
303
+ return ListTables()
304
+ count = get_u32(data, 0)
305
+ if count is None or 4 + count * 16 > len(data):
306
+ return ListTables()
307
+ cursor = 4
308
+ descriptors: list[tuple[int, int]] = []
309
+ for _ in range(count):
310
+ record = bounded_slice(data, cursor, 16)
311
+ if record is None:
312
+ return ListTables()
313
+ lsid = get_u32(record, 0)
314
+ if lsid is None:
315
+ return ListTables()
316
+ descriptors.append((lsid, record[12]))
317
+ cursor += 16
318
+ budget.charge()
319
+ definitions: dict[int, ListDefinition] = {}
320
+ for index, (lsid, override_count) in enumerate(descriptors, start=1):
321
+ levels = list(by_lsid.get(lsid, tuple(LevelDefinition() for _ in range(LEVELS))))
322
+ overrides: list[int | None] = [None] * LEVELS
323
+ for _ in range(override_count):
324
+ record = bounded_slice(data, cursor, 8)
325
+ if record is None:
326
+ break
327
+ start = get_u32(record, 0) or 0
328
+ bits = record[4]
329
+ level_index = bits & 0x0F
330
+ has_start = bool(bits & 0x10)
331
+ has_format = bool(bits & 0x20)
332
+ cursor += 8
333
+ budget.charge()
334
+ if has_format:
335
+ parsed = _parse_level(data, cursor)
336
+ if parsed is None:
337
+ break
338
+ level_def, cursor = parsed
339
+ if level_index < LEVELS:
340
+ levels[level_index] = level_def
341
+ if has_start:
342
+ overrides[level_index] = level_def.start
343
+ elif has_start and level_index < LEVELS:
344
+ levels[level_index] = LevelDefinition(
345
+ marker=levels[level_index].marker,
346
+ start=int(start),
347
+ restart=levels[level_index].restart,
348
+ tokens=levels[level_index].tokens,
349
+ )
350
+ overrides[level_index] = int(start)
351
+ definitions[index] = ListDefinition(
352
+ lsid=lsid,
353
+ levels=tuple(levels),
354
+ overrides=tuple(overrides),
355
+ )
356
+ return ListTables(definitions)
@@ -0,0 +1,164 @@
1
+ """Word 二进制解析器与 Converter 之间的内部语义模型。"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from typing import TypeAlias
7
+
8
+
9
+ @dataclass(frozen=True, slots=True)
10
+ class DocCharStyle:
11
+ """一个连续 DOC 文字 run 的可见字符样式。"""
12
+
13
+ bold: bool = False
14
+ italic: bool = False
15
+ underline: bool = False
16
+ emphasis: bool = False
17
+ strike: bool = False
18
+ superscript: bool = False
19
+ subscript: bool = False
20
+ hidden: bool = False
21
+ deleted: bool = False
22
+
23
+
24
+ @dataclass(frozen=True, slots=True)
25
+ class DocTextRun:
26
+ """一段样式及超链接目标相同的可见文字。"""
27
+
28
+ text: str
29
+ style: DocCharStyle = DocCharStyle()
30
+ hyperlink: str | None = None
31
+ formula: bool = False
32
+
33
+
34
+ @dataclass(frozen=True, slots=True)
35
+ class DocListInfo:
36
+ """段落从 PlfLst/PlfLfo 解析出的列表信息。"""
37
+
38
+ identity: int
39
+ level: int
40
+ ordered: bool
41
+ start: int = 1
42
+ label: str | None = None
43
+
44
+
45
+ @dataclass(frozen=True, slots=True)
46
+ class DocTableCellFormat:
47
+ """一格 Word 表格在行定义中的合并属性。"""
48
+
49
+ right: int
50
+ horizontal_first: bool = False
51
+ horizontal_continue: bool = False
52
+ vertical_first: bool = False
53
+ vertical_continue: bool = False
54
+
55
+
56
+ @dataclass(frozen=True, slots=True)
57
+ class DocTableFormat:
58
+ """一个 TTP 段落解析出的表格行定义。"""
59
+
60
+ boundaries: tuple[int, ...] = ()
61
+ cells: tuple[DocTableCellFormat, ...] = ()
62
+ header: bool = False
63
+
64
+
65
+ @dataclass(slots=True)
66
+ class DocParagraph:
67
+ """完成样式、字段和段落属性解析的段落。"""
68
+
69
+ cp_start: int
70
+ cp_end: int
71
+ runs: list[DocTextRun] = field(default_factory=list)
72
+ images: list[DocVisualPayload] = field(default_factory=list)
73
+ style_name: str = ""
74
+ heading_level: int | None = None
75
+ is_title: bool = False
76
+ is_toc: bool = False
77
+ toc_level: int | None = None
78
+ is_caption: bool = False
79
+ is_code: bool = False
80
+ anchor: str | None = None
81
+ list_info: DocListInfo | None = None
82
+ in_table: bool = False
83
+ table_depth: int = 0
84
+ cell_mark: bool = False
85
+ row_mark: bool = False
86
+ table_format: DocTableFormat | None = None
87
+
88
+
89
+ @dataclass(frozen=True, slots=True)
90
+ class DocImagePayload:
91
+ """一张从 PICF/OfficeArt 恢复的图片原始载荷。"""
92
+
93
+ data: bytes
94
+ extension: str
95
+ content_type: str
96
+ equation_latex: str | None = None
97
+ render_size_emu: tuple[int, int] | None = None
98
+
99
+
100
+ @dataclass(frozen=True, slots=True)
101
+ class DocChartPayload:
102
+ """一个可编辑 OLE chart 的 HTML 数据和可选预览图。"""
103
+
104
+ content: str
105
+ preview: DocImagePayload | None = None
106
+
107
+
108
+ DocVisualPayload: TypeAlias = DocImagePayload | DocChartPayload
109
+
110
+
111
+ @dataclass(slots=True)
112
+ class DocImage:
113
+ """按主 story CP 定位的内联或浮动图片。"""
114
+
115
+ cp: int
116
+ payload: DocImagePayload
117
+
118
+
119
+ @dataclass(slots=True)
120
+ class DocTableCell:
121
+ """Word 表格单元格及其嵌套内容。"""
122
+
123
+ blocks: list[DocElement] = field(default_factory=list)
124
+ row_span: int = 1
125
+ col_span: int = 1
126
+
127
+
128
+ @dataclass(slots=True)
129
+ class DocTableRow:
130
+ """Word 表格的一行。"""
131
+
132
+ cells: list[DocTableCell] = field(default_factory=list)
133
+ header: bool = False
134
+
135
+
136
+ @dataclass(slots=True)
137
+ class DocTable:
138
+ """按 CP 顺序组装出的普通或嵌套表格。"""
139
+
140
+ cp_start: int
141
+ cp_end: int
142
+ rows: list[DocTableRow] = field(default_factory=list)
143
+
144
+
145
+ DocElement: TypeAlias = DocParagraph | DocImage | DocTable
146
+
147
+
148
+ @dataclass(slots=True)
149
+ class DocSection:
150
+ """一个 Word section 及其页面辅助文本。"""
151
+
152
+ cp_start: int
153
+ cp_end: int
154
+ elements: list[DocElement] = field(default_factory=list)
155
+ headers: list[DocParagraph] = field(default_factory=list)
156
+ footers: list[DocParagraph] = field(default_factory=list)
157
+ footnotes: list[DocParagraph] = field(default_factory=list)
158
+
159
+
160
+ @dataclass(slots=True)
161
+ class DocDocument:
162
+ """一份可投影为 model-list 的 DOC 文档。"""
163
+
164
+ sections: list[DocSection] = field(default_factory=list)