chart = {
const format = d3.format(",");
const root = d3.hierarchy(data).eachBefore((i => d => d.index = i++)(0));
const nodes = root.descendants();
const width = 928;
const nodeSize = 20;
const height = (nodes.length + 1) * nodeSize;
const columns = [
{
label: "Count",
value: d => d.children ? 0 : 1,
format: (value, d) => d.children ? format(value) : "-",
x: 1020
}
];
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [-nodeSize / 2, -nodeSize * 3 / 2, width, height])
.attr("style", "max-width: 100%; height: auto; font: 10px sans-serif; overflow: visible;");
const link = svg.append("g")
.attr("fill", "none")
.attr("stroke", "#999")
.selectAll()
.data(root.links())
.join("path")
.attr("d", d => `
M${d.source.depth * nodeSize},${d.source.index * nodeSize}
V${d.target.index * nodeSize}
h${nodeSize}
`);
function getItemColor(d) {
const text = d.data.short_text;
const itemColor =
text.startsWith("[SUPPORT -") ? "#5CA066" :
text.startsWith("[ATTACK -") ? "#CC6666" :
"#000";
return itemColor;
}
function getItemFont(d) {
const text = d.data.short_text;
const pattern = /^\[[^\]]+\]/;
const itemFont = pattern.test(text) ? "bold" : "normal";
return itemFont;
}
const node = svg.append("g")
.selectAll()
.data(nodes)
.join("g")
.attr("transform", d => `translate(0,${d.index * nodeSize})`);
node.append("circle")
.attr("cx", d => d.depth * nodeSize)
.attr("r", 2.5)
.attr("fill", d => d.children ? null : "#999");
node.append("text")
.attr("dy", "0.32em")
.attr("x", d => d.depth * nodeSize + 6)
.text(d => d.data.text);
node.append("title")
.text(d => d.ancestors().reverse().map(d => d.data.name).join("/"));
const textElements = svg.selectAll('text');
textElements.each(function(d) {
var text = d3.select(this).text();
var ixStopToken = text.indexOf("] ");
var firstWord = text.substring(0, ixStopToken);
var restOfText = text.substring(ixStopToken + 1);
d3.select(this).text(null)
.append("tspan")
.style("fill", getItemColor(d))
.style("font-weight", getItemFont(d))
.text((ixStopToken > 0 ? firstWord + "] " : firstWord));
d3.select(this).append("tspan")
.text(restOfText);
});
for (const {label, value, format, x} of columns) {
svg.append("text")
.attr("dy", "0.32em")
.attr("y", -nodeSize)
.attr("x", x)
.attr("text-anchor", "end")
.attr("font-weight", "bold")
.text(label);
node.append("text")
.attr("dy", "0.32em")
.attr("x", x)
.attr("text-anchor", "end")
.attr("fill", d => d.children ? null : "#555")
.data(root.copy().sum(value).descendants())
.text(d => format(d.value, d));
}
return svg.node();
}