commit c01138a81c7052b87073395429500356ce4596f2 Author: jackyzha0 <j.zhao2k19@gmail.com> Date: Sun Jul 18 09:35:42 2021 -0400 add base structure diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0de2938 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.DS_Store +public +resources +.idea +content/.obsidian \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..147e2ca --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 jackyzha0 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..0666d7b --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# quartz +Simple second brain and digital garden. + +```shell +# Installation +go install github.com/jackyzha0/hugo-obsidian + +# Run +hugo-obsidian -input=content -output=data +``` \ No newline at end of file diff --git a/assets/darkmode.js b/assets/darkmode.js new file mode 100644 index 0000000..93bf6da --- /dev/null +++ b/assets/darkmode.js @@ -0,0 +1,26 @@ +// Darkmode toggle +const toggleSwitch = document.querySelector('#darkmode-toggle') + +const userPref = window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark' +const currentTheme = localStorage.getItem('theme') ?? userPref + +if (currentTheme) { + document.documentElement.setAttribute('saved-theme', currentTheme); + if (currentTheme === 'dark') { + toggleSwitch.checked = true + } +} + +const switchTheme = (e) => { + if (e.target.checked) { + document.documentElement.setAttribute('saved-theme', 'dark') + localStorage.setItem('theme', 'dark') + } + else { + document.documentElement.setAttribute('saved-theme', 'light') + localStorage.setItem('theme', 'light') + } +} + +// listen for toggle +toggleSwitch.addEventListener('change', switchTheme, false) \ No newline at end of file diff --git a/assets/darkmode.scss b/assets/darkmode.scss new file mode 100644 index 0000000..dde5be6 --- /dev/null +++ b/assets/darkmode.scss @@ -0,0 +1,67 @@ + +.darkmode { + text-align: right; + + & > .toggle { + display: none; + box-sizing: border-box; + + &:checked + .toggle-button:after { + left: 50%; + } + + & + .toggle-button { + box-sizing: border-box; + outline: 0; + display: inline-block; + width: 3em; + height: 1.5em; + position: relative; + cursor: pointer; + border: 2px solid var(--gray); + user-select: none; + padding: 2px; + transition: all 0.2s ease; + border-radius: 2em; + + &:after, &:before { + position: relative; + display: block; + box-sizing: border-box; + content: ""; + width: 50%; + height: 100%; + } + + &:before { + display: none; + } + + &:after { + left: 0; + transition: all 0.2s ease; + background: var(--gray); + content: ""; + border-radius: 1em; + } + } + } + + & #dayIcon { + position: relative; + width: 20px; + height: 20px; + top: -1.5px; + margin: 0 7px; + fill: var(--gray); + } + + & #nightIcon { + position: relative; + width: 18px; + height: 18px; + top: -2px; + margin: 0 7px; + fill: var(--gray); + } +} \ No newline at end of file diff --git a/assets/syntax.scss b/assets/syntax.scss new file mode 100644 index 0000000..27c37f4 --- /dev/null +++ b/assets/syntax.scss @@ -0,0 +1,99 @@ +/* Background */ .chroma { color: #f8f8f2; background-color: #282a36 } +/* Other */ .chroma .x { } +/* Error */ .chroma .err { } +/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; } +/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; } +/* LineHighlight */ .chroma .hl { display: block; width: 100%;background-color: #ffffcc } +/* LineNumbersTable */ .chroma .lnt { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f } +/* LineNumbers */ .chroma .ln { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f } +/* Keyword */ .chroma .k { color: #ff79c6 } +/* KeywordConstant */ .chroma .kc { color: #ff79c6 } +/* KeywordDeclaration */ .chroma .kd { color: #8be9fd; font-style: italic } +/* KeywordNamespace */ .chroma .kn { color: #ff79c6 } +/* KeywordPseudo */ .chroma .kp { color: #ff79c6 } +/* KeywordReserved */ .chroma .kr { color: #ff79c6 } +/* KeywordType */ .chroma .kt { color: #8be9fd } +/* Name */ .chroma .n { } +/* NameAttribute */ .chroma .na { color: #50fa7b } +/* NameBuiltin */ .chroma .nb { color: #8be9fd; font-style: italic } +/* NameBuiltinPseudo */ .chroma .bp { } +/* NameClass */ .chroma .nc { color: #50fa7b } +/* NameConstant */ .chroma .no { } +/* NameDecorator */ .chroma .nd { } +/* NameEntity */ .chroma .ni { } +/* NameException */ .chroma .ne { } +/* NameFunction */ .chroma .nf { color: #50fa7b } +/* NameFunctionMagic */ .chroma .fm { } +/* NameLabel */ .chroma .nl { color: #8be9fd; font-style: italic } +/* NameNamespace */ .chroma .nn { } +/* NameOther */ .chroma .nx { } +/* NameProperty */ .chroma .py { } +/* NameTag */ .chroma .nt { color: #ff79c6 } +/* NameVariable */ .chroma .nv { color: #8be9fd; font-style: italic } +/* NameVariableClass */ .chroma .vc { color: #8be9fd; font-style: italic } +/* NameVariableGlobal */ .chroma .vg { color: #8be9fd; font-style: italic } +/* NameVariableInstance */ .chroma .vi { color: #8be9fd; font-style: italic } +/* NameVariableMagic */ .chroma .vm { } +/* Literal */ .chroma .l { } +/* LiteralDate */ .chroma .ld { } +/* LiteralString */ .chroma .s { color: #f1fa8c } +/* LiteralStringAffix */ .chroma .sa { color: #f1fa8c } +/* LiteralStringBacktick */ .chroma .sb { color: #f1fa8c } +/* LiteralStringChar */ .chroma .sc { color: #f1fa8c } +/* LiteralStringDelimiter */ .chroma .dl { color: #f1fa8c } +/* LiteralStringDoc */ .chroma .sd { color: #f1fa8c } +/* LiteralStringDouble */ .chroma .s2 { color: #f1fa8c } +/* LiteralStringEscape */ .chroma .se { color: #f1fa8c } +/* LiteralStringHeredoc */ .chroma .sh { color: #f1fa8c } +/* LiteralStringInterpol */ .chroma .si { color: #f1fa8c } +/* LiteralStringOther */ .chroma .sx { color: #f1fa8c } +/* LiteralStringRegex */ .chroma .sr { color: #f1fa8c } +/* LiteralStringSingle */ .chroma .s1 { color: #f1fa8c } +/* LiteralStringSymbol */ .chroma .ss { color: #f1fa8c } +/* LiteralNumber */ .chroma .m { color: #bd93f9 } +/* LiteralNumberBin */ .chroma .mb { color: #bd93f9 } +/* LiteralNumberFloat */ .chroma .mf { color: #bd93f9 } +/* LiteralNumberHex */ .chroma .mh { color: #bd93f9 } +/* LiteralNumberInteger */ .chroma .mi { color: #bd93f9 } +/* LiteralNumberIntegerLong */ .chroma .il { color: #bd93f9 } +/* LiteralNumberOct */ .chroma .mo { color: #bd93f9 } +/* Operator */ .chroma .o { color: #ff79c6 } +/* OperatorWord */ .chroma .ow { color: #ff79c6 } +/* Punctuation */ .chroma .p { } +/* Comment */ .chroma .c { color: #6272a4 } +/* CommentHashbang */ .chroma .ch { color: #6272a4 } +/* CommentMultiline */ .chroma .cm { color: #6272a4 } +/* CommentSingle */ .chroma .c1 { color: #6272a4 } +/* CommentSpecial */ .chroma .cs { color: #6272a4 } +/* CommentPreproc */ .chroma .cp { color: #ff79c6 } +/* CommentPreprocFile */ .chroma .cpf { color: #ff79c6 } +/* Generic */ .chroma .g { } +/* GenericDeleted */ .chroma .gd { color: #8b080b } +/* GenericEmph */ .chroma .ge { text-decoration: underline } +/* GenericError */ .chroma .gr { } +/* GenericHeading */ .chroma .gh { font-weight: bold } +/* GenericInserted */ .chroma .gi { font-weight: bold } +/* GenericOutput */ .chroma .go { color: #44475a } +/* GenericPrompt */ .chroma .gp { } +/* GenericStrong */ .chroma .gs { } +/* GenericSubheading */ .chroma .gu { font-weight: bold } +/* GenericTraceback */ .chroma .gt { } +/* GenericUnderline */ .chroma .gl { text-decoration: underline } +/* TextWhitespace */ .chroma .w { } + +.lntd:first-of-type > .chroma { + padding-right: 0; +} + +.chroma code { + font-family: 'Fira Code' !important; + font-size: 0.85em; + line-height: 1em; + background: none; + padding: 0; +} + +.chroma { + border-radius: 3px; + margin: 0; +} \ No newline at end of file diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..da90bbf --- /dev/null +++ b/config.toml @@ -0,0 +1,4 @@ +baseURL = "https://quartz.jzhao.xyz/" +languageCode = "en-us" +googleAnalytics = "UA-148413215-1" +pygmentsUseClasses = true \ No newline at end of file diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..e69de29 diff --git a/content/moc/directory.md b/content/moc/directory.md new file mode 100644 index 0000000..e69de29 diff --git a/content/notes/config.md b/content/notes/config.md new file mode 100644 index 0000000..e69de29 diff --git a/content/notes/setup.md b/content/notes/setup.md new file mode 100644 index 0000000..e69de29 diff --git a/content/notes/troubleshooting.md b/content/notes/troubleshooting.md new file mode 100644 index 0000000..e69de29 diff --git a/content/notes/welcome.md b/content/notes/welcome.md new file mode 100644 index 0000000..e69de29 diff --git a/data/config.yaml b/data/config.yaml new file mode 100644 index 0000000..8d0ae8a --- /dev/null +++ b/data/config.yaml @@ -0,0 +1,11 @@ +name: Quartz Example Page +description: + Here is the page description. This is an example Quartz site that details installation, + setup, customization, and troubleshooting for Quartz itself. +page_title: + Quartz Example Page +links: + - link_name: twitter + link: https://twitter.com/_jzhao + - link_name: github + link: https://github.com/jackyzha0 \ No newline at end of file diff --git a/data/graphConfig.yaml b/data/graphConfig.yaml new file mode 100644 index 0000000..089d5d3 --- /dev/null +++ b/data/graphConfig.yaml @@ -0,0 +1,11 @@ +enableLegend: false +enableDrag: true +enableZoom: false +base: + node: "#284b63" + activeNode: "#f28482" + inactiveNode: "#a8b3bd" + link: "#babdbf" + activeLink: "#5a7282" +paths: + - /moc: "#4388cc" \ No newline at end of file diff --git a/layouts/404.html b/layouts/404.html new file mode 100644 index 0000000..e69de29 diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html new file mode 100644 index 0000000..ccb3b93 --- /dev/null +++ b/layouts/_default/baseof.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en"> +{{ block "head" . }} +{{ end }} + +<body> +{{ block "main" . }} +{{ end }} +</body> +</html> \ No newline at end of file diff --git a/layouts/_default/single.html b/layouts/_default/single.html new file mode 100644 index 0000000..c7ce881 --- /dev/null +++ b/layouts/_default/single.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html lang="en"> +{{ partial "head.html" . }} + +<body> +<div class="singlePage"> + <!-- Begin actual content --> + {{partial "darkmode.html" .}} + <article> + {{if .Title}}<h1>{{ .Title }}</h1>{{end}} + {{- .Content -}} + </article> + {{partial "footer.html" .}} +</div> + +{{- with resources.Get "darkmode.js" | minify -}} +<script> + {{.Content | safeJS }} +</script> +{{- end -}} + +</body> + +</html> \ No newline at end of file diff --git a/layouts/index.html b/layouts/index.html new file mode 100644 index 0000000..e69de29 diff --git a/layouts/partials/backlinks.html b/layouts/partials/backlinks.html new file mode 100644 index 0000000..2ae4976 --- /dev/null +++ b/layouts/partials/backlinks.html @@ -0,0 +1,9 @@ +<ol class="backlinks"> + {{$curPage := strings.TrimRight "/" .Page.RelPermalink }} + {{$inbound := index $.Site.Data.linkIndex.index.backlinks $curPage}} + {{- range $inbound -}} + <li> + <a href="{{index . "source"}}">{{index . "source"}}</a> + </li> + {{- end -}} +</ol> \ No newline at end of file diff --git a/layouts/partials/darkmode.html b/layouts/partials/darkmode.html new file mode 100644 index 0000000..3d36d9a --- /dev/null +++ b/layouts/partials/darkmode.html @@ -0,0 +1,16 @@ +<div class='darkmode'> + <label id="toggle-label-light" for='darkmode-toggle' tabindex="-1"> + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="dayIcon" x="0px" y="0px" viewBox="0 0 35 35" style="enable-background:new 0 0 35 35;" xml:space="preserve"> + <title>Light Mode</title> + <path d="M6,17.5C6,16.672,5.328,16,4.5,16h-3C0.672,16,0,16.672,0,17.5 S0.672,19,1.5,19h3C5.328,19,6,18.328,6,17.5z M7.5,26c-0.414,0-0.789,0.168-1.061,0.439l-2,2C4.168,28.711,4,29.086,4,29.5 C4,30.328,4.671,31,5.5,31c0.414,0,0.789-0.168,1.06-0.44l2-2C8.832,28.289,9,27.914,9,27.5C9,26.672,8.329,26,7.5,26z M17.5,6 C18.329,6,19,5.328,19,4.5v-3C19,0.672,18.329,0,17.5,0S16,0.672,16,1.5v3C16,5.328,16.671,6,17.5,6z M27.5,9 c0.414,0,0.789-0.168,1.06-0.439l2-2C30.832,6.289,31,5.914,31,5.5C31,4.672,30.329,4,29.5,4c-0.414,0-0.789,0.168-1.061,0.44 l-2,2C26.168,6.711,26,7.086,26,7.5C26,8.328,26.671,9,27.5,9z M6.439,8.561C6.711,8.832,7.086,9,7.5,9C8.328,9,9,8.328,9,7.5 c0-0.414-0.168-0.789-0.439-1.061l-2-2C6.289,4.168,5.914,4,5.5,4C4.672,4,4,4.672,4,5.5c0,0.414,0.168,0.789,0.439,1.06 L6.439,8.561z M33.5,16h-3c-0.828,0-1.5,0.672-1.5,1.5s0.672,1.5,1.5,1.5h3c0.828,0,1.5-0.672,1.5-1.5S34.328,16,33.5,16z M28.561,26.439C28.289,26.168,27.914,26,27.5,26c-0.828,0-1.5,0.672-1.5,1.5c0,0.414,0.168,0.789,0.439,1.06l2,2 C28.711,30.832,29.086,31,29.5,31c0.828,0,1.5-0.672,1.5-1.5c0-0.414-0.168-0.789-0.439-1.061L28.561,26.439z M17.5,29 c-0.829,0-1.5,0.672-1.5,1.5v3c0,0.828,0.671,1.5,1.5,1.5s1.5-0.672,1.5-1.5v-3C19,29.672,18.329,29,17.5,29z M17.5,7 C11.71,7,7,11.71,7,17.5S11.71,28,17.5,28S28,23.29,28,17.5S23.29,7,17.5,7z M17.5,25c-4.136,0-7.5-3.364-7.5-7.5 c0-4.136,3.364-7.5,7.5-7.5c4.136,0,7.5,3.364,7.5,7.5C25,21.636,21.636,25,17.5,25z" /> + </svg> + </label> + <input class='toggle' id='darkmode-toggle' type='checkbox' tabindex="-1"> + <label class='toggle-button' for='darkmode-toggle'></label> + <label id="toggle-label-dark" for='darkmode-toggle' tabindex="-1"> + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="nightIcon" x="0px" y="0px" viewBox="0 0 100 100" style="enable-background='new 0 0 100 100'" xml:space="preserve"> + <title>Dark Mode</title> + <path d="M96.76,66.458c-0.853-0.852-2.15-1.064-3.23-0.534c-6.063,2.991-12.858,4.571-19.655,4.571 C62.022,70.495,50.88,65.88,42.5,57.5C29.043,44.043,25.658,23.536,34.076,6.47c0.532-1.08,0.318-2.379-0.534-3.23 c-0.851-0.852-2.15-1.064-3.23-0.534c-4.918,2.427-9.375,5.619-13.246,9.491c-9.447,9.447-14.65,22.008-14.65,35.369 c0,13.36,5.203,25.921,14.65,35.368s22.008,14.65,35.368,14.65c13.361,0,25.921-5.203,35.369-14.65 c3.872-3.871,7.064-8.328,9.491-13.246C97.826,68.608,97.611,67.309,96.76,66.458z" /> + </svg> + </label> +</div> \ No newline at end of file diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html new file mode 100644 index 0000000..3afeb8e --- /dev/null +++ b/layouts/partials/footer.html @@ -0,0 +1,21 @@ +<div> + <hr/> + {{partial "graph.html" .}} + <ul id="sub-nav"> + <li><a href="/">↳ Take me home</a></li> + </ul> +</div> + +<!-- Contact Info --> +<div id="contact_buttons" class="lt-centre"> + <footer> + <p>made by {{ $.Site.Data.config.name }}, © {{ dateFormat "2006" now }}</p> + <a href="https://github.com/jackyzha0/quartz">source</a> + {{ if not .IsHome }} + <a href="/">home</a> + {{end}} + {{- range $.Site.Data.links.footer -}} + <a href="{{.link}}">{{.link_name}}</a> + {{- end -}} + </footer> +</div> \ No newline at end of file diff --git a/layouts/partials/graph.html b/layouts/partials/graph.html new file mode 100644 index 0000000..ea9cf1a --- /dev/null +++ b/layouts/partials/graph.html @@ -0,0 +1,218 @@ +<script src="https://cdn.jsdelivr.net/npm/d3@6"></script> +<div id="graph-container"></div> +<style> + :root { + --g-node: {{.Site.Data.graphConfig.base.node}}; + --g-node-active: {{.Site.Data.graphConfig.base.activeNode}}; + --g-node-inactive: {{.Site.Data.graphConfig.base.inactiveNode}}; + --g-link: {{.Site.Data.graphConfig.base.link}}; + --g-link-active: {{.Site.Data.graphConfig.base.activeLink}}; + } +</style> +<script> + const index = {{$.Site.Data.linkIndex.index}} + const links = {{$.Site.Data.linkIndex.links}} + const curPage = {{ strings.TrimRight "/" .Page.RelPermalink }} + const pathColors = {{$.Site.Data.graphConfig.paths}} + + const parseIdsFromLinks = (links) => [...(new Set(links.flatMap(link => ([link.source, link.target]))))] + + const data = { + nodes: parseIdsFromLinks(links).map(id => ({id})), + links, + } + + const color = (d) => { + if (d.id === curPage) { + return "var(--g-node-active)" + } + + for (const pathColor of pathColors) { + const path = Object.keys(pathColor)[0] + const colour = pathColor[path] + if (d.id.startsWith(path)) { + return colour + } + } + + return "var(--g-node)" + } + + const drag = simulation => { + function dragstarted(event, d) { + if (!event.active) simulation.alphaTarget(1).restart(); + d.fx = d.x; + d.fy = d.y; + } + + function dragged(event,d) { + d.fx = event.x; + d.fy = event.y; + } + + function dragended(event,d) { + if (!event.active) simulation.alphaTarget(0); + d.fx = null; + d.fy = null; + } + + const enableDrag = {{$.Site.Data.graphConfig.enableDrag}} + const noop = () => {} + return d3.drag() + .on("start", enableDrag ? dragstarted : noop) + .on("drag", enableDrag ? dragged : noop) + .on("end", enableDrag ? dragended : noop); + } + + const height = 400 + const width = document.getElementById("graph-container").offsetWidth + + const simulation = d3.forceSimulation(data.nodes) + .force("charge", d3.forceManyBody().strength(-20)) + .force("link", d3.forceLink(data.links) + .id(d => d.id) + ) + .force("center", d3.forceCenter()); + + const svg = d3.select('#graph-container') + .append('svg') + .attr('width', width) + .attr('height', height) + .attr("viewBox", [-width / 2, -height / 2, width, height]); + + // legend + const enableLegend = {{$.Site.Data.graphConfig.enableLegend}} + if (enableLegend) { + const legend = [ + {"Current": "var(--g-node-active)"}, + {"Note": "var(--g-node)"}, + ...pathColors + ] + legend.forEach((legendEntry, i) => { + const key = Object.keys(legendEntry)[0] + const colour = legendEntry[key] + svg.append("circle").attr("cx", -width/2 + 20).attr("cy", height/2 - 30 * (i+1)).attr("r", 6).style("fill", colour) + svg.append("text").attr("x", -width/2 + 40).attr("y", height/2 - 30 * (i+1)).text(key).style("font-size", "15px").attr("alignment-baseline","middle") + }) + } + + // draw links between nodes + const link = svg.append("g") + .selectAll("line") + .data(data.links) + .join("line") + .attr("class", "link") + .attr("stroke", "var(--g-link)") + .attr("stroke-width", 2) + .attr("data-source", d => d.source.id) + .attr("data-target", d => d.target.id) + + // svg groups + const graphNode = svg.append("g") + .selectAll("g") + .data(data.nodes) + .enter().append("g") + + // draw individual nodes + const node = graphNode.append("circle") + .attr("class", "node") + .attr("id", (d) => d.id) + .attr("r", (d) => { + const numOut = index.links[d.id]?.length || 0 + const numIn = index.backlinks[d.id]?.length || 0 + return 3 + (numOut + numIn) / 4 + }) + .attr("fill", color) + .style("cursor", "pointer") + .on("click", (_, d) => { + window.location.href = d.id; + }) + .on("mouseover", function (_, d) { + d3.selectAll(".node") + .transition() + .duration(100) + .attr("fill", "var(--g-node-inactive)") + + const neighbours = parseIdsFromLinks([...(index.links[d.id] || []), ...(index.backlinks[d.id] || [])]) + const neighbourNodes = d3.selectAll(".node").filter(d => neighbours.includes(d.id)) + const currentId = d.id + const links = d3.selectAll(".link").filter(d => d.source.id === currentId || d.target.id === currentId) + + // highlight neighbour nodes + neighbourNodes + .transition() + .duration(200) + .attr("fill", color) + + // highlight links + links + .transition() + .duration(200) + .attr("stroke", "var(--g-link-active)") + + // show text for self + d3.select(this.parentNode) + .select("text") + .raise() + .transition() + .duration(200) + .style("opacity", 1) + }).on("mouseleave", function (_,d) { + d3.selectAll(".node") + .transition() + .duration(200) + .attr("fill", color) + + const currentId = d.id + const links = d3.selectAll(".link").filter(d => d.source.id === currentId || d.target.id === currentId) + + links + .transition() + .duration(200) + .attr("stroke", "var(--g-link)") + + d3.select(this.parentNode) + .select("text") + .transition() + .duration(200) + .style("opacity", 0) + }) + .call(drag(simulation)); + + // draw labels + const labels = graphNode.append("text") + .attr("dx", 12) + .attr("dy", ".35em") + .text((d) => d.id) + .style("opacity", 0) + .style("pointer-events", "none") + .call(drag(simulation)); + + // set panning + const enableZoom = {{$.Site.Data.graphConfig.enableZoom}} + if (enableZoom) { + svg.call(d3.zoom() + .extent([[0, 0], [width, height]]) + .scaleExtent([0.25, 4]) + .on("zoom", ({transform}) => { + link.attr("transform", transform); + node.attr("transform", transform); + labels.attr("transform", transform); + })); + } + + // progress the simulation + simulation.on("tick", () => { + link + .attr("x1", d => d.source.x) + .attr("y1", d => d.source.y) + .attr("x2", d => d.target.x) + .attr("y2", d => d.target.y); + node + .attr("cx", d => d.x) + .attr("cy", d => d.y); + labels + .attr("x", d => d.x) + .attr("y", d => d.y); + }); +</script> \ No newline at end of file diff --git a/layouts/partials/head.html b/layouts/partials/head.html new file mode 100644 index 0000000..5e42a2c --- /dev/null +++ b/layouts/partials/head.html @@ -0,0 +1,24 @@ +<head> + <link rel="preconnect" href="https://www.googletagmanager.com"> + <link crossorigin rel="preconnect" href="https://www.google-analytics.com"> + {{ template "_internal/google_analytics_async.html" . }} + + <!-- Meta tags --> + <meta charset="UTF-8"> + <meta name="description" content="{{$.Site.Data.config.description}}"> + <title>{{$.Site.Data.config.page_title}}</title> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="shortcut icon" type="image/png" href="/icon.png" /> + + <!-- CSS Stylesheets and Fonts --> + <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&family=Source+Sans+Pro:wght@400;700&family=Fira+Code:wght@400;700&display=swap" rel="stylesheet"> + {{ $css := slice "darkmode.scss" "syntax.scss"}} + {{range $css}} + {{$sass := resources.Get . | resources.ToCSS }} + {{with $sass | minify}} + <style> + {{.Content | safeCSS}} + </style> + {{end}} + {{end}} +</head> \ No newline at end of file diff --git a/layouts/partials/header.html b/layouts/partials/header.html new file mode 100644 index 0000000..e69de29 diff --git a/static/icon.png b/static/icon.png new file mode 100644 index 0000000..7294a8b Binary files /dev/null and b/static/icon.png differ