Siteβ―Builder
Editing:
socialPromptinator-before-add-toolbar.js
writable 0666
/* Promptinator β social edition β v2025β07β22βH * --------------------------------------------------------- * Adds [Hβlabelβ~hidden text~] tokens (hidden instructions) * β’ Shows only a single ββ’β in the live prompt preview * β’ Opens a textarea editor on click / βοΈ * β’ Hidden text is still injected into the full prompt * Accepts dataβedit / dataβthink flags, Eβbutton placeholder * logic, profile autoβfill, pencil toggle, etc. (unchanged) * --------------------------------------------------------- */ export default class Promptinator { /* ββββββββββ static helpers ββββββββββ */ static _lastMeta = []; static _lastState = []; static _hasE = false; static _escAttr = s => String(s) .replace(/&/g,'&').replace(/"/g,'"') .replace(/</g,'<').replace(/>/g,'>'); /* ββββββββββ init ββββββββββ */ static init({ mount, defaultPrompt }) { const prompt = mount.dataset.prompt || defaultPrompt || mount.textContent.trim(); let template = prompt; /* β± NEW: βHβ added to the recognised cmd letters */ const RX = /\[(?:([A-DEIH]?)-)?([^~|\-\]]*)(?:-([^~\]]*))?(?:~([^~]+)~)?\]/ig; const state = {}, meta = []; /* flags -------------------------------------------------------- */ const valEdit = mount.dataset.edit ?? mount.getAttribute('edit') ?? '1'; const valThink = mount.dataset.think ?? (mount.hasAttribute('think') ? mount.getAttribute('think') : '1'); const allowEdit = valEdit !== '0' && valEdit !== 'false'; const allowThink = valThink !== '0' && valThink !== 'false'; /* profile helpers (unchanged) ---------------------------------- */ let prof = window.profileData || null; let hasProf = Boolean(prof); const nonEmpty = v => v !== null && v !== undefined && String(v).trim() !== ''; const pick = (path,f='') => path.split('.').reduce((o,k)=>o&&o[k], prof) ?? f; function applyProfile(st, mt){ if(!hasProf) return; mt.forEach((m,i)=>{ const lab=(m.lab||'').toLowerCase(); const set=v=>{ if(nonEmpty(v)) st[i]=v; }; switch(lab){ case 'handle': set(prof.handle); return; case 'slug': set(prof.slug); return; case 'name': set(prof.name||prof.display_name); return; case 'display_name': set(prof.display_name); return; case 'slogan': set(prof.slogan); return; case 'description': set(prof.description); return; case 'address': set(prof.address); return; case 'city': set(prof.city); return; case 'state': set(prof.state); return; case 'zip': set(prof.zip); return; case 'lat': set(prof.lat); return; case 'lon': set(prof.lon); return; case 'phone': set(prof.phone); return; case 'website': set(prof.website); return; case 'email': set(prof.email); return; case 'premium': set(prof.premium?'Yes':'No'); return; } const ch={ youtube:'channels.video.youtube',rumble:'channels.video.rumble', odysee:'channels.video.odysee',spotify:'channels.podcast.spotify', apple:'channels.podcast.apple',rss:'channels.podcast.rss', twitter:'channels.social.twitter',tiktok:'channels.social.tiktok', instagram:'channels.social.instagram',facebook:'channels.social.facebook', linkedin:'channels.social.linkedin',patreon:'channels.social.patreon' }; if(lab in ch){ set(pick(ch[lab])); return; } if(m.cmd==='C'){ if(lab.startsWith('service')&&Array.isArray(prof.tags)){ m.opts=prof.tags; if(!st[i].length&&prof.tags.length) st[i]=[prof.tags[0]]; } if(lab.startsWith('location')&&Array.isArray(prof.location_tags)){ m.opts=prof.location_tags; if(!st[i].length&&prof.location_tags.length) st[i]=[prof.location_tags[0]]; } } }); } /* wait for late profileData ------------------------------------ */ let tries=0; const watch=setInterval(()=>{ if(!hasProf&&window.profileData){ prof=window.profileData; hasProf=true; applyProfile(state,meta); render(); clearInterval(watch); } if(++tries>20) clearInterval(watch); },150); /* ---------- renderer ----------------------------------------- */ function render(){ meta.length=0; let idx=0; template.replace(RX,(_,cmd='',lab='',ops='',def='')=>{ lab=lab.trim(); const opts=ops.split('|').filter(Boolean); if(!(idx in state)){ state[idx]=cmd==='C' ? (def?def.split(',').map(v=>v.trim()):opts.slice(0,1)) : (def||opts[0]||lab); } meta.push({cmd:cmd||'A',lab,opts,def}); idx++; return''; }); if(!render._profApplied){ applyProfile(state,meta); render._profApplied=true; } idx=0; const html=template.replace(RX,(_,cmd='',lab='')=>{ lab=lab.trim(); const val=state[idx]; let out; if(cmd==='C'){ const list=(Array.isArray(val)?val:[val]).filter(Boolean); if(!list.length) list.push('+'); out=list.map(v=>`<span class="token" data-i="${idx}" data-label="${lab}">[${v}]</span>`).join(', '); }else if(cmd==='E'){ out=`<button class="token e-btn" data-i="${idx}" data-label="${lab}">${/^\S+@\S+\.\S+$/.test(val)?'Send':'Submit'}</button>`; }else if(cmd==='H'){ /* β± NEW β hidden instructions show only a dot */ out=`<span class="token h-dot" data-i="${idx}" data-label="${lab}" title="Hidden instruction">β’</span>`; }else{ out=`<span class="token" data-i="${idx}" data-label="${lab}">[${nonEmpty(val)?val:'+'}]</span>`; } idx++; return out; }); const hasE=meta.some(m=>m.cmd==='E'); Promptinator._hasE=hasE; const aiButtons=(allowThink&&!hasE)?` <div class="ai-buttons" style="margin-top:1em;display:flex;flex-wrap:wrap;gap:.6em;"> <a class="ai-btn chatgpt" target="_blank" style="display:inline-flex;align-items:center;gap:.3em;background:#5c3bff;color:#fff;font-weight:600;border-radius:7px;padding:.4em 1.2em;text-decoration:none;">π§ ChatGPT</a> <a class="ai-btn perplexity" target="_blank" style="display:inline-flex;align-items:center;gap:.3em;background:#22a8e5;color:#fff;font-weight:600;border-radius:7px;padding:.4em 1.2em;text-decoration:none;">π Perplexity</a> <a class="ai-btn copilot" target="_blank" style="display:inline-flex;align-items:center;gap:.3em;background:#10c775;color:#fff;font-weight:600;border-radius:7px;padding:.4em 1.2em;text-decoration:none;">π€ Copilot</a> </div>`:''; promptText.innerHTML=html.replace(/\n/g,'<br>')+aiButtons; if(allowThink&&!hasE){ let i=0; const full=template.replace(RX,()=>{ const v=state[i++]; return Array.isArray(v)?v.join(', '):v; }); promptText.querySelector('.chatgpt').href ='https://chat.openai.com/?prompt='+encodeURIComponent(full); promptText.querySelector('.perplexity').href='https://www.perplexity.ai/search?q='+encodeURIComponent(full); promptText.querySelector('.copilot').href ='https://copilot.microsoft.com/?q='+encodeURIComponent(full); } } /* render */ /* ---------- editor & event wiring ----------------------------- */ const editor=document.createElement('div'); editor.innerHTML=` <div style="display:flex;align-items:baseline;gap:.5em;"> ${allowEdit?'<span id="edit-link" style="cursor:pointer">βοΈ</span>':''} <div class="prompt-text" style="flex:1 1 auto;"></div> </div> ${allowEdit?`<form id="edit-form" style="display:none;margin-top:.6em;"> <textarea style="width:100%;min-height:90px;font-family:monospace;"></textarea> <div style="text-align:right;margin-top:.7em;"><button type="submit">SaveΒ &Β Update</button></div> </form>`:''}`; mount.innerHTML=''; mount.append(editor); const promptText=editor.querySelector('.prompt-text'); if(allowEdit){ const link = editor.querySelector('#edit-link'), form = editor.querySelector('#edit-form'), ta = form.querySelector('textarea'); link.onclick=()=>{ const closed=getComputedStyle(form).display==='none'; if(closed){ form.style.display=''; ta.value=template; ta.focus(); } else { form.style.display='none'; } }; form.onsubmit=e=>{ e.preventDefault(); template=ta.value.trim(); Object.keys(state).forEach(k=>delete state[k]); render._profApplied=false; render(); form.style.display='none'; }; } render(); /* first paint */ mount.addEventListener('click',e=>{ if(!e.target.matches('.token')) return; const i=+e.target.dataset.i, info=meta[i], val=state[i]; if(info.cmd==='E'){ Promptinator._lastMeta=meta.slice(); Promptinator._lastState=Object.assign([],state); } Promptinator._popup(info,Array.isArray(val)?val.join(', '):val,v=>{ state[i]=info.cmd==='C'?v.split(',').map(s=>s.trim()).filter(Boolean):v; render(); }); }); } /* init */ /* ---------- popup ---------------------------------------------- */ static _popup(meta,cur,done){ let dlg=document.getElementById('promptinator-dlg'); if(!dlg){ dlg=document.createElement('dialog'); dlg.id='promptinator-dlg'; document.body.append(dlg); dlg.addEventListener('click',e=>{ if(e.target===dlg) dlg.close(); }); dlg.addEventListener('cancel',e=>{ e.preventDefault(); dlg.close(); }); } const pretty=s=>s.replace(/[-_]/g,' ').replace(/\b\w/g,c=>c.toUpperCase()); const nice=meta.lab&&meta.lab.trim() ? pretty(meta.lab) : (cur || {A:'Text Input',B:'Choice',C:'Options',D:'Dropdown',E:'Send',I:'URL Picker',H:'Hidden note'}[meta.cmd] || 'Input'); const showPH = Promptinator._hasE && cur === meta.def; const phAttr = showPH ? ` placeholder="${Promptinator._escAttr(cur)}"` : ''; const valAttr= showPH ? '' : Promptinator._escAttr(cur); let inner=''; switch(meta.cmd){ case 'C':{ let opts=meta.opts; const labLow=(meta.lab||'').toLowerCase(); if(window.profileData){ if(labLow.startsWith('service')&&Array.isArray(window.profileData.tags)) opts=window.profileData.tags; if(labLow.startsWith('location')&&Array.isArray(window.profileData.location_tags)) opts=window.profileData.location_tags; } inner=`<fieldset><legend>${nice}</legend>`+ opts.map(o=>`<label><input type="checkbox" value="${o}" ${cur.split(', ').includes(o)?'checked':''}> ${o}</label>`).join('')+ `</fieldset> <div style="text-align:right;margin-top:.7em;"><button type="button">Done</button></div>`; break; } case 'A': case 'H': /* β± NEW β H uses same textarea editor */ inner=`<label>${nice}<textarea style="width:100%;font-size:1rem;" rows="4"${phAttr}>${valAttr}</textarea></label> <div style="text-align:right;margin-top:.7em;"><button type="button">Done</button></div>`; break; case 'B': inner=`<fieldset><legend>${nice}</legend>`+ meta.opts.map(o=>`<label><input type="radio" name="r" value="${o}" ${o===cur?'checked':''}> ${o}</label>`).join('')+ `</fieldset>`; break; case 'D':{ let opts=meta.opts; if(opts.length===1&&/^\d+$/.test(opts[0])) opts=Array.from({length:+opts[0]},(_,i)=>String(i+1)); inner=`<label>${nice}<select>`+ opts.map(o=>`<option${o===cur?' selected':''}>${o}</option>`).join('')+ `</select></label>`; break; } case 'I': inner=`<label>${nice}<select>`+ (showPH?`<option disabled selected>${Promptinator._escAttr(cur)}</option>`:'')+ meta.opts.map(u=>`<option${u===cur?' selected':''}>${u}</option>`).join('')+ `</select></label> <iframe hidden style="width:100%;height:300px;border:1px solid #ccc;margin-top:.6em;"></iframe> <div style="text-align:right;margin-top:.7em;"><button type="button">Use site</button></div>`; break; case 'E':{ const isEmail=/^\S+@\S+\.\S+$/.test(cur); inner=`<div style="padding:1em 0;text-align:center;font-size:1.1rem;font-weight:600;">${nice}</div> <div style="text-align:right;margin-top:.7em;"><button type="button">${isEmail?'Send':'Submit'}</button></div>`; break; } default: inner=`<label>${nice}<input type="text" style="width:100%;font-size:1rem;"${phAttr} value="${valAttr}"></label> <div style="text-align:right;margin-top:.7em;"><button type="button">Done</button></div>`; } dlg.innerHTML=`<div class="popup-body">${inner}</div>`; dlg.showModal(); const pb=dlg.querySelector('.popup-body'); /* commandβspecific handlers ----------------------------------- */ if(meta.cmd==='C'){ pb.querySelector('button').onclick=()=>{ const vals=[...pb.querySelectorAll('input:checked')].map(i=>i.value); done(vals.join(', ')||cur); dlg.close(); }; return; } if(meta.cmd==='E'){ const btn=pb.querySelector('button'); const isEmail=/^\S+@\S+\.\S+$/.test(cur); if(isEmail){ const body=Promptinator._lastMeta.map((m,i)=>`${pretty(m.lab)}: ${Promptinator._lastState[i]}`).join('\n'); btn.onclick=()=>{ window.location.href=`mailto:${cur}?subject=${encodeURIComponent(nice)}&body=${encodeURIComponent(body)}`; dlg.close(); }; }else{ const form=document.createElement('form'); form.method='post'; form.action=cur; const t=document.createElement('input'); t.type='hidden'; t.name='_formTitle'; t.value=nice; form.append(t); Promptinator._lastMeta.forEach((m,i)=>{ const inp=document.createElement('input'); inp.type='hidden'; inp.name=pretty(m.lab).replace(/\s+/g,'-').toLowerCase(); inp.value=Promptinator._lastState[i]; form.append(inp); }); pb.append(form); btn.onclick=()=>{ form.submit(); dlg.close(); }; } return; } if(meta.cmd==='A'||meta.cmd==='H'){ const ta=pb.querySelector('textarea'); ta.focus(); pb.querySelector('button').onclick=()=>{ done(ta.value); dlg.close(); }; return; } if(meta.cmd==='B'){ pb.onclick=e=>{ if(e.target.name==='r'){ done(e.target.value); dlg.close(); } }; return; } if(meta.cmd==='D'){ pb.querySelector('select').onchange=e=>{ done(e.target.value); dlg.close(); }; return; } if(meta.cmd==='I'){ const sel=pb.querySelector('select'), fr=pb.querySelector('iframe'); sel.onchange=()=>{ fr.hidden=false; fr.src=sel.value; }; pb.querySelector('button').onclick=()=>{ done(sel.value||cur); dlg.close(); }; return; } /* default singleβline */ const inp=pb.querySelector('input'); inp.focus(); pb.querySelector('button').onclick=()=>{ done(inp.value); dlg.close(); }; inp.onkeydown=e=>{ if(e.key==='Enter'){ done(inp.value); dlg.close(); } }; } /* popup */ }
Save changes
Create folder
writable 0777
Create
Cancel