简体   繁体   English

在React中用html标签替换字符串之间的字符

[英]Replacing characters between strings with html tags in react

I'm trying to parse some text so that _this is emphasized!_ is wrapped in <em> tags like so: <em>this is emphasized!</em> . 我正在尝试解析一些文本,以便将_this is emphasized!_包裹在<em>标记中,例如: <em>this is emphasized!</em>

My component currently looks like this: 我的组件当前如下所示:

export default class TextParser extends React.Component {
  render() {
    let text = this.props.text,
        parsed, regex, paragraphs;

    regex = {
      paragraph: /(?:\r\n){2,}/g,
      emphasize: /\_(.*?)\_/g,
      strong: /\*(.*?)\*/g,
    }

    // Apply regex
    text = text.replace(regex.emphasize, (str) => {
      let parsed = str.substr(1, str.length - 1);

      return ('<em>' + parsed + '</em>')
    })

    paragraphs = text.split(regex.paragraph) || []
    paragraphs = paragraphs.map((text, i) => {
      return (
        <p key={i}>
          {text}
        </p>
      )
    })

    return (
      <div className="document">{paragraphs}</div>
    )
  }
}

This does not work, however the output html displays the tags in plain text instead of using them in the html. 这不起作用,但是输出html以纯文本显示标记,而不是在html中使用它们。 This is of course because of sanitization. 这当然是由于消毒。

I could dangerouslySetInnerHTML but I want to avoid that. 我可以dangerouslySetInnerHTML但是我想避免这种情况。 How can I replace the underscores between text with <em> tags? 如何用<em>标签替换文本之间的下划线?

As you noticed, placing the string "<em>" as part of the result of replace just adds that string and not an actual tag. 如您所见,将字符串"<em>"作为replace结果的一部分只会添加该字符串,而不是实际的标签。

You will not be able create tags directly inside of replace because that is operating on a string. 您将无法直接在replace内部创建标签,因为该操作是在字符串上进行的。

Instead, break the string up into separate elements and add the tags where you need them. 而是将字符串分成单独的元素,然后在需要的地方添加标签。 You already do something like this in the paragraph case. 您已经在段落案例中做了类似的事情。

Because the paragraph case also operates on a string, these kind of operations can only be done nested, since once you complete the operation you no longer have a plain text string, you have an array of objects. 由于段落大小写也对字符串进行操作,因此这类操作只能嵌套进行,因为一旦完成操作,您将不再具有纯文本字符串,而是具有对象数组。 So in this example I moved the <em> parsing inside the paragraph parsing. 因此,在此示例中,我将<em>解析移到了段落解析中。

One last note, I had to modify the regex for emphasize so that it captured the underscores, because I need to check again whether it was a match or not after I have done the split. 最后一点,我必须修改正则表达式以使其emphasize以便捕获下划线,因为完成拆分后我需要再次检查它是否匹配。

let text = this.props.text,
    parsed, regex, paragraphs;

regex = {
  paragraph: /(?:\r\n){2,}/g,
  emphasize: /(\_.*?\_)/g,
  strong: /\*(.*?)\*/g,
}

paragraphs = text.split(regex.paragraph) || []
paragraphs = paragraphs.map((text, i) => {
  return (
    <p key={i}>
      {        
           // Apply regex
           text.split(regex.emphasize).map((str) => {
           let parsed = str.search(regex.emphasize) !== -1 
              ? (<em>{str.substr(1, str.length - 2)}</em>) 
              : str;
            return parsed;
        })}
    </p>
  )
})

return (
  <div className="document">{paragraphs}</div>
)

Based on your comments below, you also want to know how to handle either/or formatting case. 根据下面的评论,您还想知道如何处理一个或多个格式化案例。 So for completeness I have included the code for that here. 因此,为了完整起见,我在此处包括了该代码。 I chose to combine the formatting patterns into a single regex, and then I explicitly check for '_' or '*' to decide whether to add em or b tags. 我选择将格式设置模式组合到单个正则表达式中,然后显式检查“ _”或“ *”以决定是否添加emb标签。 I then recursively call this when there is a match, in case there are additional matches within. 然后,当有匹配项时,如果其中有其他匹配项,我将递归调用此方法。 You may choose to clean this up differently, but I hope this helps. 您可以选择以其他方式清理它,但希望对您有所帮助。

let text = this.props.text,
    parsed, regex, paragraphs;

regex = {
  paragraph: /(?:\r\n){2,}/g,
  formatting: /(\_.*?\_)|(\*.*?\*)/g,
}

  let applyFormatting = (text) => {
    return text.split(regex.formatting).filter(n => n).map((str) => {
    let parsed = str[0] == '_'
        ? (<em>{applyFormatting(str.substr(1, str.length - 2))}</em>)
        : str[0] == '*'
        ? (<b>{applyFormatting(str.substr(1, str.length - 2))}</b>)
        : str;
    return parsed;
  });
};

paragraphs = text.split(regex.paragraph) || []
paragraphs = paragraphs.map((text, i) => {
  return (
    <p key={i}>
      { applyFormatting(text) }
    </p>
  )
})

return (
  <div className="document">{paragraphs}</div>
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM