mirror of
https://github.com/amark/gun.git
synced 2025-05-19 13:26:48 +00:00
138 lines
3.7 KiB
JavaScript
138 lines
3.7 KiB
JavaScript
;(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;
|
|
}()); |