Quiero mostrar un texto a HTML mediante una función de JavaScript. ¿Cómo puedo escapar de caracteres especiales html en JS? ¿Hay una API?
fuente
Quiero mostrar un texto a HTML mediante una función de JavaScript. ¿Cómo puedo escapar de caracteres especiales html en JS? ¿Hay una API?
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
replace()
llamadas son innecesarias. Las cadenas simples de un solo carácter funcionarían igual de bien.
function escapeHtml(html){
var text = document.createTextNode(html);
var p = document.createElement('p');
p.appendChild(text);
return p.innerHTML;
}
// Escape while typing & print result
document.querySelector('input').addEventListener('input', e => {
console.clear();
console.log( escapeHtml(e.target.value) );
});
<input style='width:90%; padding:6px;' placeholder='<b>cool</b>'>
Puedes usar la función de jQuery.text()
.
Por ejemplo:
De la documentación de jQuery con respecto a la .text()
función:
Debemos tener en cuenta que este método escapa a la cadena proporcionada según sea necesario para que se procese correctamente en HTML. Para hacerlo, llama al método DOM .createTextNode (), no interpreta la cadena como HTML.
Las versiones anteriores de la documentación de jQuery estaban redactadas de esta manera ( énfasis agregado ):
Debemos tener en cuenta que este método escapa a la cadena proporcionada según sea necesario para que se procese correctamente en HTML. Para hacerlo, llama al método DOM .createTextNode (), que reemplaza caracteres especiales con sus equivalentes de entidad HTML (como & lt; para <).
const str = "foo<>'\"&";
$('<div>').text(str).html()
los rendimientosfoo<>'"&
Creo que encontré la forma correcta de hacerlo ...
// Create a DOM Text node:
var text_node = document.createTextNode(unescaped_text);
// Get the HTML element where you want to insert the text into:
var elem = document.getElementById('msg_span');
// Optional: clear its old contents
//elem.innerHTML = '';
// Append the text node into it:
elem.appendChild(text_node);
document.createTextNode("<script>alert('Attack!')</script>").textContent
Usando lodash
_.escape('fred, barney, & pebbles');
// => 'fred, barney, & pebbles'
Esta es, con mucho, la forma más rápida en que lo he visto hacer. Además, lo hace todo sin agregar, eliminar o cambiar elementos en la página.
function escapeHTML(unsafeText) {
let div = document.createElement('div');
div.innerText = unsafeText;
return div.innerHTML;
}
var divCode = '<div data-title="' + escapeHTML('Jerry "Bull" Winston') + '">Div content</div>'
generará HTML no válido.
Fue interesante encontrar una mejor solución:
var escapeHTML = function(unsafe) {
return unsafe.replace(/[&<"']/g, function(m) {
switch (m) {
case '&':
return '&';
case '<':
return '<';
case '"':
return '"';
default:
return ''';
}
});
};
Yo no analizo >
porque no rompe el código XML / HTML en el resultado.
Aquí están los puntos de referencia: http://jsperf.com/regexpairs
Además, creé una escape
función universal : http://jsperf.com/regexpairs2
La forma más concisa y eficaz de mostrar texto no codificado es usar la textContent
propiedad.
Más rápido que usar innerHTML
. Y eso sin tener en cuenta los gastos generales de escape.
document.body.textContent = 'a <b> c </b>';
</
se cumpla la secuencia de cierre .
Los elementos DOM admiten la conversión de texto a HTML mediante la asignación a innerText . innerText no es una función, pero su asignación funciona como si se escapara el texto.
document.querySelectorAll('#id')[0].innerText = 'unsafe " String >><>';
<br>
elementos en lugar de nuevas líneas, que pueden romper ciertos elementos, como estilos o scripts. El createTextNode
no es propenso a este problema.
innerText
tiene algunos problemas de legado / especificaciones. Mejor de usar textContent
.
Puedes codificar todos los caracteres de tu cadena:
function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}
O simplemente apunte a los personajes principales de los que preocuparse (&, inebreaks, <,>, "y ') como:
function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}
test.value=encode('How to encode\nonly html tags &<>\'" nice & fast!');
/*************
* \x26 is &ersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55">www.WHAK.com</textarea>
Una línea (para ES6 +):
var escapeHtml = s => (s + '').replace(/[&<>"']/g, m => ({
'&': '&', '<': '<', '>': '>',
'"': '"', "'": '''
})[m]);
Para versiones anteriores:
function escapeHtml(s) {
return (s + '').replace(/[&<>"']/g, function (m) {
return ({
'&': '&', '<': '<', '>': '>',
'"': '"', "'": '''
})[m];
});
}
Encontré este problema al construir una estructura DOM. Esta pregunta me ayudó a resolverlo. Quería usar un doble chevron como separador de ruta, pero agregar un nuevo nodo de texto resultó directamente en la visualización del código de caracteres escapado, en lugar del carácter en sí:
var _div = document.createElement('div');
var _separator = document.createTextNode('»');
//_div.appendChild(_separator); /* this resulted in '»' being displayed */
_div.innerHTML = _separator.textContent; /* this was key */
Si ya usa módulos en su aplicación, puede usar el módulo escape-html .
import escapeHtml from 'escape-html';
const unsafeString = '<script>alert("XSS");</script>';
const safeString = escapeHtml(unsafeString);
Se me ocurrió esta solución.
Supongamos que queremos agregar algo de HTML al elemento con datos inseguros del usuario o la base de datos.
var unsafe = 'some unsafe data like <script>alert("oops");</script> here';
var html = '';
html += '<div>';
html += '<p>' + unsafe + '</p>';
html += '</div>';
element.html(html);
No es seguro contra los ataques XSS. Ahora agregue esto.
$(document.createElement('div')).html(unsafe).text();
Así es
var unsafe = 'some unsafe data like <script>alert("oops");</script> here';
var html = '';
html += '<div>';
html += '<p>' + $(document.createElement('div')).html(unsafe).text(); + '</p>';
html += '</div>';
element.html(html);
¡Para mí, esto es mucho más fácil que usarlo .replace()
y lo eliminará! todas las posibles etiquetas html (espero).
<script>
en <script>
.