回答:
ブラウザで実行している場合、最も簡単な方法は、ブラウザに実行させるだけです...
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
。
<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();
代わりに。
更新:
コメントで指摘されているように、状況によっては、このソリューションは、攻撃者の影響を受ける可能性があるhtml
場合に含まれるJavaScriptを実行しhtml
ます。別のソリューションを使用してください。
$("<p>").html(html).text();
jQuery('<span>Text :) <img src="a" onerror="alert(1)"></span>').text()
hypoxideによって投稿された上記の関数は正常に機能しますが、基本的にはWebリッチテキストエディター(FCKEditorなど)で作成されたHTMLを変換し、すべてのHTMLをクリアしますが、HTMLとプレーンテキストバージョンは、STMP電子メール(HTMLとプレーンテキストの両方)の正しい部分の作成に役立ちます。
長い間Googleを検索していた後、私と同僚は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
(改行文字)に置き換えて、ある種の視覚的なフォーマットが保持されるようにしました。
リンクの形式(例:)を変更BBC (Link->http://www.bbc.co.uk)
するには$2 (Link->$1)
、を編集します。$1
は、href URL / URIであり、$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エンコードされたコードを通常に変換しました。いくつかのテストの後、ほとんどの完全なWebページを、ページタイトルとコンテンツが保持される単純なテキストに変換できるようです。
簡単な例では、
<!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の代わりに1つだけ置換できます。また、エンティティのデコードを除いて、次のような単一の正規表現を使用できるようです/<[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やShog9のソリューションよりも明らかにエレガントでないソリューションとして、もう1つは、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>
require.jsでも動作します:
define(["textversionjs"], function(createTextVersion) {
var yourHtml = "<h1>Your HTML</h1><ul><li>goes</li><li>here.</li></ul>";
var textVersion = createTextVersion(yourHtml);
});
すべてではないにしても、最も言及されたすべての回答を試した後、それらのすべてがエッジケースであり、私のニーズを完全にサポートすることができませんでした。
私はphpがどのようにそれを実行するのかを調査し始め、ここでstrip_tagsメソッドを複製するphp.js libに出会いました:http ://phpjs.org/functions/strip_tags/
allowed == ''
OPが要求したものであると考えるときは、より速くすることができます。これは、バイロンが以下で答えたものとほぼ同じです(バイロンは[^>]
間違っているだけです)
allowed
param を使用する場合、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, "");
[^<>]
with を変更する必要[^>]
があります<
。そうすると、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("");
しかし、それは他の理由でも完璧な解決策ではありません。
iframeサンドボックス属性を使用して、htmlタグを安全に削除できます。
ここでの考え方は、文字列を正規表現しようとする代わりに、DOM要素にテキストを挿入してその要素のtextContent
/ innerText
プロパティをクエリすることにより、ブラウザーのネイティブパーサーを利用するというものです。
テキストを挿入するのに最適な要素は、サンドボックス化されたiframeです。これにより、任意のコードの実行を防ぐことができます(別名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
and const
演算子を使用して適切にスコープがブロックされているため、おそらくIIFEを使用しないでください。また、あなたの解決策を使用して、私は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
param を使用する場合、XSSに対して脆弱です: stripTags('<p onclick="alert(1)">mytext</p>', '<p>')
戻り値<p onclick="alert(1)">mytext</p>
また、素晴らしいhtmlparser2の純粋な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などのツールを使用してWebアプリケーションをパックした場合、ノードとブラウザの両方で機能します。
<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,"");
htmlを取り除く単純な2行のjquery。
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
input
要素は1行のテキストのみをサポートします:
テキスト状態は、要素の値の1行のプレーンテキスト編集コントロールを表します。
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);