From c990c6b248e1c1e255188c189e0ff5dec604b807 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Mon, 13 Mar 2023 13:33:58 +0800 Subject: [PATCH] Add missing anchorElements file --- packages/web/lib/anchorElements.ts | 69 ++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 packages/web/lib/anchorElements.ts diff --git a/packages/web/lib/anchorElements.ts b/packages/web/lib/anchorElements.ts new file mode 100644 index 000000000..faba6f92c --- /dev/null +++ b/packages/web/lib/anchorElements.ts @@ -0,0 +1,69 @@ +const ANCHOR_ELEMENTS_BLOCKED_ATTRIBUTES = [ + 'omnivore-highlight-id', + 'data-twitter-tweet-id', + 'data-instagram-id', +] + +// We search in reverse so we can find the last element +// that is visible on the page +export const getTopOmnivoreAnchorElement = ( + articleContentElement: HTMLElement +): string | undefined => { + let topVisibleRect: Element | undefined = undefined + const anchors = Array.from( + document.querySelectorAll(`[data-omnivore-anchor-idx]`) + ).reverse() + + for (const anchor of anchors) { + const rect = anchor.getBoundingClientRect() + if (rect.top >= 0 && rect.bottom <= articleContentElement.clientHeight) { + if ( + topVisibleRect && + topVisibleRect.getBoundingClientRect().top < rect.top + ) { + continue + } + topVisibleRect = anchor + } + } + + return topVisibleRect?.getAttribute(`data-omnivore-anchor-idx`) ?? undefined +} + +export function parseDomTree( + pageNode: HTMLDivElement | null +): HTMLDivElement[] { + if (!pageNode || pageNode.childNodes.length == 0) { + return [] + } + + const nodesToVisitStack: [HTMLDivElement] = [pageNode] + const visitedNodeList = [] + + while (nodesToVisitStack.length > 0) { + const currentNode = nodesToVisitStack.pop() + if ( + currentNode?.nodeType !== Node.ELEMENT_NODE || + // Avoiding dynamic elements from being counted as anchor-allowed elements + ANCHOR_ELEMENTS_BLOCKED_ATTRIBUTES.some((attrib) => + currentNode.hasAttribute(attrib) + ) + ) { + continue + } + visitedNodeList.push(currentNode) + ;[].slice + .call(currentNode.childNodes) + .reverse() + .forEach(function (node) { + nodesToVisitStack.push(node) + }) + } + + visitedNodeList.shift() + visitedNodeList.forEach((node, index) => { + // start from index 1, index 0 reserved for anchor unknown. + node.setAttribute('data-omnivore-anchor-idx', (index + 1).toString()) + }) + return visitedNodeList +}