rxiv-maker 1.16.8__tar.gz → 1.18.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 (383) hide show
  1. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/CHANGELOG.md +123 -0
  2. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/PKG-INFO +2 -1
  3. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/pyproject.toml +2 -0
  4. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/__version__.py +1 -1
  5. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/build.py +7 -0
  6. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/framework/workflow_commands.py +69 -3
  7. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/citation_processor.py +5 -3
  8. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/config_manager.py +1 -0
  9. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/exporters/docx_citation_mapper.py +18 -0
  10. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/exporters/docx_content_processor.py +110 -30
  11. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/exporters/docx_exporter.py +76 -32
  12. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/exporters/docx_writer.py +345 -67
  13. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/templates/registry.py +1 -0
  14. rxiv_maker-1.18.0/src/rxiv_maker/utils/accent_character_map.py +150 -0
  15. rxiv_maker-1.18.0/src/rxiv_maker/utils/author_affiliation_processor.py +128 -0
  16. rxiv_maker-1.18.0/src/rxiv_maker/utils/citation_range_formatter.py +118 -0
  17. rxiv_maker-1.18.0/src/rxiv_maker/utils/comment_filter.py +46 -0
  18. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/docx_helpers.py +43 -118
  19. rxiv_maker-1.18.0/src/rxiv_maker/utils/label_extractor.py +185 -0
  20. rxiv_maker-1.18.0/src/rxiv_maker/utils/pdf_splitter.py +116 -0
  21. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/tex/style/rxiv_maker_style.cls +33 -33
  22. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/cli/test_changelog_command.py +26 -2
  23. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/cli/test_init_command.py +38 -27
  24. rxiv_maker-1.18.0/tests/fixtures/docx_export/sample_manuscript/2025__unknown_et_al__rxiv.docx +0 -0
  25. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/exporters/test_docx_citation_mapper.py +11 -1
  26. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/exporters/test_docx_content_processor.py +8 -9
  27. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_citation_processor.py +90 -0
  28. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_docx_helpers.py +4 -2
  29. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_importlib_edge_cases.py +2 -1
  30. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_track_changes.py +27 -35
  31. rxiv_maker-1.16.8/tests/fixtures/docx_export/sample_manuscript/2025__unknown_et_al__rxiv.docx +0 -0
  32. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/.gitignore +0 -0
  33. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/LICENSE +0 -0
  34. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/README.md +0 -0
  35. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/docs/api/README.md +0 -0
  36. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/docs/api/index.md +0 -0
  37. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/logo/logo-rxiv-maker.afdesign +0 -0
  38. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/logo/logo-rxiv-maker.png +0 -0
  39. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/logo/logo-rxiv-maker.svg +0 -0
  40. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/__init__.py +0 -0
  41. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/__init__.py +0 -0
  42. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/__main__.py +0 -0
  43. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/__init__.py +0 -0
  44. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/arxiv.py +0 -0
  45. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/bibliography.py +0 -0
  46. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/cache_management.py +0 -0
  47. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/changelog.py +0 -0
  48. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/check_installation.py +0 -0
  49. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/clean.py +0 -0
  50. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/completion.py +0 -0
  51. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/config.py +0 -0
  52. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/create_repo.py +0 -0
  53. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/docx.py +0 -0
  54. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/figures.py +0 -0
  55. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/get_rxiv_preprint.py +0 -0
  56. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/init.py +0 -0
  57. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/install_deps.py +0 -0
  58. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/repo_init.py +0 -0
  59. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/repos.py +0 -0
  60. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/repos_search.py +0 -0
  61. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/setup.py +0 -0
  62. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/track_changes.py +0 -0
  63. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/upgrade.py +0 -0
  64. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/validate.py +0 -0
  65. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/commands/version.py +0 -0
  66. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/framework/__init__.py +0 -0
  67. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/framework/base.py +0 -0
  68. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/framework/cache_commands.py +0 -0
  69. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/framework/config_commands.py +0 -0
  70. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/framework/content_commands.py +0 -0
  71. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/framework/decorators.py +0 -0
  72. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/framework/utility_commands.py +0 -0
  73. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/framework.py +0 -0
  74. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/interactive.py +0 -0
  75. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/interactive_prompts.py +0 -0
  76. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/cli/main.py +0 -0
  77. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/config/defaults.py +0 -0
  78. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/config/validator.py +0 -0
  79. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/__init__.py +0 -0
  80. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/code_processor.py +0 -0
  81. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/comment_processor.py +0 -0
  82. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/custom_command_processor.py +0 -0
  83. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/figure_processor.py +0 -0
  84. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/html_processor.py +0 -0
  85. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/list_processor.py +0 -0
  86. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/math_processor.py +0 -0
  87. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/md2tex.py +0 -0
  88. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/python_executor.py +0 -0
  89. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/section_processor.py +0 -0
  90. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/supplementary_note_processor.py +0 -0
  91. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/table_processor.py +0 -0
  92. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/text_formatters.py +0 -0
  93. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/types.py +0 -0
  94. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/converters/url_processor.py +0 -0
  95. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/cache/__init__.py +0 -0
  96. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/cache/advanced_cache.py +0 -0
  97. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/cache/bibliography_cache.py +0 -0
  98. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/cache/cache_utils.py +0 -0
  99. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/cache/doi_cache.py +0 -0
  100. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/cache/secure_cache_utils.py +0 -0
  101. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/content_processor.py +0 -0
  102. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/environment_bootstrap.py +0 -0
  103. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/environment_manager.py +0 -0
  104. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/error_codes.py +0 -0
  105. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/error_recovery.py +0 -0
  106. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/logging_config.py +0 -0
  107. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/__init__.py +0 -0
  108. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/cache_manager.py +0 -0
  109. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/dependency_manager.py +0 -0
  110. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/execution_manager.py +0 -0
  111. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/file_manager.py +0 -0
  112. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/install_manager.py +0 -0
  113. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/state_manager.py +0 -0
  114. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/unified_config_manager.py +0 -0
  115. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/validation_manager.py +0 -0
  116. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/managers/workflow_manager.py +0 -0
  117. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/path_manager.py +0 -0
  118. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/progress_framework.py +0 -0
  119. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/repo_config.py +0 -0
  120. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/repository.py +0 -0
  121. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/session_optimizer.py +0 -0
  122. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/core/validation_framework.py +0 -0
  123. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/data/tips.yaml +0 -0
  124. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/__init__.py +0 -0
  125. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/__init__.py +0 -0
  126. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/add_bibliography.py +0 -0
  127. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/build_manager.py +0 -0
  128. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/cleanup.py +0 -0
  129. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/fix_bibliography.py +0 -0
  130. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/generate_docs.py +0 -0
  131. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/generate_figures.py +0 -0
  132. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/generate_preprint.py +0 -0
  133. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/prepare_arxiv.py +0 -0
  134. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/setup_environment.py +0 -0
  135. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/track_changes.py +0 -0
  136. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/validate.py +0 -0
  137. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/engines/operations/validate_pdf.py +0 -0
  138. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/exporters/__init__.py +0 -0
  139. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/__init__.py +0 -0
  140. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/dependency_handlers/__init__.py +0 -0
  141. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/dependency_handlers/latex.py +0 -0
  142. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/dependency_handlers/r_lang.py +0 -0
  143. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/dependency_handlers/system_libs.py +0 -0
  144. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/platform_installers/__init__.py +0 -0
  145. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/platform_installers/base.py +0 -0
  146. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/platform_installers/linux.py +0 -0
  147. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/platform_installers/macos.py +0 -0
  148. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/platform_installers/windows.py +0 -0
  149. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/utils/__init__.py +0 -0
  150. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/utils/logging.py +0 -0
  151. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/utils/progress.py +0 -0
  152. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/install/utils/verification.py +0 -0
  153. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/manuscript_utils/__init__.py +0 -0
  154. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/manuscript_utils/figure_utils.py +0 -0
  155. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/processors/__init__.py +0 -0
  156. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/processors/author_processor.py +0 -0
  157. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/processors/markdown_preprocessor.py +0 -0
  158. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/processors/template_processor.py +0 -0
  159. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/processors/yaml_processor.py +0 -0
  160. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/rxiv_maker_cli.py +0 -0
  161. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/scripts/__init__.py +0 -0
  162. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/scripts/custom_doc_generator.py +0 -0
  163. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/scripts/validate_manuscript.py +0 -0
  164. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/services/__init__.py +0 -0
  165. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/services/base.py +0 -0
  166. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/services/build_service.py +0 -0
  167. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/services/configuration_service.py +0 -0
  168. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/services/manuscript_service.py +0 -0
  169. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/services/publication_service.py +0 -0
  170. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/services/validation_service.py +0 -0
  171. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/templates/__init__.py +0 -0
  172. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/templates/manager.py +0 -0
  173. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/tex/python_execution_section.tex +0 -0
  174. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/__init__.py +0 -0
  175. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/author_name_formatter.py +0 -0
  176. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/bibliography_checksum.py +0 -0
  177. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/bibliography_parser.py +0 -0
  178. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/bst_generator.py +0 -0
  179. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/changelog_parser.py +0 -0
  180. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/citation_utils.py +0 -0
  181. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/dependency_checker.py +0 -0
  182. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/doi_resolver.py +0 -0
  183. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/email_encoder.py +0 -0
  184. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/figure_checksum.py +0 -0
  185. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/file_helpers.py +0 -0
  186. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/github.py +0 -0
  187. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/homebrew_checker.py +0 -0
  188. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/install_detector.py +0 -0
  189. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/operation_ids.py +0 -0
  190. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/pdf_utils.py +0 -0
  191. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/performance.py +0 -0
  192. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/platform.py +0 -0
  193. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/python_execution_reporter.py +0 -0
  194. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/retry.py +0 -0
  195. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/rich_upgrade_notifier.py +0 -0
  196. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/text_utils.py +0 -0
  197. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/tips.py +0 -0
  198. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/title_sync.py +0 -0
  199. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/unicode_safe.py +0 -0
  200. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/update_checker.py +0 -0
  201. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/utils/url_to_doi.py +0 -0
  202. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validate.py +0 -0
  203. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/__init__.py +0 -0
  204. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/base_validator.py +0 -0
  205. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/citation_validator.py +0 -0
  206. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/doi/__init__.py +0 -0
  207. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/doi/api_clients.py +0 -0
  208. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/doi/metadata_comparator.py +0 -0
  209. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/doi_validator.py +0 -0
  210. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/figure_validator.py +0 -0
  211. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/latex_error_parser.py +0 -0
  212. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/math_validator.py +0 -0
  213. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/pdf_validator.py +0 -0
  214. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/reference_validator.py +0 -0
  215. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/rxiv_maker/validators/syntax_validator.py +0 -0
  216. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/tex/style/rxiv_maker_style.bst +0 -0
  217. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/src/tex/template.tex +0 -0
  218. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/__init__.py +0 -0
  219. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/cli/__init__.py +0 -0
  220. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/cli/test_build.py +0 -0
  221. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/cli/test_main.py +0 -0
  222. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/conftest.py +0 -0
  223. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/e2e/__init__.py +0 -0
  224. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/e2e/test_dummy_manuscript_generator.py +0 -0
  225. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/e2e/test_figure_workflow_validation.py +0 -0
  226. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/00_CONFIG.yml +0 -0
  227. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/01_MAIN.md +0 -0
  228. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/03_REFERENCES.bib +0 -0
  229. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/FIGURES/Fig1.png +0 -0
  230. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/FIGURES/Fig2.png +0 -0
  231. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/FIGURES/Fig3.png +0 -0
  232. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/README.md +0 -0
  233. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/docx_export/sample_manuscript/01_MAIN.md +0 -0
  234. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/docx_export/sample_manuscript/02_SUPPLEMENTARY_INFO.md +0 -0
  235. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/docx_export/sample_manuscript/03_REFERENCES.bib +0 -0
  236. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/fixtures/docx_export/sample_manuscript/sample_manuscript.docx +0 -0
  237. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/__init__.py +0 -0
  238. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_article_generation.py +0 -0
  239. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_bibliography_author_format_docx.py +0 -0
  240. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_binary_distribution.py +0 -0
  241. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_centralized_components.py +0 -0
  242. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_citation_injection.py +0 -0
  243. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_comment_system_integration.py +0 -0
  244. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_docx_export_integration.py +0 -0
  245. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_doi_fallback_integration.py +0 -0
  246. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_doi_validation_integration.py +0 -0
  247. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_example_manuscript.py +0 -0
  248. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_guillaume_fixtures.py +0 -0
  249. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_homebrew_workflow_validation.py +0 -0
  250. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_infrastructure_suite.py +0 -0
  251. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_init_build_workflow.py +0 -0
  252. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_install_verification_integration.py +0 -0
  253. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_latex_dependency_integration.py +0 -0
  254. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_manuscript_directory_integration.py +0 -0
  255. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_manuscript_python_execution_reporting.py +0 -0
  256. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_practical_manuscript_workflows.py +0 -0
  257. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_pypi_package_integration.py +0 -0
  258. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_python_execution_integration.py +0 -0
  259. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_repository_cli_integration.py +0 -0
  260. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_supplementary_formatting.py +0 -0
  261. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_user_reported_issue.py +0 -0
  262. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/integration/test_validation_workflow.py +0 -0
  263. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/README.md +0 -0
  264. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/conftest.py +0 -0
  265. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/test_cli_argument_parsing.py +0 -0
  266. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/test_discord_reported_issues.py +0 -0
  267. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/test_error_message_quality.py +0 -0
  268. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/test_google_colab_integration.py +0 -0
  269. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/test_guillaume_edge_cases.py +0 -0
  270. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/test_guillaume_pr131_rewrite.py +0 -0
  271. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/test_path_resolution.py +0 -0
  272. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/test_widget_author_behavior.py +0 -0
  273. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/regression/test_widget_interactions_playwright.py +0 -0
  274. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/smoke/__init__.py +0 -0
  275. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/smoke/test_basic_functionality.py +0 -0
  276. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/smoke/test_cli_smoke.py +0 -0
  277. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/system/__init__.py +0 -0
  278. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/system/test_ci_matrix.py +0 -0
  279. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/system/test_cli_workflows.py +0 -0
  280. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/system/test_end_to_end.py +0 -0
  281. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/test_homebrew_checker.py +0 -0
  282. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/test_install_detector.py +0 -0
  283. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/__init__.py +0 -0
  284. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/exporters/__init__.py +0 -0
  285. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_add_bibliography.py +0 -0
  286. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_arxiv_command.py +0 -0
  287. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_async_execution_manager.py +0 -0
  288. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_author_name_formatter.py +0 -0
  289. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_author_processor.py +0 -0
  290. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_bst_generator.py +0 -0
  291. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_build_command.py +0 -0
  292. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_build_manager.py +0 -0
  293. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_build_manager_manuscript_path.py +0 -0
  294. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_cache_security.py +0 -0
  295. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_cache_utils.py +0 -0
  296. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_check_installation_command.py +0 -0
  297. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_citation_rendering.py +0 -0
  298. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_citation_style.py +0 -0
  299. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_citation_utils.py +0 -0
  300. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_cli_cleanup_integration.py +0 -0
  301. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_cli_structure.py +0 -0
  302. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_comment_processor.py +0 -0
  303. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_conda_installation_manager.py +0 -0
  304. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_conda_platform_detection.py +0 -0
  305. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_cross_platform_optimizations.py +0 -0
  306. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_custom_command_processor.py +0 -0
  307. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_dependency_manager.py +0 -0
  308. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_dependency_package_names.py +0 -0
  309. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_docx_doi_resolution.py +0 -0
  310. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_doi_fallback_system.py +0 -0
  311. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_doi_resolver.py +0 -0
  312. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_doi_validator.py +0 -0
  313. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_email_encoder.py +0 -0
  314. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_environment_manager.py +0 -0
  315. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_error_handling_scenarios.py +0 -0
  316. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_execution_manager_comprehensive.py +0 -0
  317. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_figure_generator.py +0 -0
  318. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_figure_processor.py +0 -0
  319. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_figure_processor_error_handling.py +0 -0
  320. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_file_helpers.py +0 -0
  321. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_fix_bibliography.py +0 -0
  322. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_generate_docs.py +0 -0
  323. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_generate_preprint.py +0 -0
  324. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_github.py +0 -0
  325. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_github_actions_integration.py +0 -0
  326. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_install_platform_installers.py +0 -0
  327. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_install_system_libs.py +0 -0
  328. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_install_verification.py +0 -0
  329. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_interactive_path_change.py +0 -0
  330. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_interactive_validators.py +0 -0
  331. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_latex_dependency_handler.py +0 -0
  332. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_manuscript_figure_utils.py +0 -0
  333. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_manuscript_repository.py +0 -0
  334. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_math_processor.py +0 -0
  335. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_md2tex.py +0 -0
  336. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_mermaid_fallback.py +0 -0
  337. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_path_manager.py +0 -0
  338. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_pdf_validator.py +0 -0
  339. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_platform_comprehensive.py +0 -0
  340. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_platform_detector.py +0 -0
  341. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_processor_suite.py +0 -0
  342. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_python_execution_reporter.py +0 -0
  343. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_python_executor.py +0 -0
  344. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_release_orchestrator.py +0 -0
  345. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_repository_manager.py +0 -0
  346. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_rich_upgrade_notifier.py +0 -0
  347. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_rxiv_setup_command.py +0 -0
  348. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_security_features.py +0 -0
  349. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_security_scanner.py +0 -0
  350. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_setup_environment.py +0 -0
  351. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_style_file_resolution.py +0 -0
  352. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_supplementary_note_processor.py +0 -0
  353. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_table_rotation.py +0 -0
  354. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_template_processor.py +0 -0
  355. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_text_formatters.py +0 -0
  356. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_text_utils.py +0 -0
  357. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_tips.py +0 -0
  358. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_title_sync.py +0 -0
  359. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_title_sync_validation.py +0 -0
  360. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_trailing_slash_regression.py +0 -0
  361. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_upgrade_command.py +0 -0
  362. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_url_to_doi.py +0 -0
  363. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_utils.py +0 -0
  364. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_validate_backticks.py +0 -0
  365. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_validate_command_fixed.py +0 -0
  366. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_validate_manuscript.py +0 -0
  367. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_validation_suite.py +0 -0
  368. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_validators.py +0 -0
  369. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/unit/test_yaml_processor.py +0 -0
  370. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/README.md +0 -0
  371. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/figure-positioning/00_CONFIG.yml +0 -0
  372. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/figure-positioning/01_MAIN.md +0 -0
  373. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/figure-positioning/03_REFERENCES.bib +0 -0
  374. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/figure-positioning/FIGURES/Figure__positioning_test.png +0 -0
  375. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/figure-positioning/FIGURES/Figure__positioning_test.py +0 -0
  376. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/figure-positioning/FIGURES/ReadyFig.png +0 -0
  377. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/figure-positioning/FIGURES/ReadyFig.py +0 -0
  378. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/figure-positioning/README.md +0 -0
  379. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/methods-placement/00_CONFIG.yml +0 -0
  380. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/methods-placement/01_MAIN.md +0 -0
  381. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/methods-placement/02_SUPPLEMENTARY_INFO.md +0 -0
  382. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/methods-placement/03_REFERENCES.bib +0 -0
  383. {rxiv_maker-1.16.8 → rxiv_maker-1.18.0}/tests/visual/methods-placement/README.md +0 -0
