2015-08-05 22 views
15

Người dùng nhập tin nhắn trò chuyện, được hiển thị trực tiếp tới trang bằng mẫu Mustache. Rõ ràng, HTML nên được thoát để ngăn chặn việc tiêm HTML, nhưng sau đó một lần nữa các liên kết sẽ được hiển thị là <a href='...'>.Thoát khỏi các tin nhắn trò chuyện do người dùng tạo nhưng hiển thị liên kết

Có nhiều cách tiếp cận khác nhau mà tôi đã cố gắng sử dụng {{{ ... }}} để trả về nội dung HTML chưa thoát, điều này có nghĩa là liên kết sẽ được hiển thị và tôi cần tự lo liệu HTML. Có cách nào an toàn để làm điều đó mà không dựa vào một giải pháp nửa nướng tôi viết bản thân mình?

jQuery.text() sẽ tuyệt vời, nhưng tôi đoán nó sẽ hiển thị lại <a> dưới dạng văn bản.

Tôi có thể làm gì khác ở đây?

+1

Bạn nghĩ gì về việc sử dụng loại đánh dấu khác cho các liên kết trong trò chuyện, chẳng hạn như BBCode hoặc Markdown? Đây là cách nó thường hoạt động trên các bảng thảo luận khác nhau cũng như ở đây. – JacobMiki

+1

@JacobMiki Nhưng đây không phải là về việc thiết lập một cú pháp chung cho markdown, nhưng chỉ để kết xuất. Facebook Chat cũng không cần điều đó. – Mahoni

Trả lời

10

Nếu bạn không muốn viết giải pháp thoát hoặc phân tích cú pháp của riêng mình, có một plugin jQuery để xử lý các liên kết được gọi là Linkify. Bạn có thể chỉ cần thoát khỏi các tin nhắn và sau đó phân tích cú pháp chúng phía máy khách.

Ví dụ về cách thức hoạt động:

var text = "<div>Test<br>Test<br>Test http://stackoverflow.com</div>"; 
$('div').text(text); 

// Before: &lt;div&gt;Test&lt;br&gt;Test&lt;br&gt;Test http://stackoverflow.com&lt;/div&gt; 

$('div').linkify(); 

// After: lt;div&gt;Test&lt;br&gt;Test&lt;br&gt;Test <a href="http://stackoverflow.com" class="linkified" target="_blank">http://stackoverflow.com</a>&lt;/div&gt; 
0

Chỉ cần một ý tưởng: Bạn có thể xây dựng chức năng thoát của riêng bạn

escape : function() { 
    return function(val, render) { 
     var $s = $(val); 
     var $elements = $s.find("*").not("a"); //add other white-listed elements seperated by comma 
     for (var i = $elements.length - 1; i >= 0; i--) { 
      var e = $elements[i]; 
      $(e).replaceWith(e.innerHTML); 
     } 
     return $s.html(); 
    } 
} 

Bạn có thể gọi hàm bằng

{{#escape}}{{{YOUR_TEXT}}}{{/escape}} 

tôi đã không kiểm tra này. Giải pháp này cần jQuery. Mã trên được dựa trên giải pháp này: https://stackoverflow.com/a/27764431/1479486

0

thử chèn đầu tiên trong .text() và sau đó sử dụng regexp cho làm cho liên kết với .html(). Ở đây bạn có thể thấy một ví dụ vani:

var a="see formula a<b>c in http://test.com or https://x.com?p=3"; 

var hold=document.createElement('div'); 
hold.textContent=a; 

hold.innerHTML=hold.innerHTML.replace(
    /(https?:\/\/[-$A-Za-z0-9%_?&.~+\/=]+)/g, 
    '<a href="$1">$1</a>' 
); 

window.addEventListener('load',function(){ 
    document.body.appendChild(hold); 
}); 

Đối với một regexp acurate hơn bạn có thể thấy here

+1

[Ở đây] (https://mathiasbynens.be/demo/url-regex) bạn có thể thấy nhiều lựa chọn thay thế hơn cho regexp –

0

Nếu bạn kết thúc đi xuống con đường regex bộ lọc sau và regex là người hăng hái nhất tôi tìm thấy cho chọn tất cả các loại url mà người dùng của bạn sẽ cố gắng nhập.

Heres một regexr để chơi đùa với nó: http://regexr.com/3bjk9

(function() { 
    'use strict'; 

    angular 
     .module('core.filters') 
     .filter('urlToA', urlToA); 

    // -------------------- 

    function urlToA() { 
     return function (string, noClick) { 
      var urlPattern = /((?:(http|https|Http|Https|rtsp|Rtsp):\/\/(?:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,64}(?:\:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,25})?\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\:\d{1,5})?)(\/(?:(?:[a-zA-Z0-9\;\/\?\:\@\&\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?(?:\b|$)/gi; // jshint ignore:line 

      return string ? string.replace(urlPattern, replace) : string; 

      function replace (url) { 
       var httpUrl = url.indexOf('http') === -1 ? 'http://' + url : url; 

       if (noClick) { 
        return '<a>' + url + '</a>'; 
       } else { 
        return '<a href="' + httpUrl + '">' + url + '</a>'; 
       } 
      } 
     }; 
    } 

})(); 
Các vấn đề liên quan