Ruby on Rails: comment rendre une chaîne au format HTML?

154

j'ai

@str = "<b>Hi</b>"

et à mon avis erb:

<%= @str %>

Ce qui s'affichera sur la page est: <b>Hi</b>quand ce que je veux vraiment, c'est Salut . Quelle est la manière ruby ​​"d'interpréter" une chaîne comme du balisage HTML?


Edit : le cas où

@str = "<span class=\"classname\">hello</span>"

Si à mon avis je fais

<%raw @str %>

Le code source HTML est <span class=\"classname\">hello</span> là où ce que je veux vraiment <span class="classname">hello</span>(sans les contre-obliques qui échappaient aux guillemets). Quelle est la meilleure façon de "unescape" ces doubles guillemets?

Tim
la source
Vous pouvez également envisager d'utiliser la syntaxe% Q [] pour l'échappement de chaîne. par exemple %Q["quotation marks"] => "\"quotation marks\"" Source: en.wikibooks.org/wiki/Ruby_Programming/Syntax/ ... Je ne sais pas si cela aide.
0112

Réponses:

328

METTRE À JOUR

Pour des raisons de sécurité, il est recommandé d'utiliser à la sanitizeplace de html_safe. Lien


Ce qui se passe, c'est que, par mesure de sécurité, Rails échappe votre chaîne pour vous car il peut contenir du code malveillant. Mais si vous dites à Rails que votre chaîne est html_safe, elle la passera à travers.

@str = "<b>Hi</b>".html_safe
<%= @str %>

OU

@str = "<b>Hi</b>"
<%= @str.html_safe %>

L'utilisation rawfonctionne bien, mais tout ce qu'il fait est de convertir la chaîne en chaîne, puis d'appeler html_safe. Quand je sais que j'ai une chaîne, je préfère appeler directement html_safe, car cela saute une étape inutile et clarifie ce qui se passe. Les détails sur l'échappement de chaîne et la protection XSS se trouvent dans cet Asciicast .

Jacob
la source
Fantastique. Je n'ai pas pu trouver comment faire cela même après avoir cherché pendant une heure. Merci pour votre réponse.
Salil le
1
J'ai toujours utilisé raw. Très heureux de savoir à ce sujet!
jmcharnes
Donner des écheveaux du futur =)
Carlos Morales
1
sanitize est supprimé selon stackoverflow.com/questions/44575106/…
Youness
16

Utiliser brut :

<%=raw @str >

Mais comme @ jmort253 le dit correctement, considérez à quoi appartient vraiment le HTML.

Michael Stum
la source
Salut, cette solution fonctionne, sauf avec une mise en garde: s'il vous plaît voir la question modifiée
Tim
14

Si vous êtes railsqui utilise erubis - le plus cool façon de le faire est

<%== @str >

Notez le double signe égal. Voir la question relative à SO pour plus d'informations.

jibiel
la source
7

Vous mélangez votre logique métier avec votre contenu. Au lieu de cela, je vous recommande d'envoyer les données sur votre page, puis d'utiliser quelque chose comme JQuery pour placer les données là où vous en avez besoin.

Cela a l'avantage de conserver tout votre HTML dans les pages HTML auxquelles il appartient afin que vos concepteurs Web puissent modifier le HTML ultérieurement sans avoir à passer par le code côté serveur.

Ou si vous ne souhaitez pas utiliser JavaScript, vous pouvez essayer ceci:

@str = "Hi"

<b><%= @str ></b>

Au moins de cette façon, votre HTML se trouve dans la page HTML à laquelle il appartient.

