rxiv-maker 1.16.7__tar.gz → 1.17.0__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 (378) hide show
  1. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/CHANGELOG.md +117 -0
  2. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/PKG-INFO +2 -1
  3. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/pyproject.toml +2 -0
  4. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/__version__.py +1 -1
  5. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/build.py +7 -0
  6. rxiv_maker-1.17.0/src/rxiv_maker/cli/commands/docx.py +177 -0
  7. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/framework/workflow_commands.py +66 -2
  8. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/citation_processor.py +5 -3
  9. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/config_manager.py +1 -0
  10. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/dependency_manager.py +12 -0
  11. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/exporters/docx_citation_mapper.py +99 -0
  12. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/exporters/docx_content_processor.py +128 -30
  13. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/exporters/docx_exporter.py +179 -24
  14. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/exporters/docx_writer.py +227 -27
  15. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/templates/registry.py +1 -0
  16. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/bst_generator.py +27 -7
  17. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/docx_helpers.py +62 -3
  18. rxiv_maker-1.17.0/src/rxiv_maker/utils/pdf_splitter.py +116 -0
  19. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/tex/style/rxiv_maker_style.cls +33 -33
  20. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/exporters/test_docx_citation_mapper.py +11 -1
  21. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/exporters/test_docx_content_processor.py +8 -9
  22. rxiv_maker-1.17.0/tests/unit/test_bst_generator.py +132 -0
  23. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_citation_processor.py +90 -0
  24. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_dependency_package_names.py +37 -0
  25. rxiv_maker-1.17.0/tests/unit/test_docx_doi_resolution.py +248 -0
  26. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_docx_helpers.py +4 -2
  27. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_importlib_edge_cases.py +2 -1
  28. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_track_changes.py +27 -35
  29. rxiv_maker-1.16.7/src/rxiv_maker/cli/commands/docx.py +0 -103
  30. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/.gitignore +0 -0
  31. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/LICENSE +0 -0
  32. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/README.md +0 -0
  33. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/docs/api/README.md +0 -0
  34. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/docs/api/index.md +0 -0
  35. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/logo/logo-rxiv-maker.afdesign +0 -0
  36. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/logo/logo-rxiv-maker.png +0 -0
  37. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/logo/logo-rxiv-maker.svg +0 -0
  38. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/__init__.py +0 -0
  39. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/__init__.py +0 -0
  40. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/__main__.py +0 -0
  41. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/__init__.py +0 -0
  42. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/arxiv.py +0 -0
  43. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/bibliography.py +0 -0
  44. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/cache_management.py +0 -0
  45. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/changelog.py +0 -0
  46. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/check_installation.py +0 -0
  47. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/clean.py +0 -0
  48. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/completion.py +0 -0
  49. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/config.py +0 -0
  50. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/create_repo.py +0 -0
  51. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/figures.py +0 -0
  52. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/get_rxiv_preprint.py +0 -0
  53. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/init.py +0 -0
  54. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/install_deps.py +0 -0
  55. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/repo_init.py +0 -0
  56. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/repos.py +0 -0
  57. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/repos_search.py +0 -0
  58. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/setup.py +0 -0
  59. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/track_changes.py +0 -0
  60. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/upgrade.py +0 -0
  61. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/validate.py +0 -0
  62. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/commands/version.py +0 -0
  63. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/framework/__init__.py +0 -0
  64. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/framework/base.py +0 -0
  65. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/framework/cache_commands.py +0 -0
  66. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/framework/config_commands.py +0 -0
  67. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/framework/content_commands.py +0 -0
  68. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/framework/decorators.py +0 -0
  69. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/framework/utility_commands.py +0 -0
  70. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/framework.py +0 -0
  71. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/interactive.py +0 -0
  72. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/interactive_prompts.py +0 -0
  73. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/cli/main.py +0 -0
  74. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/config/defaults.py +0 -0
  75. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/config/validator.py +0 -0
  76. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/__init__.py +0 -0
  77. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/code_processor.py +0 -0
  78. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/comment_processor.py +0 -0
  79. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/custom_command_processor.py +0 -0
  80. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/figure_processor.py +0 -0
  81. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/html_processor.py +0 -0
  82. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/list_processor.py +0 -0
  83. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/math_processor.py +0 -0
  84. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/md2tex.py +0 -0
  85. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/python_executor.py +0 -0
  86. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/section_processor.py +0 -0
  87. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/supplementary_note_processor.py +0 -0
  88. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/table_processor.py +0 -0
  89. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/text_formatters.py +0 -0
  90. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/types.py +0 -0
  91. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/converters/url_processor.py +0 -0
  92. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/cache/__init__.py +0 -0
  93. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/cache/advanced_cache.py +0 -0
  94. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/cache/bibliography_cache.py +0 -0
  95. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/cache/cache_utils.py +0 -0
  96. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/cache/doi_cache.py +0 -0
  97. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/cache/secure_cache_utils.py +0 -0
  98. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/content_processor.py +0 -0
  99. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/environment_bootstrap.py +0 -0
  100. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/environment_manager.py +0 -0
  101. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/error_codes.py +0 -0
  102. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/error_recovery.py +0 -0
  103. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/logging_config.py +0 -0
  104. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/__init__.py +0 -0
  105. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/cache_manager.py +0 -0
  106. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/execution_manager.py +0 -0
  107. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/file_manager.py +0 -0
  108. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/install_manager.py +0 -0
  109. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/state_manager.py +0 -0
  110. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/unified_config_manager.py +0 -0
  111. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/validation_manager.py +0 -0
  112. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/managers/workflow_manager.py +0 -0
  113. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/path_manager.py +0 -0
  114. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/progress_framework.py +0 -0
  115. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/repo_config.py +0 -0
  116. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/repository.py +0 -0
  117. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/session_optimizer.py +0 -0
  118. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/core/validation_framework.py +0 -0
  119. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/data/tips.yaml +0 -0
  120. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/__init__.py +0 -0
  121. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/__init__.py +0 -0
  122. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/add_bibliography.py +0 -0
  123. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/build_manager.py +0 -0
  124. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/cleanup.py +0 -0
  125. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/fix_bibliography.py +0 -0
  126. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/generate_docs.py +0 -0
  127. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/generate_figures.py +0 -0
  128. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/generate_preprint.py +0 -0
  129. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/prepare_arxiv.py +0 -0
  130. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/setup_environment.py +0 -0
  131. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/track_changes.py +0 -0
  132. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/validate.py +0 -0
  133. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/engines/operations/validate_pdf.py +0 -0
  134. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/exporters/__init__.py +0 -0
  135. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/__init__.py +0 -0
  136. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/dependency_handlers/__init__.py +0 -0
  137. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/dependency_handlers/latex.py +0 -0
  138. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/dependency_handlers/r_lang.py +0 -0
  139. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/dependency_handlers/system_libs.py +0 -0
  140. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/platform_installers/__init__.py +0 -0
  141. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/platform_installers/base.py +0 -0
  142. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/platform_installers/linux.py +0 -0
  143. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/platform_installers/macos.py +0 -0
  144. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/platform_installers/windows.py +0 -0
  145. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/utils/__init__.py +0 -0
  146. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/utils/logging.py +0 -0
  147. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/utils/progress.py +0 -0
  148. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/install/utils/verification.py +0 -0
  149. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/manuscript_utils/__init__.py +0 -0
  150. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/manuscript_utils/figure_utils.py +0 -0
  151. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/processors/__init__.py +0 -0
  152. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/processors/author_processor.py +0 -0
  153. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/processors/markdown_preprocessor.py +0 -0
  154. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/processors/template_processor.py +0 -0
  155. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/processors/yaml_processor.py +0 -0
  156. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/rxiv_maker_cli.py +0 -0
  157. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/scripts/__init__.py +0 -0
  158. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/scripts/custom_doc_generator.py +0 -0
  159. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/scripts/validate_manuscript.py +0 -0
  160. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/services/__init__.py +0 -0
  161. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/services/base.py +0 -0
  162. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/services/build_service.py +0 -0
  163. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/services/configuration_service.py +0 -0
  164. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/services/manuscript_service.py +0 -0
  165. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/services/publication_service.py +0 -0
  166. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/services/validation_service.py +0 -0
  167. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/templates/__init__.py +0 -0
  168. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/templates/manager.py +0 -0
  169. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/tex/python_execution_section.tex +0 -0
  170. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/__init__.py +0 -0
  171. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/author_name_formatter.py +0 -0
  172. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/bibliography_checksum.py +0 -0
  173. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/bibliography_parser.py +0 -0
  174. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/changelog_parser.py +0 -0
  175. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/citation_utils.py +0 -0
  176. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/dependency_checker.py +0 -0
  177. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/doi_resolver.py +0 -0
  178. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/email_encoder.py +0 -0
  179. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/figure_checksum.py +0 -0
  180. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/file_helpers.py +0 -0
  181. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/github.py +0 -0
  182. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/homebrew_checker.py +0 -0
  183. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/install_detector.py +0 -0
  184. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/operation_ids.py +0 -0
  185. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/pdf_utils.py +0 -0
  186. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/performance.py +0 -0
  187. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/platform.py +0 -0
  188. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/python_execution_reporter.py +0 -0
  189. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/retry.py +0 -0
  190. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/rich_upgrade_notifier.py +0 -0
  191. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/text_utils.py +0 -0
  192. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/tips.py +0 -0
  193. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/title_sync.py +0 -0
  194. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/unicode_safe.py +0 -0
  195. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/update_checker.py +0 -0
  196. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/utils/url_to_doi.py +0 -0
  197. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validate.py +0 -0
  198. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/__init__.py +0 -0
  199. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/base_validator.py +0 -0
  200. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/citation_validator.py +0 -0
  201. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/doi/__init__.py +0 -0
  202. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/doi/api_clients.py +0 -0
  203. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/doi/metadata_comparator.py +0 -0
  204. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/doi_validator.py +0 -0
  205. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/figure_validator.py +0 -0
  206. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/latex_error_parser.py +0 -0
  207. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/math_validator.py +0 -0
  208. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/pdf_validator.py +0 -0
  209. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/reference_validator.py +0 -0
  210. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/rxiv_maker/validators/syntax_validator.py +0 -0
  211. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/tex/style/rxiv_maker_style.bst +0 -0
  212. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/src/tex/template.tex +0 -0
  213. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/__init__.py +0 -0
  214. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/cli/__init__.py +0 -0
  215. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/cli/test_build.py +0 -0
  216. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/cli/test_changelog_command.py +0 -0
  217. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/cli/test_init_command.py +0 -0
  218. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/cli/test_main.py +0 -0
  219. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/conftest.py +0 -0
  220. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/e2e/__init__.py +0 -0
  221. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/e2e/test_dummy_manuscript_generator.py +0 -0
  222. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/e2e/test_figure_workflow_validation.py +0 -0
  223. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/00_CONFIG.yml +0 -0
  224. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/01_MAIN.md +0 -0
  225. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/03_REFERENCES.bib +0 -0
  226. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/FIGURES/Fig1.png +0 -0
  227. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/FIGURES/Fig2.png +0 -0
  228. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/FIGURES/Fig3.png +0 -0
  229. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/README.md +0 -0
  230. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/docx_export/sample_manuscript/01_MAIN.md +0 -0
  231. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/docx_export/sample_manuscript/02_SUPPLEMENTARY_INFO.md +0 -0
  232. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/docx_export/sample_manuscript/03_REFERENCES.bib +0 -0
  233. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/docx_export/sample_manuscript/2025__unknown_et_al__rxiv.docx +0 -0
  234. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/fixtures/docx_export/sample_manuscript/sample_manuscript.docx +0 -0
  235. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/__init__.py +0 -0
  236. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_article_generation.py +0 -0
  237. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_bibliography_author_format_docx.py +0 -0
  238. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_binary_distribution.py +0 -0
  239. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_centralized_components.py +0 -0
  240. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_citation_injection.py +0 -0
  241. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_comment_system_integration.py +0 -0
  242. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_docx_export_integration.py +0 -0
  243. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_doi_fallback_integration.py +0 -0
  244. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_doi_validation_integration.py +0 -0
  245. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_example_manuscript.py +0 -0
  246. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_guillaume_fixtures.py +0 -0
  247. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_homebrew_workflow_validation.py +0 -0
  248. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_infrastructure_suite.py +0 -0
  249. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_init_build_workflow.py +0 -0
  250. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_install_verification_integration.py +0 -0
  251. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_latex_dependency_integration.py +0 -0
  252. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_manuscript_directory_integration.py +0 -0
  253. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_manuscript_python_execution_reporting.py +0 -0
  254. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_practical_manuscript_workflows.py +0 -0
  255. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_pypi_package_integration.py +0 -0
  256. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_python_execution_integration.py +0 -0
  257. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_repository_cli_integration.py +0 -0
  258. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_supplementary_formatting.py +0 -0
  259. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_user_reported_issue.py +0 -0
  260. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/integration/test_validation_workflow.py +0 -0
  261. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/README.md +0 -0
  262. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/conftest.py +0 -0
  263. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/test_cli_argument_parsing.py +0 -0
  264. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/test_discord_reported_issues.py +0 -0
  265. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/test_error_message_quality.py +0 -0
  266. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/test_google_colab_integration.py +0 -0
  267. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/test_guillaume_edge_cases.py +0 -0
  268. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/test_guillaume_pr131_rewrite.py +0 -0
  269. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/test_path_resolution.py +0 -0
  270. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/test_widget_author_behavior.py +0 -0
  271. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/regression/test_widget_interactions_playwright.py +0 -0
  272. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/smoke/__init__.py +0 -0
  273. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/smoke/test_basic_functionality.py +0 -0
  274. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/smoke/test_cli_smoke.py +0 -0
  275. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/system/__init__.py +0 -0
  276. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/system/test_ci_matrix.py +0 -0
  277. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/system/test_cli_workflows.py +0 -0
  278. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/system/test_end_to_end.py +0 -0
  279. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/test_homebrew_checker.py +0 -0
  280. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/test_install_detector.py +0 -0
  281. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/__init__.py +0 -0
  282. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/exporters/__init__.py +0 -0
  283. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_add_bibliography.py +0 -0
  284. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_arxiv_command.py +0 -0
  285. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_async_execution_manager.py +0 -0
  286. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_author_name_formatter.py +0 -0
  287. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_author_processor.py +0 -0
  288. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_build_command.py +0 -0
  289. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_build_manager.py +0 -0
  290. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_build_manager_manuscript_path.py +0 -0
  291. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_cache_security.py +0 -0
  292. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_cache_utils.py +0 -0
  293. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_check_installation_command.py +0 -0
  294. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_citation_rendering.py +0 -0
  295. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_citation_style.py +0 -0
  296. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_citation_utils.py +0 -0
  297. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_cli_cleanup_integration.py +0 -0
  298. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_cli_structure.py +0 -0
  299. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_comment_processor.py +0 -0
  300. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_conda_installation_manager.py +0 -0
  301. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_conda_platform_detection.py +0 -0
  302. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_cross_platform_optimizations.py +0 -0
  303. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_custom_command_processor.py +0 -0
  304. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_dependency_manager.py +0 -0
  305. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_doi_fallback_system.py +0 -0
  306. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_doi_resolver.py +0 -0
  307. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_doi_validator.py +0 -0
  308. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_email_encoder.py +0 -0
  309. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_environment_manager.py +0 -0
  310. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_error_handling_scenarios.py +0 -0
  311. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_execution_manager_comprehensive.py +0 -0
  312. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_figure_generator.py +0 -0
  313. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_figure_processor.py +0 -0
  314. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_figure_processor_error_handling.py +0 -0
  315. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_file_helpers.py +0 -0
  316. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_fix_bibliography.py +0 -0
  317. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_generate_docs.py +0 -0
  318. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_generate_preprint.py +0 -0
  319. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_github.py +0 -0
  320. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_github_actions_integration.py +0 -0
  321. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_install_platform_installers.py +0 -0
  322. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_install_system_libs.py +0 -0
  323. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_install_verification.py +0 -0
  324. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_interactive_path_change.py +0 -0
  325. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_interactive_validators.py +0 -0
  326. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_latex_dependency_handler.py +0 -0
  327. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_manuscript_figure_utils.py +0 -0
  328. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_manuscript_repository.py +0 -0
  329. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_math_processor.py +0 -0
  330. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_md2tex.py +0 -0
  331. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_mermaid_fallback.py +0 -0
  332. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_path_manager.py +0 -0
  333. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_pdf_validator.py +0 -0
  334. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_platform_comprehensive.py +0 -0
  335. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_platform_detector.py +0 -0
  336. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_processor_suite.py +0 -0
  337. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_python_execution_reporter.py +0 -0
  338. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_python_executor.py +0 -0
  339. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_release_orchestrator.py +0 -0
  340. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_repository_manager.py +0 -0
  341. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_rich_upgrade_notifier.py +0 -0
  342. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_rxiv_setup_command.py +0 -0
  343. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_security_features.py +0 -0
  344. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_security_scanner.py +0 -0
  345. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_setup_environment.py +0 -0
  346. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_style_file_resolution.py +0 -0
  347. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_supplementary_note_processor.py +0 -0
  348. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_table_rotation.py +0 -0
  349. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_template_processor.py +0 -0
  350. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_text_formatters.py +0 -0
  351. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_text_utils.py +0 -0
  352. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_tips.py +0 -0
  353. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_title_sync.py +0 -0
  354. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_title_sync_validation.py +0 -0
  355. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_trailing_slash_regression.py +0 -0
  356. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_upgrade_command.py +0 -0
  357. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_url_to_doi.py +0 -0
  358. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_utils.py +0 -0
  359. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_validate_backticks.py +0 -0
  360. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_validate_command_fixed.py +0 -0
  361. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_validate_manuscript.py +0 -0
  362. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_validation_suite.py +0 -0
  363. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_validators.py +0 -0
  364. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/unit/test_yaml_processor.py +0 -0
  365. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/README.md +0 -0
  366. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/figure-positioning/00_CONFIG.yml +0 -0
  367. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/figure-positioning/01_MAIN.md +0 -0
  368. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/figure-positioning/03_REFERENCES.bib +0 -0
  369. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/figure-positioning/FIGURES/Figure__positioning_test.png +0 -0
  370. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/figure-positioning/FIGURES/Figure__positioning_test.py +0 -0
  371. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/figure-positioning/FIGURES/ReadyFig.png +0 -0
  372. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/figure-positioning/FIGURES/ReadyFig.py +0 -0
  373. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/figure-positioning/README.md +0 -0
  374. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/methods-placement/00_CONFIG.yml +0 -0
  375. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/methods-placement/01_MAIN.md +0 -0
  376. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/methods-placement/02_SUPPLEMENTARY_INFO.md +0 -0
  377. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/methods-placement/03_REFERENCES.bib +0 -0
  378. {rxiv_maker-1.16.7 → rxiv_maker-1.17.0}/tests/visual/methods-placement/README.md +0 -0
