Найти узел по позиции символа (позиция относительно innerText) - PullRequest
4 голосов
/ 27 апреля 2020

У меня есть эта структура (может быть более сложной / содержать вложенные теги)

<div id="editor">
 <p>Some <i>text</i>
 <p>Some other text</p>
</div>

Я извлекаю текст, как видно на экране с editor.innerText И я получаю:

Некоторые text

Какой-то другой текст

Мой бэкэнд-сервис анализирует этот текст и подсвечивает меня "позициями". Для приведенного выше примера допустим, что он возвращает (0,9), означая, что start - это текстовый узел, содержащий «Some», а конечный узел - это «text». Как я могу найти эти узлы по заданным позициям?

У меня был некоторый успех в сборе текста с помощью обхода DOM и отслеживании позиций, но я теряю новые строки и некоторые пробелы (из-за textContent) .

1 Ответ

3 голосов
/ 27 апреля 2020

Ответ на этот вопрос не тривиален.

Лучшее решение - передать innerHtml в бэкэнд-сервис, чтобы правильно выделить текст, и он должен быть в состоянии разобрать HTML.

Однако другое ваше решение - передать ваш innerText бэкэнду, затем пройти через все символы в innerHtml и игнорировать все символы в угловых скобках.

Это, вероятно, потребует некоторой очистки пробела и небольшого количества HTML искажений, но я оставлю это на ваше усмотрение.

Вот пример того, что я имею в виду

let searchHtml = "<p>Some <i>text</i><p>Some other text</p>";
let outputHtml = "";
let highlightOpenTag = "<b>";
let highlightCloseTag = "</b>";
let currentlyHighlighting = false;
// Start and end positions from your backend
let startIndex = 0;
let endIndex = 9;
let inTag = false;
let textIndex = 0;

for (let i = 0; i < searchHtml.length; i++) {
  let char = searchHtml[i];
  // We don't want to insert highlight tags when we're inside a tag already
  if (char === '<') inTag = true;
  if (inTag) {
    outputHtml += char;
  } else {
    // If we're not in a tag, but we are within the text positions
    // returned from the backend, let's get highlighting
    if (textIndex >= startIndex && textIndex < endIndex) {
      if (!currentlyHighlighting) {
        outputHtml += highlightOpenTag;
        currentlyHighlighting = true;
      }
    }
    outputHtml += char;
    // If we're about to hit a tag and we're already highlighting then
    // insert our end highlight tag
    if((searchHtml.length < i+1 || searchHtml[i+1]) === '<' && currentlyHighlighting) {
      outputHtml += highlightCloseTag;
      currentlyHighlighting = false;
    }
    textIndex++;
  }  
  
  if (char === '>') inTag = false;
}

console.log(outputHtml);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...