Existe-t-il un moyen simple de prendre une chaîne de code HTML en JavaScript et de supprimer le code HTML?
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 .
myString.replace(/<(?:.|\n)*?>/gm, '');
Manière la plus simple:
jQuery(html).text();
Cela récupère tout le texte d'une chaîne de code HTML.
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'>")
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.
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.
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.
Cela devrait faire le travail sur n’importe quel environnement Javascript (NodeJS inclus) .text.replace(/<[^>]+>/g, '');
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 "normal text" and stuff using <html encoding>
</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(/ /gi," ");
returnText=returnText.replace(/&/gi,"&");
returnText=returnText.replace(/"/gi,'"');
returnText=returnText.replace(/</gi,'<');
returnText=returnText.replace(/>/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 />
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, "");
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;
}
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);
});
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/
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:
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>
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");
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, "");
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.
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é textContent
innerText
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));
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, '');
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 : '';
});
}
Avec jQuery, vous pouvez simplement le récupérer en utilisant
$('#elementID').text()
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.
jquery simple en 2 lignes pour effacer le code HTML.
var content = "<p>checking the html source </p><p>
</p><p>with </p><p>all</p><p>the html </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
Utiliser Jquery:
function stripTags() {
return $('<p></p>').html(textToEscape).text()
}
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;
}
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, '');
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 || "";
}
Pour les caractères d'échappement, cela fonctionnera également à l'aide d'une correspondance de modèle:
myString.replace(/((<)|(<)(?:.|\n)*?(>)|(>))/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);
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]);
}
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!