Search code examples
phptypo3typo3-11.x

TYPO3 11 content element Plain HTML with <style>


TYPO3 11.5.4

I want to add a Plain HTML content element to a page, e.g.:

<style type="text/css">
  h1#testheader { font-weight: bold; }
</style>
<h1 id="testheader">
  Header
</h1>

(just as a simplified example)

But rendered output is:

<style type="text/css"> h1#testheader { font-weight: bold; } </style>
Header

I thought that style is allowed because I set:

lib.parseFunc.allowTags = ...,style,...
lib.parseFunc_RTE.allowTags = ...,style,...

but it doesn't work. Setting

lib.parseFunc.htmlSanitize = 0

helps but is there something better to allow <style> in Plain HTML content elements?

EDIT: Looking into the DB entry the html tags are not encoded, so no "<" or ">" instead of "<" and ">", so it's not an issue of the RTE.


Solution

  • After some more research (hours of hours again invested) I come to the conclusion that the only way is to extend the HTMLSanitizer.

    The following sources have been used for this solution:

    https://punkt.de/de/blog/2021/htmlsanitizer-in-typo3.html https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/9.5.x/Important-94484-IntroduceHTMLSanitizer.html https://gist.github.com/ohader/2239dab247e18d23e677fd1b816f4fd5

    The complete solution to allow <style>,<script> and <iframe> is shown below.

    Still I am not able to allow <font> with this approach!

    It's implemented in a local site package (gpcf_theme) and composer is used.

    Add <style>,<script> and <iframe> to

    lib.parseFunc.allowTags = ... style, ..., iframe, script, ...
    

    in the TypoScript part of the site package.

    style seems to be standard and is already part of this list.

    The path to the local site package is:

    local_packages/gpcf_theme
    

    with a symbolic link to it from:

    public/typo3conf/ext/gpcf_theme -> ../../../local_packages/gpcf_theme
    

    These are the important file changes:

    local_packages/gpcf_theme/composer.json:

    {
            "name": "oheil/gpcf_theme",
            ...
            "autoload": {
                    "psr-4": {
                            "Oheil\\GpcfTheme\\": "Classes/"
                    }
            },
            ...
    }
    

    local_packages/gpcf_theme/ext_localconf.php:

    <?php
    defined('TYPO3_MODE') || die();
    
    ...
    $GLOBALS['TYPO3_CONF_VARS']['SYS']['htmlSanitizer']['default'] = \Oheil\GpcfTheme\MyDefaultBuilder::class;
    ...
    

    local_packages/gpcf_theme/Classes/MyDefaultBuilder.php

    <?php
    
    namespace Oheil\GpcfTheme;
    
    use TYPO3\CMS\Core\Html\DefaultSanitizerBuilder;
    use TYPO3\HtmlSanitizer\Behavior;
    use TYPO3\HtmlSanitizer\Behavior\Attr;
    use TYPO3\HtmlSanitizer\Behavior\Tag;
    
    class MyDefaultBuilder extends \TYPO3\CMS\Core\Html\DefaultSanitizerBuilder
    {
        protected function createBehavior(): \TYPO3\HtmlSanitizer\Behavior
        {
            // https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/9.5.x/Important-94484-IntroduceHTMLSanitizer.html
    
            return parent::createBehavior()
                    ->withName('common')
                    ->withTags(
                            (new Tag(
                                    'style',
                                    Tag::ALLOW_CHILDREN + Behavior::ENCODE_INVALID_TAG
                            ))->addAttrs(
                                    (new Attr('type')),
                                    ...$this->globalAttrs
                            ),
                            (new Tag(
                                    'iframe',
                                    Tag::ALLOW_CHILDREN
                            ))->addAttrs(
                                    ...array_merge(
                                            $this->globalAttrs,
                                            [$this->srcAttr],
                                            $this->createAttrs('scrolling', 'marginwidth', 'marginheight', 'frameborder', 'vspace', 'hspace', 'height', 'width')
                                    )
                            ),
                            (new Tag(
                                    'script',
                                    Tag::ALLOW_CHILDREN
                            ))->addAttrs(
                                    ...array_merge(
                                            $this->globalAttrs,
                                            [$this->srcAttr]
                                    )
                            ),
                            // more tags...
            );
        }
    }
    

    After these changes of course you need to clear the TYPO3 cache and (not sure here) you need to do:

    composer remove "oheil/gpcf_theme"
    composer require "oheil/gpcf_theme"
    

    The above is working now, but I am still happy for any expert to give some more insights in what is wrong or can be done better, perhaps easier?

    And why does this not work for <font> ? Example:

    <font class="font713099">Some Text</font>