BabelDOC 0.3.61__tar.gz → 0.3.63__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.
Files changed (295) hide show
  1. {babeldoc-0.3.61 → babeldoc-0.3.63}/PKG-INFO +16 -3
  2. {babeldoc-0.3.61 → babeldoc-0.3.63}/README.md +15 -2
  3. babeldoc-0.3.63/babeldoc/__init__.py +1 -0
  4. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/assets/embedding_assets_metadata.py +21 -21
  5. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/const.py +1 -1
  6. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/detect_scanned_file.py +30 -6
  7. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/utils/fontmap.py +37 -0
  8. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/high_level.py +92 -0
  9. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/main.py +17 -1
  10. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/tools/generate_font_metadata.py +15 -1
  11. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/translation_config.py +16 -0
  12. {babeldoc-0.3.61 → babeldoc-0.3.63}/pyproject.toml +2 -2
  13. {babeldoc-0.3.61 → babeldoc-0.3.63}/uv.lock +1 -1
  14. babeldoc-0.3.61/babeldoc/__init__.py +0 -1
  15. {babeldoc-0.3.61 → babeldoc-0.3.63}/.cursorignore +0 -0
  16. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
  17. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
  18. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/PULL_REQUEST_TEMPLATE/pr_form.yml +0 -0
  19. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  20. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/dependabot.yml +0 -0
  21. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/labels.yml +0 -0
  22. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/release-drafter.yml +0 -0
  23. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/workflows/codeql.yml +0 -0
  24. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/workflows/docs.yml +0 -0
  25. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/workflows/labeler.yml +0 -0
  26. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/workflows/lint.yml +0 -0
  27. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/workflows/pr-lint.yml +0 -0
  28. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/workflows/publish-to-pypi.yml +0 -0
  29. {babeldoc-0.3.61 → babeldoc-0.3.63}/.github/workflows/test.yml +0 -0
  30. {babeldoc-0.3.61 → babeldoc-0.3.63}/.gitignore +0 -0
  31. {babeldoc-0.3.61 → babeldoc-0.3.63}/.pre-commit-config.yaml +0 -0
  32. {babeldoc-0.3.61 → babeldoc-0.3.63}/LICENSE +0 -0
  33. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/assets/assets.py +0 -0
  34. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/asynchronize/__init__.py +0 -0
  35. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/converter.py +0 -0
  36. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/__init__.py +0 -0
  37. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/babeldoc_exception/BabelDOCException.py +0 -0
  38. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/backend/__init__.py +0 -0
  39. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/backend/pdf_creater.py +0 -0
  40. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/frontend/__init__.py +0 -0
  41. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/frontend/il_creater.py +0 -0
  42. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/il_version_1.py +0 -0
  43. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/il_version_1.rnc +0 -0
  44. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/il_version_1.rng +0 -0
  45. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/il_version_1.xsd +0 -0
  46. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/__init__.py +0 -0
  47. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/add_debug_information.py +0 -0
  48. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/automatic_term_extractor.py +0 -0
  49. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/il_translator.py +0 -0
  50. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/il_translator_llm_only.py +0 -0
  51. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/layout_parser.py +0 -0
  52. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/paragraph_finder.py +0 -0
  53. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/remove_descent.py +0 -0
  54. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/styles_and_formulas.py +0 -0
  55. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/table_parser.py +0 -0
  56. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/midend/typesetting.py +0 -0
  57. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/translator/__init__.py +0 -0
  58. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/translator/cache.py +0 -0
  59. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/translator/translator.py +0 -0
  60. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/utils/atomic_integer.py +0 -0
  61. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/utils/layout_helper.py +0 -0
  62. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/utils/mupdf_helper.py +0 -0
  63. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/utils/paragraph_helper.py +0 -0
  64. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/utils/priority_thread_pool_executor.py +0 -0
  65. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/utils/style_helper.py +0 -0
  66. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/utils/zstd_helper.py +0 -0
  67. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/document_il/xml_converter.py +0 -0
  68. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/docvision/README.md +0 -0
  69. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/docvision/__init__.py +0 -0
  70. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/docvision/base_doclayout.py +0 -0
  71. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/docvision/doclayout.py +0 -0
  72. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/docvision/rpc_doclayout.py +0 -0
  73. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/docvision/table_detection/rapidocr.py +0 -0
  74. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/format/office/__init__.py +0 -0
  75. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/glossary.py +0 -0
  76. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfinterp.py +0 -0
  77. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/LICENSE +0 -0
  78. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/__init__.py +0 -0
  79. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/_saslprep.py +0 -0
  80. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/arcfour.py +0 -0
  81. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/ascii85.py +0 -0
  82. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/casting.py +0 -0
  83. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/ccitt.py +0 -0
  84. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/78-EUC-H.pickle.gz +0 -0
  85. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/78-EUC-V.pickle.gz +0 -0
  86. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/78-H.pickle.gz +0 -0
  87. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/78-RKSJ-H.pickle.gz +0 -0
  88. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/78-RKSJ-V.pickle.gz +0 -0
  89. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/78-V.pickle.gz +0 -0
  90. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/78ms-RKSJ-H.pickle.gz +0 -0
  91. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/78ms-RKSJ-V.pickle.gz +0 -0
  92. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/83pv-RKSJ-H.pickle.gz +0 -0
  93. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/83pv-RKSJ-V.pickle.gz +0 -0
  94. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/90ms-RKSJ-H.pickle.gz +0 -0
  95. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/90ms-RKSJ-V.pickle.gz +0 -0
  96. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/90msp-RKSJ-H.pickle.gz +0 -0
  97. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/90msp-RKSJ-V.pickle.gz +0 -0
  98. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/90pv-RKSJ-H.pickle.gz +0 -0
  99. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/90pv-RKSJ-V.pickle.gz +0 -0
  100. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Add-H.pickle.gz +0 -0
  101. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Add-RKSJ-H.pickle.gz +0 -0
  102. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Add-RKSJ-V.pickle.gz +0 -0
  103. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Add-V.pickle.gz +0 -0
  104. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/B5-H.pickle.gz +0 -0
  105. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/B5-V.pickle.gz +0 -0
  106. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/B5pc-H.pickle.gz +0 -0
  107. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/B5pc-V.pickle.gz +0 -0
  108. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/CNS-EUC-H.pickle.gz +0 -0
  109. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/CNS-EUC-V.pickle.gz +0 -0
  110. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/CNS1-H.pickle.gz +0 -0
  111. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/CNS1-V.pickle.gz +0 -0
  112. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/CNS2-H.pickle.gz +0 -0
  113. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/CNS2-V.pickle.gz +0 -0
  114. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/ETHK-B5-H.pickle.gz +0 -0
  115. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/ETHK-B5-V.pickle.gz +0 -0
  116. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/ETen-B5-H.pickle.gz +0 -0
  117. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/ETen-B5-V.pickle.gz +0 -0
  118. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/ETenms-B5-H.pickle.gz +0 -0
  119. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/ETenms-B5-V.pickle.gz +0 -0
  120. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/EUC-H.pickle.gz +0 -0
  121. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/EUC-V.pickle.gz +0 -0
  122. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Ext-H.pickle.gz +0 -0
  123. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Ext-RKSJ-H.pickle.gz +0 -0
  124. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Ext-RKSJ-V.pickle.gz +0 -0
  125. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Ext-V.pickle.gz +0 -0
  126. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GB-EUC-H.pickle.gz +0 -0
  127. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GB-EUC-V.pickle.gz +0 -0
  128. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GB-H.pickle.gz +0 -0
  129. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GB-V.pickle.gz +0 -0
  130. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBK-EUC-H.pickle.gz +0 -0
  131. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBK-EUC-V.pickle.gz +0 -0
  132. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBK2K-H.pickle.gz +0 -0
  133. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBK2K-V.pickle.gz +0 -0
  134. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBKp-EUC-H.pickle.gz +0 -0
  135. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBKp-EUC-V.pickle.gz +0 -0
  136. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBT-EUC-H.pickle.gz +0 -0
  137. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBT-EUC-V.pickle.gz +0 -0
  138. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBT-H.pickle.gz +0 -0
  139. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBT-V.pickle.gz +0 -0
  140. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBTpc-EUC-H.pickle.gz +0 -0
  141. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBTpc-EUC-V.pickle.gz +0 -0
  142. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBpc-EUC-H.pickle.gz +0 -0
  143. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/GBpc-EUC-V.pickle.gz +0 -0
  144. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/H.pickle.gz +0 -0
  145. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKdla-B5-H.pickle.gz +0 -0
  146. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKdla-B5-V.pickle.gz +0 -0
  147. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKdlb-B5-H.pickle.gz +0 -0
  148. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKdlb-B5-V.pickle.gz +0 -0
  149. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKgccs-B5-H.pickle.gz +0 -0
  150. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKgccs-B5-V.pickle.gz +0 -0
  151. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKm314-B5-H.pickle.gz +0 -0
  152. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKm314-B5-V.pickle.gz +0 -0
  153. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKm471-B5-H.pickle.gz +0 -0
  154. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKm471-B5-V.pickle.gz +0 -0
  155. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKscs-B5-H.pickle.gz +0 -0
  156. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/HKscs-B5-V.pickle.gz +0 -0
  157. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Hankaku-H.pickle.gz +0 -0
  158. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Hankaku-V.pickle.gz +0 -0
  159. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Hiragana-H.pickle.gz +0 -0
  160. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Hiragana-V.pickle.gz +0 -0
  161. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSC-EUC-H.pickle.gz +0 -0
  162. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSC-EUC-V.pickle.gz +0 -0
  163. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSC-H.pickle.gz +0 -0
  164. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSC-Johab-H.pickle.gz +0 -0
  165. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSC-Johab-V.pickle.gz +0 -0
  166. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSC-V.pickle.gz +0 -0
  167. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSCms-UHC-H.pickle.gz +0 -0
  168. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSCms-UHC-HW-H.pickle.gz +0 -0
  169. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSCms-UHC-HW-V.pickle.gz +0 -0
  170. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSCms-UHC-V.pickle.gz +0 -0
  171. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSCpc-EUC-H.pickle.gz +0 -0
  172. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/KSCpc-EUC-V.pickle.gz +0 -0
  173. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Katakana-H.pickle.gz +0 -0
  174. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Katakana-V.pickle.gz +0 -0
  175. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/NWP-H.pickle.gz +0 -0
  176. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/NWP-V.pickle.gz +0 -0
  177. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/README.txt +0 -0
  178. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/RKSJ-H.pickle.gz +0 -0
  179. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/RKSJ-V.pickle.gz +0 -0
  180. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Roman-H.pickle.gz +0 -0
  181. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/Roman-V.pickle.gz +0 -0
  182. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniCNS-UCS2-H.pickle.gz +0 -0
  183. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniCNS-UCS2-V.pickle.gz +0 -0
  184. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniCNS-UTF16-H.pickle.gz +0 -0
  185. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniCNS-UTF16-V.pickle.gz +0 -0
  186. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniCNS-UTF32-H.pickle.gz +0 -0
  187. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniCNS-UTF32-V.pickle.gz +0 -0
  188. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniCNS-UTF8-H.pickle.gz +0 -0
  189. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniCNS-UTF8-V.pickle.gz +0 -0
  190. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniGB-UCS2-H.pickle.gz +0 -0
  191. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniGB-UCS2-V.pickle.gz +0 -0
  192. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniGB-UTF16-H.pickle.gz +0 -0
  193. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniGB-UTF16-V.pickle.gz +0 -0
  194. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniGB-UTF32-H.pickle.gz +0 -0
  195. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniGB-UTF32-V.pickle.gz +0 -0
  196. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniGB-UTF8-H.pickle.gz +0 -0
  197. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniGB-UTF8-V.pickle.gz +0 -0
  198. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS-UCS2-H.pickle.gz +0 -0
  199. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS-UCS2-HW-H.pickle.gz +0 -0
  200. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS-UCS2-HW-V.pickle.gz +0 -0
  201. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS-UCS2-V.pickle.gz +0 -0
  202. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS-UTF16-H.pickle.gz +0 -0
  203. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS-UTF16-V.pickle.gz +0 -0
  204. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS-UTF32-H.pickle.gz +0 -0
  205. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS-UTF32-V.pickle.gz +0 -0
  206. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS-UTF8-H.pickle.gz +0 -0
  207. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS-UTF8-V.pickle.gz +0 -0
  208. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS2004-UTF16-H.pickle.gz +0 -0
  209. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS2004-UTF16-V.pickle.gz +0 -0
  210. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS2004-UTF32-H.pickle.gz +0 -0
  211. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS2004-UTF32-V.pickle.gz +0 -0
  212. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS2004-UTF8-H.pickle.gz +0 -0
  213. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJIS2004-UTF8-V.pickle.gz +0 -0
  214. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJISX0213-UTF32-H.pickle.gz +0 -0
  215. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJISX0213-UTF32-V.pickle.gz +0 -0
  216. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJISX02132004-UTF32-H.pickle.gz +0 -0
  217. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniJISX02132004-UTF32-V.pickle.gz +0 -0
  218. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniKS-UCS2-H.pickle.gz +0 -0
  219. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniKS-UCS2-V.pickle.gz +0 -0
  220. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniKS-UTF16-H.pickle.gz +0 -0
  221. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniKS-UTF16-V.pickle.gz +0 -0
  222. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniKS-UTF32-H.pickle.gz +0 -0
  223. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniKS-UTF32-V.pickle.gz +0 -0
  224. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniKS-UTF8-H.pickle.gz +0 -0
  225. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/UniKS-UTF8-V.pickle.gz +0 -0
  226. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/V.pickle.gz +0 -0
  227. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/WP-Symbol-H.pickle.gz +0 -0
  228. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/WP-Symbol-V.pickle.gz +0 -0
  229. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/to-unicode-Adobe-CNS1.pickle.gz +0 -0
  230. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/to-unicode-Adobe-GB1.pickle.gz +0 -0
  231. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/to-unicode-Adobe-Japan1.pickle.gz +0 -0
  232. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmap/to-unicode-Adobe-Korea1.pickle.gz +0 -0
  233. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/cmapdb.py +0 -0
  234. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/converter.py +0 -0
  235. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/data_structures.py +0 -0
  236. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/encodingdb.py +0 -0
  237. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/fontmetrics.py +0 -0
  238. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/glyphlist.py +0 -0
  239. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/high_level.py +0 -0
  240. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/image.py +0 -0
  241. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/jbig2.py +0 -0
  242. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/latin_enc.py +0 -0
  243. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/layout.py +0 -0
  244. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/lzw.py +0 -0
  245. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/pdfcolor.py +0 -0
  246. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/pdfdevice.py +0 -0
  247. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/pdfdocument.py +0 -0
  248. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/pdfexceptions.py +0 -0
  249. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/pdffont.py +0 -0
  250. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/pdfinterp.py +0 -0
  251. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/pdfpage.py +0 -0
  252. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/pdfparser.py +0 -0
  253. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/pdftypes.py +0 -0
  254. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/psexceptions.py +0 -0
  255. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/psparser.py +0 -0
  256. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/py.typed +0 -0
  257. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/runlength.py +0 -0
  258. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/settings.py +0 -0
  259. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/pdfminer/utils.py +0 -0
  260. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/progress_monitor.py +0 -0
  261. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/result_merger.py +0 -0
  262. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/split_manager.py +0 -0
  263. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/tools/italic_assistance.py +0 -0
  264. {babeldoc-0.3.61 → babeldoc-0.3.63}/babeldoc/tools/italic_recognize_tool.py +0 -0
  265. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/CODE_OF_CONDUCT.md +0 -0
  266. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/CONTRIBUTING.md +0 -0
  267. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/CONTRIBUTOR_REWARD.md +0 -0
  268. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md +0 -0
  269. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/ImplementationDetails/ILTranslator/ILTranslator.md +0 -0
  270. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/ImplementationDetails/PDFCreation/PDFCreation.md +0 -0
  271. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/ImplementationDetails/PDFParsing/PDFParsing.md +0 -0
  272. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md +0 -0
  273. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/ImplementationDetails/README.md +0 -0
  274. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/ImplementationDetails/StylesAndFormulas/StylesAndFormulas.md +0 -0
  275. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/ImplementationDetails/Typesetting/Typesetting.md +0 -0
  276. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/README.md +0 -0
  277. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/deploy.sh +0 -0
  278. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/example/demo_glossary.csv +0 -0
  279. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-banner.png +0 -0
  280. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.png +0 -0
  281. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-big-logo-darkmode-with-transparent-background.svg +0 -0
  282. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-big-logo-with-transparent-background.png +0 -0
  283. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-big-logo-with-transparent-background.svg +0 -0
  284. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-big-logo.png +0 -0
  285. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-contributor_reward_example.png +0 -0
  286. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-preview.gif +0 -0
  287. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-small-logo-with-transparent-background.png +0 -0
  288. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-small-logo-with-transparent-background.svg +0 -0
  289. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/images/babeldoc-small-logo.png +0 -0
  290. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/index.md +0 -0
  291. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/intro-to-pdf-object.md +0 -0
  292. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/requirements.txt +0 -0
  293. {babeldoc-0.3.61 → babeldoc-0.3.63}/docs/supported_languages.md +0 -0
  294. {babeldoc-0.3.61 → babeldoc-0.3.63}/mkdocs.yml +0 -0
  295. {babeldoc-0.3.61 → babeldoc-0.3.63}/tests/test_translation_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: BabelDOC
