web-dev-qa-db-fra.com

Passer du code HTML brut à #markup

J'ai du contenu html, il provient d'une bibliothèque externe donc je ne peux pas le changer, il a beaucoup de <span> et <div> balises avec des attributs tels que: <span style="color: #0000ff;">, mais quand j'utilise:

$render = array(
  '#markup' => $myhtmlcontent,
);

Dans un tableau de rendu, Drupal supprime les attributs et ne conserve que <span> sans les styles.

Alors, comment puis-je éviter Drupal change ce que je passe en tant que balisage, qui n'a pas besoin de filtre parce que la bibliothèque le rend sûr, ou enfin lui permet d'autoriser les styles?

27
Yukare

Utilisez un modèle en ligne:

  return [
    '#type' => 'inline_template',
    '#template' => '{{ somecontent }}',
    '#context' => [
      'somecontent' => $somecontent
    ]
  ];

Dans votre cas, sans contexte, juste en HTML.

Vous pouvez également utiliser l'élément html_tag pour des choses comme le script ou le lien, etc.

29
user21641

Comme indiqué dans Présentation de l'API de rend , dans Drupal 8, la chaîne transmise à #markup est transmise par \ Drupal\Component\Utility\Xss :: filterAdmin () , qui supprime les vecteurs XSS connus tout en autorisant une liste permissive de balises HTML qui ne sont pas des vecteurs XSS. Vous pouvez utiliser #allowed_tags pour définir la liste des balises autorisées, mais cela ne s'arrêterait pas Drupal de supprimer les attributs (par exemple le style).

$output['filtered_string'] = array(
  '#markup' => '<em>This is filtered</em>',
  '#allowed_tags' => ['strong'],
);

Comme dans votre cas, vous passez un balisage HTML complexe, vous devez utiliser #type (comme suggéré par Ivan Jaros ou utiliser #theme. Dans ce cas, #type semble une meilleure solution.

Vous pouvez également implémenter un nouveau type, avec un plugin d'élément de rendu, mais si c'est le seul cas où vous en avez besoin, l'implémentation d'un plugin d'élément de rendu est probablement excessive.

20
kiamlaluno

Dans un tableau de rendu, faites simplement ceci:

return [
  '#children' => $html,
];

EDIT: Vous pouvez également utiliser la méthode décrite par @nvahalik dans l'autre réponse, en combinaison avec '#markup'. Je pense que cela est plus proche de l'utilisation prévue de l'API de rendu.

use Drupal\Core\Render\Markup;

[..]
return [
  '#markup' => Markup::create($html),
];

Par exemple. si $html a été produit avec PHP highlight_string() , il contiendra des attributs de style qui seront supprimés avec #markup. Mais #children Les conserve.

Comment tester cela?

Allez dans devel/php (avec le module devel installé).

$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());

J'obtiens personnellement cette sortie:

"""
'<div>markup onionpowder</div>\n
<div style="font-weight: bold;">children onionpowder</div>\n
<div style="font-weight: bold;">safe markup onionpowder</div>\n
'
"""

(La "poudre d'oignon" permet de définir des points de rupture conditionnels dans les fonctions de rendu)

Mais cela dépend peut-être de la version Drupal?

Il peut également arriver que cela soit (peut-être involontairement) à nouveau traité dans un autre point du pipeline.

Notes techniques

Voir https://git.drupalcode.org/project/drupal/blob/8.8.x/core/lib/Drupal/Core/Render/Renderer.php#L184

Le '#markup' Est filtré dans ->ensureMarkupIsSafe(), qui est appelé depuis ->doRender(). La même chose ne s'applique pas à '#children' Dans la version de Drupal que j'utilisais (c'est un site de test local, ne peut pas mettre à jour atm).

15
donquixote

Si vous souhaitez ajouter un balisage simple pour rendre les tableaux, vous pouvez le créer en utilisant \ Drupal\Core\Render\Markup . Cela vous permettra de mettre du HTML brut dans quelque chose. Par exemple, voici comment il est utilisé dans le module Permission Report pour mettre du HTML dans des tableaux :

$rows[] = [
  [
    'data' => $this->l($meta['title'], new Url('permission_report.permission', ['user_permission' => $perm], $options)),
  ],
  ['data' => $users_having_role],
  ['data' => Markup::create(implode(', ', $display_roles))],
];
12
nvahalik