@@ -7,6 +7,129 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.18.0] - 2025-12-23
11
+
12
+ ### Added
13
+
14
+ - **DOCX Configuration Options**: New manuscript config options for enhanced control
15
+ - `docx.hide_highlighting`: Disable colored highlighting of references (default: false)
16
+ - `docx.hide_comments`: Disable comment inclusion in output (default: false)
17
+ - Provides flexibility for different journal submission requirements
18
+ - **Co-First Author Support**: Full support for co-first authors in DOCX export
19
+ - Dagger markers (†) for co-first authors
20
+ - "These authors contributed equally" note section
21
+ - Automatic detection based on author metadata
22
+ - **Corresponding Author Support**: Enhanced author metadata handling
23
+ - Asterisk markers (*) for corresponding authors
24
+ - Dedicated correspondence section with email information
25
+ - Email decoding for both plain `email` and base64-encoded `email64` fields
26
+ - **Centralized Utilities**: Five new shared utility modules to reduce code duplication
27
+ - `utils/accent_character_map.py`: LaTeX accent → Unicode conversion (60+ mappings)
28
+ - `utils/comment_filter.py`: Metadata comment filtering logic
29
+ - `utils/citation_range_formatter.py`: Citation range formatting ([1][2][3] → [1-3])
30
+ - `utils/label_extractor.py`: Cross-reference label extraction for figures, tables, equations
31
+ - `utils/author_affiliation_processor.py`: Author and affiliation processing logic
32
+ - Ensures consistency between DOCX and PDF/LaTeX generation
33
+ - Single source of truth reduces bug surface area and improves maintainability
34
+
35
+ ### Changed
36
+
37
+ - **DOCX Typography**: Professional font and sizing improvements
38
+ - Arial as default font for entire document (Normal style + all heading styles 1-9)
39
+ - Standardized 8pt font size for affiliations, correspondence, co-first notes, and legends
40
+ - All headings now explicitly use black font color (RGBColor(0, 0, 0))
41
+ - Improved readability and professional appearance
42
+
43
+ ### Fixed
44
+
45
+ - **Init Command Environment Variable**: Fixed test isolation issue in init command
46
+ - Init command no longer uses `MANUSCRIPT_PATH` environment variable
47
+ - Environment variable is for finding existing manuscripts, not initialization
48
+ - Prevents test failures where multiple tests tried to use the same directory
49
+ - All 25 init command tests now pass reliably in CI
50
+ - **Init Command CI Compatibility**: Fixed subprocess execution in nox environments
51
+ - Changed from `["rxiv"]` to `[sys.executable, "-m", "rxiv_maker.cli"]`
52
+ - Ensures init command tests work in CI nox environments where `rxiv` may not be in PATH
53
+ - Improves test reliability across different execution contexts
54
+
55
+ ### Documentation
56
+
57
+ - **Code Reduction**: Removed ~100 lines of duplicate code from DOCX exporter through centralization
58
+ - **Backward Compatibility**: All changes maintain existing behavior with default configuration
59
+ - **Testing**: All 37 DOCX tests pass (26 passed, 9 skipped, 2 warnings)
60
+
61
+ ## [1.17.0] - 2025-12-22
62
+
63
+ ### Added
64
+
65
+ - **PDF Splitting Feature**: New `--split-si` flag for `rxiv pdf` command
66
+ - Automatically splits generated PDFs into main manuscript and supplementary information sections
67
+ - Auto-detects SI markers ("Supplementary Information", "Supplementary Material", "Supporting Information", etc.)
68
+ - Generates properly named split files: `{year}__{author}_et_al__rxiv__main.pdf` and `{year}__{author}_et_al__rxiv__si.pdf`
69
+ - Places split files in MANUSCRIPT directory with consistent naming convention
70
+ - Addresses common journal submission requirements for separate main and SI files
71
+ - **Color-Coded DOCX References**: Visual distinction for different reference types
72
+ - Main figures: bright green highlighting
73
+ - Main tables: blue highlighting
74
+ - Supplementary elements (figures, tables, notes): turquoise highlighting
75
+ - Citations: yellow highlighting
76
+ - Equations: violet highlighting
77
+ - Improves readability and helps track different element types during review
78
+ - **Citation Range Formatting**: Automatic formatting of adjacent citations
79
+ - Formats `[4][5][6]` as `[4-6]` for cleaner presentation
80
+ - Handles both adjacent bracket citations and comma-separated citations
81
+ - Maintains readability while reducing visual clutter
82
+ - **DOCX Configuration Options**: New manuscript config options
83
+ - `docx.hide_si`: Control supplementary information visibility (default: false)
84
+ - `docx.figures_at_end`: Place main figures at end before bibliography (default: false)
85
+ - Clearer semantics than previous `add_si` option
86
+ - Supports different journal formatting requirements
87
+ - **Subscript/Superscript Support**: Chemical formulas and mathematical notation in DOCX
88
+ - Supports `~subscript~` and `^superscript^` markdown syntax
89
+ - Enables proper formatting of chemical formulas (H~2~O) and exponents (x^2^)
90
+
91
+ ### Fixed
92
+
93
+ - **Citation Extraction Bug**: Citations between triple-backtick code blocks now extract correctly
94
+ - Fixed regex processing order to handle triple backticks before single backticks
95
+ - Prevents citations from being incorrectly marked as "protected code content"
96
+ - Resolves issue where `[@key]` citations remained unconverted in DOCX output
97
+ - Added regression tests to prevent future occurrences
98
+ - **Bibliography Formatting**: Enhanced cleanup for malformed BibTeX entries
99
+ - HTML entity decoding: `é` → `é`, `á` → `á`, `…` → `…`
100
+ - Malformed name repair: fixes split author names (e.g., "Pé and Rez, Fernando" → "Pérez, Fernando")
101
+ - Brace cleanup: removes stray braces after Unicode characters
102
+ - Handles escaped HTML entities from BibTeX (`\&\#233` → `é`)
103
+ - Whitespace normalization for cleaner bibliography entries
104
+ - **Table Caption Formatting**: Supplementary tables now show proper labels
105
+ - Displays "Supp. Table SX." prefix with correct font sizing
106
+ - Preserves table label identifiers during processing
107
+ - Supports hyphens in table label names
108
+ - **Comment Filtering**: Markdown metadata comments no longer appear in DOCX
109
+ - Filters comments starting with "note:", "comment:" (case-insensitive)
110
+ - Prevents manuscript-specific metadata from appearing in final output
111
+ - Improves multi-line comment parsing
112
+
113
+ ### Changed
114
+
115
+ - **Figure Centering**: All figures now centered by default in DOCX exports
116
+ - Improves visual presentation and alignment with journal standards
117
+ - Consistent formatting across all figure types
118
+ - **Citation Handling**: Citations treated as highlighted text instead of separate objects
119
+ - Maintains citation ranges in yellow highlighting
120
+ - Simplifies DOCX structure while preserving visual distinction
121
+ - **PDF Spacing**: Optimized manuscript spacing for increased content density
122
+ - Tighter spacing between back matter section headers and text
123
+ - Improved overall visual hierarchy
124
+ - More content per page without sacrificing readability
125
+
126
+ ### Documentation
127
+
128
+ - **Updated CLAUDE.md**: Enhanced development documentation
129
+ - Removed Docker/Podman engine references (moved to separate docker-rxiv-maker repository)
130
+ - Added PDF splitting feature documentation
131
+ - Clarified testing workflows and CI requirements
132
+
10
133
  ## [1.16.8] - 2025-12-19
