将包含<,>(特殊字符)的字符串转换为html

时间:2018-11-30 05:47:26

标签: javascript html typescript browser replace

我有一个字符串,<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 :(得分:0)

在替换<之前,您必须用&lt;替换>,用&gt;替换te

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

答案 1 :(得分:0)

Regular expressions and HTML don't mix very well。就您而言,如果您非常小心,则可以手动转义所有适当的值并生成有效的HTML。如果您有些粗心,则可能会遇到格式错误或不安全的内容的问题。这并不是说“您绝对绝不能那样做”,而是您至少应该意识到这样做的陷阱。

推荐的解决方案永远不要自己以编程方式操作HTML字符串。相反,您应该操纵HTMLElement objects并信任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);

它将以您想要的方式突出显示。

好的,希望能有所帮助。祝你好运!