3
- Version: 0.3.61
3
+ Version: 0.3.63
4
4
  Summary: Yet Another Document Translator
5
5
  Project-URL: Homepage, https://github.com/funstory-ai/BabelDOC
6
6
  Project-URL: Issues, https://github.com/funstory-ai/BabelDOC/issues
@@ -210,7 +210,8 @@ uv run babeldoc --files example.pdf --files example2.pdf --openai --openai-model
210
210
  - `--show-char-box`: Show character bounding boxes (debug only, default: False)
211
211
  - `--skip-scanned-detection`: Skip scanned document detection (default: False). When using split translation, only the first part performs detection if not skipped.
212
212
  - `--ocr-workaround`: Use OCR workaround (default: False). Only suitable for documents with black text on white background. When enabled, white rectangular blocks will be added below the translation to cover the original text content, and all text will be forced to black color.
213
-
213
+ - `--auto-enable-ocr-workaround`: Enable automatic OCR workaround (default: False). If a document is detected as heavily scanned, this will attempt to enable OCR processing and skip further scan detection. See "Important Interaction Note" below for crucial details on how this interacts with `--ocr-workaround` and `--skip-scanned-detection`.
214
+ - `--primary-font-family`: Override primary font family for translated text. Choices: 'serif' for serif fonts, 'sans-serif' for sans-serif fonts, 'script' for script/italic fonts. If not specified, uses automatic font selection based on original text properties.
214
215
 
