преобразовать строку, содержащую <,> (специальные символы) в html - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть строка: <some text>
Я пытаюсь выделить в ней "te", используя функцию замены

 InnerHTML = innerHTML.replace(some_Regex_Pattern['te'], '<span style=\'background-color:#FFFB00\'>$&</span>');

Полученная строка:

<some <span class=\'highlight\' style=\'background-color:#FFFB00\'>te</span>xt>

Теперь установка этого элемента в element.innerHTML рассматривается как HTML-тег, вызывающий проблему.
В DOM я получаю элемент как

<some <span class=\'highlight\' style=\'background-color:#FFFB00\'>te</span>xt></some>

Я получаю строку в неправильной формеКак я могу преобразовать его в правильный формат, не внося изменений в правильный тег HTML, например, здесь?

Как я могу решить эту проблему, .. Если это не понятно, пожалуйста, прокомментируйте, ..

Ответы [ 2 ]

0 голосов
/ 30 ноября 2018

Регулярные выражения и HTML не очень хорошо сочетаются .В вашем случае, если вы очень осторожны , вы можете вручную экранировать все правильные значения и создать действительный HTML.Если вы даже немного небрежны , у вас будут проблемы с искаженным или небезопасным контентом.Это не означает, что «вы никогда не должны делать это таким образом», но вы должны, по крайней мере, знать о подводных камнях, связанных с этим.

Рекомендованное решение никогда не заключается в программном манипулировании строками HTML самостоятельно.Вместо этого вы должны манипулировать HTMLElement объектами и доверять вашему движку JavaScript обработку HTML.

В вашем случае я бы сказал, что в этом вопросе есть два компонента.

Один: преобразовать строку в представление, где фрагменты строки помечены как «следует подсветить» или «не следует выделять».Если вы введете следующий интерфейс (вы все-таки использовали тег TypeScript):

interface HighlightableString {
    value: string;
    highlighted: boolean;
}

Тогда строка с выделенными разделами может быть представлена ​​как Array<HighlightableString>.

Итак, вам нужна функция для преобразования строки типа "<some text>" и подстроки "te" во что-то вроде

[ 
  {value: "<some ", highlighted: false}, 
  {value: "te", highlighted: true}, 
  {value: "xt>", highlighted: false}
]

Вот одна из возможных реализаций этой функции, но вы можете сделать этокак хочешь.И это совершенно правильное место для использования регулярных выражений, поскольку здесь нет способа представить «небезопасный» или «искаженный» HTML здесь:

function highlightSubstring(s: string, substring: string): Array<HighlightableString> {
    if (substring.length === 0) return [{ value: s, highlighted: false }]
    const ret: Array<HighlightableString> = [];
    for (
      var prevPos = 0, pos = s.indexOf(substring); 
      pos >= 0; 
      prevPos = pos + substring.length, pos = s.indexOf(substring, prevPos)
    ) {
        ret.push({ value: s.substring(prevPos, pos), highlighted: false });
        ret.push({ value: substring, highlighted: true });
    }
    ret.push({ value: s.substring(prevPos), highlighted: false });
    return ret;
}

Два: с учетом Array<HighlightableString>, родительский HTMLElement и некоторым способом выделения текста (например, HTMLElement, представляющим такое выделение), добавьте правильно выделенный текст к этому родительскому элементу.Здесь вы действительно не хотите использовать регулярные выражения или текст HTML вообще.Вот одна из возможных реализаций:

function appendHighlightedString(
  highlightableStrings: Array<HighlightableString>, 
  parentElement: HTMLElement, 
  highlightElement: HTMLElement
) {
  highlightableStrings.forEach(hs => {
    const textNode = document.createTextNode(hs.value);
      if (hs.highlighted) {
          const highlightClone = highlightElement.cloneNode(true);
          highlightClone.appendChild(textNode)
          parentElement.appendChild(highlightClone)
      } else {
          parentElement.appendChild(textNode);
      }
  })
}

Обратите внимание, как эта функция использует Text узлов и элементов клонирования и добавления.Он никогда не смотрит на HTML напрямую.

Хорошо, давайте посмотрим, работает ли это.Я попробую это с содержанием <test content>:

// make a highlight element
const highlightElement = document.createElement("span");
highlightElement.style.backgroundColor = '#FFFB00';

const wholeString = document.createElement("div"); // or whatever the parent element is
appendHighlightedString(
  highlightSubstring("<test content>", "te"), 
  wholeString, 
  highlightElement
);

Давайте посмотрим, что он сделал в Firefox:

console.log(wholeString.innerHTML);
// &lt;<span style="background-color: rgb(255, 251, 0);">te</span>st 
// con<span style="background-color: rgb(255, 251, 0);">te</span>nt&gt;

Ну, браузер решил использовать rgb(255, 251, 0) вместо #FFFB00.Но это прерогатива браузера;мы вышли из игры HTML.Дело в том, что если вы добавите этот элемент в документ,

document.body.appendChild(wholeString);

он будет выделен так, как вы хотите.

Хорошо, надеюсь, это поможет.Удачи!

0 голосов
/ 30 ноября 2018

Вы должны заменить < на &lt; и > на &gt; перед заменой te.

innerHTML.replace('<', '&lt;').replace('>', '&gt;')...
...