如何在jQuery Terminal中获取DOM文本选区的起始与结束索引?
jQuery Terminal 选区索引API实现方案
实现思路
基于你提供的DOM结构特点实现:
- 提示符统一在
.cmd-prompt节点下,用户输入内容拆分到两个节点:历史输入行存放在.cmd-end-line,当前输入行存放在.cmd-cursor-line - 所有可渲染字符都挂载了
data-text属性,直接读取该属性即可拿到原始字符,无需处理HTML实体转义问题
核心实现代码
function getTerminalSelection() { const cmdEl = document.querySelector('.cmd'); const selection = window.getSelection(); // 无选中内容直接返回 if (!selection.rangeCount) return null; const range = selection.getRangeAt(0); // 选区不在终端命令区域内直接返回 if (!cmdEl.contains(range.commonAncestorContainer)) return null; // 计算提示符总长度,用户输入偏移需要扣除该值 const promptEl = cmdEl.querySelector('.cmd-prompt'); const promptLength = Array.from(promptEl.querySelectorAll('[data-text]')) .reduce((len, node) => len + node.dataset.text.length, 0); // 按顺序收集所有用户输入字符节点,包含换行符 const inputNodes = []; // 上一行输入内容 const endLine = cmdEl.querySelector('.cmd-end-line'); inputNodes.push(...Array.from(endLine.querySelectorAll('[data-text]'))); // 插入换行符虚拟节点,匹配实际输入的换行 inputNodes.push({ dataset: { text: '\n' } }); // 当前行输入内容 const cursorLine = cmdEl.querySelector('.cmd-cursor-line'); inputNodes.push(...Array.from(cursorLine.querySelectorAll('[data-text]'))); // 计算选中位置相对于用户输入开头的偏移 function calculateOffset(node, offsetInNode) { // 查找当前节点对应的带data-text属性的父节点 let targetNode = node.nodeType === Node.TEXT_NODE ? node.parentElement : node; while (targetNode && !targetNode.dataset?.text) { targetNode = targetNode.parentElement; } // 选中位置在提示符区域 if (promptEl.contains(targetNode)) { return Math.max(0, offsetInNode - promptLength); } // 累计计算输入区域的偏移 let totalOffset = 0; for (const n of inputNodes) { if (n === targetNode) { totalOffset += offsetInNode; break; } totalOffset += n.dataset.text.length; } // 边界处理:偏移不小于0,不超过输入总长度 const maxInputLength = inputNodes.reduce((len, n) => len + n.dataset.text.length, 0); return Math.min(Math.max(0, totalOffset), maxInputLength); } let startOffset = calculateOffset(range.startContainer, range.startOffset); let endOffset = calculateOffset(range.endContainer, range.endOffset); // 处理反选情况,保证返回的索引从小到大 if (startOffset > endOffset) { [startOffset, endOffset] = [endOffset, startOffset]; } // 选区完全在提示符区域返回null,也可根据需求改为返回[0, 0] return startOffset === 0 && endOffset === 0 ? null : [startOffset, endOffset]; }
规则匹配说明
- 规则1:选中
> He|lo wor|d时,提示符长度为2,计算后起始偏移为2,结束偏移为8,返回[2, 8] - 规则2:选区左端点在提示符区域时,起始偏移自动取0,右端点超出输入长度时自动截断为最大输入长度,符合
[0, 5]的输出要求 - 规则3:选区完全位于提示符区域时,计算后起止偏移均为0,返回
null,可自行修改为返回[0, 0]
内容的提问来源于stack exchange,提问作者jcubic
相关产品推荐
相关产品推荐