@@ -7,6 +7,123 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.17.0] - 2025-12-22
11
+
12
+ ### Added
13
+
14
+ - **PDF Splitting Feature**: New `--split-si` flag for `rxiv pdf` command
15
+ - Automatically splits generated PDFs into main manuscript and supplementary information sections
16
+ - Auto-detects SI markers ("Supplementary Information", "Supplementary Material", "Supporting Information", etc.)
17
+ - Generates properly named split files: `{year}__{author}_et_al__rxiv__main.pdf` and `{year}__{author}_et_al__rxiv__si.pdf`
18
+ - Places split files in MANUSCRIPT directory with consistent naming convention
19
+ - Addresses common journal submission requirements for separate main and SI files
20
+ - **Color-Coded DOCX References**: Visual distinction for different reference types
21
+ - Main figures: bright green highlighting
22
+ - Main tables: blue highlighting
23
+ - Supplementary elements (figures, tables, notes): turquoise highlighting
24
+ - Citations: yellow highlighting
25
+ - Equations: violet highlighting
26
+ - Improves readability and helps track different element types during review
27
+ - **Citation Range Formatting**: Automatic formatting of adjacent citations
28
+ - Formats `[4][5][6]` as `[4-6]` for cleaner presentation
29
+ - Handles both adjacent bracket citations and comma-separated citations
30
+ - Maintains readability while reducing visual clutter
31
+ - **DOCX Configuration Options**: New manuscript config options
32
+ - `docx.hide_si`: Control supplementary information visibility (default: false)
33
+ - `docx.figures_at_end`: Place main figures at end before bibliography (default: false)
34
+ - Clearer semantics than previous `add_si` option
35
+ - Supports different journal formatting requirements
36
+ - **Subscript/Superscript Support**: Chemical formulas and mathematical notation in DOCX
37
+ - Supports `~subscript~` and `^superscript^` markdown syntax
38
+ - Enables proper formatting of chemical formulas (H~2~O) and exponents (x^2^)
39
+
40
+ ### Fixed
41
+
42
+ - **Citation Extraction Bug**: Citations between triple-backtick code blocks now extract correctly
43
+ - Fixed regex processing order to handle triple backticks before single backticks
44
+ - Prevents citations from being incorrectly marked as "protected code content"
45
+ - Resolves issue where `[@key]` citations remained unconverted in DOCX output
46
+ - Added regression tests to prevent future occurrences
47
+ - **Bibliography Formatting**: Enhanced cleanup for malformed BibTeX entries
48
+ - HTML entity decoding: `é` → `é`, `á` → `á`, `…` → `…`
49
+ - Malformed name repair: fixes split author names (e.g., "Pé and Rez, Fernando" → "Pérez, Fernando")
50
+ - Brace cleanup: removes stray braces after Unicode characters
51
+ - Handles escaped HTML entities from BibTeX (`\&\#233` → `é`)
52
+ - Whitespace normalization for cleaner bibliography entries
53
+ - **Table Caption Formatting**: Supplementary tables now show proper labels
54
+ - Displays "Supp. Table SX." prefix with correct font sizing
55
+ - Preserves table label identifiers during processing
56
+ - Supports hyphens in table label names
57
+ - **Comment Filtering**: Markdown metadata comments no longer appear in DOCX
58
+ - Filters comments starting with "note:", "comment:" (case-insensitive)
59
+ - Prevents manuscript-specific metadata from appearing in final output
60
+ - Improves multi-line comment parsing
61
+
62
+ ### Changed
63
+
64
+ - **Figure Centering**: All figures now centered by default in DOCX exports
65
+ - Improves visual presentation and alignment with journal standards
66
+ - Consistent formatting across all figure types
67
+ - **Citation Handling**: Citations treated as highlighted text instead of separate objects
68
+ - Maintains citation ranges in yellow highlighting
69
+ - Simplifies DOCX structure while preserving visual distinction
70
+ - **PDF Spacing**: Optimized manuscript spacing for increased content density
71
+ - Tighter spacing between back matter section headers and text
72
+ - Improved overall visual hierarchy
73
+ - More content per page without sacrificing readability
74
+
75
+ ### Documentation
76
+
77
+ - **Updated CLAUDE.md**: Enhanced development documentation
78
+ - Removed Docker/Podman engine references (moved to separate docker-rxiv-maker repository)
79
+ - Added PDF splitting feature documentation
80
+ - Clarified testing workflows and CI requirements
81
+
82
+ ## [1.16.8] - 2025-12-19
83
+
84
+ ### Added
85
+
86
+ - **Automatic Poppler Installation**: Interactive installation prompt for DOCX export on macOS
87
+ - Detects missing poppler utilities when exporting to DOCX with PDF figures
88
+ - Offers automatic installation via Homebrew with user confirmation
89
+ - Shows clear installation instructions for Linux (apt) and other platforms
90
+ - Gracefully falls back to placeholders when poppler unavailable
91
+ - **DOI Resolution Implementation**: `--resolve-dois` flag now fully functional for DOCX export
92
+ - Resolves missing DOIs using CrossRef API with intelligent title matching
93
+ - Cleans LaTeX commands from titles for accurate search results
94
+ - Validates matches using year information when available
95
+ - Handles network failures and timeouts gracefully
96
+ - Logs resolved DOIs for transparency
97
+ - **Poppler Dependency Tracking**: Registered poppler in DependencyManager
98
+ - Added as system binary dependency with alternatives (pdftoppm, pdfinfo)
99
+ - Included in `rxiv check-installation` output
100
+ - Provides platform-specific installation hints
101
+
102
+ ### Fixed
103
+
104
+ - **BST File Regex Bug**: Corrected bibliography style file generation to only modify `format.names`
105
+ - Previous regex matched both `format.names` and `format.full.names` functions
106
+ - Now specifically targets only `format.names` function using DOTALL flag
107
+ - Prevents corruption of citation labels in natbib
108
+ - Eliminates warning: "Found 2 format string patterns in .bst file"
109
+ - Raises error if unexpected matches found (defensive programming)
110
+ - **PDF to Image Conversion**: Improved error handling for missing poppler utilities
111
+ - Distinguishes between poppler not installed, corrupted PDFs, and other errors
112
+ - Uses proper logging instead of print statements
113
+ - Re-raises poppler errors to allow CLI to offer installation
114
+ - Provides specific error messages for different failure types
115
+
116
+ ### Changed
117
+
118
+ - **DOCX Export Experience**: Enhanced PDF figure embedding workflow
119
+ - Pre-flight check detects poppler availability before attempting conversion
120
+ - Caches poppler status to avoid repeated checks
121
+ - Shows helpful warnings with installation instructions
122
+ - PDF figures embed correctly when poppler is installed
123
+ - **Homebrew Formula**: Added poppler as dependency
124
+ - Users installing via `brew install rxiv-maker` now get poppler automatically
125
+ - Ensures DOCX export works out of the box for Homebrew users
126
+
10
127
  ## [1.16.7] - 2025-12-18
