Skip to content

Instantly share code, notes, and snippets.

@stanley2058
Last active June 20, 2025 06:39
Show Gist options
  • Save stanley2058/472b3b9bd21d187e65e26b2fd71aa340 to your computer and use it in GitHub Desktop.
Save stanley2058/472b3b9bd21d187e65e26b2fd71aa340 to your computer and use it in GitHub Desktop.
Highlight all `ui-` class on a web page
// ==UserScript==
// @name HackMD `ui-` classes highlighter
// @namespace http://hackmd.io/
// @version 0.1.2
// @description Show all `ui-` classes
// @author stanley2058, Yukaii
// @match https://hackmd.io/*
// @match https://local.localhost/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=hackmd.io
// @grant GM.getValue
// @grant GM.setValue
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// ==/UserScript==
const setVal = (k, v) => typeof GM !== 'undefined' ? GM.setValue(k, v) : Promise.resolve(localStorage.setItem(k, v));
const getVal = (k, v) => typeof GM !== 'undefined' ? GM.getValue(k, v) : Promise.resolve(localStorage.getItem(k) ?? v);
(async function() {
let highlighting = false;
let overlays = new Map();
// Add tooltip styles
const style = document.createElement('style');
style.textContent = `
#highlight-toggle {
position: relative;
}
#highlight-toggle::after {
content: attr(title);
position: absolute;
background: #333;
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
white-space: pre;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s, visibility 0.2s;
pointer-events: none;
bottom: 120%;
left: 50%;
transform: translateX(-50%);
}
#highlight-toggle::before {
content: '';
position: absolute;
border: 5px solid transparent;
border-top-color: #333;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s, visibility 0.2s;
pointer-events: none;
bottom: calc(120% - 10px);
left: 50%;
transform: translateX(-50%);
}
#highlight-toggle:hover::after,
#highlight-toggle:hover::before {
opacity: 1;
visibility: visible;
}
`;
document.head.appendChild(style);
function validatePosition(position) {
const defaultPosition = { left: '10px', bottom: '10px' };
if (!position) return defaultPosition;
const left = parseInt(position.left);
const bottom = parseInt(position.bottom);
if (isNaN(left) || isNaN(bottom) ||
left < 0 || left > window.innerWidth - 40 ||
bottom < 0 || bottom > window.innerHeight - 40) {
return defaultPosition;
}
return {
left: `${left}px`,
bottom: `${bottom}px`
};
}
const savedPosition = validatePosition(JSON.parse(await getVal('highlightBtnPosition', null)));
const isVisible = await getVal('highlightBtnVisible') !== 'false';
const toggleBtn = document.createElement('button');
toggleBtn.id = 'highlight-toggle';
toggleBtn.setAttribute('aria-label', 'Toggle UI Class Highlighter');
toggleBtn.setAttribute('title', 'Toggle UI Class Highlighter\nLeft click: Toggle highlight\nRight click: Hide button\nCtrl+click: Remove overlay');
toggleBtn.setAttribute('draggable', 'true');
Object.assign(toggleBtn.style, {
position: 'fixed',
left: savedPosition.left,
bottom: savedPosition.bottom,
zIndex: '10002',
padding: '8px',
background: '#FFA500',
border: 'none',
borderRadius: '50%',
cursor: 'pointer',
width: '40px',
height: '40px',
display: isVisible ? 'flex' : 'none',
alignItems: 'center',
justifyContent: 'center',
opacity: '0.95',
});
toggleBtn.innerHTML = '🔍';
toggleBtn.addEventListener('mouseenter', () => {
toggleBtn.style.background = '#FF8C00';
});
toggleBtn.addEventListener('mouseleave', () => {
toggleBtn.style.background = '#FFA500';
});
const dropOverlay = document.createElement('div');
Object.assign(dropOverlay.style, {
position: 'fixed',
left: 0,
top: 0,
zIndex: '10001',
width: '100dvw',
height: '100dvh',
display: 'none',
});
let isDragging = false;
let currentX;
let currentY;
let initialX;
let initialY;
let xOffset = 0;
let yOffset = 0;
toggleBtn.addEventListener('dragstart', (e) => {
dropOverlay.style.display = 'block';
initialX = e.clientX - xOffset;
initialY = e.clientY - yOffset;
});
dropOverlay.addEventListener('dragover', (e) => {
e.preventDefault();
});
dropOverlay.addEventListener('drop', (e) => {
dropOverlay.style.display = 'none';
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
xOffset = currentX;
yOffset = currentY;
const { width, height } = toggleBtn.getBoundingClientRect();
const left = Math.max(0, Math.min(window.innerWidth - 40, e.clientX - width / 2));
const bottom = Math.max(0, Math.min(window.innerHeight - 40, window.innerHeight - e.clientY - height / 2));
toggleBtn.style.left = `${left}px`;
toggleBtn.style.bottom = `${bottom}px`;
setVal('highlightBtnPosition', JSON.stringify({
left: toggleBtn.style.left,
bottom: toggleBtn.style.bottom
}));
});
toggleBtn.addEventListener('contextmenu', (e) => {
e.preventDefault();
toggleBtn.style.display = 'none';
setVal('highlightBtnVisible', 'false');
});
async function enableUIClassDebug () {
const currentPosition = validatePosition(JSON.parse(await getVal('highlightBtnPosition', null)));
toggleBtn.style.left = currentPosition.left;
toggleBtn.style.bottom = currentPosition.bottom;
toggleBtn.style.display = 'flex';
setVal('highlightBtnVisible', 'true');
setVal('highlightBtnPosition', JSON.stringify(currentPosition));
console.log('UI Class Debug enabled. The button has been restored to a valid position.');
};
window.enableUIClassDebug = enableUIClassDebug;
function getTrackingClasses(element) {
return Array.from(element.classList)
.filter(className => className.startsWith('ui-'));
}
function createOverlay(element) {
const rect = element.getBoundingClientRect();
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const overlay = document.createElement('div');
Object.assign(overlay.style, {
position: 'absolute',
background: 'rgba(255, 255, 0, 0.3)',
border: '2px solid #FFA500',
zIndex: '10000',
left: (rect.left + scrollLeft) + 'px',
top: (rect.top + scrollTop) + 'px',
width: rect.width + 'px',
height: rect.height + 'px'
});
const label = document.createElement('div');
Object.assign(label.style, {
position: 'absolute',
background: '#FFA500',
color: 'black',
padding: '2px 6px',
borderRadius: '3px',
fontSize: '12px',
fontFamily: 'monospace',
zIndex: '10001',
display: 'none',
left: (rect.left + scrollLeft) + 'px',
whiteSpace: 'nowrap',
transform: ''
});
const trackingClasses = getTrackingClasses(element).join(', ');
label.textContent = trackingClasses;
overlay.addEventListener('mouseenter', () => {
const viewportHeight = window.innerHeight;
const viewportWidth = window.innerWidth;
const elementCenterY = rect.top + (rect.height / 2);
const elementCenterX = rect.left + (rect.width / 2);
if (elementCenterY < viewportHeight / 2) {
label.style.top = (rect.bottom + scrollTop + 4) + 'px';
} else {
label.style.top = (rect.top + scrollTop - 24) + 'px';
}
if (elementCenterX < viewportWidth / 2) {
label.style.transform = '';
} else {
label.style.transform = `translateX(calc(-100% + ${rect.width}px))`;
}
label.style.display = 'block';
});
overlay.addEventListener('mouseleave', () => {
label.style.display = 'none';
});
overlay.addEventListener('click', (e) => {
window.navigator.clipboard
.writeText(label.innerText)
.catch(console.error);
if (!e.ctrlKey && !e.metaKey) return;
document.body.removeChild(overlay);
document.body.removeChild(label);
e.preventDefault();
e.stopPropagation();
});
document.body.appendChild(overlay);
document.body.appendChild(label);
return [overlay, label];
}
function toggleHighlights() {
highlighting = !highlighting;
if (highlighting) {
$("[class^='ui-'],[class*=' ui-']").each((_, element) => {
const [overlay, label] = createOverlay(element);
overlays.set(element, [overlay, label]);
});
} else {
for (const [overlay, label] of overlays.values()) {
overlay.remove();
label.remove();
}
overlays.clear();
}
}
toggleBtn.addEventListener('click', toggleHighlights);
document.body.appendChild(dropOverlay);
document.body.appendChild(toggleBtn);
window.addEventListener('keydown', async (e) => {
const shouldTriggerToggle =
(e.ctrlKey && e.shiftKey && e.key === 'U') ||
(e.metaKey && e.shiftKey && e.key === 'u');
const shouldToggleButtonDisplay =
(e.ctrlKey && e.shiftKey && e.key === 'H') ||
(e.metaKey && e.shiftKey && e.key === 'h');
if (shouldTriggerToggle) {
e.preventDefault();
toggleHighlights();
}
if (shouldToggleButtonDisplay) {
e.preventDefault();
const disabled = await getVal('highlightBtnVisible') === 'false';
if (disabled) {
enableUIClassDebug();
} else {
toggleBtn.style.display = 'none';
setVal('highlightBtnVisible', 'false');
}
}
});
})();
@stanley2058
Copy link
Author

