fix(search): anchor search containers strictly inside my-search and prevent body injection v1.5.1

This commit is contained in:
Enes Yakıştır
2026-09-19 09:50:12 +03:00
parent 2d4dcafe82
commit 96e6750f99
2 changed files with 46 additions and 25 deletions
+46 -25
View File
@@ -2012,25 +2012,32 @@ try {
} }
function ensureFediverseBridge(query, currentSearchTarget) { function ensureFediverseBridge(query, currentSearchTarget) {
var searchMount = document.querySelector('my-search, my-search-results');
if (!searchMount) return;
var bridge = document.getElementById('yaktube-fediverse-bridge'); var bridge = document.getElementById('yaktube-fediverse-bridge');
var ondemandContainer = document.getElementById('yaktube-ondemand-container');
var searchResult = searchMount.querySelector('.search-result');
if (!bridge) { if (!bridge) {
bridge = document.createElement('div'); bridge = document.createElement('div');
bridge.id = 'yaktube-fediverse-bridge'; bridge.id = 'yaktube-fediverse-bridge';
bridge.className = 'yaktube-fediverse-bridge'; bridge.className = 'yaktube-fediverse-bridge';
bridge.setAttribute('role', 'region'); bridge.setAttribute('role', 'region');
bridge.setAttribute('aria-label', 'Fediverse Video Arama Ağı ve Kapsam Seçimi'); bridge.setAttribute('aria-label', 'Fediverse Video Arama Ağı ve Kapsam Seçimi');
var searchResult = document.querySelector('.search-result, my-search .search-result');
var ondemandContainer = document.getElementById('yaktube-ondemand-container');
if (searchResult && searchResult.parentNode) {
searchResult.parentNode.insertBefore(bridge, searchResult);
} else if (ondemandContainer && ondemandContainer.parentNode) {
ondemandContainer.parentNode.insertBefore(bridge, ondemandContainer.nextSibling);
} else {
var mainCol = document.querySelector('my-search, main, .main-col') || document.body;
mainCol.appendChild(bridge);
} }
// Ensure bridge is always strictly inside searchMount
if (ondemandContainer && ondemandContainer.parentElement === searchMount) {
if (ondemandContainer.nextSibling !== bridge) {
searchMount.insertBefore(bridge, ondemandContainer.nextSibling);
}
} else if (searchResult && searchResult.parentElement === searchMount) {
if (bridge.nextSibling !== searchResult) {
searchMount.insertBefore(bridge, searchResult);
}
} else if (bridge.parentElement !== searchMount) {
searchMount.appendChild(bridge);
} }
var isFediverse = currentSearchTarget === 'search-index'; var isFediverse = currentSearchTarget === 'search-index';
@@ -2199,8 +2206,8 @@ try {
'</div>' + '</div>' +
'</div>'; '</div>';
var mainMount = var mainMount = document.querySelector('my-search, my-search-results, .main-col .main-row, .main-col, main');
document.querySelector('my-search, my-search-results, router-outlet, main, .main-col') || document.body; if (!mainMount) mainMount = document.querySelector('.main-col');
if (mainMount && mainMount.firstChild) { if (mainMount && mainMount.firstChild) {
mainMount.insertBefore(liveContainer, mainMount.firstChild); mainMount.insertBefore(liveContainer, mainMount.firstChild);
} else if (mainMount) { } else if (mainMount) {
@@ -2491,6 +2498,14 @@ try {
var query = searchParam.trim(); var query = searchParam.trim();
// Clean up any stray containers mistakenly attached directly to document.body
try {
var strays = document.querySelectorAll('body > #yaktube-ondemand-container, body > #yaktube-fediverse-bridge');
strays.forEach(function (s) {
s.remove();
});
} catch (e) {}
// Ensure Fediverse Global Search (SepiaSearch) is default target if not specified in URL // Ensure Fediverse Global Search (SepiaSearch) is default target if not specified in URL
if (!url.searchParams.has('searchTarget')) { if (!url.searchParams.has('searchTarget')) {
url.searchParams.set('searchTarget', 'search-index'); url.searchParams.set('searchTarget', 'search-index');
@@ -2499,34 +2514,40 @@ try {
} }
var currentSearchTarget = url.searchParams.get('searchTarget') || 'search-index'; var currentSearchTarget = url.searchParams.get('searchTarget') || 'search-index';
// CRITICAL: We MUST wait for Angular to mount the search view (<my-search>)!
// If we inject before <my-search> exists, it lands in document.body before <my-app>,
// which pushes the entire site header, sidebar, and layout down the page.
var searchMount = document.querySelector('my-search, my-search-results');
if (!searchMount) {
return;
}
var queryKey = query + '___' + currentSearchTarget; var queryKey = query + '___' + currentSearchTarget;
var lastQueryKey = lastQuery + '___' + lastSearchTarget; var lastQueryKey = lastQuery + '___' + lastSearchTarget;
var container = document.getElementById('yaktube-ondemand-container');
var nativeResults = searchMount.querySelector('.search-result');
if (queryKey === lastQueryKey) { if (queryKey === lastQueryKey) {
var existingBridge = document.getElementById('yaktube-fediverse-bridge'); if (container && container.parentElement !== searchMount) {
if (!existingBridge && document.querySelector('my-search')) { searchMount.insertBefore(container, nativeResults || searchMount.firstChild);
ensureFediverseBridge(query, currentSearchTarget);
} }
ensureFediverseBridge(query, currentSearchTarget);
return; return;
} }
lastQuery = query; lastQuery = query;
lastSearchTarget = currentSearchTarget; lastSearchTarget = currentSearchTarget;
var container = document.getElementById('yaktube-ondemand-container');
if (!container) { if (!container) {
container = document.createElement('div'); container = document.createElement('div');
container.id = 'yaktube-ondemand-container'; container.id = 'yaktube-ondemand-container';
container.className = 'yaktube-ondemand-section'; container.className = 'yaktube-ondemand-section';
container.setAttribute('role', 'region'); container.setAttribute('role', 'region');
container.setAttribute('aria-label', 'Canlı YouTube ve ' + getInstanceName() + ' Arama Sonuçları'); container.setAttribute('aria-label', 'Canlı YouTube ve ' + getInstanceName() + ' Arama Sonuçları');
searchMount.insertBefore(container, nativeResults || searchMount.firstChild);
var mainContent = } else if (container.parentElement !== searchMount) {
document.querySelector('my-search, my-search-results, router-outlet, main, .main-col') || document.body; searchMount.insertBefore(container, nativeResults || searchMount.firstChild);
if (mainContent && mainContent.firstChild) {
mainContent.insertBefore(container, mainContent.firstChild);
} else if (mainContent) {
mainContent.appendChild(container);
}
} }
container.innerHTML = container.innerHTML =
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "peertube-plugin-yaktube-ondemand", "name": "peertube-plugin-yaktube-ondemand",
"version": "1.5.0", "version": "1.5.1",
"description": "Accessible On-Demand YouTube Import, Live Streams, Smart Recommendations, Sleep Timer, Touch Gestures, Voice Assistant & A11y Engine for PeerTube", "description": "Accessible On-Demand YouTube Import, Live Streams, Smart Recommendations, Sleep Timer, Touch Gestures, Voice Assistant & A11y Engine for PeerTube",
"main": "main.js", "main": "main.js",
"library": "./main.js", "library": "./main.js",