Write scientific articles in Markdown and convert them to journal-ready LaTeX/PDF (Copernicus, Science, AMS, ...)
Project description
texmark
Write scientific articles in markdown — and submit them to any journal.
- Instant preview. Markdown renders live in most editors (VS Code, Cursor, JetBrains, vim) and on GitHub itself, so you see your draft as you type. No more wait-on-pdflatex cycles every time you change a sentence.
- Git + GitHub as a paper backend. Branches, pull requests, issues, blame, and diffs work the way they were designed to. Collaborators review changes with the same tooling they already use for code.
- One source, any journal. texmark compiles your markdown to any of the supported LaTeX templates. Start writing first, decide on a target journal later, and switch mid-way (or after rejection) by flipping a single yaml field — no rewriting needed.
- No lock-in. The intermediate
.texis right there next to the PDF. Unplug texmark whenever you want and continue the manuscript in plain LaTeX — useful for the final polish that journals usually demand.
Installation
pip install texmark
External dependencies
texmark itself is pure Python, but it shells out to a few external tools to produce the final PDF. Install them via your system package manager.
- pandoc — the markdown → tex engine (the
pypandocPyPI dependency is a wrapper, the binary is not installable via pip). - A LaTeX distribution providing
pdflatexandbibtexplus the standard package set (hyperref,natbib,amsmath,graphicx,geometry,microtype,booktabs,caption,mathptmx,newtxtext,newtxmath,apacite,draftwatermark,mdframed,tikz,xcolor,appendix,lineno,epstopdf, …). - rsync — used to assemble the build directory (templates, images, bibliography).
On Debian / Ubuntu:
sudo apt install pandoc rsync \
texlive-latex-extra texlive-bibtex-extra \
texlive-publishers texlive-fonts-extra
…or just texlive-full for the easy answer.
On macOS (Homebrew):
brew install pandoc rsync
brew install --cask mactex # or basictex + tlmgr install <packages>
A handful of LaTeX packages that aren't in TeX Live's smaller installs
(notably trackchanges, algorithm / algorithmicx, jabbrv) are
bundled with texmark under texmark/templates/<journal>/ and copied
into the build directory automatically, so you don't need to install them
separately.
Example
See example.md for a sample markdown file with yaml metadata in the header.
The command to convert the markdow to tex is:
texmark example.md
And to convert to PDF
texmark example.md --pdf
For another journal, it is enough to change the journal -> template' field in the yaml metadata. For testing it is also possible to pass -jfor--journal-template`:
texmark example.md --pdf -j science -o build/example-science.pdf --tex build/example-science.tex
See the example tex and pdf results in build
Journal templates
Pick the template that matches your target journal and add it to the yaml header of your markdown:
journal:
template: ametsoc # template name, see table below
options: twocol # optional, per-template — see the docs page
| template | covers | example | docs |
|---|---|---|---|
copernicus (aliases cp, esd, ...) |
Copernicus / EGU: ACP, BG, CP, ESD, HESS, NHESS, TC, ... | docs | |
science |
AAAS Science, Science Advances | docs | |
ametsoc (aliases jclim, jas, mwr, bams, ...) |
AMS: J. Climate, JAS, MWR, BAMS, ... | docs | |
arxiv (alias preprint) |
arXiv preprint, generic article-class | docs | |
elsarticle (alias elsevier) |
Elsevier: QSR, EPSL, GPC, Earth-Science Reviews, Cell, Lancet, ... | docs | |
agujournal (aliases agu, jgr, grl, james, wrr, ...) |
AGU: JGR family, GRL, Earth's Future, JAMES, ... | docs | |
springernature (aliases nature, naturecomms, natclimchange, natgeoscience, scirep) |
Springer Nature: Nature, Nature Communications, Nature Climate Change, Nature Geoscience, Scientific Reports, ... | docs | |
pnas |
PNAS | docs |
Each template ships a default journal.options value chosen to produce a
publication-style PDF (typeset 2-column journal look, no draft watermarks).
For peer-review submission you usually want to switch to the publisher's
submission options (e.g. preprint,12pt for Elsevier, draft for AGU, the
empty default for AMS 1.5-spacing). The per-journal docs page lists the
alternatives.
Partial support only. Before submitting, you will likely need to hand-edit
the final LaTeX — appendix structure, special sections (Methods Online,
Extended Data, Significance, …) and journal-specific cross-reference macros
are not all wired up automatically. Use the example PDF to confirm the
layout looks reasonable, then run texmark --tex out.tex and finish the
manuscript in LaTeX directly.
Common yaml fields (all templates)
title: "Paper title"
authors:
- firstname: Mahé
lastname: Perrette
affiliation: 1 # integer index into `affiliations` (most templates)
email: mahe.perrette@gmail.com
- firstname: Co
lastname: Author
affiliation: 2
affiliations:
- "Alfred Wegener Institute, ..."
- "Another Institution"
date: "2026-05-26"
bibliography: references.bib
journal:
template: <name> # required: picks the journal template + filters
options: <str or list> # optional: class options (per-template default)
collect_figures_and_tables: true # optional: see section below
figure-width: 80% # optional: pandoc figure default
figure-span: full # optional: wraps in figure* (full text width)
Section-style metadata can also be given as markdown # ... headings. Any
of # Abstract, # Acknowledgments, # Data Availability, # Appendix,
# Supplementary Material, # Significance, # Capsule, # Key Points,
# Plain Language Summary, # Author Contributions, # Competing Interests,
# Materials and Methods, # Funding, # Highlights, # Keywords will be
extracted out of the body and injected into the right LaTeX command for the
target journal. The exact list each template recognises is in
texmark/filters/main.py.
Collect figures and tables at the end of the document
Just add
collect_figures_and_tables: true
to your markdown yaml metadata.
Advanced: latex template
The templates are written in jinja2.
Just copy from e.g. texmark/templates/science/template.tex to your own, e.g. custom_template.tex And run again with:
texmark example.md --pdf -j science -o build/example-science.pdf --tex build/example-science.tex --template custom_template.tex
The -j journal template option (here science) is still used to set custom filters (e.g. only \cite for Science, no \citet ; extract specific sections as metadata to be injected as {{section}} instead of {{body}} etc). The machinery is defined in texmark/filters.py and can in principle be extended or copied.
Two approaches are possible:
- just add more filters via the
--filterscommand or in the yaml metadata. - extend the existing filters in a module, e.g. custom_filter.py, that extends the
filtersdict from thetexmark.filtersmodule (see the source code to check the details). And then pass it via--filters-module custom_filterparameter (orcustom_filterin the metadata) to prompt the texmark filter to load that module and make it available via-j your-custom-name. Note that will require you to explicitly pass--templateas well. Unless you overwrite an existing filter.
Ackowledgements
This project benefited greatly from AI support to extend the initial list of supported journals and further extend this package capability.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file texmark-0.6.2.tar.gz.
File metadata
- Download URL: texmark-0.6.2.tar.gz
- Upload date:
- Size: 377.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e78e0b611feaafebb0f87fe30ada8a415379fb72b180fbbb916c180448790019
|
|
| MD5 |
b466e4b831fb56d3025b63c0764732a9
|
|
| BLAKE2b-256 |
a17d21ccf0b4ed9881a265401c468a95b06a9446d382be155376bd1d3439405e
|
Provenance
The following attestation bundles were made for texmark-0.6.2.tar.gz:
Publisher:
pypi.yml on perrette/texmark
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
texmark-0.6.2.tar.gz -
Subject digest:
e78e0b611feaafebb0f87fe30ada8a415379fb72b180fbbb916c180448790019 - Sigstore transparency entry: 1632951299
- Sigstore integration time:
-
Permalink:
perrette/texmark@aba9a9efca860148c715f20918f1e6f9bdf9580e -
Branch / Tag:
refs/tags/v0.6.2 - Owner: https://github.com/perrette
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@aba9a9efca860148c715f20918f1e6f9bdf9580e -
Trigger Event:
push
-
Statement type:
File details
Details for the file texmark-0.6.2-py3-none-any.whl.
File metadata
- Download URL: texmark-0.6.2-py3-none-any.whl
- Upload date:
- Size: 384.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a1d87e1d0e8af6e2606f45308e0ca509c21106e3be8d90b7214c295e539a6c1
|
|
| MD5 |
174b21e6793f4f558b388a9987bcb7e8
|
|
| BLAKE2b-256 |
1d8f335cda46fd182745728e6c9e3d991d408e8cd339016cc2abd33e625232e1
|
Provenance
The following attestation bundles were made for texmark-0.6.2-py3-none-any.whl:
Publisher:
pypi.yml on perrette/texmark
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
texmark-0.6.2-py3-none-any.whl -
Subject digest:
7a1d87e1d0e8af6e2606f45308e0ca509c21106e3be8d90b7214c295e539a6c1 - Sigstore transparency entry: 1632951313
- Sigstore integration time:
-
Permalink:
perrette/texmark@aba9a9efca860148c715f20918f1e6f9bdf9580e -
Branch / Tag:
refs/tags/v0.6.2 - Owner: https://github.com/perrette
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi.yml@aba9a9efca860148c715f20918f1e6f9bdf9580e -
Trigger Event:
push
-
Statement type: