Azure DevOps Archive Highlighter v1.0.0

← Back to User Scripts

Script Content

// ==UserScript==
// @name         Azure DevOps: Archive Highlighter
// @namespace    https://www.timhilton.xyz/user-scripts
// @version      1.0.1
// @description  Highlight "ARCHIVE - DO NOT USE" wiki in search results
// @author       Tim Hilton using Claude
// @match        https://dev.azure.com/*/_search*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const LOG_PREFIX = '[Azure DevOps: Archive Highlighter]';

    // Function to highlight archive spans
    function highlightArchiveSpans() {
        console.debug(`${LOG_PREFIX} Checking for archive spans`);
        
        let highlightedCount = 0;
        document.querySelectorAll('.project-and-wiki span').forEach(span => {
            if (span.textContent.trim() === 'ARCHIVE - DO NOT USE') {
                if (span.style.border !== '3px solid red') {
                    span.style.border = '3px solid red';
                    highlightedCount++;
                }
            }
        });
        
        if (highlightedCount > 0) {
            console.log(`${LOG_PREFIX} ✅ Highlighted ${highlightedCount} archive spans`);
        }
    }

    console.debug(`${LOG_PREFIX} Initializing script`);

    // Initial highlight
    console.debug(`${LOG_PREFIX} Running initial highlight`);
    highlightArchiveSpans();

    // Set up mutation observer
    const targetNode = document.querySelector('.search-view-container');

    if (targetNode) {
        console.debug(`${LOG_PREFIX} Search view container found, setting up observer`);
        
        let observerFireCount = 0;
        const observer = new MutationObserver((mutations) => {
            observerFireCount++;
            console.debug(`${LOG_PREFIX} MutationObserver fired (count: ${observerFireCount})`);
            highlightArchiveSpans();
        });

        observer.observe(targetNode, {
            childList: true,
            subtree: true
        });

        console.log(`${LOG_PREFIX} ✅ Observer attached to search view container`);
    } else {
        console.debug(`${LOG_PREFIX} Search view container not found, setting up delayed observer`);
        
        // If container isn't found immediately, wait for it
        let containerObserverFireCount = 0;
        const containerObserver = new MutationObserver((mutations) => {
            containerObserverFireCount++;
            console.debug(`${LOG_PREFIX} Container observer fired (count: ${containerObserverFireCount})`);
            
            const container = document.querySelector('.search-view-container');
            if (container) {
                console.debug(`${LOG_PREFIX} Search view container found, setting up main observer`);
                
                let observerFireCount = 0;
                const observer = new MutationObserver(() => {
                    observerFireCount++;
                    console.debug(`${LOG_PREFIX} MutationObserver fired (count: ${observerFireCount})`);
                    highlightArchiveSpans();
                });

                observer.observe(container, {
                    childList: true,
                    subtree: true
                });

                containerObserver.disconnect();
                console.log(`${LOG_PREFIX} ✅ Observer attached to search view container (delayed)`);
            }
        });

        containerObserver.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    console.log(`${LOG_PREFIX} 🎉 Script initialized successfully`);
})();