In a render array, simply do this:
return [
'#children' => $html,
];
EDIT: Alternatively use the method described by @nvahalik in the other answer, in combination with '#markup'. I think this is closer to the intended usage of the render API.
use Drupal\Core\Render\Markup;
[..]
return [
'#markup' => Markup::create($html),
];
E.g. if the $html
was produced with PHP's highlight_string()
, it will contain style attributes which would be removed with #markup
. But #children
preserves them.
How to test this?
Go to devel/php (with devel module installed).
$elements = [
['#markup' => '<div style="font-weight: bold;">markup onionpowder</div>' . "\n"],
['#children' => '<div style="font-weight: bold;">children onionpowder</div>' . "\n"],
['#markup' => \Drupal\Core\Render\Markup::create('<div style="font-weight: bold;">safe markup onionpowder</div>' . "\n")],
];
var_export(drupal_render($elements)->__toString());
I personally get this output:
"""
'<div>markup onionpowder</div>\n
<div style="font-weight: bold;">children onionpowder</div>\n
<div style="font-weight: bold;">safe markup onionpowder</div>\n
'
"""
(The "onionpowder" allows to set conditional break points in the render functions)
But perhaps it depends on the Drupal version?
Also it can happen that this will be (perhaps unintentionally) processed again in a different point in the pipeline.
Technical notes
See https://git.drupalcode.org/project/drupal/blob/8.8.x/core/lib/Drupal/Core/Render/Renderer.php#L184
The '#markup'
is filtered in ->ensureMarkupIsSafe()
, which is called from within ->doRender()
. The same does not apply to '#children'
in the version of Drupal I was using (It's a local test site, cannot update atm).