This is probably an unusual scenario, but let me explain where I am.... I have a custom module that processes a feed from an external source and generates content (creates nodes). For some reason <br /> tags are coming through 'converted' rather than as raw HTML. In Drupal 7 I used PHP str_replace() to rectify this like:
File: node--video.tpl.php (where 'video' is my content type.
<?php $filteredDescription = str_replace('<br />', '<br />', $content['body'][0]['#markup']); $content['body'][0]['#markup'] = $filteredDescription; ?> <div class="content"<?php print $content_attributes; ?>> <?php print render($content); ?> </div>
This worked well and was nice and simple, however in Drupal 9 (D8 too) we use TWIG and none of the replace functions I tried worked.
I figured the solution lied in using THEME_preprocess_node() where I could check the node type, filter the body field and create a new variable, then use that variable in the TWIG template.
This kind of worked but the body field also had some filtering that converted a url to a link, for example a facebook.com link would be converted to a working link. Therefore I needed the body field filtered to correct any links and then the <br /> tags to be fixed.
This took me a while to figure out but is actually quite simple and uses a function called check_markup(). The function needs two arguments i.e.
$filteredBody = check_markup($node->body->value, $node->body->format);
Let's say my theme is called myD9theme and my content type is called videoto make this easier to read.
File: myD9theme.theme
function myD9theme_preprocess_node(&$variables) { $nodeType = $variables['node']->getType(); if($nodeType == 'video'){ $nodeBody = check_markup($variables['node']->body->value, $variables['node']->body->format); // Filtered HTML $variables['videoBodyStripped'] = str_replace('<br />', '
', $nodeBody); // String replace } }
$variables['videoBodyStripped'] creates a new variable (videoBodyStripped) that can be used in the TWIG template like {{ videoBodyStripped }}.
File: node--video.html.twig
<div id="node-{{ node.id }}" {{ attributes.addClass(nodevideo') }}> <div {{ content_attributes.addClass('content') }}> {# content.body #} {# node.body.value|raw #} {# content.body|replace({'<br />' : '<br />'}) #} {# {% set twig_content_variable = node.body.value %} {% set replace_value_var = '<br />' %} {% set replace_with_value_var = '<br />' %} {{ twig_content_variable|replace({ (replace_value_var): replace_with_value_var }) }} #} {# Seems to be a lot of ways to do this, that don't work. Eventually did it in myD9theme_preprocess_node() #} {{ videoBodyStripped|raw }} </div> </div>
I've left my original workings in place so you can see the TWIG solutions, but the main line to pay attention to is: {{ videoBodyStripped|raw }} where I output my new variable using the |raw filter.
Remember to rebuild the cache or your new code won't be read!