cloud-castle / html-builder
Объектная модель HTML+CSS+JS для PHP 8.1+: класс на каждый DOM-элемент, объекты атрибутов, стилей, событий и значений, цепочки методов (fluent), генерация и разбор HTML, CSS и JavaScript, CSS-селекторы и обход дерева, минификация и форматирование, потоковый рендеринг на генераторах. Безопасно по умо
Requires
- php: >=8.1
- ext-json: *
- ext-mbstring: *
- cloud-castle/file-system: ^1.4
- cloud-castle/serialize: ^1.2
- cloud-castle/support: ^1.2
Requires (Dev)
- deptrac/deptrac: ^3.0 || ^4.0
- ergebnis/composer-normalize: ^2.45
- friendsofphp/php-cs-fixer: ^3.75
- icanhazstring/composer-unused: ^0.9
- infection/infection: ^0.29 || ^0.33
- php-parallel-lint/php-parallel-lint: ^1.4
- phpmd/phpmd: ^2.15
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^1.12 || ^2.1
- phpstan/phpstan-deprecation-rules: ^1.2 || ^2.0
- phpstan/phpstan-phpunit: ^1.4 || ^2.0
- phpstan/phpstan-strict-rules: ^1.6 || ^2.0
- phpunit/phpunit: ^10.5 || ^11.5
- psalm/plugin-phpunit: ^0.19 || ^0.20
- rector/rector: ^1.2 || ^2.0
- roave/security-advisories: dev-latest
- squizlabs/php_codesniffer: ^3.12 || ^4.0
- vimeo/psalm: ^6.0
- webmozart/assert: ^1.11
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-28 00:28:05 UTC
README
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano
CloudCastle HtmlBuilder
Пакет собирает и разбирает HTML, CSS и JavaScript через объектную модель, в которой объектом является каждый элемент, атрибут, свойство стиля, значение и событие.
Пакет
Репозитории
Качество кода
Установка
composer require cloud-castle/html-builder
Требуется PHP 8.1+ и расширения json, mbstring. Никаких других расширений не нужно:
разбор HTML, CSS и JavaScript выполняется на чистом PHP, поэтому пакет работает одинаково
на любом хостинге и в любом контейнере.
Быстрый старт
<?php
use CloudCastle\HtmlBuilder\Html;
use CloudCastle\HtmlBuilder\Css\Value\Color;
use CloudCastle\HtmlBuilder\Event\Event;
use CloudCastle\HtmlBuilder\Event\Handler\CallHandler;
$card = Html::div()->id('карточка')->addClass('card')
->style(['display' => 'flex', 'gap' => '1rem'])
->title('Товар из каталога')
->append(
Html::img()->src('/изображения/товар.png')->alt('Товар')->loading('lazy'),
Html::h2()->addClass('card__title')->text('Кофемолка'),
Html::span()->addClass('card__price')->style(['color' => Color::hex('#2f6f3e')])->text('4 900 ₽'),
Html::button()->type('button')
->on(Event::click(CallHandler::of('cart.add', 17)))
->text('В корзину'),
);
echo $card->render();
<div class="card" id="карточка" title="Товар из каталога" style="display: flex; gap: 1rem"><img src="/изображения/товар.png" alt="Товар" loading="lazy"><h2 class="card__title">Кофемолка</h2><span class="card__price" style="color: #2f6f3e">4 900 ₽</span><button type="button" onclick="cart.add(17)">В корзину</button></div>
Разбор работает в обе стороны: разметку можно прочитать, обойти селекторами, изменить и снова вывести.
$document = Html::fromFile('страница.html');
foreach ($document->querySelectorAll('ul.catalog > li.item > a') as $link) {
$link->attr('rel', 'nofollow')->addClass('external');
}
echo $document->render(RenderOptions::pretty());
Возможности
- Объектная модель документа. Отдельный класс на каждый из 211 тегов разметки, у каждого — типизированные методы своих атрибутов и общий набор глобальных атрибутов.
- Атрибут — объект. Обычный, логический, перечислимый, адресный, набора данных, доступности, класса, стиля и обработчика события: каждый вид знает свои правила вывода и проверки.
- Стили объектами. 187 типизированных методов свойств, значения-объекты (цвет, размер, функция,
переменная, список), управляющие правила
@media,@supports,@font-face,@keyframes, раскрытие и сворачивание сокращённых свойств. - JavaScript объектами. Инструкции и выражения, литералы, обращения, вызовы, стрелочные функции, обработчики событий и сжатие кода с учётом автоматической расстановки точек с запятой, объединение файлов и карта кода Source Map v3.
- Разбор без расширений. HTML, CSS и JavaScript читаются на чистом PHP с восстановлением незакрытых тегов, неявным закрытием и пределами длины и вложенности.
- Выборка по селекторам CSS и по XPath. Комбинаторы
>,+,~, позиционные псевдоклассы,:has(),:is(),:where(),:not(), состояния формы, селекторы атрибутов и расчёт специфичности; рядом — подмножество XPath с осями, предикатами и чтением значений атрибутов, тоже безext-dom. - Безопасность по умолчанию. Экранирование по контексту, белые списки схем адресов, очистка
недоверенной разметки, запрет
expression()иjavascript:в стилях, пределы против разметки-бомбы. - Доводка пользовательского содержимого. Абзацы из переводов строк, ссылки вместо адресов в тексте, приведение адресов к абсолютным и пометка внешних ссылок.
- Потоковая выборка. Селектор применяется прямо к потоку лексем: совпадения находятся без построения дерева — быстрее, чем по дереву, и с расходом памяти, не зависящим от документа.
- Потоковый вывод. Разметка отдаётся генератором, потоковый писатель и потоковая очистка работают без построения дерева: расход памяти не зависит от размера документа.
- Перенос между процессами. Дерево сериализуется в JSON, XML и YAML и восстанавливается обратно.
Полный список — в каталоге возможностей: страница на каждую из 66 возможностей с примером, который сверяется исполнением при каждой сборке, сравнением с аналогами и схемой места возможности в работе пакета.
Сравнение с аналогами
Все таблицы ниже сгенерированы автоматически из честных сравнительных тестов
(composer docs:compare) на ОДИНАКОВОЙ операции для всех аналогов, PHP 8.1.34, без Xdebug.
Перечень возможностей — объединение наборов всех десяти пакетов, а не только сильные стороны
этого.
1. Функциональность
| Возможность | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Построение разметки | |||||||||||
| Объектная модель документа с деревом узлов | ✅ | ✅ | ✅ | ⚠️ dom | ✅ | ⚠️ dom | ❌ | ❌ | ❌ | ❌ | |
| Отдельный класс на каждый тег разметки (211 тегов) | ✅ | ❌ | ⚠️ частично | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Типизированные методы атрибутов у каждого элемента | ✅ | ❌ | ⚠️ частично | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Глобальные атрибуты отдельными методами | ✅ | ❌ | ⚠️ частично | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Атрибут — объект (логический, перечислимый, адресный, данные, aria) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Потоковая запись разметки без дерева узлов | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Вывод генератором (потоковая отдача частями) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Форматированный вывод с отступами | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | |
| Сборка документа с каркасом (html, head, body) | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Копирование поддерева (глубокая копия) | ✅ | ✅ | ❌ | ⚠️ dom | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Разбор разметки | |||||||||||
| Разбор HTML без расширения ext-dom | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | |
| Потоковый токенизатор (генератор лексем) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Восстановление незакрытых и перекрёстных тегов | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | |
| Неявное закрытие тегов (li, td, p) | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | |
| Сырой текст script, style, textarea, title | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | |
| Пределы длины и вложенности против разметки-бомбы | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | |
| Позиция ошибки (строка и столбец) в сообщении | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | |
| Разбор фрагмента и документа по отдельности | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | |
| Раскодирование ссылок на символы при разборе | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | |
| Выборка и обход | |||||||||||
| Выборка по селекторам CSS | ✅ | ❌ | ❌ | ⚠️ xpath | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | |
| Комбинаторы >, +, ~ и вложенные списки селекторов | ✅ | ❌ | ❌ | ❌ | ⚠️ частично | ✅ | ❌ | ❌ | ❌ | ❌ | |
| Позиционные псевдоклассы (nth-child, nth-of-type) | ✅ | ❌ | ❌ | ❌ | ⚠️ частично | ✅ | ❌ | ❌ | ❌ | ❌ | |
| Псевдоклассы :has(), :is(), :where(), :not() | ✅ | ❌ | ❌ | ❌ | ❌ | ⚠️ частично | ❌ | ❌ | ❌ | ❌ | |
| Псевдоклассы состояния формы (:checked, :required) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Селекторы атрибутов со всеми операторами и флагом i | ✅ | ❌ | ❌ | ❌ | ⚠️ частично | ✅ | ❌ | ❌ | ❌ | ❌ | |
| Ленивый обход дерева генератором | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Расчёт специфичности селектора | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Поиск ближайшего предка по селектору (closest) | ✅ | ❌ | ❌ | ❌ | ❌ | ⚠️ частично | ❌ | ❌ | ❌ | ❌ | |
| Выборка по записи XPath без расширения ext-dom | ✅ | ❌ | ❌ | ⚠️ dom | ⚠️ dom | ⚠️ dom | ❌ | ❌ | ❌ | ❌ | |
| Чтение значений атрибутов записью XPath | ✅ | ❌ | ❌ | ⚠️ dom | ⚠️ dom | ⚠️ dom | ❌ | ❌ | ❌ | ❌ | |
| Выборка по селектору без построения дерева | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Значения, текст и разметка совпадений потоком | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| CSS | |||||||||||
| Объектная модель таблицы стилей | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | |
| Типизированные методы на каждое свойство (187) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Значения-объекты: цвет, размер, функция, переменная | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ⚠️ частично | ❌ | ❌ | ❌ | |
| Управляющие правила (@media, @supports, @font-face) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | |
| Разбор записи цвета и перевод между форматами | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ⚠️ частично | ❌ | ❌ | ❌ | |
| Контраст и относительная яркость цвета | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Сжатие таблицы стилей | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | |
| Отбор правил по элементу с учётом специфичности | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Раскрытие и сворачивание сокращённых свойств | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ⚠️ устарело | ❌ | ❌ | ❌ | |
| JavaScript | |||||||||||
| Объектная модель кода (инструкции и выражения) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Разбор кода в объектную модель | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Сжатие кода с учётом автоматических точек с запятой | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ⚠️ без разбора | |
| Обработчики событий как объекты | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Безопасная передача данных PHP в код (литералы) | ✅ | ✅ | ⚠️ частично | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Объединение файлов кода при сжатии | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | |
| Карта кода для сжатых скриптов | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Безопасность | |||||||||||
| Экранирование по контексту (текст, атрибут, CSS, JS, URL) | ✅ | ⚠️ частично | ⚠️ частично | ⚠️ частично | ❌ | ❌ | ❌ | ⚠️ частично | ⚠️ частично | ❌ | |
| Белый список схем адресов | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | |
| Очистка разметки по белым спискам | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | |
| Потоковая очистка без дерева | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Отбор свойств инлайнового стиля при очистке | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | |
| Запрет выражений CSS и адресов javascript: в стилях | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ⚠️ частично | ❌ | |
| Защита от подмены схемы через ссылки на символы | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | |
| Пределы разбора против отказа в обслуживании | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | |
| Абзацы из пользовательского текста | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | |
| Адреса в тексте становятся ссылками | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | |
| Приведение адресов к абсолютным | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | |
| Пометка внешних ссылок | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | |
| Переносимость и сопровождение | |||||||||||
| Работа без расширений PHP, кроме json и mbstring | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | |
| Сериализация дерева в JSON, XML, YAML и обратно | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | |
| Чтение и запись файлов разметки | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | |
| Единый фасад для всех операций | ✅ | ⚠️ частично | ⚠️ частично | ❌ | ❌ | ❌ | ❌ | ⚠️ частично | ❌ | ❌ | |
| Строгая типизация и уровень max статического анализа | ✅ | ⚠️ частично | ✅ | ❌ | ⚠️ частично | ⚠️ частично | ⚠️ частично | ❌ | ⚠️ частично | ❌ | |
| Документация на шести языках | ✅ | ⚠️ частично | ❌ | ❌ | ❌ | ⚠️ частично | ❌ | ❌ | ⚠️ частично | ❌ | |
| Всего | 🏆 66 | 4 | 3 | 9 | 11 | 9 | 6 | 17 | 9 | 4 |
🏆 Победитель: cloud-castle/html-builder — 66 / 66; ближайший: ezyang/htmlpurifier (17).
2. Покрытие возможностей
| Решение | Возможностей | Доля | Итог |
|---|---|---|---|
| 🏆 cloud-castle/html-builder | 66 / 66 | 100% | лучшее среди аналогов |
| ezyang/htmlpurifier | 17 / 66 | 26% | аналог |
| voku/simple_html_dom | 11 / 66 | 17% | аналог |
| masterminds/html5 | 9 / 66 | 14% | аналог |
| symfony/dom-crawler + css-selector | 9 / 66 | 14% | аналог |
| symfony/html-sanitizer | 9 / 66 | 14% | аналог |
| sabberworm/php-css-parser | 6 / 66 | 9% | аналог |
| nette/utils (Html) | 4 / 66 | 6% | аналог |
| matthiasmullie/minify | 4 / 66 | 6% | аналог |
| yiisoft/html | 3 / 66 | 5% | аналог |
🏆 Победитель: cloud-castle/html-builder — 66 / 66; ближайший: ezyang/htmlpurifier (17).
3. Производительность
Одинаковая операция для всех аналогов, минимум из повторов, без Xdebug.
Построение документа объектной моделью (200 блоков)
| Решение | Показатель | Итог |
|---|---|---|
| nette/utils (Html) | нет данных | аналог |
| yiisoft/html | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Построение документа потоковой записью (200 блоков)
| Решение | Показатель | Итог |
|---|---|---|
| nette/utils (Html) | нет данных | аналог |
| yiisoft/html | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Разбор документа 24 КБ в объектную модель
| Решение | Показатель | Итог |
|---|---|---|
| masterminds/html5 | нет данных | аналог |
| voku/simple_html_dom | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Разбор и выборка по селектору «ul.catalog > li.item > a»
| Решение | Показатель | Итог |
|---|---|---|
| symfony/dom-crawler + css-selector | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Разбор и выборка по записи XPath «//ul[…]/li[…]/a»
| Решение | Показатель | Итог |
|---|---|---|
| symfony/dom-crawler + ext-dom | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Выборка по селектору «ul.catalog > li.item > a» без построения дерева
| Решение | Показатель | Итог |
|---|---|---|
| symfony/dom-crawler + css-selector | нет данных | аналог |
| voku/simple_html_dom | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Разбор таблицы стилей из 200 правил
| Решение | Показатель | Итог |
|---|---|---|
| sabberworm/php-css-parser | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Очистка недоверенной разметки 21 КБ деревом
| Решение | Показатель | Итог |
|---|---|---|
| ezyang/htmlpurifier | нет данных | аналог |
| symfony/html-sanitizer | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Очистка недоверенной разметки 21 КБ потоком
| Решение | Показатель | Итог |
|---|---|---|
| ezyang/htmlpurifier | нет данных | аналог |
| symfony/html-sanitizer | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Сжатие кода JavaScript 14 КБ
| Решение | Показатель | Итог |
|---|---|---|
| matthiasmullie/minify | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
4. Потребление памяти
Пиковая память процесса на тех же сценариях, изолированный запуск на каждый случай.
Построение документа объектной моделью (200 блоков)
| Решение | Показатель | Итог |
|---|---|---|
| nette/utils (Html) | нет данных | аналог |
| yiisoft/html | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Построение документа потоковой записью (200 блоков)
| Решение | Показатель | Итог |
|---|---|---|
| nette/utils (Html) | нет данных | аналог |
| yiisoft/html | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Разбор документа 24 КБ в объектную модель
| Решение | Показатель | Итог |
|---|---|---|
| masterminds/html5 | нет данных | аналог |
| voku/simple_html_dom | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Разбор и выборка по селектору «ul.catalog > li.item > a»
| Решение | Показатель | Итог |
|---|---|---|
| symfony/dom-crawler + css-selector | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Разбор и выборка по записи XPath «//ul[…]/li[…]/a»
| Решение | Показатель | Итог |
|---|---|---|
| symfony/dom-crawler + ext-dom | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Выборка по селектору «ul.catalog > li.item > a» без построения дерева
| Решение | Показатель | Итог |
|---|---|---|
| symfony/dom-crawler + css-selector | нет данных | аналог |
| voku/simple_html_dom | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Разбор таблицы стилей из 200 правил
| Решение | Показатель | Итог |
|---|---|---|
| sabberworm/php-css-parser | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Очистка недоверенной разметки 21 КБ деревом
| Решение | Показатель | Итог |
|---|---|---|
| ezyang/htmlpurifier | нет данных | аналог |
| symfony/html-sanitizer | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Очистка недоверенной разметки 21 КБ потоком
| Решение | Показатель | Итог |
|---|---|---|
| ezyang/htmlpurifier | нет данных | аналог |
| symfony/html-sanitizer | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
Сжатие кода JavaScript 14 КБ
| Решение | Показатель | Итог |
|---|---|---|
| matthiasmullie/minify | нет данных | аналог |
| cloud-castle/html-builder | нет данных | аналог |
🏆 Победитель: нет данных.
5. Безопасность и корректность
| Возможность | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Экранирование по контексту (текст, атрибут, CSS, JS, URL) | ✅ | ⚠️ частично | ⚠️ частично | ⚠️ частично | ❌ | ❌ | ❌ | ⚠️ частично | ⚠️ частично | ❌ |
| Белый список схем адресов | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Очистка разметки по белым спискам | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Потоковая очистка без дерева | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Отбор свойств инлайнового стиля при очистке | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| Запрет выражений CSS и адресов javascript: в стилях | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ⚠️ частично | ❌ |
| Защита от подмены схемы через ссылки на символы | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Пределы разбора против отказа в обслуживании | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Абзацы из пользовательского текста | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| Адреса в тексте становятся ссылками | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| Приведение адресов к абсолютным | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| Пометка внешних ссылок | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| Всего | 🏆 12 | 0 | 0 | 0 | 0 | 0 | 0 | 10 | 4 | 0 |
🏆 Победитель: cloud-castle/html-builder — 12 / 12; ближайший: ezyang/htmlpurifier (10).
6. Стандарты безопасности
| Стандарт безопасности | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Файл SECURITY.md с политикой раскрытия уязвимостей | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ |
| Публикация рекомендаций по безопасности (security advisories) | ⚠️ частично | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Проверка зависимостей composer audit в непрерывной сборке | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ |
| Оценка OpenSSF Scorecard | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ |
| Статический анализ безопасности (Psalm taint, PHPStan) | ✅ | ⚠️ частично | ✅ | ❌ | ⚠️ частично | ⚠️ частично | ⚠️ частично | ❌ | ⚠️ частично | ❌ |
| Защита от CWE-79 (межсайтовое исполнение сценариев) | ✅ | ⚠️ частично | ⚠️ частично | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Защита от CWE-400 (исчерпание ресурсов при разборе) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ⚠️ частично | ⚠️ частично | ❌ |
| Защита от CWE-601 (перенаправление на недоверенный адрес) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Защита от CWE-1333 (отказ через регулярные выражения) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Тесты на попытки обхода защиты (XSS-набор) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Мутационное тестирование кода безопасности (MSI 100%) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Подписанные теги релизов | ❌ | ⚠️ частично | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ |
| Всего | 🏆 9 | 2 | 6 | 1 | 0 | 5 | 2 | 4 | 8 | 1 |
🏆 Победитель: cloud-castle/html-builder — 9 / 12; ближайший: symfony/html-sanitizer (8).
7. Качество кода
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Покрытие строк тестами | 100% | 95% | 100% | 92% | 87% | 96% | 93% | 75% | 97% | 90% |
| Индекс мутационного тестирования (MSI) | 100% | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных |
| Уровень PHPStan | 10 | 8 | 10 | 0 | 5 | 9 | 8 | 0 | 9 | 0 |
| Уровень Psalm (errorLevel, чем ниже — строже) | 1 | нет данных | 1 | нет данных | 4 | нет данных | нет данных | нет данных | нет данных | нет данных |
| Проверка стиля кода (PHPCS/PSR-12) | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| Контроль архитектурных слоёв (Deptrac) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Проверка мёртвого кода (PHPMD, Psalm unused) | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Тесты производительности и утечек памяти в сборке | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Русская документация с примерами на каждую возможность | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Всего | 🏆 9 | 1 | 5 | 0 | 1 | 1 | 1 | 0 | 1 | 0 |
🏆 Победитель: cloud-castle/html-builder — 9 / 9; ближайший: yiisoft/html (5).
8. Проверки по видам
Таблица на каждый вид проверки: синтаксис, Psalm, PHPStan, PHPMD, PHPCS, Rector, Deptrac, мутации, покрытие и утечки памяти.
Синтаксическая проверка (phplint)
Разбор каждого файла пакета на всех поддерживаемых версиях PHP.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Проверка синтаксиса в сборке | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| Версий PHP в матрице сборки | 5 | 5 | 4 | 4 | 4 | 4 | 4 | 3 | 4 | 4 |
| Всего | 🏆 2 | 🏆 2 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
🏆 Победитель: cloud-castle/html-builder, nette/utils (Html) — 2 / 2; ближайший: yiisoft/html (1).
Статический анализ Psalm
Строгость уровня и поиск неиспользуемого кода.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Уровень Psalm (чем ниже — строже) | 1 | нет данных | 1 | нет данных | 4 | нет данных | нет данных | нет данных | нет данных | нет данных |
| Поиск неиспользуемого кода (findUnusedCode) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Всего | 🏆 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
🏆 Победитель: cloud-castle/html-builder — 2 / 2; ближайший: yiisoft/html (1).
Статический анализ PHPStan
Уровень строгости и число оставленных исключений в базовой линии.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Уровень PHPStan | 10 | 8 | 10 | 0 | 5 | 9 | 8 | 0 | 9 | 0 |
| Записей в базовой линии (игнорируемых ошибок) | 0 | нет данных | 0 | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных |
| Всего | 🏆 2 | 0 | 🏆 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
🏆 Победитель: cloud-castle/html-builder, yiisoft/html — 2 / 2; ближайший: nette/utils (Html) (0).
Анализ сложности (PHPMD)
Чистота кода, неиспользуемые элементы и пороги сложности.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| PHPMD в сборке | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Замечаний PHPMD | 0 | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных |
| Всего | 🏆 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
🏆 Победитель: cloud-castle/html-builder — 2 / 2; ближайший: nette/utils (Html) (0).
Проверка стиля (PHPCS/PSR-12)
Единый стиль кода и отсутствие расхождений с PSR-12.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Проверка стиля в сборке | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| Замечаний стиля | 0 | нет данных | 0 | нет данных | нет данных | 0 | нет данных | нет данных | 0 | нет данных |
| Всего | 🏆 2 | 1 | 🏆 2 | 0 | 1 | 🏆 2 | 1 | 0 | 🏆 2 | 0 |
🏆 Победитель: cloud-castle/html-builder, yiisoft/html, symfony/dom-crawler + css-selector, symfony/html-sanitizer — 2 / 2; ближайший: nette/utils (Html) (1).
Проверка модернизации (Rector)
Код соответствует возможностям целевой версии PHP без устаревших конструкций.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Rector в сборке | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Предлагаемых правок | 0 | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных |
| Всего | 🏆 2 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
🏆 Победитель: cloud-castle/html-builder — 2 / 2; ближайший: yiisoft/html (1).
Контроль архитектурных слоёв (Deptrac)
Направление зависимостей между слоями проверяется автоматически.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Deptrac в сборке | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Нарушений слоёв | 0 | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных |
| Всего | 🏆 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
🏆 Победитель: cloud-castle/html-builder — 2 / 2; ближайший: nette/utils (Html) (0).
Мутационное тестирование
Мутанты, которых тесты не замечают, — мера настоящей полноты тестов.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Индекс мутационного тестирования (MSI) | 100% | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных |
| Выживших мутантов | 0 | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных |
| Всего | 🏆 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
🏆 Победитель: cloud-castle/html-builder — 2 / 2; ближайший: nette/utils (Html) (0).
Тесты безопасности
Отдельный набор тестов на попытки обхода защиты и на устойчивость разбора.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Набор тестов на обход защиты в сборке | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Тесты устойчивости к отказу через регулярные выражения | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Всего | 🏆 2 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
🏆 Победитель: cloud-castle/html-builder — 2 / 2; ближайший: ezyang/htmlpurifier (1).
Покрытие тестами
Доля строк и классов, исполняемых тестами.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Покрытие строк | 100% | 95% | 100% | 92% | 87% | 96% | 93% | 75% | 97% | 90% |
| Покрытие классов | 100% | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных |
| Всего | 🏆 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
🏆 Победитель: cloud-castle/html-builder — 2 / 2; ближайший: yiisoft/html (1).
Проверка утечек памяти
Рост памяти после повторного создания и уничтожения деревьев.
| Показатель | 🏆 CloudCastle | nette | yiisoft | masterminds | voku | crawler | sabberworm | purifier | sanitizer | minify |
|---|---|---|---|---|---|---|---|---|---|---|
| Проверка утечек в сборке | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Рост памяти за 1000 циклов | 0 | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных | нет данных |
| Всего | 🏆 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
🏆 Победитель: cloud-castle/html-builder — 2 / 2; ближайший: nette/utils (Html) (0).
О памяти честно. Пакет строит объектную модель, поэтому на разборе документа в 24 КБ занимает около 6 МБ против 2 МБ у обёрток над
ext-dom. В потоковых режимах — запись разметки, очистка, сжатие — расход падает до 2 МБ, и там пакет не уступает никому. Память — единственная ось, где он уступает при построении дерева; по функциональности, безопасности и качеству кода он лидирует.
Те же таблицы отдельными страницами: возможности, производительность и память, безопасность и стандарты, качество кода, проверки по видам.
Честно о плюсах и минусах
Плюсы
- Полная объектная модель: элемент, атрибут, стиль, значение, событие и узел скрипта — объекты с проверками, а не строки.
- Работает без расширений PHP, кроме
jsonиmbstring: одинаково на любом хостинге. - Самая быстрая потоковая запись разметки (0.78 мс против 1.11 мс), разбор таблицы стилей (2.1 мс против 18.8 мс) и потоковая очистка недоверенной разметки (4.7 мс против 7.0 мс), которая ещё и расходует меньше всех памяти — 2 МБ против 4 МБ у обоих санитайзеров.
- Выборка по дереву быстрее обёртки над
libxml: 5.5 мс против 6.8 мс по селектору CSS и 5.5 мс против 6.9 мс по записи XPath на документе 24 КБ — и это на чистом PHP, безext-dom. - Разбор документа быстрее
masterminds/html5(4.3 мс против 7.5 мс), хотя тот читает разметку расширениемlibxml. - Потоковая выборка находит совпадения без построения дерева: 4.0 мс против 6.7 мс у
symfony/dom-crawlerна документе 24 КБ, 2 МБ памяти вместо 6 МБ. - Безопасность заложена в типы: экранирование по контексту, охрана схем, пределы разбора.
- Покрытие тестами 100%, мутационный индекс 100%, статический анализ максимального уровня.
- Документация на шести языках и страница на каждую возможность.
Минусы
- Пакет моложе и менее распространён, чем аналоги: у него нет истории в десятки лет и тысяч зависимых проектов.
- Объектная модель тратит больше памяти, когда строит дерево: на документ в 24 КБ уходит около
6 МБ против 2 МБ у обёрток над
ext-dom. Это осознанный обмен памяти на функциональность — в потоковых режимах расход падает до 2 МБ, и там пакет не уступает никому. - Очистка деревом чуть уступает
symfony/html-sanitizerпо времени (7.2 мс против 7.0 мс на 21 КБ), опережая при этомezyang/htmlpurifier(8.1 мс); потоковая очистка того же содержимого быстрее обоих санитайзеров — 4.7 мс. - Чтение документа расширением
libxmlбыстрее на сырой скорости: там работает код на C, и на чистом PHP это не отыгрывается. Поэтому разбор в дерево — 4.3 мс против 1.3 мс уvoku/simple_html_dom, а потоковая выборка — 4.0 мс против его же 1.6 мс на 24 КБ. - Построение дерева объектной моделью медленнее строкового сборщика (3.4 мс против 1.1 мс на 200 блоков) — это плата за проверки и типы; потоковая запись той же разметки укладывается в 0.78 мс и обгоняет всех.
- Сжатие JavaScript медленнее
matthiasmullie/minify(1.95 мс против 0.84 мс на 14 КБ): наш минификатор разбирает код в лексемы и учитывает автоматическую расстановку точек с запятой, а не заменяет по регулярным выражениям — за счёт этого он не ломает код, где перевод строки завершает инструкцию.
Когда пакет подходит
- Генерация разметки в CRM и админках. Формы, таблицы, карточки собираются кодом, а не шаблонами: типизированные методы не дают выпустить неверный атрибут.
- Очистка пользовательского содержимого. Письма, комментарии, описания товаров: политика очистки описывается белыми списками, а потоковый режим держит память под контролем.
- Письма и выгрузки. Инлайновые стили, XML-карты, выгрузки на сотни мегабайт — потоковый писатель пишет разметку частями.
- Обработка чужих страниц. Разбор, выборка по селекторам, правка и повторный вывод без расширений PHP — удобно для парсеров и импортёров.
- Проекты с требованиями к безопасности. Финтех и медицина: экранирование по контексту, охрана схем адресов и пределы разбора снижают риск внедрения кода.
Когда пакет не нужен: разовая склейка двух строк разметки (хватит sprintf) или задача
«прочитать текст большого документа как можно быстрее» — там выгоднее обёртка над ext-dom.
Разработка
composer ci
Команда выполняет всё, что проверяет сборка: линтеры, статический анализ, тесты, покрытие, проверку документации и примеров.
Полный прогон в порядке «синтаксис → Psalm → PHPStan → PHPMD → PHPCS → Rector → Deptrac → тесты → покрытие → мутации → безопасность → память → утечки → производительность → документация»:
composer test:all
Полный список команд — composer list; описание каждой — в composer.json (раздел scripts-descriptions).
Документация
- Оглавление документации — разделы по темам
- Каталог возможностей — страница на каждую возможность
- Быстрый старт · Архитектура · Безопасность · Память
- Руководство в формате RST: быстрый старт, архитектура, безопасность, сравнение
- Wiki пакета
- Сопровождение: история изменений · порядок обновления · как внести вклад · поддержка · управление проектом · политика безопасности · кодекс поведения
Лицензия
MIT. Подробности — в файле LICENSE.
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano