pdfmd-cli 3.11.1__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.
@@ -0,0 +1,371 @@
1
+ Metadata-Version: 2.4
2
+ Name: pdfmd-cli
3
+ Version: 3.11.1
4
+ Summary: One command from Markdown to a good-looking PDF: a Pandoc wrapper with smart defaults, project-file discovery and a multi-engine fallback chain
5
+ Author: Ali Perdekhan
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/aliperdehan/pdfmd
8
+ Project-URL: Changelog, https://github.com/aliperdehan/pdfmd/blob/main/CHANGELOG.md
9
+ Keywords: pandoc,markdown,pdf,latex,cli
10
+ Classifier: Environment :: Console
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
13
+ Classifier: Topic :: Text Processing :: Markup :: LaTeX
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: pyyaml
18
+ Requires-Dist: pypdf
19
+ Dynamic: license-file
20
+
21
+ # pdfmd
22
+
23
+ **One command from Markdown to a good-looking PDF.** `pdfmd` wraps
24
+ [Pandoc](https://pandoc.org) and fills in everything you would otherwise
25
+ have to remember: sensible fonts and margins, the right Markdown dialect,
26
+ your project's metadata/preamble/filter files, and a fallback chain across
27
+ every PDF engine you have installed.
28
+
29
+ ```console
30
+ $ pdfmd lecture
31
+ AUTO: READER TITLE MARGIN MONOFONT. Use --verbose to see in full
32
+ OK lecture.md
33
+ ```
34
+
35
+ <p align="center">
36
+ <img src="https://raw.githubusercontent.com/aliperdehan/pdfmd/main/docs/lecture.png" width="560" alt="lecture.md rendered to PDF">
37
+ </p>
38
+
39
+ That PDF came from [`examples/lecture.md`](https://github.com/aliperdehan/pdfmd/blob/main/examples/lecture.md), a plain
40
+ Markdown file with no front matter and no configuration. Plain `pandoc
41
+ lecture.md -o lecture.pdf` doesn't even get that far: its default engine,
42
+ `pdflatex`, stops at the `Δ` on line 5 with an error. With a Unicode engine
43
+ it would build, but with wide default margins, and with the `# Title`
44
+ line as an ordinary section heading instead of a title.
45
+
46
+ ## Why
47
+
48
+ Pandoc can do nearly anything, but its defaults assume you'll pass the right
49
+ flags every time. In practice that means one of two things: a long command
50
+ you copy from an old shell history, or a Makefile in every folder. `pdfmd`
51
+ turns that knowledge into defaults:
52
+
53
+ - **It decides per document, not globally.** A file with no YAML front
54
+ matter is treated as ordinary GitHub-flavoured Markdown. A file that has
55
+ front matter is assumed to be written for Pandoc and is left alone.
56
+ - **It finds your project files.** A `metadata.yaml`, `preamble.tex` or
57
+ `<name>.lua` beside the document (or in a `metadata/` folder next to it)
58
+ is picked up automatically, so every document in a folder shares one
59
+ house style without any flags.
60
+ - **It doesn't give up on the first engine.** If `lualatex` fails or isn't
61
+ installed, it tries the next engine, then the next, and tells you why each
62
+ one failed.
63
+ - **It shows what it did.** Every automatic decision prints an `AUTO` line,
64
+ `-v` shows the exact Pandoc command, and every default can be switched off.
65
+
66
+ ## Install
67
+
68
+ ```sh
69
+ pipx install pdfmd-cli
70
+ ```
71
+
72
+ That puts a `pdfmd` command on your PATH, with its Python dependencies, in
73
+ its own isolated environment. `uv tool install pdfmd-cli` does the same.
74
+ To update later, run `pipx upgrade pdfmd-cli`. (The package is named
75
+ `pdfmd-cli` because `pdfmd` on PyPI is an unrelated PDF-to-Markdown tool.
76
+ The command is still `pdfmd`. For the latest unreleased code, use `pipx
77
+ install git+https://github.com/aliperdehan/pdfmd`.)
78
+
79
+ `pdfmd` drives programs that pip can't install, so you also need:
80
+
81
+ - **[Pandoc](https://pandoc.org/installing.html)** (required)
82
+ - **at least one PDF engine**. [Typst](https://typst.app) is the quickest
83
+ start; a TeX distribution (MacTeX, TeX Live) gives the best results and
84
+ is what you need for LaTeX packages and math-heavy documents.
85
+
86
+ ```sh
87
+ brew install pipx pandoc typst # macOS, the quick start
88
+ brew install --cask mactex-no-gui # optional: full LaTeX (large)
89
+ ```
90
+
91
+ ```sh
92
+ sudo apt install pipx pandoc texlive-xetex # Debian/Ubuntu
93
+ ```
94
+
95
+ Optional extras: [Quarto](https://quarto.org) for `.qmd` files,
96
+ `pandoc-crossref` for `@fig:`/`@tbl:` references, and LibreOffice for
97
+ Office files.
98
+
99
+ <details>
100
+ <summary>Without pipx</summary>
101
+
102
+ `pdfmd.py` is a single file that needs Python 3.10+. It also runs
103
+ directly, and `pyyaml`/`pypdf` are optional (features that need them are
104
+ skipped with a warning):
105
+
106
+ ```sh
107
+ git clone https://github.com/aliperdehan/pdfmd.git ~/pdfmd
108
+ echo 'alias pdfmd="python3 ~/pdfmd/pdfmd.py"' >> ~/.zshrc # or ~/.bashrc
109
+ ```
110
+
111
+ macOS's built-in `/usr/bin/python3` is 3.9, which is too old; pdfmd says
112
+ so and exits.
113
+ </details>
114
+
115
+ Check what `pdfmd` can find on your system:
116
+
117
+ ```console
118
+ $ pdfmd --check-dependencies
119
+ OK pandoc (/opt/homebrew/bin/pandoc)
120
+ OK 1. lualatex (/Library/TeX/texbin/lualatex)
121
+ OK 2. xelatex (/Library/TeX/texbin/xelatex)
122
+ OK 3. pdflatex (/Library/TeX/texbin/pdflatex)
123
+ OK 4. latexmk (/Library/TeX/texbin/latexmk)
124
+ OK 5. tectonic (/opt/homebrew/bin/tectonic)
125
+ OK 6. typst (/opt/homebrew/bin/typst)
126
+ OK 7. weasyprint (/opt/homebrew/bin/weasyprint)
127
+ MISS 8. wkhtmltopdf
128
+ ...
129
+ OK 14. soffice (/Applications/LibreOffice.app/Contents/MacOS/soffice)
130
+ OK quarto (only needed for .qmd files) (/usr/local/bin/quarto)
131
+ ```
132
+
133
+ The numbers are the fallback order, and also shortcuts: `-e 6` means
134
+ `-e typst`.
135
+
136
+ ## Usage
137
+
138
+ Every command below can be run from inside [`examples/`](https://github.com/aliperdehan/pdfmd/tree/main/examples/).
139
+
140
+ ### One document
141
+
142
+ ```sh
143
+ pdfmd lecture # finds lecture.md, writes lecture.pdf beside it
144
+ pdfmd lecture.md --open # ...and opens it when done
145
+ pdfmd ~/notes/lecture.md -d # write the PDF into the current directory instead
146
+ pdfmd lecture -w # watch: rebuild on every save, until Ctrl+C
147
+ ```
148
+
149
+ A bare name is looked up as `<name>.md`. The name can contain dots:
150
+ `pdfmd notes-v1.2` builds `notes-v1.2.md`.
151
+
152
+ ### Other output formats
153
+
154
+ The format is taken from `-o`'s extension, or given explicitly with `--to`:
155
+
156
+ ```sh
157
+ pdfmd lecture -o lecture.html
158
+ pdfmd lecture -o lecture.docx
159
+ pdfmd lecture --to typst -o lecture.typ
160
+ pdfmd lecture -o lecture.tex # a complete, compilable .tex, not a fragment
161
+ ```
162
+
163
+ ### Slides
164
+
165
+ ```sh
166
+ pdfmd slides -p # Beamer slides; each heading starts a slide
167
+ ```
168
+
169
+ <p align="center">
170
+ <img src="https://raw.githubusercontent.com/aliperdehan/pdfmd/main/docs/slides.png" width="380" alt="A Beamer slide from examples/slides.md">
171
+ </p>
172
+
173
+ ### A whole folder
174
+
175
+ ```console
176
+ $ pdfmd notes -b
177
+ AUTO: READER TITLE MARGIN MONOFONT. Use --verbose to see in full
178
+ AUTO: MARGIN. Use --verbose to see in full
179
+ AUTO: MARGIN. Use --verbose to see in full
180
+ OK notes/lecture.md
181
+ OK notes/week1.md
182
+ OK notes/week2.md
183
+ ```
184
+
185
+ `-b` converts every `.md` in the folder into its own PDF, in parallel
186
+ (`-j N` sets the number of workers). Add `--recursive` to include
187
+ subfolders, and `-o DIR` to collect the PDFs somewhere else.
188
+
189
+ ### A book or report from several files
190
+
191
+ ```console
192
+ $ pdfmd book -r -o book.pdf
193
+ OK book/01-intro.md
194
+ OK book/02-methods.md
195
+ AUTO: MARGIN. Use --verbose to see in full
196
+ OK REPORT book.pdf
197
+ ```
198
+
199
+ `-r` (also spelled `--report` or `--book`) joins every `.md` in the folder
200
+ into a single PDF, in the order of each file's `chapter:` front-matter
201
+ field. See [`examples/book/`](https://github.com/aliperdehan/pdfmd/tree/main/examples/book/). `-i FILE` leaves one file
202
+ out, and `--exclude-unnumbered` skips files without a `chapter:`.
203
+
204
+ ### Tables straight from a CSV file
205
+
206
+ ```markdown
207
+ Measured values:
208
+
209
+ ::: {.csv file="data.csv"}
210
+ :::
211
+ ```
212
+
213
+ <p align="center">
214
+ <img src="https://raw.githubusercontent.com/aliperdehan/pdfmd/main/docs/results.png" width="480" alt="A CSV file rendered as a table">
215
+ </p>
216
+
217
+ - The delimiter is detected from the extension (`.tsv` means tab), or set
218
+ with `delimiter=";"`.
219
+ - The first row is the header unless you add `header="false"`.
220
+ - Large files are capped at 10 rows × 7 columns, so a huge CSV can't
221
+ silently fill 40 pages. `rows=all` or `cols=20` raise the cap. When a
222
+ table is cut, the PDF itself shows a note saying so.
223
+
224
+ This works for every output format.
225
+
226
+ ### Not just Markdown
227
+
228
+ ```sh
229
+ pdfmd paper.tex # compiled directly with a LaTeX engine: reruns until
230
+ # references settle, runs bibtex/biber, and leaves
231
+ # no .aux/.log clutter (--keep-aux keeps them)
232
+ pdfmd minutes.docx # Word/PowerPoint/Excel/ODF: converted by LibreOffice
233
+ pdfmd analysis.qmd # handed to Quarto, so code chunks actually run
234
+ pdfmd page.html # anything else Pandoc can read (give the extension)
235
+ ```
236
+
237
+ ## What it does automatically
238
+
239
+ Most of these print an `AUTO` line, and each can be switched off individually.
240
+
241
+ | `AUTO` kind | When | What happens |
242
+ |---|---|---|
243
+ | `READER` | no YAML front matter | reads the file as GitHub-flavoured Markdown (content-sized table columns, relaxed blank-line rules) |
244
+ | `TITLE` | no front matter, first line is `# Title` | that heading becomes the document title, and the remaining headings move up one level |
245
+ | `MARGIN` | no margin or geometry set anywhere | 1-inch margins instead of LaTeX's wide defaults |
246
+ | `MAINFONT` | no `mainfont:` and no `-f` | STIX Two Text, retried with DejaVu Serif if any glyph is missing (Times New Roman if DejaVu isn't installed) |
247
+ | `MONOFONT` | the document contains code | JetBrains Mono for code (Menlo or another installed monospace font if it isn't installed) |
248
+ | `tablewidth` | a wide pipe table | balances column widths so the table fits the page, and leaves narrow tables at their natural width |
249
+ | `YAML` / `TEX` / `LUA` | project files found | attaches `metadata.yaml`, `preamble.tex`, `<name>.lua` (see below) |
250
+ | `citeproc` | `@key` / `[@key, p. 90]` citations | adds `--citeproc`, so citations and the reference list render from your `bibliography:` without any flag (`--no-citeproc` turns it off) |
251
+ | `crossref` | `@fig:`/`@tbl:` references | adds the `pandoc-crossref` filter, ahead of citeproc |
252
+ | `papersize` | `pagesize: a4` (a common typo) | converts it to Pandoc's real `papersize:` |
253
+
254
+ `-v` explains each decision and prints the exact command it runs:
255
+
256
+ ```console
257
+ $ pdfmd lecture -v
258
+ CMD pandoc lecture.md -o lecture.pdf --pdf-engine=lualatex -f gfm -V 'mainfont=STIX Two Text' -V geometry:margin=1in -V 'monofont=JetBrains Mono' --shift-heading-level-by=-1 --lua-filter .../pdfmd-tablewidth.lua
259
+ CMD pandoc lecture.md -o lecture.pdf --pdf-engine=lualatex -f gfm -V 'mainfont=DejaVu Serif' ...
260
+ AUTO READER lecture.md: no YAML front matter; reading as gfm
261
+ AUTO TITLE lecture.md: promoted leading '# ' heading to Pandoc title metadata
262
+ AUTO MARGIN lecture.md: no geometry/margin set; using geometry:margin=1in on LaTeX-family engines
263
+ AUTO MONOFONT lecture.md: has code but no monofont set; using JetBrains Mono on LaTeX-family engines
264
+ OK lecture.md
265
+ ```
266
+
267
+ The second `CMD` line is the font fallback at work: STIX Two Text was
268
+ missing a glyph, so the document was rebuilt with DejaVu Serif. (Temporary
269
+ file paths are shortened here.)
270
+
271
+ **When a PDF doesn't look the way the Markdown suggests, run `-v` first.**
272
+ The cause is usually one of these automatic decisions, and `-v` names it.
273
+
274
+ ### Switching defaults off
275
+
276
+ ```sh
277
+ pdfmd lecture --no-auto # everything off: close to plain pandoc
278
+ pdfmd lecture --no-auto margin mainfont # only these
279
+ ```
280
+
281
+ ### Passing options to Pandoc
282
+
283
+ Any option `pdfmd` doesn't recognise is passed straight to Pandoc:
284
+
285
+ ```sh
286
+ pdfmd lecture --toc --number-sections
287
+ pdfmd lecture -V fontsize=12pt
288
+ ```
289
+
290
+ ### Settings inside the document
291
+
292
+ Or put settings in the document itself, so nobody has to remember the flag:
293
+
294
+ ```yaml
295
+ ---
296
+ title: Lab report
297
+ pdfmd-options:
298
+ no-auto: [margin, monofont]
299
+ pdf-engine: tex # only TeX engines; never fall back to HTML ones
300
+ ---
301
+ ```
302
+
303
+ `pdf-engine:` takes an engine name (`lualatex`, `typst`, ...) or a family:
304
+ `tex`, `typst`, `html` or `office`. A family limits the fallback chain to
305
+ that kind of engine. For example, a document full of chemical structures
306
+ can require TeX, and a plain memo can skip the slow LaTeX run. `-e` on the
307
+ command line always wins, and a bare `-e` means "try every engine".
308
+
309
+ ## Project files
310
+
311
+ `pdfmd` looks next to the document, and in a `metadata/` folder beside it,
312
+ for:
313
+
314
+ | File | Used as |
315
+ |---|---|
316
+ | `metadata.yaml` | shared Pandoc metadata (fonts, bibliography, CSL, ...) |
317
+ | `<name>.yaml` | per-document metadata, layered on top of `metadata.yaml` |
318
+ | `report.yaml` / `book.yaml` | metadata for `-r` builds |
319
+ | `preamble.tex`, `latex-preamble.tex`, `<name>-preamble.tex`, `preamble-*.tex` | LaTeX added to the header, generic files first |
320
+ | `<name>.lua` | a Pandoc Lua filter for that document |
321
+
322
+ **Only these names are picked up automatically.** An unrelated `.lua` or
323
+ `.tex` file lying in the folder never changes a render. When several YAML
324
+ files could apply and none is clearly meant, `pdfmd` stops and asks you to
325
+ choose with `-y FILE`, rather than guessing. `-y` alone turns discovery
326
+ off.
327
+
328
+ With a `metadata/` folder, a report's own folder can hold nothing but
329
+ `report.md` and `report.pdf`. Relative paths inside the metadata (such as
330
+ `bibliography: refs.bib`) resolve from `metadata/`, and image paths in the
331
+ document still resolve from the document's own folder.
332
+
333
+ One shared metadata file can also be **symlinked** into many folders. A
334
+ relative `bibliography: refs.bib` inside it then finds the `refs.bib`
335
+ next to the file's real copy, so you never need an absolute path.
336
+
337
+ ## Build stamps and snapshots
338
+
339
+ Both are off by default.
340
+
341
+ - **`--stamp`** keeps a `BUILD NOTES` HTML comment at the end of the `.md`
342
+ up to date. It records when the document was compiled and with which
343
+ `pdfmd` version, plus the versions of any LaTeX packages you name with
344
+ `--stamp-packages`. The comment is invisible in the PDF. `--stamp-mode history` also keeps a list of past compiles.
345
+ - **`--backup`** saves a timestamped copy of the source into `backup/`
346
+ after every successful build. A copy is skipped when nothing changed,
347
+ and `keep: 30` limits how many are kept.
348
+
349
+ Both can be turned on for a whole folder from `metadata.yaml`:
350
+
351
+ ```yaml
352
+ pdfmd-options:
353
+ stamp: true
354
+ backup: { dir: backup, keep: 30 }
355
+ ```
356
+
357
+ Separately, when `pypdf` is installed, every PDF built by `pdfmd` gets two
358
+ hidden metadata keys, `PdfmdVersions` and `PdfmdBuildDate`, which you can
359
+ read with `pdfinfo -meta`. Turn this off with `--no-stamp-pdf-metadata`.
360
+
361
+ ## Reference
362
+
363
+ - `pdfmd --help` lists every flag.
364
+ - The docstring at the top of [`pdfmd.py`](https://github.com/aliperdehan/pdfmd/blob/main/pdfmd.py) is the full reference
365
+ for each behaviour and its edge cases.
366
+ - [`CHANGELOG.md`](https://github.com/aliperdehan/pdfmd/blob/main/CHANGELOG.md) records what changed in each version and
367
+ why.
368
+
369
+ ## License
370
+
371
+ [MIT](https://github.com/aliperdehan/pdfmd/blob/main/LICENSE)
@@ -0,0 +1,7 @@
1
+ pdfmd.py,sha256=XAx4c0KPcF1ygDjIvDEJ9j0tUZvW-3ExS9YkK4kYEJQ,285071
2
+ pdfmd_cli-3.11.1.dist-info/licenses/LICENSE,sha256=MCSVIaybWs1SP6H-iEtqt18F_gYgroqK1MvKdK5fApU,1070
3
+ pdfmd_cli-3.11.1.dist-info/METADATA,sha256=eMcU2ede3tbnvKUJyir1iM5u0ez8nMR21-M-i1km6H8,14786
4
+ pdfmd_cli-3.11.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
5
+ pdfmd_cli-3.11.1.dist-info/entry_points.txt,sha256=nFmnwAHbnolStmKacUZB7gekSLN1rmsfP8dptj3hxeE,37
6
+ pdfmd_cli-3.11.1.dist-info/top_level.txt,sha256=tWfrDualAm-j8oXAgjByCQNLBfDvHIvgropth1YiDGU,6
7
+ pdfmd_cli-3.11.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pdfmd = pdfmd:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ali Perdekhan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ pdfmd