#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. Это звучит невероятно сложно. Регулярное выражение — это такой мозговой штурм для меня. Вы можете мне помочь?