pdfmd-cli 3.26.20__tar.gz → 3.29.8__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.
Files changed (233) hide show
  1. {pdfmd_cli-3.26.20/pdfmd_cli.egg-info → pdfmd_cli-3.29.8}/PKG-INFO +410 -60
  2. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/README.md +407 -58
  3. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd.py +5592 -629
  4. pdfmd_cli-3.29.8/pdfmd_chem/__init__.py +2 -0
  5. pdfmd_cli-3.29.8/pdfmd_chem/__main__.py +12 -0
  6. pdfmd_cli-3.29.8/pdfmd_chem/batch.py +129 -0
  7. pdfmd_cli-3.29.8/pdfmd_chem/render.py +315 -0
  8. pdfmd_cli-3.29.8/pdfmd_chem/siunitx.py +701 -0
  9. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8/pdfmd_cli.egg-info}/PKG-INFO +410 -60
  10. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_cli.egg-info/SOURCES.txt +58 -0
  11. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_cli.egg-info/entry_points.txt +2 -0
  12. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_cli.egg-info/top_level.txt +3 -0
  13. pdfmd_cli-3.29.8/pdfmd_css/__init__.py +277 -0
  14. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_direct/__init__.py +3 -3
  15. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_direct/html.py +13 -5
  16. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_help/__init__.py +39 -9
  17. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_images/remote.py +24 -1
  18. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_labels/scan.py +15 -4
  19. pdfmd_cli-3.29.8/pdfmd_lua/chem.lua +79 -0
  20. pdfmd_cli-3.29.8/pdfmd_lua/chem_client.lua +156 -0
  21. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/csv_table.lua +153 -31
  22. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/diagram.lua +32 -5
  23. pdfmd_cli-3.29.8/pdfmd_lua/ebook.lua +51 -0
  24. pdfmd_cli-3.29.8/pdfmd_lua/ebook_input.lua +53 -0
  25. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/flat.lua +38 -1
  26. pdfmd_cli-3.29.8/pdfmd_lua/graphviz.cjs +59 -0
  27. pdfmd_cli-3.29.8/pdfmd_lua/katex.cjs +33 -0
  28. pdfmd_cli-3.29.8/pdfmd_lua/mathjax.cjs +54 -0
  29. pdfmd_cli-3.29.8/pdfmd_lua/pagebreak.lua +159 -0
  30. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/raw.lua +8 -0
  31. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/table_width.lua +15 -0
  32. pdfmd_cli-3.29.8/pdfmd_lua/title_meta.lua +59 -0
  33. pdfmd_cli-3.29.8/pdfmd_lua/typst.lua +100 -0
  34. pdfmd_cli-3.29.8/pdfmd_lua/weasyprint.lua +272 -0
  35. pdfmd_cli-3.29.8/pdfmd_mhchem/LICENSE +201 -0
  36. pdfmd_cli-3.29.8/pdfmd_mhchem/__init__.py +6 -0
  37. pdfmd_cli-3.29.8/pdfmd_mhchem/parser.py +1207 -0
  38. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_office/__init__.py +2 -1
  39. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_office/odt.py +13 -0
  40. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_office/office.lua +315 -381
  41. pdfmd_cli-3.29.8/pdfmd_office/properties.py +100 -0
  42. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_setup/__init__.py +17 -6
  43. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_setup/fancy.py +90 -16
  44. pdfmd_cli-3.29.8/pdfmd_setup/inventory.py +244 -0
  45. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_setup/plain.py +39 -10
  46. pdfmd_cli-3.29.8/pdfmd_setup/registry.py +442 -0
  47. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pyproject.toml +10 -4
  48. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_attach.py +265 -5
  49. pdfmd_cli-3.29.8/tests/test_attach_format.py +66 -0
  50. pdfmd_cli-3.29.8/tests/test_autolog.py +183 -0
  51. pdfmd_cli-3.29.8/tests/test_bopen.py +111 -0
  52. pdfmd_cli-3.29.8/tests/test_browser_engine.py +114 -0
  53. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_build_record.py +2 -1
  54. pdfmd_cli-3.29.8/tests/test_calibre.py +179 -0
  55. pdfmd_cli-3.29.8/tests/test_calibre_markdown.py +138 -0
  56. pdfmd_cli-3.29.8/tests/test_calibre_targets.py +506 -0
  57. pdfmd_cli-3.29.8/tests/test_check_source.py +96 -0
  58. pdfmd_cli-3.29.8/tests/test_chem.py +246 -0
  59. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_code_blocks.py +24 -0
  60. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_compat.py +15 -2
  61. pdfmd_cli-3.29.8/tests/test_css.py +174 -0
  62. pdfmd_cli-3.29.8/tests/test_css_v2.py +148 -0
  63. pdfmd_cli-3.29.8/tests/test_csv_table.py +251 -0
  64. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_diagrams.py +33 -1
  65. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_direct.py +7 -0
  66. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_doctor.py +13 -0
  67. pdfmd_cli-3.29.8/tests/test_ebook_input.py +156 -0
  68. pdfmd_cli-3.29.8/tests/test_edit_pdf.py +180 -0
  69. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_embedding.py +13 -0
  70. pdfmd_cli-3.29.8/tests/test_engine_chain.py +115 -0
  71. pdfmd_cli-3.29.8/tests/test_engine_filters.py +391 -0
  72. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_flat.py +7 -3
  73. pdfmd_cli-3.29.8/tests/test_header_includes.py +239 -0
  74. pdfmd_cli-3.29.8/tests/test_install_calibre.py +223 -0
  75. pdfmd_cli-3.29.8/tests/test_install_core_tex.py +145 -0
  76. pdfmd_cli-3.29.8/tests/test_install_diagram.py +184 -0
  77. pdfmd_cli-3.29.8/tests/test_install_python.py +97 -0
  78. pdfmd_cli-3.29.8/tests/test_jobs.py +71 -0
  79. pdfmd_cli-3.29.8/tests/test_katex_scale.py +99 -0
  80. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_labels.py +127 -1
  81. pdfmd_cli-3.29.8/tests/test_mathfont.py +109 -0
  82. pdfmd_cli-3.29.8/tests/test_mathjax.py +356 -0
  83. pdfmd_cli-3.29.8/tests/test_mhchem.py +120 -0
  84. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_native.py +13 -4
  85. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_office.py +3 -2
  86. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_office_latex.py +415 -15
  87. pdfmd_cli-3.29.8/tests/test_old_python_syntax.py +67 -0
  88. pdfmd_cli-3.29.8/tests/test_package_helper.py +94 -0
  89. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_packaging.py +10 -0
  90. pdfmd_cli-3.29.8/tests/test_pagebreak.py +234 -0
  91. pdfmd_cli-3.29.8/tests/test_pan_tec.py +36 -0
  92. pdfmd_cli-3.29.8/tests/test_picture_cache_protocol.py +131 -0
  93. pdfmd_cli-3.29.8/tests/test_plot_cache.py +168 -0
  94. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_polish.py +49 -4
  95. pdfmd_cli-3.29.8/tests/test_presets.py +154 -0
  96. pdfmd_cli-3.29.8/tests/test_rawcode.py +94 -0
  97. pdfmd_cli-3.29.8/tests/test_remote_csl.py +167 -0
  98. pdfmd_cli-3.29.8/tests/test_setup.py +720 -0
  99. pdfmd_cli-3.29.8/tests/test_standalone_source.py +406 -0
  100. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_table_widths.py +2 -1
  101. pdfmd_cli-3.29.8/tests/test_texpackages.py +105 -0
  102. pdfmd_cli-3.26.20/pdfmd_setup/registry.py +0 -246
  103. pdfmd_cli-3.26.20/tests/test_csv_table.py +0 -125
  104. pdfmd_cli-3.26.20/tests/test_setup.py +0 -218
  105. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/LICENSE +0 -0
  106. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_check/__init__.py +0 -0
  107. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_check/lint.py +0 -0
  108. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_cli.egg-info/dependency_links.txt +0 -0
  109. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_cli.egg-info/requires.txt +0 -0
  110. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_direct/defaults.py +0 -0
  111. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_direct/typst.py +0 -0
  112. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_edit/__init__.py +0 -0
  113. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_flat/__init__.py +0 -0
  114. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_flat/asciify.py +0 -0
  115. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_flat/keep.py +0 -0
  116. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_history/__init__.py +0 -0
  117. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_history/git.py +0 -0
  118. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_history/hst.py +0 -0
  119. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_history/versions.py +0 -0
  120. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_images/__init__.py +0 -0
  121. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_images/scan.py +0 -0
  122. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_images/svg.py +0 -0
  123. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/LICENSE +0 -0
  124. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/VENDORED.md +0 -0
  125. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/__init__.py +0 -0
  126. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/_kerning_data.py +0 -0
  127. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/assets/fonts/DejaVuSans-LICENSE.txt +0 -0
  128. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/assets/fonts/DejaVuSans.ttf +0 -0
  129. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/ast.py +0 -0
  130. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/cidfont.py +0 -0
  131. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/embedded.py +0 -0
  132. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/embedded_metrics.py +0 -0
  133. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/emoji.py +0 -0
  134. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/emoji_font.py +0 -0
  135. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/fonts.py +0 -0
  136. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/html_filter.py +0 -0
  137. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/image_loader.py +0 -0
  138. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/layout.py +0 -0
  139. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/parser.py +0 -0
  140. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/pdf.py +0 -0
  141. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/py.typed +0 -0
  142. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/render.py +0 -0
  143. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/truetype.py +0 -0
  144. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_inkmd/url_filter.py +0 -0
  145. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_labels/__init__.py +0 -0
  146. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_labels/replay.py +0 -0
  147. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/__init__.py +0 -0
  148. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/ascii.lua +0 -0
  149. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/code.lua +0 -0
  150. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/code_wrap.tex +0 -0
  151. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/graphicx.tex +0 -0
  152. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/images.lua +0 -0
  153. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/pdf_images.lua +0 -0
  154. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_lua/select.lua +0 -0
  155. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_office/docx.py +0 -0
  156. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_office/docx_post.py +0 -0
  157. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_office/fonts.py +0 -0
  158. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_office/fragments.py +0 -0
  159. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_office/labels.py +0 -0
  160. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_office/spec.py +0 -0
  161. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_office/units.py +0 -0
  162. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_raw/__init__.py +0 -0
  163. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_tables/__init__.py +0 -0
  164. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_tables/convert.py +0 -0
  165. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_tables/scan.py +0 -0
  166. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_tables/verify.py +0 -0
  167. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/__init__.py +0 -0
  168. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/article/__name__.md +0 -0
  169. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/article/description.txt +0 -0
  170. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/article/next.txt +0 -0
  171. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/article/refs.bib +0 -0
  172. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/book/__name__.md +0 -0
  173. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/book/description.txt +0 -0
  174. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/book/next.txt +0 -0
  175. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/book/parts/10-introduction.md +0 -0
  176. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/book/parts/20-methods.md +0 -0
  177. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/book/parts/30-results.md +0 -0
  178. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/notes/__name__.md +0 -0
  179. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/notes/description.txt +0 -0
  180. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/notes/next.txt +0 -0
  181. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/report/__name__.md +0 -0
  182. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/report/data.csv +0 -0
  183. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/report/description.txt +0 -0
  184. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/report/next.txt +0 -0
  185. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/slides/__name__.md +0 -0
  186. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/slides/description.txt +0 -0
  187. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_templates/data/slides/next.txt +0 -0
  188. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/__init__.py +0 -0
  189. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/_catalog.py +0 -0
  190. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/_scripts.py +0 -0
  191. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/_tessdata_catalog.py +0 -0
  192. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/colorfont.py +0 -0
  193. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/emoji.py +0 -0
  194. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/fonts.py +0 -0
  195. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/install.py +0 -0
  196. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/plan.py +0 -0
  197. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/scripts.py +0 -0
  198. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/tessdata.py +0 -0
  199. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/pdfmd_unicode/translit.py +0 -0
  200. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/setup.cfg +0 -0
  201. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_api.py +0 -0
  202. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_apple_emoji.py +0 -0
  203. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_ascii.py +0 -0
  204. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_budget.py +0 -0
  205. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_cache_location.py +0 -0
  206. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_check.py +0 -0
  207. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_completion.py +0 -0
  208. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_config.py +0 -0
  209. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_display_path.py +0 -0
  210. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_docx_tables.py +0 -0
  211. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_edit.py +0 -0
  212. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_help.py +0 -0
  213. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_history.py +0 -0
  214. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_images.py +0 -0
  215. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_install_ocr.py +0 -0
  216. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_keep_source.py +0 -0
  217. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_latex_errors.py +0 -0
  218. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_lookup.py +0 -0
  219. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_lua_trust.py +0 -0
  220. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_markdown_features.py +0 -0
  221. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_pdf_input.py +0 -0
  222. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_raw.py +0 -0
  223. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_reader.py +0 -0
  224. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_sections.py +0 -0
  225. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_soffice_parts.py +0 -0
  226. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_tables.py +0 -0
  227. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_templates.py +0 -0
  228. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_tessdata.py +0 -0
  229. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_text_input.py +0 -0
  230. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_translit.py +0 -0
  231. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_typst_input.py +0 -0
  232. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_unicode.py +0 -0
  233. {pdfmd_cli-3.26.20 → pdfmd_cli-3.29.8}/tests/test_versions.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdfmd-cli