215
216
  - `--rpc-doclayout`: RPC service host address for document layout analysis (default: None)
216
217
  - `--working-dir`: Working directory for translation. If not set, use temp directory.
@@ -328,6 +329,7 @@ show_char_box = false # Show character bounding boxes (debug)
328
329
  ocr_workaround = false # Use OCR workaround for scanned PDFs
329
330
  rpc_doclayout = "" # RPC service host for document layout analysis
330
331
  working_dir = "" # Working directory for translation
332
+ auto_enable_ocr_workaround = false # Enable automatic OCR workaround for scanned PDFs. See docs for interaction with ocr_workaround and skip_scanned_detection.
331
333
 
332
334
  # Translation service
333
335
  openai = true
@@ -477,4 +479,15 @@ Everyone interacting in YADT and its sub-projects' codebases, issue trackers, ch
477
479
  <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=funstory-ai/babeldoc&type=Date" />
478
480
  <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=funstory-ai/babeldoc&type=Date"/>
479
481
  </picture>
480
- </a>
482
+ </a>
483
+
484
+ > [!WARNING]
485
+ > **Important Interaction Note for `--auto-enable-ocr-workaround`:**
486
+ >
487
+ > When `--auto-enable-ocr-workaround` is set to `true` (either via command line or config file):
488
+ >
489
+ > 1. During the initial setup, the values for `ocr_workaround` and `skip_scanned_detection` will be forced to `false` by `TranslationConfig`, regardless of whether you also set `--ocr-workaround` or `--skip-scanned-detection` flags.
490
+ > 2. Then, during the scanned document detection phase (`DetectScannedFile` stage):
491
+ > * If the document is identified as heavily scanned (e.g., >80% scanned pages) AND `auto_enable_ocr_workaround` is `true` (i.e., `translation_config.auto_enable_ocr_workaround` is true), the system will then attempt to set both `ocr_workaround` to `true` and `skip_scanned_detection` to `true`.
492
+ >
493
+ > This means that `--auto-enable-ocr-workaround` effectively gives the system control to enable OCR processing for scanned documents, potentially overriding manual settings for `--ocr-workaround` and `--skip_scanned_detection` based on its detection results. If the document is *not* detected as heavily scanned, then the initial `false` values for `ocr_workaround` and `skip_scanned_detection` (forced by `--auto-enable-ocr-workaround` at the `TranslationConfig` initialization stage) will remain in effect unless changed by other logic.
@@ -159,7 +159,8 @@ uv run babeldoc --files example.pdf --files example2.pdf --openai --openai-model
159
159
  - `--show-char-box`: Show character bounding boxes (debug only, default: False)