11
128
 
12
129
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rxiv-maker
3
- Version: 1.16.7
3
+ Version: 1.17.0
4
4
  Summary: Write scientific preprints in Markdown. Generate publication-ready PDFs efficiently.
5
5
  Project-URL: Homepage, https://github.com/HenriquesLab/rxiv-maker
6
6
  Project-URL: Documentation, https://github.com/HenriquesLab/rxiv-maker#readme
@@ -56,6 +56,7 @@ Requires-Dist: mypy>=1.0; extra == 'dev'
56
56
  Requires-Dist: nbstripout>=0.7.1; extra == 'dev'
57
57
  Requires-Dist: nox>=2023.0.0; extra == 'dev'
58
58
  Requires-Dist: pre-commit>=4.2.0; extra == 'dev'
59
+ Requires-Dist: pypdf2>=3.0.0; extra == 'dev'
59
60
  Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
60
61
  Requires-Dist: pytest-benchmark>=4.0.0; extra == 'dev'
61
62
  Requires-Dist: pytest-clarity>=1.0.0; extra == 'dev'
@@ -93,6 +93,8 @@ dev = [
93
93
  # Type checking
94
94
  "types-requests>=2.32.4.20250611",
95
95
  "types-PyYAML>=6.0.0",
96
+ # PDF utilities
97
+ "PyPDF2>=3.0.0",
96
98
  # Documentation and utilities
97
99
  "coverage[toml]>=7.0",
98
100
  "nbstripout>=0.7.1",
@@ -1,3 +1,3 @@
1
1
  """Version information."""
2
2
 
3
- __version__ = "1.16.7"
3
+ __version__ = "1.17.0"
@@ -30,6 +30,7 @@ from ..framework import BuildCommand
30
30
  @click.option("--keep-output", is_flag=True, help="Preserve existing output directory (default: clear before build)")
31
31
  @click.option("--docx", is_flag=True, help="Also export to DOCX format for collaborative review")
32
32
  @click.option("--resolve-dois", "-r", is_flag=True, help="Attempt to resolve missing DOIs (when using --docx)")
33
+ @click.option("--split-si", is_flag=True, help="Split PDF into main and SI sections (__main.pdf and __si.pdf)")
33
34
  @click.option("--verbose", "-v", is_flag=True, help="Enable verbose output")
34
35
  @click.option("--quiet", "-q", is_flag=True, help="Suppress non-essential output")
35
36
  @click.option("--debug", "-d", is_flag=True, help="Enable debug output")
@@ -49,6 +50,7 @@ def build(
49
50
  keep_output: bool,
50
51
  docx: bool,
51
52
  resolve_dois: bool,
53
+ split_si: bool,
52
54
  verbose: bool,
53
55
  quiet: bool,
54
56
  debug: bool,
@@ -81,6 +83,10 @@ def build(
81
83
 
82
84
  $ rxiv pdf --docx --resolve-dois
83
85
 
86
+ **Split PDF into main and SI sections:**
87
+
88
+ $ rxiv pdf --split-si
89
+
84
90
  **Force regenerate all figures:**
85
91
 
86
92
  $ rxiv pdf --force-figures
@@ -108,6 +114,7 @@ def build(
108
114
  keep_output=keep_output,
109
115
  docx=docx,
110
116
  resolve_dois=resolve_dois,
117
+ split_si=split_si,
111
118
  debug=debug or verbose,
112
119
  quiet=quiet,
113
120
  container_mode=container_mode,
@@ -0,0 +1,177 @@
1
+ """DOCX export command for rxiv-maker CLI."""
2
+
3
+ import platform
4
+ import shutil
5
+ import subprocess
6
+
7
+ import rich_click as click
8
+ from rich.console import Console
9
+
10
+ from ...core.logging_config import get_logger
11
+ from ...core.managers.dependency_manager import DependencyStatus, get_dependency_manager
12
+ from ...exporters.docx_exporter import DocxExporter
13
+
14
+ logger = get_logger()
15
+ console = Console()
16
+
17
+
18
+ def _check_and_offer_poppler_installation(console: Console, quiet: bool, verbose: bool) -> None:
19
+ """Check poppler availability and offer automatic installation via brew.
20
+
21
+ Args:
22
+ console: Rich console for output
23
+ quiet: Whether to suppress output
24
+ verbose: Whether verbose mode is enabled
25
+ """
26
+ # Check if poppler is installed
27
+ manager = get_dependency_manager()
28
+ result = manager.check_dependency("pdftoppm")
29
+
30
+ if result.status == DependencyStatus.AVAILABLE:
31
+ if verbose:
32
+ console.print("[dim]✓ Poppler utilities available[/dim]")
33
+ return
34
+
35
+ # Poppler is missing - offer to install
36
+ system = platform.system()
37
+
38
+ if system == "Darwin" and shutil.which("brew"):
39
+ # macOS with Homebrew
40
+ if not quiet:
41
+ console.print("[yellow]⚠️ Poppler not found[/yellow]")
42
+ console.print(" Poppler is needed to embed PDF figures in DOCX files.")
43
+ console.print(" Without it, PDF figures will appear as placeholders.")
44
+ console.print()
45
+
46
+ if click.confirm(" Would you like to install poppler now via Homebrew?", default=True):
47
+ console.print("[cyan]Installing poppler...[/cyan]")
48
+ try:
49
+ result = subprocess.run(
50
+ ["brew", "install", "poppler"],
51
+ capture_output=True,
52
+ text=True,
53
+ timeout=300,
54
+ )
55
+
56
+ if result.returncode == 0:
57
+ console.print("[green]✅ Poppler installed successfully![/green]")
58
+ # Clear dependency cache so it gets re-checked
59
+ manager.clear_cache()
60
+ else:
61
+ console.print(f"[red]❌ Installation failed:[/red] {result.stderr}")
62
+ console.print(" You can install manually with: brew install poppler")
63
+ except subprocess.TimeoutExpired:
64
+ console.print("[red]❌ Installation timed out[/red]")
65
+ except Exception as e:
66
+ console.print(f"[red]❌ Installation error:[/red] {e}")
67
+ else:
68
+ console.print(" [dim]Skipping poppler installation. PDF figures will show as placeholders.[/dim]")
69
+
70
+ elif system == "Linux":
71
+ # Linux
72
+ if not quiet:
73
+ console.print("[yellow]⚠️ Poppler not found[/yellow]")
74
+ console.print(" Install with: sudo apt install poppler-utils")
75
+ console.print()
76
+ else:
77
+ # Other platforms or brew not available
78
+ if not quiet:
79
+ console.print("[yellow]⚠️ Poppler not found[/yellow]")
80
+ console.print(f" Install instructions: {result.resolution_hint}")
81
+ console.print()
82
+
83
+
84
+ @click.command(context_settings={"help_option_names": ["-h", "--help"]})
85
+ @click.argument(
86
+ "manuscript_path",
87
+ type=click.Path(exists=True, file_okay=False),
88
+ required=False,
89
+ metavar="[MANUSCRIPT_PATH]",
90
+ )
91
+ @click.option(
92
+ "--resolve-dois",
93
+ "-r",
94
+ is_flag=True,
95
+ help="Attempt to resolve missing DOIs from metadata",
96
+ )
97
+ @click.option(
98
+ "--no-footnotes",
99
+ is_flag=True,
100
+ help="Disable references section (citations only)",
101
+ )
102
+ @click.option("--verbose", "-v", is_flag=True, help="Enable verbose output")
103
+ @click.option("--quiet", "-q", is_flag=True, help="Suppress non-essential output")
104
+ def docx(
105
+ manuscript_path: str | None,
106
+ resolve_dois: bool,
107
+ no_footnotes: bool,
108
+ verbose: bool,
109
+ quiet: bool,
110
+ ) -> None:
111
+ """Export manuscript to DOCX format for collaborative review.
112
+
113
+ Generates a Word document with numbered citations, embedded figures,
114
+ and a complete references section with DOI links. Output is automatically
115
+ saved to the manuscript directory with the same naming pattern as the PDF.
116
+
117
+ **MANUSCRIPT_PATH**: Directory containing manuscript files.
118
+ Defaults to MANUSCRIPT/
119
+
120
+ **Output**: Automatically saved to MANUSCRIPT/YEAR__lastname_et_al__rxiv.docx
121
+
122
+ ## Examples
123
+
124
+ **Basic export:**
125
+
126
+ $ rxiv docx
127
+
128
+ **Export from custom directory:**
129
+
130
+ $ rxiv docx MY_PAPER/
131
+
132
+ **With DOI resolution for missing entries:**
133
+
134
+ $ rxiv docx --resolve-dois
135
+
136
+ **Without references section (citations only):**
137
+
138
+ $ rxiv docx --no-footnotes
139
+ """
140
+ try:
141
+ # Configure logging
142
+ if verbose:
143
+ logger.set_level("DEBUG")
144
+ elif quiet:
145
+ logger.set_level("WARNING")
146
+
147
+ # Set manuscript path
148
+ manuscript_path = manuscript_path or "MANUSCRIPT"
149
+
150
+ # Create exporter
151
+ if not quiet:
152
+ console.print("[cyan]📄 Exporting manuscript to DOCX...[/cyan]")
153
+
154
+ exporter = DocxExporter(
155
+ manuscript_path=manuscript_path,
156
+ resolve_dois=resolve_dois,
157
+ include_footnotes=not no_footnotes,
158
+ )
159
+
160
+ # Pre-flight check for poppler (if manuscript contains PDF figures)
161
+ _check_and_offer_poppler_installation(console, quiet, verbose)
162
+
163
+ # Perform export
164
+ docx_path = exporter.export()
165
+
166
+ # Success message
167
+ if not quiet:
168
+ console.print(f"[green]✅ DOCX exported:[/green] {docx_path}")
169
+
170
+ except FileNotFoundError as e:
171
+ console.print(f"[red]❌ Error:[/red] {e}")
172
+ raise click.Abort() from e
173
+ except Exception as e:
174
+ if verbose:
175
+ logger.error(f"DOCX export failed: {e}")
176
+ console.print(f"[red]❌ Export failed:[/red] {e}")
177
+ raise click.Abort() from e
@@ -142,6 +142,7 @@ class BuildCommand(BaseCommand):
142
142
  keep_output: bool = False,
143
143
  docx: bool = False,
144
144
  resolve_dois: bool = False,
145
+ split_si: bool = False,
145
146
  debug: bool = False,
146
147
  quiet: bool = False,
147
148
  container_mode: Optional[str] = None,
@@ -156,6 +157,7 @@ class BuildCommand(BaseCommand):
156
157
  keep_output: Preserve existing output directory
157
158
  docx: Also export to DOCX format
158
159
  resolve_dois: Attempt to resolve missing DOIs (for DOCX export)
160
+ split_si: Split PDF into main and SI sections
159
161
  debug: Enable debug output
160
162
  quiet: Suppress non-critical warnings
161
163
  container_mode: Container behavior mode
@@ -223,6 +225,10 @@ class BuildCommand(BaseCommand):
223
225
  if docx:
224
226
  self._export_docx(resolve_dois=resolve_dois, quiet=quiet, debug=debug)
225
227
 
228
+ # Split PDF if requested
229
+ if split_si:
230
+ self._split_pdf(pdf_path, quiet=quiet, debug=debug)
231
+
226
232
  # Show helpful tips after successful build
227
233
  self._show_build_tips()
228
234
 
@@ -252,11 +258,69 @@ class BuildCommand(BaseCommand):
252
258
  self.console.print(f"[green]✅ DOCX exported:[/green] {docx_path}")
253
259
 
254
260
  except Exception as e:
255
- self.console.print(f"[yellow]⚠️ DOCX export failed:[/yellow] {e}", err=True)
261
+ self.console.print(f"[yellow]⚠️ DOCX export failed:[/yellow] {e}")
262
+ if debug:
263
+ import traceback
264
+
265
+ self.console.print(f"[dim]{traceback.format_exc()}[/dim]")
266
+
267
+ def _split_pdf(self, pdf_path: Path, quiet: bool = False, debug: bool = False) -> None:
268
+ """Split PDF into main and SI sections after successful PDF build.
269
+
270
+ Args:
271
+ pdf_path: Path to the generated PDF
272
+ quiet: Suppress non-essential output
273
+ debug: Enable debug output
274
+ """
275
+ try:
276
+ from ...processors.yaml_processor import extract_yaml_metadata
277
+ from ...utils.file_helpers import find_manuscript_md
278
+ from ...utils.pdf_splitter import split_pdf
279
+ from ...utils.pdf_utils import get_custom_pdf_filename
280
+
281
+ if not quiet:
282
+ self.console.print("\n[cyan]✂️ Splitting PDF into main and SI sections...[/cyan]")
283
+
284
+ # Split the PDF
285
+ main_path, si_path = split_pdf(pdf_path)
286
+
287
+ if main_path and si_path:
288
+ # Extract metadata to generate custom filename
289
+ manuscript_md = find_manuscript_md(str(self.path_manager.manuscript_path))
290
+ yaml_metadata = extract_yaml_metadata(str(manuscript_md))
291
+
292
+ # Get base filename (e.g., "2025__saraiva_et_al__rxiv.pdf")
293
+ base_filename = get_custom_pdf_filename(yaml_metadata)
294
+ base_name = base_filename.replace(".pdf", "")
295
+
296
+ # Generate final filenames with __main and __si suffixes
297
+ main_filename = f"{base_name}__main.pdf"
298
+ si_filename = f"{base_name}__si.pdf"
299
+
300
+ # Copy split files to manuscript directory
301
+ final_main_path = self.path_manager.manuscript_path / main_filename
302
+ final_si_path = self.path_manager.manuscript_path / si_filename
303
+
304
+ shutil.copy2(main_path, final_main_path)
305
+ shutil.copy2(si_path, final_si_path)
306
+
307
+ if not quiet:
308
+ self.console.print("[green]✅ PDF split successfully:[/green]")
309
+ self.console.print(f" 📄 Main: {final_main_path}")
310
+ self.console.print(f" 📄 SI: {final_si_path}")
311
+ elif main_path is None and si_path is None:
312
+ if not quiet:
313
+ self.console.print("[yellow]⚠️ Could not split PDF: SI section marker not found[/yellow]")
314
+ else:
315
+ if not quiet:
316
+ self.console.print("[yellow]⚠️ PDF splitting partially failed[/yellow]")
317
+
318
+ except Exception as e:
319
+ self.console.print(f"[yellow]⚠️ PDF splitting failed:[/yellow] {e}")
256
320
  if debug:
257
321
  import traceback
258
322
 
259
- self.console.print(f"[dim]{traceback.format_exc()}[/dim]", err=True)
323
+ self.console.print(f"[dim]{traceback.format_exc()}[/dim]")
260
324
 
261
325
  def _show_build_tips(self) -> None:
262
326
  """Show helpful tips after successful PDF build."""
@@ -202,9 +202,11 @@ def extract_citations_from_text(text: MarkdownContent) -> list[CitationKey]:
202
202
  backtick_patterns.append(match.group(0))
203
203
  return f"__BACKTICK_PATTERN_{len(backtick_patterns) - 1}__"
204
204
 
205
- # Match both single backticks `...` and triple backticks ```...```
206
- text_cleaned = re.sub(r"`[^`]+`", protect_backticks, text)
207
- text_cleaned = re.sub(r"```.*?```", protect_backticks, text_cleaned, flags=re.DOTALL)
205
+ # IMPORTANT: Match triple backticks FIRST, then single backticks
206
+ # This prevents the single-backtick pattern from matching across triple-backtick blocks
207
+ # (e.g., from a ` before ```latex to the first ` inside the code block)
208
+ text_cleaned = re.sub(r"```.*?```", protect_backticks, text, flags=re.DOTALL)
209
+ text_cleaned = re.sub(r"`[^`]+`", protect_backticks, text_cleaned)
208
210
 
209
211
  # Find bracketed multiple citations
210
212
  bracketed_matches = re.findall(r"\[(@[^]]+)\]", text_cleaned)
@@ -343,6 +343,7 @@ class ConfigManager:
343
343
  "bibliography": {"file": "03_REFERENCES.bib", "style": "nature"},
344
344
  "citation_style": "numbered",
345
345
  "enable_inline_doi_resolution": False,
346
+ "docx": {"hide_si": False, "figures_at_end": False},
346
347
  "cache": {"enabled": True, "ttl_hours": 24},
347
348
  "version": "1.0",
348
349
  "acknowledge_rxiv_maker": True,
@@ -487,6 +487,18 @@ class DependencyManager:
487
487
  )
488
488
  )
489
489
 
490
+ # Poppler utilities for PDF to image conversion (DOCX export)
491
+ self.register_dependency(
492
+ DependencySpec(
493
+ name="pdftoppm",
494
+ type=DependencyType.SYSTEM_BINARY,
495
+ required=False, # Only needed for DOCX export with PDF figures
496
+ alternatives=["pdfinfo"],
497
+ contexts={"docx", "export"},
498
+ install_hint="macOS: brew install poppler | Linux: sudo apt install poppler-utils",
499
+ )
500
+ )
501
+
490
502
  def register_dependency(self, spec: DependencySpec) -> None:
491
503
  """Register a dependency specification.
492
504
 
@@ -13,6 +13,102 @@ from ..converters.citation_processor import extract_citations_from_text
13
13
  class CitationMapper:
14
14
  """Maps citation keys to sequential numbers for DOCX export."""
15
15
 
16
+ @staticmethod
17
+ def _format_citation_ranges(text: str) -> str:
18
+ """Format consecutive citations as ranges.
19
+
20
+ Converts patterns like [1][2][3] to [1-3], [15][16] to [15-16], etc.
21
+ Also formats comma-separated lists like [1, 2, 3] to [1-3].
22
+
23
+ Args:
24
+ text: Text with numbered citations
25
+
26
+ Returns:
27
+ Text with consecutive citations formatted as ranges
28
+
29
+ Example:
30
+ >>> CitationMapper._format_citation_ranges("text [1][2][3] more")
31
+ 'text [1-3] more'
32
+ >>> CitationMapper._format_citation_ranges("text [1, 2, 3] more")
33
+ 'text [1-3] more'
34
+ >>> CitationMapper._format_citation_ranges("text [1][3][4] more")
35
+ 'text [1][3-4] more'
36
+ """
37
+
38
+ # Pattern 1: Handle adjacent bracketed citations [1][2][3] or [1] [2] [3]
39
+ def combine_adjacent(match_obj):
40
+ # Extract all numbers from consecutive brackets (allowing spaces between)
41
+ numbers = [int(n) for n in re.findall(r"\[(\d+)\]", match_obj.group(0))]
42
+ return CitationMapper._format_number_list(numbers)
43
+
44
+ # Find sequences of adjacent bracketed numbers (with optional spaces between)
45
+ text = re.sub(r"(?:\[\d+\]\s*){2,}", combine_adjacent, text)
46
+
47
+ # Pattern 2: Handle comma-separated citations within single brackets [1, 2, 3]
48
+ def combine_comma_separated(match_obj):
49
+ # Extract all numbers from comma-separated list
50
+ numbers_str = match_obj.group(1)
51
+ numbers = [int(n.strip()) for n in numbers_str.split(",")]
52
+ return CitationMapper._format_number_list(numbers)
53
+
54
+ text = re.sub(r"\[([\d,\s]+)\]", combine_comma_separated, text)
55
+
56
+ return text
57
+
58
+ @staticmethod
59
+ def _format_number_list(numbers: List[int]) -> str:
60
+ """Format a list of citation numbers as ranges.
61
+
62
+ Args:
63
+ numbers: List of citation numbers
64
+
65
+ Returns:
66
+ Formatted string with ranges
67
+
68
+ Example:
69
+ >>> CitationMapper._format_number_list([1, 2, 3, 5, 6, 8])
70
+ '[1-3, 5-6, 8]'
71
+ >>> CitationMapper._format_number_list([15, 16])
72
+ '[15-16]'
73
+ >>> CitationMapper._format_number_list([1, 3, 5])
74
+ '[1, 3, 5]'
75
+ """
76
+ if not numbers:
77
+ return "[]"
78
+
79
+ # Sort numbers
80
+ sorted_nums = sorted(set(numbers))
81
+
82
+ # Build ranges
83
+ ranges = []
84
+ start = sorted_nums[0]
85
+ end = sorted_nums[0]
86
+
87
+ for num in sorted_nums[1:]:
88
+ if num == end + 1:
89
+ # Continue current range
90
+ end = num
91
+ else:
92
+ # End current range and start new one
93
+ if start == end:
94
+ # Single number
95
+ ranges.append(str(start))
96
+ else:
97
+ # Range (including 2 consecutive numbers like 15-16)
98
+ ranges.append(f"{start}-{end}")
99
+ start = num
100
+ end = num
101
+
102
+ # Add final range
103
+ if start == end:
104
+ # Single number
105
+ ranges.append(str(start))
106
+ else:
107
+ # Range (including 2 consecutive numbers like 15-16)
108
+ ranges.append(f"{start}-{end}")
109
+
110
+ return f"[{', '.join(ranges)}]"
111
+
16
112
  def create_mapping(self, citations: List[str]) -> Dict[str, int]:
17
113
  """Create citation key → number mapping.
18
114
 
@@ -121,4 +217,7 @@ class CitationMapper:
121
217
  for i, pattern in enumerate(email_patterns):
122
218
  text = text.replace(f"__EMAIL_PATTERN_{i}__", pattern)
123
219
 
220
+ # Format consecutive citations as ranges (e.g., [1][2][3] -> [1-3])
221
+ text = self._format_citation_ranges(text)
222
+
124
223
  return text