{
const width=400;
const height = 400;
const svgNode = svg`<svg width=${width+200} height=${height+200}></svg>`
const svgSelection = d3.select(svgNode);
const line = d3.line()
.curve(d3.curveCatmullRom)
.x(d => d.x*width)
.y(d => d.y*height);
const g = svgSelection.append('g').attr('transform',`translate(${100},${100})`)
g.append('g')
.selectAll('path')
.data(links)
.enter()
.append('path')
.attr('d', ({ source, target, data }) =>
line([
{
x: source.x,
y: source.y
}
].concat(
data.points || [],
[ {
x: target.x,
y: target.y
}
])
))
.attr('fill','none')
.attr('stroke','black')
const nodes = g.append('g')
.selectAll('g')
.data(descendants)
.enter()
.append('g')
.attr('transform', ({x, y}) => `translate(${x*width}, ${y*height})`);
nodes.append('circle')
.attr('r',20)
.attr('fill','white')
.attr('stroke','black')
nodes.append('text').text(d => d.id).attr('text-anchor','middle').attr('alignment-baseline','middle')
yield svgNode;
}