160
160
  - `--skip-scanned-detection`: Skip scanned document detection (default: False). When using split translation, only the first part performs detection if not skipped.
161
161
  - `--ocr-workaround`: Use OCR workaround (default: False). Only suitable for documents with black text on white background. When enabled, white rectangular blocks will be added below the translation to cover the original text content, and all text will be forced to black color.
162
-
162
+ - `--auto-enable-ocr-workaround`: Enable automatic OCR workaround (default: False). If a document is detected as heavily scanned, this will attempt to enable OCR processing and skip further scan detection. See "Important Interaction Note" below for crucial details on how this interacts with `--ocr-workaround` and `--skip-scanned-detection`.
163
+ - `--primary-font-family`: Override primary font family for translated text. Choices: 'serif' for serif fonts, 'sans-serif' for sans-serif fonts, 'script' for script/italic fonts. If not specified, uses automatic font selection based on original text properties.
163
164
 
164
165
  - `--rpc-doclayout`: RPC service host address for document layout analysis (default: None)
165
166
  - `--working-dir`: Working directory for translation. If not set, use temp directory.
@@ -277,6 +278,7 @@ show_char_box = false # Show character bounding boxes (debug)
277
278
  ocr_workaround = false # Use OCR workaround for scanned PDFs
278
279
  rpc_doclayout = "" # RPC service host for document layout analysis
279
280
  working_dir = "" # Working directory for translation
281
+ auto_enable_ocr_workaround = false # Enable automatic OCR workaround for scanned PDFs. See docs for interaction with ocr_workaround and skip_scanned_detection.
280
282
 
281
283
  # Translation service
282
284
  openai = true
@@ -426,4 +428,15 @@ Everyone interacting in YADT and its sub-projects' codebases, issue trackers, ch
426
428
  <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=funstory-ai/babeldoc&type=Date" />
427
429
  <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=funstory-ai/babeldoc&type=Date"/>
428
430
  </picture>
429
- </a>
431
+ </a>
432
+
433
+ > [!WARNING]
434
+ > **Important Interaction Note for `--auto-enable-ocr-workaround`:**
435
+ >
436
+ > When `--auto-enable-ocr-workaround` is set to `true` (either via command line or config file):
437
+ >
438
+ > 1. During the initial setup, the values for `ocr_workaround` and `skip_scanned_detection` will be forced to `false` by `TranslationConfig`, regardless of whether you also set `--ocr-workaround` or `--skip-scanned-detection` flags.
439
+ > 2. Then, during the scanned document detection phase (`DetectScannedFile` stage):
440
+ > * If the document is identified as heavily scanned (e.g., >80% scanned pages) AND `auto_enable_ocr_workaround` is `true` (i.e., `translation_config.auto_enable_ocr_workaround` is true), the system will then attempt to set both `ocr_workaround` to `true` and `skip_scanned_detection` to `true`.
441
+ >
442
+ > This means that `--auto-enable-ocr-workaround` effectively gives the system control to enable OCR processing for scanned documents, potentially overriding manual settings for `--ocr-workaround` and `--skip_scanned_detection` based on its detection results. If the document is *not* detected as heavily scanned, then the initial `false` values for `ocr_workaround` and `skip_scanned_detection` (forced by `--auto-enable-ocr-workaround` at the `TranslationConfig` initialization stage) will remain in effect unless changed by other logic.
@@ -0,0 +1 @@
1
+ __version__ = "0.3.63"
@@ -49,7 +49,7 @@ EMBEDDING_FONT_METADATA = {
49
49
  "font_name": "Go Noto Kurrent-Bold Bold",
50
50
  "italic": 0,
51
51
  "monospace": 0,
52
- "serif": 1,
52
+ "serif": 0,
53
53
  "sha3_256": "000b37f592477945b27b7702dcad39f73e23e140e66ddff9847eb34f32389566",
54
54
  "size": 15303772,
55
55
  },
@@ -62,7 +62,7 @@ EMBEDDING_FONT_METADATA = {
62
62
  "font_name": "Go Noto Kurrent-Regular Regular",
63
63
  "italic": 0,
64
64
  "monospace": 0,
65
- "serif": 1,
65
+ "serif": 0,
66
66
  "sha3_256": "4324a60d507c691e6efc97420647f4d2c2d86d9de35009d1c769861b76074ae6",
67
67
  "size": 15515760,
68
68
  },
