WYSIWYG с контентным

Долгий и трудный путь к созданию WYSIWYG!

Прежде всего, чтобы понять мою боль, прочтите статью « Почему contenteditable - это ужасно », написанную Ником Сантосом, инженером-программистом @Medium.

И, если этого будет недостаточно, вы можете получить более четкое представление о содержании, прочитав « ContentEditable - хорошее, плохое и уродливое » Пиотрека Кошулиньского , Ведущий разработчик CKEditor.

Прочитав статьи выше, вы можете спросить: ПОЧЕМУ! Скажите только ПОЧЕМУ !? Что ж, потому что заключается в том, что альтернативы не подходят для проектов, которые мы разрабатываем для нашего Client @ fleka. Мы попробовали несколько редакторов WYSIWYG, в том числе CKEditor и Redactor, но когда эти инструменты переходят в руки конечных пользователей (то есть наших клиентов), проблемы начинают выскакивать; они, конечно, не могут управлять содержимым HTML, и они, конечно же, копируют и вставляют текст из любого источника (например, Word), неся с собой множество странных тегов и элементов HTML.

Не поймите меня неправильно, CKEditor - это очень мощный проект с открытым исходным кодом, управляемый сообществом, и вы действительно можете сделать с ним МНОГО вещей; Я просто пытался найти более элегантное и простое решение для наших проектов AngularJS, создав компонент AngularJS, который можно было бы легко реализовать во всех наших веб-приложениях. CKEditor оказалось сложно включить в наш процесс минификации (на базе Grunt), и, чтобы не забыть, во fleka мы всегда стремимся к наилучшему возможному UX: с помощью CKEditor нам совсем непросто настроить его. идеально вписаться в наш индивидуальный дизайн.

Redactor, с другой стороны, помимо своей цены, он оказался полезным для наших проектов, его легко настроить и интегрировать с пользовательским кодом, и он довольно хорошо вписывается в наши проекты, но создает действительно много автоматических и бесполезных (на по крайней мере для меня) HTML-элементы, которые, на мой взгляд, имеют тенденцию усложнять работу редакторов контента, потому что очень легко вставить текст в неправильные элементы, даже если вы не заметите этого, если не проверите HTML-код / ​​представление доступно в редакторе Redactor.

Итак, давайте проясним это: вам НЕ нужно создавать свой личный редактор WYSIWYG, особенно если у вас нет возможности посвятить ему месяцы: contenteditable не является стандартом и он создает несколько разных проблем в разных браузерах, поэтому вы не хотите идти по этому пути, если только вы не знаете, что делаете, но также в этом случае подумайте об этом дважды, пожалуйста! ;)

Открытие удовлетворенного

Когда я захотел углубиться в эту тему, я начал изучать HTML-код редактора Medium, и я проделал то же самое с редактором Redactor. И после первых дней знакомства с contenteditable = ”true” я начал понимать, что все не так просто, как казалось. По умолчанию браузеры начинают добавлять ‹span› и действуют таким образом, что создают настоящий беспорядок и путаницу внутри HTML-кода, поэтому предстоит много работы «за кулисами» чтобы исправить все эти действия по умолчанию.

Вот несколько примеров с Redactor:

Здесь вы можете видеть, что Redactor оставляет 2 узла ‹strong› полностью разделенными и не пытается преобразовать слово в один единственный узел. Мне лично вообще не нравится такое поведение по умолчанию.

Теперь посмотрим, как CKEditor справляется с той же ситуацией:

CKEditor определенно работает лучше, удаляя один из двух элементов ‹strong› и добавляя второй узел внутри первого. Но, тем не менее, это слово остается как 2 разделенных текстовых узла; Я думаю, что с точки зрения HTML это намного лучше, чем результат Redactor, но опять же я хотел бы иметь только один элемент с одним текстовым узлом для этой конкретной ситуации.

Наконец, после первых дней разработки, вот пример нашего индивидуального решения:

Редактор достаточно умен, чтобы удалить второй элемент ‹b›, добавить текстовый узел к первому и «нормализовать» его к одному элементу с единственным текстовым узлом внутри. Но мы хотим использовать ‹strong›, и я не буду раздражать вас по поводу причин его использования вместо ‹b›, потому что вы можете легко выполнить поиск в Google по этой теме.

Пользовательский редактор DOM

Когда вы устанавливаете элемент HTML, скажем ‹div›, как contenteditable, вы ожидаете, что сразу же сработают несколько общих действий, но печальная правда заключается в том, что вместо этого вам нужно исправить многие из этих поведений. , чтобы иметь возможность создавать хорошую семантику из вставленного текста, когда вставка, форматирование и новые строки создаются в самом contenteditable. Вот почему я начал создавать собственный редактор DOM, который, среди прочего, должен:
- заботиться о преобразовании элементов в правильные (без добавления стиля и диапазона здесь и там);
- перехватывать события клавиатуры для правильного запуска пользовательских методов;
- позаботьтесь об отмене / возврате действий с помощью настраиваемого диспетчера отмены.

- Менеджер семантического кода

По умолчанию элемент contenteditable будет использовать ‹b› и ‹i›, потому что он не предназначен для создания семантического кода, и поэтому нам нужно позаботиться о преобразовании элементов в ‹strong› и ‹i› (и наоборот, что означает, что необходимо разрешить удаление форматирования текста, который, например, уже выделен жирным шрифтом).
После этого хороший редактор контента должен как минимум позаботиться о списков ‹ul› (упорядоченных и неупорядоченных, конечно), обратите внимание, чтобы не допускать странных вложенных элементов, форматировать разрешенные вложенные элементы определенным образом и т. д.

- Диспетчер событий клавиатуры

Другими событиями, которые необходимо обрабатывать вручную, являются сочетания клавиш клавиатуры, например, для преобразования выделенного текста, выделенного жирным шрифтом, или для предотвращения отмены по умолчанию и запуска настраиваемого диспетчера отмены. Это также важно, чтобы перехватить действие вставки и очистить текст, когда он копируется из внешнего источника (например, Word), сохраняя базовое форматирование текста (полужирный, курсив, ссылки и т. Д.), Которое редактор должен поддерживать вне. из коробки.

- Менеджер истории (отменить / повторить)

После того, как я позаботился о семантическом HTML, настал момент, когда я понял, что мне нужно настраиваемое управление историей (Undo / Redo). Ура! Это связано с тем, что, когда вы обрабатываете узлы DOM самостоятельно, вы портите историю по умолчанию, которую браузер создает для вас, а это означает, что, когда вы отменяете одно действие, очень возможно, что браузер отменит appendChild () , но не удалит ни один узел, который вы удалили с помощью removeChild () в том же действии…
Очень хорошая статья об этом: « Обнаружить, отменить и повторить DOM меняется с помощью Mutation Observer » Адди Османи, инженером Google, который предлагает использовать Mutation Observer.

Следующие шаги…

Следующие шаги (которые я попытаюсь осветить в одном из следующих постов) будут:
- макет: разрешить возможность размещения определенных элементов;
- управление изображениями: загрузка / сохранение / получение изображений использовать их внутри редактора;

Если вам это интересно, напишите мне здесь.