Supprimer le HTML du texte JavaScript

656

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

Bryan
la source

Réponses:

763

Si vous utilisez un navigateur, le moyen le plus simple consiste simplement à laisser le navigateur le faire pour vous ...

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

Remarque: comme les gens l'ont remarqué dans les commentaires, il vaut mieux éviter cela si vous ne contrôlez pas la source du code HTML (par exemple, ne l'exécutez pas sur tout ce qui pourrait provenir d'une entrée utilisateur). Pour ces scénarios, vous pouvez toujours laisser le navigateur faire le travail pour vous - voir la réponse de Saba sur l'utilisation du DOMParser désormais largement disponible .

Shog9
la source
40
N'oubliez pas que cette approche est plutôt incohérente et ne parviendra pas à supprimer certains caractères dans certains navigateurs. Par exemple, dans Prototype.js, nous utilisons cette approche pour les performances, mais contournons certaines des lacunes - github.com/kangax/prototype/blob/…
kangax
11
N'oubliez pas que votre espace sera gâché. J'ai utilisé cette méthode, puis j'ai eu des problèmes car certains codes de produit contenaient des espaces doubles, qui se sont retrouvés comme des espaces simples après avoir récupéré le innerText de la DIV. Ensuite, les codes de produit ne correspondaient pas plus tard dans l'application.
Magnus Smith
11
@Magnus Smith: Oui, si les espaces blancs sont une préoccupation - ou vraiment, si vous avez besoin de ce texte qui n'implique pas directement le DOM HTML spécifique avec lequel vous travaillez - alors vous feriez mieux d'utiliser l'un des autres solutions données ici. Les principaux avantages de cette méthode sont qu'elle est 1) triviale et 2) traitera de manière fiable les balises, les espaces blancs, les entités, les commentaires, etc. de la même manière que le navigateur que vous utilisez . C'est souvent utile pour le code client Web, mais pas nécessairement approprié pour interagir avec d'autres systèmes où les règles sont différentes.
Shog9
220
Ne l'utilisez pas avec du HTML provenant d'une source non fiable. Pour voir pourquoi, essayez de courirstrip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")
Mike Samuel
24
Si le html contient des images (balises img), les images seront demandées par le navigateur. Ce n'est pas bon.
douyw
592
myString.replace(/<[^>]*>?/gm, '');
nickf
la source
4
Ne fonctionne pas <img src=http://www.google.com.kh/images/srpr/nav_logo27.png onload="alert(42)" si vous injectez via document.writeou concaténez avec une chaîne qui contient un >avant d'injecter via innerHTML.
Mike Samuel
1
@PerishableDave, je suis d'accord que le >sera laissé dans le second. Ce n'est pas un risque d'injection cependant. Le danger se produit en raison de la <gauche dans le premier, ce qui fait que l'analyseur HTML se trouve dans un contexte autre que l'état des données lorsque le second démarre. Notez qu'il n'y a pas de transition de l'état des données à >.
Mike Samuel
73
@MikeSamuel Avons-nous déjà décidé de cette réponse? Utilisateur naïf ici prêt à copier-coller.
Ziggy
1
Cela aussi, je crois, devient complètement confus si l'on donne quelque chose comme <button onClick="dostuff('>');"></button>Supposons que le HTML est correctement écrit, vous devez toujours tenir compte du fait qu'un signe supérieur à peut être quelque part dans le texte cité dans un attribut. Vous voudrez également supprimer tout le texte à l'intérieur des <script>balises, au moins.
Jonathon
15
@AntonioMax, j'ai répondu à cette question ad nauseam , mais au fond de votre question, car le code critique de sécurité ne doit pas être copié et collé. Vous devez télécharger une bibliothèque et la maintenir à jour et corrigée afin d'être protégé contre les vulnérabilités récemment découvertes et contre les changements dans les navigateurs.
Mike Samuel
249

Manière la plus simple:

jQuery(html).text();

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