@@ -75,7 +75,7 @@ EMBEDDING_FONT_METADATA = {
75
75
  "font_name": "Klee One Regular",
76
76
  "italic": 0,
77
77
  "monospace": 0,
78
- "serif": 1,
78
+ "serif": 0,
79
79
  "sha3_256": "8585c29f89b322d937f83739f61ede5d84297873e1465cad9a120a208ac55ce0",
80
80
  "size": 8724704,
81
81
  },
@@ -88,7 +88,7 @@ EMBEDDING_FONT_METADATA = {
88
88
  "font_name": "LXGW WenKai GB Regular",
89
89
  "italic": 0,
90
90
  "monospace": 0,
91
- "serif": 1,
91
+ "serif": 0,
92
92
  "sha3_256": "b563a5e8d9db4cd15602a3a3700b01925e80a21f99fb88e1b763b1fb8685f8ee",
93
93
  "size": 19558756,
94
94
  },
@@ -101,7 +101,7 @@ EMBEDDING_FONT_METADATA = {
101
101
  "font_name": "LXGW WenKai Mono TC Regular",
102
102
  "italic": 0,
103
103
  "monospace": 1,
104
- "serif": 1,
104
+ "serif": 0,
105
105
  "sha3_256": "596b278d11418d374a1cfa3a50cbfb82b31db82d3650cfacae8f94311b27fdc5",
106
106
  "size": 13115416,
107
107
  },
@@ -114,7 +114,7 @@ EMBEDDING_FONT_METADATA = {
114
114
  "font_name": "LXGW WenKai TC Regular",
115
115
  "italic": 0,
116
116
  "monospace": 0,
117
- "serif": 1,
117
+ "serif": 0,
118
118
  "sha3_256": "66ccd0ffe8e56cd585dabde8d1292c3f551b390d8ed85f81d7a844825f9c2379",
119
119
  "size": 13100328,
120
120
  },
@@ -127,7 +127,7 @@ EMBEDDING_FONT_METADATA = {
127
127
  "font_name": "MaruBuri Regular",
128
128
  "italic": 0,
129
129
  "monospace": 0,
130
- "serif": 1,
130
+ "serif": 0,
131
131
  "sha3_256": "abb672dde7b89e06914ce27c59159b7a2933f26207bfcc47981c67c11c41e6d1",
132
132
  "size": 3268988,
133
133
  },
@@ -140,7 +140,7 @@ EMBEDDING_FONT_METADATA = {
140
140
  "font_name": "Noto Sans Bold",
141
141
  "italic": 0,
142
142
  "monospace": 0,
143
- "serif": 1,
143
+ "serif": 0,
144
144
  "sha3_256": "ecd38d472c1cad07d8a5dffd2b5a0f72edcd40fff2b4e68d770da8f2ef343a82",
145
145
  "size": 630964,
146
146
  },
@@ -153,7 +153,7 @@ EMBEDDING_FONT_METADATA = {
153
153
  "font_name": "Noto Sans Bold Italic",
154
154
  "italic": 1,
155
155
  "monospace": 0,
156
- "serif": 1,
156
+ "serif": 0,
157
157
  "sha3_256": "0b6c690a4a6b7d605b2ecbde00c7ac1a23e60feb17fa30d8b972d61ec3ff732b",
158
158
  "size": 644340,
159
159
  },
@@ -166,7 +166,7 @@ EMBEDDING_FONT_METADATA = {
166
166
  "font_name": "Noto Sans Italic",
167
167
  "italic": 1,
168
168
  "monospace": 0,
169
- "serif": 1,
169
+ "serif": 0,
170
170
  "sha3_256": "830652f61724c017e5a29a96225b484a2ccbd25f69a1b3f47e5f466a2dbed1ad",
171
171
  "size": 642344,
172
172
  },
@@ -179,7 +179,7 @@ EMBEDDING_FONT_METADATA = {
179
179
  "font_name": "Noto Sans Regular",
180
180
  "italic": 0,
181
181
  "monospace": 0,
182
- "serif": 1,
182
+ "serif": 0,
183
183
  "sha3_256": "7dfe2bbf97dc04c852d1223b220b63430e6ad03b0dbb28ebe6328a20a2d45eb8",
184
184
  "size": 629024,
185
185
  },
@@ -244,7 +244,7 @@ EMBEDDING_FONT_METADATA = {
244
244
  "font_name": "Source Han Sans CN Bold",
245
245
  "italic": 0,
246
246
  "monospace": 0,
247
- "serif": 1,
247
+ "serif": 0,
248
248
  "sha3_256": "82314c11016a04ef03e7afd00abe0ccc8df54b922dee79abf6424f3002a31825",
249
249
  "size": 10174460,
250
250
  },
@@ -257,7 +257,7 @@ EMBEDDING_FONT_METADATA = {
257
257
  "font_name": "Source Han Sans CN Regular",
258
258
  "italic": 0,
259
259
  "monospace": 0,
260
- "serif": 1,
260
+ "serif": 0,
261
261
  "sha3_256": "b45a80cf3650bfc62aa014e58243c6325e182c4b0c5819e41a583c699cce9a8f",
262
262
  "size": 10397552,
263
263
  },
@@ -270,7 +270,7 @@ EMBEDDING_FONT_METADATA = {
270
270
  "font_name": "Source Han Sans HK Bold",
271
271
  "italic": 0,
272
272
  "monospace": 0,
273
- "serif": 1,
273
+ "serif": 0,
274
274
  "sha3_256": "3eecd57457ba9a0fbad6c794f40e7ae704c4f825091aef2ac18902ffdde50608",
275
275
  "size": 6856692,
276
276
  },
@@ -283,7 +283,7 @@ EMBEDDING_FONT_METADATA = {
283
283
  "font_name": "Source Han Sans HK Regular",
284
284
  "italic": 0,
285
285
  "monospace": 0,
286
- "serif": 1,
286
+ "serif": 0,
287
287
  "sha3_256": "5fe4141f9164c03616323400b2936ee4c8265314492e2b822c3a6fbfb63ffe08",
288
288
  "size": 6999792,
289
289
  },
@@ -296,7 +296,7 @@ EMBEDDING_FONT_METADATA = {
296
296
  "font_name": "Source Han Sans JP Bold",
297
297
  "italic": 0,
298
298
  "monospace": 0,
299
- "serif": 1,
299
+ "serif": 0,
300
300
  "sha3_256": "fb05bd84d62e8064117ee357ab6a4481e1cde931e8e984c0553c8c4b09dc3938",
301
301
  "size": 5603068,
302
302
  },