11
134
 
12
135
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rxiv-maker
3
- Version: 1.16.8
3
+ Version: 1.18.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.8"
3
+ __version__ = "1.18.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,
@@ -30,8 +30,10 @@ class InitCommand(BaseCommand):
30
30
  self.engine = "local" # Only local engine is supported
31
31
 
32
32
  # Store manuscript path without PathManager validation since we're creating the directory
33
+ # NOTE: For init command, we should NOT use environment variable MANUSCRIPT_PATH
34
+ # as it's meant for finding existing manuscripts, not determining where to initialize
33
35
  if manuscript_path is None:
34
- manuscript_path = EnvironmentManager.get_manuscript_path() or "MANUSCRIPT"
36
+ manuscript_path = "MANUSCRIPT"
35
37
 
36
38
  # Store the raw path for use in execute_operation
37
39
  self.raw_manuscript_path = manuscript_path
@@ -142,6 +144,7 @@ class BuildCommand(BaseCommand):
142
144
  keep_output: bool = False,
143
145
  docx: bool = False,
144
146
  resolve_dois: bool = False,
147
+ split_si: bool = False,
145
148
  debug: bool = False,
146
149
  quiet: bool = False,
147
150
  container_mode: Optional[str] = None,
@@ -156,6 +159,7 @@ class BuildCommand(BaseCommand):
156
159
  keep_output: Preserve existing output directory
157
160
  docx: Also export to DOCX format
158
161
  resolve_dois: Attempt to resolve missing DOIs (for DOCX export)
162
+ split_si: Split PDF into main and SI sections
159
163
  debug: Enable debug output
160
164
  quiet: Suppress non-critical warnings
161
165
  container_mode: Container behavior mode
@@ -223,6 +227,10 @@ class BuildCommand(BaseCommand):
223
227
  if docx:
224
228
  self._export_docx(resolve_dois=resolve_dois, quiet=quiet, debug=debug)
225
229
 
230
+ # Split PDF if requested
231
+ if split_si:
232
+ self._split_pdf(pdf_path, quiet=quiet, debug=debug)
233
+
226
234
  # Show helpful tips after successful build
227
235
  self._show_build_tips()
228
236
 
@@ -252,11 +260,69 @@ class BuildCommand(BaseCommand):
252
260
  self.console.print(f"[green]✅ DOCX exported:[/green] {docx_path}")
253
261
 
254
262
  except Exception as e:
255
- self.console.print(f"[yellow]⚠️ DOCX export failed:[/yellow] {e}", err=True)
263
+ self.console.print(f"[yellow]⚠️ DOCX export failed:[/yellow] {e}")
264
+ if debug:
265
+ import traceback
266
+
267
+ self.console.print(f"[dim]{traceback.format_exc()}[/dim]")
268
+
269
+ def _split_pdf(self, pdf_path: Path, quiet: bool = False, debug: bool = False) -> None:
270
+ """Split PDF into main and SI sections after successful PDF build.
271
+
272
+ Args:
273
+ pdf_path: Path to the generated PDF
274
+ quiet: Suppress non-essential output
275
+ debug: Enable debug output
276
+ """
277
+ try:
278
+ from ...processors.yaml_processor import extract_yaml_metadata
279
+ from ...utils.file_helpers import find_manuscript_md
280
+ from ...utils.pdf_splitter import split_pdf
281
+ from ...utils.pdf_utils import get_custom_pdf_filename
282
+
283
+ if not quiet:
284
+ self.console.print("\n[cyan]✂️ Splitting PDF into main and SI sections...[/cyan]")
285
+
286
+ # Split the PDF
287
+ main_path, si_path = split_pdf(pdf_path)
288
+
289
+ if main_path and si_path:
290
+ # Extract metadata to generate custom filename
291
+ manuscript_md = find_manuscript_md(str(self.path_manager.manuscript_path))
292
+ yaml_metadata = extract_yaml_metadata(str(manuscript_md))
293
+
294
+ # Get base filename (e.g., "2025__saraiva_et_al__rxiv.pdf")
295
+ base_filename = get_custom_pdf_filename(yaml_metadata)
296
+ base_name = base_filename.replace(".pdf", "")
297
+
298
+ # Generate final filenames with __main and __si suffixes
299
+ main_filename = f"{base_name}__main.pdf"
300
+ si_filename = f"{base_name}__si.pdf"
301
+
302
+ # Copy split files to manuscript directory
303
+ final_main_path = self.path_manager.manuscript_path / main_filename
304
+ final_si_path = self.path_manager.manuscript_path / si_filename
305
+
306
+ shutil.copy2(main_path, final_main_path)
307
+ shutil.copy2(si_path, final_si_path)
308
+
309
+ if not quiet:
310
+ self.console.print("[green]✅ PDF split successfully:[/green]")
311
+ self.console.print(f" 📄 Main: {final_main_path}")
312
+ self.console.print(f" 📄 SI: {final_si_path}")
313
+ elif main_path is None and si_path is None:
314
+ if not quiet:
315
+ self.console.print("[yellow]⚠️ Could not split PDF: SI section marker not found[/yellow]")
316
+ else:
317
+ if not quiet:
318
+ self.console.print("[yellow]⚠️ PDF splitting partially failed[/yellow]")
319
+
320
+ except Exception as e:
321
+ self.console.print(f"[yellow]⚠️ PDF splitting failed:[/yellow] {e}")
256
322
  if debug:
