1// Define reusable constants 2const WARNING_STYLES = 3 'display: flex; align-items: center; justify-content: center; padding: 10px; text-align: center; gap: 8px;'; 4const CONTAINER_STYLES = 'text-align: center; width: 100%;'; 5const COLOR_SCHEMES = { 6 adblock_warning: { 7 background: 'rgba(250, 176, 5, .1)', 8 color: '#e67700', 9 icon: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-ad-off"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 5h10a2 2 0 0 1 2 2v10m-2 2h-14a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2" /><path d="M7 15v-4a2 2 0 0 1 2 -2m2 2v4" /><path d="M7 13h4" /><path d="M17 9v4" /><path d="M16.115 12.131c.33 .149 .595 .412 .747 .74" /><path d="M3 3l18 18" /></svg>` 10 }, 11 translate_warning: { 12 background: 'rgba(34, 139, 230, .1)', 13 color: '#1864ab', 14 icon: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-language"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M4 5h7" /><path d="M9 3v2c0 4.418 -2.239 8 -5 8" /><path d="M5 9c0 2.144 2.952 3.908 6.7 4" /><path d="M12 20l4 -9l4 9" /><path d="M19.1 18h-6.2" /></svg>` 15 } 16}; 17const WARNINGS = { 18 adblock_warning: 19 'Using Adblock may cause navigation issues. Please disable Adblock for a better experience', 20 translate_warning: 'If you experience issues with the interface, please consider disabling translations' 21}; 22 23let el = document.getElementById('__warning__'); 24if (!el) { 25 el = document.createElement('div'); 26 el.setAttribute('id', '__warning__'); 27 document.body.prepend(el); 28} 29 30// Helper to apply styles 31function applyStyles(element, styles) { 32 if (!element) { 33 return; 34 } 35 36 const currentStyle = element.getAttribute('style') || ''; 37 element.setAttribute('style', currentStyle + styles); 38} 39 40// Add a single warning 41function addWarning(message, warningType) { 42 const existingMessage = el.innerText; 43 if (!existingMessage.includes(message)) { 44 const warningItem = document.createElement('div'); 45 const {background, color, icon} = COLOR_SCHEMES[warningType]; 46 47 applyStyles(warningItem, `${WARNING_STYLES}background-color: ${background}; color: ${color};`); 48 warningItem.innerHTML = `${icon}<span>${message}</span>`; 49 el.appendChild(warningItem); 50 } 51 52 el.setAttribute('style', CONTAINER_STYLES); 53} 54 55// Monitor language changes 56const originalLanguage = document.documentElement.lang; 57const observer = new MutationObserver(() => { 58 const lang = document.documentElement.lang; 59 if (lang !== 'en' && lang !== originalLanguage) { 60 addWarning(WARNINGS.translate_warning, 'translate_warning'); 61 } else if (lang === 'en') { 62 const warningItems = el.querySelectorAll('div'); 63 warningItems.forEach((item) => { 64 if (item.innerText.includes(WARNINGS.translate_warning)) { 65 item.remove(); 66 } 67 }); 68 } 69}); 70 71function detectAdblocker(callback) { 72 const adBait = document.createElement('div'); 73 adBait.setAttribute('class', 'ads-banner'); // Class name often targeted by ad blockers 74 adBait.setAttribute('style', 'position: absolute; top: -9999px; height: 10px;'); // Hidden visually but present in the DOM 75 document.body.appendChild(adBait); 76 77 // Use a timeout to check if the element is removed or hidden 78 setTimeout(() => { 79 const isAdblockActive = !adBait.offsetParent; // `offsetParent` will be null if removed or hidden 80 document.body.removeChild(adBait); // Clean up the bait element 81 callback(isAdblockActive); 82 }, 100); // Arbitrary small delay to allow the ad blocker time to process 83} 84 85// Example usage 86detectAdblocker((isBlocked) => { 87 if (isBlocked) { 88 addWarning(WARNINGS.adblock_warning, 'adblock_warning'); 89 } 90}); 91 92observer.observe(document.documentElement, { 93 attributes: true, 94 attributeFilter: ['lang'] 95});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.