Siteβ―Builder
Editing:
play-jsonv5.php
writable 0666
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Ultimate Prompt Playground v5</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"> <style> body { max-width: 900px; margin: 2rem auto; font-family: system-ui, sans-serif; } h1 { text-align: center; margin-bottom: 1.5rem; } .prompt-card { position: relative; background:#fff; border:1px solid #ddd; border-radius:8px; padding:1rem; margin-bottom:1.5rem; } .prompt-text { display: flex; flex-wrap: wrap; gap: .2rem; align-items: flex-start; line-height: 1.6; white-space: normal; } .token { display: inline-flex; flex: 0 1 auto; min-width: 0; background: #e8e0ff; color: #5c3bff; padding: .2rem .5rem; border-radius: 4px; cursor: pointer; margin: .2rem .2rem .2rem 0; white-space: normal; overflow-wrap: anywhere; } .token:hover { background: #d4c6ff; } .toolbar { position: absolute; background: #fff; border: 1px solid #ccc; border-radius: 6px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); padding: .6rem; z-index: 10; display: flex; flex-direction: column; gap: .5rem; width: 220px; } .toolbar label { font-size: .9rem; margin-bottom: .2rem; } .toolbar input[type="text"], .toolbar textarea, .toolbar select { width: 100%; padding: .3rem; border: 1px solid #999; border-radius: 4px; font-size: 1rem; } .toolbar textarea { resize: vertical; } .toolbar .checkbox-list { display: flex; flex-direction: column; gap: .3rem; max-height: 150px; overflow: auto; } /* remove explicit Close button; toolbar will auto-close on click-away or selection */ .ai-btns { margin-top: 1rem; display: flex; gap: .6rem; } .ai-btns a { flex: 1; text-align: center; background: #6c48ff; color: #fff; padding: .6rem; border-radius: 6px; text-decoration: none; font-weight: 600; } .ai-btns a.perplexity { background: #1ca7ec; } .ai-btns a.copilot { background: #00c853; color: #173E22; } </style> </head> <body> <h1>Ultimate Prompt Playground v5</h1> <div id="app"></div> <script> (async () => { const SEP = ' β’ '; const RX = /\[(?:([A-DI]?)-)?([^~|\-\]]+)(?:-([^~\]]+))?(?:~([^~]+)~)?\]/g; const data = await fetch('prompts.json').then(r => r.json()); const app = document.getElementById('app'); function positionToolbar(toolbar, tok) { const card = tok.closest('.prompt-card'); const tokRect = tok.getBoundingClientRect(); const cardRect = card.getBoundingClientRect(); const top = tokRect.bottom - cardRect.top; const left = tokRect.left - cardRect.left; toolbar.style.top = top + 'px'; toolbar.style.left = left + 'px'; } data.forEach((item, idx) => { const tpl = item.prompt; const meta = [], state = {}; const tokenized = tpl.replace(RX, (m, cmd='', lab, ops='', def='') => { const opts = ops.split('|').map(s => s.trim()).filter(Boolean); let initial = def; if (cmd === 'C' && def) initial = def.split(',').map(s => s.trim()).join(SEP); meta.push({ cmd, lab, opts }); state[lab] = initial; return `<span class="token" data-i="${meta.length-1}">${initial}</span>`; }); const card = document.createElement('div'); card.className = 'prompt-card'; card.innerHTML = ` <div class="prompt-text">${tokenized.replace(/\n/g,'<br>')}</div> <div class="ai-btns"> <a class="chatgpt" data-base="https://chatgpt.com/?prompt=">ChatGPT</a> <a class="perplexity" data-base="https://www.perplexity.ai/search?q=">Perplexity</a> <a class="copilot" data-base="https://copilot.microsoft.com/?q=">Copilot</a> </div> `; app.append(card); const toolbar = document.createElement('div'); toolbar.className = 'toolbar'; toolbar.style.display = 'none'; card.append(toolbar); function rebuild() { let out = tpl.replace(RX, (_,__,lab) => state[lab] || ''); card.querySelectorAll('.ai-btns a').forEach(a => { a.href = a.dataset.base + encodeURIComponent(out); }); } rebuild(); card.querySelectorAll('.token').forEach(tok => tok.addEventListener('click', e => { const mi = +tok.dataset.i; const { cmd, lab, opts } = meta[mi]; const cur = state[lab]; toolbar.innerHTML = ''; positionToolbar(toolbar, tok); toolbar.style.display = 'flex'; // auto-close click-away const onDocClick = ev => { if (!toolbar.contains(ev.target) && ev.target !== tok) { toolbar.style.display = 'none'; document.removeEventListener('mousedown', onDocClick); } }; document.addEventListener('mousedown', onDocClick); const lbl = document.createElement('label'); lbl.textContent = lab.replace(/_/g,' '); toolbar.append(lbl); if (cmd === 'A') { const ta = document.createElement('textarea'); ta.rows = 4; ta.value = cur; ta.oninput = () => { state[lab] = ta.value; tok.textContent = ta.value; rebuild(); }; toolbar.append(ta); } else if (cmd === 'B') { opts.forEach(o => { const lb = document.createElement('label'); const r = document.createElement('input'); r.type = 'radio'; r.name = lab; r.value = o; r.checked = (o === cur); r.onchange = () => { state[lab] = o; tok.textContent = o; rebuild(); toolbar.style.display = 'none'; }; lb.append(r, ' ', o); toolbar.append(lb); }); } else if (cmd === 'C') { const list = document.createElement('div'); list.className = 'checkbox-list'; opts.forEach(o => { const lb = document.createElement('label'); const c = document.createElement('input'); c.type = 'checkbox'; c.value = o; c.checked = state[lab].split(SEP).includes(o); c.onchange = () => { const sel = [...list.querySelectorAll('input:checked')].map(i => i.value); state[lab] = sel.join(SEP); tok.textContent = state[lab]; rebuild(); }; lb.append(c, ' ', o); list.append(lb); }); toolbar.append(list); } else if (cmd === 'D') { const sel = document.createElement('select'); const isNum = opts.every(o => /^\d+$/.test(o)); const arr = isNum ? Array.from({ length: Math.max(...opts.map(n => +n)) }, (_, i) => '' + (i + 1)) : opts; arr.forEach(o => { const op = document.createElement('option'); op.textContent = o; op.value = o; if (o === cur) op.selected = true; sel.append(op); }); sel.onchange = () => { state[lab] = sel.value; tok.textContent = sel.value; rebuild(); toolbar.style.display = 'none'; }; toolbar.append(sel); } else { const inp = document.createElement('input'); inp.type = 'text'; inp.value = cur; inp.oninput = () => { state[lab] = inp.value; tok.textContent = inp.value; rebuild(); }; toolbar.append(inp); } })); }); })(); </script> </body> </html>
Save changes
Create folder
writable 0777
Create
Cancel