257
323
  import traceback
258
324
 
259
- self.console.print(f"[dim]{traceback.format_exc()}[/dim]", err=True)
325
+ self.console.print(f"[dim]{traceback.format_exc()}[/dim]")
260
326
 
261
327
  def _show_build_tips(self) -> None:
262
328
  """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,
@@ -8,11 +8,26 @@ import re
8
8
  from typing import Dict, List
9
9
 
10
10
  from ..converters.citation_processor import extract_citations_from_text
11
+ from ..utils.citation_range_formatter import format_citation_ranges
11
12
 
12
13
 
13
14
  class CitationMapper:
14
15
  """Maps citation keys to sequential numbers for DOCX export."""
15
16
 
17
+ @staticmethod
18
+ def _format_citation_ranges(text: str) -> str:
19
+ """Format consecutive citations as ranges.
20
+
21
+ Uses centralized citation range formatter from utils module.
22
+
23
+ Args:
24
+ text: Text with numbered citations
25
+
26
+ Returns:
27
+ Text with consecutive citations formatted as ranges
28
+ """
29
+ return format_citation_ranges(text)
30
+
16
31
  def create_mapping(self, citations: List[str]) -> Dict[str, int]:
17
32
  """Create citation key → number mapping.
18
33
 
@@ -121,4 +136,7 @@ class CitationMapper:
121
136
  for i, pattern in enumerate(email_patterns):
