2022-12-15 20:28:08 +01:00

133 lines
3.7 KiB
Plaintext

<script>
const getCssVar = (variable) => getComputedStyle(document.body).getPropertyValue(variable);
function htmlDecode(input) {
var doc = new DOMParser().parseFromString(input, "text/html");
return doc.documentElement.textContent;
}
const backLinks = [
{%- for backlink in backlinks -%}
{
id: {{backlink.id}},
title: "{{backlink.title | safe}}",
url: "{{backlink.url}}"
},
{%- endfor -%}
];
const outbound = [
{%- for out in outbound -%}
{
id: {{out.id}},
title: "{{out.title | safe}}",
url: "{{out.url}}"
},
{%- endfor -%}
].map(x => {
x.id += backLinks.length;
return x;
});
const outboundDuplicatesRemoved = outbound.filter(x => !backLinks.find(b => b.url === x.url));
const title = "{{page.fileSlug}}" || "Home"
const currentNode = {
title,
id: 0,
url: "{{page.url}}"
};
const gData = {
nodes: [
currentNode,
...backLinks,
...outboundDuplicatesRemoved
],
links: [
...backLinks.map(backlink => ({source: backlink.id, target: 0})),
...outboundDuplicatesRemoved.map(outlink => ({source: 0, target: outlink.id}))
]
};
gData
.links
.forEach(link => {
const a = gData
.nodes
.find(x => x.id === link.source);
const b = gData
.nodes
.find(x => x.id === link.target);
if (a && b) {
!a.neighbors && (a.neighbors = []);
!b.neighbors && (b.neighbors = []);
a
.neighbors
.push(b);
b
.neighbors
.push(a);
!a.links && (a.links = []);
!b.links && (b.links = []);
a
.links
.push(link);
b
.links
.push(link);
}
});
let Graph;
function renderGraph(width, height) {
if (Graph) {
Graph
.width(width)
.height(height);
Graph.zoomToFit()
Graph.zoom(3)
return;
}
Graph = ForceGraph()(document.getElementById('link-graph'))
.width(width)
.height(height)
.nodeCanvasObject((node, ctx) => {
const numberOfLinks = (node.links && node.links.length) || 2;
const numberOfNeighbours = (node.neighbors && node.neighbors.length) || 2;
const nodeR = Math.min(7, Math.max((numberOfLinks + numberOfNeighbours) / 2, 2));
ctx.beginPath();
ctx.arc(node.x, node.y, nodeR, 0, 2 * Math.PI, false);
ctx.fillStyle = getCssVar("--text-accent");
ctx.fill();
const label = htmlDecode(node.title)
const fontSize = 3.5;
ctx.font = `${fontSize}px Sans-Serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'top';
ctx.fillText(label, node.x, node.y + nodeR + 2);
})
.linkColor(() => getCssVar("--text-muted") || getCssVar("--text-normal"))
.graphData(gData)
.onNodeClick(node => {
window.location = node.url;
});
setTimeout(() => {
Graph.zoomToFit();
Graph.zoom(3);
}, 10);
}
renderGraph(330,300);
</script>