Makko, the people-oriented static site generator made for blogging.

ugh.

+104 -40
+75 -17
doc/blog/styles.css
··· 21 21 body { 22 22 min-height: 100vh; 23 23 max-width: 800px; 24 - padding: 40px; 24 + padding: 20px; 25 25 margin: auto; 26 26 27 27 display: flex; ··· 39 39 background-position: bottom; 40 40 41 41 color: var(--foreground); 42 + 43 + transition: 0.1s; 42 44 } 43 45 44 46 section:has(footer) { ··· 252 254 background-size: contain; 253 255 } 254 256 257 + /* ========================= 258 + TOC 259 + ========================= */ 260 + 255 261 #toc-container { 256 262 position: fixed; 257 263 left: 20px; 258 - top: 100px; 259 264 width: 300px; 260 - max-height: calc(100vh - 120px); 265 + height: 100vh; 261 266 overflow-y: auto; 262 267 padding: 15px; 263 268 z-index: 1000; 269 + } 264 270 265 - display: flex; 271 + /* Toggle button */ 272 + #toc-toggle { 273 + display: none; 274 + position: fixed; 275 + top: 20px; 276 + left: 20px; 277 + 278 + width: 32px; 279 + height: 32px; 280 + 281 + background-color: var(--background); 282 + border: 1px solid var(--foreground); 283 + cursor: pointer; 284 + 285 + z-index: 2000; 286 + 266 287 flex-direction: column; 267 - gap: 20px; 288 + justify-content: center; 289 + align-items: center; 290 + gap: 6px; 291 + } 292 + 293 + #toc-toggle:hover { 294 + background-color: var(--accent-transparent); 295 + } 296 + 297 + #toc-toggle span { 298 + display: block; 299 + width: 100%; 300 + height: 4px; 301 + background-color: var(--foreground); 302 + transition: 0.3s; 303 + } 304 + 305 + /* Hamburger → X */ 306 + #toc-toggle.active span:nth-child(1) { 307 + transform: rotate(45deg) translate(6px, 6px); 308 + } 309 + 310 + #toc-toggle.active span:nth-child(2) { 311 + opacity: 0; 312 + } 313 + 314 + #toc-toggle.active span:nth-child(3) { 315 + transform: rotate(-45deg) translate(6px, -6px); 268 316 } 269 317 270 318 #toc-content ul { ··· 282 330 } 283 331 284 332 #toc-content a { 285 - color: #333; 333 + color: var(--foreground); 286 334 text-decoration: none; 287 335 display: block; 288 336 padding: 6px 8px; ··· 290 338 font-weight: normal; 291 339 } 292 340 293 - #toc-content a:hover { 294 - background-color: #f0f0f0; 295 - color: var(--accent); 296 - font-weight: bold; 297 - } 298 - 341 + #toc-content a:hover, 299 342 #toc-content a.active { 300 343 background-color: var(--accent-transparent); 301 344 color: var(--accent); ··· 303 346 font-weight: bold; 304 347 } 305 348 306 - .header-link { 307 - font-size: 0.5em; 308 - } 309 - 310 349 @media (max-width: 1500px) { 311 350 body { 312 351 margin: 0; ··· 315 354 } 316 355 317 356 @media (max-width: 1200px) { 357 + #toc-toggle { 358 + display: flex; 359 + } 360 + 318 361 #toc-container { 319 - display: none; 362 + inset: 0; 363 + width: 100vw; 364 + height: 100vh; 365 + max-width: none; 366 + 367 + background-color: var(--background); 368 + transform: translateX(-100%); 369 + transition: transform 0.3s ease; 370 + 371 + padding: 80px 20px 20px; 372 + border-right: none; 373 + } 374 + 375 + #toc-container.active { 376 + transform: translateX(0); 320 377 } 321 378 322 379 body { ··· 324 381 } 325 382 } 326 383 384 + /* LIGHT MODE */ 327 385 @media (prefers-color-scheme: light) { 328 386 body { 329 387 background: none;
+27
doc/blog/toc.js
··· 68 68 69 69 const tree = buildTree(tocItems); 70 70 71 + const tocToggle = document.createElement("button"); 72 + tocToggle.id = "toc-toggle"; 73 + tocToggle.textContent = "☰"; 74 + tocToggle.setAttribute("aria-label", "Toggle table of contents"); 75 + 71 76 const tocContainer = document.createElement("div"); 72 77 tocContainer.id = "toc-container"; 73 78 tocContainer.innerHTML = ` ··· 82 87 </div> 83 88 `; 84 89 90 + document.body.appendChild(tocToggle); 85 91 document.body.appendChild(tocContainer); 86 92 93 + tocToggle.addEventListener("click", function () { 94 + const isActive = tocContainer.classList.toggle("active"); 95 + tocToggle.textContent = isActive ? "X" : "☰"; 96 + }); 97 + 98 + document.addEventListener("click", function (e) { 99 + if ( 100 + !tocContainer.contains(e.target) && 101 + !tocToggle.contains(e.target) && 102 + tocContainer.classList.contains("active") 103 + ) { 104 + tocContainer.classList.remove("active"); 105 + tocToggle.textContent = "☰"; 106 + } 107 + }); 108 + 87 109 document.querySelectorAll("#toc-content a").forEach((link) => { 88 110 link.addEventListener("click", function (e) { 89 111 e.preventDefault(); ··· 97 119 behavior: "smooth", 98 120 }); 99 121 history.pushState(null, null, `#${targetId}`); 122 + 123 + if (window.innerWidth <= 1200) { 124 + tocContainer.classList.remove("active"); 125 + tocToggle.textContent = "☰"; 126 + } 100 127 } 101 128 }); 102 129 });
+1 -1
doc/makko.json
··· 23 23 "on_modify": null 24 24 }, 25 25 "hashes": { 26 - "TGm1pyN0WiY": "dCZMIYD12b0" 26 + "TGm1pyN0WiY": "f-dq6c2CniQ" 27 27 } 28 28 }
+1 -22
doc/templates/post.html
··· 8 8 <script src="/highlight.min.js"></script> 9 9 <script src="toc.js"></script> 10 10 11 - <script> 12 - hljs.highlightAll(); 13 - </script> 11 + <script>hljs.highlightAll();</script> 14 12 15 13 <link rel="stylesheet" href="/highlight.css" /> 16 14 <link rel="stylesheet" href="/styles.css" /> 17 - 18 - <style> 19 - @media (max-width: 1500px) { 20 - body { 21 - margin: 0; 22 - margin-left: auto; 23 - } 24 - } 25 - 26 - @media (max-width: 1200px) { 27 - #toc-container { 28 - display: none; 29 - } 30 - 31 - body { 32 - margin: auto; 33 - } 34 - } 35 - </style> 36 15 </head> 37 16 38 17 <body>