Каждому, кто ходил извилистой тропкой автоматической генерации pdf из markdown файлов ведомы связанные с этой задачей пеньки решения: Pandoc, LaTex, wkhtmltopdf и т.п.

Хочу поделиться с сообществом новым (по крайней мере для меня) вариантом решения этой задачи в Python.

Этот вариант имеет следующие плюсы.

  • Все зависимости в requrments.txt, никаких внешних бинарников.

  • Нет проблем с кириллицей, картинками и наиболее популярными элементами разметки.

  • Возможность использования разных размеров страниц внутри одного pdf.

  • Настраиваемый режим создания оглавления (bookmarks).

Данный способ основан на использовании библиотек markdown-it-py (md -> html) и PyMuPDF (html -> pdf). Связывает их между собой маленький класс Python.

Ставим:

pip install markdown-pdf

Создаем pdf с оглавлением (bookmarks) из заголовков до 2 уровня.

from markdown_pdf import MarkdownPdf

pdf = MarkdownPdf(toc_level=2)

Добавляем в pdf три секции markdown. Каждая секция начинается с новой страницы. Заголовки из первой секции не включаем в оглавление.

from markdown_pdf import Section

pdf.add_section(Section("# Title\n", toc=False))
pdf.add_section(Section("# Head1\n\nbody\n"))
pdf.add_section(Section("## Head2\n\n### Head3\n\n"))

Устанавливаем свойства pdf документа.

pdf.meta["title"] = "Руководство пользователя"
pdf.meta["author"] = "А.C.Пушкин"

Сохраняем в файл.

pdf.save("guide.pdf")

Благодарю за внимание.

Комментарии (9)


  1. yarkov
    04.10.2023 06:06

    Вы просто README перепечатали?


    1. vb64 Автор
      04.10.2023 06:06

      readme_ru


    1. ivankudryavtsev
      04.10.2023 06:06
      +3

      Стоит заметить, что проект авторства автора, так что вполне себе :)

      @vb64немного бы сторителлинга добавить - как вы дошли до жизни такой. Статья была бы изящнее, мотивационнее для других разработчиков и читалась бы с большим интересом.

      Не нашел на GitHub в actions публикации на pypi. Вы руками публикуете? Как гарантируете соответствие публикуемого кода коду в GitHub?


      1. vb64 Автор
        04.10.2023 06:06

        боюсь, что полный рассказ о страданиях получился бы слишком длинным, в нескольких томах :)

        мало народу до конца дочитало бы.


        1. sbw
          04.10.2023 06:06

          Достижения без страданий - это слишком идеально и неинтересно, и обычно так не бывает. Страдания без смысла и достижений - ну такое чтиво, для мазохистов. А вот если их правильно объединить при помощи пути героя, то это совсем по-другому будет читаться. Через тернии к звёздам! ????????????


      1. vb64 Автор
        04.10.2023 06:06

        насчет публикаций на pypi - да, руками публикую.

        насчет гарантий соответствия - не задумывался, честно говоря. если подскажете какие-то бестпрактикс, и что вообще почитать по этому вопросу, то буду весьма благодарен.

        впрочем, в данном конкретном случае размер кода - 85 строк, так что можно и руками сравнить :)


        1. ivankudryavtsev
          04.10.2023 06:06
          +1

          Я просто голову греть не люблю на тему: "надо вспомнить как сделать".

          Можете глянуть в моих репках, если интересно как публиковать: https://github.com/insight-platform/savant-rs/blob/main/.github/workflows/savant-rs-ci.yml#L55

          стоит заметить, что я использую Maturin, потому что у меня Rust с Python-врапперами, но думаю, что там замена на вашу тулзу решает вопрос.


      1. yarkov
        04.10.2023 06:06

        О, а я спросонья и не заметил. Посыпаю голову пеплом)


  1. autarkie
    04.10.2023 06:06

    Quarto вам в помощь.