Deploy
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
(function(){
|
||||||
|
let enabled=false,overlay=null,badge=null;
|
||||||
|
function init(){
|
||||||
|
if(document.getElementById('__vula_ov'))return;
|
||||||
|
overlay=document.createElement('div');
|
||||||
|
overlay.id='__vula_ov';
|
||||||
|
overlay.style.cssText='position:fixed;pointer-events:none;border:2px solid #f97316;border-radius:3px;z-index:999999;transition:top .08s,left .08s,width .08s,height .08s;display:none;box-sizing:border-box;';
|
||||||
|
badge=document.createElement('div');
|
||||||
|
badge.id='__vula_badge';
|
||||||
|
badge.style.cssText='position:fixed;background:#f97316;color:#fff;font:bold 11px/1.4 monospace;padding:3px 8px;border-radius:3px;z-index:1000000;pointer-events:none;display:none;white-space:nowrap;';
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
document.body.appendChild(badge);
|
||||||
|
}
|
||||||
|
function cap(s){return s.charAt(0).toUpperCase()+s.slice(1);}
|
||||||
|
function classify(el){
|
||||||
|
let sec='',n=el;
|
||||||
|
while(n&&n!==document.body){
|
||||||
|
// data-vula-section injected by AICodeValidator post-pass — most reliable source
|
||||||
|
if(n.dataset&&n.dataset.vulaSection){sec=n.dataset.vulaSection;break;}
|
||||||
|
const cls=(n.className||'').toString(),tag=n.tagName.toLowerCase();
|
||||||
|
if(/hero|about|services|contact|team|pricing|faq|gallery|testimonial|footer|header|navigation/i.test(cls)){
|
||||||
|
sec=cls.split(' ').find(c=>/hero|about|services|contact|team|pricing|faq|gallery|testimonial|footer|header|navigation/i.test(c))||tag;break;
|
||||||
|
}
|
||||||
|
if(['section','nav','header','footer'].includes(tag)){sec=tag;break;}
|
||||||
|
n=n.parentElement;
|
||||||
|
}
|
||||||
|
const tag=el.tagName.toLowerCase();
|
||||||
|
let type='element',label='';
|
||||||
|
if(tag==='img'){type='image';label=el.alt||'Image';}
|
||||||
|
else if(tag==='button'||(tag==='a'&&el.href)){type='button';label=(el.textContent||'').trim().slice(0,30)||'Button';}
|
||||||
|
else if(/^h[1-4]$/.test(tag)){type='heading';label=(el.textContent||'').trim().slice(0,40)||'Heading';}
|
||||||
|
else if(tag==='p'||tag==='span'){type='text';label=(el.textContent||'').trim().slice(0,40)||'Text';}
|
||||||
|
else if(tag==='input'||tag==='textarea'){type='input';label=el.placeholder||el.name||'Input';}
|
||||||
|
else{type='section';label=sec||tag;}
|
||||||
|
return{section:sec,type,label,tag,className:(el.className||'').toString()};
|
||||||
|
}
|
||||||
|
function hl(el){
|
||||||
|
if(!overlay)return;
|
||||||
|
const r=el.getBoundingClientRect();
|
||||||
|
overlay.style.cssText=overlay.style.cssText;
|
||||||
|
overlay.style.display='block';
|
||||||
|
overlay.style.top=(r.top-2)+'px';overlay.style.left=(r.left-2)+'px';
|
||||||
|
overlay.style.width=(r.width+4)+'px';overlay.style.height=(r.height+4)+'px';
|
||||||
|
const info=classify(el);
|
||||||
|
badge.style.display='block';
|
||||||
|
badge.textContent=(info.section?cap(info.section)+' › ':'')+info.label;
|
||||||
|
badge.style.top=Math.max(4,r.top-24)+'px';badge.style.left=r.left+'px';
|
||||||
|
}
|
||||||
|
function over(e){if(!enabled)return;e.stopPropagation();init();hl(e.target);}
|
||||||
|
function sendToParent(msg){
|
||||||
|
// Works in both iframe (window.parent) and new tab (window.opener)
|
||||||
|
var t=window.parent!==window?window.parent:(window.opener||null);
|
||||||
|
if(t)t.postMessage(msg,'*');
|
||||||
|
}
|
||||||
|
function click(e){
|
||||||
|
if(!enabled)return;e.preventDefault();e.stopPropagation();
|
||||||
|
var info=classify(e.target);
|
||||||
|
// Use elementType to avoid overwriting the message type field
|
||||||
|
sendToParent({type:'vula:selected',elementType:info.type,section:info.section,label:info.label,tag:info.tag,className:info.className});
|
||||||
|
}
|
||||||
|
function enable(){enabled=true;init();document.addEventListener('mouseover',over,true);document.addEventListener('click',click,true);document.body.style.cursor='crosshair';}
|
||||||
|
function disable(){enabled=false;document.removeEventListener('mouseover',over,true);document.removeEventListener('click',click,true);document.body.style.cursor='';if(overlay){overlay.style.display='none';badge.style.display='none';}}
|
||||||
|
window.addEventListener('message',function(e){
|
||||||
|
if(!e.data)return;
|
||||||
|
if(e.data.type==='vula:enable')enable();
|
||||||
|
else if(e.data.type==='vula:disable')disable();
|
||||||
|
});
|
||||||
|
// Announce ready so IDE can re-send enable state after iframe reload
|
||||||
|
function announceReady(){sendToParent({type:'vula:ready'});}
|
||||||
|
if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',announceReady);}
|
||||||
|
else{announceReady();}
|
||||||
|
}());
|
||||||
Reference in New Issue
Block a user