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:
|
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('/')}`; |
|
} |
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 ;)
tiny-cfi:
tiny-cfi/tinycfi.js
Lines 1 to 41 in e9fc323