File size: 3,014 Bytes
9860743
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
(async function () {
  "use strict";
  const manifest = await fetch("logbook.json", { cache: "no-store" }).then(r => r.json());
  const nodes = [manifest.root].concat(manifest.root.children || []);
  const nav = document.getElementById("nav");
  const content = document.getElementById("content");

  function inline(text) {
    return text
      .replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
      .replace(/`([^`]+)`/g, "<code>$1</code>")
      .replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>");
  }

  function markdown(source) {
    const lines = source.split("\n");
    let html = "", paragraph = [], i = 0;
    const flush = () => { if (paragraph.length) { html += `<p>${inline(paragraph.join(" "))}</p>`; paragraph = []; } };
    while (i < lines.length) {
      const line = lines[i], t = line.trim();
      if (!t) { flush(); i++; continue; }
      if (t.startsWith("```")) {
        flush(); const body = []; i++;
        while (i < lines.length && !lines[i].trim().startsWith("```")) body.push(lines[i++]);
        html += `<pre><code>${inline(body.join("\n"))}</code></pre>`; i++; continue;
      }
      const h = t.match(/^(#{1,3})\s+(.*)$/);
      if (h) { flush(); html += `<h${h[1].length}>${inline(h[2])}</h${h[1].length}>`; i++; continue; }
      if (t.startsWith("> ")) { flush(); html += `<blockquote>${inline(t.slice(2))}</blockquote>`; i++; continue; }
      if (t.startsWith("- ")) {
        flush(); const items = [];
        while (i < lines.length && lines[i].trim().startsWith("- ")) items.push(`<li>${inline(lines[i++].trim().slice(2))}</li>`);
        html += `<ul>${items.join("")}</ul>`; continue;
      }
      if (t.startsWith("|") && i + 1 < lines.length && lines[i + 1].includes("---")) {
        flush(); const rows = [];
        while (i < lines.length && lines[i].trim().startsWith("|")) rows.push(lines[i++].trim().slice(1, -1).split("|").map(x => x.trim()));
        const head = rows[0], body = rows.slice(2);
        html += `<table><thead><tr>${head.map(x => `<th>${inline(x)}</th>`).join("")}</tr></thead><tbody>${body.map(row => `<tr>${row.map(x => `<td>${inline(x)}</td>`).join("")}</tr>`).join("")}</tbody></table>`; continue;
      }
      paragraph.push(t); i++;
    }
    flush(); return html;
  }

  async function show(node) {
    document.querySelectorAll("nav a").forEach(a => a.classList.toggle("active", a.dataset.slug === node.slug));
    const text = await fetch(node.file, { cache: "no-store" }).then(r => r.text());
    content.innerHTML = markdown(text);
    history.replaceState(null, "", `#${node.slug}`);
    window.scrollTo(0, 0);
  }

  nodes.forEach(node => {
    const link = document.createElement("a");
    link.href = `#${node.slug}`; link.dataset.slug = node.slug; link.textContent = node.title;
    link.onclick = event => { event.preventDefault(); show(node); };
    nav.appendChild(link);
  });
  const initial = nodes.find(node => `#${node.slug}` === location.hash) || manifest.root;
  await show(initial);
})();