Bug #92194

ContentObjectRenderer wraps <img> tags in <p> tags

Added by Reindl Bernd about 1 year ago. Updated 3 months ago.

Status:
Needs Feedback
Priority:
Must have
Assignee:
-
Category:
-
Target version:
-
Start date:
2020-09-04
Due date:
% Done:

0%

Estimated time:
TYPO3 Version:
10
PHP Version:
Tags:
Complexity:
Is Regression:
Sprint Focus:

Description

$this->_parseFunc($data, $tagConfig) in ContentObjectRenderer::_parseFunc() where the tags are parsed returns a string wrapped in <p></p>.
E.G. $tag is img "$data = $this->_parseFunc($data, $conf);" returns "<p><img .....></p>" but should return "<img ....>".

I Think this happens because "$data = $this->_parseFunc($data, $conf);" uses $conf als param. But i think it should use $tagConfig instead.

if (strpos($data, '<') !== false && isset($conf['tags.']) && is_array($conf['tags.'])) {
foreach ($conf['tags.'] as $tag => $tagConfig) {
// only match tag `a` in `<a href"...">` but not in `<abbr>`
if (preg_match('#<' . $tag . '[\s/>]#', $data)) {
$data = $this->_parseFunc($data, $conf);
break;
}
}
}

if (strpos($data, '<') !== false && isset($conf['tags.']) && is_array($conf['tags.'])) {
foreach ($conf['tags.'] as $tag => $tagConfig) {
// only match tag `a` in `<a href"...">` but not in `<abbr>`
if (preg_match('#<' . $tag . '[\s/>]#', $data)) {
$data = $this->_parseFunc($data, $tagConfig);
break;
}
}
}


Files

rte_ckeditor_image.zip (644 KB) rte_ckeditor_image.zip Reindl Bernd, 2021-01-22 06:52
#1

Updated by Reindl Bernd about 1 year ago

Still in 10.4.9

#2

Updated by Reindl Bernd about 1 year ago

Idle since 3 months :(

#3

Updated by Benni Mack 10 months ago

  • Subject changed from ContentObjectRenderer to ContentObjectRenderer wraps <img> tags in <p> tags
  • Status changed from New to Needs Feedback

Thanks for your report.

Can you send me your:
  • lib.parseFunc / lib.parseFunc_RTE
  • example content which is handed into the method?
#4

Updated by Reindl Bernd 10 months ago

Benni Mack wrote in #note-3:

Thanks for your report.

Can you send me your:
  • lib.parseFunc / lib.parseFunc_RTE
  • example content which is handed into the method?

TYPO3 10.4.12 "Fluid Content Elements (fluid_styled_content)
@# Creates persistent ParseFunc setup for non-HTML content.
lib.parseFunc {
makelinks = 1
makelinks {
http {
keep = {$styles.content.links.keep}
extTarget = {$styles.content.links.extTarget}
}
mailto {
keep = path
}
}
tags {
a = TEXT
a {
current = 1
typolink {
parameter.data = parameters:href
title.data = parameters:title
ATagParams.data = parameters:allParams # the target attribute takes precedence over config.intTarget
target.ifEmpty.data = parameters:target # the target attribute takes precedence over the constant (styles.content.links.extTarget) # which takes precedence over config.extTarget # do not pass extTarget as reference, as it might not be set resulting in the string being # written to the target attribute
extTarget.ifEmpty < config.extTarget
extTarget.ifEmpty.override = {$styles.content.links.extTarget}
extTarget.override.data = parameters:target
}
}
}
allowTags = {$styles.content.allowTags}
denyTags = *
sword = <span class="ce-sword">|</span>
constants = 1
nonTypoTagStdWrap {
HTMLparser = 1
HTMLparser {
keepNonMatchedTags = 1
htmlSpecialChars = 2
}
}
}

  1. Creates persistent ParseFunc setup for RTE content (which is mainly HTML) based on the "default" transformation.
    lib.parseFunc_RTE < lib.parseFunc
    lib.parseFunc_RTE { # Processing <ol>, <ul> and <table> blocks separately
    externalBlocks = article, aside, blockquote, div, dd, dl, footer, header, nav, ol, section, table, ul, pre
    externalBlocks {
    ol {
    stripNL = 1
    stdWrap.parseFunc = < lib.parseFunc
    }
    ul {
    stripNL = 1
    stdWrap.parseFunc = < lib.parseFunc
    }
    pre {
    stdWrap.parseFunc < lib.parseFunc
    }
    table {
    stripNL = 1
    stdWrap {
    HTMLparser = 1
    HTMLparser {
    tags.table.fixAttrib.class {
    default = contenttable
    always = 1
    list = contenttable
    }
    keepNonMatchedTags = 1
    }
    }
    HTMLtableCells = 1
    HTMLtableCells { # Recursive call to self but without wrapping non-wrapped cell content
    default.stdWrap {
    parseFunc = < lib.parseFunc_RTE
    parseFunc.nonTypoTagStdWrap.encapsLines {
    nonWrappedTag =
    innerStdWrap_all.ifBlank =
    }
    }
    addChr10BetweenParagraphs = 1
    }
    }
    div {
    stripNL = 1
    callRecursive = 1
    }
    article < .div
    aside < .div
    blockquote < .div
    footer < .div
    header < .div
    nav < .div
    section < .div
    dl < .div
    dd < .div
    }
    nonTypoTagStdWrap {
    encapsLines {
    encapsTagList = p,pre,h1,h2,h3,h4,h5,h6,hr,dt
    remapTag.DIV = P
    nonWrappedTag = P
    innerStdWrap_all.ifBlank =  
    }
    }
    nonTypoTagStdWrap {
    HTMLparser = 1
    HTMLparser {
    keepNonMatchedTags = 1
    htmlSpecialChars = 2
    }
    }
    }@

TS added by "rte_ckeditor_image"
@## TS setup for TYPO3 image rendering

#******************************************************
  1. Including library for processing of magic images and file abstraction attributes on img tag #******************************************************

lib.parseFunc {
tags.img = TEXT
tags.img {
current = 1
preUserFunc = Netresearch\RteCKEditorImage\Controller\ImageRenderingController->renderImageAttributes
}
tags.a = TEXT
tags.a {
current = 1
preUserFunc = Netresearch\RteCKEditorImage\Controller\ImageLinkRenderingController->renderImages
}
nonTypoTagStdWrap.HTMLparser.tags.img.fixAttrib {
allparams.unset = 1
data-htmlarea-file-uid.unset = 1
data-htmlarea-file-table.unset = 1
data-htmlarea-zoom.unset = 1
data-htmlarea-clickenlarge.unset = 1
}
}
@

Content:
<p class="text-center"><a href="t3://page?uid=122"><img alt="10 well-named Pump Manuacturers belong to the SPA" data-htmlarea-file-table="sys_file" data-htmlarea-file-uid="1561" height="300" src="https://www.starpumpalliance.com/fileadmin/user_upload/bb03e3aebd.jpg" title="10 well-named Pump Manuacturers belong to the SPA" width="300" /></a>          <a href="t3://page?uid=118"><img alt="13 Types of Pumps from different Pump Technologies" data-htmlarea-file-table="sys_file" data-htmlarea-file-uid="1562" height="300" src="https://www.starpumpalliance.com/fileadmin/user_upload/7a7eefc40a.jpg" title="13 Types of Pumps from different Pump Technologies" width="300" /></a>          <a href="/about-spa/#c3712"><img alt="The SPA Members are present in more than 110 Countries" data-htmlarea-file-table="sys_file" data-htmlarea-file-uid="1563" height="300" src="https://www.starpumpalliance.com/fileadmin/user_upload/1acdb5e37a.jpg" title="The SPA Members are present in more than 110 Countries" width="300" /></a></p>

Best regards
Bernd

#5

Updated by Riccardo De Contardi 10 months ago

I am not totally sure (or I could possibly be totally wrong) wether this could come some CKEditor manipulation...

something like an inline element (img) must be wrapped in a block element

#6

Updated by Reindl Bernd 10 months ago

Riccardo De Contardi wrote in #note-5:

I am not totally sure (or I could possibly be totally wrong) wether this could come some CKEditor manipulation...

something like an inline element (img) must be wrapped in a block element

But with $conf instead of $tagConf ....


<p>
<img ...>
<img ...>
<img ...>
</p>

results in


<p><img ...></p>
<p><img ...></p>
<p><img ...></p>

because every image is wrapped no matter if it already is wrapped.

And $tagConf contains the settings for current tag. If you don't us it. What is it for?

#7

Updated by Riccardo De Contardi 10 months ago

I found an issue that could be related to this one: https://forge.typo3.org/issues/92301

#8

Updated by Reindl Bernd 3 months ago

  • Priority changed from Should have to Must have

Still in TYPO3 10.4.20.

So easy to solve. So why is this ticket ignored?

#9

Updated by Mike Rucinski 3 months ago

We run into the same problem after migrating from Typo3 v8 to v10.
As Bernd pointed out, it is obvious that the forEach loop passes the wrong parameter to the _parsFunc call: (ContentObjectRenderer.php -> Line 3993)

foreach ($conf['tags.'] as $tag => $tagConfig) {
// only match tag `a` in `<a href"...">` but not in `<abbr>`
if (preg_match('#<' . $tag . '[\s/>]#', $data)) {
$data = $this->_parseFunc($data, $conf);  // <-- this is the culprit
break;
}
}

You can see that $tagConfig is being set in the loop definition but it is never used.
Changing the _parseFunc call's second parameter to $tagConfig, fixes the problem for us.

foreach ($conf['tags.'] as $tag => $tagConfig) {
// only match tag `a` in `<a href"...">` but not in `<abbr>`
if (preg_match('#<' . $tag . '[\s/>]#', $data)) {
$data = $this->_parseFunc($data, $tagConfig); // <-- this fixes the issue
break;
}
}

Please fix this in the main branch so we don't have to apply a hot fix.

#10

Updated by Ralf Hübner 3 months ago

I´ve use 10.4.20 and I wondered why the a-Tag is´nt shown in frontend.

In ck-Editor I have this:
<p><a href="..."><img ...></a></p>

But the frontend renders:
<p><img ...></p>

I tested the fix above and the a-Tag is noew rendered ;-)

Also available in: Atom PDF