Доброго времени суток! Хочу поделиться радостной новостью! Недавно я успешно завершил разработку и довел до производственной готовности проект @texditor/editor — мощного и легкого блочного редактора контента. И самое крутое то, что его уже можно «пощупать». На данный момент он интегрирован на этом сайте и именно с его помощью написано это сообщение! Редактор достиг стабильной версии, которую я считаю сильным базовым релизом. Хотя документация еще в процессе разработки 😄, первый серьезный шаг сделан!
Преодоление вызовов
Честно признаюсь, этот проект дался мне невероятно тяжело. Я погнался за двумя зайцами: хотел создать редактор с идеально современным, интуитивным интерфейсом и при этом начинить его всеми мыслимыми функциями. Эта гонка за идеалом на стыке юзабилити и функциональности оказалась настоящим испытанием, но невероятно продуктивной.
Интеграция и тестирование
Переход от тестирования к реальной эксплуатации редактора выявил серьезные проблемы, связанные с безопасностью, валидацией входящих данных и целостностью их структуры. Стандартных методов, таких как экранирование и последовательная очистка блоков, оказалось недостаточно для гарантии надежности. Осознавая ответственность не только за свои проекты, но и за продукты других разработчиков, я принял решение о разработке специализированной библиотеки. Её ключевыми функциями стали комплексная фильтрация, строгая валидация, обеспечение структурной целостности данных и рендеринг в чистый HTML для сторонников классического подхода.
Для тех кому уже не терпится, проект расположен на github https://github.com/texditor/blockify-php или установку через composer.
composer require texditor/blockify-php
Структура
После тщательного анализа десятков возможных архитектурных решений я остановился на варианте, который сочетает в себе простоту реализации и современный, элегантный синтаксис.
src/ ├── Exceptions/ # Специализированные исключения ├── Interfaces/ # Фундаментальные интерфейсы │ ├── ConfigInterface.php │ ├── BlockModelInterface.php │ └── RenderableInterface.php ├── Models/ # Модели блоков с правилами обработки ├── Blockify.php # Основной класс-обработчик ├── BlockModel.php # Базовая модель блока ├── Config.php # Единый источник конфигурации └── HtmlBuilder.php # Рендерер HTML
Модели блоков
Приоритетными направлениями были объявлены простота установки и расширение функционала для обработки блочных моделей:
<?php
namespace Texditor\Blockify\Models;
use Texditor\Blockify\BlockModel;
class CodeBlock extends BlockModel
{
protected string $inputName = 'code';
protected string $outputName = 'pre';
protected array $allowedTags = [];
protected bool $isPreformatted = true;
}
По сути это и есть готовая модель, которую можно сразу использовать. "Под капотом" у неё уже есть множество методов, так как она наследует их от BlockModel. Чтобы сделать модель идеально подходящей для ваших нужд, просто создайте на её основе свой класс и внесите нужные правки.
Использование
Библиотека реализована таким образом, что её можно использовать как в среде с сервис-контейнерами (например, в рамках Laravel, Symfony), так и в стандартных PHP-условиях с обычным инстанцированием классов (пример взят из Github).
<?php
use Texditor\Blockify\Blockify;
use Texditor\Blockify\Config;
use Texditor\Blockify\Models\ParagraphBlock;
use Texditor\Blockify\Models\CodeBlock;
use Texditor\Blockify\Models\FilesBlock;
use Texditor\Blockify\Models\GalleryBlock;
use Texditor\Blockify\Models\HeaderBlock;
use Texditor\Blockify\Models\OrderedListBlock;
use Texditor\Blockify\Models\UnorderedListBlock;
// Создаем конфигурацию и добавляем модели блоков
$config = (new Config())
->addModels(
(new ParagraphBlock())
->setAllowedTags(['a', 'b']),
new CodeBlock(),
(new FilesBlock())
->setSourceProtocols(['https', 'http'])
->setSourceProtocols(['https', 'http'])
// or only locally
->setSourceRegex(["/^\/uploads\/.*\.(png|jpg|jpeg|gif)$/"]),
(new GalleryBlock())
// ->setIsMeta(true)
// ->setIsMetaCaption(true)
// ->setIsMetaDesc(false)
->setMetaPosition('top')
->setImageTypes(['image/png', 'image/jpeg'])
->setVideoTypes(['video/mp4'])
->setVideoAttributes([
'controls' => 'true'
]),
new UnorderedListBlock(),
new OrderedListBlock(),
// Default h1
new HeaderBlock(),
(new HeaderBlock())
->setOutputName('h2')
->setInputName('h2'),
//...
);
// Получаем данные в виде строки
$jsonData = $_POST['data'] ?? '';
// Запускаем процесс чистки и валидации
$blockify = (new Blockify($config))
->setData($jsonData);
// Получаем безопасные данные
$blocks = $blockify->getData();
Рассмотрим в сравненнии с обычным HTML-кодом:
<!-- И из простого "Привет мир" (даже с большим количеством пробелов)--> <p>Привет мир! <script>alert();</script></p>
// Получаем JSON со списком блоков
[
{
"type": "p"
"data": "Привет мир <script>alert();</script>"
}
]
// и разумеется все теги будут экранированы, т.к не являются частью структуры данныхДобавив в параграф дополнительные данные, такие как полужирный текст, мы получаем массив с несколькими уровнями вложенности, отражающий иерархическую структуру контента.
<h2>Заголовок</h2> <p>Привет мир! Добавим не много <b>жирного</b> в наш рацион.</p> <pre><?php echo</pre>
[
{
"type" : "h2",
"data" : [
"Заголовок"
]
},
{
"type" : "p",
"data" : [
"Привет мир! Добавим не много ",
{
"type" : "b",
"data" : [
"жирного "
]
},
"в наш рацион."
]
},
// Эти данные будут экранированы
{
"type" : "code",
"data" : [
"<?php echo"
]
}
]Заключение
Blockify PHP — это получилась не просто библиотека безопасности, а комплексное решение для работы с структурированным контентом. Она покрывает более 90% типичных требований при работе с данными редактора контента, обеспечивая:
- 🔒 Безопасность: Многоуровневая защита от XSS и инъекций
- 🏗️ Структуру: Четкая семантическая организация контента
- 🔧 Гибкость: Легкое расширение и кастомизация
- 🚀 Производительность: Оптимизированная обработка больших данных
- 🔌 Интегрируемость: Работа с любым PHP-фреймворком
Нет элементов для отображения