Очиститель HTML: преобразование ‹body› в ‹div›

помещение

Я хочу использовать HTML Purifier для преобразования тегов <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> и его атрибута styleclass, и id) через директивы конфигурации (они являются частью рабочего большого списка, который анализируется на HTML.AllowedElements и HTML.AllowedAttributes).

Я отключил кэширование определений.

$config->set('Cache.DefinitionImpl', null);

К сожалению, в этой настройке кажется, что HTMLPurifier_TagTransform_Simple никогда не вызывал свой метод transform().

HTML.Родительский?

Я предполагаю, что виноват мой HTML.Parent, для которого установлено значение 'div', поскольку вполне естественно, что <div> не допускает дочерний элемент <body>. Однако установка HTML.Parent на 'html' приводит меня к следующему результату:

ErrorException: нельзя использовать нераспознанный элемент в качестве родителя

Добавление...

$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 Purifier. Вот файл:

{
    "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'.)


person pinkgothic    schedule 04.05.2010    source источник


Ответы (2)


Этот код является причиной того, что то, что вы делаете, не работает:

/**
 * 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.ConvertDocumentToFragment как false; если остальная часть вашего кода не содержит ошибок, она должна работать прямо оттуда. Я не верю, что ваше определение bodyElem необходимо.

person Edward Z. Yang    schedule 04.05.2010
comment
Командующий засадами, на помощь! Спасибо — круто, все работает! :D Для завершения (если кто-то еще наткнется на это): определение $bodyElem кажется необходимым. Я также был немного обеспокоен тем, что <title>blah</title> в последнем фрагменте вместо blah, но потом вспомнил, что я могу просто добавить 'head' в список Core.HiddenElements. Теперь это работает как шарм! - person pinkgothic; 05.05.2010
comment
И еще одно быстрое дополнение для завершения: <body> и его style-атрибут не обязательно должны быть в белом списке тегов, только тег, в который он преобразован (и его атрибут). - person pinkgothic; 05.05.2010

Не проще ли было бы сделать:

$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>';
person Ben    schedule 04.05.2010
comment
В окончательном выводе HTML Purifier, когда я знаю, что ничто вредоносное не пережило процесс, это, вероятно, действительно вариант. Однако, прежде чем я пропущу что-то с простой заменой строки, я бы предпочел знать, что могу положиться на решение; HTML Purifier надежно анализирует и размечает HTML, и, учитывая, что я совершенно уверен, что то, что я упускаю из виду, является небольшой проблемой, я определенно предпочел бы это решение. Но, тем не менее, спасибо. :) - person pinkgothic; 04.05.2010