JavaScriptでHTMLの特殊文字をエスケープできますか?


201

JavaScript機能でHTMLにテキストを表示したい。JSでHTML特殊文字をエスケープするにはどうすればよいですか?APIはありますか?


11
この質問はjQueryについて尋ねないため、これは重複ではありません。私はjQueryを使用しないので、これにのみ興味があります...
lvella

回答:


330
function escapeHtml(unsafe) {
    return unsafe
         .replace(/&/g, "&")
         .replace(/</g, "&lt;")
         .replace(/>/g, "&gt;")
         .replace(/"/g, "&quot;")
         .replace(/'/g, "&#039;");
 }

11
なぜ「&#039;」「&apos;」ではありません ?
sereda


2
replace()呼び出しでの正規表現は不要だと思います。プレーンな古い1文字の文字列も同様に機能します。
jamix 2014年

22
@jamix最新のブラウザエンジンは単純な正規表現を最適化しながら、生の文字列でグローバル置換を行うことはできません。
ビョルン

5
標準のAPIはありますか、これが唯一の方法ですか?
Sunil Garg

55

function escapeHtml(html){
  var text = document.createTextNode(html);
  var p = document.createElement('p');
  p.appendChild(text);
  return p.innerHTML;
}

// Escape while typing & print result
document.querySelector('input').addEventListener('input', e => {
  console.clear();
  console.log( escapeHtml(e.target.value) );
});
<input style='width:90%; padding:6px;' placeholder='&lt;b&gt;cool&lt;/b&gt;'>


ここで働くが、ブラウザで私のためにオフラインで作業していない

48

jQueryの.text()関数を使用できます。

例えば:

http://jsfiddle.net/9H6Ch/

.text()関数に関するjQueryドキュメントから:

このメソッドは、HTMLで正しくレンダリングされるように、必要に応じて提供された文字列をエスケープすることに注意する必要があります。そのためには、DOMメソッド.createTextNode()を呼び出し、文字列をHTMLとして解釈しません。

jQueryドキュメントの以前のバージョンでは、次のように表現されています(強調が追加されています)。

このメソッドは、HTMLで正しくレンダリングされるように、必要に応じて提供された文字列をエスケープすることに注意する必要があります。そのためには、DOMメソッド.createTextNode()を呼び出します。このメソッドは、特殊文字を同等のHTMLエンティティ(&lt; for <など)に置き換えます


3
あなたはこのように変換したい場合でも、新鮮な要素でそれを使用することができますconst str = "foo<>'\"&"; $('<div>').text(str).html()利回りfoo&lt;&gt;'"&amp;
amoebe

28

私はそれを行う適切な方法を見つけたと思います...

// Create a DOM Text node:
var text_node = document.createTextNode(unescaped_text);

// Get the HTML element where you want to insert the text into:
var elem = document.getElementById('msg_span');

// Optional: clear its old contents
//elem.innerHTML = '';

// Append the text node into it:
elem.appendChild(text_node);

今日、HTMLについて何か新しいことを学びました。w3schools.com/jsref/met_document_createtextnode.asp
Sellorio 2018年

1
:あなたはこのようにそれにアクセスしようとする場合は、テキストノードの内容がエスケープされていないことに注意してくださいdocument.createTextNode("<script>alert('Attack!')</script>").textContent
maechler

テキストを設定するだけの場合は、これが正しい方法です。これもtextContentですが、十分にサポートされていないようです。これは機能しませんが、一部のテキストと一部のHTMLで文字列を作成している場合は、エスケープする必要があります。
jgmjgm


20

これは、私が見た中で最速の方法です。さらに、ページの要素を追加、削除、または変更せずにすべてを実行します。

function escapeHTML(unsafeText) {
    let div = document.createElement('div');
    div.innerText = unsafeText;
    return div.innerHTML;
}

7
警告:引用符をエスケープしないため、HTMLコードの属性値内の出力を使用できません。たとえばvar divCode = '<div data-title="' + escapeHTML('Jerry "Bull" Winston') + '">Div content</div>'、無効なHTMLが生成されます!
izogfif

17

より良い解決策を見つけることは興味深いことでした:

var escapeHTML = function(unsafe) {
  return unsafe.replace(/[&<"']/g, function(m) {
    switch (m) {
      case '&':
        return '&amp;';
      case '<':
        return '&lt;';
      case '"':
        return '&quot;';
      default:
        return '&#039;';
    }
  });
};

>結果のXML / HTMLコードを壊さないため、解析しません。

ベンチマークは次のとおりです。http//jsperf.com/regexpairs また、ユニバーサルを作成しましたescape関数:http : //jsperf.com/regexpairs2


1
スイッチを使用すると、マップよりも大幅に高速になることは興味深いです。期待していなかった!共有してくれてありがとう!
Peter

可能なコードや考慮に入れることができるよりもはるかに多くのユニコード文字があります。この手動の方法はまったくお勧めしません。
vsync 2018年

なぜマルチバイト文字をエスケープするのですか?どこでもUTF-8を使用するだけです。
Neonit

4
>をスキップすると、コードが破損する可能性があります。<>の中もhtmlであることを覚えておく必要があります。その場合、>をスキップすると中断します。タグ間でのみエスケープする場合は、おそらくエスケープ<と&のみが必要です。
jgmjgm

8

エンコードされていないテキストを表示する最も簡潔で高性能な方法は、textContentプロパティを使用することです。

を使用するより高速ですinnerHTML。そして、それはオーバーヘッドのエスケープを考慮に入れていません。

document.body.textContent = 'a <b> c </b>';


@ZzZombo、それはスタイルとスクリプトタグで動作しないことは完全に正常です。それらにコンテンツを追加するときは、テキストではなくコードを追加します。この場合はinnerHTMLを使用します。さらに、エスケープする必要はありません。これらはHTMLとして解析されない2つの特別なタグです。解析時には、終了シーケンス</が満たされるまで、それらのコンテンツはテキストとして扱われます。
ユーザー

6

DOM要素はinnerTextに割り当てることでテキストをHTMLに変換することをサポートします。innerTextは関数ではありませんが、それに割り当てると、テキストがエスケープされたかのように機能します。

document.querySelectorAll('#id')[0].innerText = 'unsafe " String >><>';

1
少なくともChromeでは、マルチラインテキストを割り当てると<br>、改行の代わりに要素が追加され、スタイルやスクリプトなどの特定の要素が壊れる可能性があります。createTextNodeこの問題になりやすいではありません。
ZzZombo 2017

1
innerTextいくつかのレガシー/仕様の問題があります。使用する方が良いtextContent
Roy Tinker

3

文字列のすべての文字をエンコードできます。

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

または、次のように、心配するメインキャラクター(&、inebreak、<、>、 "、 ')をターゲットにします。

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

test.value=encode('How to encode\nonly html tags &<>\'" nice & fast!');

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55">&#119;&#119;&#119;&#46;&#87;&#72;&#65;&#75;&#46;&#99;&#111;&#109;</textarea>


独自のエスケープ関数を作成することは、一般的に悪い考えです。この点で他の回答の方が優れています。
jannis

2

ワンライナー(ES6 +用):

var escapeHtml = s => (s + '').replace(/[&<>"']/g, m => ({
    '&': '&amp;', '<': '&lt;', '>': '&gt;',
    '"': '&quot;', "'": '&#39;'
})[m]);

古いバージョンの場合:

function escapeHtml(s) {
    return (s + '').replace(/[&<>"']/g, function (m) {
        return ({
            '&': '&amp;', '<': '&lt;', '>': '&gt;',
            '"': '&quot;', "'": '&#39;'
        })[m];
    });
}

0

DOM構造を構築するときにこの問題に遭遇しました。この質問は私がそれを解決するのに役立ちました。パスの区切り記号としてダブルシェブロンを使用したかったのですが、新しいテキストノードを直接追加すると、文字自体ではなく、エスケープされた文字コードが表示されました。

var _div = document.createElement('div');
var _separator = document.createTextNode('&raquo;');
//_div.appendChild(_separator); /* this resulted in '&raquo;' being displayed */
_div.innerHTML = _separator.textContent; /* this was key */

0

アプリですでにモジュールを使用している場合は、escape-htmlモジュールを使用できます。

import escapeHtml from 'escape-html';
const unsafeString = '<script>alert("XSS");</script>';
const safeString = escapeHtml(unsafeString);

-3

prototype.jsライブラリを使用してこれを試してください:

string.escapeHTML();

デモを試す


5
これには「prototype.js」ライブラリが必要ですが、デモからはすぐにはわかりませんでした。:(
audiodude 2014

-4

私はこの解決策を思いつきました。

ユーザーまたはデータベースからの安全でないデータを含む要素にhtmlを追加するとします。

var unsafe = 'some unsafe data like <script>alert("oops");</script> here';

var html = '';
html += '<div>';
html += '<p>' + unsafe + '</p>';
html += '</div>';

element.html(html);

XSS攻撃に対して安全ではありません。これを追加します。

$(document.createElement('div')).html(unsafe).text();

そうです

var unsafe = 'some unsafe data like <script>alert("oops");</script> here';

var html = '';
html += '<div>';
html += '<p>' + $(document.createElement('div')).html(unsafe).text(); + '</p>';
html += '</div>';

element.html(html);

私にとって、これは使用するよりもはるかに簡単で、.replace()削除されます!!! 可能なすべてのhtmlタグ(希望)。


これは危険な考えです。要素がDOMにアタッチされている場合は、安全でないHTML文字列をHTMLとして解析します。代わりに.innerTextを使用してください。
teknopaul 2017

これは安全ではありません。に変換&lt;script&gt;され<script>ます。
fgb 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.