Сайт как окно редактора

Николай Носков 4 мин

Лэйаут повторяет окно современного Neovim — AstroNvim с темой Catppuccin Mocha: слева дерево файлов, в центре буфер, справа сплит с оглавлением, сверху таблайн, снизу строка статуса. Речь именно о современном редакторе: пастельные цвета, низкий контраст, панели разделены не рамками, а слоями фона. Зелёного на чёрном, ASCII-рамок и мерцания в интерфейсе нет.

Слои вместо линий

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

Палитра Mocha: от crust к surface

В CSS это четыре уровня:

:root {
  --bg-page: var(--ctp-crust);     /* фон страницы */
  --bg-sidebar: var(--ctp-mantle); /* дерево файлов */
  --bg-buffer: var(--ctp-base);    /* основной буфер */
  --bg-cursorline: var(--ctp-surface0);
}

Цвета не вписаны руками: Catppuccin берётся из пакета @catppuccin/palette, остальные темы — из тех же тем Shiki, которыми подсвечивается код. Слои, которых нет в палитре, вычисляются через color-mix, чтобы перепад яркости оставался одинаковым во всех темах.

Один цвет — одна роль

Акцентов в палитре много, поэтому ролей ровно четыре:

  • mauve — ссылки;
  • blue — активный файл в дереве;
  • subtext0 — даты и метаданные;
  • green — теги.

Всё остальное — основной цвет текста и оттенки серого. Тело статьи всегда основного цвета: пастель на тёмном фоне хороша в интерфейсе, но в длинном абзаце контраст проваливается. Интерфейс может шептать, текст должен говорить нормальным голосом. Исключение одно — блоки кода: подсветка использует больше цветов, чем четыре роли.

В темах, где подходящего цвета нет, слоты подменяются: в Rosé Pine теги жёлтые, в Dracula и Nord активный файл голубой.

Шрифты

Моноширинный шрифт живёт только в «хроме»: дерево, табы, строка статуса, номера строк, заголовки. Текст набран Inter, около 17 пикселей, интерлиньяж 1,7, колонка примерно в 70 знаков. Ширина колонки задана в em, поэтому при смене размера текста число знаков в строке сохраняется.

Что создаёт иллюзию

  1. Номера строк в гаттере: абзац считается одной строкой, как в Vim с включённым переносом, а в блоках кода нумеруется каждая строка.
  2. Подсветка строки под курсором мыши — тем же surface0, что и в дереве.
  3. Мигающий блочный курсор в конце заголовка.
  4. Строка статуса, где процент считается от настоящей прокрутки: на десктопе прокручивается буфер, на мобильном — документ.
loop.mp4 — видео рядом с постом: зациклено, без звука, весит меньше гифки и не мылит цвета.

Чего в интерфейсе нет и не будет: командной строки, в которую нельзя ничего ввести, и перехвата клавиш браузера. Неработающий нарисованный интерфейс раздражает сильнее, чем его отсутствие.

Темы и размер текста

Читателю. В строке статуса справа есть выбор темы и три кнопки размера текста. Выбор запоминается в браузере и применяется до первой отрисовки, без вспышки. Без JavaScript переключателей нет, сайт показывается в теме по умолчанию.

Автору. Всё задаётся в src/styles/themes.ts:

  • DEFAULT_THEME — тема по умолчанию;
  • THEMES — список тем: Catppuccin берётся из пакета, остальные из Shiki;
  • новая тема — одна строка вида fromShiki('github', githubDark) плюс импорт @shikijs/themes/github-dark-default; список готовых тем — ls node_modules/@shikijs/themes/dist;
  • roles — из каких цветов палитры брать ссылки, активный файл и теги, если стандартные слоты не подходят;
  • FONT_SIZES — три размера текста, TEXT_COLORS — имена цветов для записи :цвет[…].

Настройки сайта

  • src/site.config.ts — название, описание, автор и язык.
  • astro.config.mjs — адрес сайта в site (нужен для RSS и канонических ссылок), markdown-плагин, темы подсветки кода.
  • public/favicon.svg — иконка вкладки.

Где что лежит

  • src/content/posts/ — посты;
  • src/content.config.ts — схема фронтматтера;
  • src/pages/ — лента, пост, теги, RSS, 404;
  • src/layouts/Editor.astro — «окно редактора»: дерево, таб, буфер, оглавление, строка статуса;
  • src/components/ — дерево файлов, оглавление, строка статуса, список постов;
  • src/lib/tree.ts — построение дерева из папок;
  • src/lib/markdown-color.ts — запись цвета и блоки ascii;
  • src/integrations/post-media.ts — видео рядом с постом;
  • src/styles/ — темы, оформление интерфейса и текста.

Команды

npm run dev      # сайт с автообновлением на localhost:4321
npm run build    # сборка в dist/, падает на ошибках фронтматтера
npm run preview  # посмотреть собранный dist/

Если после правки markdown-плагина, тем подсветки или astro.config.mjs посты выглядят по-старому, Astro отдаёт их из кэша. Остановите npm run dev, удалите кэш и запустите снова:

rm -rf node_modules/.astro .astro/data-store.json