2012-07-19 3 views
2

JavaScript 객체에서 HTML 코드를 생성하는 prototype.js Template을 가지고 있다면 어떻게 HTML이 깨지지 않도록 JavaScript 객체의 데이터에서 HTML 요소를 자동으로 이스케이프 처리 할 수 ​​있습니까?prototype.js 템플릿에 HTML 엔티티를 인코딩하려면 어떻게해야합니까?

샘플 자바 스크립트 코드 : data.statement는 인용 부호 " 포함되어 있기 때문에

var data = { 
    name: 'Josh', 
    url: 'http://josh.gitlin.name/', 
    statement: 'I\'m a JavaScript and PHP developer. Find me on Stack Overflow and say "hi"!' 
} 

var template = new Template(
    '<div><label>Name: <input name=\"name\" value=\"#{name}\"></label></div>'+ 
    '<div><label>URL: <input name=\"url\" value=\"#{url}\"></label></div>'+ 
    '<div><label>Personal Statement: <input name=\"statement\" value=\"#{statement}\"></label></div>' 
); 

$('test').update(template.evaluate(data)); 

JSFiddle code for the above

위의 코드는 잘못된 <input> 태그를 생성합니다. data 개체를 수정하거나 data 개체를 복제하지 않고 Template이 위의 예에서 HTML 엔터티를 자동으로 이스케이프하도록하려면 어떻게해야합니까? 이 작업을 수행하기 위해

답변

1

, 두 가지 일이 필요

  1. Template 클래스의 escape 방법은 HTML 엔티티를 탈출 알고 있어야
  2. escapeHTML method which Prototype.js adds to the String object는에 인용 부호를 인코딩하도록 확장되어야합니다
  3. &quot; 엔티티. (그리고 아마도 더 그것은 지금 너무 단순입니다 ....)

는 모두이 두 다음 코드를 사용하여 달성 할 수있다 :

String.prototype.escapeHTML = String.prototype.escapeHTML.wrap(function(proceed){ 
    return proceed().replace(/"/g,'&quot;'); 
}); 

Template.addMethods({ 
    evaluateEscapeHTML: function(object) { 
     if (object && Object.isFunction(object.toTemplateReplacements)) 
      object = object.toTemplateReplacements(); 

     return this.template.gsub(this.pattern, function(match) { 
      if (object == null) return (match[1] + ''); 

      var before = match[1] || ''; 
      if (before == '\\') return match[2]; 

      var ctx = object, expr = match[3], 
       pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; 

      match = pattern.exec(expr); 
      if (match == null) return before; 

      while (match != null) { 
      var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; 
      ctx = ctx[comp]; 
      if (null == ctx || '' == match[3]) break; 
      expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); 
      match = pattern.exec(expr); 
      } 

      return before + String.interpret(ctx).escapeHTML(); 
     }); 
    } 
}); 

이 코드는하여 Prototype.js를 확장합니다 을 템플릿 새로운 evaluateEscapeHTML 방법을 추가, 그래서이 코드는 번 를 실행해야하며, 그때부터, 어떤 Template는 이제 새로운 evaluateEscapeHTML 방법이됩니다

을 내가 로했다
var template = new Template(
    '<div><label>Name: <input name=\"name\" value=\"#{name}\"></label></div>'+ 
    '<div><label>URL: <input name=\"url\" value=\"#{url}\"></label></div>'+ 
    '<div><label>Personal Statement: <input name=\"statement\" value=\"#{statement}\"></label></div>' 
); 

$('test').update(template.evaluate(data)); 

JSFiddle to test this

참고 prototype.js를 버전 1.7에서에게 Template 클래스에서 전체evaluate 방법을 중복. 이것은 이후 버전의 evaluate 메소드가 개선 될 경우 내 코드도 개선되어야한다는 점에서 큰 단점을 가지고 있습니다. 그러나 나는 이것을 할 수있는 더 좋은 방법을 찾지 못했습니다.

return before + String.interpret(ctx); 

에 :

내가 만든 evaluate 방법에 대한 구체적인 수정이 줄을 변경했다가 같은 수치가 왜 그럴 수있는, 모두의

return before + String.interpret(ctx).escapeHTML(); 

어떻게 든 extend 또는 wrap 코드의 나머지 부분 ...

1

소스 코드를 읽는 중 템플릿에는 아무 것도 없습니다. 탈출 HTML. 또한 제공된 String#escapeHTML은 태그 (wtf)를 정규식 (wtf2)으로 제거하려고 시도하며 따옴표를 벗어나지 않으므로 꽤 심한 편입니다.

당신은 수동으로 문자열을 탈출 할 수 :

function escapeHTML(text) { 
    var map = { 
     "&" : "amp", 
     "'": "#39", 
     '"': "quot", 
     "<": "lt", 
     ">": "gt" 

    }; 

    return text.replace(/[&'"<>]/g, function(m) { 
     return "&" + map[m] + ";"; 
    }); 
} 
+1

난 그냥 내 자신의 코드를 작성하고 escapeHTML'이 얼마나 끔찍한'깜짝 놀라게했다. 더 좋은 제안이 있습니까? 그렇지 않은 경우 제공 한 코드가 마음에 듭니다. (내 솔루션에 대한 생각 또한 환영 받았다.) – Josh

+0

@Josh 나는이 기능이 일을 잘 수행해야한다고 생각한다. 나는 Template의 핵심 기능에 이것을 주입하기에 충분한 프로토 타입에 익숙하지 않다. 그래서 그것에 대해 아무 말도 할 수 없습니다. 나는 진짜 템플릿 엔진을 사용 하겠지만, 그것들이 부족한 것은 아니다. : P – Esailija

+0

필자는 이것을 Template의 핵심 기능에 주입 할 수있는 프로토 타입에 익숙합니다. ':-)'당신의 기능에 감사 드리며, 나는 그 우물을 사용할 것입니다. – Josh

관련 문제