Замена символов между строками html-тегами в react

#javascript #html #reactjs

#javascript #HTML #reactjs

Вопрос:

Я пытаюсь разобрать некоторый текст так, чтобы он _this is emphasized!_ был заключен в <em> теги следующим образом: <em>this is emphasized!</em> .

Мой компонент в настоящее время выглядит следующим образом:

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

    regex = {
      paragraph: /(?:rn){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>
    )
  }
}
  

Это не работает, однако выходной html-код отображает теги в виде обычного текста вместо того, чтобы использовать их в html. Это, конечно, из-за очистки.

Я мог бы dangerouslySetInnerHTML , но я хочу избежать этого. Как я могу заменить подчеркивания между текстом <em> тегами?

Ответ №1:

Как вы заметили, размещение строки "<em>" как части результата replace просто добавляет эту строку, а не фактический тег.

Вы не сможете создавать теги непосредственно внутри replace , потому что это работает со строкой.

Вместо этого разбейте строку на отдельные элементы и добавьте теги там, где они вам нужны. Вы уже делаете что-то подобное в случае с абзацем.

Поскольку регистр paragraph также работает со строкой, такого рода операции могут выполняться только вложенными, поскольку после завершения операции у вас больше нет обычной текстовой строки, у вас есть массив объектов. Итак, в этом примере я переместил <em> синтаксический анализ внутрь синтаксического анализа абзаца.

И последнее замечание: мне пришлось изменить регулярное выражение для emphasize , чтобы оно отображало символы подчеркивания, потому что мне нужно еще раз проверить, было ли совпадение или нет после того, как я выполнил разделение.

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

regex = {
  paragraph: /(?:rn){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>
)
  

Основываясь на ваших комментариях ниже, вы также хотите знать, как обрабатывать регистр форматирования either / or. Итак, для полноты картины я включил код для этого сюда. Я решил объединить шаблоны форматирования в одно регулярное выражение, а затем явно проверить наличие ‘_’ или ‘*’, чтобы решить, добавлять ли теги em или b . Затем я рекурсивно вызываю это, когда есть совпадение, на случай, если внутри есть дополнительные совпадения. Вы можете решить очистить это по-другому, но я надеюсь, что это поможет.

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

regex = {
  paragraph: /(?:rn){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>
)
  

Комментарии:

1. Отличный ответ! Есть ли сухой способ заставить его анализировать * символы и превращать их в <strong> также?

2. Это может быть немного сложнее, если есть возможность вложить их. Если нет, то это, вероятно, не слишком сложно. Можем ли мы игнорировать возможность выделения текста курсивом * и жирным * шрифтом или вам нужно поддерживать этот тип вложенного подчеркивания / strong?

3. Мне нужны и то, и другое, и, возможно, больше в будущем. Это делается для того, чтобы пользователи могли использовать форматированный текст в своем контенте.

4. Я понимаю, таким образом, вы не можете просто разделить один раз, а затем применить теги. Вам нужно будет каждый раз, когда вы находите совпадение, применять теги, а затем продолжать поиск других совпадений. Поскольку они могут располагаться в любом порядке (например, выделенный полужирным шрифтом текст и курсивом текст ), это нужно будет сделать так, чтобы сначала были найдены самые внешние теги, а затем продолжался поиск результирующих подстрок.

5. Это звучит невероятно сложно. Регулярное выражение — это такой мозговой штурм для меня. Вы можете мне помочь?