私はのような文字列があります
var str = 'One & two & three';
webサーバーによってHTMLにレンダリングされます。これらの文字列をに変換する必要があります
'One & two & three'
現在、それは私がやっていることです(jQueryの助けを借りて):
$(document.createElement('div')).html('{{ driver.person.name }}').text()
しかし、私はそれを間違ってやっているという不安な気持ちを持っています。私が試してみました
unescape("&")
しかし、それはうまくいかないようで、decodeURI/decodeURIComponentもしません。
他に、よりネイティブでエレガントな方法はありますか?
JavaScriptからHTML(テキストなど)を解釈するためのより近代的なオプションは、DOMParser
APIでのHTMLサポートです( MDNのここを参照 )。これにより、ブラウザのネイティブHTMLパーサーを使用して文字列をHTMLドキュメントに変換できます。 2014年後半以降、すべての主要ブラウザの新しいバージョンでサポートされています。
テキストの内容をデコードしたいだけであれば、それを唯一の内容として文書本体に入れ、その文書を解析してその.body.textContent
を取り出すことができます。
var encodedStr = 'hello & world';
var parser = new DOMParser;
var dom = parser.parseFromString(
'<!doctype html><body>' + encodedStr,
'text/html');
var decodedString = dom.body.textContent;
console.log(decodedString);
DOMParser
のドラフト仕様 を見るとわかるように、JavaScriptは解析済み文書に対しては有効になっていないので、セキュリティーを気にせずにこのテキスト変換を実行できます。
parseFromString(str, type)
メソッドは、タイプに応じて、次の手順を実行する必要があります。
"text/html"
strを
HTML parser
で解析し、新しく作成されたDocument
を返します。スクリプトフラグは "無効"に設定する必要があります。
注意
script
要素は実行不可能とマークされ、noscript
の内容はマークアップとして解析されます。
これはこの質問の範囲を超えていますが、、解析されたDOMノード自体(テキストの内容だけではなく)を取って移動する場合は注意してください。ライブドキュメントDOMに対しては、それらのスクリプティングが再度有効にされる可能性があり、セキュリティ上の懸念がある可能性があります。まだ調査していないので注意してください。
すべてのエンコードされたHTMLエンティティをデコードする必要がありますか、それとも単に&
自体をデコードする必要がありますか。
&
を処理するだけでよい場合は、これを実行できます。
var decoded = encoded.replace(/&/g, '&');
すべてのHTMLエンティティをデコードする必要がある場合は、jQueryなしでそれを実行できます。
var elem = document.createElement('textarea');
elem.innerHTML = encoded;
var decoded = elem.value;
この回答の以前のバージョンのセキュリティホールを浮き彫りにしている以下のMarkのコメントに注意してください、そして潜在的なXSS脆弱性を軽減するためにtextarea
よりdiv
を使うことを勧めます。これらの脆弱性は、jQueryを使用しているか、普通のJavaScriptを使用しているかにかかわらず存在します。
Matthias Bynensにはこのためのライブラリがあります。 https://github.com/mathiasbynens/he
例:
console.log(
he.decode("Jörg & Jürgen rocked to & fro ")
);
// Logs "Jörg & Jürgen rocked to & fro"
要素のHTMLコンテンツを設定してからそのテキストコンテンツを読み返すことを含むハッキングよりも優先することをお勧めします。そのようなアプローチはうまくいく可能性がありますが、信頼できないユーザー入力で使用された場合、見かけ上危険であり、XSSの機会を提示します。
本当にライブラリにロードできない場合は、 この回答 で説明されているtextarea
ハックを使用して、ほぼ重複する質問をすることができます。私が知っているセキュリティホール:
function decodeEntities(encodedString) {
var textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}
console.log(decodeEntities('1 & 2')); // '1 & 2'
しかし、セキュリティ上の問題に注意してください。これは、これと同様のアプローチに影響を及ぼします。リンクされた回答に記載されています。このアプローチはハックです、そして将来のtextarea
(あるいは特定のブラウザでのバグ)の許容される内容への変更は突然XSSホールがある日にそれに依存するコードに通じるかもしれません。
var htmlEnDeCode = (function() {
var charToEntityRegex,
entityToCharRegex,
charToEntity,
entityToChar;
function resetCharacterEntities() {
charToEntity = {};
entityToChar = {};
// add the default set
addCharacterEntities({
'&' : '&',
'>' : '>',
'<' : '<',
'"' : '"',
''' : "'"
});
}
function addCharacterEntities(newEntities) {
var charKeys = [],
entityKeys = [],
key, echar;
for (key in newEntities) {
echar = newEntities[key];
entityToChar[key] = echar;
charToEntity[echar] = key;
charKeys.Push(echar);
entityKeys.Push(key);
}
charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
}
function htmlEncode(value){
var htmlEncodeReplaceFn = function(match, capture) {
return charToEntity[capture];
};
return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
}
function htmlDecode(value) {
var htmlDecodeReplaceFn = function(match, capture) {
return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
};
return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
}
resetCharacterEntities();
return {
htmlEncode: htmlEncode,
htmlDecode: htmlDecode
};
})();
これはExtJSのソースコードからのものです。
element.innerText
もトリックを行います。
私のようにそれを探しているのであれば - その間、Nice and safe JQueryメソッドがあります。
https://api.jquery.com/jquery.parsehtml/
あなたはf.ex.することができますコンソールにこれを入力してください。
var x = "test &";
> undefined
$.parseHTML(x)[0].textContent
> "test &"
そのため、$ .parseHTML(x)は配列を返します。テキスト内にHTMLマークアップがある場合、array.lengthは1より大きくなります。
あなたはLodashのエスケープ/エスケープ機能を使用することができます https://lodash.com/docs/4.17.5#unescape
import unescape from 'lodash/unescape';
const str = unescape('fred, barney, & pebbles');
strは'fred, barney, & pebbles'
になります
jQueryはあなたのためにエンコードおよびデコードします。ただし、divではなくtextareaタグを使用する必要があります。
var str1 = 'One & two & three';
var str2 = "One & two & three";
$(document).ready(function() {
$("#encoded").text(htmlEncode(str1));
$("#decoded").text(htmlDecode(str2));
});
function htmlDecode(value) {
return $("<textarea/>").html(value).text();
}
function htmlEncode(value) {
return $('<textarea/>').text(value).html();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="encoded"></div>
<div id="decoded"></div>
まずボディのどこかに<span id="decodeIt" style="display:none;"></span>
を作成します
次に、これにinnerHTMLとしてデコードする文字列を割り当てます。
document.getElementById("decodeIt").innerHTML=stringtodecode
最後に、
stringtodecode=document.getElementById("decodeIt").innerText
これが全体のコードです:
var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText
一行の人のために:
const htmlDecode = innerHTML => Object.assign(document.createElement('textarea'), {innerHTML}).value;
console.log(htmlDecode('Complicated - Dimitri Vegas & Like Mike'));
一般的なものをキャッチするJavaScriptソリューション:
var map = {amp: '&', lt: '<', gt: '>', quot: '"', '#039': "'"}
str = str.replace(/&([^;]+);/g, (m, c) => map[c])
私はJSON配列から&を削除するためにあらゆることを試みました。上記の例のどれも、しかし https://stackoverflow.com/users/2030321/chris 私の問題を解決するために導いた素晴らしい解決策を与えた。
var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText
JSONデータを配列に引き込んでいるモーダルウィンドウに挿入する方法がわからないため、使用しませんでしたが、例に基づいて試してみましたが、うまくいきました。
var modal = document.getElementById('demodal');
$('#ampersandcontent').text(replaceAll(data[0],"&", "&"));
それは単純で、うまくいくから好きです。しかし、なぜそれが広く使われていないのかわからない。簡単な解決策を見つけるためにハイ&ローを検索しました。私は構文の理解を求め続け、そしてこれを使用することに何らかのリスクがあるかどうか。まだ何も見つかっていません。