【问题标题】:reactStringReplace: trouble formatting bold/italic/underline text with capture group regexreactStringReplace:使用捕获组正则表达式格式化粗体/斜体/下划线文本时遇到问题
【发布时间】:2018-11-04 07:33:00
【问题描述】:

来自https://github.com/iansinnott/react-string-replace/issues/33的共享问题

反应字符串替换:https://github.com/iansinnott/react-string-replace

我在使用reactStringReplace 格式化带有粗体/斜体标签的文本时遇到问题。我的设置如下:

var text1 = "[b]Testing bold [i]and italic[/i] tags[/b]"
var text2 = "[b]Testing bold [i]and italic tags[/b][/i]"

let replaced = reactStringReplace(text1, /\[b\]([\s\S]+)\[\/b\]/g, (match, i) => {
   return <b key={i}>{match}</b>
})
replaced = reactStringReplace(replaced, /\[i\]([\s\S]+)\[\/i\]/g, (match, i) => {
   return <i key={i}>{match}</i>
})

// result (html)
<b>Testing [i]bold and italic[/i] tags</b>
<b>Testing [i]bold and italic tags</b>[/i]

我不确定这是reactStringReplace 的问题,还是我正在使用的正则表达式的问题,还是其他问题。如果我首先应用斜体替换,我会在我期望的位置得到斜体标签,但 [b] 标签保持不变。这个用例可以使用reactStringReplace 还是我需要使用dangerouslySetInnerHtml

奖励:reactStringReplace 是否能够处理不平衡的标签,或者像 text2 那样格式不正确的标签,或者我应该做一些预处理以确保字符串正确平衡和格式化?

【问题讨论】:

  • 到目前为止,还不能处理嵌套替换。我看到您正在开发一个补丁以将此功能添加到 reactStringReplace。但这可能超出了这个问题的范围。

标签: javascript regex reactjs


【解决方案1】:

您的样本有多个问题,

  • 您没有使用推荐的 JSX 密钥格式 &lt;i key={match + i}&gt;{match}&lt;/i&gt;(见下文)
  • 您的匹配项重叠
  • 你贪婪的+ 量词可能匹配得太多了。
  • 缺少;s等

广告。 1:引用完整example

在许多 React 示例中,您会看到使用了 iindex 变量
作为 JSX 标记的键(例如本例中的 &lt;a&gt; 标记),但是在这种情况下,我们在三个单独的循环中进行迭代。 这意味着我们不能使用key={i},因为所有三个 JSX 标签可以获得相同的密钥。

广告。 2:然而,这里最关键的部分是您的匹配项重叠,这与reactStringReplace 不匹配。

演示:

const text = 'Hey @ian_sinn#reactconf';
let replacedText;

// Match @-mentions
replacedText = reactStringReplace(text, /@(\w+)/g, (match, i) => (
  <b key={match + i}>@{match}</b>
));

// Match hashtags
replacedText = reactStringReplace(replacedText, /#(\w+)/g, (match, i) => (
  <a key={match + i} href={`https://twitter.com/hashtag/${match}`}>#{match}</a>
));

我们在这个样本中有不同的匹配:首先,@ian_sinn 被匹配和替换,然后是#reactconf,因此替换按预期工作;但是,如果您将第一个正则表达式替换为 .,则将 \w 更改为重叠匹配:现在,将不会应用第二个替换。

如果您避免重叠匹配,它会起作用:

render() {    
    const text = '[b]Testing bold [i]and italic[/i] tags[/b]';
    let replacedText;

    replacedText = reactStringReplace(text, /\[b\]((?:(?!\[\/b\]|\[i\]|\[\/i\]).)*)/g, (match, i) => (
      <b key={match + i}>{match}</b> 
    ));

    replacedText = reactStringReplace(replacedText, /\[i\]((?:(?!\[\/b\]|\[i\]|\[\/i\]).)*)/g, (match, i) => (
      <b><i key={match + i}>{match}</i></b>
    ));

    replacedText = reactStringReplace(replacedText, /\[\/i\]((?:(?!\[\/b\]|\[i\]|\[\/i\]).)*)/g, (match, i) => (
      <b key={match + i}>{match}</b>
    ));

    replacedText = reactStringReplace(replacedText, /\[\/b\]((?:(?!\[\/b\]|\[i\]|\[\/i\]|$).)*)$/g, (match, i) => (
      <b key={match + i}>{match}</b>
    ));

    return (
      <div>
        {replacedText}
      </div>
    );
  },
});

但这需要你在问题上抛出更复杂的正则表达式,给你丑陋的标记,并且可以说,破坏了整个冒险的目的......

广告。 3:将此与使用不贪婪匹配的简单普通正则表达式替换进行比较:[\s\S]+?

const str = `[b]Testing bold [i]and italic[/i] tags[/b]`;
const result = str.replace(/\[b\]([\s\S]+?)\[\/b\]/gm, `<b>$1</b>`)
                  .replace(/\[i\]([\s\S]+?)\[\/i\]/gm, `<i>$1</i>`);
console.log('Substitution result: ', result);

判决:悲伤,但现在official。截至目前,reactStringReplace 不处理嵌套替换:

因为替换可以将数据类型更改为 字符串。如果你看这里,你会发现它只运行替换 字符串。一旦你的第一个替换已经运行在 结果数组将是一个对象(即&lt;b&gt;...&lt;/b&gt;),因此无需替换 将在内部字符串上运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-24
    • 2021-03-08
    相关资源
    最近更新 更多