scientific-writer 2.1.1__py3-none-any.whl → 2.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of scientific-writer might be problematic. Click here for more details.

Files changed (311) hide show
  1. scientific_writer/.claude/settings.local.json +30 -0
  2. scientific_writer/.claude/skills/citation-management/SKILL.md +1046 -0
  3. scientific_writer/.claude/skills/citation-management/assets/bibtex_template.bib +264 -0
  4. scientific_writer/.claude/skills/citation-management/assets/citation_checklist.md +386 -0
  5. scientific_writer/.claude/skills/citation-management/references/bibtex_formatting.md +908 -0
  6. scientific_writer/.claude/skills/citation-management/references/citation_validation.md +794 -0
  7. scientific_writer/.claude/skills/citation-management/references/google_scholar_search.md +725 -0
  8. scientific_writer/.claude/skills/citation-management/references/metadata_extraction.md +870 -0
  9. scientific_writer/.claude/skills/citation-management/references/pubmed_search.md +839 -0
  10. scientific_writer/.claude/skills/citation-management/scripts/doi_to_bibtex.py +204 -0
  11. scientific_writer/.claude/skills/citation-management/scripts/extract_metadata.py +569 -0
  12. scientific_writer/.claude/skills/citation-management/scripts/format_bibtex.py +349 -0
  13. scientific_writer/.claude/skills/citation-management/scripts/search_google_scholar.py +282 -0
  14. scientific_writer/.claude/skills/citation-management/scripts/search_pubmed.py +398 -0
  15. scientific_writer/.claude/skills/citation-management/scripts/validate_citations.py +497 -0
  16. scientific_writer/.claude/skills/clinical-reports/IMPLEMENTATION_SUMMARY.md +641 -0
  17. scientific_writer/.claude/skills/clinical-reports/README.md +236 -0
  18. scientific_writer/.claude/skills/clinical-reports/SKILL.md +1088 -0
  19. scientific_writer/.claude/skills/clinical-reports/assets/case_report_template.md +352 -0
  20. scientific_writer/.claude/skills/clinical-reports/assets/clinical_trial_csr_template.md +353 -0
  21. scientific_writer/.claude/skills/clinical-reports/assets/clinical_trial_sae_template.md +359 -0
  22. scientific_writer/.claude/skills/clinical-reports/assets/consult_note_template.md +305 -0
  23. scientific_writer/.claude/skills/clinical-reports/assets/discharge_summary_template.md +453 -0
  24. scientific_writer/.claude/skills/clinical-reports/assets/hipaa_compliance_checklist.md +395 -0
  25. scientific_writer/.claude/skills/clinical-reports/assets/history_physical_template.md +305 -0
  26. scientific_writer/.claude/skills/clinical-reports/assets/lab_report_template.md +309 -0
  27. scientific_writer/.claude/skills/clinical-reports/assets/pathology_report_template.md +249 -0
  28. scientific_writer/.claude/skills/clinical-reports/assets/quality_checklist.md +338 -0
  29. scientific_writer/.claude/skills/clinical-reports/assets/radiology_report_template.md +318 -0
  30. scientific_writer/.claude/skills/clinical-reports/assets/soap_note_template.md +253 -0
  31. scientific_writer/.claude/skills/clinical-reports/references/case_report_guidelines.md +570 -0
  32. scientific_writer/.claude/skills/clinical-reports/references/clinical_trial_reporting.md +693 -0
  33. scientific_writer/.claude/skills/clinical-reports/references/data_presentation.md +530 -0
  34. scientific_writer/.claude/skills/clinical-reports/references/diagnostic_reports_standards.md +629 -0
  35. scientific_writer/.claude/skills/clinical-reports/references/medical_terminology.md +588 -0
  36. scientific_writer/.claude/skills/clinical-reports/references/patient_documentation.md +744 -0
  37. scientific_writer/.claude/skills/clinical-reports/references/peer_review_standards.md +585 -0
  38. scientific_writer/.claude/skills/clinical-reports/references/regulatory_compliance.md +577 -0
  39. scientific_writer/.claude/skills/clinical-reports/scripts/check_deidentification.py +346 -0
  40. scientific_writer/.claude/skills/clinical-reports/scripts/compliance_checker.py +78 -0
  41. scientific_writer/.claude/skills/clinical-reports/scripts/extract_clinical_data.py +102 -0
  42. scientific_writer/.claude/skills/clinical-reports/scripts/format_adverse_events.py +103 -0
  43. scientific_writer/.claude/skills/clinical-reports/scripts/generate_report_template.py +163 -0
  44. scientific_writer/.claude/skills/clinical-reports/scripts/terminology_validator.py +133 -0
  45. scientific_writer/.claude/skills/clinical-reports/scripts/validate_case_report.py +334 -0
  46. scientific_writer/.claude/skills/clinical-reports/scripts/validate_trial_report.py +89 -0
  47. scientific_writer/.claude/skills/document-skills/docx/LICENSE.txt +30 -0
  48. scientific_writer/.claude/skills/document-skills/docx/SKILL.md +197 -0
  49. scientific_writer/.claude/skills/document-skills/docx/docx-js.md +350 -0
  50. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  51. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  52. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  53. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  54. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  55. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  56. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  57. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  58. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  59. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  60. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  61. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  62. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  63. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  64. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  65. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  66. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  67. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  68. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  69. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  70. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  71. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  72. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  73. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  74. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  75. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  76. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  77. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  78. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  79. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  80. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  81. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
  82. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  83. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  84. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  85. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  86. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  87. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  88. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  89. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/pack.py +159 -0
  90. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/unpack.py +29 -0
  91. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validate.py +69 -0
  92. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/__init__.py +15 -0
  93. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/base.py +951 -0
  94. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/docx.py +274 -0
  95. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/pptx.py +315 -0
  96. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/redlining.py +279 -0
  97. scientific_writer/.claude/skills/document-skills/docx/ooxml.md +610 -0
  98. scientific_writer/.claude/skills/document-skills/docx/scripts/__init__.py +1 -0
  99. scientific_writer/.claude/skills/document-skills/docx/scripts/document.py +1276 -0
  100. scientific_writer/.claude/skills/document-skills/docx/scripts/templates/comments.xml +3 -0
  101. scientific_writer/.claude/skills/document-skills/docx/scripts/templates/commentsExtended.xml +3 -0
  102. scientific_writer/.claude/skills/document-skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  103. scientific_writer/.claude/skills/document-skills/docx/scripts/templates/commentsIds.xml +3 -0
  104. scientific_writer/.claude/skills/document-skills/docx/scripts/templates/people.xml +3 -0
  105. scientific_writer/.claude/skills/document-skills/docx/scripts/utilities.py +374 -0
  106. scientific_writer/.claude/skills/document-skills/pdf/LICENSE.txt +30 -0
  107. scientific_writer/.claude/skills/document-skills/pdf/SKILL.md +294 -0
  108. scientific_writer/.claude/skills/document-skills/pdf/forms.md +205 -0
  109. scientific_writer/.claude/skills/document-skills/pdf/reference.md +612 -0
  110. scientific_writer/.claude/skills/document-skills/pdf/scripts/check_bounding_boxes.py +70 -0
  111. scientific_writer/.claude/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
  112. scientific_writer/.claude/skills/document-skills/pdf/scripts/check_fillable_fields.py +12 -0
  113. scientific_writer/.claude/skills/document-skills/pdf/scripts/convert_pdf_to_images.py +35 -0
  114. scientific_writer/.claude/skills/document-skills/pdf/scripts/create_validation_image.py +41 -0
  115. scientific_writer/.claude/skills/document-skills/pdf/scripts/extract_form_field_info.py +152 -0
  116. scientific_writer/.claude/skills/document-skills/pdf/scripts/fill_fillable_fields.py +114 -0
  117. scientific_writer/.claude/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  118. scientific_writer/.claude/skills/document-skills/pptx/LICENSE.txt +30 -0
  119. scientific_writer/.claude/skills/document-skills/pptx/SKILL.md +484 -0
  120. scientific_writer/.claude/skills/document-skills/pptx/html2pptx.md +625 -0
  121. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  122. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  123. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  124. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  125. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  126. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  127. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  128. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  129. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  130. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  131. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  132. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  133. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  134. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  135. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  136. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  137. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  138. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  139. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  140. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  141. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  142. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  143. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  144. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  145. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  146. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  147. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  148. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  149. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  150. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  151. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  152. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
  153. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  154. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  155. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  156. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  157. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  158. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  159. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  160. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/pack.py +159 -0
  161. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/unpack.py +29 -0
  162. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validate.py +69 -0
  163. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
  164. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/base.py +951 -0
  165. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/docx.py +274 -0
  166. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
  167. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
  168. scientific_writer/.claude/skills/document-skills/pptx/ooxml.md +427 -0
  169. scientific_writer/.claude/skills/document-skills/pptx/scripts/html2pptx.js +979 -0
  170. scientific_writer/.claude/skills/document-skills/pptx/scripts/inventory.py +1020 -0
  171. scientific_writer/.claude/skills/document-skills/pptx/scripts/rearrange.py +231 -0
  172. scientific_writer/.claude/skills/document-skills/pptx/scripts/replace.py +385 -0
  173. scientific_writer/.claude/skills/document-skills/pptx/scripts/thumbnail.py +450 -0
  174. scientific_writer/.claude/skills/document-skills/xlsx/LICENSE.txt +30 -0
  175. scientific_writer/.claude/skills/document-skills/xlsx/SKILL.md +289 -0
  176. scientific_writer/.claude/skills/document-skills/xlsx/recalc.py +178 -0
  177. scientific_writer/.claude/skills/hypothesis-generation/SKILL.md +155 -0
  178. scientific_writer/.claude/skills/hypothesis-generation/assets/hypothesis_output_template.md +302 -0
  179. scientific_writer/.claude/skills/hypothesis-generation/references/experimental_design_patterns.md +327 -0
  180. scientific_writer/.claude/skills/hypothesis-generation/references/hypothesis_quality_criteria.md +196 -0
  181. scientific_writer/.claude/skills/hypothesis-generation/references/literature_search_strategies.md +505 -0
  182. scientific_writer/.claude/skills/latex-posters/README.md +417 -0
  183. scientific_writer/.claude/skills/latex-posters/SKILL.md +919 -0
  184. scientific_writer/.claude/skills/latex-posters/assets/baposter_template.tex +257 -0
  185. scientific_writer/.claude/skills/latex-posters/assets/beamerposter_template.tex +244 -0
  186. scientific_writer/.claude/skills/latex-posters/assets/poster_quality_checklist.md +358 -0
  187. scientific_writer/.claude/skills/latex-posters/assets/tikzposter_template.tex +251 -0
  188. scientific_writer/.claude/skills/latex-posters/references/latex_poster_packages.md +745 -0
  189. scientific_writer/.claude/skills/latex-posters/references/poster_content_guide.md +748 -0
  190. scientific_writer/.claude/skills/latex-posters/references/poster_design_principles.md +806 -0
  191. scientific_writer/.claude/skills/latex-posters/references/poster_layout_design.md +900 -0
  192. scientific_writer/.claude/skills/latex-posters/scripts/review_poster.sh +214 -0
  193. scientific_writer/.claude/skills/literature-review/SKILL.md +546 -0
  194. scientific_writer/.claude/skills/literature-review/assets/review_template.md +412 -0
  195. scientific_writer/.claude/skills/literature-review/references/citation_styles.md +166 -0
  196. scientific_writer/.claude/skills/literature-review/references/database_strategies.md +381 -0
  197. scientific_writer/.claude/skills/literature-review/scripts/generate_pdf.py +176 -0
  198. scientific_writer/.claude/skills/literature-review/scripts/search_databases.py +303 -0
  199. scientific_writer/.claude/skills/literature-review/scripts/verify_citations.py +222 -0
  200. scientific_writer/.claude/skills/markitdown/INSTALLATION_GUIDE.md +318 -0
  201. scientific_writer/.claude/skills/markitdown/LICENSE.txt +22 -0
  202. scientific_writer/.claude/skills/markitdown/OPENROUTER_INTEGRATION.md +359 -0
  203. scientific_writer/.claude/skills/markitdown/QUICK_REFERENCE.md +309 -0
  204. scientific_writer/.claude/skills/markitdown/README.md +184 -0
  205. scientific_writer/.claude/skills/markitdown/SKILL.md +450 -0
  206. scientific_writer/.claude/skills/markitdown/SKILL_SUMMARY.md +307 -0
  207. scientific_writer/.claude/skills/markitdown/assets/example_usage.md +463 -0
  208. scientific_writer/.claude/skills/markitdown/references/api_reference.md +399 -0
  209. scientific_writer/.claude/skills/markitdown/references/file_formats.md +542 -0
  210. scientific_writer/.claude/skills/markitdown/scripts/batch_convert.py +228 -0
  211. scientific_writer/.claude/skills/markitdown/scripts/convert_literature.py +283 -0
  212. scientific_writer/.claude/skills/markitdown/scripts/convert_with_ai.py +243 -0
  213. scientific_writer/.claude/skills/paper-2-web/SKILL.md +455 -0
  214. scientific_writer/.claude/skills/paper-2-web/references/installation.md +141 -0
  215. scientific_writer/.claude/skills/paper-2-web/references/paper2poster.md +346 -0
  216. scientific_writer/.claude/skills/paper-2-web/references/paper2video.md +305 -0
  217. scientific_writer/.claude/skills/paper-2-web/references/paper2web.md +187 -0
  218. scientific_writer/.claude/skills/paper-2-web/references/usage_examples.md +436 -0
  219. scientific_writer/.claude/skills/peer-review/SKILL.md +375 -0
  220. scientific_writer/.claude/skills/peer-review/references/common_issues.md +552 -0
  221. scientific_writer/.claude/skills/peer-review/references/reporting_standards.md +290 -0
  222. scientific_writer/.claude/skills/research-grants/README.md +285 -0
  223. scientific_writer/.claude/skills/research-grants/SKILL.md +896 -0
  224. scientific_writer/.claude/skills/research-grants/assets/budget_justification_template.md +453 -0
  225. scientific_writer/.claude/skills/research-grants/assets/nih_specific_aims_template.md +166 -0
  226. scientific_writer/.claude/skills/research-grants/assets/nsf_project_summary_template.md +92 -0
  227. scientific_writer/.claude/skills/research-grants/references/broader_impacts.md +392 -0
  228. scientific_writer/.claude/skills/research-grants/references/darpa_guidelines.md +636 -0
  229. scientific_writer/.claude/skills/research-grants/references/doe_guidelines.md +586 -0
  230. scientific_writer/.claude/skills/research-grants/references/nih_guidelines.md +851 -0
  231. scientific_writer/.claude/skills/research-grants/references/nsf_guidelines.md +570 -0
  232. scientific_writer/.claude/skills/research-grants/references/specific_aims_guide.md +458 -0
  233. scientific_writer/.claude/skills/research-lookup/README.md +116 -0
  234. scientific_writer/.claude/skills/research-lookup/SKILL.md +443 -0
  235. scientific_writer/.claude/skills/research-lookup/examples.py +174 -0
  236. scientific_writer/.claude/skills/research-lookup/lookup.py +93 -0
  237. scientific_writer/.claude/skills/research-lookup/research_lookup.py +335 -0
  238. scientific_writer/.claude/skills/research-lookup/scripts/research_lookup.py +261 -0
  239. scientific_writer/.claude/skills/scholar-evaluation/SKILL.md +254 -0
  240. scientific_writer/.claude/skills/scholar-evaluation/references/evaluation_framework.md +663 -0
  241. scientific_writer/.claude/skills/scholar-evaluation/scripts/calculate_scores.py +378 -0
  242. scientific_writer/.claude/skills/scientific-critical-thinking/SKILL.md +530 -0
  243. scientific_writer/.claude/skills/scientific-critical-thinking/references/common_biases.md +364 -0
  244. scientific_writer/.claude/skills/scientific-critical-thinking/references/evidence_hierarchy.md +484 -0
  245. scientific_writer/.claude/skills/scientific-critical-thinking/references/experimental_design.md +496 -0
  246. scientific_writer/.claude/skills/scientific-critical-thinking/references/logical_fallacies.md +478 -0
  247. scientific_writer/.claude/skills/scientific-critical-thinking/references/scientific_method.md +169 -0
  248. scientific_writer/.claude/skills/scientific-critical-thinking/references/statistical_pitfalls.md +506 -0
  249. scientific_writer/.claude/skills/scientific-schematics/SKILL.md +2035 -0
  250. scientific_writer/.claude/skills/scientific-schematics/assets/block_diagram_template.tex +199 -0
  251. scientific_writer/.claude/skills/scientific-schematics/assets/circuit_template.tex +159 -0
  252. scientific_writer/.claude/skills/scientific-schematics/assets/flowchart_template.tex +161 -0
  253. scientific_writer/.claude/skills/scientific-schematics/assets/pathway_template.tex +162 -0
  254. scientific_writer/.claude/skills/scientific-schematics/assets/tikz_styles.tex +422 -0
  255. scientific_writer/.claude/skills/scientific-schematics/references/best_practices.md +562 -0
  256. scientific_writer/.claude/skills/scientific-schematics/references/diagram_types.md +637 -0
  257. scientific_writer/.claude/skills/scientific-schematics/references/python_libraries.md +791 -0
  258. scientific_writer/.claude/skills/scientific-schematics/references/tikz_guide.md +734 -0
  259. scientific_writer/.claude/skills/scientific-schematics/scripts/circuit_generator.py +307 -0
  260. scientific_writer/.claude/skills/scientific-schematics/scripts/compile_tikz.py +292 -0
  261. scientific_writer/.claude/skills/scientific-schematics/scripts/generate_flowchart.py +281 -0
  262. scientific_writer/.claude/skills/scientific-schematics/scripts/pathway_diagram.py +406 -0
  263. scientific_writer/.claude/skills/scientific-writing/SKILL.md +443 -0
  264. scientific_writer/.claude/skills/scientific-writing/references/citation_styles.md +720 -0
  265. scientific_writer/.claude/skills/scientific-writing/references/figures_tables.md +806 -0
  266. scientific_writer/.claude/skills/scientific-writing/references/imrad_structure.md +658 -0
  267. scientific_writer/.claude/skills/scientific-writing/references/reporting_guidelines.md +748 -0
  268. scientific_writer/.claude/skills/scientific-writing/references/writing_principles.md +824 -0
  269. scientific_writer/.claude/skills/treatment-plans/README.md +483 -0
  270. scientific_writer/.claude/skills/treatment-plans/SKILL.md +817 -0
  271. scientific_writer/.claude/skills/treatment-plans/assets/chronic_disease_management_plan.tex +636 -0
  272. scientific_writer/.claude/skills/treatment-plans/assets/general_medical_treatment_plan.tex +616 -0
  273. scientific_writer/.claude/skills/treatment-plans/assets/mental_health_treatment_plan.tex +745 -0
  274. scientific_writer/.claude/skills/treatment-plans/assets/pain_management_plan.tex +770 -0
  275. scientific_writer/.claude/skills/treatment-plans/assets/perioperative_care_plan.tex +724 -0
  276. scientific_writer/.claude/skills/treatment-plans/assets/quality_checklist.md +471 -0
  277. scientific_writer/.claude/skills/treatment-plans/assets/rehabilitation_treatment_plan.tex +727 -0
  278. scientific_writer/.claude/skills/treatment-plans/references/goal_setting_frameworks.md +411 -0
  279. scientific_writer/.claude/skills/treatment-plans/references/intervention_guidelines.md +507 -0
  280. scientific_writer/.claude/skills/treatment-plans/references/regulatory_compliance.md +476 -0
  281. scientific_writer/.claude/skills/treatment-plans/references/specialty_specific_guidelines.md +607 -0
  282. scientific_writer/.claude/skills/treatment-plans/references/treatment_plan_standards.md +456 -0
  283. scientific_writer/.claude/skills/treatment-plans/scripts/check_completeness.py +318 -0
  284. scientific_writer/.claude/skills/treatment-plans/scripts/generate_template.py +244 -0
  285. scientific_writer/.claude/skills/treatment-plans/scripts/timeline_generator.py +369 -0
  286. scientific_writer/.claude/skills/treatment-plans/scripts/validate_treatment_plan.py +367 -0
  287. scientific_writer/.claude/skills/venue-templates/SKILL.md +590 -0
  288. scientific_writer/.claude/skills/venue-templates/assets/grants/nih_specific_aims.tex +235 -0
  289. scientific_writer/.claude/skills/venue-templates/assets/grants/nsf_proposal_template.tex +375 -0
  290. scientific_writer/.claude/skills/venue-templates/assets/journals/nature_article.tex +171 -0
  291. scientific_writer/.claude/skills/venue-templates/assets/journals/neurips_article.tex +283 -0
  292. scientific_writer/.claude/skills/venue-templates/assets/journals/plos_one.tex +317 -0
  293. scientific_writer/.claude/skills/venue-templates/assets/posters/beamerposter_academic.tex +311 -0
  294. scientific_writer/.claude/skills/venue-templates/references/conferences_formatting.md +564 -0
  295. scientific_writer/.claude/skills/venue-templates/references/grants_requirements.md +787 -0
  296. scientific_writer/.claude/skills/venue-templates/references/journals_formatting.md +486 -0
  297. scientific_writer/.claude/skills/venue-templates/references/posters_guidelines.md +628 -0
  298. scientific_writer/.claude/skills/venue-templates/scripts/customize_template.py +206 -0
  299. scientific_writer/.claude/skills/venue-templates/scripts/query_template.py +260 -0
  300. scientific_writer/.claude/skills/venue-templates/scripts/validate_format.py +255 -0
  301. scientific_writer/CLAUDE.md +748 -0
  302. scientific_writer/__init__.py +2 -2
  303. scientific_writer/api.py +14 -7
  304. scientific_writer/cli.py +12 -7
  305. scientific_writer/core.py +27 -5
  306. {scientific_writer-2.1.1.dist-info → scientific_writer-2.2.2.dist-info}/METADATA +5 -1
  307. scientific_writer-2.2.2.dist-info/RECORD +312 -0
  308. scientific_writer-2.1.1.dist-info/RECORD +0 -11
  309. {scientific_writer-2.1.1.dist-info → scientific_writer-2.2.2.dist-info}/WHEEL +0 -0
  310. {scientific_writer-2.1.1.dist-info → scientific_writer-2.2.2.dist-info}/entry_points.txt +0 -0
  311. {scientific_writer-2.1.1.dist-info → scientific_writer-2.2.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,497 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Citation Validation Tool
4
+ Validate BibTeX files for accuracy, completeness, and format compliance.
5
+ """
6
+
7
+ import sys
8
+ import re
9
+ import requests
10
+ import argparse
11
+ import json
12
+ from typing import Dict, List, Tuple, Optional
13
+ from collections import defaultdict
14
+
15
+ class CitationValidator:
16
+ """Validate BibTeX entries for errors and inconsistencies."""
17
+
18
+ def __init__(self):
19
+ self.session = requests.Session()
20
+ self.session.headers.update({
21
+ 'User-Agent': 'CitationValidator/1.0 (Citation Management Tool)'
22
+ })
23
+
24
+ # Required fields by entry type
25
+ self.required_fields = {
26
+ 'article': ['author', 'title', 'journal', 'year'],
27
+ 'book': ['title', 'publisher', 'year'], # author OR editor
28
+ 'inproceedings': ['author', 'title', 'booktitle', 'year'],
29
+ 'incollection': ['author', 'title', 'booktitle', 'publisher', 'year'],
30
+ 'phdthesis': ['author', 'title', 'school', 'year'],
31
+ 'mastersthesis': ['author', 'title', 'school', 'year'],
32
+ 'techreport': ['author', 'title', 'institution', 'year'],
33
+ 'misc': ['title', 'year']
34
+ }
35
+
36
+ # Recommended fields
37
+ self.recommended_fields = {
38
+ 'article': ['volume', 'pages', 'doi'],
39
+ 'book': ['isbn'],
40
+ 'inproceedings': ['pages'],
41
+ }
42
+
43
+ def parse_bibtex_file(self, filepath: str) -> List[Dict]:
44
+ """
45
+ Parse BibTeX file and extract entries.
46
+
47
+ Args:
48
+ filepath: Path to BibTeX file
49
+
50
+ Returns:
51
+ List of entry dictionaries
52
+ """
53
+ try:
54
+ with open(filepath, 'r', encoding='utf-8') as f:
55
+ content = f.read()
56
+ except Exception as e:
57
+ print(f'Error reading file: {e}', file=sys.stderr)
58
+ return []
59
+
60
+ entries = []
61
+
62
+ # Match BibTeX entries
63
+ pattern = r'@(\w+)\s*\{\s*([^,\s]+)\s*,(.*?)\n\}'
64
+ matches = re.finditer(pattern, content, re.DOTALL | re.IGNORECASE)
65
+
66
+ for match in matches:
67
+ entry_type = match.group(1).lower()
68
+ citation_key = match.group(2).strip()
69
+ fields_text = match.group(3)
70
+
71
+ # Parse fields
72
+ fields = {}
73
+ field_pattern = r'(\w+)\s*=\s*\{([^}]*)\}|(\w+)\s*=\s*"([^"]*)"'
74
+ field_matches = re.finditer(field_pattern, fields_text)
75
+
76
+ for field_match in field_matches:
77
+ if field_match.group(1):
78
+ field_name = field_match.group(1).lower()
79
+ field_value = field_match.group(2)
80
+ else:
81
+ field_name = field_match.group(3).lower()
82
+ field_value = field_match.group(4)
83
+
84
+ fields[field_name] = field_value.strip()
85
+
86
+ entries.append({
87
+ 'type': entry_type,
88
+ 'key': citation_key,
89
+ 'fields': fields,
90
+ 'raw': match.group(0)
91
+ })
92
+
93
+ return entries
94
+
95
+ def validate_entry(self, entry: Dict) -> Tuple[List[Dict], List[Dict]]:
96
+ """
97
+ Validate a single BibTeX entry.
98
+
99
+ Args:
100
+ entry: Entry dictionary
101
+
102
+ Returns:
103
+ Tuple of (errors, warnings)
104
+ """
105
+ errors = []
106
+ warnings = []
107
+
108
+ entry_type = entry['type']
109
+ key = entry['key']
110
+ fields = entry['fields']
111
+
112
+ # Check required fields
113
+ if entry_type in self.required_fields:
114
+ for req_field in self.required_fields[entry_type]:
115
+ if req_field not in fields or not fields[req_field]:
116
+ # Special case: book can have author OR editor
117
+ if entry_type == 'book' and req_field == 'author':
118
+ if 'editor' not in fields or not fields['editor']:
119
+ errors.append({
120
+ 'type': 'missing_required_field',
121
+ 'field': 'author or editor',
122
+ 'severity': 'high',
123
+ 'message': f'Entry {key}: Missing required field "author" or "editor"'
124
+ })
125
+ else:
126
+ errors.append({
127
+ 'type': 'missing_required_field',
128
+ 'field': req_field,
129
+ 'severity': 'high',
130
+ 'message': f'Entry {key}: Missing required field "{req_field}"'
131
+ })
132
+
133
+ # Check recommended fields
134
+ if entry_type in self.recommended_fields:
135
+ for rec_field in self.recommended_fields[entry_type]:
136
+ if rec_field not in fields or not fields[rec_field]:
137
+ warnings.append({
138
+ 'type': 'missing_recommended_field',
139
+ 'field': rec_field,
140
+ 'severity': 'medium',
141
+ 'message': f'Entry {key}: Missing recommended field "{rec_field}"'
142
+ })
143
+
144
+ # Validate year
145
+ if 'year' in fields:
146
+ year = fields['year']
147
+ if not re.match(r'^\d{4}$', year):
148
+ errors.append({
149
+ 'type': 'invalid_year',
150
+ 'field': 'year',
151
+ 'value': year,
152
+ 'severity': 'high',
153
+ 'message': f'Entry {key}: Invalid year format "{year}" (should be 4 digits)'
154
+ })
155
+ elif int(year) < 1600 or int(year) > 2030:
156
+ warnings.append({
157
+ 'type': 'suspicious_year',
158
+ 'field': 'year',
159
+ 'value': year,
160
+ 'severity': 'medium',
161
+ 'message': f'Entry {key}: Suspicious year "{year}" (outside reasonable range)'
162
+ })
163
+
164
+ # Validate DOI format
165
+ if 'doi' in fields:
166
+ doi = fields['doi']
167
+ if not re.match(r'^10\.\d{4,}/[^\s]+$', doi):
168
+ warnings.append({
169
+ 'type': 'invalid_doi_format',
170
+ 'field': 'doi',
171
+ 'value': doi,
172
+ 'severity': 'medium',
173
+ 'message': f'Entry {key}: Invalid DOI format "{doi}"'
174
+ })
175
+
176
+ # Check for single hyphen in pages (should be --)
177
+ if 'pages' in fields:
178
+ pages = fields['pages']
179
+ if re.search(r'\d-\d', pages) and '--' not in pages:
180
+ warnings.append({
181
+ 'type': 'page_range_format',
182
+ 'field': 'pages',
183
+ 'value': pages,
184
+ 'severity': 'low',
185
+ 'message': f'Entry {key}: Page range uses single hyphen, should use -- (en-dash)'
186
+ })
187
+
188
+ # Check author format
189
+ if 'author' in fields:
190
+ author = fields['author']
191
+ if ';' in author or '&' in author:
192
+ errors.append({
193
+ 'type': 'invalid_author_format',
194
+ 'field': 'author',
195
+ 'severity': 'high',
196
+ 'message': f'Entry {key}: Authors should be separated by " and ", not ";" or "&"'
197
+ })
198
+
199
+ return errors, warnings
200
+
201
+ def verify_doi(self, doi: str) -> Tuple[bool, Optional[Dict]]:
202
+ """
203
+ Verify DOI resolves correctly and get metadata.
204
+
205
+ Args:
206
+ doi: Digital Object Identifier
207
+
208
+ Returns:
209
+ Tuple of (is_valid, metadata)
210
+ """
211
+ try:
212
+ url = f'https://doi.org/{doi}'
213
+ response = self.session.head(url, timeout=10, allow_redirects=True)
214
+
215
+ if response.status_code < 400:
216
+ # DOI resolves, now get metadata from CrossRef
217
+ crossref_url = f'https://api.crossref.org/works/{doi}'
218
+ metadata_response = self.session.get(crossref_url, timeout=10)
219
+
220
+ if metadata_response.status_code == 200:
221
+ data = metadata_response.json()
222
+ message = data.get('message', {})
223
+
224
+ # Extract key metadata
225
+ metadata = {
226
+ 'title': message.get('title', [''])[0],
227
+ 'year': self._extract_year_crossref(message),
228
+ 'authors': self._format_authors_crossref(message.get('author', [])),
229
+ }
230
+ return True, metadata
231
+ else:
232
+ return True, None # DOI resolves but no CrossRef metadata
233
+ else:
234
+ return False, None
235
+
236
+ except Exception:
237
+ return False, None
238
+
239
+ def detect_duplicates(self, entries: List[Dict]) -> List[Dict]:
240
+ """
241
+ Detect duplicate entries.
242
+
243
+ Args:
244
+ entries: List of entry dictionaries
245
+
246
+ Returns:
247
+ List of duplicate groups
248
+ """
249
+ duplicates = []
250
+
251
+ # Check for duplicate DOIs
252
+ doi_map = defaultdict(list)
253
+ for entry in entries:
254
+ doi = entry['fields'].get('doi', '').strip()
255
+ if doi:
256
+ doi_map[doi].append(entry['key'])
257
+
258
+ for doi, keys in doi_map.items():
259
+ if len(keys) > 1:
260
+ duplicates.append({
261
+ 'type': 'duplicate_doi',
262
+ 'doi': doi,
263
+ 'entries': keys,
264
+ 'severity': 'high',
265
+ 'message': f'Duplicate DOI {doi} found in entries: {", ".join(keys)}'
266
+ })
267
+
268
+ # Check for duplicate citation keys
269
+ key_counts = defaultdict(int)
270
+ for entry in entries:
271
+ key_counts[entry['key']] += 1
272
+
273
+ for key, count in key_counts.items():
274
+ if count > 1:
275
+ duplicates.append({
276
+ 'type': 'duplicate_key',
277
+ 'key': key,
278
+ 'count': count,
279
+ 'severity': 'high',
280
+ 'message': f'Citation key "{key}" appears {count} times'
281
+ })
282
+
283
+ # Check for similar titles (possible duplicates)
284
+ titles = {}
285
+ for entry in entries:
286
+ title = entry['fields'].get('title', '').lower()
287
+ title = re.sub(r'[^\w\s]', '', title) # Remove punctuation
288
+ title = ' '.join(title.split()) # Normalize whitespace
289
+
290
+ if title:
291
+ if title in titles:
292
+ duplicates.append({
293
+ 'type': 'similar_title',
294
+ 'entries': [titles[title], entry['key']],
295
+ 'severity': 'medium',
296
+ 'message': f'Possible duplicate: "{titles[title]}" and "{entry["key"]}" have identical titles'
297
+ })
298
+ else:
299
+ titles[title] = entry['key']
300
+
301
+ return duplicates
302
+
303
+ def validate_file(self, filepath: str, check_dois: bool = False) -> Dict:
304
+ """
305
+ Validate entire BibTeX file.
306
+
307
+ Args:
308
+ filepath: Path to BibTeX file
309
+ check_dois: Whether to verify DOIs (slow)
310
+
311
+ Returns:
312
+ Validation report dictionary
313
+ """
314
+ print(f'Parsing {filepath}...', file=sys.stderr)
315
+ entries = self.parse_bibtex_file(filepath)
316
+
317
+ if not entries:
318
+ return {
319
+ 'total_entries': 0,
320
+ 'errors': [],
321
+ 'warnings': [],
322
+ 'duplicates': []
323
+ }
324
+
325
+ print(f'Found {len(entries)} entries', file=sys.stderr)
326
+
327
+ all_errors = []
328
+ all_warnings = []
329
+
330
+ # Validate each entry
331
+ for i, entry in enumerate(entries):
332
+ print(f'Validating entry {i+1}/{len(entries)}: {entry["key"]}', file=sys.stderr)
333
+ errors, warnings = self.validate_entry(entry)
334
+
335
+ for error in errors:
336
+ error['entry'] = entry['key']
337
+ all_errors.append(error)
338
+
339
+ for warning in warnings:
340
+ warning['entry'] = entry['key']
341
+ all_warnings.append(warning)
342
+
343
+ # Check for duplicates
344
+ print('Checking for duplicates...', file=sys.stderr)
345
+ duplicates = self.detect_duplicates(entries)
346
+
347
+ # Verify DOIs if requested
348
+ doi_errors = []
349
+ if check_dois:
350
+ print('Verifying DOIs...', file=sys.stderr)
351
+ for i, entry in enumerate(entries):
352
+ doi = entry['fields'].get('doi', '')
353
+ if doi:
354
+ print(f'Verifying DOI {i+1}: {doi}', file=sys.stderr)
355
+ is_valid, metadata = self.verify_doi(doi)
356
+
357
+ if not is_valid:
358
+ doi_errors.append({
359
+ 'type': 'invalid_doi',
360
+ 'entry': entry['key'],
361
+ 'doi': doi,
362
+ 'severity': 'high',
363
+ 'message': f'Entry {entry["key"]}: DOI does not resolve: {doi}'
364
+ })
365
+
366
+ all_errors.extend(doi_errors)
367
+
368
+ return {
369
+ 'filepath': filepath,
370
+ 'total_entries': len(entries),
371
+ 'valid_entries': len(entries) - len([e for e in all_errors if e['severity'] == 'high']),
372
+ 'errors': all_errors,
373
+ 'warnings': all_warnings,
374
+ 'duplicates': duplicates
375
+ }
376
+
377
+ def _extract_year_crossref(self, message: Dict) -> str:
378
+ """Extract year from CrossRef message."""
379
+ date_parts = message.get('published-print', {}).get('date-parts', [[]])
380
+ if not date_parts or not date_parts[0]:
381
+ date_parts = message.get('published-online', {}).get('date-parts', [[]])
382
+
383
+ if date_parts and date_parts[0]:
384
+ return str(date_parts[0][0])
385
+ return ''
386
+
387
+ def _format_authors_crossref(self, authors: List[Dict]) -> str:
388
+ """Format author list from CrossRef."""
389
+ if not authors:
390
+ return ''
391
+
392
+ formatted = []
393
+ for author in authors[:3]: # First 3 authors
394
+ given = author.get('given', '')
395
+ family = author.get('family', '')
396
+ if family:
397
+ formatted.append(f'{family}, {given}' if given else family)
398
+
399
+ if len(authors) > 3:
400
+ formatted.append('et al.')
401
+
402
+ return ', '.join(formatted)
403
+
404
+
405
+ def main():
406
+ """Command-line interface."""
407
+ parser = argparse.ArgumentParser(
408
+ description='Validate BibTeX files for errors and inconsistencies',
409
+ epilog='Example: python validate_citations.py references.bib'
410
+ )
411
+
412
+ parser.add_argument(
413
+ 'file',
414
+ help='BibTeX file to validate'
415
+ )
416
+
417
+ parser.add_argument(
418
+ '--check-dois',
419
+ action='store_true',
420
+ help='Verify DOIs resolve correctly (slow)'
421
+ )
422
+
423
+ parser.add_argument(
424
+ '--auto-fix',
425
+ action='store_true',
426
+ help='Attempt to auto-fix common issues (not implemented yet)'
427
+ )
428
+
429
+ parser.add_argument(
430
+ '--report',
431
+ help='Output file for JSON validation report'
432
+ )
433
+
434
+ parser.add_argument(
435
+ '--verbose',
436
+ action='store_true',
437
+ help='Show detailed output'
438
+ )
439
+
440
+ args = parser.parse_args()
441
+
442
+ # Validate file
443
+ validator = CitationValidator()
444
+ report = validator.validate_file(args.file, check_dois=args.check_dois)
445
+
446
+ # Print summary
447
+ print('\n' + '='*60)
448
+ print('CITATION VALIDATION REPORT')
449
+ print('='*60)
450
+ print(f'\nFile: {args.file}')
451
+ print(f'Total entries: {report["total_entries"]}')
452
+ print(f'Valid entries: {report["valid_entries"]}')
453
+ print(f'Errors: {len(report["errors"])}')
454
+ print(f'Warnings: {len(report["warnings"])}')
455
+ print(f'Duplicates: {len(report["duplicates"])}')
456
+
457
+ # Print errors
458
+ if report['errors']:
459
+ print('\n' + '-'*60)
460
+ print('ERRORS (must fix):')
461
+ print('-'*60)
462
+ for error in report['errors']:
463
+ print(f'\n{error["message"]}')
464
+ if args.verbose:
465
+ print(f' Type: {error["type"]}')
466
+ print(f' Severity: {error["severity"]}')
467
+
468
+ # Print warnings
469
+ if report['warnings'] and args.verbose:
470
+ print('\n' + '-'*60)
471
+ print('WARNINGS (should fix):')
472
+ print('-'*60)
473
+ for warning in report['warnings']:
474
+ print(f'\n{warning["message"]}')
475
+
476
+ # Print duplicates
477
+ if report['duplicates']:
478
+ print('\n' + '-'*60)
479
+ print('DUPLICATES:')
480
+ print('-'*60)
481
+ for dup in report['duplicates']:
482
+ print(f'\n{dup["message"]}')
483
+
484
+ # Save report
485
+ if args.report:
486
+ with open(args.report, 'w', encoding='utf-8') as f:
487
+ json.dump(report, f, indent=2)
488
+ print(f'\nDetailed report saved to: {args.report}')
489
+
490
+ # Exit with error code if there are errors
491
+ if report['errors']:
492
+ sys.exit(1)
493
+
494
+
495
+ if __name__ == '__main__':
496
+ main()
497
+