made with requirebin
Created
June 11, 2014 11:52
-
-
Save batiste/6fa081fae01fbc2cc78e to your computer and use it in GitHub Desktop.
requirebin sketch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var likely = require("likely.js"); | |
var data = {list:[1, 2, 3]}; | |
var template = likely.Template([ | |
'for key, value in list', | |
' p', | |
' {{ value }}' | |
]); | |
var tree1 = template.tree(likely.Context(data)); | |
data.list[0] = 10; | |
data.list.push(20); | |
// data.list = [10, 2, 3, 20] | |
var tree2 = template.tree(likely.Context(data)); | |
var diff = tree1.diff(tree2) // computes the DOM diff between the 2 render tree | |
function censor(key, value) { | |
if(key == 'node'){ | |
return undefined | |
} | |
return value; | |
} | |
alert(JSON.stringify(diff, censor, 2)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require=function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){"use strict";var util=require("./util");var EXPRESSION_REG=/^{{(.+?)}}/;function StringValue(txt){this.type="value";if(txt[0]=='"'){this.value=txt.replace(/^"|"$/g,"")}else if(txt[0]=="'"){this.value=txt.replace(/^'|'$/g,"")}else{throw new util.CompileError("Invalid string value "+txt)}}StringValue.prototype.evaluate=function(context){return this.value};StringValue.reg=/^"(?:\\"|[^"])*"|^'(?:\\'|[^'])*'/;function EqualOperator(txt){this.type="operator";this.left=null;this.right=null}EqualOperator.prototype.evaluate=function(context){return this.left.evaluate(context)==this.right.evaluate(context)};EqualOperator.reg=/^==/;function NotEqualOperator(txt){this.type="operator";this.left=null;this.right=null}NotEqualOperator.prototype.evaluate=function(context){return this.left.evaluate(context)!=this.right.evaluate(context)};NotEqualOperator.reg=/^!=/;function BiggerOperator(txt){this.type="operator";this.left=null;this.right=null}BiggerOperator.prototype.evaluate=function(context){return this.left.evaluate(context)>this.right.evaluate(context)};BiggerOperator.reg=/^>/;function SmallerOperator(txt){this.type="operator";this.left=null;this.right=null;this.evaluate=function(context){return this.left.evaluate(context)<this.right.evaluate(context)}}SmallerOperator.prototype.evaluate=function(context){return this.left.evaluate(context)<this.right.evaluate(context)};SmallerOperator.reg=/^</;function OrOperator(txt){this.type="operator";this.left=null;this.right=null}OrOperator.prototype.evaluate=function(context){return this.left.evaluate(context)||this.right.evaluate(context)};OrOperator.reg=/^or/;function AndOperator(txt){this.type="operator";this.left=null;this.right=null}AndOperator.prototype.evaluate=function(context){return this.left.evaluate(context)&&this.right.evaluate(context)};AndOperator.reg=/^and/;function Name(txt){this.type="value";this.name=txt}Name.prototype.evaluate=function(context){var value=context.get(this.name);return value};Name.reg=/^[A-Za-z][\w\.]{0,}/;function Filter(txt){this.type="operator";this.left=null;this.right=null}Filter.prototype.evaluate=function(context){var fct=context.get(this.right.name);return fct.apply(this,[this.left.evaluate(context),context])};Filter.reg=/^\|/;function MultiplyOperator(txt){this.type="operator";this.left=null;this.right=null}MultiplyOperator.prototype.evaluate=function(context){return this.left.evaluate(context)*this.right.evaluate(context)};MultiplyOperator.reg=/^\*/;function PlusOperator(txt){this.type="operator";this.left=null;this.right=null}PlusOperator.prototype.evaluate=function(context){return this.left.evaluate(context)+this.right.evaluate(context)};PlusOperator.reg=/^\+/;function MinusOperator(txt){this.type="operator";this.left=null;this.right=null}MinusOperator.prototype.evaluate=function(context){return this.left.evaluate(context)-this.right.evaluate(context)};MinusOperator.reg=/^\-/;function FunctionCall(txt){this.type="value";var m=txt.match(/^([a-zA-Z][a-zA-Z0-9\.]*)\(([^\)]*)\)/);this.funcName=m[1];this.params=m[2].split(",")}FunctionCall.prototype.evaluate=function(context){var func=context.get(this.funcName),i,params=[];for(i=0;i<this.params.length;i++){params.push(context.get(util.trim(this.params[i])))}return func.apply(context,params)};FunctionCall.reg=/^[a-zA-Z][a-zA-Z0-9\.]*\([^\)]*\)/;function NumberValue(txt){this.type="value";this.number=parseFloat(txt,10);this.evaluate=function(context){return this.number}}NumberValue.reg=/^[0-9]+/;function IfOperator(txt){this.type="operator";this.left=null;this.right=null}IfOperator.prototype.evaluate=function(context){var rv=this.right.evaluate(context);if(rv){return this.left.evaluate(context)}return rv};IfOperator.reg=/^if /;function InOperator(txt){this.type="operator";this.left=null;this.right=null}InOperator.prototype.evaluate=function(context){var left=this.left.evaluate(context);var right=this.right.evaluate(context);if(right===undefined){throw new util.RuntimeError("right side of in operator cannot be undefined")}if(right.indexOf){return right.indexOf(left)!=-1}else{return right.hasOwnProperty(left)}};InOperator.reg=/^in /;function NotOperator(txt){this.type="unary";this.right=null}NotOperator.prototype.evaluate=function(context){return!this.right.evaluate(context)};NotOperator.reg=/^not /;function compileTextAndExpressions(txt){var expr,around;var list=[];while(true){var match=/{{(.+?)}}/.exec(txt);if(!match){if(txt){list.push(txt)}break}expr=build(match[1]);around=txt.split(match[0],2);if(around[0].length){list.push(around[0])}list.push(expr);txt=around[1]}return list}function evaluateExpressionList(expressions,context){var str="",i;for(i=0;i<expressions.length;i++){var param=expressions[i];if(param.evaluate){str+=param.evaluate(context)}else{str+=param}}return str}var expression_list=[MultiplyOperator,PlusOperator,MinusOperator,BiggerOperator,SmallerOperator,EqualOperator,NotEqualOperator,Filter,NotOperator,IfOperator,InOperator,OrOperator,AndOperator,StringValue,NumberValue,FunctionCall,Name];function build(input){return buildExpressions(parseExpressions(input))}function parseExpressions(input){var currentExpr=null,i,expr,match,found,parsed=[];while(input){input=util.trim(input);found=false;for(i=0;i<expression_list.length;i++){expr=expression_list[i];match=expr.reg.exec(input);if(match){input=input.slice(match[0].length);parsed.push(new expr(match[0],currentExpr));found=true;i=0}}if(found===false){throw new util.CompileError("Expression parser: Impossible to parse further : "+input)}}return parsed}function buildExpressions(list){var i,j,expr;for(i=0;i<expression_list.length;i++){for(j=0;j<list.length;j++){if(list.length==1){return list[0]}expr=list[j];if(expr instanceof expression_list[i]){if(expr.type=="operator"){expr.left=list[j-1];expr.right=list[j+1];list.splice(j-1,2);list[j-1]=expr;j=j-1}if(expr.type=="unary"){expr.right=list[j+1];list.splice(j+1,1)}if(expr.type=="value"){throw new util.CompileError("Expression builder: expected an operator but got "+expr.constructor.name)}}}}if(list.length==1){return list[0]}else{throw new util.CompileError("Expression builder: incorrect expression construction "+list)}}module.exports={build:build,compileTextAndExpressions:compileTextAndExpressions,buildExpressions:buildExpressions,parseExpressions:parseExpressions,evaluateExpressionList:evaluateExpressionList,StringValue:StringValue,Name:Name,EXPRESSION_REG:EXPRESSION_REG}},{"./util":6}],"07ZQBr":[function(require,module,exports){"use strict";var util=require("./util");var render=require("./render");var expression=require("./expression");var template=require("./template");function updateData(context,dom){var name=dom.getAttribute("lk-bind"),value;if(!name){throw"No lk-bind attribute on the element"}if(dom.type=="checkbox"&&!dom.checked){value=""}else{value=dom.value}context.modify(name,value)}function Binding(dom,tpl,data){this.dom=dom;this.data=data;this.context=new template.Context(this.data);this.template=tpl;this.init()}Binding.prototype.tree=function(){return this.template.tree(new template.Context(this.data))};Binding.prototype.init=function(){this.dom.innerHTML="";this.currentTree=this.tree();this.currentTree.domTree(this.dom);this.bindEvents()};Binding.prototype.diff=function(){var newTree=this.tree();var diff=this.currentTree.diff(newTree);render.applyDiff(diff,this.dom);this.currentTree=newTree;this.lock=false};Binding.prototype.dataEvent=function(e){var dom=e.target;var name=dom.getAttribute("lk-bind");if(name){var renderNode=this.getRenderNodeFromPath(dom);updateData(renderNode.context,dom);if(!this.lock){this.lock=true;this.diff()}var event=new CustomEvent("dataViewChanged",{name:name});this.dom.dispatchEvent(event)}};Binding.prototype.getRenderNodeFromPath=function(dom){var path=dom.getAttribute("lk-path");var renderNode=this.currentTree;var bits=path.split("."),i;for(i=1;i<bits.length;i++){renderNode=renderNode.children[bits[i]]}return renderNode};Binding.prototype.anyEvent=function(e){var dom=e.target;var lkEvent=dom.getAttribute("lk-"+e.type);if(!lkEvent){return}var renderNode=this.getRenderNodeFromPath(dom);renderNode.node.attrs["lk-"+e.type].evaluate(renderNode.context)};Binding.prototype.bindEvents=function(){var i;this.dom.addEventListener("keyup",function(e){this.dataEvent(e)}.bind(this),false);this.dom.addEventListener("change",function(e){this.dataEvent(e)}.bind(this),false);var events="click,change,mouseover,focus,keydown,keyup,keypress,submit,blur".split(",");for(i=0;i<events.length;i++){this.dom.addEventListener(events[i],function(e){this.anyEvent(e)}.bind(this),false)}};Binding.prototype.update=function(){this.diff()};function Component(name,tpl,controller){if(this.constructor!==Component){return new Component(name,tpl,controller)}if(template.componentCache[name]){util.CompileError("Component with name "+name+" already exist")}this.name=name;this.template=tpl;this.controller=controller;template.componentCache[name]=this}module.exports={Template:template.buildTemplate,ContextName:template.ContextName,updateData:updateData,Binding:Binding,Component:Component,getDom:render.getDom,componentCache:template.componentCache,parseExpressions:expression.parseExpressions,compileTextAndExpressions:expression.compileTextAndExpressions,buildExpressions:expression.buildExpressions,expressions:{StringValue:expression.StringValue},applyDiff:render.applyDiff,diffCost:render.diffCost,parseAttributes:template.parseAttributes,attributesDiff:render.attributesDiff,Context:template.Context,CompileError:util.CompileError,RuntimeError:util.RuntimeError,escape:util.escape,expression:expression,setHandicap:function(n){render.handicap=n}}},{"./expression":1,"./render":4,"./template":5,"./util":6}],"likely.js":[function(require,module,exports){module.exports=require("07ZQBr")},{}],4:[function(require,module,exports){"use strict";function RenderedNode(node,context,renderer,path){this.children=[];this.node=node;this.context=context;this.renderer=renderer;this.path=path||"";this.nodeName=node.nodeName}RenderedNode.prototype.repr=function(level){var str="",i;if(level===undefined){level=0}for(i=0;i<level;i++){str+=" "}str+=String(this.node)+" path "+this.path+"\r\n";for(i=0;i<this.children.length;i++){str+=this.children[i].repr(level+1)}return str};RenderedNode.prototype.domTree=function(append_to){var node=append_to||this.node.domNode(this.context,this.path),i,child_tree;for(i=0;i<this.children.length;i++){child_tree=this.children[i].domTree();if(node.push){node.push(child_tree)}else{node.appendChild(child_tree)}}return node};RenderedNode.prototype.domHtml=function(){var i;var d=document.createElement("div");for(i=0;i<this.children.length;i++){var child=this.children[i].domTree();d.appendChild(child)}return d.innerHTML};function diffCost(diff){var value=0,i;for(i=0;i<diff.length;i++){if(diff[i].action=="remove"){value+=5}if(diff[i].action=="add"){value+=2}if(diff[i].action=="mutate"){value+=1}if(diff[i].action=="stringmutate"){value+=1}}return value}RenderedNode.prototype._diff=function(rendered_node,accu,path){var i,j,source_pt=0;if(path===undefined){path=""}if(!rendered_node){accu.push({action:"remove",node:this,path:path});return accu}if(rendered_node.node.nodeName!=this.node.nodeName){accu.push({action:"remove",node:this,path:path});accu.push({action:"add",node:rendered_node,path:path});return accu}if(this.nodeName=="string"&&this.renderer!=rendered_node.renderer){accu.push({action:"stringmutate",node:this,value:rendered_node.renderer,path:path});return accu}else{var a_diff=attributesDiff(this.attrs,rendered_node.attrs);if(a_diff.length){accu.push({action:"mutate",node:this,attributesDiff:a_diff,path:path})}}var l1=this.children.length;var l2=rendered_node.children.length;j=0;i=0;source_pt=0;for(;i<l1;i++){var diff=0,after_source_diff=0,after_target_diff=0,after_source_cost=null,after_target_cost=null;var after_target=rendered_node.children[j+1];var after_source=this.children[i+1];if(!rendered_node.children[j]){accu.push({action:"remove",node:this.children[i],path:path+"."+source_pt});continue}diff=this.children[i]._diff(rendered_node.children[j],[],path+"."+source_pt);var cost=diffCost(diff);if(after_source){after_source_diff=after_source._diff(rendered_node.children[j],[],path+"."+source_pt);after_source_cost=diffCost(after_source_diff)+module.exports.handicap}if(after_target){after_target_diff=this.children[i]._diff(after_target,[],path+"."+source_pt);after_target_cost=diffCost(after_target_diff)+module.exports.handicap}if((!after_target||cost<=after_target_cost)&&(!after_source||cost<=after_source_cost)){accu=accu.concat(diff);source_pt+=1}else if(after_source&&(!after_target||after_source_cost<=after_target_cost)){accu.push({type:"after_source",action:"remove",node:this.children[i],path:path+"."+source_pt});accu=accu.concat(after_source_diff);source_pt+=1;i++}else if(after_target){accu=accu.concat(after_target_diff);accu.push({type:"after_target",action:"add",node:rendered_node.children[j],path:path+"."+source_pt});source_pt+=2;j++}else{throw"Should never happen"}j++}for(i=0;i<l2-j;i++){accu.push({action:"add",node:rendered_node.children[j+i],path:path+"."+(source_pt+1)});source_pt+=1}return accu};RenderedNode.prototype.diff=function(rendered_node){var accu=[];return this._diff(rendered_node,accu)};function attributesDiff(a,b){var changes=[],key;for(key in a){if(b[key]===false){changes.push({action:"remove",key:key})}else if(b[key]!==undefined){if(b[key]!=a[key]){changes.push({action:"mutate",key:key,value:b[key]})}}else{changes.push({action:"remove",key:key})}}for(key in b){if(a[key]===undefined){changes.push({action:"add",key:key,value:b[key]})}}return changes}function getDom(dom,path,stop){var i,p=path.split("."),d=dom;if(stop===undefined){stop=0}for(i=0;i<p.length-stop;i++){if(p[i]){d=d.childNodes[parseInt(p[i],10)]}}return d}function applyDiff(diff,dom){var i,j,_diff,_dom,parent;for(i=0;i<diff.length;i++){_diff=diff[i];_dom=getDom(dom,_diff.path);if(_diff.action=="remove"){_dom.parentNode.removeChild(_dom)}if(_diff.action=="add"){var newNode=_diff.node.domTree();if(_dom){_dom.parentNode.insertBefore(newNode,_dom)}else{parent=getDom(dom,_diff.path,1);parent.appendChild(newNode)}}if(_diff.action=="mutate"){for(j=0;j<_diff.attributesDiff.length;j++){var a_diff=_diff.attributesDiff[j];if(a_diff.action=="mutate"){if("value,selected,checked".indexOf(a_diff.key)!=-1){if(_dom[a_diff.key]!=a_diff.value){_dom[a_diff.key]=a_diff.value}}_dom.setAttribute(a_diff.key,a_diff.value)}if(a_diff.action=="remove"){if("checked,selected".indexOf(a_diff.key)!=-1){_dom[a_diff.key]=false}_dom.removeAttribute(a_diff.key)}if(a_diff.action=="add"){if("checked,selected".indexOf(a_diff.key)!=-1){_dom[a_diff.key]=a_diff.value}_dom.setAttribute(a_diff.key,a_diff.value)}}}if(_diff.action=="stringmutate"){_dom.nodeValue=_diff.value}}}module.exports={RenderedNode:RenderedNode,applyDiff:applyDiff,attributesDiff:attributesDiff,diffCost:diffCost,getDom:getDom,handicap:1}},{}],5:[function(require,module,exports){"use strict";var util=require("./util");var render=require("./render");var expression=require("./expression");var templateCache={};var componentCache={};var VARNAME_REG=/^[a-zA-Z_$][0-9a-zA-Z_$]*/;var HTML_ATTR_REG=/^[A-Za-z][\w-]{0,}/;var DOUBLE_QUOTED_STRING_REG=/^"(\\"|[^"])*"/;function ContextName(name){this.bits=name.split(".")}ContextName.prototype.substituteAlias=function(context){if(context.aliases.hasOwnProperty(this.bits[0])){var newBits=context.aliases[this.bits[0]].split(".");this.bits.shift();this.bits=newBits.concat(this.bits)}};ContextName.prototype.start=function(){return this.bits[0]};ContextName.prototype.str=function(){return this.bits.join(".")};function Context(data,parent){if(this.constructor!==Context){return new Context(data,parent)}this.data=data;this.parent=parent;this.aliases={};this.watching={}}Context.prototype.addAlias=function(sourceName,aliasName){if(sourceName===aliasName){throw new util.CompileError("Alias with the name "+aliasName+" already present in this context.")}this.aliases[aliasName]=sourceName};Context.prototype.resolveName=function(name){name.substituteAlias(this);if(this.data.hasOwnProperty(name.start())){var value=this.data[name.start()];var i=1;while(i<name.bits.length){if(!value.hasOwnProperty(name.bits[i])){return undefined}value=value[name.bits[i]];i++}return[this,name.str(),value]}if(this.parent){return this.parent.resolveName(name)}};Context.prototype.getNamePath=function(name){var resolved=this.resolveName(new ContextName(name));if(resolved){return resolved[1]}};Context.prototype.watch=function(name,callback){this.watching[name]=callback};Context.prototype.get=function(name){var resolved=this.resolveName(new ContextName(name));if(resolved){return resolved[2]}};Context.prototype.modify=function(name,value){this._modify(new ContextName(name),value)};Context.prototype._modify=function(name,value){if(this.watching.hasOwnProperty(name.str())){this.watching[name.str()](value)}name.substituteAlias(this);if(this.data.hasOwnProperty(name.start())){var data=this.data;var i=0;while(i<name.bits.length-1){if(!data.hasOwnProperty(name.bits[i])){return undefined}data=data[name.bits[i]];i++}data[name.bits[i]]=value;return true}if(this.parent){return this.parent._modify(name,value)}};Context.prototype.set=function(name,value){this.data[name]=value};function parseAttributes(v,node){var attrs={},n,s;while(v){v=util.trim(v);n=v.match(HTML_ATTR_REG);if(!n){node.cerror("parseAttributes: No attribute name found in "+v)}v=v.substr(n[0].length);n=n[0];if(v[0]!="="){node.cerror("parseAttributes: No equal sign after name "+n)}v=v.substr(1);s=v.match(DOUBLE_QUOTED_STRING_REG);if(s){attrs[n]=new StringNode(null,s[0])}else{s=v.match(expression.EXPRESSION_REG);if(s===null){node.cerror("parseAttributes: No string or expression found after name "+n)}else{var expr=expression.build(s[1]);attrs[n]=expr}}v=v.substr(s[0].length)}return attrs}function Node(parent,content,level,line){this.line=line;this.parent=parent;this.content=content;this.level=level;this.children=[]}Node.prototype.repr=function(level){var str="",i;if(level===undefined){level=0}for(i=0;i<level;i++){str+=" "}str+=String(this)+"\r\n";for(i=0;i<this.children.length;i++){str+=this.children[i].repr(level+1)}return str};Node.prototype.tree=function(context,path,pos){if(path===undefined){path="";pos=0;this.isRoot=true}var t=new render.RenderedNode(this,context,"",path);t.children=this.treeChildren(context,path,pos);return t};Node.prototype.cerror=function(msg){throw new util.CompileError(this.toString()+": "+msg)};Node.prototype.domNode=function(){return[]};Node.prototype.treeChildren=function(context,path,pos){var t=[],i,p,j,children=null,child=null;j=pos;for(i=0;i<this.children.length;i++){p=path;child=this.children[i];if(child.hasOwnProperty("nodeName")){p+="."+j;j++;children=child.tree(context,p,0);t.push(children)}else if(!child.renderExlcuded){children=child.tree(context,p,j);if(children){t=t.concat(children);j+=children.length}}}return t};Node.prototype.addChild=function(child){this.children.push(child)};Node.prototype.toString=function(){return this.constructor.name+"("+this.content.replace("\n","")+") at line "+this.line};function CommentNode(parent,content,level,line){Node.call(this,parent,content,level,line);parent.children.push(this);this.renderExlcuded=true}util.inherits(CommentNode,Node);function HtmlNode(parent,content,level,line){Node.call(this,parent,content,level,line);this.nodeName=this.content.split(" ")[0];this.attrs=parseAttributes(this.content.substr(this.nodeName.length),this);parent.addChild(this)}util.inherits(HtmlNode,Node);HtmlNode.prototype.tree=function(context,path,pos){var t=new render.RenderedNode(this,context,this.domNode(context,path),path);t.attrs=this.renderAttributes(context,path);t.children=this.treeChildren(context,path,pos);return t};function bindingName(node){if(node instanceof expression.Name){return node.name}if(node instanceof StringNode&&node.compiledExpression.length==1&&node.compiledExpression[0]instanceof expression.Name){return node.compiledExpression[0].name}}HtmlNode.prototype.renderAttributes=function(context,path){var r_attrs={},key,attr,name;for(key in this.attrs){attr=this.attrs[key];if(key.indexOf("lk-")===0){r_attrs["lk-path"]=path;if(key==="lk-bind"){r_attrs[key]=attr.evaluate(context)}else{r_attrs[key]="true"}continue}if(attr.evaluate){var v=attr.evaluate(context);if(v===false){}else{r_attrs[key]=v}}else{r_attrs[key]=attr}}if("input,select,textarea".indexOf(this.nodeName)!=-1&&this.attrs.hasOwnProperty("value")){attr=this.attrs.value;name=bindingName(attr);if(name&&this.attrs["lk-bind"]===undefined){r_attrs["lk-bind"]=name;r_attrs["lk-path"]=path}}if(this.nodeName=="textarea"&&this.children.length==1){name=bindingName(this.children[0].expression);if(name&&this.attrs["lk-bind"]===undefined){r_attrs["lk-bind"]=name;r_attrs["lk-path"]=path;r_attrs.value=this.children[0].expression.evaluate(context)}}return r_attrs};HtmlNode.prototype.domNode=function(context,path){var node=document.createElement(this.nodeName),key,attrs=this.renderAttributes(context,path);for(key in attrs){node.setAttribute(key,attrs[key])}return node};function ForNode(parent,content,level,line){Node.call(this,parent,content,level,line);var var1,var2,sourceName;content=util.trim(content.substr(4));var1=content.match(VARNAME_REG);if(!var1){this.cerror("first variable name is missing")}content=util.trim(content.substr(var1[0].length));if(content[0]==","){content=util.trim(content.substr(1));var2=content.match(VARNAME_REG);if(!var2){this.cerror("second variable after comma is missing")}content=util.trim(content.substr(var2[0].length))}if(!content.match(/^in/)){this.cerror("in keyword is missing")}content=util.trim(content.substr(2));sourceName=content.match(expression.Name.reg);if(!sourceName){this.cerror("iterable name is missing")}this.sourceName=sourceName[0];content=util.trim(content.substr(sourceName[0].length));if(content!==""){this.cerror("left over unparsable content: "+content)}if(var1&&var2){this.indexName=var1;this.alias=var2[0]}else{this.alias=var1[0]}parent.addChild(this)}util.inherits(ForNode,Node);ForNode.prototype.tree=function(context,path,pos){var t=[],key;var d=context.get(this.sourceName);for(key in d){var new_data={};if(this.indexName){new_data[this.indexName]=key}var new_context=new Context(new_data,context);new_context.addAlias(this.sourceName+"."+key,this.alias);t=t.concat(this.treeChildren(new_context,path,t.length+pos))}return t};function IfNode(parent,content,level,line){Node.call(this,parent,content,level,line);this.expression=expression.build(content.replace(/^if/g,""));parent.children.push(this)}util.inherits(IfNode,Node);IfNode.prototype.tree=function(context,path,pos){if(!this.expression.evaluate(context)){if(this.else){return this.else.tree(context,path,pos)}return}return this.treeChildren(context,path,pos)};function ElseNode(parent,content,level,line,currentNode){Node.call(this,parent,content,level,line);this.searchIf(currentNode)}util.inherits(ElseNode,Node);ElseNode.prototype.tree=function(context,path,pos){return this.treeChildren(context,path,pos)};function IfElseNode(parent,content,level,line,currentNode){Node.call(this,parent,content,level,line);this.expression=expression.build(content.replace(/^elseif/g,""));this.searchIf(currentNode)}util.inherits(IfElseNode,IfNode);IfElseNode.prototype.searchIf=function searchIf(currentNode){while(currentNode){if(currentNode.level<this.level){this.cerror("cannot find a corresponding if-like statement at the same level.")}if(currentNode.level==this.level){if(!(currentNode instanceof IfNode)){this.cerror("at the same level is not a if-like statement.")}currentNode.else=this;break}currentNode=currentNode.parent}};ElseNode.prototype.searchIf=IfElseNode.prototype.searchIf;function ExpressionNode(parent,content,level,line){Node.call(this,parent,content,level,line);this.nodeName="string";var m=content.match(expression.EXPRESSION_REG);if(!m){this.cerror("declared improperly")}this.expression=expression.build(m[1]);parent.addChild(this)}util.inherits(ExpressionNode,Node);ExpressionNode.prototype.tree=function(context,path){var renderer=String(this.expression.evaluate(context));var t=new render.RenderedNode(this,context,renderer,path);return t};ExpressionNode.prototype.domNode=function(context){return document.createTextNode(this.expression.evaluate(context))};function StringNode(parent,content,level,line){Node.call(this,parent,content,level,line);this.nodeName="string";this.string=this.content.replace(/^"|"$/g,"").replace(/\\"/g,'"',"gm");this.compiledExpression=expression.compileTextAndExpressions(this.string);if(parent){parent.addChild(this)}}util.inherits(StringNode,Node);StringNode.prototype.tree=function(context,path){var renderer=expression.evaluateExpressionList(this.compiledExpression,context);var t=new render.RenderedNode(this,context,renderer,path);return t};StringNode.prototype.evaluate=function(context){return expression.evaluateExpressionList(this.compiledExpression,context)};StringNode.prototype.domNode=function(context){return document.createTextNode(expression.evaluateExpressionList(this.compiledExpression,context))};StringNode.prototype.addChild=function(child){this.cerror("cannot have children")};function IncludeNode(parent,content,level,line){Node.call(this,parent,content,level,line);this.name=util.trim(content.split(" ")[1]);this.template=templateCache[this.name];if(this.template===undefined){this.cerror("Template with name "+this.name+" is not registered")}parent.addChild(this)}util.inherits(IncludeNode,Node);IncludeNode.prototype.tree=function(context,path,pos){return this.template.treeChildren(context,path,pos)};function ComponentNode(parent,content,level,line){Node.call(this,parent,content,level,line);content=util.trim(content).substr(10);var name=content.match(VARNAME_REG);if(!name){this.cerror("Component name is missing")}content=util.trim(content.substr(name[0].length));this.name=name[0];this.attrs=parseAttributes(content,this);this.component=componentCache[this.name];if(this.component===undefined){this.cerror("Component with name "+this.name+" is not registered")}parent.addChild(this)}util.inherits(ComponentNode,Node);ComponentNode.prototype.tree=function(context,path,pos){var new_context=new Context({},context);var key,attr,value,source;for(key in this.attrs){attr=this.attrs[key];if(attr.evaluate){value=attr.evaluate(context);if(value===false){}else{new_context.set(key,value);source=bindingName(attr);if(source&&key!=source){new_context.addAlias(source,key)}}}else{}}if(this.component.controller){this.component.controller(new_context)}return this.component.template.treeChildren(new_context,path,pos)};ComponentNode.prototype.repr=function(level){return this.component.template.repr(level+1)};function createNode(parent,content,level,line,currentNode){var node;if(content.length===0){node=new StringNode(parent,"\n",level,line+1)}else if(content.indexOf("#")===0){node=new CommentNode(parent,content,level,line+1)}else if(content.indexOf("if ")===0){node=new IfNode(parent,content,level,line+1)}else if(content.indexOf("elseif ")===0){node=new IfElseNode(parent,content,level,line+1,currentNode)}else if(content.indexOf("else")===0){node=new ElseNode(parent,content,level,line+1,currentNode)}else if(content.indexOf("for ")===0){node=new ForNode(parent,content,level,line+1)}else if(content.indexOf("include ")===0){node=new IncludeNode(parent,content,level,line+1)}else if(content.indexOf("component ")===0){node=new ComponentNode(parent,content,level,line+1)}else if(content.indexOf('"')===0){node=new StringNode(parent,content,level,line+1)}else if(/^\w/.exec(content)){node=new HtmlNode(parent,content,level,line+1)}else if(content.indexOf("{{")===0){node=new ExpressionNode(parent,content,level,line+1)}else{throw new util.CompileError("createNode: unknow node type "+content)}return node}function buildTemplate(tpl,templateName){if(typeof tpl=="object"){tpl=tpl.join("\n")}var root=new Node(null,"",0),lines,line,level,content,i,currentNode=root,parent,searchNode;lines=tpl.split("\n");for(i=0;i<lines.length;i++){line=lines[i];level=line.match(/\s*/)[0].length+1;content=line.slice(level-1);var j=0;while(content.match(/\\$/)){j++;content=content.replace(/\\$/,"")+lines[i+j]}i=i+j;j=0;if(content.match(/^"""/)){content=content.replace(/^"""/,'"');while(!content.match(/"""$/)){j++;if(i+j>lines.length){throw new util.CompileError("Multiline string started but unfinished at line "+(i+1))}content=content+lines[i+j]}content=content.replace(/"""$/,'"')}i=i+j;searchNode=currentNode;parent=null;while(true){if(level>searchNode.level){parent=searchNode;break}if(!searchNode.parent){throw new util.CompileError("Indentation error at line "+(i+1))}if(level==searchNode.level){parent=searchNode.parent;break}searchNode=searchNode.parent}if(parent.children.length){if(parent.children[0].level!=level){throw new util.CompileError("Indentation error at line "+(i+1))}}var node=createNode(parent,content,level,i,currentNode);currentNode=node}if(templateName){templateCache[templateName]=root}return root}module.exports={buildTemplate:buildTemplate,parseAttributes:parseAttributes,Context:Context,templateCache:templateCache,componentCache:componentCache,ContextName:ContextName}},{"./expression":1,"./render":4,"./util":6}],6:[function(require,module,exports){"use strict";function inherits(child,parent){child.prototype=Object.create(parent.prototype);child.prototype.constructor=child}function CompileError(msg){this.name="CompileError";this.message=msg||""}CompileError.prototype=Error.prototype;function RuntimeError(msg){this.name="RuntimeError";this.message=msg||""}RuntimeError.prototype=Error.prototype;function escape(unsafe){return unsafe.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function trim(txt){return txt.replace(/^\s+|\s+$/g,"")}module.exports={inherits:inherits,CompileError:CompileError,RuntimeError:RuntimeError,escape:escape,trim:trim}},{}]},{},[]);var likely=require("likely.js");var data={list:[1,2,3]};var template=likely.Template(["for key, value in list"," p"," {{ value }}"]);var tree1=template.tree(likely.Context(data));data.list[0]=10;data.list.push(20);var tree2=template.tree(likely.Context(data));var diff=tree1.diff(tree2);function censor(key,value){if(key=="node"){return undefined}return value}alert(JSON.stringify(diff,censor,2)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "requirebin-sketch", | |
"version": "1.0.0", | |
"dependencies": { | |
"likely.js": "0.9.2" | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<style type='text/css'>html, body { margin: 0; padding: 0; border: 0; } | |
body, html { height: 100%; width: 100%; }</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment