Created
April 8, 2025 22:36
-
-
Save disouzam/44ace407cb704369a8ed8adb6d8b4dcd to your computer and use it in GitHub Desktop.
Get all computed styles from a HTML page - for debugging purposes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Get all computed styles of a page | |
class Stack { | |
constructor() { | |
this.stack = []; | |
} | |
push(element) { | |
this.stack.push(element); | |
} | |
pop() { | |
if (this.isEmpty()) { | |
return "Stack is empty"; | |
} | |
return this.stack.pop(); | |
} | |
invertedStack() { | |
const invStack = new Stack(); | |
const currentStackSize = this.size(); | |
for (let i = currentStackSize - 1; i >= 0; i--) { | |
invStack.push(this.stack[i]); | |
} | |
return invStack; | |
} | |
isEmpty() { | |
return this.stack.length === 0; | |
} | |
peek() { | |
if (this.isEmpty()) { | |
return "Stack is empty"; | |
} | |
return this.stack[this.stack.length - 1]; | |
} | |
size() { | |
return this.stack.length; | |
} | |
} | |
const unWantedTagNames = ['HEAD', 'LINK', 'META', 'SCRIPT', 'STYLE', 'TITLE']; | |
function getArrayOfNodeStyles(element, arrayOfNodeStyles) { | |
const tagName = element.tagName; | |
if (unWantedTagNames.includes(tagName)) { | |
return arrayOfNodeStyles; | |
} | |
const nodeStyles = { | |
elementTag: tagName, | |
elementClasses: element.classList, | |
elementId: element.id, | |
elementStyle: getComputedStyle(element) | |
} | |
arrayOfNodeStyles.push(nodeStyles); | |
return arrayOfNodeStyles; | |
} | |
function getAllChildrenElements(element) { | |
const childrenStack = new Stack(); | |
const currentChildren = element.children; | |
for (let child of currentChildren) { | |
childrenStack.push(child); | |
const childrenOfChildren = getAllChildrenElements(child); | |
const invertedStack = childrenOfChildren.invertedStack(); | |
while (!invertedStack.isEmpty()) { | |
const poppedElement = invertedStack.pop(); | |
childrenStack.push(poppedElement); | |
} | |
} | |
return childrenStack; | |
} | |
function getAllElementsUnderHtmlElement() { | |
const htmlElement = document.getElementsByTagName('html')[0]; | |
const stackOfElements = new Stack(); | |
stackOfElements.push(htmlElement); | |
const childrenElements = getAllChildrenElements(htmlElement); | |
const invertedStack = childrenElements.invertedStack(); | |
while (!invertedStack.isEmpty()) { | |
const poppedElement = invertedStack.pop(); | |
stackOfElements.push(poppedElement); | |
} | |
return stackOfElements; | |
} | |
function registerObserver(targetNode) { | |
// https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver | |
// Options for the observer (which mutations to observe) | |
const config = { attributes: true, childList: true, subtree: true }; | |
// Callback function to execute when mutations are observed | |
const callback = (mutationList, observer) => { | |
// https://stackoverflow.com/questions/40137825/mutation-observer-with-external-callback-function-code/40138582#40138582 | |
for (const mutation of mutationList) { | |
if (mutation.type === "childList") { | |
console.log(`[${targetNode.tagName} - ${targetNode.id}] A child node has been added or removed.`); | |
} else if (mutation.type === "attributes") { | |
console.log(`[${targetNode.tagName} - ${targetNode.id}] The ${mutation.attributeName} attribute was modified.`); | |
} | |
} | |
const localStackOfElements = getAllElementsUnderHtmlElement(); | |
console.warn(`Number of elements in the stack of elements: ${localStackOfElements.size()}`); | |
getAllComputedStyles(localStackOfElements); | |
}; | |
// Create an observer instance linked to the callback function | |
const observer = new MutationObserver(callback); | |
// Start observing the target node for configured mutations | |
observer.observe(targetNode, config); | |
} | |
function getAllComputedStyles(stackOfElements) { | |
const stackToComputeStyles = stackOfElements.invertedStack(); | |
let arrayOfNodeStyles = []; | |
while (!stackToComputeStyles.isEmpty()) { | |
const poppedElement = stackToComputeStyles.pop(); | |
arrayOfNodeStyles = getArrayOfNodeStyles(poppedElement, arrayOfNodeStyles); | |
} | |
console.log(JSON.stringify(arrayOfNodeStyles)); | |
} | |
function processDOM() { | |
const stackOfElements = getAllElementsUnderHtmlElement(); | |
const invertedStack2 = stackOfElements.invertedStack(); | |
while (!invertedStack2.isEmpty()) { | |
const poppedElement = invertedStack2.pop(); | |
registerObserver(poppedElement); | |
} | |
getAllComputedStyles(stackOfElements); | |
} | |
processDOM(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment