Strip HTML จากข้อความจาวาสคริปต์


คำตอบ:


761

หากคุณใช้เบราว์เซอร์วิธีที่ง่ายที่สุดคือให้เบราว์เซอร์ทำเพื่อคุณ ...

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

หมายเหตุ: เนื่องจากคนอื่น ๆ ได้ระบุไว้ในความคิดเห็นซึ่งจะเป็นการหลีกเลี่ยงที่ดีที่สุดหากคุณไม่ได้ควบคุมแหล่งที่มาของ HTML (ตัวอย่างเช่นอย่าใช้สิ่งนี้กับสิ่งที่อาจมาจากการป้อนข้อมูลของผู้ใช้) สำหรับสถานการณ์เหล่านั้นคุณยังคงสามารถให้เบราว์เซอร์ทำงานแทนคุณได้- ดูคำตอบของ Saba เกี่ยวกับการใช้ DOMParser ที่มีอยู่ในปัจจุบัน


40
โปรดจำไว้ว่าวิธีการนี้ค่อนข้างไม่สอดคล้องกันและจะไม่สามารถตัดอักขระบางตัวในเบราว์เซอร์บางตัวได้ ตัวอย่างเช่นใน Prototype.js เราใช้วิธีการนี้เพื่อประสิทธิภาพ แต่หลีก
เลี่ยง

11
โปรดจำไว้ว่าช่องว่างของคุณจะเลอะเทอะ ฉันเคยใช้วิธีการนี้แล้วมีปัญหาเนื่องจากรหัสผลิตภัณฑ์บางอย่างมีช่องว่างคู่ซึ่งลงเอยด้วยการเว้นวรรคเดียวหลังจากที่ฉันได้รับ InnerText กลับจาก DIV จากนั้นรหัสผลิตภัณฑ์ไม่ตรงกันในแอปพลิเคชันในภายหลัง
Magnus Smith

11
@Magnus Smith: ใช่ถ้าช่องว่างเป็นข้อกังวล - หรือจริงๆถ้าคุณมีความต้องการสำหรับข้อความนี้ที่ไม่เกี่ยวข้องโดยตรงกับ HTML DOM ที่คุณกำลังใช้งานอยู่ - คุณควรใช้อีกอันหนึ่ง โซลูชั่นที่ได้รับที่นี่ ข้อดีหลักของวิธีนี้คือว่ามันเป็น 1) จิ๊บจ๊อยและ 2) ความน่าเชื่อถือจะดำเนินการแท็ก, ช่องว่าง, หน่วยงาน, ความเห็น, ฯลฯ ในลักษณะเดียวกับเบราว์เซอร์ที่คุณกำลังทำงานอยู่ใน ซึ่งมีประโยชน์สำหรับรหัสเว็บไคลเอ็นต์ แต่ไม่จำเป็นต้องเหมาะสมสำหรับการโต้ตอบกับระบบอื่น ๆ ที่มีกฎแตกต่างกัน
Shog9

220
อย่าใช้สิ่งนี้กับ HTML จากแหล่งที่ไม่น่าเชื่อถือ หากต้องการดูว่าทำไมให้ลองเรียกใช้strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")
Mike Samuel

24
หาก html มีภาพ (แท็ก img) รูปภาพจะถูกร้องขอโดยเบราว์เซอร์ นั่นไม่ดีเลย
douyw

591
myString.replace(/<[^>]*>?/gm, '');

4
ไม่ทำงาน<img src=http://www.google.com.kh/images/srpr/nav_logo27.png onload="alert(42)" ถ้าคุณกำลังฉีดผ่านdocument.writeหรือเชื่อมโยงกับสตริงที่มีหนึ่งก่อนที่จะฉีดผ่านทาง> innerHTML
Mike Samuel

1
@PerishableDave ฉันยอมรับว่า>จะเหลือในครั้งที่สอง นั่นไม่ใช่อันตรายจากการฉีด อันตรายเกิดขึ้นเนื่องจาก<ทิ้งไว้ในครั้งแรกซึ่งทำให้ตัวแยกวิเคราะห์ HTML อยู่ในบริบทอื่นนอกเหนือจากสถานะข้อมูลเมื่อเริ่มต้นที่สอง โปรดทราบว่าไม่มีการเปลี่ยนจากสถานะข้อมูล>เป็น
Mike Samuel

73
@ MikeSamuel เราตัดสินใจเกี่ยวกับคำตอบนี้หรือยัง ผู้ใช้ที่ไร้เดียงสาที่นี่พร้อมที่จะคัดลอกวาง
Ziggy

1
ฉันก็เชื่อเช่นกันว่าสับสนถ้ามีบางอย่างเช่น<button onClick="dostuff('>');"></button>สมมติว่าเขียน HTML อย่างถูกต้องคุณยังต้องคำนึงว่าเครื่องหมายที่มากกว่านั้นอาจอยู่ในข้อความที่ยกมาในแอตทริบิวต์ นอกจากนี้คุณต้องการลบข้อความทั้งหมดภายใน<script>แท็กอย่างน้อยที่สุด
Jonathon

15
@AntonioMax ฉันได้ตอบคำถามคลื่นไส้โฆษณานี้ แต่เป็นเนื้อหาของคำถามของคุณเพราะรหัสความปลอดภัยที่สำคัญไม่ควรคัดลอก & วาง คุณควรดาวน์โหลดไลบรารี่และอัพเดทให้ทันสมัยและแก้ไขเพื่อให้คุณปลอดภัยจากช่องโหว่ที่เพิ่งค้นพบและการเปลี่ยนแปลงในเบราว์เซอร์
Mike Samuel

249

วิธีที่ง่ายที่สุด:

jQuery(html).text();

ที่ดึงข้อความทั้งหมดจากสตริงของ html


111
เรามักจะใช้ jQuery สำหรับโครงการเนื่องจากโครงการของเรามีจาวาสคริปต์มากมาย ดังนั้นเราจึงไม่ได้เพิ่มจำนวนมากเราใช้ประโยชน์จากรหัส API ที่มีอยู่ ...
ทำเครื่องหมาย

32
คุณใช้มัน แต่ OP อาจจะไม่ได้ คำถามเกี่ยวกับ Javascript ไม่ใช่ JQuery
Dementic

105
มันยังคงเป็นคำตอบที่มีประโยชน์สำหรับผู้ที่ต้องทำสิ่งเดียวกันกับ OP (เช่นฉัน) และไม่รังเกียจการใช้ jQuery (เช่นฉัน) ไม่ต้องพูดถึงมันอาจมีประโยชน์กับ OP หากพวกเขากำลังพิจารณาใช้ jQuery จุดประสงค์ของเว็บไซต์คือการแบ่งปันความรู้ โปรดจำไว้ว่าผลกระทบที่ทำให้หนาวสั่นที่คุณอาจมีโดยการตีสอนคำตอบที่เป็นประโยชน์โดยไม่มีเหตุผลที่ดี
acjay

27
@Dementic อย่างน่าตกใจฉันพบว่ากระทู้ที่มีหลายคำตอบมีประโยชน์มากที่สุดเพราะบ่อยครั้งที่คำตอบรองตรงตามความต้องการที่แท้จริงของฉันในขณะที่คำตอบหลักตรงกับกรณีทั่วไป
Eric Goldberg

36
ที่จะไม่ทำงานถ้าคุณบางส่วนของสตริงไม่ได้ห่อในแท็ก html เช่น "<b> ข้อผิดพลาด: </b> โปรดป้อนอีเมลที่ถูกต้อง" จะกลับมาเฉพาะ "ข้อผิดพลาด:"
Aamir Afridi

127

ผมอยากจะแบ่งปันฉบับแก้ไขของShog9 's คำตอบที่ได้รับการอนุมัติ


ดังที่Mike Samuelชี้ด้วยความคิดเห็นฟังก์ชันนั้นสามารถเรียกใช้โค้ดจาวาสคริปต์แบบอินไลน์
แต่Shog9พูดถูก "ให้เบราว์เซอร์ทำเพื่อคุณ ... "

ดังนั้น .. ที่นี่รุ่นที่แก้ไขของฉันโดยใช้DOMParser :

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

ที่นี่รหัสเพื่อทดสอบจาวาสคริปต์แบบอินไลน์:

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

นอกจากนี้มันไม่ได้ขอทรัพยากรในการแยกวิเคราะห์ (เช่นภาพ)

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

