mirror of
https://github.com/amark/gun.git
synced 2025-06-07 22:56:42 +00:00
link and normalize
This commit is contained in:
parent
2aae735960
commit
c243d71e71
44
gun.js
44
gun.js
@ -264,11 +264,11 @@
|
|||||||
|| num_is(v)){ // by "number" we mean integers or decimals.
|
|| num_is(v)){ // by "number" we mean integers or decimals.
|
||||||
return true; // simple values are valid.
|
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 = {_: '#'};
|
Val.link = Val.rel = {_: '#'};
|
||||||
;(function(){
|
;(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.
|
if(v && v[rel_] && !v._ && obj_is(v)){ // must be an object.
|
||||||
var o = {};
|
var o = {};
|
||||||
obj_map(v, map, 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._ = '.';
|
Type.obj.has._ = '.';
|
||||||
var rel_ = Val.link._, u;
|
var rel_ = Val.link._, u;
|
||||||
var bi_is = Type.bi.is;
|
var bi_is = Type.bi.is;
|
||||||
@ -473,7 +473,7 @@
|
|||||||
env.map = env;
|
env.map = env;
|
||||||
}
|
}
|
||||||
if(env.soul){
|
if(env.soul){
|
||||||
at.rel = Val.rel.ify(env.soul);
|
at.link = Val.link.ify(env.soul);
|
||||||
}
|
}
|
||||||
env.shell = (as||{}).shell;
|
env.shell = (as||{}).shell;
|
||||||
env.graph = env.graph || {};
|
env.graph = env.graph || {};
|
||||||
@ -488,16 +488,16 @@
|
|||||||
at.env = env;
|
at.env = env;
|
||||||
at.soul = soul;
|
at.soul = soul;
|
||||||
if(Node.ify(at.obj, map, at)){
|
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){
|
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;
|
return at;
|
||||||
}
|
}
|
||||||
function map(v,k,n){
|
function map(v,k,n){
|
||||||
var at = this, env = at.env, is, tmp;
|
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?
|
return n._; // TODO: Bug?
|
||||||
}
|
}
|
||||||
if(!(is = valid(v,k,n, at,env))){ return }
|
if(!(is = valid(v,k,n, at,env))){ return }
|
||||||
@ -506,8 +506,8 @@
|
|||||||
if(obj_has(v, Node._) && Node.soul(v)){ // ? for safety ?
|
if(obj_has(v, Node._) && Node.soul(v)){ // ? for safety ?
|
||||||
at.node._ = obj_copy(v._);
|
at.node._ = obj_copy(v._);
|
||||||
}
|
}
|
||||||
at.node = Node.soul.ify(at.node, Val.rel.is(at.rel));
|
at.node = Node.soul.ify(at.node, Val.link.is(at.link));
|
||||||
at.rel = at.rel || Val.rel.ify(Node.soul(at.node));
|
at.link = at.link || Val.link.ify(Node.soul(at.node));
|
||||||
}
|
}
|
||||||
if(tmp = env.map){
|
if(tmp = env.map){
|
||||||
tmp.call(env.as || {}, v,k,n, at);
|
tmp.call(env.as || {}, v,k,n, at);
|
||||||
@ -526,14 +526,14 @@
|
|||||||
}
|
}
|
||||||
tmp = node(env, {obj: v, path: at.path.concat(k)});
|
tmp = node(env, {obj: v, path: at.path.concat(k)});
|
||||||
if(!tmp.node){ return }
|
if(!tmp.node){ return }
|
||||||
return tmp.rel; //{'#': Node.soul(tmp.node)};
|
return tmp.link; //{'#': Node.soul(tmp.node)};
|
||||||
}
|
}
|
||||||
function soul(id){ var at = this;
|
function soul(id){ var at = this;
|
||||||
var prev = Val.link.is(at.rel), graph = at.env.graph;
|
var prev = Val.link.is(at.link), graph = at.env.graph;
|
||||||
at.rel = at.rel || Val.rel.ify(id);
|
at.link = at.link || Val.link.ify(id);
|
||||||
at.rel[Val.rel._] = id;
|
at.link[Val.link._] = id;
|
||||||
if(at.node && at.node[Node._]){
|
if(at.node && at.node[Node._]){
|
||||||
at.node[Node._][Val.rel._] = id;
|
at.node[Node._][Val.link._] = id;
|
||||||
}
|
}
|
||||||
if(obj_has(graph, prev)){
|
if(obj_has(graph, prev)){
|
||||||
graph[id] = graph[prev];
|
graph[id] = graph[prev];
|
||||||
@ -573,13 +573,13 @@
|
|||||||
}
|
}
|
||||||
function map(v,k){ var tmp, obj;
|
function map(v,k){ var tmp, obj;
|
||||||
if(Node._ === k){
|
if(Node._ === k){
|
||||||
if(obj_empty(v, Val.rel._)){
|
if(obj_empty(v, Val.link._)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.obj[k] = obj_copy(v);
|
this.obj[k] = obj_copy(v);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!(tmp = Val.rel.is(v))){
|
if(!(tmp = Val.link.is(v))){
|
||||||
this.obj[k] = v;
|
this.obj[k] = v;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -871,7 +871,7 @@
|
|||||||
var list_is = Gun.list.is;
|
var list_is = Gun.list.is;
|
||||||
var text = Gun.text, text_is = text.is, text_rand = text.random;
|
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 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;
|
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) };
|
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])){
|
if(!(at = next[key])){
|
||||||
return;
|
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;
|
// data = tmp.put;
|
||||||
//}
|
//}
|
||||||
if(at.has){
|
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)){
|
if(u === at.put || !Gun.val.link.is(data)){
|
||||||
at.put = data;
|
at.put = data;
|
||||||
}
|
}
|
||||||
@ -1222,7 +1222,7 @@
|
|||||||
var empty = {}, u;
|
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 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 text_rand = Gun.text.random;
|
||||||
var _soul = Gun.val.rel._, node_ = Gun.node._;
|
var _soul = Gun.val.link._, node_ = Gun.node._;
|
||||||
})(USE, './chain');
|
})(USE, './chain');
|
||||||
|
|
||||||
;USE(function(module){
|
;USE(function(module){
|
||||||
@ -1395,7 +1395,7 @@
|
|||||||
if(!soul && Gun.val.is(msg.put)){
|
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)!');
|
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);
|
}, true);
|
||||||
return gun;
|
return gun;
|
||||||
}
|
}
|
||||||
@ -1495,7 +1495,7 @@
|
|||||||
function soul(id, as, msg, eve){
|
function soul(id, as, msg, eve){
|
||||||
var as = as.as, cat = as.at; as = as.as;
|
var as = as.as, cat = as.at; as = as.as;
|
||||||
var at = ((msg || {}).$ || {})._ || {};
|
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(eve){ eve.stun = true }
|
||||||
if(!id){ // polyfill async uuid for SEA
|
if(!id){ // polyfill async uuid for SEA
|
||||||
at.via.back('opt.uuid')(function(err, id){ // TODO: improve perf without anonymous callback
|
at.via.back('opt.uuid')(function(err, id){ // TODO: improve perf without anonymous callback
|
||||||
|
364
lib/normalize.js
364
lib/normalize.js
@ -1,138 +1,284 @@
|
|||||||
;(function(){
|
(function(){
|
||||||
function normalize(opt){
|
|
||||||
var el = $(this);
|
$.normalize = function(html, customOpt){
|
||||||
opt = opt || $.extend(true, normalize.opt, opt||{});
|
var html, root$, wrapped, opt;
|
||||||
el.children().each(function(){
|
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$ = $('<div>'+html+'</div>');
|
||||||
|
}
|
||||||
|
// initial recursion
|
||||||
|
(html.$ || root$).contents().each(function(){
|
||||||
|
if(this.nodeType === this.TEXT_NODE) {
|
||||||
|
this.textContent = this.textContent.replace(/^[ \n]+|[ \n]+$/g, ' ');
|
||||||
|
return;
|
||||||
|
}
|
||||||
var a = {$: $(this), opt: opt};
|
var a = {$: $(this), opt: opt};
|
||||||
a.tag = normalize.tag(a.$);
|
initTag(a);
|
||||||
$(a.opt.mutate).each(function(i,fn){
|
$.normalize(a);
|
||||||
fn && fn(a);
|
|
||||||
});
|
});
|
||||||
})
|
if(root$){
|
||||||
return el;
|
stateMachine();
|
||||||
};
|
return root$.html();
|
||||||
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: {
|
var baseOpt = {
|
||||||
'a': {attrs:{'src':1}, exclude:{'a':1}},
|
hierarchy: ['div', 'pre', 'ol', 'ul', 'li',
|
||||||
'b': {exclude:{'b':1}},
|
'h1', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'a', // block
|
||||||
//'blockquote':1,
|
'b', 'code', 'i', 'span', 's', 'sub', 'sup', 'u', // inline
|
||||||
|
'br'] // empty
|
||||||
|
,tags: {
|
||||||
|
'a': {attrs:{'href':1}, exclude:{'a':1}},
|
||||||
|
'b': {exclude:{'b':1,'p':1}},
|
||||||
'br': {empty: 1},
|
'br': {empty: 1},
|
||||||
'div': 1,
|
'i': {exclude:{'i':1,'p':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}},
|
'span': {exclude:{'p':1,'ul':1,'ol':1,'li':1,'br':1}},
|
||||||
'u': {exclude:{'u':1,'p':1}},
|
's': {space:1},
|
||||||
'ul':1
|
'u': {exclude:{'u':1,'p':1},space: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: {
|
,convert: {
|
||||||
'em': 'i', 'strong': 'b'
|
'em': 'i', 'strong': 'b', 'strike': 's',
|
||||||
}
|
}
|
||||||
,attrs: {
|
,attrs: {
|
||||||
'id':1
|
'id':1
|
||||||
,'class':1
|
,'class':1
|
||||||
,'style':1
|
,'style':1
|
||||||
}
|
}
|
||||||
,mutate: [
|
,blockTag: function(a){
|
||||||
function(a){ // attr
|
return a.opt.tags[a.tag].order < a.opt.tags.a.order;
|
||||||
a.attrs = [];
|
}
|
||||||
a.attr = $.extend(a.opt.attrs, n.get(a.opt,'tags.'+ a.tag +'attrs'));
|
,mutate: [exclude, moveSpaceUp, next, parentOrderWrap]
|
||||||
a.attr = n.attrs(a.$, function(v,i){
|
}
|
||||||
a.$.removeAttr(i);
|
|
||||||
if(a.attr[i.toLowerCase()]){
|
var defaultOpt = prepareOptTags($.extend(true, {}, baseOpt));
|
||||||
a.attrs.push(i)
|
|
||||||
return v;
|
var unstableList = [];
|
||||||
|
|
||||||
|
function addUnstable(a) { // NOT ES5
|
||||||
|
if(!a.tag) { throw Error("not tag in ", a) }
|
||||||
|
if(a.unstable) return;
|
||||||
|
unstableList.push(a);
|
||||||
|
a.unstable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initTag(a) {
|
||||||
|
// initial handling (container, convert, attributes):
|
||||||
|
a.tag = tag(a.$);
|
||||||
|
if(empty(a)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parseAndRemoveAttrs(a);
|
||||||
|
convert(a);
|
||||||
|
setAttrs(a);
|
||||||
|
a.$[0].a = a; // link from dom element back to a
|
||||||
|
// state machine init
|
||||||
|
unstableList.push(a);
|
||||||
|
a.unstable = true;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stateMachine() {
|
||||||
|
if(unstableList.length===0)
|
||||||
|
return;
|
||||||
|
var a, i = -1;
|
||||||
|
while (a = unstableList.pop()) { // PERF: running index is probably faster than shift (mutates array)
|
||||||
|
a.unstable = false;
|
||||||
|
$(a.opt.mutate).each(function(i,fn){
|
||||||
|
return fn && fn(a, addUnstable);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareOptTags(opt) {
|
||||||
|
var name, tag, tags = opt.tags;
|
||||||
|
for(name in tags) {
|
||||||
|
if(opt.hierarchy.indexOf(name)===-1)
|
||||||
|
throw Error('tag "'+name+'" is missing hierachy definition');
|
||||||
|
}
|
||||||
|
opt.hierarchy.forEach(function(name){
|
||||||
|
if(!tags[name]){
|
||||||
|
tags[name] = {attrs: opt.attrs};
|
||||||
|
}
|
||||||
|
(tag=tags[name]).attrs = $.extend(tag.attrs||{}, opt.attrs);
|
||||||
|
tag.name = name; // not used, debug help (REMOVE later?)
|
||||||
|
// order
|
||||||
|
tag.order = opt.hierarchy.indexOf(name)
|
||||||
|
if(tag.order === -1) {
|
||||||
|
throw Error("Order of '"+name+"' not defined in hierarchy");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if this tag is gonna get converted, wait to add attr back till after the convert
|
return opt;
|
||||||
if(a.attrs && !n.get(a.opt, 'convert.' + a.tag)){
|
}
|
||||||
h.attr(a.$, a.attr, a.attrs);
|
|
||||||
|
// GENERAL UTILS
|
||||||
|
|
||||||
|
function get(o, args){ // path argments as separate string parameters
|
||||||
|
if(typeof args === 'string')
|
||||||
|
return o[args[0]];
|
||||||
|
var i = 0, l = args.length, u;
|
||||||
|
while((o = o[args[i++]]) != null && i < l){};
|
||||||
|
return i < l ? u : o;
|
||||||
|
}
|
||||||
|
|
||||||
|
function has(obj,prop){
|
||||||
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT UTILS
|
||||||
|
|
||||||
|
function tag(e){
|
||||||
|
return (($(e)[0]||{}).nodeName||'').toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function joint(e, d){
|
||||||
|
d = (d? 'next' : 'previous') + 'Sibling';
|
||||||
|
return $(($(e)[0]||{})[d]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create key val attributes object from elements attributes
|
||||||
|
function attrsAsObj(e, filterCb){
|
||||||
|
var attrObj = {};
|
||||||
|
(e = $(e)) && e.length && $(e[0].attributes||[]).each(function(value,name){
|
||||||
|
name = name.nodeName||name.name;
|
||||||
|
value = e.attr(name);
|
||||||
|
value = filterCb? filterCb(value,name,e) : value;
|
||||||
|
if(value !== undefined && value !== false)
|
||||||
|
attrObj[name] = value;
|
||||||
|
});
|
||||||
|
return attrObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: PERF testing - for loop to compare through?
|
||||||
|
function sameAttrs(a, b) {
|
||||||
|
return JSON.stringify(a.attr) === JSON.stringify(b.attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// INITIAL MUTATORS
|
||||||
|
|
||||||
|
function parseAndRemoveAttrs(a) {
|
||||||
|
a.attrs = [];
|
||||||
|
var tag = a.opt.convert[a.tag] || a.tag,
|
||||||
|
tOpt = a.opt.tags[tag];
|
||||||
|
a.attr = tOpt && attrsAsObj(a.$, function(value,name){
|
||||||
|
a.$.removeAttr(name);
|
||||||
|
if(tOpt.attrs[name.toLowerCase()]){
|
||||||
|
a.attrs.push(name)
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAttrs(a){
|
||||||
|
var l = function(ind,name){
|
||||||
|
var t = name;
|
||||||
|
name = a.attrs? name : ind;
|
||||||
|
var value = a.attrs? a.attr[name.toLowerCase()] : t;
|
||||||
|
a.$.attr(name, value);
|
||||||
|
}
|
||||||
|
a.attrs? $(a.attrs.sort()).each(l) : $.each(a.attr,l);
|
||||||
|
}
|
||||||
|
|
||||||
|
function convert(a){
|
||||||
|
var t;
|
||||||
|
if(t = a.opt.convert[a.tag]){
|
||||||
|
a.$.replaceWith(a.$ = $('<'+ (a.tag = t.toLowerCase()) +'>').append(a.$.contents()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
,function(a, tmp){ // convert
|
|
||||||
if(!(tmp = n.get(a.opt,'convert.' + a.tag))){ return }
|
// LOOPING (STATE MACHINE) MUTATORS
|
||||||
a.attr = a.attr || n.attrs(a.$);
|
|
||||||
a.$.replaceWith(a.$ = $('<'+ (a.tag = tmp.toLowerCase()) +'>').append(a.$.contents()));
|
function exclude(a, addUnstable){
|
||||||
h.attr(a.$, a.attr, a.attrs);
|
var t = get(a.opt, ['tags', a.tag]),
|
||||||
}
|
pt = get(a.opt, ['tags', tag(a.$.parent())]);
|
||||||
,function(a, tmp){ // lookahead
|
if(!t || (pt && get(pt, ['exclude', a.tag]))){
|
||||||
if((tmp = n.joint(a.$,1)) && (tmp = tmp.contents()).length === 1 && a.tag === n.tag(tmp = tmp.first())){
|
var c = a.$.contents();
|
||||||
a.$.append(tmp.parent()); // no need to unwrap the child, since the recursion will do it for us
|
a.$.replaceWith(c);
|
||||||
|
c.length===1 && c[0].a && addUnstable(c[0].a);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
,function(a){ // recurse
|
|
||||||
// this needs to precede the exclusion and empty.
|
function moveSpaceUp(a, addUnstable){
|
||||||
normalize(a);
|
var n = a.$[0];
|
||||||
}
|
if(moveSpace(n, true) + moveSpace(n, false)) {
|
||||||
,function(a, tmp){ // exclude
|
// either front, back or both spaces moved
|
||||||
if(!n.get(a.opt,'tags.' + a.tag)
|
var c;
|
||||||
|| ((tmp = n.get(a.opt,'tags.'+ a.tag +'.exclude'))
|
if(n.textContent==='') {
|
||||||
&& a.$.parents($.map(tmp,function(i,v){return v})+' ').length)
|
empty(a);
|
||||||
){
|
} else if((c = a.$.contents()[0]) && c.a) {
|
||||||
a.$.replaceWith(a.$.contents());
|
parentOrderWrap(c.a, addUnstable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
,function(a, tmp){ // prior
|
|
||||||
if((tmp = n.joint(a.$)).length && a.tag === n.tag(tmp)){
|
|
||||||
tmp.append(a.$.contents());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function moveSpace(n, bef) {
|
||||||
|
var childRe = bef? /^ / : / $/,
|
||||||
|
parentRe = bef? / $/ : /^ /,
|
||||||
|
c = bef? 'firstChild' : 'lastChild',
|
||||||
|
s = bef? 'previousSibling' : 'nextSibling';
|
||||||
|
sAdd = bef? 'after' : 'before';
|
||||||
|
pAdd = bef? 'prepend' : 'append';
|
||||||
|
if(!n || !n[c] || n[c].nodeType !== n.TEXT_NODE || !n[c].wholeText.match(childRe)) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
,function(a){ // empty
|
if((n2 = n[s]) && !n.a.opt.blockTag(n.a)) {
|
||||||
// should always go last, since the element will be removed!
|
if(n2.nodeType === 3 && !n2.textContent.match(parentRe)) {
|
||||||
if(a.opt.empty || !n.has(a.opt,'empty')){
|
n2.textContent = (bef?'':' ') + n2.textContent + (bef?' ':'');
|
||||||
if(!n.get(a.opt,'tags.'+ a.tag +'.empty')
|
} else if(n2.nodeType === 1) {
|
||||||
&& !a.$.contents().length){
|
$(n2)[sAdd](' ');
|
||||||
|
}
|
||||||
|
} else if((n2 = n.parentNode) && !n.a.opt.blockTag(n.a)) {
|
||||||
|
$(n2)[pAdd](' ');
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
n[c].textContent = n[c].wholeText.replace(childRe, '');
|
||||||
|
if(!n[c].wholeText.length)
|
||||||
|
$(n[c]).remove();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function next(a, addUnstable, t){
|
||||||
|
var t = t || joint(a.$, true), sm;
|
||||||
|
if(!t.length || a.opt.blockTag(a))
|
||||||
|
return;
|
||||||
|
if(a.opt.spaceMerge && t.length===1 && t[0].nodeType === 3 && t[0].wholeText===' '){
|
||||||
|
if(!(t2 = joint(t, true)).length || a.opt.blockTag(t2[0].a))
|
||||||
|
return;
|
||||||
|
t.remove();
|
||||||
|
t2.prepend(' ');
|
||||||
|
return next(a, addUnstable, t2);
|
||||||
|
}
|
||||||
|
if(!t[0].a || a.tag !== t[0].a.tag || !sameAttrs(a, t[0].a))
|
||||||
|
return;
|
||||||
|
t.prepend(a.$.contents());
|
||||||
|
empty(a);
|
||||||
|
addUnstable(t[0].a);
|
||||||
|
(t = t.children(":first")).length && addUnstable(t[0].a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function empty(a){
|
||||||
|
var t = a.opt.tags[a.tag];
|
||||||
|
if((!t || !t.empty) && !a.$.contents().length && !a.$[0].attributes.length){
|
||||||
a.$.remove();
|
a.$.remove();
|
||||||
|
return true; // NOTE true/false - different API than in exclude
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parentOrderWrap(a, addUnstable){
|
||||||
|
var parent = a.$.parent(), children = parent.contents(),
|
||||||
|
tags = a.opt.tags, ptag;
|
||||||
|
|
||||||
|
if(children.length===1 && children[0] === a.$[0]
|
||||||
|
&& (ptag=tags[tag(parent)]) && ptag.order > tags[a.tag].order){
|
||||||
|
parent.after(a.$);
|
||||||
|
parent.append(a.$.contents());
|
||||||
|
a.$.append(parent);
|
||||||
|
addUnstable(parent[0].a);
|
||||||
|
addUnstable(a);
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
}
|
||||||
$.fn.normalize = normalize;
|
})();
|
||||||
}());
|
|
Loading…
x
Reference in New Issue
Block a user