Skip to content

Instantly share code, notes, and snippets.

@eps1lon
Last active November 21, 2021 21:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eps1lon/7facfc47758c3969807733fb75a177a7 to your computer and use it in GitHub Desktop.
Save eps1lon/7facfc47758c3969807733fb75a177a7 to your computer and use it in GitHub Desktop.
Hightlight visible Suspense boundaries

Highlights server-side rendered Suspense boundaries.

  1. Create Chrome Devtools snippet with content of source file
  2. Run snippet
let treeWalker = document.createTreeWalker(document, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT, null, null);
let node = null;
let boundariesNodesList = [];
let boundariesStack = []
let currentBoundary = [];
while ((node = treeWalker.nextNode()) !== null) {
if (node.nodeType === Node.COMMENT_NODE) {
if (isSuspenseBoundaryStart(node)) {
boundariesStack.push(currentBoundary)
currentBoundary = [node]
} else if (isSuspenseBoundaryEnd(node)) {
currentBoundary.push(node);
boundariesNodesList.push(currentBoundary)
currentBoundary = boundariesStack.pop()
}
} else {
currentBoundary.push(node);
}
}
const boundaries = boundariesNodesList.map(boundaryNodes => {
const boundaryStart = boundaryNodes.at(0)
const boundaryEnd = boundaryNodes.at(-1);
const nodes = boundaryNodes.slice(1, -1);
const boundaryChildren = []
let currentNode = null;
boundaryNodes.forEach(node => {
if (node.nodeType === Node.COMMENT_NODE) {
} else if (currentNode === null) {
currentNode = node;
} else if (!currentNode.contains(node)) {
boundaryChildren.push(currentNode)
currentNode = node;
}
})
boundaryChildren.push(currentNode)
const range = new Range();
range.setStartAfter(boundaryStart);
range.setEndBefore(boundaryEnd);
return { range, start: boundaryStart, end: boundaryEnd, children: boundaryChildren }
})
console.log(boundaries)
try {
clearBoundaryHighlights()
} catch (error) {
console.error('Trouble clearing pre-existing boundaries:', error)
}
boundaries.forEach(highlightBoundary);
function isSuspenseBoundaryStart(commentNode) {
return commentNode.textContent === '$'
}
function isSuspenseBoundaryEnd(commentNode) {
return commentNode.textContent === '/$'
}
function clearBoundaryHighlights() {
document.querySelectorAll('.boundary-highlight').forEach(highlight => {
highlight.remove();
});
}
function highlightBoundary({ range }) {
const { top, left, width, height} = range.getBoundingClientRect();
if (width === 0 && height === 0) {
return;
}
const highlight = document.createElement('div');
highlight.className = 'boundary-highlight'
highlight.style.position = 'absolute';
highlight.style.pointerEvents = 'none';
highlight.style.backgroundColor = 'transparent';
highlight.style.border = '2px solid red';
highlight.style.width = `${width}px`;
highlight.style.height = `${height}px`;
highlight.style.top = `${window.scrollY + top}px`;
highlight.style.left = `${window.scrollX + left}px`;
document.body.appendChild(highlight);
console.log(highlight)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment