Escape de HTML usando jQuery [duplicado]

Se me ocurrió un truco para escapar de HTML usando jQuery y me pregunto si alguien ve un problema con él.

$('<i></i>').text(TEXT_TO_ESCAPE).html();

La <i> La etiqueta es solo una simulación, ya que jQuery necesita un contenedor para establecer el texto.

¿Existe quizás una forma más fácil de hacer esto? Tenga en cuenta que necesito el texto almacenado en una variable, no para mostrarlo (de lo contrario, podría simplemente llamar elem.text(TEXT_TO_ESCAPE);).

¡Gracias!

preguntado el 16 de mayo de 11 a las 16:05

¿Qué quiere decir exactamente con "HTML de escape"? ¿Quieres convertir caracteres como <, > y & a sus correspondientes entidades HTML? -

su ejemplo podría acortarse a: $('<i>').text(TEXT_TO_ESCAPE).html(); -

3 Respuestas

Esa es una forma bastante estándar de hacerlo, mi versión usaba un <div> aunque:

return $('<div/>').text(t).html();

Sin embargo, esto no es técnicamente 100% seguro, como señala Mike Samuel, pero probablemente sea bastante seguro en la práctica.

El Prototype.js actual hace esto:

function escapeHTML() {
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}

Pero solía usar el truco de "poner texto en un div y extraer el HTML".

También hay _.escape en subrayado, eso lo hace así:

// List of HTML entities for escaping.
var htmlEscapes = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  "'": '&#x27;',
  '/': '&#x2F;'
};

// Regex containing the keys listed immediately above.
var htmlEscaper = /[&<>"'\/]/g;

// Escape a string for HTML interpolation.
_.escape = function(string) {
  return ('' + string).replace(htmlEscaper, function(match) {
    return htmlEscapes[match];
  });
};

Es más o menos el mismo enfoque que el de Prototype. La mayor parte del JavaScript que hago últimamente tiene subrayado disponible, por lo que tiendo a usar _.escape en estos días.

Respondido el 20 de Septiembre de 13 a las 21:09

Muchas bibliotecas hacen esto. Solo tenga en cuenta que el resultado aquí es seguro para incrustarlo en un contexto PCDATA y un contexto RCDATA, pero no en un contexto de atributo, ya que las comillas no se escapan. Si puede ser susceptible a ataques UTF-7 y similares, también debe escapar de '+': en.wikipedia.org/wiki/UTF-7#Security - Mike Samuel

@ Mike: No creo que el .text(t).html() o prototipos replace Los enfoques son realmente tan buenos, ambos enfoques tienen problemas. La falta de un encodeHTML() La función en la biblioteca estándar de JavaScript es un agujero enorme y un descuido bastante sorprendente. - mu es demasiado corto

@muis: No lo creo: el lenguaje principal de JavaScript no está dirigido específicamente a los navegadores web. - Marcel Korpel

@Marcel: Pero tenemos encodeURIComponent y las raíces de JavaScript están en los navegadores web. Y, el hecho de que cada uno termine escribiendo el suyo propio indica que hay una brecha en las bibliotecas estándar. - mu es demasiado corto

@muis Gracias por el puntero a Prototype. Resulta que mi método propuesto no funciona como esperaba en algunos navegadores (lea: IE) - Michael Mior

No hay garantía de que html() se escapará por completo, por lo que es posible que el resultado no sea seguro después de la concatenación.

html() está basado en innerHTML, y un navegador podría, sin violar muchas expectativas, implementar innerHTML así que eso $("<i></i>").text("1 <").html() is "1 <", Y que $("<i></i>").text("b>").html() is "b>".

Luego, si concatenas esos dos resultados seguros individualmente, obtienes "1 <b>" que obviamente no será la versión HTML de la concatenación de las dos piezas de texto plano.

Por lo tanto, este método no es seguro por deducción de los primeros principios, y no existe una especificación de innerHTML (aunque HTML5 lo aborda).

La mejor manera de verificar si hace lo que desea es probar casos de esquina como este.

contestado el 16 de mayo de 11 a las 22:05

De hecho, quiero $("<i></i>").text("1 <").html() para ser "1 &lt;" y $("<i></i>").text("b>").html() para ser "b&gt;". (que funciona) - Michael Mior

@Michael, si lo ha probado en los principales navegadores y funciona, genial. Desde el 15 de junio de 2009, una versión actual de Safari en realidad desahuciado > entonces <input name="Hello&gt;World"> fue devuelto a través de innerHTML as <input name="Hello>World">. Sin embargo, es posible que se haya solucionado en los navegadores modernos. Mi punto es que las pruebas son la forma de ganar confianza. - Mike Samuel

Eso debería funcionar. Básicamente, así es como lo hace la biblioteca Prototype.js, o al menos cómo solía hacerlo. Por lo general, lo hago con tres llamadas a ".replace ()", pero eso es principalmente un hábito.

contestado el 16 de mayo de 11 a las 21:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.