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,113 @@
1
+ """PPTX 固定规则和形状变换数据契约。"""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any, Final, Optional
5
+ from pptx.enum.shapes import PP_PLACEHOLDER
6
+ from docvortex.foundation.type_identity import preserve_type_module
7
+
8
+
9
+ IGNORED_NOTES_PLACEHOLDER_TYPES: Final = {
10
+ PP_PLACEHOLDER.SLIDE_IMAGE,
11
+ PP_PLACEHOLDER.SLIDE_NUMBER,
12
+ PP_PLACEHOLDER.DATE,
13
+ PP_PLACEHOLDER.FOOTER,
14
+ }
15
+
16
+
17
+ MIN_PICTURE_DIMENSION_RATIO: Final = 0.1
18
+
19
+
20
+ MIN_PICTURE_AREA_RATIO: Final = 0.01
21
+
22
+
23
+ BACKGROUND_PICTURE_TEXT_COVERAGE_RATIO: Final = 0.1
24
+
25
+
26
+ PPTX_XYCUT_BETA: Final = 2.0
27
+
28
+
29
+ PPTX_XYCUT_DENSITY_THRESHOLD: Final = 0.9
30
+
31
+
32
+ DRAWINGML_NS: Final = "http://schemas.openxmlformats.org/drawingml/2006/main"
33
+
34
+
35
+ RELATIONSHIP_NS: Final = "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
36
+
37
+
38
+ SVG_BLIP_NS: Final = "http://schemas.microsoft.com/office/drawing/2016/SVG/main"
39
+
40
+
41
+ A14_DRAWING_NS: Final = "http://schemas.microsoft.com/office/drawing/2010/main"
42
+
43
+
44
+ OMML_NS: Final = "http://schemas.openxmlformats.org/officeDocument/2006/math"
45
+
46
+
47
+ _EFFECTIVE_FONT_SIZE_KEY: Final = "_effective_font_size_pt"
48
+
49
+
50
+ _EFFECTIVE_ALL_BOLD_KEY: Final = "_effective_all_bold"
51
+
52
+
53
+ _PPTX_TITLE_CANDIDATE_KEY: Final = "_pptx_title_candidate"
54
+
55
+
56
+ _PPTX_TITLE_ROLE_KEY: Final = "_pptx_title_role"
57
+
58
+
59
+ _PPTX_TITLE_ROLE_CENTER: Final = "center_title"
60
+
61
+
62
+ _PPTX_TITLE_ROLE_TITLE: Final = "title"
63
+
64
+
65
+ _PPTX_TITLE_ROLE_SUBTITLE: Final = "subtitle"
66
+
67
+
68
+ _PPTX_TITLE_PLACEHOLDER_ROLES: Final = {
69
+ PP_PLACEHOLDER.CENTER_TITLE: _PPTX_TITLE_ROLE_CENTER,
70
+ PP_PLACEHOLDER.TITLE: _PPTX_TITLE_ROLE_TITLE,
71
+ PP_PLACEHOLDER.SUBTITLE: _PPTX_TITLE_ROLE_SUBTITLE,
72
+ }
73
+
74
+
75
+ @dataclass(frozen=True)
76
+ class _SlideTransform:
77
+ scale_x: float = 1.0
78
+ scale_y: float = 1.0
79
+ translate_x: float = 0.0
80
+ translate_y: float = 0.0
81
+
82
+ def apply_bbox(
83
+ self,
84
+ bbox: Optional[tuple[float, float, float, float]],
85
+ ) -> Optional[tuple[float, float, float, float]]:
86
+ """按既有形状缩放和平移规则转换几何,保持嵌套变换顺序。"""
87
+ if bbox is None:
88
+ return None
89
+
90
+ left = self.scale_x * bbox[0] + self.translate_x
91
+ top = self.scale_y * bbox[1] + self.translate_y
92
+ right = self.scale_x * bbox[2] + self.translate_x
93
+ bottom = self.scale_y * bbox[3] + self.translate_y
94
+ return (left, top, right, bottom)
95
+
96
+ def compose(self, inner: "_SlideTransform") -> "_SlideTransform":
97
+ """按既有形状缩放和平移规则转换几何,保持嵌套变换顺序。"""
98
+ return _SlideTransform(
99
+ scale_x=self.scale_x * inner.scale_x,
100
+ scale_y=self.scale_y * inner.scale_y,
101
+ translate_x=self.scale_x * inner.translate_x + self.translate_x,
102
+ translate_y=self.scale_y * inner.translate_y + self.translate_y,
103
+ )
104
+
105
+
106
+ @dataclass(frozen=True)
107
+ class _FlattenedShape:
108
+ shape: Any
109
+ bbox: Optional[tuple[float, float, float, float]]
110
+
111
+
112
+ preserve_type_module(_SlideTransform, "docvortex.analyzers.native.office.pptx.pptx_converter")
113
+ preserve_type_module(_FlattenedShape, "docvortex.analyzers.native.office.pptx.pptx_converter")
@@ -0,0 +1,558 @@
1
+ """PPTX 列表标记与编号,复用当前转换器的单文档状态。"""
2
+
3
+ from typing import Optional
4
+ from lxml import etree
5
+ from pptx.enum.shapes import PP_PLACEHOLDER
6
+ from .....schema import BlockType
7
+
8
+
9
+ class _PptxLists:
10
+ """集中维护列表标记与编号,不改变文档生命周期和公开入口。"""
11
+
12
+ def _get_paragraph_list_info(self, shape, paragraph) -> dict:
13
+ """基于段落->文本框->布局->母版继承链解析段落列表属性。"""
14
+ marker_info = self._get_effective_list_marker(shape, paragraph)
15
+ p = paragraph._element
16
+ level = marker_info.get("level", self._get_paragraph_level(p))
17
+ kind = marker_info.get("kind")
18
+
19
+ if marker_info.get("is_list") is False:
20
+ return {
21
+ "is_list": False,
22
+ "attribute": "unordered",
23
+ "level": level,
24
+ "kind": kind,
25
+ "start": None,
26
+ "start_is_explicit_restart": False,
27
+ }
28
+
29
+ if kind == "buAutoNum":
30
+ return {
31
+ "is_list": True,
32
+ "attribute": "ordered",
33
+ "level": level,
34
+ "kind": kind,
35
+ "start": marker_info.get("start"),
36
+ "start_is_explicit_restart": marker_info.get(
37
+ "start_is_explicit_restart",
38
+ False,
39
+ ),
40
+ }
41
+
42
+ if kind in ("buChar", "buBlip"):
43
+ return {
44
+ "is_list": True,
45
+ "attribute": "unordered",
46
+ "level": level,
47
+ "kind": kind,
48
+ "start": None,
49
+ "start_is_explicit_restart": False,
50
+ }
51
+
52
+ if marker_info.get("is_list") is True:
53
+ return {
54
+ "is_list": True,
55
+ "attribute": "unordered",
56
+ "level": level,
57
+ "kind": kind,
58
+ "start": None,
59
+ "start_is_explicit_restart": False,
60
+ }
61
+
62
+ # 兜底:段落级标记 + 缩进层级判断
63
+ bu_auto_num = p.find(".//a:buAutoNum", namespaces={"a": self.namespaces["a"]})
64
+ if bu_auto_num is not None:
65
+ start = self._parse_positive_int(bu_auto_num.get("startAt"))
66
+ return {
67
+ "is_list": True,
68
+ "attribute": "ordered",
69
+ "level": paragraph.level,
70
+ "kind": "buAutoNum",
71
+ "start": start,
72
+ "start_is_explicit_restart": start is not None,
73
+ }
74
+
75
+ if p.find(".//a:buChar", namespaces={"a": self.namespaces["a"]}) is not None:
76
+ return {
77
+ "is_list": True,
78
+ "attribute": "unordered",
79
+ "level": paragraph.level,
80
+ "kind": "buChar",
81
+ "start": None,
82
+ "start_is_explicit_restart": False,
83
+ }
84
+
85
+ if paragraph.level > 0:
86
+ return {
87
+ "is_list": True,
88
+ "attribute": "unordered",
89
+ "level": paragraph.level,
90
+ "kind": None,
91
+ "start": None,
92
+ "start_is_explicit_restart": False,
93
+ }
94
+
95
+ return {
96
+ "is_list": False,
97
+ "attribute": "unordered",
98
+ "level": 0,
99
+ "kind": None,
100
+ "start": None,
101
+ "start_is_explicit_restart": False,
102
+ }
103
+
104
+ def _ensure_list_level(
105
+ self,
106
+ list_stack: list,
107
+ level: int,
108
+ attribute: str,
109
+ start: Optional[int] = None,
110
+ start_is_explicit_restart: bool = False,
111
+ ):
112
+ """将列表栈调整到目标层级,并在必要时创建同级/子级列表块。"""
113
+ while len(list_stack) > level + 1:
114
+ list_stack.pop()
115
+
116
+ if len(list_stack) == level + 1 and list_stack[level].get("attribute") != attribute:
117
+ list_stack.pop()
118
+
119
+ if self._should_restart_ordered_list(
120
+ list_stack,
121
+ level,
122
+ attribute,
123
+ start,
124
+ start_is_explicit_restart,
125
+ ):
126
+ list_stack.pop()
127
+
128
+ while len(list_stack) < level + 1:
129
+ ilevel = len(list_stack)
130
+ new_list_block = {
131
+ "type": BlockType.LIST,
132
+ "attribute": attribute,
133
+ "ilevel": ilevel,
134
+ "content": [],
135
+ }
136
+ if attribute == "ordered" and start is not None and ilevel == level:
137
+ new_list_block["start"] = start
138
+
139
+ if list_stack:
140
+ list_stack[-1]["content"].append(new_list_block)
141
+ else:
142
+ self.cur_page.append(new_list_block)
143
+
144
+ list_stack.append(new_list_block)
145
+
146
+ @staticmethod
147
+ def _get_ordered_list_next_number(list_block: dict) -> int:
148
+ """计算当前有序列表继续追加同级文本项时应使用的下一个编号。"""
149
+ try:
150
+ start = int(list_block.get("start", 1))
151
+ except (TypeError, ValueError):
152
+ start = 1
153
+ direct_item_count = sum(1 for item in list_block.get("content", []) if item.get("type") != BlockType.LIST)
154
+ return start + direct_item_count
155
+
156
+ def _should_restart_ordered_list(
157
+ self,
158
+ list_stack: list,
159
+ level: int,
160
+ attribute: str,
161
+ start: Optional[int],
162
+ start_is_explicit_restart: bool,
163
+ ) -> bool:
164
+ """判断 startAt 是否表示当前同级有序列表需要重新开始。"""
165
+ if not start_is_explicit_restart:
166
+ return False
167
+ if attribute != "ordered" or start is None:
168
+ return False
169
+ if len(list_stack) != level + 1:
170
+ return False
171
+ current_list = list_stack[level]
172
+ if current_list.get("attribute") != "ordered":
173
+ return False
174
+ if not current_list.get("content"):
175
+ return False
176
+ return start != self._get_ordered_list_next_number(current_list)
177
+
178
+ def _append_list_item(
179
+ self,
180
+ list_stack: list,
181
+ level: int,
182
+ attribute: str,
183
+ content: str,
184
+ start: Optional[int] = None,
185
+ start_is_explicit_restart: bool = False,
186
+ ):
187
+ """向目标层级列表追加文本项。"""
188
+ self._ensure_list_level(
189
+ list_stack,
190
+ level,
191
+ attribute,
192
+ start,
193
+ start_is_explicit_restart,
194
+ )
195
+ list_stack[-1]["content"].append(
196
+ {
197
+ "type": BlockType.TEXT,
198
+ "content": content,
199
+ }
200
+ )
201
+
202
+ @staticmethod
203
+ def _normalize_contiguous_list_level(
204
+ raw_level: int,
205
+ base_level: int,
206
+ ) -> int:
207
+ """
208
+ 将连续列表段的首个可见层级归一化为0级,避免缺失父级时输出代码块缩进。
209
+ """
210
+ return max(0, raw_level - base_level)
211
+
212
+ def _is_list_item(self, paragraph) -> tuple[bool, str]:
213
+ """
214
+ 判断段落是否应被视为列表项。
215
+ 该方法首先尝试通过拥有该段落的形状来解析列表样式信息。
216
+ 如果无法做到,则回退到基于段落属性和级别的更简单检查。
217
+ Args:
218
+ paragraph: 需要检查的'python-pptx'段落对象。
219
+
220
+ Returns:
221
+ 返回一个2元组(`is_list`, `bullet_type`),其中:
222
+ `is_list` - 若段落被视为列表项,为True,否则为False;
223
+ `bullet_type` - 为以下之一:'Bullet'(项目符号)、'Numbered'(编号)或'None',
224
+ 描述列表标记类型。
225
+ """
226
+ # 尝试从段落获取形状(包含该段落的对象),如果可能的话
227
+ shape = None
228
+ try:
229
+ # 这个路径适用于python-pptx段落对象
230
+ # 首先获取文本框架(段落的父对象)
231
+ text_frame = paragraph._parent
232
+ # 然后获取形状(文本框架的父对象)
233
+ shape = text_frame._parent
234
+ except AttributeError:
235
+ pass
236
+
237
+ if shape is not None:
238
+ list_info = self._get_paragraph_list_info(shape, paragraph)
239
+ if not list_info["is_list"]:
240
+ return (False, "None")
241
+
242
+ if list_info["attribute"] == "ordered":
243
+ return (True, "Numbered")
244
+ return (True, "Bullet")
245
+
246
+ # 如果无法获取形状,使用更简单的检查方式
247
+ p = paragraph._element
248
+ if p.find(".//a:buChar", namespaces={"a": self.namespaces["a"]}) is not None:
249
+ return (True, "Bullet")
250
+ elif p.find(".//a:buAutoNum", namespaces={"a": self.namespaces["a"]}) is not None:
251
+ return (True, "Numbered")
252
+ elif paragraph.level > 0:
253
+ # 很可能是子列表项(缩进表示嵌套)
254
+ return (True, "None")
255
+ else:
256
+ return (False, "None")
257
+
258
+ def _get_effective_list_marker(self, shape, paragraph) -> dict:
259
+ """
260
+ 返回描述段落的有效列表标记的字典。
261
+ 列表标记信息可以来自多个来源:直接段落属性、形状级别的列表样式、
262
+ 布局占位符或主幻灯片文本样式。此辅助方法解析所有这些层,并返回
263
+ 有效标记的统一视图。
264
+
265
+ Args:
266
+ shape: 包含段落的形状对象。
267
+ paragraph: 需要检查的'python-pptx'段落对象。
268
+
269
+ Returns:
270
+ 返回列表标记信息的字典,其中:
271
+ `is_list` - True/False/None,表示这是否是列表项;
272
+ `kind` - 为以下之一:`buChar`、`buAutoNum`、`buBlip`、`buNone`或None,描述标记类型;
273
+ `detail` - 项目符号字符或编号类型字符串,或如果不适用则为None;
274
+ `start_is_explicit_restart` - True 表示 start 来自段落级显式 startAt;
275
+ `level` - 段落级别,范围在(0, 8)内。
276
+ """
277
+ p = paragraph._element
278
+ lvl = self._get_paragraph_level(p)
279
+
280
+ # 1) 直接段落属性
281
+ pPr = p.find("a:pPr", namespaces=self.namespaces)
282
+ is_list, kind, detail, start = self._parse_bullet_from_paragraph_properties(pPr)
283
+ if is_list is not None:
284
+ return {
285
+ "is_list": is_list,
286
+ "kind": kind,
287
+ "detail": detail,
288
+ "level": lvl,
289
+ "start": start,
290
+ # 只有段落自身声明的 startAt 才表示一次显式重启。
291
+ "start_is_explicit_restart": kind == "buAutoNum" and start is not None,
292
+ }
293
+
294
+ # 2) 形状级别的列表样式(txBody/a:lstStyle)
295
+ txBody = shape._element.find(".//p:txBody", namespaces=self.namespaces)
296
+ is_list, kind, detail, start = self._parse_bullet_from_text_body_list_style(txBody, lvl)
297
+ if is_list is not None:
298
+ return {
299
+ "is_list": is_list,
300
+ "kind": kind,
301
+ "detail": detail,
302
+ "level": lvl,
303
+ "start": start,
304
+ "start_is_explicit_restart": False,
305
+ }
306
+
307
+ # 3) 布局占位符列表样式(如果这是一个占位符)
308
+ layout_result = None
309
+ if shape.is_placeholder:
310
+ layout_ph = self._resolve_layout_placeholder(shape)
311
+
312
+ if layout_ph is not None:
313
+ layout_tx = layout_ph._element.find(".//p:txBody", namespaces=self.namespaces)
314
+ (
315
+ is_list,
316
+ kind,
317
+ detail,
318
+ start,
319
+ ) = self._parse_bullet_from_text_body_list_style(layout_tx, lvl)
320
+
321
+ # 仅在is_list明确为True/False时使用布局结果
322
+ if is_list is not None:
323
+ layout_result = {
324
+ "is_list": is_list,
325
+ "kind": kind,
326
+ "detail": detail,
327
+ "level": lvl,
328
+ "start": start,
329
+ "start_is_explicit_restart": False,
330
+ }
331
+
332
+ # 4) 解析主文本样式
333
+ ph_type = shape.placeholder_format.type
334
+ master = shape.part.slide.slide_layout.slide_master
335
+ (
336
+ is_list,
337
+ kind,
338
+ detail,
339
+ start,
340
+ ) = self._parse_bullet_from_master_text_styles(master, ph_type, lvl)
341
+
342
+ # 检查主样式是否有标记信息
343
+ if kind in ("buChar", "buAutoNum", "buBlip"):
344
+ return {
345
+ "is_list": True,
346
+ "kind": kind,
347
+ "detail": detail,
348
+ "level": lvl,
349
+ "start": start,
350
+ "start_is_explicit_restart": False,
351
+ }
352
+ elif is_list is not None:
353
+ return {
354
+ "is_list": is_list,
355
+ "kind": kind,
356
+ "detail": detail,
357
+ "level": lvl,
358
+ "start": start,
359
+ "start_is_explicit_restart": False,
360
+ }
361
+
362
+ # If layout has explicit is_list value but master didn't override it, use layout
363
+ # 如果布局有显式的is_list值但主样式没有覆盖它,则使用布局结果
364
+ if layout_result is not None:
365
+ return layout_result
366
+
367
+ return {
368
+ "is_list": None,
369
+ "kind": None,
370
+ "detail": None,
371
+ "level": lvl,
372
+ "start": None,
373
+ "start_is_explicit_restart": False,
374
+ }
375
+
376
+ def _get_paragraph_level(self, paragraph) -> int:
377
+ """
378
+ 返回段落XML元素的缩进级别。
379
+ 段落可以有不同的缩进级别(0-8)。级别存储在段落属性XML元素的'lvl'属性中。
380
+
381
+ Args:
382
+ paragraph: 需要提取级别的段落XML元素。
383
+
384
+ Returns:
385
+ 返回范围在(0, 8)内的段落级别。当找不到'a:pPr'元素、没有'lvl'属性
386
+ 或'lvl'属性值无效时,返回0。
387
+ """
388
+ pPr = paragraph.find("a:pPr", namespaces=self.namespaces)
389
+ if pPr is not None and "lvl" in pPr.attrib:
390
+ try:
391
+ return int(pPr.get("lvl"))
392
+ except ValueError:
393
+ pass
394
+ return 0
395
+
396
+ @staticmethod
397
+ def _parse_positive_int(value: Optional[str]) -> Optional[int]:
398
+ """解析正整数属性,非法或缺失时返回 None。"""
399
+ if value is None:
400
+ return None
401
+ try:
402
+ parsed = int(value)
403
+ except (TypeError, ValueError):
404
+ return None
405
+ return parsed if parsed > 0 else None
406
+
407
+ def _parse_bullet_from_paragraph_properties(
408
+ self, pPr
409
+ ) -> tuple[Optional[bool], Optional[str], Optional[str], Optional[int]]:
410
+ """
411
+ 从段落属性节点解析项目符号或编号信息。
412
+ 检查'a:pPr'或'a:lvlXpPr'元素,并提取关于项目符号字符、自动编号、
413
+ 图片项目符号或显式'buNone'标记的信息。
414
+
415
+ Args:
416
+ pPr: 段落属性XML元素('a:pPr'或'a:lvlXpPr')。
417
+
418
+ Returns:
419
+ 返回一个4元组(`is_list`, `kind`, `detail`, `start`),其中:
420
+ `is_list` - 为True/False/None,表示这是否是列表项;
421
+ `kind` - 为以下之一:`buChar`(项目符号字符)、`buAutoNum`(自动编号)、
422
+ `buBlip`(图片项目符号)、`buNone`(无标记)或None,描述标记类型;
423
+ `detail` - 项目符号字符、编号类型字符串,或如果不适用则为None。
424
+ `start` - 自动编号起始值;未声明时为None。
425
+ """
426
+ if pPr is None:
427
+ return (None, None, None, None)
428
+
429
+ # 显式指定无项目符号
430
+ if pPr.find("a:buNone", namespaces=self.namespaces) is not None:
431
+ return (False, "buNone", None, None)
432
+
433
+ # 项目符号字符
434
+ buChar = pPr.find("a:buChar", namespaces=self.namespaces)
435
+ if buChar is not None:
436
+ return (True, "buChar", buChar.get("char"), None)
437
+
438
+ # 自动编号
439
+ buAuto = pPr.find("a:buAutoNum", namespaces=self.namespaces)
440
+ if buAuto is not None:
441
+ return (
442
+ True,
443
+ "buAutoNum",
444
+ buAuto.get("type"),
445
+ self._parse_positive_int(buAuto.get("startAt")),
446
+ )
447
+
448
+ # 图片项目符号
449
+ buBlip = pPr.find("a:buBlip", namespaces=self.namespaces)
450
+ if buBlip is not None:
451
+ return (True, "buBlip", "image", None)
452
+
453
+ return (None, None, None, None)
454
+
455
+ def _parse_bullet_from_text_body_list_style(
456
+ self, txBody, lvl: int
457
+ ) -> tuple[Optional[bool], Optional[str], Optional[str], Optional[int]]:
458
+ """
459
+ 从文本体的列表样式中解析项目符号或编号信息。
460
+ 在'txBody'下搜索'a:lstStyle/a:lvl{lvl+1}pPr',并使用级别特定的段落属性
461
+ 推断项目符号或编号信息。
462
+
463
+ Args:
464
+ txBody: 文本体XML元素'p:txBody'。
465
+ lvl: 段落级别,范围在(0, 8)内。
466
+ Returns:
467
+ 返回一个4元组(`is_list`, `kind`, `detail`, `start`),其中:
468
+ `is_list` - 为True/False/None,表示这是否是列表项;
469
+ `kind` - 为以下之一:`buChar`、`buAutoNum`、`buBlip`、`buNone`或None;
470
+ `detail` - 项目符号字符、编号类型字符串,或如果不适用则为None。
471
+ `start` - 自动编号起始值;未声明时为None。
472
+ """
473
+ if txBody is None:
474
+ return (None, None, None, None)
475
+ lstStyle = txBody.find("a:lstStyle", namespaces=self.namespaces)
476
+ lvl_pPr = self._find_level_properties_in_list_style(lstStyle, lvl)
477
+ return self._parse_bullet_from_paragraph_properties(lvl_pPr)
478
+
479
+ def _parse_bullet_from_master_text_styles(
480
+ self, slide_master, placeholder_type, lvl: int
481
+ ) -> tuple[Optional[bool], Optional[str], Optional[str], Optional[int]]:
482
+ """
483
+ 从主幻灯片的文本样式中解析项目符号或编号信息。
484
+ 在主幻灯片的'p:txStyles'中查找相应的样式bucket('titleStyle'、'bodyStyle'或
485
+ 'otherStyle'),并为给定的级别提取项目符号或编号信息。
486
+
487
+ Args:
488
+ slide_master: 与当前幻灯片关联的主幻灯片对象。
489
+ placeholder_type: 来自'PP_PLACEHOLDER'的占位符类型枚举。
490
+ lvl: 段落级别,范围在(0, 8)内。
491
+
492
+ Returns:
493
+ 返回一个4元组(`is_list`, `kind`, `detail`, `start`),其中:
494
+ `is_list` - 为True/False/None,表示这是否是列表项;
495
+ `kind` - 为以下之一:`buChar`、`buAutoNum`、`buBlip`、`buNone`或None;
496
+ `detail` - 项目符号字符、编号类型字符串,或如果不适用则为None。
497
+ `start` - 自动编号起始值;未声明时为None。
498
+ """
499
+ style = self._get_master_text_style_node(slide_master, placeholder_type)
500
+ if style is None:
501
+ return (None, None, None, None)
502
+
503
+ lvl_pPr = style.find(f".//a:lvl{lvl + 1}pPr", namespaces=self.namespaces)
504
+ return self._parse_bullet_from_paragraph_properties(lvl_pPr)
505
+
506
+ def _find_level_properties_in_list_style(self, lstStyle, lvl: int):
507
+ """Find the level-specific paragraph properties node from a list style.
508
+ 从列表样式中查找指定级别的段落属性节点。
509
+
510
+ This looks for an `a:lvl{lvl+1}pPr` node inside an `a:lstStyle` element, where
511
+ 在'a:lstStyle'元素内查找'a:lvl{lvl+1}pPr'节点,其中'a:lvl1pPr'对应级别0,
512
+ `a:lvl1pPr` corresponds to level 0, `a:lvl2pPr` to level 1, and so on.
513
+ 'a:lvl2pPr'对应级别1,依此类推。
514
+
515
+ Args:
516
+ lstStyle: List style XML element `a:lstStyle`.
517
+ lstStyle: 列表样式XML元素'a:lstStyle'。
518
+ lvl: Paragraph level in the range (0, 8).
519
+ lvl: 段落级别,范围在(0, 8)内。
520
+
521
+ Returns:
522
+ Matching `a:lvl{lvl+1}pPr` XML element, or None if no matching element is
523
+ 匹配的'a:lvl{lvl+1}pPr'XML元素,如果未找到匹配元素则返回None。
524
+ found.
525
+ """
526
+ if lstStyle is None:
527
+ return None
528
+ tag = f"a:lvl{lvl + 1}pPr"
529
+ return lstStyle.find(tag, namespaces=self.namespaces)
530
+
531
+ def _get_master_text_style_node(self, slide_master, placeholder_type) -> Optional[etree._Element]:
532
+ """
533
+ 获取占位符的相应主文本样式节点。
534
+ 大多数内容占位符(BODY/OBJECT)使用'p:bodyStyle',而标题使用'p:titleStyle'。
535
+ 所有其他占位符默认使用'p:otherStyle'。
536
+
537
+ Args:
538
+ slide_master: 与当前幻灯片关联的主幻灯片对象。
539
+ placeholder_type: 来自'PP_PLACEHOLDER'的占位符类型枚举。
540
+
541
+ Returns:
542
+ 从主幻灯片的'p:txStyles'中匹配的样式节点('p:bodyStyle'、'p:titleStyle'或'p:otherStyle'),或当未定义样式时返回None。
543
+ """
544
+ txStyles = slide_master._element.find(".//p:txStyles", namespaces=self.namespaces)
545
+ if txStyles is None:
546
+ return None
547
+
548
+ if placeholder_type in (PP_PLACEHOLDER.BODY, PP_PLACEHOLDER.OBJECT):
549
+ return txStyles.find("p:bodyStyle", namespaces=self.namespaces)
550
+
551
+ if placeholder_type in (
552
+ PP_PLACEHOLDER.TITLE,
553
+ PP_PLACEHOLDER.CENTER_TITLE,
554
+ PP_PLACEHOLDER.SUBTITLE,
555
+ ):
556
+ return txStyles.find("p:titleStyle", namespaces=self.namespaces)
557
+
558
+ return txStyles.find("p:otherStyle", namespaces=self.namespaces)
@@ -0,0 +1,20 @@
1
+ from typing import Any, BinaryIO
2
+
3
+ from ... import PptxModel
4
+
5
+
6
+ def convert_path(file_path: str) -> list[list[dict[str, Any]]]:
7
+ """从 PPTX 文件路径调用统一模型入口。"""
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
+ """兼容旧二进制转换函数,并转发给 PptxModel。"""
15
+
16
+ return PptxModel().predict(file_binary)
17
+
18
+
19
+ if __name__ == "__main__":
20
+ print(convert_path("powerpoint_sample.pptx"))