kirbysayshi/Vash — pull request #5 by rjgotten (2012-07-02 22:55:48+00:00)
Title: ASP.NET MVC-like HTML helpers

I've done some work on extensibility for Vash with helper methods, like the `HtmlHelper` extension methods that are used with ASP.NET MVC. I've also introduced a `toHtmlString` marker-method, that identifies objects with pre-encoded HTML strings. (It takes after the `IHtmlString` interface from ASP.NET, ofcourse. May be more familiar as its most common encountered implementor: `MvcHtmlString`.) This allows you to pre-encode data in your viewmodel without having to worry about `vash.raw` properly being used or not. When `htmlEscape` is enabled, Vash will simply do the appropriate thing when it does or does not see the interface method.

Sofar, I've ported over the `vash.raw( ... )` parse token into a `vash.helpers.raw` method and refactored the regex-replace based escaping (which was being copied and pasted into each individual function body) into a `vash.helpers.escape` method. (I've also removed the parsing hack for vash.raw, ofcourse.) It's a bit more overhead, but sofar the impact seems negligable. As the changes isolate the regex replacement into a re-used function, performance should theoretically even improve on multiple calls; the code should be able to become 'hot' and be compiled down to native code much more easily.

Note that `vash.helpers.raw` does little else but wrap the passed in value into a lightweight object that has a `toHtmlString` method. This method is the marker serving as the `IHtmlString` equivalent and any object implementing it will short-circuit `vash.helpers.escape` by grabbing the result of `toHtmlString`.

Externalizing the HTML escaping allows also for an interesting scenario I have yet to try out. You can potentially use dependency injection to supply different escaping methods to NodeJS and browsers; browsers can in theory use the DOM with a cached element and text node, like so:

```javascript
vash.helpers.escape = ((function() {
var elem = document.createElement("span"),
node = elem.appendChild( document.createTextNode( "" );

return function( val ) {
node.value = ( val != null ? val.toString() : "" );
return elem.innerHTML;
}
})();
```

Definitely more secure, but I wonder if it would also be faster than the stack of regexes ...