@@ -309,7 +309,7 @@ EMBEDDING_FONT_METADATA = {
309
309
  "font_name": "Source Han Sans JP Regular",
310
310
  "italic": 0,
311
311
  "monospace": 0,
312
- "serif": 1,
312
+ "serif": 0,
313
313
  "sha3_256": "722cfbdcc0fd83fe07a3d1b10e9e64343c924a351d02cfe8dbb6ec4c6bc38230",
314
314
  "size": 5723960,
315
315
  },
@@ -322,7 +322,7 @@ EMBEDDING_FONT_METADATA = {
322
322
  "font_name": "Source Han Sans KR Bold",
323
323
  "italic": 0,
324
324
  "monospace": 0,
325
- "serif": 1,
325
+ "serif": 0,
326
326
  "sha3_256": "02959eb2c1eea0786a736aeb50b6e61f2ab873cd69c659389b7511f80f734838",
327
327
  "size": 5858892,
328
328
  },
@@ -335,7 +335,7 @@ EMBEDDING_FONT_METADATA = {
335
335
  "font_name": "Source Han Sans KR Regular",
336
336
  "italic": 0,
337
337
  "monospace": 0,
338
- "serif": 1,
338
+ "serif": 0,
339
339
  "sha3_256": "aba70109eff718e8f796f0185f8dca38026c1661b43c195883c84577e501adf2",
340
340
  "size": 5961704,
341
341
  },
@@ -348,7 +348,7 @@ EMBEDDING_FONT_METADATA = {
348
348
  "font_name": "Source Han Sans TW Bold",
349
349
  "italic": 0,
350
350
  "monospace": 0,
351
- "serif": 1,
351
+ "serif": 0,
352
352
  "sha3_256": "4a92730e644a1348e87bba7c77e9b462f257f381bd6abbeac5860d8f8306aee6",
353
353
  "size": 6883224,
354
354
  },
@@ -361,7 +361,7 @@ EMBEDDING_FONT_METADATA = {
361
361
  "font_name": "Source Han Sans TW Regular",
362
362
  "italic": 0,
363
363
  "monospace": 0,
364
- "serif": 1,
364
+ "serif": 0,
365
365
  "sha3_256": "6129b68ff4b0814624cac7edca61fbacf8f4d79db6f4c3cfc46b1c48ea2f81ac",
366
366
  "size": 7024812,
367
367
  },
@@ -3,7 +3,7 @@ import shutil
3
3
  import subprocess
4
4
  from pathlib import Path
5
5
 
6
- __version__ = "0.3.61"
6
+ __version__ = "0.3.63"
7
7
 
8
8
  CACHE_FOLDER = Path.home() / ".cache" / "babeldoc"
9
9
 
@@ -3,6 +3,7 @@ import logging
3
3
  import cv2
4
4
  import numpy as np
5
5
  import pymupdf
6
+ import regex
6
7
  from skimage.metrics import structural_similarity
7
8
 
8
9
  from babeldoc.document_il import il_version_1
@@ -63,6 +64,20 @@ class DetectScannedFile:
63
64
  ),
64
65
  )
65
66
 
67
+ def fast_check(self, doc: pymupdf.Document) -> bool:
68
+ if doc:
69
+ hit_list = [0] * len(doc)
70
+ for page in doc:
71
+ contents_list = page.get_contents()
72
+ for index in contents_list:
73
+ contents = doc.xref_stream(index)
74
+ if regex.search(rb"/Artifact(\s*\<\<|\s+BDC)", contents):
75
+ hit_list[page.number] += 1
76
+ if regex.search(rb"\s3\s+Tr\s", contents):
77
+ hit_list[page.number] += 1
78
+ return bool(sum(hit_list) > len(doc) * 0.8)
79
+ return False
80
+
66
81
  def process(self, docs: il_version_1.Document):
67
82
  """Generate layouts for all pages that need to be translated."""
68
83
  # Get pages that need to be translated
@@ -96,11 +111,20 @@ class DetectScannedFile:
96
111
  progress.advance(1)
97
112
 
98
113
  if scanned > threshold:
99
- logger.warning(
100
- f"Detected {scanned} scanned pages, which is more than 80% of the total pages. "
101
- "Please check the input PDF file.",
102
- )
103
- raise ScannedPDFError("Scanned PDF detected.")
114
+ if self.translation_config.auto_enable_ocr_workaround:
115
+ logger.warning(
116
+ f"Detected {scanned} scanned pages, which is more than 80% of the total pages. "
117
+ "Turning on OCR workaround.",
118
+ )
119
+ self.translation_config.shared_context_cross_split_part.auto_enabled_ocr_workaround = True
120
+ self.translation_config.ocr_workaround = True
121
+ self.translation_config.skip_scanned_detection = True
122
+ else:
123
+ logger.warning(
124
+ f"Detected {scanned} scanned pages, which is more than 80% of the total pages. "
125
+ "Please check the input PDF file.",
126
+ )
127
+ raise ScannedPDFError("Scanned PDF detected.")
104
128
 
105
129
  @staticmethod
106
130
  def detect_page_is_scanned(page: il_version_1.Page, pdf: pymupdf.Document) -> bool:
@@ -130,4 +154,4 @@ class DetectScannedFile:
130
154
  )[:, :, ::-1]
131
155
  before_page_image = cv2.cvtColor(before_page_image, cv2.COLOR_RGB2GRAY)
132
156
  after_page_image = cv2.cvtColor(after_page_image, cv2.COLOR_RGB2GRAY)
133
- return structural_similarity(before_page_image, after_page_image) > 0.98
157
+ return structural_similarity(before_page_image, after_page_image) > 0.97
@@ -1,3 +1,4 @@
1
+ import enum
1
2
  import functools
2
3
  import logging
3
4
  import re
@@ -12,11 +13,39 @@ from babeldoc.translation_config import TranslationConfig
12
13
  logger = logging.getLogger(__name__)
13
14
 
14
15
 
16
+ class PrimaryFontFamily(enum.IntEnum):
17
+ SERIF = 1
18
+ SANS_SERIF = 2
19
+ SCRIPT = 3
20
+ NONE = 4
21
+
22
+ @classmethod
23
+ def from_str(cls, value: str):
24
+ if value == "serif":
25
+ return cls.SERIF
26
+ elif value == "sans-serif":
27
+ return cls.SANS_SERIF
28
+ elif value == "script":
29
+ return cls.SCRIPT
30
+ else:
31
+ return cls.NONE
32
+
33
+
15
34
  class FontMapper:
16
35
  stage_name = "Add Fonts"
17
36
 
18
37
  def __init__(self, translation_config: TranslationConfig):
19
38
  self.translation_config = translation_config
39
+ assert translation_config.primary_font_family in [
40
+ None,
41
+ "serif",
42
+ "sans-serif",
43
+ "script",
44
+ ]
45
+ self.primary_font_family = PrimaryFontFamily.from_str(
46
+ translation_config.primary_font_family,
47
+ )
48
+
20
49
  font_family = assets.get_font_family(translation_config.lang_out)
21
50
  self.font_file_names = []
22
51
  for k in (
@@ -141,6 +170,14 @@ class FontMapper:
141
170
  )
142
171
  return None
143
172
 
173
+ if self.primary_font_family == PrimaryFontFamily.SERIF:
174
+ serif = True
175
+ elif self.primary_font_family == PrimaryFontFamily.SANS_SERIF:
176
+ serif = False
177
+ elif self.primary_font_family == PrimaryFontFamily.SCRIPT:
178
+ serif = False
179
+ italic = True
180
+
144
181
  script_font_map_result = self.map_in_type(
145
182
  bold, italic, monospaced, serif, char_unicode, "script"
146
183
  )
@@ -4,6 +4,7 @@ import hashlib
4
4
  import io
5
5
  import logging
6
6
  import pathlib
7
+ import re
7
8
  import shutil
8
9
  import threading
9
10
  import time
@@ -21,6 +22,8 @@ from babeldoc.assets.assets import warmup
21
22
  from babeldoc.const import CACHE_FOLDER
22
23
  from babeldoc.converter import TranslateConverter
23
24
  from babeldoc.document_il import il_version_1
25
+ from babeldoc.document_il.babeldoc_exception.BabelDOCException import ExtractTextError
26
+ from babeldoc.document_il.babeldoc_exception.BabelDOCException import ScannedPDFError
24
27
  from babeldoc.document_il.backend.pdf_creater import SAVE_PDF_STAGE_NAME
25
28
  from babeldoc.document_il.backend.pdf_creater import SUBSET_FONT_STAGE_NAME
26
29
  from babeldoc.document_il.backend.pdf_creater import PDFCreater
