components_jsx-from-text.js
import { React } from '@gravityforms/libraries';
/**
* @module JSXFromText
* @description A component to create JSX from text by replacing custom tags and wrapping inner text in passed components.
*
* @since 3.1.0
*
* @param {object} props Component props.
* @param {string} props.closingSymbol The closing symbol for the custom tags.
* @param {string} props.openingSymbol The opening symbol for the custom tags.
* @param {string} props.text The text to process.
* @param {Array} props.tokens The tokens to replace in the text.
*
* @return {JSX.Element} The JSXFromText component.
*/
export default function JSXFromText( {
closingSymbol = '%%',
openingSymbol = '%%',
text = '',
tokens = [],
} ) {
const tokenMap = tokens.reduce( ( acc, token ) => {
acc[ token.key ] = token;
return acc;
}, {} );
const processText = ( t ) => {
const regex = new RegExp( `${ openingSymbol }(.*?)${ closingSymbol }([\\s\\S]*?)${ openingSymbol }\\1${ closingSymbol }`, 'g' );
let lastIndex = 0;
const elements = [];
t.replace( regex, ( match, tokenKey, innerText, index ) => {
// Push the text before the matched tag
elements.push( t.slice( lastIndex, index ) );
// Create and push the JSX element
const token = tokenMap[ tokenKey ];
if ( token ) {
const Component = token.component;
elements.push( <Component { ...token.props } key={ `${ tokenKey }-${ index }` }>{ innerText }</Component> );
} else {
elements.push( innerText );
}
lastIndex = index + match.length;
} );
// Push any remaining text after the last match
elements.push( t.slice( lastIndex ) );
return elements;
};
return <>{ processText( text ) }</>;
}