2

I am using theme_preprocess_node to modify an HTML tag, but the tag is being stripped somewhere in the theme layer.

mytemplate.twig

{% if node.field_embedded_media.value %}
  {{ content }}

mytheme.theme

    function mytheme_preprocess_node(&$variables) {
      if ($variables['view_mode'] == 'ebook_export') {
        $contentBody = $variables['node']->get('body')->value;

        $pattern = '/<drupal-media/';
        $replace = '<drupal-media data-view-mode="markdown_link"';
        $contentBody = preg_replace($pattern, $replace, $contentBody);

        $variables['content']['body'] = array(
            '#markup' => $contentBody
          );
        }
     }

Original input (node body value):

<drupal-media data-align="center" data-entity-type="media" data-entity-uuid="269d4491-9866-403c-90e3-c1298e9857de"></drupal-media>

This is some text.

<drupal-media data-align="center" data-entity-type="media" data-entity-uuid="269d4491-9866-403c-90e3-c1298e9857de"></drupal-media><pre>

This is some more text.

dpm($contentBody) in mytheme_preprocess_node (this is what I want to output, and it's correct here)

<drupal-media data-view-mode="markdown_link" data-align="center" data-entity-type="media" data-entity-uuid="269d4491-9866-403c-90e3-c1298e9857de"></drupal-media>

This is some text.

<drupal-media data-view-mode="markdown_link" data-align="center" data-entity-type="media" data-entity-uuid="269d4491-9866-403c-90e3-c1298e9857de"></drupal-media>

This is some more text.

Actual HTML output on page render (this is what I get, and the <drupal-media> tags are gone)

This is some text.

This is some more text.

The <drupal-media> tags got stripped. How do I prevent them from being stripped? I don't understand enough about the theme layer to determine where this is happening.

1

1 Answer 1

3

As described in Render API overview, the value passed in #markup is sanitized via \Drupal\Component\Utility\Xss::filterAdmin(). You can eventually pass the tags not to filter via the #allowed_tags properties, but the tag attributes could still be sanited.

To have full control on what it is sanitized, you should use #theme or #type instead of #markup. (The first is my choice when the markup is rendered only in a single place/page. Alternatively, you could also use #inline_template as in the following example code taken from the documentation page.

$build['hello'] = [
  '#type' => 'inline_template',
  '#template' => "{% trans %} Hello {% endtrans %} <strong>{{name}}</strong>",
  '#context' => [
    'name' => $name,
  ],
];

It allows to use any Twig filter Drupal core can use and to have full control over the rendered tags.
It's the easier alternative to #theme which doesn't require to implement hook_theme() nor putting the template content in a separated file. (If you need to reuse the same inline template in different pages, or the template content is rather complex, using #theme is still preferable.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.