web-dev-qa-db-fra.com

Décoder amp; retour à en JavaScript

J'ai des ficelles comme

var str = 'One & two & three';

rendu en HTML par le serveur Web. J'ai besoin de transformer ces cordes en

'One & two & three'

Actuellement, c'est ce que je fais (avec l'aide de jQuery):

$(document.createElement('div')).html('{{ driver.person.name }}').text()

Cependant, j'ai le sentiment troublant que je me trompe. j'ai essayé

unescape("&")

mais cela ne semble pas fonctionner, ni decodeURI/decodeURIComponent.

Y a-t-il d'autres façons plus indigènes et élégantes de le faire?

207
Art

Une option plus moderne pour interpréter le code HTML (texte ou autre) à partir de JavaScript est le support HTML dans l'API DOMParser ( voir ici dans MDN ). Cela vous permet d'utiliser l'analyseur HTML natif du navigateur pour convertir une chaîne en un document HTML. Il est pris en charge dans les nouvelles versions de tous les principaux navigateurs depuis fin 2014.

Si nous voulons simplement décoder du contenu textuel, nous pouvons le placer comme contenu unique dans un corps de document, analyser le document et extraire le son .body.textContent.

var encodedStr = 'hello & world';

var parser = new DOMParser;
var dom = parser.parseFromString(
    '<!doctype html><body>' + encodedStr,
    'text/html');
var decodedString = dom.body.textContent;

console.log(decodedString);

Nous pouvons voir dans spécification préliminaire pour DOMParser que JavaScript n'est pas activé pour le document analysé, ce qui nous permet d'effectuer cette conversion de texte sans souci de sécurité.

La méthode parseFromString(str, type) doit exécuter ces étapes en fonction du type :

  • "text/html"

    Analyse str avec un HTML parser et renvoie le Document nouvellement créé.

    L'indicateur de script doit être défini sur "désactivé".

    REMARQUE

    Les éléments script sont marqués comme non exécutables et le contenu de noscript est analysé comme un balisage.

Cela dépasse le cadre de cette question, mais , veuillez noter que si vous prenez les nœuds DOM analysés eux-mêmes (pas uniquement leur contenu texte) et les déplacez dans le document en direct DOM, il est possible que leur script soit réactivé et que des problèmes de sécurité se posent. Je n'ai pas fait de recherches, alors faites preuve de prudence.

80
Jeremy Banks

Avez-vous besoin de décoder toutes les entités HTML encodées ou simplement &amp; lui-même?

Si vous avez seulement besoin de gérer &amp;, alors vous pouvez le faire:

var decoded = encoded.replace(/&amp;/g, '&');

Si vous devez décoder toutes les entités HTML, vous pouvez le faire sans jQuery:

var elem = document.createElement('textarea');
elem.innerHTML = encoded;
var decoded = elem.value;

Veuillez prendre note des commentaires de Mark ci-dessous qui soulignent les failles de sécurité dans une version antérieure de cette réponse et vous recommandons d'utiliser textarea plutôt que div pour atténuer les vulnérabilités XSS potentielles. Ces vulnérabilités existent que vous utilisiez ou non jQuery ou JavaScript simple.

269
LukeH

Matthias Bynens a une bibliothèque pour cela: https://github.com/mathiasbynens/he

Exemple:

console.log(
    he.decode("J&#246;rg &amp J&#xFC;rgen rocked to &amp; fro ")
);
// Logs "Jörg & Jürgen rocked to & fro"

Je suggère de le privilégier par rapport aux hacks impliquant la définition du contenu HTML d'un élément, puis la lecture de son contenu textuel. De telles approches peuvent fonctionner, mais sont faussement dangereuses et représentent des opportunités XSS si elles sont utilisées avec une entrée utilisateur non fiable.

Si vous ne pouvez vraiment pas supporter de charger dans une bibliothèque, vous pouvez utiliser le hack textarea décrit dans cette réponse à une question presque en double, qui, contrairement à diverses approches similaires qui ont déjà été utilisées. suggéré, n'a pas de faille de sécurité que je sache:

function decodeEntities(encodedString) {
    var textArea = document.createElement('textarea');
    textArea.innerHTML = encodedString;
    return textArea.value;
}

console.log(decodeEntities('1 &amp; 2')); // '1 & 2'

Mais prenez note des problèmes de sécurité affectant des approches similaires à celles-ci, que je mentionne dans la réponse associée! Cette approche est un hack, et les modifications futures du contenu autorisé d'un textarea (ou de bogues dans certains navigateurs) pourraient conduire à un code qui repose sur le fait qu'il subit soudainement un trou XSS.

