Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #8452: Fix-String-escapeHTML-and-String-unescapeHTML.patch

File Fix-String-escapeHTML-and-String-unescapeHTML.patch, 4.2 kB (added by jdalton, 5 months ago)

Fixed unescapeHTML to decode complex HTML entities in all browsers, fixed memory leak, fixed IE bug with escaped HTML

  • a/src/string.js

    old new  
    7878  escapeHTML: function() { 
    7979    var self = arguments.callee; 
    8080    self.text.data = this; 
    81     return self.div.innerHTML; 
     81    return self.wrapper.innerHTML; 
    8282  }, 
    8383 
    8484  unescapeHTML: function() { 
    8585    var div = new Element('div'); 
    86     div.innerHTML = this.stripTags(); 
    87     return div.childNodes[0] ? (div.childNodes.length > 1 ?  
    88       $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :  
     86    div.innerHTML = '<pre>'+this.stripTags()+'</pre>'; 
     87    div = div.firstChild; 
     88    return div.childNodes[0] ? (div.childNodes.length > 1 ? 
     89      $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : 
    8990      div.childNodes[0].nodeValue) : ''; 
    9091  }, 
    9192   
     
    206207  } 
    207208}); 
    208209 
    209 if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { 
    210   escapeHTML: function() { 
    211     return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); 
    212   }, 
    213   unescapeHTML: function() { 
    214     return this.stripTags().replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>'); 
    215   } 
    216 }); 
    217  
    218210String.prototype.gsub.prepareReplacement = function(replacement) { 
    219211  if (Object.isFunction(replacement)) return replacement; 
    220212  var template = new Template(replacement); 
     
    223215 
    224216String.prototype.parseQuery = String.prototype.toQueryParams; 
    225217 
     218if (Prototype.Browser.IE) 
     219  String.prototype.unescapeHTML = String.prototype.unescapeHTML.wrap(function(proceed){ 
     220    return proceed().replace(/\r/g,'\n') 
     221  }); 
     222if (Prototype.Browser.WebKit && Prototype.BrowserFeatures.SelectorsAPI) 
     223  String.prototype.escapeHTML = new Function('', 
     224    String.prototype.escapeHTML.toString().substring(14).replace(/;?\s*}$/,'') + '.replace(/>/g,"&gt;")' 
     225  ); 
     226 
    226227Object.extend(String.prototype.escapeHTML, { 
    227   div:  document.createElement('div'), 
     228  wrapper: document.createElement('pre'), 
    228229  text: document.createTextNode('') 
    229230}); 
    230231 
    231 String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text); 
     232String.prototype.escapeHTML.wrapper.appendChild(String.prototype.escapeHTML.text); 
     233 
     234if('&'.escapeHTML() !== '&amp;'){ 
     235  with(String.prototype.escapeHTML){ 
     236    text = wrapper.removeChild(text); 
     237    wrapper = document.createElement('xmp'); 
     238    wrapper.appendChild(text); 
     239  } 
     240
     241 
     242(function(){ 
     243  Event.observe(window, 'unload', function(){ 
     244    with(String.prototype.escapeHTML) wrapper = text = null; 
     245  }) 
     246}).defer(); 
    232247 
    233248var Template = Class.create({ 
    234249  initialize: function(template, pattern) { 
  • a/test/unit/string.html

    old new  
    277277        'a&lt;a href="blah"&gt;blub&lt;/a&gt;b&lt;span&gt;&lt;div&gt;&lt;/div&gt;&lt;/span&gt;cdef&lt;strong&gt;!!!!&lt;/strong&gt;g'.unescapeHTML()); 
    278278       
    279279      this.assertEqual(largeTextUnescaped, largeTextEscaped.unescapeHTML()); 
    280        
     280       
     281      this.assertEqual('test ú', 'test &uacute;'.unescapeHTML()); 
    281282      this.assertEqual('1\n2', '1\n2'.unescapeHTML()); 
    282       this.assertEqual('Pride & Prejudice', '<h1>Pride &amp; Prejudice</h1>'.unescapeHTML()); 
     283      this.assertEqual('Pride & Prejudice', '<h1>Pride &amp; Prejudice</h1>'.unescapeHTML()); 
     284       
     285      var escapedTest = '"&lt;" means "<" in HTML'; 
     286      this.assertEqual(escapedTest, escapedTest.escapeHTML().unescapeHTML()); 
    283287       
    284288      this.benchmark(function() { largeTextEscaped.unescapeHTML() }, 1000); 
    285289