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

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

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

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

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

В 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