-
{% for post in posts %}
- {{ post['title'] }} {% endfor %}
:title: Как я написал этот блог :date: 5 Aug 22 :type: page .. note:: Статья малось устарела и не соответсвует текущей действительности. ======================= Как я написал этот блог ======================= Я очень давно планировал написать блог. Именно что написать CMS для ведения блога. Если погуглить, то CMS для этих целей сотни на разных языках с разным позиционированием и фичами. Но мне хотелось своего. Первые попытки создать сайт были на `Flask`_, особым успехом не увенчались, но это была хорошая практика и я немного прокачал свой уровень программирования. Для блога я не хотел использовать базу данных. Вместо этого я хранил статьи в исходном Markdown, а метаданные по каждой статье писал в отдельный JSON, который заменял мне БД. С тем же успехом я мог бы использовать SQLite, но мне нужно было хранить контент в text/plain. Блог даже работал, но мне хотелось сделать админку, чтобы можно было писать прямо в браузере. На этой части разработка заглохла и я окончательно запутался в импортах в Python) Прошло ещё много времени, я вернулся к идее, но решил сделать ставку на простоту и начал писать на `Bottle`_. Здесь разработка остановилась не дойдя даже до варианта хоть как-то работающей системы. Причины скорее всего надо искать в лени. Устав я взял `CMS Bludit`_ и стал вести свои редкие заметки в нём. Решение не самое плохое, но и не супер отличное. Для простой кастомизации футера пришлось городить костыли. .. _Flask: https://flask.palletsprojects.com/ .. _Bottle: https://bottlepy.org/ .. _CMS Bludit: https://www.bludit.com/ru/ Статика VS динамика =================== Преимуществ у статических сайтов много. Об этом уже много написано. Мне больше всего в статических сайтах нравится то, что: * роутингом запросов не управляет какой-либо скрипт, я могу свободно распоряжаться тем, что у меня есть в DocumentRoot; * не нужно настраивать application-сервер и реверс-прокси на него. С редактированием сайта чуть сложнее, так как сперва надо внести изменения локально, а затем заменить изменившиеся файлы на сервере. Но и тут есть какие-то решения. Я рассматривал уже готовые генераторы статических сайтов, но у них всех были фатальные недостатки: * они сложные и требуют изучения документации чтобы начать писать; * написать собственную тему задача весьма непростая; * они написаны не мной. Здесь и рождается мой велосипед, которому я не придумал названия. Буду называть его `генератором`. *re*\ **Structured**\ *Text* ============================ Я очень долго писал на Markdown, но в один момент понял, что возможностей языка стало нехватать. Тут пришёлся очень кстати `Python-Markdown`_ к которому можно было прикручивать `расширения`_. Одно даже сам `написал`_. Постепенно я пришёл к `reStructuredText`_. Все приколюхи, которые в нём есть существуют не за счёт расширения синтаксиса плагинами, а заложены в спецификации. Функциональности из коробки хватает чтобы писать даже `формулы`_. Такие вещи делаются через `роли` и `директивы`. Некоторые готовые директивы есть в системе документации `Sphinx`_. Их я собираюсь потихоньку скопировать к себе. Ещё одно большое преимущество перед Markdown состоит в том, что reStructuredText поддерживает атрибуты. Вот как это выглядит: .. code-block:: rst :title: Как я написал этот блог :date: 5 Aug 2022 Это нативная фича, которую можно использовать в статьях для добавления метаданных. По сути это место, где можно сделать настройки, касающиеся отдельно взятой статьи. Большинство генераторов статических сайтов колхозят нечно подобное в Markdown, делая исходник статьи непригодным для парсинга другими инструментами. Это причина по которой в старой реализации блога мне пришлось использовать JSON для метаданных. .. _Sphinx: https://www.sphinx-doc.org/en/master/index.html .. _Python-Markdown: https://python-markdown.github.io/ .. _расширения: https://python-markdown.github.io/extensions/ .. _написал: https://pypi.org/project/markdown-alerts/ .. _rST: https://docutils.sourceforge.io/rst.html .. _формулы: https://docutils.sourceforge.io/docs/ref/rst/mathematics.html Обзор ===== Сайт состоит из следующих частей. rst_blg.py Непосредственно код генератора. Сейчас там всего около 200 строк без учёта комментариев. requirements.txt Список зависимостей. Стараюсь держать минимум. Пока что там: `docutils`, `jinja2`, `toml` и `pygments`. settings.toml Файл с настройками. Здесь можно переопределить практически всё. Makefile Через него запускаются команды для сборки сайта и некоторые другие. Не является обязательным, но с ним удобнее. layouts Директория для шаблонов Jinja2. assets Директория для хранения статических файлов, будь то CSS, JS или изображения. Всё что нужно для визуального оформления страниц. Внутренняя структура каталога может быть произвольной. content Директория с исходниками статей в reStructuredText. Сюда можно также положить любые файлы и директории. build В эту директорию копируются ассеты, файлы и сгенерированный HTML. Статьи, шаблоны и ассеты могут быть оформлены абсолютно любым образом. Скрипту безразлично что собирать. Пути и имена всех директорий можно переопределить в settings.toml. Исходники с небольшой инструкцией я положил сюда: https://git.nxhs.cloud/ge/blog Написание постов ================ Тут всё предельно просто. Пишем файл и кладём в директорию `content`. В файле должны быть указаны обязательные атрибуты ``:title:`` и ``:date:``. Блог пока не умеет работать с вложенной структурой статей. Поэтому всё будет свалено в кучу в корневую директорию сайта. Все статьи добавляются в список постов и отображаются на главной странице. Для того, чтобы сделать "отдельную" страницу, надо добавить атрибут ``:not_a_post:``. ================= ======= =========== ==================================== Атрибут Тип Умолчание Описание ================= ======= =========== ==================================== ``:title:`` Строка Заголовок статьи ``:date:`` Дата Дата публикации, формат задаётся в settings.toml ``:not_a_post:`` Флаг для одиночных страниц ================= ======= =========== ==================================== Темы оформления =============== Никаких готовых тем. Пишем CSS вручную. Генератору сайтов всё равно что там будет. От уровеня представления он никак не зависит. Так что можно писать любые шаблоны и стили для них. Отдельно можно задать тему для блоков кода. Список тем для Pygments с превью есть на странице https://pygments.org/styles/ Чтобы поменять тему, например, на `default` надо выполнить команду: .. code-block:: shell make css default # или pygmentize -f html -S default -a .highlight > assets/css/pygments/default.css Затем поменять значение ``theme`` в секции ``pygments`` settings.toml. .. code-block:: toml [pygments] theme = 'default' Шаблоны ======== Шаблоны можно писать какие угодно. Для этогой сайта я написал три файла. Приведу их без лишних строк. **base.j2** .. code-block:: html+jinja
{% if posts %} {{ site_title }} {% else %} {{ site_title }} / {{ page_title }}
{% endif %}