122
137
  text = text.replace(f"__EMAIL_PATTERN_{i}__", pattern)
123
138
 
139
+ # Format consecutive citations as ranges (e.g., [1][2][3] -> [1-3])
140
+ text = self._format_citation_ranges(text)
141
+
124
142
  return text
@@ -7,6 +7,8 @@ DOCX generation with python-docx.
7
7
  import re
8
8
  from typing import Any, Dict, List, Optional
9
9
 
10
+ from ..utils.comment_filter import is_metadata_comment
11
+
10
12
 
11
13
  class DocxContentProcessor:
12
14
  """Parses markdown content into structured format for DOCX writing."""
@@ -55,10 +57,38 @@ class DocxContentProcessor:
55
57
  i += 1
56
58
  continue
57
59
 
58
- # Skip HTML/markdown comments
60
+ # Parse HTML/markdown comments (single-line and multi-line)
61
+ # Skip informational/metadata comments (those starting with "Note:")
59
62
  if line.strip().startswith("<!--"):
60
- i += 1
61
- continue
63
+ # Check if it's a single-line comment
64
+ if line.strip().endswith("-->"):
65
+ # Single-line comment
66
+ comment_text = line.strip()[4:-3].strip()
67
+ # Skip metadata comments (e.g., "note that...", "Comment: ...")
68
+ if comment_text and not is_metadata_comment(comment_text):
69
+ sections.append({"type": "comment", "text": comment_text})
70
+ i += 1
71
+ continue
72
+ else:
73
+ # Multi-line comment - collect all lines until -->
74
+ comment_lines = [line.strip()[4:]] # Remove <!--
75
+ i += 1
76
+ while i < len(lines):
77
+ if lines[i].strip().endswith("-->"):
78
+ # Last line of comment
79
+ comment_lines.append(lines[i].strip()[:-3]) # Remove -->
80
+ i += 1
81
+ break
82
+ else:
83
+ comment_lines.append(lines[i].strip())
84
+ i += 1
85
+
86
+ # Join and add comment
87
+ comment_text = " ".join(comment_lines).strip()
88
+ # Skip metadata comments (e.g., "note that...", "Comment: ...")
89
+ if comment_text and not is_metadata_comment(comment_text):
90
+ sections.append({"type": "comment", "text": comment_text})
91
+ continue
62
92
 
