Permalink
Browse files

Initial commit! Wheeee!!!

  • Loading branch information...
0 parents commit 7130ea1e7b24e5da10910da07c53d6bb3372632d @rektide rektide committed May 17, 2012
Showing with 200 additions and 0 deletions.
  1. +38 −0 README.md
  2. +90 −0 duster-ko.js
  3. +1 −0 lib/dust-0.3.0.js
  4. +1 −0 lib/dustjs.git.url
  5. +1 −0 lib/knockout-2.1.0.debug.js.url
  6. +1 −0 lib/knockout-2.1.0.js
  7. +19 −0 package.json
  8. +2 −0 sample/helloworld.dust
  9. +21 −0 sample/helloworld.dust.js
  10. +26 −0 sample/sample.xhtml
@@ -0,0 +1,38 @@
+# Duster-Ko #
+
+Duster-KO is a Dust.JS[1] implementation & hack-up of a Knockout[2] Template Engine[3]. There's not a lot of the well famed uber-schmancy asynchronous & parallel Dust.js super-powers going on; this is a pretty straight & simple means of using Dust.js templates.
+
+# Usage #
+
+Is pretty straightforwards:
+
+* include and give an id for each compiled dust template: `<script type="application/javascript" src="mytemplate.dust.js" id="mytemplate"/>`
+* bind to it. `<div data-bind="mytemplate"/>`
+* `ko.applyBindings(myModelView)`
+* ...
+* uh, you also neeed to hack Dust. `:(` (hack already done & provided)
+
+# Implementation #
+
+Oh, pretty straightforwards, not much magic.
+
+* Create a Dust helper-filter and make it default, to evaluate Observerable objects properly (call as a function with no arguments).
+* Derive a utterly vanilla Knockout Template Engine that calls into Dust.
+* A small hack to Dust to keep it from trying to evaluate Observables like functional Dust tags. See: `:(`
+
+# Why the Dust hack #
+
+:(
+
+Unpleasant business, that.
+
+Dust expects any functional tags to accept a set of parameters (chunk, context). We could build a Dust-friendly wrapper for every KO Observer, and build Dust contexts out of these, but that seems like an awful lot of unnecessary object creation.
+
+Instead, we just hack Dust to not evaluate Observers like it normally would, and handle the aftermath with a more stock standard helper-filter.
+
+# References #
+
+[1] http://akdubya.github.com/dustjs/
+[2] http://knockoutjs.com/
+[3] https://github.com/SteveSanderson/knockout/blob/master/src/templating/templateEngine.js
+
@@ -0,0 +1,90 @@
+// DUST utilities
+
+/**
+* helper dust function to run a template sychronously, without mucking with callbacks.
+* @params template the name of the dust template to be rendered
+* @params ctx the context to render with
+*/
+function _renderTemplate(template,ctx){
+ var result
+ dust.render(template,ctx,function(err,out){
+ if(err)
+ throw template+": "+err.message
+ result= out
+ })
+ return result
+}
+
+/**
+* cache of Function objects that the dust.helpers.eval uses.
+*/
+var _dustEvalCache= {}
+
+// DUST integration with knockout
+
+/**
+* an eval helper, for executing arbitrary javascript inside dust.
+*/
+var _dustEvalGlobal= function(chunk,ctx,bodies,params){
+ var code,
+ block= bodies&&bodies.block,
+ param= params&&params.src
+ if(block){
+ code= block(new dust.chunk(), ctx).data
+ }else if(params && params.src){
+ code= params.src
+ }
+
+ var val= eval(code)
+ //console.log("=DEVAL=",this,arguments,"|",code,"|",val)
+ chunk.write(val)
+}
+
+/**
+* a new filter, o, which will evaluate Knockout's observable objects.
+*/
+dust.filters.o= function(val){
+ if(!!val && typeof val == "function" && val.name == "observable")
+ return val()
+ return val
+}
+
+/**
+* override the default html-escaping filter with one which also evaluates observables.
+*/
+dust.filters.h= function(val){
+ return dust.escapeHtml(dust.filters.o(val))
+}
+
+
+// KNOCKOUT duster template engine
+
+ko.dusterTemplateEngine = function () { }
+ko.dusterTemplateEngine.prototype = ko.utils.extend(new ko.templateEngine(), {
+ renderTemplateSource: function (templateSource, bindingContext, options) {
+
+ var name= typeof options == "string" ? options : options.name,
+ template= dust.cache[name]
+ if(!template)
+ throw "template "+name+" not found"
+
+ var ctx= dust.makeBase({
+ eval: _dustEvalGlobal
+ })
+ ctx= ctx.push(bindingContext.$root)
+ for(var i in bindingContext.$parents){
+ ctx= ctx.push(bindingContet.$parents[i])
+ }
+ ctx= ctx.push(bindingContext.$data)
+ //console.log("=RTS=",this,templateSource,bindingContext,options,"|",name,ctx)
+
+ var render= _renderTemplate(name,ctx)
+ return ko.utils.parseHtmlFragment(render)
+ },
+ createJavaScriptEvaluatorBlock: function(script) {
+ //console.log("=EVAL=",this,script)
+ var escaped= script.replace("\"", "\\\"")
+ return "{#eval src="+script+"/}"
+ }
+});
+ko.setTemplateEngine(new ko.dusterTemplateEngine())
@@ -0,0 +1 @@
+https://github.com/akdubya/dustjs.git
@@ -0,0 +1 @@
+https://github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.debug.js
@@ -0,0 +1,19 @@
+{
+ "name": "duster-ko",
+ "description": "dust.js templating engine in knockout.js",
+ "version": "1.0.0",
+ "main": "duster-ko.js",
+ "keywords": ["templating","knockout","dust","knockout.js","dust.js"],
+ "maintainers": [{
+ "name": "Matthew Fowle",
+ "email": "fowle@socialtables.com",
+ "web": "http://socialtables.com"
+ }],
+ "homepage": "http://socialtables.com",
+ "implements": ["CommonJS/Modules/1.0"],
+ "engines": { "node": ">=0.6.0" },
+ "dependencies": {
+ "dust": ">= 0.3.0"
+ },
+ "repository": {"type": "git", "url": "http://git.socialtables.com/duster-ko.git"}
+}
@@ -0,0 +1,2 @@
+Hellloooooo, {name}! {#eval} 2 + {n} {/eval} {~n}
+Of course, {name}! {#eval src="2 + 4"/}
@@ -0,0 +1,21 @@
+(function(){
+ dust.register("helloworld",body_0);
+ function body_0(chk,ctx){
+ return chk
+ .write("Hellloooooo, ")
+ .reference(ctx.get("name"),ctx,"h")
+ .write("! ")
+ .section(ctx.get("eval"),ctx,{"block":body_1},null)
+ .write(" \nOf course, ")
+ .reference(ctx.get("name"),ctx,"h")
+ .write("! ")
+ .section(ctx.get("eval"),ctx,{},{"src":"2 + 4"});
+ }
+ function body_1(chk,ctx){
+ return chk
+ .write(" 2 + ")
+ .reference(ctx.get("n"),ctx,"h")
+ .write(" ");
+ }
+ return body_0;
+})();
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en"
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:xhtml="http://www.w3.org/1999/xhtml"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:st="http://socialtables.com">
+<head>
+<title>Duster Scratch Page</title>
+<script type="application/javascript" src="../lib/dust-0.3.0.js"/>
+<script type="application/javascript" src="../lib/knockout-2.1.0.js"/>
+<script type="application/javascript" src="../duster-ko.js"/>
+<script type="application/javascript" src="helloworld.dust.js" id="helloworld"/>
+</head>
+<body>
+ <h1>hi!</h1>
+ <div data-bind="template: 'helloworld'"/>
+ <script type="application/javascript">
+ var viewModel= {
+ name: ko.observable("world"),
+ n: ko.observable(3)
+ }
+ console.log("go!")
+ ko.applyBindings(viewModel)
+ </script>
+</body>
+</html>

0 comments on commit 7130ea1

Please sign in to comment.