@ara-web/sds
Version:
Write code faster without worry about future debts or scalability in the future
135 lines (112 loc) • 3.94 kB
text/typescript
import { Debug } from "@ara-web/p-hintjens";
import { Adapter } from "../src/tree";
export class NodeAdapter<BranchedModuleObject extends Node> implements Adapter<Node, BranchedModuleObject>{
private EMPTY_OBJECT = {};
public isTag(elem: Node): elem is BranchedModuleObject {
return elem.nodeType === 1;
}
public getChildren(elem: Node): Node[] {
return elem.childNodes ? Array.prototype.slice.call(elem.childNodes, 0) : [];
}
public getParent(elem: BranchedModuleObject): BranchedModuleObject|null {
return elem.parentNode as unknown as BranchedModuleObject;
}
public removeSubsets(nodes: Node[]): Node[] {
let idx = nodes.length;
let node: Node;
let ancestor: Node | null;
let replace: boolean;
// 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
delete nodes[idx];
replace = true;
while(ancestor) {
if(nodes.indexOf(ancestor) > -1) {
replace = false;
nodes.splice(idx, 1);
break;
}
ancestor = this.getParent(ancestor as unknown as BranchedModuleObject)
}
// If the node has been found to be unique, re-insert it.
if(replace) {
nodes[idx] = node;
}
}
return nodes;
}
public existsOne(test, elems){
return elems.some((elem) => {
return this.isTag(elem) ?
test(elem) || this.existsOne(test, this.getChildren(elem)) :
false;
});
}
public getSiblings (elem){
var parent = this.getParent(elem);
return parent ? this.getChildren(parent) : [elem];
}
public getAttributeValue(elem, name){
if(elem.attributes && name in elem.attributes){
var attr = elem.attributes[name];
return typeof attr === "string" ? attr : attr.value;
} else if (name === "class" && elem.classList) {
return Array.from(elem.classList).join(" ");
}
}
public hasAttrib(elem, name){
return name in (elem.attributes || this.EMPTY_OBJECT);
}
public getName(elem){
return (elem.tagName || "").toLowerCase();
}
public findOne(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 = this.getChildren(arr[i]);
if(childs && childs.length > 0){
elem = this.findOne(test, childs);
}
}
}
return elem;
}
public findAll(test, elems: Node[]): BranchedModuleObject[] {
Debug.push(`findAll`)
Debug.log(`Find all predicate: ${test.toString()}`)
var result: BranchedModuleObject[] = [];
for(var i = 0, j = elems.length; i < j; i++){
Debug.log(`\n\n\n`)
Debug.log(`${i}/${elems.length-1}) name '${test.name}' against elem name '${this.getName(elems[i] as unknown as BranchedModuleObject)}'`)
Debug.log(`${i}/${elems.length-1}) ${JSON.stringify(test.next, null, 4)}`)
Debug.log(`${i}/${elems.length-1}) ${JSON.stringify(elems[i].nodeName, null, 4)}`)
if(!this.isTag(elems[i])) continue;
if(test(elems[i])) {
Debug.log(`${i}/${elems.length-1}) passed`)
result.push(elems[i] as unknown as BranchedModuleObject);
} else {
Debug.log(`${i}/${elems.length-1}) not passed`)
}
var childs = this.getChildren(elems[i]);
if(childs) {
const foundChildren = this.findAll(test, childs);
Debug.log(`${i}/${elems.length-1}) found children: ${foundChildren.length}`)
result = result.concat(foundChildren);
}
}
Debug.pop();
return result;
}
public getText(elem) {
if(Array.isArray(elem)) return elem.map(this.getText).join("");
if(this.isTag(elem)) return this.getText(this.getChildren(elem));
if(elem.nodeType === 3) return elem.nodeValue;
return "";
}
}