web-dev-qa-db-fra.com

Supprimer le code HTML du texte JavaScript

Existe-t-il un moyen simple de prendre une chaîne de code HTML en JavaScript et de supprimer le code HTML? 

530
Bryan

Si vous utilisez un navigateur, le moyen le plus simple est simplement de laissez le navigateur le faire pour vous ...

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

Remarque: comme le notent les gens dans les commentaires, évitez cela si vous ne contrôlez pas la source du code HTML (par exemple, ne l'exécutez pas sur quoi que ce soit qui aurait pu provenir d'une entrée utilisateur). Pour ces scénarios, vous pouvez still laisser le navigateur effectuer le travail à votre place - voir la réponse de Saba sur l'utilisation du DOMParser désormais disponible .

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

Manière la plus simple:

jQuery(html).text();

Cela récupère tout le texte d'une chaîne de code HTML. 

224
Mark

Je voudrais partager une version modifiée de la réponse approuvée du Shog9 .


Comme Mike Samuel l'a souligné avec un commentaire, cette fonction peut exécuter des codes javascript en ligne.
Mais Shog9 a raison de dire "laissez le navigateur le faire pour vous ..." 

alors .. voici ma version éditée, en utilisant DOMParser :

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

voici le code pour tester le javascript en ligne:

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

En outre, il ne demande pas de ressources lors de l'analyse (comme des images)

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

En tant qu'extension de la méthode jQuery, si votre chaîne risque de ne pas contenir du code HTML (par exemple, si vous essayez de supprimer du code HTML d'un champ de formulaire)

jQuery(html).text();

renverra une chaîne vide s'il n'y a pas de HTML

Utilisation:

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

au lieu.

Mise à jour: Comme indiqué dans les commentaires, dans certains cas, cette solution exécutera le code javascript contenu dans html si la valeur de html peut être influencée par un attaquant, utilisez une solution différente.

52
user999305

Conversion de HTML pour l'envoi d'e-mails en texte brut en conservant les liens hypertexte (a href)

La fonction ci-dessus publiée par hypoxide fonctionne bien, mais je cherchais un moyen de convertir le code HTML créé dans un éditeur Web RichText (par exemple, FCKEditor) et d'effacer tout le code HTML, tout en laissant tous les liens, car je voulais le la version en texte brut pour aider à créer les parties correctes d'un courrier électronique STMP (HTML et texte brut).

Après une longue période de recherche sur Google, mes collègues et moi-même sommes arrivés à cela en utilisant le moteur de regex en 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, " $2 (Link->$1) ");
str=str.replace(/<(?:.|\s)*?>/g, "");

la variable str commence comme ceci:

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>

et ensuite, une fois le code exécuté, il ressemble à ceci: -

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

Comme vous pouvez le voir, tout le code HTML a été supprimé et le lien maintenu avec le texte avec lien hypertexte est toujours intact. De plus, j'ai remplacé les balises <p> et <br> par \n (caractère newline), de sorte qu'une certaine mise en forme visuelle a été conservée.

Pour changer le format du lien (par exemple, BBC (Link->http://www.bbc.co.uk)), il suffit de modifier la $2 (Link->$1), où $1 est l'URL/URI href et le $2 est le texte avec lien hypertexte. Avec les liens directement dans le corps du texte brut, la plupart des clients de messagerie SMTP les convertissent afin que l'utilisateur puisse cliquer dessus.

Espérant que ceci puisse t'être utile.

35
Jibberboy2000

Une amélioration de la réponse acceptée.

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

De cette façon, un fonctionnement comme celui-ci ne fera aucun mal:

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

Firefox, Chromium et Explorer 9+ sont en sécurité . Opera Presto est toujours vulnérable . De plus, les images mentionnées dans les chaînes ne sont pas téléchargées dans Chromium et Firefox enregistre les requêtes http.

30
Janghou

Cela devrait faire le travail sur n’importe quel environnement Javascript (NodeJS inclus) .text.replace(/<[^>]+>/g, '');

16
Karl.S

J'ai modifié La réponse de Jibberboy2000 pour inclure plusieurs formats de balises <BR />, supprimer tout le contenu des balises <SCRIPT> et <STYLE>, formater le code HTML résultant en supprimant plusieurs espaces et sauts de ligne et convertir un code codé au format HTML en code normal. Après quelques tests, il apparaît que vous pouvez convertir la plupart des pages Web complètes en texte simple dans lequel le titre et le contenu de la page sont conservés.

Dans l'exemple simple,

<!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>

devient

C'est mon titre

Cette chaîne a du code HTML que je veux supprimer

Dans cette ligne, la BBC ( http://www.bbc.co.uk ) avec un lien est mentionnée.

Revenons maintenant au "texte normal" et au contenu utilisant 

La fonction JavaScript et la page de test ressemblent à ceci:

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, " $2 ($1)");

    //-- 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;
}

Il a été utilisé avec ce code 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 />
15
Elendurwen
var text = html.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, "");

Ceci est une version regex plus résiliente au HTML malformé, comme:

Tags non fermés

Some text <img

"<", ">" à l'intérieur des attributs de balises

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

Newlines

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

Le code

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

Une autre solution, certes moins élégante que celle de nickf ou de Shog9, consisterait à parcourir le DOM de manière récursive en commençant à la balise <body> et à ajouter chaque nœud de texte.

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;
}
7
Bryan

Si vous souhaitez conserver les liens et la structure du contenu (h1, h2, etc.), vous devez alors consulter TextVersionJS Vous pouvez l’utiliser avec n’importe quel code HTML, bien qu’il ait été créé pour convertir un courrier électronique HTML en texte brut .

L'utilisation est très simple. Par exemple dans node.js:

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

var textVersion = createTextVersion(yourHtml);

Ou dans le navigateur avec pure 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>

Cela fonctionne aussi avec require.js:

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

Après avoir essayé toutes les réponses mentionnées, la plupart sinon toutes avaient des cas Edge et ne pouvaient pas subvenir complètement à mes besoins.

J'ai commencé à explorer comment php le fait et suis tombé sur la lib php.js qui reproduit la méthode strip_tags ici: http://phpjs.org/functions/strip_tags/

4
Deminetix
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('');
}

Comptes pour les attributs internes et <img onerror="javascript"> dans les éléments dom nouvellement créés.

usage:

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

démo:

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

démo de top answer faisant les choses terribles:

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

4
user40521

Beaucoup de personnes ont déjà répondu à cette question, mais j’ai pensé qu’il serait peut-être utile de partager la fonction que j’ai écrite qui supprime les balises HTML d’une chaîne, mais vous permet d’inclure un tableau de balises que vous ne voulez pas supprimer. C'est assez court et a bien fonctionné pour moi.

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>
4
Harry Stevens

J'ai apporté quelques modifications au script original de Jibber 2000 .___. J'espère qu'il sera utile à quelqu'un

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

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

Je pense que le moyen le plus simple consiste à utiliser simplement les expressions régulières comme mentionné ci-dessus. Bien qu'il n'y ait aucune raison d'en utiliser plusieurs. Essayer:

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

Voici une version qui répond en quelque sorte aux préoccupations de sécurité de 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 "";
   }
}

Remarque, il retournera une chaîne vide si le balisage HTML n'est pas un code XML valide (les balises doivent être fermées et les attributs doivent être cités). Ce n'est pas idéal, mais cela évite d'avoir à exploiter le potentiel de sécurité.

Si vous n'avez pas besoin d'un balisage XML valide, vous pouvez essayer d'utiliser:

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

mais ce n'est pas une solution parfaite non plus pour d'autres raisons.

3
Jeremy Johnstone

Vous pouvez supprimer les balises HTML en toute sécurité à l’aide de l’attribut iframe sandbox .

L'idée ici est qu'au lieu d'essayer de regex notre chaîne, nous tirons parti de l'analyseur natif du navigateur en injectant le texte dans un élément DOM, puis en interrogeant la propriété textContentinnerText de cet élément.

L'élément le mieux adapté à l'injection de notre texte est un iframe en mode bac à sable, ce qui nous permet d'empêcher toute exécution de code arbitraire (également appelé XSS ).

L'inconvénient de cette approche est qu'il ne fonctionne que dans les navigateurs.

Voici ce que je suis venu avec (Pas testé au combat):

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 || "";
  };
})();

_/Utilisation ( demo ):

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));
2
Etienne Martin

Je devais simplement supprimer les balises <a> et les remplacer par le texte du lien.

Cela semble bien fonctionner.

htmlContent= htmlContent.replace(/<a.*href="(.*?)">/g, '');
htmlContent= htmlContent.replace(/<\/a>/g, '');
2
FrigginGlorious

Le code ci-dessous vous permet de conserver certaines balises HTML tout en supprimant toutes les autres. 

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($0, $1) {
          return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
      });
}
2
aWebDeveloper

Avec jQuery, vous pouvez simplement le récupérer en utilisant 

$('#elementID').text()
2
ianaz

Il est également possible d’utiliser l’analyseur fantastique -htmlparser2 pure JS HTML. Voici une démo de travail:

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('');

La sortie sera This is a simple example.

Voyez-le en action ici: https://tonicdev.com/jfahrenkrug/extract-text-from-html

Cela fonctionne à la fois dans le noeud et dans le navigateur si vous compressez votre application Web en utilisant un outil tel que webpack.

2
Johannes Fahrenkrug

jquery simple en 2 lignes pour effacer le code 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
1
Developer

Utiliser Jquery: 

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

input element ne prend en charge que le texte d'une ligne :

L'état du texte représente un contrôle d'édition de texte en clair d'une ligne pour la valeur de l'élément.

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

Update: cela fonctionne comme prévu

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

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

  // 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;
}
1
Mike Datsko

J'ai moi-même créé une expression régulière de travail:

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

La réponse acceptée fonctionne généralement bien, mais dans IE si la chaîne html est null, vous obtenez le "null" (au lieu de ''). Fixé: 

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

Pour les caractères d'échappement, cela fonctionnera également à l'aide d'une correspondance de modèle:

myString.replace(/((&lt)|(<)(?:.|\n)*?(&gt)|(>))/gm, '');
    (function($){
        $.html2text = function(html) {
            if($('#scratch_pad').length === 0) {
                $('<div id="lh_scratch"></div>').appendTo('body');  
            }
            return $('#scratch_pad').html(html).text();
        };

    })(jQuery);

Définissez ceci comme un plugin jquery et utilisez-le comme suit:

$.html2text(htmlContent);
0
Shiv Shankar

https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML

var div = document.getElementsByTagName('div');
for (var i=0; i<div.length; i++) {
    div[i].insertAdjacentHTML('afterend', div[i].innerHTML);
    document.body.removeChild(div[i]);
}
0
sonichy
function strip_html_tags(str)
{
   if ((str===null) || (str===''))
       return false;
  else
   str = str.toString();
  return str.replace(/<[^>]*>/g, '');
}

Un moyen plus sûr de supprimer le code HTML avec jQuery consiste tout d'abord à utiliser jQuery.parseHTML pour créer un DOM, en ignorant tous les scripts, avant de laisser jQuery créer un élément, puis de récupérer uniquement le texte.

function stripHtml(unsafe) {
    return $($.parseHTML(unsafe)).text();
}

Peut effacer le code HTML de:

<img src="unknown.gif" onerror="console.log('running injections');">

Et d'autres exploits.

nonJoy!

0
nickl-