Harden tracker anchor detection for new comment layout

This commit is contained in:
2026-02-26 00:45:04 +01:00
parent 0511139f99
commit b175603b54

View File

@@ -309,17 +309,94 @@ function getTrackerInsertionAnchorInPost(postElement, buttonBar) {
return anchor && anchor.parentElement === postElement ? anchor : null; return anchor && anchor.parentElement === postElement ? anchor : null;
} }
function hasCommentComposerSignal(node) {
if (!node || !node.querySelector) {
return false;
}
return Boolean(
node.querySelector(
'div[role="textbox"][contenteditable="true"], [role="textbox"][aria-label*="komment" i], [role="textbox"][aria-label*="comment" i], [role="textbox"][aria-placeholder*="komment" i], [role="textbox"][aria-placeholder*="comment" i]'
)
);
}
function countActionRoleSignals(node) {
if (!node || !node.querySelector) {
return 0;
}
const hasLike = Boolean(node.querySelector('[data-ad-rendering-role="like_button"], [data-ad-rendering-role*="gefällt" i]'));
const hasComment = Boolean(node.querySelector('[data-ad-rendering-role="comment_button"]'));
const hasShare = Boolean(node.querySelector('[data-ad-rendering-role="share_button"]'));
return [hasLike, hasComment, hasShare].filter(Boolean).length;
}
function isReliableActionBarCandidate(postElement, candidate) {
if (!postElement || !candidate || !candidate.isConnected || !postElement.contains(candidate)) {
return false;
}
if (candidate.closest('.fb-tracker-ui')) {
return false;
}
if (hasCommentComposerSignal(candidate)) {
return false;
}
const buttonCount = candidate.querySelectorAll('[role="button"], button').length;
if (buttonCount > 80) {
return false;
}
const actionRoleSignals = countActionRoleSignals(candidate);
if (actionRoleSignals >= 2) {
return true;
}
return hasInteractionButtons(candidate);
}
function findActionBarByDataRoles(postElement) {
if (!postElement) {
return null;
}
const markers = Array.from(postElement.querySelectorAll(
'[data-ad-rendering-role="like_button"], [data-ad-rendering-role*="gefällt" i], [data-ad-rendering-role="comment_button"], [data-ad-rendering-role="share_button"]'
));
for (const marker of markers) {
let current = marker;
for (let depth = 0; depth < 8 && current && current !== postElement; depth++) {
if (isReliableActionBarCandidate(postElement, current)) {
return current;
}
current = current.parentElement;
}
}
return null;
}
function resolveActionButtonBar(postElement, buttonBar) { function resolveActionButtonBar(postElement, buttonBar) {
if (!postElement) { if (!postElement) {
return null; return null;
} }
if (buttonBar && buttonBar.isConnected && postElement.contains(buttonBar)) { const dataRoleResolved = findActionBarByDataRoles(postElement);
if (dataRoleResolved) {
return dataRoleResolved;
}
if (buttonBar && isReliableActionBarCandidate(postElement, buttonBar)) {
return buttonBar; return buttonBar;
} }
const resolved = findButtonBar(postElement); const resolved = findButtonBar(postElement);
if (resolved && resolved.isConnected && postElement.contains(resolved)) { if (resolved && isReliableActionBarCandidate(postElement, resolved)) {
return resolved; return resolved;
} }
@@ -428,6 +505,29 @@ function findAdjacentCommentSortAnchor(postElement, actionAnchor = null) {
return null; return null;
} }
function findCommentSortAnchorInPost(postElement) {
if (!postElement) {
return null;
}
const sortCandidates = Array.from(
postElement.querySelectorAll('[aria-label*="relevantes zuerst" i], [aria-label*="most relevant" i], [aria-label*="neueste" i], [aria-label*="newest" i], [role="button"], button')
);
for (const candidate of sortCandidates) {
if (!isLikelyCommentSortNode(candidate)) {
continue;
}
const topLevel = getTopLevelAnchorWithinPost(postElement, candidate) || candidate;
if (topLevel && topLevel.parentElement && postElement.contains(topLevel)) {
return topLevel;
}
}
return null;
}
function createTrackerInsertionMarker() { function createTrackerInsertionMarker() {
const marker = document.createElement('div'); const marker = document.createElement('div');
marker.className = 'fb-tracker-insertion-anchor'; marker.className = 'fb-tracker-insertion-anchor';
@@ -472,6 +572,14 @@ function positionTrackerInsertionMarker(postElement, marker, buttonBar, postNum
return true; return true;
} }
const fallbackSortAnchor = findCommentSortAnchorInPost(postElement);
if (fallbackSortAnchor && fallbackSortAnchor.parentElement) {
fallbackSortAnchor.parentElement.insertBefore(marker, fallbackSortAnchor);
setTrackerInsertionMarkerLocked(marker, true);
console.log('[FB Tracker] Post #' + postNum + ' - Marker fallback inserted before comment sort');
return true;
}
postElement.appendChild(marker); postElement.appendChild(marker);
setTrackerInsertionMarkerLocked(marker, false); setTrackerInsertionMarkerLocked(marker, false);
console.log('[FB Tracker] Post #' + postNum + ' - Marker fallback appended to post'); console.log('[FB Tracker] Post #' + postNum + ' - Marker fallback appended to post');