Использование MkDocs для создания сайта с документацией
Оглавление
- Что такое генератор статического сайта? И почему был выбран именно MkDocs?
- Создание и генерация тестового сайта.
- Как и на каком языке писать материалы для генератора MkDocs?
- Разбираем структуру файла mkdocs.yml.
- Настраиваем Gitlab CI для генерации статического сайта.
- Делаем свой docker-образ и добавляем в него плагин mkdocs-with-pdf для генерации PDF-файла («печать всего сайта»).
- Послесловие.
Перед началом
В этот раз мы публикуем не просто куски кода — мы выложили в открытый доступ весь «боевой» репозиторий с текущей документацией, а также скриптами сборки этого сайта.
Самые нетерпеливые могут сразу посмотреть репозиторий на сайте gitlab.com.
Что такое генератор статического сайта? И почему был выбран именно MkDocs?
Генератор статического сайта это программа, собирающая полноценный сайт из одного или нескольких шаблонов, а также материалов для сайта.
Создание или редактирование статического сайта выполняется предельно просто:
- Владелец создаёт новый файл или редактирует существующий в человекочитаемом формате (например, в markdown).
- Далее запускается генератор статического сайта — и результатом работы он выдаёт сайт в виде набора html-страниц с уже применённой темой, форматированием, построенным оглавлением и пр.
- Полученный сайт владелец уже может использовать локально. Ну или выложить на каком-либо хостинге — чтобы к нему могли получить доступ другие люди.
И важно отметить: для статических сайтов не требуется поддержка каких-либо серверных языков и/или баз данных — всё уже свёрстано и готово к использованию.
Минусом же статических сайтов является то, что все пользователи будут видеть один и тот же контент (то есть сделать авторизацию, разделение на роли и прочее не получится).
На сегодняшний день список самых популярных систем, способных сгенерировать статические сайты, достаточно небольшой:
- Jekyll. Написан на Ruby, его использует Github для Github Pages (вероятно потому, что один из создателей Jekyll — сооснователь github?).
- Hugo. Написан на Go, позиционирует себя как самый быстрый генератор статических сайтов.
- Sphinx. Написан на Python. Именно с его помощью сгенерирована документация к языку Python.
- MkDocs. Также написан на Python.
MkDocs был выбран как самый популярный генератор на Github (на момент написания статьи у репозитория MkDocs было более 12 тыс. «звёздочек»). А больше всего приглянулся его форк с красивой (по моему мнению) встроенной темой, называемый Material for MkDocs. А всё потому, что сгенерированный с его помощью сайт из коробки предоставлял и гибкую вёрстку, и человекочитаемые url-ы, и встроенный быстрый поиск по всем статьям (который не требует какой-либо серверной реализации).
Создание и генерация тестового сайта
Для того, кто не очень знаком с языком Python, но немного представляет что такое контейнеризация, проще всего воспользоваться MkDocs с использованием их docker-образа.
При подготовке этого материала использовалась ОС Linux (дистрибутив Debian 10).
Перед созданием первого сайта на компьютере выполним в терминале (bash) команду docker pull squidfunk/mkdocs-material
для загрузки docker-образа mkdocs.
На заметку: команды docker pull
и docker run
могут требовать прав суперпользователя. Соответственно, если для выполнения команды не хватает прав, перейдите в режим суперпользователя командой su
или воспользуйтесь командой sudo
.
Как создать новую папку с материалами для сайта
-
Выберите папку, в которой будут храниться материалы для генерации сайта (например,
/home/user/test/
). -
Откройте в указанной папке терминал (или перейдите в существующем терминале в нужную папку (например, командой
cd /home/user/test/
). -
Выполните в открытом терминале команду
В результате в нашей папке появятся два новых файла:
Файл mkdocs.yml
— это файл конфигурации, используемый MkDocs. Файлы, находящиеся в папке docs
(в частности, index.md) — это исходные материалы, из которых в дальнейшем будет сгенерирован наш сайт.
Как сгенерировать сайт по существующим материалам
Выполните в терминале, открытом в папке с материалами (папке с файлом mkdocs.yml) команду
В результате в папке с материалами появилась подпапка site
, в которую генератор записал наш только что созданный сайт. Выглядит он следующим образом:
Как пересоздавать сайт “на лету” при внесении изменений в файлы
MkDocs умеет также создавать превью сайта «на лету», отслеживая изменения в исходных материалах в реальном времени и перестраивая только их. Для включения такого режима выполните в терминале, открытом в папке с материалами (папке с файлом mkdocs.yml) команду
Пока команда выполняется (прервать её можно, нажав комбинацию клавиш Ctrl+C), на вашем компьютере на порту 8000 будет запущен веб-сервер, который вы можете использовать для просмотра результатов ваших правок на сайте. Просто откройте браузер, введите в строке адреса http://localhost:8000/ — и смотрите как выглядит сгенерированный сайт (правда, для обновления текущий страницы придётся нажимать F5).
Как и на каком языке писать материалы для генератора MkDocs?
Генератор сайтов MkDocs в качестве исходных материалов поддерживает файлы как формата markdown (.md) так и формата html.
Стоп-стоп, скажете вы. Html? Зачем нам генерировать сайт из “материалов” на языке html, если результат — всё равно html?!
Дело в том, MkDocs не только преобразовывает markdown в html, но и корректно применяет к этим страницам темы, а также даёт простор для работы своим многочисленным плагинам, которые: осуществляют подсветку кода, индексируют содержимое для быстрого поиска, могут сгенерировать PDF-содержимое одной страницы или всего сайта и т.д.
Таким образом давайте условимся: исходные материалы это то, что содержит информацию и минимум применения сложных разметки, стилей и прочего, а сгенерированный сайт это результат работы генератора, содержащий те же тексты, что и в исходных материалах, но уже с применёнными темами и иным добавленным генератором содержимым.
Что же писать в исходных материалах?
Да в принципе всё, что захотите. MkDocs полностью поддерживает синтаксис markdown. Для примера картинка с markdown-текстом слева и сгенерированным из него html справа:
Текст в формате markdown и как он выглядит после преобразования в html:
Более подробно о формате markdown и о том, как оформлять такие документы, написано в шпаргалке по markdown.
И, — что для меня оказалось очень важно — MkDocs совершенно нормально относится к html-тэгам как внутри html, так и внутри markdown-файлов.
Нам это пригодилось для вставки в начало некоторых страниц справки html-плеера с видеоуроком по той же теме, что описана в материале.
Пример встраивания youtube-плеера в наш help
Разбираем структуру файла mkdocs.yml
Давайте подробнее изучим содержимое созданного на предыдущем шаге файла mkdocs.yml
Негусто.
К счастью, все сайты с документацией по MkDocs собраны с помощью генератора MkDocs и можно посмотреть содержимое mkdocs.yml, к примеру, сайта https://www.mkdocs.org/.
Приведём содержимое этого файла с дополнительными комментариями, на что влияют указанные в файле параметры:
# [Обязательное] Название сайта
site_name: MkDocs
# Базовый адрес сайта
site_url: https://www.mkdocs.org/
# Описание сайта. Добавляется в meta в html-заголовке каждой страницы.
site_description: Project documentation with Markdown.
# Автор (или авторы) сайта. Добавляется в html-заголовок каждой страницы.
site_author: MkDocs Team
# Ссылка на репозиторий, в котором хранятся исходные материалы.
repo_url: https://github.com/mkdocs/mkdocs/
# Относительный путь, который в сочетании со ссылкой на репозиторий (repo_url)
# и относительным адресом страницы даст адрес, по которому можно вызвать
# редактор страницы. Для repo_url-ов известных площадок (например,
# GitHub или GitLab можно оставить пустым - он подставится автоматически)
edit_uri: ""
# Информация о теме, которая будет применена для сгенерированного сайта.
# И её параметрах
theme:
name: mkdocs
locale: en
analytics: {gtag: 'G-274394082'}
highlightjs: true
hljs_languages:
- yaml
- django
# Структура навигации генерируемого сайта.
nav:
- Home: index.md
- Getting Started: getting-started.md
- User Guide:
- Overview: user-guide/index.md
- Installation: user-guide/installation.md
- Writing Your Docs: user-guide/writing-your-docs.md
- Choosing Your Theme: user-guide/choosing-your-theme.md
- Customizing Your Theme: user-guide/customizing-your-theme.md
- Localizing Your Theme: user-guide/localizing-your-theme.md
- Configuration: user-guide/configuration.md
- Deploying Your Docs: user-guide/deploying-your-docs.md
- Developer Guide:
- Overview: dev-guide/index.md
- Themes: dev-guide/themes.md
- Translations: dev-guide/translations.md
- Plugins: dev-guide/plugins.md
- About:
- Release Notes: about/release-notes.md
- Contributing: about/contributing.md
- License: about/license.md
extra_css:
- css/extra.css
# Список подключённых расширений для препроцессора языка Markdown
markdown_extensions:
- toc:
permalink:
- admonition
- attr_list
- def_list
- mdx_gh_links:
user: mkdocs
repo: mkdocs
copyright: Copyright © 2014 <a href="https://twitter.com/_tomchristie">Tom Christie</a>.
# Список использованных плагинов MkDocs
plugins:
- search
- redirects:
redirect_maps:
user-guide/plugins.md: dev-guide/plugins.md
user-guide/custom-themes.md: dev-guide/themes.md
user-guide/styling-your-docs.md: user-guide/choosing-your-theme.md
На что хочется обратить внимание в структуре навигации из примера выше:
- Путь страницы в url будет сгенерирован из
site_url
и относительного пути страницы в репозитории. Например, страницаUser Guide -> Overview
будет доступна по urlhttps://www.mkdocs.org/user-guide/index.html
(потому, что файл, из которого сгенерировали страницу, имел относительный путьuser-guide/index.md
). - Один файл можно указать в навигации и более одного раза.
- Если файл отсутствует в разделе
nav
— соответствующая страница всё равно будет сгенерирована, но не будет показана в навигации сайта. При этом перейти на неё, зная её url (см. первый пункт списка), вполне себе можно. - Плагин redirects (подробнее об использовании плагинов расскажу чуть ниже) позволяет настроить переадресацию страниц со старого расположения на новое.
Более подробно о структуре файла mkdocs.yml а также на то, как он влияет на используемую тему, расскажет подробная справка на сайтах mkdocs.org, Material for mkdocs а также примеры файлов mkdocs.yml в других репозиториях.
Настраиваем Gitlab CI и Gitlab Runner для генерации статического сайта
Следующий этап — это добавление сайта в систему контроля версии (СКВ) и написание скрипта, который сам собирал бы нам сайт как только мы сохраним новую его версию.
Воспользуемся git-ом как СКВ и Gitlab CI для обработки действий.
Внимание. У вас может возникнуть вопрос: а зачем мы, собственно, настраиваем Gitlab CI, если выше была показана команда serve, которая на лету создаёт сайт и поддерживает его в актуальном состоянии при изменениях в файлах?
Ответ включает как минимум следующие пункты:
- Команда
serve
не обеспечивает сохранение истории изменений, а СКВ для этого и предназначена. - Команда
serve
не предназначена для работы в production-окружении. В частности, serve может «сломаться» если при очередной сборке произошла ошибка (например, структура mkdocs.yml стала некорректной).
Поскольку многие читатели знакомы с git, я уберу под спойлер инструкцию по созданию репозитория и его сохранению (пушу) в Gitlab.
Теперь, когда репозиторий создан и связан с Gitlab, создадим в папке с исходными материалами файл .gitlab-ci.yml. О структуре этого файла мы кратко рассказывали в предыдущей публикации. Посему не будем подробно останавливаться на структуре, лишь приведём код файла:
stages:
- build
build_docs_job:
stage: build
# tags: docker # раскомментируйте эту строку если вам
# потребуются метки для определения конкретного Runner-а
# (см. ниже)
only:
- /^master$/
- merge_requests
image:
name: squidfunk/mkdocs-material
entrypoint: [""]
script:
- 'mkdocs build --site-dir site'
artifacts:
name: "site_$($CI_PIPELINE_IID)"
paths:
- site
Этим файлом мы указали Gitlab CI собирать сайт каждый раз, когда появляются новые коммиты в ветке master или в процессе создания или обновления merge request-ов.
Конечно, для того, чтобы это заработало, потребуется установить Gitlab Runner на машину, которая и будет собирать сайт по написанной в файле .gitlab-ci.yml «инструкции».
На заметку: подробную и актуальную инструкцию по установке Gitlab Gunner на ту сборку ОС Linux, что установлена у вас, можно посмотреть на сайте документации Gitlab.
Ниже для примера мы приведём пошаговую инструкцию как это сделать для ОС Debian Linux:
- Посмотрите токен для регистрации Runner-а в вашем Gitlab. В зависимости от того, где будет доступен ваш Runner:
- только в одном проекте — смотрите токен в меню проекта Settings > CI/CD в разделе Runners,
- в группе проектов — смотрите токен в меню группы Settings > CI/CD в разделе Runners,
- для всех проектов Gitlab-а — смотрите токен в секции администрирования, меню Overview > Runners.
- Найдите актуальную для вашей архитектуры версию Gitlab Runner на сайте https://gitlab-runner-downloads.s3.amazonaws.com/latest/index.html.
- Скачайте нужный deb-пакет с помощью браузера или команды в терминале
curl -LJO "https://gitlab-runner-downloads.s3.amazonaws.com/latest/deb/gitlab-runner_${arch}.deb"
, где${arch}
следует заменить на выбранную вами архитектуру. - Выполните в терминале команду для установки скачанного пакета Gitlab Runner
sudo dpkg -i gitlab-runner_<arch>.deb
где<arch>
опять же, следует заменить на выбранную вами архитектуру. - Зарегистрируйте раннер командой
sudo gitlab-runner register
Далее потребуется ввести ответы на вопросы мастера регистрации Runner-а: - coordinator URL — http или https адрес вашего сервера gitlab;
- gitlab-ci token — введите токен, полученный на предыдущем шаге;
- gitlab-ci description — описание Runner-а, которое будет показываться в интерфейсе Gitlab-а;
- gitlab-ci tags — через запятую введите тэги для Runner-а. Если вы не знакомы с этим механизмом, оставьте поле пустым. Отредактировать его можно позднее через интерфейс самого gitlab-а. Тэги можно использовать для того, чтобы определённые задачи выполнялись на определённых Runner-ах (например, чтобы настроить сборку ПО на Runner-е, развёрнутом на компьютере ОС Windows, а подготовку документации на Runner-е с ОС Linux);
- enter the executor — ответьте
docker
. На этом шаге указывается оболочка, в которой будут выполняться команды.
На заметку: если у вас несколько runner-ов с разными исполнителями (например, shell для сборки ПО, а docker для сбора документации), настройте тэги для этого раннера. Для этого добавьте в тэги раннера, например, слово docker
— и уберите первый символ решётки (#) из файла .gitlab-ci.yml. Ну или аналогичным образом настройте тэг с другим именем.
Проверим работу того, что настроили — сделаем коммит с созданным кодом. Можно прямо в ветку master, если, конечно, вы работаете в тестовом репозитории. В ином случае рекомендуем создать отдельную ветку с этими изменениями, затем создать на эту ветку merge request.
Так выглядит настроенная автосборка
Делаем свой docker-образ и добавляем в него плагин для генерации PDF-файла
Что ж, в целом проект уже работает. Однако для того, чтобы им воспользоваться, требуется либо соединение с интернетом, либо передать клиенту много html-страничек. Но что если требуется, к примеру, распечатать все материалы? Давайте настроим экспорт всего сгенерированного сайта в формат PDF и добавим его в артефакты Gitlab CI.
Стандартный функционал MkDocs сделать печать в PDF не позволят — но не беда, для этого и многих других функций сам генератор поддерживает плагины. И нас будет интересовать плагин mkdocs-with-pdf.
Чтобы добавить его в docker-образ генератора, потребуется модифицировать этот образ. И сделать это можно буквально в пару строк:
-
Создайте в папке с файлом mkdocs.yml новый файл с именем dockerfile
-
Добавьте в него следующие строки:
FROM squidfunk/mkdocs-material
RUN pip install mkdocs-with-pdf
- Откройте страницу Container Registry в вашем проекте в Gitlab (<адрес вашего проекта в gitlab>/container_registry, на картинке стрелочки 1 и 2), подсмотрите на ней имя образа, которое следует использовать при сборке (стрелочка 3).
Страница Container Registry в Gitlab
- Откройте терминал в папке с файлом Dockerfile и выполните в нём команду сборки модифицированного образа:
sudo docker build -t <имя образа, которое следует использовать> .
С вероятностью 100% сборка образа закончится ошибкой так как образ squidfunk/mkdocs-material
основан на Alpine Linux, где многие компоненты (типа компилятора gcc) по умолчанию отсутствуют. Чтобы образ собрался корректно. нам понадобится перед установкой пакета загрузить все необходимые не связанные с python-ом зависимости для него.
После дописывания зависимостей (которые были у плагина на момент написания статьи) файл Dockerfile будет выглядеть следующим образом:
FROM squidfunk/mkdocs-material
RUN apk add build-base ttf-ubuntu-font-family libffi-dev zlib-devlibwebp-dev jpeg-dev harfbuzz-dev fribidi-dev freetype-devcairo-dev musl-dev pango-dev gdk-pixbuf-dev&& pip install mkdocs-with-pdf
- Когда сборка завершилась успехом, авторизуемся на сервере gitlab через докер, после чего загружаем полученный образ на сервер:
docker login <имя образа для сервера gitlab, указанное на странице Container Registry>
docker push <имя образа для сервера gitlab, указанное на странице Container Registry>
И осталось только отредактировать mkdocs.yml чтобы включить в нём сборку сайта в PDF-файл. Для этого добавим раздел plugins, в котором перечислим все включаемые плагины (в данном случае только один — with-pdf
), а также их параметры.
site_name: My Docs
# На заметку: без явного указания темы пересобранный с плагином образ material-mkdocs сайт собрать не может
theme:
name: material
plugins:
- with-pdf:
cover: true
cover_title: My Docs
cover_subtitle: версия для PDF
copyright: (C) 2021 Rostelecom PJSC
toc_title: Оглавление
toc_level: 3
output_path: ./help.pdf
Пара слов об использованных параметрах:
- cover_title — заголовок, который будет указан на сгенерированной странице PDF. Может отличаться от названия сайта.
- cover_subtitle — подзаголовок, который будет указан на сгенерированной странице PDF.
- copyright — копирайт.
- toc_title — название оглавление (по умолчанию contents).
- toc_level — оглавление по умолчанию строится сначала по структуре навигации, а затем по заголовкам в документе. Параметр toc_level указывает максимальный уровень заголовка, который включается в оглавление. Например, значение 3 говорит о том, что все заголовки от первого до третьего уровня (h1 — h3).
- output_path — путь имя сгенерированного pdf-файла.
Полный их список доступен на странице плагина.
Запускаем в терминале сборку сайта (уже нашим образом)
docker run --rm -it -v ${PWD}:/docs <имя образа для сервера gitlab, указанное на странице Container Registry> build
И убеждаемся, что в корневой папке появился файл help.pdf
со всем содержимым сайта, а также кликабельным оглавлением
Сгенерированный вместе с сайтом pdf-файл
Послесловие
На текущий момент мы продолжаем улучшать генерацию сайта со справочной информацией, а также стараемся наполнять и поддерживать его.
В рамках этой статьи были рассказаны лишь основы, однако мы уже двигаемся дальше:
- Добавлен плагин
monorepo
для сборки сайта из нескольких отдельно живущих папок с материалами. Мы скомбинировали плагинmonorepo
с плагиномwith-pdf
чтобы можно было собирать и отдельные части сайта в PDF (будут только некоторые тонкости при указании папки с переопределениями темы при генерации части сайта). - Включены плагины
search
(поиск по сайту) иgit-revision-date
(чтобы отображать дату последнего изменения страницы). - Тема сайта дорабатывается под корпоративные стандарты.
- Также дорабатывается возможность автогенерации PDF-файла для справки прямо в процессе сборки нашего ПО (так как, в частности, материалы из раздела «Настольное приложение» поставляются вместе с ПО «Настольное приложение Видеонаблюдение»).
Если у вас будут вопросы — пишите в комментариях, мы с радостью ответим. А или предложения по улучшению — merge request-ы мы просматриваем достаточно оперативно.