upd
This commit is contained in:
parent
d14a3f95a7
commit
423468a50b
@ -13,6 +13,6 @@
|
||||
* `vk-toot <https://git.nxhs.cloud/ge/vk-toot>`_ -- кросспостер VK -> Mastodon
|
||||
* `piglet <https://git.hxhs.cloud/ge/piglet>`_ -- клиент DNS API Porkbun
|
||||
* roadwarrior -- менеджер подключений к VPN и прокси
|
||||
* `n! <https://git.nxhs.cloud/ge/n>` -- консольный менеджер заметок
|
||||
* `n! <https://git.nxhs.cloud/ge/n>`_ -- консольный менеджер заметок
|
||||
|
||||
Остальное есть в `Gitea <https://git.nxhs.cloud/ge/>`_.
|
||||
|
@ -1,339 +0,0 @@
|
||||
: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
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<link rel="icon" href="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=">
|
||||
<link rel="stylesheet" href="assets/css/pygments/{{ pygments_theme }}.css">
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
<title>{{ page_title }} | {{ site_title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<p>
|
||||
{% if posts %}
|
||||
{{ site_title }}
|
||||
{% else %}
|
||||
<a href="/">{{ site_title }}</a> / {{ page_title }}</p>
|
||||
{% endif %}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
<footer>
|
||||
<!-- Footer content -->
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
**post.j2**
|
||||
|
||||
.. code-block:: html+jinja
|
||||
|
||||
{% extends "base.j2" %}
|
||||
{% block content %}
|
||||
|
||||
<article>
|
||||
{{ post | safe }}
|
||||
<article>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
**index.j2**
|
||||
|
||||
.. code-block:: html+jinja
|
||||
|
||||
{% extends "base.j2" %}
|
||||
{% block content %}
|
||||
|
||||
<section>
|
||||
<ul id="posts">
|
||||
{% for post in posts %}
|
||||
<li>
|
||||
<a href="/{{ post['path'] }}">{{ post['title'] }}</a>
|
||||
<span class="meta"> — {{ post['date'] }}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
settings.toml
|
||||
=============
|
||||
|
||||
Сначала я хотел использовать обычный INI, но мне нужно было получать из конфига
|
||||
словарь. Немного подумал и выбрал TOML. Он отлично сериализируется в словарь,
|
||||
визуально повторяет INI.
|
||||
|
||||
**settings.toml** разделён на несколько секций.
|
||||
|
||||
site
|
||||
Данные касающиеся непосредственно сайта.
|
||||
|
||||
title
|
||||
Название сайта
|
||||
|
||||
index_page_title
|
||||
Заголовок главной страницы. Для всех остальных страниц заголовок
|
||||
берётся из атрибута.
|
||||
|
||||
datatime_format
|
||||
Формат даты для атрибута ``:date:``.
|
||||
|
||||
build
|
||||
Параметры, используетмые при сборке.
|
||||
|
||||
build_dir
|
||||
Директория, куда будет сохранён собранный сайт.
|
||||
|
||||
content_dir
|
||||
Директория с исходниками статей.
|
||||
|
||||
templates_dir
|
||||
Директория с шаблонами Jinja2.
|
||||
|
||||
assets_dir
|
||||
Директория с ассетами.
|
||||
|
||||
pygments
|
||||
Параметры подсветки синтаксиса в блоках кода.
|
||||
|
||||
theme
|
||||
Стиль Pygments.
|
||||
|
||||
docutils
|
||||
Конфигурация для docutils. Здесь можно указать любые параметры, которые
|
||||
есть здесь: https://docutils.sourceforge.io/docs/user/config.html
|
||||
|
||||
Мне достаточно:
|
||||
|
||||
.. code-block:: toml
|
||||
|
||||
[docutils]
|
||||
initial_header_level = 2
|
||||
section_self_link = true
|
||||
syntax_highlight = 'short'
|
||||
|
||||
Что ещё хочется сделать
|
||||
=======================
|
||||
|
||||
В перспективе я планирую добавить следующие фичи.
|
||||
|
||||
- RSS
|
||||
- OpenGraph
|
||||
- Webmention
|
||||
- Расширить возможности rST до уровня Sphinx
|
||||
- Улучшить CSS
|
||||
- Комментарии
|
||||
- Кастомный лейаут для отдельных статей
|
||||
- Поддержка вложенной структуры статей
|
||||
|
||||
.. * https://jinja.palletsprojects.com/en/3.0.x/templates/
|
||||
* https://docutils.sourceforge.io/docs/user/config.html
|
||||
|
Loading…
Reference in New Issue
Block a user