Использование расширения Chrome для замены символов, содержащих более одной строки в обновлении статуса Facebook

Я создал расширение Google Chrome, чтобы пользователи могли выбирать текст в компоненте. Это отлично работает для большинства сайтов. Тем не менее, Facebook обрабатывает обновления статуса по-разному. Кажется, что даже если вы заполняете то, что кажется единственным текстовым полем, на самом деле он использует конструкцию div > div > span > span для каждой отдельной строки в этом текстовом поле. Я понятия не имею, почему они решили это сделать, но значительно упростили замену нескольких строк текста.

Есть ли способ выбрать несколько строк (или даже смежных частей нескольких строк) текста в обновлении статуса Facebook и заменить данные?

Соответствующая часть моего кода выглядит следующим образом:

function replace_text(language){
    let selection = window.getSelection();
    string = selection.toString();

    /* This section contains code that uses string.replace to replace characters in the string. */

    document.execCommand("insertText", false, string);

}

Основываясь на том, как работает мой код сейчас, если я заменю текст на одной строке, у меня нет проблем. Но, если я заменю текст, который охватывает несколько строк, я получаю пустое непригодное поле ввода. Несомненно, это потому, что он удаляет части html-кода. Как я могу исправить свой код, чтобы процесс замены работал правильно не только для других сайтов, но и для Facebook?

Ответ 1

На данный момент одной общей темой среди всех обновлений статуса (и комментариев) является то, что их тексты находятся в одном или наборе элементов span с атрибутом data-text, установленным на true. Поэтому дайте им возможность:

document.querySelectorAll("span[data-text='true']");

Для меня я ввел в поле состояния 3 строки и поле комментариев 1 строки фиктивного текста. Поэтому, когда я выполняю вышеуказанный код в консоли, он возвращает массив из четырех объединенных строк:

>>> (4) [span, span, span, span]

С этим массивом я могу использовать метод Array.prototype.forEach() для итерации через промежутки и замены innerText:

document.querySelectorAll("span[data-text='true']").forEach(function(element) {
    element.innerText = element.innerText.replace('Lorem ipsum','Hello world');
});

Однако важно отметить, что эти изменения сделаны в самом HTML, а Facebook не сохраняет все свои данные непосредственно в HTML. Поэтому он может вызвать нежелательные события, когда вы вводите текст в поле, не фокусируете, меняете текст в поле и переориентируете это поле. Когда вы переориентируете, я считаю, что он захватывает данные того, что было в тексте, прежде чем вы сфокусировали это поле, от внешнего источника, такого как React Virtual DOM. Чтобы не допустить этого, изменения должны быть сделаны после нажатия поля (реального или симулирующего) или при вводе пользователем с использованием своего рода MutationObserver (ЦСИ).