jmort253
la source
Le problème est que mon application prend un fichier qui est mal balisé et le «traduit» via des expressions régulières en un bon balisage HTML à envoyer à la vue. Par conséquent, le balisage HTML qui est généré est dynamique, je ne peux donc pas savoir a priori quelles balises sont censées entourer @str. Où pourrais-je effectuer ce travail de «traduction», sinon dans les modèles? Je pensais que nous n'étions pas censés avoir un code logique complet dans les vues.
Tim
1
C'est vraiment une question d'opinion. Lors du développement d'une nouvelle application, je préfère tout garder aussi propre que possible. Mais souvent, nous devons travailler dans les limites de ce que les autres nous ont laissé. Si votre source de données renvoie un balisage HTML, jetez peut-être un œil à l'utilisation de "raw" comme décrit dans la solution de Michael Stum.
jmort253
1
Si vous avez hérité de la prise en charge de certains codes et que le code a des zones qui montrent une mauvaise réflexion ou une mauvaise conception, il est de votre responsabilité de le nettoyer pour le rendre plus maintenable. Le laisser tel que vous l'avez trouvé, c'est bien quand c'est un bon code pour commencer, mais le laisser meilleur que ce que vous avez trouvé, c'est bien quand il a besoin de travail. Une partie de mon travail consiste à gérer certaines applications héritées; Je suis fan de ne pas réparer les choses qui ne sont pas cassées, mais elles ne pourraient pas être améliorées facilement à cause de la façon dont elles ont été écrites. J'ai dû réécrire la plupart des appels de fonction, mais c'est tellement plus facile à travailler maintenant.
The Tin Man
Vous ne devriez pas utiliser JavaScript pour votre interpolation HTML s'il n'y a aucune autre raison d'utiliser JS. Cela cassera votre site pour les navigateurs non-JS (oui, il y en a ).
Marnen Laibow-Koser
1
Bien sûr, si vous autorisez le contenu non échappé, la responsabilité de garantir le balisage non malveillant dépend de vous.
Macario
6

Ou vous pouvez essayer la méthode CGI.unescapeHTML .

CGI.unescapeHTML "&lt;p&gt;This is a Paragraph.&lt;/p&gt;"
=> "<p>This is a Paragraph.</p>"
Arman Ortega
la source
0

puisque vous traduisez et choisissez votre code recherché dans le fichier codé de merde d'une personne, pourriez-vous utiliser content_tag, en combinaison avec votre regex.

En volant les documents de l'API, vous pouvez interpoler ce code traduit en un content_tagformat similaire:

<%= content_tag translated_tag_type.to_sym, :class => "#{translated_class}" do -%>
<%= translated_text %>
<% end -%>
# => <div class="strong">Hello world!</div>

Ne connaissant pas votre code, ce genre de réflexion garantira que votre code traduit est trop conforme.

pjammer
la source
Je suppose que translate_text est le contenu réel de la div, non? c'est-à-dire, dans l'exemple, ce serait "Hello world!"? Et si translate_text contient plus de HTML, c'est-à-dire des divs ou des étendues imbriqués? Dois-je alors appeler content_tag plusieurs fois?
Tim
et ... désolé, appuyez sur Entrée tôt ... chaque div / span imbriqué à l'intérieur est toujours un content_tag et vous devez toujours le valider, n'est-ce pas? Puisque nous ne pouvons pas voir ce que vous faites avec votre traduction sophistiquée ;-), je suppose que vous recherchez TOUTES les balises, peu importe si l'expression régulière est sur le «parent» du html ... tel que <ul>. vous ne mettriez pas tous les li comme une grosse ficelle à imprimer, n'est-ce pas? chacun serait son propre content_tag: li, texte correct?
pjammer le
0

@str = "<span class=\"classname\">hello</span>" Si à mon avis je fais

<%raw @str %> Le code source HTML est <span class=\"classname\">hello</span>ce que je veux vraiment <span class="classname">hello</span>(sans les contre-obliques qui échappaient aux guillemets doubles). Quelle est la meilleure façon de "unescape" ces doubles guillemets?

Solution: utilisez des guillemets doubles à l'intérieur de guillemets simples (ou simples à l'intérieur de doubles) pour éviter de s'échapper avec une barre oblique inverse.

@str = '<span class="classname">hello</span>'
<%raw @str %>
crash
la source
0

La version html_safe fonctionne bien dans Rails 4 ...

<%= "<center style=\"color: green; font-size: 1.1em\" > Administrators only </center>".html_safe if current_user.admin? %
>
Géorgie
la source