Usuń HTML z tekstowego JavaScript

655

Czy istnieje prosty sposób, aby pobrać ciąg HTML w JavaScript i usunąć HTML?

Bryan
źródło

Odpowiedzi:

760

Jeśli korzystasz z przeglądarki, najłatwiej jest po prostu pozwolić przeglądarce zrobić to za Ciebie ...

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

Uwaga: jak zauważyli ludzie w komentarzach, najlepiej tego uniknąć, jeśli nie kontrolujesz źródła kodu HTML (na przykład nie uruchamiaj go na niczym, co mogłoby pochodzić z danych wprowadzonych przez użytkownika). W przypadku tych scenariuszy nadal możesz pozwolić, aby przeglądarka wykonała pracę za Ciebie - zobacz odpowiedź Saby na temat korzystania z powszechnie dostępnego DOMParser .

Shog9
źródło
40
Pamiętaj tylko, że takie podejście jest raczej niespójne i nie spowoduje usunięcia niektórych znaków w niektórych przeglądarkach. Na przykład w Prototype.js używamy tego podejścia do wydajności, ale omijamy
kangax
11
Pamiętaj, że twoje białe znaki będą pomieszane. Kiedyś korzystałem z tej metody, a potem miałem problemy, ponieważ niektóre kody produktów zawierały podwójne spacje, które skończyły jako pojedyncze spacje po odzyskaniu tekstu wewnętrznego z DIV. Następnie kody produktów nie pasowały później w aplikacji.
Magnus Smith
11
@Magnus Smith: Tak, jeśli spacja jest problemem - a tak naprawdę, jeśli potrzebujesz tego tekstu, który nie dotyczy bezpośrednio konkretnej DOM HTML, z którą pracujesz - lepiej skorzystaj z jednego z pozostałych podane tutaj rozwiązania. Głównymi zaletami tej metody jest to, że jest ona 1) trywialna, a 2) niezawodnie przetwarza tagi, białe znaki, encje, komentarze itp. W taki sam sposób, jak przeglądarka, w której pracujesz . Jest to często przydatne w kodzie klienta WWW, ale niekoniecznie jest odpowiednie do interakcji z innymi systemami, w których reguły są różne.
Shog9
220
Nie używaj tego w HTML z niezaufanego źródła. Aby zobaczyć, dlaczego, spróbuj uruchomićstrip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")
Mike Samuel
24
Jeśli html zawiera obrazy (tagi img), zdjęcia zostaną zażądane przez przeglądarkę. To nie jest dobrze.
douyw
589
myString.replace(/<[^>]*>?/gm, '');
pseudonim
źródło
4
Nie działa, <img src=http://www.google.com.kh/images/srpr/nav_logo27.png onload="alert(42)" jeśli wstrzykujesz przez document.writelub łączysz z łańcuchem zawierającym >przed wstrzyknięciem przez innerHTML.
Mike Samuel,
1
@PerishableDave, zgadzam się, że >zostaną w drugim. Nie jest to jednak ryzyko wstrzyknięcia. Zagrożenie występuje z powodu <pozostawienia w pierwszym, co powoduje, że parser HTML jest w kontekście innym niż stan danych, gdy rozpoczyna się drugi. Uwaga: nie ma przejścia ze stanu danych na >.
Mike Samuel,
73
@MikeSamuel Czy zdecydowaliśmy się już na tę odpowiedź? Tutaj naiwny użytkownik jest gotowy do skopiowania i wklejenia.
Ziggy
1
To również, jak sądzę, staje się całkowicie mylące, jeśli biorąc pod uwagę coś takiego, <button onClick="dostuff('>');"></button>zakładając, że poprawnie napisany HTML, nadal musisz wziąć pod uwagę, że gdzieś w cytowanym tekście atrybutu może znajdować się znak większy niż Ponadto chciałbyś <script>przynajmniej usunąć cały tekst z tagów.
Jonathon,
15
@AntonioMax, ja odpowiedzieli na to pytanie znudzenia , ale do meritum pytania, ponieważ bezpieczeństwo kod krytyczne nie powinny być kopiowane i wklejane. Należy pobrać bibliotekę, aktualizować ją i poprawiać, aby zabezpieczyć się przed niedawno odkrytymi lukami i zmianami w przeglądarkach.
Mike Samuel
249

Najprostszy sposób:

jQuery(html).text();

To pobiera cały tekst z ciągu HTML.

