前提
Flaskを利用した記事投稿プラットフォームを作っています。おおまかなシステムは出来上がりました。
記事はマークダウンで記述することができ、XSS対策として一部のHTMLを使用することができます。使用できないHTMLはPythonでエスケープします。
エスケープ処理は以下のコードで行っています。
Python
1import bleach 2bleach.clean(article.content, tags=["div","br","span","img","code","pre"],attributes={"*":["style"],"img":["src","width","height"]},styles=["color","margin"])
実現したいこと
NoteやQiita、teratailなどと同じようにソースコードの貼り付けを可能にしたい。
現状
<pre><code></code></pre>内にコード(HTML)を記述すると、bleachのホワイトリストに登録したタグはそのまま解釈してしまいます。また、<!DOCTYPE html>などは表示すらされず消えてしまいます。ブラウザ側のJavaScriptで<pre></pre>内の特殊文字をエスケープしてそのまま表示されるようにしたのですが、ホワイトリスト以外のタグは「&」など、特殊文字コードで表示されてしまいます。
どなたか回答よろしくお願いいたします。
追記
マークダウンで記述するようにしているため、{{content | markdown}} と、フィルターをかけています。
以下のコードのようにJavaScriptで<pre>内をエスケープする処理も考えましたが、bleachで許可していないタグなどは特殊文字で表示されてしまいます。予めエスケープされているので当然といえば当然なのでしょうが....
JavaScript
1 var escapeHtml = (function (String) { 2 var escapeMap = { 3 '&': '&', 4 "'": ''', 5 '`': '`', 6 '"': '"', 7 '<': '<', 8 '>': '>' 9 }; 10 var escapeReg = '['; 11 var reg; 12 for (var p in escapeMap) { 13 if (escapeMap.hasOwnProperty(p)) { 14 escapeReg += p; 15 } 16 } 17 escapeReg += ']'; 18 reg = new RegExp(escapeReg, 'g'); 19 return function escapeHtml (str) { 20 str = (str === null || str === undefined) ? '' : '' + str; 21 return str.replace(reg, function (match) { 22 return escapeMap[match]; 23 }); 24 }; 25}(String)); 26 27var pre = document.querySelectorAll('pre'); 28for(var i = 0; i < pre.length; i++) { 29 pre[i].innerHTML = escapeHtml(pre[i].innerHTML); 30}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/09/18 03:36
2020/09/18 03:54