3
มีมูลค่าเพิ่มที่โซลูชั่นนี้ทำงานเฉพาะในเบราว์เซอร์
kris_IV

1
นี่ไม่ใช่สตริแท็ก แต่อย่าง PHP htmlspecialchars () ยังมีประโยชน์สำหรับฉัน
Daantje

โปรดทราบว่าสิ่งนี้จะลบช่องว่างออกจากจุดเริ่มต้นของข้อความด้วย
Raine Revere

นอกจากนี้ยังต้องทราบว่าสิ่งนี้สามารถทำงานได้ใน Web Workers
Chris Seufert

นี้น่าจะเป็นมากเร็วกว่า @ คำตอบของ Shog9
ชามู Kamensky

55

เป็นส่วนขยายของวิธี jQuery หากสตริงของคุณอาจไม่มี HTML (เช่นหากคุณพยายามลบ HTML ออกจากเขตข้อมูลฟอร์ม)

jQuery(html).text();`

จะส่งคืนสตริงว่างถ้าไม่มี HTML

ใช้:

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

แทน.

อัปเดต: ดัง ที่ได้กล่าวไว้ในความคิดเห็นในบางกรณีโซลูชันนี้จะเรียกใช้จาวาสคริปต์ที่บรรจุอยู่ภายในhtmlหากค่าที่htmlอาจได้รับอิทธิพลจากผู้โจมตีให้ใช้โซลูชันอื่น


12
หรือ$("<p>").html(html).text();
ดิมิทาร์ดิมิทรอฟ

4
สิ่งนี้ยังคงเรียกใช้รหัสที่เป็นอันตรายได้jQuery('<span>Text :) <img src="a" onerror="alert(1)"></span>').text()
Simon

ลอง jQuery ("aa & # X003c; script> alert (1) & # X003c; / script> a"). text ();
Grzegorz Kaczan

41

การแปลง HTML สำหรับข้อความธรรมดาส่งอีเมลถึงการเชื่อมโยงหลายมิติ (href) เหมือนเดิม

ฟังก์ชั่นด้านบนที่โพสต์โดย hypoxide ใช้งานได้ดี แต่ฉันหลังจากสิ่งที่โดยทั่วไปแล้วจะแปลง HTML ที่สร้างขึ้นในโปรแกรมแก้ไขเว็บ RichText (เช่น FCKEditor) และล้าง HTML ทั้งหมด แต่ปล่อยให้ลิงก์ทั้งหมดเนื่องจากฉันต้องการทั้ง HTML และ เวอร์ชันข้อความล้วนเพื่อช่วยในการสร้างชิ้นส่วนที่ถูกต้องไปยังอีเมล STMP (ทั้ง HTML และข้อความธรรมดา)

หลังจากค้นหา Google ด้วยตัวเองเป็นเวลานานและเพื่อนร่วมงานของฉันได้พบสิ่งนี้โดยใช้เครื่องมือ regex ใน 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, "");

strตัวแปรเริ่มออกมาเช่นนี้

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

จากนั้นหลังจากรันโค้ดแล้วจะมีลักษณะดังนี้: -

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


Now back to normal text and stuff

ในขณะที่คุณสามารถดู HTML ทั้งหมดได้ถูกลบออกและการเชื่อมโยงได้รับการสานต่อด้วยข้อความเชื่อมโยงหลายมิติยังคงเหมือนเดิม นอกจากนี้ฉันได้แทนที่<p>และ<br>แท็กด้วย\n(newline char) เพื่อให้การจัดรูปแบบภาพบางอย่างถูกรักษาไว้

หากต้องการเปลี่ยนรูปแบบลิงก์ (เช่น. BBC (Link->http://www.bbc.co.uk)) เพียงแค่แก้ไข$2 (Link->$1)โดยที่$1คือ URL ของ href / URI และ$2เป็นข้อความเชื่อมโยงหลายมิติ ด้วยลิงก์โดยตรงในเนื้อความของข้อความไคลเอ็นต์ SMTP ส่วนใหญ่จะแปลงสิ่งเหล่านี้เพื่อให้ผู้ใช้มีความสามารถในการคลิกที่พวกเขา

หวังว่าคุณจะพบว่ามีประโยชน์นี้


ไม่สามารถจัดการ "& nbsp;"
Rose Nettoyeur

33

การปรับปรุงคำตอบที่ยอมรับ

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

วิธีที่สิ่งนี้ทำงานแบบนี้จะไม่เป็นอันตราย:

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

Firefox, Chromium และ Explorer 9+ นั้นปลอดภัย Opera Presto ยังคงมีช่องโหว่ รูปภาพที่กล่าวถึงในสตริงจะไม่ถูกดาวน์โหลดใน Chromium และ Firefox ที่บันทึกคำขอ HTTP


นี่เป็นวิธีที่นั่น แต่ไม่ปลอดภัยจาก<script><script>alert();
Arth

1
ไม่ได้เรียกใช้สคริปต์ใด ๆ ที่นี่ใน Chromium / Opera / Firefox บน Linux ดังนั้นทำไมจึงไม่ปลอดภัย
Janghou

คำขอโทษของฉันฉันต้องพลาดการทดสอบฉันอาจลืมคลิกเรียกใช้อีกครั้งบน jsFiddle
Arth

อาร์กิวเมนต์ "ใหม่" ไม่จำเป็นต้องคิดเลยเหรอ?
Jon Schneider

ตามรายละเอียดเป็นตัวเลือกในปัจจุบัน แต่มันก็ไม่ได้เสมอ
Janghou

23

สิ่งนี้ควรทำงานบนสภาพแวดล้อม Javascript ใด ๆ (รวม 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, '');

@pstanton คุณสามารถให้ตัวอย่างการทำงานของงบของคุณได้หรือไม่
Karl.S

3
<html><style..>* {font-family:comic-sans;}</style>Some Text</html>
pstanton

@pstanton ฉันได้แก้ไขรหัสและเพิ่มความคิดเห็นขออภัยสำหรับการตอบสนองช้า
Karl.S

16

ฉันเปลี่ยนคำตอบของ Jibberboy2000เพื่อรวมหลาย<BR />รูปแบบของแท็กลบทุกอย่างภายใน<SCRIPT>และ<STYLE>แท็กจัดรูปแบบ HTML ที่เป็นผลลัพธ์โดยลบตัวแบ่งบรรทัดและช่องว่างหลายบรรทัดและแปลงรหัส HTML ที่เข้ารหัสบางส่วนให้เป็นปกติ หลังจากการทดสอบบางอย่างปรากฏว่าคุณสามารถแปลงหน้าเว็บเต็มรูปแบบส่วนใหญ่ให้เป็นข้อความแบบเรียบง่ายโดยที่ชื่อหน้าและเนื้อหาจะถูกเก็บไว้

ในตัวอย่างง่ายๆ

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

<head>

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

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

</style>
</head>

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

กลายเป็น

นี่คือชื่อของฉัน

สตริงนี้มีรหัส html ที่ฉันต้องการลบ

ในบรรทัดนี้ BBC ( http://www.bbc.co.uk ) ที่มีลิงก์ระบุไว้

ตอนนี้กลับไปที่ "ข้อความปกติ" และสิ่งที่ใช้

ฟังก์ชัน JavaScript และหน้าทดสอบมีลักษณะดังนี้:

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

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

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

มันถูกใช้กับ 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 />

1
ฉันชอบวิธีนี้เพราะมันมีตัวอักษรพิเศษ html แต่ก็ยังไม่เพียงพอสำหรับพวกเขา ... คำตอบที่ดีที่สุดสำหรับฉันที่จะจัดการกับพวกเขาทั้งหมด (ซึ่งอาจเป็นสิ่งที่ jquery ทำ)
Daniel Gerson

2
ผมคิดว่าควรจะเป็น/<p.*>/gi /<p.*?>/gi
cbron

โปรดทราบว่าการลบทั้งหมด<br>แท็กคุณสามารถใช้การแสดงออกปกติดีแทน: /<br\s*\/?>/วิธีการที่คุณจะมีเพียงหนึ่งแทนที่แทน 3. นอกจากนี้ก็ดูเหมือนว่าฉันที่ยกเว้นสำหรับการถอดรหัสของหน่วยงานที่คุณสามารถมี regex /<[a-z].*?\/?>/เดียวอะไรเช่นนี้
Alexis Wilke

สคริปต์ที่ดี แต่เนื้อหาตารางเป็นอย่างไร ความคิดใด ๆ ที่สามารถแสดงได้
Hristo Enev

@DanielGerson การเข้ารหัส html มีขนดกจริงรวดเร็วจริง ๆ แต่วิธีที่ดีที่สุดดูเหมือนจะใช้
ไลบรารี่ของ

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

นี่เป็นรุ่น regex ซึ่งยืดหยุ่นได้มากกว่า HTML ที่มีรูปแบบไม่ถูกต้องเช่น:

แท็กที่ไม่เปิดเผย

Some text <img

"<", ">" ภายในแอตทริบิวต์แท็ก

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

การขึ้นบรรทัดใหม่

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

รหัส

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

7

อีกวิธีหนึ่งที่ได้รับการยอมรับน้อยกว่าโซลูชันของ Nickf หรือ Shog9 นั้นคือการเดิน DOM ซ้ำ ๆ โดยเริ่มที่แท็ก <body> และต่อท้ายแต่ละโหนดข้อความ

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

3
Yikes หากคุณกำลังจะสร้างต้นไม้ DOM จากสายของคุณให้ใช้วิธีของ shog!
nickf

ใช่โซลูชันของฉันใช้ค้อนเลื่อนที่ซึ่งค้อนปกติเหมาะสมกว่า :-) และฉันก็เห็นด้วยว่าคำตอบของคุณและของ Shog9 นั้นดีกว่าและพูดโดยทั่วไปในคำตอบ ฉันยังล้มเหลวในการสะท้อนในการตอบสนองของฉันว่า html นั้นมีอยู่ในสายอักขระแล้ว :-(
Bryan

1
เพื่อความเป็นธรรมสิ่งนี้มีค่า - หากคุณต้องเก็บรักษา / ทั้งหมด / ของข้อความไว้อย่างน้อยก็จะมีช็อตที่เหมาะสมในการจับ newlines, tabs, carriage return ฯลฯ ... จากนั้นอีกครั้งโซลูชันของ nickf ควรทำเช่นเดียวกัน และทำได้เร็วกว่า ... เอ๊ะ
Shog9

7

หากคุณต้องการเก็บลิงค์และโครงสร้างของเนื้อหา (h1, h2 ฯลฯ ) คุณควรตรวจสอบTextVersionJSคุณสามารถใช้กับ HTML ใดก็ได้แม้ว่ามันจะถูกสร้างขึ้นเพื่อแปลงอีเมล HTML เป็นข้อความธรรมดา

การใช้งานง่ายมาก ตัวอย่างเช่นใน node.js:

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

var textVersion = createTextVersion(yourHtml);

หรือในเบราว์เซอร์ด้วย 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>

นอกจากนี้ยังทำงานร่วมกับ require.js:

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

4

หลังจากลองคำตอบทั้งหมดที่กล่าวถึงมากที่สุดหากไม่ใช่ทั้งหมดมีกรณีที่เป็นขอบและไม่สามารถรองรับความต้องการของฉันได้อย่างสมบูรณ์

ฉันเริ่มสำรวจว่า php ทำอย่างไรและพบกับ php.js lib ซึ่งจำลองวิธี strip_tags ที่นี่: http://phpjs.org/functions/strip_tags/


นี่เป็นฟังก์ชั่นที่เรียบร้อยและบันทึกไว้อย่างดี อย่างไรก็ตามมันสามารถทำได้เร็วขึ้นเมื่อallowed == ''ฉันคิดว่าเป็นสิ่งที่ OP ขอมาซึ่งเกือบจะเป็นสิ่งที่ Byron ตอบด้านล่าง (Byron เท่านั้น[^>]ผิด)
Alexis Wilke

1
หากคุณใช้allowedพารามิเตอร์คุณมีความเสี่ยงต่อ 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('');
}

บัญชีสำหรับ> คุณลักษณะภายในและ<img onerror="javascript">ในองค์ประกอบ dom ที่สร้างขึ้นใหม่

การใช้งาน:

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

การสาธิต:

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

ตัวอย่างคำตอบยอดนิยมที่ทำสิ่งที่น่ากลัว:

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


คุณจะต้องจัดการกับคำพูดที่หลบหนีภายในค่าแอตทริบิวต์ด้วย (เช่นstring with <a malicious="attribute \">this text should be removed, but is not">example</a>)
รถกระบะโลแกน

4

ผู้คนจำนวนมากตอบคำถามนี้ไปแล้ว แต่ฉันคิดว่ามันอาจจะมีประโยชน์ในการแบ่งปันฟังก์ชั่นที่ฉันเขียนที่ดึงแท็ก HTML ออกจากสตริง แต่อนุญาตให้คุณใส่อาเรย์ของแท็กที่คุณไม่ต้องการถอด มันค่อนข้างสั้นและใช้งานได้ดีสำหรับฉัน

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

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

3

ฉันคิดว่าวิธีที่ง่ายที่สุดคือเพียงใช้นิพจน์ปกติตามที่มีคนกล่าวถึงข้างต้น แม้ว่าจะไม่มีเหตุผลที่จะใช้พวกมัน ลอง:

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

11
อย่าทำสิ่งนี้ถ้าคุณใส่ใจเรื่องความปลอดภัย หากอินพุตของผู้ใช้คือ: '<scr <script> ipt> alert (42); </ scr </script> ipt>' ดังนั้นเวอร์ชันที่ปล้นจะเป็นดังนี้: '<script> การแจ้งเตือน (42); </ สคริปต์ >' ดังนั้นนี่คือช่องโหว่ XSS
molnarg

คุณควรเปลี่ยน[^<>]ด้วย[^>]เพราะแท็กที่ถูกต้องไม่สามารถมี<อักขระได้ช่องโหว่ XSS จะหายไป
Alexis Wilke

3

ฉันได้ทำการดัดแปลงสคริปต์ Jibberboy2000 ดั้งเดิมหวังว่ามันจะเป็นประโยชน์สำหรับใครบางคน

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

นี่เป็นเวอร์ชั่นที่ sorta เน้นเรื่องความปลอดภัยของ MikeSamuel:

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

หมายเหตุมันจะส่งคืนสตริงว่างถ้ามาร์กอัพ HTML ไม่ใช่ XML ที่ถูกต้อง (aka ต้องปิดแท็กและต้องอ้างแอตทริบิวต์) สิ่งนี้ไม่เหมาะ แต่จะหลีกเลี่ยงปัญหาของความปลอดภัยที่อาจเกิดขึ้น

หากไม่มีมาร์กอัพ XML ที่ถูกต้องเป็นข้อกำหนดสำหรับคุณคุณสามารถลองใช้:

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

แต่นั่นไม่ใช่โซลูชันที่สมบูรณ์แบบไม่ว่าด้วยเหตุผลอื่น


ที่จะล้มเหลวในหลายกรณีถ้าข้อความที่มาจากการป้อนข้อมูลของผู้ใช้ (textarea หรือวิดเจ็ต contenteditable ... )
อเล็กซิส Wilke

3

คุณสามารถดึงแท็ก HTML ใช้แอตทริบิวต์ iframe Sandbox

แนวคิดที่นี่คือแทนที่จะพยายาม regex สตริงของเราเราใช้ประโยชน์จาก parser พื้นเมืองของเบราว์เซอร์โดยการฉีดข้อความลงในองค์ประกอบ DOM แล้วสอบถามคุณสมบัติtextContent/ innerTextขององค์ประกอบนั้น

องค์ประกอบที่เหมาะสมที่สุดในการแทรกข้อความของเราคือ iframe แบบ sandboxed วิธีการที่เราสามารถป้องกันการเรียกใช้รหัสโดยอำเภอใจ (หรือที่เรียกว่าXSS )

ข้อเสียของวิธีนี้คือมันใช้ได้เฉพาะกับเบราว์เซอร์เท่านั้น

นี่คือสิ่งที่ฉันได้รับ (ไม่ผ่านการทดสอบการต่อสู้):

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

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

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

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

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

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

การใช้งาน ( สาธิต ):

console.log(stripHtmlTags(`<img onerror='alert("could run arbitrary JS here")' src='bogus'>XSS injection :)`));
console.log(stripHtmlTags(`<script>alert("awdawd");</` + `script>Script tag injection :)`));
console.log(stripHtmlTags(`<strong>I am bold text</strong>`));
console.log(stripHtmlTags(`<html>I'm a HTML tag</html>`));
console.log(stripHtmlTags(`<body>I'm a body tag</body>`));
console.log(stripHtmlTags(`<head>I'm a head tag</head>`));
console.log(stripHtmlTags(null));

