nestedTree = (origRoot, showOwnerLinks = false) => {
const root = prepareRoot(origRoot);
const nodes = root.descendants();
const links = root.links();
const height = (nodes.length + 1) * nodeSize;
const viewBox = [-nodeSize / 2, (-nodeSize * 3) / 2, width / 1.5, height];
const svg = d3
.create("svg")
.attr("height", height)
.attr("viewBox", viewBox)
.attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;");
const g = svg
.append("g")
.attr("transform", `translate(${showOwnerLinks ? 220 : 0},0)`)
.attr("name", "move-to-middle");
const linksGroup = g
.append("g")
.attr("fill", "none")
.attr("stroke", "#333")
.attr("name", "links");
const nodesGroup = g.append("g").attr("name", "nodes");
const ownerGroup = g.append("g").attr("name", "owner-arcs");
draw(nodes, links);
function draw(nodes, links) {
const link = linksGroup
.selectAll("path")
.data(links, (l) => `${l.source.data.id}-${l.target.data.id}`)
.join((enter) => enter.append("path").attr("d", linkPath));
const node = nodesGroup
.selectAll("g")
.data(nodes, (d) => d.data.id)
.join((enter) => drawNode(enter));
if (showOwnerLinks) {
const owners = nodes.filter((d) => {
return (
!d.data.isDOM &&
d.data.owner &&
d.data.name !== "[ ]" &&
d.data.name !== "Fragment"
);
});
const ownerArcs = ownerGroup
.selectAll("path")
.data(owners)
.join("path")
.attr("stroke", "black")
.attr("stroke-dasharray", 2)
.attr("fill", "none")
.attr("d", (d, i) => {
const { x1, y1, x2, y2, r } = d.data;
return arc({ x1, y1, x2, y2, r });
});
}
}
return Object.assign(svg.node(), { draw });
}