Внешние репозитории
Контент сайта не обязан лежать в одном репозитории с блоками и конфигами. Тексты и изображения могут храниться в отдельных репозиториях контента, а движок собирает сайт из них. Это удобно, когда один контент обслуживает несколько сайтов или когда над текстами работает отдельная команда.
Здесь важно чёткое разделение: ядро читает контент из каталога на диске, а наполняет этот каталог расширение. Клонирование репозиториев Git в ядро не входит — это необязательный инструмент, как и всё остальное в экосистеме (см. семейство репозиториев).
Ядро: корень контента
Движок читает .md-файлы из корня контента — первого уровня в levels.json, по умолчанию content/:
["content", "blocks"]
Строка карты сайта [models, free/models.md] разрешается в content/free/models.md. Каталог может быть локальным или указывать на клон внешнего репозитория — движку всё равно, как файлы там оказались. Он лишь читает то, что уже лежит на диске: ни клонирования, ни обновления ядро не делает.
Это прямая аналогия с кодированием изображений: движок копирует готовые файлы, а готовит их отдельная команда.
Расширение: наполнение каталога
Для подготовки репозиториев нужен git в PATH, а для обновлений также нужен Git LFS; см. команду подготовки.
Команда подготовки читает общий файл config/external.json — массив адресов Git. Аргумента таргета у неё нет; при отсутствии файла или пустом массиве она ничего не подготавливает:
[
"git@github.com:acme/acme-content.git",
"git@github.com:acme/acme-assets.git"
]
Наполнение — это command-расширение: команда nuckty content-external читает external.json, клонирует каждый репозиторий в external/<repo>/ (имя каталога — имя репозитория без .git) и обновляет рабочую копию. Затем укажите клон первым уровнем в levels.json, и движок читает контент оттуда:
["external/acme-content", "content", "blocks"]
Это отдельный шаг, как и подготовка изображений. Сборка не запускает команду автоматически. Для работы без сети нужны готовые входные файлы и расширения, не обращающиеся к сети. Воспроизводимость требует фиксированных версий и метаданных. Git также может использоваться ядром для времени изменения исходников; без него оно равно null.
external/
acme-content/ ← клон, первый уровень levels.json
acme-assets/ ← общие ассеты
Исключите external/ из репозитория Git сайта, добавив его в .gitignore. Команда подготовки не создаёт это правило и не меняет levels.json за вас.
Роли репозиториев в site.json
В config/site.json можно описать роли репозиториев:
| Поле | Назначение |
|---|---|
contentRepo | Основной репозиторий контента — обычно тот, что стоит первым уровнем в levels.json. |
assetRepos | Дополнительные репозитории с ассетами (изображения, файлы для скачивания). |
githubRawBase | База для переписывания ссылок на сырые файлы GitHub. null — не переписывать. |
contentRepo и assetRepos — описательные поля: они не выбирают корень Markdown и не фильтруют сканирование ассетов. Корень задаёт первый уровень levels.json, а внешние источники стадий — external.json в configDir текущего таргета. При отдельных каталогах конфигурации согласуйте эти списки с общим config/external.json, который читает команда подготовки.
Зачем это нужно
- Разделение ролей. Над текстами работает одна команда, над движком и вёрсткой — другая. Контент живёт своей жизнью, сборка — своей.
- Один контент — несколько сайтов. Один репозиторий контента может обслуживать несколько таргетов или разных сайтов.
- Чистые исходники. В репозитории сайта нет копии чужого контента — только ссылка в
external.jsonи путь вlevels.json.
Чего это не заменяет
Внешние репозитории — про источники контента, а не про публикацию: готовый артефакт по-прежнему собирается в outDir и публикуется целиком (см. публикацию по FTP). И это не замена расширениям: расширения подключаются через ext[], а external.json лишь перечисляет источники контента.