stanley2058 commented Jan 11, 2025

  • Clicking on the overlay will copy the label text to clipboard
  • Ctrl / Cmd + Left click to temporarily remove an overlay
  • Ctrl + Shift + u to toggle (Cmd + Shift + u on Mac)

@Yukaii
Copy link

Yukaii commented Jan 12, 2025

Made some improvements

  • Update the button UI style with tooltip and icon
  • Right click to dismiss the button
  • expose enableUIClassDebug to re-enable the UI
スクリーンショット 2025-01-12 昼2 30 57
// ==UserScript==
// @name         HackMD `ui-` classes highlighter
// @namespace    http://hackmd.io/
// @version      0.1.0
// @description  Show all `ui-` classes
// @author       stanley2058
// @match        https://hackmd.io/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=hackmd.io
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// @grant        none
// ==/UserScript==

(function() {
    let highlighting = false;
    let overlays = new Map();

    // Add tooltip styles
    const style = document.createElement('style');
    style.textContent = `
        #highlight-toggle {
            position: relative;
        }
        
        #highlight-toggle::after {
            content: attr(title);
            position: absolute;
            background: #333;
            color: white;
            padding: 4px 8px;
            border-radius: 4px;
            font-size: 12px;
            white-space: pre;
            opacity: 0;
            visibility: hidden;
            transition: opacity 0.2s, visibility 0.2s;
            pointer-events: none;
            bottom: 120%;
            left: 50%;
            transform: translateX(-50%);
        }
        
        #highlight-toggle::before {
            content: '';
            position: absolute;
            border: 5px solid transparent;
            border-top-color: #333;
            opacity: 0;
            visibility: hidden;
            transition: opacity 0.2s, visibility 0.2s;
            pointer-events: none;
            bottom: calc(120% - 10px);
            left: 50%;
            transform: translateX(-50%);
        }
        
        #highlight-toggle:hover::after,
        #highlight-toggle:hover::before {
            opacity: 1;
            visibility: visible;
        }
    `;
    document.head.appendChild(style);

    function validatePosition(position) {
        const defaultPosition = { left: '10px', bottom: '10px' };
        
        if (!position) return defaultPosition;

        const left = parseInt(position.left);
        const bottom = parseInt(position.bottom);

        if (isNaN(left) || isNaN(bottom) ||
            left < 0 || left > window.innerWidth - 40 ||
            bottom < 0 || bottom > window.innerHeight - 40) {
            return defaultPosition;
        }

        return {
            left: `${left}px`,
            bottom: `${bottom}px`
        };
    }

    const savedPosition = validatePosition(JSON.parse(localStorage.getItem('highlightBtnPosition')));
    const isVisible = localStorage.getItem('highlightBtnVisible') !== 'false';

    const toggleBtn = document.createElement('button');
    toggleBtn.id = 'highlight-toggle';
    toggleBtn.setAttribute('aria-label', 'Toggle UI Class Highlighter');
    toggleBtn.setAttribute('title', 'Toggle UI Class Highlighter\nLeft click: Toggle highlight\nRight click: Hide button\nCtrl+click: Remove overlay');
    
    Object.assign(toggleBtn.style, {
        position: 'fixed',
        left: savedPosition.left,
        bottom: savedPosition.bottom,
        zIndex: '10002',
        padding: '8px',
        background: '#FFA500',
        border: 'none',
        borderRadius: '50%',
        cursor: 'pointer',
        width: '40px',
        height: '40px',
        display: isVisible ? 'flex' : 'none',
        alignItems: 'center',
        justifyContent: 'center',
        opacity: '0.95',
    });

    toggleBtn.innerHTML = '🔍';

    toggleBtn.addEventListener('mouseenter', () => {
        toggleBtn.style.background = '#FF8C00';
    });
    toggleBtn.addEventListener('mouseleave', () => {
        toggleBtn.style.background = '#FFA500';
    });

    let isDragging = false;
    let currentX;
    let currentY;
    let initialX;
    let initialY;
    let xOffset = 0;
    let yOffset = 0;

    toggleBtn.addEventListener('mousedown', dragStart);
    document.addEventListener('mousemove', drag);
    document.addEventListener('mouseup', dragEnd);

    function dragStart(e) {
        if (e.button === 2) return;
        initialX = e.clientX - xOffset;
        initialY = e.clientY - yOffset;
        if (e.target === toggleBtn) {
            isDragging = true;
        }
    }

    function drag(e) {
        if (isDragging) {
            e.preventDefault();
            currentX = e.clientX - initialX;
            currentY = e.clientY - initialY;
            xOffset = currentX;
            yOffset = currentY;

            const left = Math.max(0, Math.min(window.innerWidth - 40, e.clientX));
            const bottom = Math.max(0, Math.min(window.innerHeight - 40, window.innerHeight - e.clientY));

            toggleBtn.style.left = `${left}px`;
            toggleBtn.style.bottom = `${bottom}px`;
        }
    }

    function dragEnd() {
        if (!isDragging) return;
        isDragging = false;
        localStorage.setItem('highlightBtnPosition', JSON.stringify({
            left: toggleBtn.style.left,
            bottom: toggleBtn.style.bottom
        }));
    }

    toggleBtn.addEventListener('contextmenu', (e) => {
        e.preventDefault();
        toggleBtn.style.display = 'none';
        localStorage.setItem('highlightBtnVisible', 'false');
    });

    window.enableUIClassDebug = function() {
        const currentPosition = validatePosition(JSON.parse(localStorage.getItem('highlightBtnPosition')));
        toggleBtn.style.left = currentPosition.left;
        toggleBtn.style.bottom = currentPosition.bottom;
        
        toggleBtn.style.display = 'flex';
        localStorage.setItem('highlightBtnVisible', 'true');
        localStorage.setItem('highlightBtnPosition', JSON.stringify(currentPosition));
        
        console.log('UI Class Debug enabled. The button has been restored to a valid position.');
    };

    function getTrackingClasses(element) {
        return Array.from(element.classList)
            .filter(className => className.startsWith('ui-'));
    }

    function createOverlay(element) {
        const rect = element.getBoundingClientRect();
        const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
        const scrollTop = window.pageYOffset || document.documentElement.scrollTop;

        const overlay = document.createElement('div');
        Object.assign(overlay.style, {
            position: 'absolute',
            background: 'rgba(255, 255, 0, 0.3)',
            border: '2px solid #FFA500',
            zIndex: '10000',
            left: (rect.left + scrollLeft) + 'px',
            top: (rect.top + scrollTop) + 'px',
            width: rect.width + 'px',
            height: rect.height + 'px'
        });

        const label = document.createElement('div');
        Object.assign(label.style, {
            position: 'absolute',
            background: '#FFA500',
            color: 'black',
            padding: '2px 6px',
            borderRadius: '3px',
            fontSize: '12px',
            fontFamily: 'monospace',
            zIndex: '10001',
            display: 'none',
            left: (rect.left + scrollLeft) + 'px',
            whiteSpace: 'nowrap',
            transform: ''
        });

        const trackingClasses = getTrackingClasses(element).join(', ');
        label.textContent = trackingClasses;

        overlay.addEventListener('mouseenter', () => {
            const viewportHeight = window.innerHeight;
            const viewportWidth = window.innerWidth;
            const elementCenterY = rect.top + (rect.height / 2);
            const elementCenterX = rect.left + (rect.width / 2);

            if (elementCenterY < viewportHeight / 2) {
                label.style.top = (rect.bottom + scrollTop + 4) + 'px';
            } else {
                label.style.top = (rect.top + scrollTop - 24) + 'px';
            }

            if (elementCenterX < viewportWidth / 2) {
                label.style.transform = '';
            } else {
                label.style.transform = `translateX(calc(-100% + ${rect.width}px))`;
            }

            label.style.display = 'block';
        });

        overlay.addEventListener('mouseleave', () => {
            label.style.display = 'none';
        });

        overlay.addEventListener('click', (e) => {
            window.navigator.clipboard
                .writeText(label.innerText)
                .catch(console.error);
            if (!e.ctrlKey && !e.metaKey) return;
            document.body.removeChild(overlay);
            document.body.removeChild(label);
            e.preventDefault();
            e.stopPropagation();
        });

        document.body.appendChild(overlay);
        document.body.appendChild(label);

        return [overlay, label];
    }

    function toggleHighlights() {
        highlighting = !highlighting;

        if (highlighting) {
            $("[class^='ui-'],[class*=' ui-']").each((_, element) => {
                const [overlay, label] = createOverlay(element);
                overlays.set(element, [overlay, label]);
            });
        } else {
            for (const [overlay, label] of overlays.values()) {
                overlay.remove();
                label.remove();
            }
            overlays.clear();
        }
    }

    toggleBtn.addEventListener('click', toggleHighlights);
    document.body.appendChild(toggleBtn);

    window.addEventListener('keydown', (e) => {
        const shouldTriggerToggle =
              (e.ctrlKey && e.shiftKey && e.key === 'U') ||
              (e.metaKey && e.shiftKey && e.key === 'u');

        const shouldToggleButtonDisplay =
              (e.ctrlKey && e.shiftKey && e.key === 'H') ||
              (e.metaKey && e.shiftKey && e.key === 'h');

        if (shouldTriggerToggle) {
            e.preventDefault();
            toggleHighlights();
        }
        if (shouldToggleButtonDisplay) {
            e.preventDefault();
            const disabled = toggleBtn.getAttribute('data-clickable') === 'false';
            if (disabled) {
                toggleBtn.style.opacity = '0.95';
                toggleBtn.style.pointerEvents = 'auto';
                toggleBtn.setAttribute('data-clickable', 'true');
            } else {
                toggleBtn.style.opacity = '0.3';
                toggleBtn.style.pointerEvents = 'none';
                toggleBtn.setAttribute('data-clickable', 'false');
            }
        }
    });
})();

