Кодировать html-объекты в javascript

Я работаю в CMS, который позволяет пользователям вводить контент. Проблема в том, что при добавлении символов ® он может не отображаться хорошо во всех браузерах. Я хотел бы настроить список символов, которые нужно искать, а затем преобразовать в соответствующий объект html. Например

® = > ®
& Амп; = > &
© = > ©
™ = > ™

После преобразования его нужно обернуть в тег <sup>, в результате получится следующее:

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

Поскольку необходим конкретный размер шрифта и стиль заполнения:

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

Будет ли JavaScript похожим на это?

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([?]);
}

Где "[?]" означает, что есть что-то, о чем я не уверен.

Дополнительные сведения:

  • Я хотел бы сделать это с использованием чистого JavaScript, а не того, что спасибо библиотеке, как jQuery, спасибо.
  • Backend - Ruby
  • Использование RefineryCMS, построенного с помощью Ruby on Rails

Ответ 1

Вы можете использовать регулярное выражение для замены любого символа в данном юникодном диапазоне с его эквивалентом сущности html. Код будет выглядеть примерно так:

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

Этот код заменит все символы в данном диапазоне (unicode 00A0 - 9999, а также амперсанд, больше и меньше) с их эквивалентами сущностей html, который просто &#nnn;, где nnn - это значение unicode, которое мы получить от charCodeAt.

Смотрите здесь: http://jsfiddle.net/E3EqX/13/ (в этом примере используется jQuery для селекторов элементов, используемых в примере., не использует jQuery)

Выполнение этих преобразований не решает всех проблем - убедитесь, что вы используете кодировку символов UTF8, убедитесь, что ваша база данных хранит строки в UTF8. Вы еще можете видеть экземпляры, в которых символы отображаются неправильно, в зависимости от конфигурации системного шрифта и других проблем из-под вашего контроля.

Documentation

Ответ 2

В настоящее время принятый ответ имеет несколько проблем. Этот пост объясняет их и предлагает более надежное решение. Решение, предложенное в этом ответе:

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

Флаг i является избыточным, поскольку ни один символ Unicode в диапазоне от U + 00A0 до U + 9999 не имеет варианта в верхнем/нижнем регистре, который находится за пределами того же диапазона.

Флаг m является избыточным, потому что ^ или $ не используются в регулярном выражении.

Почему диапазон от U + 00A0 до U + 9999? Это кажется произвольным.

В любом случае, для решения, которое правильно кодирует все, кроме безопасных и печатаемых символов ASCII на входе (включая астральные символы!), И реализует все именованные ссылки на символы (не только в HTML4), используйте библиотеку he (отказ от ответственности: эта библиотека моя). Из его README:

он (для "сущностей HTML") - надежный кодер/декодер сущностей HTML, написанный на JavaScript. Он поддерживает все стандартизированные именованные ссылки на символы в соответствии с HTML, обрабатывает неоднозначные амперсанды и другие крайние случаи так же, как это делает браузер, имеет обширный набор тестов и - в отличие от многих других решений JavaScript - он прекрасно обрабатывает астральные символы Юникода. Онлайн демо доступно.

Также см. Этот соответствующий ответ.

Ответ 3

У меня была такая же проблема, и я создал 2 функции для создания сущностей и перевода их обратно к нормальным символам. Следующие методы переводят любую строку в объекты HTML и обратно на прототипе String

/**
 * Convert a string to HTML entities
 */
String.prototype.toHtmlEntities = function() {
    return this.replace(/./gm, function(s) {
        return "&#" + 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]);
    })
};

Затем вы можете использовать его следующим образом:

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

Вывод в консоли:

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 

Ответ 4

Без какой-либо библиотеки, если вам не нужно поддерживать IE < 9, вы можете создать элемент html и установить его содержимое Node.textContent:

var str = "<this is not a tag>";
var p = document.createElement("p");
p.textContent = str;
var converted = p.innerHTML;

Вот пример: https://jsfiddle.net/1erdhehv/

Ответ 5

Вы можете использовать это.