63
93
  # Skip LaTeX commands like <clearpage>
64
94
  if line.strip().startswith("<") and line.strip().endswith(">") and " " not in line.strip():
@@ -335,18 +365,21 @@ class DocxContentProcessor:
335
365
  runs = []
336
366
 
337
367
  # Find all formatting markers, links, and citations
338
- # Pattern to match: <<HIGHLIGHT_YELLOW>>text<</HIGHLIGHT_YELLOW>>, <<XREF>>text<</XREF>>, [text](url), **bold**, __underlined__, *italic*, _italic_, `code`, $math$, [number]
368
+ # Pattern to match: <<HIGHLIGHT_YELLOW>>text<</HIGHLIGHT_YELLOW>>, <<XREF:type>>text<</XREF>>, <!-- comment -->, [text](url), **bold**, __underlined__, *italic*, _italic_, ~subscript~, ^superscript^, `code`, $math$, [number]
339
369
  pattern = re.compile(
340
370
  r"(<<HIGHLIGHT_YELLOW>>([^<]+)<</HIGHLIGHT_YELLOW>>)" # Yellow highlight (must be first)
341
- r"|(<<XREF>>([^<]+)<</XREF>>)" # Cross-reference
371
+ r"|(<<XREF:(\w+)>>([^<]+)<</XREF>>)" # Cross-reference with type
372
+ r"|(<!--\s*(.+?)\s*-->)" # HTML comments (inline)
342
373
  r"|(\[([^\]]+)\]\(([^)]+)\))" # Markdown link [text](url) (before citations)
343
374
  r"|(\*\*([^*]+)\*\*)" # Bold
344
375
  r"|(__([^_]+)__)" # Underline with double underscores (must come before single underscore)
345
376
  r"|(\*([^*]+)\*)" # Italic with asterisks
346
377
  r"|(_([^_]+)_)" # Italic with underscores
378
+ r"|(~([^~]+)~)" # Subscript
379
+ r"|(\^([^^]+)\^)" # Superscript
347
380
  r"|(`([^`]+)`)" # Code
348
381
  r"|(\$([^\$]+)\$)" # Inline math
349
- r"|(\[(\d+(?:,\s*\d+)*)\])" # Citation numbers
382
+ r"|(\[(\d+(?:[-,]\s*\d+)*)\])" # Citation numbers (supports both ranges [1-3] and lists [1, 2])
350
383
  )
351
384
 
352
385
  last_end = 0
@@ -378,67 +411,99 @@ class DocxContentProcessor:
378
411
  if run["type"] == "text":
379
412
  run["highlight_yellow"] = True
380
413
  runs.append(run)
381
- elif match.group(3): # Cross-reference
414
+ elif match.group(3): # Cross-reference with type
382
415
  runs.append(
383
416
  {
384
417
  "type": "text",
385
- "text": match.group(4),
418
+ "text": match.group(5), # Text is now in group 5
386
419
  "bold": False,
387
420
  "italic": False,
388
421
  "underline": False,
389
422
  "code": False,
390
423
  "xref": True,
424
+ "xref_type": match.group(4), # Type is in group 4
391
425
  }
392
426
  )
393
- elif match.group(5): # Markdown link [text](url)
427
+ elif match.group(6): # Inline HTML comment
428
+ comment_text = match.group(7).strip()
429
+ # Skip metadata comments (e.g., "note that...", "Comment: ...")
430
+ if comment_text and not is_metadata_comment(comment_text):
431
+ runs.append({"type": "inline_comment", "text": comment_text})
432
+ elif match.group(8): # Markdown link [text](url)
394
433
  runs.append(
395
434
  {
396
435
  "type": "hyperlink",
397
- "text": match.group(6),
398
- "url": match.group(7),
436
+ "text": match.group(9),
437
+ "url": match.group(10),
399
438
  }
400
439
  )
401
- elif match.group(8): # Bold
440
+ elif match.group(11): # Bold
402
441
  # Recursively parse inner text for underline/italic/other formatting
403
- inner_text = match.group(9)
442
+ inner_text = match.group(12)
404
443
  inner_runs = self._parse_inline_formatting(inner_text, citation_map)
405
444
  # Add bold to all inner runs
406
445
  for run in inner_runs:
407
446
  if run["type"] == "text":
408
447
  run["bold"] = True
409
448
  runs.append(run)
