Відповіді:
Якщо ви працюєте в браузері, то найпростіший спосіб - просто дозволити веб-переглядачу зробити це за вас ...
function stripHtml(html)
{
var tmp = document.createElement("DIV");
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText || "";
}
Примітка: як люди зазначали у коментарях, цього найкраще уникати, якщо ви не керуєте джерелом HTML (наприклад, не запускайте це на тому, що могло б з’явитись із введення користувача). Для цих сценаріїв, ви можете все ще дозволити браузеру зробити роботу для вас - см відповіді Сабов на використання в даний час широко доступний DomParser .
strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")
myString.replace(/<[^>]*>?/gm, '');
<img src=http://www.google.com.kh/images/srpr/nav_logo27.png onload="alert(42)"
якщо ви вводите ін'єкцію через document.write
або об'єднуються з рядком, який містить >
перед введенням через innerHTML
.
>
воля залишиться в другій. Однак це не є небезпечним для ін'єкцій. Небезпека виникає внаслідок <
зліва в першій, що призводить до того, що HTML-аналізатор знаходиться в контексті, відмінному від стану даних, коли починається другий. Зауважте, що немає переходу від стану даних >
.
<button onClick="dostuff('>');"></button>
Припустимо, правильно написаний HTML, ви все ще повинні враховувати, що більший, ніж знак, може бути десь у цитованому тексті атрибута. Також ви хочете <script>
принаймні видалити весь текст всередині тегів.
Найпростіший спосіб:
jQuery(html).text();
Це витягує весь текст із рядка HTML.
Я хотів би поділитися відредагованою версією схваленої відповіді Shog9 .
Як зауважив Майк Самуель із коментарем, ця функція може виконувати вбудовані коди JavaScript.
Але Shog9 має рацію, кажучи "нехай браузер зробить це за вас ..."
так .. ось моя відредагована версія за допомогою DOMParser :
function strip(html){
var doc = new DOMParser().parseFromString(html, 'text/html');
return doc.body.textContent || "";
}
тут код для перевірки вбудованого JavaScript:
strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")
Крім того, він не вимагає ресурсів для розбору (як зображення)
strip("Just text <img src='https://assets.rbl.ms/4155638/980x.jpg'>")
Як розширення до методу jQuery, якщо ваша рядок може не містити HTML (наприклад, якщо ви намагаєтесь видалити HTML з поля форми)
jQuery(html).text();`
поверне порожній рядок, якщо немає HTML
Використання:
jQuery('<p>' + html + '</p>').text();
замість цього.
Оновлення:
Як було зазначено в коментарях, за деяких обставин це рішення виконуватиме JavaScript, який міститься в межах, html
якщо на значення html
могло вплинути зловмисник, використовуйте інше рішення.
$("<p>").html(html).text();
jQuery('<span>Text :) <img src="a" onerror="alert(1)"></span>').text()
Вищенаведена функція, розміщена гіпоксидом, працює чудово, але я працював над тим, що в основному перетворив би 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
(char new line), щоб збереглося якесь візуальне форматування.
Щоб змінити формат посилання (напр. BBC (Link->http://www.bbc.co.uk)
), Просто відредагуйте $2 (Link->$1)
, де $1
є URL-адреса href / URI і the $2
- гіперпосилання. З посиланнями безпосередньо в тексті простого тексту більшість клієнтів пошти SMTP перетворюють їх, щоб користувач мав можливість натискати на них.
Сподіваюся, ви вважаєте це корисним.
Поліпшення прийнятої відповіді.
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();
Це повинно працювати в будь-якому середовищі 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, '');
<html><style..>* {font-family:comic-sans;}</style>Some Text</html>
Я змінив відповідь 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 "normal text" and stuff using <html encoding>
</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(/ /gi," ");
returnText=returnText.replace(/&/gi,"&");
returnText=returnText.replace(/"/gi,'"');
returnText=returnText.replace(/</gi,'<');
returnText=returnText.replace(/>/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 />
/<p.*>/gi
має бути /<p.*?>/gi
.
<br>
тегів ви можете використовувати гарне регулярний вираз замість цього: /<br\s*\/?>/
таким чином у вас є тільки один замінити замість 3. Крім того, мені здається , що для декодування осіб , за винятком ви можете мати один регулярний вираз, що - щось на зразок цього: /<[a-z].*?\/?>/
.
var text = html.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, "");
Це версія регулярної виразки, яка є більш стійкою до неправильного 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, "");
Іншим, правда, менш елегантним рішенням, ніж Nickf's або 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;
}
Якщо ви хочете зберегти посилання та структуру вмісту (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);
Або в браузері з чистим 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>
Він також працює з Requ.js:
define(["textversionjs"], function(createTextVersion) {
var yourHtml = "<h1>Your HTML</h1><ul><li>goes</li><li>here.</li></ul>";
var textVersion = createTextVersion(yourHtml);
});
Спробувавши всі відповіді, згадані більшість, якщо не всі вони мали кращі справи і не змогли повністю підтримати мої потреби.
Я почав досліджувати, як це робить php, і натрапив на php.js lib, який повторює метод strip_tags тут: http://phpjs.org/functions/strip_tags/
allowed == ''
я думаю, це те, про що просив ОП, а це майже те, що Байрон відповів нижче (Байрон тільки [^>]
помилився.)
allowed
парам, ви вразливі до XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')
повертається<p onclick="alert(1)">mytext</p>
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/
демонстрація топ-відповіді, що робить жахливі речі:
string with <a malicious="attribute \">this text should be removed, but is not">example</a>
).
Багато людей вже відповіли на це, але я вважав, що може бути корисним поділитися функцією, яку я написав, що знімає 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>
Я думаю, що найпростіший спосіб - просто використовувати регулярні вирази, як хтось згаданий вище. Хоча немає жодної причини використовувати купу з них. Спробуйте:
stringWithHTML = stringWithHTML.replace(/<\/?[a-z][a-z0-9]*[^<>]*>/ig, "");
[^<>]
з , [^>]
оскільки дійсний тег не може містити <
символ, то вразливість XSS зникає.
Я вніс деякі зміни в оригінальний сценарій 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");
Ось версія, яка сортує адресу @ 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 (він же має бути закритий, а атрибути повинні бути цитовані). Це не ідеально, але це дозволяє уникати можливості використання потенціалу безпеки.
Якщо для вас не є дійсна розмітка XML, ви можете спробувати скористатися:
var doc = document.implementation.createHTMLDocument("");
але це не ідеальне рішення ні з інших причин.
Ви можете сміливо знімати HTML-теги за допомогою атрибуту iframe sandbox .
Ідея тут полягає в тому, що замість того, щоб намагатися повторно виразити наш рядок, ми скористаємось нативним аналізатором браузера, вводячи текст у елемент DOM, а потім запитуючи textContent
/ innerText
властивість цього елемента.
Найкращим елементом, в який потрібно вставити наш текст, є пісочний кадр, тому ми можемо запобігти будь-якому довільному виконанню коду (Також відомому як 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));
let
та const
. Також, використовуючи ваше рішення, я отримав багато посилань на iframes
не використовувані всередині документа. Подумайте про додавання document.body.removeChild(sandbox)
коду для майбутніх читачів на основі копій-макаронних виробів.
Нижче код дозволяє зберігати деякі теги 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 : '';
});
}
phpjs
). Якщо ви використовуєте allowed
парам, ви вразливі до XSS: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')
повертається<p onclick="alert(1)">mytext</p>
Можна також використовувати фантастичний htserparser2 чистий 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.
Мені просто потрібно було викреслити <a>
теги і замінити їх текстом посилання.
Це, здається, працює чудово.
htmlContent= htmlContent.replace(/<a.*href="(.*?)">/g, '');
htmlContent= htmlContent.replace(/<\/a>/g, '');
title="..."
.
Для більш легкого рішення спробуйте це => https://css-tricks.com/snippets/javascript/strip-html-tags-in-javascript/
var StrippedString = OriginalString.replace(/(<([^>]+)>)/ig,"");
простий дворядковий jquery, щоб зняти 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
Прийнята відповідь здебільшого добре працює, проте в IE, якщо html
рядок null
ви отримаєте "null"
(замість ''). Виправлено:
function strip(html)
{
if (html == null) return "";
var tmp = document.createElement("DIV");
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText || "";
}
Використання Jquery:
function stripTags() {
return $('<p></p>').html(textToEscape).text()
}
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;
}
(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);