<!DOCTYPE html><html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#0f172a" />
<title>Paste Editor</title><!-- Ace -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.9/ace.js" defer></script>
<style>
:root {
--bg: #0f172a;
--panel: #111827;
--text: #e5e7eb;
--muted: #94a3b8;
--border: #243244;
--accent: #60a5fa;
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font: 14px/1.5 system-ui, sans-serif;
display: flex;
flex-direction: column;
overscroll-behavior-y: none;
}
body.no-scroll { overflow: hidden; }
/* Top bar */
.bar {
display: flex;
gap: .5rem;
align-items: center;
padding: .5rem .75rem;
background: var(--panel);
border-bottom: 1px solid var(--border);
flex-wrap: wrap;
}
.bar select {
background: #0b1220;
color: var(--text);
border: 1px solid var(--border);
border-radius: 6px;
padding: .3rem .4rem;
font-size: .9rem;
}
.bar .btn { font-size: .9rem; }
.bar strong { font-size: .95rem; }
.bar label { font-size: .9rem; }
@media (max-width: 640px) {
.bar { padding: .4rem .5rem; gap: .4rem; }
.bar strong { font-size: .85rem; }
.bar label { font-size: .85rem; }
.bar select { padding: .25rem .35rem; font-size: .85rem; }
.bar .btn { padding: .35rem .5rem; font-size: .85rem; }
}
/* Toolbar */
.toolbar {
display: flex;
gap: .5rem;
flex-wrap: wrap;
align-items: center;
padding: .5rem 1rem;
background: #0b1220;
border-bottom: 1px solid var(--border);
}
.find-mode,
.find-input,
.btn {
border: 1px solid var(--border);
background: #0b1220;
color: var(--text);
border-radius: 6px;
}
.find-mode { padding: .4rem .5rem; }
.find-input { padding: .4rem .6rem; min-width: 250px; }
.btn { padding: .45rem .7rem; cursor: pointer; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }
.btn-accent { border-color: var(--accent); background: rgba(96,165,250,.12); }
.count { color: var(--muted); margin-left: .25rem; font-size: .9rem; }
.badge { margin-left: .75rem; color: #cbd5e1; font-size: .85rem; }
/* Editor */
.pane { flex: 1; min-height: 0; }
#editor { width: 100%; height: 100%; }
.ace_selected_block {
position: absolute;
background: rgba(80,160,255,.18);
border: 1px solid rgba(80,160,255,.35);
}
/* Overlay sheet */
.overlay {
position: fixed;
inset: 0;
display: none;
align-items: center;
justify-content: center;
z-index: 9999;
background: rgba(0,0,0,.55);
backdrop-filter: blur(2px);
}
.overlay.open { display: flex; }
.sheet {
background: #0b1220;
border: 1px solid var(--border);
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0,0,0,.35);
width: min(960px, 94vw);
max-height: 88vh;
display: flex;
flex-direction: column;
}
.sheet-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: .8rem 1rem;
border-bottom: 1px solid var(--border);
}
.sheet-title { font-weight: 600; }
.sheet-close {
background: transparent;
border: 1px solid var(--border);
border-radius: 8px;
color: var(--text);
width: 34px;
height: 34px;
cursor: pointer;
}
.sheet-body { padding: 1rem; overflow: auto; }
.sheet-body textarea {
width: 100%;
height: 50vh;
min-height: 200px;
background: #0a101b;
color: var(--text);
border: 1px solid var(--border);
border-radius: 10px;
padding: .75rem;
resize: vertical;
}
.sheet-foot {
display: flex;
gap: .5rem;
flex-wrap: wrap;
justify-content: flex-end;
padding: 1rem;
border-top: 1px solid var(--border);
}
.sheet-foot .btn { min-width: 120px; }
.btn-ghost { background: transparent; }
.btn-primary { background: #0f172a; border-color: var(--accent); }
.btn-primary:hover { background: #132036; }
/* Focus ring for accessibility */
:is(button, [role="button"], select, input, textarea):focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
</style>
</head>
<body>
<!-- Top bar -->
<div class="bar">
<strong>Paste Editor</strong><label for="modeSel">Mode:</label>
<select id="modeSel" aria-label="Language mode">
<option value="javascript">JavaScript</option>
<option value="typescript">TypeScript</option>
<option value="php">PHP</option>
<option value="python">Python</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="json">JSON</option>
<option value="sql">SQL</option>
<option value="markdown">Markdown</option>
<option value="sh">Shell</option>
<option value="text">Plain Text</option>
</select>
<button id="bringBtn" class="btn btn-accent" type="button">Bring In</button>
<span id="detectedBadge" class="badge" aria-live="polite"></span>
</div>
<!-- Find toolbar -->
<div class="toolbar" role="region" aria-label="Find toolbar">
<label for="findMode" class="sr-only">Find mode</label>
<select id="findMode" class="find-mode" aria-label="Find mode">
<option value="normal">Normal text</option>
<option value="function">Function</option>
<option value="tag">Tag (HTML)</option>
<option value="variable">Variable</option>
<option value="attribute">Attribute / ID</option>
</select>
<input id="findInput" class="find-input" placeholder="Query (blank = browse all in current mode)" aria-label="Find query" />
<button class="btn" id="prevBtn" type="button" aria-label="Previous">▲</button>
<button class="btn" id="nextBtn" type="button" aria-label="Next">▼</button>
<button class="btn" id="clearBtn" type="button">Clear</button>
<span class="count" id="countHint" aria-live="polite"></span>
</div>
<!-- Editor -->
<div class="pane">
<div id="editor" aria-label="Code editor">// Paste code here</div>
</div>
<!-- Bring In overlay -->
<div id="overlay" class="overlay" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="sheetTitle">
<div class="sheet">
<div class="sheet-head">
<div class="sheet-title" id="sheetTitle">Bring In</div>
<button id="sheetClose" class="sheet-close" type="button" aria-label="Close">×</button>
</div>
<div class="sheet-body">
<label for="bringText" class="sr-only">Snippet to analyze</label>
<textarea id="bringText" placeholder="Paste snippet to analyze..."></textarea>
</div>
<div class="sheet-foot">
<button id="locateBtn" class="btn btn-primary" type="button">Locate</button>
<button id="pasteBtn" class="btn btn-primary" type="button">Paste at Cursor</button>
<button id="replaceBtn" class="btn btn-primary" type="button">Replace Block/Selection</button>
<button id="cancelBtn" class="btn btn-ghost" type="button">Close</button>
</div>
</div>
</div>
<script>
// --- Ace init ---
const ed = ace.edit("editor");
ed.setTheme("ace/theme/monokai");
ed.session.setMode("ace/mode/javascript");
ed.setOptions({
wrap: true,
tabSize: 2,
useSoftTabs: true,
showPrintMargin: false,
fontSize: 14,
});
const ms = document.getElementById("modeSel");
ms.addEventListener("change", (e) => ed.session.setMode("ace/mode/" + e.target.value));
// --- Overlay controls (avoid clobbering window.open/close) ---
const ov = document.getElementById("overlay");
const bb = document.getElementById("bringBtn");
const cb = document.getElementById("sheetClose");
const cnb = document.getElementById("cancelBtn");
const lb = document.getElementById("locateBtn");
const pb = document.getElementById("pasteBtn");
const rb = document.getElementById("replaceBtn");
const bt = document.getElementById("bringText");
const db = document.getElementById("detectedBadge");
function openSheet() {
ov.classList.add("open");
ov.setAttribute("aria-hidden", "false");
document.body.classList.add("no-scroll");
setTimeout(() => bt.focus(), 0);
}
function closeSheet() {
ov.classList.remove("open");
ov.setAttribute("aria-hidden", "true");
document.body.classList.remove("no-scroll");
ed.focus();
}
bb.onclick = openSheet;
cb.onclick = closeSheet;
cnb.onclick = closeSheet;
ov.onclick = (e) => e.target === ov && closeSheet();
ov.onkeydown = (e) => {
if (e.key === "Escape") closeSheet();
if ((e.metaKey || e.ctrlKey) && e.key === "Enter") lb.click();
};
// --- Find UI ---
const fi = document.getElementById("findInput");
const fm = document.getElementById("findMode");
const prb = document.getElementById("prevBtn");
const nxb = document.getElementById("nextBtn");
const clb = document.getElementById("clearBtn");
const ch = document.getElementById("countHint");
let t = ""; // current query text
let m = []; // matches
let i = -1; // index of current match
const c = { function: null, tag: null, variable: null, attribute: null };
let lr = null; // last selection range
ed._bm = []; // block markers
function clearHighlights() {
ed._bm.forEach((x) => ed.session.removeMarker(x));
ed._bm = [];
lr = null;
}
function selectMatch(x) {
if (!x) return;
clearHighlights();
const R = ace.require("ace/range").Range;
const r = new R(
x.startLine,
x.startColumn || 0,
x.endLine || x.startLine,
x.endColumn || (ed.session.getLine(x.endLine || x.startLine) || "").length
);
const id = ed.session.addMarker(r, "ace_selected_block", "text");
ed._bm.push(id);
ed.selection.setRange(r, false);
ed.scrollToLine(x.startLine, true, true, () => {});
lr = r.clone();
}
function detectLang(s) {
s = s.trim();
if (/^<!DOCTYPE html>|^<html[\s>]|^<\w+[\s>]/i.test(s)) return "html";
if (/^<\?php/i.test(s)) return "php";
if (/^\s*def\s+\w+\s*|^\s*class\s+\w+/i.test(s)) return "python";
if (/^\s*(let|const|var)\s+|function\s+\w+\s*\(|=>\s*\{/.test(s)) return "javascript";
return null;
}
function detectEnt(s) {
const l = (s.split("\n").find((x) => x.trim()) || "").trim();
// HTML tag/selector
if (/^<\w+[\s>]/.test(l)) {
const x = l.match(/^<([a-zA-Z][\w:-]*)\b([^>]*?)>?/);
if (x) {
const tg = (x[1] || "").toLowerCase();
const at = x[2] || "";
const id = (at.match(/\bid=["']?([^"'\s>]+)/i) || [])[1];
const cl = (at.match(/\bclass=["']([^"']+)/i) || [])[1];
if (id) return { mode: "attribute", query: "#" + id, label: "id: " + id };
if (cl) {
const fc = cl.split(/\s+/).filter(Boolean)[0];
if (fc) return { mode: "attribute", query: "." + fc, label: "class: " + fc };
}
if (tg) return { mode: "tag", query: tg, label: "tag: " + tg };
}
}
// JS/TS/Python function
const fn =
l.match(/^\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(/) ||
l.match(/^\s*(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s*)?\([^)]*\s*=>\s*\{/) ||
l.match(/^\s*def\s+(\w+)\s*\(/);
if (fn) return { mode: "function", query: fn[1], label: "function: " + fn[1] };
// Variable
const v = l.match(/^\s*(?:var|let|const)\s+([$A-Za-z_][\w$]*)/) || l.match(/^\s*\$([A-Za-z_]\w*)\s*=/);
if (v) return { mode: "variable", query: v[1], label: "variable: " + v[1] };
// CSS-like selector typed directly
if (/^#[-\w:]+$/.test(l) || /^\.[-\w:]+$/.test(l)) return { mode: "attribute", query: l, label: "selector: " + l };
return null;
}
// Actions
lb.onclick = () => {
const s = bt.value;
const lg = detectLang(s);
if (lg) {
ms.value = lg;
ed.session.setMode("ace/mode/" + lg);
}
const e = detectEnt(s);
if (e) {
fm.value = e.mode;
fi.value = e.query;
db.textContent = "Detected " + e.label;
} else {
db.textContent = "No entity detected";
}
closeSheet();
};
pb.onclick = () => {
const s = bt.value;
if (s) {
const p = ed.getCursorPosition();
ed.session.insert(p, s);
}
closeSheet();
};
rb.onclick = () => {
const s = bt.value;
if (s) {
const sr = ed.getSelectionRange();
if (!ed.session.getTextRange(sr)) {
if (lr) ed.session.replace(lr, s);
else {
const rw = ed.getCursorPosition().row;
const ln = ed.session.getLine(rw);
const R = ace.require("ace/range").Range;
ed.session.replace(new R(rw, 0, rw, ln.length), s);
}
} else {
ed.session.replace(sr, s);
}
}
closeSheet();
};
// Simple find nav via keyboard
document.addEventListener("keydown", (e) => {
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "f") {
e.preventDefault();
fi.focus();
}
});
// TODO: Wire up actual search logic as needed (placeholders kept from original snippet)
prb.addEventListener("click", () => {});
nxb.addEventListener("click", () => {});
clb.addEventListener("click", () => { fi.value = ""; ch.textContent = ""; });
</script>
</body>
</html>