Pregunta La codificación HTML se pierde cuando se lee el atributo del campo de entrada


Estoy usando JavaScript para extraer un valor de un campo oculto y mostrarlo en un cuadro de texto. El valor en el campo oculto está codificado.

Por ejemplo,

<input id='hiddenId' type='hidden' value='chalk &amp; cheese' />

se tira en

<input type='text' value='chalk &amp; cheese' />

a través de jQuery para obtener el valor del campo oculto (en este punto pierdo la codificación):

$('#hiddenId').attr('value')

El problema es que cuando leo chalk &amp; cheese desde el campo oculto, JavaScript parece perder la codificación. Escapar " y ', Quiero que la codificación permanezca.

¿Hay una biblioteca JavaScript o un método jQuery que codifique HTML una cadena?


692
2017-08-02 21:08


origen


Respuestas:


Yo uso estas funciones:

function htmlEncode(value){
  // Create a in-memory div, set its inner text (which jQuery automatically encodes)
  // Then grab the encoded contents back out. The div never exists on the page.
  return $('<div/>').text(value).html();
}

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

Básicamente, se crea un elemento div en la memoria, pero nunca se agrega al documento.

Sobre el htmlEncode función que configuro innerText del elemento y recuperar el codificado innerHTML; sobre el htmlDecode función que configuro innerHTML valor del elemento y el innerText es recuperado

Verifique un ejemplo en ejecución aquí.


1029
2017-08-02 22:03



El truco de jQuery no codifica las comillas y, en IE, quitará el espacio en blanco.

Basado en escapar templatetag en Django, que supongo que ya se usó / probó mucho, hice esta función que hace lo que se necesita.

Es posiblemente más simple (y posiblemente más rápido) que cualquiera de las soluciones para el problema de eliminación del espacio en blanco, y codifica comillas, lo cual es esencial si vas a usar el resultado dentro de un valor de atributo, por ejemplo.

function htmlEscape(str) {
    return str
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
}

// I needed the opposite function today, so adding here too:
function htmlUnescape(str){
    return str
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&');
}

Actualización 2013-06-17:
En la búsqueda del escape más rápido encontré esta implementación de un replaceAll método:
http://dumpsite.com/forum/index.php?topic=4.msg29#msg29
(también se hace referencia aquí: El método más rápido para reemplazar todas las instancias de un personaje en una cadena)
Algunos resultados de rendimiento aquí:
http://jsperf.com/htmlencoderegex/25

Da cadena de resultado idéntica a la incorporada replace cadenas arriba. Estaría muy feliz si alguien pudiera explicar por qué es más rápido?

Actualización 2015-03-04:
Me acabo de dar cuenta de que AngularJS está utilizando exactamente el método anterior:
https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

Agregan un par de refinamientos, parecen estar manejando un oscuro problema Unicode así como convertir todos los caracteres no alfanuméricos en entidades. Tenía la impresión de que este último no era necesario siempre que tuvieras un conjunto de caracteres UTF8 especificado para tu documento.

Notaré que (4 años después) Django todavía no hace ninguna de estas cosas, así que no estoy seguro de lo importantes que son:
https://github.com/django/django/blob/1.8b1/django/utils/html.py#L44

Actualización 2016-04-06:
También es posible que desee escapar de barra diagonal /. Esto no es necesario para una codificación HTML correcta, sin embargo, es recomendado por OWASP como una medida de seguridad anti-XSS. (gracias a @JNF por sugerir esto en los comentarios)

        .replace(/\//g, '&#x2F;');

524
2017-08-19 15:41



Aquí hay una versión que no es jQuery que es considerablemente más rápida que la jQuery .html()versión y el .replace() versión. Esto conserva todos los espacios en blanco, pero al igual que la versión de jQuery, no maneja las comillas.

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

Velocidad:  http://jsperf.com/htmlencoderegex/17

speed test

Manifestación:  jsFiddle

Salida:

output

Guión:

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

function htmlDecode( html ) {
    var a = document.createElement( 'a' ); a.innerHTML = html;
    return a.textContent;
};

document.getElementById( 'text' ).value = htmlEncode( document.getElementById( 'hidden' ).value );

//sanity check
var html = '<div>   &amp; hello</div>';
document.getElementById( 'same' ).textContent = 
      'html === htmlDecode( htmlEncode( html ) ): ' 
    + ( html === htmlDecode( htmlEncode( html ) ) );

HTML:

<input id="hidden" type="hidden" value="chalk    &amp; cheese" />
<input id="text" value="" />
<div id="same"></div>

76
2018-03-11 20:48



Sé que este es viejo, pero quería publicar una variación de la respuesta aceptada eso funcionará en IE sin eliminar líneas:

function multiLineHtmlEncode(value) {
    var lines = value.split(/\r\n|\r|\n/);
    for (var i = 0; i < lines.length; i++) {
        lines[i] = htmlEncode(lines[i]);
    }
    return lines.join('\r\n');
}

function htmlEncode(value) {
    return $('<div/>').text(value).html();
} 

32
2017-10-26 16:32



Guion bajo proporciona _.escape() y _.unescape() métodos que hacen esto.

> _.unescape( "chalk &amp; cheese" );
  "chalk & cheese"

> _.escape( "chalk & cheese" );
  "chalk &amp; cheese"

28
2018-01-10 15:04



Buena respuesta. Tenga en cuenta que si el valor para codificar es undefined o null con jQuery 1.4.2 puede recibir errores como:

jQuery("<div/>").text(value).html is not a function

O

Uncaught TypeError: Object has no method 'html'

La solución es modificar la función para verificar un valor real:

function htmlEncode(value){ 
    if (value) {
        return jQuery('<div/>').text(value).html(); 
    } else {
        return '';
    }
}

12
2017-11-02 22:40



Para aquellos que prefieren javascript simple, este es el método que he utilizado con éxito:

function escapeHTML (str)
{
    var div = document.createElement('div');
    var text = document.createTextNode(str);
    div.appendChild(text);
    return div.innerHTML;
}

9
2017-10-12 21:13