どうやら、これは私が思っていたよりも見つけるのが難しいです。そしてそれはとても簡単です...
JavaScriptに組み込まれているPHPのhtmlspecialcharsと同等の機能はありますか?それを自分で実装するのはかなり簡単ですが、組み込み関数を使用するのであれば、それを使用する方がいいでしょう。
PHPに不慣れな人のために、htmlspecialcharsは<htmltag/>
のようなものを<htmltag/>
に変換します
escape()
とencodeURI()
がこのように機能しないことを知っています。
ソリューションコードに問題があります。各特殊文字の最初の出現のみをエスケープします。例えば:
escapeHtml('Kip\'s <b>evil</b> "test" code\'s here');
Actual: Kip's <b>evil</b> "test" code's here
Expected: Kip's <b>evil</b> "test" code's here
適切に動作するコードは次のとおりです。
function escapeHtml(text) {
return text
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
次のコードは上記と同じ結果を生成しますが、特にテキストの大きなブロックでパフォーマンスが向上します(ありがとう jbo5112 )。
function escapeHtml(text) {
var map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}
それがHTMLエンコーディングです。それを行うためのネイティブjavascript関数はありませんが、グーグルで検索してうまく処理することができます。
例えば。 http://sanzon.wordpress.com/2008/05/01/neat-little-html-encoding-trick-in-javascript/
編集:
これは私がテストしたものです。
var div = document.createElement('div');
var text = document.createTextNode('<htmltag/>');
div.appendChild(text);
console.log(div.innerHTML);
出力:<htmltag/>
読む価値がある: http://bigdingus.com/2007/12/29/html-escaping-in-javascript/
escapeHTML: (function() {
var MAP = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
var repl = function(c) { return MAP[c]; };
return function(s) {
return s.replace(/[&<>'"]/g, repl);
};
})()
注:これは一度だけ実行します。そして、既にエンコードされた文字列で実行しないでください。 &
は&amp;
になります
JQueryを使用すると、次のようになります。
var escapedValue = $('<div/>').text(value).html();
関連する質問から jQueryによるHTML文字列のエスケープ
コメントで述べたように、この実装では二重引用符と一重引用符がそのまま残されています。つまり、要素属性を生のhtml文字列として作成する必要がある場合は、このソリューションを使用しないでください。
HTMLをエスケープする関数は次のとおりです。
function escapeHtml(str)
{
var map =
{
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return str.replace(/[&<>"']/g, function(m) {return map[m];});
}
デコードするには:
function decodeHtml(str)
{
var map =
{
'&': '&',
'<': '<',
'>': '>',
'"': '"',
''': "'"
};
return str.replace(/&|<|>|"|'/g, function(m) {return map[m];});
}
Underscore.jsは、このための機能を提供します。
_.escape(string)
文字列をエスケープしてHTMLに挿入し、&、<、>、 "、および '文字を置き換えます。
http://underscorejs.org/#escape
これは組み込みのJavaScript関数ではありませんが、すでにアンダースコアを使用している場合、変換する文字列が大きすぎない場合は、独自の関数を記述するよりも優れた代替手段です。
さらに別の考えは、すべての文字マッピングを完全に放棄し、代わりにすべての不要な文字をそれぞれの数値文字参照に変換することです:
function escapeHtml(raw) {
return raw.replace(/[&<>"']/g, function onReplace(match) {
return '&#' + match.charCodeAt(0) + ';';
});
}
注指定されたRegExは、OPがエスケープしたい特定の文字のみを処理しますが、エスケープされたHTMLが使用されるコンテキストに応じて、これらの文字では不十分な場合があります。 Ryan Groveの記事 HTMLエスケープには&、<、>、および " 以上のトピックがあります。また、状況によっては、回避するために次のRegExが必要になる場合があります。 XSSインジェクション:
var regex = /[&<>"'` !@$%()=+{}[\]]/g
String.prototype.escapeHTML = function() {
return this.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
サンプル :
var toto = "test<br>";
alert(toto.escapeHTML());
おそらく、このような機能は必要ありません。コードはすでにブラウザ*にあるため、実際に使用するためにブラウザで逆方向にデコードする必要があるHTMLを生成およびエンコードする代わりに、DOMに直接アクセスできます。
innerText
プロパティを使用して、プレーンテキストをDOMに安全に挿入し、提示されたエスケープ関数を使用するよりもはるかに高速に挿入します。静的な事前エンコード文字列をinnerHTML
に割り当てるよりも faster です。
classList
を使用してクラスを編集し、dataset
を使用してdata-
属性を設定し、setAttribute
を他の属性に設定します。
これらはすべてあなたのためにエスケープを処理します。より正確に言うと、DOMのテキスト表現であるHTMLに取り組んでいるので、エスケープは必要なく、エンコードは下で実行されません**。
// use existing element
var author = 'John "Superman" Doe <[email protected]>';
var el = document.getElementById('first');
el.dataset.author = author;
el.textContent = 'Author: '+author;
// or create a new element
var a = document.createElement('a');
a.classList.add('important');
a.href = '/search?q=term+"exact"&n=50';
a.textContent = 'Search for "exact" term';
document.body.appendChild(a);
// actual HTML code
console.log(el.outerHTML);
console.log(a.outerHTML);
.important { color: red; }
<div id="first"></div>
*この回答は、サーバー側のJavaScriptユーザー(Node.js、 etc。 )を対象としたものではありません
**その後、明示的に実際のHTMLに変換しない限り。例えば。 innerHTML
にアクセスする-これは、他の回答で提案された$('<div/>').text(value).html();
を実行したときに起こることです。したがって、最終目標がドキュメントにデータを挿入することである場合、この方法でそれを行うことにより、2回作業を行うことになります。また、結果のHTMLでは、すべてがエンコードされているわけではなく、有効にするために必要な最小値のみがエンコードされていることがわかります。コンテキストに依存して行われるため、このjQueryメソッドは引用符をエンコードしないため、汎用のエスケープ機能として使用しないでください。属性値の場所に信頼できないデータまたは引用符を含むデータを含む文字列としてHTMLを構築する場合、引用符のエスケープが必要です。 DOM APIを使用する場合、エスケープを気にする必要はまったくありません。
Node.JSユーザー(またはブラウザーでJadeランタイムを使用しているユーザー)の場合、Jadeのエスケープ機能を使用できます。
require('jade').runtime.escape(...);
他の誰かがそれを維持している場合、自分でそれを書く意味はありません。 :)
function htmlEscape(str){
return str.replace(/[&<>'"]/g,x=>'&#'+x.charCodeAt(0)+';')
}
このソリューションでは、文字の数値コードを使用します。たとえば、<
は<
に置き換えられます。
そのパフォーマンスは マップを使用したソリューション よりわずかに劣りますが、次のような利点があります。
O.k.w.の回答について少し詳しく説明します。
そのためにブラウザのDOM関数を使用できます。
var utils = {
dummy: document.createElement('div'),
escapeHTML: function(s) {
this.dummy.textContent = s
return this.dummy.innerHTML
}
}
utils.escapeHTML('<escapeThis>&')
これは<escapeThis>&
を返します
標準関数createElement
を使用して不可視要素を作成し、関数textContent
を使用してコンテンツとして文字列を設定し、次にinnerHTML
を使用してHTML表現のコンテンツを取得します。
これがそのパフォーマンスと.replace( '&'、 '&')。replace( '<'、 '<')を使用した連鎖ロジックではないため、これがレースで勝つことを願っています...
var mapObj = {
'&':"&",
'<':"<",
'>':">",
'"':""",
'\'':"'"
};
var re = new RegExp(Object.keys(mapObj).join("|"),"gi");
function escapeHtml(str)
{
return str.replace(re, function(matched)
{
return mapObj[matched.toLowerCase()];
});
}
console.log('<script type="text/javascript">alert('Hello World');</script>');
console.log(escapeHtml('<script type="text/javascript">alert('Hello World');</script>'));
逆にしたもの:
function decodeHtml(text) {
return text
.replace(/&/g, '&')
.replace(/</ , '<')
.replace(/>/, '>')
.replace(/"/g,'"')
.replace(/'/g,"'");
}
function htmlspecialchars(str) {
if (typeof(str) == "string") {
str = str.replace(/&/g, "&"); /* must do & first */
str = str.replace(/"/g, """);
str = str.replace(/'/g, "'");
str = str.replace(/</g, "<");
str = str.replace(/>/g, ">");
}
return str;
}