leonidas / transparency

Transparency is a semantic template engine for the browser. It maps JSON objects to DOM elements by id, class and data-bind attributes.
http://leonidas.github.com/transparency/
MIT License
969 stars 112 forks source link

Support unescaped rendering with directives #10

Closed pyykkis closed 12 years ago

pyykkis commented 12 years ago

Transparency escapes values before rendering (see https://github.com/leonidas/transparency/issues/8 for the details). However, sometimes unescaped values should be rendered, e.g., when using wysiwyg editors.

Design and implement directive support for unescaped values.

miohtama commented 12 years ago

Some template engines, e.g. Django, use special "SafeHTML" class / function to mark strings to be raw HTML (friendly).

With this kind of implementation we could avoid the need for directives, or have it as optional step and simple mark data to be HTML when data is constructed.

Some examples what could be done:

 var data =  {
       htmlPayload : $.safeHTML("<h1>hello</h1>")
  }

 var directives = {
      htmlPayload : function() { return $.safeHTML(myData); }
 }

Where the implementation of safeHTML() would simply

Note: GitHub commet box is horrible for code because of non-fixed width font.

Some info:

pyykkis commented 12 years ago

Thanks for the well-thought proposal.

As you pointed out, string is actually a primitive type in javascript and can't be extended as object. However, extending String object should be ok.

s1 = "foo";
s1.safe = true;
s1.safe; // undefined

s2 = new String("foo");
s2.safe = true;
s2.safe // true

I'm focusing on performance for a day or two. In the meanwhile, feel free to go for it, in case you've time to spare =]

pyykkis commented 12 years ago

As I got rid of jQuery, I introduced transparency global object, t.

I propose we implement t.SafeHTML(str) constructor, which builds a String object s with attribute s.safeHTML = true. I guess it would be enough to support this via directives, as below:

data =
  title: "<h1>Hello World!</h1>"
  body:  "<div>My great adventures in Stockholm.</div>"

directives =
  title: -> t.SafeHTML @title
  body:  -> t.SafeHTML @body

$('#content').render data, directives

PS. It is indeed a pain in the ass to write code into comments without fixed font.

raimohanska commented 12 years ago

Are you sure it's a good idea to pollute the global namespace with "t"? We've already got ourselves a T for translations :)

pyykkis commented 12 years ago

I guess I have to expose one object, if I'm going to provide transparency without jQuery?

t might be a bad choice though. How 'bout Transparency.render() and Transparency.SafeHTML() or .SafeHtml()? That should probably be less prone to clash with anything else and user could assign to by himself to t, T, or whatever is convenient.

Out of curiosity, are you using a library/framework for translations? If so, what that might be? =)

miohtama commented 12 years ago

Please use UGLY full caps for globals: TRANSPARENCY (only if you are going to make it a forced global)

http://yuiblog.com/blog/2006/06/01/global-domination/

E.g. Three.js, Yahoo YUI does this and it is generally accepted best practice:

https://github.com/mrdoob/three.js/blob/master/src/Three.js

However, since globals are not that popular, I suggest you add minimal boilerplate to export Transparency in different ways

I recently saw a project having boilerplate for all this, but I cannot remember which it was anymore :(

miohtama commented 12 years ago

Also if you prefer short t you can always alias it locally:

   var t = window.TRANSPARENCY;
miohtama commented 12 years ago

Moved further discussion regarding namespaces to https://github.com/leonidas/transparency/issues/15

pyykkis commented 12 years ago

Based on discussion at https://github.com/leonidas/transparency/issues/15, Transparency.SafeHtml(str) should be ok as a constructor function for html strings.

raimohanska commented 12 years ago

Regarding i18n, we are using jsperanto (https://github.com/jpjoyal/jsperanto). We also use JavascriptMVC and have hacked together a transparency view plugin for that. For our convenience, we included localization into that plugin, so that the templates are localized before use. We use a resourceKey attribute in the DOM elements to annotate translated parts in the template.

This plugin might be released as OSS, but there's the problem that it kinda couples transparency with jsperanto. For us it's good but it probably decreases the plugin's general applicability. Maybe I should release it without the localization part.

pyykkis commented 12 years ago

Thanks for the info!

I implemented html first version for rendering with directives, available at master. Syntax (yet to be updated to readme):

  it "should render safe html content with directives", ->
    doc = jQuery(
     '<div>
        <div class="person">
          <span class="name"></span><span class="email"></span>
        </div>
      </div>')

    person =
      firstname: '<b>Jasmine</b>'
      lastname:  '<i>Taylor</i>'
      email:     'jasmine.tailor@example.com'

    directives =
      name: (element) -> (window.Transparency.safeHtml "#{@firstname} #{@lastname}")

    expected = jQuery(
      '<div>
        <div class="person">
          <span class="name"><b>Jasmine</b> <i>Taylor</i></span>
          <span class="email">jasmine.tailor@example.com</span>
        </div>
      </div>')
pyykkis commented 12 years ago

https://github.com/leonidas/transparency/issues/26 takes care of this. Closing.