# Генератор статических сайтов в 90 строк Python кода Создано: 16 апреля 2025 [In English](/en/blog/2025/01-sitegen) Давным-давно я сделал небольшой сайт-визитку - он состоял из трех простеньких HTML-страниц, одного CSS-файла (который я генерировал из SCSS), нескольких шрифтов и картинок. Этого было более чем достаточно, чтобы ссылка на мой сайт красовалась в каком-либо резюме или профиле соцсети.  Недавно я решил продолжить работу над своим pet проектом и хотел бы публиковать на своем сайте всякие заметки и статьи на эту тему. Мне не хотелось вручную возиться с HTML-файлам, поэтому я решил подыскать альтернативу в виде какого-нибудь статического генератора сайтов. В идеале, я хотел бы, чтобы он был: - Небольшим и достаточно простым - Мог работать с Markdown - Мог выполнять подсветку синтаксиса в блоках кода К сожалению, я не смог найти ни одно подходящее для себя решение, поэтому я решил собрать свое на коленке используя Python, парсер Markdown'а mistune, шаблонизатор Jinja2 и Pygments. Весь процесс генерации сводиться к следующему: 1. Для каждого файла во входном каталоге проверяем, является ли он Markdown - Если да - преобразуем его в HTML (с подсветкой синтаксиса) и записываем в выходной каталог - Если нет - копируем файл как есть в выходной каталог 2. Сжимаем содержимое выходного каталога У данного процесса генерации есть достаточно крупный недостаток - из-за того, что нет постобработки HTML, любые ссылки на другие страницы Markdown должны заканчиваться расширением `.html`[^1]. [^1]: Эту проблему можно устранить с помощью специальной настройки веб-сервера, которая заменяет в расширение `.md` на `.html` или путем автоматического дописывания расширения `.html` (к примеру: `try_files $uri $uri.html`). Сам код генератора: ```python import re, jinja2, mistune, shutil, os, pathlib, tarfile from pygments.lexers import get_lexer_by_name from pygments.formatters import HtmlFormatter from pygments import highlight class PygmentsHTMLRenderer(mistune.HTMLRenderer): def block_code(self, code: str, info = None): if not info: return '\n
%s\n' % mistune.escape(code)
lexer = get_lexer_by_name(info, stripall=True)
formatter = HtmlFormatter(lineseparator='