znak
źródło
111
Zawsze używamy jQuery do projektów, ponieważ niezmiennie nasze projekty mają dużo Javascript. Dlatego nie dodaliśmy masowo, skorzystaliśmy z istniejącego kodu API ...
Mark
32
Używasz go, ale OP może nie. pytanie dotyczyło Javascript NOT JQuery.
Dementyczny
105
To wciąż przydatna odpowiedź dla osób, które muszą zrobić to samo co OP (jak ja) i nie przeszkadza w użyciu jQuery (jak ja), nie wspominając, może być przydatne OP, jeśli rozważają użycie jQuery. Celem witryny jest dzielenie się wiedzą. Pamiętaj, że efekt chłodzący możesz mieć, karcąc użyteczne odpowiedzi bez uzasadnionego powodu.
acjay
27
@ Szokująco szokujące, uważam, że wątki z wieloma odpowiedziami są najbardziej przydatne, ponieważ często druga odpowiedź odpowiada moim dokładnym potrzebom, podczas gdy główna odpowiedź odpowiada ogólnemu przypadkowi.
Eric Goldberg,
36
To nie zadziała, jeśli jakaś część łańcucha nie jest zawinięta w tag HTML. np. „<b> Błąd: </b> proszę wpisać poprawny adres e-mail” zwróci tylko „Błąd:”
Aamir Afridi
127

Chciałbym udostępnić zredagowaną wersję zatwierdzonej odpowiedzi Shog9 .


Jak zauważył Mike Samuel w komentarzu, ta funkcja może wykonywać wbudowane kody javascript.
Ale Shog9 ma rację mówiąc „pozwól przeglądarce zrobić to za Ciebie ...”

więc .. tutaj moja edytowana wersja przy użyciu DOMParser :

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

tutaj kod do testowania wbudowanego javascript:

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

Ponadto nie żąda zasobów podczas analizowania (jak obrazy)

strip("Just text <img src='https://assets.rbl.ms/4155638/980x.jpg'>")
Sabaz
źródło
3
Warto dodać, że to rozwiązanie działa tylko w przeglądarce.
kris_IV,
1
To nie są tagi strip, ale bardziej jak PHP htmlspecialchars (). Nadal mi się przydaje.
Daantje
Zauważ, że usuwa to również białe znaki z początku tekstu.
Raine Revere,
Należy również zauważyć, że działa to w przypadku pracowników sieci
Chris Seufert
Wydaje się, że jest to znacznie szybsze niż odpowiedź @ Shog9
Shmuel Kamensky
55

Jako rozszerzenie metody jQuery, jeśli Twój ciąg może nie zawierać HTML (np. Jeśli próbujesz usunąć HTML z pola formularza)