410
- elif match.group(10): # Underline
449
+ elif match.group(13): # Underline
411
450
  # Recursively parse inner text for bold/italic/other formatting
412
- inner_text = match.group(11)
451
+ inner_text = match.group(14)
413
452
  inner_runs = self._parse_inline_formatting(inner_text, citation_map)
414
453
  # Add underline to all inner runs
415
454
  for run in inner_runs:
416
455
  if run["type"] == "text":
417
456
  run["underline"] = True
418
457
  runs.append(run)
419
- elif match.group(12): # Italic with asterisks
458
+ elif match.group(15): # Italic with asterisks
420
459
  # Recursively parse inner text for bold/underline/other formatting
421
- inner_text = match.group(13)
460
+ inner_text = match.group(16)
422
461
  inner_runs = self._parse_inline_formatting(inner_text, citation_map)
423
462
  # Add italic to all inner runs
424
463
  for run in inner_runs:
425
464
  if run["type"] == "text":
426
465
  run["italic"] = True
427
466
  runs.append(run)
428
- elif match.group(14): # Italic with underscores
467
+ elif match.group(17): # Italic with underscores
429
468
  # Recursively parse inner text for bold/underline/other formatting
430
- inner_text = match.group(15)
469
+ inner_text = match.group(18)
431
470
  inner_runs = self._parse_inline_formatting(inner_text, citation_map)
432
471
  # Add italic to all inner runs
433
472
  for run in inner_runs:
434
473
  if run["type"] == "text":
435
474
  run["italic"] = True
436
475
  runs.append(run)
437
- elif match.group(16): # Code
476
+ elif match.group(19): # Subscript
438
477
  runs.append(
439
478
  {
440
479
  "type": "text",
441
- "text": match.group(17),
480
+ "text": match.group(20),
481
+ "bold": False,
482
+ "italic": False,
483
+ "underline": False,
484
+ "code": False,
485
+ "xref": False,
486
+ "subscript": True,
487
+ }
488
+ )
489
+ elif match.group(21): # Superscript
490
+ runs.append(
491
+ {
492
+ "type": "text",
493
+ "text": match.group(22),
494
+ "bold": False,
495
+ "italic": False,
496
+ "underline": False,
497
+ "code": False,
498
+ "xref": False,
499
+ "superscript": True,
500
+ }
501
+ )
502
+ elif match.group(23): # Code
503
+ runs.append(
504
+ {
505
+ "type": "text",
506
+ "text": match.group(24),
442
507
  "bold": False,
443
508
  "italic": False,
444
509
  "underline": False,
@@ -446,14 +511,23 @@ class DocxContentProcessor:
446
511
  "xref": False,
447
512
  }
448
513
  )
449
- elif match.group(18): # Inline math
450
- runs.append({"type": "inline_equation", "latex": match.group(19)})
451
- elif match.group(20): # Citation
452
- # Parse citation numbers (may be multiple: [1, 2, 3])
453
- numbers_str = match.group(21)
454
- numbers = [int(n.strip()) for n in numbers_str.split(",")]
455
- for num in numbers:
456
- runs.append({"type": "citation", "number": num})
514
+ elif match.group(25): # Inline math
515
+ runs.append({"type": "inline_equation", "latex": match.group(26)})
516
+ elif match.group(27): # Citation
517
+ # Keep citation as formatted text with yellow highlighting
518
+ # The citation mapper has already formatted ranges (e.g., [1-3], [1, 4-6, 8])
519
+ citation_text = match.group(0) # Full match including brackets
520
+ runs.append(
521
+ {
522
+ "type": "text",
523
+ "text": citation_text,
524
+ "bold": False,
525
+ "italic": False,
526
+ "underline": False,
527
+ "code": False,
528
+ "highlight_yellow": True, # Highlight citations in yellow
529
+ }
530
+ )
457
531
 
458
532
  last_end = match.end()
459
533
 
@@ -516,6 +590,7 @@ class DocxContentProcessor:
516
590
  # Look ahead for caption line (skip empty lines)
517
591
  caption = ""
518
592
  label = ""
593
+ is_supplementary = False # Default to main figure
519
594
  next_i = start_idx + 1
520
595
 
521
596
  # Skip empty lines to find caption
@@ -529,6 +604,9 @@ class DocxContentProcessor:
529
604
 
530
605
  # Check for {#fig:label ...} or {#sfig:label ...} **Caption**
531
606
  if next_line and (next_line.startswith("{#fig:") or next_line.startswith("{#sfig:")):
607
+ # Detect if it's a supplementary figure
608
+ is_supplementary = next_line.startswith("{#sfig:")
609
+
532
610
  # Extract label if present
533
611
  label_match = re.match(r"\{#s?fig:(\w+)[^}]*\}", next_line)
534
612
  if label_match:
@@ -572,6 +650,7 @@ class DocxContentProcessor:
572
650
  "alt": alt_text,
573
651
  "caption": caption,
574
652
  "label": label,
653
+ "is_supplementary": is_supplementary,
575
654
  }, next_i
576
655
 
577
656
  def _parse_table(self, lines: List[str], start_idx: int) -> tuple[Optional[Dict[str, Any]], int]:
@@ -626,7 +705,8 @@ class DocxContentProcessor:
626
705
  if i < len(lines):
627
706
  caption_line = lines[i].strip()
628
707
  # Match {#stable:label} Caption or {#table:label} Caption
629
- caption_match = re.match(r"^\{#(stable|table):(\w+)\}\s*(.+)$", caption_line)
708
+ # Allow hyphens and underscores in label names (e.g., "tool-comparison")
709
+ caption_match = re.match(r"^\{#(stable|table):([\w-]+)\}\s*(.+)$", caption_line)
630
710
  if caption_match:
631
711
  label = f"{caption_match.group(1)}:{caption_match.group(2)}"
632
712
  caption = caption_match.group(3).strip()