latextify 0.1.0rc1__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.
- latextify-0.1.0rc1/.dockerignore +20 -0
- latextify-0.1.0rc1/.gitattributes +5 -0
- latextify-0.1.0rc1/.github/dependabot.yml +13 -0
- latextify-0.1.0rc1/.github/workflows/ci.yml +172 -0
- latextify-0.1.0rc1/.github/workflows/codeql.yml +23 -0
- latextify-0.1.0rc1/.github/workflows/dependency-audit.yml +45 -0
- latextify-0.1.0rc1/.github/workflows/publish.yml +72 -0
- latextify-0.1.0rc1/.github/workflows/release.yml +120 -0
- latextify-0.1.0rc1/.gitignore +52 -0
- latextify-0.1.0rc1/CONTRIBUTING.md +51 -0
- latextify-0.1.0rc1/LICENSE +202 -0
- latextify-0.1.0rc1/NOTICE +9 -0
- latextify-0.1.0rc1/PKG-INFO +264 -0
- latextify-0.1.0rc1/README.md +220 -0
- latextify-0.1.0rc1/SECURITY.md +96 -0
- latextify-0.1.0rc1/deploy/hf-space/DEPLOY.md +77 -0
- latextify-0.1.0rc1/deploy/hf-space/Dockerfile +46 -0
- latextify-0.1.0rc1/deploy/hf-space/README.md +43 -0
- latextify-0.1.0rc1/deploy/hf-space/warm_cache.py +83 -0
- latextify-0.1.0rc1/deploy/render/DEPLOY.md +50 -0
- latextify-0.1.0rc1/deploy/render/Dockerfile +44 -0
- latextify-0.1.0rc1/examples/01-all-embedded/.gitignore +4 -0
- latextify-0.1.0rc1/examples/01-all-embedded/README.md +69 -0
- latextify-0.1.0rc1/examples/01-all-embedded/make_manuscript.py +135 -0
- latextify-0.1.0rc1/examples/01-all-embedded/run.py +53 -0
- latextify-0.1.0rc1/examples/02-word-plus-figures/.gitignore +6 -0
- latextify-0.1.0rc1/examples/02-word-plus-figures/README.md +71 -0
- latextify-0.1.0rc1/examples/02-word-plus-figures/make_manuscript.py +135 -0
- latextify-0.1.0rc1/examples/02-word-plus-figures/run.py +50 -0
- latextify-0.1.0rc1/examples/03-multipart-refmanager/.gitignore +5 -0
- latextify-0.1.0rc1/examples/03-multipart-refmanager/README.md +109 -0
- latextify-0.1.0rc1/examples/03-multipart-refmanager/make_manuscript.py +279 -0
- latextify-0.1.0rc1/examples/03-multipart-refmanager/run.py +53 -0
- latextify-0.1.0rc1/examples/README.md +59 -0
- latextify-0.1.0rc1/latextify/__init__.py +15 -0
- latextify-0.1.0rc1/latextify/__main__.py +11 -0
- latextify-0.1.0rc1/latextify/audit/__init__.py +20 -0
- latextify-0.1.0rc1/latextify/audit/equations.py +433 -0
- latextify-0.1.0rc1/latextify/citations/__init__.py +37 -0
- latextify-0.1.0rc1/latextify/citations/authoryear_index.py +54 -0
- latextify-0.1.0rc1/latextify/citations/bib.py +353 -0
- latextify-0.1.0rc1/latextify/citations/bibmatch.py +57 -0
- latextify-0.1.0rc1/latextify/citations/bibtex_in.py +212 -0
- latextify-0.1.0rc1/latextify/citations/corrections.py +173 -0
- latextify-0.1.0rc1/latextify/citations/crossref.py +343 -0
- latextify-0.1.0rc1/latextify/citations/csl_json_in.py +60 -0
- latextify-0.1.0rc1/latextify/citations/endnote.py +208 -0
- latextify-0.1.0rc1/latextify/citations/endnote_xml_in.py +72 -0
- latextify-0.1.0rc1/latextify/citations/fields.py +334 -0
- latextify-0.1.0rc1/latextify/citations/mendeley.py +27 -0
- latextify-0.1.0rc1/latextify/citations/merge.py +77 -0
- latextify-0.1.0rc1/latextify/citations/nbib_in.py +143 -0
- latextify-0.1.0rc1/latextify/citations/plaintext.py +622 -0
- latextify-0.1.0rc1/latextify/citations/reconcile.py +245 -0
- latextify-0.1.0rc1/latextify/citations/reflist_nondocx.py +94 -0
- latextify-0.1.0rc1/latextify/citations/refs_import.py +72 -0
- latextify-0.1.0rc1/latextify/citations/validate.py +303 -0
- latextify-0.1.0rc1/latextify/citations/wordnative.py +211 -0
- latextify-0.1.0rc1/latextify/citations/zotero.py +128 -0
- latextify-0.1.0rc1/latextify/cli.py +517 -0
- latextify-0.1.0rc1/latextify/cli_batch.py +226 -0
- latextify-0.1.0rc1/latextify/cli_clean.py +50 -0
- latextify-0.1.0rc1/latextify/cli_equations.py +92 -0
- latextify-0.1.0rc1/latextify/cli_export.py +100 -0
- latextify-0.1.0rc1/latextify/cli_review.py +114 -0
- latextify-0.1.0rc1/latextify/compile/__init__.py +12 -0
- latextify-0.1.0rc1/latextify/compile/logs.py +148 -0
- latextify-0.1.0rc1/latextify/compile/pdf.py +42 -0
- latextify-0.1.0rc1/latextify/compile/tectonic.py +383 -0
- latextify-0.1.0rc1/latextify/emit/__init__.py +41 -0
- latextify-0.1.0rc1/latextify/emit/alt_formats.py +458 -0
- latextify-0.1.0rc1/latextify/emit/alt_formats_render.py +264 -0
- latextify-0.1.0rc1/latextify/emit/anchors.py +272 -0
- latextify-0.1.0rc1/latextify/emit/metadata.py +36 -0
- latextify-0.1.0rc1/latextify/emit/project.py +971 -0
- latextify-0.1.0rc1/latextify/emit/submission.py +312 -0
- latextify-0.1.0rc1/latextify/figures/__init__.py +29 -0
- latextify-0.1.0rc1/latextify/figures/convert.py +476 -0
- latextify-0.1.0rc1/latextify/figures/crop.py +254 -0
- latextify-0.1.0rc1/latextify/figures/extract.py +288 -0
- latextify-0.1.0rc1/latextify/figures/override.py +186 -0
- latextify-0.1.0rc1/latextify/gui/__init__.py +18 -0
- latextify-0.1.0rc1/latextify/gui/demo.py +178 -0
- latextify-0.1.0rc1/latextify/gui/downloads.py +140 -0
- latextify-0.1.0rc1/latextify/gui/exporting.py +55 -0
- latextify-0.1.0rc1/latextify/gui/folder_picker.py +47 -0
- latextify-0.1.0rc1/latextify/gui/guard.py +131 -0
- latextify-0.1.0rc1/latextify/gui/schemas.py +192 -0
- latextify-0.1.0rc1/latextify/gui/server.py +921 -0
- latextify-0.1.0rc1/latextify/gui/static/alt-export.js +73 -0
- latextify-0.1.0rc1/latextify/gui/static/app.js +458 -0
- latextify-0.1.0rc1/latextify/gui/static/clean.js +64 -0
- latextify-0.1.0rc1/latextify/gui/static/export.js +90 -0
- latextify-0.1.0rc1/latextify/gui/static/index.html +204 -0
- latextify-0.1.0rc1/latextify/gui/static/results.js +88 -0
- latextify-0.1.0rc1/latextify/gui/static/review.js +193 -0
- latextify-0.1.0rc1/latextify/gui/static/style.css +182 -0
- latextify-0.1.0rc1/latextify/gui/upload_utils.py +80 -0
- latextify-0.1.0rc1/latextify/gui/uploads_routes.py +161 -0
- latextify-0.1.0rc1/latextify/ingest/__init__.py +16 -0
- latextify-0.1.0rc1/latextify/ingest/_xml.py +39 -0
- latextify-0.1.0rc1/latextify/ingest/archive_guard.py +198 -0
- latextify-0.1.0rc1/latextify/ingest/citation_sentinels.py +162 -0
- latextify-0.1.0rc1/latextify/ingest/docx_clean.py +431 -0
- latextify-0.1.0rc1/latextify/ingest/filters.py +1061 -0
- latextify-0.1.0rc1/latextify/ingest/formats.py +105 -0
- latextify-0.1.0rc1/latextify/ingest/frontmatter.py +70 -0
- latextify-0.1.0rc1/latextify/ingest/metadata_guess.py +919 -0
- latextify-0.1.0rc1/latextify/ingest/metadata_guess_nondocx.py +93 -0
- latextify-0.1.0rc1/latextify/ingest/pandoc.py +242 -0
- latextify-0.1.0rc1/latextify/ingest/portable_anchors.py +68 -0
- latextify-0.1.0rc1/latextify/ingest/preflight.py +353 -0
- latextify-0.1.0rc1/latextify/kit/README-OFFLINE.md +119 -0
- latextify-0.1.0rc1/latextify/kit/__init__.py +10 -0
- latextify-0.1.0rc1/latextify/kit/build.py +468 -0
- latextify-0.1.0rc1/latextify/kit/install_template.py +209 -0
- latextify-0.1.0rc1/latextify/model/__init__.py +76 -0
- latextify-0.1.0rc1/latextify/model/_compat.py +53 -0
- latextify-0.1.0rc1/latextify/model/body.py +52 -0
- latextify-0.1.0rc1/latextify/model/compile.py +54 -0
- latextify-0.1.0rc1/latextify/model/emit.py +127 -0
- latextify-0.1.0rc1/latextify/model/equations.py +107 -0
- latextify-0.1.0rc1/latextify/model/figure.py +146 -0
- latextify-0.1.0rc1/latextify/model/meta.py +59 -0
- latextify-0.1.0rc1/latextify/model/preflight.py +72 -0
- latextify-0.1.0rc1/latextify/model/reconcile.py +74 -0
- latextify-0.1.0rc1/latextify/model/refs.py +77 -0
- latextify-0.1.0rc1/latextify/model/validate.py +123 -0
- latextify-0.1.0rc1/latextify/report/__init__.py +13 -0
- latextify-0.1.0rc1/latextify/report/render.py +344 -0
- latextify-0.1.0rc1/latextify/templates/__init__.py +17 -0
- latextify-0.1.0rc1/latextify/templates/authors.py +131 -0
- latextify-0.1.0rc1/latextify/templates/journals/.gitkeep +0 -0
- latextify-0.1.0rc1/latextify/templates/journals/achemso/manifest.yaml +91 -0
- latextify-0.1.0rc1/latextify/templates/journals/achemso/metadata.tex.j2 +36 -0
- latextify-0.1.0rc1/latextify/templates/journals/achemso/preamble.tex.j2 +26 -0
- latextify-0.1.0rc1/latextify/templates/journals/aip-advances/manifest.yaml +10 -0
- latextify-0.1.0rc1/latextify/templates/journals/aip-apl/manifest.yaml +12 -0
- latextify-0.1.0rc1/latextify/templates/journals/aip-jap/manifest.yaml +10 -0
- latextify-0.1.0rc1/latextify/templates/journals/aps-prapplied/manifest.yaml +4 -0
- latextify-0.1.0rc1/latextify/templates/journals/aps-prl/manifest.yaml +6 -0
- latextify-0.1.0rc1/latextify/templates/journals/aps-prx/manifest.yaml +4 -0
- latextify-0.1.0rc1/latextify/templates/journals/aps-rmp/manifest.yaml +4 -0
- latextify-0.1.0rc1/latextify/templates/journals/elsarticle/manifest.yaml +57 -0
- latextify-0.1.0rc1/latextify/templates/journals/elsarticle/metadata.tex.j2 +36 -0
- latextify-0.1.0rc1/latextify/templates/journals/elsarticle/preamble.tex.j2 +12 -0
- latextify-0.1.0rc1/latextify/templates/journals/elsarticle/vendor/elsarticle.cls +1403 -0
- latextify-0.1.0rc1/latextify/templates/journals/ieeetran/manifest.yaml +42 -0
- latextify-0.1.0rc1/latextify/templates/journals/ieeetran/metadata.tex.j2 +20 -0
- latextify-0.1.0rc1/latextify/templates/journals/ieeetran/preamble.tex.j2 +17 -0
- latextify-0.1.0rc1/latextify/templates/journals/iopart/VENDOR_LICENSE.txt +63 -0
- latextify-0.1.0rc1/latextify/templates/journals/iopart/manifest.yaml +73 -0
- latextify-0.1.0rc1/latextify/templates/journals/iopart/metadata.tex.j2 +32 -0
- latextify-0.1.0rc1/latextify/templates/journals/iopart/preamble.tex.j2 +20 -0
- latextify-0.1.0rc1/latextify/templates/journals/iopart/vendor/.gitattributes +6 -0
- latextify-0.1.0rc1/latextify/templates/journals/iopart/vendor/iopart.cls +1107 -0
- latextify-0.1.0rc1/latextify/templates/journals/iopart/vendor/iopart10.clo +1 -0
- latextify-0.1.0rc1/latextify/templates/journals/iopart/vendor/iopart12.clo +1 -0
- latextify-0.1.0rc1/latextify/templates/journals/revtex4-2/manifest.yaml +57 -0
- latextify-0.1.0rc1/latextify/templates/journals/revtex4-2/metadata.tex.j2 +22 -0
- latextify-0.1.0rc1/latextify/templates/journals/revtex4-2/preamble.tex.j2 +17 -0
- latextify-0.1.0rc1/latextify/templates/journals/sn-jnl/VENDOR_LICENSE.txt +30 -0
- latextify-0.1.0rc1/latextify/templates/journals/sn-jnl/manifest.yaml +99 -0
- latextify-0.1.0rc1/latextify/templates/journals/sn-jnl/metadata.tex.j2 +23 -0
- latextify-0.1.0rc1/latextify/templates/journals/sn-jnl/preamble.tex.j2 +22 -0
- latextify-0.1.0rc1/latextify/templates/journals/sn-jnl/vendor/.gitattributes +6 -0
- latextify-0.1.0rc1/latextify/templates/journals/sn-jnl/vendor/sn-jnl.cls +1 -0
- latextify-0.1.0rc1/latextify/templates/journals/sn-jnl/vendor/sn-mathphys-ay.bst +3208 -0
- latextify-0.1.0rc1/latextify/templates/journals/sn-jnl/vendor/sn-mathphys-num.bst +3211 -0
- latextify-0.1.0rc1/latextify/templates/journals/wiley/manifest.yaml +103 -0
- latextify-0.1.0rc1/latextify/templates/journals/wiley/metadata.tex.j2 +23 -0
- latextify-0.1.0rc1/latextify/templates/journals/wiley/preamble.tex.j2 +14 -0
- latextify-0.1.0rc1/latextify/templates/loader.py +539 -0
- latextify-0.1.0rc1/plans/FORMATS_AND_PRIVACY_PLAN.md +180 -0
- latextify-0.1.0rc1/plans/GUI_MULTIFILE_PLAN.md +94 -0
- latextify-0.1.0rc1/plans/GUI_OPTIONS_FORMATS_PLAN.md +195 -0
- latextify-0.1.0rc1/plans/MANUSCRIPT_FIDELITY_PLAN.md +227 -0
- latextify-0.1.0rc1/plans/OFFLINE_DISTRIBUTION_PLAN.md +182 -0
- latextify-0.1.0rc1/plans/archive/GUI_JOURNALS_EXPORT_PLAN.md +100 -0
- latextify-0.1.0rc1/plans/archive/LATEXTIFY_PLAN.md +438 -0
- latextify-0.1.0rc1/plans/archive/OFFLINE_PORTABILITY_PLAN.md +219 -0
- latextify-0.1.0rc1/plans/archive/SECURITY_RELIABILITY_AUDIT_PLAN.md +392 -0
- latextify-0.1.0rc1/pyproject.toml +130 -0
- latextify-0.1.0rc1/render.yaml +20 -0
- latextify-0.1.0rc1/startup.bat +59 -0
- latextify-0.1.0rc1/startup.sh +75 -0
- latextify-0.1.0rc1/tests/fixtures/README.md +56 -0
- latextify-0.1.0rc1/tests/fixtures/bracket_cited.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/clean.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/cropped_figure.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/endnote_cited.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/equations.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/figures.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/golden/achemso_metadata.tex +27 -0
- latextify-0.1.0rc1/tests/fixtures/golden/achemso_preamble.tex +20 -0
- latextify-0.1.0rc1/tests/fixtures/golden/elsarticle_metadata.tex +18 -0
- latextify-0.1.0rc1/tests/fixtures/golden/elsarticle_preamble_authoryear.tex +11 -0
- latextify-0.1.0rc1/tests/fixtures/golden/elsarticle_preamble_numeric.tex +11 -0
- latextify-0.1.0rc1/tests/fixtures/golden/ieeetran_metadata.tex +16 -0
- latextify-0.1.0rc1/tests/fixtures/golden/ieeetran_preamble.tex +9 -0
- latextify-0.1.0rc1/tests/fixtures/golden/iopart_metadata.tex +21 -0
- latextify-0.1.0rc1/tests/fixtures/golden/iopart_preamble.tex +15 -0
- latextify-0.1.0rc1/tests/fixtures/golden/revtex4-2_metadata.tex +13 -0
- latextify-0.1.0rc1/tests/fixtures/golden/revtex4-2_preamble.tex +9 -0
- latextify-0.1.0rc1/tests/fixtures/golden/sn-jnl_metadata.tex +15 -0
- latextify-0.1.0rc1/tests/fixtures/golden/sn-jnl_preamble.tex +13 -0
- latextify-0.1.0rc1/tests/fixtures/golden/sn-jnl_preamble_authoryear.tex +13 -0
- latextify-0.1.0rc1/tests/fixtures/golden/wiley_metadata.tex +15 -0
- latextify-0.1.0rc1/tests/fixtures/golden/wiley_preamble_authoryear.tex +12 -0
- latextify-0.1.0rc1/tests/fixtures/golden/wiley_preamble_numeric.tex +12 -0
- latextify-0.1.0rc1/tests/fixtures/hand_cited.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/make_bracket_cited.py +75 -0
- latextify-0.1.0rc1/tests/fixtures/make_clean.py +38 -0
- latextify-0.1.0rc1/tests/fixtures/make_cropped_figure.py +83 -0
- latextify-0.1.0rc1/tests/fixtures/make_endnote_cited.py +261 -0
- latextify-0.1.0rc1/tests/fixtures/make_equations.py +169 -0
- latextify-0.1.0rc1/tests/fixtures/make_figures.py +85 -0
- latextify-0.1.0rc1/tests/fixtures/make_hand_cited.py +93 -0
- latextify-0.1.0rc1/tests/fixtures/make_metadata_titlepage.py +74 -0
- latextify-0.1.0rc1/tests/fixtures/make_supplement.py +194 -0
- latextify-0.1.0rc1/tests/fixtures/make_tables.py +93 -0
- latextify-0.1.0rc1/tests/fixtures/make_unsupported.py +139 -0
- latextify-0.1.0rc1/tests/fixtures/make_wordnative_cited.py +195 -0
- latextify-0.1.0rc1/tests/fixtures/make_zotero_cited.py +272 -0
- latextify-0.1.0rc1/tests/fixtures/metadata_titlepage.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/paper.yaml +16 -0
- latextify-0.1.0rc1/tests/fixtures/supplement.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/tables.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/unsupported.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/wordnative_cited.docx +0 -0
- latextify-0.1.0rc1/tests/fixtures/zotero_cited.docx +0 -0
- latextify-0.1.0rc1/tests/test_archive_guard.py +209 -0
- latextify-0.1.0rc1/tests/test_audit_equations.py +475 -0
- latextify-0.1.0rc1/tests/test_citation_sentinels.py +161 -0
- latextify-0.1.0rc1/tests/test_citations_bib.py +281 -0
- latextify-0.1.0rc1/tests/test_citations_bibmatch.py +161 -0
- latextify-0.1.0rc1/tests/test_citations_bibtex_in.py +186 -0
- latextify-0.1.0rc1/tests/test_citations_bracket_refs.py +219 -0
- latextify-0.1.0rc1/tests/test_citations_compile_stub.py +158 -0
- latextify-0.1.0rc1/tests/test_citations_corrections.py +201 -0
- latextify-0.1.0rc1/tests/test_citations_crossref.py +427 -0
- latextify-0.1.0rc1/tests/test_citations_csl_json_in.py +109 -0
- latextify-0.1.0rc1/tests/test_citations_degradation.py +148 -0
- latextify-0.1.0rc1/tests/test_citations_endnote.py +143 -0
- latextify-0.1.0rc1/tests/test_citations_endnote_compile.py +116 -0
- latextify-0.1.0rc1/tests/test_citations_endnote_xml_in.py +136 -0
- latextify-0.1.0rc1/tests/test_citations_extract.py +176 -0
- latextify-0.1.0rc1/tests/test_citations_extract_endnote.py +99 -0
- latextify-0.1.0rc1/tests/test_citations_extract_wordnative.py +83 -0
- latextify-0.1.0rc1/tests/test_citations_fields.py +144 -0
- latextify-0.1.0rc1/tests/test_citations_merge.py +200 -0
- latextify-0.1.0rc1/tests/test_citations_nbib_in.py +105 -0
- latextify-0.1.0rc1/tests/test_citations_parsers.py +112 -0
- latextify-0.1.0rc1/tests/test_citations_plaintext.py +638 -0
- latextify-0.1.0rc1/tests/test_citations_reconstruct.py +255 -0
- latextify-0.1.0rc1/tests/test_citations_refs_import.py +70 -0
- latextify-0.1.0rc1/tests/test_citations_stress.py +372 -0
- latextify-0.1.0rc1/tests/test_citations_validate.py +293 -0
- latextify-0.1.0rc1/tests/test_citations_wordnative.py +171 -0
- latextify-0.1.0rc1/tests/test_cli.py +1370 -0
- latextify-0.1.0rc1/tests/test_cli_review.py +150 -0
- latextify-0.1.0rc1/tests/test_compat_strenum.py +53 -0
- latextify-0.1.0rc1/tests/test_compile_logs.py +190 -0
- latextify-0.1.0rc1/tests/test_compile_tectonic.py +232 -0
- latextify-0.1.0rc1/tests/test_docx_clean.py +373 -0
- latextify-0.1.0rc1/tests/test_emit.py +993 -0
- latextify-0.1.0rc1/tests/test_emit_submission.py +183 -0
- latextify-0.1.0rc1/tests/test_examples.py +107 -0
- latextify-0.1.0rc1/tests/test_export_formats.py +388 -0
- latextify-0.1.0rc1/tests/test_fidelity_captions_reflist.py +197 -0
- latextify-0.1.0rc1/tests/test_figures.py +313 -0
- latextify-0.1.0rc1/tests/test_figures_convert.py +528 -0
- latextify-0.1.0rc1/tests/test_figures_crop.py +250 -0
- latextify-0.1.0rc1/tests/test_figures_tiff.py +131 -0
- latextify-0.1.0rc1/tests/test_figures_wide.py +110 -0
- latextify-0.1.0rc1/tests/test_filters.py +505 -0
- latextify-0.1.0rc1/tests/test_filters_headings.py +124 -0
- latextify-0.1.0rc1/tests/test_frontmatter.py +297 -0
- latextify-0.1.0rc1/tests/test_gui.py +1717 -0
- latextify-0.1.0rc1/tests/test_gui_demo.py +234 -0
- latextify-0.1.0rc1/tests/test_journal_pdf_layout.py +119 -0
- latextify-0.1.0rc1/tests/test_kit_build.py +242 -0
- latextify-0.1.0rc1/tests/test_manuscript_formats.py +278 -0
- latextify-0.1.0rc1/tests/test_metadata_guess.py +835 -0
- latextify-0.1.0rc1/tests/test_package.py +25 -0
- latextify-0.1.0rc1/tests/test_pandoc.py +179 -0
- latextify-0.1.0rc1/tests/test_pdf_combine.py +67 -0
- latextify-0.1.0rc1/tests/test_preflight.py +187 -0
- latextify-0.1.0rc1/tests/test_repo_integrity.py +107 -0
- latextify-0.1.0rc1/tests/test_report.py +557 -0
- latextify-0.1.0rc1/tests/test_supplement.py +450 -0
- latextify-0.1.0rc1/tests/test_tables.py +342 -0
- latextify-0.1.0rc1/tests/test_tectonic_integrity.py +210 -0
- latextify-0.1.0rc1/tests/test_templates.py +819 -0
- latextify-0.1.0rc1/tests/test_templates_item22.py +537 -0
- latextify-0.1.0rc1/tests/test_templates_sn_jnl.py +308 -0
- latextify-0.1.0rc1/tests/test_xml_hardening.py +117 -0
- latextify-0.1.0rc1/uv.lock +1422 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Build context hygiene for deploy/render/Dockerfile (context = repo root).
|
|
2
|
+
# Only the installable package + metadata should reach the image.
|
|
3
|
+
.git
|
|
4
|
+
.venv
|
|
5
|
+
.claude
|
|
6
|
+
__pycache__
|
|
7
|
+
**/__pycache__
|
|
8
|
+
*.pyc
|
|
9
|
+
build
|
|
10
|
+
dist
|
|
11
|
+
output
|
|
12
|
+
png
|
|
13
|
+
plans
|
|
14
|
+
tests
|
|
15
|
+
examples
|
|
16
|
+
deploy/hf-space/README.md
|
|
17
|
+
deploy/hf-space/DEPLOY.md
|
|
18
|
+
deploy/render/DEPLOY.md
|
|
19
|
+
*.log
|
|
20
|
+
uv.lock
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
lint:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
20
|
+
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
- name: Install
|
|
24
|
+
run: uv sync --locked
|
|
25
|
+
- name: Ruff
|
|
26
|
+
run: uv run ruff check .
|
|
27
|
+
|
|
28
|
+
test:
|
|
29
|
+
name: test (${{ matrix.os }}, py${{ matrix.python }})
|
|
30
|
+
strategy:
|
|
31
|
+
fail-fast: false
|
|
32
|
+
matrix:
|
|
33
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
34
|
+
python: ["3.10", "3.11", "3.13"]
|
|
35
|
+
runs-on: ${{ matrix.os }}
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
38
|
+
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
|
39
|
+
with:
|
|
40
|
+
python-version: ${{ matrix.python }}
|
|
41
|
+
- name: Install
|
|
42
|
+
run: uv sync --locked
|
|
43
|
+
- name: Unit tests (no TeX engine, no network)
|
|
44
|
+
run: uv run pytest -q -m "not tectonic and not network"
|
|
45
|
+
|
|
46
|
+
integration:
|
|
47
|
+
# Full suite including real Tectonic compiles. One platform is enough:
|
|
48
|
+
# the compile path is exercised on Windows by local development.
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
52
|
+
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
|
53
|
+
with:
|
|
54
|
+
python-version: "3.12"
|
|
55
|
+
- name: Cache Tectonic binary and package bundle
|
|
56
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
57
|
+
with:
|
|
58
|
+
path: |
|
|
59
|
+
~/.cache/latextify
|
|
60
|
+
~/.cache/Tectonic
|
|
61
|
+
key: tectonic-${{ runner.os }}-v1
|
|
62
|
+
- name: Install
|
|
63
|
+
run: uv sync --locked
|
|
64
|
+
- name: Pre-fetch Tectonic binary
|
|
65
|
+
# Test skip-guards only DETECT the binary at collection time (no
|
|
66
|
+
# download), so the integration job fetches it explicitly first. The
|
|
67
|
+
# download is a pinned, checksum-verified release-asset URL served by a
|
|
68
|
+
# CDN (not the rate-limited releases API), so no token is needed.
|
|
69
|
+
run: uv run python -c "from latextify.compile.tectonic import ensure_tectonic; print(ensure_tectonic())"
|
|
70
|
+
- name: Full test suite (real docx -> PDF compiles)
|
|
71
|
+
run: uv run pytest -q -m "not network"
|
|
72
|
+
|
|
73
|
+
offline-kit:
|
|
74
|
+
# Proves the whole offline story end to end: build a kit (network ON),
|
|
75
|
+
# then install it and compile a PDF with the network POISONED. This is the
|
|
76
|
+
# regression gate that keeps a stray runtime network call from silently
|
|
77
|
+
# breaking air-gapped use. Kept small (one Python, one journal) for speed;
|
|
78
|
+
# the release workflow builds the full multi-target kits.
|
|
79
|
+
runs-on: ubuntu-latest
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
82
|
+
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
|
83
|
+
with:
|
|
84
|
+
python-version: "3.13"
|
|
85
|
+
- name: Cache Tectonic binary and package bundle
|
|
86
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
87
|
+
with:
|
|
88
|
+
path: |
|
|
89
|
+
~/.cache/latextify
|
|
90
|
+
~/.cache/Tectonic
|
|
91
|
+
key: tectonic-${{ runner.os }}-v1
|
|
92
|
+
- name: Install
|
|
93
|
+
run: uv sync --locked
|
|
94
|
+
- name: Pre-fetch Tectonic (pinned, checksum-verified release asset)
|
|
95
|
+
run: uv run python -c "from latextify.compile.tectonic import ensure_tectonic; print(ensure_tectonic())"
|
|
96
|
+
- name: Build a current-platform kit (network ON) and a fixture manuscript
|
|
97
|
+
run: |
|
|
98
|
+
uv run latextify make-kit --target current --python-versions 3.13 \
|
|
99
|
+
--journals revtex4-2 -o build
|
|
100
|
+
uv run python - <<'PY'
|
|
101
|
+
from docx import Document
|
|
102
|
+
d = Document()
|
|
103
|
+
d.add_heading("Offline CI Demo", 0)
|
|
104
|
+
d.add_paragraph("Ada Offline")
|
|
105
|
+
d.add_heading("Abstract", 1)
|
|
106
|
+
d.add_paragraph("A fixture manuscript compiled with no network access.")
|
|
107
|
+
d.add_heading("Introduction", 1)
|
|
108
|
+
d.add_paragraph("Body text exercising headings, an abstract, and a PDF compile.")
|
|
109
|
+
d.save("demo.docx")
|
|
110
|
+
PY
|
|
111
|
+
echo "PYBIN=$(uv python find 3.13)" >> "$GITHUB_ENV"
|
|
112
|
+
- name: Install kit + convert to PDF with the network POISONED
|
|
113
|
+
env:
|
|
114
|
+
# GitHub de-dupes env keys case-insensitively, so set ONE case only.
|
|
115
|
+
# Uppercase is honoured by Rust/reqwest (Tectonic) and Python alike.
|
|
116
|
+
HTTPS_PROXY: http://127.0.0.1:9
|
|
117
|
+
HTTP_PROXY: http://127.0.0.1:9
|
|
118
|
+
ALL_PROXY: http://127.0.0.1:9
|
|
119
|
+
run: |
|
|
120
|
+
KIT=build/latextify-offline-linux-x64
|
|
121
|
+
"$PYBIN" "$KIT/install.py"
|
|
122
|
+
"$KIT/latextify" convert demo.docx -j revtex4-2 -o demo-out --pdf
|
|
123
|
+
test -f demo-out/revtex4-2/main.pdf || { echo "no PDF produced offline"; exit 1; }
|
|
124
|
+
echo "offline PDF compiled: $(du -h demo-out/revtex4-2/main.pdf)"
|
|
125
|
+
|
|
126
|
+
offline-kit-py310-windows:
|
|
127
|
+
name: offline kit installs on Python 3.10 (Windows)
|
|
128
|
+
# Every other kit-install gate above targets the newest supported
|
|
129
|
+
# interpreter (3.13) on Linux; none proves the offline kit against the
|
|
130
|
+
# OLDEST supported Python (3.10, our documented floor -- see
|
|
131
|
+
# requires-python in pyproject.toml) on the platform most kit users
|
|
132
|
+
# actually run: Windows. A future dependency bump could silently break
|
|
133
|
+
# the 3.10 floor without this catching it. Kept fast: emit-only
|
|
134
|
+
# (--no-warm-tex, no --pdf) -- the PDF/Tectonic offline path is already
|
|
135
|
+
# covered by the `offline-kit` job above.
|
|
136
|
+
runs-on: windows-latest
|
|
137
|
+
steps:
|
|
138
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
139
|
+
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
|
140
|
+
with:
|
|
141
|
+
python-version: "3.13"
|
|
142
|
+
- name: Install
|
|
143
|
+
run: uv sync --locked
|
|
144
|
+
- name: Set up the TARGET Python 3.10 (what install.py will run under)
|
|
145
|
+
id: py310
|
|
146
|
+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
|
147
|
+
with:
|
|
148
|
+
python-version: "3.10"
|
|
149
|
+
- name: Build an emit-only kit covering Python 3.10 (network ON)
|
|
150
|
+
run: uv run latextify make-kit --target current --python-versions 3.10 --no-warm-tex --output build
|
|
151
|
+
- name: Install the kit under Python 3.10, network POISONED
|
|
152
|
+
env:
|
|
153
|
+
# Same reasoning as the Linux offline-kit job: uppercase only, one
|
|
154
|
+
# case, so GitHub's case-insensitive env-key de-dupe can't collide.
|
|
155
|
+
HTTPS_PROXY: http://127.0.0.1:9
|
|
156
|
+
HTTP_PROXY: http://127.0.0.1:9
|
|
157
|
+
ALL_PROXY: http://127.0.0.1:9
|
|
158
|
+
run: |
|
|
159
|
+
& "${{ steps.py310.outputs.python-path }}" "build/latextify-offline-windows-x64/install.py"
|
|
160
|
+
if ($LASTEXITCODE -ne 0) { throw "install.py failed under Python 3.10 (exit $LASTEXITCODE)" }
|
|
161
|
+
- name: Convert a fixture manuscript offline (emit-only, no --pdf)
|
|
162
|
+
env:
|
|
163
|
+
HTTPS_PROXY: http://127.0.0.1:9
|
|
164
|
+
HTTP_PROXY: http://127.0.0.1:9
|
|
165
|
+
ALL_PROXY: http://127.0.0.1:9
|
|
166
|
+
run: |
|
|
167
|
+
& "build/latextify-offline-windows-x64/LaTeXtify.bat" convert tests/fixtures/clean.docx -j revtex4-2 -o demo-out
|
|
168
|
+
if ($LASTEXITCODE -ne 0) { throw "convert failed under the Python 3.10 kit (exit $LASTEXITCODE)" }
|
|
169
|
+
if (-not (Test-Path "demo-out/revtex4-2/main.tex")) {
|
|
170
|
+
throw "Python 3.10 kit did not produce demo-out/revtex4-2/main.tex"
|
|
171
|
+
}
|
|
172
|
+
Write-Host "offline (Python 3.10, Windows): produced demo-out/revtex4-2/main.tex"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "31 7 * * 1"
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
analyze:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
security-events: write
|
|
16
|
+
actions: read
|
|
17
|
+
contents: read
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
20
|
+
- uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4
|
|
21
|
+
with:
|
|
22
|
+
languages: python
|
|
23
|
+
- uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Dependency audit
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
schedule:
|
|
8
|
+
# Weekly (Mon 06:00 UTC): catch advisories newly disclosed against pinned,
|
|
9
|
+
# otherwise-unchanged dependencies between code changes.
|
|
10
|
+
- cron: "0 6 * * 1"
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
pip-audit:
|
|
21
|
+
name: pip-audit (locked runtime deps)
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
25
|
+
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
- name: Export locked runtime dependencies
|
|
29
|
+
# Audit exactly what ships to users: runtime deps only (no dev tools),
|
|
30
|
+
# resolved from uv.lock so the audit matches the pinned tree. --no-deps
|
|
31
|
+
# in the next step then audits precisely this closure without
|
|
32
|
+
# re-resolving. Hashes are omitted here because uv already verifies them
|
|
33
|
+
# on install; pip-audit's job in CI is CVE scanning, not integrity.
|
|
34
|
+
run: >-
|
|
35
|
+
uv export --frozen --no-dev --no-emit-project --no-hashes
|
|
36
|
+
--format requirements-txt -o requirements-audit.txt
|
|
37
|
+
- name: Audit for known vulnerabilities
|
|
38
|
+
# Exits non-zero if any dependency has a known advisory (PyPI + OSV).
|
|
39
|
+
#
|
|
40
|
+
# Failure policy: a PR that introduces or inherits a vulnerable
|
|
41
|
+
# dependency must upgrade it. An advisory may be waived only with a
|
|
42
|
+
# documented exception -- add `--ignore-vuln <ID>` below with a comment
|
|
43
|
+
# naming the package, advisory ID, why LaTeXtify is not exposed, and a
|
|
44
|
+
# review/expiry date.
|
|
45
|
+
run: uvx pip-audit --requirement requirements-audit.txt --no-deps
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Publishes the sdist + wheel to PyPI. Triggers ONLY on a published GitHub
|
|
4
|
+
# Release -- never on a plain push, a pull request, or even a tag push (tag
|
|
5
|
+
# pushes drive release.yml's offline-kit build instead). This is the
|
|
6
|
+
# machinery only: it cannot fire a real publish until an OWNER completes the
|
|
7
|
+
# two one-time setup steps below.
|
|
8
|
+
#
|
|
9
|
+
# ---------------------------------------------------------------------------
|
|
10
|
+
# OWNER SETUP REQUIRED before the first real publish (both are one-time,
|
|
11
|
+
# human actions on pypi.org / GitHub -- this workflow cannot do either):
|
|
12
|
+
#
|
|
13
|
+
# 1. Register a PENDING trusted publisher at
|
|
14
|
+
# https://pypi.org/manage/account/publishing/ for a new project named
|
|
15
|
+
# "latextify":
|
|
16
|
+
# Owner: pquarterman17
|
|
17
|
+
# Repository name: LaTeXtify
|
|
18
|
+
# Workflow name: publish.yml
|
|
19
|
+
# Environment name: pypi
|
|
20
|
+
# (PyPI creates the "latextify" project automatically on the first
|
|
21
|
+
# successful publish from this trusted publisher -- no manual project
|
|
22
|
+
# creation needed.)
|
|
23
|
+
#
|
|
24
|
+
# 2. Publish a GitHub Release (e.g. tag v0.1.0). The `release: published`
|
|
25
|
+
# event below is what triggers the `publish` job -- nothing publishes
|
|
26
|
+
# before that happens.
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
on:
|
|
30
|
+
release:
|
|
31
|
+
types: [published]
|
|
32
|
+
|
|
33
|
+
concurrency:
|
|
34
|
+
group: publish-${{ github.ref }}
|
|
35
|
+
cancel-in-progress: false
|
|
36
|
+
|
|
37
|
+
permissions:
|
|
38
|
+
contents: read
|
|
39
|
+
|
|
40
|
+
jobs:
|
|
41
|
+
build:
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
45
|
+
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.12"
|
|
48
|
+
- name: Build sdist + wheel
|
|
49
|
+
run: uv build
|
|
50
|
+
- name: Validate distribution metadata
|
|
51
|
+
run: uvx twine check dist/*
|
|
52
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
53
|
+
with:
|
|
54
|
+
name: dist
|
|
55
|
+
path: dist/
|
|
56
|
+
if-no-files-found: error
|
|
57
|
+
|
|
58
|
+
publish:
|
|
59
|
+
name: Publish to PyPI (trusted publishing)
|
|
60
|
+
needs: build
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
environment:
|
|
63
|
+
name: pypi
|
|
64
|
+
url: https://pypi.org/project/latextify/
|
|
65
|
+
permissions:
|
|
66
|
+
id-token: write # OIDC trusted publishing -- no API token stored in secrets
|
|
67
|
+
steps:
|
|
68
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
69
|
+
with:
|
|
70
|
+
name: dist
|
|
71
|
+
path: dist/
|
|
72
|
+
- uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
name: Release kits
|
|
2
|
+
|
|
3
|
+
# On a version tag, build the three offline kits and attach them (plus a
|
|
4
|
+
# source zip and checksums) to a GitHub release, so an air-gapped machine can
|
|
5
|
+
# "download from the releases page" with no online build host at all.
|
|
6
|
+
# Complements the CI `offline-kit` job, which proves one kit installs and
|
|
7
|
+
# compiles a PDF offline on every push.
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
tags: ["v*"]
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write # create the release and upload assets
|
|
15
|
+
|
|
16
|
+
concurrency:
|
|
17
|
+
group: release-${{ github.ref }}
|
|
18
|
+
cancel-in-progress: false
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
build-kits:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
timeout-minutes: 60
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
26
|
+
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
|
27
|
+
with:
|
|
28
|
+
python-version: "3.13"
|
|
29
|
+
- name: Cache Tectonic binary and package bundle
|
|
30
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
|
31
|
+
with:
|
|
32
|
+
path: |
|
|
33
|
+
~/.cache/latextify
|
|
34
|
+
~/.cache/Tectonic
|
|
35
|
+
key: tectonic-${{ runner.os }}-v1
|
|
36
|
+
- name: Install
|
|
37
|
+
run: uv sync --locked
|
|
38
|
+
- name: Pre-fetch Tectonic (authenticated; anonymous API rate-limits on runners)
|
|
39
|
+
env:
|
|
40
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
41
|
+
run: uv run python -c "from latextify.compile.tectonic import ensure_tectonic; print(ensure_tectonic())"
|
|
42
|
+
|
|
43
|
+
- name: Build native Linux kit (warms the shared, portable TeX cache)
|
|
44
|
+
env:
|
|
45
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
46
|
+
run: uv run latextify make-kit --target linux-x64 -o build
|
|
47
|
+
|
|
48
|
+
# NOTE -- native-build preference: this workflow cross-builds the
|
|
49
|
+
# win-x64 (and macos-arm64) kits from a single Linux runner, on a
|
|
50
|
+
# GitHub-hosted-runner cost/simplicity tradeoff (one TeX warm-up pass
|
|
51
|
+
# instead of three, no matrix). A NATIVE Windows kit build --
|
|
52
|
+
# `latextify make-kit --target win-x64` run ON Windows, warming its own
|
|
53
|
+
# TeX cache directly -- is the PREFERRED way to produce the Windows
|
|
54
|
+
# kit: it exercises the real target-platform Tectonic binary end to
|
|
55
|
+
# end, rather than shipping `--no-warm-tex` and trusting that a
|
|
56
|
+
# Linux-warmed, source-only cache regenerates its engine format
|
|
57
|
+
# correctly the first time on Windows. (The CI `offline-kit-py310-windows`
|
|
58
|
+
# job partially covers this by installing+running a Windows kit, but it
|
|
59
|
+
# is also `--no-warm-tex`/emit-only for speed -- it does not warm-test
|
|
60
|
+
# this path either.) If a native Windows release runner ever becomes
|
|
61
|
+
# available, prefer switching the win-x64 build to it over this
|
|
62
|
+
# cross-build path.
|
|
63
|
+
- name: Build cross Windows/macOS kits, sharing the warmed cache
|
|
64
|
+
env:
|
|
65
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
66
|
+
run: |
|
|
67
|
+
# The warmed cache ships TeX *sources* only (host-independent); the
|
|
68
|
+
# target regenerates its engine format offline. So warm ONCE on Linux
|
|
69
|
+
# and reuse it for the cross targets rather than re-downloading the
|
|
70
|
+
# whole TeX bundle two more times.
|
|
71
|
+
for tgt in win-x64 macos-arm64; do
|
|
72
|
+
uv run latextify make-kit --target "$tgt" --no-warm-tex -o build
|
|
73
|
+
done
|
|
74
|
+
uv run python - <<'PY'
|
|
75
|
+
import json
|
|
76
|
+
import shutil
|
|
77
|
+
from pathlib import Path
|
|
78
|
+
|
|
79
|
+
build = Path("build")
|
|
80
|
+
src_kit = build / "latextify-offline-linux-x64"
|
|
81
|
+
src_cache = src_kit / "tex-bundle-cache"
|
|
82
|
+
warmed = json.loads((src_kit / "bundle-info.json").read_text())["warmed_journals"]
|
|
83
|
+
|
|
84
|
+
for name in ("latextify-offline-windows-x64", "latextify-offline-macos-arm64"):
|
|
85
|
+
kit = build / name
|
|
86
|
+
shutil.copytree(src_cache, kit / "tex-bundle-cache", dirs_exist_ok=True)
|
|
87
|
+
info_path = kit / "bundle-info.json"
|
|
88
|
+
info = json.loads(info_path.read_text())
|
|
89
|
+
info["warm_tex"] = True
|
|
90
|
+
info["warmed_journals"] = warmed
|
|
91
|
+
info_path.write_text(json.dumps(info, indent=2) + "\n")
|
|
92
|
+
print(f"shared warmed cache into {name} ({len(warmed)} journals)")
|
|
93
|
+
PY
|
|
94
|
+
|
|
95
|
+
- name: Package kits, source zip, and checksums
|
|
96
|
+
run: |
|
|
97
|
+
git archive --format=zip --prefix=latextify-src/ -o build/latextify-source.zip HEAD
|
|
98
|
+
cd build
|
|
99
|
+
for d in latextify-offline-*/; do
|
|
100
|
+
name="${d%/}"
|
|
101
|
+
zip -qr "$name.zip" "$name"
|
|
102
|
+
done
|
|
103
|
+
sha256sum *.zip > SHA256SUMS.txt
|
|
104
|
+
echo "--- release assets ---"
|
|
105
|
+
ls -lh *.zip SHA256SUMS.txt
|
|
106
|
+
cat SHA256SUMS.txt
|
|
107
|
+
|
|
108
|
+
- name: Create release and upload assets
|
|
109
|
+
env:
|
|
110
|
+
GH_TOKEN: ${{ github.token }}
|
|
111
|
+
run: |
|
|
112
|
+
cd build
|
|
113
|
+
gh release create "${GITHUB_REF_NAME}" \
|
|
114
|
+
--title "LaTeXtify ${GITHUB_REF_NAME}" \
|
|
115
|
+
--generate-notes \
|
|
116
|
+
latextify-offline-windows-x64.zip \
|
|
117
|
+
latextify-offline-linux-x64.zip \
|
|
118
|
+
latextify-offline-macos-arm64.zip \
|
|
119
|
+
latextify-source.zip \
|
|
120
|
+
SHA256SUMS.txt
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.venv/
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.pytest_cache/
|
|
7
|
+
.ruff_cache/
|
|
8
|
+
.mypy_cache/
|
|
9
|
+
|
|
10
|
+
# Packaging output (uv build / python -m build)
|
|
11
|
+
dist/
|
|
12
|
+
|
|
13
|
+
# Secrets / local env (none tracked; ignore proactively)
|
|
14
|
+
.env
|
|
15
|
+
.env.*
|
|
16
|
+
|
|
17
|
+
# Editors / IDEs (may embed local absolute paths)
|
|
18
|
+
.vscode/
|
|
19
|
+
.idea/
|
|
20
|
+
|
|
21
|
+
# LaTeX build artifacts
|
|
22
|
+
*.aux
|
|
23
|
+
*.log
|
|
24
|
+
*.bbl
|
|
25
|
+
*.blg
|
|
26
|
+
*.out
|
|
27
|
+
*.fls
|
|
28
|
+
*.fdb_latexmk
|
|
29
|
+
*.synctex.gz
|
|
30
|
+
|
|
31
|
+
# Tool output trees (per-paper conversion output lives next to the paper, not here)
|
|
32
|
+
output/
|
|
33
|
+
|
|
34
|
+
# Launcher error log (startup.bat / startup.sh write this next to themselves)
|
|
35
|
+
latextify-startup.log
|
|
36
|
+
|
|
37
|
+
# OS
|
|
38
|
+
.DS_Store
|
|
39
|
+
Thumbs.db
|
|
40
|
+
|
|
41
|
+
# Claude Code files (never tracked in this public repo: local agent config,
|
|
42
|
+
# session worktrees, and any project-instruction files stay local-only)
|
|
43
|
+
.claude/
|
|
44
|
+
CLAUDE.md
|
|
45
|
+
CLAUDE.local.md
|
|
46
|
+
|
|
47
|
+
# Local-only working notes (hosting/ops docs, parked roadmaps -- not for the
|
|
48
|
+
# public repo; see the owner's notes/ directory)
|
|
49
|
+
notes/
|
|
50
|
+
|
|
51
|
+
# Offline kit build output (latextify make-kit)
|
|
52
|
+
/build/
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest! This is a young project; issues and PRs are welcome.
|
|
4
|
+
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
git clone https://github.com/pquarterman17/LaTeXtify
|
|
9
|
+
cd LaTeXtify
|
|
10
|
+
uv sync # creates .venv, installs everything incl. dev deps
|
|
11
|
+
uv run pytest # full suite (downloads the Tectonic binary on first run)
|
|
12
|
+
uv run ruff check .
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Fast subset (no TeX engine, no network):
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
uv run pytest -m "not tectonic and not network"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The `tectonic`-marked tests skip unless the Tectonic binary is already on
|
|
22
|
+
PATH or in the cache — the skip guards deliberately never download at
|
|
23
|
+
collection time. Fetch it once and they activate:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
uv run python -c "from latextify.compile.tectonic import ensure_tectonic; print(ensure_tectonic())"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Ground rules
|
|
30
|
+
|
|
31
|
+
- **Tests first-class:** every bug fix carries a minimal reproducing test;
|
|
32
|
+
every feature carries tests. The suite must be green (`pytest` + `ruff
|
|
33
|
+
check .`) before a PR.
|
|
34
|
+
- **Journals are data:** adding a journal means adding a folder under
|
|
35
|
+
`latextify/templates/journals/` (manifest.yaml + two Jinja templates +
|
|
36
|
+
golden-file tests) — never editing converter code. Copy `revtex4-2/` as
|
|
37
|
+
the worked example, and check vendored files' licenses before committing
|
|
38
|
+
them (see `sn-jnl/` and `iopart/` for the pattern; Wiley shows the
|
|
39
|
+
documented-skip pattern for non-redistributable classes).
|
|
40
|
+
- **IR discipline:** data crossing stage boundaries uses the frozen
|
|
41
|
+
dataclasses in `latextify/model/` — no ad-hoc dicts.
|
|
42
|
+
- **Commit style:** `type(scope): imperative description` (feat, fix,
|
|
43
|
+
refactor, docs, test, chore).
|
|
44
|
+
- `.docx` test fixtures are generated, never hand-edited: each has a
|
|
45
|
+
committed `tests/fixtures/make_<name>.py` script.
|
|
46
|
+
|
|
47
|
+
## Architecture orientation
|
|
48
|
+
|
|
49
|
+
Read `plans/archive/LATEXTIFY_PLAN.md`'s Context section — it documents the
|
|
50
|
+
pipeline, the write-once/`generated/` output contract, and the design
|
|
51
|
+
decisions with dates.
|