Siteβ―Builder
Editing:
play2.php
writable 0666
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Sliding In-Place Token Editor + AI Buttons</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: 860px; margin: 3rem auto; font-family: sans-serif; } h1 { text-align: center; margin-bottom: 2rem; } article.prompt-card { background: #fff; border: 1px solid #ddd; border-radius: 8px; padding: 1rem; margin-bottom: 1.5rem; } .prompt-text { line-height: 1.6; } .token { color: #5c3bff; font-weight: 600; cursor: pointer; position: relative; } .token .tooltip { position: absolute; bottom: 100%; left: 0; background: #fff; color: #000; padding: .2rem .4rem; border: 1px solid #ccc; border-radius: 4px; font-size: .8rem; white-space: nowrap; opacity: 0; transform: translateY(4px); transition: opacity .2s, transform .2s; pointer-events: none; } .token:hover .tooltip { opacity: 1; transform: translateY(0); } .editor-panel { max-height: 0; overflow: hidden; opacity: 0; transition: max-height .3s ease, opacity .2s ease; margin-top: 1rem; } .editor-panel.open { max-height: 600px; opacity: 1; overflow-y: auto; } .editor-panel .body { background: #f9f9f9; border: 1px solid #ccc; border-radius: 6px; padding: .8rem; padding-bottom: 1.5rem; } .editor-panel .body input[type="text"], .editor-panel .body textarea, .editor-panel .body select { width: 100%; margin-top: .5rem; padding: .4rem; border: 1px solid #999; border-radius: 4px; font-size: 1rem; } .editor-panel .body label { display: block; margin-top: .5rem; font-weight: normal; } .editor-panel .body button { position: sticky; bottom: .5rem; margin-top: 1rem; padding: .5rem .8rem; background: #5c3bff; color: #fff; border: none; border-radius: 4px; cursor: pointer; } .ai-btns { margin-top: 1rem; display: flex; gap: .7rem; } .ai-btns a { display: inline-block; padding: .5em 1em; border-radius: 6px; color: #fff; text-decoration: none; font-weight: 600; } .ai-btns a.chatgpt { background: #6c48ff; } .ai-btns a.perplexity { background: #1ca7ec; } .ai-btns a.copilot { background: #00c853; color: #173E22; } .ai-btns a:hover { filter: brightness(1.1); } </style> </head> <body> <h1>Interactive Prompt Playground</h1> <div id="app"></div> <script type="application/json" id="seed"> [ "Write a bedtime story titled [A-story_title- ~Magical Night Adventure~] for a [D-child_gender- |girl|boy| ~girl~] named [child_name~Melanie~]. The plot must feature [C-themes- |unicorns|spaceships|fairy tales|dragons| ~unicorns, fairy tales~] and be told in a [B-tone- |gentle|funny|adventurous| ~gentle~] tone.\n\nProvide exactly [D-paragraphs-5~3~] paragraphs.\n\n(If you need inspiration: ) [I-reference- |https://en.wikipedia.org/wiki/Bedtime_story|https://www.gutenberg.org/| ~Pick a site~]" ] </script> <script> (() => { const SEP = ' β’ '; const RX = /\[(?:([A-DI]?)-)?([^~|\-\]]+)(?:-([^~\]]+))?(?:~([^~]+)~)?\]/g; const prompts = JSON.parse(document.getElementById('seed').textContent); const app = document.getElementById('app'); prompts.forEach((tpl, pi) => { const meta = [], state = {}; // First pass: build tokenized HTML and capture meta const html = tpl.replace(RX, function(match, cmd, lab, ops, def) { cmd = cmd || ''; ops = ops || ''; def = def || ''; const opts = ops.split('|').map(s => s.trim()).filter(Boolean); meta.push({ cmd, lab, opts, def }); state[lab] = def; return `<span class="token" data-i="${meta.length-1}">` + `[${def}]` + `<span class="tooltip">${lab.replace(/[-_]/g,' ')}</span>` + `</span>`; }); // Create card element const card = document.createElement('article'); card.className = 'prompt-card'; card.innerHTML = `<p class="prompt-text">${html.replace(/\n/g,'<br>')}</p>` + `<div class="editor-panel"><div class="body"></div></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); // Update AI buttons helper const updateButtons = promptText => { card.querySelectorAll('.ai-btns a').forEach(a => { a.href = a.dataset.base + encodeURIComponent(promptText); }); }; updateButtons(tpl); // Token click β open editor card.querySelectorAll('.token').forEach(tok => { tok.addEventListener('click', () => { const mi = +tok.dataset.i; const m = meta[mi]; const cur = state[m.lab]; const panel = card.querySelector('.editor-panel'); const body = panel.querySelector('.body'); let fieldHTML = ''; if (m.cmd === 'A') { fieldHTML = `<textarea rows="3">${cur}</textarea>`; } else if (m.cmd === 'B') { fieldHTML = m.opts.map(o => `<label><input type="radio" name="r${pi}${mi}" value="${o}"${o===cur?' checked':''}> ${o}</label>` ).join(''); } else if (m.cmd === 'C') { fieldHTML = m.opts.map(o => `<label><input type="checkbox" value="${o}"${cur.split(SEP).includes(o)?' checked':''}> ${o}</label>` ).join(''); } else if (m.cmd === 'D') { let optsList = m.opts.slice(); if (optsList.every(o => /^\d+$/.test(o))) { const max = Math.max(...optsList.map(Number)); optsList = Array.from({length:max}, (_, i) => '' + (i+1)); } fieldHTML = `<select>${optsList.map(o => `<option${o===cur?' selected':''}>${o}</option>` ).join('')}</select>`; } else /* I or default */ { if (m.cmd === 'I') { fieldHTML = `<select><option disabled selected>${cur}</option>` + m.opts.map(u => `<option>${u}</option>`).join('') + `</select>`; } else { fieldHTML = `<input type="text" value="${cur}">`; } } body.innerHTML = `<strong>${m.lab.replace(/[-_]/g,' ')}</strong><br>` + fieldHTML + `<button>Save</button>`; panel.classList.add('open'); // Save handler body.querySelector('button').onclick = () => { let v; if (m.cmd === 'C') { v = [...body.querySelectorAll('input[type=checkbox]:checked')] .map(el => el.value) .join(SEP) || cur; } else if (m.cmd === 'B') { const sel = body.querySelector('input[type=radio]:checked'); v = sel ? sel.value : cur; } else { v = body.querySelector('textarea, input[type=text], select').value; } state[m.lab] = v; tok.firstChild.nodeValue = `[${v}]`; // Rebuild full prompt from state const newPrompt = tpl.replace(RX, function(_, _cmd, lab2) { return state[lab2] || ''; }); updateButtons(newPrompt); panel.classList.remove('open'); }; }); }); }); })(); </script> </body> </html>
Save changes
Create folder
writable 0777
Create
Cancel