如何利用第三方返回的offset值正确用HTML标签包裹标记词?
问题:HTML标签包裹标记词时替换位置错误
场景说明
原始段落文本:
Hi, my nme is John, and I am from uas.\nthis sentce dones mke sense.\nHi, my nme is John, and I am from uas.
第三方返回的标记词数据:
[ { offset: 7, token: 'nme', type: 'UnknownToken' }, { offset: 52, token: 'dones', type: 'UnknownToken' }, { offset: 58, token: 'mke', type: 'UnknownToken' } ]
期望效果:用<span class="underline">包裹每个标记词,例如:
<span class="underline">nme</span>
错误代码及输出
用户的处理逻辑:
function replaceAt(str, index, replacement) { return ( str.substring(0, index) + replacement + str.substring(index + replacement.length) ); } let input = `Hi, my nme is John, and I am from uas.\nthis sentce dones mke sense\nHi, my nme is John, and I am from uas.`; const flagTokens = [ { offset: 7, token: "nme", type: "UnknownToken" }, { offset: 52, token: "dones", type: "UnknownToken" }, { offset: 58, token: "mke", type: "UnknownToken" }, ]; flagTokens.forEach((item) => { input = replaceAt( input, item.offset, `<span class="underline">${item.token}</span>` ); }); console.log("Output:", input);
错误输出:
Hi, my <span class="underline">nme</span>his sentce <span <span class="underline">mke</span>
问题原因
- 替换顺序错误:按offset从小到大替换时,每次替换会增加字符串长度,导致后续基于原始字符串的offset位置完全偏移。
- replaceAt函数逻辑错误:替换时应该切掉原token的长度,而非replacement的长度。原函数中
str.substring(index + replacement.length)的写法错误,会保留原token的部分内容,同时截断后续文本。
解决方案
步骤1:修正replaceAt函数
替换时截取原token长度的内容,确保原标记词被完整替换:
function replaceAt(str, index, originalLength, replacement) { return str.substring(0, index) + replacement + str.substring(index + originalLength); }
步骤2:按offset从大到小排序标记数组
先替换位置靠后的标记,避免前面的替换操作改变后续标记的原始offset:
flagTokens.sort((a, b) => b.offset - a.offset);
完整修正代码
function replaceAt(str, index, originalLength, replacement) { return str.substring(0, index) + replacement + str.substring(index + originalLength); } let input = `Hi, my nme is John, and I am from uas.\nthis sentce dones mke sense\nHi, my nme is John, and I am from uas.`; const flagTokens = [ { offset: 7, token: "nme", type: "UnknownToken" }, { offset: 52, token: "dones", type: "UnknownToken" }, { offset: 58, token: "mke", type: "UnknownToken" }, ]; // 按offset从大到小排序,避免前面的替换影响后面的位置 flagTokens.sort((a, b) => b.offset - a.offset); flagTokens.forEach((item) => { const replacement = `<span class="underline">${item.token}</span>`; input = replaceAt(input, item.offset, item.token.length, replacement); }); console.log("Output:", input);
正确输出
Hi, my <span class="underline">nme</span> is John, and I am from uas. this sentce <span class="underline">dones</span> <span class="underline">mke</span> sense Hi, my <span class="underline">nme</span> is John, and I am from uas.
内容的提问来源于stack exchange,提问作者Ven Nilson
相关产品推荐
相关产品推荐