3
- Version: 3.26.20
3
+ Version: 3.29.8
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
- License-Expression: MIT
6
+ License-Expression: MIT AND Apache-2.0
7
7
  Project-URL: Homepage, https://github.com/aliperdehan/pdfmd
8
8
  Project-URL: Changelog, https://github.com/aliperdehan/pdfmd/blob/main/CHANGELOG.md
9
9
  Keywords: pandoc,markdown,pdf,latex,cli
@@ -16,6 +16,7 @@ Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
17
  License-File: pdfmd_inkmd/LICENSE
18
18
  License-File: pdfmd_inkmd/assets/fonts/DejaVuSans-LICENSE.txt
19
+ License-File: pdfmd_mhchem/LICENSE
19
20
  Requires-Dist: pyyaml
20
21
  Requires-Dist: pypdf
21
22
  Provides-Extra: math
@@ -46,10 +47,20 @@ Word or OpenDocument file that follows its page setup, fonts and LaTeX (see
46
47
 
47
48
  ```console
48
49
  $ pdfmd lecture
49
- AUTO: READER TITLE MARGIN MONOFONT. Use --verbose to see in full
50
- OK lecture.md
50
+ FOUND metadata: metadata.yaml + preamble.tex
51
+ DEFAULTS margin 1in, font STIX Two Text, code in JetBrains Mono, title from heading
52
+ AUTO: READER. Use --verbose to see in full
53
+ OK lecture.md > lecture.pdf (lualatex)
51
54
  ```
52
55
 
56
+ `FOUND` is what pdfmd picked up from the folder, `DEFAULTS` what it applied because nothing said otherwise
57
+ (the global metadata of `pdfmd --setup`, the title taken from a leading `# ` heading, a wide table whose columns it
58
+ balanced), and the `AUTO:` line the other decisions it made. Files of one folder are listed under it once
59
+ (`metadata: metadata.yaml + preamble.tex`; `--setup` can list each with its path instead). Each line is cut at the
60
+ width of the terminal (110 characters when the output is piped): `+3 more (--verbose)`. `--verbose` prints every
61
+ decision with its reason. The closing line names the file the build made, `OK lecture.md > lecture.pdf`; `--setup`
62
+ sets what stands between the two.
63
+
53
64
  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
65
  the file, its metadata, preamble and filters, and writes the PDF beside it (with several Markdown files it asks for
55
66
  one, or for `-b` to convert all of them or `-r` to join them). `pdfmd --help` is one short page; `pdfmd --help all`
@@ -90,6 +101,7 @@ turns that knowledge into defaults:
90
101
  given a Word recipe; what is left (tikz, chemfig, math Pandoc cannot convert) is drawn by LaTeX in the document's
91
102
  own preamble and embedded as vector pictures. `pdfmd-options: {office: {latex: auto|images|off}}`, `--no-auto
92
103
  officelatex` and `pdfmd --setup` switch it (see [Word and OpenDocument output](#word-and-opendocument-output)).
104
+ The file's properties hold the document's title and authors, and nothing of the machine that built it.
93
105
  - **It handles every script and emoji.** Text the main font cannot draw (Arabic,
94
106
  Hebrew, Chinese, Japanese, Korean, Greek, Cyrillic with Kazakh letters, Indic and
95
107
  more) is set run by run in an installed font for its script, emoji become colour
@@ -164,6 +176,11 @@ sudo pacman -S python-pipx pandoc-cli typst texlive # Arch
164
176
 
165
177
  On any Linux, `pdfmd --install full` (Pandoc and Typst) needs no package manager and no root.
166
178
 
179
+ The extras that are Python packages (`pdfmd --install math`, `tui`, `translit`, `batchocr` ...) go into the Python pdfmd runs
180
+ from; when that Python is managed by the system (Homebrew's, Debian's: "externally-managed-environment", PEP 668) pdfmd puts
181
+ them in its own folder instead, `~/.local/share/pdfmd/python/3.14` (one per Python version), which it adds to the end of
182
+ the module path when it starts. Nothing is installed into the system's Python.
183
+
167
184
  ```powershell
168
185
  py -m pip install --user pipx; py -m pipx ensurepath # Windows
169
186
  winget install --id JohnMacFarlane.Pandoc; winget install --id Typst.Typst
@@ -210,12 +227,79 @@ OK 7. weasyprint (/opt/homebrew/bin/weasyprint)
210
227
  MISS 8. wkhtmltopdf
211
228
  ...
212
229
  OK 14. soffice (/Applications/LibreOffice.app/Contents/MacOS/soffice)
230
+ OK calibre (only when named: -e calibre) (/opt/homebrew/bin/ebook-convert)
213
231
  OK quarto (only needed for .qmd files) (/usr/local/bin/quarto)
214
232
  ```
215
233
 
216
234
  The numbers are the fallback order, and also shortcuts: `-e 6` means
217
235
  `-e typst`.
218
236
 
237
+ **An order of your own.** `-e` takes a comma list, tried in the order written and nothing else:
238
+ `-e typst,calibre,lualatex` tries Typst, then Calibre, then LuaLaTeX. A word is an engine (or its alias), a family
239
+ (`tex`, `html`, `typst`: its installed members, in place) or `pandoc` (every engine Pandoc drives; never Calibre). A word
240
+ whose engine is not installed is passed over with a NOTE while another one of the list can run, and the build stops only
241
+ when none can. `pdf-engine:` in `pdfmd-options`, the front matter, a metadata file or the config takes the same list
242
+ (`pdf-engine: [typst, lualatex]`). Without `-e` the chain is the numbered one above, unchanged.
243
+
244
+ `-e calibre` prints the document with [Calibre](https://calibre-ebook.com)'s `ebook-convert`
245
+ instead: Pandoc writes one HTML page (math as MathML, which Calibre draws with its own
246
+ MathJax) and Calibre turns it into a PDF with the document's paper, margins, `fontsize:` and
247
+ language, page numbers, and bookmarks from the headings. LaTeX in the document is made native
248
+ or drawn as a picture, as for a Word file. Calibre is not in the numbered chain: it comes first when you
249
+ name it (`-e calibre`, or `pdf-engine: calibre` in `pdfmd-options:`), and (v3.29.1) it and the browsers
250
+ (`-e edge`, `chrome`, `chromium`, `brave`: Pandoc's HTML page, printed headless) are tried last when no engine is named
251
+ and LaTeX, Typst and the HTML engines have all failed, ahead of LibreOffice; `--doctor` lists them as last resorts.
252
+ A comma list of your own never adds them (`-e pandoc` is every engine Pandoc drives, not these).
253
+
254
+ With no Pandoc at all, Calibre reads the Markdown itself (v3.29): its own Markdown reader (tables, footnotes, fenced code, lists)
255
+ prints it, before the rough built-in renderers, with the document's paper and margins. It has no math (formulas are text) and
256
+ none of Pandoc's syntax, and says so (`NOTE`, `WARN`). `-e calibre` or `-e native` without Pandoc picks it; with Pandoc,
257
+ `-e calibre` is the HTML route above.
258
+
259
+ `pdfmd --install calibre` (v3.29) gets Calibre when it is missing (190 to 360 MB). In a terminal on a Mac or Windows it offers
260
+ `brew install --cask calibre` or `winget install --id calibre.calibre -e` first. Otherwise (or on answering `d`) pdfmd downloads the
261
+ release file for your machine and checks it against the SHA-256 GitHub lists for it, and refuses a download whose checksum is not
262
+ listed: on macOS it opens the disk image read-only and copies `calibre.app` into `~/Applications`, on Linux (x86-64, ARM)
263
+ it unpacks the archive into pdfmd's data folder (no root, no desktop entries), and either way runs `ebook-convert --version`
264
+ to check. Windows: `winget`, or the installer from calibre-ebook.com. Calibre is a program pdfmd runs, never one it contains.
265
+
266
+ A browser prints a Markdown document too (v3.29): `-e edge`, `-e chrome`, `-e chromium` or `-e brave` (or `-e browser` for the
267
+ first one installed) has Pandoc write one self-contained HTML page and the browser, headless, print it with the document's
268
+ paper and margins (`papersize`, `geometry`, `margin`: as `@page`) and 12pt text. The math is MathML, which the browser draws
269
+ itself; LaTeX in the document is made native or drawn as a picture, as for a Word file. Like Calibre, a browser comes first when you
270
+ name it and last when you do not (see above); an `.html` file already goes to one first when it has scripts or MathML.
271
+
272
+ Calibre also writes ebooks (v3.29): `pdfmd book.md -o book.azw3` (or `--to azw3`) has Pandoc write an EPUB 3 (chapters,
273
+ contents, the metadata, the math as MathML) and Calibre turn it into the target, `book.azw3` beside the document. The
274
+ twelve targets only Calibre writes are `azw3`, `mobi`, `kepub`, `lit`, `lrf`, `pdb`, `rb`, `snb`, `tcr`, `pmlz`, `htmlz`
275
+ and `txtz`; each was converted back to text to check that its words, list and table are there. (Before v3.29 `-o
276
+ book.azw3` wrote a PDF under that name.) `epub`, `docx`, `rtf`, `txt` and `fb2` Pandoc writes itself, with more of its own
277
+ features (styles, tables, footnotes); they go through Calibre only when `-e calibre` is on the command line (a
278
+ `pdf-engine: calibre` is a PDF setting), with a NOTE. `-e calibre` with another target (`.tex`, `.html`, `.md`) stops and
279
+ lists what Calibre writes. One document at a time, not `-b` or `-r`.
280
+
281
+ The math of an ebook: a Kindle or a Kobo does not draw MathML, and a MOBI has no place for it. `azw3`, `mobi`, `kepub`, `lit`
282
+ and `lrf` (and `docx` through Calibre) get each formula drawn by LaTeX as a picture, in the document's own preamble and with
283
+ its `\ce` and siunitx, as a Word file's pictures are (needs a LaTeX engine and Poppler's `pdftocairo`); the plain formats
284
+ (`pdb`, `rb`, `snb`, `tcr`, `pmlz`, `txtz`, `rtf`, `txt`, `fb2`) get the formulas as text, the simple ones with their
285
+ superscripts and the rest as TeX, with one `WARN` that counts them, and so does a picture target on a machine with no LaTeX.
286
+ `epub` and `htmlz` keep the MathML. A `--mathml` or `--math-method` of your own is kept.
287
+
288
+ An ebook can be the input too (v3.29): `pdfmd book.epub` builds `book.pdf` beside it, `pdfmd book.mobi -o book.md` writes its
289
+ Markdown (with its pictures in `media/`) for you to edit, `pdfmd book.azw3 --to docx` a Word file. An EPUB is read by Pandoc;
290
+ `mobi`, `azw`, `azw3`, `azw4`, `kepub`, `lit`, `lrf`, `pdb`, `prc`, `chm`, `snb`, `tcr`, `rb`, `pmlz`, `htmlz` and `txtz` first go
291
+ through Calibre's `ebook-convert` into an EPUB (Calibre is needed for those, not for an EPUB). The closing line names the
292
+ book. One book at a time, not with other files, `-b` or `-r`; a book with DRM, and an ebook of nothing but pictures (a comic),
293
+ cannot be read. A formula a MOBI holds as a picture stays a picture. Calibre's own scaffolding in the converted book (an
294
+ anchor for every file it split the book into, its page-break divs and classes) is dropped from the Markdown; with
295
+ `-o book.md` the pictures are copied to a `media/` folder beside it.
296
+
297
+ LibreOffice writes what Pandoc cannot too (v3.29): `pdfmd letter.md -o letter.doc` (Word 97) has Pandoc write the Word file (the
298
+ same one `-o letter.docx` writes: your reference document, native equations and tables, pictures for what LaTeX alone can draw)
299
+ and headless LibreOffice turn it into `.doc`. `rtf`, `odt`, `txt` and `epub` go through LibreOffice only with `-e soffice` (or
300
+ `-e libreoffice`, `-e office`) first on the command line, with a NOTE; without it Pandoc writes them from the document itself,
301
+ which is the better file. `-e soffice` with another target (`.tex`, `.md`) lists what it writes.
302
+
219
303
  For everything at once, `pdfmd --doctor` is one page on the Markdown-to-PDF tools, fonts
220
304
  and emoji, PDF reading (batchocr, Tesseract, Poppler, OCR languages), your config file and
221
305
  the cache, ending with the command that fixes each missing piece:
@@ -246,6 +330,8 @@ MISS xelatex: could not build it (! LaTeX Error: File `stix2.sty' not found.)
246
330
  OK typst: built a PDF in 1.1 s
247
331
  ```
248
332
 
333
+ The last resorts are tried too (v3.29): an installed browser (`edge: built a PDF in 6.1 s`) and Calibre, which also writes a small
334
+ ebook (`calibre:azw3: built an AZW3 ebook in 18.0 s`), so a missing Qt library shows here and not in the middle of a book.
249
335
  It takes a few seconds per engine (a minute or more if TeX has to fetch packages); without `--deep` nothing is built.
250
336
 
251
337
  ### Tab completion
@@ -263,7 +349,7 @@ pdfmd --completion fish > ~/.config/fish/completions/pdfmd.fish
263
349
 
264
350
  The oldest Pandoc `pdfmd` is tested with is **3.1.3** (what the claude.ai sandbox has); the whole test suite runs against
265
351
  it. An older one may work, and the first build with it says so once; `pdfmd --doctor` lists what a given Pandoc does
266
- without. With 3.1.3: Typst PDFs cannot show a picture `pdfmd` drew itself (before 3.2), a numbered equation in a Word file
352
+ without. With 3.1.3: a numbered equation in a Word file
267
353
  sits in a plain table instead of a borderless one (before 3.4), and `--extract-tables` leaves a table whose caption has
268
354
  a `{#tbl:id}` (before 3.8.2: Pandoc reads that as words, so the change could not be checked). A `pandoc-crossref` must be
269
355
  the release built for the Pandoc you run; one built for another is not run, with a warning, because it would put `??` where
@@ -291,7 +377,7 @@ $ pdfmd notes.md
291
377
  NOTE Pandoc was not found: building with the built-in renderer (inkmd). The output is plain ...
292
378
  NATIVE notes.md via inkmd
293
379
  WARN native (inkmd): notes.md: 2 math expression(s) set as plain text (Unicode, sub/superscripts, display math centred); ...
294
- OK notes.md
380
+ OK notes.md > notes.pdf
295
381
  ```
296
382
 
297
383
  - **[inkmd](https://github.com/eagredev/inkmd)**, written by Dylan Moir (MIT
@@ -314,6 +400,13 @@ OK notes.md
314
400
  where the built-in renderer and every engine that can draw colour emoji
315
401
  (Typst) find it; without it emoji print as `[rocket]`-style labels in the
316
402
  built-in renderer.
403
+ - `pdfmd --install math:mathjax` (MathJax 4 and its STIX Two math font, about 12 MB to download, about 2 MB on
404
+ disk) and `pdfmd --install math:katex` (KaTeX, about 1.5 MB) are for WeasyPrint's PDFs, not the built-in
405
+ renderer: they typeset its math (see "WeasyPrint does not typeset math itself" below).
406
+ - `pdfmd --install core:tex` (also `cortex`, about 50 MB) is the other core: **Pandoc and Tectonic**, the self-contained
407
+ LaTeX engine (its release from GitHub, checked against the SHA-256 GitHub lists, into pdfmd's own tools folder). Tectonic
408
+ fetches the TeX files a document needs from the network the first time, then works from its cache. `core:typst`
409
+ (or `core`) is `--install full` below. `pan-tec` (see "Other command names") runs pdfmd on it.
317
410
  - `pdfmd --install full` leaves the fallback behind: it installs **Pandoc** (the
318
411
  real binary from PyPI's `pypandoc_binary`, about 35 MB, also `--install pandoc`
319
412
  / `pdfmd-cli[pandoc]`) and **Typst** (Typst's own release from GitHub, about
@@ -324,7 +417,8 @@ OK notes.md
324
417
 
325
418
  Every input is treated as GitHub-flavoured Markdown. Pandoc-only syntax is
326
419
  converted where possible (`\newpage` and `<!-- pagebreak -->` become a page
327
- break, footnotes become endnotes for inkmd, `$` prices are not mistaken for math)
420
+ break, as they do through Pandoc with `pagebreak:`, see *Page breaks in every
421
+ format*; footnotes become endnotes for inkmd, `$` prices are not mistaken for math)
328
422
  and removed otherwise (heading and image attributes, `:::` divs, raw LaTeX,
329
423
  `<!-- comments -->`), with one warning per kind. CSV tables
330
424
  (`::: {.csv file="data.csv"}`) work as they do with Pandoc. The title, author and date in the
@@ -429,6 +523,28 @@ Ctrl-G go to a line, Ctrl-K / Ctrl-U cut and paste a line, Ctrl-Z / Ctrl-Y undo
429
523
  when there are unsaved changes); F1 lists them. Options given beside it (`pdfmd --edit lecture -e lualatex`) are used
430
524
  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.
431
525
 
526
+ **Edit a PDF in place.** A PDF that carries its source (`--attach-source`; `pdfmd --check-source` says which do) can be
527
+ edited and rebuilt where it lies:
528
+
529
+ ```sh
530
+ pdfmd --edit report.pdf # the built-in editor, on the source as one file in a temporary folder
531
+ pdfmd --edit report.pdf --editor "code --wait" # your own: the folder is watched and rebuilt on every save
532
+ ```
533
+
534
+ A document is edited as the ONE file its source is: the text with its metadata, preamble, bibliography and style, and the `.tex`
535
+ and CSV files it reads, as blocks after the text (`<!-- pdfmd-at: ... -->` comments say on which line each one is); only what
536
+ is not text (your package, pictures, files in sibling folders) is beside it. You edit that file; Ctrl-B (or each save with
537
+ `--editor`) builds it, and when you leave, `report.pdf` is replaced by the rebuilt one, which carries the source again, and
538
+ the old one is kept in `.backups/` beside it. Before it is replaced pdfmd checks that the rebuilt PDF still carries its source
539
+ and everything the old one carried; a PDF without its source is refused (yours stays as it was), and what is missing is named.
540
+ The temporary folder is removed when you leave. For the files it was made from, `pdfmd --restore report.pdf` (or `--unpack`). Nothing
541
+ changes when you leave without editing, or when the last version does not build. The options of the first build are the
542
+ ones the document and its metadata record; the command-line ones are the ones you give now, and the global metadata of
543
+ `pdfmd --setup` is this machine's (a rebuild on another one can differ). A book built with `-r` is edited as a book: your editor gets every
544
+ chapter file and each save rebuilds all of them in the order the book was built (the built-in editor opens the first chapter and names the
545
+ others). `--editor CMD` also works on a Markdown file
546
+ (a watch that rebuilds on every save, until the editor closes), and `pdfmd --setup` keeps a default editor.
547
+
432
548
  ### In VS Code
433
549
 
434
550
  `pdfmd --init-vscode` writes a `.vscode/tasks.json` here (build, build and open, watch, check, extract tables; Terminal > Run
@@ -660,6 +776,13 @@ office:
660
776
  reference-doc: house.dotx
661
777
  ```
662
778
 
779
+ The same file can list `lua:` (Lua filters beside the document besides `<package>.lua`, which a document that loads the
780
+ package gets by name anyway), `draft-skip:` (`commands:` that take one argument and `spans:` of a start macro up to its stop
781
+ macro, which the label scan's draft pass need not draw, as it skips `chemfig`) and `picture-cache:` (the macro names and the
782
+ request-file suffix a package used for the picture cache before the protocol had neutral names, see "For a package author").
783
+ pdfmd names no package: all of this is found by reading the packages a document loads, in its preamble files or its
784
+ `header-includes:`.
785
+
663
786
  ```yaml
664
787
  pdfmd-options:
665
788
  office:
@@ -674,14 +797,20 @@ pdfmd-options:
674
797
  **LaTeX in the document.** Pandoc turns `$x^2$` into a Word equation and drops everything else of
675
798
  LaTeX. For `.docx` and `.odt` pdfmd adds a filter that makes it native where it can:
676
799
 
677
- - `\ce{Ag+(aq) + Cl-(aq) -> AgCl(s)}` (mhchem) and `\si{\gram\per\mole}`, `\SI{5}{\milli\liter}`,
800
+ - `\ce{Ag+(aq) + Cl-(aq) -> AgCl(s)}` (mhchem) and `\si{\gram\per\mole}`, `\qty{5}{\mL}`,
678
801
  `\num{1.5e-3}` (siunitx) become formatted text with real subscripts, charges and units, and, inside
679
- math, Word equation pieces;
802
+ math, Word equation pieces. `\ce` is read by a port of mhchem's own parser, so it comes out as LaTeX sets it;
803
+ siunitx follows your `\sisetup`, `\DeclareSIUnit`s and unit shortcuts, those of your own packages too. A
804
+ formula with words over its arrow is an equation;
805
+ the same in an HTML, EPUB, Markdown, text or Typst file and a PowerPoint deck, whose writers would drop them;
680
806
  - `\begin{equation}`, `align`, `reaction`... become Word equations with their number at the right;
681
807
  - raw `figure`, `tabular`, lists, `\emph`, `\newpage`... are read by Pandoc's own LaTeX reader;
682
808
  - `\ref`, `\eqref`, `\cref`, `\Cref`, `\pageref` and the "Figure 3." in front of a caption use the numbers
683
809
  LaTeX itself gave (pdfmd builds the PDF once, in its cache, and reads the `.aux`; reused while the sources
684
- are older), with the caption separator (`labelsep=`) and `\crefname`s of your preamble;
810
+ are older), with the caption separator (`labelsep=`) and `\crefname`s of your preamble. Each reference is a link
811
+ to what it names. A `\label` in a caption, in a block drawn as a picture or on any line of an equation becomes a
812
+ bookmark there. In OpenDocument a labelled table, figure or div, and a citation's entry in the references, get one
813
+ too, since its writer bookmarks none of them;
685
814
  - **what is left is drawn by LaTeX**: tikz, chemfig, a house style's own macros, math Pandoc cannot convert are compiled in
686
815
  *your document's own preamble* (the same fonts, packages and macros as the PDF, one fragment to a page), and the
687
816
  pages go into the Word file as vector pictures: an SVG with a 300 dpi PNG fallback (Word 2016 and later draw the SVG,
@@ -710,9 +839,10 @@ quick way to see what is left to give a recipe (see the profile below).
710
839
  (Pandoc's own behaviour). `office: {labels: off}` skips the PDF build (numbers are then counted).
711
840
 
712
841
  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
713
- keeps the page size, margins and fonts, shows equations and draws what LaTeX can; a **Typst or WeasyPrint run after LaTeX
714
- failed** gets what the document says in LaTeX as native text or pictures instead of nothing; and HTML, Typst and
715
- WeasyPrint builds do it on request (`pdfmd-options: {office: {latex: auto}}`).
842
+ keeps the page size, margins and fonts, shows equations and draws what LaTeX can. A **Typst or WeasyPrint PDF** (named
843
+ with `-e`, or after LaTeX failed) gets what the document says in LaTeX as native text or pictures instead of nothing,
844
+ whenever it has LaTeX they would drop; `raw: {typst: [typst]}` (or `office: {latex: off}`) keeps Pandoc's own behaviour.
845
+ HTML and Typst *files* (`-o x.html`, `--to typst`) do it on request (`pdfmd-options: {office: {latex: auto}}`).
716
846
 
717
847
  ### Stopping part-way
718
848
 
@@ -735,6 +865,7 @@ them beside it. What the text points at otherwise (images, files a preamble
735
865
  the assembled file.
736
866
 
737
867
  ```sh
868
+ pdfmd report --merge # everything: one file that builds alone, anywhere
738
869
  pdfmd report --assemble-only --embed-metadata # metadata.yaml, preamble.tex, Lua filters, .bib/.csl
739
870
  pdfmd report --assemble-only --embed-metadata metadata preamble # only those
740
871
  pdfmd report --assemble-only --embed-metadata --lua-mode ref # name the filter instead of copying it
@@ -790,22 +921,36 @@ file you can edit again. Ask for it, on the command line or in the document:
790
921
 
791
922
  ```sh
792
923
  pdfmd report --attach-source # the source goes into report.pdf as an attachment
793
- pdfmd report --bundle # ... and the data and files its LaTeX reads
924
+ pdfmd report --bundle # ... and the image files too (the data and LaTeX inputs are carried anyway)
794
925
  pdfmd --restore report.pdf # write the folder back into report.restored/
926
+ pdfmd --check-source # which PDFs in this folder carry their source (a file or folder works too)
795
927
  ```
796
928
 
929
+ ```console
930
+ $ pdfmd --check-source
931
+ NONE WA1.pdf no WA1.md beside it
932
+ SOURCE WA3.pdf WA3.md, 52 lines, pdfmd 3.28.22
933
+ NONE WA5.pdf WA5.md is beside it: pdfmd WA5.md --attach-source
934
+ CHECK 3 PDFs: 1 with the source, 2 without
935
+ ```
936
+
937
+ `--check-source` (alias `--sources`) only reads the attachment list, so it is quick on a whole folder; it notes a
938
+ Markdown file beside the PDF that is newer than the build, and exits 1 when a PDF has no source.
939
+
797
940
  ```yaml
798
941
  pdfmd-options:
799
942
  attach-source: true # alias: embed-source
800
- bundle: true # or `all`: the whole folder, not just what the text points at
943
+ bundle: sources # the default: the files the text reads, no images
944
+ # `true`: and the images · `all`: the whole folder · `false`: the source alone
801
945
  bundle-packages: true # also your own LaTeX packages (see below)
802
946
  strip-comments: true # the default for the attached copy; see "Comments"
803
947
  attach-bibliography: used # or `all`
948
+ attach-csl: false # the default: the citation style is named, not attached (see below)
804
949
  ```
805
950
 
806
951
  Put these in the shared metadata file and every document that finds it carries
807
952
  its source. The attachment is the assembled Markdown with the metadata,
808
- preamble, Lua filters, bibliography and CSL style folded in (the file
953
+ preamble, Lua filters and bibliography folded in, and the CSL style too when `attach-csl: true` (the file
809
954
  `--assemble-only --embed-metadata` writes), plus a manifest of the original
810
955
  layout, so `--restore` gives back `report.md`, `metadata/`, `parts/` and the rest
811
956
  where they were, each as a standalone file (a symlinked metadata file or
@@ -818,17 +963,41 @@ style, a compound library, a shared bibliography and parts.
818
963
  a plain attach needs no bundle for them: a JPEG comes back byte for byte, a PNG
819
964
  as the same pixels (alpha kept), and an SVG or PDF figure as a vector PDF
820
965
  (`fig.svg` becomes `fig.pdf`, and the restored Markdown follows).
821
- - **`--bundle` is for what the PDF does not draw:** CSV data, LaTeX included
822
- with `\input`, listings. They are stored as separate attachments (`files/...`),
823
- found from the text, the preamble and, in turn, from the files found; also
824
- those only your own TeX tree resolves (`\input{library}` from `texmf-home`).
825
- `--bundle all` takes the whole folder except output and housekeeping. Over
826
- 100 MB (`bundle-max-mb`) only the source is attached. Data whose file name a
827
- macro builds cannot be found: use `all`.
966
+ - **The files the text reads travel with it.** CSV data, LaTeX included with `\input`, listings: stored as
967
+ separate attachments (`files/...`), found from the text, the preamble and, in turn, from the files found;
968
+ also those only your own TeX tree resolves (`\input{library}` from `texmf-home`). A restored report builds
969
+ again; only images are left out (the PDF has them). Over 100 MB (`bundle-max-mb`) only the source is
970
+ attached. `bundle: false` (or `--no-bundle`) keeps the source alone; `--bundle` (`bundle: true`) stores the
971
+ image files too, `--bundle all` the whole folder except output and housekeeping. Data whose file name a
972
+ macro builds cannot be found: use `all`. A Markdown output (`--keep-source`) has no PDF to take pictures
973
+ from and keeps the source alone unless you ask.
974
+ - **`--restore` and `--unpack` stay short.** They count what they write by folder; `--verbose` lists every
975
+ file, and `--restore --list` always does.
828
976
  - **Your own LaTeX packages** (a house style in `texmf-home`) are recorded with
829
977
  their version, and `--restore` tells you what is missing; `--bundle-packages`
830
- stores them too (with what they `\input` and the graphics they name).
831
- The TeX distribution's own packages, fonts and Pandoc are not carried.
978
+ stores them too: the style file, the `<package>-pdfmd.yaml` beside it (what the package tells pdfmd: its
979
+ title-page keys, its picture-cache names), what it `\input`s and the graphics it hands to `\includegraphics`
980
+ (a logo named by `\newcommand{\LogoFile}{logo}`, not every word that happens to be a file's name). A package that sits
981
+ in the document's own folder, as it does in a restored source, is kept when the source is attached again. Together
982
+ with `attach-csl` a report that sets both in its shared metadata rebuilds on a machine with nothing of yours
983
+ installed (checked in an empty home folder). The TeX distribution's own packages, fonts and Pandoc are not carried.
984
+ - **The text files are in the source's text.** The `.tex` files a document reads and its CSV data are blocks of the
985
+ attached `pdfmd-source.md`, after the text (`.tex` first, then the data) and before the bibliography and style at the
986
+ very end, so one file holds everything you edit; the pictures and your package stay separate attachments (and a file
987
+ that is not text, or too big, or whose line ends are mixed). `<!-- pdfmd-at: ... -->` comments say on which line each block is (an index after the front matter and one
988
+ before each part of the text that names a file); pdfmd writes them whenever it writes the source and removes them
989
+ wherever it reads one, so they never reach a build and a restore gives back your text as it was.
990
+ - **Files in sibling folders** (`\input{../schemes/x.tex}`, a CSV in `../ir/`) are stored too, up to two folders above
991
+ the document's (never the home folder or above), as blocks of the text like the rest (their path starts with `..`),
992
+ and `--restore` puts the folder back in the same layout: the document in `<folder>/<its folder's name>/`, the siblings
993
+ beside it. A file with Windows line ends (CRLF all through) is a block with an `eol: crlf` line and comes back byte for
994
+ byte. `pdfmd --edit report.pdf` writes those files where the document reads them before every build, so editing a
995
+ block is editing the file; a build of the source file alone (no `--edit`) never writes outside its own folder and
996
+ says so when a file it reads from there is missing. A bibliography the metadata names by the real
997
+ folder of a symlinked metadata file (a shared `nulab.bib`) is embedded, pruned to the entries the text cites.
998
+ - **A newer source is refused, not half restored.** The manifest has a format number (2 since v3.28.45, when the chain of
999
+ folders, the text files as blocks and the `..` files came in). A pdfmd that reads up to 1 stops with `was made by a
1000
+ newer pdfmd (...); upgrade pdfmd to restore it`, and this one restores both 1 and 2.
832
1001
  - **Comments.** Notes to yourself do not travel: the attached source loses its
833
1002
  `<!-- -->` comments, the LaTeX preamble's `%` comments, the text between a
834
1003
  `.bib`'s entries, a CSL file's XML comments and the `#` comments of YAML
@@ -841,9 +1010,18 @@ style, a compound library, a shared bibliography and parts.
841
1010
  comments and quoting included; `--restore` of such a PDF is a full source
842
1011
  copy. The data files of `.csv` blocks (`tables/*.csv`) are always stored
843
1012
  with the source.
1013
+ - **Your global metadata (`pdfmd --setup`) stays yours.** It counts in the
1014
+ source below the document's own files, as in a build, but `--restore` does
1015
+ not write it back. It names its keys instead, and a build of the restored
1016
+ folder uses the global metadata of the machine it runs on.
844
1017
  - **Only the bibliography entries you cite** are attached (and what they
845
1018
  cross-reference), not a shared file of hundreds; `attach-bibliography: all`
846
1019
  keeps it whole, and `nocite: '@*'` keeps every entry.
1020
+ - **The citation style is not attached unless you ask** (`--attach-csl`, `attach-csl: true`, `--embed-metadata csl` for an
1021
+ assembled file). A style is 10-90 KB (apa.csl 86 KB, nu-labreport.csl 72 KB, ieee.csl 18 KB) and the global metadata sets
1022
+ one for every document, cited or not. A style is only ever attached when the document cites something. Without it the
1023
+ manifest records the name and `--restore` says that a build needs a style of that name (Pandoc's own `csl/` folder, or
1024
+ beside the document); a house style that exists nowhere else should travel, so set `attach-csl: true` for it.
847
1025
  - **It is opt-in, and it is everything you wrote.** An attached source includes
848
1026
  what the author would not send in an email; check `--list` before sharing.
849
1027
  - `--restore` never overwrites a file and never writes outside its folder. A
@@ -945,9 +1123,9 @@ stamped or backed up unless you ask (`stamp=True`, `backup=True`). A failure rai
945
1123
  `variables=` a dict of Pandoc variables, `extra_args=` anything else the command line takes, `cwd=` the folder it runs
946
1124
  in and `timeout=` seconds.
947
1125
 
948
- ### Other command names: `mdpdf` and `inkmd`
1126
+ ### Other command names: `mdpdf`, `inkmd`, `batchmd` and `pan-tec`
949
1127
 
950
- pdfmd also installs `mdpdf` and `inkmd` commands that take those tools' own keys
1128
+ pdfmd also installs `mdpdf`, `inkmd`, `batchmd` and `pan-tec` commands that take those tools' own keys
951
1129
  and do what they did, with pdfmd behind them:
952
1130
 
953
1131
  ```sh
@@ -955,8 +1133,18 @@ mdpdf -o out.pdf -f ",,{page}" -a "Name" -p A4 chapter1.md chapter2.md
955
1133
  inkmd notes.md -o notes.pdf --page-size a4 --family times
956
1134
  cat notes.md | inkmd > notes.pdf # standard input and output, like inkmd
957
1135
  inkmd notes.md -e lualatex # naming another engine uses it instead
1136
+ batchmd ~/notes # every .md in the folder, as pdfmd -b ~/notes
1137
+ batchmd -e inkmd # the current folder, with the built-in renderer
958
1138
  ```
959
1139
 
1140
+ `pan-tec` is the first version of pdfmd, a shell function around `pandoc "$@" --pdf-engine=tectonic --pdf-engine-opt=--chatter=minimal`
1141
+ (v3.29): `pan-tec test.md -o ex.pdf` is `pdfmd -e tectonic test.md -o ex.pdf --pdf-engine-opt=--chatter=minimal`, with everything else
1142
+ pdfmd does. Name another engine (`-e typst`) or a chatter level of your own and that is used instead.
1143
+
1144
+ `batchmd` is `pdfmd -b`: each Markdown file in the folder becomes its own PDF beside it.
1145
+ It takes the current folder when you name none (`pdfmd -b` alone refuses), and every
1146
+ other option is pdfmd's.
1147
+
960
1148
  `mdpdf` turns bookmarks and attached links on and combines several inputs into one
961
1149
  PDF. `inkmd` is `pdfmd -e inkmd`; like inkmd it writes the PDF to standard output
962
1150
  when you give `-o -`, or no `-o` while output is piped (at a terminal it writes
@@ -979,16 +1167,17 @@ pdfmd slides -p # Beamer slides; each heading starts a slide
979
1167
 
980
1168
  ```console
981
1169
  $ pdfmd notes -b
982
- AUTO: READER TITLE MARGIN MONOFONT. Use --verbose to see in full
983
- AUTO: MARGIN. Use --verbose to see in full
984
- AUTO: MARGIN. Use --verbose to see in full
985
- OK notes/lecture.md
986
- OK notes/week1.md
987
- OK notes/week2.md
1170
+ DEFAULTS margin 1in, font STIX Two Text, code in JetBrains Mono, title from heading
1171
+ AUTO: READER. Use --verbose to see in full
1172
+ OK notes/lecture.md > lecture.pdf
1173
+ OK notes/week1.md > week1.pdf
1174
+ OK notes/week2.md > week2.pdf
988
1175
  ```
989
1176
 
990
1177
  `-b` converts every `.md` in the folder into its own PDF, in parallel
991
- (`-j N` sets the number of workers). Add `--recursive` to include
1178
+ (`-j N` sets the number of workers). `--bopen SPEC` opens some of the finished files when
1179
+ the batch is done: `f5` the first five, `l5` the last five, `fl10` the first five and the last five, `e3` the third, sixth, ninth ... file, `s3` the first, fourth, seventh ... (Python's `[::3]`),
1180
+ `f2,l3` a mix, or none for all (any number works; the files open in the order the batch lists them). Add `--recursive` to include
992
1181
  subfolders, and `-o DIR` to collect the PDFs somewhere else.
993
1182
 
994
1183
  ### A book or report from several files
@@ -997,7 +1186,7 @@ subfolders, and `-o DIR` to collect the PDFs somewhere else.
997
1186
  $ pdfmd book -r -o book.pdf
998
1187
  OK book/01-intro.md
999
1188
  OK book/02-methods.md
1000
- AUTO: MARGIN. Use --verbose to see in full
1189
+ DEFAULTS margin 1in, font STIX Two Text
1001
1190
  OK REPORT book.pdf
1002
1191
  ```
1003
1192
 
@@ -1053,11 +1242,16 @@ section, figure, table or equation outside the part then prints its number
1053
1242
  own sections, figures and equations continue from the parts before it. What the
1054
1243
  scan cannot count is whatever the document defines itself (a macro that opens
1055
1244
  a figure, say): that label stays `??`, and the build says the numbers are
1056
- approximate. `\pageref` is always `??`. The last full build's `.aux` (cache on,
1245
+ approximate. So does a label after a caption in an environment the document
1246
+ defines itself (a table wrapper of a house style): it prints `??`, never the
1247
+ number of the heading before it, and the build says how many there were.
1248
+ `\pageref` is always `??`. The last full build's `.aux` (cache on,
1057
1249
  below) is exact and is used first; the scan fills in what it does not know.
1058
1250
  `pdfmd-options: {seed-labels: auto|aux|scan|draft|off}` or `--seed-labels` picks
1059
- the source (`draft` runs LaTeX once over the whole document without output, for
1060
- exact numbers at about half a compile's cost); `off` brings back the `??`. A section of an ordinary document
1251
+ the source (`draft` runs LaTeX once over the whole document without output and
1252
+ without drawing its pictures, TikZ, pgfplots, chemfig and images, for exact
1253
+ numbers at a fraction of a compile, though a page reference into what was left out
1254
+ prints `??`; `--no-auto draftpictures` draws them); `off` brings back the `??`. A section of an ordinary document
1061
1255
  (`doc#results`) gets the same for the references it makes, but keeps numbering
1062
1256
  its own headings from 1.
1063
1257
 
@@ -1084,11 +1278,27 @@ from the last full build; without the cache they are counted from the
1084
1278
  sources, above). It never skips a build: Pandoc and
1085
1279
  LaTeX still process the whole document from the current sources and package
1086
1280
  every time, so a change shows in the next build. `cache: {plots: true}` (or
1087
- `--cache-plots`, with nulabreport >= 1.26.0) additionally stores each plot as a
1088
- PDF and reuses it until the package, the preamble, the engine or the plot's
1089
- data file changes. Off by default; `--no-cache` for one build; `pdfmd --clear-cache`
1281
+ `--cache-plots`; LuaLaTeX) additionally stores each whole picture of a package that takes part
1282
+ (nulabreport's plots and chemical schemes do) as a
1283
+ PDF in the document's cache folder and reuses it (a part built alone uses the whole
1284
+ document's, unless its preamble differs by more than the title) until the package,
1285
+ the preamble, the engine, TeX Live's packages (a `tlmgr update`) or a file the plot
1286
+ read changes (its data file, a file of the package's own: checked by
1287
+ SHA-1 of the contents before every build). Off by default; `--no-cache` for one build; `pdfmd --clear-cache`
1090
1288
  (or deleting the folder) is always safe.
1091
1289
 
1290
+ *For a package author:* the protocol names no package. A style file that mentions `pdfmdCacheDir` takes part; pdfmd then
1291
+ defines `\pdfmdCacheDir` (the folder, with a trailing slash) and `\pdfmdCacheVersion` (3: the markers below are version 3) before the document. The package looks
1292
+ a picture up by its own key as `<folder>/<key>.pdf` with its size in `<key>.dim` (`\pdfmdCacheWd`, `Ht`, `Dp`), typesets
1293
+ inline on a miss, and appends `<key>@@|@@<macro>@@|@@<arguments>@@|@@<context>` to `<job>.pdfmdreq`. After the build pdfmd
1294
+ runs each request in a standalone job with the same preamble (`\pdfmdCacheRender` defined, so there is no lookup): the
1295
+ context, then `\setbox0\hbox{<macro><arguments>}`; that box is the page. A context may hold `@@plain@@` (what follows is read
1296
+ with ordinary catcodes, not expl3's: settings with spaces in their names), `@@runs=2@@` (typeset twice, for a picture
1297
+ whose arrows point at its own nodes) and `@@margin=56pt@@` (the page is the box plus that on every side, `\pdfmdCacheMargin` in
1298
+ the `.dim`: for ink that overflows its box, which you include shifted back). If the job defines `\pdfmdCachePost` after the
1299
+ box, its text comes back as `\pdfmdCachePostStored` in the `.dim`, for you to run on a hit (a global the picture changes). nulabreport's first names (`\LabPlotCacheDir`, `.plotreq`, `\Lab@pc@wd`) still work as
1300
+ aliases.
1301
+
1092
1302
  **Where the cache lives.** By default in `~/.cache/pdfmd`, one folder per document.
1093
1303
  Folders get moved (a lab report from Downloads into OneDrive), and a cache keyed by
1094
1304
  the old path would be lost: so each cache folder records which document it is, and a
@@ -1141,16 +1351,25 @@ Water,18.015,1.20
1141
1351
  braces, with the identifier as `#tbl:id` there too. A caption in the attributes wins over a line after the block.
1142
1352
  - A relative `file=` is found beside the document (and along the resource path), wherever Pandoc runs. With both
1143
1353
  `file=` and data inside the block, the file is used.
1144
- - The delimiter is `delimiter=";"` or its name (`semicolon`, `tab`, `pipe`, `space`, `colon`, `comma`); without one it
1145
- comes from the extension (`.tsv` means tab) or from the first line (whichever of `,` `;` tab `|` it holds most of).
1354
+ - The delimiter is `delimiter=";"` or its name (`semicolon`, `tab`, `pipe`, `space`, `colon`, `comma`), or
1355
+ `pdfmd-options: {csv: {delimiter: semicolon}}` for every table; without one it is guessed: whichever of `,` `;` tab `|`
1356
+ splits the first lines into the same number of fields (the extension's own, comma or tab for `.tsv`, on a tie). When
1357
+ the guess is not what the file's name says (a `;` file named `.csv`), the build warns and says how to name it.
1146
1358
  - Columns are aligned with `align="lcr"` (or `align="left,center,right"`), or by a second row in the data made of
1147
1359
  `---`, `:--`, `:-:`, `--:` as in a pipe table; `align=` wins. If such a row is really data, say `separator="none"`.
1148
1360
  `widths="5,1,1"` sets relative widths, and a second row with unequal dashes does too. Without either, pdfmd picks
1149
1361
  widths that suit the contents.
1150
1362
  - The first row is the header unless you add `header="false"`.
1151
1363
  - Large files are capped at 10 rows × 7 columns, so a huge CSV can't
1152
- silently fill 40 pages. `rows=all` or `cols=20` raise the cap. When a
1153
- table is cut, the PDF itself shows a note saying so.
1364
+ silently fill 40 pages. A cut table keeps both ends: the first 7 rows, a row
1365
+ of `…`, the last 3, and the first 5 columns, a `…` column, the last 2 (about
1366
+ any cap keeps its last ⌊√cap⌋: 16 + 4 of 20, 25 + 5 of 30; `cut="head"` or `csv: {cut: head}` keeps the first
1367
+ ones only). `rows=all` or `cols=20` raise the cap. When a table is cut, the
1368
+ build warns and the PDF itself shows a note saying so. For every table of a
1369
+ document: `--csv-rows N|all` / `--csv-cols N|all`, or
1370
+ `pdfmd-options: {csv: {rows: all, cols: 12, cut: ends, delimiter: auto, header: false, reader: gfm}}`
1371
+ (in the front matter, a metadata file, or the config, where `pdfmd --setup`
1372
+ sets rows, columns, the cut and the delimiter); a div's own attributes still win.
1154
1373
 
1155
1374
  This works for every output format.
1156
1375
 
@@ -1183,6 +1402,38 @@ line above it (or under its caption); the comment survives comment stripping, be
1183
1402
  A comment between a table and its caption would stop Pandoc from reading the caption as one, so there is no such
1184
1403
  position.
1185
1404
 
1405
+ ### One style sheet for the page: `--css`, `pdfmd.css`, `css-scope`
1406
+
1407
+ A `.css` file styles the writers that read CSS: HTML, EPUB, the PDF the HTML engines make (WeasyPrint and the rest) and
1408
+ Calibre. pdfmd finds `pdfmd.css` or `<name>.css` beside the document (and in its `metadata/` folder; `--no-auto css` turns the
1409
+ search off), takes `css:` from the front matter or a metadata file (Pandoc's own key), `pdfmd-options: {css: file.css}`
1410
+ (a name or a list; `pdfmd --setup` keeps one for every document) and `--css FILE`; they come in that order, the last after the
1411
+ others, as in CSS.
1412
+
1413
+ ```css
1414
+ @page { size: A4; margin: 2cm 2.5cm } /* paper and margins */
1415
+ body { font-family: "STIX Two Text"; font-size: 11pt; line-height: 1.3; text-indent: 1.2em }
1416
+ a { color: #0645AD } /* links */
1417
+ code, pre { font-family: "JetBrains Mono" }
1418
+ ```
1419
+
1420
+ With `css-scope: all` (`pdfmd-options`, or `--css-scope all`; the default is `html`) the sheet is read for the other writers
1421
+ too: those four rules become the paper, margins, font, size, line spacing, indent, link colour and code font that LaTeX,
1422
+ Typst and Word take, **below** what the document, its metadata and the command line set (`--verbose` says
1423
+ "body font-size 11pt -> fontsize=11pt" for each one it used, and names what it did not: tables, anything else).
1424
+ Only rules that say it plainly count: `@page`, `html`/`body`/`:root`, `a`, `code`/`pre`, `h1`-`h5`; the last one wins. A media
1425
+ query is read as a browser prints (v3.29): `print` and `all` apply, `screen` and the other media types do not, a comma is "or",
1426
+ `only` and `not` count, `(orientation: landscape)` is read against the sheet's own `@page` size, and a feature of the screen or of
1427
+ a width (`(min-width: 600px)`) is not for a printed page and is named. A body size LaTeX has no class for (anything but 10, 11
1428
+ and 12 pt) is named, not used. It is a small reader on purpose: a CSS cascade has no counterpart in LaTeX.
1429
+
1430
+ Headings (v3.29): `h1`-`h5` with a `color`, `font-size` (`em`, `%`, `pt`, `px`: of the body's size), `font-family`,
1431
+ `font-weight` or `font-style` are set for LaTeX too, as titlesec's starred formats (the numbering and the spacing stay the
1432
+ class's; `h1` is `\section`, `h2` `\subsection` ... `h5` `\subparagraph`; `h6` has no LaTeX level). It is done only for the plain
1433
+ article class, and never over a document that formats its headings itself: a `titlesec`, `sectsty`, KOMA or memoir command, or a
1434
+ `\section` of its own, in the preamble, the `header-includes` or a metadata file, is named in a `CSS` note and nothing is added
1435
+ (and when `titlesec` is not installed, one LaTeX warning says so). A family needs XeLaTeX or LuaLaTeX.
1436
+
1186
1437
  ### Code: wrapping and line numbers
1187
1438
 
1188
1439
  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
@@ -1238,7 +1489,12 @@ Drawings are kept in the cache by their content, so a rebuild does not draw them
1238
1489
  (`{#fig:id}` with pandoc-crossref numbers it), `width=` sizes it, `engine=` picks the Graphviz layout (`dot`, `neato`,
1239
1490
  `fdp`, `sfdp`, `circo`, `twopi`), `theme=` the Mermaid theme, `layout=` the D2 layout (`dagre`, `elk`). A tool that is
1240
1491
  not installed leaves the block as code with one warning (`--strict` makes it an error) and says how to install it;
1241
- a diagram the tool cannot parse stays as code too. `pdfmd --doctor` shows which tools are there, and
1492
+ a diagram the tool cannot parse stays as code too, and the warning gives the tool's own words. `pdfmd --install diagram:d2`
1493
+ puts D2's release binary (17 MB, checked against the SHA-256 GitHub lists) in pdfmd's tools folder, and `--install
1494
+ diagram:dot` Graphviz built to WebAssembly (2 MB, run by node, which pdfmd fetches when there is none): it writes only SVG,
1495
+ which pdfmd converts for a PDF or Word picture with `rsvg-convert` or `inkscape` (D2 needs the same), and it sizes labels
1496
+ by Graphviz's own estimate of the font, a couple of percent off the real tool's. A tool of your own on PATH is always the one
1497
+ that runs. `pdfmd --doctor` shows which tools are there, and
1242
1498
  `--no-auto diagrams` turns the whole thing off. The attributes need Pandoc's Markdown (a file with front matter); a file
1243
1499
  read as gfm takes the plain ```` ```dot ```` form. Mermaid needs Chrome (mermaid-cli downloads one); in a sandbox
1244
1500
  `PDFMD_MMDC_CONFIG=puppeteer.json` is handed to `mmdc -p`.
@@ -1294,6 +1550,30 @@ in HTML, Typst and flat Markdown builds (an SVG for HTML and Markdown; a piece t
1294
1550
  out). Not yet: HTML drawn as a picture, Word XML as
1295
1551
  anything but Word XML.
1296
1552
 
1553
+ **Page breaks in every format.** Each output understands one way of writing a page break and drops the others: LaTeX
1554
+ takes `\newpage`, WeasyPrint a CSS-break `<div>`, Word only its own XML, Typst none of them. Ask for it and every
1555
+ spelling of the families you name becomes the output's own (LaTeX `\newpage`, Typst `#pagebreak`, a CSS break for HTML,
1556
+ EPUB and WeasyPrint, a Word or OpenDocument page break, a form feed in `--to txt`, `<!-- pagebreak -->` in `--to gfm`):
1557
+
1558
+ ```yaml
1559
+ pdfmd-options:
1560
+ pagebreak: true # every family; or a list of them:
1561
+ # pagebreak: [comment, tex]
1562
+ ```
1563
+
1564
+ | family | spellings |
1565
+ |---|---|
1566
+ | `comment` | `<!-- pagebreak -->`, `<!-- page-break -->`, `<!-- newpage -->`, `<!-- new-page -->`, `<!-- pdfmd: pagebreak -->` |
1567
+ | `tex` | `\newpage`, `\pagebreak`, `\pagebreak[3]`, `\clearpage`, `\cleardoublepage` (an odd page) |
1568
+ | `html` | `<div style="page-break-after: always"></div>` (or `break-before: page`), `<div class="pagebreak"></div>`, `<hr class="pagebreak">` |
1569
+ | `div` | an empty `::: pagebreak` (or `newpage`) |
1570
+ | `typst` | a raw `` ```{=typst} `` `#pagebreak()` |
1571
+ | `word` | a raw `` ```{=openxml} `` page-break paragraph |
1572
+
1573
+ It is off unless asked (the document, a metadata file, or `pdfmd --setup` under *Universal markup*); `--pagebreak
1574
+ [KIND ...]` and `--no-pagebreak` decide for one run. A spelling already in the output's own language stays as written,
1575
+ and slides leave a break out with a note. The built-in renderer (no Pandoc) reads the comment and TeX spellings anyway.
1576
+
1297
1577
  **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
1298
1578
  EPUB, a PDF through WeasyPrint) every image that is a PDF, `![fig](plot.pdf)` or `<img src="plot.pdf">`, is converted to
1299
1579
  an SVG with poppler's `pdftocairo` (or `mutool`, `pdf2svg`, `inkscape`) and stays vector; the first page is used and the
@@ -1308,16 +1588,16 @@ pdfmd paper.tex # compiled directly with a LaTeX engine: reruns until
1308
1588
  # no .aux/.log clutter (--keep-aux keeps them)
1309
1589
  pdfmd minutes.docx # Word/PowerPoint/Excel/ODF: converted by LibreOffice
1310
1590
  pdfmd analysis.qmd # handed to Quarto, so code chunks actually run
1311
- pdfmd page.html # built by WeasyPrint, or a browser if the page runs scripts: no Pandoc
1591
+ pdfmd page.html # built by WeasyPrint, or a browser if the page runs scripts or has MathML: no Pandoc
1312
1592
  pdfmd note.typ # compiled by Typst itself: the page setup in the file is kept
1313
1593
  pdfmd notes.rst # anything else Pandoc can read (give the extension)
1314
1594
  ```
1315
1595
 
1316
1596
  A finished `.typ` or `.html` file goes straight to its own engine, because Pandoc would read it into its own model
1317
1597
  and write it out again, and the page size, the styles and the scripts would not survive the trip. For a page that is
1318
- WeasyPrint first (it is quiet and needs no browser); a page with `<script>` goes to Chrome, Chromium, Edge or Brave
1319
- (headless, printing the page), as does one WeasyPrint cannot draw, and wkhtmltopdf, Prince, pagedjs-cli and LibreOffice
1320
- come after. `-e edge` (or `weasyprint`, `chromium`...) picks one. As with an Office file, such a document gets none of
1598
+ WeasyPrint first (it is quiet and needs no browser); a page with `<script>` or MathML (`<math>`, which WeasyPrint prints
1599
+ as flat text) goes to Chrome, Chromium, Edge or Brave (headless, printing the page), as does one WeasyPrint cannot draw,
1600
+ and wkhtmltopdf, Prince, pagedjs-cli and LibreOffice come after. `-e edge` (or `weasyprint`, `chromium`...) picks one. As with an Office file, such a document gets none of
1321
1601
  pdfmd's defaults, since it is finished; `--apply-defaults` (also in `pdfmd --setup`) gives it the title, author, date,
1322
1602
  language, font, font size, paper and margin of its `metadata.yaml`, ahead of its own settings so those win. A `.tex`
1323
1603
  file that no LaTeX engine can compile is tried through Pandoc, with a warning.
@@ -1345,6 +1625,7 @@ Most of these print an `AUTO` line, and each can be switched off individually.
1345
1625
  | `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 |
1346
1626
  | `MARGIN` | no margin or geometry set anywhere | 1-inch margins instead of LaTeX's wide defaults |
1347
1627
  | `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` |
1628
+ | `MATHFONT` | pdfmd chose the main font itself (no `-f`, no `mainfont:`/`mathfont:` in the document or its metadata), the engine is LuaLaTeX, XeLaTeX, Tectonic or Typst (Pandoc 3.12+), and the companion is installed | the math font that goes with the text font: STIX Two Math for STIX Two Text, DejaVu Math TeX Gyre for DejaVu Serif, Libertinus Math, New Computer Modern Math, TeX Gyre Termes/Pagella Math; without it formulas are set in Latin Modern Math (Typst: New Computer Modern Math). `--no-auto mathfont` (or `font`) stops it |
1348
1629
  | `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 |
1349
1630
  | `MONOFONT` | the document contains code | JetBrains Mono for code (Menlo or another installed monospace font if it isn't installed) |
1350
1631
  | `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 |
@@ -1353,8 +1634,11 @@ Most of these print an `AUTO` line, and each can be switched off individually.
1353
1634
  | `codewrap` | code blocks in a LaTeX build | long lines wrap at the margin (`--no-code-wrap` or `--no-auto codewrap` for the old behaviour) |
1354
1635
  | `YAML` / `TEX` / `LUA` | project files found | attaches `metadata.yaml`, `preamble.tex`, `<name>.lua` (see below) |
1355
1636
  | `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) |
1637
+ | `remotecsl` | `csl: https://.../ieee.csl` in the front matter or a metadata file | fetches the style once and keeps it (again after 30 days), so a Pandoc built without HTTP support and a build with no network still work: offline it takes that copy, else a style of the same name in Pandoc's own `csl/` folder, with a WARN, else Pandoc's default style with a WARN (`pdfmd-options: {csl-fallback: error}` stops instead) |
1356
1638
  | `crossref` | `@fig:`/`@tbl:` references or `{#fig:...}` labels | adds the `pandoc-crossref` filter, ahead of citeproc |
1357
1639
  | `papersize` | `pagesize: a4` (a common typo) | converts it to Pandoc's real `papersize:` |
1640
+ | `texpackages` | `\ce{H2O}` (mhchem) or `\SI{25}{\celsius}`, `\num`, `\qty` (siunitx) in a LaTeX build whose preamble does not load the package | loads it, last in the preamble, unless it is loaded already (your options win), the command is defined some other way, or the package is not installed |
1641
+ | `draftpictures` | a part (or section) built alone with `seed-labels: draft` | the draft pass over the whole document does not draw TikZ pictures (pgfplots too), `\chemfig`, chemfig schemes or images: they step no counter. A page reference into what was left out prints `??`; a picture that ends inside a macro makes pdfmd run the pass again with the pictures |
1358
1642
 
1359
1643
  `-v` explains each decision and prints the exact command it runs:
1360
1644
 
@@ -1366,7 +1650,7 @@ AUTO READER lecture.md: no YAML front matter; reading as gfm
1366
1650
  AUTO TITLE lecture.md: promoted leading '# ' heading to Pandoc title metadata
1367
1651
  AUTO MARGIN lecture.md: no geometry/margin set; using geometry:margin=1in on LaTeX-family engines
1368
1652
  AUTO MONOFONT lecture.md: has code but no monofont set; using JetBrains Mono on LaTeX-family engines
1369
- OK lecture.md (lualatex)
1653
+ OK lecture.md > lecture.pdf (lualatex)
1370
1654
  ```
1371
1655
 
1372
1656
  The second `CMD` line is the font fallback at work: STIX Two Text was
@@ -1383,12 +1667,32 @@ build that quietly fell back to Typst does not look like one that did not:
1383
1667
  $ pdfmd paper
1384
1668
  WARN paper.md: lualatex failed (! Undefined control sequence.); trying xelatex...
1385
1669
  WARN paper.md: xelatex failed (! Undefined control sequence.); trying typst...
1386
- OK paper.md (typst; lualatex, xelatex failed)
1670
+ OK paper.md > paper.pdf (typst; lualatex, xelatex failed)
1387
1671
  ```
1388
1672
 
1389
1673
  When LaTeX itself stops, the warning also says where: Pandoc reports a line of the LaTeX it wrote, so pdfmd finds those
1390
1674
  words in your Markdown and prints `near line 9 of paper.md: ...has \badmacro`.
1391
1675
 
1676
+ WeasyPrint does not typeset math itself. With MathJax in place, `pdfmd --install math:mathjax` (MathJax 4.1's TeX input
1677
+ and HTML output and the STIX Two math font, which goes with pdfmd's default body font: about 12 MB to download, about 2 MB
1678
+ on disk in `~/.local/share/pdfmd/mathjax`, each package pinned and checked against its SHA-256; and node, when there is
1679
+ none on your PATH: node's own release from nodejs.org, about 30 MB, checked the same way, into pdfmd's tools folder), a
1680
+ Markdown document built with `-e weasyprint` (or one that falls back to it) has its math typeset by MathJax before
1681
+ WeasyPrint prints it: fractions, roots, matrices, accents, limits, stretchy arrows and braces, `\ce` reactions, in the
1682
+ STIX Two Math, sized to the body font's x-height when the body is not STIX Two Text. (MathJax's other math fonts, New
1683
+ Computer Modern, TeX Gyre Termes and Pagella and DejaVu, are not offered yet: their tall delimiters built from pieces came
1684
+ out broken in WeasyPrint.) WeasyPrint draws some of MathJax's output a little off (an accent three points over its letter, a
1685
+ fraction's denominator too low, a bar that ran past its letter); pdfmd's own style rules put that right. A formula MathJax cannot read goes to KaTeX when `pdfmd --install math:katex` has put it in place (a `NOTE` says
1686
+ how many), and a formula neither reads (a macro from your LaTeX preamble, say) stays text, with one `WARN` for all of
1687
+ them. KaTeX alone, without MathJax, does what it did: `--no-auto mathjax` asks for that. Without either, the math is
1688
+ Pandoc's plain math, simple formulas in Unicode (`αᵢ ≤ β`) and the others as their TeX, with one `WARN`; Typst or a
1689
+ LaTeX engine typesets them. A math option of your own (`--mathml`, `--math-method=...`) is kept, and `--doctor` says
1690
+ which of them you get.
1691
+
1692
+ A link to an anchor the document does not have (`[see 13.5](#135-your-own-defaults)` quoted from another document) is
1693
+ only a warning for LaTeX and HTML, but Typst stops on it. For Typst, PDF or `.typ`, such a link becomes its text, and
1694
+ one `WARN` names the anchors.
1695
+
1392
1696
  `--strict` (or `pdfmd-options: {strict: true}` in the document; `--no-strict` overrides it) makes that, and every other
1393
1697
  warning, an error for scripts and CI: a file whose build printed a `WARN` line, or about which Pandoc warned (an image
1394
1698
  or citation it could not find, a LaTeX reference left undefined), is reported `FAIL` with the first warnings listed and
@@ -1534,21 +1838,45 @@ options:
1534
1838
  pdf-engine: lualatex
1535
1839
  ```
1536
1840
 
1537
- **`pdfmd --setup`** changes the same defaults from a menu, without editing the files: a numbered list (nothing to
1841
+ **`pdfmd --setup`** (or `pdfmd --config`) changes the same defaults from a menu, without editing the files: a numbered list (nothing to
1538
1842
  install, works over ssh), each setting with its choices and what they mean. It covers what a document would otherwise
1539
1843
  say in `pdfmd-options:` or its front matter, for every document:
1540
1844
 
1541
1845
  - *global metadata* (a `metadata.yaml` beside the config file, below anything a document's own folder says): author, language,
1542
1846
  paper size, font size, page geometry, main and code font, line spacing, coloured links, table of contents, and for
1543
1847
  citations the bibliography file, the CSL style and linked citations;
1848
+ The global metadata can be switched off (`--no-global-metadata`, `pdfmd-options: {global-metadata: false}`, or
1849
+ the *Use the global metadata* row; `--global-metadata` turns it back on for one run) and replaced by a **preset**: another
1850
+ file, `presets/NAME.yaml` beside the config file. `--preset lab` (or `lab.yaml`, or a path), `pdfmd-options: {preset: lab}`
1851
+ in a document or a folder's metadata, or the *Which set of global metadata* row chooses it; `--preset none` takes no global
1852
+ metadata, `default` is `metadata.yaml`. `pdfmd --setup --preset lab` edits that preset's rows (it makes the file), and
1853
+ `pdfmd --presets` lists them and marks the one a build here would use. The command line wins, then the document, then the
1854
+ folder's metadata, then the config.
1544
1855
  - characters a font lacks or none draws, fonts for other scripts, romanization packs;
1545
- - the citation engine, the PDF engine, the default output format, HTML (one file, math method), LaTeX and reference
1546
- numbers in Word files;
1547
- - PDF finishing (header, footer, bookmarks, attached links) and the source file (the "Compiled with..." stamp, backups,
1548
- comment stripping, attaching the source and its files to the PDF);
1549
- - the cache, reading `.txt` as Markdown, and which of pdfmd's automatic behaviours (`--no-auto` kinds) are off.
1550
-
1551
- Choosing 0 (for a text, `-`) gives a setting its built-in default back; `s` saves, `q` quits. The files are rewritten without your
1856
+ - the citation engine; output (the PDF engine, the default output format, defaults for `.typ` and `.html` files);
1857
+ HTML (full page, one file, style sheet, math method); tables (the rows, columns, cut and delimiter of `.csv` tables,
1858
+ pipe-table widths); code (wrapping, line numbers); Word and OpenDocument (LaTeX in them, reference numbers, the
1859
+ template);
1860
+ - plain Markdown, text and ASCII output (`--to gfm`, `txt`, `ascii`: scripts, math, title block, the source carried at
1861
+ the end);
1862
+ - PDF finishing (header, footer, bookmarks, attached links, a hybrid PDF); the build history (the "Compiled with..."
1863
+ stamp and its details); backups (their folder, names and how many are kept); the source inside the PDF (attaching
1864
+ the source, its files and its LaTeX packages, comment stripping);
1865
+ - the cache (reference numbers, plots, a part built alone); input (the Markdown reader, reading `.txt` as Markdown, raw
1866
+ pieces);
1867
+ - checks and limits (`--strict`, the size budgets, the codes `--check` leaves out), and which of pdfmd's automatic
1868
+ behaviours (`--no-auto` kinds) are off.
1869
+
1870
+ Every flag and every `pdfmd-options` key is either one of these rows or left out on purpose: `o` lists the rest (commands,
1871
+ what is about one run or one document, trust, what pdfmd writes for itself) with the reason, and a test keeps that
1872
+ complete. Choosing 0 (for a text, `-`) gives a setting its built-in default back; `s` saves, `q` quits.
1873
+
1874
+ **Switching whole features off.** `d` in `--setup` (or `disabled: [history, tables]` in `config.yaml`) switches off
1875
+ features you never use: modes, source, tables, history, code, raw, markdown, fonts, builtin, office, cache (the topics
1876
+ of `--help`; output, setup and debug stay on). Their options leave `--help`, shell completion (regenerate it with
1877
+ `--completion`) and the setup screen, and the command line refuses them; `pdfmd --disabled --history doc` uses one for a
1878
+ single run and `pdfmd --disabled --help all` shows them. A document's own `pdfmd-options` still apply, so a document
1879
+ from someone else builds the same. In the full-screen setup, `r` resets a row (it used to be `d`). The files are rewritten without your
1552
1880
  comments (the old one is kept as `.bak`). The same keys can be written by hand under `options:` of `config.yaml`. A
1553
1881
  full-screen version is optional: `pdfmd --install tui` (prompt_toolkit, about 1 MB), then `pdfmd --setup fancy`, or set
1554
1882
  "This setup screen" to fancy to make it the one `pdfmd --setup` opens. The first time pdfmd finishes a build in a terminal
@@ -1579,6 +1907,24 @@ files could apply and none is clearly meant, `pdfmd` stops and asks you to
1579
1907
  choose with `-y FILE`, rather than guessing. `-y` alone turns discovery
1580
1908
  off.
1581
1909
 
1910
+ **When two metadata files set the same key, the later one wins**, as in Pandoc:
1911
+ `<name>.yaml` over `metadata.yaml`, `report.yaml` over `metadata.yaml`, and the
1912
+ second of `-y base.yaml -y extra.yaml`. This holds for Pandoc's keys and for
1913
+ pdfmd's own (`pdfmd-options:`, `margin:`), key by key: the earlier file still
1914
+ gives whatever the later one leaves out. The document's own front matter beats
1915
+ every file. `--metadata-precedence first` (or `metadata-precedence: first` in
1916
+ `pdfmd --setup`, under Input) turns this round so that the first file wins.
1917
+ Until 3.27.22, pdfmd's own keys followed that `first` rule while Pandoc's followed
1918
+ the later file.
1919
+
1920
+ A `header-includes:` stays when a preamble file joins it: the document's own, or
1921
+ else the one of the metadata file that wins (above). The same holds
1922
+ for the header files pdfmd adds itself, such as the code-wrapping header of a
1923
+ document with code. A metadata file's lines go before `preamble.tex`, and the
1924
+ document's own go after everything. An `--include-in-header` you pass yourself
1925
+ replaces them all, as it does in Pandoc. The global `metadata.yaml` that
1926
+ `pdfmd --setup` writes is the lowest of all metadata files.
1927
+
1582
1928
  With a `metadata/` folder, a report's own folder can hold nothing but
1583
1929
  `report.md` and `report.pdf`. Relative paths inside the metadata (such as
1584
1930
  `bibliography: refs.bib`) resolve from `metadata/`, and image paths in the
@@ -1662,3 +2008,7 @@ read with `pdfinfo -meta`. Turn this off with `--no-stamp-pdf-metadata`.
1662
2008
  ## License
1663
2009
 
1664
2010
  [MIT](https://github.com/aliperdehan/pdfmd/blob/main/LICENSE)
2011
+
2012
+ `pdfmd_mhchem/` is a Python port of Martin Hensel's
2013
+ [mhchemParser](https://github.com/mhchem/mhchemParser) (the parser of mhchem's `\ce` and `\pu` that MathJax and KaTeX
2014
+ use) and keeps its [Apache License 2.0](https://github.com/aliperdehan/pdfmd/blob/main/pdfmd_mhchem/LICENSE).