docvortex 0.4.10__tar.gz → 0.4.12__tar.gz
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.
- {docvortex-0.4.10/src/docvortex.egg-info → docvortex-0.4.12}/PKG-INFO +1 -1
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/epub/xhtml.py +11 -2
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/html/constants.py +0 -2
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/html/resources.py +17 -43
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/image.py +4 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/text.py +31 -2
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/resources.py +22 -20
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/mathml.py +23 -2
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/contracts.py +1 -3
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/export/files.py +12 -3
- docvortex-0.4.12/src/docvortex/foundation/_svg_raster.py +158 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/version.py +1 -1
- {docvortex-0.4.10 → docvortex-0.4.12/src/docvortex.egg-info}/PKG-INFO +1 -1
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex.egg-info/SOURCES.txt +2 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_odf_test_utils.py +6 -1
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_epub.py +49 -1
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_html.py +45 -61
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_odf.py +62 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_office_title_types.py +42 -10
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_shared_helpers.py +47 -0
- docvortex-0.4.12/tests/unittest/test_svg_raster.py +79 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/LICENSE.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/MANIFEST.in +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/README.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/README.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/demo.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/office_docs/README.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/office_docs/docx_01.doc +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/office_docs/docx_01.docx +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/office_docs/pptx_01.ppt +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/office_docs/pptx_01.pptx +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/office_docs/rtf_01.rtf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/office_docs/xlsx_01.xls +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/office_docs/xlsx_01.xlsx +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/2407.00079v4_origi-10.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/IEBM_A_2667169_O-5.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/caibao1.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/demo1.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/demo2.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/demo3.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/demo4.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/demo6.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/mixed_elements_pages_03_06.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/mixed_elements_pages_07_10.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/mixed_elements_pages_11_15.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/mixed_elements_pages_39_40.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs/small_ocr.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs//344/270/255/346/226/207/350/256/272/346/226/207.pdf" +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs//344/270/255/346/226/207/350/256/272/346/226/2072.pdf" +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs//344/270/255/346/226/207/350/256/272/346/226/2073.pdf" +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/demo/pdfs//344/270/255/346/226/207/350/256/272/346/226/2074.pdf" +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/HTML_PROTOCOL.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/JSON_PROTOCOL.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/METADATA.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/PDF_FONTS.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/RENDER_OWNERSHIP.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/USAGE.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/flash-manual-annotations-2026-09-15.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/flash-round2-annotations-2026-09-15.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/flash-rule-generalization-2026-09-15.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/flash-spatial-layout-followup-2026-09-16.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/flash-spatial-layout-round3-2026-09-16.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/flash-title-coverage-2026-09-16.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/docs/sdk-0.4.md +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/pyproject.toml +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/schemas/middle-2.0.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/schemas/model-2.0.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/setup.cfg +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/hyperlink.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/image.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/markup/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/markup/anchors.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/markup/formula.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/markup/projector.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/markup/styles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/mathml.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/names.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/_shared/xycut.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/contracts.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/csv.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/epub/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/epub/constants.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/epub/converter.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/epub/errors.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/epub/metadata.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/epub/package.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/epub/properties.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/html/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/html/anchors.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/html/converter.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/html/document.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/html/errors.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/html/metadata.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/html/selector.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/assembly.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/constants.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/converter.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/errors.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/images.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/metadata.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/package.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/path.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/reading_order.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/resources.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/scene.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/ofd/vector.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/bookmarks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/doc_converter.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/fib.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/fields.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/formatting.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/images.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/lists.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/parser.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/pieces.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/records.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/sprm.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/doc/styles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/context.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/docx_converter.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/equationxml.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/fields.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/formatting_types.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/main.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/numbering.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/office_xml.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/package_normalizer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/resources.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/styles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/docx/tables.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/equation/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/equation/image.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/equation/latex_dict.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/equation/mtef.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/equation/mtef_v5.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/equation/omml.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/equation/ooxml.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/errors.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/legacy/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/legacy/binary.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/legacy/officeart.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/legacy/ole.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/limits.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/metadata.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/chart.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/constants.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/converters.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/errors.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/metadata.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/package.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/styles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/odf/table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/ooxml_chart.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/opc.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/ppt/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/ppt/models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/ppt/parser.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/ppt/ppt_converter.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/ppt/records.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/ppt/style_text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/context.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/lists.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/main.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/package_normalizer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/pptx_converter.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/shapes.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/text_styles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/titles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/rich_text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/rtf/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/rtf/converter.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/rtf/lexer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/rtf/math.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/rtf/metadata.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/rtf/models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/rtf/parser.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/spreadsheet/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/spreadsheet/html.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/spreadsheet/models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/spreadsheet/projector.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/streams.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xls/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xls/chart.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xls/embedded_chart.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xls/models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xls/number_format.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xls/parser.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xls/records.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xls/strings.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xls/xls_converter.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xlsx/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xlsx/main.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xlsx/ooxml_ole.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xlsx/package_normalizer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/xlsx/xlsx_converter.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_script_geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/candidate.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/contracts.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/engine.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/rule_band.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/sparse_common.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/sparse_hybrid.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/sparse_multiline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/text_grid.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/_table_recovery/vector.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/annotation_bands.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/auxiliary_text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/char_geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/code_blocks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/formulas.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/graphics.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/index_blocks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/inline/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/inline/common.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/inline/detection.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/inline/matching.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/inline/materialize.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/inline/scripts.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/inline/types.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/layout_evidence.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/line_layout.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/line_merging.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/native_text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/pipeline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/spatial_text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/table_annotations.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/table_constants.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/table_detection.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/table_filled_grid.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/table_geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/table_materialization.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/table_rows.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/table_rules.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/table_text_styles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/tables.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/text_assembly/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/text_assembly/annotations.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/text_assembly/assembly.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/text_assembly/common.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/text_assembly/continuity.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/text_assembly/footnotes.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/text_assembly/merging.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/text_assembly/rows.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/text_blocks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/text_roles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/title_analysis/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/title_analysis/body_profile.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/title_analysis/common.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/title_analysis/compact_titles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/title_analysis/document_profile.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/title_analysis/lane_titles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/title_analysis/page_titles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/title_analysis/prototype.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/title_analysis/structural.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/titles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/typography.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/pdf/visual_annotations.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/pdf.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/api.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/assets/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/assets/images.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/assets/store.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/cli.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/codecs/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/codecs/html/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/codecs/html/contracts.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/codecs/html/materializer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/codecs/html/parser.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/codecs/html/resources.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/codecs/json.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/inline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/links.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/markup/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/markup/anchors.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/markup/formula.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/markup/projector.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/markup/styles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/normalization.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/spans.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/table/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/table/blocks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/table/content.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/table/document.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/table/html.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/table/models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/table/rules.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/table/structure.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/content/tree.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/detection.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/filetypes.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/page_range.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/_document.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/classify.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/constants.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/font_runtime.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/images.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/layout.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/metadata.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/native_annotations.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/native_contracts.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/native_coordinates.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/native_lifecycle.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/native_objects.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/native_text_geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/pdfium.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/raster.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/text/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/text/_contracts.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/text/dedup.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/text/extract.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/text/geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/text/groups.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/pdf/visuals.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/properties.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/document/source.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/errors.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/export/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/export/bundle.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/export/middle.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/_coordinates.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/_geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/_hyperlink.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/_image.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/_image_operations.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/_image_payload.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/_text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/image_encoding.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/language.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/type_identity.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/foundation/xml_names.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/metadata.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/options.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/postprocess/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/postprocess/content.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/postprocess/document.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/postprocess/lists.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/postprocess/page_blocks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/postprocess/pages.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/postprocess/paragraphs.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/postprocess/visual.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/public_api.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/common/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/common/context.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/common/html_table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/common/index.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/common/list_items.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/common/planner.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/docx/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/docx/assets.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/docx/inline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/docx/math.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/docx/renderer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/docx/styles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/docx/table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/epub/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/epub/assets.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/epub/package.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/epub/renderer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/html/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/html/inline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/html/renderer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/html/sanitizer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/html/table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/latex/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/latex/assets.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/latex/inline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/latex/renderer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/latex/table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/markdown/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/markdown/assets.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/markdown/blocks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/markdown/escaping.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/markdown/inline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/markdown/renderer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/markdown/table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/assets.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/diagnostics.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/font_plan.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/formula.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/formula_layout.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/inline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/original.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/pagination.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/paragraph.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/renderer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/styles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/table_content.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/table_layout.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/pdf/title_layout.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/structured_content/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/_internal/structured_content/renderer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/api.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/contracts.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/docx.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/epub.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/fragments.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/html.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/latex.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/markdown.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/pdf.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/render/structured_content.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/resources/epub/docvortex.css +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/resources/fonts/DroidSansFallbackFull.ttf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/resources/fonts/NOTICE +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/resources/fonts/manifest.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/resources/html/docvortex.css +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/resources/html/docvortex.min.css +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/resources/unicode/EquivalentUnifiedIdeograph-17.0.0.txt +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/result.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/schema.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/visualization.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex.egg-info/dependency_links.txt +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex.egg-info/entry_points.txt +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex.egg-info/requires.txt +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex.egg-info/top_level.txt +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/benchmarks/flash_pdf.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/benchmarks/native_pdf_table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/benchmarks/pdf_render.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/benchmarks/pipeline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/evaluate_native_pdf_table_manifest.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_layout_block_expectations.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_layout_geometry_manifest.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_layout_semantic_expectations.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_manual_annotations.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_manual_review_decisions.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_reviewed_history.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_round2_annotations.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_round2_review_decisions.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_round3_annotations.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_round3_followup_review_decisions.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_round3_review_decisions.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_rule_generalization_review_decisions.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/flash_title_coverage_review_decisions.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/generate_synthetic_pdf_fixtures.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/native_pdf_table_cross_page_manifest.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/native_pdf_table_demo_manifest.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/native_pdf_table_script_truth.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/pdf_char_dedup.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/pdf_mixed_font_script_line.json +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/fixtures/rtf/semantic.rtf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_architecture.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_benchmark_entrypoint.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_brand_protocol.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_cli_logging.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_complete_pipeline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_converter_lifecycle.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_document_envelope.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_document_metadata.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_format_matrix.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_geometry_api.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_history_geometry_tools.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_html_namespace.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_mixed_font_script_reference.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_pdf_analysis_api.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_pdf_font_geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_pdf_font_runtime.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_pdf_model_text_normalization.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_pdf_output_text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_pdf_render_pool.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_pdf_source_row_merging.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_pdf_symbol_normalization.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_public_export_api.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_public_image_api.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_public_pipeline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_refactor_raster.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_refactor_rendering.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_refactor_resources.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_release_ci_gate.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_render_ownership.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_renderer_branding.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_shared_boundaries.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_system_font_pdf_pipeline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/test_validated_geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_docx_equationxml_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_epub_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_flash_pdf_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_image_mtef_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_legacy_doc_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_legacy_ppt_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_legacy_xls_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_metafile_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_mtef_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_mtef_v5_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_native_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_ofd_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_office_image_mtef_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_ooxml_mtef_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/_span_test_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/annotated/connexin.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/annotated/fornax.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/annotated/frames_v1.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/annotated/frames_v2.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/annotated/k2_treap.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/annotated/mmlu_redux.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/annotated/nash_review.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/annotated/nougat.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/bloom_form_labels.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/journal_dual_caption.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/journal_layout_tables.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/math_display_formulas.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/mixed_text_layout_sample.pdf.xor +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_layout/quantum_appendix_layout.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/flash_table_annotations_synthetic.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/metabolic_pathway_page_3.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_cjk_layout_synthetic.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/annual_report_fundraising_projects_table.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/annual_report_management_roles_table.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/annual_report_research_projects_table.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/conference_schedule_tables.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/engineering_process_restrictions_table.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/fund_asset_and_transaction_tables.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/fund_manager_profile_table.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/manufacturing_facilities_cross_page_table.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/pollutant_discharge_tables.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/procurement_contract_tables.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/procurement_document_blank_page_tables.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/native_pdf_tables/quarterly_report_financial_tables.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/pdfs/test.pdf +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_backend_architecture.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_backend_block_object_regressions.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_docx_assets.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_docx_complex_fields.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_docx_math.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_docx_render.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_docx_special_char_tables.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_docx_table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_emfplus_integration.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_epub_backlinks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_epub_quoted_note_types.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_epub_render.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_bbox_grid_comparison.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_csv.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_docx_equationxml.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_image_mtef.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_legacy_chart_data.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_legacy_doc.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_legacy_doc_mtef.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_legacy_ppt.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_legacy_xls.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_legacy_xls_ppt_mtef.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_manual_annotations.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_markup_anchors.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_model.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_mtef_v5.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_ofd.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_office_image_mtef.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_office_metafile.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_office_models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_office_mtef_v5.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_office_package_normalizers.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_ooxml_mtef.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_auxiliary_text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_char_geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_code_blocks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_document_profile.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_equation_images.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_extractor.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_formulas.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_graphics.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_index_blocks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_layout_repairs.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_line_metadata.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_native_text.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_pipeline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_reviewed_history.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_samples.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_scripts.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_semantics.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_tables.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_text_blocks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_text_visibility.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_titles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_pdf_visual_annotations.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_round2_annotations.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_round3_annotations.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_rtf.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_rule_generalization.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_spatial_evidence.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_flash_spreadsheet_projector.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_guess_suffix_ole2.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_html_css_build.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_html_render.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_html_security.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_hybrid_script_source_pdfs.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_latex_render.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_markdown_render.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_middle_json_block_models.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_middle_json_export.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_middle_json_validator.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_model_json.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_native_pdf_table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_native_pdf_table_demo_manifest.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_native_pdf_table_manifest.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_native_pdf_table_pipeline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_native_pdf_table_scripts.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_native_table_performance_equivalence.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_ofd_assembly.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_ofd_vector_tables.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_office_demo_exports.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_office_demo_pages.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_office_parser_regressions.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_cjk_style.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_cjk_wrapping.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_classify.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_demo_links.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_diagnostic_levels.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_document.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_formula_layout.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_object_clipping.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_original_layout.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_pagination.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_paragraph_cache.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_render.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_render_diagnostics.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_structured_tables.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_table_cache.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_table_round2.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_text_dedup.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_text_styles.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_title_font_plan.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_title_space.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_pdf_visualization.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_postprocess_page_blocks.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_postprocess_pages.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_postprocess_paragraphs.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_postprocess_visual.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_render_api.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_render_html_table.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_render_image_renderer.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_render_list_index_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_structured_content_render.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_table_merge.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_table_merge_cell_merge.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_text_block_anchor.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_text_boundary_rules.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tests/unittest/test_text_utils.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tools/__init__.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tools/build_html_css.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tools/calibrate_pdf_geometry.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tools/capture_baseline.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tools/capture_platform_layout.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tools/compare_font_platforms.py +0 -0
- {docvortex-0.4.10 → docvortex-0.4.12}/tools/font_geometry.py +0 -0
|
@@ -35,6 +35,7 @@ from docvortex.content.markup.projector import (
|
|
|
35
35
|
|
|
36
36
|
from ....content.spans import normalize_span_dicts
|
|
37
37
|
from ....foundation._image_payload import parse_image_data_uri_strict
|
|
38
|
+
from ....foundation._svg_raster import serialize_svg_image
|
|
38
39
|
from .._shared.hyperlink import sanitize_hyperlink_target
|
|
39
40
|
from .constants import IMAGE_MEDIA_BY_EXTENSION, SVG_MEDIA_TYPE
|
|
40
41
|
from .package import EpubPackage
|
|
@@ -275,14 +276,22 @@ class _EpubMarkupContext:
|
|
|
275
276
|
)
|
|
276
277
|
|
|
277
278
|
def resolve_image(self, source: str, *, alt: str = "") -> ResolvedMarkupImage | None:
|
|
278
|
-
"""读取并严格校验一个 EPUB
|
|
279
|
+
"""读取并严格校验一个 EPUB 包内图片引用,SVG 光栅化为 PNG。"""
|
|
279
280
|
target = self.package.resolve_reference(source, base_part=self.chapter_path)
|
|
280
281
|
if target is None:
|
|
281
282
|
return ResolvedMarkupImage(alt=alt) if alt else None
|
|
282
283
|
media_type = (self.package.content_type_for(target.path) or "").casefold()
|
|
283
284
|
extension = target.path.rsplit(".", 1)[-1].casefold() if "." in target.path else ""
|
|
284
285
|
media_type = media_type or IMAGE_MEDIA_BY_EXTENSION.get(extension, "")
|
|
285
|
-
if
|
|
286
|
+
if media_type == SVG_MEDIA_TYPE:
|
|
287
|
+
payload = self.package.read_part(target.path, asset=True)
|
|
288
|
+
if payload is None:
|
|
289
|
+
return ResolvedMarkupImage(alt=alt) if alt else None
|
|
290
|
+
data_uri = serialize_svg_image(payload)
|
|
291
|
+
if data_uri is None:
|
|
292
|
+
return ResolvedMarkupImage(alt=alt) if alt else None
|
|
293
|
+
return ResolvedMarkupImage(image_base64=data_uri, alt=alt)
|
|
294
|
+
if not media_type.startswith("image/"):
|
|
286
295
|
return ResolvedMarkupImage(alt=alt) if alt else None
|
|
287
296
|
payload = self.package.read_part(target.path, asset=True)
|
|
288
297
|
if payload is None:
|
|
@@ -8,7 +8,6 @@ MAX_HTML_NODES: Final = 2_000_000
|
|
|
8
8
|
MAX_HTML_DEPTH: Final = 256
|
|
9
9
|
MAX_HTML_IMAGE_BYTES: Final = 20 * 1024 * 1024
|
|
10
10
|
MAX_HTML_IMAGE_TOTAL_BYTES: Final = 128 * 1024 * 1024
|
|
11
|
-
MAX_REMOTE_IMAGE_FETCH_SECONDS: Final = 10
|
|
12
11
|
MAX_HTML_STYLESHEET_BYTES: Final = 5 * 1024 * 1024
|
|
13
12
|
MAX_HTML_STYLESHEET_TOTAL_BYTES: Final = 20 * 1024 * 1024
|
|
14
13
|
MAX_HTML_RENDERED_BYTES: Final = 256 * 1024 * 1024
|
|
@@ -23,5 +22,4 @@ __all__ = [
|
|
|
23
22
|
"MAX_HTML_RENDERED_BYTES",
|
|
24
23
|
"MAX_HTML_STYLESHEET_BYTES",
|
|
25
24
|
"MAX_HTML_STYLESHEET_TOTAL_BYTES",
|
|
26
|
-
"MAX_REMOTE_IMAGE_FETCH_SECONDS",
|
|
27
25
|
]
|
|
@@ -6,7 +6,6 @@ import base64
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Protocol
|
|
8
8
|
from urllib.parse import SplitResult, unquote, urljoin, urlsplit, urlunsplit
|
|
9
|
-
from urllib.request import urlopen
|
|
10
9
|
|
|
11
10
|
from lxml import etree # type: ignore[reportMissingImports]
|
|
12
11
|
|
|
@@ -14,13 +13,13 @@ from docvortex.content.markup import ResolvedMarkupImage
|
|
|
14
13
|
from docvortex.document.contracts import HtmlSourceContext
|
|
15
14
|
|
|
16
15
|
from ....foundation._image_payload import parse_image_data_uri_strict, validate_remote_image_url
|
|
16
|
+
from ....foundation._svg_raster import looks_like_svg_payload, serialize_svg_image
|
|
17
17
|
from .._shared.hyperlink import sanitize_hyperlink_target
|
|
18
18
|
from .constants import (
|
|
19
19
|
MAX_HTML_IMAGE_BYTES,
|
|
20
20
|
MAX_HTML_IMAGE_TOTAL_BYTES,
|
|
21
21
|
MAX_HTML_STYLESHEET_BYTES,
|
|
22
22
|
MAX_HTML_STYLESHEET_TOTAL_BYTES,
|
|
23
|
-
MAX_REMOTE_IMAGE_FETCH_SECONDS,
|
|
24
23
|
)
|
|
25
24
|
from .errors import HtmlResourceLimitError
|
|
26
25
|
|
|
@@ -67,7 +66,6 @@ class HtmlResourceContext:
|
|
|
67
66
|
self._image_bytes = 0
|
|
68
67
|
self._stylesheet_bytes = 0
|
|
69
68
|
self._image_cache: dict[Path, str] = {}
|
|
70
|
-
self._remote_image_cache: dict[str, str] = {}
|
|
71
69
|
self._data_image_cache: dict[str, ResolvedMarkupImage] = {}
|
|
72
70
|
self._stylesheet_cache: dict[Path, str] = {}
|
|
73
71
|
self._local_root = source_context.local_resource_root.resolve() if source_context.local_resource_root else None
|
|
@@ -160,14 +158,14 @@ class HtmlResourceContext:
|
|
|
160
158
|
return sanitize_hyperlink_target(normalized, allow_relative=True, allow_fragment=True)
|
|
161
159
|
|
|
162
160
|
def resolve_image(self, source: str, *, alt: str = "") -> ResolvedMarkupImage | None:
|
|
163
|
-
"""按 data URI、远程 URL
|
|
161
|
+
"""按 data URI、远程 URL、本地安全文件的顺序解析图片,远程图片仅保留受限外链。"""
|
|
164
162
|
normalized = (source or "").strip()
|
|
165
163
|
if not normalized:
|
|
166
164
|
return ResolvedMarkupImage(alt=alt) if alt else None
|
|
167
165
|
if normalized.casefold().startswith("data:"):
|
|
168
166
|
return self._resolve_data_image(normalized, alt=alt)
|
|
169
167
|
if remote_url := self._resolve_remote_image_url(normalized):
|
|
170
|
-
return
|
|
168
|
+
return ResolvedMarkupImage(image_url=remote_url, alt=alt)
|
|
171
169
|
local_path = self._resolve_local_path(normalized)
|
|
172
170
|
if local_path is None or not local_path.is_file():
|
|
173
171
|
return ResolvedMarkupImage(alt=alt) if alt else None
|
|
@@ -178,7 +176,10 @@ class HtmlResourceContext:
|
|
|
178
176
|
payload = source_file.read(MAX_HTML_IMAGE_BYTES + 1)
|
|
179
177
|
if len(payload) > MAX_HTML_IMAGE_BYTES:
|
|
180
178
|
raise HtmlResourceLimitError(f"HTML image exceeds max_html_image_bytes={MAX_HTML_IMAGE_BYTES}")
|
|
181
|
-
|
|
179
|
+
if local_path.suffix.casefold() == ".svg" or looks_like_svg_payload(payload):
|
|
180
|
+
data_uri = serialize_svg_image(payload)
|
|
181
|
+
else:
|
|
182
|
+
data_uri = _image_data_uri(payload)
|
|
182
183
|
if data_uri is None:
|
|
183
184
|
return ResolvedMarkupImage(alt=alt) if alt else None
|
|
184
185
|
self._charge_image_bytes(len(payload))
|
|
@@ -228,7 +229,7 @@ class HtmlResourceContext:
|
|
|
228
229
|
return self.anchors.note_anchor(note) if self.anchors else None
|
|
229
230
|
|
|
230
231
|
def _resolve_data_image(self, data_uri: str, *, alt: str) -> ResolvedMarkupImage | None:
|
|
231
|
-
"""严格解析 data URI
|
|
232
|
+
"""严格解析 data URI 并执行图片预算,SVG 光栅化为 PNG 后内嵌。"""
|
|
232
233
|
if cached := self._data_image_cache.get(data_uri):
|
|
233
234
|
return ResolvedMarkupImage(image_base64=cached.image_base64, alt=alt)
|
|
234
235
|
if len(data_uri) > MAX_HTML_IMAGE_BYTES * 2:
|
|
@@ -238,7 +239,15 @@ class HtmlResourceContext:
|
|
|
238
239
|
except ValueError:
|
|
239
240
|
return ResolvedMarkupImage(alt=alt) if alt else None
|
|
240
241
|
if extension == "svg":
|
|
241
|
-
|
|
242
|
+
if len(payload) > MAX_HTML_IMAGE_BYTES:
|
|
243
|
+
raise HtmlResourceLimitError(f"HTML image exceeds max_html_image_bytes={MAX_HTML_IMAGE_BYTES}")
|
|
244
|
+
raster_uri = serialize_svg_image(payload)
|
|
245
|
+
if raster_uri is None:
|
|
246
|
+
return ResolvedMarkupImage(alt=alt) if alt else None
|
|
247
|
+
self._charge_image_bytes(len(payload))
|
|
248
|
+
resolved = ResolvedMarkupImage(image_base64=raster_uri, alt=alt)
|
|
249
|
+
self._data_image_cache[data_uri] = resolved
|
|
250
|
+
return resolved
|
|
242
251
|
if len(payload) > MAX_HTML_IMAGE_BYTES:
|
|
243
252
|
raise HtmlResourceLimitError(f"HTML image exceeds max_html_image_bytes={MAX_HTML_IMAGE_BYTES}")
|
|
244
253
|
self._charge_image_bytes(len(payload))
|
|
@@ -246,41 +255,6 @@ class HtmlResourceContext:
|
|
|
246
255
|
self._data_image_cache[data_uri] = resolved
|
|
247
256
|
return resolved
|
|
248
257
|
|
|
249
|
-
def _resolve_remote_image(self, remote_url: str, *, alt: str) -> ResolvedMarkupImage:
|
|
250
|
-
"""远程图片默认保持外链,来源显式开启下载时按缓存下载内嵌。"""
|
|
251
|
-
if not self.source_context.fetch_remote_images:
|
|
252
|
-
return ResolvedMarkupImage(image_url=remote_url, alt=alt)
|
|
253
|
-
if cached := self._remote_image_cache.get(remote_url):
|
|
254
|
-
return ResolvedMarkupImage(image_base64=cached, alt=alt)
|
|
255
|
-
data_uri = self._fetch_remote_image(remote_url)
|
|
256
|
-
if data_uri is None:
|
|
257
|
-
return ResolvedMarkupImage(image_url=remote_url, alt=alt)
|
|
258
|
-
self._remote_image_cache[remote_url] = data_uri
|
|
259
|
-
return ResolvedMarkupImage(image_base64=data_uri, alt=alt)
|
|
260
|
-
|
|
261
|
-
def _fetch_remote_image(self, remote_url: str) -> str | None:
|
|
262
|
-
"""在单图上限与超时约束内下载远程图片并复核签名,网络失败返回 None 退回外链。"""
|
|
263
|
-
try:
|
|
264
|
-
with urlopen(remote_url, timeout=MAX_REMOTE_IMAGE_FETCH_SECONDS) as response:
|
|
265
|
-
chunks: list[bytes] = []
|
|
266
|
-
remaining = MAX_HTML_IMAGE_BYTES + 1
|
|
267
|
-
while remaining > 0:
|
|
268
|
-
chunk = response.read(remaining)
|
|
269
|
-
if not chunk:
|
|
270
|
-
break
|
|
271
|
-
chunks.append(chunk)
|
|
272
|
-
remaining -= len(chunk)
|
|
273
|
-
except (OSError, ValueError):
|
|
274
|
-
return None
|
|
275
|
-
payload = b"".join(chunks)
|
|
276
|
-
if len(payload) > MAX_HTML_IMAGE_BYTES:
|
|
277
|
-
raise HtmlResourceLimitError(f"HTML image exceeds max_html_image_bytes={MAX_HTML_IMAGE_BYTES}")
|
|
278
|
-
data_uri = _image_data_uri(payload)
|
|
279
|
-
if data_uri is None:
|
|
280
|
-
return None
|
|
281
|
-
self._charge_image_bytes(len(payload))
|
|
282
|
-
return data_uri
|
|
283
|
-
|
|
284
258
|
def _charge_image_bytes(self, byte_count: int) -> None:
|
|
285
259
|
"""累计实际保留的图片字节,并在超限时终止整份文档。"""
|
|
286
260
|
self._image_bytes += byte_count
|
|
@@ -11,6 +11,7 @@ from loguru import logger
|
|
|
11
11
|
from metafile_render import MetafileError, MetafileResourceLimitError, render_metafile
|
|
12
12
|
from PIL import Image, ImageDraw, ImageFont, UnidentifiedImageError
|
|
13
13
|
|
|
14
|
+
from ....foundation._svg_raster import is_svg_image_part, looks_like_svg_payload, serialize_svg_image
|
|
14
15
|
from ....foundation.image_encoding import image_to_b64str
|
|
15
16
|
|
|
16
17
|
VECTOR_IMAGE_FORMATS = frozenset({"WMF", "EMF"})
|
|
@@ -267,6 +268,9 @@ def serialize_office_image(
|
|
|
267
268
|
return rendered
|
|
268
269
|
return serialize_vector_part_with_placeholder(part_name, content_type)
|
|
269
270
|
|
|
271
|
+
if is_svg_image_part(part_name, content_type) or looks_like_svg_payload(image_data):
|
|
272
|
+
return serialize_svg_image(image_data)
|
|
273
|
+
|
|
270
274
|
try:
|
|
271
275
|
pil_image = Image.open(BytesIO(image_data))
|
|
272
276
|
if is_vector_image(pil_image):
|
|
@@ -20,6 +20,7 @@ from .....content.spans import (
|
|
|
20
20
|
inline_span_plain_text,
|
|
21
21
|
strip_span_dicts,
|
|
22
22
|
)
|
|
23
|
+
from .....foundation._svg_raster import serialize_svg_image
|
|
23
24
|
from .....foundation.image_encoding import image_to_b64str
|
|
24
25
|
from .....schema import BlockType
|
|
25
26
|
from ..._shared.hyperlink import sanitize_hyperlink_target
|
|
@@ -108,16 +109,36 @@ def _style_html(text: str, style: TextStyle) -> str:
|
|
|
108
109
|
return rendered
|
|
109
110
|
|
|
110
111
|
|
|
112
|
+
_SVG_RENDER_DPI = 200
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _frame_render_size(frame: etree._Element | None) -> tuple[int, int] | None:
|
|
116
|
+
"""按 draw:frame 显示尺寸换算渲染像素,作为 SVG 光栅化的目标尺寸。"""
|
|
117
|
+
from .converters import _length_to_points
|
|
118
|
+
|
|
119
|
+
if frame is None:
|
|
120
|
+
return None
|
|
121
|
+
width = _length_to_points(frame.get(qname("svg", "width")))
|
|
122
|
+
height = _length_to_points(frame.get(qname("svg", "height")))
|
|
123
|
+
if width <= 0 or height <= 0:
|
|
124
|
+
return None
|
|
125
|
+
return (max(1, round(width / 72 * _SVG_RENDER_DPI)), max(1, round(height / 72 * _SVG_RENDER_DPI)))
|
|
126
|
+
|
|
127
|
+
|
|
111
128
|
def _serialize_odf_image(
|
|
112
129
|
image_bytes: bytes,
|
|
113
130
|
*,
|
|
114
131
|
part_name: str | None,
|
|
115
132
|
content_type: str | None,
|
|
133
|
+
size_hint: tuple[int, int] | None = None,
|
|
116
134
|
) -> str | None:
|
|
117
|
-
"""序列化 ODF 图片;SVG
|
|
135
|
+
"""序列化 ODF 图片;SVG 光栅化为 PNG,SVM 和 GDIMeta 使用安全占位图保留对象位置。"""
|
|
118
136
|
normalized_type = (content_type or "").split(";", 1)[0].strip().casefold()
|
|
119
137
|
suffix = (part_name or "").rsplit(".", 1)[-1].casefold() if "." in (part_name or "") else ""
|
|
120
138
|
if normalized_type == "image/svg+xml" or suffix == "svg":
|
|
139
|
+
rendered = serialize_svg_image(image_bytes, size_hint=size_hint)
|
|
140
|
+
if rendered is not None:
|
|
141
|
+
return rendered
|
|
121
142
|
placeholder = create_text_placeholder((320, 180), ["SVG image", "Preview unavailable"])
|
|
122
143
|
return image_to_b64str(placeholder, image_format="JPEG")
|
|
123
144
|
if suffix == "svm" or "gdimetafile" in normalized_type or image_bytes.startswith(b"VCLMTF"):
|
|
@@ -712,7 +733,15 @@ class OdfBlockParser:
|
|
|
712
733
|
)
|
|
713
734
|
if not image_bytes:
|
|
714
735
|
return None, alt
|
|
715
|
-
return
|
|
736
|
+
return (
|
|
737
|
+
_serialize_odf_image(
|
|
738
|
+
image_bytes,
|
|
739
|
+
part_name=part_name,
|
|
740
|
+
content_type=content_type,
|
|
741
|
+
size_hint=_frame_render_size(parent),
|
|
742
|
+
),
|
|
743
|
+
alt,
|
|
744
|
+
)
|
|
716
745
|
|
|
717
746
|
def _object_root(self, object_element: etree._Element) -> tuple[etree._Element | None, str | None]:
|
|
718
747
|
"""读取 draw:object 指向的子文档内容树和成员路径。"""
|
{docvortex-0.4.10 → docvortex-0.4.12}/src/docvortex/analyzers/native/office/pptx/resources.py
RENAMED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""PPTX 图片、图表与公式资源,复用当前转换器的单文档状态。"""
|
|
2
2
|
|
|
3
|
-
import base64
|
|
4
3
|
from typing import Any, Optional
|
|
5
4
|
from loguru import logger
|
|
6
5
|
from pptx.enum.shapes import MSO_SHAPE_TYPE
|
|
@@ -222,11 +221,19 @@ class _PptxResources:
|
|
|
222
221
|
return
|
|
223
222
|
|
|
224
223
|
if content_type == "image/svg+xml":
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
224
|
+
img_base64 = serialize_office_image(image_bytes, content_type=content_type)
|
|
225
|
+
if img_base64 is None:
|
|
226
|
+
# SVG 光栅化失败时回退到 PowerPoint 为 SVG 原生伴随存储的栅量 blip。
|
|
227
|
+
fallback_data = self._get_shape_image_data(shape, include_svg=False)
|
|
228
|
+
if fallback_data is not None and fallback_data[1] != "image/svg+xml":
|
|
229
|
+
img_base64 = serialize_office_image(fallback_data[0], content_type=fallback_data[1])
|
|
230
|
+
if img_base64 is not None:
|
|
231
|
+
self.cur_page.append(
|
|
232
|
+
{
|
|
233
|
+
"type": BlockType.IMAGE,
|
|
234
|
+
"image_base64": img_base64,
|
|
235
|
+
}
|
|
236
|
+
)
|
|
230
237
|
return
|
|
231
238
|
|
|
232
239
|
img_base64 = serialize_office_image(
|
|
@@ -256,19 +263,14 @@ class _PptxResources:
|
|
|
256
263
|
)
|
|
257
264
|
|
|
258
265
|
@staticmethod
|
|
259
|
-
def
|
|
260
|
-
"""按原有图片、图表与公式资源规则执行 _bytes_to_data_uri,保持输入顺序与降级行为。"""
|
|
261
|
-
encoded = base64.b64encode(image_bytes).decode("utf-8")
|
|
262
|
-
return f"data:{content_type};base64,{encoded}"
|
|
263
|
-
|
|
264
|
-
@staticmethod
|
|
265
|
-
def _find_first_embedded_image_rid(shape) -> Optional[str]:
|
|
266
|
+
def _find_first_embedded_image_rid(shape, *, include_svg: bool = True) -> Optional[str]:
|
|
266
267
|
"""按原有图片、图表与公式资源规则执行 _find_first_embedded_image_rid,保持输入顺序与降级行为。"""
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
268
|
+
if include_svg:
|
|
269
|
+
svg_blips = shape._element.findall(f".//{{{SVG_BLIP_NS}}}svgBlip")
|
|
270
|
+
for svg_blip in svg_blips:
|
|
271
|
+
relationship_id = svg_blip.get(f"{{{RELATIONSHIP_NS}}}embed")
|
|
272
|
+
if relationship_id:
|
|
273
|
+
return relationship_id
|
|
272
274
|
|
|
273
275
|
blips = shape._element.findall(f".//{{{DRAWINGML_NS}}}blip")
|
|
274
276
|
for blip in blips:
|
|
@@ -296,11 +298,11 @@ class _PptxResources:
|
|
|
296
298
|
return False
|
|
297
299
|
return True
|
|
298
300
|
|
|
299
|
-
def _get_shape_image_data(self, shape) -> Optional[tuple[bytes, Optional[str]]]:
|
|
301
|
+
def _get_shape_image_data(self, shape, *, include_svg: bool = True) -> Optional[tuple[bytes, Optional[str]]]:
|
|
300
302
|
"""按原有图片、图表与公式资源规则执行 _get_shape_image_data,保持输入顺序与降级行为。"""
|
|
301
303
|
relationship_id = None
|
|
302
304
|
if hasattr(shape, "_element"):
|
|
303
|
-
relationship_id = self._find_first_embedded_image_rid(shape)
|
|
305
|
+
relationship_id = self._find_first_embedded_image_rid(shape, include_svg=include_svg)
|
|
304
306
|
|
|
305
307
|
if relationship_id:
|
|
306
308
|
try:
|
|
@@ -6,6 +6,7 @@ import re
|
|
|
6
6
|
|
|
7
7
|
from lxml import etree # type: ignore[reportMissingImports]
|
|
8
8
|
|
|
9
|
+
from ..foundation._text import normalize_formula_tag_content
|
|
9
10
|
from ..foundation.xml_names import local_name
|
|
10
11
|
|
|
11
12
|
_OPERATOR_MAP = {
|
|
@@ -71,6 +72,8 @@ _LATEX_MATH_TOKEN_ESCAPES = {
|
|
|
71
72
|
"}": r"\}",
|
|
72
73
|
"~": r"\~{}",
|
|
73
74
|
}
|
|
75
|
+
# Word 线性格式把公式编号分隔符写作 ``#(n)``;经 mo 转义后行尾呈现为 ``\#(n)``。
|
|
76
|
+
_EQUATION_TAG_RE = re.compile(r"\\#\s*\(([^()]*)\)\s*$")
|
|
74
77
|
|
|
75
78
|
|
|
76
79
|
def _escape_text(value: str) -> str:
|
|
@@ -83,6 +86,22 @@ def _escape_math_token(value: str) -> str:
|
|
|
83
86
|
return "".join(_LATEX_MATH_TOKEN_ESCAPES.get(char, char) for char in value)
|
|
84
87
|
|
|
85
88
|
|
|
89
|
+
def _tag_equation_number(latex: str) -> str | None:
|
|
90
|
+
"""把 Word 公式编号分隔符残留的行尾 ``\\#(n)`` 转换为 LaTeX ``\\tag``。
|
|
91
|
+
|
|
92
|
+
参考 OMML 转换器 ``do_eqarr`` 的既有语义:单行公式数组末尾的编号
|
|
93
|
+
``#(n)`` 输出为 ``公式\\tag{n}``,同时避免 ``\\tag`` 进入 matrix 环境。
|
|
94
|
+
"""
|
|
95
|
+
match = _EQUATION_TAG_RE.search(latex)
|
|
96
|
+
if match is None:
|
|
97
|
+
return None
|
|
98
|
+
formula = latex[: match.start()].rstrip()
|
|
99
|
+
tag_content = normalize_formula_tag_content(match.group(1))
|
|
100
|
+
if not formula or not tag_content:
|
|
101
|
+
return None
|
|
102
|
+
return rf"{formula}\tag{{{tag_content}}}"
|
|
103
|
+
|
|
104
|
+
|
|
86
105
|
def _children(element: etree._Element) -> list[etree._Element]:
|
|
87
106
|
"""返回当前元素的全部普通 XML 子元素。"""
|
|
88
107
|
return [child for child in element if isinstance(child.tag, str)]
|
|
@@ -107,7 +126,7 @@ def _convert(element: etree._Element) -> str:
|
|
|
107
126
|
if name in {"mi", "mn"}:
|
|
108
127
|
return _GREEK_MAP.get(text, _escape_math_token(text))
|
|
109
128
|
if name == "mo":
|
|
110
|
-
return _OPERATOR_MAP.get(text, text)
|
|
129
|
+
return _OPERATOR_MAP.get(text, _escape_math_token(text))
|
|
111
130
|
if name == "mtext":
|
|
112
131
|
return rf"\text{{{_escape_text(text)}}}"
|
|
113
132
|
if name == "mspace":
|
|
@@ -139,6 +158,8 @@ def _convert(element: etree._Element) -> str:
|
|
|
139
158
|
return rf"\left{opening}{separators[0].join(values)}\right{closing}"
|
|
140
159
|
if name == "mtable":
|
|
141
160
|
rows = [_convert(child) for child in children if local_name(child) in {"mtr", "mlabeledtr"}]
|
|
161
|
+
if len(rows) == 1 and (tagged := _tag_equation_number(rows[0])) is not None:
|
|
162
|
+
return tagged
|
|
142
163
|
return r"\begin{matrix}" + r" \\ ".join(rows) + r"\end{matrix}"
|
|
143
164
|
if name in {"mtr", "mlabeledtr"}:
|
|
144
165
|
return " & ".join(_convert(child) for child in children)
|
|
@@ -160,7 +181,7 @@ def mathml_to_latex(math_element: etree._Element) -> str | None:
|
|
|
160
181
|
if "tex" in encoding and (annotation.text or "").strip():
|
|
161
182
|
return (annotation.text or "").strip()
|
|
162
183
|
latex = _convert(math_element).strip()
|
|
163
|
-
return latex or None
|
|
184
|
+
return _tag_equation_number(latex) or latex or None
|
|
164
185
|
|
|
165
186
|
|
|
166
187
|
__all__ = ["mathml_to_latex"]
|
|
@@ -10,14 +10,12 @@ from pathlib import Path
|
|
|
10
10
|
class HtmlSourceContext:
|
|
11
11
|
"""保存相对链接解析及 HTML 解码所需的来源上下文。
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
HTTP(S) 图片发起网络请求并内嵌,不可信输入的 SSRF 风险由调用者承担。
|
|
13
|
+
远程图片永不下载,仅在结果中保留受限 HTTP(S) 外链,解析过程保持零网络请求。
|
|
15
14
|
"""
|
|
16
15
|
|
|
17
16
|
source_uri: str | None = None
|
|
18
17
|
local_resource_root: Path | None = None
|
|
19
18
|
transport_encoding: str | None = None
|
|
20
|
-
fetch_remote_images: bool = False
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
__all__ = ["HtmlSourceContext"]
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from pathlib import Path
|
|
6
|
+
from urllib.parse import urlsplit
|
|
6
7
|
|
|
7
8
|
from ..assets import AssetStore
|
|
8
9
|
from ..content.tree import iter_child_blocks
|
|
@@ -28,7 +29,7 @@ def materialize_middle(middle_json: MiddleJson, assets: AssetStore | None = None
|
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def validate_materialized_assets(middle_json: MiddleJson, assets: AssetStore) -> None:
|
|
31
|
-
"""
|
|
32
|
+
"""拒绝缺失的已物化素材,保证结果包内部引用完整;源文档外链原样保留。"""
|
|
32
33
|
from bs4 import BeautifulSoup
|
|
33
34
|
|
|
34
35
|
pending = [block for page in middle_json.pages for block in page.blocks]
|
|
@@ -38,8 +39,6 @@ def validate_materialized_assets(middle_json: MiddleJson, assets: AssetStore) ->
|
|
|
38
39
|
image_path = getattr(block, "image_path", None)
|
|
39
40
|
if image_path and image_path not in assets:
|
|
40
41
|
raise ValueError(f"Missing materialized asset: {image_path}")
|
|
41
|
-
if getattr(block, "image_url", None) and not image_path:
|
|
42
|
-
raise ValueError("An external image must be materialized before saving a bundle")
|
|
43
42
|
content = getattr(block, "content", None)
|
|
44
43
|
if str(block.type) not in {"table_body", "chart_body", "image_body"} or not isinstance(content, str):
|
|
45
44
|
continue
|
|
@@ -47,6 +46,8 @@ def validate_materialized_assets(middle_json: MiddleJson, assets: AssetStore) ->
|
|
|
47
46
|
continue
|
|
48
47
|
for image in BeautifulSoup(content, "html.parser").find_all("img"):
|
|
49
48
|
reference = image.get("src")
|
|
49
|
+
if reference and _is_external_reference(reference):
|
|
50
|
+
continue
|
|
50
51
|
if reference and reference not in assets:
|
|
51
52
|
raise ValueError(f"Missing materialized HTML image: {reference}")
|
|
52
53
|
|
|
@@ -63,4 +64,12 @@ def write_artifact(artifact: RenderArtifact, path: Path, *, overwrite: bool) ->
|
|
|
63
64
|
return ExportResult(path=path, asset_paths=tuple(path.parent / name for name in artifact.assets))
|
|
64
65
|
|
|
65
66
|
|
|
67
|
+
def _is_external_reference(reference: str) -> bool:
|
|
68
|
+
"""判断富文本图片引用是否为保留的受限 HTTP(S) 外链。"""
|
|
69
|
+
try:
|
|
70
|
+
return urlsplit(reference).scheme.casefold() in {"http", "https"}
|
|
71
|
+
except ValueError:
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
|
|
66
75
|
__all__ = ["materialize_middle", "validate_materialized_assets", "write_artifact"]
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""把外部 SVG 图片资源受控光栅化为 PNG data URI 的共享能力。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import base64
|
|
6
|
+
import math
|
|
7
|
+
import re
|
|
8
|
+
import xml.etree.ElementTree as ElementTree
|
|
9
|
+
from io import BytesIO
|
|
10
|
+
from pathlib import PurePosixPath
|
|
11
|
+
from typing import Final
|
|
12
|
+
|
|
13
|
+
from loguru import logger
|
|
14
|
+
|
|
15
|
+
from ._image_payload import (
|
|
16
|
+
MAX_DECODED_RASTER_DIMENSION,
|
|
17
|
+
MAX_DECODED_RASTER_PIXELS,
|
|
18
|
+
_parse_svg_root_strict,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
SVG_MEDIA_TYPE: Final = "image/svg+xml"
|
|
22
|
+
SVG_IMAGE_EXTENSION: Final = ".svg"
|
|
23
|
+
# 小尺寸 logo 按固有像素直出会明显发虚,统一放大到最小可视长边。
|
|
24
|
+
_MIN_RENDER_LONG_EDGE: Final = 512
|
|
25
|
+
_SVG_LENGTH_RE = re.compile(r"^([0-9]*\.?[0-9]+)\s*(px|pt|pc|mm|cm|in|q|%)?$", re.IGNORECASE)
|
|
26
|
+
_LENGTH_TO_PX: Final = {
|
|
27
|
+
"": 1.0,
|
|
28
|
+
"px": 1.0,
|
|
29
|
+
"pt": 96.0 / 72.0,
|
|
30
|
+
"pc": 16.0,
|
|
31
|
+
"mm": 96.0 / 25.4,
|
|
32
|
+
"cm": 96.0 / 2.54,
|
|
33
|
+
"in": 96.0,
|
|
34
|
+
"q": 96.0 / 101.6,
|
|
35
|
+
}
|
|
36
|
+
_SVG_PAYLOAD_SNIFF_WINDOW: Final = 4096
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def is_svg_image_part(part_name: object | None = None, content_type: str | None = None) -> bool:
|
|
40
|
+
"""根据部件扩展名和声明媒体类型判断是否为 SVG 图片部件。"""
|
|
41
|
+
normalized_type = (content_type or "").split(";", 1)[0].strip().casefold()
|
|
42
|
+
if normalized_type == SVG_MEDIA_TYPE:
|
|
43
|
+
return True
|
|
44
|
+
suffix = PurePosixPath(str(part_name or "")).suffix.casefold()
|
|
45
|
+
return suffix == SVG_IMAGE_EXTENSION
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def looks_like_svg_payload(image_data: bytes) -> bool:
|
|
49
|
+
"""按载荷前缀嗅探 SVG 根节点,兜底识别被错误标注的图片部件。"""
|
|
50
|
+
head = image_data[:_SVG_PAYLOAD_SNIFF_WINDOW].lstrip()
|
|
51
|
+
if head.startswith(b"<svg") or head.startswith(b"<svg:"):
|
|
52
|
+
return True
|
|
53
|
+
return head.startswith(b"<?xml") and b"<svg" in head
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _length_to_px(value: str | None) -> float | None:
|
|
57
|
+
"""把 SVG width/height 长度解析为像素值,百分比等上下文相关单位返回 None。"""
|
|
58
|
+
match = _SVG_LENGTH_RE.match((value or "").strip())
|
|
59
|
+
if match is None:
|
|
60
|
+
return None
|
|
61
|
+
unit = match.group(2) or ""
|
|
62
|
+
if unit == "%":
|
|
63
|
+
return None
|
|
64
|
+
return float(match.group(1)) * _LENGTH_TO_PX[unit.casefold()]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _intrinsic_size(root: ElementTree.Element) -> tuple[int, int] | None:
|
|
68
|
+
"""从 svg 根元素解析固有像素尺寸,width/height 不可用时回退 viewBox。"""
|
|
69
|
+
width = _length_to_px(root.get("width"))
|
|
70
|
+
height = _length_to_px(root.get("height"))
|
|
71
|
+
if width is not None and height is not None and width > 0 and height > 0:
|
|
72
|
+
return max(1, round(width)), max(1, round(height))
|
|
73
|
+
view_box = (root.get("viewBox") or "").replace(",", " ").split()
|
|
74
|
+
if len(view_box) == 4:
|
|
75
|
+
try:
|
|
76
|
+
box_width, box_height = float(view_box[2]), float(view_box[3])
|
|
77
|
+
except ValueError:
|
|
78
|
+
return None
|
|
79
|
+
if box_width > 0 and box_height > 0:
|
|
80
|
+
return max(1, round(box_width)), max(1, round(box_height))
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _clamped_size(width: int, height: int) -> tuple[int, int]:
|
|
85
|
+
"""按光栅单边与总像素预算等比收缩目标尺寸。"""
|
|
86
|
+
scale = min(
|
|
87
|
+
1.0,
|
|
88
|
+
MAX_DECODED_RASTER_DIMENSION / width,
|
|
89
|
+
MAX_DECODED_RASTER_DIMENSION / height,
|
|
90
|
+
math.sqrt(MAX_DECODED_RASTER_PIXELS / (width * height)),
|
|
91
|
+
)
|
|
92
|
+
if scale >= 1.0:
|
|
93
|
+
return width, height
|
|
94
|
+
return max(1, round(width * scale)), max(1, round(height * scale))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _render_size(
|
|
98
|
+
intrinsic: tuple[int, int] | None,
|
|
99
|
+
size_hint: tuple[int, int] | None,
|
|
100
|
+
) -> tuple[int, int] | None:
|
|
101
|
+
"""解析渲染目标尺寸:显式提示优先,其次固有尺寸并放大到最小长边。"""
|
|
102
|
+
if size_hint is not None and size_hint[0] > 0 and size_hint[1] > 0:
|
|
103
|
+
return _clamped_size(max(1, round(size_hint[0])), max(1, round(size_hint[1])))
|
|
104
|
+
if intrinsic is None:
|
|
105
|
+
return None
|
|
106
|
+
width, height = intrinsic
|
|
107
|
+
long_edge = max(width, height)
|
|
108
|
+
if long_edge < _MIN_RENDER_LONG_EDGE:
|
|
109
|
+
width = max(1, round(width * _MIN_RENDER_LONG_EDGE / long_edge))
|
|
110
|
+
height = max(1, round(height * _MIN_RENDER_LONG_EDGE / long_edge))
|
|
111
|
+
return _clamped_size(width, height)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _is_fully_transparent(png: bytes) -> bool:
|
|
115
|
+
"""检测光栅化结果是否全透明,用于让无视觉内容的 SVG 走调用方降级。"""
|
|
116
|
+
from PIL import Image
|
|
117
|
+
|
|
118
|
+
with Image.open(BytesIO(png)) as image:
|
|
119
|
+
if image.mode not in {"RGBA", "LA"}:
|
|
120
|
+
return False
|
|
121
|
+
return image.getextrema()[-1][1] == 0
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def serialize_svg_image(image_data: bytes, *, size_hint: tuple[int, int] | None = None) -> str | None:
|
|
125
|
+
"""把外部 SVG 字节光栅化为透明 PNG data URI,无法安全渲染时返回 None。
|
|
126
|
+
|
|
127
|
+
resvg 不执行脚本也不加载外部资源,是外部 SVG 进入输出的安全净化边界;
|
|
128
|
+
``skip_system_fonts=True`` 保证跨平台输出确定,代价是未转路径的 ``<text>``
|
|
129
|
+
不渲染文字。DTD、实体声明和超预算载荷在解析阶段即被拒绝。
|
|
130
|
+
"""
|
|
131
|
+
try:
|
|
132
|
+
root = _parse_svg_root_strict(image_data)
|
|
133
|
+
except ValueError as exc:
|
|
134
|
+
logger.warning(f"SVG image payload cannot be parsed safely: {exc}")
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
import resvg_py
|
|
138
|
+
|
|
139
|
+
target_size = _render_size(_intrinsic_size(root), size_hint)
|
|
140
|
+
# 严格解析后的树重序列化为 UTF-8,避免原始声明的非 UTF-8 编码干扰渲染输入。
|
|
141
|
+
markup = ElementTree.tostring(root, encoding="unicode")
|
|
142
|
+
render_options: dict[str, int] = {}
|
|
143
|
+
if target_size is not None:
|
|
144
|
+
render_options["width"] = target_size[0]
|
|
145
|
+
render_options["height"] = target_size[1]
|
|
146
|
+
try:
|
|
147
|
+
png = resvg_py.svg_to_bytes(svg_string=markup, skip_system_fonts=True, **render_options)
|
|
148
|
+
if not png:
|
|
149
|
+
return None
|
|
150
|
+
if _is_fully_transparent(png):
|
|
151
|
+
logger.debug("Rasterized SVG image is fully transparent; degrading to caller fallback")
|
|
152
|
+
return None
|
|
153
|
+
except Exception as exc: # noqa: BLE001 - resvg 异常面未定型,统一降级由调用方兜底
|
|
154
|
+
logger.warning(f"SVG image cannot be rasterized: {exc}")
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
encoded = base64.b64encode(png).decode("ascii")
|
|
158
|
+
return f"data:image/png;base64,{encoded}"
|
|
@@ -352,6 +352,7 @@ src/docvortex/foundation/_hyperlink.py
|
|
|
352
352
|
src/docvortex/foundation/_image.py
|
|
353
353
|
src/docvortex/foundation/_image_operations.py
|
|
354
354
|
src/docvortex/foundation/_image_payload.py
|
|
355
|
+
src/docvortex/foundation/_svg_raster.py
|
|
355
356
|
src/docvortex/foundation/_text.py
|
|
356
357
|
src/docvortex/foundation/image_encoding.py
|
|
357
358
|
src/docvortex/foundation/language.py
|
|
@@ -628,6 +629,7 @@ tests/unittest/test_render_html_table.py
|
|
|
628
629
|
tests/unittest/test_render_image_renderer.py
|
|
629
630
|
tests/unittest/test_render_list_index_utils.py
|
|
630
631
|
tests/unittest/test_structured_content_render.py
|
|
632
|
+
tests/unittest/test_svg_raster.py
|
|
631
633
|
tests/unittest/test_table_merge.py
|
|
632
634
|
tests/unittest/test_table_merge_cell_merge.py
|
|
633
635
|
tests/unittest/test_text_block_anchor.py
|