Очиститель HTML: Преобразование в
Предпосылка
Я хотел бы использовать Очиститель HTML для преобразования тегов <body>
в теги <div>
, чтобы сохранить встроенный стиль элемента <body>
, например, <body style="background:color#000000;">Hi there.</body>
превратится в <div style="background:color#000000;">Hi there.</div>
. Я смотрю на комбинацию пользовательского тега и класса TagTransform
.
Текущая настройка
В моем разделе конфигурации я в настоящее время делаю следующее:
$htmlDef = $this->configuration->getHTMLDefinition(true);
// defining the element to avoid triggering 'Element 'body' is not supported'
$bodyElem = $htmlDef->addElement('body', 'Block', 'Flow', 'Core');
$bodyElem->excludes = array('body' => true);
// add the transformation rule
$htmlDef->info_tag_transform['body'] = new HTMLPurifier_TagTransform_Simple('div');
...а также разрешить <body>
и его style
(и class
, и id
) атрибут через конфигурацию директивы (они являются частью рабочего большого списка, который разбирается на HTML.AllowedElements
и HTML.AllowedAttributes
).
Я отключил кэширование определений.
$config->set('Cache.DefinitionImpl', null);
К сожалению, в этой настройке кажется, что HTMLPurifier_TagTransform_Simple
никогда не вызывается метод transform()
.
HTML.Родитель?
Я предполагаю, что виновником является мой HTML.Parent
, для которого установлено значение 'div'
, поскольку, вполне естественно, <div>
не допускает дочернего элемента <body>
. Однако установка HTML.Parent
на 'html'
приводит меня в замешательство:
Исключение ошибки: Невозможно использовать нераспознанный элемент в качестве родительского
Добавление...
$htmlElem = $htmlDef->addElement('html', 'Block', 'Flow', 'Core');
$htmlElem->excludes = array('html' => true);
...избавляется от этого сообщения об ошибке, но по-прежнему не преобразует тег - вместо этого он удаляется.
Добавление...
$htmlElem = $htmlDef->addElement('html', 'Block', 'Custom: head?, body', 'Core');
$htmlElem->excludes = array('html' => true);
...также ничего не делает, потому что он выдает мне сообщение об ошибке:
ErrorException: Trying to get property of non-object
[...]/library/HTMLPurifier/Strategy/FixNesting.php:237
[...]/library/HTMLPurifier/Strategy/Composite.php:18
[...]/library/HTMLPurifier.php:181
[...]
Сейчас я все еще работаю с последним вариантом, пытаясь определить точный синтаксис, который мне нужно предоставить, но если кто-то знает, как мне помочь, основываясь на своем собственном прошлом опыте, я был бы признателен любые указатели в правильном направлении.
Уровень HTML.tidylevel?
Как единственный другой виновник, которого я могу себе представить, мой HTML.TidyLevel
установлен в 'heavy'
. Я еще не перепробовал все возможные созвездия на этом, но пока это не имеет никакого значения.
(Поскольку я касался этого только вторично, я изо всех сил пытаюсь вспомнить, какие созвездия я уже пробовал, чтобы не перечислять их здесь, но сейчас мне не хватает уверенности, что я не пропущу что-то, что я сделал или неправильно что-то понял. Я возможно, я отредактирую этот раздел позже, когда проведу специальное тестирование!)
Полная конфигурация
Мои данные конфигурации хранятся в JSON, а затем анализируются в очистителе HTML. Вот файл:
{
"CSS" : {
"MaxImgLength" : "800px"
},
"Core" : {
"CollectErrors" : true,
"HiddenElements" : {
"script" : true,
"style" : true,
"iframe" : true,
"noframes" : true
},
"RemoveInvalidImg" : false
},
"Filter" : {
"ExtractStyleBlocks" : true
},
"HTML" : {
"MaxImgLength" : 800,
"TidyLevel" : "heavy",
"Doctype" : "XHTML 1.0 Transitional",
"Parent" : "html"
},
"Output" : {
"TidyFormat" : true
},
"Test" : {
"ForceNoIconv" : true
},
"URI" : {
"AllowedSchemes" : {
"http" : true,
"https" : true,
"mailto" : true,
"ftp" : true
},
"DisableExternalResources" : true
}
}
(URI.Base
, URI.Munge
и Cache.SerializerPath
также установлены, но я удалил их в этой вставке. Кроме того, HTML.Parent
предостережение: Как уже упоминалось, обычно это значение равно 'div'
.)
2 answers
Этот код является причиной того, что то, что вы делаете, не работает:
/** * Takes a string of HTML (fragment or document) and returns the content * @todo Consider making protected */ public function extractBody($html) { $matches = array(); $result = preg_match('!<body[^>]*>(.*)</body>!is', $html, $matches); if ($result) { return $matches[1]; } else { return $html; } }
Вы можете отключить его с помощью %Core.Преобразуйте documenttofragment как false; если остальная часть вашего кода не содержит ошибок, он должен работать прямо оттуда. Я не верю, что ваше определение тела необходимо.j
Не было бы намного проще сделать:
$search = array('<body', 'body>');
$replace = array('<div', 'div>');
$html = '<body style="background:color#000000;">Hi there.</body>';
echo str_replace($search, $replace, $html);
>> '<div style="background:color#000000;">Hi there.</div>';