-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Like Tiny-CFI, this also only supports DOM elements, but with ID assertions (yeah!) :)
(internally I use a custom DOM-Range JSON serialization format, so I have not relied on CFI much, other than for informational purposes ... but CFI can indeed be a useful interoperable "standard" in some cases, so I would love to see a complete mini-footprint robust implementation that includes support for character ranges ;)
export function generateCfiSteps(target) {
if (!target || target.nodeType !== this.window.Node.ELEMENT_NODE) {
return undefined;
}
let cfi = "";
let currentElement = target;
while (currentElement.parentNode && currentElement.parentNode.nodeType === Node.ELEMENT_NODE) {
const children = currentElement.parentNode.children;
for (let i = 0; i < children.length; i++) {
if (currentElement === children[i]) {
cfi = ((i + 1) * 2) +
(currentElement.id ? ("[" + currentElement.id + "]") : "") +
(cfi.length ? ("/" + cfi) : "");
break;
}
}
currentElement = currentElement.parentNode;
}
return "/" + cfi;
}tiny-cfi:
Lines 1 to 41 in e9fc323
| function isWhitespaceNode(node) { | |
| return !/[^\t\n\r ]/.test(node.textContent); | |
| } | |
| export function generateCfiSteps(target, root = this.window.document.documentElement) { | |
| const window = this.window; | |
| const treeWalker = window.document.createTreeWalker( | |
| root, | |
| window.NodeFilter.SHOW_ELEMENT + window.NodeFilter.SHOW_TEXT, | |
| { | |
| acceptNode: function (node) { | |
| if (node.nodeType === window.Node.TEXT_NODE && isWhitespaceNode(node)) { | |
| return window.NodeFilter.FILTER_REJECT; | |
| } | |
| return window.NodeFilter.FILTER_ACCEPT; | |
| } | |
| }, | |
| false | |
| ); | |
| let currentNode; | |
| if (target.nodeType === window.Node.TEXT_NODE) { | |
| currentNode = target.parentNode; | |
| } else { | |
| currentNode = target; | |
| } | |
| treeWalker.currentNode = currentNode; | |
| const path = []; | |
| do { | |
| let index = 1; | |
| while (treeWalker.previousSibling()) { | |
| index = index + 1; | |
| } | |
| path.push(index * 2); | |
| currentNode = treeWalker.parentNode(); | |
| } while (currentNode && currentNode !== root); | |
| return `/${path.reverse().join('/')}`; | |
| } |
Metadata
Metadata
Assignees
Labels
No labels