All files / Rindu/utils htmlToReact.ts

10.52% Statements 2/19
0% Branches 0/8
0% Functions 0/5
11.11% Lines 2/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 3544x       2x                                                            
import { createElement, ReactNode } from "react";
 
type FormatFunction = (str: string) => string | ReactNode[];
 
export function htmlToReact(
  htmlString: string,
  format: FormatFunction = (str) => str ?? ""
): ReactNode {
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlString, "text/html");
  const body = doc.body;
  const div = document.createElement("div");
  Array.from(body.childNodes).forEach((child) => div.appendChild(child));
  function traverse(node: Node): ReactNode {
    if (node.nodeType === Node.TEXT_NODE) {
      return format((node as Text).textContent ?? "");
    } else Iif (node.nodeType === Node.ELEMENT_NODE) {
      const children = Array.from(node.childNodes).map(traverse);
      const props: Record<string, string> = {};
      Array.from((node as Element).attributes).forEach((attr) => {
        props[attr.name] = attr.value;
      });
 
      return createElement(
        (node as Element).tagName.toLowerCase(),
        props,
        ...children
      );
    }
    return null;
  }
 
  return traverse(div);
}