Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Text Selection</title> | |
| <style> | |
| #settings { | |
| margin-bottom: 15px; | |
| padding: 10px; | |
| border: 1px solid #ccc; | |
| border-radius: 6px; | |
| background: #fafafa; | |
| width: 90%; | |
| } | |
| #inputBox { | |
| width: 90%; | |
| min-height: 150px; | |
| border: 1px solid #ccc; | |
| padding: 10px; | |
| white-space: pre-wrap; | |
| overflow-wrap: break-word; | |
| } | |
| #results { | |
| margin-top: 15px; | |
| font-family: monospace; | |
| background: #f4f4f4; | |
| padding: 10px; | |
| border-radius: 6px; | |
| border: 1px solid #ddd; | |
| white-space: pre-wrap; | |
| user-select: text; | |
| } | |
| label { | |
| margin-right: 10px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <h3>Highlight text to get indices (accurate whitespace & line break)</h3> | |
| <!-- Settings Panel --> | |
| <div id="settings"> | |
| <strong>Settings (rename keys):</strong><br><br> | |
| <label>Span Text Key: <input id="keySpan" type="text" value="span_text"></label> | |
| <label>Start Key: <input id="keyStart" type="text" value="start"></label> | |
| <label>End Key: <input id="keyEnd" type="text" value="end"></label> | |
| </div> | |
| <!-- Editable div --> | |
| <div id="inputBox" contenteditable="true"></div> | |
| <button onclick="getSelectionIndices()">Get Span JSON</button> | |
| <pre id="results"></pre> | |
| <script> | |
| let spans = []; | |
| let lastText = ""; | |
| // Convert HTML content to normalized text where line breaks are \n | |
| function getNormalizedText(container) { | |
| let html = container.innerHTML; | |
| // Replace empty divs with \n | |
| html = html.replace(/<div><br><\/div>/gi, '\n'); | |
| // Replace remaining divs with \n at start, remove closing divs | |
| html = html.replace(/<div>/gi, '\n').replace(/<\/div>/gi, ''); | |
| // Replace <br> with \n | |
| html = html.replace(/<br\s*\/?>/gi, '\n'); | |
| // Replace with space | |
| html = html.replace(/ /g, ' '); | |
| // Strip other tags just in case | |
| html = html.replace(/<[^>]+>/g, ''); | |
| return html; | |
| } | |
| function getSelectionIndices() { | |
| const container = document.getElementById("inputBox"); | |
| const selection = window.getSelection(); | |
| if (!selection || !selection.rangeCount) return; | |
| const range = selection.getRangeAt(0); | |
| if (!container.contains(range.startContainer) || !container.contains(range.endContainer)) return; | |
| const selectedText = selection.toString(); | |
| if (!selectedText) return; | |
| // Normalize the container text | |
| const normalizedText = getNormalizedText(container); | |
| // Get text before selection | |
| const preRange = range.cloneRange(); | |
| preRange.selectNodeContents(container); | |
| preRange.setEnd(range.startContainer, range.startOffset); | |
| const tempDiv = document.createElement("div"); | |
| tempDiv.appendChild(preRange.cloneContents()); | |
| let preText = getNormalizedText(tempDiv); | |
| const start = preText.length; | |
| const end = start + selectedText.length; | |
| const spanInfo = { span_text: selectedText, start, end }; | |
| // Prepend and keep last 5 spans | |
| spans.unshift(spanInfo); | |
| spans = spans.slice(0, 5); | |
| renderSpans(); | |
| } | |
| function renderSpans() { | |
| const keySpan = document.getElementById("keySpan").value || "span_text"; | |
| const keyStart = document.getElementById("keyStart").value || "start"; | |
| const keyEnd = document.getElementById("keyEnd").value || "end"; | |
| const renamedSpans = spans.map(s => ({ | |
| [keySpan]: s.span_text, | |
| [keyStart]: s.start, | |
| [keyEnd]: s.end | |
| })); | |
| document.getElementById("results").innerText = renamedSpans.length | |
| ? JSON.stringify(renamedSpans, null, 2) | |
| : ""; | |
| } | |
| // Reset spans if input text changes | |
| document.getElementById("inputBox").addEventListener("input", function() { | |
| const currentText = getNormalizedText(this); | |
| if (currentText !== lastText) { | |
| spans = []; | |
| document.getElementById("results").innerText = ""; | |
| lastText = currentText; | |
| } | |
| }); | |
| // Re-render spans if key names change | |
| document.getElementById("keySpan").addEventListener("input", renderSpans); | |
| document.getElementById("keyStart").addEventListener("input", renderSpans); | |
| document.getElementById("keyEnd").addEventListener("input", renderSpans); | |
| </script> | |
| </body> | |
| </html> | |