Codificar entidades HTML en JavaScript

Resuelto JGallardo asked hace 11 años • 19 respuestas

Estoy trabajando en un CMS que permite a los usuarios ingresar contenido. El problema es que cuando añaden símbolos ®, es posible que no se muestre bien en todos los navegadores. Me gustaría configurar una lista de símbolos que se deben buscar y luego convertir a la entidad html correspondiente. Por ejemplo

® => ®
& => &
© => ©
™ =>™

Después de la conversión, es necesario envolverlo en una <sup>etiqueta, lo que da como resultado esto:

®=><sup>&reg;</sup>

Porque es necesario un tamaño de fuente y un estilo de relleno determinados:

sup { font-size: 0.6em; padding-top: 0.2em; }

¿JavaScript sería algo como esto?

var regs = document.querySelectorAll('®');
  for ( var i = 0, l = imgs.length; i < l; ++i ) {
  var [?] = regs[i];
  var [?] = document.createElement('sup');
  img.parentNode.insertBefore([?]);
  div.appendChild([?]);
}

Donde "[?]" significa que hay algo de lo que no estoy seguro.

Detalles adicionales:

  • Me gustaría hacer esto con JavaScript puro, no con algo que requiera una biblioteca como jQuery, gracias.
  • El backend es Ruby
  • Usando RefineryCMS que está construido con Ruby on Rails
JGallardo avatar Sep 12 '13 02:09 JGallardo
Aceptado

Puede usar expresiones regulares para reemplazar cualquier carácter en un rango Unicode determinado con su entidad html equivalente. El código se vería así:

var encodedStr = rawStr.replace(/[\u00A0-\u9999<>\&]/g, function(i) {
   return '&#'+i.charCodeAt(0)+';';
});

O en ES6 (misma implementación, pero una línea):

const encodedStr = rawStr.replace(/[\u00A0-\u9999<>\&]/g, i => '&#'+i.charCodeAt(0)+';')

Este código reemplazará todos los caracteres en el rango dado (unicode 00A0 - 9999, así como el signo comercial, mayor y menor que) con sus equivalentes de entidad html, que es simplemente &#nnn;de dónde nnnproviene el valor Unicode que obtenemos charCodeAt.

Véalo en acción aquí: http://jsfiddle.net/E3EqX/13/ (este ejemplo usa jQuery para los selectores de elementos utilizados en el ejemplo. El código base en sí, arriba, no usa jQuery)

Realizar estas conversiones no resuelve todos los problemas: asegúrese de utilizar la codificación de caracteres UTF8 y de que su base de datos almacene las cadenas en UTF8. Es posible que aún vea casos en los que los caracteres no se muestran correctamente, dependiendo de la configuración de fuentes del sistema y otros problemas que están fuera de su control.

Documentación

  • String.charCodeAt- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
  • Entidades de caracteres HTML: http://www.chucke.com/entities.html
Chris Baker avatar Sep 11 '2013 19:09 Chris Baker

La respuesta actualmente aceptada tiene varias cuestiones. Esta publicación los explica y ofrece una solución más sólida. La solución sugerida en esa respuesta anteriormente tenía:

var encodedStr = rawStr.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
  return '&#' + i.charCodeAt(0) + ';';
});

La ibandera es redundante ya que ningún símbolo Unicode en el rango de U+00A0 a U+9999 tiene una variante mayúscula/minúscula que esté fuera de ese mismo rango.

La mbandera es redundante porque ^no $se utilizan en la expresión regular.

¿Por qué el rango U+00A0 a U+9999? Parece arbitrario.

De todos modos, para obtener una solución que codifique correctamente todos los símbolos ASCII excepto los seguros e imprimibles en la entrada (¡incluidos los símbolos astrales!) e implemente todas las referencias de caracteres con nombre (no solo los de HTML4), use la biblioteca he (descargo de responsabilidad: esta biblioteca es mía ). Desde su LÉAME:

él (para “entidades HTML”) es un codificador/decodificador de entidades HTML robusto escrito en JavaScript. Admite todas las referencias de caracteres con nombre estandarizados según HTML , maneja símbolos ambiguos y otros casos extremos tal como lo haría un navegador , tiene un amplio conjunto de pruebas y, a diferencia de muchas otras soluciones de JavaScript, maneja perfectamente los símbolos Unicode astrales. Hay una demostración en línea disponible.

Consulte también esta respuesta relevante de Stack Overflow .

Mathias Bynens avatar May 23 '2014 16:05 Mathias Bynens

Tuve el mismo problema y creé 2 funciones para crear entidades y traducirlas a caracteres normales. Los siguientes métodos traducen cualquier cadena a entidades HTML y nuevamente al prototipo de cadena.

/**
 * Convert a string to HTML entities
 */
String.prototype.toHtmlEntities = function() {
    return this.replace(/./gm, function(s) {
        // return "&#" + s.charCodeAt(0) + ";";
        return (s.match(/[a-z0-9\s]+/i)) ? s : "&#" + s.charCodeAt(0) + ";";
    });
};

/**
 * Create string from HTML entities
 */
String.fromHtmlEntities = function(string) {
    return (string+"").replace(/&#\d+;/gm,function(s) {
        return String.fromCharCode(s.match(/\d+/gm)[0]);
    })
};

Luego puedes usarlo de la siguiente manera:

var str = "Test´†®¥¨©˙∫ø…ˆƒ∆÷∑™ƒ∆æø𣨠ƒ™en tést".toHtmlEntities();
console.log("Entities:", str);
console.log("String:", String.fromHtmlEntities(str));

Salida en consola:

Entities: &#68;&#105;&#116;&#32;&#105;&#115;&#32;&#101;&#180;&#8224;&#174;&#165;&#168;&#169;&#729;&#8747;&#248;&#8230;&#710;&#402;&#8710;&#247;&#8721;&#8482;&#402;&#8710;&#230;&#248;&#960;&#163;&#168;&#160;&#402;&#8482;&#101;&#110;&#32;&#116;&#163;&#101;&#233;&#115;&#116;
String: Dit is e´†®¥¨©˙∫ø…ˆƒ∆÷∑™ƒ∆æø𣨠ƒ™en t£eést 
ar34z avatar Nov 19 '2014 15:11 ar34z