@stanley2058
Copy link
Author

Made some improvements

* Update the button UI style with tooltip and icon

* Right click to dismiss the button

* expose `enableUIClassDebug` to re-enable the UI
スクリーンショット 2025-01-12 昼2 30 57

I've changed it up a bit:

  • Use GM setValue/getValue APIs for userscript users.
  • The Ctrl/Cmd + Shift + U shortcut now binds to toggle hide or show the button.
  • Relocation now uses drag & drop event instead of mouse event to prevent triggering highlight on drop.

@stanley2058
Copy link
Author

Minified bookmarklet of v0.1.2 and instructions generated by Gemini 2.5 Pro:

How to use:

  1. Create a new bookmark in your browser.
  2. Name it something descriptive (e.g., "UI Class Highlighter").
  3. Paste the entire javascript:... code block into the URL/Location field of the bookmark.
  4. Save the bookmark.
  5. Navigate to a page you want to inspect (like HackMD).
  6. Click the bookmarklet. The orange button should appear.
javascript:void(async function(){const setVal=(k,v)=>Promise.resolve(localStorage.setItem(k,v));const getVal=(k,v)=>Promise.resolve(localStorage.getItem(k)??v);let h=!1,ov=new Map;const st=document.createElement('style');st.textContent=`#highlight-toggle{position:relative;}#highlight-toggle::after{content:attr(title);position:absolute;background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;white-space:pre;opacity:0;visibility:hidden;transition:opacity .2s,visibility .2s;pointer-events:none;bottom:120%;left:50%;transform:translateX(-50%);}#highlight-toggle::before{content:'';position:absolute;border:5px solid transparent;border-top-color:#333;opacity:0;visibility:hidden;transition:opacity .2s,visibility .2s;pointer-events:none;bottom:calc(120% - 10px);left:50%;transform:translateX(-50%);}#highlight-toggle:hover::after,#highlight-toggle:hover::before{opacity:1;visibility:visible;}`;document.head.appendChild(st);function validatePos(p){const d={left:'10px',bottom:'10px'};if(!p)return d;const l=parseInt(p.left),b=parseInt(p.bottom);return isNaN(l)||isNaN(b)||l<0||l>window.innerWidth-40||b<0||b>window.innerHeight-40?d:{left:`${l}px`,bottom:`${b}px`}}const sp=validatePos(JSON.parse(await getVal('highlightBtnPosition',null)));const vis=await getVal('highlightBtnVisible')!=='false';const b=document.createElement('button');b.id='highlight-toggle';b.setAttribute('aria-label','Toggle UI Class Highlighter');b.setAttribute('title','Toggle UI Class Highlighter\nLeft click: Toggle highlight\nRight click: Hide button\nCtrl+click: Remove overlay');b.setAttribute('draggable','true');Object.assign(b.style,{position:'fixed',left:sp.left,bottom:sp.bottom,zIndex:'10002',padding:'8px',background:'#FFA500',border:'none',borderRadius:'50%',cursor:'pointer',width:'40px',height:'40px',display:vis?'flex':'none',alignItems:'center',justifyContent:'center',opacity:'0.95'});b.innerHTML='🔍';b.addEventListener('mouseenter',()=>b.style.background='#FF8C00');b.addEventListener('mouseleave',()=>b.style.background='#FFA500');const drp=document.createElement('div');Object.assign(drp.style,{position:'fixed',left:0,top:0,zIndex:'10001',width:'100dvw',height:'100dvh',display:'none'});let isDragging=!1,cx,cy,ix,iy,xo=0,yo=0;b.addEventListener('dragstart',e=>{drp.style.display='block';ix=e.clientX-xo;iy=e.clientY-yo});drp.addEventListener('dragover',e=>e.preventDefault());drp.addEventListener('drop',e=>{drp.style.display='none';cx=e.clientX-ix;cy=e.clientY-iy;xo=cx;yo=cy;const{width:w,height:ht}=b.getBoundingClientRect(),l=Math.max(0,Math.min(window.innerWidth-40,e.clientX-w/2)),bt=Math.max(0,Math.min(window.innerHeight-40,window.innerHeight-e.clientY-ht/2));b.style.left=`${l}px`;b.style.bottom=`${bt}px`;setVal('highlightBtnPosition',JSON.stringify({left:b.style.left,bottom:b.style.bottom}))});b.addEventListener('contextmenu',e=>{e.preventDefault();b.style.display='none';setVal('highlightBtnVisible','false')});async function enableDebug(){const cp=validatePos(JSON.parse(await getVal('highlightBtnPosition',null)));b.style.left=cp.left;b.style.bottom=cp.bottom;b.style.display='flex';setVal('highlightBtnVisible','true');setVal('highlightBtnPosition',JSON.stringify(cp));console.log('UI Class Debug enabled. Button restored.')};window.enableUIClassDebug=enableDebug;function getCls(el){return Array.from(el.classList).filter(c=>c.startsWith('ui-'))}function createOv(el){const r=el.getBoundingClientRect(),sl=window.pageXOffset||document.documentElement.scrollLeft,st=window.pageYOffset||document.documentElement.scrollTop,ol=document.createElement('div');Object.assign(ol.style,{position:'absolute',background:'rgba(255,255,0,.3)',border:'2px solid #FFA500',zIndex:'10000',left:r.left+sl+'px',top:r.top+st+'px',width:r.width+'px',height:r.height+'px'});const lb=document.createElement('div');Object.assign(lb.style,{position:'absolute',background:'#FFA500',color:'black',padding:'2px 6px',borderRadius:'3px',fontSize:'12px',fontFamily:'monospace',zIndex:'10001',display:'none',left:r.left+sl+'px',whiteSpace:'nowrap',transform:''});const tc=getCls(el).join(', ');lb.textContent=tc;ol.addEventListener('mouseenter',()=>{const vh=window.innerHeight,vw=window.innerWidth,ecy=r.top+r.height/2,ecx=r.left+r.width/2;lb.style.top=ecy<vh/2?r.bottom+st+4+'px':r.top+st-24+'px';lb.style.transform=ecx<vw/2?'':`translateX(calc(-100% + ${r.width}px))`;lb.style.display='block'});ol.addEventListener('mouseleave',()=>{lb.style.display='none'});ol.addEventListener('click',e=>{window.navigator.clipboard.writeText(lb.innerText).catch(console.error);if(!e.ctrlKey&&!e.metaKey)return;document.body.removeChild(ol);document.body.removeChild(lb);e.preventDefault();e.stopPropagation()});document.body.appendChild(ol);document.body.appendChild(lb);return[ol,lb]}function toggleHl(){h=!h;if(h){document.querySelectorAll("[class^='ui-'],[class*=' ui-']").forEach(el=>{const[ol,lb]=createOv(el);ov.set(el,[ol,lb])})}else{for(const[ol,lb]of ov.values()){ol.remove();lb.remove()}ov.clear()}}b.addEventListener('click',toggleHl);document.body.appendChild(drp);document.body.appendChild(b);window.addEventListener('keydown',async e=>{const t1=(e.ctrlKey&&e.shiftKey&&e.key==='U')||(e.metaKey&&e.shiftKey&&e.key==='u');const t2=(e.ctrlKey&&e.shiftKey&&e.key==='H')||(e.metaKey&&e.shiftKey&&e.key==='h');if(t1){e.preventDefault();toggleHl()}if(t2){e.preventDefault();const d=await getVal('highlightBtnVisible')==='false';if(d){enableDebug()}else{b.style.display='none';setVal('highlightBtnVisible','false')}}})})();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment