根据 textContent 中的索引突出显示文本

2024-01-10

Bounty

正如 jsPerf 所展示的,测试时最新发布版本的 Firefox、Chrome 和 Internet Explorer 中最快的解决方案将获得奖励or创建此类解决方案最有用的答案由我自行决定。哇哈哈!

I'll be mostly对采用所有偏移和未处理的解决方案感到满意<span>并为其添加突出显示,以便parent.textContent = parent.textContent然后在更新的偏移列表上运行解决方案将重新强调,但这具有不利的时间复杂度,因此不是首选。


相关问题

  • 一个字符串与另一个字符串重叠突出显示问题 https://stackoverflow.com/q/49621999/5223757
    (不具有重叠功能)
  • 如何获取 HTML 字符串中给定偏移量处的父元素? https://stackoverflow.com/q/908477/5223757
    (从这个问题的变体演变而来)

我有一个元素只包含文本,我想强调。我也有一系列[startline, startcol, endline, endcol]其中,知道每条线的长度.textContent,我可以标准化为[startoffset, endoffset]。我怎么能够强调每对偏移之间?

这个问题比看起来更难,因为:

  • 不保证内容不重复(因此无法查找/替换),并且
  • 突出显示最终必须在已经突出显示的文本上执行,有时与已经突出显示的文本相交,并且
  • 高亮必须根据父元素的索引来执行.textContent财产。

定义

  • 强调:放置元素的文本子集textContent在一个或多个<span class="highlighted">不改变父元素的textContent值,使得突出显示 n 次的文本位于 n 嵌套内<span class="highlighted">元素。
  • offset:一个非负整数,表示某个点之前(位于两个字符之间)的字符数。
  • 特点:JavaScript 为您提供的给定索引处的值的实例.textContent字符串(包括空格)。

MCVE

function highlight(parent, startoff, endoff) {
  // Erm...
  parent.textContent;
}

// Test cases

var starts = [
  5,  44, 0, 50, 6,  100, 99,  50, 51, 52
];
var ends = [
  20, 62, 4, 70, 10, 100, 101, 54, 53, 53
];
for (var i = 0; i < 10; i += 1) {
  highlight(document.getElementById("target"),
            starts[i], ends[i]);
}
#target {
  white-space: pre-wrap;
}
<span id="target">
'Twas brillig, and the slithy toves
  Did gyre and gimble in the wabe:
All mimsy were the borogoves,
  And the mome raths outgrabe.

"Beware the Jabberwock, my son!
  The jaws that bite, the claws that catch!
Beware the Jubjub bird, and shun
  The frumious Bandersnatch!"

He took his vorpal sword in hand:
  Long time the manxome foe he sought --
So rested he by the Tumtum tree,
  And stood awhile in thought.

And, as in uffish thought he stood,
  The Jabberwock, with eyes of flame,
Came whiffling through the tulgey wood,
  And burbled as it came!

One, two! One, two! And through and through
  The vorpal blade went snicker-snack!
He left it dead, and with its head
  He went galumphing back.

"And, has thou slain the Jabberwock?
  Come to my arms, my beamish boy!
O frabjous day! Callooh! Callay!'
  He chortled in his joy.

'Twas brillig, and the slithy toves
  Did gyre and gimble in the wabe;
All mimsy were the borogoves,
  And the mome raths outgrabe.
</span>

对开始/结束位置进行标准化以避免重叠。

  1. 将起始位置和结束位置合并到具有相反值的单个列表(例如 -1 和 1)
  2. 按位置值排序列表,然后按标记值排序(并且基于二级排序,您可以区分顺序范围or合并它们)
  3. 遍历头寸列表并将当前头寸的价值标记添加到当前总和中;一旦它是“0” - 这意味着您刚刚找到了某些设置的嵌套/相交部分的结尾;

这样,您将获得突出显示的位置,而无需嵌套/重叠范围。

用文本节点和 HTML 元素的混合来替换文本节点(例如<span>) documentFragment and .replaceChild()将帮助:

let starts = [
    5,  44, 0, 50, 6,  100, 99,  50, 51, 52
];
let ends = [
    20, 62, 4, 70, 10, 100, 101, 54, 53, 53
];

let positions = [];
let normalizedPositions = [];
starts.forEach(function(position) {
    positions.push({position, value: 1});
});
ends.forEach(function(position) {
    positions.push({position, value: -1});
});
positions = positions.sort(function(a, b) {
    return a.position - b.position || 
        b.value - a.value
});

var currentSection = {from: 0, counter: 0};

for(position of positions) {
    if (!currentSection.counter) {
        if (position.value === -1) {
            throw `inconsistent boundaries: closing before opening ${position.position}`;
        }
        currentSection.from = position.position;  
    }
    currentSection.counter += position.value;

    if (!currentSection.counter) { 
        normalizedPositions.push({
            from: currentSection.from, 
            to: position.position
        });
    }
}
if (currentSection.counter) {
    throw "last section has not been closed properly";   
}


let parentNode = document.querySelector('p');
let textNodeToReplace = parentNode.childNodes[0];
let sourceText = textNodeToReplace.nodeValue;

let documentFragment = document.createDocumentFragment();
let withoutHighlightingStart = 0;

normalizedPositions.forEach(function (highlightRange) {
    if (highlightRange.from> withoutHighlightingStart) {
      let notHighlighted = createTextNode(sourceText.slice(withoutHighlightingStart, highlightRange.from));
      documentFragment.appendChild(notHighlighted);
    }
    let highlighted = createHighlighted(sourceText.slice(highlightRange.from, highlightRange.to));
    documentFragment.appendChild(highlighted);
    withoutHighlightingStart = highlightRange.to;
});
let lastNotHighlighted = createTextNode(sourceText.slice(withoutHighlightingStart));
documentFragment.appendChild(lastNotHighlighted);

parentNode.replaceChild(documentFragment, textNodeToReplace);

function createTextNode(str) {
   return document.createTextNode(str);
}

function createHighlighted(str) {
   let span = document.createElement('span');
   span.classList.add('highlight');
   span.appendChild(createTextNode(str));
   return span;
}
.highlight {
    background-color: yellow;
    color: dark-blue;
}
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

根据 textContent 中的索引突出显示文本 的相关文章