39
Mark Amery
var htmlEnDeCode = (function() {
    var charToEntityRegex,
        entityToCharRegex,
        charToEntity,
        entityToChar;

    function resetCharacterEntities() {
        charToEntity = {};
        entityToChar = {};
        // add the default set
        addCharacterEntities({
            '&amp;'     :   '&',
            '&gt;'      :   '>',
            '&lt;'      :   '<',
            '&quot;'    :   '"',
            '&#39;'     :   "'"
        });
    }

    function addCharacterEntities(newEntities) {
        var charKeys = [],
            entityKeys = [],
            key, echar;
        for (key in newEntities) {
            echar = newEntities[key];
            entityToChar[key] = echar;
            charToEntity[echar] = key;
            charKeys.Push(echar);
            entityKeys.Push(key);
        }
        charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
        entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
    }

    function htmlEncode(value){
        var htmlEncodeReplaceFn = function(match, capture) {
            return charToEntity[capture];
        };

        return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
    }

    function htmlDecode(value) {
        var htmlDecodeReplaceFn = function(match, capture) {
            return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
        };

        return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
    }

    resetCharacterEntities();

    return {
        htmlEncode: htmlEncode,
        htmlDecode: htmlDecode
    };
})();

Cela provient du code source ExtJS.

23
WaiKit Kung

element.innerText fait aussi l'affaire.

16
avg_joe

Si vous le recherchez, comme moi, il existe une méthode JQuery agréable et sûre.

https://api.jquery.com/jquery.parsehtml/

Vous pouvez f.ex. tapez ceci dans votre console:

var x = "test &amp;";
> undefined
$.parseHTML(x)[0].textContent
> "test &"

Donc, $ .parseHTML (x) renvoie un tableau et si vous avez du balisage HTML dans votre texte, le tableau.length sera supérieur à 1.

11
cslotty

Vous pouvez utiliser la fonction Lodash unescape/escape https://lodash.com/docs/4.17.5#unescape

import unescape from 'lodash/unescape';

const str = unescape('fred, barney, &amp; pebbles');

str deviendra 'fred, barney, & pebbles'

8
I am L

jQuery va encoder et décoder pour vous. Cependant, vous devez utiliser une balise textarea, pas une div.

var str1 = 'One & two & three';
var str2 = "One &amp; two &amp; three";
  
$(document).ready(function() {
   $("#encoded").text(htmlEncode(str1)); 
   $("#decoded").text(htmlDecode(str2));
});

function htmlDecode(value) {
  return $("<textarea/>").html(value).text();
}

function htmlEncode(value) {
  return $('<textarea/>').text(value).html();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<div id="encoded"></div>
<div id="decoded"></div>
8
Jason Williams

Commencez par créer un <span id="decodeIt" style="display:none;"></span> quelque part dans le corps.

Ensuite, assignez la chaîne à décoder en tant que innerHTML à ceci:

document.getElementById("decodeIt").innerHTML=stringtodecode

Finalement,

stringtodecode=document.getElementById("decodeIt").innerText

Voici le code général:

var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText
4
Infoglaze.com

Pour les gars d'une ligne:

const htmlDecode = innerHTML => Object.assign(document.createElement('textarea'), {innerHTML}).value;

console.log(htmlDecode('Complicated - Dimitri Vegas &amp; Like Mike'));
2
Ninh Pham

une solution javascript qui capture les plus communs:

var map = {amp: '&', lt: '<', gt: '>', quot: '"', '#039': "'"}
str = str.replace(/&([^;]+);/g, (m, c) => map[c])

c'est l'inverse de https://stackoverflow.com/a/4835406/2738039

1
Peter Brandt

J'ai tout essayé pour supprimer et d'un tableau JSON. Aucun des exemples ci-dessus, mais https://stackoverflow.com/users/2030321/chris a donné une excellente solution qui m'a amené à résoudre mon problème.

var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText

Je ne l'ai pas utilisé, car je ne savais pas comment l'insérer dans une fenêtre modale qui extrayait des données JSON dans un tableau, mais je l'ai essayé à l'aide de l'exemple, et cela a fonctionné:

var modal = document.getElementById('demodal');
$('#ampersandcontent').text(replaceAll(data[0],"&amp;", "&"));

J'aime ça parce que c'était simple et que ça marche, mais je ne sais pas pourquoi ce n'est pas très utilisé. Cherché salut & bas pour trouver une solution simple. Je continue à chercher à comprendre la syntaxe, et s'il y a un risque à l'utiliser. Je n'ai encore rien trouvé.

0
Digexart