История создания Editor.js — модульного визуального редактора от команды студентов CodeX
На его основе работает редактор vc.ru, TJ и DTF.
Три с половиной года разработки, 24 репозитория, 500 закрытых пулл-реквестов и бессчётное число коммитов — большой opensource-проект готов к выходу из беты.
Если быть точным, это вторая версия проекта, в которой мы решили изменить название редактора с CodeX Editor на Editor.js, попутно переписав его с нуля. В статье я расскажу о пути, который прошла команда от первых набросков до релиза на Product Hunt.
CodeX
Осенью 2015 года состоялась первая встреча клуба веб-разработки: студенты и молодые разработчики сформировали команду энтузиастов для изучения новых технологий, экспериментов и исследований. На второй встрече, вместе с запуском сайта, нам понадобился визуальный редактор, в котором мы могли бы писать статьи о своих экспериментах. В тот же вечер в репозиторий CodeX Editor был отправлен первый коммит.
Сегодня CodeX — это по-прежнему небольшая команда, но с большой (97 репозиториев!) инфраструктурой собственных opensource-библиотек и микросервисов, интегрированных друг с другом. А CodeX Editor 2.0 или Editor.js — один из наших крупнейших и основных проектов.
О редакторе
Основная концепция — блочная структура и чистые данные в виде JSON на выходе. В отличие от большинства редакторов, где пользователь работает с текстом внутри одной редактируемой обертки, в Editor.js каждый структурный элемент статьи — блок — это отдельный редактируемый элемент.
Блоки могут быть какие угодно: абзацы, заголовки, цитаты, списки, изображения, твиты, опросы и так далее.
После сохранения редактор возвращает данные о каждом блоке.
Каждый блок — это отдельный плагин. Задача самого редактора — предоставить удобный API для простой разработки любых плагинов и обеспечить взаимодействие пользователя с материалом: выделение, перемещение и удаление блоков, обработку вставки текста и так далее. Инструменты форматирования и панели настроек блока также формируются плагинами.
Именно простота API и стала самой сложной и самой удачной идеей.
Первая версия
Рабочий концепт был готов через несколько недель разработки, но для выпуска первой стабильной версии потребовался ещё год. Каждый раз, изменяя код, мы обсуждали главные вопросы: будет ли удобно разработчикам плагинов, не повысит ли это порог входа, универсальное ли выбрано решение.
В качестве образцов блоков мы написали первые плагины: «Параграф», «Заголовок», «Картинка», «Список» и еще некоторые. Старались придумать примеры разных сценариев: от простого набора и оформления текста до плагинов, взаимодействующих с серверной частью. Это позволило развивать API, который даёт возможность создать абсолютно любой плагин.
Например, плагин Twitter по вставленной в текст ссылке должен был формировать виджет твита. Для этого на страницу надо предварительно подключить Twitter SDK — так в API появился метод 'prepare'. При инициализации редактор собирает prepare всех плагинов, запускает их и дожидается завершения перед отрисовкой интерфейса.
Осенью 2016 года мы внедрили первую версию на наш сайт, а также в контент-сервис CodeX Media. Примерно в это же время в «Комитете» началась разработка новой модульной платформы для изданий Osnova — и в качестве редактора выбрали CodeX Editor.
Форк Paragraph
В «Комитете» на всех платформах развиваются мощные UGC-сообщества. Каждый пользователь может написать и опубликовать материал, а одна из задач платформы — снизить шансы на то, что вёрстка будет некачественная и некрасивая.
Другими словами, на сервере происходит подробная валидация и очистка данных каждого блока материала, которые приводятся к нужной структуре. Для этих задач наш редактор, возвращающий аккуратный JSON вместо обычного HTML-кода, подходит как нельзя лучше.
Помимо этого, JSON-структура позволяет легко извлекать нужные данные из материала. Например, можно получить первый блок с картинкой и использовать его как обложку для соцсетей в meta-информации. Или получить первый текстовый блок и выводить его в ленте.
Опять же за счет блочной структуры, материалы можно верстать отдельно для веба и мобильных приложений, для Instant Articles, Google AMP и даже озвучивать голосом.
Уже за первые месяцы работы редактора на DTF удалось поправить большое количество мелких багов и узких необработанных кейсов.
Чтобы разграничить зоны ответственности, мы создали приватный форк CodeX Editor, получивший название Paragraph. Он решает задачи платформы, развиваясь, совершенствуя дизайн и повышая стабильность. Основной упор сделали на разработку новых плагинов и совершенствование имеющихся.
На сегодняшний день разработка Editor.js и Paragraph ведется параллельно.
Вторая версия
Лето 2017 года. Мы в CodeX решили устроить ивент: снять на неделю коттедж в лесу на берегу озера и днями и ночами работать плечом к плечу, осваивая новую область технологий: AR.
О том, что у нас в итоге получилось, можно рассказать отдельную историю. Но в перерывах между изучением всевозможных SDK, пока кто-то ложился поспать, а кто-то наоборот просыпался, был создан прототип второй версии редактора.
К тому времени кодовая база одного только ядра Editor.js уже насчитывала более десяти модулей и десятки тысяч строк кода — подступило время рефакторинга, пересмотра архитектуры и реализации когда-то придуманных концептов.
Впрочем, рефакторингом это можно назвать с натяжкой — код ядра, а затем и плагинов, был полностью переписан с нуля.
- Появилась возможность инициировать несколько редакторов на странице параллельно.
- Полностью обновлен и проработан API: убраны избыточные методы, названия и структура стали более логичными, появились новые возможности. Обратной совместимостью решили пожертвовать — слишком уж хорош получался новый интерфейс, а клиентов, кроме нас самих, к тому времени практически не было, ведь проект нигде не анонсировался.
- Появился API для разработки не только плагинов для блоков, но и инструментов форматирования — выделения фрагментов текстов маркером, вставки инлайнового кода, ссылок и так далее.
- Настройки блоков тоже стали плагинами: например, можно создать настройку «Спойлер», которая появится у всех блоков и будет сворачивать их содержимое.
- Проект был полностью переписан на TypeScript. Это повысило надежность и улучшило структуру модулей.
- Появилась подробная документация API и циклы гайдов по написанию плагинов.
На реализацию новых возможностей и переписывание кода ушел ни много ни мало год. И летом 2018 года мы анонсировали открытое бета-тестирование проекта.
Бета-тестирование
Запуск беты мы анонсировали в нашем небольшом паблике и Telegram-канале. Несмотря на малое число подписчиков, появились заинтересованные в продукте люди, и со временем их становилось все больше.
Чтобы было удобнее взаимодействовать с зарождающимся комьюнити, мы создали чат в Telegram, где можно сообщать об ошибках и задавать вопросы по разработке плагинов.
Это принесло свои результаты — в ходе тестирования многие моменты были улучшены, а на многие вещи удалось взглянуть со стороны. Где-то понадобилось улучшить документацию, а где-то изменить API.
Доработок и новых идей оказалось столько, что запланированный месяц тестирования вылился в пять. Где-то в середине мы поняли, что название CodeX Editor не самое удачное — большинство людей называли редактор просто CodeX. Домен editorjs.io оказался свободен.
Затянувшийся ремонт подошел к концу.
Релиз
Выпуск продукта оказался непростой задачей: требовалось не только протестировать код и сверстать лендинг, но и провести большой объем мероприятий по подготовке к запуску полноценного комьюнити.
Мы написали десятки гайдов и статей для разработчиков плагинов, сняли множество поясняющих GIF-анимаций, тщательно проработали документацию API, создали отдельную организацию на GitHub, в которой будут публиковаться лучшие плагины и дополнения.
За все время работы над проектом главным мотиватором каждого члена команды был предстоящий момент релиза. Под ним мы подразумевали публикацию проекта во всемирном хит-параде продуктов Product Hunt.
И сегодня этот день настал. Представляем вашему вниманию Editor.js 2.0 — новый редактор и новая большая opensource-история.
Отличный редактор !
А он открытый ? его в своих проектах юзать можно будет ?
(принцип тот же остался - на сервер типа массив параграфов уходить будет ?)
Спасибо !
Привет!
Исходный код открыт и выложен на гитхабе :)
Вот тут можно найти ядро — https://github.com/codex-team/editor.js, а здесь наши плагины — https://github.com/editor-js
Ядро распространяем под лицензией Apache-2.0 (можно делать все, что угодно, упоминая оригинальную лицензию), плагины под MIT.
Формат данных и другие подробности есть в документации — https://editorjs.io
Обожаю редакторы как на комитете, телеграфе, телетайпе и вордпрессе.ком (именно ком).
Крутая штука!
Восхищаюсь вашей работой. Спасибо большое! Как пользователь ранее использовал другие предложения рынка, но теперь я точно знаю куда смотреть) На ханте апвот оставил.
Подскажите, пожалуйста, на вашем сайте https://editorjs.io/ вижу примечание связанное с видео, но в редакторе тестирую возможности и его не нахожу. Как добавить видео? А второй вопрос, возможно ли добавлять иной код, например плейлист с Я.музыка?
Все зависит от плагинов, которые вы будете использовать. Для любой задачи можно написать свой плагин.
Мы написали несколько для примера:
https://github.com/editor-js
У нас есть плагин Image, который поддерживает загрузку гифок и mp4, но требуется серверная имплементация
Есть плагин Embed, который позволяет вставлять YouTube, Vimeo и тд по ссылкам. Кстати, Яндекс.Музыку тоже поддерживает.
Очень здорово! Этот мир нуждается в хороших WYSIWYG-редакторах :)
В сравнении с draft.js вы не стали пытаться работать с внутренним состоянием блока и просто оставили там html. Надо сказать, решение изящное (я в свое время не сработался с draft.js/slate.js — слишком много приходится кода вокруг писать, и результат не стабилен), но вдруг захочется большего? Например, есть ли возможность (или появится), сохранить в JSON блока дополнительные ключи с какими-либо данными и соответствует ли это философии проекта?
А можете вкратце написать, как вы работаете с состоянием (обновлением) редактора (понятно, что можно подсмотреть в коде), но хотелось бы ваш взгляд, почему сделали так, а не иначе. И проверяли ли на больших текстах (от 40 тыс. знаков)?
Наконец, вопрос про хранение в JSON. Если вы настраиваете поиск по тексту, насколько все усложняется? (логично хранить это в jsonb постгреса — подозреваю, что у вас так и есть)
Именно из-за усложнения вывода таких данных и не стали пока применять отдельные структуры для форматирования инлайн-фрагментов. Внутренние споры об этом ведем до сих пор. Но наша изначальная задумка — максимально низкий порог входа для разработчиков. В будущих обновлениях, возможно, появится выбор.
Про дополнительные поля в JSON — прямо в точку. Уже проектируем такой уровень API. Нужен нам для плагина комментариев.
Про состояние, если совсем кратко, используем Proxy. То есть у нас по сути написан реактивный диспетчер блоков — добавили или изменили блок в массиве, он изменился в DOM.
Про хранение JSON планируем написать отдельную заметку в документации. У нас по разному везде. Тут, например jsonb. Elasticsearch легко интегрируется.