var escapeChars = {
  '¢' : 'cent',
  '£' : 'pound',
  '¥' : 'yen',
  '€': 'euro',
  '©' :'copy',
  '®' : 'reg',
  '<' : 'lt',
  '>' : 'gt',
  '"' : 'quot',
  '&' : 'amp',
  '\'' : '#39'
};

var regexString = '[';
for(var key in escapeChars) {
  regexString += key;
}
regexString += ']';

var regex = new RegExp( regexString, 'g');

function escapeHTML(str) {
  return str.replace(regex, function(m) {
    return '&' + escapeChars[m] + ';';
  });
};

https://github.com/epeli/underscore.string/blob/master/escapeHTML.js

var htmlEntities = {
    nbsp: ' ',
    cent: '¢',
    pound: '£',
    yen: '¥',
    euro: '€',
    copy: '©',
    reg: '®',
    lt: '<',
    gt: '>',
    quot: '"',
    amp: '&',
    apos: '\''
};

function unescapeHTML(str) {
    return str.replace(/\&([^;]+);/g, function (entity, entityCode) {
        var match;

        if (entityCode in htmlEntities) {
            return htmlEntities[entityCode];
            /*eslint no-cond-assign: 0*/
        } else if (match = entityCode.match(/^#x([\da-fA-F]+)$/)) {
            return String.fromCharCode(parseInt(match[1], 16));
            /*eslint no-cond-assign: 0*/
        } else if (match = entityCode.match(/^#(\d+)$/)) {
            return String.fromCharCode(~~match[1]);
        } else {
            return entity;
        }
    });
};

Ответ 6

Если вы хотите избежать кодирования HTML-сущностей более одного раза

function encodeHTML(str){
    return str.replace(/[\u00A0-\u9999<>&](?!#)/gim, function(i) {
      return '&#' + i.charCodeAt(0) + ';';
    });
}

function decodeHTML(str){
    return str.replace(/&#([0-9]{1,3});/gi, function(match, num) {
        return String.fromCharCode(parseInt(num));
    });
}

пример

var text = "<a>Content</a>";

text = encodeHTML(text);
console.log("Encode 1 times: " + text);

// &#60;a&#62;Content&#60;/a&#62;

text = encodeHTML(text);
console.log("Encode 2 times: " + text);

// &#60;a&#62;Content&#60;/a&#62;

text = decodeHTML(text);
console.log("Decoded: " + text);

// <a>Content</a>

Ответ 7

Если вы уже используете jQuery, попробуйте html().

$('<div>').text('<script>alert("gotcha!")</script>').html()
// "&lt;script&gt;alert("gotcha!")&lt;/script&gt;"

Создается текст в памяти node, и на него вызывается html().

Это некрасиво, он отнимает немного памяти, и я понятия не имею, насколько он настолько тщателен, как что-то вроде библиотеки he, но если вы уже используете jQuery, возможно, это вариант для вас.

Взято из сообщения в блоге Кодировать объекты HTML с jQuery от Felix Geisendörfer.

Ответ 8

Специальные символы HTML и ESCAPE CODES

Зарезервированные символы должны быть экранированы HTML: мы можем использовать escape-символ символа для обозначения любого символа Юникода [Ex: и - U + 00026] в HTML, XHTML или XML, используя только символы ASCII. Числовые символьные ссылки [Пример: ampersand (& ) - &#38;] и Именованные символьные ссылки [Ex: &amp;] являются типами character escape used in markup.


Предопределенные объекты

    Original Character      XML entity replacement     XML numeric replacement  
                  <                                     &lt;                                            &#60;                    
                  >                                      &gt;                                          &#62;                    
                  "                                      &quot;                                       &#34;                    
                  &                                    &amp;                                        &#38;                    
                   '                                     &apos;                                       &#39;                    

Чтобы отображать HTML-теги как обычную форму на веб-странице, мы используем теги <pre>, <code> или можем их избежать. Экранирование строки путем замены любым вхождением символа "&" на строку "&amp;" и любые вхождения символа ">" по строке "&gt;". Пример: stackoverflow post

function escapeCharEntities() {
    var map = {
        "&": "&amp;",
        "<": "&lt;",
        ">": "&gt;",
        "\"": "&quot;",
        "'": "&apos;"
    };
    return map;
}

var mapkeys = '', mapvalues = '';
var html = {
    encodeRex : function () {
        return  new RegExp(mapkeys, 'gm');
    }, 
    decodeRex : function () {
        return  new RegExp(mapvalues, 'gm');
    },
    encodeMap : JSON.parse( JSON.stringify( escapeCharEntities () ) ),
    decodeMap : JSON.parse( JSON.stringify( swapJsonKeyValues( escapeCharEntities () ) ) ),
    encode : function ( str ) {
        return str.replace(html.encodeRex(), function(m) { return html.encodeMap[m]; });
    },
    decode : function ( str ) {
        return str.replace(html.decodeRex(), function(m) { return html.decodeMap[m]; });
    }
};

function swapJsonKeyValues ( json ) {
    var count = Object.keys( json ).length;
    var obj = {};
    var keys = '[', val = '(', keysCount = 1;
    for(var key in json) {
        if ( json.hasOwnProperty( key ) ) {
            obj[ json[ key ] ] = key;
            keys += key;
            if( keysCount < count ) {
                val += json[ key ]+'|';
            } else {
                val += json[ key ];
            }
            keysCount++;
        }
    }
    keys += ']';    val  += ')';
    console.log( keys, ' == ', val);
    mapkeys = keys;
    mapvalues = val;
    return obj;
}

console.log('Encode: ', html.encode('<input type="password" name="password" value=""/>') ); 
console.log('Decode: ', html.decode(html.encode('<input type="password" name="password" value=""/>')) );

O/P:
Encode:  &lt;input type=&quot;password&quot; name=&quot;password&quot; value=&quot;&quot;/&gt;
Decode:  <input type="password" name="password" value=""/>

Ответ 9

Иногда вы просто хотите кодировать каждый символ... Эта функция заменяет "все, кроме ничего" в regxp.

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

function encode(w) {
  return w.replace(/[^]/g, function(w) {
    return "&#" + w.charCodeAt(0) + ";";
  });
}

test.value=encode(document.body.innerHTML.trim());
<textarea id=test rows=11 cols=55>www.WHAK.com</textarea>

Ответ 10

var htmlEntities = [
            {regex:/&/g,entity:'&amp;'},
            {regex:/>/g,entity:'&gt;'},
            {regex:/</g,entity:'&lt;'},
            {regex:/"/g,entity:'&quot;'},
            {regex:/á/g,entity:'&aacute;'},
            {regex:/é/g,entity:'&eacute;'},
            {regex:/í/g,entity:'&iacute;'},
            {regex:/ó/g,entity:'&oacute;'},
            {regex:/ú/g,entity:'&uacute;'}
        ];

total = <some string value>

for(v in htmlEntities){
    total = total.replace(htmlEntities[v].regex, htmlEntities[v].entity);
}

Массивное решение

Ответ 11

replaceHtmlEntities(text) {
  var tagsToReplace = {
    '&amp;': '&',
    '&lt;': '<',
    '&gt;': '>',
  };
  var newtext = text;
  for (var tag in tagsToReplace) {
    if (Reflect.apply({}.hasOwnProperty, this, [tagsToReplace, tag])) {
      var regex = new RegExp(tag, 'g');
      newtext = newtext.replace(regex, tagsToReplace[tag]);
    }
  }
  return newtext;
}

Ответ 12

function encodeHTML(str) {
    return document.createElement("a").appendChild( 
        document.createTextNode(str)).parentNode.innerHTML;
};

function decodeHTML(str) {
    var element = document.createElement("a"); 
    element.innerHTML = str;
    return element.textContent;
};
var str = "<"
var enc = encodeHTML(str);
var dec = decodeHTML(enc);
console.log("str: " + str, "\nenc: " + enc, "\ndec: " + dec);

Ответ 13

Вы можете использовать метод charCodeAt(), чтобы проверить, имеет ли указанный символ значение выше 127 и преобразует его в цифровую ссылку с помощью toString(16).