Closed pyykkis closed 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
Put strings in a nested container
function UnescapedString(str) {
this.str = str;
}
function safeHTML(str) {
return new UnescatedString(str);
}
function safeHTML2(str) {
var str2 = new String(str);
str2.safe = true; // XXX: Not sure if possible with JS implementations
return str2;
}
Then in the render loop the render method checks the presence of attribute or typeof string to see whether to dump it out as innerText or innerHTML.
Note: GitHub commet box is horrible for code because of non-fixed width font.
Some info:
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 =]
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.
Are you sure it's a good idea to pollute the global namespace with "t"? We've already got ourselves a T for translations :)
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? =)
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 :(
Also if you prefer short t you can always alias it locally:
var t = window.TRANSPARENCY;
Moved further discussion regarding namespaces to https://github.com/leonidas/transparency/issues/15
Based on discussion at https://github.com/leonidas/transparency/issues/15, Transparency.SafeHtml(str)
should be ok as a constructor function for html strings.
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.
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>')
https://github.com/leonidas/transparency/issues/26 takes care of this. Closing.
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.