blob: 6394cbd01693653a566d8a78c17581ff3f42809b [file] [log] [blame]
'use strict'
module.exports = adapterFactory;
function adapterFactory(implementation){
ensureImplementation(implementation);
var adapter = {}
var baseAdapter = {
removeSubsets: function (nodes){
return removeSubsets(adapter, nodes);
},
existsOne: function(test, elems){
return existsOne(adapter, test, elems);
},
getSiblings: function(elem){
return getSiblings(adapter, elem);
},
hasAttrib: function(elem, name){
return hasAttrib(adapter, elem, name);
},
findOne: function(test, arr){
return findOne(adapter, test, arr);
},
findAll: function(test, elems){
return findAll(adapter, test, elems)
}
};
Object.assign(adapter, baseAdapter, implementation);
return adapter;
}
var expectImplemented = [
"isTag", "getAttributeValue", "getChildren", "getName", "getParent",
"getText"
];
function ensureImplementation(implementation){
if(!implementation) throw new TypeError("Expected implementation")
var notImplemented = expectImplemented.filter(function(fname){
return typeof implementation[fname] !== "function";
});
if(notImplemented.length){
var notList = "(" + notImplemented.join(", ") + ")";
var message = "Expected functions " + notList + " to be implemented";
throw new Error(message);
}
}
function removeSubsets(adapter, nodes){
var idx = nodes.length, node, ancestor, replace;
// Check if each node (or one of its ancestors) is already contained in the
// array.
while(--idx > -1){
node = ancestor = nodes[idx];
// Temporarily remove the node under consideration
nodes[idx] = null;
replace = true;
while(ancestor){
if(nodes.indexOf(ancestor) > -1){
replace = false;
nodes.splice(idx, 1);
break;
}
ancestor = adapter.getParent(ancestor)
}
// If the node has been found to be unique, re-insert it.
if(replace){
nodes[idx] = node;
}
}
return nodes;
}
function existsOne(adapter, test, elems){
return elems.some(function(elem){
return adapter.isTag(elem) ?
test(elem) || adapter.existsOne(test, adapter.getChildren(elem)) :
false;
});
}
function getSiblings(adapter, elem){
var parent = adapter.getParent(elem);
return parent && adapter.getChildren(parent);
}
function hasAttrib(adapter, elem, name){
return adapter.getAttributeValue(elem,name) !== undefined
}
function findOne(adapter, test, arr){
var elem = null;
for(var i = 0, l = arr.length; i < l && !elem; i++){
if(test(arr[i])){
elem = arr[i];
} else {
var childs = adapter.getChildren(arr[i]);
if(childs && childs.length > 0){
elem = adapter.findOne(test, childs);
}
}
}
return elem;
}
function findAll(adapter, test, elems){
var result = [];
for(var i = 0, j = elems.length; i < j; i++){
if(!adapter.isTag(elems[i])) continue;
if(test(elems[i])) result.push(elems[i]);
var childs = adapter.getChildren(elems[i]);
if(childs) result = result.concat(adapter.findAll(test, childs));
}
return result;
}