Удаление HTML из текста JavaScript



есть ли простой способ взять строку html в JavaScript и удалить html?

792   30  

30 ответов:

Если вы работаете в браузере, то самый простой способ-это просто браузер сделает это за вас...

function strip(html)
{
   var tmp = document.createElement("DIV");
   tmp.innerHTML = html;
   return tmp.textContent || tmp.innerText || "";
}

Примечание: как люди отметили в комментариях, этого лучше избегать, если вы не контролируете источник HTML (например, не запускайте это ни на чем, что могло бы исходить из пользовательского ввода). Для этих сценариев, вы можете еще пусть браузер сделает работу за вас -см. ответ Сабы на использование теперь широко доступного DOMParser.

myString.replace(/<(?:.|\n)*?>/gm, '');

самый простой способ:

jQuery(html).text();

который извлекает весь текст из строки html.

как расширение метода jQuery, если ваша строка может не содержать HTML (например, если вы пытаетесь удалить HTML из поля формы)

jQuery(html).text();

вернет пустую строку, если нет html

использование:

jQuery('<p>' + html + '</p>').text();

.

обновление: Как было указано в комментариях, в некоторых случаях это решение будет выполнять javascript, содержащийся в html если значение html может быть под влиянием злоумышленника, используйте другое решение.

Я хотел бы поделиться отредактированную версию Shog9одобренный ответ.


как Майк Сэмюэль указал с комментарием, что функция может выполнять встроенные коды javascript.
Но Shog9 прав, когда говорит: "пусть браузер сделает это за вас..."

так.. вот моя отредактированная версия, используя DOMParser:

function strip(html){
   var doc = new DOMParser().parseFromString(html, 'text/html');
   return doc.body.textContent || "";
}

здесь код для проверки встроенного javascript:

strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")

кроме того, он не запрашивает ресурсы на разбор (например, изображения)

strip("Just text <img src='https://assets.rbl.ms/4155638/980x.jpg'>")

преобразование HTML в обычный текст по электронной почте, сохраняя гиперссылки (с href, в) интактных

функции выше написал hypoxide работает нормально, но я был после чего-то, что будет в принципе преобразовать HTML, созданные в веб-richtext с редактора (например FCKEditor) и убрать все HTML, но оставить все ссылки из-за того, что я хотел, как HTML и обычный текст, чтобы помочь создать правильные части к СТМП электронной почты (HTML и обычный текст).

после долгого время поиска Google сам и мои коллеги придумали это с помощью движка регулярных выражений в Javascript:

str='this string has <i>html</i> code i want to <b>remove</b><br>Link Number 1 -><a href="http://www.bbc.co.uk">BBC</a> Link Number 1<br><p>Now back to normal text and stuff</p>
';
str=str.replace(/<br>/gi, "\n");
str=str.replace(/<p.*>/gi, "\n");
str=str.replace(/<a.*href="(.*?)".*>(.*?)<\/a>/gi, "  (Link->) ");
str=str.replace(/<(?:.|\s)*?>/g, "");

the str переменная начинается так:

this string has <i>html</i> code i want to <b>remove</b><br>Link Number 1 -><a href="http://www.bbc.co.uk">BBC</a> Link Number 1<br><p>Now back to normal text and stuff</p>

и затем после запуска кода это выглядит так: -

