pdfmd-cli 3.23.17__tar.gz → 3.25.20__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.
- {pdfmd_cli-3.23.17/pdfmd_cli.egg-info → pdfmd_cli-3.25.20}/PKG-INFO +510 -28
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/README.md +507 -27
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd.py +4053 -553
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20/pdfmd_cli.egg-info}/PKG-INFO +510 -28
- pdfmd_cli-3.25.20/pdfmd_cli.egg-info/SOURCES.txt +125 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_cli.egg-info/requires.txt +3 -0
- pdfmd_cli-3.25.20/pdfmd_cli.egg-info/top_level.txt +13 -0
- pdfmd_cli-3.25.20/pdfmd_direct/__init__.py +14 -0
- pdfmd_cli-3.25.20/pdfmd_direct/defaults.py +166 -0
- pdfmd_cli-3.25.20/pdfmd_direct/html.py +207 -0
- pdfmd_cli-3.25.20/pdfmd_direct/typst.py +34 -0
- pdfmd_cli-3.25.20/pdfmd_edit/__init__.py +284 -0
- pdfmd_cli-3.25.20/pdfmd_help/__init__.py +178 -0
- pdfmd_cli-3.25.20/pdfmd_history/__init__.py +11 -0
- pdfmd_cli-3.25.20/pdfmd_history/git.py +86 -0
- pdfmd_cli-3.25.20/pdfmd_history/hst.py +133 -0
- pdfmd_cli-3.25.20/pdfmd_history/versions.py +99 -0
- pdfmd_cli-3.25.20/pdfmd_images/__init__.py +11 -0
- pdfmd_cli-3.25.20/pdfmd_images/remote.py +60 -0
- pdfmd_cli-3.25.20/pdfmd_images/scan.py +70 -0
- pdfmd_cli-3.25.20/pdfmd_images/svg.py +107 -0
- pdfmd_cli-3.25.20/pdfmd_lua/__init__.py +17 -0
- pdfmd_cli-3.25.20/pdfmd_lua/code.lua +90 -0
- pdfmd_cli-3.25.20/pdfmd_lua/code_wrap.tex +15 -0
- pdfmd_cli-3.25.20/pdfmd_lua/csv_table.lua +443 -0
- pdfmd_cli-3.25.20/pdfmd_lua/graphicx.tex +1 -0
- pdfmd_cli-3.25.20/pdfmd_lua/images.lua +68 -0
- pdfmd_cli-3.25.20/pdfmd_lua/pdf_images.lua +94 -0
- pdfmd_cli-3.25.20/pdfmd_lua/raw.lua +318 -0
- pdfmd_cli-3.25.20/pdfmd_lua/table_width.lua +216 -0
- pdfmd_cli-3.25.20/pdfmd_office/__init__.py +29 -0
- pdfmd_cli-3.25.20/pdfmd_office/docx.py +426 -0
- pdfmd_cli-3.25.20/pdfmd_office/docx_post.py +141 -0
- pdfmd_cli-3.25.20/pdfmd_office/fonts.py +39 -0
- pdfmd_cli-3.25.20/pdfmd_office/fragments.py +232 -0
- pdfmd_cli-3.25.20/pdfmd_office/labels.py +131 -0
- pdfmd_cli-3.25.20/pdfmd_office/odt.py +155 -0
- pdfmd_cli-3.25.20/pdfmd_office/office.lua +1486 -0
- pdfmd_cli-3.25.20/pdfmd_office/spec.py +106 -0
- pdfmd_cli-3.25.20/pdfmd_office/units.py +117 -0
- pdfmd_cli-3.25.20/pdfmd_raw/__init__.py +90 -0
- pdfmd_cli-3.25.20/pdfmd_setup/__init__.py +26 -0
- pdfmd_cli-3.25.20/pdfmd_setup/fancy.py +192 -0
- pdfmd_cli-3.25.20/pdfmd_setup/plain.py +113 -0
- pdfmd_cli-3.25.20/pdfmd_setup/registry.py +246 -0
- pdfmd_cli-3.25.20/pdfmd_tables/__init__.py +8 -0
- pdfmd_cli-3.25.20/pdfmd_tables/convert.py +427 -0
- pdfmd_cli-3.25.20/pdfmd_tables/scan.py +382 -0
- pdfmd_cli-3.25.20/pdfmd_tables/verify.py +65 -0
- pdfmd_cli-3.25.20/pdfmd_unicode/_tessdata_catalog.py +133 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_unicode/colorfont.py +50 -1
- pdfmd_cli-3.25.20/pdfmd_unicode/tessdata.py +160 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pyproject.toml +5 -1
- pdfmd_cli-3.25.20/tests/test_api.py +69 -0
- pdfmd_cli-3.25.20/tests/test_apple_emoji.py +59 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_attach.py +28 -1
- pdfmd_cli-3.25.20/tests/test_code_blocks.py +165 -0
- pdfmd_cli-3.25.20/tests/test_compat.py +124 -0
- pdfmd_cli-3.25.20/tests/test_completion.py +47 -0
- pdfmd_cli-3.25.20/tests/test_csv_table.py +125 -0
- pdfmd_cli-3.25.20/tests/test_direct.py +296 -0
- pdfmd_cli-3.25.20/tests/test_display_path.py +43 -0
- pdfmd_cli-3.25.20/tests/test_doctor.py +45 -0
- pdfmd_cli-3.25.20/tests/test_docx_tables.py +49 -0
- pdfmd_cli-3.25.20/tests/test_edit.py +125 -0
- pdfmd_cli-3.25.20/tests/test_embedding.py +209 -0
- pdfmd_cli-3.25.20/tests/test_help.py +62 -0
- pdfmd_cli-3.25.20/tests/test_history.py +224 -0
- pdfmd_cli-3.25.20/tests/test_images.py +297 -0
- pdfmd_cli-3.25.20/tests/test_install_ocr.py +57 -0
- pdfmd_cli-3.25.20/tests/test_markdown_features.py +65 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_native.py +12 -1
- pdfmd_cli-3.25.20/tests/test_office.py +476 -0
- pdfmd_cli-3.25.20/tests/test_office_latex.py +488 -0
- pdfmd_cli-3.25.20/tests/test_raw.py +246 -0
- pdfmd_cli-3.25.20/tests/test_setup.py +218 -0
- pdfmd_cli-3.25.20/tests/test_soffice_parts.py +81 -0
- pdfmd_cli-3.25.20/tests/test_table_widths.py +113 -0
- pdfmd_cli-3.25.20/tests/test_tables.py +532 -0
- pdfmd_cli-3.25.20/tests/test_tessdata.py +102 -0
- pdfmd_cli-3.25.20/tests/test_text_input.py +69 -0
- pdfmd_cli-3.25.20/tests/test_typst_input.py +80 -0
- pdfmd_cli-3.25.20/tests/test_versions.py +258 -0
- pdfmd_cli-3.23.17/pdfmd_cli.egg-info/SOURCES.txt +0 -53
- pdfmd_cli-3.23.17/pdfmd_cli.egg-info/top_level.txt +0 -3
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/LICENSE +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_cli.egg-info/dependency_links.txt +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_cli.egg-info/entry_points.txt +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/LICENSE +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/VENDORED.md +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/__init__.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/_kerning_data.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/assets/fonts/DejaVuSans-LICENSE.txt +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/assets/fonts/DejaVuSans.ttf +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/ast.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/cidfont.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/embedded.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/embedded_metrics.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/emoji.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/emoji_font.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/fonts.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/html_filter.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/image_loader.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/layout.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/parser.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/pdf.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/py.typed +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/render.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/truetype.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_inkmd/url_filter.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_unicode/__init__.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_unicode/_catalog.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_unicode/_scripts.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_unicode/emoji.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_unicode/fonts.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_unicode/install.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_unicode/plan.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_unicode/scripts.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/pdfmd_unicode/translit.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/setup.cfg +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_cache_location.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_config.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_lookup.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_packaging.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_pdf_input.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_polish.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_sections.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_translit.py +0 -0
- {pdfmd_cli-3.23.17 → pdfmd_cli-3.25.20}/tests/test_unicode.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pdfmd-cli
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.25.20
|
|
4
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
5
|
Author: Ali Perdekhan
|
|
6
6
|
License-Expression: MIT
|
|
@@ -28,6 +28,8 @@ Requires-Dist: pypinyin; extra == "translit"
|
|
|
28
28
|
Requires-Dist: anyascii; extra == "translit"
|
|
29
29
|
Provides-Extra: pandoc
|
|
30
30
|
Requires-Dist: pypandoc_binary; extra == "pandoc"
|
|
31
|
+
Provides-Extra: tui
|
|
32
|
+
Requires-Dist: prompt_toolkit>=3; extra == "tui"
|
|
31
33
|
Dynamic: license-file
|
|
32
34
|
|
|
33
35
|
# pdfmd
|
|
@@ -38,7 +40,9 @@ Dynamic: license-file
|
|
|
38
40
|
[Pandoc](https://pandoc.org) and fills in everything you would otherwise
|
|
39
41
|
have to remember: sensible fonts and margins, the right Markdown dialect,
|
|
40
42
|
your project's metadata/preamble/filter files, and a fallback chain across
|
|
41
|
-
every PDF engine you have installed.
|
|
43
|
+
every PDF engine you have installed. The same document also builds to a
|
|
44
|
+
Word or OpenDocument file that follows its page setup, fonts and LaTeX (see
|
|
45
|
+
[Word and OpenDocument output](#word-and-opendocument-output)).
|
|
42
46
|
|
|
43
47
|
```console
|
|
44
48
|
$ pdfmd lecture
|
|
@@ -46,6 +50,11 @@ AUTO: READER TITLE MARGIN MONOFONT. Use --verbose to see in full
|
|
|
46
50
|
OK lecture.md
|
|
47
51
|
```
|
|
48
52
|
|
|
53
|
+
In a folder with a single Markdown file you do not even need the name: `cd` into the folder and run `pdfmd`. It finds
|
|
54
|
+
the file, its metadata, preamble and filters, and writes the PDF beside it (with several Markdown files it asks for
|
|
55
|
+
one, or for `-b` to convert all of them or `-r` to join them). `pdfmd --help` is one short page; `pdfmd --help all`
|
|
56
|
+
is the complete option list and `pdfmd --help tables` (or `source`, `history`, `output` ...) one subject at a time.
|
|
57
|
+
|
|
49
58
|
<p align="center">
|
|
50
59
|
<img src="https://raw.githubusercontent.com/aliperdehan/pdfmd/main/docs/lecture.png" width="560" alt="lecture.md rendered to PDF">
|
|
51
60
|
</p>
|
|
@@ -74,6 +83,34 @@ turns that knowledge into defaults:
|
|
|
74
83
|
- **It doesn't give up on the first engine.** If `lualatex` fails or isn't
|
|
75
84
|
installed, it tries the next engine, then the next, and tells you why each
|
|
76
85
|
one failed.
|
|
86
|
+
- **It writes real Word files.** `pdfmd report -o report.docx` reads the front matter the PDF reads (paper size,
|
|
87
|
+
margins, fonts, line spacing) and writes it into the file's page setup and styles, so the Word file is laid out the
|
|
88
|
+
way the PDF is. With LaTeX installed, what only LaTeX can say in the document comes along: `\ce{...}` chemistry,
|
|
89
|
+
`\SI{...}{...}` units and equations become native, editable Word text and equations; a house style's own macros can be
|
|
90
|
+
given a Word recipe; what is left (tikz, chemfig, math Pandoc cannot convert) is drawn by LaTeX in the document's
|
|
91
|
+
own preamble and embedded as vector pictures. `pdfmd-options: {office: {latex: auto|images|off}}`, `--no-auto
|
|
92
|
+
officelatex` and `pdfmd --setup` switch it (see [Word and OpenDocument output](#word-and-opendocument-output)).
|
|
93
|
+
- **It handles every script and emoji.** Text the main font cannot draw (Arabic,
|
|
94
|
+
Hebrew, Chinese, Japanese, Korean, Greek, Cyrillic with Kazakh letters, Indic and
|
|
95
|
+
more) is set run by run in an installed font for its script, emoji become colour
|
|
96
|
+
pictures, and `pdfmd --install fonts` fetches missing fonts without admin rights
|
|
97
|
+
(see [Other scripts](#other-scripts)).
|
|
98
|
+
- **It finds documents by name, in any script.** `pdfmd glyukoza` opens
|
|
99
|
+
`Глюкоза.md`; with `--translit` packs, `pdfmd tyche` finds `Τύχη.md` and
|
|
100
|
+
`pdfmd mingyun` finds `命運.md`.
|
|
101
|
+
- **It reads PDFs too.** `pdfmd paper.pdf` restores a PDF's own embedded source or
|
|
102
|
+
OCRs the pages to Markdown (see [PDF to Markdown](#pdf-to-markdown)).
|
|
103
|
+
- **Tables can be data.** A `::: {.csv}` block puts a table's data in a CSV file or right in the document (any
|
|
104
|
+
delimiter, alignment and widths as attributes), and `pdfmd --extract-tables` turns the tables you already have into
|
|
105
|
+
such blocks after checking that Pandoc reads the same tables back (see [Tables straight from a CSV
|
|
106
|
+
file](#tables-straight-from-a-csv-file)). A table that is too wide gets its columns sized by their content.
|
|
107
|
+
- **Long code wraps, SVG and web images work.** Code lines wrap at the margin in a LaTeX build, an SVG is converted for
|
|
108
|
+
LaTeX with whatever is installed, and an image from the web is fetched once and kept.
|
|
109
|
+
- **Finished files are not rewritten.** A `.typ` file goes to Typst and an `.html` file to WeasyPrint or a browser, so
|
|
110
|
+
the page setup, styles and scripts survive; `--hybrid` makes the PDF open in LibreOffice as an editable document.
|
|
111
|
+
- **It keeps the history.** `pdfmd --history` lists the backups, commits and compiles of a file, `--history-restore`
|
|
112
|
+
puts a version back (backing up the one it replaces), and the build history can live in a `.hst` file instead of the
|
|
113
|
+
document (see [Build stamps, history and snapshots](#build-stamps-history-and-snapshots)).
|
|
77
114
|
- **It shows what it did.** Every automatic decision prints an `AUTO` line,
|
|
78
115
|
`-v` shows the exact Pandoc command, and every default can be switched off.
|
|
79
116
|
|
|
@@ -121,8 +158,12 @@ brew install --cask mactex-no-gui # optional: full LaTeX (large)
|
|
|
121
158
|
|
|
122
159
|
```sh
|
|
123
160
|
sudo apt install pipx pandoc texlive-xetex # Debian/Ubuntu
|
|
161
|
+
sudo dnf install pipx pandoc texlive-xetex # Fedora (add Typst with `pdfmd --install typst`)
|
|
162
|
+
sudo pacman -S python-pipx pandoc-cli typst texlive # Arch
|
|
124
163
|
```
|
|
125
164
|
|
|
165
|
+
On any Linux, `pdfmd --install full` (Pandoc and Typst) needs no package manager and no root.
|
|
166
|
+
|
|
126
167
|
```powershell
|
|
127
168
|
py -m pip install --user pipx; py -m pipx ensurepath # Windows
|
|
128
169
|
winget install --id JohnMacFarlane.Pandoc; winget install --id Typst.Typst
|
|
@@ -140,8 +181,8 @@ Office files.
|
|
|
140
181
|
<details>
|
|
141
182
|
<summary>Without pipx</summary>
|
|
142
183
|
|
|
143
|
-
`pdfmd.py`
|
|
144
|
-
|
|
184
|
+
`pdfmd.py` needs Python 3.9+ and runs straight from a clone, with the folders beside it
|
|
185
|
+
(`pdfmd_inkmd/` for the no-Pandoc fallback, `pdfmd_office/`, `pdfmd_setup/`, `pdfmd_unicode/`). It also runs
|
|
145
186
|
directly, and `pyyaml`/`pypdf` are optional (features that need them are
|
|
146
187
|
skipped with a warning):
|
|
147
188
|
|
|
@@ -175,6 +216,55 @@ OK quarto (only needed for .qmd files) (/usr/local/bin/quarto)
|
|
|
175
216
|
The numbers are the fallback order, and also shortcuts: `-e 6` means
|
|
176
217
|
`-e typst`.
|
|
177
218
|
|
|
219
|
+
For everything at once, `pdfmd --doctor` is one page on the Markdown-to-PDF tools, fonts
|
|
220
|
+
and emoji, PDF reading (batchocr, Tesseract, Poppler, OCR languages), your config file and
|
|
221
|
+
the cache, ending with the command that fixes each missing piece:
|
|
222
|
+
|
|
223
|
+
```console
|
|
224
|
+
$ pdfmd --doctor
|
|
225
|
+
...
|
|
226
|
+
Reading PDFs (PDF to Markdown):
|
|
227
|
+
OK batchocr 1.2.5
|
|
228
|
+
MISS tesseract: not found
|
|
229
|
+
MISS poppler: not found
|
|
230
|
+
|
|
231
|
+
1 thing(s) to fix:
|
|
232
|
+
1. tesseract (scanned PDFs) and poppler (scanned PDFs)
|
|
233
|
+
brew install tesseract poppler
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Tab completion
|
|
237
|
+
|
|
238
|
+
`pdfmd --completion bash|zsh|fish` prints a completion script, generated from the command
|
|
239
|
+
line itself so it never goes out of date:
|
|
240
|
+
|
|
241
|
+
```sh
|
|
242
|
+
pdfmd --completion zsh > ~/.zfunc/_pdfmd # ~/.zfunc in $fpath, then compinit
|
|
243
|
+
pdfmd --completion bash > ~/.local/share/bash-completion/completions/pdfmd
|
|
244
|
+
pdfmd --completion fish > ~/.config/fish/completions/pdfmd.fish
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### An older Pandoc, and a machine with no network
|
|
248
|
+
|
|
249
|
+
The oldest Pandoc `pdfmd` is tested with is **3.1.3** (what the claude.ai sandbox has); the whole test suite runs against
|
|
250
|
+
it. An older one may work, and the first build with it says so once; `pdfmd --doctor` lists what a given Pandoc does
|
|
251
|
+
without. With 3.1.3: Typst PDFs cannot show a picture `pdfmd` drew itself (before 3.2), a numbered equation in a Word file
|
|
252
|
+
sits in a plain table instead of a borderless one (before 3.4), and `--extract-tables` leaves a table whose caption has
|
|
253
|
+
a `{#tbl:id}` (before 3.8.2: Pandoc reads that as words, so the change could not be checked). A `pandoc-crossref` must be
|
|
254
|
+
the release built for the Pandoc you run; one built for another is not run, with a warning, because it would put `??` where
|
|
255
|
+
the numbers go.
|
|
256
|
+
|
|
257
|
+
Where `pip install pdfmd-cli` cannot reach the network (a sandbox with no DNS that only takes an upload), two ways:
|
|
258
|
+
|
|
259
|
+
```sh
|
|
260
|
+
python3 scripts/build_zipapp.py # on a machine with pdfmd's source: dist/pdfmd.pyz, 1.4 MB, PyYAML and pypdf inside
|
|
261
|
+
python3 pdfmd.pyz report.md # on the other: needs Python 3.9+, Pandoc and a PDF engine; unpacks itself once
|
|
262
|
+
# into ~/.cache/pdfmd/pyz/ because Pandoc has to open the Lua filters as files
|
|
263
|
+
|
|
264
|
+
pip download pdfmd-cli -d wheelhouse # or: a folder of wheels, carried over
|
|
265
|
+
pip install --no-index --find-links wheelhouse pdfmd-cli
|
|
266
|
+
```
|
|
267
|
+
|
|
178
268
|
### No Pandoc? The built-in fallback
|
|
179
269
|
|
|
180
270
|
On a machine with no Pandoc, or Pandoc but no PDF engine, `pdfmd` does not
|
|
@@ -278,6 +368,28 @@ letters, no tones, vowels left out where the script leaves them out. Names that
|
|
|
278
368
|
romanize alike (homophones) are listed as ambiguous, never picked between. The
|
|
279
369
|
same spelling rules find a section by its heading (`doc#tyche`).
|
|
280
370
|
|
|
371
|
+
### A small editor
|
|
372
|
+
|
|
373
|
+
```sh
|
|
374
|
+
pdfmd --install tui # once: prompt_toolkit, about 1 MB
|
|
375
|
+
pdfmd --edit lecture # nano-like full screen; Ctrl-B saves and builds, Ctrl-P opens the PDF
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
`pdfmd --edit` (alpha) opens the Markdown file in a plain full-screen editor with the build one key away: Ctrl-S
|
|
379
|
+
saves, Ctrl-B saves and builds (what pdfmd said stays at the bottom), Ctrl-P opens the result, Ctrl-W / F3 find,
|
|
380
|
+
Ctrl-G go to a line, Ctrl-K / Ctrl-U cut and paste a line, Ctrl-Z / Ctrl-Y undo and redo, Ctrl-X leaves (asking once
|
|
381
|
+
when there are unsaved changes); F1 lists them. Options given beside it (`pdfmd --edit lecture -e lualatex`) are used
|
|
382
|
+
for the build, and a name that does not exist yet starts a new file. It is deliberately rough: a base for what comes later.
|
|
383
|
+
|
|
384
|
+
### In VS Code
|
|
385
|
+
|
|
386
|
+
`pdfmd --init-vscode` writes a `.vscode/tasks.json` here (build, build and open, watch, extract tables; Terminal > Run
|
|
387
|
+
Build Task). The [`vscode/`](https://github.com/aliperdehan/pdfmd/tree/main/vscode) folder of the repository is a small
|
|
388
|
+
extension over the same command line: build (`Cmd/Ctrl+Alt+B`), build and open, build as Word/HTML/Typst/slides, extract
|
|
389
|
+
tables (all, or chosen ones), file history, compare and restore, restore the source a PDF carries (right-click it). Every
|
|
390
|
+
command it runs is written to the *pdfmd* output panel. Install it with `npx @vscode/vsce package` and
|
|
391
|
+
`code --install-extension pdfmd-vscode-*.vsix`.
|
|
392
|
+
|
|
281
393
|
### One section
|
|
282
394
|
|
|
283
395
|
`pdfmd doc#onlyapart` builds just the section whose heading is "Only a Part"
|
|
@@ -305,6 +417,111 @@ pdfmd lecture --to typst -o lecture.typ
|
|
|
305
417
|
pdfmd lecture -o lecture.tex # a complete, compilable .tex, not a fragment
|
|
306
418
|
```
|
|
307
419
|
|
|
420
|
+
### Word and OpenDocument output
|
|
421
|
+
|
|
422
|
+
Plain Pandoc ignores `papersize`, `geometry`, `mainfont` and `fontsize` when it writes `.docx`
|
|
423
|
+
or `.odt`: you get a Letter page in the default fonts. pdfmd writes them into the *reference
|
|
424
|
+
document* Pandoc builds the file from, so the page and the text follow the same front matter as the PDF:
|
|
425
|
+
|
|
426
|
+
| Front matter | In the Word file |
|
|
427
|
+
|---|---|
|
|
428
|
+
| `papersize: a4` (also `letter`, `legal`, `a5`, `b5`..., `classoption: [a4paper, landscape]`) | page size and orientation |
|
|
429
|
+
| `geometry:` (a list, `margin=2cm`, `top=1in,left=...`, `paperwidth=...`) or `margin:` | page margins |
|
|
430
|
+
| `mainfont`, `sansfont`, `monofont`, `CJKmainfont`, `fontsize`, `linestretch`, `lang`, `indent` | body, heading and code fonts, sizes, line spacing, language, first-line indent |
|
|
431
|
+
|
|
432
|
+
A `.docx` carries font *names*, not fonts, and the person opening it has Times New Roman, not
|
|
433
|
+
STIX Two Text. So well-known fonts Word does not ship are mapped to the closest one it does (STIX
|
|
434
|
+
Two Text, Libertinus, Latin Modern to Times New Roman; Helvetica Neue, Inter to Arial; JetBrains
|
|
435
|
+
Mono, Menlo, Fira Code to Consolas), with an `AUTO OFFICE` note; `office: {fonts: exact}` keeps
|
|
436
|
+
your names. Without any of these keys pdfmd's own look applies: black bold headings sized like a LaTeX
|
|
437
|
+
article, a centred title block, booktabs-style table rules, Times New Roman and Consolas.
|
|
438
|
+
|
|
439
|
+
**Your own template.** A reference document decides the page and fonts itself, and pdfmd then
|
|
440
|
+
changes only what the document's `office:` block names. It is found, in order, as
|
|
441
|
+
`office: {reference-doc: FILE}`, `<name>-reference.docx` or `reference.docx` (`.dotx` works too,
|
|
442
|
+
`.odt`/`.ott` for ODT, `.pptx`/`.potx` for slides) beside the document, in its `metadata/` folder or
|
|
443
|
+
beside its metadata files, and finally in `~/.config/pdfmd/`. Pandoc's own `--reference-doc` is left
|
|
444
|
+
alone. Only builds whose output is `.docx`/`.odt`/`.pptx` look for one. `pdfmd --init-reference`
|
|
445
|
+
writes `reference.docx` (also `odt`, `pptx`): Pandoc's styles with pdfmd's look, to restyle in Word.
|
|
446
|
+
|
|
447
|
+
A template keeps its own style names. `office: {styles: {Heading1: LRH1, BodyText: LRNormal, Table: TableGrid}}`
|
|
448
|
+
makes the Heading 1, Body Text and table Pandoc writes look like the template's own `LR H1`, `LR Normal` and
|
|
449
|
+
`Table Grid` (a missing Pandoc style is created from the source); `office: {replace: {NULAB-KICKER: "Course
|
|
450
|
+
wording"}}` rewrites text in the template's headers and footers; `office: {title-page: true}` gives the first
|
|
451
|
+
page a page of its own, without header or footer.
|
|
452
|
+
|
|
453
|
+
**A LaTeX package can tell pdfmd about itself.** Beside a package's `.sty` (or in an `office/` or `pdfmd/` folder there)
|
|
454
|
+
pdfmd looks for `<package>-pdfmd.yaml`, and for its Word support: `<package>-reference.docx`/`.dotx`,
|
|
455
|
+
`<package>-office.lua` (the profile above) and `<package>-office.yaml` (the `office:` defaults, with `by-option:`
|
|
456
|
+
entries for what an option of `\usepackage[opt]{package}` adds). A document that loads the package gets all of it with
|
|
457
|
+
no setting of its own, and a package without these files behaves exactly as before.
|
|
458
|
+
|
|
459
|
+
`<package>-pdfmd.yaml` holds `latex-keys:`, the front-matter keys the package's macros are filled from
|
|
460
|
+
(`experiment: LabExperiment` turns `experiment: Titration` into `\renewcommand{\LabExperiment}{Titration}` after the
|
|
461
|
+
preamble), and an optional `office:` section, the same as `<package>-office.yaml`, for a package that wants one file:
|
|
462
|
+
|
|
463
|
+
```yaml
|
|
464
|
+
latex-keys:
|
|
465
|
+
experiment: LabExperiment
|
|
466
|
+
group: LabGroup
|
|
467
|
+
office:
|
|
468
|
+
reference-doc: house.dotx
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
```yaml
|
|
472
|
+
pdfmd-options:
|
|
473
|
+
office:
|
|
474
|
+
reference-doc: ../templates/house.dotx # or leave it to be found
|
|
475
|
+
papersize: a4 # change just this on top of the template
|
|
476
|
+
fonts: exact # keep STIX Two Text and friends as named
|
|
477
|
+
style: plain # no pdfmd look (headings, title block, table rules)
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
`--no-auto officeref` turns the search off, `--no-auto officestyle` leaves Pandoc's default alone.
|
|
481
|
+
|
|
482
|
+
**LaTeX in the document.** Pandoc turns `$x^2$` into a Word equation and drops everything else of
|
|
483
|
+
LaTeX. For `.docx` and `.odt` pdfmd adds a filter that makes it native where it can:
|
|
484
|
+
|
|
485
|
+
- `\ce{Ag+(aq) + Cl-(aq) -> AgCl(s)}` (mhchem) and `\si{\gram\per\mole}`, `\SI{5}{\milli\liter}`,
|
|
486
|
+
`\num{1.5e-3}` (siunitx) become formatted text with real subscripts, charges and units, and, inside
|
|
487
|
+
math, Word equation pieces;
|
|
488
|
+
- `\begin{equation}`, `align`, `reaction`... become Word equations with their number at the right;
|
|
489
|
+
- raw `figure`, `tabular`, lists, `\emph`, `\newpage`... are read by Pandoc's own LaTeX reader;
|
|
490
|
+
- `\ref`, `\eqref`, `\cref`, `\Cref`, `\pageref` and the "Figure 3." in front of a caption use the numbers
|
|
491
|
+
LaTeX itself gave (pdfmd builds the PDF once, in its cache, and reads the `.aux`; reused while the sources
|
|
492
|
+
are older), with the caption separator (`labelsep=`) and `\crefname`s of your preamble;
|
|
493
|
+
- **what is left is drawn by LaTeX**: tikz, chemfig, a house style's own macros, math Pandoc cannot convert are compiled in
|
|
494
|
+
*your document's own preamble* (the same fonts, packages and macros as the PDF, one fragment to a page), and the
|
|
495
|
+
pages go into the Word file as vector pictures: an SVG with a 300 dpi PNG fallback (Word 2016 and later draw the SVG,
|
|
496
|
+
LibreOffice and older readers the PNG). An inline fragment sits on the text's baseline, a wide one is scaled to the
|
|
497
|
+
text width, a figure's caption stays text with its number. `\includegraphics{plot.pdf}` and `` (Word cannot
|
|
498
|
+
show a PDF) are converted the same way. Pictures are cached by content, so a rebuild draws only what changed
|
|
499
|
+
(`pdfmd --clear-cache` empties it). A fragment that will not compile is named in a warning and left out; the rest of
|
|
500
|
+
the document is built. Needs `pdftocairo` (Poppler) and a LaTeX engine; without them the fragments are reported only.
|
|
501
|
+
- **a house style's own macros** can be told to pdfmd: `office.lua` (or `<name>-office.lua`) beside the document, in its
|
|
502
|
+
`metadata/` folder or in `~/.config/pdfmd/`, or `office: {profile: FILE}`, is a small Lua file:
|
|
503
|
+
`return {ignore = {"\\LabCaptionBegin"}, commands = {prelab = function(args) return {pandoc.Strong{pandoc.Str("[pre-lab " .. args[1] .. "]")}} end}}`
|
|
504
|
+
says which macros to drop and what the others mean in a Word file (a command may return text, or blocks such as a
|
|
505
|
+
native table); an optional `pandoc = function(doc, helpers)` hook may restructure the whole document. The helpers
|
|
506
|
+
include `inlines(tex)`/`blocks(tex)` (LaTeX read with the filter's own math, `\ce` and `\si` applied),
|
|
507
|
+
`read_file(name)` (a file the document's `\input` would find), `number_caption(table, "table")`, `labels()`,
|
|
508
|
+
`preamble()`, `meta()`, `warn(text)`; a profile can thus build a house table from the package's own data, as nulabreport
|
|
509
|
+
does for `\chemicals`.
|
|
510
|
+
- what cannot be done at all is named in a warning (`-v` lists it).
|
|
511
|
+
|
|
512
|
+
`pdfmd report.md --check-docx` says what a Word build would make native and what it would draw as pictures, naming the
|
|
513
|
+
environment or macro behind each (`the tikzpicture environment`, `the macro \irspectrum`), without drawing or writing anything: a
|
|
514
|
+
quick way to see what is left to give a recipe (see the profile below).
|
|
515
|
+
|
|
516
|
+
`pdfmd-options: {office: {latex: auto}}` is the default; `latex: images` draws everything LaTeX says as a picture
|
|
517
|
+
(formulas, `\ce` and units too, instead of making them native); `latex: off` or `--no-auto officelatex` skips all of it
|
|
518
|
+
(Pandoc's own behaviour). `office: {labels: off}` skips the PDF build (numbers are then counted).
|
|
519
|
+
|
|
520
|
+
The same filter serves the other outputs when LaTeX is the problem: **the soffice fallback** (the Word file above, then LibreOffice: `pdfmd -e soffice report.md` is the `.docx` as LibreOffice draws it) now
|
|
521
|
+
keeps the page size, margins and fonts, shows equations and draws what LaTeX can; a **Typst or WeasyPrint run after LaTeX
|
|
522
|
+
failed** gets what the document says in LaTeX as native text or pictures instead of nothing; and HTML, Typst and
|
|
523
|
+
WeasyPrint builds do it on request (`pdfmd-options: {office: {latex: auto}}`).
|
|
524
|
+
|
|
308
525
|
### Stopping part-way
|
|
309
526
|
|
|
310
527
|
`--stop-at` ends the build after a stage; everything before it runs as normal:
|
|
@@ -422,12 +639,16 @@ style, a compound library, a shared bibliography and parts.
|
|
|
422
639
|
The TeX distribution's own packages, fonts and Pandoc are not carried.
|
|
423
640
|
- **Comments.** Notes to yourself do not travel: the attached source loses its
|
|
424
641
|
`<!-- -->` comments, the LaTeX preamble's `%` comments, the text between a
|
|
425
|
-
`.bib`'s entries
|
|
426
|
-
`strip-comments: [preamble, bibliography]` or
|
|
427
|
-
(`--strip-comments-in`, `--keep-comments-in`). Code
|
|
428
|
-
verbatim environments are never touched, and a
|
|
429
|
-
bare `%`, because it swallows the line break.
|
|
430
|
-
|
|
642
|
+
`.bib`'s entries, a CSL file's XML comments and the `#` comments of YAML
|
|
643
|
+
files. Choose per kind: `strip-comments: [preamble, bibliography]` or
|
|
644
|
+
`{markdown: false}` (`--strip-comments-in`, `--keep-comments-in`). Code
|
|
645
|
+
blocks, `\verb`, `\url` and verbatim environments are never touched, and a
|
|
646
|
+
`%` that closes a line keeps a bare `%`, because it swallows the line break.
|
|
647
|
+
With `strip-comments: false` (or `metadata` kept) the attached source gives
|
|
648
|
+
back your metadata files and the document's front matter byte for byte,
|
|
649
|
+
comments and quoting included; `--restore` of such a PDF is a full source
|
|
650
|
+
copy. The data files of `.csv` blocks (`tables/*.csv`) are always stored
|
|
651
|
+
with the source.
|
|
431
652
|
- **Only the bibliography entries you cite** are attached (and what they
|
|
432
653
|
cross-reference), not a shared file of hundreds; `attach-bibliography: all`
|
|
433
654
|
keeps it whole, and `nocite: '@*'` keeps every entry.
|
|
@@ -461,10 +682,32 @@ options of [M1ck4's pdfmd](https://github.com/M1ck4/pdfmd) (`--ocr`, `--lang`,
|
|
|
461
682
|
work as they did. Install the reader once:
|
|
462
683
|
|
|
463
684
|
```sh
|
|
464
|
-
pdfmd --install batchocr # pip install batchocr[md] from its GitHub release
|
|
465
|
-
|
|
685
|
+
pdfmd --install batchocr # pip install batchocr[md] from its GitHub release,
|
|
686
|
+
# then offers the system programs below
|
|
466
687
|
```
|
|
467
688
|
|
|
689
|
+
Scanned pages also need **Tesseract** (OCR) and **Poppler** (`pdftotext`, `pdftoppm`).
|
|
690
|
+
Those are separate programs with their own builds for every platform, so pdfmd does not
|
|
691
|
+
bundle them; `--install batchocr` finds your package manager (Homebrew, apt, dnf, pacman,
|
|
692
|
+
zypper, apk, scoop, Chocolatey or winget), shows the exact command and, on an interactive
|
|
693
|
+
terminal, runs it if you say yes (`PDFMD_NO_PROMPT=1` only prints it). By hand:
|
|
694
|
+
|
|
695
|
+
```sh
|
|
696
|
+
brew install tesseract poppler # macOS (and Linuxbrew)
|
|
697
|
+
sudo apt install tesseract-ocr poppler-utils # Debian/Ubuntu; dnf: tesseract poppler-utils
|
|
698
|
+
scoop install tesseract poppler # Windows (or choco install ...)
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
OCR languages are packs of their own. `pdfmd --install ocr` lists the Tesseract languages
|
|
702
|
+
pdfmd can fetch, and `pdfmd --install ocr:rus,kaz` (or `ru`, `kazakh`, `zh`, `ja`...) downloads
|
|
703
|
+
them into pdfmd's own folder, with no admin rights and each file checked against a checksum
|
|
704
|
+
pinned in pdfmd (the compact `tessdata_fast` models, Apache-2.0; English and the orientation
|
|
705
|
+
model come along). `pdfmd scan.pdf --lang rus` then uses that folder whenever it has every
|
|
706
|
+
language you asked for, and Tesseract's own languages otherwise (a `TESSDATA_PREFIX` you set
|
|
707
|
+
always wins). `pdfmd --uninstall ocr:rus` removes one. The package managers have them too:
|
|
708
|
+
`brew install tesseract-lang`, `apt install tesseract-ocr-rus`, `dnf install
|
|
709
|
+
tesseract-langpack-rus`. `pdfmd --check-dependencies` reports batchocr, Tesseract and Poppler.
|
|
710
|
+
|
|
468
711
|
Credits and licences: batchocr's Markdown structure stages are M1ck4's
|
|
469
712
|
(MIT; that project is archived) and are vendored inside batchocr with their
|
|
470
713
|
licence. PyMuPDF, which they use, is AGPL-3.0: it is installed as its own
|
|
@@ -491,6 +734,25 @@ comma inside a field). The text is Helvetica, so letters outside Latin-1 become
|
|
|
491
734
|
their base letter or `?`. `--attach-links` stores each linked file as
|
|
492
735
|
`linked/PATH` and puts a paperclip in the margin beside the link.
|
|
493
736
|
|
|
737
|
+
### Use it from Python
|
|
738
|
+
|
|
739
|
+
```python
|
|
740
|
+
import pdfmd
|
|
741
|
+
|
|
742
|
+
pdfmd.convert_file("report.md", "docx") # -> Path("report.docx")
|
|
743
|
+
pdfmd.convert_file("report.md", "pdf", "out/report.pdf", variables={"geometry": "margin=2cm"},
|
|
744
|
+
extra_args=["--engine", "typst"])
|
|
745
|
+
html = pdfmd.convert_text("# Hi\n\nSome *text*.\n", "html") # str for text formats, bytes for pdf/docx/odt/pptx/epub
|
|
746
|
+
rst = pdfmd.convert_text(open("notes.rst").read(), "docx", format="rst")
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
Each call runs the command-line tool (as `pypandoc` runs Pandoc), so a document builds exactly as `pdfmd` would build it,
|
|
750
|
+
with all the auto-discovery of the document's folder, and nothing in the caller's process is touched. The source is not
|
|
751
|
+
stamped or backed up unless you ask (`stamp=True`, `backup=True`). A failure raises `pdfmd.PdfmdError` (with
|
|
752
|
+
`returncode`, `stdout` and `stderr`); `check=False` returns the path anyway. `metadata=` takes metadata files,
|
|
753
|
+
`variables=` a dict of Pandoc variables, `extra_args=` anything else the command line takes, `cwd=` the folder it runs
|
|
754
|
+
in and `timeout=` seconds.
|
|
755
|
+
|
|
494
756
|
### Other command names: `mdpdf` and `inkmd`
|
|
495
757
|
|
|
496
758
|
pdfmd also installs `mdpdf` and `inkmd` commands that take those tools' own keys
|
|
@@ -643,8 +905,31 @@ Measured values:
|
|
|
643
905
|
<img src="https://raw.githubusercontent.com/aliperdehan/pdfmd/main/docs/results.png" width="480" alt="A CSV file rendered as a table">
|
|
644
906
|
</p>
|
|
645
907
|
|
|
646
|
-
|
|
647
|
-
|
|
908
|
+
Or write the data in the document itself, in a code block so that nothing in it is read as Markdown:
|
|
909
|
+
|
|
910
|
+
````markdown
|
|
911
|
+
::: {.csv align="lrr"}
|
|
912
|
+
```
|
|
913
|
+
Compound,Mass (g),Price
|
|
914
|
+
Water,18.015,1.20
|
|
915
|
+
"Ethanol, dry",46.07,3.45
|
|
916
|
+
```
|
|
917
|
+
:::
|
|
918
|
+
|
|
919
|
+
: Masses and prices {#tbl:m}
|
|
920
|
+
````
|
|
921
|
+
|
|
922
|
+
- Cells are read as Pandoc Markdown (`H~2~O`, `$x^2$`, `\ce{...}`, `[@key]`); `reader="gfm"` makes them plain GFM.
|
|
923
|
+
- A caption is the line after the block (`: Caption {#tbl:id}`, or `Table: Caption`), or `caption="Caption"` inside the
|
|
924
|
+
braces, with the identifier as `#tbl:id` there too. A caption in the attributes wins over a line after the block.
|
|
925
|
+
- A relative `file=` is found beside the document (and along the resource path), wherever Pandoc runs. With both
|
|
926
|
+
`file=` and data inside the block, the file is used.
|
|
927
|
+
- The delimiter is `delimiter=";"` or its name (`semicolon`, `tab`, `pipe`, `space`, `colon`, `comma`); without one it
|
|
928
|
+
comes from the extension (`.tsv` means tab) or from the first line (whichever of `,` `;` tab `|` it holds most of).
|
|
929
|
+
- Columns are aligned with `align="lcr"` (or `align="left,center,right"`), or by a second row in the data made of
|
|
930
|
+
`---`, `:--`, `:-:`, `--:` as in a pipe table; `align=` wins. If such a row is really data, say `separator="none"`.
|
|
931
|
+
`widths="5,1,1"` sets relative widths, and a second row with unequal dashes does too. Without either, pdfmd picks
|
|
932
|
+
widths that suit the contents.
|
|
648
933
|
- The first row is the header unless you add `header="false"`.
|
|
649
934
|
- Large files are capped at 10 rows × 7 columns, so a huge CSV can't
|
|
650
935
|
silently fill 40 pages. `rows=all` or `cols=20` raise the cap. When a
|
|
@@ -652,6 +937,118 @@ Measured values:
|
|
|
652
937
|
|
|
653
938
|
This works for every output format.
|
|
654
939
|
|
|
940
|
+
#### Turning tables into CSV blocks, and back
|
|
941
|
+
|
|
942
|
+
```
|
|
943
|
+
pdfmd --extract-tables report.md # every table becomes a .csv block reading tables/<name>.csv
|
|
944
|
+
pdfmd --expand-tables report.md # and back to ordinary tables
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
`--extract-tables` rewrites the document in place, after copying the old one to the backup folder, and says so. Pipe,
|
|
948
|
+
simple, multiline and grid tables are all read (the ones inside code blocks are not tables). The files are named after
|
|
949
|
+
the captions (`Masses and prices` gives `tables/masses-and-prices.csv`), or `table1`, `table2` by position;
|
|
950
|
+
`--table-names a,b,c` names them, and a list that does not match the number of tables is an error that changes nothing.
|
|
951
|
+
`--table-numbers 1,3-4` extracts just those tables (by position in the document) and leaves the rest; the names then go to
|
|
952
|
+
the chosen ones. In a document in parts the data goes to the report's `tables/` folder and an unnamed table is named after
|
|
953
|
+
its part (`discussion-table1.csv`).
|
|
954
|
+
The caption, the alignment and the widths the document chose stay as attributes of the block, and before anything is
|
|
955
|
+
written Pandoc reads the old and the new document and the tables must come out the same. A table Pandoc cannot write
|
|
956
|
+
as CSV (a list inside a cell, a cell spanning rows, no header row) is left as it is, with the reason; so is every
|
|
957
|
+
`.csv` block already in the document, and if the check fails the whole document is left untouched and the command exits
|
|
958
|
+
with an error. A document with no front matter is built as `gfm`, which reads pipe tables only, so only those are
|
|
959
|
+
touched there. `--tables-inline` puts the data
|
|
960
|
+
inside the document (in a fenced block) instead of in files, `--tables-dir DIR` picks the folder, and `--dry-run` shows
|
|
961
|
+
the change without making it. `--expand-tables` is the reverse, every row included.
|
|
962
|
+
|
|
963
|
+
A `.csv` block that holds its data inside the document stays as it is, unless you pass `--extract-inline-csv`, which moves
|
|
964
|
+
that data to a file as well. To keep one table or block as it is whatever you run, put `<!-- pdfmd: ignore -->` on the
|
|
965
|
+
line above it (or under its caption); the comment survives comment stripping, because pdfmd's own comments are kept.
|
|
966
|
+
A comment between a table and its caption would stop Pandoc from reading the caption as one, so there is no such
|
|
967
|
+
position.
|
|
968
|
+
|
|
969
|
+
### Code: wrapping and line numbers
|
|
970
|
+
|
|
971
|
+
With a LaTeX engine a long line of code wraps at the margin instead of running off the page (a long path or option list
|
|
972
|
+
breaks where the line is full), and `{wrap=false}` on one block, `--no-code-wrap` or `code-wrap: false` in
|
|
973
|
+
`pdfmd-options` lets it run on. Line numbers are off until you ask for them:
|
|
974
|
+
|
|
975
|
+
````markdown
|
|
976
|
+
``` {.python .numberLines startFrom=10}
|
|
977
|
+
def f(x):
|
|
978
|
+
return x * 2
|
|
979
|
+
```
|
|
980
|
+
````
|
|
981
|
+
|
|
982
|
+
`--line-numbers` (or `pdfmd-options: {line-numbers: true}`, or the setting in `pdfmd --setup`) numbers every code block,
|
|
983
|
+
`--line-numbers 5` numbers every fifth line, `{.noNumberLines}` leaves one block out, and `step=5` and `numbersep=8pt`
|
|
984
|
+
adjust a single block.
|
|
985
|
+
|
|
986
|
+
### Images: SVG and remote ones
|
|
987
|
+
|
|
988
|
+
LaTeX reads PDF, PNG and JPEG, not SVG. In a LaTeX build pdfmd converts each SVG the document names, once, with
|
|
989
|
+
whatever is installed (`rsvg-convert`, Inkscape, `cairosvg`, `svglib`, or LibreOffice, which most machines have), keeps
|
|
990
|
+
the PDF by the file's content, and uses it where the document wrote the SVG: a Markdown image, a raw
|
|
991
|
+
`\includegraphics{figure.svg}`, a raw `\includesvg{figure}`. A raw `\includegraphics` also gets `graphicx` loaded,
|
|
992
|
+
which Pandoc only does for a Markdown image (a PNG in one used to stop the build with "undefined control sequence").
|
|
993
|
+
A Markdown image from the web is fetched once and kept for a week, so the build does not need the network again, an SVG
|
|
994
|
+
badge works, and a Pandoc built without HTTP support (Homebrew's is) no longer drops it; with no network there is one
|
|
995
|
+
warning and the image's description stays. `--no-auto svg` and `--no-auto remoteimages` turn the two off, and
|
|
996
|
+
`pdfmd --doctor` says which converter will be used.
|
|
997
|
+
|
|
998
|
+
### Editable in LibreOffice, and one file that carries its data
|
|
999
|
+
|
|
1000
|
+
`--hybrid` makes the PDF a LibreOffice *hybrid PDF*: besides its pages it carries an OpenDocument copy of the document
|
|
1001
|
+
(`Original.odt`, or `.odp`, `.ods`), and when LibreOffice opens the PDF it opens that copy as a document you can edit,
|
|
1002
|
+
instead of the pages in Draw. An Office file (`pdfmd minutes.docx --hybrid`) is converted by LibreOffice, so the copy is
|
|
1003
|
+
the file itself; a Markdown file gets an `.odt` built by pdfmd with its metadata, so what LibreOffice shows is the
|
|
1004
|
+
Word-route rendering of the source (not the LaTeX pages). `pdfmd --restore report.pdf` writes the ODF file back out.
|
|
1005
|
+
`pdfmd-options: {hybrid: true}` or `pdfmd --setup` makes it the default.
|
|
1006
|
+
|
|
1007
|
+
A single Markdown file can carry its data too: `pdfmd report.md --assemble-only --embed-metadata files -o report.one.md`
|
|
1008
|
+
folds in the images, CSV tables and included files the text points at (text as it is, anything else as base64), and the
|
|
1009
|
+
file builds on its own, in an empty folder; `pdfmd --unpack` writes them back byte for byte. It is left out of the default
|
|
1010
|
+
kinds because it can be big (`bundle-max-mb` caps it); for a PDF, `--bundle` stores the same files beside the source.
|
|
1011
|
+
|
|
1012
|
+
### HTML, LaTeX, Typst and Word pieces inside Markdown
|
|
1013
|
+
|
|
1014
|
+
Markdown can carry raw pieces: `<img>`, `<table>`, `<b>` and `<div>` (HTML), `\ce{...}` or a tikz picture (LaTeX), a
|
|
1015
|
+
`` ```{=typst} `` block, Word or OpenDocument XML. Pandoc keeps the ones written in the format it is writing and drops
|
|
1016
|
+
every other, silently, so a document that mixes them loses pieces in every build. `pdfmd-options.raw` (or `--raw`) says
|
|
1017
|
+
which syntaxes take part in each output family, and carries the foreign ones over:
|
|
1018
|
+
|
|
1019
|
+
```yaml
|
|
1020
|
+
pdfmd-options:
|
|
1021
|
+
raw:
|
|
1022
|
+
tex: [tex, html, typst] # LaTeX builds: PDF through lualatex, xelatex ...
|
|
1023
|
+
typst: [typst, html, tex] # Typst builds
|
|
1024
|
+
html: [html, tex, typst] # HTML, EPUB, PDF through weasyprint and the other HTML engines (-e html)
|
|
1025
|
+
office: [office, html] # Word and OpenDocument, and PDF through soffice
|
|
1026
|
+
```
|
|
1027
|
+
|
|
1028
|
+
```sh
|
|
1029
|
+
pdfmd report --raw # everything for every family
|
|
1030
|
+
pdfmd report --raw-for html=tex,typst --raw-for tex=html # or per family, on the command line
|
|
1031
|
+
```
|
|
1032
|
+
|
|
1033
|
+
A family takes the syntaxes it lists, in this way: its own syntax stays as written; **HTML** is read by Pandoc's HTML
|
|
1034
|
+
reader, so an `<img>` becomes the target's image (an SVG then goes through the image conversion below), a `<table>` a
|
|
1035
|
+
real table, `<b>...</b>` bold text and a `<div>` around Markdown a division, even when the opening and the closing tag
|
|
1036
|
+
sit in separate pieces; **LaTeX** is read by Pandoc's LaTeX reader (what it does not know, a custom macro, stays LaTeX
|
|
1037
|
+
and is lost outside LaTeX; Word builds keep their own LaTeX route, see
|
|
1038
|
+
[Word and OpenDocument output](#word-and-opendocument-output)); **Typst** is drawn by `typst compile` as a cropped
|
|
1039
|
+
vector picture, a PDF for LaTeX, Typst and Word, an SVG for HTML. A syntax a family does not list is dropped, its own
|
|
1040
|
+
included, which is odd but a clear way to say "this output has no HTML in it". A family not mentioned is left to Pandoc
|
|
1041
|
+
as it always was, `raw: all` lists everything, and `--no-raw` turns it off for a run. Pictures are kept in pdfmd's cache by
|
|
1042
|
+
their content. (An HTML file that is not self-contained points at the cache; use `--self-contained` to carry them.)
|
|
1043
|
+
Not yet: LaTeX pieces Pandoc cannot read (tikz, chemfig) as pictures in HTML, HTML drawn as a picture, Word XML as
|
|
1044
|
+
anything but Word XML.
|
|
1045
|
+
|
|
1046
|
+
**PDF images in HTML.** A browser does not show a PDF in `<img>`, an SVG it does. For an HTML build (a web page, an
|
|
1047
|
+
EPUB, a PDF through WeasyPrint) every image that is a PDF, `` or `<img src="plot.pdf">`, is converted to
|
|
1048
|
+
an SVG with poppler's `pdftocairo` (or `mutool`, `pdf2svg`, `inkscape`) and stays vector; the first page is used and the
|
|
1049
|
+
SVG is kept by the PDF's content. It is on by default, since it only changes what would not have shown; `--no-auto
|
|
1050
|
+
pdfimages` turns it off. LaTeX and Typst read PDFs themselves, and Word has its own route.
|
|
1051
|
+
|
|
655
1052
|
### Not just Markdown
|
|
656
1053
|
|
|
657
1054
|
```sh
|
|
@@ -660,25 +1057,52 @@ pdfmd paper.tex # compiled directly with a LaTeX engine: reruns until
|
|
|
660
1057
|
# no .aux/.log clutter (--keep-aux keeps them)
|
|
661
1058
|
pdfmd minutes.docx # Word/PowerPoint/Excel/ODF: converted by LibreOffice
|
|
662
1059
|
pdfmd analysis.qmd # handed to Quarto, so code chunks actually run
|
|
663
|
-
pdfmd page.html #
|
|
1060
|
+
pdfmd page.html # built by WeasyPrint, or a browser if the page runs scripts: no Pandoc
|
|
1061
|
+
pdfmd note.typ # compiled by Typst itself: the page setup in the file is kept
|
|
1062
|
+
pdfmd notes.rst # anything else Pandoc can read (give the extension)
|
|
664
1063
|
```
|
|
665
1064
|
|
|
1065
|
+
A finished `.typ` or `.html` file goes straight to its own engine, because Pandoc would read it into its own model
|
|
1066
|
+
and write it out again, and the page size, the styles and the scripts would not survive the trip. For a page that is
|
|
1067
|
+
WeasyPrint first (it is quiet and needs no browser); a page with `<script>` goes to Chrome, Chromium, Edge or Brave
|
|
1068
|
+
(headless, printing the page), as does one WeasyPrint cannot draw, and wkhtmltopdf, Prince, pagedjs-cli and LibreOffice
|
|
1069
|
+
come after. `-e edge` (or `weasyprint`, `chromium`...) picks one. As with an Office file, such a document gets none of
|
|
1070
|
+
pdfmd's defaults, since it is finished; `--apply-defaults` (also in `pdfmd --setup`) gives it the title, author, date,
|
|
1071
|
+
language, font, font size, paper and margin of its `metadata.yaml`, ahead of its own settings so those win. A `.tex`
|
|
1072
|
+
file that no LaTeX engine can compile is tried through Pandoc, with a warning.
|
|
1073
|
+
|
|
1074
|
+
The reader comes from the file's extension, as in Pandoc, and a bare name is looked up as `<name>.md`, so give the
|
|
1075
|
+
extension for anything else. The automatic decisions about Markdown (`READER`, `TITLE`, `citeproc`, `crossref` below)
|
|
1076
|
+
apply to Markdown files only.
|
|
1077
|
+
|
|
1078
|
+
**A plain-text file as Markdown (opt-in).** `pdfmd notes.txt --text-to-markdown` reads a `.txt` file the way a person typed it
|
|
1079
|
+
and guesses its structure: headings (capitals, `1.2 Title`, `====` underlines), bullet and numbered lists, tables from
|
|
1080
|
+
columns separated by runs of spaces, indented blocks as code, hard-wrapped lines joined into paragraphs. The words never
|
|
1081
|
+
change (the letters and digits of the result are the input's), and a text that measures as garbled (symbol soup, OCR
|
|
1082
|
+
noise, replacement characters) gets paragraphs only, with the rule that fired printed. `MODE` is `auto` (default),
|
|
1083
|
+
`force` (guess even in a garbled text) or `paragraphs`. It needs batchocr 1.2.5 (`pdfmd --install batchocr`), writes `notes.md`
|
|
1084
|
+
beside the text (never over a file that is there) and builds from it; with `-o x.md` the conversion is all it does.
|
|
1085
|
+
Off unless asked: `--text-to-markdown`, or `options: {text-to-markdown: auto}` in the config file (or `pdfmd --setup`).
|
|
1086
|
+
|
|
666
1087
|
## What it does automatically
|
|
667
1088
|
|
|
668
1089
|
Most of these print an `AUTO` line, and each can be switched off individually.
|
|
669
1090
|
|
|
670
1091
|
| `AUTO` kind | When | What happens |
|
|
671
1092
|
|---|---|---|
|
|
672
|
-
| `READER` | no YAML front matter | reads the file as GitHub-flavoured Markdown (content-sized table columns, relaxed blank-line rules) |
|
|
673
|
-
| `TITLE` | no front matter, first line is `# Title` | that heading becomes the document title, and the remaining headings move up one level |
|
|
1093
|
+
| `READER` | a Markdown file with no YAML front matter | reads the file as GitHub-flavoured Markdown (content-sized table columns, relaxed blank-line rules) |
|
|
1094
|
+
| `TITLE` | a Markdown file with no front matter, first line is `# Title` | that heading becomes the document title, and the remaining headings move up one level |
|
|
674
1095
|
| `MARGIN` | no margin or geometry set anywhere | 1-inch margins instead of LaTeX's wide defaults |
|
|
675
1096
|
| `MAINFONT` | no `mainfont:` and no `-f` | STIX Two Text (Times New Roman if it isn't installed), or a serif that has the letters when the document is mostly in a script STIX Two Text lacks (Kazakh Cyrillic, say); retried with DejaVu Serif if a glyph is still missing. A font you name is never changed except by `fallback: document` |
|
|
676
1097
|
| `UNICODE` | text the main font cannot draw (Arabic, Han, Greek with accents, rare symbols...) | sets each run in an installed font for its script (see *Other scripts*), instead of printing boxes |
|
|
677
1098
|
| `MONOFONT` | the document contains code | JetBrains Mono for code (Menlo or another installed monospace font if it isn't installed) |
|
|
678
|
-
| `tablewidth` | a
|
|
1099
|
+
| `tablewidth` | a pipe table with plain `---` separators and long lines | picks the column widths that give the fewest lines within the text width (a column never narrower than its longest word), and gives a table that fits its natural width back; unequal dashes (`--|-----`) are kept, and `table-widths: keep` in `pdfmd-options` leaves every table as written |
|
|
1100
|
+
| `svg`, `remoteimages` | an SVG, or an image from the web, in a LaTeX build | the SVG is converted to a PDF (once), the remote image is fetched and kept (`--no-auto svg`, `--no-auto remoteimages`) |
|
|
1101
|
+
| `typstdirect`, `htmldirect` | a `.typ` or `.html` file | built by Typst / WeasyPrint or a browser, not through Pandoc (`--no-auto typstdirect` for the old route) |
|
|
1102
|
+
| `codewrap` | code blocks in a LaTeX build | long lines wrap at the margin (`--no-code-wrap` or `--no-auto codewrap` for the old behaviour) |
|
|
679
1103
|
| `YAML` / `TEX` / `LUA` | project files found | attaches `metadata.yaml`, `preamble.tex`, `<name>.lua` (see below) |
|
|
680
|
-
| `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) |
|
|
681
|
-
| `crossref` | `@fig:`/`@tbl:` references | adds the `pandoc-crossref` filter, ahead of citeproc |
|
|
1104
|
+
| `citeproc` | `@key` / `[@key, p. 90]` citations (as Pandoc reads them: `@key` in a code span or an e-mail address is none) | adds `--citeproc`, so citations and the reference list render from your `bibliography:` without any flag (`--no-citeproc` turns it off) |
|
|
1105
|
+
| `crossref` | `@fig:`/`@tbl:` references or `{#fig:...}` labels | adds the `pandoc-crossref` filter, ahead of citeproc |
|
|
682
1106
|
| `papersize` | `pagesize: a4` (a common typo) | converts it to Pandoc's real `papersize:` |
|
|
683
1107
|
|
|
684
1108
|
`-v` explains each decision and prints the exact command it runs:
|
|
@@ -703,6 +1127,12 @@ The cause is usually one of these automatic decisions, and `-v` names it.
|
|
|
703
1127
|
|
|
704
1128
|
### Other scripts
|
|
705
1129
|
|
|
1130
|
+
<p align="center">
|
|
1131
|
+
<img src="https://raw.githubusercontent.com/aliperdehan/pdfmd/main/docs/scripts.png" width="560" alt="examples/scripts.md: Kazakh, Greek, Arabic, Hebrew, Chinese, Japanese, Korean and Hindi text, and emoji, in one PDF">
|
|
1132
|
+
</p>
|
|
1133
|
+
|
|
1134
|
+
(That is [`examples/scripts.md`](https://github.com/aliperdehan/pdfmd/blob/main/examples/scripts.md), built with no configuration.)
|
|
1135
|
+
|
|
706
1136
|
A document that mixes scripts needs more than one font. With lualatex or
|
|
707
1137
|
xelatex, `pdfmd` reads the character tables of your installed fonts, finds
|
|
708
1138
|
the characters the main font cannot draw and sets each run of them in a font
|
|
@@ -744,10 +1174,10 @@ Emoji are set as pictures with lualatex and xelatex (which cannot draw colour
|
|
|
744
1174
|
fonts): each emoji, flag, skin tone, family or keycap is looked up in the colour
|
|
745
1175
|
emoji font (`pdfmd --install emoji`, a system Noto Color Emoji, or else Apple Color Emoji on
|
|
746
1176
|
a Mac), its picture taken out of the font file and included at the height of the text, in
|
|
747
|
-
inline code and code blocks too. Apple's font is read
|
|
748
|
-
emoji, skin tones and
|
|
749
|
-
|
|
750
|
-
for those). The pictures
|
|
1177
|
+
inline code and code blocks too. Apple's font is read through its glyph names (the same
|
|
1178
|
+
way for single emoji, skin tones, flags, keycaps and the joined emoji it has a glyph for,
|
|
1179
|
+
such as a woman scientist); the few it composes in tables pdfmd does not read (a family of
|
|
1180
|
+
four, say) are reported as undrawable (install Noto for those). The pictures
|
|
751
1181
|
are kept in pdfmd's cache folder; a `.tex` written with `--to latex` points
|
|
752
1182
|
there.
|
|
753
1183
|
|
|
@@ -831,6 +1261,27 @@ options:
|
|
|
831
1261
|
pdf-engine: lualatex
|
|
832
1262
|
```
|
|
833
1263
|
|
|
1264
|
+
**`pdfmd --setup`** changes the same defaults from a menu, without editing the files: a numbered list (nothing to
|
|
1265
|
+
install, works over ssh), each setting with its choices and what they mean. It covers what a document would otherwise
|
|
1266
|
+
say in `pdfmd-options:` or its front matter, for every document:
|
|
1267
|
+
|
|
1268
|
+
- *global metadata* (a `metadata.yaml` beside the config file, below anything a document's own folder says): author, language,
|
|
1269
|
+
paper size, font size, page geometry, main and code font, line spacing, coloured links, table of contents, and for
|
|
1270
|
+
citations the bibliography file, the CSL style and linked citations;
|
|
1271
|
+
- characters a font lacks or none draws, fonts for other scripts, romanization packs;
|
|
1272
|
+
- the citation engine, the PDF engine, the default output format, HTML (one file, math method), LaTeX and reference
|
|
1273
|
+
numbers in Word files;
|
|
1274
|
+
- PDF finishing (header, footer, bookmarks, attached links) and the source file (the "Compiled with..." stamp, backups,
|
|
1275
|
+
comment stripping, attaching the source and its files to the PDF);
|
|
1276
|
+
- the cache, reading `.txt` as Markdown, and which of pdfmd's automatic behaviours (`--no-auto` kinds) are off.
|
|
1277
|
+
|
|
1278
|
+
Choosing 0 (for a text, `-`) gives a setting its built-in default back; `s` saves, `q` quits. The files are rewritten without your
|
|
1279
|
+
comments (the old one is kept as `.bak`). The same keys can be written by hand under `options:` of `config.yaml`. A
|
|
1280
|
+
full-screen version is optional: `pdfmd --install tui` (prompt_toolkit, about 1 MB), then `pdfmd --setup fancy`, or set
|
|
1281
|
+
"This setup screen" to fancy to make it the one `pdfmd --setup` opens. The first time pdfmd finishes a build in a terminal
|
|
1282
|
+
with no config file yet, it prints one `TIP` line about `--setup` (never in a pipe, in CI, or from the Python API;
|
|
1283
|
+
`PDFMD_NO_PROMPT=1` silences it).
|
|
1284
|
+
|
|
834
1285
|
The decisions pdfmd remembers for you (the Lua filters it trusts, an offer you
|
|
835
1286
|
dismissed) live in the same folder, not in `~/.cache/pdfmd`, so cleaning the cache
|
|
836
1287
|
(`--clear-cache`) cannot lose them; files from an older version are moved there
|
|
@@ -864,15 +1315,16 @@ One shared metadata file can also be **symlinked** into many folders. A
|
|
|
864
1315
|
relative `bibliography: refs.bib` inside it then finds the `refs.bib`
|
|
865
1316
|
next to the file's real copy, so you never need an absolute path.
|
|
866
1317
|
|
|
867
|
-
## Build stamps and snapshots
|
|
1318
|
+
## Build stamps, history and snapshots
|
|
868
1319
|
|
|
869
|
-
|
|
1320
|
+
All are off by default.
|
|
870
1321
|
|
|
871
1322
|
- **`--stamp`** keeps a `BUILD NOTES` HTML comment at the end of the `.md`
|
|
872
1323
|
up to date. It records when the document was compiled and with which
|
|
873
1324
|
`pdfmd` version, plus the versions of any LaTeX packages you name with
|
|
874
1325
|
`--stamp-packages`. The comment is invisible in the PDF. `--stamp-mode history` also keeps a list of past compiles.
|
|
875
|
-
- **`--backup`** saves a timestamped copy of the source into `backup/`
|
|
1326
|
+
- **`--backup`** saves a timestamped copy of the source into `.backups/` (a hidden folder; an existing `backup/` is kept
|
|
1327
|
+
using, and pdfmd says where the first copy went)
|
|
876
1328
|
after every successful build. A copy is skipped when nothing changed,
|
|
877
1329
|
and `keep: 30` limits how many are kept.
|
|
878
1330
|
|
|
@@ -881,15 +1333,45 @@ Both can be turned on for a whole folder from `metadata.yaml`:
|
|
|
881
1333
|
```yaml
|
|
882
1334
|
pdfmd-options:
|
|
883
1335
|
stamp: true
|
|
884
|
-
backup: { dir:
|
|
1336
|
+
backup: { dir: .backups, keep: 30 }
|
|
885
1337
|
```
|
|
886
1338
|
|
|
1339
|
+
**History in a file instead of in the document.** `--stamp-store file` (or `stamp: {store: file}`) writes each compile
|
|
1340
|
+
to `NAME.hst` in the backup folder, and the document itself is not edited by a build. The file is one line per entry,
|
|
1341
|
+
newest first, so it reads in any editor, two of them join with `cat`, and `pdfmd --merge-history a.hst b.hst -o all.hst`
|
|
1342
|
+
keeps every entry once:
|
|
1343
|
+
|
|
1344
|
+
```
|
|
1345
|
+
# pdfmd history of report.md -- one entry per line, newest first: WHEN | KIND | TEXT [| key=value ...]
|
|
1346
|
+
2026-10-09 11:22:01 | compiled | with nulabreport v1.27.7, pdfmd v3.25.7 | sha=3fa91c0d4b21 out=report.pdf
|
|
1347
|
+
```
|
|
1348
|
+
|
|
1349
|
+
`pdfmd --history-to-file report.md` moves the whole `BUILD NOTES` block that pdfmd owns into that file (the compiles as
|
|
1350
|
+
entries, anything written by hand inside it as one `note` entry), and `--history-to-notes` builds the block again (both
|
|
1351
|
+
back the document up first, `--dry-run` shows). A document may carry several
|
|
1352
|
+
`BUILD NOTES` blocks (yours, an AI agent's): pdfmd writes only into the one that already holds its own lines, or the
|
|
1353
|
+
only one there is, or starts one of its own when there are several and none is its; the rest is never touched, and a
|
|
1354
|
+
line `pdfmd: ignore` in a block keeps pdfmd out of it. The file travels with the document: `--embed-metadata` folds it
|
|
1355
|
+
in (`hst`), `--unpack` writes it out, and `--attach-source` stores it in the PDF for `--restore`.
|
|
1356
|
+
|
|
1357
|
+
**Going back.** `pdfmd --history report.md` lists every version it can find, newest first: the backups (in `.backups`,
|
|
1358
|
+
and in an older `backup/`, `backups/`... beside the document, whatever naming each file has), the git commits that
|
|
1359
|
+
changed the file (the repository may be a folder above), and the compiles recorded in its history. In a terminal the
|
|
1360
|
+
list is navigable: a number shows what differs, `d 3` the diff, `r 3` restores. Without one, `--history-diff` and
|
|
1361
|
+
`--history-restore` take a number, a backup's timestamp (any start of it: `20261003`), a file name, a commit hash,
|
|
1362
|
+
`latest`, or `previous` (the newest that is not the file as it is). A restore backs the file up first, so nothing is
|
|
1363
|
+
ever lost; it keeps the build notes and history of the file as it is now, and adds a `Restored version ...` entry
|
|
1364
|
+
(`stamp: {restored-note: false}` or `--no-restored-note` leave it out; `--dry-run` shows what would change).
|
|
1365
|
+
`pdfmd --init-backups report.md` turns all of this on for a document: backups and a history file, set in its front
|
|
1366
|
+
matter under an `AUTO GENERATED` comment (`--global` for every document), and a first copy.
|
|
1367
|
+
|
|
887
1368
|
Separately, when `pypdf` is installed, every PDF built by `pdfmd` gets two
|
|
888
1369
|
hidden metadata keys, `PdfmdVersions` and `PdfmdBuildDate`, which you can
|
|
889
1370
|
read with `pdfinfo -meta`. Turn this off with `--no-stamp-pdf-metadata`.
|
|
890
1371
|
|
|
891
1372
|
## Reference
|
|
892
1373
|
|
|
1374
|
+
- [`docs/recipes.md`](https://github.com/aliperdehan/pdfmd/blob/main/docs/recipes.md) is the task-by-task manual: fifteen chapters of "how do I..." with the commands (the basics, a house style, long documents, tables, code and images, raw HTML/LaTeX/Typst, other inputs and outputs, the PDF that carries its source, history, fonts and scripts, speed, the editor and VS Code, and what to do when something looks wrong), plus an option reference by task.
|
|
893
1375
|
- `pdfmd --help` lists every flag.
|
|
894
1376
|
- The docstring at the top of [`pdfmd.py`](https://github.com/aliperdehan/pdfmd/blob/main/pdfmd.py) is the full reference
|
|
895
1377
|
for each behaviour and its edge cases.
|