| 130 | } |
| 131 | |
| 132 | function replaceElements( |
| 133 | nodes: ReactNode[], |
| 134 | elements?: Array<FunctionComponent>, |
| 135 | elementIndex: { current: number } = { current: 0 }, |
| 136 | ): ReactNode[] { |
| 137 | const ELEMENT_PATTERN = /<element:([\w.]+)>(.*?)<\/element:\1>/gs; |
| 138 | |
| 139 | if (_.isEmpty(elements)) { |
| 140 | return nodes.map((node) => { |
| 141 | if (typeof node !== "string") return node; |
| 142 | |
| 143 | return node.replace(ELEMENT_PATTERN, (match, elementName, content) => { |
| 144 | return content; |
| 145 | }); |
| 146 | }); |
| 147 | } |
| 148 | |
| 149 | return nodes |
| 150 | .map((node) => { |
| 151 | if (typeof node !== "string") return node; |
| 152 | |
| 153 | const segments: ReactNode[] = []; |
| 154 | let lastIndex = 0; |
| 155 | |
| 156 | let match; |
| 157 | |
| 158 | while ((match = ELEMENT_PATTERN.exec(node)) !== null) { |
| 159 | if (match.index > lastIndex) { |
| 160 | segments.push(node.slice(lastIndex, match.index)); |
| 161 | } |
| 162 | |
| 163 | const [fullMatch, elementName, content] = match; |
| 164 | const Element = elements?.[elementIndex.current]; |
| 165 | elementIndex.current++; |
| 166 | |
| 167 | const innerContent = replaceElements([content], elements, elementIndex); |
| 168 | if (Element) { |
| 169 | segments.push(createElement(Element, {}, ...innerContent)); |
| 170 | } else { |
| 171 | segments.push(...innerContent); |
| 172 | } |
| 173 | |
| 174 | lastIndex = match.index + fullMatch.length; |
| 175 | } |
| 176 | |
| 177 | if (lastIndex < node.length) { |
| 178 | segments.push(node.slice(lastIndex)); |
| 179 | } |
| 180 | |
| 181 | return segments; |
| 182 | }) |
| 183 | .flat(); |
| 184 | } |
| 185 | |
| 186 | function replaceFunctions( |
| 187 | nodes: ReactNode[], |