feat: export docs to pdf
Описание
Необходимо экспортировать контент сайта документации в PDF
Решение — плагин mkdocs-with-pdf
для MkDocs
Результат
document-fixed.pdf
>>>Артефакты устранены. Проблему с битыми svg-изображениями решил заменой на png-изображения
document.pdf
>>>Генерируется при выполнении команды mkdocs build
Замечания:
- проблемы с svg-изображениями и отсутствие части текста в первом разделе
- крупные EBNF-диаграммы некорректно масштабируются
- весит 20.6 МБ
document_from_html.pdf
>>>Напечатан в PDF из файла for_pdf_print.html, который получен при выполнении команды mkdocs build > for_pdf_print.html
Замечания:
- проблемы в первом разделе отсутствуют
- крупные EBNF-диаграммы некорректно масштабируются
- весит 5.6 МБ
- есть пустые страницы — их можно исключить при настройке печати в PDF
- слишком большие отступы до и после svg-изображений
- в файле
for_pdf_print.html
проще контролировать стили
Заметки
1. Запуск `mkdocs-with-pdf`
mkdocs-with-pdf
Запуск При запуске плагина mkdocs-with-pdf
возникает ошибка типа AttributeError
. Для обхода ошибки я исправляю код ./weasyprint/pdf/fonts.py:
else:
# Store width and Unicode map for all glyphs
font_widths, cmap = {}, {}
+ try:
for letter, key in font.ttfont.getBestCmap().items():
glyph = font.ttfont.getGlyphID(key)
if glyph not in cmap:
cmap[glyph] = chr(letter)
width = font.ttfont.getGlyphSet()[key].width
font_widths[glyph] = width * 1000 / font.upem
+ except:
+ continue
max_x = max(font_widths.values()) if font_widths else 0
bbox = (0, font.descent, max_x, font.ascent)
Контекст ошибки `mkdocs-with-pdf`
Traceback (most recent call last):
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/bin/mkdocs", line 8, in <module>
sys.exit(cli())
^^^^^
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/click/core.py", line 1157, in __call__
return self.main(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/click/core.py", line 1078, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/click/core.py", line 1688, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/click/core.py", line 1434, in invoke
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/click/core.py", line 783, in invoke
return __callback(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/mkdocs/__main__.py", line 286, in build_command
build.build(cfg, dirty=not clean)
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/mkdocs/commands/build.py", line 354, in build
config.plugins.on_post_build(config=config)
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/mkdocs/plugins.py", line 542, in on_post_build
return self.run_event('post_build', config=config)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/mkdocs/plugins.py", line 509, in run_event
result = method(**kwargs)
^^^^^^^^^^^^^^^^
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/mkdocs_with_pdf/plugin.py", line 135, in on_post_build
self.generator.on_post_build(config, self.config['output_path'])
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/mkdocs_with_pdf/generator.py", line 157, in on_post_build
render.write_pdf(abs_pdf_path)
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/weasyprint/document.py", line 390, in write_pdf
pdf = generate_pdf(self, target, zoom, **options)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/weasyprint/pdf/__init__.py", line 273, in generate_pdf
pdf_fonts = build_fonts_dictionary(
^^^^^^^^^^^^^^^^^^^^^^^
File "/home/asabirov/.local/share/virtualenvs/docs-bOyF4WXG/lib/python3.12/site-packages/weasyprint/pdf/fonts.py", line 47, in build_fonts_dictionary
for letter, key in font.ttfont.getBestCmap().items():
^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'getBestCmap'
2. Артефакты в pdf-файле
Артефакты в pdf-файле
В сгенерированном pdf-файле присутствуют артефакты рендеринга:
- В первом разделе:
- большинство svg-изображений побились или отсутствуют
- отсутствуют значительные куски текста
- Крупные EBNF-диаграммы некорректно масштабируются
- В выносках:
- иконки типов выносок перекрыли заголовки
- некоторые заголовки прилипли к левому краю
- Заголовки h4–h6 расположились левее заголовков h1–h3
Некоторые из этих артефактов устранены с помощью добавлений в файл docs/extra/style.css
- Target branch:
main
- Changes should be cherry-picked to
24.2
: no - Staging: https://docs.binary.picodata.io/picodata/asabirov_export_docs_to_pdf/
Edited by Artur Sabirov