Skip to content

Commit 21e084c

Browse files
authored
Add dom-shape metric to markup (#140)
* Add dom-shape metric to markup * Add depth as explicit attribute
1 parent bfe54a5 commit 21e084c

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

dist/markup.js

+141
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,147 @@ try { // whole process is placed in a try/catch so we can log uncaught errors
645645
return {
646646
hrefs_without_special_scheme
647647
};
648+
})(),
649+
650+
'dom-shape': (() => {
651+
652+
//================================================================
653+
// helpers
654+
//================================================================
655+
656+
function depthOf(node, currentDepth = 0) {
657+
if (node === document.body) {
658+
return currentDepth;
659+
} else {
660+
return depthOf(node.parentNode, currentDepth + 1);
661+
}
662+
}
663+
664+
function mean(arr) {
665+
let total = arr.reduce((acc, curr) => acc + curr, 0)
666+
return total / arr.length;
667+
}
668+
669+
function stddev(arr, mean) {
670+
let squareDiffs = arr.map((k) => (k - mean) ** 2);
671+
let sumSquareDiffs = squareDiffs.reduce((acc, curr) => acc + curr, 0);
672+
return Math.sqrt(sumSquareDiffs / arr.length);
673+
}
674+
675+
function skew(mean, mode, stdDev) {
676+
return (mean - mode) / stdDev;
677+
}
678+
679+
function median(sortedArr) {
680+
let length = sortedArr.length;
681+
if (length % 2 === 0) {
682+
return (sortedArr[length / 2 - 1] + sortedArr[length / 2]) / 2;
683+
} else {
684+
return sortedArr[(length - 1) / 2];
685+
}
686+
}
687+
688+
function mode(arr) {
689+
let mode = {};
690+
let max = 0, count = 0;
691+
for (const item of arr) {
692+
if (mode[item]) {
693+
mode[item]++;
694+
} else {
695+
mode[item] = 1;
696+
}
697+
if(count < mode[item]) {
698+
max = item;
699+
count = mode[item];
700+
}
701+
}
702+
return max
703+
}
704+
705+
function range(sortedArr) {
706+
return {min: sortedArr[0], max: sortedArr[sortedArr.length - 1]};
707+
}
708+
709+
let stats = {};
710+
711+
stats.nodesCount = document.querySelector("*").length;
712+
713+
stats.bodyNodesCount = document.querySelectorAll("body *").length
714+
let bodyLeafNodes = document.querySelectorAll("body :not(:has(*))");
715+
stats.bodyLeafNodesCount = bodyLeafNodes.length
716+
717+
let depths = [];
718+
for (const leafNode of bodyLeafNodes) {
719+
depths.push(depthOf(leafNode));
720+
}
721+
depths.sort((a, b) => a - b);
722+
723+
let meanDepth = mean(depths);
724+
let stdDevDepth = stddev(depths, meanDepth);
725+
let modeDepth = mode(depths);
726+
let skewDepth = skew(meanDepth, modeDepth, stdDevDepth);
727+
stats.depth = {
728+
mean: meanDepth,
729+
median: median(depths),
730+
mode: modeDepth,
731+
stddev : stdDevDepth,
732+
skew : skewDepth,
733+
range: range(depths),
734+
}
735+
736+
let bodyNonLeafNodes = document.querySelectorAll("body :has(*)");
737+
stats.bodyNonLeafNodesCount = bodyNonLeafNodes.length
738+
let branchFactors = [];
739+
for (const nonLeafNode of bodyNonLeafNodes) {
740+
branchFactors.push(nonLeafNode.childNodes.length);
741+
}
742+
branchFactors.sort((a, b) => a - b);
743+
744+
let meanBranchFactor = mean(branchFactors);
745+
let stdDevBranchFactor = stddev(branchFactors, meanBranchFactor);
746+
let modeBranchFactor = mode(branchFactors);
747+
let skewBranchFactor = skew(meanBranchFactor, modeBranchFactor, stdDevBranchFactor);
748+
stats.branchFactor = {
749+
mean: meanBranchFactor,
750+
median: median(branchFactors),
751+
mode: modeBranchFactor,
752+
stddev : stdDevBranchFactor,
753+
skew : skewBranchFactor,
754+
range: range(branchFactors),
755+
}
756+
757+
stats.branchFactorByDepth = []
758+
for (let depth = 0; depth < stats.depth.range.max; depth++) {
759+
760+
let selector = "body ";
761+
for (let i = 0; i < depth; i++) {
762+
selector += " > :has(*)";
763+
}
764+
let parentNodesAtThisLevel = document.querySelectorAll(selector);
765+
let branchFactors = [];
766+
for (const nonLeafNode of parentNodesAtThisLevel) {
767+
branchFactors.push(nonLeafNode.childNodes.length);
768+
}
769+
branchFactors.sort((a, b) => a - b);
770+
771+
let meanBranchFactor = mean(branchFactors);
772+
let stdDevBranchFactor = stddev(branchFactors, meanBranchFactor);
773+
let modeBranchFactor = mode(branchFactors);
774+
let skewBranchFactor = skew(meanBranchFactor, modeBranchFactor, stdDevBranchFactor);
775+
stats.branchFactorByDepth[depth] = {
776+
depth: depth,
777+
count: parentNodesAtThisLevel.length,
778+
mean: meanBranchFactor,
779+
stddev : stdDevBranchFactor,
780+
skew : skewBranchFactor,
781+
median: median(branchFactors),
782+
mode: modeBranchFactor,
783+
range: range(branchFactors),
784+
}
785+
}
786+
787+
return stats;
788+
648789
})()
649790
};
650791
}

0 commit comments

Comments
 (0)