-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.html.tera
More file actions
159 lines (142 loc) · 6.31 KB
/
Copy pathindex.html.tera
File metadata and controls
159 lines (142 loc) · 6.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
{% import "_macros.html.tera" as macros %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ site.title }} — meshfox</title>
{%- for icon in icons %}
<link rel="{{ icon.rel }}" href="{{ icon.href }}"{% if icon.type %} type="{{ icon.type }}"{% endif %}{% if icon.sizes %} sizes="{{ icon.sizes }}"{% endif %}>
{%- endfor %}
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="site-header">
<pre class="mascot" aria-hidden="true"> /\_/\
( ¬‿¬ )
> ^ <</pre>
<div class="site-header-text">
<h1>{{ site.title }}</h1>
</div>
</header>
<main class="canvas-wrap">
<div class="tree">{{ macros::node(n=site.root) }}</div>
</main>
<footer class="site-footer">
<p>Generated by <code>meshfox static</code> {{ meshfox_version }}{% if canvas_commit %} · canvas at <code>{{ canvas_commit }}</code>{% endif %}.</p>
</footer>
<script>
// The whole tree (root/depth-1's own small nudge, every deeper level's
// real rightward branching, and every structural parent/child connector)
// is pure CSS now — see style.css's own doc comments — so this script has
// exactly one job left: draw `meshfox:edge` cross-references, which (unlike
// a structural edge) can point anywhere in the tree, not just to a DOM
// sibling, so they still need a real browser-measured position. Re-run on
// load and on (debounced) resize since those positions are genuinely
// viewport-responsive.
(function () {
var edges = {{ site.edges | json_encode | safe }};
if (!edges.length) return;
function svgEl(tag) {
return document.createElementNS("http://www.w3.org/2000/svg", tag);
}
var overlay = null;
// Every node's `offsetLeft`/`offsetTop`/`offsetWidth`/`offsetHeight` are
// already relative to `.tree` (its own `offsetParent`, being the nearest
// *positioned* ancestor — see style.css's own doc comment) regardless of
// scrolling anywhere, unlike `getBoundingClientRect` (viewport-relative,
// which silently goes stale the moment `.canvas-wrap` scrolls without
// firing `resize`). Appending the overlay as a child of `.tree` itself
// (rather than `document.body`) and drawing every path in these same
// `.tree`-relative coordinates keeps it moving together with the nodes
// it connects under any scroll.
function nodeBox(el) {
var left = el.offsetLeft;
var top = el.offsetTop;
var width = el.offsetWidth;
var height = el.offsetHeight;
return { left: left, top: top, width: width, height: height, right: left + width, bottom: top + height };
}
function drawEdges() {
if (overlay) overlay.remove();
var tree = document.querySelector(".tree");
var width = tree.offsetWidth;
var height = tree.offsetHeight;
overlay = svgEl("svg");
overlay.setAttribute("class", "mesh-edge-overlay");
overlay.setAttribute("width", width);
overlay.setAttribute("height", height);
var defs = svgEl("defs");
overlay.appendChild(defs);
// Same `--accent-default` custom property style.css uses for every
// other arrow on the page (the CSS-drawn structural connectors) — an
// edge with no explicit `color` of its own reads as the same accent
// rather than a separate, unrelated gray; already tuned for contrast
// against `--bg` in both themes, read fresh here rather than
// duplicated as a hardcoded hex so light/dark and any future retheme
// stay in sync automatically.
var defaultColor = getComputedStyle(document.documentElement).getPropertyValue("--accent-default").trim() || "#ff6e15";
edges.forEach(function (edge, i) {
var from = document.getElementById("node-" + edge.from);
var to = document.getElementById("node-" + edge.to);
if (!from || !to) return;
var a = nodeBox(from);
var b = nodeBox(to);
var color = edge.color || defaultColor;
var markerId = "mesh-arrow-" + i;
if (edge.arrow_end) {
var marker = svgEl("marker");
marker.setAttribute("id", markerId);
marker.setAttribute("viewBox", "0 0 10 10");
marker.setAttribute("refX", "9");
marker.setAttribute("refY", "5");
marker.setAttribute("markerWidth", "7");
marker.setAttribute("markerHeight", "7");
marker.setAttribute("orient", "auto");
var head = svgEl("path");
head.setAttribute("d", "M0,0 L10,5 L0,10 z");
head.setAttribute("fill", color);
marker.appendChild(head);
defs.appendChild(marker);
}
// Curved (bezier), deliberately unlike a structural edge's
// right-angle CSS connector — see web/src/DeletableEdge.tsx, which
// makes the same distinction for the same reason: a cross-reference
// can point anywhere, so it reading differently from "this is the
// tree" is the point.
var sx = a.right;
var sy = a.top + a.height / 2;
var tx = b.left;
var ty = b.top + b.height / 2;
var offset = Math.max(Math.abs(tx - sx) * 0.5, 30);
var d = "M " + sx + " " + sy + " C " + (sx + offset) + " " + sy + " " + (tx - offset) + " " + ty + " " + tx + " " + ty;
var path = svgEl("path");
path.setAttribute("d", d);
path.setAttribute("fill", "none");
path.setAttribute("stroke", color);
path.setAttribute("stroke-width", "1.6");
if (edge.style === "dashed") path.setAttribute("stroke-dasharray", "7,5");
else if (edge.style === "dotted") path.setAttribute("stroke-dasharray", "1.5,4");
if (edge.arrow_end) path.setAttribute("marker-end", "url(#" + markerId + ")");
overlay.appendChild(path);
});
tree.appendChild(overlay);
}
drawEdges();
window.addEventListener("load", drawEdges);
var resizeTimer;
window.addEventListener("resize", function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(drawEdges, 150);
});
// Folding a node (native `<details>`, see _macros.html.tera/style.css —
// no JS of its own) moves every node below/beside it, which can move an
// edge endpoint too; `toggle` fires on the `<details>` itself for both
// directions (open and close), and bubbles, so one delegated listener
// catches every node's own toggle without needing to attach one per node
// or know which nodes are even foldable.
document.querySelector(".tree").addEventListener("toggle", drawEdges, true);
})();
</script>
</body>
</html>