рдореЗрд░реЗ рдкрд╛рд╕ рдпрд╣ рдХреЛрдб рд╣реИ рдЬреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИ:
_.each(matches, (match) ->
string = string.replace(match, ->
<span className="match" key={i++}>{match}</span>
)
)
рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╕рд╛рде рдорд┐рд╢реНрд░рд┐рдд рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рд╣реЛрдЧрд╛ред рдмреБрд░рд╛ рдореБрдЭреЗ рдкрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВ рдХреИрд╕реЗ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдЕрдВрджрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдШрдЯрдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реВрдБ? рдореИрдВ рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдШрдЯрдХ рдХреЗ рд╕рд╛рде рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдард┐рди рдорд╛рдорд▓рд╛ред
рдРрд╕рд╛ рдХреБрдЫ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:
const escapeRE = new RegExp(/([.*+?^=!:$(){}|[\]\/\\])/g)
const safeRE = (string) => {
return string.replace(escapeRE, "\\$1")
}
class Hightlight extends Component {
static propTypes = {
match : PropTypes.string,
string : PropTypes.string,
}
render() {
return (
<span
dangerouslySetInnerHTML={{
__html : string.replace(safeRE(this.props.match), "<strong className\"match\">$1</strong>")
}} />
)
}
}
рд╣рд╛рдВ, рдореИрдВ dangerouslySetInnerHTML
рдХрд╛ рджреБрд░реБрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕реЛрдЪ рд░рд╣рд╛ рд╣реВрдВ рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдкрд╕рдВрдж рдирд╣реАрдВ рд╣реИред рдЗрд╕ рдкрджреНрдзрддрд┐ рдХреЛ рдЕрдЪреНрдЫреЗ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдЦрддрд░рдирд╛рдХ рд░реВрдк рд╕реЗ рд▓реЗрдмрд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рд╡рд╣рд╛рдБ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рднреАрддрд░ jsx рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕рд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ? рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкрд╛рд░реНрд╕ рд╣реИ iE
var example = "this one word <span className="match" key={i++}>hello</span> is highlighted"
рдФрд░ рдЗрд╕реЗ рдПрдХ рд░реЗрдВрдбрд░ рд╡рд┐рдзрд┐ рдореЗрдВ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдВ?
@binarykitchen рдЖрдк рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рддрддреНрд╡реЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдпрд╣реА рдЖрдкрдХреЛ рдпрд╣рд╛рдВ рдХрд░рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ, рдЖрдк рдЗрд╕реЗ рдХреЗрд╡рд▓ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЗ рд╕рд╛рде рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
@syranide рд╣рд╛рдБ, рдореБрдЭреЗ рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрддрд╛ рд╣реИред рдореЗрд░рд╛ рдХрд╣рдирд╛ рд╣реИ: рдХреНрдпрд╛ рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ JSX/рд░рд┐рдПрдХреНрдЯ рдлреАрдЪрд░ рдирд╣реАрдВ рд╣реЛрдЧрд╛? рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░реЗрдВ рдФрд░ рдХрд┐рд╕реА рднреА рдЯреИрдЧ рдХреЛ рдЪрд╛рдЗрд▓реНрдб рд░рд┐рдПрдХреНрдЯ рдШрдЯрдХреЛрдВ рдореЗрдВ рдмрджрд▓ рджреЗрдВред
рдЖрдк split
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд░реЗрдЧреЗрдХреНрд╕ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░ рдХреИрдкреНрдЪрд░ рдХрд┐рдП рдЧрдП рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ:
var parts = "I am a cow; cows say moo. MOOOOO.".split(/(\bmoo+\b)/gi);
for (var i = 1; i < parts.length; i += 2) {
parts[i] = <span className="match" key={i}>{parts[i]}</span>;
}
return <div>{parts}</div>;
рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдЕрд╕реНрдкрд╖реНрдЯ рд╣реИред
рд░рдирдЯрд╛рдЗрдо рдкрд░ JSX рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдирд╛ рддреНрд░реБрдЯрд┐-рдкреНрд░рд╡рдг рдФрд░ рдзреАрдорд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рдЖрд╕рд╛рдиреА рд╕реЗ рд╕реБрд░рдХреНрд╖рд╛ рдирд┐рд╣рд┐рддрд╛рд░реНрде рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ - рдпрд╣ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдЦрддрд░рдирд╛рдХ рд░реВрдк рд╕реЗ SetInnerHTML рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╕реБрд░рдХреНрд╖рд┐рдд рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рдпрд╣ рдЯрд╛рдЗрдк рдХреЗрд╕ рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рд╕рд╛ рдореБрджреНрджрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ
тАФ рдПрдордПрд▓рдмреА
12 рдорд╛рд░реНрдЪ 2015 рдХреЛ, 21:37 рдмрдЬреЗ, рдмреЗрди рдЕрд▓реНрдкрд░рдЯ рдиреЛрдЯрд┐рдлрд┐рдХреЗрд╢рди @github.com рдиреЗ рд▓рд┐рдЦрд╛:
рдЖрдк рд╕реНрдкреНрд▓рд┐рдЯ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд░реЗрдЧреЗрдХреНрд╕ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░ рдХреИрдкреНрдЪрд░ рдХрд┐рдП рдЧрдП рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ:
var part = "рдореИрдВ рдПрдХ рдЧрд╛рдп рд╣реВрдБ, рдЧрд╛рдпреЗрдВ рдореВ рдХрд╣рддреА рд╣реИрдВред MOOOOOред".split(/(\bmoo+\b)/gi);
рдХреЗ рд▓рд┐рдП (var i = 1; i < рднрд╛рдЧреЛрдВред рд▓рдВрдмрд╛рдИ; i += 2) {
рднрд╛рдЧреЛрдВ [i] = ;}рд╡рд╛рдкрд╕реА{рднрд╛рдЧреЛрдВ};
рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдЕрд╕реНрдкрд╖реНрдЯ рд╣реИред-
рдЗрд╕ рдИрдореЗрд▓ рдХрд╛ рд╕реАрдзреЗ рдЙрддреНрддрд░ рджреЗрдВ рдпрд╛ рдЗрд╕реЗ GitHub рдкрд░ рджреЗрдЦреЗрдВред
рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╕рдордп рднреА рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдореЗрдВ рднрд╛рдЧ рдЧрдпрд╛ (рдпрд╛рдиреА <span>
рдЯреИрдЧ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ)ред рдореИрдВрдиреЗ рдЙрдкрд░реЛрдХреНрдд @spicyj рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдореЙрдбреНрдпреВрд▓ рдмрдирд╛рдирд╛ рд╕рдорд╛рдкреНрдд рдХрд░ рджрд┐рдпрд╛ред рд░реБрдЪрд┐ рд░рдЦрдиреЗ рд╡рд╛рд▓реЗ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП: iansinnott/react-string-replace
@iansinnott рдЗрд╕реЗ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдореИрдВрдиреЗ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛, рддрдм рдореБрдЭреЗ рдПрд╣рд╕рд╛рд╕ рд╣реБрдЖ рдХрд┐ рдореБрдЭреЗ рдкреВрд░реНрдг String.prototype.replace
API рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА (рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдлрд╝рдВрдХреНрд╢рди рдХреЗ рднреАрддрд░ рдПрдХ regexp рдХреЗ рд▓рд┐рдП рд╡реНрдпрдХреНрддрд┐рдЧрдд рдорд┐рд▓рд╛рди рд╕рдореВрд╣реЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)ред рдореБрдЭреЗ рдПрд╣рд╕рд╛рд╕ рд╣реБрдЖ рдХрд┐ рдкрд░рд┐рд╡рд░реНрддрди рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдкреИрдЪ рд╕реЗ рдЕрдзрд┐рдХ рд╣реЛрдЧрд╛ (рдФрд░ рдПрдХ рдПрдкреАрдЖрдИ рдкрд░рд┐рд╡рд░реНрддрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ) рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдПрдХ рдирдпрд╛ рд░реЗрдкреЛ рдмрдирд╛рдпрд╛: https://github.com/oztune/string-replace-to-array
рдпрджрд┐ react-string-replace
рдЖрдкрдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рдЕрдиреБрд░реВрдк рдирд╣реАрдВ рд╣реИ:
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдиреЗ рдореЗрд░реЗ рд▓рд┐рдП рдЯреЗрдХреНрд╕реНрдЯ рдХреА рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рднреАрддрд░ рдХреАрд╡рд░реНрдб рдХреЛ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд┐рдпрд╛, рдмрд┐рдирд╛
HTML рдХреЛ рдЦрддрд░рдирд╛рдХ рддрд░реАрдХреЗ рд╕реЗ рд╕реЗрдЯ рдХрд░рдирд╛:
/**
* Find and highlight relevant keywords within a block of text
* <strong i="7">@param</strong> {string} label - The text to parse
* <strong i="8">@param</strong> {string} value - The search keyword to highlight
* <strong i="9">@return</strong> {object} A JSX object containing an array of alternating strings and JSX
*/
const formatLabel = (label, value) => {
if (!value) {
return label;
}
return (<span>
{ label.split(value)
.reduce((prev, current, i) => {
if (!i) {
return [current];
}
return prev.concat(<b key={value + current}>{ value }</b>, current);
}, [])
}
</span>);
};
formatLabel('Lorem ipsum dolor sit amet', 'dolor');
// <span>Lorem ipsum <b>dolor</b> sit amet</span>
рдореБрдЭреЗ рдХреБрдЫ рдкреИрдЯрд░реНрди рд╕реЗ рдореЗрд▓ рдЦрд╛рдиреЗ рд╡рд╛рд▓реЗ рдЙрд▓реНрд▓реЗрдЦреЛрдВ рдХреЗ рд▓рд┐рдП рдРрд╕рд╛ рдХреБрдЫ рдЪрд╛рд╣рд┐рдП рддрд╛рдХрд┐ рдпрд╣ рдХрдИ рдорд╛рдиреЛрдВ рдХреЛ рд▓рдкреЗрдЯ рд╕рдХреЗ рдФрд░ @richardwestenra рд╕рдорд╛рдзрд╛рди рдореЗрдВ рдХреБрдЫ рдмрджрд▓рд╛рд╡ рдХрд┐рдПред рд╢рд╛рдпрдж рдпрд╣ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ред
/**
* Find and highlight mention given a matching pattern within a block of text
* <strong i="7">@param</strong> {string} text - The text to parse
* <strong i="8">@param</strong> {array} values - Values to highlight
* <strong i="9">@param</strong> {RegExp} regex - The search pattern to highlight
* <strong i="10">@return</strong> {object} A JSX object containing an array of alternating strings and JSX
*/
const formatMentionText = (text, values, regex) => {
if (!values.length)
return text;
return (<div>
{text.split(regex)
.reduce((prev, current, i) => {
if (!i)
return [current];
return prev.concat(
values.includes(current) ?
<mark key={i + current}>
{current}
</mark>
: current
);
}, [])}
</div>);
};
const text = 'Lorem ipsum dolor sit amet [[Jonh Doe]] and [[Jane Doe]]';
const values = ['Jonh Doe', 'Jane Doe'];
const reg = new RegExp(/\[\[(.*?)\]\]/); // Match text inside two square brackets
formatMentionText(text, values, reg);
// Lorem ipsum dolor sit amet <mark>Jonh Doe</mark> and <mark>Jane Doe</mark>
рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛ рдереА рдФрд░ рдореИрдВрдиреЗ рдЗрд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреЛрд░реНрдЯрд▓реЛрдВ рдХреЗ рд╕рд╛рде рд╣рд▓ рдХрд┐рдпрд╛, рдЖрд╕рд╛рдиреА рд╕реЗ рдиреЛрдб рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдПрдХ div рдХреЗ рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛ рдФрд░ рдЙрд╕ div рдореЗрдВ createPortal рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкрдиреЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдШрдЯрдХ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ред
@rmtngh рдореИрдВ рдЙрддреНрд╕реБрдХ рд╣реВрдВ рдХрд┐ рдЖрдкрдХреЛ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реЛрдЧреАред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЕрдзрд┐рдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдХреНрдпрд╛ рдЖрдк рдиреЙрди-рд░рд┐рдПрдХреНрд╢рди рдХреЛрдб рдЗрдВрдЯрд░рд▓реЗрд╕ рдХрд░ рд░рд╣реЗ рд╣реИрдВ?
рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ, рдореИрдВ string-replace-to-array
(рдореИрдВ рд▓реЗрдЦрдХ рд╣реВрдВ) рдХреА рдлрд┐рд░ рд╕реЗ рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдпрд╣ рдХрдИ рд╡рд╛рддрд╛рд╡рд░рдгреЛрдВ рдкрд░ рд▓рдбрд╝рд╛рдИ рдФрд░ рд╕рдордп-рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрд╣ рднреА рдХрд╛рдлреА рдЫреЛрдЯрд╛ рд╣реИ (рдкреВрд░реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдпрд╣ рдлрд╛рдЗрд▓ рд╣реИ https://github.com/oztune/string-replace-to-array/blob/master/string-replace-to-array.js)ред
рд░реЗрдЧреЗрдХреНрд╕ рдХреЗ рд╕рд╛рде рдПрдХ рдЙрдкрдпреЛрдЧ рдЙрджрд╛рд╣рд░рдг рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
import replace from 'string-replace-to-array'
// The API is designed to match the native 'String.replace',
// except it can handle non-string replacements.
replace(
'Hello Hermione Granger...',
/(Hermione) (Granger)/g,
function (fullName, firstName, lastName, offset, string) {
return <Person firstName={ firstName } lastName={ lastName } key={ offset } />
}
)
// output: ['Hello ', <Person firstName="Hermione" lastName="Granger" key={ 0 } />, ...]
@oztune рдЖрдкрдХреЗ рдЙрддреНрддрд░ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рд╕реАрдПрдордПрд╕ рдХреЗ рдПрдХ wysiwyg рд╕рдВрдкрд╛рджрдХ рд╕реЗ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдПрдЪрдЯреАрдПрдордПрд▓ рдорд╛рд░реНрдХрдЕрдк рдХреА рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИ рдФрд░ рдореИрдВ рдЙрд╕ рдорд╛рд░реНрдХрдЕрдк рдХреЗ рдЕрдВрджрд░ рдХреБрдЫ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдШрдЯрдХреЛрдВ рдХреЛ рд░рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рдХреНрдпрд╛ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкреЛрд░реНрдЯрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реЛрдЧрд╛? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкреЛрд░реНрдЯрд▓ рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдШрдЯрдХ рдХреЛ рдирд┐рдХрдЯрддрдо рдиреЛрдб рдХреЗ рдмрдЬрд╛рдп рдХрд┐рд╕реА рдЕрдиреНрдп рдиреЛрдб рдХреЗ рдЕрдВрджрд░ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдирд╛ рд╣реИ рдЬреЛ рд╕рд╛рдорд╛рдиреНрдп рдШрдЯрдХ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рд╕реЗ рдЕрдзрд┐рдХ рдорд╣рдВрдЧрд╛ рдирд╣реАрдВ рд╣реЛрдЧрд╛ рдФрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХрдорд╛рддреНрд░ рдЕрддрд┐рд░рд┐рдХреНрдд рдХрджрдо рд╣реИ рдЬреЛ рджреЗрд╢реА рдЬреЗрдПрд╕ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдХреНрдпрд╛ рдореБрдЭреЗ рдХреБрдЫ рдпрд╛рдж рдЖ рд░рд╣рд╛ рд╣реИ? рдХреНрдпрд╛ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдХреЛрдИ рд▓рд╛рдн рд╣реЛрдЧрд╛?
@rmtngh рдореИрдВ рдХрд╣реВрдВрдЧрд╛ рдХрд┐ рдпрд╣ рдЗрд╕ рдмрд╛рдд рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдХреНрдпрд╛ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк рдЕрдкрдиреЗ DOM рдЯреНрд░реА рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рдХреБрдЫ рд░рд┐рдПрдХреНрдЯ рдШрдЯрдХреЛрдВ рдХреЛ рдЫрд┐рдбрд╝рдХрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рдФрд░ рдЯреНрд░реА рдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд░рд┐рдПрдХреНрдЯ рдХреЗ рд╕рд╛рде рдкреНрд░рд╕реНрддреБрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ, рддреЛ рдкреЛрд░реНрдЯрд▓ рдЬрд╛рдиреЗ рдХрд╛ рд░рд╛рд╕реНрддрд╛ рд╣реИред рдЬрд┐рд╕ рд╡рд┐рдзрд┐ рдХрд╛ рдореИрдВрдиреЗ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ рд╡рд╣ рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рд╣реИ рдЬрдм рдЖрдк рдЬрд┐рди рднрд╛рдЧреЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╡реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рд░рд┐рдПрдХреНрдЯ рдШрдЯрдХ рдХреЗ рдЕрдВрджрд░ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдП рдЧрдП рд╣реИрдВред
рдпрд╣рд╛рдВ рд╡рд╣ рдХреЛрдб рд╣реИ рдЬреЛ рджрд┐рдП рдЧрдП рдЯреЗрдХреНрд╕реНрдЯ рдФрд░ рдкреИрдЯрд░реНрди рдореЗрдВ рдиреЛрдбреНрд╕ рдХреА рдПрдХ рд╕рд░рдгреА рджреЗрддрд╛ рд╣реИ:
const highlightPattern = (text, pattern) => {
const splitText = text.split(pattern);
if (splitText.length <= 1) {
return text;
}
const matches = text.match(pattern);
return splitText.reduce((arr, element, index) => (matches[index] ? [
...arr,
element,
<mark>
{matches[index]}
</mark>,
] : [...arr, element]), []);
};
рдзрдиреНрдпрд╡рд╛рдж @wojtekmaj
рдкреИрдЯрд░реНрди рдореЗрдВ рд╕рдореВрд╣реЛрдВ рдХреЗ рд▓рд┐рдП рдореЗрд░рд╛ рд╕рдВрд╕реНрдХрд░рдг:
const replacePatternToComponent = (text, pattern, Component) => {
const splitText = text.split(pattern);
const matches = text.match(pattern);
if (splitText.length <= 1) {
return text;
}
return splitText.reduce((arr, element) => {
if (!element) return arr;
if(matches.includes(element)) {
return [...arr, Component];
}
return [...arr, element];
},
[]
);
};
const string = 'Foo [first] Bar [second]';
const pattern = /(\[first\])|(\[second\])/g;
replacePatternToComponent(string, pattern, <Component />);
рдЯрд╛рдЗрдкрдкреНрд░рддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рджреГрд╖реНрдЯрд┐рдХреЛрдг:
const formatString = (
str: string,
formatingFunction?: (value: number | string) => React.ReactNode,
...values: Array<number | string>
) => {
const templateSplit = new RegExp(/{(\d)}/g);
const isNumber = new RegExp(/^\d+$/);
const splitedText = str.split(templateSplit);
return splitedText.map(sentence => {
if (isNumber.test(sentence)) {
const value = values[Number(sentence)];
return Boolean(formatingFunction) ? formatingFunction(value) : value;
}
return sentence;
});
};
рдЙрдкрдпреЛрдЧ рдХрд╛ рдЙрджрд╛рд╣рд░рдг:
const str = '{0} test {1} test';
formatString(str, value => <b>{value}</b>, value1, value2);
рдкрд░рд┐рдгрд╛рдо:
<b>value1</b> test <b>value2</b> test
@rmtngh рдХреНрдпрд╛ рдЖрдк рдЗрд╕ рдмрд╛рдд рдХрд╛ рдирдореВрдирд╛ рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЖрдкрдиреЗ createportal рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдорд╛рд░реНрдХрдЕрдк рд╕рдВрд╡рд░реНрдзрди рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛? рдореИрдВ рдРрд╕рд╛ рд╣реА рдХрд░рдиреЗ рдХреА рд╕реЛрдЪ рд░рд╣рд╛ рд╣реВрдВред
@Dashue HTML рд╕реНрдЯреНрд░рд┐рдВрдЧ рдФрд░ рдЙрд╕ рдкрд░ рдЖрдкрдХрд╛ рдХрд┐рддрдирд╛ рдирд┐рдпрдВрддреНрд░рдг рд╣реИ, рдЗрд╕ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддреЗ рд╣реБрдП, рдЕрдкрдиреЗ рдорд╛рд░реНрдХрдЕрдк рдХреЗ рдЕрдВрджрд░ рдЕрдкрдиреЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдШрдЯрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд▓рдХреНрд╖реНрдп рдмрдирд╛рдиреЗ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ,
рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рд╕рд░реНрд╡рд░ рдХреА рддрд░рдл рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЕрдкрдиреЗ рддрддреНрд╡реЛрдВ рдХреЛ рдПрдХ рдЖрдИрдбреА рджреЗрдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗред рдХреБрдЫ рдЗрд╕ рддрд░рд╣ :
<div id="component_target_1"></div>
рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рдЕрдВрджрд░, \id="(component_target_\d)"\g
рдХреЛ regexp рдХреЗ рд╕рд╛рде рджреЗрдЦреЗрдВ, рдЖрдИрдбреА (state.targets) рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ рдФрд░ рдЕрдкрдиреЗ рдШрдЯрдХреЛрдВ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдВ:
let mappedComponents
if(this.state.targets && this.state.targets.length){
mappedComponents = this.state.targets.map((id,index)=><MyComponent id={id} key={id} />)
}
рдпрд╣рд╛рдБ "MyComponent" рдХрд╛ рдПрдХ рдирдореВрдирд╛ рд╣реИ:
import React from 'react'
import ReactDOM from 'react-dom'
export default class MyComponent extends React.Component {
constructor(props) {
super(props)
}
getWrapper(){
return document.getElementById(this.props.id)
}
render() {
if(!this.getWrapper()) return null
const content = <div>
Hello there! I'm rendered with react.
</div>
return ReactDOM.createPortal(
content,
this.getWrapper(),
);
}
}
рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ HTML рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкрд░ рдЕрдзрд┐рдХ рдирд┐рдпрдВрддреНрд░рдг рдирд╣реАрдВ рд╣реИ, рддреЛ рднреА рдЖрдк рдЙрд╕реА рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЖрдкрдХреЛ рдХреБрдЫ рддрддреНрд╡реЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдФрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рд▓рдХреНрд╖реНрдп рддрддреНрд╡ рдХреЛ рдЗрдВрдЬреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред
рдмрдврд╝рд┐рдпрд╛ рд╕реВрддреНрд░ рджреЛрд╕реНрддреЛрдВ!
рдореИрдВрдиреЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд░рд┐рдПрдХреНрдЯ рдЯреЗрдХреНрд╕реНрдЯ рд╣рд╛рдЗрд▓рд╛рдЗрдЯрд░ рдкреЗрди рдмрдирд╛рдпрд╛ рд╣реИ рдЬреЛ рдЗрд╕ рдзрд╛рдЧреЗ рдореЗрдВ рдХреБрдЫ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ (рдХреБрдЫ рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рджреВ рдХреЗ рд╕рд╛рде ...), рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рднрд╡рд┐рд╖реНрдп рдХреЗ рдЖрдЧрдВрддреБрдХ рдЗрд╕реЗ рдЙрдкрдпреЛрдЧреА рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдпрд╣рд╛рдВ map
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╕рдорд╛рдзрд╛рди рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ,
рдлреЛрд░реНрдХрд┐рдВрдЧ @sophiebits рд╕рдорд╛рдзрд╛рди рдпрд╣рд╛рдБ:
const reg = new RegExp(/(\bmoo+\b)/, 'gi');
const parts = text.split(reg);
return <div>{parts.map(part => (part.match(reg) ? <b>{part}</b> : part))}</div>;
рд╕реБрдВрджрд░ рдЙрдкрд╛рдп @rehat101
рдпрд╣рд╛рдБ рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ - рдЕрдВрддрд░рд┐рдХреНрд╖ рдЪрд░рд┐рддреНрд░ рджреНрд╡рд╛рд░рд╛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдирд╛ рдФрд░ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╢рдмреНрджреЛрдВ рдХреА рддрд▓рд╛рд╢ рдХрд░рдирд╛ред
рдпрд╣ HTML рдореЗрдВ рдереЛрдбрд╝рд╛ рдЧрдбрд╝рдмрдбрд╝ рд╣реИ рд▓реЗрдХрд┐рди рдХреМрди рдкрд░рд╡рд╛рд╣ рдХрд░рддрд╛ рд╣реИ
ЁЯТЧ RegExp рдФрд░ рдирдХреНрд╢рд╛ рдЗрд╕реЗ рдмрд╣реБрдд рд╕рд╛рдл рдХрд░рддреЗ рд╣реИрдВред рдореИрдВ
const Speech = ({ speech, speeches, setSpeeches, i, text }) => {
const highlightRegExp = new RegExp(
/you|can|do|it|puedes|hacerlo|ping├╝inos|son|bellos/,
"gi"
);
const delineator = " ";
const parts = text.split(delineator);
return (
<div>
{parts.map(part =>
part.match(highlightRegExp) ? <b>{part + " "}</b> : part + " "
)}
</div>
);
};
рд╕реБрдВрджрд░ @ rehat101
рдпрджрд┐
react-string-replace
рдЖрдкрдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рдЕрдиреБрд░реВрдк рдирд╣реАрдВ рд╣реИ:
рдкреНрд░рддрд┐рднрд╛рд╢рд╛рд▓реА! рдореБрдЭреЗ рдпрд╣ рдмреЗрд╣рдж рдЙрдкрдпреЛрдЧреА рд▓рдЧрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЬреНрдпрд╛рджрд╛рддрд░ рдмрд╛рд░ рдЖрдкрдХреЛ рдореВрд▓ рд╕реНрдЯреНрд░рд┐рдВрдЧ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ
рдореИрдВрдиреЗ @nullhook рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреЛ рдПрдХ рдкреНрд░рд╢реНрди рд╕реЗ рдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рд╕рд╛ рджреЛрдмрд╛рд░рд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреА рдФрд░ Google рдЦреЛрдЬ рд╕реНрд╡рдд: рдкреВрд░реНрдг рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдпрд╛рдж рдХрд┐рдпрд╛
js
const highlightQueryText = (text: string, filterValue: string) => {
const reg = new RegExp(`(${filterValue})`, 'gi');
const textParts = text.split(reg);
return (
<span style={{ fontWeight: 600 }}>
{textParts.map(part => (part.match(reg) ? <span style={{ fontWeight: 'normal' }}>{part}</span> : part))}
</span>
);
};
рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдЗрд╕рдореЗрдВ рд▓рдХреНрд╖рд┐рдд рдорд╛рд░реНрдХрдЕрдк рдЦреЛрдЬрдиреЗ рдФрд░ рдЗрд╕реЗ JSX рдШрдЯрдХреЛрдВ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП html-react-parser рдХреЗ рд╕рд╛рде html рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЛ рд╕рд╛рдл рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП DOMPurify рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕рдВрдпреЛрдЬрди рдорд┐рд▓рд╛ - рдореИрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдкреНрд░реЙрдкреНрд╕ рдХреЗ рд╕рд╛рде Rebass рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ .. рдЬреЛ рдХрд╛рдлреА рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╕рд╛рдордиреЗ рдЖрдпрд╛, рджреЛ рдкреИрдХреЗрдЬ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдкрд╛рд░реНрд╕рд░ рдХреЛ рд░реЛрд▓ рдХрд░рдиреЗ рдХреЗ рдКрдкрд░реА рд╣рд┐рд╕реНрд╕реЗ рд╕реЗ рдмрдЪрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВрдЧреЗ, рдореИрдВ рдмрд┐рдирд╛ рд╕реНрд╡рдЪреНрдЫрддрд╛ рдХреЗ рдЗрд╕ рдкрд╛рд░реНрд╕рд░ рдкреИрдХреЗрдЬ рдХреА рдЕрдиреБрд╢рдВрд╕рд╛ рдирд╣реАрдВ рдХрд░рддрд╛ред рдЗрд╕рдХреЗ рд╕рд╛рде рд╕рдВрдШрд░реНрд╖ рдХрд░рдиреЗ рд╡рд╛рд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдЕрднреА рднреА рдЗрд╕ рдХреЛрдбрдкреЗрди рдХреА рдЧреБрдВрдЬрд╛рдЗрд╢ рд╣реИ рдЬреЛ рдЗрд╕рдХреЗ рд▓рд╛рдпрдХ рд╣реИ: https://codesandbox.io/s/eager-wiles-5hpffред рдХрд┐рд╕реА рднреА рд╕реБрдзрд╛рд░ рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рднреА рдмрд╣реБрдд рд╕рд░рд╛рд╣рдирд╛ рдХреА рдЬрд╛рддреА рд╣реИред
рдЕрд░реЗ рдЬреЗрд╕реА,
рдпрд╣ рдЯреЗрдХреНрд╕реНрдЯ рд▓реЗрдиреЗ рдФрд░ рдЗрд╕реЗ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдЕрдЪреНрдЫрд╛ рдХреЙрдореНрдмреЛ рдЬреИрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдШрдЯрдХ! рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ a . рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛
рдПрдХ рдШрдЯрдХ рдХреЗ рд╕рд╛рде рд╕реНрдЯреНрд░рд┐рдВрдЧред
рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред
рдорд╛рд░реНрдХрдбрд╛рдЙрди рдХреЛ рдШрдЯрдХреЛрдВ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреИрдорд╕реНрдЯреИрдХ рд╕рд╛рдЗрдЯ рдореЗрдВ рднреА рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рд╕рд╛рджрд░,
рдбреЗрд░реЗрдХ
рдбреЗрд░реЗрдХ рдЖрд░ред рдСрд╕реНрдЯрд┐рди, рдкреАрдЯреА, рдбреАрдкреАрдЯреА, рдПрдордПрд╕, рдмреАрд╕реАрдЯреАрдПрдордмреА, рдПрд▓рдПрдордЯреА, рд╕реАрдПрд╕рд╕реАрдПрд╕
рд▓рд┐рдВрдХреНрдбрдЗрди рдкрд░ рдореБрдЭрд╕реЗ рдЬреБрдбрд╝реЗрдВ: https://www.linkedin.com/in/derek-austin/
рдмреБрдзрд╡рд╛рд░ рдХреЛ, 26 рдлрд░рд╡рд░реА, 2020, 4:35 рдЕрдкрд░рд╛рд╣реНрди рдЬреЗрд╕реА рд▓реБрдИрд╕ рдиреЛрдЯрд┐рдлрд┐рдХреЗрд╢рди @github.com рдиреЗ рд▓рд┐рдЦрд╛:
рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ HTML рдХреЛ рд╕рд╛рдл рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП DOMPurify рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕рдВрдпреЛрдЬрди рдорд┐рд▓рд╛
рдЗрд╕рдореЗрдВ рд▓рдХреНрд╖рд┐рдд рдорд╛рд░реНрдХрдЕрдк рдЦреЛрдЬрдиреЗ рдФрд░ рдЗрд╕реЗ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП html-react-parser рдХреЗ рд╕рд╛рде рддрд╛рд░
JSX рдШрдЯрдХреЛрдВ рдХреЗ рд▓рд┐рдП - рдореИрдВ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдкреНрд░реЙрдкреНрд╕ рдХреЗ рд╕рд╛рде Rebass рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ .. рдХрд┐
рдХрд╛рдлреА рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдмрд╛рд╣рд░ рдЖрдпрд╛, рджреЛ рдкреИрдХреЗрдЬ рдЖрдкрдХреЛ рдУрд╡рд░рд╣реЗрдб рд╕реЗ рдмрдЪрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВрдЧреЗ
рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдкрд╛рд░реНрд╕рд░ рд░реЛрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ рд╕рд┐рд░реНрдл рдЗрд╕ рдкрд╛рд░реНрд╕рд░ рдкреИрдХреЗрдЬ рдХреА рдЕрдиреБрд╢рдВрд╕рд╛ рдирд╣реАрдВ рдХрд░рддрд╛
рдмрд┐рдирд╛ рд╕реИрдирд┐рдЯрд╛рдЗрдЬреЗрд╢рди рдХреЗред рдЗрд╕рд╕реЗ рдЬреВрдЭ рд░рд╣реЗ рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрднреА рднреА рдЧреБрдВрдЬрд╛рдЗрд╢ рд╣реЛ рд╕рдХрддреА рд╣реИ
рдпрд╣ рдХреЛрдбрдкреЗрди рдЗрд╕рдХреЗ рд▓рд╛рдпрдХ рдХреНрдпрд╛ рд╣реИ:
https://codesandbox.io/s/eager-wiles-5hpffред рдХрд┐рд╕реА рднреА рд╕реБрдзрд╛рд░ рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛
рдмрд╣реБрдд рд╕рд░рд╛рд╣рдирд╛ рднреА рдХреАред-
рдЖрдк рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдиреЗ рдЯрд┐рдкреНрдкрдгреА рдХреА рдереАред
рдЗрд╕ рдИрдореЗрд▓ рдХрд╛ рд╕реАрдзреЗ рдЙрддреНрддрд░ рджреЗрдВ, рдЗрд╕реЗ GitHub рдкрд░ рджреЗрдЦреЗрдВ
https://github.com/facebook/react/issues/3386?email_source=notifications&email_token=AMV42QTV4FDXZIFXCGB3NZDRE3OATA5CNFSM4A5VRBI2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMWXHJJKTDN ,
рдпрд╛ рд╕рджрд╕реНрдпрддрд╛ рд╕рдорд╛рдкреНрдд рдХрд░реЗрдВ
https://github.com/notifications/unsubscribe-auth/AMV42QXARIOKOYSJ4C5IFQLRE3OATANCNFSM4A5VRBIQ
.
рдЖрдк
split
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд░реЗрдЧреЗрдХреНрд╕ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░ рдХреИрдкреНрдЪрд░ рдХрд┐рдП рдЧрдП рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ:var parts = "I am a cow; cows say moo. MOOOOO.".split(/(\bmoo+\b)/gi); for (var i = 1; i < parts.length; i += 2) { parts[i] = <span className="match" key={i}>{parts[i]}</span>; } return <div>{parts}</div>;
рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдЕрд╕реНрдкрд╖реНрдЯ рд╣реИред
рдпрд╣ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЗрд╕реЗ рдХреЛрдгреАрдп рдореЗрдВ рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛? рдореИрдВрдиреЗ рдЖрдкрдХреЗ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдкреНрд░рд╢реНрди рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рд╣реИ:
https://stackoverflow.com/questions/60889171/wrap-certain-words-with-a-component-in-a-contenteditable-div-in-angular
рд╣реИрд▓реЛ рджреЛрд╕реНрддреЛрдВ, рдореБрдЭреЗ рдЖрдкрдХреА рдорджрдж рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ, рдореИрдВ рд░рд┐рдПрдХреНрдЯ рдиреЗрдЯрд┐рд╡ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдореБрдЭреЗ рдЬреЛ рдХрд░рдирд╛ рд╣реИ рд╡рд╣ рдПрдХ рдЯреЗрдХреНрд╕реНрдЯ рд╕реЗ рд╣реИ рдЬрд┐рд╕реЗ рдореИрдВ рдбреАрдмреА рд╕реЗ рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рд╛рд░реВрдк (рдлрд╝реЙрдиреНрдЯ рд░рдВрдЧ, рд▓рд┐рдВрдХ) рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП @ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рддрд╛ рд╣реВрдВ , рдЬрдм рдЦреЛрдЬ рдореЗрдВ рд╣реЛрддрд╛ рд╣реИ рдЯреЗрдХреНрд╕реНрдЯ рдореЗрдВ 1 рд╕рд┐рдВрдЧрд▓ рдореИрдЪ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХреЛ рд╕рднреА рдЕрдЪреНрдЫрд╛ рдмрдирд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди! рдпрджрд┐ рдкрд╛рда рдореЗрдВ рдХрдИ @рдЙрд▓реНрд▓реЗрдЦ рд╣реИрдВ, рддреЛ рдпрд╣ рдореБрдЭреЗ рдПрдХ рддреНрд░реБрдЯрд┐ рджреЗрддрд╛ рд╣реИред
/////рдкрд╛рда рдЙрджрд╛рд╣рд░рдг: _рд╣реЗ рдХреНрдпрд╛ рд╣реБрдЖ @-id:1- рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ ??
//// рдЗрд╕рдХреЗ рд╕рд░рдгреА рдХреЛ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг: [idusuario: "1", usuario: "@luigbren", рдкреНрд░рд╛рд░реВрдк: "@-id:1-".....]
const PatternToComponent = (text, usuarios,) => {
let mentionsRegex = new RegExp(/@-(id:[0-9]+)-/, 'gim');
let matches = text.match(mentionsRegex);
if (matches && matches.length) {
matches = matches.map(function (match, idx) {
let usrTofind = matches[idx]
//////////////////////////////////////////////////////////////////
const mentFormat = listusers.filter(function (item) {
const itemData = item.format;
return itemData.indexOf(usrTofind) > -1;
});
if (mentFormat.length > 0) {
let idusuario = mentFormat[0].idusuario
let replc = mentFormat[0].usuario
console.log(usrTofind) //// here find @-id:1-
console.log(replc) //// here is <strong i="12">@luigbren</strong> for replace
////////// now here replace part of the string, @-id:1- with a <Text> component
///////// with <strong i="13">@luigbren</strong> and the link, this is repeated for every <strong i="14">@mention</strong> found
parts = text.split(usrTofind);
for (var i = 1; i < parts.length; i += 2) {
parts[i] = <Text key={i} style={{ color: '#00F' }} onPress={() => { alert('but this is'); }}>{replc}</Text>;
}
return text = parts;
/////////////////////////////////////////////////////////////////////
} else {
return text
}
});
} else {
return text
}
return text
};
рдЗрд╕ рддрд░рд╣ рдХреЛрдб рдХреЗрд╡рд▓ рдореЗрд░реЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬрдм рдкрд╛рда рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рдЙрд▓реНрд▓реЗрдЦ рд╣реЛрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг '_рд╣реЗ рдХреНрдпрд╛ рд╣реБрдЖ @-рдЖрдИрдбреА: 1- рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ ??_', рд▓реЗрдХрд┐рди рдЬрдм рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдпрд╣ рдореБрдЭреЗ рдПрдХ рддреНрд░реБрдЯрд┐ рджреЗрддрд╛ рд╣реИ , рдЙрджрд╛рд╣рд░рдг: '_рд╣реЗ рдХреНрдпрд╛ рд╣реБрдЖ @-id:1- рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ ?? @-id:2- @-id:3-_'... рддреНрд░реБрдЯрд┐: TypeError: text.split рдХреЛрдИ рдлрд╝рдВрдХреНрд╢рди рдирд╣реАрдВ рд╣реИ рдФрд░ рдпрджрд┐ _parts = text.split(usrTofind) рд░рдЦрдиреЗ рдХреЗ рдмрдЬрд╛рдп;_ рдореИрдВ _parts = text.toString рд░рдЦрддрд╛ рд╣реВрдВ ().split(usrTofind);_ рдпрд╣ рдореБрдЭреЗ рдПрдХ [рдСрдмреНрдЬреЗрдХреНрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ] рддреНрд░реБрдЯрд┐ рджреЗрддрд╛ рд╣реИ
рдЖрдк рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП html-react-parser
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдлрд┐рд░ рдиреЛрдб рдирд╛рдо рдХреЛ jsx рдШрдЯрдХреЛрдВ рд╕реЗ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдЖрдкрдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЛ рдмрджрд▓рдХрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рддрддреНрд╡реЛрдВ рдХреЛ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред
parse(body, {
replace: domNode => {
if (domNode.name === 'select') { // or
return React.createElement(
Select, // your react component
{ },
domToReact(domNode.children)
);
}
}
рдХреЛрдИ рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ react-router-dom
рдХреЛ рдХреИрд╕реЗ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?
рдЙрджрд╛рд╣рд░рдг:
var text = "Are You okay <strong i="9">@sara</strong> ?";
var href= <Link to={{
pathname: '/user/sara',
}}> <strong i="10">@sara</strong> </Link>;
var replace = text.replace("@sara", href);
//output : Are You okey [Object Object] ?
рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рдирддрд╛ рдХрд┐ [рдСрдмреНрдЬреЗрдХреНрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ] рдХреМрди рд╣реИ? рдореИрдВ рдХрд╣рддрд╛ рд╣реВрдВ "рдХреНрдпрд╛ рдЖрдк рдареАрдХ рд╣реИрдВ @sara", рд▓реЗрдХрд┐рди рдЗрд╕ рдХреЛрдб рдиреЗ рдХрд┐рд╕реА рдФрд░ рдХреЛ рдмреБрд▓рд╛рдпрд╛!
рдореЗрд░реЗ рдкрд╛рд╕ react-native
рдореЗрдВ рд▓рдЧрднрдЧ рдПрдХ рд╣реА рдкреНрд░рд╢реНрди рд╣реИ, рдЕрдЧрд░ рдХреЛрдИ рдореЗрд░реА рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ рддреЛ рдореИрдВ рд╕рд░рд╛рд╣рдирд╛ рдХрд░рддрд╛ рд╣реВрдВ
рдЗрд╕ рдкреИрдХреЗрдЬ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдореЗрд░реЗ рд▓рд┐рдП рдХреБрдЫ рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд┐рдпрд╛ https://www.npmjs.com/package/regexify-string
рдореИрдВ рдЗрд╕ рд╕рдорд╛рд░реЛрд╣ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдБ:
export const replaceWithHtml = (
text: string,
textToReplace: string,
replaceValue: any,
): any[] => {
const delimiter = '|||||'
return text && text.includes(textToReplace)
? text
.replace(textToReplace, `${delimiter}${textToReplace}${delimiter}`)
.split(delimiter)
.map((i) => {
if (i === textToReplace) {
return replaceValue
} else {
return i || null
}
})
: text
}
рдЙрд╕рдХреЗ рдЬреИрд╕рд╛:
const text = 'This is an [icon]'
replaceWithHtml(
text,
'[icon]',
<i className="icon-cogs" />,
)
рдореИрдВ рдХреБрдЫ рдХреАрд╡рд░реНрдб рдХреЛ рдХреБрдЫ рддрддреНрд╡реЛрдВ рд╕реЗ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╕ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдЗрдВрдЯрд░рдкреЛрд▓реЗрд╢рди рдЯреВрд▓ рдЪрд╛рд╣рддрд╛ рдерд╛ред
рдЕрдкрдиреЗ рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рддрддреНрд╡реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВ React.Fragment
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред
const interpolate = (text, values) => {
const pattern = /([$0-9]+)/g
const matches = text.match(pattern)
const parts = text.split(pattern)
if (!matches) {
return text
}
return parts.map((part, index) => (
<Fragment key={part + index}>{matches.includes(part) ? values[part] : part}</Fragment>
))
}
// ...
<p>
{interpolate('$1 with $2 is fun!', {
$1: <em>Playing</em>,
$2: <strong>JavaScript</strong>,
})}
</p>
// <p><em>Playing</em> with <strong>JavaScript</strong> is fun!</p>
split()
рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж @sophiebits ЁЯЩП
@pedrodurek рдХреЗ рд╕рдорд╛рдзрд╛рди рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдпрд╣рд╛рдБ рдореЗрд░реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╣реИ (рдХреЗрд╡рд▓ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рдмрдЬрд╛рдп рдкрдардиреАрдп рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдЕрдиреБрд╡рд╛рдж):
export const insertComponentsIntoText = (
str: string,
replacements: {
[key: string]: React.ReactNode
}
) => {
const splitRegex = new RegExp(/\[\[(\w*)\]\]/g);
const parts = str.split(splitRegex);
return parts.map(part => {
if (replacements.hasOwnProperty(part)) {
return replacements[part];
}
return part;
});
};
рдЙрджрд╛рд╣рд░рдг:
insertComponentsIntoText(`"Please accept our [[privacyPolicyLink]] and [[termsLink].", {
"privacyPolicyLink": <a key="privacyPolicyLink" href="/privacy">Privacy Policy</a>,
"termsLink": <a key="termsLink" href="/terms">Terms and Conditions</a>
})
... рдмрди рдЬрд╛рддрд╛ рд╣реИ...
Please accept our <a key="privacyPolicyLink" href="/privacy">Privacy Policy</a> and <a key="termsLink" href="/terms">Terms and Conditions</a>.
(рдХреБрдВрдЬреА рдЖрд╡рд╢реНрдпрдХ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╕рд░рдгреА рдмрди рдЬрд╛рддреА рд╣реИ, рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреБрдВрдЬреА рдХреЗ рдмрд┐рдирд╛ рд╕рд░рдгреА рддрддреНрд╡реЛрдВ рдХреЛ рдкрд╕рдВрдж рдирд╣реАрдВ рдХрд░рддреА рд╣реИред)
рдЗрд╕ рдкреИрдХреЗрдЬ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдореЗрд░реЗ рд▓рд┐рдП рдХреБрдЫ рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд┐рдпрд╛ https://www.npmjs.com/package/regexify-string
рдореИрдВ рднреАред рдЙрди рд╕рднреА рдХреЛ рдЖрдЬрдорд╛рдпрд╛ рд╕рд┐рд░реНрдл рдпрд╣ рдкреИрдХреЗрдЬ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЖрдкрдХреЛ рдзрдиреНрдпрд╡рд╛рдж!
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдЖрдк
split
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд░реЗрдЧреЗрдХреНрд╕ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░ рдХреИрдкреНрдЪрд░ рдХрд┐рдП рдЧрдП рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕реЗ:рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдЕрд╕реНрдкрд╖реНрдЯ рд╣реИред