React: рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдПрдХ рдШрдЯрдХ рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдмрджрд▓реЗрдВ?

рдХреЛ рдирд┐рд░реНрдорд┐рдд 12 рдорд╛рд░реНрдЪ 2015  ┬╖  40рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: facebook/react

рдореЗрд░реЗ рдкрд╛рд╕ рдпрд╣ рдХреЛрдб рд╣реИ рдЬреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИ:

    _.each(matches, (match) ->
      string = string.replace(match, ->
        <span className="match" key={i++}>{match}</span>
      )
    )

рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд╕рд╛рде рдорд┐рд╢реНрд░рд┐рдд рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рд╣реЛрдЧрд╛ред рдмреБрд░рд╛ рдореБрдЭреЗ рдкрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдореИрдВ рдХреИрд╕реЗ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдЕрдВрджрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдШрдЯрдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝ рд╕рдХрддрд╛ рд╣реВрдБ? рдореИрдВ рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдШрдЯрдХ рдХреЗ рд╕рд╛рде рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдХреБрдЫ рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреНрд░реИрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдард┐рди рдорд╛рдорд▓рд╛ред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдЖрдк 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>;

рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рдЕрд╕реНрдкрд╖реНрдЯ рд╣реИред

рд╕рднреА 40 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдРрд╕рд╛ рдХреБрдЫ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:

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 рдЖрдкрдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рдЕрдиреБрд░реВрдк рдирд╣реАрдВ рд╣реИ:

https://github.com/EfogDev/react-process-string

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдиреЗ рдореЗрд░реЗ рд▓рд┐рдП рдЯреЗрдХреНрд╕реНрдЯ рдХреА рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рднреАрддрд░ рдХреАрд╡рд░реНрдб рдХреЛ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд┐рдпрд╛, рдмрд┐рдирд╛
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 рдФрд░ рдирдХреНрд╢рд╛ рдЗрд╕реЗ рдмрд╣реБрдд рд╕рд╛рдл рдХрд░рддреЗ рд╣реИрдВред рдореИрдВ

image

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 рдЖрдкрдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рдЕрдиреБрд░реВрдк рдирд╣реАрдВ рд╣реИ:

https://github.com/EfogDev/react-process-string

рдкреНрд░рддрд┐рднрд╛рд╢рд╛рд▓реА! рдореБрдЭреЗ рдпрд╣ рдмреЗрд╣рдж рдЙрдкрдпреЛрдЧреА рд▓рдЧрддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЬреНрдпрд╛рджрд╛рддрд░ рдмрд╛рд░ рдЖрдкрдХреЛ рдореВрд▓ рд╕реНрдЯреНрд░рд┐рдВрдЧ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ

рдореИрдВрдиреЗ @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

рдореИрдВ рднреАред рдЙрди рд╕рднреА рдХреЛ рдЖрдЬрдорд╛рдпрд╛ рд╕рд┐рд░реНрдл рдпрд╣ рдкреИрдХреЗрдЬ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЖрдкрдХреЛ рдзрдиреНрдпрд╡рд╛рдж!

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

krave1986 picture krave1986  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

UnbearableBear picture UnbearableBear  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

kocokolo picture kocokolo  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

tleunen picture tleunen  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

huxiaoqi567 picture huxiaoqi567  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