@@ -595,6 +598,12 @@ def do_translate(
595
598
  # not being able to copy translated text can be fixed,
596
599
  # the macOS preview is broken
597
600
  # fix_cmap(result, translation_config)
601
+ try:
602
+ migrate_toc(translation_config, result)
603
+ except Exception as e:
604
+ logger.error(
605
+ f"Failed to migrate TOC from {translation_config.input_file}: {e}"
606
+ )
598
607
  pm.translate_done(result)
599
608
  return result
600
609
 
@@ -612,6 +621,51 @@ def do_translate(
612
621
  translation_config.cleanup_temp_files()
613
622
 
614
623
 
624
+ def migrate_toc(
625
+ translation_config: TranslationConfig, translate_result: TranslateResult
626
+ ):
627
+ old_doc = Document(translation_config.input_file)
628
+ if not old_doc:
629
+ return
630
+
631
+ try:
632
+ fix_filter(old_doc)
633
+ fix_null_xref(old_doc)
634
+ except Exception:
635
+ logger.exception("auto fix failed, please check the pdf file")
636
+
637
+ toc_data = old_doc.get_toc()
638
+
639
+ if not toc_data:
640
+ logger.info("No TOC found in the original PDF, skipping migration.")
641
+ return
642
+
643
+ files = {
644
+ translate_result.dual_pdf_path,
645
+ # translate_result.mono_pdf_path,
646
+ translate_result.no_watermark_dual_pdf_path,
647
+ # translate_result.no_watermark_mono_pdf_path
648
+ }
649
+
650
+ for f in files:
651
+ mig_toc_temp_input = translation_config.get_working_file_path(
652
+ "mig_toc_temp.pdf"
653
+ )
654
+ shutil.copy(f, mig_toc_temp_input)
655
+ new_doc = Document(mig_toc_temp_input.as_posix())
656
+ if not new_doc:
657
+ continue
658
+
659
+ new_doc.set_toc(toc_data)
660
+ PDFCreater.save_pdf_with_timeout(
661
+ new_doc,
662
+ f.as_posix(),
663
+ translation_config=translation_config,
664
+ clean=not translation_config.skip_clean,
665
+ tag="mig_toc",
666
+ )
667
+
668
+
615
669
  def fix_media_box(doc: Document) -> None:
616
670
  mediabox_data = {}
617
671
  for x in range(1, doc.xref_length()):
@@ -633,12 +687,30 @@ def fix_media_box(doc: Document) -> None:
633
687
  return mediabox_data
634
688
 
635
689
 
690
+ def check_cid_char(il: il_version_1.Document):
691
+ chars = []
692
+ for page in il.page:
693
+ chars.extend(page.pdf_character)
694
+
695
+ cid_count = 0
696
+ for char in chars:
697
+ if re.match(r"^\(cid:\d+\)$", char.char_unicode):
698
+ cid_count += 1
699
+
700
+ return cid_count > len(chars) * 0.8
701
+
702
+
636
703
  def _do_translate_single(
637
704
  pm: ProgressMonitor,
638
705
  translation_config: TranslationConfig,
639
706
  ) -> TranslateResult:
640
707
  """Original translation logic for a single document or part"""
641
708
  translation_config.progress_monitor = pm
709
+
710
+ if translation_config.shared_context_cross_split_part.auto_enabled_ocr_workaround:
711
+ translation_config.ocr_workaround = True
712
+ translation_config.skip_scanned_detection = True
713
+
642
714
  original_pdf_path = translation_config.input_file
643
715
  if translation_config.debug:
644
716
  doc_input = Document(original_pdf_path)
@@ -674,6 +746,23 @@ def _do_translate_single(
674
746
 
675
747
  resfont = None
676
748
  doc_pdf2zh.save(temp_pdf_path)
749
+
750
+ if not translation_config.skip_scanned_detection and DetectScannedFile(
751
+ translation_config
752
+ ).fast_check(doc_pdf2zh):
753
+ if translation_config.auto_enable_ocr_workaround:
754
+ logger.warning(
755
+ "Fast scanned check hit, Turning on OCR workaround.",
756
+ )
757
+ translation_config.shared_context_cross_split_part.auto_enabled_ocr_workaround = True
758
+ translation_config.ocr_workaround = True
759
+ translation_config.skip_scanned_detection = True
760
+ else:
761
+ logger.warning(
762
+ "Fast scanned check hit, Please check the input PDF file.",
763
+ )
764
+ raise ScannedPDFError("Scanned PDF detected.")
765
+
677
766
  il_creater = ILCreater(translation_config)
678
767
  il_creater.mupdf = doc_pdf2zh
679
768
  xml_converter = XMLConverter()
@@ -696,6 +785,9 @@ def _do_translate_single(
696
785
  translation_config.get_working_file_path("create_il.debug.json"),
697
786
  )
698
787
 
788
+ if check_cid_char(docs):
789
+ raise ExtractTextError("The document contains too many CID chars.")
790
+
699
791
  # Rest of the original translation logic...
700
792
  # [Previous implementation of do_translate continues here]
701
793
 
@@ -21,7 +21,7 @@ from babeldoc.translation_config import TranslationConfig
21
21
  from babeldoc.translation_config import WatermarkOutputMode
22
22
 
23
23
  logger = logging.getLogger(__name__)
24
- __version__ = "0.3.61"
24
+ __version__ = "0.3.63"
25
25
 
26
26
 
27
27
  def create_parser():
@@ -248,6 +248,19 @@ def create_parser():
248
248
  default=True,
249
249
  help="Disable automatic term extraction. (Config file: set auto_extract_glossary = false)",
250
250
  )
251
+ translation_group.add_argument(
252
+ "--auto-enable-ocr-workaround",
253
+ action="store_true",
254
+ default=False,
255
+ help="Enable automatic OCR workaround. If a document is detected as heavily scanned, this will attempt to enable OCR processing and skip further scan detection. Note: This option interacts with `--ocr-workaround` and `--skip-scanned-detection`. See documentation for details. (default: False)",
256
+ )
257
+ translation_group.add_argument(
258
+ "--primary-font-family",
259
+ type=str,
260
+ choices=["serif", "sans-serif", "script"],
261
+ default=None,
262
+ help="Override primary font family for translated text. Choices: 'serif' for serif fonts, 'sans-serif' for sans-serif fonts, 'script' for script/italic fonts. If not specified, uses automatic font selection based on original text properties.",
263
+ )
251
264
  # service option argument group
252
265
  service_group = translation_group.add_mutually_exclusive_group()
253
266
  service_group.add_argument(
@@ -468,6 +481,8 @@ async def main():
468
481
  glossaries=loaded_glossaries,
469
482
  pool_max_workers=args.pool_max_workers,
470
483
  auto_extract_glossary=args.auto_extract_glossary,
484
+ auto_enable_ocr_workaround=args.auto_enable_ocr_workaround,
485
+ primary_font_family=args.primary_font_family,
471
486
  )
472
487
 
473
488
  # Create progress handler
@@ -602,6 +617,7 @@ def cli():
602
617
  or v.name.startswith("httpx")
603
618
  or "http11" in v.name
604
619
  or "openai" in v.name
620
+ or "pdfminer" in v.name
605
621
  ):
606
622
  v.disabled = True
607
623
  v.propagate = False
@@ -6,6 +6,7 @@ import argparse
6
6
  import hashlib
7
7
  import io
8
8
  import logging
9
+ import re
9
10
  from pathlib import Path
10
11
 
11
12
  import babeldoc.high_level
@@ -17,6 +18,13 @@ from rich.logging import RichHandler
17
18
 
18
19
  logger = logging.getLogger(__name__)
19
20
 
21
+ serif_keywords = [
22
+ "serif",
23
+ ]
24
+ sans_serif_keywords = ["sans", "GoNotoKurrent"]
25
+ serif_regex = "|".join(serif_keywords)
26
+ sans_serif_regex = "|".join(sans_serif_keywords)
27
+
20
28
 
21
29
  def get_font_metadata(font_path) -> PdfFont:
22
30
  doc = pymupdf.open()
@@ -74,6 +82,12 @@ def main():
74
82
  break
75
83
  hash_.update(chunk)
76
84
  extracted_metadata = get_font_metadata(font_path)
85
+
86
+ if re.search(serif_regex, extracted_metadata.name, re.IGNORECASE):
87
+ serif = 1
88
+ else:
89
+ serif = 0
90
+
77
91
  metadata = {
78
92
  "file_name": font_path.name,
79
93
  "font_name": extracted_metadata.name,
@@ -81,7 +95,7 @@ def main():
81
95
  "bold": extracted_metadata.bold,
82
96
  "italic": extracted_metadata.italic,
83
97
  "monospace": extracted_metadata.monospace,
84
- "serif": extracted_metadata.serif,
98
+ "serif": serif,
85
99
  "ascent": extracted_metadata.ascent,
86
100
  "descent": extracted_metadata.descent,
87
101
  "sha3_256": hash_.hexdigest(),
@@ -31,6 +31,7 @@ class SharedContextCrossSplitPart:
31
31
  self.user_glossaries: list[Glossary] = []
32
32
  self.auto_extracted_glossary: Glossary | None = None
33
33
  self.raw_extracted_terms: list[tuple[str, str]] = []
34
+ self.auto_enabled_ocr_workaround = False
34
35
 
35
36
  def initialize_glossaries(self, initial_glossaries: list[Glossary] | None):
36
37
  with self._lock:
@@ -150,6 +151,8 @@ class TranslationConfig:
150
151
  glossaries: list[Glossary] | None = None,
151
152
  pool_max_workers: int | None = None,
152
153
  auto_extract_glossary: bool = True,
154
+ auto_enable_ocr_workaround: bool = False,
155
+ primary_font_family: str | None = None,
153
156
  ):
154
157
  self.translator = translator
155
158
  initial_user_glossaries = list(glossaries) if glossaries else []
@@ -251,6 +254,19 @@ class TranslationConfig:
251
254
  self.custom_system_prompt = custom_system_prompt
252
255
  self.add_formula_placehold_hint = add_formula_placehold_hint
253
256
  self.auto_extract_glossary = auto_extract_glossary
257
+ self.auto_enable_ocr_workaround = auto_enable_ocr_workaround
258
+
259
+ if auto_enable_ocr_workaround:
260
+ self.ocr_workaround = False
261
+ self.skip_scanned_detection = False
262
+
263
+ assert primary_font_family in [
264
+ None,
265
+ "serif",
266
+ "sans-serif",
267
+ "script",
268
+ ]
269
+ self.primary_font_family = primary_font_family
254
270
 
255
271
  def parse_pages(self, pages_str: str | None) -> list[tuple[int, int]] | None:
256
272
  """解析页码字符串,返回页码范围列表