1 files deleted
1 files added
12 files modified
| | |
| | | async function drawGraph( |
| | | url, |
| | | baseUrl, |
| | | pathColors, |
| | | depth, |
| | |
| | | enableZoom |
| | | ) { |
| | | const container = document.getElementById('graph-container') |
| | | |
| | | const { index, links, content } = await fetchData |
| | | const curPage = url.replace(baseUrl, '') |
| | | |
| | | // Use .pathname to remove hashes / searchParams / text fragments |
| | | const cleanUrl = window.location.origin + window.location.pathname |
| | | |
| | | const curPage = cleanUrl.replace(/\/$/g, "").replace(baseUrl, "") |
| | | |
| | | const parseIdsFromLinks = (links) => [ |
| | | ...new Set(links.flatMap((link) => [link.source, link.target])), |
| | |
| | | function htmlToElement(html) { |
| | | const template = document.createElement('template') |
| | | const template = document.createElement("template") |
| | | html = html.trim() |
| | | template.innerHTML = html |
| | | return template.content.firstChild |
| | |
| | | |
| | | function initPopover(baseURL, useContextualBacklinks) { |
| | | const basePath = baseURL.replace(window.location.origin, "") |
| | | document.addEventListener("DOMContentLoaded", () => { |
| | | fetchData.then(({ content }) => { |
| | | const links = [...document.getElementsByClassName("internal-link")] |
| | | links |
| | | .filter(li => li.dataset.src || (li.dataset.idx && useContextualBacklinks)) |
| | | .forEach(li => { |
| | | if (li.dataset.ctx) { |
| | | console.log(li.dataset.ctx) |
| | | const linkDest = content[li.dataset.src] |
| | | const popoverElement = `<div class="popover"> |
| | | fetchData.then(({ content }) => { |
| | | const links = [...document.getElementsByClassName("internal-link")] |
| | | links |
| | | .filter(li => li.dataset.src || (li.dataset.idx && useContextualBacklinks)) |
| | | .forEach(li => { |
| | | if (li.dataset.ctx) { |
| | | const linkDest = content[li.dataset.src] |
| | | const popoverElement = `<div class="popover"> |
| | | <h3>${linkDest.title}</h3> |
| | | <p>${highlight(removeMarkdown(linkDest.content), li.dataset.ctx)}...</p> |
| | | <p class="meta">${new Date(linkDest.lastmodified).toLocaleDateString()}</p> |
| | | </div>` |
| | | const el = htmlToElement(popoverElement) |
| | | li.appendChild(el) |
| | | li.addEventListener("mouseover", () => { |
| | | el.classList.add("visible") |
| | | }) |
| | | li.addEventListener("mouseout", () => { |
| | | el.classList.remove("visible") |
| | | }) |
| | | } else { |
| | | const linkDest = content[li.dataset.src.replace(/\/$/g, "").replace(basePath, "")] |
| | | if (linkDest) { |
| | | const popoverElement = `<div class="popover"> |
| | | <h3>${linkDest.title}</h3> |
| | | <p>${removeMarkdown(linkDest.content).split(" ", 20).join(" ")}...</p> |
| | | <p class="meta">${new Date(linkDest.lastmodified).toLocaleDateString()}</p> |
| | | </div>` |
| | | const el = htmlToElement(popoverElement) |
| | | li.appendChild(el) |
| | | li.addEventListener("mouseover", () => { |
| | |
| | | li.addEventListener("mouseout", () => { |
| | | el.classList.remove("visible") |
| | | }) |
| | | } else { |
| | | const linkDest = content[li.dataset.src.replace(/\/$/g, "").replace(basePath, "")] |
| | | if (linkDest) { |
| | | const popoverElement = `<div class="popover"> |
| | | <h3>${linkDest.title}</h3> |
| | | <p>${removeMarkdown(linkDest.content).split(" ", 20).join(" ")}...</p> |
| | | <p class="meta">${new Date(linkDest.lastmodified).toLocaleDateString()}</p> |
| | | </div>` |
| | | const el = htmlToElement(popoverElement) |
| | | li.appendChild(el) |
| | | li.addEventListener("mouseover", () => { |
| | | el.classList.add("visible") |
| | | }) |
| | | li.addEventListener("mouseout", () => { |
| | | el.classList.remove("visible") |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| New file |
| | |
| | | import { router, navigate } from "https://unpkg.com/million@1.8.9-0/dist/router.mjs" |
| | | |
| | | export const attachSPARouting = (draw) => { |
| | | // SPA navigation for access later |
| | | window.navigate = navigate |
| | | // We only mutate document.title and content within .singlePage element |
| | | router(".singlePage") |
| | | // We need on initial load, then subsequent redirs |
| | | // requestAnimationFrame() delays graph draw until SPA routing is finished |
| | | window.addEventListener("million:navigate", () => requestAnimationFrame(draw)) |
| | | window.addEventListener("DOMContentLoaded", () => requestAnimationFrame(draw)) |
| | | } |
| | |
| | | // SPA navigation |
| | | window.navigate( |
| | | new URL( |
| | | `${BASE_URL}${id}#:~:text=${encodeURIComponent(term)}/` |
| | | `${BASE_URL.replace(/\/$/g, "")}${id}#:~:text=${encodeURIComponent(term)}/` |
| | | ), |
| | | '.singlePage' |
| | | ) |
| | |
| | | openToc: false |
| | | enableLinkPreview: true |
| | | enableLatex: true |
| | | enableSPA: false |
| | | enableSPA: true |
| | | enableContextualBacklinks: true |
| | | description: |
| | | Host your second brain and digital garden for free. Quartz features extremely fast full-text search, |
| | |
| | | </article> |
| | | {{partial "contact.html" .}} |
| | | </div> |
| | | {{partial "popover.html" .}} |
| | | </body> |
| | | |
| | | </html> |
| | |
| | | <li><a href="{{ .Permalink }}">{{ .LinkTitle | humanize }}</a></li> |
| | | {{ end }} |
| | | </ul> |
| | | {{partial "toc.html" .}} |
| | | {{partial "toc.html" .}} |
| | | {{partial "textprocessing.html" . }} |
| | | </article> |
| | | {{partial "footer.html" .}} |
| | | {{partial "popover.html" .}} |
| | | </div> |
| | | </body> |
| | | |
| | |
| | | </article> |
| | | {{partial "contact.html" .}} |
| | | </div> |
| | | {{partial "popover.html" .}} |
| | | </body> |
| | | |
| | | </html> |
| | |
| | | </article> |
| | | {{partial "contact.html" .}} |
| | | </div> |
| | | {{partial "popover.html" .}} |
| | | </body> |
| | | |
| | | </html> |
| | |
| | | {{partial "darkmode.html" .}} |
| | | </header> |
| | | <article> |
| | | {{partial "toc.html" .}} |
| | | {{partial "toc.html" .}} |
| | | {{partial "textprocessing.html" . }} |
| | | </article> |
| | | {{partial "footer.html" .}} |
| | | {{partial "popover.html" .}} |
| | | </div> |
| | | </body> |
| | | </html> |
| | | |
| | |
| | | </style> |
| | | {{ $js := resources.Get "js/graph.js" | resources.Fingerprint "md5" }} |
| | | <script src="{{ $js.Permalink }}"></script> |
| | | <script> |
| | | drawGraph( |
| | | {{strings.TrimRight "/" .Page.Permalink}}, |
| | | {{strings.TrimRight "/" .Site.BaseURL}}, |
| | | {{$.Site.Data.graphConfig.paths}}, |
| | | {{$.Site.Data.graphConfig.depth}}, |
| | | {{$.Site.Data.graphConfig.enableDrag}}, |
| | | {{$.Site.Data.graphConfig.enableLegend}}, |
| | | {{$.Site.Data.graphConfig.enableZoom}} |
| | | ); |
| | | </script> |
| | |
| | | <script src="{{$darkMode.Permalink}}"></script> |
| | | {{partial "katex.html" .}} |
| | | |
| | | {{ $popover := resources.Get "js/popover.js" | resources.Fingerprint "md5" | |
| | | resources.Minify }} |
| | | <script src="{{$popover.Permalink}}"></script> |
| | | |
| | | <!-- Preload page vars --> |
| | | {{$linkIndex := resources.Get "indices/linkIndex.json" | resources.Fingerprint |
| | | "md5" | resources.Minify | }} {{$contentIndex := resources.Get |
| | |
| | | })) |
| | | </script> |
| | | {{if $.Site.Data.config.enableSPA}} |
| | | {{ $router := resources.Get "js/router.js" | resources.Fingerprint "md5" | |
| | | resources.Minify }} |
| | | <script type="module"> |
| | | import { router, navigate } from "https://unpkg.com/million/dist/router.mjs"; |
| | | // SPA navigation for access later |
| | | window.navigate = navigate; |
| | | // We only mutate document.title and content within .singlePage element |
| | | router(".singlePage"); |
| | | const callback = () => { |
| | | // requestAnimationFrame() delays graph draw until SPA routing is finished |
| | | const draw = () => { |
| | | const container = document.getElementById("graph-container"); |
| | | // retry if the graph is not ready |
| | | if (!container) return requestAnimationFrame(draw); |
| | | // clear the graph in case there is anything within it |
| | | container.textContent = ""; |
| | | import { attachSPARouting } from '{{$router.Permalink}}'; |
| | | // NOTE: everything within this callback will be executed for every page navigation. This is a good place to put JavaScript that loads or modifies data on the page. |
| | | const draw = () => { |
| | | const container = document.getElementById("graph-container") |
| | | // retry if the graph is not ready |
| | | if (!container) return requestAnimationFrame(draw) |
| | | // clear the graph in case there is anything within it |
| | | container.textContent = "" |
| | | |
| | | drawGraph( |
| | | {{strings.TrimRight "/" .Page.Permalink}}, |
| | | {{strings.TrimRight "/" .Site.BaseURL}}, |
| | | {{$.Site.Data.graphConfig.paths}}, |
| | | {{$.Site.Data.graphConfig.depth}}, |
| | | {{$.Site.Data.graphConfig.enableDrag}}, |
| | | {{$.Site.Data.graphConfig.enableLegend}}, |
| | | {{$.Site.Data.graphConfig.enableZoom}} |
| | | ); |
| | | }; |
| | | requestAnimationFrame(draw); |
| | | drawGraph( |
| | | {{strings.TrimRight "/" .Site.BaseURL}}, |
| | | {{$.Site.Data.graphConfig.paths}}, |
| | | {{$.Site.Data.graphConfig.depth}}, |
| | | {{$.Site.Data.graphConfig.enableDrag}}, |
| | | {{$.Site.Data.graphConfig.enableLegend}}, |
| | | {{$.Site.Data.graphConfig.enableZoom}} |
| | | ); |
| | | |
| | | {{if $.Site.Data.config.enableLinkPreview}} |
| | | initPopover({{strings.TrimRight "/" .Site.BaseURL }}, {{$.Site.Data.config.enableContextualBacklinks}}) |
| | | {{end}} |
| | | {{if $.Site.Data.config.enableLatex}} |
| | | renderMathInElement(document.body, { |
| | | delimiters: [ |
| | | {left: '$$', right: '$$', display: true}, |
| | | {left: '$', right: '$', display: false}, |
| | | ], |
| | | throwOnError : false |
| | | }); |
| | | {{end}} |
| | | }; |
| | | // We need on initial load, then subsequent redirs |
| | | window.addEventListener("million:navigate", callback); |
| | | window.addEventListener("DOMContentLoaded", callback); |
| | | attachSPARouting(draw); |
| | | </script> |
| | | {{else}} |
| | | <script>window.navigate = (url) => window.location.href = url</script> |
| | |
| | | <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.1/dist/katex.min.css" integrity="sha384-R4558gYOUz8mP9YWpZJjofhk+zx0AS11p36HnD2ZKj/6JR5z27gSSULCNHIRReVs" crossorigin="anonymous"> |
| | | <script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.1/dist/katex.min.js" integrity="sha384-z1fJDqw8ZApjGO3/unPWUPsIymfsJmyrDVWC8Tv/a1HeOtGmkwNd/7xUS0Xcnvsx" crossorigin="anonymous"></script> |
| | | <script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.1/dist/contrib/auto-render.min.js" integrity="sha384-+XBljXPPiv+OzfbB3cVmLHf4hdUFHlWNZN5spNQ7rmHTXpd7WvJum6fIACpNNfIR" crossorigin="anonymous"></script> |
| | | <script> |
| | | document.addEventListener("DOMContentLoaded", function() { |
| | | renderMathInElement(document.body, { |
| | | delimiters: [ |
| | | {left: '$$', right: '$$', display: true}, |
| | | {left: '$', right: '$', display: false}, |
| | | ], |
| | | throwOnError : false |
| | | }); |
| | | }); |
| | | </script> |
| | | {{end}} |