marque
la source
111
Nous utilisons toujours jQuery pour les projets car invariablement nos projets ont beaucoup de Javascript. Par conséquent, nous n'avons pas ajouté de volume, nous avons profité du code API existant ...
Mark
32
Vous l'utilisez, mais l'OP peut ne pas. la question concernait Javascript PAS JQuery.
Dementic
105
C'est toujours une réponse utile pour les personnes qui ont besoin de faire la même chose que l'OP (comme moi) et cela ne me dérange pas d'utiliser jQuery (comme moi), sans parler, cela aurait pu être utile à l'OP s'ils envisageaient d'utiliser jQuery. Le but du site est de partager les connaissances. Gardez à l'esprit que l'effet de refroidissement que vous pourriez avoir en châtiant des réponses utiles sans bonne raison.
acjay
27
@Dementic choquant, je trouve que les fils avec plusieurs réponses sont les plus utiles, car souvent une réponse secondaire répond à mes besoins exacts, tandis que la réponse principale répond au cas général.
Eric Goldberg
36
Cela ne fonctionnera pas si une partie de la chaîne n'est pas encapsulée dans une balise html. par exemple "<b> Erreur: </b> Veuillez entrer un e-mail valide" ne renverra que "Erreur:"
Aamir Afridi
128

Je voudrais partager une version édité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 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 || "";
}

ici le code pour tester le javascript inline:

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

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

strip("Just text <img src='https://assets.rbl.ms/4155638/980x.jpg'>")
Sabaz
la source
3
Il convient d'ajouter que cette solution ne fonctionne que dans le navigateur.
kris_IV
1
Il ne s'agit pas de balises de strip, mais plutôt de PHP htmlspecialchars (). Toujours utile pour moi.
Daantje
Notez que cela supprime également les espaces du début du texte.
Raine Revere
À noter également, cela fonctionne dans Web Workers
Chris Seufert
Cela semble être beaucoup plus rapide que la réponse de @ Shog9
Shmuel Kamensky
55

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

jQuery(html).text();`

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

Utilisation:

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

au lieu.

Mise à jour: Comme cela a été souligné dans les commentaires, dans certaines circonstances, cette solution exécutera le javascript contenu dans htmlsi la valeur de htmlpourrait être influencée par un attaquant, utilisez une solution différente.

user999305
la source
12
Ou$("<p>").html(html).text();
Dimitar Dimitrov
4
Cela exécute toujours un code probablement dangereuxjQuery('<span>Text :) <img src="a" onerror="alert(1)"></span>').text()
Simon
essayez jQuery ("aa & # X003c; script> alert (1) & # X003c; / script> a"). text ();
Grzegorz Kaczan
41

Conversion de HTML pour les e-mails en texte brut en conservant les hyperliens (a href) intacts

La fonction ci-dessus publiée par hypoxyde fonctionne bien, mais je recherchais quelque chose qui convertirait essentiellement du HTML créé dans un éditeur Web RichText (par exemple FCKEditor) et effacer tout le HTML mais laisser tous les liens car je voulais à la fois le HTML et la version en texte brut pour faciliter la création des parties correctes d'un e-mail STMP (HTML et texte brut).

Après une longue période de recherche sur Google, mes collègues et moi-même avons trouvé cela en utilisant le moteur 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 strvariable 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>

puis après l'exécution du code, 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 HTML a été supprimé et le lien a été persévéré avec le texte hyperlié est toujours intact. J'ai également remplacé les balises <p>et <br>par\n (newline char) afin de conserver une sorte de formatage visuel.

Pour modifier le format du lien (par exemple BBC (Link->http://www.bbc.co.uk)), il suffit de modifier le $2 (Link->$1), où $1est l'URL / URI href et le $2texte est un 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 ait la possibilité de cliquer dessus.

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

Jibberboy2000
la source
Il ne gère pas "& nbsp;"
Rose Nettoyeur
33

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, quelque chose comme ça ne fera aucun mal:

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

Firefox, Chromium et Explorer 9+ sont sûrs. 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 pour enregistrer les requêtes http.

Janghou
la source
C'est une partie du chemin, mais ce n'est pas sûr<script><script>alert();
Arth
1
Cela n'exécute aucun script ici dans Chromium / Opera / Firefox sur Linux, alors pourquoi n'est-il pas sûr?
Janghou
Mes excuses, je dois avoir raté le test, j'ai probablement oublié de cliquer à nouveau sur le jsFiddle.
Arth
L'argument "Nouveau" est superflu, je pense?
Jon Schneider
Selon les spécifications, c'est facultatif de nos jours, mais ce n'était pas toujours le cas.
Janghou
23

Cela devrait faire le travail sur n'importe quel environnement Javascript (NodeJS inclus).

const text = `
<html lang="en">
  <head>
    <style type="text/css">*{color:red}</style>
    <script>alert('hello')</script>
  </head>
  <body><b>This is some text</b><br/><body>
</html>`;

// Remove style tags and content
text.replace(/<style[^>]*>.*<\/style>/gm, '')
    // Remove script tags and content
    .replace(/<script[^>]*>.*<\/script>/gm, '')
    // Remove all opening, closing and orphan HTML tags
    .replace(/<[^>]+>/gm, '')
    // Remove leading spaces and repeated CR/LF
    .replace(/([\r\n]+ +)+/gm, '');
Karl.S
la source
@pstanton pourriez-vous donner un exemple de travail de votre déclaration?
Karl.S
3
<html><style..>* {font-family:comic-sans;}</style>Some Text</html>
pstanton
@pstanton J'ai corrigé le code et ajouté des commentaires, désolé pour la réponse tardive.
Karl.S
16

J'ai modifié la réponse de Jibberboy2000 pour inclure plusieurs <BR />formats de balises, tout supprimer à l'intérieur <SCRIPT>et<STYLE> balises, formater le HTML résultant en supprimant plusieurs sauts de ligne et espaces et convertir du code codé HTML en normal. Après quelques tests, il apparaît que vous pouvez convertir la plupart des pages Web complètes en texte simple où 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 BBC ( http://www.bbc.co.uk ) avec lien est mentionné.

Maintenant, revenons au "texte normal" et tout en 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 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 />
Elendurwen
la source
1
J'aime cette solution car elle traite les caractères spéciaux html ... mais pas encore assez ... la meilleure réponse pour moi serait de les traiter tous. (ce qui est probablement ce que jquery fait).
Daniel Gerson
2
Je pense que ça /<p.*>/gidevrait l'être /<p.*?>/gi.
cbron
Notez que pour supprimer tout <br> les balises vous pouvez utiliser une bonne expression régulière à la place: /<br\s*\/?>/cette façon , vous avez juste un remplacement au lieu de 3. En outre , il me semble que , sauf pour le décodage des entités que vous pouvez avoir un seul regex, quelque chose comme ceci: /<[a-z].*?\/?>/.
Alexis Wilke
Joli script. Mais qu'en est-il du contenu des tableaux? Toute idée comment peut-elle être affichée
Hristo Enev
@DanielGerson, l'encodage html devient vraiment velu, très rapide, mais la meilleure approche semble être d'utiliser la bibliothèque
he
15
var text = html.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, "");

Il s'agit d'une version regex, plus résistante au HTML malformé, comme:

Balises non fermées

Some text <img

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

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, "");
Hégémon
la source
7

Une autre solution, certes moins élégante que celle de nickf ou Shog9, serait de parcourir récursivement le DOM en commençant par la balise <body> et d'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;
}
Bryan
la source
3
beurk. si vous allez créer un arbre DOM à partir de votre chaîne, alors utilisez simplement shog's way!
nickf
Oui, ma solution manie un marteau de traîneau où un marteau ordinaire est plus approprié :-). Et je suis d'accord que les solutions que vous proposez et celles de Shog9 sont meilleures, et en gros, en ont dit autant dans la réponse. J'ai également omis de refléter dans ma réponse que le code HTML est déjà contenu dans une chaîne, ce qui rend ma réponse essentiellement inutile en ce qui concerne la question d'origine de toute façon. :-(
Bryan
1
Pour être honnête, cela a de la valeur - si vous devez absolument conserver / tout / le texte, alors cela a au moins une chance décente de capturer les nouvelles lignes, les tabulations, les retours chariot, etc ... Là encore, la solution de nickf devrait faire la même chose , et faire beaucoup plus vite ... hein.
Shog9
7

Si vous souhaitez conserver les liens et la structure du contenu (h1, h2, etc.), vous devez vérifier TextVersionJS.Vous pouvez l'utiliser avec n'importe quel code HTML, bien qu'il ait été créé pour convertir un e-mail 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>

Il fonctionne également 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);
});
gyula.nemeth
la source
4

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

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

Deminetix
la source
Il s'agit d'une fonction soignée et bien documentée. Cependant, cela peut être fait plus rapidement quand allowed == ''je pense que c'est ce que le PO a demandé, ce qui est presque ce que Byron a répondu ci-dessous (Byron a seulement eu [^>]tort.)
Alexis Wilke
1
Si vous utilisez le allowedparamètre, vous êtes vulnérable à XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')retours<p onclick="alert(1)">mytext</p>
Chris Cinelli
4
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('');
}

Tient compte des attributs internes et des <img onerror="javascript">é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 la meilleure réponse faisant les choses terribles:

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

utilisateur40521
la source
Vous devrez également gérer les guillemets d'échappement à l'intérieur d'une valeur d'attribut (par exemple string with <a malicious="attribute \">this text should be removed, but is not">example</a>).
ramassage Logan du
4

Beaucoup de gens ont déjà répondu à cette question, mais j'ai pensé qu'il pourrait ê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 souhaitez pas supprimer. C'est assez court et ça fonctionne bien 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>
Harry Stevens
la source
3

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

stringWithHTML = stringWithHTML.replace(/<\/?[a-z][a-z0-9]*[^<>]*>/ig, "");
Byron Carasco
la source
11
Ne faites pas cela si vous vous souciez de la sécurité. Si l'entrée utilisateur est la suivante: '<scr <script> ipt> alert (42); </ scr </script> ipt>' alors la version supprimée sera la suivante: '<script> alert (42); </ script > '. Il s'agit donc d'une vulnérabilité XSS.
molnarg
Vous devez modifier le [^<>]avec [^>]car une balise valide ne peut pas inclure de <caractère, alors la vulnérabilité XSS disparaît.
Alexis Wilke du
3

J'ai apporté quelques modifications au script Jibberboy2000 original 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");
Jaxolotl
la source
3

Voici une version qui répond en quelque sorte au problème 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 du XML valide (aka, les balises doivent être fermées et les attributs doivent être cités). Ce n'est pas idéal, mais cela évite d'avoir le potentiel d'exploiter la 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.

Jeremy Johnstone
la source
Cela échouera dans de nombreuses circonstances si le texte provient de la saisie de l'utilisateur (zone de texte ou widget modifiable ...)
Alexis Wilke
3

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

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

L'élément le mieux adapté pour injecter notre texte est un iframe en bac à sable, de cette façon nous pouvons empêcher toute exécution de code arbitraire (également connu sous le nom de XSS ).

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

Voici ce que j'ai trouvé (non 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 ( démo ):

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));
Etienne Martin
la source
Excellente solution pour les environnements Web! Vous ne devriez probablement pas utiliser un IIFE car depuis ECMAScript 2015, les variables de portée de bloc sont déjà correctement étendues au bloc avec les opérateurs letet const. De plus, en utilisant votre solution, j'ai obtenu de nombreuses références de iframesnon utilisées dans le document. Pensez à ajouter un document.body.removeChild(sandbox)dans le code pour les futurs lecteurs basés sur les pâtes à copier.
Amin NAIRI
2

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

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

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 : '';
      });
}
aWebDeveloper
la source
1
Vous devez citer la source ( phpjs). Si vous utilisez le allowedparamètre, vous êtes vulnérable à XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')retours<p onclick="alert(1)">mytext</p>
Chris Cinelli
2

Il est également possible d'utiliser le fantastique analyseur HTML JS htmlparser2 pur. Voici une démo fonctionnelle:

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 sur le nœud et sur le navigateur si vous compressez votre application Web à l'aide d'un outil tel que webpack.

Johannes Fahrenkrug
la source
2

J'avais juste besoin de retirer les <a>balises et de les remplacer par le texte du lien.

Cela semble très bien fonctionner.

htmlContent= htmlContent.replace(/<a.*href="(.*?)">/g, '');
htmlContent= htmlContent.replace(/<\/a>/g, '');
FrigginGlorious
la source
Cela ne s'applique qu'à une balise et nécessite une modification pour être une fonction large.
m3nda
Oui, en plus une balise d'ancrage pourrait avoir de nombreux autres attributs tels que le title="...".
Alexis Wilke
1

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, ''); 
MarekJ47
la source
1

simple jquery 2 lignes pour dépouiller le 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
Développeur
la source
1

La réponse acceptée fonctionne très bien la plupart du temps, cependant dans IE si la htmlchaîne est, nullvous 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 || "";
}
basarat
la source
1

Utilisation de Jquery:

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

inputl'élément ne prend en charge qu'un texte de ligne :

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

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

Mise à jour: 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;
}
Mike Datsko
la source
Ne fonctionne pas, veuillez toujours mentionner le navigateur que vous utilisez lorsque vous postez une réponse. Ceci est inexact et ne fonctionnera pas dans Chrome 61. Les balises sont simplement rendues sous forme de chaîne.
vdegenne
0
    (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-le comme un plugin jquery et utilisez-le comme suit:

$.html2text(htmlContent);
Shiv Shankar
la source
Disons que cela vient de l'entrée de l'utilisateur. Il peut être utilisé pour ajouter un script ou des macros à votre page
Oluwatumbi