jQuery(html).text();`

zwróci pusty ciąg, jeśli nie ma HTML

Posługiwać się:

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

zamiast.

Aktualizacja: Jak wskazano w komentarzach, w niektórych okolicznościach to rozwiązanie wykona javascript zawarty w nim, htmljeśli htmlatakujący może wpłynąć na wartość, użyj innego rozwiązania.

użytkownik999305
źródło
12
Lub$("<p>").html(html).text();
Dimitar Dimitrov
4
To wciąż wykonuje prawdopodobnie niebezpieczny kodjQuery('<span>Text :) <img src="a" onerror="alert(1)"></span>').text()
Simon
spróbuj jQuery ("aa & # X003c; script> alert (1) & # X003c; / script> a"). text ();
Grzegorz Kaczan
41

Konwertowanie HTML na e-maile w formacie zwykłego tekstu z zachowaniem nienaruszonych hiperłączy (href)

Powyższa funkcja opublikowana przez hipoksyd działa dobrze, ale szukałem czegoś, co w zasadzie przekształciłoby HTML utworzony w edytorze Web RichText (na przykład FCKEditor) i wyczyściło cały HTML, ale zostawiłem wszystkie linki, ponieważ chciałem zarówno HTML, jak i wersja zwykłego tekstu ułatwiająca tworzenie poprawnych części wiadomości e-mail STMP (zarówno HTML, jak i zwykły tekst).

Po długim czasie przeszukiwania Google sam i moi koledzy wymyślili to za pomocą silnika regex w 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, "");

strzmienna zaczyna się tak:

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>

a następnie po uruchomieniu kodu wygląda to tak:

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

Jak widać, cały HTML został usunięty, a łącze zostało wytrwałe, a hiperłączony tekst jest nadal nienaruszony. Mam również otrzymuje <p>i <br>tagi z\n (char nowego wiersza), tak, że jakiś rodzaj formatowania wizualnego został zatrzymany.

Aby zmienić format linku (np. BBC (Link->http://www.bbc.co.uk)), Po prostu edytuj $2 (Link->$1), gdzie $1jest adres URL / URI href, a $2tekst jest hiperlinkiem. Dzięki linkom bezpośrednio w treści zwykłego tekstu większość klientów poczty SMTP konwertuje je, aby użytkownik mógł je kliknąć.

Mam nadzieję, że to było przydatne.

Jibberboy2000
źródło
Nie obsługuje „& nbsp;”
Rose Nettoyeur
33

Poprawa przyjętej odpowiedzi.

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

W ten sposób coś takiego działa nie zaszkodzi:

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

Firefox, Chromium i Explorer 9+ są bezpieczne. Opera Presto jest nadal podatna na ataki. Również obrazy wymienione w ciągach nie są pobierane w Chromium i Firefox zapisując żądania HTTP.

Janghou
źródło
Jest to pewna droga, ale nie jest bezpieczne<script><script>alert();
Arth
1
To nie uruchamia żadnych skryptów tutaj w Chromium / Opera / Firefox na Linuksie, więc dlaczego to nie jest bezpieczne?
Janghou,
Przepraszam, musiałem przejść test, prawdopodobnie zapomniałem kliknąć ponownie uruchom jsFiddle.
Arth
Myślę, że argument „Nowy” jest zbyteczny?
Jon Schneider
Zgodnie ze specyfikacją jest to obecnie opcjonalne, ale nie zawsze tak było.
Janghou,
23

Powinno to działać w dowolnym środowisku Javascript (w tym NodeJS).

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
źródło
@pstanton, czy możesz podać działający przykład swojego oświadczenia?
Karl.S.
3
<html><style..>* {font-family:comic-sans;}</style>Some Text</html>
pstanton
@pstanton Naprawiłem kod i dodałem komentarze, przepraszam za spóźnioną odpowiedź.
Karl.S1
15

I zmienił odpowiedź Jibberboy2000 w celu uwzględnienia kilku <BR />formatów tagów, usuń wszystko wewnątrz <SCRIPT>i<STYLE> tagów formatowania wynikowy HTML poprzez usunięcie wielu podziały wiersza i spacje i przekonwertować pewną HTML zakodowany kod do normy. Po kilku testach okazuje się, że można przekonwertować większość pełnych stron internetowych na prosty tekst, w którym zachowany jest tytuł strony i treść.

W prostym przykładzie

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

staje się

To jest mój tytuł

Ten ciąg ma kod HTML, który chcę usunąć

W tej linii wspomniano BBC ( http://www.bbc.co.uk ) z linkiem.

Teraz wróć do „normalnego tekstu” i innych rzeczy

Funkcja JavaScript i strona testowa wyglądają tak:

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

Został użyty z tym 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
źródło
1
Podoba mi się to rozwiązanie, ponieważ obsługuje znaki specjalne HTML ... ale wciąż nie jest ich wystarczająco dużo ... najlepsza odpowiedź dla mnie poradziłaby sobie z nimi wszystkimi. (co prawdopodobnie robi jquery).
Daniel Gerson
2
Myślę, że /<p.*>/gipowinno być /<p.*?>/gi.
cbron
Należy zauważyć, że w celu usunięcia wszystkich <br>tagów można użyć wyrażenia regularnego dobrą zamiast: /<br\s*\/?>/w ten sposób można mieć tylko jedno zastąpić zamiast 3. Ponadto wydaje mi się, że oprócz dekodowania jednostek można mieć jednego regex, coś takiego: /<[a-z].*?\/?>/.
Alexis Wilke
Niezły scenariusz. Ale co z zawartością tabeli? Każdy pomysł, jak można go wyświetlić
Hristo Enev
@DanielGerson, kodowanie html staje się naprawdę włochate, naprawdę szybkie, ale najlepszym podejściem wydaje się być korzystanie z biblioteki he
KyleMit
15
var text = html.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, "");

To jest wersja wyrażenia regularnego, która jest bardziej odporna na zniekształcone HTML, takie jak:

Niezamknięte tagi

Some text <img

„<”, „>” wewnątrz atrybutów tagu

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

Newlines

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

Kod

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

Innym, co prawda mniej eleganckim rozwiązaniem niż nickf czy Shog9, byłoby rekursywne przejście DOM zaczynając od znacznika <body> i dołączenie każdego węzła tekstowego.

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
źródło
3
tak. jeśli masz zamiar stworzyć drzewo DOM ze swojego łańcucha, skorzystaj ze sposobu shoga!
nickf
Tak, moje rozwiązanie wykorzystuje młot, w którym bardziej odpowiedni jest zwykły młotek :-). I zgadzam się, że twoje i Shog9 są lepsze, i w zasadzie powiedziałem to samo w odpowiedzi. W mojej odpowiedzi nie udało mi się również odzwierciedlić, że HTML jest już zawarty w ciągu, co czyni moją odpowiedź zasadniczo bezużyteczną w odniesieniu do pierwotnego pytania. :-(
Bryan
1
Szczerze mówiąc, ma to wartość - jeśli absolutnie musisz zachować / cały / tekst, to ma to co najmniej przyzwoity strzał w przechwytywanie nowych linii, tabulatorów, zwrotów karetki itp. Z drugiej strony rozwiązanie Nickfa powinno zrobić to samo i robić znacznie szybciej ... eh.
Shog9
7

Jeśli chcesz zachować linki i strukturę treści (h1, h2 itp.), Powinieneś sprawdzić TextVersionJS Możesz go używać z dowolnym HTML- em , chociaż został stworzony do konwersji wiadomości e-mail HTML na zwykły tekst.

Użycie jest bardzo proste. Na przykład w node.js:

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

var textVersion = createTextVersion(yourHtml);

Lub w przeglądarce z czystym 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>

Działa również z wymaga.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
źródło
4

Po wypróbowaniu wszystkich wymienionych odpowiedzi większość, jeśli nie wszystkie, miały przypadkowe przypadki i nie były w stanie w pełni zaspokoić moich potrzeb.

Zacząłem badać, w jaki sposób robi to php, i natknąłem się na bibliotekę php.js, która replikuje metodę strip_tags tutaj: http://phpjs.org/functions/strip_tags/

Deminetix
źródło
To zgrabna i dobrze udokumentowana funkcja. Można go jednak przyspieszyć, gdy allowed == ''myślę, że o to poprosił PO, co prawie odpowiada Byron poniżej (Byron tylko [^>]pomylił się).
Alexis Wilke,
1
Jeśli użyjesz allowedparam, jesteś podatny na XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')return<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('');
}

Konta dla> wewnętrznych atrybutów i <img onerror="javascript">nowo tworzonych elementów dom.

stosowanie:

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

próbny:

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

demo najlepszych odpowiedzi na te okropne rzeczy:

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

40521
źródło
Będziesz także musiał obsługiwać cytowane znaki wewnątrz wartości atrybutu (np string with <a malicious="attribute \">this text should be removed, but is not">example</a>.).
Logan Pickup
4

Wiele osób już na to odpowiedziało, ale pomyślałem, że użyteczne może być udostępnienie napisanej przeze mnie funkcji, która usuwa tagi HTML z łańcucha, ale umożliwia dołączenie tablicy tagów, których nie chcesz usuwać. Jest dość krótki i działa dobrze dla mnie.

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
źródło
3

Myślę, że najłatwiej jest po prostu użyć wyrażeń regularnych, jak ktoś wspomniany powyżej. Chociaż nie ma powodu, aby używać ich wielu. Próbować:

stringWithHTML = stringWithHTML.replace(/<\/?[a-z][a-z0-9]*[^<>]*>/ig, "");
Byron Carasco
źródło
11
Nie rób tego, jeśli zależy Ci na bezpieczeństwie. Jeśli dane wejściowe użytkownika są następujące: „<scr <script> ipt> alert (42); </ scr </script> ipt>”, wówczas wersja pozbawiona jest: „<script> alert (42); </ script > ”. Jest to usterka XSS.
molnarg
Należy zmienić [^<>]z [^>]ponieważ prawidłowy tag nie może zawierać <znak, a następnie luka XSS znika.
Alexis Wilke
3

Wprowadziłem pewne modyfikacje do oryginalnego skryptu Jibberboy2000 Mam nadzieję, że przyda się komuś

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
źródło
3

Oto wersja, która w pewnym sensie rozwiązuje problem bezpieczeństwa @ 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 "";
   }
}

Uwaga: zwróci pusty ciąg, jeśli znacznik HTML nie jest prawidłowym kodem XML (inaczej: tagi muszą być zamknięte, a atrybuty muszą być cytowane). Nie jest to idealne, ale pozwala uniknąć problemu wykorzystania potencjału bezpieczeństwa.

Jeśli nie masz poprawnego znacznika XML, możesz spróbować użyć:

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

ale nie jest to idealne rozwiązanie z innych powodów.

Jeremy Johnstone
źródło
To się nie powiedzie w wielu okolicznościach, jeśli tekst pochodzi z danych wprowadzanych przez użytkownika (textarea lub contentedable widget ...)
Alexis Wilke
3

Możesz bezpiecznie usunąć tagi HTML za pomocą atrybutu piaskownicy iframe .

Chodzi o to, że zamiast regexować nasz ciąg znaków, korzystamy z natywnego parsera przeglądarki, wstrzykując tekst do elementu DOM, a następnie sprawdzając właściwość textContent/ innerTexttego elementu.

Najlepszym elementem do wstrzykiwania naszego tekstu jest ramka iframe w piaskownicy, w ten sposób możemy zapobiec wykonaniu dowolnego kodu (znanego również jako XSS ).

Minusem tego podejścia jest to, że działa tylko w przeglądarkach.

Oto, co wymyśliłem (nie przetestowane w walce):

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

Zastosowanie ( 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));
Etienne Martin
źródło
Świetne rozwiązanie dla środowisk internetowych! Prawdopodobnie nie powinieneś używać IIFE, ponieważ od ECMAScript 2015 zmienne o zasięgu blokowym są już odpowiednio skalowane do bloku za pomocą operatorów leti const. Ponadto, korzystając z twojego rozwiązania, otrzymałem wiele odnośników, które iframesnie zostały użyte w dokumencie. Zastanów się nad dodaniem document.body.removeChild(sandbox)kodu do przyszłych czytników opartych na makaronie.
Amin NAIRI,
2

Z jQuery możesz po prostu pobrać go za pomocą

$('#elementID').text()
ianaz
źródło
2

Poniższy kod pozwala zachować niektóre tagi HTML podczas usuwania wszystkich pozostałych

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
źródło
1
Powinieneś zacytować source ( phpjs). Jeśli użyjesz allowedparam, jesteś podatny na XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')return<p onclick="alert(1)">mytext</p>
Chris Cinelli
2

Możliwe jest również użycie fantastycznego parsera HTML JS HTML htmlparser2 . Oto działające demo:

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

Wyjście będzie This is a simple example.

Zobacz to w akcji tutaj: https://tonicdev.com/jfahrenkrug/extract-text-from-html

Działa to zarówno w węźle, jak i przeglądarce, jeśli spakujesz aplikację internetową za pomocą narzędzia takiego jak webpack.

Johannes Fahrenkrug
źródło
2

Musiałem tylko usunąć <a>tagi i zastąpić je tekstem linku.

To wydaje się działać świetnie.

htmlContent= htmlContent.replace(/<a.*href="(.*?)">/g, '');
htmlContent= htmlContent.replace(/<\/a>/g, '');
Friggin Chlorious
źródło
Dotyczy to tylko tagów i wymaga dopracowania, aby być szeroką funkcją.
m3nda
Tak, plus tag zakotwiczenia może mieć wiele innych atrybutów, takich jak title="...".
Alexis Wilke
1

Sam stworzyłem działające wyrażenie regularne:

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

prosta 2-liniowa jquery do usunięcia 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
Deweloper
źródło
1

Zaakceptowana odpowiedź działa dobrze, jednak w IE, jeśli htmlciąg jest nullw postaci "null"(zamiast „”). Naprawiony:

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

Za pomocą Jquery:

function stripTags() {
    return $('<p></p>').html(textToEscape).text()
}
math2001
źródło
1

inputelement obsługuje tylko jeden tekst liniowy :

Stan tekstu reprezentuje jednowierszowy element sterujący edycji tekstu zwykłego dla wartości elementu.

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

Aktualizacja: działa zgodnie z oczekiwaniami

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
źródło
Nie działa, zawsze wspominając o przeglądarce, której używasz, publikując odpowiedź. Jest to niedokładne i nie działa w Chrome 61. Tagi są po prostu renderowane jako ciąg.
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);

Zdefiniuj to jako wtyczkę jquery i użyj jej w następujący sposób:

$.html2text(htmlContent);
Shiv Shankar
źródło
Powiedzmy, że pochodzi to od danych wejściowych użytkownika. Można go użyć do dodania skryptu lub makr do swojej strony
Oluwatumbi