Заметил за собой, что постоянно записываю всякие мелочи, полезную информацию, просто что-то из буфера обмена прямо в текстовом редакторе. Всегда где-то на фоне висит открытый Sublime Text с кучей вкладок.
И ещё я заметил, что мне удобнее всего структурировать информацию в одном файле используя синтаксис Markdown — приятнее именно исходный текст, а не результат, отображаемый на том же гитхабе.
Со временем я заметил, что таких сохраненных файлов накопилось немало, да и незакрытые вкладки убавляться не собираются. А ведь одно неосторожное движение и вся не сохранённая накопленная информация канет в небытие, да и с других устройств не посмотришь, и раскидывать по папочкам тоже не очень удобно.
Всё это привело меня к мысли написать что-то вроде своего движка для хранения всей информации в одном месте и в удобном виде. Да-да, есть куча всяких Evernote, каких-нибудь заметок, встроенных в MacOS/iOS и так далее, которые и синхронизируются, и фичи полезные имеют — но, как говорится, хочешь сделать что-то хорошо (для себя), сделай это сам. Да и, как почти любой программист, в любой непонятной ситуации я беру и пишу всё сам. Так вышло и в этот раз.
Зачем?
Подобные проекты уже существуют, да и вышеупомянутые сервисы-монстры тоже довольно удобны, но некоторые свои фичи в моём проекте дают некоторые преимущества.
В первую очередь его удобнее всего использовать как документацию для проекта (собственно, вдохновление пришло от сайта с документацией по Kotlin, откуда я и позаимствовал большую часть стилей для сгенерированного контента).
Проект полностью бесплатен и лежит в открытом доступе, ссылочка на гитхаб в конце статьи.
Что умеет?
- Генерация HTML на лету — результат не сохраняется. Уже готовые статьи можно целыми папками копировать в нужную директорию проекта. Все добавляемые и удаляемые файлы индексируются автоматически.
- Навигация тоже генерируется, а не хардкодится.
- Поиск по содержимому.
- Управление доступами — работает примерно как «группы» у организаций на гитхабе: каждой группе (я назвал их role) принадлежит список юзеров и список путей до папок/файлов, которые могут смотреть юзеры этой группы.
- При поиске, в навигации и т.д. юзер не увидит те страницы, к которым не имеет доступа.
- Статьи также можно добавлять в визуальном редакторе (в нём есть подсветка синтаксиса, кнопочки как на гитхабе, предпросмотр и т.д.)
- Всё легко конфигурируется через страницу с настройками, которая тоже сгенерирована (и добавлять новые пункты можно без труда). Итого — можно за пару команд установить локально проект, скинуть в папочку готовые Markdown-файлы, быстро настроить доступы и пользоваться.
- Куча других мелких фишек, вроде ссылок-якорей на все заголовки, кнопок для копирования над сниппетами с кодом и т.д. и т.п.
Как работает?
На чём?
Я использовал NodeJS
и express
, так как для меня данный стек показался самым минимально ресурсо-временезатратным для реализации этой конкретной задачи.
Права доступа
Логика довольно проста — passport
решает все проблемы с авторизацией. Права для пользователей и статей хранятся в MongoDB
, а пути до статей соответствуют путям до файлов на диске.
Сами «группы» нигде не хранятся, управление происходит «снизу»: у каждого юзера и пути (до статьи или категории — т.е. до файла и папки) есть свой список «ролей». Если у юзера есть хотя бы одна «роль» из списка пути, по которому он переходит, то считается, что у него есть доступ. Для просмотра любого пути юзер должен иметь доступ к самому пути и ко всем родительским: например, чтобы увидеть страницу /pages/Documentation/Habr
, нужно иметь доступ к /pages
, /pages/Documentation
и к /pages/Documentation/Habr
.
Если юзер может просматривать страницу, тогда обращаемся к файлу на диске, считываем его содержимое и отображаем.
Статьи
Для конвертации используется библиотека для Ruby
, которая называется kramdown
— все её фичи тоже поддерживаются.
После генерации HTML разметка встраивается в подготовленный шаблон, куда ещё встраивается сгенерированная навигация.
Генерация навигации работает довольно просто — рекурсивно получается полный список всех файлов и папок, затем они фильтруются по правам пользователя, а уже результативная структура «насаживается» на шаблон.
Поиск работает точно также.
Для оформления я использовал materialize
, стили с сайта документации Kotlin для самих статей, по мелочи брал идеи с редактора на гитхабе и т.д.
Исходный код доступен здесь: https://github.com/petersamokhin/nodejs-markdown-site
Не являюсь NodeJS
— или бэкенд-разработчиком, но люблю отвлечься на что-то интересное. Статью написал потому что подумал, что штука выглядит вполне полезной.
Да, есть аналоги с той же идеей (если честно, узнал уже после разработки) — но многих вышеописанных (и не описанных здесь) фич у них нет, а реализация выглядит сложнее: тот же сайт документации Kotlin хардкодит навигацию, из дополнительных фич умеет исполнять код и, вроде бы, всё, — хотя сам проект немаленький.
P.S. правил Хабра я, вроде бы, не нарушил и кроме ссылки на гитхаб и общего описания статья не содержит. Если вдруг люди проявят интерес, я могу написать серию статеек с подробным описанием всего процесса разработки или конкретных моментов — ибо одной статьёй здесь вряд ли получится отделаться.
Автор: Пётр Самохин