ทางออกที่ดีสำหรับสภาพแวดล้อมบนเว็บ! คุณไม่ควรใช้ IIFE ตั้งแต่ ECMAScript 2015 ตัวแปรบล็อกที่มีการกำหนดขอบเขตจะถูกกำหนดขอบเขตไปยังบล็อกอย่างเหมาะสมกับตัวดำเนินการletและ constนอกจากนี้การใช้โซลูชันของคุณฉันได้รับการอ้างอิงจำนวนมากที่iframesไม่ได้ใช้ภายในเอกสาร พิจารณาเพิ่มdocument.body.removeChild(sandbox)ในรหัสสำหรับผู้อ่านที่คัดลอกพาสต้าในอนาคต
Amin NAIRI


2

โค้ดด้านล่างช่วยให้คุณสามารถเก็บแท็ก html บางส่วนในขณะที่ลอกแท็กอื่น ๆ ทั้งหมด

function strip_tags(input, allowed) {

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

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

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

1
คุณควรอ้างอิงแหล่งที่มา ( phpjs) หากคุณใช้allowedพารามิเตอร์คุณมีความเสี่ยงต่อ XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')return<p onclick="alert(1)">mytext</p>
Chris Cinelli

2

นอกจากนี้ยังเป็นไปได้ที่จะใช้ตัวแยกวิเคราะห์htmlparser2 pure JS HTML นี่คือตัวอย่างการทำงาน:

var htmlparser = require('htmlparser2');

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

var result = [];

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

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

result.join('');

ผลลัพธ์จะเป็น This is a simple example.

ดูการทำงานได้ที่นี่: https://tonicdev.com/jfahrenkrug/extract-text-from-html

สิ่งนี้ใช้ได้ทั้งในโหนดและเบราว์เซอร์ถ้าคุณแพ็คแอปพลิเคชันเว็บโดยใช้เครื่องมือเช่น webpack


2

ฉันแค่ต้องตัด<a>แท็กออกและแทนที่ด้วยข้อความของลิงก์

ดูเหมือนว่าจะใช้งานได้ดี

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

ใช้เฉพาะกับแท็กและจำเป็นต้องปรับแต่งเพื่อให้ได้ฟังก์ชันที่กว้าง
m3nda

ใช่บวกแท็กสมออาจมีคุณลักษณะอื่น ๆ title="..."หลายอย่างเช่น
Alexis Wilke


1

ฉันสร้างนิพจน์ปกติที่ใช้งานได้ด้วยตัวเอง:

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

1

2 jquery บรรทัดง่าย ๆ เพื่อตัด html

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

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

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

1

คำตอบที่ได้รับการยอมรับนั้นใช้งานได้ดีส่วนใหญ่อย่างไรก็ตามใน IE หากคุณได้รับhtmlสตริง(แทนที่จะเป็น '') แก้ไขแล้ว:null"null"

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


1

inputองค์ประกอบรองรับข้อความบรรทัดเดียวเท่านั้น :

สถานะข้อความแสดงถึงการควบคุมการแก้ไขข้อความธรรมดาหนึ่งบรรทัดสำหรับค่าขององค์ประกอบ

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

อัปเดต: ใช้งานได้ตามที่คาดไว้

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

  // Remove BB code
  str = str.replace(/\[(\w+)[^\]]*](.*?)\[\/\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;
}

ใช้งานไม่ได้โปรดพูดถึงเบราว์เซอร์ที่คุณใช้เมื่อโพสต์คำตอบ สิ่งนี้ไม่ถูกต้องและจะไม่ทำงานใน Chrome 61 แท็กจะแสดงผลเป็นสตริง
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);

กำหนดสิ่งนี้เป็นปลั๊กอิน jquery และใช้มันเหมือนดังต่อไปนี้:

$.html2text(htmlContent);

ให้บอกว่าสิ่งนี้มาจากการป้อนข้อมูลของผู้ใช้ สามารถใช้เพื่อเพิ่มสคริปต์หรือมาโครลงในหน้าของคุณ
Oluwatumbi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.