import { useState } from 'react';
import { ChevronDown, ChevronRight } from 'lucide-react';
import { JsonTreeCopyableItem } from './JsonTreeCopyableItem';
export type XmlTreeProps = {
root: Element;
};
export const XmlTree = ({ root }: XmlTreeProps) => {
return (
);
};
type XmlNodeProps = {
node: Node;
depth: number;
};
// Whitespace-only text between sibling elements is DOM-pretty-print
// noise. Filter it so a 10-element document doesn't render as 21 nodes.
// Mixed content like `
Hello world!
` survives because its
// fragments contain non-whitespace.
const isWhitespaceOnlyText = (node: Node): boolean =>
node.nodeType === Node.TEXT_NODE && /^\s*$/.test(node.nodeValue ?? '');
const renderableChildren = (node: Node): Node[] =>
Array.from(node.childNodes).filter((child) => !isWhitespaceOnlyText(child));
const XmlNode = ({ node, depth }: XmlNodeProps) => {
if (node.nodeType === Node.ELEMENT_NODE) {
return ;
}
if (node.nodeType === Node.CDATA_SECTION_NODE) {
return ;
}
if (node.nodeType === Node.TEXT_NODE) {
return ;
}
// Comments, processing instructions, DOCTYPE — intentionally not
// rendered in the tree. They're rare in API responses; the Raw view
// still shows them verbatim.
return null;
};
type XmlElementNodeProps = {
element: Element;
depth: number;
};
const XmlElementNode = ({ element, depth }: XmlElementNodeProps) => {
const [expanded, setExpanded] = useState(true);
const children = renderableChildren(element);
const hasChildren = children.length > 0;
const tagName = element.nodeName;
const attributes = Array.from(element.attributes);
// Self-closing if no renderable children.
const isSelfClosing = !hasChildren;
const serializeSubtree = () => new XMLSerializer().serializeToString(element);
return (