this string has html code i want to remove
Link Number 1 -> BBC (Link->http://www.bbc.co.uk)  Link Number 1


Now back to normal text and stuff

как вы можете видеть, все HTML был удален, и ссылка была сохранена с гиперссылкой текста по-прежнему нетронутым. Также Я заменил <p> и <br> теги \n (строки типа char) так что какое-то визуальное Форматирование было сохранено.

для изменения формата ссылки (например. BBC (Link->http://www.bbc.co.uk) ) просто редактировать (Link->), где - это URL / URI href и - это текст гиперссылки. С помощью ссылок непосредственно в теле обычного текста большинство почтовых клиентов SMTP конвертируют их, чтобы пользователь мог щелкнуть по ним.

надеюсь, что вы найдете это полезным.

улучшение принятого ответа.

function strip(html)
{
   var tmp = document.implementation.createHTMLDocument("New").body;
   tmp.innerHTML = html;
   return tmp.textContent || tmp.innerText || "";
}

таким образом, что-то вроде этого не повредит:

strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")

Firefox, Chromium и Explorer 9+ безопасны. Опера Престо все еще уязвима. Также изображения, упомянутые в строках, не загружаются в Chromium и Firefox, сохраняя http-запросы.

Это должно делать работу в любой среде Javascript (включая NodeJS). text.replace(/<[^>]+>/g, '');

Я изменил ответ Jibberboy2000 включить несколько <BR /> форматы тегов, удалите все внутри <SCRIPT> и <STYLE> теги, отформатируйте полученный HTML, удалив несколько разрывов строк и пробелов и преобразуйте некоторый HTML-кодированный код в нормальный. После тестирования выясняется, что вы сможете конвертировать веб-страницы в простой текст, где заголовок страницы и контент сохраняются.

в простой например,

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<!--comment-->

<head>

<title>This is my title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style>

    body {margin-top: 15px;}
    a { color: #D80C1F; font-weight:bold; text-decoration:none; }

</style>
</head>

<body>
    <center>
        This string has <i>html</i> code i want to <b>remove</b><br>
        In this line <a href="http://www.bbc.co.uk">BBC</a> with link is mentioned.<br/>Now back to &quot;normal text&quot; and stuff using &lt;html encoding&gt;                 
    </center>
</body>
</html>

становится

это мой заголовок

эта строка имеет html-код, который я хочу удалить

в этой строке Би-би-си (http://www.bbc.co.uk) со ссылкой упоминается.

теперь вернемся к "нормальному тексту" и материалу с помощью

функция JavaScript и тестовая страница выглядят так:

function convertHtmlToText() {
    var inputText = document.getElementById("input").value;
    var returnText = "" + inputText;

    //-- remove BR tags and replace them with line break
    returnText=returnText.replace(/<br>/gi, "\n");
    returnText=returnText.replace(/<br\s\/>/gi, "\n");
    returnText=returnText.replace(/<br\/>/gi, "\n");

    //-- remove P and A tags but preserve what's inside of them
    returnText=returnText.replace(/<p.*>/gi, "\n");
    returnText=returnText.replace(/<a.*href="(.*?)".*>(.*?)<\/a>/gi, "  ()");

    //-- remove all inside SCRIPT and STYLE tags
    returnText=returnText.replace(/<script.*>[\w\W]{1,}(.*?)[\w\W]{1,}<\/script>/gi, "");
    returnText=returnText.replace(/<style.*>[\w\W]{1,}(.*?)[\w\W]{1,}<\/style>/gi, "");
    //-- remove all else
    returnText=returnText.replace(/<(?:.|\s)*?>/g, "");

    //-- get rid of more than 2 multiple line breaks:
    returnText=returnText.replace(/(?:(?:\r\n|\r|\n)\s*){2,}/gim, "\n\n");

    //-- get rid of more than 2 spaces:
    returnText = returnText.replace(/ +(?= )/g,'');

    //-- get rid of html-encoded characters:
    returnText=returnText.replace(/&nbsp;/gi," ");
    returnText=returnText.replace(/&amp;/gi,"&");
    returnText=returnText.replace(/&quot;/gi,'"');
    returnText=returnText.replace(/&lt;/gi,'<');
    returnText=returnText.replace(/&gt;/gi,'>');

    //-- return
    document.getElementById("output").value = returnText;
}

он был использован с этим HTML:

<textarea id="input" style="width: 400px; height: 300px;"></textarea><br />
<button onclick="convertHtmlToText()">CONVERT</button><br />
<textarea id="output" style="width: 400px; height: 300px;"></textarea><br />

другим, по общему признанию, менее элегантным решением, чем nickf или Shog9, было бы рекурсивное прохождение DOM, начинающееся с тега

, и добавление каждого текстового узла.
var bodyContent = document.getElementsByTagName('body')[0];
var result = appendTextNodes(bodyContent);

function appendTextNodes(element) {
    var text = '';

    // Loop through the childNodes of the passed in element
    for (var i = 0, len = element.childNodes.length; i < len; i++) {
        // Get a reference to the current child
        var node = element.childNodes[i];
        // Append the node's value if it's a text node
        if (node.nodeType == 3) {
            text += node.nodeValue;
        }
        // Recurse through the node's children, if there are any
        if (node.childNodes.length > 0) {
            appendTextNodes(node);
        }
    }
    // Return the final result
    return text;
}

Если вы хотите сохранить ссылки и структуру контента (h1, h2 и т. д.), то вы должны проверить TextVersionJS вы можете использовать его с любым HTML, хотя он был создан для преобразования HTML электронной почты в обычный текст.

использование очень прост. Например в узле.js:

var createTextVersion = require("textversionjs");
var yourHtml = "<h1>Your HTML</h1><ul><li>goes</li><li>here.</li></ul>";

var textVersion = createTextVersion(yourHtml);

или в браузере с чистым js:

<script src="textversion.js"></script>
<script>
  var yourHtml = "<h1>Your HTML</h1><ul><li>goes</li><li>here.</li></ul>";
  var textVersion = createTextVersion(yourHtml);
</script>

Он также работает с require.js:

define(["textversionjs"], function(createTextVersion) {
  var yourHtml = "<h1>Your HTML</h1><ul><li>goes</li><li>here.</li></ul>";
  var textVersion = createTextVersion(yourHtml);
});

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

Я начал изучать, как php делает это и наткнулся на php.JS lib, который реплицирует метод strip_tags здесь:http://phpjs.org/functions/strip_tags/

function stripHTML(my_string){
    var charArr   = my_string.split(''),
        resultArr = [],
        htmlZone  = 0,
        quoteZone = 0;
    for( x=0; x < charArr.length; x++ ){
     switch( charArr[x] + htmlZone + quoteZone ){
       case "<00" : htmlZone  = 1;break;
       case ">10" : htmlZone  = 0;resultArr.push(' ');break;
       case '"10' : quoteZone = 1;break;
       case "'10" : quoteZone = 2;break;
       case '"11' : 
       case "'12" : quoteZone = 0;break;
       default    : if(!htmlZone){ resultArr.push(charArr[x]); }
     }
    }
    return resultArr.join('');
}

учетные записи > внутренние атрибуты и <img onerror="javascript"> во вновь созданных элементах dom.

использование:

clean_string = stripHTML("string with <html> in it")

демо:

https://jsfiddle.net/gaby_de_wilde/pqayphzd/

демо топ ответ делать ужасные вещи:

https://jsfiddle.net/gaby_de_wilde/6f0jymL6/1/

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

function removeTags(string, array){
  return array ? string.split("<").filter(function(val){ return f(array, val); }).map(function(val){ return f(array, val); }).join("") : string.split("<").map(function(d){ return d.split(">").pop(); }).join("");
  function f(array, value){
    return array.map(function(d){ return value.includes(d + ">"); }).indexOf(true) != -1 ? "<" + value : value.split(">")[1];
  }
}

var x = "<span><i>Hello</i> <b>world</b>!</span>";
console.log(removeTags(x)); // Hello world!
console.log(removeTags(x, ["span", "i"])); // <span><i>Hello</i> world!</span>

Я внес некоторые изменения в оригинальный скрипт Jibberboy2000 Надеюсь, что это будет полезно для кого-то

str = '**ANY HTML CONTENT HERE**';

str=str.replace(/<\s*br\/*>/gi, "\n");
str=str.replace(/<\s*a.*href="(.*?)".*>(.*?)<\/a>/gi, "  (Link->) ");
str=str.replace(/<\s*\/*.+?>/ig, "\n");
str=str.replace(/ {2,}/gi, " ");
str=str.replace(/\n+\s*/gi, "\n\n");

вот версия, в которой sorta обращается к проблеме безопасности @MikeSamuel:

function strip(html)
{
   try {
       var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null);
       doc.documentElement.innerHTML = html;
       return doc.documentElement.textContent||doc.documentElement.innerText;
   } catch(e) {
       return "";
   }
}

Примечание, он будет возвращать пустую строку, если разметка HTML не является допустимым XML (ака, теги должны быть закрыты и атрибуты должны быть заключены в кавычки). Это не идеально, но позволяет избежать проблемы наличия потенциала эксплойта безопасности.

Если у вас нет допустимой разметки XML, вы можете попробовать использовать:

var doc = document.implementation.createHTMLDocument("");

но это не идеальное решение, как для других причины.

Я думаю, что самый простой способ-просто использовать регулярные выражения, как кто-то упоминал выше. Хотя нет никаких причин использовать их кучу. Попробуйте:

stringWithHTML = stringWithHTML.replace(/<\/?[a-z][a-z0-9]*[^<>]*>/ig, "");

С помощью jQuery вы можете просто получить его с помощью

$('#elementID').text()

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

function strip_tags(input, allowed) {

  allowed = (((allowed || '') + '')
    .toLowerCase()
    .match(/<[a-z][a-z0-9]*>/g) || [])
    .join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)

  var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
      commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;

  return input.replace(commentsAndPhpTags, '')
      .replace(tags, function(, ) {
          return allowed.indexOf('<' + .toLowerCase() + '>') > -1 ?  : '';
      });
}

также можно использовать фантастический htmlparser2 чистый JS HTML парсер. Вот рабочая демонстрация:

var htmlparser = require('htmlparser2');

var body = '<p><div>This is </div>a <span>simple </span> <img src="test"></img>example.</p>';

var result = [];

var parser = new htmlparser.Parser({
    ontext: function(text){
        result.push(text);
    }
}, {decodeEntities: true});

parser.write(body);
parser.end();

result.join('');

выход будет This is a simple example.

смотрите его в действии здесь:https://tonicdev.com/jfahrenkrug/extract-text-from-html

это работает как в узле, так и в браузере, если вы упаковываете веб-приложение с помощью такого инструмента, как webpack.

мне просто нужно вырезать <a> теги и заменить их на текст по ссылке.

Это, кажется, работает отлично.

htmlContent= htmlContent.replace(/<a.*href="(.*?)">/g, '');
htmlContent= htmlContent.replace(/<\/a>/g, '');
var text = html.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, "");

это регулярное выражение версии, которая более устойчива к искаженным HTML, как:

незакрытые теги

Some text <img

"" внутри атрибутов тега

Some text <img alt="x > y">

строки

Some <a href="http://google.com">

код

var html = '<br>This <img alt="a>b" \r\n src="a_b.gif" />is > \nmy<>< > <a>"text"</a'
var text = html.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, "");

Я сам создал рабочее регулярное выражение:

str=str.replace(/(<\?[a-z]*(\s[^>]*)?\?(>|$)|<!\[[a-z]*\[|\]\]>|<!DOCTYPE[^>]*?(>|$)|<!--[\s\S]*?(-->|$)|<[a-z?!\/]([a-z0-9_:.])*(\s[^>]*)?(>|$))/gi, ''); 

простой 2-строчный jquery для удаления html.

 var content = "<p>checking the html source&nbsp;</p><p>&nbsp;
  </p><p>with&nbsp;</p><p>all</p><p>the html&nbsp;</p><p>content</p>";

 var text = $(content).text();//It gets you the plain text
 console.log(text);//check the data in your console

 cj("#text_area_id").val(text);//set your content to text area using text_area_id

принятый ответ работает нормально в основном, однако в IE, если html строка null вы получаете "null" (вместо "). Исправлено:

function strip(html)
{
   if (html == null) return "";
   var tmp = document.createElement("DIV");
   tmp.innerHTML = html;
   return tmp.textContent || tmp.innerText || "";
}

С Помощью Jquery:

function stripTags() {
    return $('<p></p>').html(textToEscape).text()
}

input элемент поддержка только одной строки текста:

текст означает, что одна строка обычного текста редактирования для значения элемента.

function stripHtml(str) {
  var tmp = document.createElement('input');
  tmp.value = str;
  return tmp.value;
}

обновление: это работает, как ожидалось

function stripHtml(str) {
  // Remove some tags
  str = str.replace(/<[^>]+>/gim, '');

  // Remove BB code
  str = str.replace(/\[(\w+)[^\]]*](.*?)\[\/]/g, ' ');

  // Remove html and line breaks
  const div = document.createElement('div');
  div.innerHTML = str;

  const input = document.createElement('input');
  input.value = div.textContent || div.innerText || '';

  return input.value;
}

вы можете безопасно удалить html-теги с помощью iframe sandbox атрибут.

идея здесь заключается в том, что вместо того, чтобы регулярное выражение нашей строки, мы воспользуемся родной парсер браузера, вводя текст в DOM-элемент, а затем запрашивая textContent/innerText свойства этого элемента.

наилучшим подходящим элементом для вставки нашего текста является изолированный iframe, таким образом мы можем предотвратить любое выполнение произвольного кода (также известный как XSS).

недостатком этого подхода является то, что он работает только в браузерах.

вот что я придумал (не проверенные):

const stripHtmlTags = (() => {
  const sandbox = document.createElement("iframe");
  sandbox.sandbox = "allow-same-origin"; // <--- This is the key
  sandbox.style.setProperty("display", "none", "important");

  // Inject the sanbox in the current document
  document.body.appendChild(sandbox);

  // Get the sandbox's context
  const sanboxContext = sandbox.contentWindow.document;

  return (untrustedString) => {
    if (typeof untrustedString !== "string") return ""; 

    // Write the untrusted string in the iframe's body
    sanboxContext.open();
    sanboxContext.write(untrustedString);
    sanboxContext.close();

    // Get the string without html
    return sanboxContext.body.textContent || sanboxContext.body.innerText || "";
  };
})();

использование (демо):

console.log(stripHtmlTags(`<img onerror='alert("could run arbitrary JS here")' src='bogus'>XSS injection :)`));
console.log(stripHtmlTags(`<script>alert("awdawd");</` + `script>Script tag injection :)`));
console.log(stripHtmlTags(`<strong>I am bold text</strong>`));
console.log(stripHtmlTags(`<html>I'm a HTML tag</html>`));
console.log(stripHtmlTags(`<body>I'm a body tag</body>`));
console.log(stripHtmlTags(`<head>I'm a head tag</head>`));
console.log(stripHtmlTags(null));
    (function($){
        $.html2text = function(html) {
            if($('#scratch_pad').length === 0) {
                $('<div id="lh_scratch"></div>').appendTo('body');  
            }
            return $('#scratch_pad').html(html).text();
        };

    })(jQuery);

определите это как плагин jquery и используйте его следующим образом:

$.html2text(htmlContent);

для escape-символов также это будет работать с использованием сопоставления шаблонов:

myString.replace(/((&lt)|(<)(?:.|\n)*?(&gt)|(>))/gm, '');

Comments

    Ничего не найдено.