diff --git a/gun.js b/gun.js index 0e8e5508..e01b93ce 100644 --- a/gun.js +++ b/gun.js @@ -264,11 +264,11 @@ || num_is(v)){ // by "number" we mean integers or decimals. return true; // simple values are valid. } - return Val.rel.is(v) || false; // is the value a soul relation? Then it is valid and return it. If not, everything else remaining is an invalid data type. Custom extensions can be built on top of these primitives to support other types. + return Val.link.is(v) || false; // is the value a soul relation? Then it is valid and return it. If not, everything else remaining is an invalid data type. Custom extensions can be built on top of these primitives to support other types. } Val.link = Val.rel = {_: '#'}; ;(function(){ - Val.rel.is = function(v){ // this defines whether an object is a soul relation or not, they look like this: {'#': 'UUID'} + Val.link.is = function(v){ // this defines whether an object is a soul relation or not, they look like this: {'#': 'UUID'} if(v && v[rel_] && !v._ && obj_is(v)){ // must be an object. var o = {}; obj_map(v, map, o); @@ -287,7 +287,7 @@ } } }()); - Val.rel.ify = function(t){ return obj_put({}, rel_, t) } // convert a soul into a relation and return it. + Val.link.ify = function(t){ return obj_put({}, rel_, t) } // convert a soul into a relation and return it. Type.obj.has._ = '.'; var rel_ = Val.link._, u; var bi_is = Type.bi.is; @@ -473,7 +473,7 @@ env.map = env; } if(env.soul){ - at.rel = Val.rel.ify(env.soul); + at.link = Val.link.ify(env.soul); } env.shell = (as||{}).shell; env.graph = env.graph || {}; @@ -488,16 +488,16 @@ at.env = env; at.soul = soul; if(Node.ify(at.obj, map, at)){ - at.rel = at.rel || Val.rel.ify(Node.soul(at.node)); + at.link = at.link || Val.link.ify(Node.soul(at.node)); if(at.obj !== env.shell){ - env.graph[Val.rel.is(at.rel)] = at.node; + env.graph[Val.link.is(at.link)] = at.node; } } return at; } function map(v,k,n){ var at = this, env = at.env, is, tmp; - if(Node._ === k && obj_has(v,Val.rel._)){ + if(Node._ === k && obj_has(v,Val.link._)){ return n._; // TODO: Bug? } if(!(is = valid(v,k,n, at,env))){ return } @@ -506,8 +506,8 @@ if(obj_has(v, Node._) && Node.soul(v)){ // ? for safety ? at.node._ = obj_copy(v._); } - at.node = Node.soul.ify(at.node, Val.rel.is(at.rel)); - at.rel = at.rel || Val.rel.ify(Node.soul(at.node)); + at.node = Node.soul.ify(at.node, Val.link.is(at.link)); + at.link = at.link || Val.link.ify(Node.soul(at.node)); } if(tmp = env.map){ tmp.call(env.as || {}, v,k,n, at); @@ -526,14 +526,14 @@ } tmp = node(env, {obj: v, path: at.path.concat(k)}); if(!tmp.node){ return } - return tmp.rel; //{'#': Node.soul(tmp.node)}; + return tmp.link; //{'#': Node.soul(tmp.node)}; } function soul(id){ var at = this; - var prev = Val.link.is(at.rel), graph = at.env.graph; - at.rel = at.rel || Val.rel.ify(id); - at.rel[Val.rel._] = id; + var prev = Val.link.is(at.link), graph = at.env.graph; + at.link = at.link || Val.link.ify(id); + at.link[Val.link._] = id; if(at.node && at.node[Node._]){ - at.node[Node._][Val.rel._] = id; + at.node[Node._][Val.link._] = id; } if(obj_has(graph, prev)){ graph[id] = graph[prev]; @@ -573,13 +573,13 @@ } function map(v,k){ var tmp, obj; if(Node._ === k){ - if(obj_empty(v, Val.rel._)){ + if(obj_empty(v, Val.link._)){ return; } this.obj[k] = obj_copy(v); return; } - if(!(tmp = Val.rel.is(v))){ + if(!(tmp = Val.link.is(v))){ this.obj[k] = v; return; } @@ -871,7 +871,7 @@ var list_is = Gun.list.is; var text = Gun.text, text_is = text.is, text_rand = text.random; var obj = Gun.obj, obj_is = obj.is, obj_has = obj.has, obj_to = obj.to, obj_map = obj.map, obj_copy = obj.copy; - var state_lex = Gun.state.lex, _soul = Gun.val.rel._, _has = '.', node_ = Gun.node._, rel_is = Gun.val.link.is; + var state_lex = Gun.state.lex, _soul = Gun.val.link._, _has = '.', node_ = Gun.node._, rel_is = Gun.val.link.is; var empty = {}, u; console.debug = function(i, s){ return (console.debug.i && i === console.debug.i && console.debug.i++) && (console.log.apply(console, arguments) || s) }; @@ -1133,11 +1133,11 @@ if(!(at = next[key])){ return; } - //if(data && data[_soul] && (tmp = Gun.val.rel.is(data)) && (tmp = (cat.root.$.get(tmp)._)) && obj_has(tmp, 'put')){ + //if(data && data[_soul] && (tmp = Gun.val.link.is(data)) && (tmp = (cat.root.$.get(tmp)._)) && obj_has(tmp, 'put')){ // data = tmp.put; //} if(at.has){ - //if(!(data && data[_soul] && Gun.val.rel.is(data) === Gun.node.soul(at.put))){ + //if(!(data && data[_soul] && Gun.val.link.is(data) === Gun.node.soul(at.put))){ if(u === at.put || !Gun.val.link.is(data)){ at.put = data; } @@ -1222,7 +1222,7 @@ var empty = {}, u; var obj = Gun.obj, obj_has = obj.has, obj_put = obj.put, obj_del = obj.del, obj_to = obj.to, obj_map = obj.map; var text_rand = Gun.text.random; - var _soul = Gun.val.rel._, node_ = Gun.node._; + var _soul = Gun.val.link._, node_ = Gun.node._; })(USE, './chain'); ;USE(function(module){ @@ -1395,7 +1395,7 @@ if(!soul && Gun.val.is(msg.put)){ return Gun.log("The reference you are saving is a", typeof msg.put, '"'+ msg.put +'", not a node (object)!'); } - gun.put(Gun.val.rel.ify(soul), cb, as); + gun.put(Gun.val.link.ify(soul), cb, as); }, true); return gun; } @@ -1495,7 +1495,7 @@ function soul(id, as, msg, eve){ var as = as.as, cat = as.at; as = as.as; var at = ((msg || {}).$ || {})._ || {}; - id = at.dub = at.dub || id || Gun.node.soul(cat.obj) || Gun.node.soul(msg.put || at.put) || Gun.val.rel.is(msg.put || at.put) || (as.via.back('opt.uuid') || Gun.text.random)(); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous? + id = at.dub = at.dub || id || Gun.node.soul(cat.obj) || Gun.node.soul(msg.put || at.put) || Gun.val.link.is(msg.put || at.put) || (as.via.back('opt.uuid') || Gun.text.random)(); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous? if(eve){ eve.stun = true } if(!id){ // polyfill async uuid for SEA at.via.back('opt.uuid')(function(err, id){ // TODO: improve perf without anonymous callback diff --git a/lib/normalize.js b/lib/normalize.js index 9abe21f6..871ec6cf 100644 --- a/lib/normalize.js +++ b/lib/normalize.js @@ -1,138 +1,284 @@ -;(function(){ - function normalize(opt){ - var el = $(this); - opt = opt || $.extend(true, normalize.opt, opt||{}); - el.children().each(function(){ - var a = {$: $(this), opt: opt}; - a.tag = normalize.tag(a.$); - $(a.opt.mutate).each(function(i,fn){ - fn && fn(a); - }); - }) - return el; - }; - var n = normalize, u; - n.get = function(o, p){ - p = p.split('.'); - var i = 0, l = p.length, u; - while((o = o[p[i++]]) != null && i < l){}; - return i < l ? u : o; - } - n.has = function(o,p){ - return Object.prototype.hasOwnProperty.call(o, p); - } - n.tag = function(e){ - return (($(e)[0]||{}).nodeName||'').toLowerCase(); - } - n.attrs = function(e, cb){ - var attr = {}; - (e = $(e)) && e.length && $(e[0].attributes||[]).each(function(v,n){ - n = n.nodeName||n.name; - v = e.attr(n); - v = cb? cb(v,n,e) : v; - if(v !== u && v !== false){ attr[n] = v } - }); - return attr; - } - n.joint = function(e, d){ - d = (d? 'next' : 'previous') + 'Sibling' - return $(($(e)[0]||{})[d]); - } - var h = { - attr: function(a$, av, al){ - var l = function(i,v){ - var t = v; - i = al? v : i; - v = al? av[v.toLowerCase()] : t; - a$.attr(i, v); - } - al? $(al.sort()).each(l) : $.each(av,l); - } - } - n.opt = { // some reasonable defaults, limited to content alone. - tags: { - 'a': {attrs:{'src':1}, exclude:{'a':1}}, - 'b': {exclude:{'b':1}}, - //'blockquote':1, - 'br': {empty: 1}, - 'div': 1, - //'code':1, - 'i': {exclude:{'i':1}}, - 'img': {attrs:{'src':1}, empty: 1}, - 'li':1, 'ol':1, - 'p': {exclude:{'p':1,'div':1}}, - //'pre':1, - 's': {exclude:{'s':1}}, - 'sub':1, 'sup':1, - 'span': {exclude:{'p':1,'ul':1,'ol':1,'li':1,'br':1}}, - 'u': {exclude:{'u':1,'p':1}}, - 'ul':1 - } - // a, audio, b, br, div, i, img, li, ol, p, s, span, sub, sup, u, ul, video - // button, canvas, embed, form, iframe, input, style, svg, table, - // Text: bold, italics, underline, align, bullet, list, - ,convert: { - 'em': 'i', 'strong': 'b' - } - ,attrs: { - 'id':1 - ,'class':1 - ,'style':1 - } - ,mutate: [ - function(a){ // attr - a.attrs = []; - a.attr = $.extend(a.opt.attrs, n.get(a.opt,'tags.'+ a.tag +'attrs')); - a.attr = n.attrs(a.$, function(v,i){ - a.$.removeAttr(i); - if(a.attr[i.toLowerCase()]){ - a.attrs.push(i) - return v; - } - }); - // if this tag is gonna get converted, wait to add attr back till after the convert - if(a.attrs && !n.get(a.opt, 'convert.' + a.tag)){ - h.attr(a.$, a.attr, a.attrs); - } - } - ,function(a, tmp){ // convert - if(!(tmp = n.get(a.opt,'convert.' + a.tag))){ return } - a.attr = a.attr || n.attrs(a.$); - a.$.replaceWith(a.$ = $('<'+ (a.tag = tmp.toLowerCase()) +'>').append(a.$.contents())); - h.attr(a.$, a.attr, a.attrs); - } - ,function(a, tmp){ // lookahead - if((tmp = n.joint(a.$,1)) && (tmp = tmp.contents()).length === 1 && a.tag === n.tag(tmp = tmp.first())){ - a.$.append(tmp.parent()); // no need to unwrap the child, since the recursion will do it for us - } - } - ,function(a){ // recurse - // this needs to precede the exclusion and empty. - normalize(a); - } - ,function(a, tmp){ // exclude - if(!n.get(a.opt,'tags.' + a.tag) - || ((tmp = n.get(a.opt,'tags.'+ a.tag +'.exclude')) - && a.$.parents($.map(tmp,function(i,v){return v})+' ').length) - ){ - a.$.replaceWith(a.$.contents()); - } - } - ,function(a, tmp){ // prior - if((tmp = n.joint(a.$)).length && a.tag === n.tag(tmp)){ - tmp.append(a.$.contents()); - } - } - ,function(a){ // empty - // should always go last, since the element will be removed! - if(a.opt.empty || !n.has(a.opt,'empty')){ - if(!n.get(a.opt,'tags.'+ a.tag +'.empty') - && !a.$.contents().length){ - a.$.remove(); - } - } - } - ] - } - $.fn.normalize = normalize; -}()); \ No newline at end of file +(function(){ + + $.normalize = function(html, customOpt){ + var html, root$, wrapped, opt; + opt = html.opt || (customOpt ? prepareOptTags($.extend(true, baseOpt, customOpt)) + : defaultOpt); + if(!html.opt){ + // first call + unstableList.length = 0; // drop state from previous run (in case there has been error) + root$ = $('